Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
mcu_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 AggieAir, A Remote Sensing Unmanned Aerial System for Scientific Applications
3  * Utah State University, http://aggieair.usu.edu/
4  *
5  * Michal Podhradsky (michal.podhradsky@aggiemail.usu.edu)
6  * Calvin Coopmans (c.r.coopmans@ieee.org)
7  *
8  * 2016 Gautier Hattenberger <gautier.hattenberger@enac.fr>
9  * 2016 Alexandre Bustico <alexandre.bustico@enac.fr>
10  *
11  * This file is part of paparazzi.
12  *
13  * paparazzi is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2, or (at your option)
16  * any later version.
17  *
18  * paparazzi is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with paparazzi; see the file COPYING. If not, write to
25  * the Free Software Foundation, 59 Temple Place - Suite 330,
26  * Boston, MA 02111-1307, USA.
27  */
36 /* ChibiOS includes */
37 #include "ch.h"
38 #include "hal.h"
39 /* Paparazzi includes */
40 #include "mcu.h"
41 
42 #include "mcu_periph/ram_arch.h"
43 
44 #if defined(STM32H7XX)
45 typedef struct {
46  uint32_t *init_text_area;
47  uint32_t *init_area;
48  uint32_t *clear_area;
49  uint32_t *no_init_area;
50 } ram_init_area_t;
51 
52 static void initRam0nc(void);
53 static void init_ram_areas(const ram_init_area_t *rap);
54 static void mpuConfigureNonCachedRam(void);
55 #endif
56 
57 #if USE_HARD_FAULT_RECOVERY
58 
59 #if defined(STM32F4XX) || defined (STM32F7XX)
60 #define BCKP_SECTION ".ram5"
61 #define IN_BCKP_SECTION(var) var __attribute__ ((section(BCKP_SECTION), aligned(8)))
62 #elif defined(STM32H7XX)
63 #define BCKP_SECTION ".ram7"
64 #define IN_BCKP_SECTION(var) var __attribute__ ((section(BCKP_SECTION), aligned(8)))
65 #else
66 #error "No backup ram available"
67 #endif
68 IN_BCKP_SECTION(volatile bool hard_fault);
69 
70 /*
71  * Set hard fault handlers to trigger a soft reset
72  * This will set a flag that can be tested at startup
73  */
74 
75 CH_IRQ_HANDLER(HardFault_Handler)
76 {
77  hard_fault = true;
79 }
80 
81 CH_IRQ_HANDLER(NMI_Handler)
82 {
83  hard_fault = true;
85 }
86 
87 CH_IRQ_HANDLER(MemManage_Handler)
88 {
89  hard_fault = true;
91 }
92 
93 CH_IRQ_HANDLER(BusFault_Handler)
94 {
95  hard_fault = true;
97 }
98 
99 CH_IRQ_HANDLER(UsageFault_Handler)
100 {
101  hard_fault = true;
103 }
104 
105 bool recovering_from_hard_fault;
106 
107 // select correct register
108 #if defined(STM32F4XX)
109 #define __PWR_BACKUP_REG PWR->CSR
110 #define __PWR_BACKUP_ENABLE PWR_CSR_BRE
111 #define __PWR_BACKUP_READY PWR_CSR_BRR
112 #define __RCC_RESET_REGISTER RCC->CSR
113 #define __RCC_RESET_FLAG RCC_CSR_SFTRSTF
114 #define __RCC_RESET_REMOVE_FLAG RCC_CSR_RMVF
115 #elif defined(STM32F7XX)
116 #define __PWR_BACKUP_REG PWR->CSR1
117 #define __PWR_BACKUP_ENABLE PWR_CSR1_BRE
118 #define __PWR_BACKUP_READY PWR_CSR1_BRR
119 #define __RCC_RESET_REGISTER RCC->CSR
120 #define __RCC_RESET_FLAG RCC_CSR_SFTRSTF
121 #define __RCC_RESET_REMOVE_FLAG RCC_CSR_RMVF
122 #elif defined(STM32H7XX)
123 #define __PWR_BACKUP_REG PWR->CR2
124 #define __PWR_BACKUP_ENABLE PWR_CR2_BREN
125 #define __PWR_BACKUP_READY PWR_CR2_BRRDY
126 #define __RCC_RESET_REGISTER RCC->RSR
127 #define __RCC_RESET_FLAG RCC_RSR_SFTRSTF
128 #define __RCC_RESET_REMOVE_FLAG RCC_RSR_RMVF
129 #else
130 #error Hard fault recovery not supported
131 #endif
132 
133 #endif /* USE_HARD_FAULT_RECOVERY */
134 
140  RTC_BOOT_HOLD = 0xb0070001,
141  RTC_BOOT_FAST = 0xb0070002,
142  RTC_BOOT_CANBL = 0xb0080000,
143  RTC_BOOT_FWOK = 0xb0093a26
144 };
145 
146 /* Local functions */
147 static void mcu_deep_sleep(void);
148 #if defined(USE_RTC_BACKUP)
149 static void mcu_set_rtcbackup(uint32_t val);
150 #endif
151 
155 void mcu_arch_init(void)
156 {
157  /*
158  * System initializations.
159  * - HAL initialization, this also initializes the configured device drivers
160  * and performs the board-specific initializations.
161  * - Kernel initialization, the main() function becomes a thread and the
162  * RTOS is active.
163  */
164  halInit();
165  chSysInit();
166 
167 #if defined(STM32H7XX)
168  mpuConfigureNonCachedRam();
169 #endif
170 
171 #if USE_HARD_FAULT_RECOVERY
172  /* Backup domain SRAM enable, and with it, the regulator */
173 #if defined(STM32F4XX) || defined(STM32F7XX)
174  RCC->AHB1ENR |= RCC_AHB1ENR_BKPSRAMEN;
175  __PWR_BACKUP_REG |= __PWR_BACKUP_ENABLE;
176  while ((__PWR_BACKUP_REG & __PWR_BACKUP_READY) == 0) ; /* Waits until the regulator is stable */
177 #endif /* STM32F4 | STM32F7 */
178 
179  // test if last reset was a 'real' hard fault
180  recovering_from_hard_fault = false;
181  if (!(__RCC_RESET_REGISTER & __RCC_RESET_FLAG)) {
182  // not coming from soft reset
183  hard_fault = false;
184  } else if ((__RCC_RESET_REGISTER & __RCC_RESET_FLAG) && !hard_fault) {
185  // this is a soft reset, probably from a debug probe, so let's start in normal mode
186  hard_fault = false;
187  } else {
188  // else real hard fault
189  recovering_from_hard_fault = true;
190  hard_fault = false;
191  }
192  // *MANDATORY* clear of rcc bits
193  __RCC_RESET_REGISTER = __RCC_RESET_REMOVE_FLAG;
194  // end of reset bit probing
195 #endif /* USE_HARD_FAULT_RECOVERY */
196 }
197 
206 void mcu_reboot(enum reboot_state_t reboot_state)
207 {
208  // Powering off/deep sleep instead
209  if(reboot_state == MCU_REBOOT_POWEROFF) {
210  mcu_deep_sleep();
211  return;
212  }
213 
214 #if defined(USE_RTC_BACKUP)
215  // Set the RTC backup register if possible
216  if(reboot_state == MCU_REBOOT_FAST)
217  mcu_set_rtcbackup(RTC_BOOT_FAST);
218  else if(reboot_state == MCU_REBOOT_BOOTLOADER)
219  mcu_set_rtcbackup(RTC_BOOT_HOLD);
220 #endif
221 
222  // Restart the MCU
223  NVIC_SystemReset();
224 }
225 
230 void mcu_energy_save(void)
231 {
232 #if defined(ENERGY_SAVE_INPUTS)
234  palSetLineMode(input_line, PAL_MODE_INPUT);
235  }
236 #endif
237 #if defined(ENERGY_SAVE_LOWS)
239  palClearLine(input_low);
240  }
241 #endif
242 }
243 
252 static void mcu_deep_sleep(void)
253 {
254 #if defined(STM32F4XX)
255  /* clear PDDS and LPDS bits */
256  PWR->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS);
257  /* set LPDS and clear */
258  PWR->CR |= (PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF);
259 #elif defined(STM32F7XX)
260  /* clear PDDS and LPDS bits */
261  PWR->CR1 &= ~(PWR_CR1_PDDS | PWR_CR1_LPDS);
262  /* set LPDS and clear */
263  PWR->CR1 |= (PWR_CR1_LPDS | PWR_CR1_CSBF);
264 #elif defined(STM32H7XX)
265  /* clear LPDS */
266  PWR->CR1 &= ~PWR_CR1_LPDS;
267  /* set LPDS */
268  PWR->CR1 |= PWR_CR1_LPDS;
269 #endif
270 
271  /* Setup the deepsleep mask */
272  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
273 
274  __disable_irq();
275 
276  __SEV();
277  __WFE();
278  __WFE();
279 
280  __enable_irq();
281 
282  /* clear the deepsleep mask */
283  SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
284 }
285 
286 #if defined(USE_RTC_BACKUP)
292 static void mcu_set_rtcbackup(uint32_t val) {
293 #if !defined(STM32F1)
294  if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) {
295  RCC->BDCR |= STM32_RTCSEL;
296  RCC->BDCR |= RCC_BDCR_RTCEN;
297  }
298 #ifdef PWR_CR_DBP
299  PWR->CR |= PWR_CR_DBP;
300 #else
301  PWR->CR1 |= PWR_CR1_DBP;
302 #endif
303 #endif
304 
305 #if defined(STM32F1)
306  volatile uint32_t *dr = (volatile uint32_t *)&BKP->DR1;
307  dr[0] = (val) & 0xFFFF;
308  dr[1] = (val) >> 16;
309 #elif defined(STM32G4)
310  ((volatile uint32_t *)&TAMP->BKP0R)[0] = val;
311 #else
312  ((volatile uint32_t *)&RTC->BKP0R)[0] = val;
313 #endif
314 }
315 #endif /* USE_RTC_BACKUP */
316 
317 
318 
319 #if defined(STM32H7XX)
320 /*
321  nocache regions are
322  ° ram0nc for sdmmc1
323  ° ram3 for miscellanous ?
324  ° ram4 for bdma attached peripherals (i2c4, spi6, adc3)
325  */
326 
327 extern const uint32_t __ram0nc_base__;
328 extern const uint32_t __ram0nc_size__;
329 extern const uint32_t __ram3_base__;
330 extern const uint32_t __ram3_size__;
331 extern const uint32_t __ram4_base__;
332 extern const uint32_t __ram4_size__;
333 
334 static uint32_t getMPU_RASR_SIZE(const uint32_t ldSize)
335 {
336  // 2^n -> n-1
337  chDbgAssert(__builtin_popcount(ldSize) == 1U, "MPU region size must be 2^n");
338  chDbgAssert(ldSize >= 32U, "MPU region size must be >= 32");
339  return MPU_RASR_SIZE(__builtin_ctz(ldSize) - 1U);
340 }
341 
342 
343 static void mpuConfigureNonCachedRam(void)
344 {
345  const uint32_t mpuSharedOption = MPU_RASR_ATTR_AP_RW_RW |
346  MPU_RASR_ATTR_NON_CACHEABLE | MPU_RASR_ATTR_S |
347  MPU_RASR_ENABLE;
348 
349  const uint32_t ram0nc_base = (uint32_t) &__ram0nc_base__;
350  const uint32_t ram3_base = (uint32_t) &__ram3_base__;
351  const uint32_t ram4_base = (uint32_t) &__ram4_base__;
352 
353  const uint32_t ram0nc_size = (uint32_t) &__ram0nc_size__;
354  const uint32_t ram3_size = (uint32_t) &__ram3_size__;
355  const uint32_t ram4_size = (uint32_t) &__ram4_size__;
356 
357  chDbgAssert(ram0nc_base == 0x24000000, "MPU ram0nc addr mismatch");
358  chDbgAssert(ram3_base == 0x30040000, "MPU ram3 addr mismatch");
359  chDbgAssert(ram4_base == 0x38000000, "MPU ram4 addr mismatch");
360 
361  chDbgAssert((ram0nc_base % ram0nc_size) == 0, "MPU ram0nc base addr must be size aligned");
362  chDbgAssert(ram0nc_size == 128 * 1024, "MPU ram0nc size must be 128K");
363  chDbgAssert((ram3_base % ram3_size) == 0, "MPU ram3 base addr must be size aligned");
364  chDbgAssert((ram4_base % ram4_size) == 0, "MPU ram4 base addr must be size aligned");
365  chDbgAssert(getMPU_RASR_SIZE(ram0nc_size) == MPU_RASR_SIZE_128K, "getMPU_RASR_SIZE error");
366 
367 
368  mpuConfigureRegion(MPU_REGION_6,
369  ram0nc_base,
370  getMPU_RASR_SIZE(ram0nc_size) | mpuSharedOption
371  );
372  mpuConfigureRegion(MPU_REGION_5,
373  ram3_base,
374  getMPU_RASR_SIZE(ram3_size) | mpuSharedOption
375  );
376  mpuConfigureRegion(MPU_REGION_4,
377  ram4_base,
378  getMPU_RASR_SIZE(ram4_size) | mpuSharedOption
379  );
380  initRam0nc();
381  mpuEnable(MPU_CTRL_PRIVDEFENA);
382  __ISB();
383  __DSB();
384  SCB_CleanInvalidateDCache();
385 
386 }
387 
388 static void initRam0nc(void)
389 {
390  extern uint32_t __ram0nc_init_text__, __ram0nc_init__, __ram0nc_clear__, __ram0nc_noinit__;
391  static const ram_init_area_t ram_areas[1] = {
392  {&__ram0nc_init_text__, &__ram0nc_init__, &__ram0nc_clear__, &__ram0nc_noinit__},
393  };
394  init_ram_areas(ram_areas);
395 
396 }
397 
398 static void init_ram_areas(const ram_init_area_t *rap)
399 {
400  uint32_t *tp = rap->init_text_area;
401  uint32_t *p = rap->init_area;
402 
403  /* Copying initialization data.*/
404  while (p < rap->clear_area) {
405  *p = *tp;
406  p++;
407  tp++;
408  }
409 
410  /* Zeroing clear area.*/
411  while (p < rap->no_init_area) {
412  *p = 0;
413  p++;
414  }
415 }
416 
417 #endif
#define BOARD_GROUP_DECLFOREACH(line, group)
Definition: board.h:2063
#define STM32_RTCSEL
Definition: mcuconf.h:61
rtc_boot_magic
RTC backup register values.
Definition: mcu_arch.c:138
@ RTC_BOOT_FAST
No timeout in bootloader.
Definition: mcu_arch.c:141
@ RTC_BOOT_OFF
Normal boot.
Definition: mcu_arch.c:139
@ RTC_BOOT_CANBL
CAN bootloader, ORd with 8 bit local node ID.
Definition: mcu_arch.c:142
@ RTC_BOOT_HOLD
Hold in bootloader, do not boot application.
Definition: mcu_arch.c:140
@ RTC_BOOT_FWOK
indicates FW ran for 30s
Definition: mcu_arch.c:143
static void mcu_deep_sleep(void)
Put MCU into deep sleep mode.
Definition: mcu_arch.c:252
void mcu_arch_init(void)
Initialize the specific archittecture functions.
Definition: mcu_arch.c:155
#define ENERGY_SAVE_INPUTS
Definition: board.h:1677
#define ENERGY_SAVE_LOWS
Definition: board.h:1670
void mcu_reboot(enum reboot_state_t reboot_state)
Reboot the MCU.
Definition: mcu_arch.c:206
reboot_state_t
The requested reboot states.
Definition: mcu.h:42
void mcu_energy_save(void)
Save energy for performing operations on shutdown Used for example to shutdown SD-card logging.
Definition: mcu_arch.c:230
@ MCU_REBOOT_BOOTLOADER
Go to bootloader.
Definition: mcu.h:46
@ MCU_REBOOT_POWEROFF
Poweroff the device.
Definition: mcu.h:44
@ MCU_REBOOT_FAST
Fast reboot (skip bootloader)
Definition: mcu.h:45
static float p[2][2]
Arch independent mcu ( Micro Controller Unit ) utilities.
Specific RAM section for DMA usage on F7.
static void __enable_irq(void)
Definition: i2c_arch.c:67
static void __disable_irq(void)
Definition: i2c_arch.c:66
uint16_t val[TCOUPLE_NB]
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78