Paparazzi UAS  v5.2.2_stable-0-gd6b9f29
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures 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 
35 #include "subsystems/settings.h"
36 
37 #include <libopencm3/stm32/flash.h>
38 #include <libopencm3/stm32/crc.h>
39 #include <libopencm3/stm32/dbgmcu.h>
40 
41 struct FlashInfo {
42  uint32_t addr;
46 };
47 
48 
49 static uint32_t pflash_checksum(uint32_t ptr, uint32_t size);
50 static int32_t flash_detect(struct FlashInfo* flash);
51 static int32_t pflash_program_bytes(struct FlashInfo* flash,
52  uint32_t src,
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  uint32_t i;
69 
70  /* reset crc */
71  CRC_CR = CRC_CR_RESET;
72 
73  if (ptr % 4) {
74  /* calc in 8bit chunks */
75  for (i=0; i<(size & ~3); i+=4) {
76  CRC_DR = (*(uint8_t*) (ptr+i)) |
77  (*(uint8_t*) (ptr+i+1)) << 8 |
78  (*(uint8_t*) (ptr+i+2)) << 16 |
79  (*(uint8_t*) (ptr+i+3)) << 24;
80  }
81  } else {
82  /* calc in 32bit */
83  for (i=0; i<(size & ~3); i+=4) {
84  CRC_DR = *(uint32_t*) (ptr+i);
85  }
86  }
87 
88  /* remaining bytes */
89  switch (size % 4) {
90  case 1:
91  CRC_DR = *(uint8_t*) (ptr+i);
92  break;
93  case 2:
94  CRC_DR = (*(uint8_t*) (ptr+i)) |
95  (*(uint8_t*) (ptr+i+1)) << 8;
96  break;
97  case 3:
98  CRC_DR = (*(uint8_t*) (ptr+i)) |
99  (*(uint8_t*) (ptr+i+1)) << 8 |
100  (*(uint8_t*) (ptr+i+2)) << 16;
101  break;
102  default:
103  break;
104  }
105 
106  return CRC_DR;
107 }
108 
109 static int32_t flash_detect(struct FlashInfo* flash) {
110 
111  flash->total_size = FLASH_SIZE_ * 0x400;
112 
113 #if 1
114  /* FIXME This will not work for connectivity line (needs ID, see below), but
115  device ID is only readable when freshly loaded through JTAG?! */
116 
117  switch (flash->total_size) {
118  /* low density */
119  case 0x00004000: /* 16 kBytes */
120  case 0x00008000: /* 32 kBytes */
121  /* medium density, e.g. STM32F103RBT6 (Olimex STM32-H103) */
122  case 0x00010000: /* 64 kBytes */
123  case 0x00020000: /* 128 kBytes */
124  {
125  flash->page_size = 0x400;
126  break;
127  }
128  /* high density, e.g. STM32F103RE (Joby Lisa/M, Lisa/L) */
129  case 0x00040000: /* 256 kBytes */
130  case 0x00080000: /* 512 kBytes */
131  /* XL density */
132  case 0x000C0000: /* 768 kBytes */
133  case 0x00100000: /* 1 MByte */
134  {
135  flash->page_size = 0x800;
136  break;
137  }
138  default: {return -1;}
139  }
140 
141 #else /* this is the correct way of detecting page sizes */
142  uint32_t device_id;
143 
144  /* read device id */
145  device_id = DBGMCU_IDCODE & DBGMCU_IDCODE_DEV_ID_MASK;
146 
147  switch (device_id) {
148  /* low density */
149  case 0x412:
150  /* medium density, e.g. STM32F103RB (Olimex STM32-H103) */
151  case 0x410:
152  {
153  flash->page_size = 0x400;
154  break;
155  }
156  /* high density, e.g. STM32F103RE (Joby Lisa/L) */
157  case 0x414:
158  /* XL density */
159  case 0x430:
160  /* connectivity line */
161  case 0x418:
162  {
163  flash->page_size = 0x800;
164  break;
165  }
166  default: return -1;
167  }
168 
169  switch (flash->total_size) {
170  case 0x00004000: /* 16 kBytes */
171  case 0x00008000: /* 32 kBytes */
172  case 0x00010000: /* 64 kBytes */
173  case 0x00200000: /* 128 kBytes */
174  case 0x00040000: /* 256 kBytes */
175  case 0x00080000: /* 512 kBytes */
176  case 0x000C0000: /* 768 kBytes */
177  case 0x00100000: /* 1 MByte */
178  break;
179  default: return -1;
180  }
181 #endif
182 
183  flash->page_nr = (flash->total_size / flash->page_size) - 1;
184  flash->addr = FLASH_BEGIN + flash->page_nr * flash->page_size;
185 
186  return 0;
187 }
188 
189 // (gdb) p *flash
190 // $1 = {addr = 134739968, total_size = 524288, page_nr = 255, page_size = 2048}
191 // 0x807F800 0x80000
192 #if defined(STM32F1)
193 static int32_t pflash_program_bytes(struct FlashInfo* flash,
194  uint32_t src,
195  uint32_t size,
196  uint32_t chksum) {
197  uint32_t i;
198 
199  /* erase */
200  flash_unlock();
201  flash_erase_page(flash->addr);
202  flash_lock();
203 
204  /* verify erase */
205  for (i=0; i<flash->page_size; i+=4) {
206  if ((*(uint32_t*) (flash->addr + i)) != 0xFFFFFFFF) return -1;
207  }
208 
209  flash_unlock();
210  /* write full 16 bit words */
211  for (i=0; i<(size & ~1); i+=2) {
212  flash_program_half_word(flash->addr+i,
213  (uint16_t)(*(uint8_t*)(src+i) | (*(uint8_t*)(src+i+1)) << 8));
214  }
215  /* fill bytes with a zero */
216  if (size & 1) {
217  flash_program_half_word(flash->addr+i, (uint16_t)(*(uint8_t*)(src+i)));
218  }
219  /* write size */
220  flash_program_half_word(flash->addr+flash->page_size-FSIZ,
221  (uint16_t)(size & 0xFFFF));
222  flash_program_half_word(flash->addr+flash->page_size-FSIZ+2,
223  (uint16_t)((size >> 16) & 0xFFFF));
224  /* write checksum */
225  flash_program_half_word(flash->addr+flash->page_size-FCHK,
226  (uint16_t)(chksum & 0xFFFF));
227  flash_program_half_word(flash->addr+flash->page_size-FCHK+2,
228  (uint16_t)((chksum >> 16) & 0xFFFF));
229  flash_lock();
230 
231  /* verify data */
232  for (i=0; i<size; i++) {
233  if ((*(uint8_t*) (flash->addr+i)) != (*(uint8_t*) (src+i))) return -2;
234  }
235  if (*(uint32_t*) (flash->addr+flash->page_size-FSIZ) != size) return -3;
236  if (*(uint32_t*) (flash->addr+flash->page_size-FCHK) != chksum) return -4;
237 
238  return 0;
239 }
240 #elif defined(STM32F4)
241 static int32_t pflash_program_bytes(struct FlashInfo* flash __attribute__((unused)),
242  uint32_t src __attribute__((unused)),
243  uint32_t size __attribute__((unused)),
244  uint32_t chksum __attribute__((unused))) {
245  return -1;
246 }
247 #endif
248 
249 
251  struct FlashInfo flash_info;
252  if (flash_detect(&flash_info)) return -1;
253  if ((size > flash_info.page_size-FSIZ) || (size == 0)) return -2;
254 
255  return pflash_program_bytes(&flash_info,
256  ptr,
257  size,
258  pflash_checksum(ptr, size));
259 }
260 
262  struct FlashInfo flash;
263  uint32_t i;
264 
265  /* check parameters */
266  if (flash_detect(&flash)) return -1;
267  if ((size > flash.page_size-FSIZ) || (size == 0)) return -2;
268 
269  /* check consistency */
270  if (size != *(uint32_t*)(flash.addr+flash.page_size-FSIZ)) return -3;
271  if (pflash_checksum(flash.addr, size) !=
272  *(uint32_t*)(flash.addr+flash.page_size-FCHK))
273  return -4;
274 
275  /* copy data */
276  for (i=0; i<size; i++) {
277  *(uint8_t*) (ptr+i) = *(uint8_t*) (flash.addr+i);
278  }
279 
280  return 0;
281 }
unsigned short uint16_t
Definition: types.h:16
#define FSIZ
Definition: settings_arch.c:63
uint32_t page_nr
Definition: settings_arch.c:68
uint32_t addr
Definition: settings_arch.c:66
int32_t persistent_read(uint32_t ptr, uint32_t size)
#define FCHK
Definition: settings_arch.c:64
#define FLASH_BEGIN
Definition: settings_arch.c:62
unsigned long uint32_t
Definition: types.h:18
signed long int32_t
Definition: types.h:19
static int32_t flash_detect(struct FlashInfo *flash)
static int32_t pflash_program_bytes(struct FlashInfo *flash, uint32_t src, uint32_t size, uint32_t chksum)
static uint32_t pflash_checksum(uint32_t ptr, uint32_t size)
Definition: settings_arch.c:67
unsigned char uint8_t
Definition: types.h:14
Persistent settings interface.
uint32_t page_size
Definition: settings_arch.c:69
uint32_t total_size
Definition: settings_arch.c:67
int32_t persistent_write(uint32_t ptr, uint32_t size)