Subversion Repositories HomeAutomation

Rev

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

  1. #include <avr/interrupt.h>
  2. #include <avr/boot.h>
  3. #include <avr/pgmspace.h>
  4. #include "flash.h"
  5.  
  6. static uint16_t flash_prev_addr;
  7. static uint8_t flash_buffer_dirty = 0;
  8.  
  9. void flash_flush_buffer() {
  10.     uint8_t sreg;
  11.    
  12.     if (!flash_buffer_dirty) return; // Nothing to flush
  13.    
  14.     // Disable interrupts.
  15.    
  16.     sreg = SREG;
  17.     cli();
  18.    
  19.     eeprom_busy_wait();
  20.    
  21.     boot_page_erase(flash_prev_addr);
  22.     boot_spm_busy_wait();      // Wait until the memory is erased.
  23.    
  24.     boot_page_write(flash_prev_addr);     // Store buffer in flash page.
  25.     boot_spm_busy_wait();       // Wait until the memory is written.
  26.  
  27.     // Reenable RWW-section again. We need this if we want to jump back
  28.     // to the application after bootloading.
  29.  
  30.     boot_rww_enable ();
  31.  
  32.     // Re-enable interrupts (if they were ever enabled).
  33.  
  34.     SREG = sreg;
  35. }
  36.  
  37. void flash_load_buffer(uint16_t addr) {
  38.     //TODO: Load current flash page contents into temporary buffer to implement
  39.     // flash read-modify-writes with word granularity. (If possible, the data
  40.     // sheet is a little fuzzy about this.)
  41.     uint8_t i;
  42.     uint16_t data;
  43.     uint16_t page = (addr / SPM_PAGESIZE) * SPM_PAGESIZE;
  44.    
  45.     for (i = 0; i < SPM_PAGESIZE; i += 2) {
  46.         data = pgm_read_word(page + i);
  47.         boot_page_fill(page + i, data);
  48.     }
  49. }
  50.  
  51. void flash_write_word(uint16_t addr, uint16_t word) {
  52.    
  53.     if ((addr / SPM_PAGESIZE) != (flash_prev_addr / SPM_PAGESIZE)) {
  54.         flash_flush_buffer();
  55.         flash_load_buffer(addr);
  56.     }
  57.    
  58.     boot_page_fill(addr, word);
  59.     flash_prev_addr = addr;
  60.     flash_buffer_dirty = 1;
  61. }    
  62.  
  63. void flash_init() {
  64.     flash_prev_addr = 0xffff;
  65.     flash_buffer_dirty = 0;
  66. }
  67.