Much faster SPI with hardware Mar 2016
Unlike an USART-based serial port, SPI communication is not timing-critical, at least not on the SPI master side. Since the data clock is also sent as separate signal, slowdowns only change the communication rate. That’s why SPI is so easy to implement in bit-banged mode, as shown here.
But software implementations are always going to be slower than dedicated hardware. So here’s a hardware version which drives the clock at 9 MHz, 1/8th the CPU’s 72 MHz master clock:
$40013000 constant SPI1 SPI1 $0 + constant SPI1-CR1 SPI1 $4 + constant SPI1-CR2 SPI1 $8 + constant SPI1-SR SPI1 $C + constant SPI1-DR : +spi ( -- ) ssel @ io-0! ; \ select SPI : -spi ( -- ) ssel @ io-1! ; \ deselect SPI : >spi> ( c -- c ) \ hardware SPI, 8 bits SPI1-DR ! begin SPI1-SR @ 1 and until SPI1-DR @ ; \ single byte transfers : spi> ( -- c ) 0 >spi> ; \ read byte from SPI : >spi ( c -- ) >spi> drop ; \ write byte to SPI : spi-init ( -- ) \ set up hardware SPI 12 bit RCC-APB2ENR bis! \ set SPI1EN %0000000001010100 SPI1-CR1 ! \ clk/8, i.e. 9 MHz, master 2 bit SPI1-CR2 bis! \ SS output enable OMODE-PP ssel @ io-mode! -spi OMODE-AF-PP PA5 io-mode! IMODE-FLOAT PA6 io-mode! OMODE-AF-PP PA7 io-mode! ;
Note the special hardware pin settings using the STM32’s “alternate function” mode.
The select I/O pin is configured in the
ssel variable. Everything else is
similar to the USART2 hardware: intitialisation using lots of magic bit
settings gleaned from the datasheet, and then a single “
which transfers a single byte out and back in via the SPI registers.
At 9 MHz, this takes under 1 microsecond per byte. These high rates can only be used across short wires, but are nevertheless perfect to interface with a large variety of SPI-based chips.
Here’s a convenient utility to inspect the SPI hardware registers with a
: spi. ( -- ) \ display SPI hardware registers cr ." CR1 " SPI1-CR1 @ h.4 ." CR2 " SPI1-CR2 @ h.4 ." SR " SPI1-SR @ h.4 ;
This driver is plug-compatible with the bit-banged one presented earlier. One or the other can be loaded and used with the RFM69 driver, for example.