您好!
我会尽量简洁地解释问题,但如果有问题不清楚,请问我。 我使用的是 TDA3x EVM 板、最近在一些代码中发现了一个错误、否则效果会很好。
一般的想法是使用 SPI 与某些外部器件进行双向通信。 传输的数据可以非常小、也可以具有几 KB 的大小、每个数据包大小的相关信息位于其标头中。 对于较大的数据传输、EDMA 用于释放处理器的这种不必要负载。 意识到数据包很大、需要由 EDMA 处理、这发生在 SPI ISR 内部的传输过程中。 在这种情况下,SPI 将禁用 SPI 模块中断,根据它需要传输的大小配置 EDMA, 将触发级别更改为1、以便它可以与 EDMA 控制器配合使用、然后启用对 EDMA 控制器的请求以处理其余传输。 当 EDMA 传输完成且 SPI 再次启用中断时、触发电平将恢复为原始值。 由于此过程非常快、McSPI FIFO 的大小可确保不会丢失任何数据。
当我将某些日志函数放在此 ISR 中时,会发生意外行为。 根据我们的配置、一些计算表明、该打印函数消耗的时间超过14微秒(这是我们的触发级别)。 FIFO 内部大约为13.5微秒、因此如果 FIFO 缓冲区在我配置 EDMA 之前达到触发电平、一些数据将丢失、通信中断。 配置 EDMA 后从 ISR 内部打印日志不会产生任何问题。
据我所知、同一 ISR 本身不能中断、但我尝试在 ISR 内部手动禁用中断信号、但这无法解决问题(无论如何、硬件在处理中断时应禁用中断)。 当我在 ISR 持续时间内暂时将触发级别更改为更高的值并在退出 ISR 之前将其恢复为"已解决"问题。 我认为这不是一个好的解决方案、所以我想了解这个问题的原因、以便我可以集成一个更好的解决方案。 作为参考、我将粘贴 ISR 的某些部分(粘贴代码会破坏缩进、但 无论如何这只是一个示例)。
静态空 CustomSpiIsr (空)
{
这里是变量声明
{...
}
/*在此示例中,我仅使用 MCSPI_IRQENABLE_RX0_FULL 中断
*因此、如果发生中断、我知道这是一个中断、但原始代码是
*不同并也处理 WKE 中断
*
IRQ_STATUS = McSPIIntStatusGet (MCSPI1_BASE_ADDRESS);
/*将 Rx 完全事件的触发级别提高到0x33以避免
在 ISR 中重新触发事件
*
McSPIFIFOTrigLvlSet (MCSPI1_base_address、
0x33、
0x0、
MCSPI_TX_RX_MODE);
/*这是自定义打印功能,植入细节并不重要
*重要的是,它所需的时间比所需的时间要长
*以使下一个 RX_FULL 事件发生
*
CustomPrintFunction ("内部 ISR.\n");
/*这是已删除的 ISR 使用的不相关部分的一些示例
*因为我只想让您关注我在帖子中描述的内容
*
if (IRQ_STATUS 和 MCSPI_IRQENABLE_RX0_FULL_ENABLE_MASK)
{
/*SPI_TRIGGER_LVL 的值为9*/
对于(I = 0;I < SPI_TRIGGER_LVL;I++)
{
receiveBuffer[i]=(uint8_t) McSPIReceiveData (MCSPI1_base_address、gChNum);
}
#对接收到的数据进行计算
如果(#使用 DMA 的条件)
{
McSPIIntDisable (MCSPI1_BASE_ADDRESS、MCSPI_IRQENABLE_RX0_FULL_ENABLE_MASK);
McSPIFIFOTrigLvlSet (MCSPI1_base_address、
0x1、
0x0、
MCSPI_TX_RX_MODE);
在此处自定义配置 DMA 参数
McSPIDMAEnable (MCSPI1_BASE_ADDRESS、
MCSPI_CH0CONF_DMAR_MASK、
MCSPI_CH_NUM);
}
其他
{
否则
}
McSPIIntStatusClear (MCSPI1_BASE_ADDRESS、MCSPI_IRQSTATUS_RX0_FULL_MASK);
}
/*将 Rx 完全事件的触发级别恢复为原始*/
McSPIFIFOTrigLvlSet (MCSPI1_base_address、
SPI_TRIGGER_LVL
0x0、
MCSPI_TX_RX_MODE);
}
提前感谢、
Theodore