cancel
Showing results for 
Search instead for 
Did you mean: 

multiple SPI with DMA callback

con3
Senior

Hey everyone,

I cant seem to get separate callbacks going for my spi peripherals, each using DMA. Their both receiving data and by default seem to respond to HAL_SPI_RxCpltCallback. So whether SPI1 or SPI4's reception completes, HAL_SPI_RxCpltCallback is called for both.

I've tried to change the callback using the DMA handler;

hdma_spi1_rx .XferCpltCallback = ...; but this hasn't helped at all.

Does anyone have any idea how to change the callback to get seperate callbacks for each spi periph?

Thanks in advance!

1 ACCEPTED SOLUTION

Accepted Solutions

This is by design of Cube. You are supposed to distinguish the "source" in the callback by comparing (hspi->Instance == SPI1) etc.

Disclaimer: I don't and won't use Cube/CubeMX.

JW

View solution in original post

7 REPLIES 7

This is by design of Cube. You are supposed to distinguish the "source" in the callback by comparing (hspi->Instance == SPI1) etc.

Disclaimer: I don't and won't use Cube/CubeMX.

JW

con3
Senior

Thank @Community member​ ,

That solves it completely.

I'm assuming you use cmsis or directly work with the registers?

I think I need to move into using cmsis or fooling with the registers directly, although I can't seem to find much resources on this.

Do you have any online or books that you can recommend?

Thank you for all the help!

I don't know what you exactly mean by CMSIS - but I suspect you confuse it with the previous ST "library", SPL (Standard Peripheral Library). I don't use SPL; I use directly registers but through the symbols given in the CMSIS-mandated device headers, i.e. those provided by ST in [Cube for given family]\Drivers\CMSIS\Device\ST\[STM32xxxx]\Include\

I know of no specific book or guideline or reference for that approach. I simply read the reference manual and started writing programs. That's exactly the same method I used and use with any other mcu for a couple of decades...

JW

con3
Senior

hi @Community member​ !

Thank you for the detailed response!

I was unaware of this : ]\Drivers\CMSIS\Device\ST\[STM32xxxx]\Include\

I initially thought you setup this document yourself. By cmsis, I was referring to arm's "The Cortex Microcontroller Software Interface Standard (CMSIS) is a vendor-independent hardware abstraction layer for the Cortex®-M processor series and defines generic tool interfaces" , which seems to be what you use to program.

I've looked around for guides or projects to get going, but it's been an up hill battle with setting up a project using the bare registers as I have no references. Do you know of any project provided by ST or have one that you could maybe link me that is setup this way and well commented, that I can use as a starting point. It seems there is a major push to use HAL or other abstraction layers and I really want to get into using the bare registers both to get rid of clutter, have more control of my code and actually understand what is going on on a deeper level.

Thanks you again for all the information!

ST started a project called Snippets, for the 'F0 and the 'L0 families. This apparently collided internally with the Cube/CubeMX line, so they choked it before it could mature, and found excuses to avoid porting it to other families. But you still should be able to download at least those existing ones, e.g. https://www.st.com/en/embedded-software/stm32snippetsf0.html

Other than that, it's really just about reading the RM and writing a big number of simple test programs. Start with blinky, it's just enabling clock for GPIO in RCC, setting a pin to output, and then toggle that pin and do some loopdelay. GPIO registers are organized in a cumbersome way, so you probably will develop a bunch of macros and/or some style how to simplify their access. After loopdelay-blinky, a timer-based-blinky is the next logical step. And then the usual communication interfaces - starting with UART connected to PC, then talk through SPI and I2C to some attached chips. This brings in also the interrupts and DMA. Then there are the less-common but still relatively simple interfaces such as RTC, CAN or I2S.

Finally, the interfaces which involve complex protocols like USB and ETH - they are not that simple to pull out from scratch, and that's where ST's "libraries" may have the biggest appeal; but there still are options - the "libraries" can be studied and ported, and libraries by third parties may be available either "free" (whatever that means) or "paid" (which again may mean several things). You exchange time/effort for ownership/control.

The debugger is your friend - there are many experiments which could be done simply by manipulating the registers direcly in debugger, without writing actual program.

JW

con3
Senior

Thank you @Community member​ ,

That was very insightful.

I'll be doing my next project this way!

I appreciate all the help

Is the code something like this?

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
	/* Prevent unused argument(s) compilation warning */
        // comment below
	// UNUSED(hspi);
 
	/* NOTE : This function should not be modified, when the callback is needed,
            the HAL_SPI_RxCpltCallback should be implemented in the user file
	 */
	// (hspi->Instance == SPI1) etc.
 
	if (hspi->Instance == SPI1)
		// do something
	else if (hspi->Instance == SPI2)
		// do something
 
}