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.
你好!
我计划在 mibspi 上使用 DMA、目前正在测试模块、但我很难理解它的确切工作方式。
Mibspi 必须处理至少为2个字节到最多为823个字节的数据大小、并且可能会有所不同。 问题是使用 DMA 传递823字节数据包、我提出了2个选项。
使用 Mibspi 的所有128字缓冲器、将其作为128个元素、7个帧数据传递。 在这种情况下、(128*7)-823 = 73字节将是冗余的。 我不知道我是否正确、但如果 DMAxCOUNT 实际上是 DMA 传输的元素数量、那么我可以在 Mibspi 和 DMA 传输(接收) 823字节数据时停止它。
2.仅使用 mibspi 的1字缓冲区、将其作为1个元素、823帧数据传递、反之亦然。 写入 TX 的单个缓冲器并从 Rx 的单个缓冲器中读取。
我尝试了这两种方法来实现这一目标。 不幸的是、它运行得不是很好。 实际上、我甚至不确定这些是否可行。 我已经尝试更改了许多控制值、最常见的问题是 、mibspi Rx DMA 接收到的数据 变为相同的数据(例如 :接收"abcdefgh"变为"cccccccccccccccc")。 我想知道使用数字回送是否必须实现 这一点。
我会详细介绍一下、但 我想知道这些选项中是否有一个是可行的。
对于这种通信、最好使用兼容的 SPI、但 spi5 TX/Rx 和 sci TX/Rx 共享相同的 DMA 请求行、并且由于我必须同时使用这两者、我想使用 mibspi5并为 mibspi5使用其他 DMA 请求行。
感谢您的帮助!
您好!
只有当 DMACNTLEN 寄存器中的大计数位置位时、才使用 DMAxCOUNT。 DMAxCOUNT 中的 ICOUNT 是 DMA 传输的数量、而不是元素数量。 如果在 DMA 配置中使用帧传输、则 ICOUNT 定义帧编号。 在您的示例中、ICOUNT=7-1=6。 传输的元素数量为128*7=896。
每个 DMA 传输可轻松传输1个元素。
附件是我的 MibSPI+DMA 工作示例:
您好、Wang、
我认为您的示例未附在后面? 我检查并参考了您的 另一个 RM48L952示例:使用 DMA 的 MibSpi Tx 和 Rx -其他微控制器论坛-其他微控制器- TI E2E 支持论坛、但仍然无法正确完成。
我当前用于测试的设计如下:
txBuffer 和 rxBuffer 均为128字节大小、但数据总共为66字节。
static uint8_t txBuffer[128] = "abcdefghijklmnopqrstuvwxyz\r\n0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n"; static uint8_t rxBuffer[128] = {0};
数据格式与默认格式相同、除非 charlen 为8位。 传输组缓冲器模式为7 (挂起读取/写入)、以便 DMA 可以同步、而组缓冲器大小为1、以便 Mibspi 和 DMA 可以用于传输任何大小的数据。
在 DMA 控制数据包中、元素数量为1、帧数量为66、以发送并得到总计66字节。 此外、还可以通过更改帧计数来轻松更改数据长度。 元件的大小为8位、ttype 为 block_transfer、因此可通过单次激活来实现数据通信。
void setDmaMibspiPacketCommon(g_dmaCTRL *packet) { packet->CHCTRL = 0; packet->ELCNT = 1; packet->FRCNT = 66; packet->PORTASGN = 4; packet->RDSIZE = ACCESS_8_BIT; packet->WRSIZE = ACCESS_8_BIT; packet->TTYPE = BLOCK_TRANSFER; packet->ADDMODERD = ADDR_OFFSET; packet->ADDMODEWR = ADDR_OFFSET; packet->AUTOINIT = AUTOINIT_OFF; }
对于传输、源为 txBuffer、帧偏移为1、而目的为 TX[0]。data、两个偏移都为0。 对于接收、源为 Rx[0].data、两个偏移量都为0、而目的为 rxBuffer、帧偏移量为1。
mibspiRAM_t* ram = ((mibspiRAM_t *)0xFF0A0000U); void setDmaMibspiPacketTransmit(g_dmaCTRL *packet) { packet->ELSOFFSET = 0; packet->FRSOFFSET = 1; packet->SADD = (uint32_t)txBuffer; packet->ELDOFFSET = 0; packet->FRDOFFSET = 0; packet->DADD = (uint32_t)(&(ram->tx[0].data)); } void setDmaMibspiPacketReceive(g_dmaCTRL *packet) { packet->ELSOFFSET = 0; packet->FRSOFFSET = 0; packet->SADD = (uint32_t)(&(ram->rx[0].data)); packet->ELDOFFSET = 0; packet->FRDOFFSET = 1; packet->DADD = (uint32_t)rxBuffer; }
以下代码是主例程。 在进入循环之前、程序设置 DMA 控制数据包、启用 DMA、设置请求线路、为 DMA Rx 启用 BTC 中断。
在主循环中的每次迭代中、程序清除缓冲区、设置 DMA 通道使能、设置 DMA 请求和开始传输、然后等待直到完成。
void mibspiMasterDmaTest(){ g_dmaCTRL dmaRxPacket = {0}; g_dmaCTRL dmaTxPacket = {0}; uint32_t dmaReqlineMibspiRx = 28; /* mibspi5[14] */ uint32_t dmaReqlineMibspiTx = 29; /* mibspi5[15] */ uint32_t dmaChannelRx = DMA_CH0; uint32_t dmaChannelTx = DMA_CH1; int i; /* Digital loopback test mode */ mibspiEnableLoopback(mibspiREG5, Digital_Lbk); setDmaMibspiPacketCommon(&dmaTxPacket); setDmaMibspiPacketCommon(&dmaRxPacket); setDmaMibspiPacketTransmit(&dmaTxPacket); setDmaMibspiPacketReceive(&dmaRxPacket); /* Dma request line channel for mibspi5 */ mibspiREG5->DMACTRL[0] |= (14 << 20) | (15 << 16); /* Using oneshot mode at mibspi dma. Using it does not change behaviour */ // mibspiREG5->DMACTRL[0] |= (1 << 31); // mibspiREG5->DMACNTLEN = 1; // mibspiREG5->DMACOUNT[0] |= (65 << 16); dmaEnable(); dmaReqAssign(dmaChannelRx, dmaReqlineMibspiRx); dmaReqAssign(dmaChannelTx, dmaReqlineMibspiTx); dmaSetCtrlPacket(dmaChannelRx, dmaRxPacket); dmaSetCtrlPacket(dmaChannelTx, dmaTxPacket); /* Tx complete interrupt is not needed */ dmaEnableInterrupt(dmaChannelRx, BTC); /* Keep transfering */ while(1){ /* Wait between spi communications */ for(i = 0; i < 10000000; i++){ } /* Clear buffers to check if mibspi and dma are working correctly */ for(i = 0; i < 128; i++){ rxBuffer[i] = 0; ram->tx[i].data = 0; } /* Set dma ready */ dmaSetChEnable(dmaChannelRx, DMA_HW); dmaSetChEnable(dmaChannelTx, DMA_HW); mibspiREG5->DMACTRL[0] |= (1 << 15) | (1 << 14); /* Start transfering */ mibspiTransfer(mibspiREG5, 0); /* Wait until communication is done */ while(mibspiIsTransferComplete(mibspiREG5, 0) != true) { } } }
在 DMA 通知中、程序通过 UART (sci)将 rxBuffer 输出到 PC。
void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel) { /* Send data to console */ sciSend(sciREG, 128, rxBuffer); }
预期行为为打印
abcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
PC 端子。 但是、它会打印相同的随机字符66次、主要是 c、g 或 h。当我在传输结束后立即读取 mibspiRAM5存储器时、TX 有10 (\n)是正确的、但 Rx 有104 (h)、这是不正确的。
我认为我做得正确、但看起来不正确。 问题可能出在哪呢?
请对 tType 使用帧传输。
您好、Wang、
将 tType 更改为 Frame transfer (帧传输)并禁用 OneShot for Transfer Group (传输组)使其工作正常。
现在、我尝试使用 DMA OneShot 和 DMAxCOUNT 值来传输数据、因此在下面部分中没有注释。
void mibspiMasterDmaTest(){ ... mibspiREG5->DMACTRL[0] |= (1 << 31); mibspiREG5->DMACNTLEN = 1; mibspiREG5->DMACOUNT[0] |= (65 << 16); ... while(1){ ... } }
它会传输数据、但仅传输一次。 我查看了寄存器值、它显示 RxBuf 已满。 此外、TG0的已完成中断和已挂起中断都已置位。 在 针对 Rx 调用 DMA BTC 通知时、TG 启用且 TG 控制寄存器中触发的 TG 为1。
我是否需要更改其他一些值才能使其正常工作?
如果 DMACTRL 寄存器的第31位(OneShot)被置位、则 DMA 传输(ICOUNT + 1)帧将被置位。
如果 TGxCTRL 寄存器的 OneShot 被置位、MibSPI 只为每个触发事件传输1次(如果 TG 大小为1个缓冲区、则只传输1个缓冲区)。