2025-11-16 10:43 AM
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.
2025-11-16 12:02 PM
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.
2025-11-16 1:32 PM
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?
2025-11-17 2:00 AM
> 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