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 “>spi>” primitive 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 simple “spi.” word:

: 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.

Weblog © Jean-Claude Wippler. Generated by Hugo.