Subversion Repositories HomeAutomation

Rev

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