Subversion Repositories HomeAutomation

Rev

Rev 181 | 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/interrupt.h>
  5. #include <avr/wdt.h>
  6. #include <avr/boot.h>
  7. #include <avr/pgmspace.h>
  8. #include <avr/io.h>
  9. #include <stdio.h>
  10. #include "app_vectors.h"
  11.  
  12. //---------------------------------------------------------------------------
  13. // Globals
  14.  
  15. volatile long gMilliSecTick;
  16.  
  17. //---------------------------------------------------------------------------
  18. // Function definitions for the exported interface
  19.  
  20. void reset(void) {
  21.     //Just loop and let the watchdog reset
  22.     cli();
  23.     while(1);
  24. };
  25.  
  26. void bios_putchar(char c) {
  27.     loop_until_bit_is_set(UCSRA, UDRE);
  28.     UDR = c;
  29. };
  30.  
  31. char bios_getchar(void) {
  32.     loop_until_bit_is_set(UCSRA, RXC);
  33.     return UDR;
  34. };
  35.  
  36. long timebase_get(void) {
  37.     uint8_t sreg;
  38.     long res;
  39.    
  40.     //Disable interrupts while reading tick count
  41.     sreg=SREG;
  42.     cli();
  43.    
  44.     res = gMilliSecTick;
  45.    
  46.     SREG=sreg;
  47.    
  48.     return res;
  49. }
  50.  
  51. //---------------------------------------------------------------------------
  52. // Function definitions for the private functions
  53.  
  54. static uint16_t flash_prev_addr;
  55.  
  56. void flash_flush_buffer() {
  57.     uint8_t sreg;
  58.    
  59.     // Disable interrupts.
  60.    
  61.     sreg = SREG;
  62.     cli();
  63.    
  64.     eeprom_busy_wait();
  65.    
  66.     boot_page_erase(flash_prev_addr);
  67.     boot_spm_busy_wait();      // Wait until the memory is erased.
  68.    
  69.     boot_page_write(flash_prev_addr);     // Store buffer in flash page.
  70.     boot_spm_busy_wait();       // Wait until the memory is written.
  71.  
  72.     // Reenable RWW-section again. We need this if we want to jump back
  73.     // to the application after bootloading.
  74.  
  75.     boot_rww_enable ();
  76.  
  77.     // Re-enable interrupts (if they were ever enabled).
  78.  
  79.     SREG = sreg;
  80. }
  81.  
  82. void flash_load_buffer(uint16_t addr) {
  83.     //TODO: Load current flash page contents into temporary buffer to implement
  84.     // flash read-modify-writes with word granularity. (If possible, the data
  85.     // sheet is a little fuzzy about this.)
  86. }
  87.  
  88. void flash_write_word(uint16_t addr, uint16_t word) {
  89.    
  90.     if ((addr / SPM_PAGESIZE) != (flash_prev_addr / SPM_PAGESIZE)) {
  91.         flash_flush_buffer();
  92.         flash_load_buffer(addr);
  93.     }
  94.    
  95.     boot_page_fill(addr, word);
  96.     flash_prev_addr = addr;
  97. }    
  98.  
  99. void flash_init() {
  100.     flash_prev_addr = 0xffff;
  101. }
  102.  
  103. static int console_getchar(FILE *stream) {
  104.     return bios->can_receive();
  105. }
  106.  
  107. static int console_putchar(char c, FILE *stream) {
  108.     bios->can_send(c);
  109.     return 0;
  110. }
  111.  
  112. static FILE bios_stdio = FDEV_SETUP_STREAM(console_putchar, console_getchar,
  113.                                          _FDEV_SETUP_RW);
  114.    
  115.  
  116. //---------------------------------------------------------------------------
  117. // Interrupt Service Routines
  118. // Read app_vectors.h!
  119.  
  120. ISR(TIMEBASE_VECTOR) {
  121.     TIMEBASE_COUNTER -= TIMEBASE_RELOAD;
  122.     gMilliSecTick++;
  123.     wdt_reset();
  124. }
  125.  
  126. int main() {
  127.     void (*app_reset)(void) = 0;
  128.    
  129.     // Setup USART for debug channel
  130.     UCSRB = _BV(RXEN)|_BV(TXEN);
  131.     UBRRL = (F_CPU / 16 / F_BAUD) - 1;
  132.     stdout = &bios_stdio;
  133.     stdin = &bios_stdio;
  134.    
  135.     // Initialize a suitable hardware timer to create a 1KHz interrupt.
  136.     TIMEBASE_INIT();
  137.    
  138.     // Enable watchdog timer to protect against an application locking the
  139.     // node by leaving interrupts disabled.
  140.     wdt_enable(WDTO_500MS);
  141.    
  142.     // Move interrupt vectors to start of bootloader section and enable interrupts
  143.     GICR = _BV(IVCE);
  144.     GICR = _BV(IVSEL);
  145.     sei();
  146.    
  147.     printf("AVR BIOS\n");
  148.    
  149.     if (pgm_read_word(0) != 0xffff) {
  150.         printf("Starting application.\n");
  151.         app_reset();
  152.     }
  153.    
  154.     printf("No application found.\n");
  155.     return 0;
  156. }
  157.