Configuration of a Slave SPI

cancel
Showing results for 
Search instead for 
Did you mean: 

Configuration of a Slave SPI

1,108 Views
madogz28
Contributor II

Hi, 

I try to make my own SPI initialization without using SDK (for an internship). 

I wrote a API in order to initialize a Slave but I can't receive frames. 
Anyone know out to initialize a Slave with registers please ? 

Fred

Labels (1)
Tags (3)
6 Replies

395 Views
mikedoidge
NXP Employee
NXP Employee

Hello,

Could you please provide the project you created? It is difficult to know what could be the issue from the details you have provided. There are many things which could cause the slave to not receive the frames, it is hard to guess which could be the cause.

Mike

0 Kudos

395 Views
madogz28
Contributor II

Hi and thank you for your reply.

Here my project. 

DriverSPI_t spi0 = {
.driver_SPI = LPSPI0,
.speed = 9600,
.Frame_Size = 15u,
.mode_SPI = SPI_Mode_Master ,
.cpol = SPI_Clock_Polarity_Enable_low,
.cpha = SPI_Clock_Phase_Leading_Edge,
.IsLSBFirst = SPI_Data_MSB_First,
.spi_pcs = SPI_PCS_1,
.pin_pcs = 31, //PTA31
.pin_sck = 2,
.pin_sin = 3,
.pin_sout = 1,
.port = PORTB
      };

DriverSPI_t spi2 = {
.driver_SPI = LPSPI2,
.speed = 9600,
.Frame_Size = 31u,
.mode_SPI = SPI_Mode_Slave,
.cpol = SPI_Clock_Polarity_Enable_low,
.cpha = SPI_Clock_Phase_Following_Edge,
.IsLSBFirst = SPI_Data_MSB_First,
.spi_pcs = SPI_PCS_2,
.pin_pcs = 13,
.pin_sck = 15,
.pin_sin = 16,
.pin_sout = 8, //A8
.port = PORTE
   };


void spi_init(DriverSPI_t spi){
if(spi.driver_SPI == LPSPI0)
{
PCC->PCCn[PCC_LPSPI0_INDEX] = 0;
PCC->PCCn[PCC_LPSPI0_INDEX] = Clock_Launch_SPI; //Activation of the SPI clock
}
else if(spi.driver_SPI == LPSPI1){
PCC->PCCn[PCC_LPSPI1_INDEX] = 0;
PCC->PCCn[PCC_LPSPI1_INDEX] = Clock_Launch_SPI; //Activation of the SPI clock
}
else if(spi.driver_SPI == LPSPI2){
PCC->PCCn[PCC_LPSPI2_INDEX] = 0;
PCC->PCCn[PCC_LPSPI2_INDEX] = 0xC6000000; //Activation of the SPI clock
}

spi.driver_SPI->CR = LPSPI_CR_RST_MASK;
spi.driver_SPI->CR = 0x00000000 ; //Disable module

if(spi.mode_SPI == SPI_Mode_Master){ //Init Master mode
spi.driver_SPI->IER = LPSPI_IER_TDIE(1) | LPSPI_IER_RDIE(1) ; //Receive and transmit data interrupt enabled
spi.driver_SPI->DER = 0 ;
spi.driver_SPI->CFGR0 = 0 ;
spi.driver_SPI->CFGR1 = LPSPI_CFGR1_MASTER(spi.mode_SPI) |
LPSPI_CFGR1_SAMPLE(0) |
LPSPI_CFGR1_AUTOPCS(0) |
LPSPI_CFGR1_NOSTALL(0) |
LPSPI_CFGR1_PCSPOL(2) | //All peripheral chip select pin is active high
LPSPI_CFGR1_MATCFG(0) |
LPSPI_CFGR1_PINCFG(0) |
LPSPI_CFGR1_OUTCFG(0) |
LPSPI_CFGR1_PCSCFG(0);
spi.driver_SPI->TCR = LPSPI_TCR_FRAMESZ(spi.Frame_Size) |
LPSPI_TCR_WIDTH(0) |
LPSPI_TCR_TXMSK(0) |
LPSPI_TCR_LSBF(MSB_First) |
LPSPI_TCR_PCS(spi.spi_pcs) |
LPSPI_TCR_PRESCALE(3) | //functional clock/Prescaler = 7MHz
LPSPI_TCR_CPHA(spi.cpha) |
LPSPI_TCR_CPOL(spi.cpol);
spi.driver_SPI->CCR = LPSPI_CCR_SCKDIV(5u) | //SCK = 1Mhz, T=1µs
LPSPI_CCR_DBT(8u) | //1.43µs between frame
LPSPI_CCR_PCSSCK(4u) | //714.3 from the PCS assertion to the first SCK edge
LPSPI_CCR_SCKPCS(4u); //714.3 from the last edge to the PCS negation
spi.driver_SPI->FCR = LPSPI_FCR_TXWATER(3u) | //Transmit Data flag set when # words <= 3
LPSPI_FCR_RXWATER(0u); //Receive Data flag set when # words > 0
}
else if(spi.mode_SPI == SPI_Mode_Slave){ //Init Slave mode
spi.driver_SPI->IER = 0x00000000 ; //Receive and transmit data interrupt enabled
spi.driver_SPI->DER = 0 ;
spi.driver_SPI->CFGR0 = 0 ;
spi.driver_SPI->CFGR1 = LPSPI_CFGR1_MASTER(spi.mode_SPI) | //Slave mode
LPSPI_CFGR1_SAMPLE(0) |
LPSPI_CFGR1_AUTOPCS(1) |
LPSPI_CFGR1_NOSTALL(0) |
LPSPI_CFGR1_PCSPOL(1) | //Chip select 0 is active high
LPSPI_CFGR1_MATCFG(0) |
LPSPI_CFGR1_PINCFG(0) |
LPSPI_CFGR1_OUTCFG(0) |
LPSPI_CFGR1_PCSCFG(0);
spi.driver_SPI->TCR = LPSPI_TCR_FRAMESZ(spi.Frame_Size) | //Size of the the frame
LPSPI_TCR_WIDTH(0) |
LPSPI_TCR_RXMSK(0) |
LPSPI_TCR_LSBF(spi.IsLSBFirst) |
LPSPI_TCR_PCS(spi.spi_pcs) |
LPSPI_TCR_PRESCALE(2u) |
LPSPI_TCR_CPHA(spi.cpha) |
LPSPI_TCR_CPOL(spi.cpol);
spi.driver_SPI->FCR = LPSPI_FCR_TXWATER(3u) | //Transmit Data flag set when # words <= 3
LPSPI_FCR_RXWATER(0u); //Receive Data flag set when # words > 0
}

spi.driver_SPI->CR = SPI_Launch; //Enable module
if(spi.driver_SPI == LPSPI0){
spi.port->PCR[spi.pin_sck] |= PORT_PCR_MUX(3u);
spi.port->PCR[spi.pin_sin] |= PORT_PCR_MUX(3u);
spi.port->PCR[spi.pin_sout] |= PORT_PCR_MUX(3u);
if(spi.mode_SPI == SPI_Mode_Master){
PORTA->PCR[spi.pin_pcs] |= PORT_PCR_MUX(4u);
}
}
else if(spi.driver_SPI == LPSPI2){
spi.port->PCR[spi.pin_sck] |= PORT_PCR_MUX(3u);
spi.port->PCR[spi.pin_sin] |= PORT_PCR_MUX(3u);
PORTA->PCR[spi.pin_sout] |= PORT_PCR_MUX(3u);
if(spi.mode_SPI == SPI_Mode_Master){
spi.port->PCR[spi.pin_pcs] |= PORT_PCR_MUX(2u);
}
}
}

--------------------------------

And here the polling mode to receive the frame.

while(!(LPSPI0->SR & LPSPI_SR_TDF_MASK) );
LPSPI0->TDR = 0x1402;
LPSPI0->SR |= LPSPI_SR_TDF_MASK;

while((LPSPI2->SR & LPSPI_SR_RDF_MASK)>>LPSPI_SR_RDF_SHIFT==0);
receive_Frame_SPI = LPSPI2->RDR;
}

Thanks by advance.


Fred

0 Kudos

395 Views
mikedoidge
NXP Employee
NXP Employee

Since some of your settings are hidden behind macros, it is hard know for sure. I think you have a couple of settings wrong.

spi.driver_SPI->CR = 0x00000000 ; //Disable module -> This should be enabled, set it to 0x00000001

and

spi.driver_SPI->CCR = LPSPI_CCR_SCKDIV(5u) | //SCK = 1Mhz, T=1µs -> This should be set to 8, not 5.

You also might find this useful: https://www.nxp.com/docs/en/application-note/AN5413.pdf 

 

Best Regards,

Mike

0 Kudos

395 Views
madogz28
Contributor II

Hi, 

Yes I am sorry for that, i will put my program whitout the macro. 

#define SPI_Launch 0x00000009
#define Clock_Launch_SPI 0xC6000000

#define MSB_First 0u
#define LSB_First 1u


typedef enum{
SPI_Clock_Polarity_Enable_low = 0u,
SPI_Clock_Polarity_Enable_high = 1u
} SPI_Clock_Polarity_t;

typedef enum{
SPI_Mode_Slave = 0u,
SPI_Mode_Master = 1u
} SPI_Mode_t;

typedef enum{
SPI_Clock_Phase_Leading_Edge = 0u,
SPI_Clock_Phase_Following_Edge = 1u
} SPI_Clock_Phase_t;

typedef enum{
SPI_Data_MSB_First = 0u,
SPI_Data_LSB_First = 1u
} SPI_LSB_First_t;

typedef enum{
SPI_PCS_0 = 0u,
SPI_PCS_1 = 1u,
SPI_PCS_2 = 2u,
SPI_PCS_3 = 3u
} SPI_PCS_t;

For the Control Register CR, I already saw on the Application note AN5413 that I have to disable the module in order to set the registers, and enable the module after that. 

For the Clock Configuration Register CCR, I forgot to tell you that I used the S32K148 in HSRUN mode (The BUS_CLK is to 56MHz), so this is fine.

Again I am sorry, I don't use often forum when I have problems. 

Fred. 

0 Kudos

395 Views
mikedoidge
NXP Employee
NXP Employee

Hello Fred,

This request is really about LPSPI on the S32K1xx family and nothing specific to S32DS. I strongly urge you to pursue this on the dedicated community for the S32K family of MCUs. https://community.nxp.com/community/s32/s32k

There is much information about SPI and how to program it. You can search the discussion threads and see what others have already done.

I would also suggest that you try using the SDK demo provided in S32DS as a way to verify that your hardware setup is good. This way you will know the issue remains just in your code.

Best Regards,

Mike

395 Views
madogz28
Contributor II

Sorry, for the IER register, it's equal to 0.

0 Kudos