Platform drivers for Mbed.

Dependents:   EVAL-CN0535-FMCZ EVAL-CN0535-FMCZ EVAL-AD568x-AD569x EVAL-AD7606 ... more

Revision:
12:d85b77f4160c
Parent:
11:a2dcf0ebb5b5
Child:
13:c446482b0360
--- 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);