Paparazzi UAS  v5.0.5_stable-7-g4b8bbb7
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  * Paparazzi persistent settings low level flash routines stm32
3  *
4  * Copyright (C) 2011 Martin Mueller <martinmm@pfump.org>
5  *
6  * This file is part of Paparazzi.
7  *
8  * Paparazzi is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * Paparazzi is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Paparazzi; see the file COPYING. If not, write to
20  * the Free Software Foundation, 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  */
24 
25 /*
26  flash data is located in the last page/sector of flash
27 
28  data flash_addr
29  data_size flash_end - FSIZ
30  checksum flash_end - FCHK
31 
32  STM32: minimum write size 2 bytes, endurance 10k cycles,
33  max sector erase time 40ms, max prog time 70us per 2 bytes
34 */
35 
36 #include "subsystems/settings.h"
37 
38 #if defined(STM32F1)
39 #include <libopencm3/stm32/f1/flash.h>
40 #elif defined(STM32F4)
41 #include <libopencm3/stm32/f4/flash.h>
42 #endif
43 
44 #include <libopencm3/stm32/crc.h>
45 #include <libopencm3/stm32/dbgmcu.h>
46 
47 struct FlashInfo {
48  uint32_t addr;
52 };
53 
54 
55 static uint32_t pflash_checksum(uint32_t ptr, uint32_t size);
56 static int32_t flash_detect(struct FlashInfo* flash);
57 static int32_t pflash_program_bytes(struct FlashInfo* flash,
58  uint32_t src,
59  uint32_t size,
60  uint32_t chksum);
61 
62 #if defined(STM32F1)
63 #define FLASH_SIZE_ MMIO16(0x1FFFF7E0)
64 #elif defined(STM32F4)
65 #define FLASH_SIZE_ MMIO16(0x1FFF7A22)
66 #endif
67 
68 #define FLASH_BEGIN 0x08000000
69 #define FSIZ 8
70 #define FCHK 4
71 
72 
74  uint32_t i;
75 
76  /* reset crc */
77  CRC_CR = CRC_CR_RESET;
78 
79  if (ptr % 4) {
80  /* calc in 8bit chunks */
81  for (i=0; i<(size & ~3); i+=4) {
82  CRC_DR = (*(uint8_t*) (ptr+i)) |
83  (*(uint8_t*) (ptr+i+1)) << 8 |
84  (*(uint8_t*) (ptr+i+2)) << 16 |
85  (*(uint8_t*) (ptr+i+3)) << 24;
86  }
87  } else {
88  /* calc in 32bit */
89  for (i=0; i<(size & ~3); i+=4) {
90  CRC_DR = *(uint32_t*) (ptr+i);
91  }
92  }
93 
94  /* remaining bytes */
95  switch (size % 4) {
96  case 1:
97  CRC_DR = *(uint8_t*) (ptr+i);
98  break;
99  case 2:
100  CRC_DR = (*(uint8_t*) (ptr+i)) |
101  (*(uint8_t*) (ptr+i+1)) << 8;
102  break;
103  case 3:
104  CRC_DR = (*(uint8_t*) (ptr+i)) |
105  (*(uint8_t*) (ptr+i+1)) << 8 |
106  (*(uint8_t*) (ptr+i+2)) << 16;
107  break;
108  default:
109  break;
110  }
111 
112  return CRC_DR;
113 }
114 
115 static int32_t flash_detect(struct FlashInfo* flash) {
116 
117  flash->total_size = FLASH_SIZE_ * 0x400;
118 
119 #if 1
120  /* FIXME This will not work for connectivity line (needs ID, see below), but
121  device ID is only readable when freshly loaded through JTAG?! */
122 
123  switch (flash->total_size) {
124  /* low density */
125  case 0x00004000: /* 16 kBytes */
126  case 0x00008000: /* 32 kBytes */
127  /* medium density, e.g. STM32F103RBT6 (Olimex STM32-H103) */
128  case 0x00010000: /* 64 kBytes */
129  case 0x00020000: /* 128 kBytes */
130  {
131  flash->page_size = 0x400;
132  break;
133  }
134  /* high density, e.g. STM32F103RE (Joby Lisa/M, Lisa/L) */
135  case 0x00040000: /* 256 kBytes */
136  case 0x00080000: /* 512 kBytes */
137  /* XL density */
138  case 0x000C0000: /* 768 kBytes */
139  case 0x00100000: /* 1 MByte */
140  {
141  flash->page_size = 0x800;
142  break;
143  }
144  default: {return -1;}
145  }
146 
147 #else /* this is the correct way of detecting page sizes */
148  uint32_t device_id;
149 
150  /* read device id */
151  device_id = DBGMCU_IDCODE & DBGMCU_IDCODE_DEV_ID_MASK;
152 
153  switch (device_id) {
154  /* low density */
155  case 0x412:
156  /* medium density, e.g. STM32F103RB (Olimex STM32-H103) */
157  case 0x410:
158  {
159  flash->page_size = 0x400;
160  break;
161  }
162  /* high density, e.g. STM32F103RE (Joby Lisa/L) */
163  case 0x414:
164  /* XL density */
165  case 0x430:
166  /* connectivity line */
167  case 0x418:
168  {
169  flash->page_size = 0x800;
170  break;
171  }
172  default: return -1;
173  }
174 
175  switch (flash->total_size) {
176  case 0x00004000: /* 16 kBytes */
177  case 0x00008000: /* 32 kBytes */
178  case 0x00010000: /* 64 kBytes */
179  case 0x00200000: /* 128 kBytes */
180  case 0x00040000: /* 256 kBytes */
181  case 0x00080000: /* 512 kBytes */
182  case 0x000C0000: /* 768 kBytes */
183  case 0x00100000: /* 1 MByte */
184  break;
185  default: return -1;
186  }
187 #endif
188 
189  flash->page_nr = (flash->total_size / flash->page_size) - 1;
190  flash->addr = FLASH_BEGIN + flash->page_nr * flash->page_size;
191 
192  return 0;
193 }
194 
195 // (gdb) p *flash
196 // $1 = {addr = 134739968, total_size = 524288, page_nr = 255, page_size = 2048}
197 // 0x807F800 0x80000
198 
200  uint32_t src,
201  uint32_t size,
202  uint32_t chksum) {
203 #if defined(STM32F1)
204  uint32_t i;
205 
206  /* erase */
207  flash_unlock();
208  flash_erase_page(flash->addr);
209  flash_lock();
210 
211  /* verify erase */
212  for (i=0; i<flash->page_size; i+=4) {
213  if ((*(uint32_t*) (flash->addr + i)) != 0xFFFFFFFF) return -1;
214  }
215 
216  flash_unlock();
217  /* write full 16 bit words */
218  for (i=0; i<(size & ~1); i+=2) {
219  flash_program_half_word(flash->addr+i,
220  (uint16_t)(*(uint8_t*)(src+i) | (*(uint8_t*)(src+i+1)) << 8));
221  }
222  /* fill bytes with a zero */
223  if (size & 1) {
224  flash_program_half_word(flash->addr+i, (uint16_t)(*(uint8_t*)(src+i)));
225  }
226  /* write size */
227  flash_program_half_word(flash->addr+flash->page_size-FSIZ,
228  (uint16_t)(size & 0xFFFF));
229  flash_program_half_word(flash->addr+flash->page_size-FSIZ+2,
230  (uint16_t)((size >> 16) & 0xFFFF));
231  /* write checksum */
232  flash_program_half_word(flash->addr+flash->page_size-FCHK,
233  (uint16_t)(chksum & 0xFFFF));
234  flash_program_half_word(flash->addr+flash->page_size-FCHK+2,
235  (uint16_t)((chksum >> 16) & 0xFFFF));
236  flash_lock();
237 
238  /* verify data */
239  for (i=0; i<size; i++) {
240  if ((*(uint8_t*) (flash->addr+i)) != (*(uint8_t*) (src+i))) return -2;
241  }
242  if (*(uint32_t*) (flash->addr+flash->page_size-FSIZ) != size) return -3;
243  if (*(uint32_t*) (flash->addr+flash->page_size-FCHK) != chksum) return -4;
244 #elif defined(STM32F4)
245 
246 #endif
247 
248  return 0;
249 }
250 
252  struct FlashInfo flash_info;
253  if (flash_detect(&flash_info)) return -1;
254  if ((size > flash_info.page_size-FSIZ) || (size == 0)) return -2;
255 
256  return pflash_program_bytes(&flash_info,
257  ptr,
258  size,
259  pflash_checksum(ptr, size));
260 }
261 
263  struct FlashInfo flash;
264  uint32_t i;
265 
266  /* check parameters */
267  if (flash_detect(&flash)) return -1;
268  if ((size > flash.page_size-FSIZ) || (size == 0)) return -2;
269 
270  /* check consistency */
271  if (size != *(uint32_t*)(flash.addr+flash.page_size-FSIZ)) return -3;
272  if (pflash_checksum(flash.addr, size) !=
273  *(uint32_t*)(flash.addr+flash.page_size-FCHK))
274  return -4;
275 
276  /* copy data */
277  for (i=0; i<size; i++) {
278  *(uint8_t*) (ptr+i) = *(uint8_t*) (flash.addr+i);
279  }
280 
281  return 0;
282 }
unsigned short uint16_t
Definition: types.h:16
#define FSIZ
Definition: settings_arch.c:69
uint32_t page_nr
Definition: settings_arch.c:67
uint32_t addr
Definition: settings_arch.c:65
int32_t persistent_read(uint32_t ptr, uint32_t size)
#define FCHK
Definition: settings_arch.c:70
#define FLASH_BEGIN
Definition: settings_arch.c:68
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:73
unsigned char uint8_t
Definition: types.h:14
uint32_t page_size
Definition: settings_arch.c:68
uint32_t total_size
Definition: settings_arch.c:66
int32_t persistent_write(uint32_t ptr, uint32_t size)