Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
228 andfri 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
 
233 andfri 27
    flash_buffer_dirty = 0;
28
 
228 andfri 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
 
254 andfri 38
#ifdef FLASH_LOAD_BUFFER
39
void flash_load_buffer(uint16_t addr) BOOTLOADER;
228 andfri 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
    }
254 andfri 52
}
53
#endif
228 andfri 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();
254 andfri 59
#ifdef FLASH_LOAD_BUFFER
228 andfri 60
        flash_load_buffer(addr);
254 andfri 61
#endif
228 andfri 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
}
254 andfri 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