Subversion Repositories HomeAutomation

Rev

Rev 233 | 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.     flash_buffer_dirty = 0;
  28.  
  29.     // Reenable RWW-section again. We need this if we want to jump back
  30.     // to the application after bootloading.
  31.  
  32.     boot_rww_enable ();
  33.     // Re-enable interrupts (if they were ever enabled).
  34.  
  35.     SREG = sreg;
  36. }
  37.  
  38. #ifdef FLASH_LOAD_BUFFER
  39. void flash_load_buffer(uint16_t addr) BOOTLOADER;
  40. void flash_load_buffer(uint16_t addr) {
  41.     //TODO: Load current flash page contents into temporary buffer to implement
  42.     // flash read-modify-writes with word granularity. (If possible, the data
  43.     // sheet is a little fuzzy about this.)
  44.     uint8_t i;
  45.     uint16_t data;
  46.     uint16_t page = (addr / SPM_PAGESIZE) * SPM_PAGESIZE;
  47.    
  48.     for (i = 0; i < SPM_PAGESIZE; i += 2) {
  49.         data = pgm_read_word(page + i);
  50.         boot_page_fill(page + i, data);
  51.     }
  52. }
  53. #endif
  54.  
  55. void flash_write_word(uint16_t addr, uint16_t word) {
  56.    
  57.     if ((addr / SPM_PAGESIZE) != (flash_prev_addr / SPM_PAGESIZE)) {
  58.         flash_flush_buffer();
  59. #ifdef FLASH_LOAD_BUFFER
  60.         flash_load_buffer(addr);
  61. #endif
  62.     }
  63.    
  64.     boot_page_fill(addr, word);
  65.     flash_prev_addr = addr;
  66.     flash_buffer_dirty = 1;
  67. }    
  68.  
  69. void flash_init() {
  70.     flash_prev_addr = 0xffff;
  71.     flash_buffer_dirty = 0;
  72. }
  73.  
  74. #ifdef FLASH_COPY_DATA
  75. void flash_copy_data(uint16_t src, uint16_t dst, uint16_t len) {
  76.     uint16_t i;
  77.     flash_init();
  78.     for (i = 0; i < len; i+=2) {
  79.         flash_write_word(dst + i, pgm_read_word(src + i));
  80.     }
  81.     flash_flush_buffer();
  82. }
  83. #endif
  84.