LPC54102 and SPI SSEL

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC54102 and SPI SSEL

836 Views
JBM
Contributor V

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?

0 Kudos
Reply
6 Replies

785 Views
JBM
Contributor V

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):

RigolDS3.png

 

 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):

RigolDS2.png

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?

0 Kudos
Reply

716 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

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);

}

 

0 Kudos
Reply

711 Views
JBM
Contributor V

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.

RigolDS3.png

0 Kudos
Reply

712 Views
JBM
Contributor V

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.

0 Kudos
Reply

801 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

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;

}

xiangjun_rong_0-1715926889750.png

Pls have  try

BR

XiangJun Rong

 

0 Kudos
Reply

790 Views
JBM
Contributor V

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.

0 Kudos
Reply