-
Notifications
You must be signed in to change notification settings - Fork 75
/
eeprom.c
174 lines (133 loc) · 4.42 KB
/
eeprom.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
eeprom - routines to accessing eeprom
Copyright (C) 2011 Pavel Semerad
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
first N models are stored at EEPROM after global config
last eeprom model config is used to temporarily store of FLASH model
memory, because EEPROM has 1M write cycles (flash 10K) and
writing to FLASH stops microcontroller (EEPROM has ReadWhileWrite)
models at FLASH are stored from end of FLASH down to end of program
when FLASH model is selected, it is copied to temporary EEPROM place
and is stored back only after another model is selected
*/
#include <string.h>
#include "eeprom.h"
// read from eeprom
@inline static void eeprom_read(u8 *ee_addr, void *ram_addr, u16 length) {
memcpy(ram_addr, ee_addr, length);
}
void eeprom_read_global(void) {
eeprom_read(EEPROM_CONFIG_GLOBAL, &config_global, sizeof(config_global_s));
}
void eeprom_read_model(u8 model) {
u8 size = sizeof(config_model_s);
eeprom_read(EEPROM_CONFIG_MODEL + model * size, &config_model, size);
}
void flash_read_model(u8 model) {
u8 size = sizeof(config_model_s);
eeprom_read((u8 *)(0 - (model + 1) * size), &config_model, size);
}
// write to eeprom
static void eeprom_make_writable(void *addr) {
u8 i = 10;
// enable write to eeprom/flash
if ((u16)addr < 0x8000) {
// eeprom
FLASH_DUKR = 0xAE;
FLASH_DUKR = 0x56;
// wait for Data EEPROM area unlocked flag
do {
if (BCHK(FLASH_IAPSR, 3)) break;
} while (--i);
}
else {
// flash
FLASH_PUKR = 0x56;
FLASH_PUKR = 0xAE;
// wait for Flash Program memory unlocked flag
do {
if (BCHK(FLASH_IAPSR, 1)) break;
} while (--i);
}
}
static void eeprom_make_readonly(void *addr) {
if ((u16)addr < 0x8000) BRES(FLASH_IAPSR, 3);
else BRES(FLASH_IAPSR, 1);
}
static void eeprom_write(u8 *ee_addr, u8 *ram_addr, u16 length) {
eeprom_make_writable(ee_addr);
// write only values, which are different, check and write at
// Word mode (4 bytes)
length /= 4;
do {
if (*(u16 *)ee_addr != *(u16 *)ram_addr ||
*(u16 *)(ee_addr + 2) != *(u16 *)(ram_addr + 2)) {
// enable Word programming
BSET(FLASH_CR2, 6);
BRES(FLASH_NCR2, 6);
// write 4-byte value
ee_addr[0] = ram_addr[0];
ee_addr[1] = ram_addr[1];
ee_addr[2] = ram_addr[2];
ee_addr[3] = ram_addr[3];
// wait for EndOfProgramming flag
while (!BCHK(FLASH_IAPSR, 2)) pause();
}
ee_addr += 4;
ram_addr += 4;
} while (--length);
eeprom_make_readonly(ee_addr);
}
void eeprom_write_global(void) {
eeprom_write(EEPROM_CONFIG_GLOBAL, (u8 *)&config_global, sizeof(config_global_s));
}
void eeprom_write_model(u8 model) {
u8 size = sizeof(config_model_s);
eeprom_write(EEPROM_CONFIG_MODEL + model * size, (u8 *)&config_model, size);
}
void flash_write_model(u8 model) {
u8 size = sizeof(config_model_s);
eeprom_write((u8 *)(0 - (model + 1) * size), (u8 *)&config_model, size);
}
// initialize model memories to empty one
void eeprom_empty_models(void) {
u8 cnt = CONFIG_MODEL_MAX_EEPROM;
config_model_s *cm = (config_model_s *)EEPROM_CONFIG_MODEL;
// EEPROM first
eeprom_make_writable(cm);
// write 0x00 to first letter of each model config
do {
if (cm->name[0] != CONFIG_MODEL_EMPTY) {
cm->name[0] = CONFIG_MODEL_EMPTY;
// wait for EOP
while (!BCHK(FLASH_IAPSR, 2)) pause();
}
cm++;
} while (--cnt);
eeprom_make_readonly(cm);
// FLASH second
cnt = CONFIG_MODEL_MAX_FLASH;
cm = (config_model_s *)(-sizeof(config_model_s));
eeprom_make_writable(cm);
// write 0x00 to first letter of each model config
do {
if (cm->name[0] != CONFIG_MODEL_EMPTY) {
cm->name[0] = CONFIG_MODEL_EMPTY;
// wait for EOP
while (!BCHK(FLASH_IAPSR, 2)) pause();
}
cm--;
} while (--cnt);
eeprom_make_readonly(cm);
}