Subversion Repositories HomeAutomation

Rev

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