2017-12-08 01:48 AM
Hello everyone.
I have a strange problem where my SPI data seems to 'shift' and my DMA goes out of control (I do not have a clue why it is acting as it does). I am developing a program using the STM32L433CC together with my company's custom ASIC. I have earlier used the STM32L051C8 without problems.
My STM32L433CC runs at 80Mhz, also on the peripherals.
If I choose to run without DMA then I get proper values:
/// Enable peripheral clocks for SPI
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
/// --- SPI1 configuration ---
/// Master selection, BR: Fpclk/16, Capture on second edge SPI1->CR1 |= SPI_CR1_MSTR | SPI_CR1_CPHA | SPI_CR1_BR_1 | SPI_CR1_BR_0; /// Slave select, DMA in RX and TX- 16-bit data frame SPI1->CR2 |= SPI_CR2_SSOE | SPI_CR2_DS_3 | SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0SPI1->CR2 |= SPI_CR2_RXNEIE;
SPI1->CR1 |= SPI_CR1_SPE;/// Set priority for SPI1_IRQn
NVIC_SetPriority(SPI1_IRQn, 1); /// Enable SPI1_IRQn NVIC_EnableIRQ(SPI1_IRQn);My response for our ASIC is for 5 tries:
1110010101100001
1110010100010111
1110010101001010
1110010111010000
1110010111010111
I know for a fact that the 6 first bits should be 111001. This is show correctly for all 5 tries. It is also verified on an oscilloscope.
If I remove RX interrupt for the SPI and add DMA for TX and RX.
/// Enable peripheral clocks for DMA
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;///--- DMA1 Channel2 SPI1 RX Config ---
/// Map DMA Channel2 selection DMA1_CSELR->CSELR = (DMA1_CSELR->CSELR & ~DMA_CSELR_C2S) | (1 << DMA_CSELR_C2S_Pos); /// Set peripheral address DMA1_Channel2->CPAR = (uint32_t)&(SPI1->DR); /// Set memory address DMA1_Channel2->CMAR = (uint32_t)SPI1_RX_Data; /// Set data size DMA1_Channel2->CNDTR = (uint8_t)SPI_BUFFER_SIZE; /// Set memory increment, peripheral to memory, 16-bit transfer DMA1_Channel2->CCR |= DMA_CCR_MSIZE_0 | DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_EN;///--- DMA1 Channel3 SPI1 TX Config ---
/// Map DMA Channel3 selection DMA1_CSELR->CSELR = (DMA1_CSELR->CSELR & ~DMA_CSELR_C3S) | (1 << DMA_CSELR_C3S_Pos); /// Set peripheral address DMA1_Channel3->CPAR = (uint32_t)&(SPI1->DR); /// Set memory address DMA1_Channel3->CMAR = (uint32_t)SPI1_TX_Data; /// Set memory increment, memory to peripheral, 16-bit transfer, DMA1_Channel3->CCR |= DMA_CCR_MSIZE_0 | DMA_CCR_MINC | DMA_CCR_DIR;/// Set priority for DMA1_Channel2_IRQn
NVIC_SetPriority(DMA1_Channel2_IRQn, 2); /// Enable DMA1_Channel2_IRQn NVIC_EnableIRQ(DMA1_Channel2_IRQn);SPI_BUFFER_SIZE is just 1 so only 1 16-bit transfer is performed. I initiate transfer by using:
/// Enable DMA on SPI RX to be ready
/// for next transferDMA1_Channel2->CCR &= ~DMA_CCR_EN;
DMA1_Channel2->CNDTR = (uint8_t)SPI_BUFFER_SIZE; DMA1_Channel2->CCR |= DMA_CCR_EN;/// Enable DMA1 to initiate SPI transfer
DMA1_Channel3->CCR &=~ DMA_CCR_EN; DMA1_Channel3->CNDTR = (uint8_t)SPI_BUFFER_SIZE; DMA1_Channel3->CCR |= DMA_CCR_EN;The first 5 tries gives:
0000000001110001
0000000011100101
0000000001001011
0000000011100101
0000000001110100
If I change to 8-bit transfer and attempt to receive 2 bytes then I do not get any interrupt om the DMA_Channel2.
From the received data by DMA it looks like the data is shifted one byte. Furthermore it seems try 1, 3 and 5 are 2nd byte data while try 2 and 4 is 1st byte data. How it manages to mess it up I can not figure out.
Has anyone experienced similar problems or has any ideas how to fix it?
Regards
Sebastian Aslund
#spi-over-dma #stm32l4 #stm32l4-spi