Subversion Repositories HomeAutomation

Rev

Rev 240 | Blame | Last modification | View Log | SVN | RSS feed

  1. #include "bios_funs.h"
  2. #include "avr_cfg.h"
  3. #include <inttypes.h>
  4. #include <avr/io.h>
  5. #include <avr/interrupt.h>
  6. #include <avr/wdt.h>
  7. #include <avr/pgmspace.h>
  8. #include <stdio.h>
  9. #include "flash.h"
  10. #include "vectors.h" // Must be included after sfr_defs.h but before any ISR()
  11. #include "can.h"
  12.  
  13. #define FUNCTmask       0x1E000000
  14. #define FUNCTshift      25
  15. #define FUNCCmask       0x01FF8000
  16. #define FUNCCshift      15
  17. #define NIDmask         0x00007E00
  18. #define NIDshift        9
  19. #define SIDmask         0x000001FF
  20. #define SIDshift        0
  21.  
  22. #define FUNCTbios       0x00
  23.  
  24. #define FUNCCstartprg   0x81
  25. #define FUNCCprgdata    0x82
  26. #define FUNCCstopprg    0x83
  27.  
  28. #define PRG_STATE_IDLE          0
  29. #define PRG_STATE_PROGRAMMING   1
  30.  
  31.  
  32. //---------------------------------------------------------------------------
  33. // Globals
  34.  
  35. volatile long gMilliSecTick;
  36.  
  37. //---------------------------------------------------------------------------
  38. // Function definitions for the exported interface
  39.  
  40. void reset(void) {
  41.     //Just loop and let the watchdog reset
  42.     cli();
  43.     while(1);
  44. };
  45.  
  46. void bios_putchar(char c) {
  47.     UART_PUTCHAR(c);
  48. };
  49.  
  50. char bios_getchar(void) {
  51.     char c;
  52.     UART_GETCHAR(c)
  53.     return c;
  54. };
  55.  
  56. long timebase_get(void) {
  57.     uint8_t sreg;
  58.     long res;
  59.    
  60.     //Disable interrupts while reading tick count
  61.     sreg=SREG;
  62.     cli();
  63.    
  64.     res = gMilliSecTick;
  65.    
  66.     SREG=sreg;
  67.    
  68.     return res;
  69. }
  70.  
  71. //---------------------------------------------------------------------------
  72. // Function definitions for the private functions
  73.  
  74. static int console_getchar(FILE *stream) {
  75.     return bios_getchar();
  76. }
  77.  
  78. static int console_putchar(char c, FILE *stream) {
  79.     bios_putchar(c);
  80.     return 0;
  81. }
  82.  
  83. static FILE bios_stdio = FDEV_SETUP_STREAM(console_putchar, console_getchar,
  84.                                          _FDEV_SETUP_RW);
  85.    
  86.  
  87. //---------------------------------------------------------------------------
  88. // Interrupt Service Routines
  89. // Read app_vectors.h!
  90.  
  91. ISR(TIMEBASE_VECTOR) {
  92.     TIMEBASE_COUNTER -= TIMEBASE_RELOAD;
  93.     gMilliSecTick++;
  94.     wdt_reset();
  95. }
  96.  
  97. int main() {
  98.     void (*app_reset)(void) = 0;
  99.    
  100.     // Setup USART for debug channel
  101.     UART_INIT();
  102.     stdout = &bios_stdio;
  103.     stdin = &bios_stdio;
  104.    
  105.     // Initialize a suitable hardware timer to create a 1KHz interrupt.
  106.     TIMEBASE_INIT();
  107.    
  108.     // Enable watchdog timer to protect against an application locking the
  109.     // node by leaving interrupts disabled.
  110.     wdt_enable(WDTO_500MS);
  111.    
  112.     // Move interrupt vectors to start of bootloader section and enable interrupts
  113.     IVSEL_REG = _BV(IVCE);
  114.     IVSEL_REG = _BV(IVSEL);
  115.     sei();
  116.    
  117.     printf("AVR BIOS\n");
  118.    
  119.    
  120.     printf("CanInit...");
  121.     if (Can_Init() != CAN_OK) {
  122.         printf("FAILED!\n");
  123.     }
  124.     else {
  125.         printf("OK!\n");
  126.     }
  127.    
  128.     uint32_t timeStamp = 0;
  129.    
  130.     Can_Message_t txMsg;
  131.     Can_Message_t rxMsg;
  132.     //The databytes are just what happens to be in the memory. They are never set.
  133.     txMsg.RemoteFlag = 0;
  134.     txMsg.ExtendedFlag = 1;
  135.  
  136.     txMsg.Id = 15;
  137.     txMsg.DataLength = 2;
  138.    
  139.     uint16_t address;
  140.     uint16_t lastoffset=0x0;
  141.     uint8_t prg_state=PRG_STATE_IDLE;
  142.    
  143.     uint8_t i;
  144.     /* main loop */
  145.     while (1) {
  146.         /* service the CAN routines */
  147.         Can_Service();
  148.        
  149.         /* send CAN message and check for CAN errors once every second */
  150.         if ((timebase_get() - timeStamp) >= 10000) {
  151.             timeStamp = timebase_get();
  152.  
  153.             /* send txMsg */
  154.             //txMsg.Id++;
  155.             Can_Send(&txMsg);
  156.            
  157.             if (prg_state==PRG_STATE_IDLE) {
  158.                 if (pgm_read_word(0) != 0xffff) {
  159.                     printf("Starting application.\n");
  160.                     app_reset();
  161.                 }
  162.                 printf("No application found.\n");
  163.             }
  164.         }
  165.        
  166.         /* check if any messages have been received */
  167.         while (Can_Receive(&rxMsg) == CAN_OK) {
  168.             printf("BIOS Received: ID=%lx, DLC=%u, EXT=%u, RTR=%u, ", rxMsg.Id, (uint16_t)(rxMsg.DataLength), (uint16_t)(rxMsg.ExtendedFlag), (uint16_t)(rxMsg.RemoteFlag));
  169.             printf("data={ ");
  170.             for (i=0; i<rxMsg.DataLength; i++) {
  171.                 printf("%x ", rxMsg.Data.bytes[i]);
  172.             }
  173.             printf("}\n");
  174.            
  175.             if ((rxMsg.Id & FUNCTmask) == ((uint32_t)FUNCTbios<<FUNCTshift)) {
  176.                 //printf("Got 'bios package'\n");
  177.                 //om mottagen data är bois-data (detta borde redan filtrerats i can_receive?)
  178.                 if ((prg_state==PRG_STATE_IDLE) && ((rxMsg.Id & FUNCCmask) == ((uint32_t)FUNCCstartprg<<FUNCCshift)) && (rxMsg.DataLength == 6)) {
  179.                     //om mottagen data har funktionskoden starta programmering
  180.  
  181.                     //ska kolla om nod-id i IDENT stämmer med nodens id
  182.                     //om ok:
  183.                     prg_state=PRG_STATE_PROGRAMMING;
  184.                     address = rxMsg.Data.bytes[2];
  185.                     address |= rxMsg.Data.bytes[3];
  186.                     printf("Got 'start programming' at address %x\n", address);
  187.                 } else if (prg_state==PRG_STATE_PROGRAMMING) {
  188.                     if ((rxMsg.Id & FUNCCmask) == ((uint32_t)FUNCCprgdata<<FUNCCshift)) {
  189.                         //om mottagen data har funktionskoden programdata
  190.                         uint16_t tmpaddress = rxMsg.Data.bytes[0] + (rxMsg.Data.bytes[1] << 8);
  191.                         if (tmpaddress >= lastoffset) {
  192.                             tmpaddress += address;
  193.                             printf("Got 'programdatapacket' at offset %x\n", tmpaddress);
  194.                             for (i=2; i<rxMsg.DataLength; i+=2) {
  195.                                 flash_write_word(tmpaddress, rxMsg.Data.bytes[i] + (rxMsg.Data.bytes[i+1] << 8));
  196.                                 tmpaddress+=2;
  197.                             }
  198.                             printf("Setting lastoffset to %x\n", tmpaddress);
  199.                             lastoffset = tmpaddress;
  200.                         }
  201.                     } else if ((rxMsg.Id & FUNCCmask) == ((uint32_t)FUNCCstopprg<<FUNCCshift)) {
  202.                         flash_flush_buffer();
  203.                         prg_state=PRG_STATE_IDLE;
  204.                         lastoffset=0x0;
  205.                         //beräkna crc på all programdata mellan address och address+lastoffset
  206.                         printf("Got 'end programming'\n");
  207.                     }
  208.                 }
  209.             }
  210.            
  211.             //if (rxMsg.Id % 20 == 19) reset();
  212.         }
  213.     }
  214.  
  215.     return 0;
  216. }
  217.