Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
settings_arch.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2011 Martin Mueller <martinmm@pfump.org>
3 *
4 * This file is part of Paparazzi.
5 *
6 * Paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * Paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 */
22
36
37#include <libopencm3/stm32/flash.h>
38#include <libopencm3/stm32/crc.h>
39#include <libopencm3/stm32/dbgmcu.h>
40
47
48
50static int32_t flash_detect(struct FlashInfo *flash);
53 uint32_t size,
54 uint32_t chksum);
55
56#if defined(STM32F1)
57#define FLASH_SIZE_ MMIO16(0x1FFFF7E0)
58#elif defined(STM32F4)
59#define FLASH_SIZE_ MMIO16(0x1FFF7A22)
60#endif
61
62#define FLASH_BEGIN 0x08000000
63#define FSIZ 8
64#define FCHK 4
65
66
68{
69 uint32_t i;
70
71 /* reset crc */
73
74 if (ptr % 4) {
75 /* calc in 8bit chunks */
76 for (i = 0; i < (size & ~3); i += 4) {
77 CRC_DR = (*(uint8_t *)(ptr + i)) |
78 (*(uint8_t *)(ptr + i + 1)) << 8 |
79 (*(uint8_t *)(ptr + i + 2)) << 16 |
80 (*(uint8_t *)(ptr + i + 3)) << 24;
81 }
82 } else {
83 /* calc in 32bit */
84 for (i = 0; i < (size & ~3); i += 4) {
85 CRC_DR = *(uint32_t *)(ptr + i);
86 }
87 }
88
89 /* remaining bytes */
90 switch (size % 4) {
91 case 1:
92 CRC_DR = *(uint8_t *)(ptr + i);
93 break;
94 case 2:
95 CRC_DR = (*(uint8_t *)(ptr + i)) |
96 (*(uint8_t *)(ptr + i + 1)) << 8;
97 break;
98 case 3:
99 CRC_DR = (*(uint8_t *)(ptr + i)) |
100 (*(uint8_t *)(ptr + i + 1)) << 8 |
101 (*(uint8_t *)(ptr + i + 2)) << 16;
102 break;
103 default:
104 break;
105 }
106
107 return CRC_DR;
108}
109
111{
112
113 flash->total_size = FLASH_SIZE_ * 0x400;
114
115#if defined(STM32F1)
116 /* FIXME This will not work for connectivity line (needs ID, see below), but
117 device ID is only readable when freshly loaded through JTAG?! */
118
119 /* WARNING If you are using this for F4 this only works for memory sizes
120 * larger than 128kb. Otherwise the first few sectors are either 16kb or
121 * 64kb. To make those small devices work we would need to know what the page
122 * we want to put the settings into is. Otherwise we will might be writing
123 * into a 64kb page that is actually 16kb big.
124 */
125 switch (flash->total_size) {
126 /* low density */
127 case 0x00004000: /* 16 kBytes */
128 case 0x00008000: /* 32 kBytes */
129 /* medium density, e.g. STM32F103RBT6 (Olimex STM32-H103) */
130 case 0x00010000: /* 64 kBytes */
131 case 0x00020000: { /* 128 kBytes */
132 flash->page_size = 0x400;
133 break;
134 }
135 /* high density, e.g. STM32F103RE (Joby Lisa/M, Lisa/L) */
136 case 0x00040000: /* 256 kBytes */
137 case 0x00080000: /* 512 kBytes */
138 /* XL density */
139 case 0x000C0000: /* 768 kBytes */
140 case 0x00100000: { /* 1 MByte */
141 flash->page_size = 0x800;
142 break;
143 }
144 default: {return -1;}
145 }
146
147#elif defined(STM32F4) /* this is the correct way of detecting page sizes but we currently only use it for the F4 because the F1 version is broken. */
149
150 /* read device id */
152
153 switch (device_id) {
154 /* low density */
155 case 0x412:
156 /* medium density, e.g. STM32F103RB (Olimex STM32-H103) */
157 case 0x410: {
158 flash->page_size = 0x400;
159 break;
160 }
161 /* high density, e.g. STM32F103RE (Joby Lisa/L) */
162 case 0x414:
163 /* XL density */
164 case 0x430:
165 /* connectivity line */
166 case 0x418: {
167 flash->page_size = 0x800;
168 break;
169 }
170 case 0x0413: /* STM32F405xx/07xx and STM32F415xx/17xx) */
171 case 0x0419: /* STM32F42xxx and STM32F43xxx */
172 case 0x0423: /* STM32F401xB/C */
173 case 0x0433: /* STM32F401xD/E */
174 case 0x0431: { /* STM32F411xC/E */
175 flash->page_size = 0x20000;
176 break;
177 }
178 default: return -1;
179 }
180
181 switch (flash->total_size) {
182 case 0x00004000: /* 16 kBytes */
183 case 0x00008000: /* 32 kBytes */
184 case 0x00010000: /* 64 kBytes */
185 case 0x00020000: /* 128 kBytes */
186 case 0x00040000: /* 256 kBytes */
187 case 0x00080000: /* 512 kBytes */
188 case 0x000C0000: /* 768 kBytes */
189 case 0x00100000: /* 1 MByte */
190 case 0x00200000: /* 2 MByte */
191 break;
192 default: return -1;
193 }
194#else
195#error Unknown device
196#endif
197
198#if defined(STM32F1)
199 flash->page_nr = (flash->total_size / flash->page_size) - 1;
200 flash->addr = FLASH_BEGIN + flash->page_nr * flash->page_size;
201#elif defined(STM32F4)
202 /* We are assuming all pages are 128kb so we have to compensate for the first
203 * few pages that are smaller which means we have to skip the first 4.
204 */
205 flash->page_nr = (flash->total_size / flash->page_size) - 1 + 4;
206 flash->addr = FLASH_BEGIN + (flash->page_nr - 4) * flash->page_size;
207#endif
208
209 return 0;
210}
211
212
214{
215 uint32_t i;
216
217 /* erase */
218 flash_unlock();
219#if defined(STM32F1)
220 flash_erase_page(flash->addr);
221#elif defined(STM32F4)
223#endif
224 flash_lock();
225
226 /* verify erase */
227 for (i = 0; i < flash->page_size; i += 4) {
228 if ((*(uint32_t *)(flash->addr + i)) != 0xFFFFFFFF) { return -1; }
229 }
230 return 0;
231}
232
233// (gdb) p *flash
234// $1 = {addr = 134739968, total_size = 524288, page_nr = 255, page_size = 2048}
235// 0x807F800 0x80000
238 uint32_t size,
239 uint32_t chksum)
240{
241 uint32_t i;
242
243 /* erase, return with error if not successful */
244 if (pflash_erase(flash)) { return -1; }
245
246 flash_unlock();
247 /* write full 16 bit words */
248 for (i = 0; i < (size & ~1); i += 2) {
250 (uint16_t)(*(uint8_t *)(src + i) | (*(uint8_t *)(src + i + 1)) << 8));
251 }
252 /* fill bytes with a zero */
253 if (size & 1) {
254 flash_program_half_word(flash->addr + i, (uint16_t)(*(uint8_t *)(src + i)));
255 }
256 /* write size */
257 flash_program_half_word(flash->addr + flash->page_size - FSIZ,
258 (uint16_t)(size & 0xFFFF));
259 flash_program_half_word(flash->addr + flash->page_size - FSIZ + 2,
260 (uint16_t)((size >> 16) & 0xFFFF));
261 /* write checksum */
262 flash_program_half_word(flash->addr + flash->page_size - FCHK,
263 (uint16_t)(chksum & 0xFFFF));
264 flash_program_half_word(flash->addr + flash->page_size - FCHK + 2,
265 (uint16_t)((chksum >> 16) & 0xFFFF));
266 flash_lock();
267
268 /* verify data */
269 for (i = 0; i < size; i++) {
270 if ((*(uint8_t *)(flash->addr + i)) != (*(uint8_t *)(src + i))) { return -2; }
271 }
272 if (*(uint32_t *)(flash->addr + flash->page_size - FSIZ) != size) { return -3; }
273 if (*(uint32_t *)(flash->addr + flash->page_size - FCHK) != chksum) { return -4; }
274
275 return 0;
276}
277
279{
280 struct FlashInfo flash_info;
281 if (flash_detect(&flash_info)) { return -1; }
282 if ((size > flash_info.page_size - FSIZ) || (size == 0)) { return -2; }
283
285 (uint32_t)ptr,
286 size,
288}
289
291{
292 struct FlashInfo flash;
293 uint32_t i;
294
295 /* check parameters */
296 if (flash_detect(&flash)) { return -1; }
297 if ((size > flash.page_size - FSIZ) || (size == 0)) { return -2; }
298
299 /* check consistency */
300 if (size != *(uint32_t *)(flash.addr + flash.page_size - FSIZ)) { return -3; }
301 if (pflash_checksum(flash.addr, size) !=
302 *(uint32_t *)(flash.addr + flash.page_size - FCHK)) {
303 return -4;
304 }
305
306 /* copy data */
307 for (i = 0; i < size; i++) {
308 *(uint8_t *)((uint32_t)ptr + i) = *(uint8_t *)(flash.addr + i);
309 }
310
311 return 0;
312}
313
315{
316 struct FlashInfo flash_info;
317 if (flash_detect(&flash_info)) { return -1; }
318
319 return pflash_erase(&flash_info);
320}
int32_t persistent_write(void *ptr, uint32_t size)
int32_t persistent_read(void *ptr, uint32_t size)
int32_t persistent_clear(void)
uint16_t foo
Definition main_demo5.c:58
Persistent settings interface.
uint32_t addr
static uint32_t pflash_checksum(uint32_t ptr, uint32_t size)
static int32_t pflash_program_bytes(struct FlashInfo *flash, uint32_t src, uint32_t size, uint32_t chksum)
#define FCHK
#define FLASH_BEGIN
static int32_t flash_detect(struct FlashInfo *flash)
uint32_t total_size
#define FSIZ
static int32_t pflash_erase(struct FlashInfo *flash)
uint32_t page_size
uint32_t page_nr
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
int int32_t
Typedef defining 32 bit int type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.