>>106965040
SPI1_DRL is defined as
#define SPI1_DRL *(volatile uint8_t *)(0x4001300C)
technically it's a dereferenced pointer literal to a (volatile) uint8_t, but for coding purposes you can just pretend it's a uint8_t. defining it as a dereferenced pointer literal essentially let's you pick where specifically in memory the variable is stored. this is useful if youre programming, for instance, a microcontroller with an SPI register located specifically at 0x4001300C in memory. then, if you want to read from the SPI interface, all you have to do is read the variable.
however, since other hardware has access to the register, you want to make sure the compiler doesnt make any optimizations that assume otherwise (e.g. if you read from the register twice in succession, it could change between the two reads without the CPU doing anything, so you dont want gcc to optimize out one of the reads). so you throw the lesser known volatile keyword in there to let the compiler know whats up.
finally, for my particular microcontroller, the SPI1_DRL register is using for both transmitting AND receiving (write = transmit, read = receive). whenever the interface receives a byte, it stores it in a FIFO buffer that gets shifted out whenever the something reads from the SPI1_DRL register. i recently refactored my spi1_xfer function to use a return buffer rx, but if rx was NULL the function wouldnt read from SPI1_DRL, which caused the SPI buffer to get backed up (in SPI, every time you transmit a byte, you also receive a byte, even if the byte is garbage, so not reading the garbage bytes just resulted in the garbage being read on subsequent transfers).
so my problem was: i had to read from the variable on every transfer, even if rx was NULL. but it turns out that reads to volatile variables are always respected, so all i had to do it SPI1_DRL; and im g2g. even -Wpedantic didnt complain.