Paparazzi UAS  v6.2.0_stable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 #if USE_HARD_FAULT_RECOVERY
43 
44 #if defined(STM32F4XX) || defined (STM32F7XX)
45 #define BCKP_SECTION ".ram5"
46 #define IN_BCKP_SECTION(var) var __attribute__ ((section(BCKP_SECTION), aligned(8)))
47 #else
48 #error "No backup ram available"
49 #endif
50 IN_BCKP_SECTION(volatile bool hard_fault);
51 
52 /*
53  * Set hard fault handlers to trigger a soft reset
54  * This will set a flag that can be tested at startup
55  */
56 
57 CH_IRQ_HANDLER(HardFault_Handler)
58 {
59  hard_fault = true;
61 }
62 
63 CH_IRQ_HANDLER(NMI_Handler)
64 {
65  hard_fault = true;
67 }
68 
69 CH_IRQ_HANDLER(MemManage_Handler)
70 {
71  hard_fault = true;
73 }
74 
75 CH_IRQ_HANDLER(BusFault_Handler)
76 {
77  hard_fault = true;
79 }
80 
81 CH_IRQ_HANDLER(UsageFault_Handler)
82 {
83  hard_fault = true;
85 }
86 
87 bool recovering_from_hard_fault;
88 
89 // select correct register
90 #if defined(STM32F4XX)
91 #define __PWR_CSR PWR->CSR
92 #define __PWR_CSR_BRE PWR_CSR_BRE
93 #define __PWR_CSR_BRR PWR_CSR_BRR
94 #elif defined(STM32F7XX)
95 #define __PWR_CSR PWR->CSR1
96 #define __PWR_CSR_BRE PWR_CSR1_BRE
97 #define __PWR_CSR_BRR PWR_CSR1_BRR
98 #else
99 #error Hard fault recovery not supported
100 #endif
101 
102 #endif /* USE_HARD_FAULT_RECOVERY */
103 
109  RTC_BOOT_HOLD = 0xb0070001,
110  RTC_BOOT_FAST = 0xb0070002,
111  RTC_BOOT_CANBL = 0xb0080000,
112  RTC_BOOT_FWOK = 0xb0093a26
113 };
114 
115 /* Local functions */
116 static void mcu_deep_sleep(void);
117 #if defined(USE_RTC_BACKUP)
118 static void mcu_set_rtcbackup(uint32_t val);
119 #endif
120 
124 void mcu_arch_init(void)
125 {
126  /*
127  * System initializations.
128  * - HAL initialization, this also initializes the configured device drivers
129  * and performs the board-specific initializations.
130  * - Kernel initialization, the main() function becomes a thread and the
131  * RTOS is active.
132  */
133  halInit();
134  chSysInit();
135 
136 #if USE_HARD_FAULT_RECOVERY
137  /* Backup domain SRAM enable, and with it, the regulator */
138 #if defined(STM32F4XX) || defined(STM32F7XX)
139  RCC->AHB1ENR |= RCC_AHB1ENR_BKPSRAMEN;
140  __PWR_CSR |= __PWR_CSR_BRE;
141  while ((__PWR_CSR & __PWR_CSR_BRR) == 0) ; /* Waits until the regulator is stable */
142 #endif /* STM32F4 | STM32F7 */
143 
144  // test if last reset was a 'real' hard fault
145  recovering_from_hard_fault = false;
146  if (!(RCC->CSR & RCC_CSR_SFTRSTF)) {
147  // not coming from soft reset
148  hard_fault = false;
149  } else if ((RCC->CSR & RCC_CSR_SFTRSTF) && !hard_fault) {
150  // this is a soft reset, probably from a debug probe, so let's start in normal mode
151  hard_fault = false;
152  } else {
153  // else real hard fault
154  recovering_from_hard_fault = true;
155  hard_fault = false;
156  }
157  // *MANDATORY* clear of rcc bits
158  RCC->CSR = RCC_CSR_RMVF;
159  // end of reset bit probing
160 #endif /* USE_HARD_FAULT_RECOVERY */
161 }
162 
171 void mcu_reboot(enum reboot_state_t reboot_state)
172 {
173  // Powering off/deep sleep instead
174  if(reboot_state == MCU_REBOOT_POWEROFF) {
175  mcu_deep_sleep();
176  return;
177  }
178 
179 #if defined(USE_RTC_BACKUP)
180  // Set the RTC backup register if possible
181  if(reboot_state == MCU_REBOOT_FAST)
182  mcu_set_rtcbackup(RTC_BOOT_FAST);
183  else if(reboot_state == MCU_REBOOT_BOOTLOADER)
184  mcu_set_rtcbackup(RTC_BOOT_HOLD);
185 #endif
186 
187  // Restart the MCU
188  NVIC_SystemReset();
189 }
190 
195 void mcu_energy_save(void)
196 {
197 #if defined(ENERGY_SAVE_INPUTS)
199  palSetLineMode(input_line, PAL_MODE_INPUT);
200  }
201 #endif
202 #if defined(ENERGY_SAVE_LOWS)
204  palClearLine(input_low);
205  }
206 #endif
207 }
208 
217 static void mcu_deep_sleep(void)
218 {
219 #if defined(STM32F4XX)
220  /* clear PDDS and LPDS bits */
221  PWR->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS);
222  /* set LPDS and clear */
223  PWR->CR |= (PWR_CR_LPDS | PWR_CR_CSBF | PWR_CR_CWUF);
224 #elif defined(STM32F7XX)
225  /* clear PDDS and LPDS bits */
226  PWR->CR1 &= ~(PWR_CR1_PDDS | PWR_CR1_LPDS);
227  /* set LPDS and clear */
228  PWR->CR1 |= (PWR_CR1_LPDS | PWR_CR1_CSBF);
229 #elif defined(STM32H7XX)
230  /* clear LPDS */
231  PWR->CR1 &= ~PWR_CR1_LPDS;
232  /* set LPDS */
233  PWR->CR1 |= PWR_CR1_LPDS;
234 #endif
235 
236  /* Setup the deepsleep mask */
237  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
238 
239  __disable_irq();
240 
241  __SEV();
242  __WFE();
243  __WFE();
244 
245  __enable_irq();
246 
247  /* clear the deepsleep mask */
248  SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
249 }
250 
251 #if defined(USE_RTC_BACKUP)
257 static void mcu_set_rtcbackup(uint32_t val) {
258 #if !defined(STM32F1)
259  if ((RCC->BDCR & RCC_BDCR_RTCEN) == 0) {
260  RCC->BDCR |= STM32_RTCSEL;
261  RCC->BDCR |= RCC_BDCR_RTCEN;
262  }
263 #ifdef PWR_CR_DBP
264  PWR->CR |= PWR_CR_DBP;
265 #else
266  PWR->CR1 |= PWR_CR1_DBP;
267 #endif
268 #endif
269 
270 #if defined(STM32F1)
271  volatile uint32_t *dr = (volatile uint32_t *)&BKP->DR1;
272  dr[0] = (val) & 0xFFFF;
273  dr[1] = (val) >> 16;
274 #elif defined(STM32G4)
275  ((volatile uint32_t *)&TAMP->BKP0R)[0] = val;
276 #else
277  ((volatile uint32_t *)&RTC->BKP0R)[0] = val;
278 #endif
279 }
280 #endif /* USE_RTC_BACKUP */
#define BOARD_GROUP_DECLFOREACH(line, group)
Definition: board.h:2051
#define STM32_RTCSEL
Definition: mcuconf.h:61
rtc_boot_magic
RTC backup register values.
Definition: mcu_arch.c:107
@ RTC_BOOT_FAST
No timeout in bootloader.
Definition: mcu_arch.c:110
@ RTC_BOOT_OFF
Normal boot.
Definition: mcu_arch.c:108
@ RTC_BOOT_CANBL
CAN bootloader, ORd with 8 bit local node ID.
Definition: mcu_arch.c:111
@ RTC_BOOT_HOLD
Hold in bootloader, do not boot application.
Definition: mcu_arch.c:109
@ RTC_BOOT_FWOK
indicates FW ran for 30s
Definition: mcu_arch.c:112
static void mcu_deep_sleep(void)
Put MCU into deep sleep mode.
Definition: mcu_arch.c:217
void mcu_arch_init(void)
Initialize the specific archittecture functions.
Definition: mcu_arch.c:124
#define ENERGY_SAVE_INPUTS
Definition: board.h:1652
#define ENERGY_SAVE_LOWS
Definition: board.h:1671
void mcu_reboot(enum reboot_state_t reboot_state)
Reboot the MCU.
Definition: mcu_arch.c:171
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:195
@ 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
Arch independent mcu ( Micro Controller Unit ) utilities.
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