Paparazzi UAS v7.1_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
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 */
35
36#include <string.h>
37
38/* ChibiOS includes */
39#include "ch.h"
40#include "hal.h"
41/* Paparazzi includes */
42#include "mcu.h"
43
44#include "mcu_periph/ram_arch.h"
45
46#if defined(STM32H7XX)
47typedef struct {
48 uint32_t *init_text_area;
49 uint32_t *init_area;
50 uint32_t *clear_area;
51 uint32_t *no_init_area;
52} ram_init_area_t;
53
54static void initRam0nc(void);
55static void init_ram_areas(const ram_init_area_t *rap);
56static void mpuConfigureNonCachedRam(void);
57#endif
58
59#if USE_HARD_FAULT_RECOVERY
60
61#if defined(STM32F4XX) || defined (STM32F7XX)
62#define BCKP_SECTION ".ram5"
63#define IN_BCKP_SECTION(var) var __attribute__ ((section(BCKP_SECTION), aligned(8)))
64#elif defined(STM32H7XX)
65#define BCKP_SECTION ".ram7"
66#define IN_BCKP_SECTION(var) var __attribute__ ((section(BCKP_SECTION), aligned(8)))
67#else
68#error "No backup ram available"
69#endif
70IN_BCKP_SECTION(volatile bool hard_fault);
71
72/*
73 * Set hard fault handlers to trigger a soft reset
74 * This will set a flag that can be tested at startup
75 */
76
77CH_IRQ_HANDLER(HardFault_Handler)
78{
79 hard_fault = true;
81}
82
83CH_IRQ_HANDLER(NMI_Handler)
84{
85 hard_fault = true;
87}
88
89CH_IRQ_HANDLER(MemManage_Handler)
90{
91 hard_fault = true;
93}
94
95CH_IRQ_HANDLER(BusFault_Handler)
96{
97 hard_fault = true;
99}
100
101CH_IRQ_HANDLER(UsageFault_Handler)
102{
103 hard_fault = true;
105}
106
107bool recovering_from_hard_fault;
108
109// select correct register
110#if defined(STM32F4XX)
111#define __PWR_BACKUP_REG PWR->CSR
112#define __PWR_BACKUP_ENABLE PWR_CSR_BRE
113#define __PWR_BACKUP_READY PWR_CSR_BRR
114#define __RCC_RESET_REGISTER RCC->CSR
115#define __RCC_RESET_FLAG RCC_CSR_SFTRSTF
116#define __RCC_RESET_REMOVE_FLAG RCC_CSR_RMVF
117#elif defined(STM32F7XX)
118#define __PWR_BACKUP_REG PWR->CSR1
119#define __PWR_BACKUP_ENABLE PWR_CSR1_BRE
120#define __PWR_BACKUP_READY PWR_CSR1_BRR
121#define __RCC_RESET_REGISTER RCC->CSR
122#define __RCC_RESET_FLAG RCC_CSR_SFTRSTF
123#define __RCC_RESET_REMOVE_FLAG RCC_CSR_RMVF
124#elif defined(STM32H7XX)
125#define __PWR_BACKUP_REG PWR->CR2
126#define __PWR_BACKUP_ENABLE PWR_CR2_BREN
127#define __PWR_BACKUP_READY PWR_CR2_BRRDY
128#define __RCC_RESET_REGISTER RCC->RSR
129#define __RCC_RESET_FLAG RCC_RSR_SFTRSTF
130#define __RCC_RESET_REMOVE_FLAG RCC_RSR_RMVF
131#else
132#error Hard fault recovery not supported
133#endif
134
135#endif /* USE_HARD_FAULT_RECOVERY */
136
142 RTC_BOOT_HOLD = 0xb0070001,
143 RTC_BOOT_FAST = 0xb0070002,
144 RTC_BOOT_CANBL = 0xb0080000,
145 RTC_BOOT_FWOK = 0xb0093a26
146};
147
148/* Local functions */
149static void mcu_deep_sleep(void);
150#if defined(USE_RTC_BACKUP)
151static void mcu_set_rtcbackup(uint32_t val);
152#endif
153
158{
159 /*
160 * System initializations.
161 * - HAL initialization, this also initializes the configured device drivers
162 * and performs the board-specific initializations.
163 * - Kernel initialization, the main() function becomes a thread and the
164 * RTOS is active.
165 */
166 halInit();
167 chSysInit();
168
169#if defined(STM32H7XX)
170 mpuConfigureNonCachedRam();
171#endif
172
173#if USE_HARD_FAULT_RECOVERY
174 /* Backup domain SRAM enable, and with it, the regulator */
175#if defined(STM32F4XX) || defined(STM32F7XX)
176 RCC->AHB1ENR |= RCC_AHB1ENR_BKPSRAMEN;
177 __PWR_BACKUP_REG |= __PWR_BACKUP_ENABLE;
178 while ((__PWR_BACKUP_REG & __PWR_BACKUP_READY) == 0) ; /* Waits until the regulator is stable */
179#endif /* STM32F4 | STM32F7 */
180
181 // test if last reset was a 'real' hard fault
182 recovering_from_hard_fault = false;
183 if (!(__RCC_RESET_REGISTER & __RCC_RESET_FLAG)) {
184 // not coming from soft reset
185 hard_fault = false;
186 } else if ((__RCC_RESET_REGISTER & __RCC_RESET_FLAG) && !hard_fault) {
187 // this is a soft reset, probably from a debug probe, so let's start in normal mode
188 hard_fault = false;
189 } else {
190 // else real hard fault
191 recovering_from_hard_fault = true;
192 hard_fault = false;
193 }
194 // *MANDATORY* clear of rcc bits
195 __RCC_RESET_REGISTER |= __RCC_RESET_REMOVE_FLAG;
196 // end of reset bit probing
197#endif /* USE_HARD_FAULT_RECOVERY */
198}
199
208void mcu_reboot(enum reboot_state_t reboot_state)
209{
210 // Powering off/deep sleep instead
211 if(reboot_state == MCU_REBOOT_POWEROFF) {
213 return;
214 }
215
216#if defined(USE_RTC_BACKUP)
217 // Set the RTC backup register if possible
218 if(reboot_state == MCU_REBOOT_FAST)
219 mcu_set_rtcbackup(RTC_BOOT_FAST);
220 else if(reboot_state == MCU_REBOOT_BOOTLOADER)
221 mcu_set_rtcbackup(RTC_BOOT_HOLD);
222#endif
223
224 // Restart the MCU
225 NVIC_SystemReset();
226}
227
233{
234#if defined(ENERGY_SAVE_INPUTS)
236 palSetLineMode(input_line, PAL_MODE_INPUT);
237 }
238#endif
239#if defined(ENERGY_SAVE_LOWS)
241 palClearLine(input_low);
242 }
243#endif
244}
245
253{
254#if defined(UID_BASE)
255 uint8_t len = Min(max_len, 12);
256 memcpy(uid, (const uint8_t *)UID_BASE, len);
257 return len;
258#else
259 (void)uid;
260 (void)max_len;
261 return 0;
262#endif
263}
264
273static void mcu_deep_sleep(void)
274{
275#if defined(STM32F4XX)
276 /* clear PDDS and LPDS bits */
277 PWR->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS);
278 /* set LPDS and clear */
279 PWR->CR |= (PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF);
280#elif defined(STM32F7XX)
281 /* clear PDDS and LPDS bits */
282 PWR->CR1 &= ~(PWR_CR1_PDDS | PWR_CR1_LPDS);
283 /* set LPDS and clear */
284 PWR->CR1 |= (PWR_CR1_LPDS | PWR_CR1_CSBF);
285#elif defined(STM32H7XX)
286 /* clear LPDS */
287 PWR->CR1 &= ~PWR_CR1_LPDS;
288 /* set LPDS */
289 PWR->CR1 |= PWR_CR1_LPDS;
290#endif
291
292 /* Setup the deepsleep mask */
293 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
294
295 __disable_irq();
296
297 __SEV();
298 __WFE();
299 __WFE();
300
301 __enable_irq();
302
303 /* clear the deepsleep mask */
304 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
305}
306
307#if defined(USE_RTC_BACKUP)
313static void mcu_set_rtcbackup(uint32_t val) {
314#if !defined(STM32F1)
315 if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) {
316 RCC->BDCR |= STM32_RTCSEL;
317 RCC->BDCR |= RCC_BDCR_RTCEN;
318 }
319#ifdef PWR_CR_DBP
320 PWR->CR |= PWR_CR_DBP;
321#else
322 PWR->CR1 |= PWR_CR1_DBP;
323#endif
324#endif
325
326#if defined(STM32F1)
327 volatile uint32_t *dr = (volatile uint32_t *)&BKP->DR1;
328 dr[0] = (val) & 0xFFFF;
329 dr[1] = (val) >> 16;
330#elif defined(STM32G4)
331 ((volatile uint32_t *)&TAMP->BKP0R)[0] = val;
332#else
333 ((volatile uint32_t *)&RTC->BKP0R)[0] = val;
334#endif
335}
336#endif /* USE_RTC_BACKUP */
337
338
339
340#if defined(STM32H7XX)
341/*
342 nocache regions are
343 ° ram0nc for sdmmc1
344 ° ram3 for miscellanous ?
345 ° ram4 for bdma attached peripherals (i2c4, spi6, adc3)
346 */
347
348extern const uint32_t __ram0nc_base__;
349extern const uint32_t __ram0nc_size__;
350extern const uint32_t __ram3_base__;
351extern const uint32_t __ram3_size__;
352extern const uint32_t __ram4_base__;
353extern const uint32_t __ram4_size__;
354
355static uint32_t getMPU_RASR_SIZE(const uint32_t ldSize)
356{
357 // 2^n -> n-1
358 chDbgAssert(__builtin_popcount(ldSize) == 1U, "MPU region size must be 2^n");
359 chDbgAssert(ldSize >= 32U, "MPU region size must be >= 32");
360 return MPU_RASR_SIZE(__builtin_ctz(ldSize) - 1U);
361}
362
363
364static void mpuConfigureNonCachedRam(void)
365{
366 const uint32_t mpuSharedOption = MPU_RASR_ATTR_AP_RW_RW |
367 MPU_RASR_ATTR_NON_CACHEABLE | MPU_RASR_ATTR_S |
368 MPU_RASR_ENABLE;
369
370 const uint32_t ram0nc_base = (uint32_t) &__ram0nc_base__;
371 const uint32_t ram3_base = (uint32_t) &__ram3_base__;
372 const uint32_t ram4_base = (uint32_t) &__ram4_base__;
373
374 const uint32_t ram0nc_size = (uint32_t) &__ram0nc_size__;
375 const uint32_t ram3_size = (uint32_t) &__ram3_size__;
376 const uint32_t ram4_size = (uint32_t) &__ram4_size__;
377
378 chDbgAssert(ram0nc_base == 0x24000000, "MPU ram0nc addr mismatch");
379 chDbgAssert(ram3_base == 0x30040000, "MPU ram3 addr mismatch");
380 chDbgAssert(ram4_base == 0x38000000, "MPU ram4 addr mismatch");
381
382 chDbgAssert((ram0nc_base % ram0nc_size) == 0, "MPU ram0nc base addr must be size aligned");
383 chDbgAssert(ram0nc_size == 128 * 1024, "MPU ram0nc size must be 128K");
384 chDbgAssert((ram3_base % ram3_size) == 0, "MPU ram3 base addr must be size aligned");
385 chDbgAssert((ram4_base % ram4_size) == 0, "MPU ram4 base addr must be size aligned");
386 chDbgAssert(getMPU_RASR_SIZE(ram0nc_size) == MPU_RASR_SIZE_128K, "getMPU_RASR_SIZE error");
387
388
389 mpuConfigureRegion(MPU_REGION_6,
390 ram0nc_base,
391 getMPU_RASR_SIZE(ram0nc_size) | mpuSharedOption
392 );
393 mpuConfigureRegion(MPU_REGION_5,
394 ram3_base,
395 getMPU_RASR_SIZE(ram3_size) | mpuSharedOption
396 );
397 mpuConfigureRegion(MPU_REGION_4,
398 ram4_base,
399 getMPU_RASR_SIZE(ram4_size) | mpuSharedOption
400 );
401 initRam0nc();
402 mpuEnable(MPU_CTRL_PRIVDEFENA);
403 __ISB();
404 __DSB();
405 SCB_CleanInvalidateDCache();
406
407}
408
409static void initRam0nc(void)
410{
411 extern uint32_t __ram0nc_init_text__, __ram0nc_init__, __ram0nc_clear__, __ram0nc_noinit__;
412 static const ram_init_area_t ram_areas[1] = {
413 {&__ram0nc_init_text__, &__ram0nc_init__, &__ram0nc_clear__, &__ram0nc_noinit__},
414 };
415 init_ram_areas(ram_areas);
416
417}
418
419static void init_ram_areas(const ram_init_area_t *rap)
420{
421 uint32_t *tp = rap->init_text_area;
422 uint32_t *p = rap->init_area;
423
424 /* Copying initialization data.*/
425 while (p < rap->clear_area) {
426 *p = *tp;
427 p++;
428 tp++;
429 }
430
431 /* Zeroing clear area.*/
432 while (p < rap->no_init_area) {
433 *p = 0;
434 p++;
435 }
436}
437
438#endif
#define BOARD_GROUP_DECLFOREACH(line, group)
Definition board.h:2063
rtc_boot_magic
RTC backup register values.
Definition mcu_arch.c:140
@ RTC_BOOT_FAST
No timeout in bootloader.
Definition mcu_arch.c:143
@ RTC_BOOT_OFF
Normal boot.
Definition mcu_arch.c:141
@ RTC_BOOT_CANBL
CAN bootloader, ORd with 8 bit local node ID.
Definition mcu_arch.c:144
@ RTC_BOOT_HOLD
Hold in bootloader, do not boot application.
Definition mcu_arch.c:142
@ RTC_BOOT_FWOK
indicates FW ran for 30s
Definition mcu_arch.c:145
static void mcu_deep_sleep(void)
Put MCU into deep sleep mode.
Definition mcu_arch.c:273
void mcu_arch_init(void)
Initialize the specific archittecture functions.
Definition mcu_arch.c:157
#define ENERGY_SAVE_INPUTS
Definition board.h:1706
#define ENERGY_SAVE_LOWS
Definition board.h:1699
#define Min(x, y)
Definition esc_dshot.c:110
void mcu_reboot(enum reboot_state_t reboot_state)
Reboot the MCU.
Definition mcu_arch.c:208
reboot_state_t
The requested reboot states.
Definition mcu.h:43
void mcu_energy_save(void)
Save energy for performing operations on shutdown Used for example to shutdown SD-card logging.
Definition mcu_arch.c:232
uint8_t mcu_get_uid(uint8_t *uid, uint8_t max_len)
Get the 96-bit unique device ID of the STM32.
Definition mcu_arch.c:252
@ MCU_REBOOT_BOOTLOADER
Go to bootloader.
Definition mcu.h:47
@ MCU_REBOOT_POWEROFF
Poweroff the device.
Definition mcu.h:45
@ MCU_REBOOT_FAST
Fast reboot (skip bootloader).
Definition mcu.h:46
static float p[2][2]
Arch independent mcu ( Micro Controller Unit ) utilities.
#define STM32_RTCSEL
Definition mcuconf_h7.h:176
Specific RAM section for DMA usage on F7.
uint16_t val[TCOUPLE_NB]
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.