AnsweredAssumed Answered

kl25z spi basics

Question asked by mjg8t on May 19, 2014
Latest reply on May 22, 2014 by mjg8t

I am working with the SPI0 peripheral on the kl25z freedom board.  I was having some trouble getting the SPI receive buffer to give me the expected output. I used a loopback test on MOSI and MISO for self testing. I found that the problem was that I had to insert a manual delay in order for the proper data to be received from the buffer (see delay_nop(100) in code).  After inserting the delay the "r" receive buffer five the correct data of 0xa1- 0xa4.  Without the delay the buffer returns 0x03,0x04,0xa1,0xa2, which are the last 2 bytes from the transmit loop and the first 2 bytes of the receive loop.  You can see the attached image capture to see the sequence of events with and without the delay, with a test signal being triggered.

 

1) I thought that the "SPI_WAIT_RX_DATA" would throttle the SPI transaction without needing the manual delay.  I thought that the SPRF flag would wait upon each SPI send until it was received then proceed.  But, it seems to blow past the data actually being received?

 

It seems that there would be a more efficient way of writing the routines than using a manual delay that would have to be tuned depending on the clock rate.  But, I do not see any other flags that might help in the process.  Is a manual delay the only option?

 

 

#define TEST_LOW GPIOD_PCOR |= GPIO_PCOR_PTCO(0x01)  //debug pin
#define TEST_HIGH GPIOD_PSOR |= GPIO_PSOR_PTSO(0x01) //debug pin
#define SPI_WAIT_RX_DATA while (!(SPI0_S & SPI_S_SPRF_MASK))  //waits for the rx data ready ready
#define SPI_WAIT_TX_DATA while (!(SPI0_S & SPI_S_SPTEF_MASK)) //waits for the txef data ready ready
#define SPI_RD_WR_REG SPI0_D  //kinetis read write register
void spi_test_io( void){
  uint8_t i=0,junk,status;
  uint8_t j = 0xA0;
  uint8_t r[4] = {0};

  TEST_LOW;
  //clock out 1-8 on spi bus
  for(i=0;i<4;i++){
  SPI_WAIT_TX_DATA; //WAITS UNTIL THE TX EMPTY BUFFER FLAG GOES HIGH
  SPI_RD_WR_REG = i+1; //OUTPUT A1 ON SPI
  SPI_WAIT_RX_DATA; //THOUGHT THIS WOULD THROTTLE THE LOOP - WAIT FOR DATA TO BE TX (RECEIVED)
  }
  //delay_nop(100);  //ENOUGH TIME TO OUTPUT THE DATA....
  TEST_HIGH;


  //TRYING TO CLEAR BUFFER SO THAT CAN READ CURRENT SPI DATA
  //junk = SPI_STATUS; //read status
  junk = SPI_RD_WR_REG; //MUST READ DATA IN ORDER FOR NEXT READS TO BE CORRECT

  for(i=0;i<4;i++){
  //output and read 0xa0 - 0xa4
  SPI_WAIT_TX_DATA; //WAITS UNTIL THE TX EMPTY BUFFER FLAG GOES HIGH
  SPI_RD_WR_REG = j++; //OUTPUT A1-a4 ON SPI
  SPI_WAIT_RX_DATA; //wait for data to be tx
  r[i] = SPI_RD_WR_REG; //READ REG TO UPDATE BUFFER
  }

  TEST_LOW;
  asm("nop");
}


void spi_init( void){

  //SPI0 module initialization
  SIM_SCGC4 |= SIM_SCGC4_SPI0_MASK; // Turn on clock to SPI0 module
  SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK; // Turn on clock to Port D module
  PORTD_PCR1 = PORT_PCR_MUX(0x02); // PTD1 pin is SPI0 CLK line
  PORTD_PCR2 = PORT_PCR_MUX(0x02); // PTD2 pin is SPI0 MOSI line
  PORTD_PCR3 = PORT_PCR_MUX(0x02); // PTD3 pin is SPI0 MISO line
  PORTD_PCR0 = PORT_PCR_MUX(0x01); // PTD0 pin is configured as GPIO (CS line driven manually)
  GPIOD_PSOR |= GPIO_PSOR_PTSO(0x01); // PTD0 = 1 (CS inactive)
  GPIOD_PDDR |= GPIO_PDDR_PDD(0x01); // PTD0 pin is GPIO output

  //SETUP SPI0 PERIPHERAL
  SPI0_C1 = SPI_C1_SPE_MASK | SPI_C1_MSTR_MASK; // Enable SPI0 module, master mode //SETS SPI ENABLE AND SPI MASTER BITS
  SPI0_BR = SPI_BR_SPPR(0x04) | SPI_BR_SPR(0x02) ; // BaudRate = BusClock / ((SPPR+1) * 2^(SPR+1)) = 20970000 / ((4+1) * 2^(2+1)) = 524.25 kHz
  //SPI0_BR = SPI_BR_SPPR(0x00) | SPI_BR_SPR(0x00) ; // BaudRate = BusClock / ((SPPR+1) * 2^(SPR+1)) = 20970000 / ((4+1) * 2^(2+1)) = 5240.25 kHz

}

Outcomes