I am working on custom hardware with an LPC54102 using MCUXpresso version 11.9.1. I am using FreeRTOS and doing the transfers with the SPI_RTOS_Transfer function.
I am interfacing to a sensor that uses SPI with 16 bit frames and it requires CPOL=0, CPHA=1 and SSEL deassertion between frames. The issue I'm having with the LPC chip is trying to get the SSEL to deassert between frames.
I've interfaced with this chip before using a Kinetis chip and didn't have any problems but that chip has (in my opinion) easier control of the chip select pin.
For reference, there is a drawing in the User Manual (UM10850, Rev 2.6, August 2019), Section 24.7.2.3, Figure 52. The lower drawing (CPHA=1) shows what I'm trying to do.
I just don't see anyway with the peripherals tool to configure the SSEL to deassert after every frame. Even reading through the reference manual, I don't see any way to do meet this configuration.
This configuration from the peripherals tool looks like this:
spi_rtos_handle_t SPI0_rtosHandle;
const spi_master_config_t SPI0_config = {
.polarity = kSPI_ClockPolarityActiveHigh,
.phase = kSPI_ClockPhaseSecondEdge,
.direction = kSPI_MsbFirst,
.baudRate_Bps = 2000000UL,
.dataWidth = kSPI_Data16Bits,
.sselNum = kSPI_Ssel0,
.sselPol = kSPI_SpolActiveAllLow,
.enableLoopback = false,
.enableMaster = true,
.fifoConfig = {
.enableTxFifo = true,
.txFifoSize = 8U,
.txFifoThreshold = 1U,
.enableRxFifo = true,
.rxFifoSize = 8U,
.rxFifoThreshold = 1U
},
.delayConfig = {
.preDelay = 0U,
.postDelay = 0U,
.frameDelay = 0U,
.transferDelay = 0U
}
};
uint8_t SPI0_txBuffer[SPI0_BUFFER_SIZE];
uint8_t SPI0_rxBuffer[SPI0_BUFFER_SIZE];
spi_transfer_t SPI0_transfer = {
.txData = SPI0_txBuffer,
.rxData = SPI0_rxBuffer,
.dataSize = 10U,
.configFlags = kSPI_FrameAssert
};
Is there anyway to do this?
There may be some confusion (maybe on my part) as to what the terms frame and transfer mean. The figure I'm quoting (see attached document for figure 52) says that the Transfer_Delay value controls the minimum amount of time that the SSEL is deasserted between transfers, but the figure shows the frame delay between frames - not transfers. I am assuming that a transfer is multiple frames since the NXP function for doing a transfer, SPI_RTOS_Transfer(), transfers multiple frames.
I've tried removing the kSPI_FrameAssert flag and you can see it just removes the deassert of the chip select at the end of the transfer of four frames (CSN stays low):
If I add the kSPI_FrameAssert flag, you can see that the chip select is deasserted at the end of the transfer (CSN goes high):
Note that in neither of these does the chip select deassert between the four frames.
Also, it's not clear to me why there are long waits between frames since all the delays are zero. Maybe that is interrupt timing in FreeRTOS?
Hi,
Pls try to modify the following parameters, and have a try.
Hope it can help you
BR
XiangJun Rong
static void master_task(void *pvParameters)
{
spi_master_config_t masterConfig;
spi_rtos_handle_t master_rtos_handle;
spi_transfer_t masterXfer = {0};
uint32_t sourceClock;
status_t status;
uint32_t errorCount;
uint32_t i;
NVIC_SetPriority(EXAMPLE_SPI_MASTER_IRQ, SPI_NVIC_PRIO + 1);
SPI_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Bps = 500000;
masterConfig.sselNum = EXAMPLE_SPI_SSEL;
masterConfig.sselPol = (spi_spol_t)EXAMPLE_MASTER_SPI_SPOL;
//Rong wrote
masterConfig.delayConfig.preDelay=2;
masterConfig.delayConfig.postDelay =2;
masterConfig.delayConfig.frameDelay =2;
masterConfig.delayConfig.transferDelay =2;
///Rong writing ending
sourceClock = 12000000;
status = SPI_RTOS_Init(&master_rtos_handle, EXAMPLE_SPI_MASTER, &masterConfig, sourceClock);
if (status != kStatus_Success)
{
PRINTF("SPI master: error during initialization. \r\n");
vTaskSuspend(NULL);
}
/*Start master transfer*/
masterXfer.txData = masterSendBuffer;
//Wrong write:
masterXfer.dataSize = 1; //TRANSFER_SIZE;
//Rong wtiting ends
masterXfer.rxData = masterReceiveBuffer;
masterXfer.configFlags |= kSPI_FrameAssert;
status = SPI_RTOS_Transfer(&master_rtos_handle, &masterXfer);
PRINTF("Master transmited:");
for (i = 0; i < TRANSFER_SIZE; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", masterSendBuffer[i]);
}
PRINTF("\r\n\r\n");
PRINTF("Slave received:");
for (i = 0; i < TRANSFER_SIZE; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", slaveReceiveBuffer[i]);
}
PRINTF("\r\n\r\n");
PRINTF("Slave transmited:");
for (i = 0; i < TRANSFER_SIZE; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", slaveSendBuffer[i]);
}
PRINTF("\r\n\r\n");
PRINTF("Master received:");
for (i = 0; i < TRANSFER_SIZE; i++)
{
if (i % 8 == 0)
{
PRINTF("\r\n");
}
PRINTF("0x%2x ", masterReceiveBuffer[i]);
}
PRINTF("\r\n\r\n");
if (status == kStatus_Success)
{
PRINTF("SPI master transfer completed successfully.\r\n");
}
else
{
PRINTF("SPI master transfer completed with error.\r\n");
}
errorCount = 0;
for (i = 0; i < TRANSFER_SIZE; i++)
{
if (masterReceiveBuffer[i] != slaveSendBuffer[i])
{
errorCount++;
}
}
if (errorCount == 0)
{
PRINTF("Slave-to-master data verified ok.\r\n");
}
else
{
PRINTF("Mismatch in slave-to-master data!\r\n");
}
vTaskSuspend(NULL);
}
Setting the data size to 1 and adding the delays, set to 2, (which I've tried before) doesn't work at all. The sensor doesn't even see the data.
I will try this. Also, it would be a lot easier to read your posts if you used the code formatting function "</>" from the toolbar.
Hi,
From hardware perspective, if you set the EOT bit in the spi TXCTL or TXDATCTL register, the TX_sselx pin will be asserted for each transfer.
in the driver, I suppose it is okay:
spi_transfer_t SPI0_transfer = {
.txData = SPI0_txBuffer,
.rxData = SPI0_rxBuffer,
.dataSize = 10U,
.configFlags = kSPI_FrameAssert
};
void SPI_MASTER_IRQHandler(void)
{
/* read data to avoid rxOverflow */
while (SPI_GetStatusFlags(EXAMPLE_SPI_MASTER) & kSPI_RxNotEmptyFlag)
{
SPI_ReadData(EXAMPLE_SPI_MASTER);
}
/* send data if buffer is not full */
if (SPI_GetStatusFlags(EXAMPLE_SPI_MASTER) & kSPI_TxNotFullFlag)
{
if (masterIndex == 1)
{
/* need to disable interrupts before write last data */
SPI_DisableInterrupts(EXAMPLE_SPI_MASTER, kSPI_TxLvlIrq);
SPI_WriteData(EXAMPLE_SPI_MASTER, (uint16_t)(srcBuff[BUFFER_SIZE - masterIndex]), kSPI_FrameAssert);
}
else
{
//Rong modification begin:
SPI_WriteData(EXAMPLE_SPI_MASTER, (uint16_t)(srcBuff[BUFFER_SIZE - masterIndex]), kSPI_FrameAssert);
////////////////////////Rong modification end:
}
masterIndex--;
}
if (masterIndex == 0U)
{
masterFinished = true;
}
SDK_ISR_EXIT_BARRIER;
}
Pls have try
BR
XiangJun Rong
I already have that set. The way I read the documentation that causes the chip select to be deasserted at the end of the transfer and that is what it appears to do.
I need the chip select deasserted for each frame (16 bits) as shown in the figure I quoted.
I have the SPI working by doing a transfer for each frame but that takes about 5ms to read the data from the sensors. That's about a 1000 times longer than doing it in a single transfer which is what I need to do.
See my added post with pictures.