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
}