SPI CS pin rises too early

First time working with SPI and I am having an issue. So far SCK (GPIO 5) and MOSI (GPIO 3) are working. CS0 (GPIO 2) will go low initially, but after 8 clock cycles it will set itself to high, when I need it to stay low for 24 clock cycles in order to receive data from the MCP3008. Altering the the Frame Format Register’s length will change how long the CS pins stays low, but I can’t set it higher than 8 bits.

Picture from oscilloscope:

  • Yellow = SCK
  • Blue= CS

link to main.cpp here.

I am using a low level library - link here - that is very much in early development to interact with the Hifive1 Rev.B, so a bare bones solution would be appreciated.

Hi Gareth, Very good question you ask here. In the FE310’s SPI implementstion everything is byte-wise, thus 8 bits. There’s an undocumented option for setting multiple bytes per CS assertion - I’ll look this up and post here in a few days.
Alternately, you can always “disconnect” CS from the SPI block and put it to GPIO, thus doing pseudo bit-bang where you do your Chip Enable assertions manually.

First, I don’t think it’s a good idea to change csdef as this can result in a signal contention. Second, you write 3 bytes in a loop, but read only 2, this can result in RX FIFO overflow. Third, you set CSMODE to HOLD, this results in asserting CS before the first byte, and it stays asserted all the time. In general, you need to set CSMODE to HOLD before the first byte and set it to AUTO after the last byte.

Changed main.cpp to read rxdata every time txdata is written to and have set csmode to off.

Using GPIO results in the CS pin rising before the last clock goes low:

Using csdef fixes the issue:

Zoomed out:

But, as you said there is an issue with using csdef: on power up, UART reports ‘send flag errors’ from the WiFi module. After that though, everything appears to be fine as the data from the MISO pin is read, until several seconds later the voltage on the MISO pin drops to near zero and rxdata reads zero.

Pressing the reset button or re-flashing the chip results in the WiFi module now reporting everything is ok, but the ADC continues to output near zero voltage on the MISO pin. Removing power, then re-applying it gets the ADC outputting at a decent voltage, but again for only several seconds.

If you use a user-controlled CS, then you have to add a delay after the last byte, because the very last bit of the byte is received on a rising edge, so you can receive the whole byte before the trailing edge. Peripheral-controlled CS mode solves this problem for you.

@Disasm added a delay and it does cause the CS pin to rise after the last clock, but the MCP3008 MISO pin still outputs zeros with a voltage below 1V, several seconds from power being reapplied.

MISO with correct voltage output:

MISO seconds later:

@pds What is the undocumented option? It might help fix the issue.