Subversion Repositories HomeAutomation

Rev

Rev 342 | 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/branches/modules/EmbeddedSoftware/PIC/canBoot/Source/Main.c $
  7.  * Last changed:    $LastChangedDate: 2007-02-26 21:38:37 +0100 (Mon, 26 Feb 2007) $
  8.  * By:              $LastChangedBy: johboh $
  9.  * Revision:        $Revision: 342 $
  10.  ********************************************************************/
  11.  
  12. #include <compiler.h>
  13. #include <stackTasks.h>
  14. #include <CANdefs.h>
  15. #include <CAN.h>
  16. #include <crc16.h>
  17. #include <boot.h>
  18. #include <funcdefs.h>
  19. #include <EEaccess.h>
  20. #include <reset.h>
  21.  
  22. /** V E C T O R  R E M A P P I N G *******************************************/
  23.  
  24. #pragma code _HIGH_INTERRUPT_VECTOR = 0x000008
  25. void _high_ISR (void)
  26. {
  27.     _asm goto RM_HIGH_INTERRUPT_VECTOR _endasm
  28. }
  29.  
  30. #pragma code _LOW_INTERRUPT_VECTOR = 0x000018
  31. void _low_ISR (void)
  32. {
  33.     _asm goto RM_LOW_INTERRUPT_VECTOR _endasm
  34. }
  35.  
  36. #pragma code
  37.  
  38.  
  39. static CAN_PACKET cp;
  40. static DWORD cnt =0;
  41.  
  42. static void mainInit(void);
  43. static BOOL canGetPacket(void);
  44. void TBLWT_Func(void);
  45. void TBLWTPOSTINC_Func (void);
  46. void TBLRD_Func(void);
  47.  
  48. #define TICK_SUB_COUNTER_10MS 312
  49. #define PACKET_TIMEOUT 14
  50. #define BOOTLOADER_INIT_TIMOUT 500
  51.  
  52. DWORD tickCounter = 0;
  53. DWORD tickSubCounter = 0;
  54.  
  55. DWORD tickGet(void);
  56.  
  57. static int MY_ID = DEFAULT_ID;
  58.  
  59. void main()
  60. {
  61.     static PROGRAM_STATE pgs = pgsWAITING_START;
  62.     static PROGRAM_STATE pgsAckNext = pgsWAITING_START;
  63.  
  64.     static BYTE programmerId=0;
  65.     static BYTE pgmData[64];
  66.  
  67.     static BOOT_TYPE ackType = btACK;
  68.    
  69.     static DWORD pgmAddress = 0;
  70.     static DWORD newPgmAddress = 0;
  71.     static DWORD tBoot;
  72.     static DWORD t = 0;
  73.    
  74.     CAN_PACKET outCp;
  75.  
  76.     // Inits
  77.     mainInit();
  78.  
  79.     canInit();
  80.  
  81.     tBoot = tickGet();
  82.    
  83.     // Read ID if exist.
  84.     if (EERead(NODE_ID_EE)==NODE_HAS_ID)
  85.     {
  86.         MY_ID=EERead(NODE_ID_EE + 1);
  87.     }
  88.    
  89.     for(t=0;t<64;t++) pgmData[t]=0x0;
  90.  
  91.     // Send bootloader startup
  92.     outCp.type=ptPGM;
  93.     outCp.pgm.class=pcCTRL;
  94.     outCp.pgm.id=pctBOOTBOOT;
  95.     outCp.length=3;
  96.     outCp.data[2] = (isBOR()<<7)+(isLVD()<<6)+(isMCLR()<<5)+(isPOR()<<4)+(isWDTTO()<<3)+(isWDTWU()<<2)+(isWU()<<1);
  97.     outCp.data[1]=(BYTE)((BOOT_VERSION & 0xFF00)>>8);
  98.     outCp.data[0]=(BOOT_VERSION & 0xFF);
  99.     StatusReset();
  100.     while(!canSendMessage(outCp));
  101.    
  102.     LED0_IO= 1;
  103.  
  104.     for(;;)
  105.     {
  106.         BYTE i;
  107.         CAN_PACKET outCm;
  108.         BOOL hasPacket = canGetPacket() && (cp.type == ptBOOT && cp.boot.rid == MY_ID);
  109.  
  110.         tickSubCounter++;
  111.         if (tickSubCounter>TICK_SUB_COUNTER_10MS)
  112.         {
  113.             tickCounter++;
  114.             tickSubCounter=0;
  115.             ClrWdt();
  116.         }
  117.  
  118.         switch(pgs)
  119.         {
  120.             case pgsWAITING_START:
  121.                 // Wait for first addresspacket.
  122.                 // Set startAddress to data[2]:[0].
  123.                 // Send ack. Goto next state.
  124.                 if (hasPacket==TRUE && cp.boot.type==btADDR)
  125.                 {
  126.                     programmerId = cp.sid;
  127.                     pgmAddress = (((DWORD)cp.data[2])<<16)+(((DWORD)cp.data[1])<<8)+((DWORD)cp.data[0]);
  128.                     t = tickGet();
  129.                     ackType = btACK;
  130.                     pgsAckNext = pgsWAIT_FIRST_DATA;
  131.                     pgs = pgsSEND_ACK;
  132.                 }  
  133.  
  134.                 // Bootloader timeout
  135.                 if ((tickGet()-tBoot)>BOOTLOADER_INIT_TIMOUT)
  136.                 {
  137.                     pgs = pgsDONE;
  138.                 }
  139.                 break;
  140.  
  141.             case pgsSEND_ACK:
  142.                 // send ack
  143.                 outCp.type = ptBOOT;
  144.                 outCp.boot.rid = programmerId;
  145.                 outCp.boot.type = ackType;
  146.                 outCp.length=0;
  147.                 t = tickGet();
  148.                 pgs = pgsAckNext;
  149.  
  150.                 while(!canSendMessage(outCp));
  151.                 break;
  152.  
  153.  
  154.  
  155.             case pgsWAIT_FIRST_DATA:
  156.                 // Wait for first pgm packet. use offset to determine data index.
  157.                 // When receiving crc from host, check crc for offsets bytes.
  158.                
  159.                 if ((tickGet()-t)>PACKET_TIMEOUT)
  160.                 {
  161.                     // Timeout, resend ack/nack.
  162.                     pgsAckNext = pgsWAIT_FIRST_DATA;
  163.                     pgs = pgsSEND_ACK;
  164.                 }              
  165.  
  166.                 if (hasPacket==TRUE && cp.boot.type==btPGM)
  167.                 {
  168.                     BYTE localIndex = cp.boot.offset;
  169.                     pgmData[localIndex+0]=cp.data[0]; pgmData[localIndex+1]=cp.data[1]; pgmData[localIndex+2]=cp.data[2]; pgmData[localIndex+3]=cp.data[3];
  170.                     pgmData[localIndex+4]=cp.data[4]; pgmData[localIndex+5]=cp.data[5]; pgmData[localIndex+6]=cp.data[6]; pgmData[localIndex+7]=cp.data[7];
  171.                     pgs = pgsWAIT_DATA_OR_CRC;
  172.                 }
  173.  
  174.                 if (hasPacket==TRUE && cp.boot.type==btADDR)
  175.                 {
  176.                     tBoot = tickGet();
  177.                     pgs   = pgsWAITING_START;
  178.                 }
  179.  
  180.                 if (hasPacket==TRUE && cp.boot.type==btCRC)
  181.                 {
  182.                     pgs   = pgsWAIT_DATA_OR_CRC;
  183.                 }
  184.  
  185.                 if (hasPacket==TRUE && cp.boot.type==btDONE)
  186.                 {
  187.                     pgs = pgsDONE;
  188.                 }
  189.  
  190.  
  191.                 break;
  192.  
  193.             case pgsWAIT_DATA_OR_CRC:
  194.                 // Wait for pgm packet. use offset to determine data index.
  195.                 // When receiving crc from host, check crc for offsets bytes.
  196.                
  197.                 if (hasPacket==TRUE && cp.boot.type==btCRC)
  198.                 {
  199.                     WORD crc16 = (((WORD)cp.data[4])<<8)+((WORD)cp.data[3]);
  200.                     WORD crc16calc = calc_crc(pgmData,64);
  201.  
  202.                     // check CRC.
  203.                     if (crc16calc==crc16)
  204.                     {
  205.                         newPgmAddress = (((DWORD)cp.data[2])<<16)+(((DWORD)cp.data[1])<<8)+((DWORD)cp.data[0]);
  206.                         pgsAckNext = pgsWAIT_FIRST_DATA;
  207.                         pgs = pgsWRITE_DATA;
  208.                     }
  209.                     else
  210.                     {
  211.                         t = tickGet();
  212.                         ackType = btNACK;
  213.                         pgsAckNext = pgsWAIT_FIRST_DATA;
  214.                         pgs = pgsSEND_ACK;
  215.                     }
  216.                 }
  217.                
  218.                 if (hasPacket==TRUE && cp.boot.type==btPGM)
  219.                 {
  220.                     BYTE localIndex = cp.boot.offset;
  221.                     pgmData[localIndex+0]=cp.data[0]; pgmData[localIndex+1]=cp.data[1]; pgmData[localIndex+2]=cp.data[2]; pgmData[localIndex+3]=cp.data[3];
  222.                     pgmData[localIndex+4]=cp.data[4]; pgmData[localIndex+5]=cp.data[5]; pgmData[localIndex+6]=cp.data[6]; pgmData[localIndex+7]=cp.data[7];
  223.                 }
  224.  
  225.                 if (hasPacket==TRUE && cp.boot.type==btADDR)
  226.                 {
  227.                     tBoot = tickGet();
  228.                     pgs   = pgsWAITING_START;
  229.                 }
  230.  
  231.                 if (hasPacket==TRUE && cp.boot.type==btDONE)
  232.                 {
  233.                     pgs = pgsDONE;
  234.                 }
  235.  
  236.                 break;
  237.  
  238.  
  239.             case pgsWRITE_DATA:
  240.  
  241.                 ClrWdt();
  242.  
  243.                 // Write program and send ack.
  244.  
  245.                 // Check addr limit
  246.                 if (pgmAddress<RM_RESET_VECTOR)
  247.                 {      
  248.                     ackType = btNACK;
  249.                     pgsAckNext = pgsWAIT_FIRST_DATA;       
  250.                     pgs             = pgsSEND_ACK;
  251.                     //Not allowed to write here!
  252.                     break;
  253.                 }
  254.  
  255.                 //Load Table pointer registers with base address to erase.
  256.                 TBLPTRU = (BYTE)((pgmAddress & 0xFF0000)>>16);
  257.                 TBLPTRH = (BYTE)((pgmAddress & 0xFF00)>>8);
  258.                 TBLPTRL = (BYTE)(pgmAddress & 0xFF);
  259.  
  260.                 // point to Flash program memory
  261.                 EECON1bits.EEPGD = 1;
  262.                 // access Flash program memory
  263.                 EECON1bits.CFGS = 0;
  264.                 // enable write to memory
  265.                 EECON1bits.WREN = 1;
  266.                 // enable Row Erase operation
  267.                 EECON1bits.FREE = 1;
  268.                 // disable interrupts
  269.                 INTCONbits.GIE = 0;
  270.  
  271.                 // Do it!
  272.                 EECON2 = 0x55;
  273.                 EECON2 = 0xAA;
  274.                 EECON1bits.WR = 1;
  275.  
  276.                 // enable interrupts
  277.                 INTCONbits.GIE = 1;
  278.                
  279.                 //Load Table pointer registers with base address to program.
  280.                 TBLPTRU = (BYTE)((pgmAddress & 0xFF0000)>>16);
  281.                 TBLPTRH = (BYTE)((pgmAddress & 0xFF00)>>8);
  282.                 TBLPTRL = (BYTE)(pgmAddress & 0xFF);
  283.  
  284.                 // Load bytes
  285.                 for(i=0;i<63;i++)
  286.                 {
  287.                     TABLAT=pgmData[i];
  288.                     pgmData[i]=0x0;
  289.                     TBLWTPOSTINC_Func();
  290.                 }
  291.                 TABLAT=pgmData[63];
  292.                 TBLWT_Func();
  293.  
  294.  
  295.                 // point to Flash program memory
  296.                 EECON1bits.EEPGD = 1;
  297.                 // access Flash program memory
  298.                 EECON1bits.CFGS = 0;
  299.                 // enable write to memory
  300.                 EECON1bits.WREN = 1;
  301.                 // disable interrupts
  302.                 INTCONbits.GIE = 0;
  303.                
  304.                 // Do it!
  305.                 EECON2 = 0x55;
  306.                 EECON2 = 0xAA;
  307.                 EECON1bits.WR = 1;
  308.  
  309.                 // enable interrupts
  310.                 INTCONbits.GIE = 1;
  311.  
  312.                 // disable write to memory
  313.                 EECON1bits.WREN = 0;
  314.  
  315.                 pgmAddress     = newPgmAddress;
  316.                 ackType = btACK;       
  317.                 pgs             = pgsSEND_ACK;
  318.  
  319.             break;
  320.  
  321.             case pgsDONE:
  322.                 LED0_IO= 0;
  323.                 _asm  goto RM_RESET_VECTOR _endasm
  324.             break;
  325.  
  326.        
  327.             default:
  328.                 pgs = pgsWAITING_START;
  329.             break;
  330.         }
  331.    
  332.  
  333.     }
  334. }
  335.  
  336.  
  337. /*
  338. *   Function: mainInit
  339. *
  340. *   Input:  none
  341. *   Output: none
  342. *   Pre-conditions: none
  343. *   Affects: Se code
  344. *   Depends: none.
  345. */
  346. void mainInit()
  347. {
  348.     LED0_TRIS=0;   
  349.  
  350.     // Enable internal PORTB pull-ups
  351.     INTCON2bits.RBPU = 0;
  352.    
  353.     // Enable Interrupts
  354.     INTCONbits.GIEH = 1;
  355.     INTCONbits.GIEL = 1;
  356.  
  357.     // Enable interrupt prirority
  358.     RCONbits.IPEN=1;
  359.    
  360.  
  361. }
  362.  
  363.  
  364.  
  365. /// CAN-------------------------------------------------------
  366.  
  367. /*
  368. *   Function: canInit
  369. *
  370. *   Input:  none
  371. *   Output: none
  372. *   Pre-conditions: none
  373. *   Affects: Changes can registers.
  374. *   Depends: none.
  375. */
  376. void canInit()
  377. {
  378.     CANCON = 0x80; //request config mode
  379.     while ((CANSTAT & 0xE0) != 0x80 ); //wait for config mode request
  380.  
  381.     // BAUD AND TQS
  382.  
  383.     // 500Khz@40Mhz (new by the book)
  384.     BRGCON1 = 0x04;
  385.     BRGCON2 = 0xD1;
  386.     BRGCON3 = 0x81;
  387.  
  388.     ECANCON=0;
  389.     ECANCONbits.MDSEL1 = 1;
  390.     ECANCONbits.MDSEL0 = 0;
  391.  
  392.  
  393.     // FILTERS AND MASKS
  394.     RXB0CONbits.RXM1=1;
  395.     RXB0CONbits.RXM0=0;
  396.  
  397.  
  398.     // INTERRUPTS
  399.    
  400.     // Diable transmit interrupt
  401.     TXBIE = 0;
  402.  
  403.     //rx no interrupt
  404.     PIR3 = 0;
  405.     PIE3 = 0;
  406.  
  407.  
  408.     // Programmable no buffers interrupt
  409.     BIE0  = 0x00;  
  410.  
  411.  
  412.     //loopback mode or not
  413.     #ifdef CAN_LOOPBACK_MODE
  414.         CANCON = 0x40;//request loopback mode
  415.         while ((CANSTAT & 0xE0) != 0x40 );//wait for loopback mode
  416.     #else
  417.         CANCON = 0x00;//request normal mode
  418.         while ((CANSTAT & 0xE0) != 0x00 );//wait for normal mode
  419.     #endif
  420.  
  421. }
  422.  
  423.  
  424.  
  425.  
  426. /*
  427. *   Function: canGetPacket
  428. *
  429. *   Input:  none
  430. *   Output: none
  431. *   Pre-conditions: a call to canISR and an packet is available and banked to RXB0
  432. *   Affects: Calls canParse() function in main for parsing received packet.
  433. *   Depends: none.
  434. */
  435. BOOL canGetPacket()
  436. {
  437.  
  438.         // Get which buffer that is ful.
  439.         ECANCON=(ECANCON&0b00000)|(0b10000|(CANCON&0x0F));
  440.         if (!RXB0CONbits.RXFUL) return FALSE;
  441.    
  442.  
  443.         //RXB0SIDH 28 27 26 25 24 23 22 21
  444.         //RXB0SIDL 20 19 18 xx xx xx 17 16
  445.         //RXB0EIDH 15 14 13 12 11 10 09 08
  446.         //RXB0EIDL 07 06 05 04 03 02 01 00
  447.  
  448.         cp.type = ((RXB0SIDH&0xC)>>6);
  449.  
  450.  
  451.         if (cp.type==ptBOOT)
  452.         {
  453.             cp.boot.type  = ((RXB0SIDH&0x38)>>3);
  454.             cp.boot.offset= ((RXB0SIDH&0x7)<<5)+((RXB0SIDL&0xE0)>>3)+(RXB0SIDL&0x3);
  455.             cp.boot.rid   = RXB0EIDH;
  456.         }
  457.         else
  458.         {
  459.             cp.pgm.class= ((RXB0SIDH&0x3C)>>2);
  460.             cp.pgm.id   = (((WORD)RXB0SIDH&0x3)<<13)+(((WORD)RXB0SIDL&0xE0)<<5)+(((WORD)RXB0SIDL&0x3)<<8)+(WORD)RXB0EIDH;
  461.         }
  462.         cp.sid   = RXB0EIDL;
  463.  
  464.  
  465.         // Data length
  466.         cp.length=(RXB0DLCbits.DLC3<<3)+(RXB0DLCbits.DLC2<<2)+(RXB0DLCbits.DLC1<<1)+RXB0DLCbits.DLC0;
  467.  
  468.         // Data one bye one, for speed
  469.         cp.data[0]=RXB0D0;  cp.data[1]=RXB0D1;
  470.         cp.data[2]=RXB0D2;  cp.data[3]=RXB0D3;
  471.         cp.data[4]=RXB0D4;  cp.data[5]=RXB0D5;
  472.         cp.data[6]=RXB0D6;  cp.data[7]=RXB0D7;
  473.  
  474.         // Clear ful status
  475.         RXB0CONbits.RXFUL=0;
  476.  
  477.         return TRUE;
  478. }
  479.  
  480.  
  481. /*
  482. *   Function: canSendMessage
  483. *
  484. *   Input:  CAN_MESSAGE to send
  485. *   Output: True if packet scheduled sucess, false otherwise.
  486. *   Pre-conditions: canInit
  487. *   Affects: ..
  488. *   Depends: ..
  489. */
  490. BOOL canSendMessage(CAN_PACKET cp)
  491. {
  492.     BYTE prio = 3; 
  493.  
  494.     if ( TXB0CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00011; }
  495.     if ( TXB1CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00100; }
  496.     if ( TXB2CONbits.TXREQ == 0 )  { ECANCON=(ECANCON&0b00000)|0b00101; }
  497.     // None of the transmit buffers were empty.
  498.     else { return FALSE;}
  499.  
  500.  
  501.         //RXB0SIDH 28 27 26 25 24 23 22 21
  502.         //RXB0SIDL 20 19 18 xx xx xx 17 16
  503.         //RXB0EIDH 15 14 13 12 11 10 09 08
  504.         //RXB0EIDL 07 06 05 04 03 02 01 00
  505.  
  506.         if (cp.type==ptBOOT)
  507.         {
  508.             RXB0SIDH = ((cp.type&0x3)<<6)+((cp.boot.type&0x7)<<3)+((cp.boot.offset&0xE0)>>5);
  509.             RXB0SIDL = ((cp.boot.offset&0x1C)<<3)+(cp.boot.offset&0x3);
  510.             RXB0EIDH = cp.boot.rid;
  511.         }
  512.         else
  513.         {
  514.             RXB0SIDH = ((cp.type&0x3)<<6)+((cp.pgm.class&0xF)<<2)+((cp.pgm.id&0x6000)>>13);
  515.             RXB0SIDL = ((cp.pgm.id&0x1C00)>>5)+((cp.pgm.id&0x300)>>8);
  516.             RXB0EIDH = (cp.pgm.id&0xFF);
  517.         }
  518.         RXB0EIDL = MY_ID;
  519.  
  520.         // Data length
  521.         RXB0DLC = 0;
  522.         if (cp.length>8) RXB0DLC=8; else RXB0DLC=cp.length;
  523.        
  524.         // NOT Remote request
  525.         _asm
  526.             bcf RXB0DLC, 6, 0
  527.         _endasm
  528.  
  529.  
  530.         // Data one bye one, for speed
  531.         RXB0D0=cp.data[0];  RXB0D1=cp.data[1];
  532.         RXB0D2=cp.data[2];  RXB0D3=cp.data[3];
  533.         RXB0D4=cp.data[4];  RXB0D5=cp.data[5];
  534.         RXB0D6=cp.data[6];  RXB0D7=cp.data[7];
  535.  
  536.         // set extended or not
  537.         RXB0SIDLbits.EXID=1;
  538.  
  539.         // Priority
  540.         RXB0CON = (RXB0CON & 0b11111100) | prio;
  541.  
  542.         // mark as redy to transmit
  543.         _asm
  544.             bsf RXB0CON, 3, 0
  545.         _endasm
  546.  
  547.         return TRUE;
  548.  
  549. }
  550.  
  551.  
  552. void TBLRD_Func()
  553. {
  554. _asm
  555.     TBLRD
  556. _endasm
  557. }
  558.  
  559. void TBLWT_Func()
  560. {
  561. _asm
  562.     TBLWT
  563. _endasm
  564. }
  565.  
  566.  
  567. void TBLWTPOSTINC_Func (void){
  568. _asm
  569.     TBLWTPOSTINC
  570. _endasm
  571. }
  572.  
  573. DWORD tickGet()
  574. {
  575.     return tickCounter;
  576. }
  577.  
  578.  
  579. #pragma code user = RM_RESET_VECTOR
  580.