Platform drivers for Mbed.
Dependents: EVAL-CN0535-FMCZ EVAL-CN0535-FMCZ EVAL-AD568x-AD569x EVAL-AD7606 ... more
Diff: src/spi.cpp
- Revision:
- 12:d85b77f4160c
- Parent:
- 11:a2dcf0ebb5b5
- Child:
- 13:c446482b0360
diff -r a2dcf0ebb5b5 -r d85b77f4160c src/spi.cpp --- a/src/spi.cpp Mon Aug 03 17:21:20 2020 +0530 +++ b/src/spi.cpp Fri Aug 14 11:14:13 2020 +0530 @@ -154,36 +154,56 @@ uint8_t num_of_words; // Number of words in SPI frame uint16_t rw_data; // SPI read data uint8_t data_index = 0; // Data index + static uint8_t spi_format = 16; // SPI format if (desc) { spi = (SPI *)(((mbed_spi_desc *)(desc->extra))->spi_port); ss = (DigitalOut *)(((mbed_spi_desc *)(desc->extra))->slave_select); - - spi->format(16, desc->mode); - - /* Get the total number of words (16-bit) and leftover bytes (8-bit) */ + + /* Get the total number of words (16-bit) */ num_of_words = bytes_number / 2; - + + /* Determine the data transmit/receive format based on parity of data */ + if (!(bytes_number % 2)) { + if (spi_format != 16) { + spi->format(16, desc->mode); + spi_format = 16; + } + } else { + if (spi_format != 8) { + spi->format(8, desc->mode); + spi_format = 8; + } + } + ss->write(GPIO_LOW); - - while (num_of_words) { - /* Form a 16-bit data to be written */ - rw_data = ((uint16_t)data[data_index + 1] | ((uint16_t)data[data_index] << 8)); - - /* Transmit a 16-bit data over SPI */ - rw_data = (uint16_t)spi->write(rw_data); - - /* Extract the MSB and LSB from 16-bit read data */ - data[data_index++] = (uint8_t)(rw_data >> 8); - data[data_index++] = (uint8_t)rw_data; - - num_of_words--; - } - - /* Send the odd/single byte */ - if (bytes_number % 2) { - spi->format(8, desc->mode); - data[data_index] = (uint8_t)spi->write(data[data_index]); + + /* **Note: It is not possible to change the format of data transfer when SPI + * communication is in progress. If format is attempted to change (from 8-bit + * to 16-bit or vice a versa), the SPI communication is reset and master generates + * a single Clock signal during format change. This triggers false transfer on slave + * which results into incorrect data transfer. For this reason, the bytes with even parity + * are transferred in 16-bit format and odd parity bytes are transferred in 8-bit format. + * Application layer doesn't have any control to stop SPI reset during format change. */ + + if (!(bytes_number % 2)) { + while (num_of_words) { + /* Form a 16-bit data to be written (LE format) */ + rw_data = ((uint16_t)data[data_index + 1] | ((uint16_t)data[data_index] << 8)); + + /* Transmit a 16-bit data over SPI */ + rw_data = (uint16_t)spi->write(rw_data); + + /* Extract the MSB and LSB from 16-bit read data (LE format) */ + data[data_index++] = (uint8_t)(rw_data >> 8); + data[data_index++] = (uint8_t)rw_data; + + num_of_words--; + } + } else { + for (size_t byte = 0; byte < bytes_number; byte++) { + data[byte] = spi->write(data[byte]); + } } ss->write(GPIO_HIGH);