Implementing SPI DMA on STM32F4xx in freeRTOS


I’m attempting to implement simple SPI in RX Master Receive mode using DMA with no success.

I created a buttons_taks.c and it initiates the SPI RX transaction by calling:
HAL_SPI_Receive_DMA(hspi,pData, 4);

The task then blocks using:
xTaskNotifyWait(0, ULONG_MAX, &notifyStatus, portMAX_DELAY );

I send a Task notification to buttons_task from DMA2_Stream0_IRQHandler in stm32f4xx_it.c which CubeMX created. I added ‘user code’ in that handler to send the notification.

When the buttons_task unblocks, the value of pData[0…3] are all 0 and I expect to see 1 when as I am pressing a button.

The same code works when I make the SPI call without DMA.

I"m not certain if this is related to where I am declaring the variable pData points to, maybe going out of scope during the IRQhandler.

I’m sure I"m missing something simple.

Thank you!

Some of your question is specific to the STM32 SPI and DMA implementation, which I’m not familiar with, but if I understand correctly your SPI works correctly without DMA but not with DMA. If the DMA end interrupt executes when expected, so interrupts are enabled, etc., then it’s not clear how FreeRTOS makes a difference to that. If you put a breakpoint in the ISR, before the task gets notified, do you see the data you expect in the debugger? If so, if you then put the breakpoint in the notified task and inspect the data again, has it changed?

The interrupt does trigger but the pData value is still 0. Perhaps I’m using the wrong IRQ callback since sometimes the ‘DMA status’ is ‘ABORT’ and other times it is ‘READY’. I was expecting I could read a value in the IRQ to identify more clearly what is being interrupted. I thought there would be a ‘RX complete’ interrupt status, but I’m guessing ‘Ready’ is the same.

I’ll hunt around for an example or tutorial specific to STM32 and freeRTOS. The ones I have found so far did not provide a clear solution, including which callback to use.

I don’t think this is anything to do with FreeRTOS. More likely using the wrong interrupt, as you say, or just a misconfiguration of the DMA.

The STM cube libraries really aren’t that well designed to interface with FreeRTOS. Yes, they provide some apparent integration in the Cube, but I have generally found it better to reimplement at least the simpler I/O drivers myself. In addition, I get a family independent set of interfaces to work with.

I do think my issue is related to HAL or misconfiguration. I see ‘HAL_DMA_STATE_ABORT’ for the DMA status in my ‘DMA2_Stream0_IRQHandler’. It’s not receiving data obviously.

I wish I could easily get away from HAL but ST seems to be pushing everyone to it. It’s not simple to determine what libraries to use, and ST refers to ‘legacy’ libraries which they don’t recommend be used. They point to ‘HAL’ and CubeMX in their docs. I always see advice to stay away from HAL. What a mess. I’ll post to the ST community as this is not related to a freeRTOS issue.

Thanks for the help!!

What I do, which may not be for everyone, is just use the hardware reference manual as a specification of the hardware, and the vendor driver as an example for clarification on things, and just write my own.

I would say that, in general, vendor supplied driver libraries maybe enough to start things with, but rarely are what I would consider “well designed”, and invariably, (especially when touted as Hardware abstracted) designed to lock you into their products.