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