cancel
Showing results for 
Search instead for 
Did you mean: 

F405 Bare Metal SPI

tdorval23
Associate

Hi, I've been trying to get a ground-up bare metal implementation of SPI working on one of the STM32 boards I own, but I can't seem to make progress on any of them. I lack an ST Link for the 405, so I can't step through my program and see how the registers are configured sadly, so I figured I'd ask here to see if anyone has experience doing something similar. I've attached the relevant GPIO and SPI c code to this post, as well as the main function for my project. Any help would be much appreciated, thanks.

3 REPLIES 3
darenluie
Associate III

You’re on the right track, but SPI on the F4 can be sensitive to small setup details. Most problems come from the wrong AF pin mapping or missing SSM/SSI settings when using software NSS. Try a simple loopback test by connecting MOSI to MISO to confirm your setup. If you share which pins you’re using, it’ll be easier to spot any config issues.

Based on the schematic for the board I'm using, the pins should be B13, B14, and B15. I believe I set them to AF5, which based on the datasheet seems to be the correct setting for their respective SPI functions. I have no reason to actually be using software slave select, I just thought that was the correct configuration based on the description of the register within the reference manual. If I set SSM low, does the slave selection become irrelevant?

waclawek.jan
Super User

> I lack an ST Link for the 405, so I can't step through my program and see how the registers are configured

I highly recommend you to get one. 

But even without STLink, you should establish some way to gather information "from within", especially registers content; for example using UART.

I also recommend you to use the symbols defined in the CMSIS-mandated device header, rather than defining your own. It's also better to use symbols defined there in a systematic manner (e.g. using the (value << MODULE_REGISTER_BITFIELD_Pos) pattern).

The problem here is this:

> #define GPIO_AF_SPI ((5U << 26) | (5U << 28) | (5U << 30))

resulting in GPIOB->AFR[1] being set to 0x5400'0000 (rather than the needed 0x5550'0000), as the GPIOx_AFR[] bitfields are 4 bits wide rather than 2 bits. 

Also, I recommend either writing values to GPIO registers directly, if you know there is no other code which sets or modifies the register; or using read-modify-write (AND-OR) so that you read and write the register only once, i.e. instead of register = register AND mask; register = register OR value; write a single register = (register AND mask) OR value;.

JW