Subversion Repositories HomeAutomation

Rev

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