怀疑N32系列MCU的SPI接收DMA功能有bug,**厂家核实一下
我用N32G4FR读取SPI Flash的厂家ID,时序是发送2个字节,读取3个字节。
将SPI设置为全双工模式,不开中断何DMA,用查询方式,大概代码如下:
for (n=0;n<5;n++)
{
SPI_I2S_TransmitData(SPI3, spi_tx[n]);
while(SPI_I2S_GetStatus(SPI3, SPI_I2S_TE_FLAG) == RESET);
while(SPI_I2S_GetStatus(SPI3, SPI_I2S_RNE_FLAG) == RESET);
spi_rx[n] = SPI_I2S_ReceiveData(SPI3);
}
就是发送5个字节,前两个是有效的命令字节,后面3个空字节,是为了产生SCK时钟;接收到5个字节,前两个扔掉,后面3个是正确的Flash芯片ID。
然而改为DMA方式实现,就出了问题。首先仍然用查询方式发送2个字节,然后用DMA方式读3个字节。
主要代码如下:
//首先配置RX
DMA_EnableChannel(DMA2_CH1, DISABLE);
DMA2_CH1->TXNUM = len;
DMA2_CH1->MADDR = (uint32_t)addr;
DMA_EnableChannel(DMA2_CH1, ENABLE);
//接着配置TX,输出dummy数据,否则没有CLK
DMA_EnableChannel(DMA2_CH2, DISABLE);
DMA2_CH2->TXNUM = len;
DMA2_CH2->MADDR = (uint32_t)addr;
DMA_EnableChannel(DMA2_CH2, ENABLE);
读取的数据会有错,比如本来应该读到:11 22 33,结果首次读到的是:00 11 22,把33落下了,下一次读到的是33 11 22,其中第一个33是上次没读到的最后一个字节。
发送DMA是由SPI_I2S_TE_FLAG标志触发,接收DMA是由SPI_I2S_RNE_FLAG触发,由于TE在发送字节写入缓冲器就触发,而RNE是字节传输完毕后才触发,比TE晚了8个SCK时钟,因此我怀疑:接收DMA是用TE触发的,而不是RNE,因此读到的数据比实际要滞后一个字节。
上述代码流程也在ST和AT32的MCU上是调试过,AT32的要在启动DMA之前切换一下SPI的使能,可把片内接收缓冲区清空,但是在N32上就无效。
请厂家帮忙核实一下,谢谢!
|