2017-05-30 09:56 AM
Hi All,
I've got a
Nucleo-F103RB, and have been able to successfully implement an SPI interface to an FPGA, using the software to control the flow of the SPI.
I want to now move this across to the DMA, such that the DMA transmits and reads the data from the SPI. I've gotten the transmission part of it working correctly; data goes across correctly and the FPGA recognises it.
The issue that I have is the STM DMA reading the data, it doesn't come in the correct format:
The data from the FPGA is in 8 packets
(1 byte each), with the 3 MSB bits indicating its position within the sequence ('000' is first, '001', second, etc.), when I read the data that the DMA has received it doesn't follow this sequence it's all over the place (I know that the FPGA is transmitting the data correctly, as I've gotten this working in software). So I wonder if there are some conflicts with using the DMA, as to read data via SPI, you need to transmit data.
Below is a copy of initializing the DMA for both the transmission and receiving of data with the SPI. I've configured the SPI such that it uses the hardware Slave Select.
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Enable DMA1 clock
// DMA1 Channel 3 for SPI transmission
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DMA_StructInit(&FPGA_DMA); FPGA_DMA.DMA_BufferSize = FPGA_ArraySize*FPGA_bytesperPack; // Define the size of data to be DMA'd FPGA_DMA.DMA_DIR = DMA_DIR_PeripheralDST; // Read from memory FPGA_DMA.DMA_M2M = DMA_M2M_Disable; // Disable the Memory to Memory transfer FPGA_DMA.DMA_MemoryBaseAddr = (uint32_t) &FPGATransmitArray[0]; // Point to Transmit array FPGA_DMA.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // State data is 8bits FPGA_DMA.DMA_MemoryInc = DMA_MemoryInc_Enable; // Increment the memory pointer FPGA_DMA.DMA_Mode = DMA_Mode_Normal; // Normal DMA mode (not circular) FPGA_DMA.DMA_PeripheralBaseAddr = (uint32_t) (&(SPI_Port[SPIx]->DR)); // 0x4001300c FPGA_DMA.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // State data is 8bits wide FPGA_DMA.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // Disable peripheral pointer increment FPGA_DMA.DMA_Priority = DMA_Priority_High; // High priorityDMA_Init(DMA1_Channel3, &FPGA_DMA); // Initialise the DMA1 channel 3 (SPI_TX)
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE); // Enable the Complete Transfer Interrupt DMA_ITConfig(DMA1_Channel3, DMA_IT_TE, ENABLE); // Enable the error interruptNVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn; // DMA1 Channel 3 interrupt
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0xFF; // Lowest priority NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0xFF; // Lowest priority NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // Enable DMA1 Channel 3 interruptNVIC_Init(&NVIC_InitStructure);
SPI_SSOutputCmd(SPI_Port[SPIx], ENABLE);
SPI_I2S_DMACmd(SPI_Port[SPIx], SPI_I2S_DMAReq_Tx, ENABLE); // Enable SPI DMA interface (Txd)//DMA_Cmd(DMA1_Channel3, ENABLE);
// DMA1 Channel 2 for SPI reading
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DMA_StructInit(&FPGA_DMA); FPGA_DMA.DMA_BufferSize = FPGA_ArraySize*FPGA_bytesperPack; // Define the size of data to be DMA'd FPGA_DMA.DMA_DIR = DMA_DIR_PeripheralSRC; // Read from peripheral FPGA_DMA.DMA_M2M = DMA_M2M_Disable; // Disable the Memory to Memory transfer FPGA_DMA.DMA_MemoryBaseAddr = (uint32_t) &FPGAReadArray[0]; // Point to Transmit array FPGA_DMA.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // State data is 8bits FPGA_DMA.DMA_MemoryInc = DMA_MemoryInc_Enable; // Increment the memory pointer FPGA_DMA.DMA_Mode = DMA_Mode_Normal; // Normal DMA mode (not circular) FPGA_DMA.DMA_PeripheralBaseAddr = (uint32_t) (&(SPI_Port[SPIx]->DR)); // 0x4001300c FPGA_DMA.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // State data is 8bits wide FPGA_DMA.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // Disable peripheral pointer increment FPGA_DMA.DMA_Priority = DMA_Priority_High; // High priorityDMA_Init(DMA1_Channel2, &FPGA_DMA); // Initialise the DMA1 channel 2 (SPI_RX)
DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE); // Enable the Complete Transfer Interrupt DMA_ITConfig(DMA1_Channel2, DMA_IT_TE, ENABLE); // Enable the error interruptNVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn; // DMA1 Channel 2 interrupt
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0xFF; // Lowest priority (but higher than transmission) NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0xFF; // Lowest priority NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // Enable DMA1 Channel 2 interruptNVIC_Init(&NVIC_InitStructure);
//SPI_SSOutputCmd(SPI_Port[SPIx], ENABLE);
SPI_I2S_DMACmd(SPI_Port[SPIx], SPI_I2S_DMAReq_Rx, ENABLE); // Enable SPI DMA interface (Rxd)The interrupts are configured such that they switch off the DMA that triggered the interrupt.
Is there anything which I am missing which will make the SPI DMA read correctly?
Regards,
Thomas
Solved! Go to Solution.
2017-05-31 03:19 AM
Also requesting the same seqeunce twice I get different results
Sounds like sampling on the incorrect edge (i.e. incorrect CPOL/CPHA setting).
JW
2017-05-30 01:46 PM
when I read the data that the DMA has received it doesn't follow this sequence it's all over the place
Specifically?
Shifted by a bit, shifted by a byte, one bit of each byte appears in the neighbouring byte, anything else?
Transfer any well-recognizable sequence? Perhaps plainly looping back?
Do both DMA finish at the same time?
I'd enable Rx first to avoid risk of losing a byte or a couple of them.
JW
2017-05-31 02:13 AM
Hi JW,
So it appears that extra bits are introduced next to the highest MSB, or removed. Also requesting the same seqeunce twice I get different results (they should be the same)
Below is a sequence:
Expected Read
0x1F 0x1F
0x20 0xA0 <extra bit added near to highest MSB
0x40 0x40
0x60 0x20 <highest MSB removed
0x80 0xC0 <extra bit added
0xA0 0xD0 <extra bit added
0xC0 0xE0 <extra bit added
0xE0 0xF0 <extra bit added
0x1F 0x1F
0x30 0x30
0x40 0x40
0x60 0x60
0x80 0x80 (second try got 0x40)
0xA0 0x60 (second try got 0xD0)
0xC0 0x60 (second try got 0xE0)
0xF0 0xF0 (second try got 0xF8)
2017-05-31 03:19 AM
Also requesting the same seqeunce twice I get different results
Sounds like sampling on the incorrect edge (i.e. incorrect CPOL/CPHA setting).
JW
2017-05-31 03:45 AM
Ah....Right, so looks like I was messing with the SCLK clock speed, and hadn't quite brought it back to a working speed.
Once set this up correctly, the DMA read things correctly. Thanks Jan.