Hi all,
I'm operating a DA14580 in the external processor configuration. It is controlled by a uC (SPI master) using the GTL 5-wire SPI protocol. I keep having the problem of running into a deadlock. When streaming some data over BLE (hence a lot of traffic between the uC and the DA), I run into a state where both the DA and the uC want to transmit at the same time. More specifically, the DA gets stuck in thespi_hci_write_func()
功能。它驱动高信号高并等待SPI转移(spi_wait_for_transfer()
):
......
spi_dready_high();// asserd teready请求传输
做 {
spi_wait_for_transfer();//等待SPI主设备的SPI事务
......
However, the uC tries to send a message at the same time and gets stuck in thespi_send_hci_msg()
function, waiting for the DREADY signal to go low:
......
//禁用减少中断
dready_irq_disable();
//调用减排时间来检测是否正在收到数据
while(dready_get_status());
......
以下发生:
- The uC disables the dready interrupt, just before the DA asserts the dready signal.
- The dready signal goes high, but no interrupt is triggered on the uC side.
- 而是,UC等待降低的降低信号。
- 由于DA正在等待SPI传输,但是变量信号不会低。
- >僵局
我想知道协议如何旨在避免跑到上述僵局中。从它看起来像没有阻止这种情况的机制。
Thanks!
Mabraun.
编辑:试图提出问题描述更全面
嗨mabraun,
有一个序列数据磁带机汇er the SPI bus the signals and the data exchanged by the devices are not only the DREADY in order to prevent this condition, there are flow_on and flow_off data that should be exchanged before the two devices can transfer data over the SPI bus. You can have a look at the UM-B-013 in order to check the protocol in detail. There is a specific procedure before the master can talk to slave and vice versa in order to avoid this kind of deadlock, before the master can transmit should check if the slave is available (if the last message send from slave was a flow on byte) before invoking the spi_send_hci_msg() and disabling the interrupts.
谢谢mt_dialog.
Hi MT_dialog,
感谢您的回复。我很清楚flow_on / flow_off原则,我仔细阅读了UM-B-013。值得澄清的是,我使用了从SDK5(对于主机和DA)中提供的Proximity Reporter示例中提供的源代码,这就是为什么正确实现流量控制机制(或应该)的原因。我拥有的问题与流量控制机制无关,甚至在UM-B-013的第6.2.3节中解决:
The highlighted example is exactly the problem I'm experiencing: master wants to send message (0x05), slave wants to send flow off byte. It continues:
However, the behaviour described above (bold) doesn't seem to be implemented on the DA side (see spi_hci.c):
bool spi_hci_flow_off_func(void)
{
UINT8_T TMP;
//首先检查是否正在进行传输
if((spi_cs_getf()==0))
{
返回false;
}
NVIC_DisableIRQ(SPI_IRQn); // Disable SPI interrupt to CPU
spi_dready_high();// asserd teready请求传输
做 {
spi_wait_for_transfer();//等待SPI主设备的SPI事务
tmp = spi_rxtxreg_read();//从spi获取byte
} whiled(tmp!= dready_ack);//如果没有确认已知,请再试一次
[...]
}
上面的代码首先检查传输是否正在进行中,然后it asserts the DREADY line,然后it waits for an SPI transfer (or the DREADY_ACK byte) indefinitely. This behaviour doesn't correspond to:
让我们来看看UC(主机)方:第6.2.3节也是指出的
spi_hci_msg.c的代码如下所示:
void spi_send_hci_msg(uint16_t size, uint8_t *msg_ptr)
{
uint16_t i;
//禁用减少中断
NVIC_DisableIRQ(GPIO0_IRQn);
//调用减排时间来检测是否正在收到数据
while(gpio_getpinstatus(spi_gpio_port,spi_dready_pin));
spi_cs_high(); // Close CS
spi_cs_low();//打开CS.
spi_access(0x05);
[...]
}
The code第一的禁用减少中断,然后it polls for DREADY,然后it pulls the SPI chip select line low. If DREADY goes high right after the interrupt has been disabled, the uC will wait indefinitely for DREADY to go low again and the DREADY irq request will not be serviced. Also, the CS line does not prevent this from happening, as it is pulled low after deactivating the DREADY interrupt.
Am I missing something here?
Sorry for the long post, but I want to make sure I'm being understood correctly.
干杯!
嗨mabraun,
Please excuse me in case i got something wrong, you ve noticed that when there is an ongoing transaction from the master, so the slave has send a flow on, and the master has send a 0x08 in order to acknowledge it, so the master is ready to send data and disables the IRQ and after that immidiatelly the slave issues a flow_off in order to send data, so the DREADY pin gets high at the time that the CS is disabled (is high so it evades the CS check in the spi_cs_getf() function) since the DREADY is pulled high the master is stuck in the polling procedure and the slave is stuck waiting for a 0x08 message that will never come from the master.
您是否在应用程序中遇到过这种问题,如果您所做的话,您是否捕获了SPI交易?
谢谢mt_dialog.
Hi MT_dialog,
是的,你完全正确。在附加图像中,您将找到4个信号:
1. SPI CLK(黄色)
2. SPI MISO (blue)
3. SPI CS (pink)
4.减少(绿色)
我的范围只有4个频道,所以我无法捕获MOSI线。
In the beginning of the screenshot you can see the flow_off communication: 2 SPI bytes, containing the DREADY_ACK and the FLOW_ON bytes. After that, the master initiates a transmission (notice how the CS line goes low while DREADY is inactive). After that (successful) transmission, the slave asserts the DREADY signal (because it wants to send a flow_off message), and the master wants to send a message as well and pulls the CS line low. (for better visualization I moved the
spi_cs_low()
code line beforewhile(dready_get_status());
。否则,您将无法看到CS线被拉低。)注意,在几乎同时,在几乎同时被断言(CS低,降低高),但不会看到随后的SPI通信。那是僵局发生的时候。Thanks for your help!
Mabraun.
嗨mabraun,
与支持团队一起检查,就可以告诉我,这种情况很可能会发生,没有超时或任何其他机制,可以阻止580在主机刚开始发送数据时发送流脱机命令并且僵局似乎可能发生,但很少但它可能发生。因为我们从来没有默克这种问题,当通过SPI经营时,你可以确保这个死锁是为了确定你的系统停滞的原因,可以提供更完整的信号捕获,以确保0x05从主机(MOSI信号)留下,或者如果您能够调试,请确认这是代码在两侧粘所的位置(SPI_SEND_HCI_MSG()和SPI_HCI_FLOW_OF_FUNC())?
谢谢mt_dialog.
Hi MT_dialog,
thanks for your reply. In my current setup I am able to debug both sides, which is why I know that both sides are indeed stuck in spi_send_hci_msg() and spi_hci_flow_off_func().
I attached 4 more screen captures. I captured all 5 signal lines (all displayed in purple), in the following order: CLK, MOSI, MISO, CS, DREADY. Additionally, I used a protocol analyzer to interpret the MOSI and MISO lines, shown in blue on the screenshots. Bus 1 corresponds to MOSI, Bus2 to MISO.
1.png:Overall view on the problematic sequence resulting in the deadlock.
2.PNG:Zoomed-in view of the Flow-On sequence. DREADY is high, Master acknowledges it (0x08) and Slave sends FlowOn byte (0x06).
3.png:静音视图主机发送的第一个字节,标记消息的开头(0x05)。
4.png:放大视图发送的消息的结束the Master (CS is pulled high). Afterwards, the deadlock occurs: Slave wants to send FlowOff (which begins by asserting DREADY), Master wants to send the next message. Please note: In contrary to my previous post, I didnot移动
spi_cs_low()
code line beforewhile(dready_get_status())
, which is why you cannot see the CS line being pulled low. This is the original code behaviour. The problem, however, remains the same: The master is stuck in spi_send_hci_msg(), waiting for the DREADY signal to go low. The slave is stuck in spi_hci_flow_off_func(), waiting for an SPI transfer.如果您需要任何其他信息,请告诉我。
Thanks for your help,
Mabraun.
对此有任何更新?你会be able to provide a fixed implementation of the 5-wire SPI protocol?
谢谢,
Mabraun.
嗨mabraun,
当时这个问题被提交为更改请求,到目前为止我们有一个可能的解决方案,以克服这种僵局,但它需要花一些时间来测试并评估任何问题或局限性。我将更多地对此或下周有关这个的信息,我会告诉你。
We are sorry for any inconvenience.
谢谢mt_dialog.
Hi MT_dialog,
谢谢你的更新,这是一个很棒的新闻。请保持让我知道最新消息。
Regards,
Mabraun.