Subversion Repositories HomeAutomation

Rev

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

Rev 309 Rev 310
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 <avr/wdt.h>
4
#include <avr/wdt.h>
5
#include "flash.h"
5
#include "flash.h"
6
 
6
 
7
static uint16_t flash_prev_addr;
7
static uint16_t flash_prev_addr;
8
static uint8_t flash_buffer_dirty = 0;
8
static uint8_t flash_buffer_dirty = 0;
9
 
9
 
10
void flash_flush_buffer() {
10
void flash_flush_buffer() {
11
    uint8_t sreg;
11
    uint8_t sreg;
12
   
12
   
13
    if (!flash_buffer_dirty) return; // Nothing to flush
13
    if (!flash_buffer_dirty) return; // Nothing to flush
14
   
14
   
15
    // Disable interrupts.
15
    // Disable interrupts.
16
   
16
   
17
    sreg = SREG;
17
    sreg = SREG;
18
    cli();
18
    cli();
19
   
19
   
20
    eeprom_busy_wait();
20
    eeprom_busy_wait();
21
   
21
   
22
    boot_page_erase(flash_prev_addr);
22
    boot_page_erase(flash_prev_addr);
23
    boot_spm_busy_wait();      // Wait until the memory is erased.
23
    boot_spm_busy_wait();      // Wait until the memory is erased.
24
   
24
   
25
    boot_page_write(flash_prev_addr);     // Store buffer in flash page.
25
    boot_page_write(flash_prev_addr);     // Store buffer in flash page.
26
    boot_spm_busy_wait();       // Wait until the memory is written.
26
    boot_spm_busy_wait();       // Wait until the memory is written.
27
 
27
 
28
    flash_buffer_dirty = 0;
28
    flash_buffer_dirty = 0;
29
 
29
 
30
    // Reenable RWW-section again. We need this if we want to jump back
30
    // Reenable RWW-section again. We need this if we want to jump back
31
    // to the application after bootloading.
31
    // to the application after bootloading.
32
 
32
 
33
    boot_rww_enable ();
33
    boot_rww_enable ();
34
    // Re-enable interrupts (if they were ever enabled).
34
    // Re-enable interrupts (if they were ever enabled).
35
 
35
 
36
    SREG = sreg;
36
    SREG = sreg;
37
}
37
}
38
 
38
 
39
#ifdef FLASH_LOAD_BUFFER
39
#ifdef FLASH_LOAD_BUFFER
40
void flash_load_buffer(uint16_t addr) BOOTLOADER;
40
void flash_load_buffer(uint16_t addr) BOOTLOADER;
41
void flash_load_buffer(uint16_t addr) {
41
void flash_load_buffer(uint16_t addr) {
42
    //TODO: Load current flash page contents into temporary buffer to implement
42
    //TODO: Load current flash page contents into temporary buffer to implement
43
    // flash read-modify-writes with word granularity. (If possible, the data
43
    // flash read-modify-writes with word granularity. (If possible, the data
44
    // sheet is a little fuzzy about this.)
44
    // sheet is a little fuzzy about this.)
45
    // Update: It seems it isn't possible to write any location in the temporary
45
    // Update: It seems it isn't possible to write any location in the temporary
46
    // buffer more than once without destroying the buffer. To implement this
46
    // buffer more than once without destroying the buffer. To implement this
47
    // functionality, a sram based buffer is probably neccessary. Problem is, 
47
    // functionality, a sram based buffer is probably neccessary. Problem is, 
48
    // how should it be allocated? A global buffer uses valuable .bss space.
48
    // how should it be allocated? A global buffer uses valuable .bss space.
49
    // All functions should probably take a pointer to a buffer allocated by
49
    // All functions should probably take a pointer to a buffer allocated by
50
    // main code.
50
    // main code.
51
    uint8_t i;
51
    uint8_t i;
52
    uint16_t data;
52
    uint16_t data;
53
    uint16_t page = (addr / SPM_PAGESIZE) * SPM_PAGESIZE;
53
    uint16_t page = (addr / SPM_PAGESIZE) * SPM_PAGESIZE;
54
   
54
   
55
    for (i = 0; i < SPM_PAGESIZE; i += 2) {
55
    for (i = 0; i < SPM_PAGESIZE; i += 2) {
56
        data = pgm_read_word(page + i);
56
        data = pgm_read_word(page + i);
57
        boot_page_fill(page + i, data);
57
        boot_page_fill(page + i, data);
58
    }
58
    }
59
}
59
}
60
#endif
60
#endif
61
 
61
 
62
void flash_write_word(uint16_t addr, uint16_t word) {
62
void flash_write_word(uint16_t addr, uint16_t word) {
63
   
63
   
64
    if ((addr / SPM_PAGESIZE) != (flash_prev_addr / SPM_PAGESIZE)) {
64
    if ((addr / SPM_PAGESIZE) != (flash_prev_addr / SPM_PAGESIZE)) {
65
        flash_flush_buffer();
65
        flash_flush_buffer();
66
#ifdef FLASH_LOAD_BUFFER
66
#ifdef FLASH_LOAD_BUFFER
67
        flash_load_buffer(addr);
67
        flash_load_buffer(addr);
68
#endif
68
#endif
69
    }
69
    }
70
   
70
   
71
    boot_page_fill(addr, word);
71
    boot_page_fill(addr, word);
72
    flash_prev_addr = addr;
72
    flash_prev_addr = addr;
73
    flash_buffer_dirty = 1;
73
    flash_buffer_dirty = 1;
74
}    
74
}    
75
 
75
 
76
void flash_init() {
76
void flash_init() {
77
    flash_prev_addr = 0xffff;
77
    flash_prev_addr = 0xffff;
78
    flash_buffer_dirty = 0;
78
    flash_buffer_dirty = 0;
79
}
79
}
80
 
80
 
81
#ifdef FLASH_COPY_DATA
81
#ifdef FLASH_COPY_DATA
82
void flash_copy_data(uint16_t src, uint16_t dst, uint16_t len) {
82
void flash_copy_data(uint16_t src, uint16_t dst, uint16_t len) {
83
    uint16_t i;
83
    uint16_t i;
84
    flash_init();
84
    flash_init();
85
    cli(); // From this point we're on our own
85
    cli(); // From this point we're on our own
86
    for (i = 0; i < len; i+=2) {
86
    for (i = 0; i < len; i+=2) {
87
        flash_write_word(dst + i, pgm_read_word(src + i));
87
        flash_write_word(dst + i, pgm_read_word(src + i));
88
        wdt_reset();
88
        wdt_reset();
89
    }
89
    }
90
    flash_flush_buffer();
90
    flash_flush_buffer();
91
    while (1); // Nothing more we can do, hopefully there is a watchdog active
91
    while (1); // Nothing more we can do, hopefully there is a watchdog active
92
}
92
}
93
#endif
93
#endif
94
 
94
 
95
#ifdef FLASH_COPY_DATA_NEW
95
#ifdef FLASH_COPY_DATA_NEW
96
extern uint16_t __flash_code_start;
96
extern uint16_t __flash_code_start;
97
 
97
 
98
void flash_copy_data(uint16_t src, uint16_t dst, uint16_t len) {
98
void flash_copy_data(uint16_t src, uint16_t dst, uint16_t len) {
99
#if 0
99
#if 0
100
    uint16_t offset;
100
    uint16_t offset;
101
#endif
101
#endif
102
    uint16_t data;
102
    uint16_t data;
103
 
103
 
104
    eeprom_busy_wait();     // Make sure any current writes to eeprom
104
    eeprom_busy_wait();     // Make sure any current writes to eeprom
105
    //boot_spm_busy_wait(); // or flash has completed before updating.
105
    boot_spm_busy_wait();   // or flash has completed before updating.
106
 
106
 
107
    cli(); // From this point we're on our own
107
    cli(); // From this point we're on our own
108
   
108
   
109
#if 0
109
#if 0
110
    for (offset = 0; offset < ((len | (SPM_PAGESIZE - 1)) + 1); offset += 2) {
110
    for (offset = 0; offset < ((len | (SPM_PAGESIZE - 1)) + 1); offset += 2) {
111
        if (dst + offset >= (uint16_t)&__flash_code_start) break;
111
        if (dst + offset >= (uint16_t)&__flash_code_start) break;
112
        data = pgm_read_word(src + offset);
112
        data = pgm_read_word(src + offset);
113
        boot_page_fill(dst + offset, data);
113
        boot_page_fill(dst + offset, data);
114
        if ((dst + offset + 2) % SPM_PAGESIZE == 0) {
114
        if ((dst + offset + 2) % SPM_PAGESIZE == 0) {
115
            boot_page_erase(dst + offset);
115
            boot_page_erase(dst + offset);
116
            boot_spm_busy_wait();      // Wait until the memory is erased.
116
            boot_spm_busy_wait();      // Wait until the memory is erased.
117
           
117
           
118
            boot_page_write(dst + offset);     // Store buffer in flash page.
118
            boot_page_write(dst + offset);     // Store buffer in flash page.
119
            boot_spm_busy_wait();       // Wait until the memory is written.
119
            boot_spm_busy_wait();       // Wait until the memory is written.
120
        }
120
        }
121
           
121
           
122
        wdt_reset();
122
        wdt_reset();
123
    }
123
    }
124
#else
124
#else
125
    len = (len | (SPM_PAGESIZE - 1)) + 3; // Round len up to a whole page + 2
125
    len = (len | (SPM_PAGESIZE - 1)) + 3; // Round len up to a whole page + 2
126
   
126
   
127
    while (len -= 2) {
127
    while (len -= 2) {
128
        wdt_reset();
128
        wdt_reset();
129
 
129
 
130
        boot_spm_busy_wait();      // Wait until the memory is erased.
-
 
131
        data = pgm_read_word(src); // Read source word
130
        data = pgm_read_word(src); // Read source word
132
        boot_spm_busy_wait();      // Wait until the memory is erased.
-
 
133
        boot_page_fill_safe(dst, data); // Write word to destination
131
        boot_page_fill_safe(dst, data); // Write word to destination
-
 
132
        boot_spm_busy_wait();      // Make sure spm is ready.
134
       
133
       
135
        if ((dst + 2) % SPM_PAGESIZE == 0) { // If we just wrote the last word of a page
134
        if (((uint8_t)dst + 2) % SPM_PAGESIZE == 0) { // If we just wrote the last word of a page
-
 
135
            boot_page_erase(dst);
136
            boot_spm_busy_wait();      // Wait until the memory is erased.
136
            boot_spm_busy_wait(); // Wait until the memory is erased.
137
            boot_page_erase(dst);
137
            boot_page_write(dst); // Store buffer in flash page.
138
            boot_spm_busy_wait();       // Wait until the memory is written.
138
            boot_spm_busy_wait(); // Wait until the memory is written.
139
            boot_page_write(dst); // Store buffer in flash page.
139
            boot_rww_enable();
140
        }
140
        }
141
         
141
         
142
        src += 2;
142
        src += 2;
143
        dst += 2;
143
        dst += 2;
144
    }
144
    }
145
         
145
         
146
#endif
146
#endif
147
    while (1); // Nothing more we can do, hopefully there is a watchdog active
147
    while (1); // Nothing more we can do, hopefully there is a watchdog active
148
}
148
}
149
#endif
149
#endif
150
 
150