主题中讨论的其他器件: ADS125H02、 HALCOGEN
我已将 SPI2配置为从器件、MIBSPI1配置为主器件、两者都使用 DMA。 当 MIBSPI1未被使用时、SPI2工作正常、但是当 MIBSPI1开始数据传输时、SPI2通信失败。 据我所见、DMA 缓冲区中的数据被移位了几位。
有3个 ADC 芯片连接到 MIBSPI 端口、MCU 以7.2K 的采样率从每个 ADC 芯片读取数据。 SPI2和 MIBSPI1分别使用 BTC 和 FTC DMA 中断。 我还更改了 sys_dma.c 中的 dmaFTCAInterrupt 函数、并在触发 FTC 中断时调用另一个函数。
另一件事是 SPI2的数据大小不是固定的。 它首先接收3个16位字作为标头。 此报头包含封装尺寸、然后 MCU 将 DMA 缓冲区尺寸更改为发送/接收报头中定义的字节数。
当 SPI2配置为 ISR 模式时、它在高达4MHz 的频率下正常工作。
#define CONFIG_SPI_TX_DMA_CH DMA_CH13 #define CONFIG_SPI_RX_DMA_CH DMA_CH12 #define CONFIG_SPI_TX_DMA_REQ 3ul #define CONFIG_SPI_RX_DMA_REQ 2ul #define CONFIG_SPI_HEADER_SIZE 3 #define CONFIG_SPI_PORT spiREG2 #define CONFIG_SPI_TX_ADDR ((uint32_t)(&(CONFIG_SPI_PORT->DAT1)) + 2) #define CONFIG_SPI_RX_ADDR ((uint32_t)(&(CONFIG_SPI_PORT->BUF)) + 2) void dmaConfigSPICtrlTxPacket(g_dmaCTRL * g_dmaCTRLPKT_TX, uint32 sadd, uint32 dadd, uint16 FrameCnt) { g_dmaCTRLPKT_TX->SADD = sadd; /* source address */ g_dmaCTRLPKT_TX->DADD = dadd; /* destination address */ g_dmaCTRLPKT_TX->CHCTRL = 0; /* channel control */ g_dmaCTRLPKT_TX->FRCNT = FrameCnt; /* frame count */ g_dmaCTRLPKT_TX->ELCNT = 1; /* element count */ g_dmaCTRLPKT_TX->ELDOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT_TX->ELSOFFSET = 0; /* element source offset */ g_dmaCTRLPKT_TX->FRDOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT_TX->FRSOFFSET = 0; /* frame source offset */ g_dmaCTRLPKT_TX->PORTASGN = 4; /* port b */ g_dmaCTRLPKT_TX->RDSIZE = ACCESS_16_BIT; /* read size */ g_dmaCTRLPKT_TX->WRSIZE = ACCESS_16_BIT; /* write size */ g_dmaCTRLPKT_TX->TTYPE = FRAME_TRANSFER; /* transfer type */ g_dmaCTRLPKT_TX->ADDMODERD = ADDR_INC1; /* address mode read */ g_dmaCTRLPKT_TX->ADDMODEWR = ADDR_FIXED; /* address mode write */ g_dmaCTRLPKT_TX->AUTOINIT = AUTOINIT_ON; /* autoinit */ } void dmaConfigSPICtrlRxPacket(g_dmaCTRL * g_dmaCTRLPKT_RX, uint32 sadd, uint32 dadd, uint16 FrameCnt) { g_dmaCTRLPKT_RX->SADD = sadd; /* source address */ g_dmaCTRLPKT_RX->DADD = dadd; /* destination address */ g_dmaCTRLPKT_RX->CHCTRL = 0; /* channel control */ g_dmaCTRLPKT_RX->FRCNT = FrameCnt; /* frame count */ g_dmaCTRLPKT_RX->ELCNT = 1; /* element count */ g_dmaCTRLPKT_RX->ELDOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT_RX->ELSOFFSET = 0; /* element source offset */ g_dmaCTRLPKT_RX->FRDOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT_RX->FRSOFFSET = 0; /* frame source offset */ g_dmaCTRLPKT_RX->PORTASGN = 4; /* port b */ g_dmaCTRLPKT_RX->RDSIZE = ACCESS_16_BIT; /* read size */ g_dmaCTRLPKT_RX->WRSIZE = ACCESS_16_BIT; /* write size */ g_dmaCTRLPKT_RX->TTYPE = FRAME_TRANSFER; /* transfer type */ g_dmaCTRLPKT_RX->ADDMODERD = ADDR_FIXED; /* address mode read */ g_dmaCTRLPKT_RX->ADDMODEWR = ADDR_INC1; /* address mode write */ g_dmaCTRLPKT_RX->AUTOINIT = AUTOINIT_ON; /* autoinit */ } void setConfigSPIDMA(void) { g_dmaCTRL g_dmaCTRLPKT; dmaEnableInterrupt(CONFIG_SPI_RX_DMA_CH, BTC); //Block transfer complete dmaReqAssign(CONFIG_SPI_RX_DMA_CH, CONFIG_SPI_RX_DMA_REQ); //SPI2 RX dmaReqAssign(CONFIG_SPI_TX_DMA_CH, CONFIG_SPI_TX_DMA_REQ); //SPI2 TX dmaConfigSPICtrlTxPacket(&g_dmaCTRLPKT, (uint32_t)&ResponseData, CONFIG_SPI_TX_ADDR, CONFIG_SPI_HEADER_SIZE); dmaSetCtrlPacket(CONFIG_SPI_TX_DMA_CH, g_dmaCTRLPKT); dmaConfigSPICtrlRxPacket(&g_dmaCTRLPKT, CONFIG_SPI_RX_ADDR, (uint32_t)&RX_Data.PacketArray, CONFIG_SPI_HEADER_SIZE); dmaSetCtrlPacket(CONFIG_SPI_RX_DMA_CH, g_dmaCTRLPKT); dmaSetChEnable(CONFIG_SPI_RX_DMA_CH, DMA_HW); //SPI2 RX, hardware triggering dmaSetChEnable(CONFIG_SPI_TX_DMA_CH, DMA_HW); //SPI2 TX, hardware triggering dmaSetPriority(CONFIG_SPI_RX_DMA_CH, HIGHPRIORITY); dmaSetPriority(CONFIG_SPI_TX_DMA_CH, HIGHPRIORITY); CONFIG_SPI_PORT->GCR1 = (CONFIG_SPI_PORT->GCR1 & 0xFFFFFFFFU) | (0x1 << 24); //Enable SPI CONFIG_SPI_PORT->INT0 = (0x1 << 16); //SPI_DMAREQ; Enable DMA REQ only after setting the SPIEN bit to 1. } void sendAndGetSPIData(uint32_t outputBuffer, uint32_t inputBuffer, uint32_t ucDataLength) { dmaRAMREG->PCP[CONFIG_SPI_TX_DMA_CH].ISADDR = outputBuffer; dmaRAMREG->PCP[CONFIG_SPI_TX_DMA_CH].IDADDR = CONFIG_SPI_TX_ADDR; dmaRAMREG->PCP[CONFIG_SPI_TX_DMA_CH].ITCOUNT = (ucDataLength << 16U) | 1; dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].IDADDR = inputBuffer; dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].ISADDR = CONFIG_SPI_RX_ADDR; dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].ITCOUNT = (ucDataLength << 16U) | 1; dmaSetChEnable(CONFIG_SPI_RX_DMA_CH, DMA_HW); //SPI2 RX, hardware triggering dmaSetChEnable(CONFIG_SPI_TX_DMA_CH, DMA_HW); //SPI2 TX, hardware triggering CONFIG_SPI_PORT->GCR1 = (CONFIG_SPI_PORT->GCR1 & 0xFFFFFFFFU) | (0x1 << 24); //Enable SPI CONFIG_SPI_PORT->INT0 = (0x1 << 16); //SPI_DMAREQ; Enable DMA REQ only after setting the SPIEN bit to 1. while((dmaREG->PEND & (1ul << 0)) != 0ul); } void getConfigSPIData(uint32_t buffer, uint32_t ucDataLength) { dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].IDADDR = buffer; dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].ISADDR = CONFIG_SPI_RX_ADDR; dmaRAMREG->PCP[CONFIG_SPI_RX_DMA_CH].ITCOUNT = (ucDataLength << 16U) | 1; dmaSetChEnable(CONFIG_SPI_RX_DMA_CH, DMA_HW); //SPI2 RX, hardware triggering dmaSetChEnable(CONFIG_SPI_TX_DMA_CH, DMA_HW); //SPI2 TX, hardware triggering CONFIG_SPI_PORT->GCR1 = (CONFIG_SPI_PORT->GCR1 & 0xFFFFFFFFU) | (0x1 << 24); //Enable SPI CONFIG_SPI_PORT->INT0 = (0x1 << 16); //SPI_DMAREQ; Enable DMA REQ only after setting the SPIEN bit to 1. while((dmaREG->PEND & (1ul << 0)) != 0ul); } void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel) { CONFIG_SPI_PORT->INT0 &= ~(1ul << 16); CONFIG_SPI_PORT->GCR1 &= ~(0x1 << 24); ProcessSPI2(); } void dmaFTCAInterrupt(void) { uint32 offset = dmaREG->FTCAOFFSET; if (offset != 0U) { dmaGroupANotificationFTC(FTC, offset - 1U); } } void dmaBTCAInterrupt(void) { uint32 offset = dmaREG->BTCAOFFSET; if (offset != 0U) { dmaGroupANotification(BTC, offset - 1U); } }