17bit or 25bit spi frame using LPC546xx family

cancel
Showing results for 
Search instead for 
Did you mean: 

17bit or 25bit spi frame using LPC546xx family

Jump to solution
234 Views
Contributor II

Hi All,

I'm looking to interface to a slightly non standard spi interface using a 9bit address word as shown below to make a 17 or 25 bit total frame size.

spi17bit.png

In the LPC546xx manual (section 26.2) I see larger frame sizes beyond 16bits are supported by software. Are there further details on how this can be achieved? As I'd still have to interface to the 8 bit fifo's.

Labels (2)
0 Kudos
1 Solution
62 Views
NXP TechSupport
NXP TechSupport

Hello Ian, 

The changes you made are totally right, I will report this to the SDK team, and about your other question, the best way would be to change the data width in the section the master init is storing this configuration. This configuration is stored in g_configs so an API like the next one should do the trick:

status_t SPI_ChangeTransferWidth(SPI_Type *base, spi_data_width_t datawidth){
    uint32_t instance;
    
    instance  = SPI_GetInstance(base);
    /* store configuration */
    g_configs[instance].dataWidth = datawidth;
}

Best Regards,

Alexis Andalon

View solution in original post

11 Replies
62 Views
Contributor II

For the second part of the problem then sending an 8 bit transfer, I can't see how to get the new value of userConfig.dataWidth = kSPI_Data8Bits;  to take effect? As just updating this is ignored. 

I've also tried running the SPI_Deinit and then SPI_MasterInit again with the new value but not surprisingly this causes the bus to reset.

What is the correct way to do a two transaction spi transfer changing the spi  datawidth in between?

Kind regards

Ian

0 Kudos
63 Views
NXP TechSupport
NXP TechSupport

Hello Ian, 

The changes you made are totally right, I will report this to the SDK team, and about your other question, the best way would be to change the data width in the section the master init is storing this configuration. This configuration is stored in g_configs so an API like the next one should do the trick:

status_t SPI_ChangeTransferWidth(SPI_Type *base, spi_data_width_t datawidth){
    uint32_t instance;
    
    instance  = SPI_GetInstance(base);
    /* store configuration */
    g_configs[instance].dataWidth = datawidth;
}

Best Regards,

Alexis Andalon

View solution in original post

62 Views
Contributor II

Thanks Alexis, that's the missing piece I needed.

To close this off now, my waveforms now are 

17bits

17bits.jpg

and 25bits

25bits.jpg

Cheers

Ian

0 Kudos
62 Views
Contributor II

For the first part of the problem, sending a 9 bit transfer I found an issue in the sdk (version 2.7) 

in fsl_spi.c  lines 562 to 618 the two lines in bold need changing.

while ((txRemainingBytes != 0U) || (rxRemainingBytes != 0U) || (toReceiveCount != 0U))
{
/* if rxFIFO is not empty */
if ((base->FIFOSTAT & SPI_FIFOSTAT_RXNOTEMPTY_MASK) != 0U)
{
tmp32 = base->FIFORD;
/* rxBuffer is not empty */
if (rxRemainingBytes != 0U)
{
*(rxData++) = (uint8_t)tmp32;
rxRemainingBytes--;
/* read 16 bits at once */
if (dataWidth >= 8U)          //  was if (dataWidth >8U)  
{
*(rxData++) = (uint8_t)(tmp32 >> 8);
rxRemainingBytes--;
}
}
/* decrease number of data expected to receive */
toReceiveCount -= 1U;
}
/* transmit if txFIFO is not full and data to receive does not exceed FIFO depth */
if (((base->FIFOSTAT & SPI_FIFOSTAT_TXNOTFULL_MASK) != 0U) && (toReceiveCount < fifoDepth) &&
((txRemainingBytes != 0U) || (rxRemainingBytes >= SPI_COUNT_TO_BYTES(dataWidth, toReceiveCount + 1U))))
{
/* txBuffer is not empty */
if (txRemainingBytes != 0U)
{
tmp32 = *(txData++);
txRemainingBytes--;
/* write 16 bit at once */
if (dataWidth >= 8U)  //  was if (dataWidth >8U)  
{
tmp32 |= ((uint32_t)(*(txData++))) << 8U;
txRemainingBytes--;
}
if (txRemainingBytes == 0U)
{
tx_ctrl |= last_ctrl;
}
}
else
{
tmp32 = (uint32_t)s_dummyData[instance];
tmp32 |= (uint32_t)s_dummyData[instance] << 8U;
/* last transfer */
if (rxRemainingBytes == SPI_COUNT_TO_BYTES(dataWidth, toReceiveCount + 1U))
{
tx_ctrl |= last_ctrl;
}
}
/* send data */
tmp32 = tx_ctrl | tmp32;
base->FIFOWR = tmp32;
toReceiveCount += 1U;
}
}

I hope that gets changed in a later sdk version.

Cheers

Ian.

0 Kudos
62 Views
Contributor II

As indicated in the manual I'm looking to do this as two transfers, one of 9bits and then the remain 8bits with I assume manual control of the EOF bit in the FIFOWR register.

Though I seem to be falling down at writing the initial 9bits as I get 18bits instead.

Following the spi sdk example I define the following.

#define BUFFER_SIZE (2)

static uint8_t srcBuff[BUFFER_SIZE];
static uint8_t destBuff[BUFFER_SIZE];

spi_master_config_t userConfig = {0};
spi_transfer_t xfer = {0};

SPI_MasterGetDefaultConfig(&userConfig);
srcFreq = EXAMPLE_SPI_MASTER_CLK_FREQ;
userConfig.sselNum = (spi_ssel_t)EXAMPLE_SPI_SSEL;
userConfig.sselPol = (spi_spol_t)EXAMPLE_SPI_SPOL;
userConfig.dataWidth = kSPI_Data9Bits;


SPI_MasterInit(EXAMPLE_SPI_MASTER, &userConfig, srcFreq);

//Start Transfer
xfer.txData = srcBuff;
xfer.rxData = destBuff;
xfer.dataSize = 2;
xfer.configFlags = kSPI_FrameAssert;
SPI_MasterTransferBlocking(EXAMPLE_SPI_MASTER, &xfer);

How should I be using the datawidth register?

Cheers

Ian.

 

0 Kudos
62 Views
NXP TechSupport
NXP TechSupport

Hello Ian,

Unfortunately, the APIs in the SDK support transfer up to 16 bit. In this case, in your code you're setting 2 transfer of 9 bits, so you would need to set first a 9-bit transfer first, modify the data width, and set other transfer with the flags kSPI_FrameDelay and kSPI_FrameAssert to indicate the end of the frame.

Best Regards,
Alexis Andalon

62 Views
Contributor II

Hi Alexis thanks for the reply, this is what I was trying to achieve, though I can't see how to send just 1 transfer of 9bits as if I sent  xfer.dataSize = 1; 

at runtime I get an ASSERT ERROR " .fsl_spi.c:544 : !((dataWidth > kSPI_Data8Bits) && ((xfer->dataSize & 0x1U) != 0U)) 

not surprisingly as the api for the spi_transfer_t  has data as 8bits.

So how can I just send 1 transfer of 9bits though the api?

Thanks

Ian

0 Kudos
62 Views
NXP TechSupport
NXP TechSupport

Hello Ian,

You're right, it looks like when the driver recognizes a transfer higher than 8-bits the extra bits will put in the next byte, so you will need to filter the information in the second byte.

Best Regards,

Alexis Andalon

0 Kudos
62 Views
Contributor II

Hi Alexis this is what I'm trying to do, but there seems to be a problem with this particular combination as if I do a 10bit transfer I get what I expect 10 bits clocked out per frame with 

#define BUFFER_SIZE (2)
static uint8_t srcBuff[BUFFER_SIZE];
static uint8_t destBuff[BUFFER_SIZE];

spi_master_config_t userConfig = {0};
uint32_t srcFreq = 0;
uint32_t i = 0;
uint32_t err = 0;
spi_transfer_t xfer = {0};

for (i = 0; i < BUFFER_SIZE; i++)
{
srcBuff[BUFFER_SIZE] = 0xA5;
}

SPI_MasterGetDefaultConfig(&userConfig);
srcFreq = EXAMPLE_SPI_MASTER_CLK_FREQ;
userConfig.sselNum = (spi_ssel_t)EXAMPLE_SPI_SSEL;
userConfig.sselPol = (spi_spol_t)EXAMPLE_SPI_SPOL;
userConfig.dataWidth = kSPI_Data10Bits;
SPI_MasterInit(EXAMPLE_SPI_MASTER, &userConfig, srcFreq);

//Start Transfer
xfer.txData = srcBuff;
xfer.rxData = destBuff;
xfer.dataSize = 2;
xfer.configFlags = kSPI_FrameAssert;
 SPI_MasterTransferBlocking(EXAMPLE_SPI_MASTER, &xfer);

but when I go and just change to 9 bits with userConfig.dataWidth = kSPI_Data9Bits;

it jumps to clocking out 18bits. 

So how can I get the elusive 9 bits?

Cheers

Ian

0 Kudos
62 Views
NXP TechSupport
NXP TechSupport

Hello Ian,

Have you tried using one transmission with for example 11 bit-s and the other one for 8-bit? This to have one filtered transmission and the other to received as it is.

Best Regards,

Alexis Andalon

0 Kudos
62 Views
Contributor II

Yes all the other combinations work, 10bits through to 16 bits. It's just the one I need 9bits that doesn't, so I assume there's an error in the sdk, is there a fix?

Cheers

Ian

0 Kudos