rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
stm32_common.cpp
Go to the documentation of this file.
1/**
2 * @file stm32_common.cpp
3 * @brief Low level common STM32 code
4 *
5 * @date Mar 28, 2019
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 */
8
9#include "pch.h"
10
11#include <rusefi/expected.h>
12#include "hardware.h"
13#include "os_util.h"
14
15#ifdef STM32F4XX
16#include "stm32f4xx_hal_flash.h"
17#elif defined(STM32F7XX)
18#include "stm32f7xx_hal_flash.h"
19#elif defined(STM32H7XX)
20#include "stm32h7xx_hal_flash.h"
21#endif
22
23#if EFI_USE_OPENBLT
24/* communication with OpenBLT that is plain C, not to modify external file */
25extern "C" {
27};
28#endif
29
30#if EFI_PROD_CODE
31#include "mpu_util.h"
32#include "backup_ram.h"
33
34#ifndef ALLOW_JUMP_WITH_IGNITION_VOLTAGE
35// stm32 bootloader might touch uart ports which we cannot allow on boards where uart pins are used to control engine coils etc
36#define ALLOW_JUMP_WITH_IGNITION_VOLTAGE TRUE
37#endif
38
39static void reset_and_jump(void) {
40#if !ALLOW_JUMP_WITH_IGNITION_VOLTAGE
41 if (isIgnVoltage()) {
42 criticalError("Not allowed with ignition power");
43 return;
44 }
45#endif
46
47 #ifdef STM32H7XX
48 // H7 needs a forcible reset of the USB peripheral(s) in order for the bootloader to work properly.
49 // If you don't do this, the bootloader will execute, but USB doesn't work (nobody knows why)
50 // See https://community.st.com/s/question/0D53W00000vQEWsSAO/stm32h743-dfu-entry-doesnt-work-unless-boot0-held-high-at-poweron
51 RCC->AHB1ENR &= ~(RCC_AHB1ENR_USB1OTGHSEN | RCC_AHB1ENR_USB2OTGFSEN);
52 #endif
53
54 // and now reboot
55 NVIC_SystemReset();
56}
57
58#if EFI_DFU_JUMP
60 // leave DFU breadcrumb which assembly startup code would check, see [rusefi][DFU] section in assembly code
61
62 *((unsigned long *)0x2001FFF0) = 0xDEADBEEF; // End of RAM
63
65}
66#endif
67
69#if EFI_USE_OPENBLT
70 /* safe to call on already inited shares area */
72 /* Store sing to stay in OpenBLT */
74
76#endif
77}
78#endif /* EFI_PROD_CODE */
79
80#if EFI_PROD_CODE
81
83 FLASH_OBProgramInitTypeDef FLASH_Handle;
84
85 /* Read option bytes */
86 HAL_FLASHEx_OBGetConfig(&FLASH_Handle);
87
88 /* Return BOR value */
89 return (BOR_Level_t) FLASH_Handle.BORLevel;
90}
91
93 if (BOR_Get() == BORValue) {
94 return BOR_Result_Ok;
95 }
96
97
98 FLASH_OBProgramInitTypeDef FLASH_Handle;
99
100 FLASH_Handle.BORLevel = (uint32_t)BORValue;
101 FLASH_Handle.OptionType = OPTIONBYTE_BOR;
102
104
105 HAL_FLASHEx_OBProgram(&FLASH_Handle);
106
107 HAL_StatusTypeDef status = HAL_FLASH_OB_Launch();
108
110
111 if (status != HAL_OK) {
112 return BOR_Result_Error;
113 }
114
115 return BOR_Result_Ok;
116}
117
118void startWatchdog(int timeoutMs) {
119#if HAL_USE_WDG
120 // RL is a 12-bit value so we use a "2 ms" prescaler to support long timeouts (> 4.095 sec)
121 static WDGConfig wdgcfg;
122 wdgcfg.pr = STM32_IWDG_PR_64; // t = (1/32768) * 64 = ~2 ms
123 wdgcfg.rlr = STM32_IWDG_RL((uint32_t)((32.768f / 64.0f) * timeoutMs));
124#if STM32_IWDG_IS_WINDOWED
125 wdgcfg.winr = 0xfff; // don't use window
126#endif
127
128#ifndef __OPTIMIZE__ // gcc-specific built-in define
129 // if no optimizations, then it's most likely a debug version,
130 // and we need to enable a special watchdog feature to allow debugging
131 efiPrintf("Enabling 'debug freeze' watchdog feature...");
132#ifdef STM32H7XX
133 DBGMCU->APB4FZ1 |= DBGMCU_APB4FZ1_DBG_IWDG1;
134#else // F4 & F7
135 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_IWDG_STOP;
136#endif // STM32H7XX
137#endif // __OPTIMIZE__
138
139 static bool isStarted = false;
140 if (!isStarted) {
141 efiPrintf("Starting watchdog with timeout %d ms...", timeoutMs);
142 wdgStart(&WDGD1, &wdgcfg);
143 isStarted = true;
144 } else {
145 efiPrintf("Changing watchdog timeout to %d ms...", timeoutMs);
146 // wdgStart() uses kernel lock, thus we cannot call it here from locked or ISR code
147 wdg_lld_start(&WDGD1);
148 }
149#endif // HAL_USE_WDG
150}
151
153// Reset watchod reset counted in SharedParams after this delay
155
156void setWatchdogResetPeriod(int resetMs) {
157#if 0
158 efiPrintf("[dev] wd %d", resetMs);
159#endif
161}
162
164#if HAL_USE_WDG
165 static Timer lastTimeWasReset;
166 static efitimems_t wdUptime = 0;
167 // check if it's time to reset the watchdog
168 if (lastTimeWasReset.hasElapsedMs(watchdogResetPeriodMs)) {
169 // we assume tryResetWatchdog() is called from a timer callback
170 wdgResetI(&WDGD1);
171 lastTimeWasReset.reset();
172 // with 100 ms WD
173 if (wdUptime < watchdogCounterResetDelay) {
174 wdUptime += watchdogResetPeriodMs;
175 // we just crossed the treshold
176 if (wdUptime >= watchdogCounterResetDelay) {
177#if EFI_USE_OPENBLT
179#endif
180 }
181 }
182 }
183#endif // HAL_USE_WDG
184}
185
186uint32_t getMcuSerial() {
187 uint32_t *uid = ((uint32_t *)UID_BASE);
188 return uid[0] + uid[1] + uid[2];
189}
190
192 // looks like this holds a random value on start? Let's set a nice clean zero
193 DWT->CYCCNT = 0;
194
195 BOR_Set(BOR_Level_1); // one step above default value
196#ifndef EFI_BOOTLOADER
198#endif // EFI_BOOTLOADER
199}
200
201extern uint32_t __main_stack_base__;
202
203typedef struct port_intctx intctx_t;
204
205int getRemainingStack(thread_t *otp) {
206#if CH_DBG_ENABLE_STACK_CHECK
207 // this would dismiss coverity warning - see http://rusefi.com/forum/viewtopic.php?f=5&t=655
208 // coverity[uninit_use]
209 register intctx_t *r13 asm ("r13");
210 otp->activeStack = r13;
211
212 int remainingStack;
213 if (ch0.dbg.isr_cnt > 0) {
214 // ISR context
215 remainingStack = (int)(r13 - 1) - (int)&__main_stack_base__;
216 } else {
217 remainingStack = (int)(r13 - 1) - (int)otp->wabase;
218 }
219 otp->remainingStack = remainingStack;
220 return remainingStack;
221#else
222 UNUSED(otp);
223 return 99999;
224#endif /* CH_DBG_ENABLE_STACK_CHECK */
225}
226
227#if defined(STM32F4)
229 // Device identifier
230 // 0x419 for STM32F42xxx and STM32F43xxx
231 // 0x413 for STM32F405xx/07xx and STM32F415xx/17xx
232 return ((DBGMCU->IDCODE & DBGMCU_IDCODE_DEV_ID_Msk) == 0x419);
233}
234#endif
235
236// Stubs for per-board low power helpers
237PUBLIC_API_WEAK void boardPrepareForStop() {
238 // Default implementation - wake up on PA0 - boards should override this
239 palEnableLineEvent(PAL_LINE(GPIOA, 0), PAL_EVENT_MODE_RISING_EDGE);
240}
241
242/**
243 Standby uses special low power hardware - it always wakes on rising edge
244*/
245
247#ifdef STM32F4XX
248 //Enable Wakeup Pin for PA0
249 PWR->CSR |= PWR_CSR_EWUP;
250
251 // Clear wakeup flag - it may be set if PA0 is already
252 // high when we enable it as a wake source
253 PWR->CR |= PWR_CR_CWUF; //Clear Wakeup Pin flag for PA0
254#endif
255
256#ifdef STM32F7XX
257 PWR->CSR2 |= PWR_CSR2_EWUP1; //EWUP1: Enable Wakeup pin for PA0
258 PWR->CR2 |= PWR_CR2_CWUPF1; //Clear Wakeup Pin flag for PA0
259#endif
260
261#ifdef STM32H7XX
262 // Wake on wakeup pin 0 - PA0
263 PWR->WKUPEPR = PWR_WKUPEPR_WKUPEN1;
264
265 // clear all possible wakeup bits
266 PWR->WKUPCR = 0xFFFFFFFF;
267#endif
268}
269
270PUBLIC_API_WEAK void boardPrepareForStandby() {
272}
273
274#endif // EFI_PROD_CODE
struct port_intctx intctx_t
Non-volatile backup-RAM registers support.
TunerStudioOutputChannels outputChannels
Definition engine.h:109
BOR_Level_t
@ BOR_Level_1
static EngineAccessor engine
Definition engine.h:413
HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
Launch the option byte loading.
HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
Lock the FLASH Option Control Registers access.
HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
Unlock the FLASH Option Control Registers access.
HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
Program option bytes.
void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
Get the Option byte configuration.
bool isIgnVoltage()
UNUSED(samplingTimeSeconds)
BOR_Result_t
Definition mpu_util.h:95
@ BOR_Result_Ok
Definition mpu_util.h:96
@ BOR_Result_Error
Definition mpu_util.h:97
uint32_t efitimems_t
bool SharedParamsWriteByIndex(uint32_t idx, uint8_t value)
Writes a data byte to the shared parameter buffer at the specified index.
void SharedParamsInit(void)
Initializes the shared RAM parameters module.
void setWatchdogResetPeriod(int resetMs)
bool isStm32F42x()
void tryResetWatchdog()
BOR_Level_t BOR_Get(void)
static efitimems_t watchdogResetPeriodMs
BOR_Result_t BOR_Set(BOR_Level_t BORValue)
void jump_to_openblt()
int getRemainingStack(thread_t *otp)
void startWatchdog(int timeoutMs)
uint32_t __main_stack_base__
void baseMCUInit()
uint32_t getMcuSerial()
PUBLIC_API_WEAK void boardPrepareForStop()
void boardPreparePA0ForStandby()
void jump_to_bootloader()
PUBLIC_API_WEAK void boardPrepareForStandby()
static void reset_and_jump(void)
static const efitimems_t watchdogCounterResetDelay
Header file of FLASH HAL module.
Header file of FLASH HAL module.
Header file of FLASH HAL module.
FLASH Option Bytes Program structure definition.