[Help]K64F SPI Bare Metal example

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

[Help]K64F SPI Bare Metal example

Jump to solution
4,815 Views
rafaeltoledo
Contributor III

Hi,

Someone has an SPI code example preferably with interrupt for FRDM-K64F?

It may be a example without interrupt also, already help me a lot because I can't make the SPI work only by reading the reference manual.

Labels (1)
1 Solution
1,520 Views
rafaeltoledo
Contributor III

I developed a example of Sending/Receiving data:

#define SPI_PUSHR_PCS0_ON 0x10000

#define SPI_PUSHR_PCS1_ON 0x20000

#define SPI_PUSHR_PCS2_ON 0x40000

#define SPI_PUSHR_PCS3_ON 0x80000

#define SPI_PUSHR_PCS4_ON 0x100000

#define SPI_PUSHR_PCS5_ON 0x200000

#define SPI_CTAR_FMSZ_8BIT 0x38000000

#define SPI_CTAR_FMSZ_16BIT 0x78000000

int main(void)

{

  unsigned char cmd = 0x01;

  unsigned char receiveBuffer[3];

  //configure ports

  SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; // Enable PORT clock gating ctrl

  SIM_SCGC6 |= SIM_SCGC6_SPI0_MASK;

  //PORT D

  PORTD_PCR(0) = PORT_PCR_MUX(2); //PCS0

  PORTD_PCR(1) = PORT_PCR_MUX(2); //SCK

  PORTD_PCR(2) = PORT_PCR_MUX(2); //SOUT

  PORTD_PCR(3) = PORT_PCR_MUX(2); //SIN

  // Clear all registers

  SPI0_SR = (SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK); //clear the status bits (write-1-to-clear)

  SPI0_TCR = 0;

  SPI0_RSER = 0;

  SPI0_PUSHR = 0; //Clear out PUSHR register. Since DSPI is halted, nothing should be transmitted

  SPI0_CTAR0 = 0;

  // configure registers

  SPI0_MCR |= SPI_MCR_MSTR_MASK | SPI_MCR_PCSIS_MASK;

  SPI0_MCR &= (~SPI_MCR_DIS_RXF_MASK & ~SPI_MCR_DIS_TXF_MASK); // enable FIFOs

  SPI0_MCR &=  (~SPI_MCR_MDIS_MASK & ~SPI_MCR_HALT_MASK); //enable SPI and start transfer

  SPI0_CTAR0 |=  SPI_CTAR_FMSZ_8BIT | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_BR(6); // 8 bits, 500khz at 120Mhz

// Send Steps:

  while(1){

  SPI0_MCR |=  SPI_MCR_HALT_MASK;

  SPI0_MCR |= (SPI_MCR_CLR_RXF_MASK | SPI_MCR_CLR_TXF_MASK); //flush the fifos

  SPI0_SR |= (SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK); //clear the status bits (write-1-to-clear)

  SPI0_TCR |= SPI_TCR_SPI_TCNT_MASK;

  SPI0_MCR &=  ~SPI_MCR_HALT_MASK;

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | cmd);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xAA);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xBB);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xCC);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xDD);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_EOQ_MASK | SPI_PUSHR_PCS0_ON | 0xEE); //send last byte

  SPI0_SR |= SPI_SR_TFFF_MASK; //clear the status bits (write-1-to-clear)

  cmd++;

  }

//*****************************************************************************************************************************************

//Receive Steps: (tested with memory MX25L3206E)

while(1){

  SPI0_MCR |=  SPI_MCR_HALT_MASK;

  SPI0_MCR |= (SPI_MCR_CLR_RXF_MASK | SPI_MCR_CLR_TXF_MASK); //flush the fifos

  SPI0_SR |= (SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK); //clear the status bits (write-1-to-clear)

  SPI0_TCR |= SPI_TCR_SPI_TCNT_MASK;

  SPI0_MCR &=  ~SPI_MCR_HALT_MASK;

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK |  SPI_PUSHR_PCS_MASK | 0x9F); //command byte

  while (!(SPI0_SR & SPI_SR_RFDF_MASK)  );

  SPI0_POPR; //dummy read

  SPI0_SR = SPI_SR_RFDF_MASK;   // clear the reception flag (not self-clearing)

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xFF); //dummy byte to read

  while (!(SPI0_SR & SPI_SR_RFDF_MASK)  );

  receiveBuffer[0] = SPI0_POPR; //read

  SPI0_SR = SPI_SR_RFDF_MASK;   // clear the reception flag (not self-clearing)

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK |  SPI_PUSHR_PCS0_ON | 0xFF); //dummy byte to read

  while (!(SPI0_SR & SPI_SR_RFDF_MASK)  );

  receiveBuffer[1] = SPI0_POPR; //read

  SPI0_SR = SPI_SR_RFDF_MASK;   // clear the reception flag (not self-clearing)

  SPI0_PUSHR = (SPI_PUSHR_EOQ_MASK | SPI_PUSHR_PCS0_ON | 0xFF); //send last dummy byte to read

  while (!(SPI0_SR & SPI_SR_RFDF_MASK)  );

  receiveBuffer[2] = SPI0_POPR; //read

  SPI0_SR = SPI_SR_RFDF_MASK;   // clear the reception flag (not self-clearing)

  }

  return 0;

}

View solution in original post

3 Replies
1,521 Views
rafaeltoledo
Contributor III

I developed a example of Sending/Receiving data:

#define SPI_PUSHR_PCS0_ON 0x10000

#define SPI_PUSHR_PCS1_ON 0x20000

#define SPI_PUSHR_PCS2_ON 0x40000

#define SPI_PUSHR_PCS3_ON 0x80000

#define SPI_PUSHR_PCS4_ON 0x100000

#define SPI_PUSHR_PCS5_ON 0x200000

#define SPI_CTAR_FMSZ_8BIT 0x38000000

#define SPI_CTAR_FMSZ_16BIT 0x78000000

int main(void)

{

  unsigned char cmd = 0x01;

  unsigned char receiveBuffer[3];

  //configure ports

  SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; // Enable PORT clock gating ctrl

  SIM_SCGC6 |= SIM_SCGC6_SPI0_MASK;

  //PORT D

  PORTD_PCR(0) = PORT_PCR_MUX(2); //PCS0

  PORTD_PCR(1) = PORT_PCR_MUX(2); //SCK

  PORTD_PCR(2) = PORT_PCR_MUX(2); //SOUT

  PORTD_PCR(3) = PORT_PCR_MUX(2); //SIN

  // Clear all registers

  SPI0_SR = (SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK); //clear the status bits (write-1-to-clear)

  SPI0_TCR = 0;

  SPI0_RSER = 0;

  SPI0_PUSHR = 0; //Clear out PUSHR register. Since DSPI is halted, nothing should be transmitted

  SPI0_CTAR0 = 0;

  // configure registers

  SPI0_MCR |= SPI_MCR_MSTR_MASK | SPI_MCR_PCSIS_MASK;

  SPI0_MCR &= (~SPI_MCR_DIS_RXF_MASK & ~SPI_MCR_DIS_TXF_MASK); // enable FIFOs

  SPI0_MCR &=  (~SPI_MCR_MDIS_MASK & ~SPI_MCR_HALT_MASK); //enable SPI and start transfer

  SPI0_CTAR0 |=  SPI_CTAR_FMSZ_8BIT | SPI_CTAR_CPOL_MASK | SPI_CTAR_CPHA_MASK | SPI_CTAR_BR(6); // 8 bits, 500khz at 120Mhz

// Send Steps:

  while(1){

  SPI0_MCR |=  SPI_MCR_HALT_MASK;

  SPI0_MCR |= (SPI_MCR_CLR_RXF_MASK | SPI_MCR_CLR_TXF_MASK); //flush the fifos

  SPI0_SR |= (SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK); //clear the status bits (write-1-to-clear)

  SPI0_TCR |= SPI_TCR_SPI_TCNT_MASK;

  SPI0_MCR &=  ~SPI_MCR_HALT_MASK;

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | cmd);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xAA);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xBB);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xCC);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xDD);

  while(!(SPI0_SR & SPI_SR_TCF_MASK));

  SPI0_PUSHR = (SPI_PUSHR_EOQ_MASK | SPI_PUSHR_PCS0_ON | 0xEE); //send last byte

  SPI0_SR |= SPI_SR_TFFF_MASK; //clear the status bits (write-1-to-clear)

  cmd++;

  }

//*****************************************************************************************************************************************

//Receive Steps: (tested with memory MX25L3206E)

while(1){

  SPI0_MCR |=  SPI_MCR_HALT_MASK;

  SPI0_MCR |= (SPI_MCR_CLR_RXF_MASK | SPI_MCR_CLR_TXF_MASK); //flush the fifos

  SPI0_SR |= (SPI_SR_TCF_MASK | SPI_SR_EOQF_MASK | SPI_SR_TFUF_MASK | SPI_SR_TFFF_MASK | SPI_SR_RFOF_MASK | SPI_SR_RFDF_MASK); //clear the status bits (write-1-to-clear)

  SPI0_TCR |= SPI_TCR_SPI_TCNT_MASK;

  SPI0_MCR &=  ~SPI_MCR_HALT_MASK;

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK |  SPI_PUSHR_PCS_MASK | 0x9F); //command byte

  while (!(SPI0_SR & SPI_SR_RFDF_MASK)  );

  SPI0_POPR; //dummy read

  SPI0_SR = SPI_SR_RFDF_MASK;   // clear the reception flag (not self-clearing)

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK | SPI_PUSHR_PCS0_ON | 0xFF); //dummy byte to read

  while (!(SPI0_SR & SPI_SR_RFDF_MASK)  );

  receiveBuffer[0] = SPI0_POPR; //read

  SPI0_SR = SPI_SR_RFDF_MASK;   // clear the reception flag (not self-clearing)

  SPI0_PUSHR = (SPI_PUSHR_CONT_MASK |  SPI_PUSHR_PCS0_ON | 0xFF); //dummy byte to read

  while (!(SPI0_SR & SPI_SR_RFDF_MASK)  );

  receiveBuffer[1] = SPI0_POPR; //read

  SPI0_SR = SPI_SR_RFDF_MASK;   // clear the reception flag (not self-clearing)

  SPI0_PUSHR = (SPI_PUSHR_EOQ_MASK | SPI_PUSHR_PCS0_ON | 0xFF); //send last dummy byte to read

  while (!(SPI0_SR & SPI_SR_RFDF_MASK)  );

  receiveBuffer[2] = SPI0_POPR; //read

  SPI0_SR = SPI_SR_RFDF_MASK;   // clear the reception flag (not self-clearing)

  }

  return 0;

}

1,519 Views
EarlOrlando
Senior Contributor II

Hello Rafael,

Are you interested in using the Kinetis SDK? It provides comprehensive software support for Kinetis MCUs. It includes a hardware abstraction layer (HAL) and drivers for each MCU peripheral, USB and connectivity stacks, middleware, real-time operating systems and example applications designed to simplify and accelerate application development on Kinetis MCUs. The Kinetis SDK is complimentary and includes full source code under a permissive open-source license for all hardware abstraction and peripheral driver software. The Kinetis SDK is offered for free, and support for it is provided here.

Of course the SPI driver is supported by KSDK. Examples about its usage are located in the installation path in the folder C:\Freescale\KSDK_1.2.0\examples, you can see the spi_sdcard example in the folder C:\Freescale\KSDK_1.2.0\examples\twrk22f120m\driver_examples\spi_sdcard, this is built for the K22 MCU but due to the portability that offers KSDK, this is exactly the same code for the K64 MCU. Also, you can take a look into the SPI driver examples built to the KL devices.

Also, you can take a look into the document KSDK SPI Master-Slave with FRDM-K64F.

Please let me know if this information is useful or if I can do anything else for you.

Best regards,

Earl Orlando.

/* If this post answers your question please click the Correct Answer button. */

0 Kudos
1,520 Views
rafaeltoledo
Contributor III

Hello Earl,

I'm not using KSDK libraries purposely.

On really, I need to be able to manipulate the registers, because I'm trying to Develop my own SPI library, with some peculiarities specific to my project.

This is part of configuration for SPI0 in my code:

SPI0_INTERFACE:

SIM_SCGC5 |= MuxConfig[SPI_DeviceList[ID].RoutedPort].mask;// Enable PORT clock gating ctrl

SIM_SCGC6 |= SIM_SCGC6_SPI0_MASK; //Turn on clock to SPI module

PORT_PCR_REG(MuxConfig[SPI_DeviceList[ID].RoutedPort].port, MuxConfig[SPI_DeviceList[ID].RoutedPort].sck_pin) = PORT_PCR_MUX(MuxConfig[SPI_DeviceList[ID].RoutedPort].mux);

PORT_PCR_REG(MuxConfig[SPI_DeviceList[ID].RoutedPort].port, MuxConfig[SPI_DeviceList[ID].RoutedPort].sin_pin) = PORT_PCR_MUX(MuxConfig[SPI_DeviceList[ID].RoutedPort].mux);

PORT_PCR_REG(MuxConfig[SPI_DeviceList[ID].RoutedPort].port, MuxConfig[SPI_DeviceList[ID].RoutedPort].sout_pin) = PORT_PCR_MUX(MuxConfig[SPI_DeviceList[ID].RoutedPort].mux);

PORT_PCR_REG(MuxSCConfig[SPI_DeviceList[ID].ChipSelect].port,MuxSCConfig[SPI_DeviceList[ID].ChipSelect].pcs_pin) = PORT_PCR_MUX(MuxSCConfig[SPI_DeviceList[ID].ChipSelect].mux);

SPI0_MCR |= SPI_MCR_MSTR_MASK | SPI_DeviceList[ID].CSOption;

SPI0_MCR &= ~SPI_MCR_DIS_TXF_MASK; // enable FIFOs

SPI0_CTAR0 |=  SPI_CTAR_FMSZ(8) | SPI_DeviceList[ID].CSOption | SPI_DeviceList[ID].Polarity | SPI_DeviceList[ID].Phase | SPI_DeviceList[ID].BaudRate;

NVIC_EnableIRQ(SPI0_IRQn);

I found some examples useful like this SPI Master always sends 16 bits words in non-continuous mode

But nothing significative.

I need an functional example, configurating the port, pin, baud rate, sending and receiving data through SPI to verify my code and find my error.

0 Kudos