csr_ssp.c

00001 #include <includes.h>
00002 
00003 //Global variables for SSP software receive buffer
00004 #define CSR_SEG_SIZE 31
00005 #define CSR_RX_SEG_NUM 8
00006 
00007 volatile unsigned short int csr_rx_buffer[CSR_RX_SEG_NUM][CSR_SEG_SIZE];//FIFO read buffer for data from SSP
00008 volatile short int csr_rx_index1 = 0;     //Points to location of segment being written by SSP isr
00009 volatile short int csr_rx_index2 = 0;     //Points to location of segment being read by parser
00010                                           //If Index2 = Index1, buffer contains no unread data.
00011                                           //If Index1 precedes Index2 by one in ring, buffer is full.
00012 
00013 //Global variables for SSP software transmit buffer
00014 #define CSR_TX_BUFFER_SIZE 500
00015 volatile unsigned short int csr_tx_buffer[CSR_TX_BUFFER_SIZE];
00016 volatile short int csr_tx_index1 = 0;
00017 volatile short int csr_tx_index2 = 0;
00018 
00020 //Clear all global buffer variables. While debugging, etc., the indices do not necessarily get reset as expected.
00021 void csr_global_variable_init(void)
00022 {
00023   short unsigned int i, j;
00024     
00025   //Clear SSP receive buffer variables
00026   csr_rx_index1 = 0;
00027   csr_rx_index2 = 0;
00028   
00029   for (i = 0; i < CSR_RX_SEG_NUM; ++i)
00030   {
00031     for (j = 0; j < CSR_SEG_SIZE; ++j)
00032     {
00033       csr_rx_buffer[i][j] = 0;
00034     }
00035   }
00036   
00037   //Clear SSP transmit buffer variables
00038   csr_tx_index1 = 0;
00039   csr_tx_index2 = 0;
00040   
00041   for (i = 0; i < CSR_TX_BUFFER_SIZE; ++i)
00042   {
00043       csr_tx_buffer[i] = 0;
00044   }  
00045 }
00046 
00048 //SSP interrupt service routine for CAN -  SSP router
00049  //__irq void csr_ssp_isr(void)
00050 void csr_ssp_isr(void)
00051 { 
00052   static short int rx_index = 0, tx_index = 0, checksum = 0, send_zeroes = 0;  
00053   short unsigned int dummy; //Dump excess received data here
00054     
00055    #ifdef DEBUG
00056     if (FIO0PIN & 1<<14)
00057     {
00058       VICIntEnClr = 0xFFFFFFFF; //Disable all interrupts before debugging
00059       VICVectAddr = 0;
00060       return;
00061     }
00062   #endif
00063   
00064   //Timer1 isr
00065   if (VICFIQStatus & 1<<5)
00066   {  
00067     
00068     //Update millisecond counter and send CAN sync frames as required
00069     csr_clock_tick();
00070         
00071     //Update read buffer indexes
00072     if  (rx_index != CSR_SEG_SIZE)
00073     {
00074       // Error - either some kind of pointer corruption caused the rx_index to go out of control,
00075       // or (more likely) the SSP bit rate is too slow to send all the data within the time period
00076       // set by the timer interrupt. Set the timer interval to a bit more than the expected packet
00077       // transmission time (e.g., 10% longer)
00078       error_occurred_fiq(ERROR_SSP_LOW_RATE);
00079       b10a_mcu_red_led_blink(50);
00080     }
00081     rx_index = 0;
00082     if (++csr_rx_index1 == CSR_RX_SEG_NUM) {csr_rx_index1 = 0;}
00083     
00084     //Check for buffer overflow
00085     if (csr_rx_index1 == csr_rx_index2)
00086     {
00087       //overflow - go back to previous segment
00088       if (--csr_rx_index1 < 0) {csr_rx_index1 = CSR_RX_SEG_NUM - 1;}
00089       error_occurred_fiq(ERROR_SSP_RX_BUF_OF);
00090       b10a_mcu_red_led_blink(50);
00091       //error - read buffer overflow; will overwrite previously received segment
00092     } 
00093     
00094     //Update transmit variables
00095     checksum = 1; //Checksum is total plus one, so checksum of zero is non-zero
00096     tx_index = 0;
00097     send_zeroes = 0;
00098         
00099     //Update interrupts
00100     SSPIMSC = 0xF;    //enable all SSP interrupts
00101     T1IR = 0xFF;  // Clear all Timer1 interrupt flags.
00102   }
00103  
00104   //SSP isr
00105   if (VICFIQStatus & 1<<11)
00106   {
00107   
00108   while(SSPSR & (1<<2))   // while RX FIFO not empty, read half-words - drain hardware buffer
00109   {
00110     if (rx_index < CSR_SEG_SIZE)
00111     {
00112       csr_rx_buffer[csr_rx_index1][rx_index] = SSPDR;
00113       ++rx_index;
00114     }
00115     else    // Throw out half-words beyond the end of the packet
00116     {
00117       dummy = SSPDR;
00118     }
00119   }   
00120   
00121   while ((SSPSR & 1<<1) && (SSPIMSC & (1<<3)))
00122   {   
00123     //Software transmit buffer is empty? Pad the rest of the transmit segment with zeroes
00124     if (csr_tx_index2 == csr_tx_index1) {send_zeroes = 1;}
00125             
00126     if (tx_index < CSR_SEG_SIZE - 1) //send segment body
00127     {
00128       // To do: revise this function and the tx push buffer function to give more reliable
00129       // synchronization between the 5-halfword data points and the packets (e.g., 31 half-words).
00130       // As is, the system will resync whenever this function sends zeroes. However, behavior if the
00131       // buffer is constantly full is worrisome. No problems were seen in testing so far, though.
00132       // One solution, a little slower, is to structure the tx buffer as a 2D array, with 5-half-word elements
00133       // in a ring buffer. Each segment would always start with a fresh 5-word element, solving the sync problem
00134       // This change would also allow the use of high and low-priority buffers, to give faster throughput
00135       // and more reliable transmisson to critical data. But a little slower overall.
00136       if (!send_zeroes) //send data
00137       {
00138         SSPDR = csr_tx_buffer[csr_tx_index2];
00139         checksum += csr_tx_buffer[csr_tx_index2];
00140         if (++csr_tx_index2 == CSR_TX_BUFFER_SIZE) {csr_tx_index2 = 0;}
00141       }
00142       else          //send zeroes to pad out segment
00143       {
00144         SSPDR = 0;
00145       }
00146     }
00147     else if (tx_index == CSR_SEG_SIZE - 1)  //Send checksum
00148     {
00149       SSPDR = checksum;
00150       SSPIMSC = (SSPIMSC & ~(1<<3)) & (0xF);    //disable SSP transmit interrupts
00151     }
00152     /*
00153     else if (tx_index <= CSR_SEG_SIZE + 0)  //Send dummy words to clear DMA buffers
00154     {
00155       SSPDR = 0;
00156     }
00157     else if (tx_index > CSR_SEG_SIZE + 0)  //
00158     {
00159       SSPDR = 0;
00160       SSPIMSC = (SSPIMSC & ~(1<<3)) & (0xF);    //disable SSP transmit interrupts
00161     }
00162     */
00163 
00164     else
00165     {
00166       error_occurred_fiq(ERROR_SSP_TX_BUF_IDX);
00167       b10a_mcu_red_led_blink(50);    //Should never get here
00168  //     SSPIMSC = (SSPIMSC & ~(1<<3)) & (0xF);    //disable SSP transmit interrupts
00169     }
00170     ++tx_index; 
00171   }
00172  
00173   if (SSPMIS & (1<<1))  //receive timeout interrupt)
00174   {
00175     SSPICR = (1<<1);  //Clear receive time-out interrupt 
00176   }
00177   
00178   if (SSPMIS & (1<<0))  //RX FIFO overflow
00179   {
00180     b10a_mcu_red_led_blink(50);
00181     error_occurred_fiq(ERROR_SSP_RX_FIFO);
00182     SSPICR = (1<<0);  //Clear receive overflow interrupt 
00183    //error - SSP hardware receive buffer overflow
00184   }
00185   } 
00186 }
00188 
00190 //SSP receive data parser
00191 unsigned short int csr_pop_ssp_frame(CAN_FRAME * frameptr)
00192 {
00193   static unsigned short int j = 0;
00194   unsigned short int i, cal_checksum, no_data;
00195   
00196   no_data = 1;
00197   
00198   //Begin parsing if buffer has data available
00199   if (csr_rx_index2 != csr_rx_index1)
00200   {
00201     //New segment? Calculate checksum.
00202     if (j == 0)
00203     {
00204       while (1)
00205       {
00206         //Calculate checksum if first segment element is non-zero
00207         if (csr_rx_buffer[csr_rx_index2][0] != 0)
00208         {
00209           cal_checksum = 1;
00210           for (i = 0; i < CSR_SEG_SIZE - 1; ++i)
00211           {
00212             cal_checksum += csr_rx_buffer[csr_rx_index2][i];
00213           }
00214           
00215           if (cal_checksum == csr_rx_buffer[csr_rx_index2][CSR_SEG_SIZE - 1])
00216           {
00217             b10a_mcu_green_led_blink(50);
00218             goto PARSE;    //checksum is good, continue after while statement
00219 //              break;
00220           }
00221           else
00222           {
00223             error_occurred(ERROR_SSP_BAD_CHKSM);
00224             b10a_mcu_red_led_blink(50);
00225           }
00226         }
00227             
00228         //Advance to next segment and try again
00229         if (csr_rx_index2 == CSR_RX_SEG_NUM - 1)
00230         {
00231           csr_rx_index2 = 0;
00232         }
00233         else
00234         {
00235           ++csr_rx_index2;
00236         }
00237         
00238         //Check that buffer is not empty
00239         if (csr_rx_index2 == csr_rx_index1)
00240         {
00241           return no_data; //Buffer empty
00242         }
00243       }
00244     }
00245   
00246     PARSE:
00247     
00248     //Look for valid data address
00249     
00250     //To do: change to:  if ((csr_rx_buffer[csr_rx_index2][j] & 0xF800) != 0) to give RTR and DLC support
00251     if ((csr_rx_buffer[csr_rx_index2][j] & 0xF800) == 0x7800)
00252     {
00253       //Should have valid data at this point, if if gets this far
00254       frameptr->chan = CHAN_SSP;              //identifies source of packet to router
00255       frameptr->addr = csr_rx_buffer[csr_rx_index2][j]; //Bottom 11 bits are CAN ID (address); .addr is 11-bit field
00256       // To do: enable this line, get rid of the next, to get DLC working here
00257      // frameptr->dlc = ~(csr_rx_buffer[csr_rx_index2][j] >> 11); //Next 4 bits are data length code; .dlc is 4-bit field
00258       frameptr->dlc = 8;  //Only 8-byte payloads supported at this time (and rtr?)
00259       frameptr->rtr = csr_rx_buffer[csr_rx_index2][j++] >> 15; //Top bit is remote transmission request; .rtr is 1-bit field
00260       frameptr->payload.s.s2 = csr_rx_buffer[csr_rx_index2][j++];  //copy payload data
00261       frameptr->payload.s.s1 = csr_rx_buffer[csr_rx_index2][j++];
00262       frameptr->payload.s.s4 = csr_rx_buffer[csr_rx_index2][j++];
00263       frameptr->payload.s.s3 = csr_rx_buffer[csr_rx_index2][j++];
00264       no_data = 0;
00265     }
00266     else if ((csr_rx_buffer[csr_rx_index2][j] & 0xF800) == 0xF800)  // To do: get rid of this, not needed, see above
00267     {
00268       //remote transfer request (RTR)
00269       j += 5;
00270     }
00271     else  //not a valid data packet, skip the rest of the segment
00272     {
00273       j = CSR_SEG_SIZE - 1;
00274     }
00275   
00276     if (j == CSR_SEG_SIZE - 1)
00277     {
00278       //Advance to next segment
00279       if (csr_rx_index2 == CSR_RX_SEG_NUM - 1)
00280       {
00281         csr_rx_index2 = 0;
00282       }
00283       else
00284       {
00285         ++csr_rx_index2;
00286       }
00287       
00288       //reset j to 0
00289       j = 0;
00290     }
00291     else if (j > CSR_SEG_SIZE - 1)
00292     {
00293       error_occurred(ERROR_SSP_RX_BUF_IDX);
00294       b10a_mcu_red_led_blink(50);    //Should never get here
00295     }
00296     return no_data;   //Valid return data 
00297   }
00298   else
00299   {
00300     return no_data;   //Receive buffer empty
00301   }
00302 }
00304 
00306 unsigned short int csr_push_ssp_frame(CAN_FRAME * frame)
00307 {
00308   short int temp_index1;
00309   
00310   temp_index1 = csr_tx_index1;
00311   
00312   //load data from incoming frame
00313   csr_tx_buffer[temp_index1] = frame->addr  //CAN ID (address)
00314   | (0xF << 11)               //extra bits for future
00315   | (frame->rtr << 15)    //remote transmission request bit
00316   ;
00317   //Advance temp_index to next available location
00318   if (++temp_index1 == CSR_TX_BUFFER_SIZE)  {temp_index1 = 0;}
00319   //Check for buffer overflow
00320   if (temp_index1 == csr_tx_index2)
00321   {
00322     error_occurred(ERROR_SSP_TX_BUF_OF);
00323     return 1;
00324   }  //buffer full
00325 
00326   //Load first short int of CAN payload
00327   csr_tx_buffer[temp_index1] = frame->payload.s.s2; 
00328   //Advance temp_index to next available location
00329   if (++temp_index1 == CSR_TX_BUFFER_SIZE)  {temp_index1 = 0;}
00330   //Check for buffer overflow
00331   if (temp_index1 == csr_tx_index2)
00332   {
00333     error_occurred(ERROR_SSP_TX_BUF_OF);
00334     return 1;
00335   }  //buffer full
00336   
00337   //Load second short int of CAN payload
00338   csr_tx_buffer[temp_index1] = frame->payload.s.s1; 
00339   //Advance temp_index to next available location
00340   if (++temp_index1 == CSR_TX_BUFFER_SIZE)  {temp_index1 = 0;}  
00341   //Check for buffer overflow
00342   if (temp_index1 == csr_tx_index2) 
00343   {
00344     error_occurred(ERROR_SSP_TX_BUF_OF);
00345     return 1;
00346   } //buffer full
00347   
00348   //Load third short int of CAN payload
00349   csr_tx_buffer[temp_index1] = frame->payload.s.s4;   
00350   //Advance temp_index to next available location
00351   if (++temp_index1 == CSR_TX_BUFFER_SIZE)  {temp_index1 = 0;}  
00352   //Check for buffer overflow
00353   if (temp_index1 == csr_tx_index2) 
00354   {
00355     error_occurred(ERROR_SSP_TX_BUF_OF);
00356     return 1;
00357   } //buffer full
00358     
00359   //Load fourth short int of CAN payload  
00360   csr_tx_buffer[temp_index1] = frame->payload.s.s3;   
00361   //Advance temp_index to next available location
00362   if (++temp_index1 == CSR_TX_BUFFER_SIZE)  {temp_index1 = 0;}  
00363   //Check for buffer overflow
00364   if (temp_index1 == csr_tx_index2) 
00365   {
00366     error_occurred(ERROR_SSP_TX_BUF_OF);    
00367     return 1;
00368   } //buffer full
00369   
00370   csr_tx_index1 = temp_index1;    //update csr_tx_index1 and make new data available to isr
00371        
00372   return 0; //Frame added successfully          
00373 }
Generated on Tue Jun 29 16:36:14 2010 by  doxygen 1.6.3