Some Clarification on Confusing BCM2835 SPI Master Documentation

Wednesday, 25 Sep 2013 - 18:01 +0100| Tags: Raspberry Pi, hardware, spi

I have been adding support for peripheral types to my Raspberry Pi C++ peripherals library[1] and as a result have been reading the BCM2835 ARM Peripherals data sheet document[2] rather closely as well as the document’s errata page on eLinux[3]. I, like others, have been bumping into documentation errors – and even added one to the eLinux list errata.

When I came to implement support for the Serial Peripheral Interface master (a.k.a. SPI0) peripheral I ran into the various documentation errors in the data sheet’s associated section. Because they were mostly mentioned in the eLinux errata page, although without a definitive correction, I was unsure of the protocol on updating the section with my findings, so I thought I would post them here.

First up the table describing the fields of the CS register on pages 153 – 155 of the data sheet. There are two main problems with this table:

  1. It documents fields and values concerning a chip enable 2 line, when there are only two chip enable lines supported by the SPI0 peripheral: CE0 and CE1.

  2. There are what appears to be two ways to affect the chip enable polarity: three one bit fields defining the chip enable polarity for each chip enable line CSPOL0, CSPOL1, CSPOL2 (see 1 above) and a single bit field, CSPOL, documented as affecting all chip enable lines’ polarity.

The way the fields interact to set the state of CE0 and CE1 are as follows:

  • If the TA (transfer active) field is 0 (not active) then all chip enable lines are de-asserted

  • If TA is 1 then the chip enable line specified by the CS (Chip Select) field’s value is asserted, all others are de-asserted

  • Whether a chip enable line is asserted by being high or low is determined by the chip select polarity (CSPOL) fields’ values

The points of confusion are:

  • What does a CS field value of 2 (10 binary) mean?

  • How do CSPOL and CSPOL0, CSPOL1 and CSPOL2 interact to affect the required chip enable polarity?

To answer this question I devised a test program and hardware setup that connected the SPI0 chip enable lines (SPI0_CE0_N and SPI0_CE1_N) to LEDs such that when a chip enable line was high the associated LED was illuminated. For each combination of CSPOL, CSPOL0, CSPOL1 and CSPOL2 values the chip enable line states with TA=0, TA=1 and CS=0, TA=1 and CS=1, TA=1 and CS=2 were noted.

The answer to the first point of confusion: a CS field value of 2 de-asserts both CE0 and CE1. Maybe there was going to be a CE2 but it got lost somewhere, so this phantom CE2 line would be asserted, all others (i.e. the two real, existing chip enable lines) are de-asserted.

In answer to the second point of confusion:

  • The value of the CSPOL single bit field does not affect the polarity of CE0 and CE1 in any way

  • Likewise, the value of the CSPOL2 single bit field does not affect the polarity of CE0 and CE1 in any way (it may well of course affect the previously mused about phantom CE2 line, but how could we tell?)

  • Hence the only fields of concern when setting chip enable polarity are CSPOL0 and CSPOL1

Another point with the CS register fields that was mentioned in the eLinux errata document was that the description of the RXR (RX FIFO needs reading) status bit field seems to miss out vital information concerning how full the RX FIFO has to be for this bit to be set. I think the answer is implied in section 10.6.2 on interrupt based software operation where under point i it says:

If RXR is set read 12 bytes data from SPI_FIFO

12 bytes is ¾ of the full 16-byte FIFO, so the RX FIFO ‘high watermark’ seems to be set at ¾ full.

The final point of confusion seems to concern the SPI clock divider CLK register and the APB core clock value used by the Raspberry Pi. As far as I can tell, which corroborates what others have said[4], the state of play with regards clock values and CLK register behaviour is:

  • The Raspberry Pi’s default GPU (APB) core clock speed is 250MHz, but this can be changed – for example by changing the gpu_freq or core_freq parameters in the Raspberry Pi /boot/config.txt file.

  • The SPI0 CLK register’s single CDIV field is 16 bits wide. However the least significant bit is ignored so effective clock divider values are always even

  • CDIV values of 0 and 1 have the same effect and act as a divider value of 65536

  • Hence the maximum SPI clock rate would be half the APB (GPU) core clock frequency, with a CDIV field value of 2

  • Practically the highest SPI clock frequency will be lower due to chip pins, circuit board tracks, header pins, cables etc. not being able to handle such high frequencies