主题中讨论的其他器件:SysConfig
工具与软件:
你(们)好、
我想使用 DMA 实现 CAN RX。
是否有任何可供我参考和学习的相应文档、教程、SysConfig 和代码示例?
不幸的是,我没有找到很多合适的。
提前非常感谢。
Matze
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具与软件:
你(们)好、
我想使用 DMA 实现 CAN RX。
是否有任何可供我参考和学习的相应文档、教程、SysConfig 和代码示例?
不幸的是,我没有找到很多合适的。
提前非常感谢。
Matze
尊敬的 Matze:
我们没有确切的 CAN DMA 示例、但您可以使用基本的 CAN 示例并添加 DMA 以在缓冲区之间移动数据。 重要的部分是正确配置 DMA、以处理从源到目标的数据传输。
对于 RX、源将是 CAN RX 寄存器、目标将是一些您设置用于接收数据的缓冲区/阵列。 传输次数应为预期报文的大小除以数据包大小。 您需要将目标地址递增、而不是将源地址递增。
TX 与源递增且目的保持不变完全相反。 转移的数量和规模将是相同的意识形态。
我建议在 RX 侧通过 CAN RX 中断触发 DMA (使用事件系统)。
值得关注的示例:
此致、
Luke
谢谢!
对于 RX 源、我认为必须使用 RX FIFO0起始地址172
因为我使用的是
| 过滤器元素配置 | 如果过滤器匹配、则存储在 Rx FIFO 0中 |
但是、当我查看"Memory"视图时、我只看到以下内容:

________________________________________________________________
关于"memory"视图的第1个问题:
地址192被"DL_MCAN_msgRAMConfig"占用、尽管我配置了10个 FIFO0元素、并且 FIFO0应在332结束、而不是192结束。

________________________________________________________________
第二个关于存储器视图的问题:
当我收到 CAN 消息时、该消息不会显示在存储器视图中。 所有值保持不变。 接收本身起作用、因为消息出现在我的 rxMsg-Struct 中。 但为什么我在存储器视图中看不到它?
________________________________________________________________
编辑:恐怕我把 RAM 和 ROM 混淆了。 是这样吗? 我在 RAM 中配置 FIFO0元素的地址。 存储器视图显示了 ROM、对吧?
是否可以查看消息 RAM FIFO 的内容?
当我指定源地址时、我如何指示 DMA 引用 RAM 而不是 ROM?
________________________________________________________________
[报价用户 id="452230" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1484192/mspm0g3507-can-rx-with-dma/5700238 #5700238"]uart_rx_multibyte_fifo_interrupts我查看了此示例并尝试根据我的项目调整此示例项目中 DMA 的实现。
我在 main_msp***.c 中添加了以下行:
volatile uint8_t gRxDataframe[16];
int main(void)
{
SYSCFG_DL_init();
/* Configure DMA source, destination and size */
DL_DMA_setSrcAddr(DMA, DMA_CH0_CANRX_CHAN_ID, (uint32_t)(CAN_Info.gMCAN0MsgRAMConfigParams.rxFIFO0startAddr));
DL_DMA_setDestAddr(DMA, DMA_CH0_CANRX_CHAN_ID, (uint32_t) &gRxDataframe[0]);
DL_DMA_enableChannel(DMA, DMA_CH0_CANRX_CHAN_ID);
/* Confirm DMA channel is enabled */
while (false == DL_DMA_isChannelEnabled(DMA, DMA_CH0_CANRX_CHAN_ID)) {
__BKPT(0);
}
NVIC_EnableIRQ(MCAN0_INST_INT_IRQN);
gCheckCAN = false;
DL_SYSCTL_disableSleepOnExit();
/* Wait in SLEEP mode until DMA interrupt is triggered */
while (false == gCheckCAN) {
__WFE();
}
DL_SYSCTL_enableSleepOnExit();
我对 SysConfig 进行了以下更改:
DMA.associatedChannels.create(1); DMA.associatedChannels[0].addressMode = "f2b"; DMA.associatedChannels[0].srcLength = "BYTE"; DMA.associatedChannels[0].dstLength = "BYTE"; DMA.associatedChannels[0].configureTransferSize = true; DMA.associatedChannels[0].transferMode = "FULL_CH_REPEAT_BLOCK"; DMA.associatedChannels[0].transferSize = 16; DMA.associatedChannels[0].destIncrement = "INCREMENT"; DMA.associatedChannels[0].enableInterrupt = true; DMA.associatedChannels[0].$name = "DMA_CH0_CANRX"; DMA.associatedChannels[0].peripheral.$assign = "DMA_CH0";
我还需要做什么?
________________________________________________________________
我建议在 RX 端通过 CAN RX 中断触发 DMA (使用事件系统)。
我尝试了许多不同的可能性、但在 SysConfig 中找不到任何解决方案如何将 CAN Rx 中断链接到 DMA (通过事件系统进行任何连接触发)。 请帮助我理解这一点并找到正确的配置方法。
我有个想法、DL_DMA_startTransfer()可能就是我要查找的函数。
我将其添加到了 CAN RX 中断中、但在 Rx_Interrupt 和执行后的观察表达式"gRxDataframe"中看不到任何数据DL_DMA_startTransfer()。

提前感谢!
Matze
尊敬的 Matze:
对于 RX、DMA 设置看起来正确、我没有设置传输数量、因此请确保对于每次传输要传输的数据量、使用正确的数字。 我必须仔细检查、但 CAN 模块只有 CPU 中断、因此您的过程是正确的、即创建中断处理程序来在收到 RX 中断时启动 DMA 传输。
不过、显示的存储器地址不是 ROM、它是正常的闪存区域。 我正在查看您需要查看的地址空间、以查看 RX CAN 缓冲区。

此致、
Luke
您好、谢谢!
我没有看到设置的传输次数、因此请确保您对于每次传输的传输数据量具有正确的数字。
"转账数量"一词是什么意思?
________________________________________________________________
[报价 userid="452230" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1484192/mspm0g3507-can-rx-with-dma/5704929 #5704929"]我正在研究您需要查看哪个地址空间来查看 RX CAN 缓冲区。谢谢、我在地址0x2010.0000中快速找到了 CAN RX FIFO0。 我可以看到存储器中从该地址开始接收到的每个 CAN Msg。

我想知道为什么每个 CAN 帧在该内存中占用42 * 32位。

根据图21-21、我预期一个具有8个数据字节的 CAN 帧的大小为4 * 32位。
请澄清;)
________________________________________________________________
还有一个简短的问题:是否可以调整视图以便我在一个新行中看到每个新消息(即在此内存视图中的每个 CAN 帧后有一个换行符)?
________________________________________________________________
我还在"memory"视图中看到了"&gRxDataframe[0]、DMA 传输的目标。 但是、即使我收到一条 CAN 消息、存储器值也保持为"0"、在 FIFO 存储器视图中看到它、并且-通过断点调试- "DL_DMA_startTransfer (DMA、DMA_CH0_CANRX_CHAN_ID);"已执行。
我遗漏了什么想法? 仍然会出现什么问题?
提前感谢! 此致!
Matze
尊敬的 Matze:
传输次数为 DMASZ 位、传输大小应为需要传输的总数据大小/传输大小(字节、字、2个字等)。
这里您的数据看起来确实很奇怪、如果您的数据只应该为1或0、那么看起来像是您只在整个32位 int 中存储1位。。。
对于元素地址、您应该查看如何 创建 DL_MCAN_readMsgRam ()函数(位于 dl_mcan.c 中)。 我将稍微分解一下、但我确实建议查看该函数、基本上您需要遵循 FIFO 路径、而不是 readMsg 函数、您可以使用 DMA、将 elemAddr 作为源地址、将缓冲区作为目标地址。
正如您在元素结构中看到的、MCAN 数据包具有一组标头信息和数据。 DL_MCAN_readMsg 函数将分解所有位并将它们放入正确的组织中、因为 DMA 只会直接从寄存器中拉取数据。 因此、您需要对传输进行结构化、以便以预期数据包的倍数传输和递增所有数据。 应使用增量和传输大小来覆盖整个预期数据集

---
/*Start Addr intitial value is from your MCAN_RXF0C_F0SA setting ElemSize inital value is from your MCAN_RXESC_F0DS idx is from your MCAN_RXF0S_F0GI setting*/ startAddr = (uint32_t)(startAddr << 2U); elemSize = DL_MCAN_getMsgObjSize(elemSize); elemSize *= 4U; elemAddr = startAddr + (elemSize * idx); elemAddr += MCAN_MCAN_MSG_MEM; DL_MCAN_readMsg((uint32_t) mcan, elemAddr, elem);