can_tx.c

00001 #include <includes.h>
00002 
00003 CAN_TX_CHAN_CFG  can_tx_chan_cfgs[5];   //Five elements, index 1 to 4
00004 
00005 extern unsigned long can_elapsed_ms;   // CAN module time variable
00006 
00007 // CAN error global variables:
00008 extern volatile unsigned long can_error_1;
00009 extern volatile unsigned long can_error_2;
00010 extern volatile unsigned long can_error_3;
00011 extern volatile unsigned long can_error_4;
00012 
00013 // CAN transmit frame count global variables:
00014 volatile unsigned short can_tx_frame_count_1 = 0;
00015 volatile unsigned short can_tx_frame_count_2 = 0;
00016 volatile unsigned short can_tx_frame_count_3 = 0;
00017 volatile unsigned short can_tx_frame_count_4 = 0;
00018 
00019 unsigned short can_tx_get_frame_count_1(CAN_FRAME * frame)
00020 {
00021   frame->payload.w.w1 = can_tx_frame_count_1;
00022   can_tx_frame_count_1 = 0;     //Reset frame counter - could lose a count here, but not critical
00023   frame->payload.w.w2 = can_elapsed_ms;
00024   return 0;
00025 }
00026 
00027 unsigned short can_tx_get_frame_count_2(CAN_FRAME * frame)
00028 {
00029   frame->payload.w.w1 = can_tx_frame_count_2;
00030   can_tx_frame_count_2 = 0;     //Reset frame counter - could lose a count here, but not critical
00031   frame->payload.w.w2 = can_elapsed_ms;
00032   return 0;
00033 }
00034 
00035 unsigned short can_tx_get_frame_count_3(CAN_FRAME * frame)
00036 {
00037   frame->payload.w.w1 = can_tx_frame_count_3;
00038   can_tx_frame_count_3 = 0;     //Reset frame counter - could lose a count here, but not critical
00039   frame->payload.w.w2 = can_elapsed_ms;
00040   return 0;
00041 }
00042 
00043 unsigned short can_tx_get_frame_count_4(CAN_FRAME * frame)
00044 {
00045   frame->payload.w.w1 = can_tx_frame_count_4;
00046   can_tx_frame_count_4 = 0;     //Reset frame counter - could lose a count here, but not critical
00047   frame->payload.w.w2 = can_elapsed_ms;
00048   return 0;
00049 }
00050 
00051 // Set up CAN_TX_CHAN_CFG for channel chan; stalled is initialized to 1 to kickstart transmit process
00052 void can_tx_set_chan_cfg(CAN_CHANNEL chan,volatile unsigned long * base_addr, CAN_RING * tx_ring){
00053   can_tx_chan_cfgs[chan].base_addr = base_addr;
00054   can_tx_chan_cfgs[chan].ring      = tx_ring;
00055   can_tx_chan_cfgs[chan].stalled   = 1;
00056 }
00057 
00058 // Basic can_transmit function, calls multi-argument can_transmit_alt
00059 int can_transmit(CAN_FRAME_DESC * frame_desc){
00060   return can_transmit_alt(frame_desc,frame_desc->chan, frame_desc->rtr);
00061 }
00062 
00063 // CAN transmit function; has options for CAN channel and rtr (remote transmission request)
00064 int can_transmit_alt(CAN_FRAME_DESC * frame_desc, CAN_CHANNEL chan, char rtr){
00065   CAN_LAYOUT  layout = frame_desc->frame_layout;
00066   CAN_FRAME   frame;
00067   int         dlc;
00068 
00069 // Set data length code of transmitted frame, based on rtr bit or CAN_LAYOUT
00070   if(rtr){
00071     dlc = 0;
00072   }else{
00073     switch(layout){
00074       case CAN_LAYOUT_D:
00075       case CAN_LAYOUT_FF:
00076       case CAN_LAYOUT_II:
00077       case CAN_LAYOUT_FI:
00078       case CAN_LAYOUT_ISS:
00079         dlc = 8;
00080         break;
00081       default:
00082         //Unrecognized layout, throw error and abort.
00083         return 1;
00084     }
00085   }
00086  
00087   // Use getter functions to fill in payload data bytes of transmitted frame.
00088   // Function pointers are from the frame descriptor in the first argument
00089   if(rtr) {
00090     dlc = 0;
00091   } else {
00092     switch(layout){
00093       //WARNING!!! not for the faint of heart.  Here we are casting function pointers
00094       //to another type of function pointer, and then we call it.  If this doesn't
00095       //make sense, read about function pointers and casting.
00096       case CAN_LAYOUT_D:
00097         frame.payload.d.d1 = ((CAN_TX_GETTER_DOUBLE)frame_desc->ptr1)();
00098         dlc = 8;
00099         break;
00100       case CAN_LAYOUT_FF:
00101         frame.payload.f.f1 = ((CAN_TX_GETTER_FLOAT)frame_desc->ptr1)();
00102         frame.payload.f.f2 = ((CAN_TX_GETTER_FLOAT)frame_desc->ptr2)();
00103         dlc = 8;
00104         break;
00105       case CAN_LAYOUT_II:
00106         frame.payload.i.i1 = ((CAN_TX_GETTER_INT)frame_desc->ptr1)();
00107         frame.payload.i.i2 = ((CAN_TX_GETTER_INT)frame_desc->ptr2)();
00108         dlc = 8;
00109       break;
00110       case CAN_LAYOUT_FI:
00111         frame.payload.f.f1 = ((CAN_TX_GETTER_FLOAT)frame_desc->ptr1)();
00112         frame.payload.i.i2 = ((CAN_TX_GETTER_INT)frame_desc->ptr2)();
00113         dlc = 8;
00114       break;
00115       case CAN_LAYOUT_ISS:
00116         frame.payload.i.i1 = ((CAN_TX_GETTER_INT  )frame_desc->ptr1)();
00117         frame.payload.s.s3 = ((CAN_TX_GETTER_SHORT)frame_desc->ptr2)();
00118         frame.payload.s.s4 = ((CAN_TX_GETTER_SHORT)frame_desc->ptr3)();
00119         dlc = 8;
00120       break;
00121       default:
00122         //Unrecognized layout, throw error and abort.
00123         return 1;
00124     }
00125   }
00126 
00127   // Fill in the rest of the CAN_FRAME elements
00128   // Note that the channel number chan comes from the frame descriptor here, not the argument chan.
00129   // This may or may not be useful. ***************************************************************
00130   // So the chan argument does nothing at this point.
00131   frame.addr = frame_desc->addr;
00132   frame.chan = frame_desc->chan;
00133   frame.dlc  = dlc;
00134   frame.rtr  = rtr;
00135   
00136   //The frame is now fully populated with Address, Data Length, and Payload
00137   //and is therefore ready to be sent out.
00138   return can_transmit_frame(&frame);
00139 }
00140 
00141 /*
00142 // Push CAN_FRAME onto related CAN ring buffer
00143 int can_transmit_frame(CAN_FRAME * frame)
00144 {
00145   CAN_CHANNEL   chan      = frame->chan;
00146   CAN_RING    * ring      = can_tx_chan_cfgs[chan].ring;
00147   volatile unsigned long * base = can_tx_chan_cfgs[chan].base_addr;
00148   int           ret = 1;
00149   
00150   //Temporarily disable CAN channel chan interrupts
00151   VICIntEnClr = 1<<(20 + chan - 1); 
00152 
00153   //Push frame onto ring buffer, if not full.
00154   ret = can_ring_push(ring,frame);
00155 
00156   //Is channel stalled? Set software interrupt to unstall it.
00157   if (CAN_REG(base,CAN_SR) & (1<<2)) //Is transmit buffer 1 available?
00158   {
00159     if (!(VICRawIntr & (1<<(20 + chan - 1))))  // Is raw VIC interrupt for channel chan off?
00160     {
00161       VICSoftInt = 1<<(20 + chan - 1); //Set software interrupt bit for channel chan
00162     }
00163   }
00164 
00165   //Enable CAN channel chan interrupts
00166   VICIntEnable = 1<<(20 + chan - 1);
00167   return ret; //Return 0 if successful ring buffer push, 1 if buffer full.
00168 }
00169 
00170 void can_tx_send_next_frame(CAN_CHANNEL chan){
00171   volatile unsigned long * base           = can_tx_chan_cfgs[chan].base_addr;
00172   CAN_RING               * ring           = can_tx_chan_cfgs[chan].ring;
00173   CAN_FRAME                frame;
00174   int                      ret;
00175   int temp = CAN_REG(base,CAN_ICR); // < clear the transmit and error interrupts @todo check for errors here 
00176   
00177   if (CAN_REG(base,CAN_SR) & (1<<2)) //Is transmit buffer 1 available?
00178   {
00179     // Pop CAN_FRAME from relevant ring buffer; returns 0 if successful, 1 if ring empty.
00180     ret = can_ring_pop(ring,&frame);
00181     if(ret) 
00182     {
00183       //The buffer was empty, put channel into stall mode - disable channel chan interrupts
00184        VICIntEnClr = 1<<(20 + chan - 1);
00185     } 
00186     else // frame successfully popped from ring buffer
00187     {
00188       //Put data into relevant CAN controller data registers
00189       CAN_REG(base,CAN_TFI1) = (frame.dlc&0xF)<<16 | (frame.rtr&0x1) << 30; // PRIO = 0, FF = 0
00190       CAN_REG(base,CAN_TID1) = frame.addr;
00191       CAN_REG(base,CAN_TDA1) = frame.payload.w.w1;
00192       CAN_REG(base,CAN_TDB1) = frame.payload.w.w2;
00193       CAN_REG(base,CAN_CMR ) = (1<<0) | (1<<5); //TR: Transmit Now; STB1: Select Tx Buffer 1 for transmission
00194     }
00195   } 
00196   
00197   VICSoftIntClr = 1<<(20 + chan - 1); //Clear software interrupt bit for channel chan
00198 }
00199 */
00200 
00201 
00202 // Push CAN_FRAME onto related CAN ring buffer
00203 int can_transmit_frame(CAN_FRAME * frame){
00204   CAN_CHANNEL   chan      = frame->chan;
00205   CAN_RING    * ring      = can_tx_chan_cfgs[chan].ring;
00206   int         * p_stalled = &(can_tx_chan_cfgs[chan].stalled);
00207   int           ret;
00208 
00209   // Return 1 if ring buffer is full
00210   ret = can_ring_push(ring,frame);
00211   if(ret) {
00212     return 1;
00213   }
00214 
00215   // Is the relevant channel stalled? (Ring buffer not empty and interrupts off)
00216   if(*p_stalled) {
00217     can_tx_send_next_frame(chan);//Then unstall it
00218   }
00219   return 0; // frame was successfully pushed onto buffer
00220 }
00221 
00222 void can_tx_send_next_frame(CAN_CHANNEL chan){
00223   volatile unsigned long * base           = can_tx_chan_cfgs[chan].base_addr;
00224   CAN_RING               * ring           = can_tx_chan_cfgs[chan].ring;
00225   int                    * p_stalled      = &(can_tx_chan_cfgs[chan].stalled);
00226   CAN_FRAME                frame;
00227   int                      ret;
00228 
00229   // Pop CAN_FRAME from relevant ring buffer; returns 0 if successful, 1 if ring empty.
00230   ret = can_ring_pop(ring,&frame);
00231 
00232   if(ret) 
00233   {
00234     //The buffer was empty, put channel into stall mode
00235     *p_stalled             = 1;
00236   } 
00237   else // frame successfully popped from ring buffer
00238   {
00239     *p_stalled             = 0;
00240  
00241     if (chan == CHAN_CAN1) {can_tx_frame_count_1++;}
00242     else if (chan == CHAN_CAN2) {can_tx_frame_count_2++;}
00243     else if (chan == CHAN_CAN3) {can_tx_frame_count_3++;}
00244     else if (chan == CHAN_CAN4) {can_tx_frame_count_4++;}
00245 
00246     //Put data into relevant CAN controller data registers
00247     CAN_REG(base,CAN_TFI1) = (frame.dlc&0xF)<<16 | (frame.rtr&0x1) << 30; // PRIO = 0, FF = 0
00248     CAN_REG(base,CAN_TID1) = frame.addr;
00249     CAN_REG(base,CAN_TDA1) = frame.payload.w.w1;
00250     CAN_REG(base,CAN_TDB1) = frame.payload.w.w2;
00251     CAN_REG(base,CAN_CMR ) = (1<<0) | (1<<5); //TR: Transmit Now; STB1: Select Tx Buffer 1 for transmission
00252     
00253   }
00254 }
00255 
00256 
00257 // Use RTR (Remote Transmission Request) to subscribe to desired receive CAN IDs.
00258 // Use this function with each RX CAN_FRAME_DESC
00259 // Should be transmitted on the same channel you want to receive this ID on.
00260 void can_subscribe(CAN_FRAME_DESC * fd){
00261   CAN_FRAME frame;
00262   frame.chan = fd->chan;
00263   frame.addr = fd->addr;
00264   frame.rtr  = 1;
00265   can_transmit_frame(&frame);
00266 }
00267 
Generated on Tue Jun 29 16:36:14 2010 by  doxygen 1.6.3