S32K144W problems with custom SPI driver

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

S32K144W problems with custom SPI driver

Jump to solution
530 Views
marco_medrano
Contributor I

Hi NXP community!

I'm developing a custom SPI driver based on the SPI example from the AN5423 application note (https://www.nxp.com/docs/en/application-note/AN5413.pdf)

The problem I'm facing is that after initializing, the SPI is only able to send around 23 bytes of data, no matter what I set as the frame size in the Transmit Command Register (TCR). After that, the clock remains in high state even though I set its polarity as SCK low. While debugging, I found that it gets stuck waiting for the TDF flag of the status register to be 0. Also, the TX fifo seams to be full, but I don't know why it is not sending this data.

Here is my code:

 

static void* SPI_s_vSelectModule(uint8 u8SpiModule){

	void *pAddress = (void*)NULL;

	if(u8SpiModule == (uint8)SPI_enSPI0){

		pAddress = (void*)LPSPI0_BASE_ADDR_cfg;

	}
	else if(u8SpiModule == (uint8)SPI_enSPI2){

		pAddress = (void*)LPSPI2_BASE_ADDR_cfg;

	}
	else{
		/*	 Nothing to do	*/
	}

	return pAddress;
}


void SPI_s_vInitPorts(void){

	/*	Enable clocks	*/
	PCC->PCCn[PCC_PORTB_INDEX]|=PCC_PCCn_CGC_MASK; /* Enable clock for PORTB */
	PCC->PCCn[PCC_PORTC_INDEX]|=PCC_PCCn_CGC_MASK; /* Enable clock for PORTC */
	PCC->PCCn[PCC_PORTD_INDEX]|=PCC_PCCn_CGC_MASK; /* Enable clock for PORTD */

	/*	Config. SPI0	*/
	PORTD->PCR[15]|=PORT_PCR_MUX(4); /* Port D15: MUX = ALT4, LPSPI0_SCK reloj */
	PORTD->PCR[16]|=PORT_PCR_MUX(4); /* Port D16: MUX = ALT4, LPSPI0_SIN/MISO */
	PORTB->PCR[4]|=PORT_PCR_MUX(3); /* Port B4: MUX = ALT3, LPSPI0_SOUT/MOSI */
	PORTB->PCR[5]|=PORT_PCR_MUX(4); /* Port B5: MUX = ALT4, LPSPI0_PCS0 */

	/*	Config. SPI2	*/
	PORTC->PCR[15]|=PORT_PCR_MUX(3); /* Port C15: MUX = ALT3, LPSPI2_SCK reloj */
	PORTC->PCR[0]|=PORT_PCR_MUX(3); /* Port C0: MUX = ALT3, LPSPI2_SIN/MISO */
	PORTC->PCR[1]|=PORT_PCR_MUX(3); /* Port C1: MUX = ALT3, LPSPI2_SOUT/MOSI */
	PORTC->PCR[14]|=PORT_PCR_MUX(3); /* Port C14: MUX = ALT3, LPSPI2_PCS0 */

}

void SPI_vInitMaster(void){

LPSPI_Type *pstSPI;

for(uint8 u8x = 0; u8x < SPI_enTotalSPIs; u8x++){

if(u8x == (uint8)SPI_enSPI0){
PCC->PCCn[PCC_LPSPI0_INDEX] = 0; /* Disable clocks to modify PCS ( default) */
PCC->PCCn[PCC_LPSPI0_INDEX] = 0xC6000000; /* Enable PCS=SPLL_DIV2 (40 MHz func'l clock) */
pstSPI = (LPSPI_Type*)SPI_s_vSelectModule(u8x);
}
else if(u8x == (uint8)SPI_enSPI2){
PCC->PCCn[PCC_LPSPI2_INDEX] = 0; /* Disable clocks to modify PCS ( default) */
PCC->PCCn[PCC_LPSPI2_INDEX] = 0xC6000000; /* Enable PCS=SPLL_DIV2 (40 MHz func'l clock) */
pstSPI = (LPSPI_Type*)SPI_s_vSelectModule(u8x);
}
else{
/* Nothing to do */
}

pstSPI->CR = 0x00000000; /* Disable module for configuration */

pstSPI->IER = 0x00000000; /* Interrupts not used */

pstSPI->DER = 0x00000000; /* DMA not used */

pstSPI->CFGR0 = 0x00000000; /* Defaults: */
/* RDM0=0: rec'd data to FIFO as normal */
/* CIRFIFO=0; Circular FIFO is disabled */
/* HRSEL, HRPOL, HREN=0: Host request disabled */

pstSPI->CFGR1 = 0x00000001; /* Configurations: master mode*/
/* PCSCFG=0: PCS[3:2] are enabled */
/* OUTCFG=0: Output data retains last value when CS negated */
/* PINCFG=0: SIN is input, SOUT is output */
/* MATCFG=0: Match disabled */
/* PCSPOL=0: PCS is active low */
/* NOSTALL=0: Stall if Tx FIFO empty or Rx FIFO full */
/* AUTOPCS=0: does not apply for master mode */
/* SAMPLE=0: input data sampled on SCK edge */
/* MASTER=1: Master mode */

pstSPI->TCR = 0x5000001F; /* Transmit cmd: PCS0, 32bits, prescale func'l clk by 4. */
//pstSPI->TCR = 0x50000007; /* Transmit cmd: PCS0, 32bits, prescale func'l clk by 4. */
/* CPOL=0: SCK inactive state is low */
/* CPHA=1: Change data on SCK lead'g, capture on trail'g edge*/
/* PRESCALE=2: Functional clock divided by 2**2 = 4 */
/* PCS=0: Transfer using PCS0 */
/* LSBF=0: Data is transferred MSB first */
/*pstSPI->TCR = 0x5080001F*/ /* LSBF=1: Data is transferred LSB first */
/* BYSW=0: Byte swap disabled */
/* CONT, CONTC=0: Continuous transfer disabled */
/* RXMSK=0: Normal transfer: rx data stored in rx FIFO */
/* TXMSK=0: Normal transfer: data loaded from tx FIFO */
/* WIDTH=0: Single bit transfer */
/* FRAMESZ=15: # bits in frame = 15+1=16 */

pstSPI->CCR = 0x04090808; /* Clk dividers based on prescaled func'l clk of 100 nsec */
/* SCKPCS=4: SCK to PCS delay = 4+1 = 5 (500 nsec) */
/* PCSSCK=4: PCS to SCK delay = 9+1 = 10 (1 usec) */
/* DBT=8: Delay between Transfers = 8+2 = 10 (1 usec) */
/* SCKDIV=8: SCK divider =8+2 = 10 (1 usec: 1 MHz baud rate) */

pstSPI->FCR = 0x00000003; /* RXWATER=0: Rx flags set when Rx FIFO >0 */
/* TXWATER=3: Tx flags set when Tx FIFO <= 3 */

pstSPI->CR = 0x00000009; /* Enable module for operation */
/* DBGEN=1: module enabled in debug mode */
/* DOZEN=0: module enabled in Doze mode */
/* RST=0: Master logic not reset */
/* MEN=1: Module is enabled */
}

SPI_s_vInitPorts();
}

uint16 SPI_u8Transmit(uint8 u8SpiModule, uint8 *data, uint16 size)
{
	uint16 u16Return = (uint16)NOT_OK;
	LPSPI_Type *pstSPI;
	uint32 buffer=0;

	if(u8SpiModule < (uint8)SPI_enTotalSPIs){

		pstSPI = (LPSPI_Type*)SPI_s_vSelectModule(u8SpiModule);

		if(pstSPI != NULL){

			// Clean Tx buffer
			pstSPI->CR |= 1 << LPSPI_CR_RTF_SHIFT;

			// Configure the FRAMESZ based on the input size
			pstSPI->TCR =  0x50000000 | (size*8 - 1);

			//vSpiDelayMs(5);

			// Send all 32-bit frames that we can handle
			for(int i=0; i<(size / 4); i++)
			{
				buffer = data[4*i + 0] << 24;
				buffer |= data[4*i + 1] << 16;
				buffer |= data[4*i + 2] << 8;
				buffer |= data[4*i + 3];
				/*	Espera al que este libre	*/
				while((pstSPI->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT == 0);
				/* Transmit data */
				pstSPI->TDR = buffer;
				/* Se limpia la bandera TDF */
				pstSPI->SR |= LPSPI_SR_TDF_MASK;
			}

			// send remaining bytes
			if(size%4 > 0)
			{
				buffer = 0;
				// Send the remaining data
				for(int i=(size%4); i>0; i--)
				{
					buffer |= data[size - i] << (8*(i-1));
				}
				while((pstSPI->SR & LPSPI_SR_TDF_MASK)>>LPSPI_SR_TDF_SHIFT == 0);
				pstSPI->TDR = buffer;
				/* Se limpia la bandera TDF */
				pstSPI->SR |= LPSPI_SR_TCF_MASK;

			}

			// Clean complete flag
			pstSPI->SR |= 1 << LPSPI_SR_TCF_SHIFT;

			u16Return = (uint16)OK;
		}
		else{
			/*	Nothing to do	*/
		}
	}
	else{
		/*	Nothing to do	*/
	}

	return u16Return;
}

uint8 u8Data[] = {0x01U, 0x02U, 0x03U, 0x04U, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};

int main(void)
{
	WDOG_Disable();
	SOSC_init_8MHz(); /* Initialize system oscillator for 8 MHz xtal */
	SPLL_init_160MHz(); /* Initialize SPLL to 160 MHz with 8 MHz SOSC */
	NormalRUNmode_80MHz(); /* Init clocks: 80 MHz SPLL & core, 40 MHz bus, 20 MHz flash */
	SPI_vInitMaster();

	SPI_u8Transmit((uint8)SPI_enSPI0, u8Data, sizeof(u8Data));
	SPI_u8Transmit((uint8)SPI_enSPI0, u8Data, sizeof(u8Data));

	while(1)
	{
		vDelayMs(500);
	}
}

 

And here are some readings from a logic analyzer:

marco_medrano_0-1713230449402.png

I've been struggling with this for weeks. I'd really appreciate if you can tell me if I'm missing something

 

Tags (2)
0 Kudos
Reply
1 Solution
503 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @marco_medrano,

Try masking the RX data (TCR[RXMSK] = 1).

I don't see any code that would read RDR.

 

Thank you,

BR, Daniel

 

View solution in original post

0 Kudos
Reply
2 Replies
484 Views
marco_medrano
Contributor I

That seems to solve the issue. Thanks!

0 Kudos
Reply
504 Views
danielmartynek
NXP TechSupport
NXP TechSupport

Hi @marco_medrano,

Try masking the RX data (TCR[RXMSK] = 1).

I don't see any code that would read RDR.

 

Thank you,

BR, Daniel

 

0 Kudos
Reply