2023-01-22 01:19 AM
Hello,
I came across this question while writing a driver and I would like to ask what is your best practice in this regard. So lets say you want to interface with an chip via SPI. To perform any action, a command byte or a sequence of commands is required followed by some application data. The sequence looks like that:
| command bytes | data |
In order the perform the data transmission, I could do something like this:
/* 'pTxBuf', 'pRxBuf' are pointers to the data buffer. 'Size' is the number of data bytes to be transferred */
uint8_t txCmd[2] = { COMMAND_BYTE_1, COMMAND_BYTE_2 };
uint8_t rxCmd[2] = { 0 };
/* Start transmission by taking CS low */
HAL_GPIO_WritePin(CS_GPIO_Port CS_GPIO_Pin, GPIO_PIN_RESET);
/* Command transmission */
HAL_SPI_TransmitReceive(&hspi1, &txCmd, &rxCmd, 2, HAL_MAX_DELAY);
/* Data transmission */
HAL_SPI_TransmitReceive(&hspi1, pTxBuf, pRxBuf, Size, HAL_MAX_DELAY);
/* Stop transmission by taking CS high */
HAL_GPIO_WritePin(CS_GPIO_Port CS_GPIO_Pin, GPIO_PIN_SET);
While this works perfectly, I somehow don't feel comfortable with splitting the transfer. In another approach memcpy is engaged to copy the command sequence and data to one buffer:
/* 'pTxBuf', 'pRxBuf' are pointers to the data buffer. 'Size' is the number of data bytes to be transferred */
/* Calculate buffer size */
uint8_t tmpBufferSize = 2 + Size;
/* Create temporary buffers for holding the command sequence and data */
uint8_t tmpTxBuffer[tmpBufferSize] = { 0 };
uint8_t tmpRxBuffer[tmpBufferSize] = { 0 };
/* Set both command bytes */
txCmd[0] = COMMAND_BYTE_1;
txCmd[1] = COMMAND_BYTE_2;
/* Copy application data to temporary buffer */
memcpy(tmpTxBuffer + 2, pTxBuf, Size)
/* Start transmission by taking CS low */
HAL_GPIO_WritePin(CS_GPIO_Port CS_GPIO_Pin, GPIO_PIN_RESET);
/* Transmit entire temporary buffer */
HAL_SPI_TransmitReceive(&hspi1, &tmtTxBuffer, &tmpRxBuffer, tmpBufferSize, HAL_MAX_DELAY);
/* Stop transmission by taking CS high */
HAL_GPIO_WritePin(CS_GPIO_Port CS_GPIO_Pin, GPIO_PIN_SET);
With the second method only one HAL access is needed. I think this could be helpful for later abstraction or when using DMA. On the other hand the use memcpy carries the risk of memory leakage.
What is your best practice for transferring command sequences and data via SPI?
2023-01-22 02:17 AM
To me it's very dependent on your HW configuration. Maybe ask yourself: