Subversion Repositories HomeAutomation

Rev

Rev 228 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

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