Hi.
We are using the LPC4370 SSP0 as an SPI 8-bit Master to drive an MLX90393 hall sensor. The bitrate is 8 MHz, CPOL=1 and CPHA=1. The problem is that, after several hours interacting with the sensor at intervals of about 500 ms, with no problem, we eventually get stuck at the while in the following function:
/* SSP Polling Read in blocking mode */
uint32_t Chip_SSP_ReadFrames_Blocking(LPC_SSP_T *pSSP, uint8_t *buffer, uint32_t buffer_len)
{
uint32_t rx_cnt = 0, tx_cnt = 0;
/* Clear all remaining frames in RX FIFO */
while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE)) {
IP_SSP_ReceiveFrame(pSSP);
}
/* Clear status */
IP_SSP_ClearIntPending( pSSP, SSP_INT_CLEAR_BITMASK );
if (IP_SSP_GetDataSize( pSSP ) > SSP_BITS_8) {
// Omitted because we are using 8-bit frames.
}
else {
uint8_t *rdata8;
rdata8 = buffer;
while (tx_cnt < buffer_len || rx_cnt < buffer_len) {
/* write data to buffer */
if ((IP_SSP_GetStatus(pSSP, SSP_STAT_TNF) == SET) && (tx_cnt < buffer_len)) {
IP_SSP_SendFrame(pSSP, 0xFF); /* just send dummy data */
tx_cnt++;
}
/* Check overrun error */
if (IP_SSP_GetRawIntStatus(pSSP, SSP_RORRIS) == SET) {
return ERROR;
}
/* Check for any data available in RX FIFO */
while (IP_SSP_GetStatus(pSSP, SSP_STAT_RNE) == SET && rx_cnt < buffer_len) { // It seems RNE is never set for the last byte.
*rdata8 = IP_SSP_ReceiveFrame(pSSP);
rdata8++;
rx_cnt++;
}
}
return rx_cnt;
}
}
While we are stuck, tx_cnt = buffer_len, but rx_cnt = buffer_len - 1. In other words, all bytes have been transmitted, but we have received one byte less than expected.
I find this puzzling—if tx_cnt = buffer_len, that means all dummy bytes were sent, providing the clock signal. Regardless of the state of the other end, MISO should be sampled, and a new frame should be added to the RX FIFO. So how is it possible that rx_cnt is lower than tx_cnt?
It’s worth noting that the code in question runs within a FreeRTOS task, which can be preempted. Given that, the only plausible explanation I can think of is that some other code—either another task or an interrupt—might be "stealing" the received frame by reading the DR register before we do. However, after thoroughly investigating this possibility in the code, I haven’t found any evidence to support it, though I may have missed it.
So, what other scenarios could lead to this behavior?
Note that I am ruling out faulty hardware for a few reasons: 1) In my experience, software issues are far more common than hardware failures 2) the chip’s errata does not mention any known issues with SSP and 3) I haven’t found any reports of others encountering this issue during my research.
Thanks!