Hello,
I am struggling with the LPSPI module on the S32K144. I want to send some bytes and receive some bytes of varying length. This works with the exception that I have to send an additional dummy byte. Let's say I want to Tx 2 bytes and Rx 2 bytes, I have to Tx a total of 5 bytes. What am I missing to only have to send 4 bytes to write/read 4 bytes?
Here's my function:
void Spi_Transceive(uint8_t txLen, uint8_t *txBuf, uint8_t rxLen, uint8_t *rxBuf, uint8_t module, uint8_t pcs)
{
uint16_t total = rxLen + txLen - 1;
uint32_t totalBytes = 0;
const uint32_t tcr_base =
LPSPI_TCR_FRAMESZ(7) | // 8-bit frames
LPSPI_TCR_PCS(pcs) |
LPSPI_TCR_CPOL(0) |
LPSPI_TCR_CPHA(1) |
LPSPI_TCR_PRESCALE(0) |
LPSPI_TCR_WIDTH(0) |
LPSPI_TCR_CONTC(1);
LPSPI2->CR |= LPSPI_CR_RTF_MASK | LPSPI_CR_RRF_MASK;
LPSPI2->SR = 0xFFFFFFFFu;
LPSPI2->FCR = LPSPI_FCR_TXWATER(0) | LPSPI_FCR_RXWATER(0);
while (!(LPSPI2->SR & LPSPI_SR_TDF_MASK))
;
LPSPI2->TCR = tcr_base | LPSPI_TCR_CONT(1);
LPSPI2->TDR = (uint8_t)txBuf[0];
totalBytes++;
for (uint8_t i = 1; i < txLen; i++)
{
if (totalBytes == total)
{
LPSPI2->TCR = tcr_base | LPSPI_TCR_CONT(0);
}
while (!(LPSPI2->SR & LPSPI_SR_TDF_MASK))
;
LPSPI2->TDR = (uint8_t)txBuf[i];
totalBytes++;
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK))
;
(void)LPSPI2->RDR;
}
if (rxLen > 0)
{
while (!(LPSPI2->SR & LPSPI_SR_TDF_MASK))
;
LPSPI2->TDR = 0x00; // NOP
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK))
;
(void)LPSPI2->RDR;
}
else
{
return;
}
for (uint8_t i = 0; i < rxLen; i++)
{
if (totalBytes == total)
{
LPSPI2->TCR = tcr_base | LPSPI_TCR_CONT(0);
}
while (!(LPSPI2->SR & LPSPI_SR_TDF_MASK))
;
LPSPI2->TDR = 0x00; // NOP
totalBytes++;
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK))
;
rxBuf[i] = (uint8_t)LPSPI2->RDR;
}
}
Here's the initialization:
PCC->PCCn[PCC_LPSPI2_INDEX] = 0; /* Disable clocks to modify PCS ( default) */
PCC->PCCn[PCC_LPSPI2_INDEX] = PCC_PCCn_PR_MASK /* (default) Peripheral is present. */
| PCC_PCCn_CGC_MASK /* Enable PCS=SPLL_DIV2 (40 MHz func'l clock) */
| PCC_PCCn_PCS(6);
LPSPI2->CR = 0x00000000;
LPSPI2->IER = 0x00000000;
LPSPI2->DER = 0x00000000;
LPSPI2->CFGR0 = 0x00000000;
LPSPI2->CFGR1 = LPSPI_CFGR1_MASTER_MASK | LPSPI_CFGR1_SAMPLE(1) | LPSPI_CFGR1_AUTOPCS(0) | LPSPI_CFGR1_PCSPOL(0b0000);
LPSPI2->TCR = LPSPI_TCR_CPHA_MASK | LPSPI_TCR_PRESCALE(2) | LPSPI_TCR_PCS(0) | LPSPI_TCR_FRAMESZ(7) | LPSPI_TCR_CONT(1);
LPSPI2->CCR = LPSPI_CCR_SCKPCS(4) | LPSPI_CCR_PCSSCK(4) | LPSPI_CCR_DBT(8) | LPSPI_CCR_SCKDIV(8);
LPSPI2->FCR = LPSPI_FCR_TXWATER(3);
LPSPI2->CR = LPSPI_CR_MEN_MASK | LPSPI_CR_DBGEN_MASK;
Solved! Go to Solution.
Hi,
clear CONTC bit in TCR.
See attached main.c file I used in S32K144_Project_LPSPI demo.
It gives right frames. I tested below sequences
BR, Petr
Hi,
for each write to TDR you should increment your totalBytes. For each TDR write there should be RDR reading. After CONT is cleared you should read RDR finally. Try below one, but I did not tested that.
void Spi_Transceive(uint8_t txLen, uint8_t *txBuf, uint8_t rxLen, uint8_t *rxBuf, uint8_t module, uint8_t pcs)
{
uint16_t total = rxLen + txLen;
uint32_t totalBytes = 0;
const uint32_t tcr_base =
LPSPI_TCR_FRAMESZ(7) | // 8-bit frames
LPSPI_TCR_PCS(pcs) |
LPSPI_TCR_CPOL(0) |
LPSPI_TCR_CPHA(1) |
LPSPI_TCR_PRESCALE(0) |
LPSPI_TCR_WIDTH(0) |
LPSPI_TCR_CONTC(1);
LPSPI2->CR |= LPSPI_CR_RTF_MASK | LPSPI_CR_RRF_MASK;
LPSPI2->SR = 0xFFFFFFFFu;
LPSPI2->FCR = LPSPI_FCR_TXWATER(0) | LPSPI_FCR_RXWATER(0);
if (txLen>0)
{
LPSPI2->TCR = tcr_base | LPSPI_TCR_CONT(1);
while (!(LPSPI2->SR & LPSPI_SR_TDF_MASK));
LPSPI2->TDR = *txBuf++;
totalBytes++;
while(totalBytes < txLen)
{
while (!(LPSPI2->SR & LPSPI_SR_TDF_MASK));
LPSPI2->TDR = *txBuf++;
totalBytes++;
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK));
(void)LPSPI2->RDR;
}
if(rxLen==0)
{
LPSPI2->TCR = tcr_base | LPSPI_TCR_CONT(0);
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK));
(void)LPSPI2->RDR;
}
}
if (rxLen>0)
{
if(txLen==0) LPSPI2->TCR = tcr_base | LPSPI_TCR_CONT(1);
while (!(LPSPI2->SR & LPSPI_SR_TDF_MASK));
LPSPI2->TDR = 0x00; // NOP
totalBytes++;
if(txLen>0)
{
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK));
(void)LPSPI2->RDR;
}
while(totalBytes < total)
{
while (!(LPSPI2->SR & LPSPI_SR_TDF_MASK));
LPSPI2->TDR = 0x00; // NOP
totalBytes++;
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK));
*rxBuf++ = LPSPI2->RDR;
}
LPSPI2->TCR = tcr_base | LPSPI_TCR_CONT(0);
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK));
*rxBuf++ = LPSPI2->RDR;
}
}
BR, Petr
Hello Petr,
Thanks for your support. The first read attempt always stays forever in the while RDF mask loop. Even with your code. Any idea why?
if (rxLen == 0)
{
LPSPI2->TCR = tcr_base | LPSPI_TCR_CONT(0);
while (!(LPSPI2->SR & LPSPI_SR_RDF_MASK)) // Stuck here on 1st read
;
(void)LPSPI2->RDR;
}