Subversion Repositories HomeAutomation

Rev

Rev 110 | Rev 339 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /*********************************************************************
  2.  *
  3.  *                  Main application
  4.  *
  5.  *********************************************************************
  6.  * FileName:        $HeadURL: https://svn.auml.se/svn/HomeAutomation/trunk/EmbeddedSoftware/PIC/canBoot/Source/Main.c $
  7.  * Last changed:    $LastChangedDate: 2007-01-28 14:58:11 +0100 (Sun, 28 Jan 2007) $
  8.  * By:              $LastChangedBy: johboh $
  9.  * Revision:        $Revision: 260 $
  10.  ********************************************************************/
  11.  
  12. #include <compiler.h>
  13. #include <stackTasks.h>
  14. #include <CANdefs.h>
  15. #include <CAN.h>
  16. #include <boot.h>
  17. #include <funcdefs.h>
  18. #include <EEaccess.h>
  19.  
  20. /** V E C T O R  R E M A P P I N G *******************************************/
  21.  
  22. #pragma code _HIGH_INTERRUPT_VECTOR = 0x000008
  23. void _high_ISR (void)
  24. {
  25.     _asm goto RM_HIGH_INTERRUPT_VECTOR _endasm
  26. }
  27.  
  28. #pragma code _LOW_INTERRUPT_VECTOR = 0x000018
  29. void _low_ISR (void)
  30. {
  31.     _asm goto RM_LOW_INTERRUPT_VECTOR _endasm
  32. }
  33.  
  34. #pragma code
  35.  
  36.  
  37. #ifdef USE_CAN
  38.     #include <CAN.h>
  39. #endif
  40.  
  41. static CAN_PROTO_MESSAGE cm;
  42. static DWORD cnt =0;
  43.  
  44. static void mainInit(void);
  45. static BOOL canGetPacket(void);
  46. void TBLWT_Func(void);
  47. void TBLWTPOSTINC_Func (void);
  48. void TBLRD_Func(void);
  49.  
  50. #define TICK_SUB_COUNTER_10MS 312
  51. #define PACKET_TIMEOUT 14
  52. #define BOOTLOADER_INIT_TIMOUT 500
  53.  
  54. DWORD tickCounter = 0;
  55. DWORD tickSubCounter = 0;
  56.  
  57. DWORD tickGet(void);
  58.  
  59. static int MY_ID = DEFAULT_ID;
  60. static BYTE MY_NID = DEFAULT_NID;
  61.  
  62. void main()
  63. {
  64.     static PROGRAM_STATE pgs = pgsWATING_START;
  65.     static DWORD t = 0;
  66.     static WORD programmerSid=0;
  67.    
  68.     static BYTE errMsg = ACK_ERR_NO_ERROR;
  69.     static PROGRAM_STATE afterAckPgs = pgsWATING_START;
  70.     static DWORD pgmAddress = 0;
  71.     static BYTE bytesReceived = 0;
  72.  
  73.     DWORD tBoot;
  74.    
  75.     static BYTE pgmData[64];
  76.  
  77.     CAN_PROTO_MESSAGE outCmHeart;
  78.  
  79.     // Inits
  80.     mainInit();
  81.  
  82.     #ifdef USE_CAN
  83.         canInit();
  84.     #endif
  85.  
  86.     tBoot = tickGet();
  87.    
  88.     // Read ID and NID if exist.
  89.     if (EERead(NODE_ID_EE)==NODE_HAS_ID)
  90.     {
  91.         MY_ID=(((WORD)EERead(NODE_ID_EE + 1))<<8)+EERead(NODE_ID_EE + 2);
  92.         MY_NID=EERead(NODE_ID_EE + 3);
  93.     }
  94.  
  95.    
  96.     // Send bootloader startup heatbeat
  97.     outCmHeart.funct                    = FUNCT_BOOTLOADER;
  98.     outCmHeart.funcc                    = FUNCC_BOOT_HEARTBEAT;
  99.     outCmHeart.nid                      = MY_NID;
  100.     outCmHeart.sid                      = MY_ID;
  101.     outCmHeart.data_length              = 1;
  102.     outCmHeart.data[BOOT_DATA_HEARTBEAT_INDEX] = HEARTBEAT_BOOT_STARTUP;
  103.     while(!canSendMessage(outCmHeart,PRIO_HIGH));
  104.    
  105.     LED0_IO= 1;
  106.  
  107.     for(;;)
  108.     {
  109.         BYTE i;
  110.         CAN_PROTO_MESSAGE outCm;
  111.         BOOL hasPacket = canGetPacket();
  112.  
  113.         tickSubCounter++;
  114.         if (tickSubCounter>TICK_SUB_COUNTER_10MS)
  115.         {
  116.             tickCounter++;
  117.             tickSubCounter=0;
  118.             ClrWdt();
  119.         }
  120.  
  121.         switch(pgs)
  122.         {
  123.             case pgsWATING_START:
  124.                 // Check if there is bootloader start packet
  125.                 if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && cm.funcc==FUNCC_BOOT_INIT && ((((unsigned int)cm.data[BOOT_DATA_RID_HIGH_INDEX])<<8)+cm.data[BOOT_DATA_RID_LOW_INDEX])==MY_ID && cm.nid==MY_NID)
  126.                 {
  127.                     // Has new start packet
  128.                     pgmAddress      = (((DWORD)cm.data[BOOT_DATA_ADDRU_INDEX])<<16)+(((DWORD)cm.data[BOOT_DATA_ADDRH_INDEX])<<8)+((DWORD)cm.data[BOOT_DATA_ADDRL_INDEX]);
  129.                     programmerSid   = cm.sid;
  130.                     t               = tickGet();
  131.                     errMsg          = ACK_ERR_NO_ERROR;
  132.                     afterAckPgs     = pgsWAIT_FIRST_PGM_PACKET;
  133.                     pgs             = pgsSEND_ACK;
  134.                     // save pgm adress.
  135.                    
  136.                 }
  137.  
  138.                 // Bootloader timeout
  139.                 if ((tickGet()-tBoot)>BOOTLOADER_INIT_TIMOUT)
  140.                 {
  141.                     LED0_IO= 0;
  142.                     pgs = pgsDONE;
  143.                 }
  144.             break;         
  145.  
  146.             case pgsSEND_ACK:
  147.                 // send ack
  148.                 outCm.funct             = FUNCT_BOOTLOADER;
  149.                 outCm.funcc             = FUNCC_BOOT_ACK;
  150.                 outCm.nid               = MY_NID;
  151.                 outCm.sid               = MY_ID;
  152.                 outCm.data_length       = 8;
  153.                 outCm.data[BOOT_DATA_ERR_INDEX] = errMsg;
  154.                 t                       = tickGet();
  155.                 pgs                     = afterAckPgs;
  156.  
  157.                 while(!canSendMessage(outCm,PRIO_HIGH));
  158.             break;
  159.  
  160.  
  161.             case pgsWAIT_FIRST_PGM_PACKET:
  162.                 // wait for first pgm packet.
  163.                 if ((tickGet()-t)>PACKET_TIMEOUT)
  164.                 {
  165.                     // Timeout, resend ack.
  166.                     errMsg          = ACK_ERR_NO_ERROR;
  167.                     afterAckPgs     = pgsWAIT_FIRST_PGM_PACKET;
  168.                     pgs             = pgsSEND_ACK;
  169.                 }
  170.  
  171.                 // If programming packet...
  172.                 if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && (cm.funcc & 0x3E3)==FUNCC_BOOT_PGM && cm.nid==MY_NID && cm.sid==programmerSid)
  173.                 {
  174.                     BYTE localIndex = (BYTE)((cm.funcc & 0x1C)>>2)*8;
  175.  
  176.                     // Save bytes in memory, setup start adress etc..
  177.                     bytesReceived   = 8;       
  178.                     pgmData[localIndex+0]=cm.data[0]; pgmData[localIndex+1]=cm.data[1]; pgmData[localIndex+2]=cm.data[2]; pgmData[localIndex+3]=cm.data[3];
  179.                     pgmData[localIndex+4]=cm.data[4]; pgmData[localIndex+5]=cm.data[5]; pgmData[localIndex+6]=cm.data[6]; pgmData[localIndex+7]=cm.data[7];
  180.                
  181.                     pgs             = pgsWAIT_PGM_PACKET;
  182.                 }
  183.  
  184.  
  185.             break;
  186.  
  187.  
  188.             case pgsWAIT_PGM_PACKET:
  189.        
  190.            
  191.                 // If programming packet...
  192.                 if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && (cm.funcc & 0x3E3)==FUNCC_BOOT_PGM && cm.nid==MY_NID && cm.sid==programmerSid)
  193.                 {
  194.                     BYTE localIndex = (BYTE)((cm.funcc & 0x1C)>>2)*8;
  195.                     // Save bytes in memory, inc received bytes.
  196.                     pgmData[localIndex+0]=cm.data[0]; pgmData[localIndex+1]=cm.data[1]; pgmData[localIndex+2]=cm.data[2]; pgmData[localIndex+3]=cm.data[3];
  197.                     pgmData[localIndex+4]=cm.data[4]; pgmData[localIndex+5]=cm.data[5]; pgmData[localIndex+6]=cm.data[6]; pgmData[localIndex+7]=cm.data[7];
  198.                    
  199.                     bytesReceived   += 8;
  200.                     pgs              = pgsWAIT_PGM_PACKET;
  201.                 }
  202.  
  203.                 // If adress packet (control packet)..
  204.                 if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && cm.funcc==FUNCC_BOOT_ADDR && cm.nid==MY_NID && cm.sid==programmerSid)
  205.                 {
  206.                     // Send ack and goto wait first packet.
  207.                     // save adress.
  208.                     errMsg          = ACK_ERR_NO_ERROR;
  209.                     afterAckPgs     = pgsWAIT_FIRST_PGM_PACKET;
  210.                     pgs             = pgsSEND_ACK;
  211.                 }
  212.                
  213.                 // If end packet...
  214.                 if (hasPacket==TRUE && cm.funct==FUNCT_BOOTLOADER && cm.funcc==FUNCC_BOOT_DONE && cm.nid==MY_NID && cm.sid==programmerSid)
  215.                 {
  216.                     // write program.
  217.                     // If no bytes received at all, assume end.
  218.                     // If not 64 bytes received, send error ack and wait for first packet.
  219.                     // If 64, write.
  220.  
  221.                     if (bytesReceived==0)
  222.                     {
  223.                         // No received, done.
  224.                         errMsg          = ACK_ERR_NO_ERROR;
  225.                         afterAckPgs     = pgsDONE;
  226.                         pgs             = pgsSEND_ACK;
  227.                     }
  228.                     else if (bytesReceived!=64)
  229.                     {
  230.                         errMsg          = ACK_ERR_ERROR;
  231.                         afterAckPgs     = pgsWAIT_FIRST_PGM_PACKET;
  232.                         pgs             = pgsSEND_ACK;
  233.                     }
  234.                     else
  235.                     {
  236.                         pgs              = pgsWRITE_PROGRAM;
  237.                         afterAckPgs     = pgsDONE;
  238.                     }
  239.                 }
  240.  
  241.                 // If bytes received 64, write..
  242.                 if (bytesReceived==64)
  243.                 {
  244.                     LED0_IO=~LED0_IO;
  245.                     pgs              = pgsWRITE_PROGRAM;
  246.                     afterAckPgs     = pgsWAIT_PGM_PACKET;
  247.                     // TODO! Send ack more than once..
  248.                 }
  249.  
  250.  
  251.             break;
  252.  
  253.  
  254.             case pgsWRITE_PROGRAM:
  255.  
  256.                 ClrWdt();
  257.  
  258.                 // Write program and send ack.
  259.  
  260.                 // Check addr limit
  261.                 if (pgmAddress<RM_RESET_VECTOR)
  262.                 {              
  263.                     errMsg          = ACK_ERR_ERROR;
  264.                     pgs             = pgsSEND_ACK;
  265.                     //Not allowed to write here!
  266.                    
  267.                 }
  268.  
  269.                 //Load Table pointer registers with base address to erase.
  270.                 TBLPTRU = (BYTE)((pgmAddress & 0xFF0000)>>16);
  271.                 TBLPTRH = (BYTE)((pgmAddress & 0xFF00)>>8);
  272.                 TBLPTRL = (BYTE)(pgmAddress & 0xFF);
  273.  
  274.                 // point to Flash program memory
  275.                 EECON1bits.EEPGD = 1;
  276.                 // access Flash program memory
  277.                 EECON1bits.CFGS = 0;
  278.                 // enable write to memory
  279.                 EECON1bits.WREN = 1;
  280.                 // enable Row Erase operation
  281.                 EECON1bits.FREE = 1;
  282.                 // disable interrupts
  283.                 INTCONbits.GIE = 0;
  284.  
  285.                 // Do it!
  286.                 EECON2 = 0x55;
  287.                 EECON2 = 0xAA;
  288.                 EECON1bits.WR = 1;
  289.  
  290.                 // enable interrupts
  291.                 INTCONbits.GIE = 1;
  292.                
  293.                 //Load Table pointer registers with base address to program.
  294.                 TBLPTRU = (BYTE)((pgmAddress & 0xFF0000)>>16);
  295.                 TBLPTRH = (BYTE)((pgmAddress & 0xFF00)>>8);
  296.                 TBLPTRL = (BYTE)(pgmAddress & 0xFF);
  297.  
  298.                 // Load bytes
  299.                 for(i=0;i<63;i++)
  300.                 {
  301.                     TABLAT=pgmData[i];
  302.                     TBLWTPOSTINC_Func();
  303.                 }
  304.                 TABLAT=pgmData[63];
  305.                 TBLWT_Func();
  306.  
  307.  
  308.                 // point to Flash program memory
  309.                 EECON1bits.EEPGD = 1;
  310.                 // access Flash program memory
  311.                 EECON1bits.CFGS = 0;
  312.                 // enable write to memory
  313.                 EECON1bits.WREN = 1;
  314.                 // disable interrupts
  315.                 INTCONbits.GIE = 0;
  316.                
  317.                 // Do it!
  318.                 EECON2 = 0x55;
  319.                 EECON2 = 0xAA;
  320.                 EECON1bits.WR = 1;
  321.  
  322.                 // enable interrupts
  323.                 INTCONbits.GIE = 1;
  324.  
  325.                 // disable write to memory
  326.                 EECON1bits.WREN = 0;
  327.  
  328.                 pgmAddress     += 64;
  329.                 bytesReceived   = 0;
  330.                 errMsg          = ACK_ERR_NO_ERROR;
  331.                 pgs             = pgsSEND_ACK;
  332.  
  333.             break;
  334.  
  335.  
  336.             case pgsDONE:
  337.                 _asm  goto RM_RESET_VECTOR _endasm
  338.             break;
  339.  
  340.        
  341.  
  342.  
  343.             default:
  344.                 pgs = pgsWATING_START;
  345.             break;
  346.         }
  347.    
  348.  
  349.     }
  350. }
  351.  
  352.  
  353. /*
  354. *   Function: mainInit
  355. *
  356. *   Input:  none
  357. *   Output: none
  358. *   Pre-conditions: none
  359. *   Affects: Se code
  360. *   Depends: none.
  361. */
  362. void mainInit()
  363. {
  364.     LED0_TRIS=0;   
  365.  
  366.     // Enable internal PORTB pull-ups
  367.     INTCON2bits.RBPU = 0;
  368.    
  369.     // Enable Interrupts
  370.     INTCONbits.GIEH = 1;
  371.     INTCONbits.GIEL = 1;
  372.  
  373.     // Enable interrupt prirority
  374.     RCONbits.IPEN=1;
  375.    
  376.  
  377. }
  378.  
  379.  
  380.  
  381. /// CAN-------------------------------------------------------
  382.  
  383.  
  384. #ifdef USE_CAN
  385.  
  386.  
  387. /*
  388. *   Function: canInit
  389. *
  390. *   Input:  none
  391. *   Output: none
  392. *   Pre-conditions: none
  393. *   Affects: Changes can registers.
  394. *   Depends: none.
  395. */
  396. void canInit()
  397. {
  398.     CANCON = 0x80; //request config mode
  399.     while ((CANSTAT & 0xE0) != 0x80 ); //wait for config mode request
  400.  
  401.     // BAUD AND TQS
  402.  
  403.     // 500Khz@40Mhz (new by the book)
  404.     BRGCON1 = 0x04;
  405.     BRGCON2 = 0xD1;
  406.     BRGCON3 = 0x81;
  407.  
  408.     //BRGCON1=0;
  409.    
  410.     // Sync_Seq = 2 x TQ = 1
  411.     //BRGCON1bits.SJW1=0;
  412.     //BRGCON1bits.SJW0=1;
  413.    
  414.     // Setting BRP.
  415.     //BRGCON1=BRGCON1|CAN_BRP;
  416.    
  417.     // Maximum PHEG1
  418.     //BRGCON2bits.SEG2PHTS = 1;
  419.    
  420.     // Phase_Seg1 = 2 x TQ = 1
  421.     //BRGCON2bits.SEG1PH2 = 0;
  422.     //BRGCON2bits.SEG1PH1 = 0;
  423.     //BRGCON2bits.SEG1PH0 = 1;
  424.    
  425.     // Prop_Seq = 2 x TQ = 1
  426.     //BRGCON2bits.PRSEG2 = 0;
  427.     //BRGCON2bits.PRSEG1 = 0;
  428.     //BRGCON2bits.PRSEG0 = 1;
  429.    
  430.     //  Enableing bus wake-up
  431.     //BRGCON3bits.WAKDIS = 0;
  432.    
  433.     // Dont use filter when wakeup
  434.     //BRGCON3bits.WAKFIL = 0;
  435.    
  436.     // Phase_Seg2 = 2 x TQ = 1
  437.     //BRGCON3bits.SEG2PH2 = 0;
  438.     //BRGCON3bits.SEG2PH1 = 0;
  439.     //BRGCON3bits.SEG2PH0 = 1;
  440.  
  441.     ECANCON=0;
  442.     ECANCONbits.MDSEL1 = 1;
  443.     ECANCONbits.MDSEL0 = 0;
  444.  
  445.  
  446.     // FILTERS AND MASKS
  447.     RXB0CONbits.RXM1=1;
  448.     RXB0CONbits.RXM0=0;
  449.  
  450.  
  451.     // INTERRUPTS
  452.    
  453.     // Diable transmit interrupt
  454.     TXBIE = 0;
  455.  
  456.     //rx no interrupt
  457.     PIR3 = 0;
  458.     PIE3 = 0;
  459.  
  460.  
  461.     // Programmable no buffers interrupt
  462.     BIE0  = 0x00;  
  463.  
  464.  
  465.     //loopback mode or not
  466.     #ifdef CAN_LOOPBACK_MODE
  467.         CANCON = 0x40;//request loopback mode
  468.         while ((CANSTAT & 0xE0) != 0x40 );//wait for loopback mode
  469.     #else
  470.         CANCON = 0x00;//request normal mode
  471.         while ((CANSTAT & 0xE0) != 0x00 );//wait for normal mode
  472.     #endif
  473.  
  474. }
  475.  
  476.  
  477.  
  478.  
  479. /*
  480. *   Function: canGetPacket
  481. *
  482. *   Input:  none
  483. *   Output: none
  484. *   Pre-conditions: a call to canISR and an packet is available and banked to RXB0
  485. *   Affects: Calls canParse() function in main for parsing received packet.
  486. *   Depends: none.
  487. */
  488. BOOL canGetPacket()
  489. {
  490.  
  491.         // Get which buffer that is ful.
  492.         ECANCON=(ECANCON&0b00000)|(0b10000|(CANCON&0x0F));
  493.         if (!RXB0CONbits.RXFUL) return FALSE;
  494.    
  495.  
  496.         //RXB0SIDH 28 27 26 25 24 23 22 21
  497.         //RXB0SIDL 20 19 18 xx xx xx 17 16
  498.         //RXB0EIDH 15 14 13 12 11 10 09 08
  499.         //RXB0EIDL 07 06 05 04 03 02 01 00
  500.  
  501.         //funct xx xx xx xx 28 27 26 25
  502.         //funcc xx xx xx xx xx xx 24 23 22 21 20 19 18 17 16 15
  503.         //nid   xx xx 14 13 12 11 10 09
  504.         //sid   xx xx xx xx xx xx xx 08 07 06 05 04 03 02 01 00
  505.  
  506.  
  507.         cm.funct=((RXB0SIDH & 0xF0)>>4);
  508.         cm.funcc=(((WORD)(RXB0SIDH & 0x0F))<<6)+(((WORD)(RXB0SIDL & 0xE0))>>2)+(((WORD)(RXB0SIDL & 0x03))<<1)+(((WORD)(RXB0EIDH & 0x80))>>7);
  509.         cm.nid=((RXB0EIDH & 0x7E)>>1);
  510.         cm.sid=(((WORD)(RXB0EIDH & 0x01))<<8)+RXB0EIDL;
  511.  
  512.  
  513.         // Data length
  514.         cm.data_length=(RXB0DLCbits.DLC3<<3)+(RXB0DLCbits.DLC2<<2)+(RXB0DLCbits.DLC1<<1)+RXB0DLCbits.DLC0;
  515.  
  516.         // Data one bye one, for speed
  517.         cm.data[0]=RXB0D0;  cm.data[1]=RXB0D1;
  518.         cm.data[2]=RXB0D2;  cm.data[3]=RXB0D3;
  519.         cm.data[4]=RXB0D4;  cm.data[5]=RXB0D5;
  520.         cm.data[6]=RXB0D6;  cm.data[7]=RXB0D7;
  521.  
  522.         // Clear ful status
  523.         RXB0CONbits.RXFUL=0;
  524.  
  525.         return TRUE;
  526. }
  527.  
  528.  
  529. /*
  530. *   Function: canSendMessage
  531. *
  532. *   Input:  CAN_MESSAGE to send
  533. *   Output: True if packet scheduled sucess, false otherwise.
  534. *   Pre-conditions: canInit
  535. *   Affects: ..
  536. *   Depends: ..
  537. */
  538. BOOL canSendMessage(CAN_PROTO_MESSAGE cm,CAN_PRIORITY prio)
  539. {
  540.    
  541.     if ( TXB0CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00011; }
  542.     if ( TXB1CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00100; }
  543.     if ( TXB2CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00101; }
  544.     // None of the transmit buffers were empty.
  545.     else { return FALSE;}
  546.  
  547.     if (prio<0 || prio>3) prio = 0;
  548.  
  549.  
  550.         //RXB0SIDH 28 27 26 25 24 23 22 21
  551.         //RXB0SIDL 20 19 18 xx xx xx 17 16
  552.         //RXB0EIDH 15 14 13 12 11 10 09 08
  553.         //RXB0EIDL 07 06 05 04 03 02 01 00
  554.  
  555.         //funct xx xx xx xx 28 27 26 25
  556.         //funcc xx xx xx xx xx xx 24 23 22 21 20 19 18 17 16 15
  557.         //nid   xx xx 14 13 12 11 10 09
  558.         //sid   xx xx xx xx xx xx xx 08 07 06 05 04 03 02 01 00
  559.  
  560.         RXB0SIDH = (BYTE)((cm.funct & 0x0F)<<4)+(BYTE)((cm.funcc & 0x03C0)>>6);
  561.         RXB0SIDL = (BYTE)((cm.funcc & 0x003F)<<2)+(BYTE)((cm.funcc & 0x0006)>>1);
  562.         RXB0EIDH = (BYTE)((cm.funcc & 0x0001)<<7)+(BYTE)((cm.nid & 0x3F)<<1)+(BYTE)((cm.sid & 0x0100)>>8);
  563.         RXB0EIDL = (BYTE)((cm.sid & 0x00FF));
  564.  
  565.         // Data length
  566.         RXB0DLC = 0;
  567.         if (cm.data_length>8) RXB0DLC=8; else RXB0DLC=cm.data_length;
  568.        
  569.         // NOT Remote request
  570.         _asm
  571.             bcf RXB0DLC, 6, 0
  572.         _endasm
  573.  
  574.  
  575.         // Data one bye one, for speed
  576.         RXB0D0=cm.data[0];  RXB0D1=cm.data[1];
  577.         RXB0D2=cm.data[2];  RXB0D3=cm.data[3];
  578.         RXB0D4=cm.data[4];  RXB0D5=cm.data[5];
  579.         RXB0D6=cm.data[6];  RXB0D7=cm.data[7];
  580.  
  581.         // set extended or not
  582.         RXB0SIDLbits.EXID=1;
  583.  
  584.         // Priority
  585.         RXB0CON = (RXB0CON & 0b11111100) | prio;
  586.  
  587.         // mark as redy to transmit
  588.         _asm
  589.             bsf RXB0CON, 3, 0
  590.         _endasm
  591.  
  592.         return TRUE;
  593.  
  594. }
  595.  
  596.  
  597.  
  598. #endif //USE_CAN
  599.  
  600.  
  601.  
  602.  
  603. void TBLRD_Func()
  604. {
  605. _asm
  606.     TBLRD
  607. _endasm
  608. }
  609.  
  610. void TBLWT_Func()
  611. {
  612. _asm
  613.     TBLWT
  614. _endasm
  615. }
  616.  
  617.  
  618. void TBLWTPOSTINC_Func (void){
  619. _asm
  620.     TBLWTPOSTINC
  621. _endasm
  622. }
  623.  
  624. DWORD tickGet()
  625. {
  626.     return tickCounter;
  627. }
  628.  
  629.  
  630. #pragma code user = RM_RESET_VECTOR
  631.