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.
 
					
				
		
 PetrS
		
			PetrS
		
		
		
		
		
		
		
		
	
			
		
		
			
					
		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
 
					
				
		
 PetrS
		
			PetrS
		
		
		
		
		
		
		
		
	
			
		
		
			
					
		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;
        }
 
					
				
		
 PetrS
		
			PetrS
		
		
		
		
		
		
		
		
	
			
		
		
			
					
		