Confirming SPI data rate

Thread Starter

Samyukta Ramnath

Joined May 21, 2015
16
Besides filling a large array with data and running the program to send data at a particular data rate (say 2khz), and seeing whether in 2 seconds I get around 2000 data samples, is there any other way to actually verify the number of samples of data that I receive?
 

Papabravo

Joined Feb 24, 2006
15,078
Yes. Look at the SCLK signal from the falling edge of chip select to the rising edge of chip select. Measuring throughput is really a very crude way to measure what you are after. 100% error would not surprise me.
 

Thread Starter

Samyukta Ramnath

Joined May 21, 2015
16
Yes. Look at the SCLK signal from the falling edge of chip select to the rising edge of chip select. Measuring throughput is really a very crude way to measure what you are after. 100% error would not surprise me.
But the SCLK signal is what I have given from the master. So I am expecting 12 words, each 32 bits, and 2000 of these 12 word frames in 1 second. So the minimum clock I give from the master is 12*32*2000 = 768kHz. I gave around 1000kHz. If I measure SCLK now I'll be getting 1000 kHz, right?
 

Papabravo

Joined Feb 24, 2006
15,078
You can only relate clock rate to throughput if the transfer is synchronous and continuous In most SPI applications there is a chip select going active, several bytes of data transfer, and chip select goes inactive. As you can see there is some amount of time that is not devoted to data transfer. You can measure clock rate or throughput but it is a mistake to conflate the two measurements.
 
Last edited:

Thread Starter

Samyukta Ramnath

Joined May 21, 2015
16
You can only relate clock rate to throughput if the transfer is synchronous and continuous In most SPI applications there is a chip select going active, several bytes of data transfer, and chip select goes inactiv As you can see there is some amount of time that is not devoted to data transfer. You can measure clock rate or throughput but it is a mistake to conflate the two measurements.
I am commanding the slave to send me 2000 frames of twelve 32 bit words per second. I am giving sufficient SCLK as the master to sample this - but how do I confirm that the slave is indeed sending data at the rate it is supposed to, apart from checking throughput?


The SPI data-rate is the rate at which the master sends/receives.
You're the master, so you know the data-rate already.
Yes, that was my doubt. I know the SCLK rate - I want to confirm that the slave is sending that much data in 1 second.
 

nsaspook

Joined Aug 27, 2009
7,995
It's always byte sent/byte received. The actual contents of that data from the slave is up the slave to produce. You can embed check bits or bytes into the expected slave stream to check for correct data format and sequencing.
 

Papabravo

Joined Feb 24, 2006
15,078
SPI is not a robust protocol. At the physical layer you have no idea if the slave device is sending valid data at all. If the MISO line is stuck at '1' or stuck at '0' the master would never know because it has no way to check for valid data from the slave device. At a higher layer in the stack you can embed such information but most slave devices don't do this. It's just data.
 

nsaspook

Joined Aug 27, 2009
7,995
SPI is not a robust protocol. At the physical layer you have no idea if the slave device is sending valid data at all. If the MISO line is stuck at '1' or stuck at '0' the master would never know because it has no way to check for valid data from the slave device. At a higher layer in the stack you can embed such information but most slave devices don't do this. It's just data.
Correct. I usually have a 'special' DUMMY byte that's loaded in the slave send buffer at reset/after each command sequence waiting to be clocked out by the first master receive byte.

A simple dummy with config data.
Code:
/*
* bit 7 high for commands sent from the MASTER
* bit 6 0 send lower or 1 send upper byte ADC result first
* bits 3..0 port address
*
* bit 7 low  for config data sent in CMD_DUMMY per uC type
* bits 6 config bit code always 1
* bit   5 0=ADC ref VDD, 1=ADC rec FVR=2.048
* bit  4 0=10bit adc, 1=12bit adc
* bits 3..0 number of ADC channels
*
*/

#ifdef P8722
#define CMD_DUMMY  0b01001100   /* 12 channels VDD */
#define NUM_AI_CHAN  12
#define SPI_BUF     SSP2BUF    
#endif
#ifdef P25K22
#define CMD_DUMMY   0b01101110   /* 14 channels 2.048 but only 13 are ADC */
#define NUM_AI_CHAN  14
#define SPI_BUF     SSP2BUF
#endif
#ifdef P45K80
#define CMD_DUMMY   0b00111010   /* 10 channels 2.048 but only 9 are ADC,bit 6 set for rs232 data waiting */
#define NUM_AI_CHAN  10
#define UART_TX_MASK   0b10000000
#define UART_RX_MASK   0b01000000
#define SPI_BUF     SSPBUF
#endif
 

Thread Starter

Samyukta Ramnath

Joined May 21, 2015
16
Correct. I usually have a 'special' DUMMY byte that's loaded in the slave send buffer at reset/after each command sequence waiting to be clocked out by the first master receive byte.

A simple dummy with config data.
Code:
/*
* bit 7 high for commands sent from the MASTER
* bit 6 0 send lower or 1 send upper byte ADC result first
* bits 3..0 port address
*
* bit 7 low  for config data sent in CMD_DUMMY per uC type
* bits 6 config bit code always 1
* bit   5 0=ADC ref VDD, 1=ADC rec FVR=2.048
* bit  4 0=10bit adc, 1=12bit adc
* bits 3..0 number of ADC channels
*
*/

#ifdef P8722
#define CMD_DUMMY  0b01001100   /* 12 channels VDD */
#define NUM_AI_CHAN  12
#define SPI_BUF     SSP2BUF   
#endif
#ifdef P25K22
#define CMD_DUMMY   0b01101110   /* 14 channels 2.048 but only 13 are ADC */
#define NUM_AI_CHAN  14
#define SPI_BUF     SSP2BUF
#endif
#ifdef P45K80
#define CMD_DUMMY   0b00111010   /* 10 channels 2.048 but only 9 are ADC,bit 6 set for rs232 data waiting */
#define NUM_AI_CHAN  10
#define UART_TX_MASK   0b10000000
#define UART_RX_MASK   0b01000000
#define SPI_BUF     SSPBUF
#endif
So the dummy byte is to confirm whether the correct data is sent ... am I right?
So in my code, whenever I write to a particular address, I get back that address location in the first byte along with the data in the next three bytes, to form one four byte word, while writing the next word. So I know that I am getting the correct data. The only issue is the data rate.
Is there something like a timestamp that I can add along with the data variable when it is being stored, to give me even an approximate idea that what I am receiving is close to what I should be?
What about a USB-I2C converter to print data on to my computer screen at the rate it is being stored (popped from the rx fifo)?
 

nsaspook

Joined Aug 27, 2009
7,995
I don't see much of a problem doing that(timestamp). You know exactly what the data rate is because you control the master and know the data format sent by the slave in response.
 

Thread Starter

Samyukta Ramnath

Joined May 21, 2015
16
Thank you for your responses!
I tried using the RTC to read the number of clock cycles. I used the RTC_TPR register. I Initialized the RTC and then read the value of the RTC_TPR register before loading the data variables and after loading the data variables.

I have given a clock of 1000 kHz from the master for SPI communication, and I should be getting data at a rate of 2000 words per second from the slave. Now to achieve the timestamping, I have read the RTC clock at the event of receiving a word in the code. If the RTC clock is 32kHz, I should be able to correctly detect a data rate of 2000 words per second, right?
However, the time interval according to the RTC to get 500 data variables is much less than 0.25 seconds. It is around 0.0175 seconds.
Am I doing something wrong, either in using an RTC clock less than the SPI master clock (even though I need to detect the event as received word, not received byte), or in the way I am using the RTC clock?
The code I have used is below:

to initialize the RTC

Code:
void rtc_init(uint32 seconds, uint32 alarm, uint8 c_interval, uint8 c_value, uint8 interrupt)

{

  int i;



  /*enable the clock to SRTC module register space*/

  SIM_SCGC6 |= SIM_SCGC6_RTC_MASK;



  /*Only VBAT_POR has an effect on the SRTC, RESET to the part does not, so you must manually reset the SRTC to make sure everything is in a known state*/

  /*clear the software reset bit*/

  RTC_CR  = RTC_CR_SWR_MASK;

  RTC_CR  &= ~RTC_CR_SWR_MASK;



  /*Enable the interrupt*/

  if(interrupt)

  enable_irq(66);



  /*Enable the oscillator*/

  RTC_CR |= RTC_CR_OSCE_MASK;



  /*Wait to all the 32 kHz to stabilize, refer to the crystal startup time in the crystal datasheet*/

  for(i=0;i<0x600000;i++);



  /*Set time compensation parameters*/

  RTC_TCR = RTC_TCR_CIR(c_interval) | RTC_TCR_TCR(c_value);



  /*Configure the timer seconds and alarm registers*/

  RTC_TSR = seconds;

  RTC_TAR = alarm;

  RTC_TPR = 0;

  /*Enable the counter*/

  RTC_SR |= RTC_SR_TCE_MASK;

}



In main module, after SPI initialization:
Code:
  time_initial= RTC_TPR;

  time_initial_sec = RTC_TSR;

  // test single byte transmission

  while(j<500){

  //for (j=0;j<4;j++){

  for (i=0;i<=11;i++){

  data[j] = reg_read(0x00000000);

  //I2C0_D = data;

  //I2C0_A1 = datain;

  time = RTC_TPR;

  time_sec = RTC_TSR;

  // printf("dataout: %x\ndatain: %x\ntime: %x\nTimeDirect: %x\n\n",data,datain,*ticky,time);

  j++;

  //  if(j==500)

  // printf("500!\n");

  }

  //printf("%d\n",j);

  reg_Write(0x40000000);

  }

  printf("initial time = %d\nintial sec = %d\nFinal Time =%d\nFinalTimeSec = %d\n\n",time_initial,time_initial_sec, time,time_sec);

}



Where reg_read and reg_Write are used to read and write from and to 32 bit words respectively.
 

RamaD

Joined Dec 4, 2009
328
As members have clarified, the master defines the data rate with its clock. On each clock, whatever is present on MISO pin is going to be taken in.
So the simple way is, measure clock period with a scope. Should be 1uS.
My wild guess is, given your measurment times, either the SPI clock is 10MHz., or your time period is 0.175s.
Check your RTC clock reading, with a long time of, say 10s with a couple of start stop events. Sorry about being cryptic, but you get the idea.
 
Top