Question: When using PSoC® 3/4/5LP as an SPI master to interface with SPI slaves (such as SPI EEPROMs, SPI-based ADCs, etc.), the data read from / written to the slaves is wrong when CPU speed is decreased (or SPI speed is increased). However, the data is correct for faster CPU speeds (or for slower SPI clock frequencies). What is a possible cause for this issue and how do you fix it?
SPI slaves, such as SPI EEPROM ICs, typically interpret the first byte received from the master after the slave select (SS) line goes down as the opcode (say, to read/write, etc.), and the following few bytes as the address; then the data bytes are sent and received. Once the SS clock goes high, the state machine in the slave IC gets reset. So the next byte received from the master after the SS clock goes low would be interpreted as an opcode by the slave.
When using a PSoC 3 SPI master to send the series of bytes (opcode, address, and data), in your source code, the SPI master component would clock out the data when the SPI shift register is empty. So it is possible (when using slower CPU speeds) that the CPU may place the opcode byte onto the SPI buffer, and before the CPU places the address byte onto the SPI buffer, the SPI component completes the transaction corresponding to the opcode. Since the SPI component releases the SS line if there are no pending bytes in the SPI buffer, it is possible that the SS line goes high in between the opcode and the address byte. This would cause the slave’s state machine to reset in the middle, and see the address byte as the opcode, resulting in unexpected results.
One way to overcome this issue is to connect a separate firmware-controlled digital output pin to the SS pin of the SPI slave instead of using the SS signal supplied by the SPI component.
- Make the firmware-controlled SS pin low before starting the SPI transaction
- Make the SPI transaction (send the opcode, address, data, etc., as required by the SPI slave).
- Wait for the completion of the SPI transaction by polling for the SPIM_STS_SPI_DONE flag.
After the SPIM_STS_SPI_DONE flag gets set, make the firmware-controlled SS pin high.
This procedure would ensure that the SPI slave sees the byte sequence as intended by the user, and would result in correct data being read from / written from the SPI slave.