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 #ifdef STM32H723xx
52 RCC->AHB1ENR &= ~(RCC_AHB1ENR_USB1OTGHSEN);
53 #else
54 RCC->AHB1ENR &= ~(RCC_AHB1ENR_USB1OTGHSEN | RCC_AHB1ENR_USB2OTGFSEN);
55 #endif
56 #endif
57
58 // and now reboot
59 NVIC_SystemReset();
60}
61
62#if EFI_DFU_JUMP
64 // leave DFU breadcrumb which assembly startup code would check, see [rusefi][DFU] section in assembly code
65
66 *((unsigned long *)0x2001FFF0) = 0xDEADBEEF; // End of RAM
67
69}
70#endif
71
73#if EFI_USE_OPENBLT
74 /* safe to call on already inited shares area */
76 /* Store sing to stay in OpenBLT */
78
80#endif
81}
82#endif /* EFI_PROD_CODE */
83
84#if EFI_PROD_CODE
85
87 FLASH_OBProgramInitTypeDef FLASH_Handle;
88
89 /* Read option bytes */
90 HAL_FLASHEx_OBGetConfig(&FLASH_Handle);
91
92 /* Return BOR value */
93 return (BOR_Level_t) FLASH_Handle.BORLevel;
94}
95
97 if (BOR_Get() == BORValue) {
98 return BOR_Result_Ok;
99 }
100
101
102 FLASH_OBProgramInitTypeDef FLASH_Handle;
103
104 FLASH_Handle.BORLevel = (uint32_t)BORValue;
105 FLASH_Handle.OptionType = OPTIONBYTE_BOR;
106
108
109 HAL_FLASHEx_OBProgram(&FLASH_Handle);
110
111 HAL_StatusTypeDef status = HAL_FLASH_OB_Launch();
112
114
115 if (status != HAL_OK) {
116 return BOR_Result_Error;
117 }
118
119 return BOR_Result_Ok;
120}
121
122void startWatchdog(int timeoutMs) {
123#if HAL_USE_WDG
124 // RL is a 12-bit value so we use a "2 ms" prescaler to support long timeouts (> 4.095 sec)
125 static WDGConfig wdgcfg;
126 wdgcfg.pr = STM32_IWDG_PR_64; // t = (1/32768) * 64 = ~2 ms
127 wdgcfg.rlr = STM32_IWDG_RL((uint32_t)((32.768f / 64.0f) * timeoutMs));
128#if STM32_IWDG_IS_WINDOWED
129 wdgcfg.winr = 0xfff; // don't use window
130#endif
131
132#ifndef __OPTIMIZE__ // gcc-specific built-in define
133 // if no optimizations, then it's most likely a debug version,
134 // and we need to enable a special watchdog feature to allow debugging
135 efiPrintf("Enabling 'debug freeze' watchdog feature...");
136#ifdef STM32H7XX
137 DBGMCU->APB4FZ1 |= DBGMCU_APB4FZ1_DBG_IWDG1;
138#else // F4 & F7
139 DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_IWDG_STOP;
140#endif // STM32H7XX
141#endif // __OPTIMIZE__
142
143 static bool isStarted = false;
144 if (!isStarted) {
145 efiPrintf("Starting watchdog with timeout %d ms...", timeoutMs);
146 wdgStart(&WDGD1, &wdgcfg);
147 isStarted = true;
148 } else {
149 efiPrintf("Changing watchdog timeout to %d ms...", timeoutMs);
150 // wdgStart() uses kernel lock, thus we cannot call it here from locked or ISR code
151 wdg_lld_start(&WDGD1);
152 }
153#endif // HAL_USE_WDG
154}
155
157// Reset watchod reset counted in SharedParams after this delay
159
160void setWatchdogResetPeriod(int resetMs) {
161#if 0
162 efiPrintf("[dev] wd %d", resetMs);
163#endif
165}
166
168#if HAL_USE_WDG
169 static Timer lastTimeWasReset;
170 static efitimems_t wdUptime = 0;
171 // check if it's time to reset the watchdog
172 if (lastTimeWasReset.hasElapsedMs(watchdogResetPeriodMs)) {
173 // we assume tryResetWatchdog() is called from a timer callback
174 wdgResetI(&WDGD1);
175 lastTimeWasReset.reset();
176 // with 100 ms WD
177 if (wdUptime < watchdogCounterResetDelay) {
178 wdUptime += watchdogResetPeriodMs;
179 // we just crossed the treshold
180 if (wdUptime >= watchdogCounterResetDelay) {
181#if EFI_USE_OPENBLT
183#endif
184 }
185 }
186 }
187#endif // HAL_USE_WDG
188}
189
190uint32_t getMcuSerial() {
191 uint32_t *uid = ((uint32_t *)UID_BASE);
192 return uid[0] + uid[1] + uid[2];
193}
194
196 // looks like this holds a random value on start? Let's set a nice clean zero
197 DWT->CYCCNT = 0;
198
199
200#ifndef EFI_SKIP_BOR
201 BOR_Set(BOR_Level_1); // one step above default value
202#else
204#endif
205
206#ifndef EFI_BOOTLOADER
208#endif // EFI_BOOTLOADER
209}
210
211extern uint32_t __main_stack_base__;
212
213typedef struct port_intctx intctx_t;
214
215int getRemainingStack(thread_t *otp) {
216#if CH_DBG_ENABLE_STACK_CHECK
217 // this would dismiss coverity warning - see http://rusefi.com/forum/viewtopic.php?f=5&t=655
218 // coverity[uninit_use]
219 register intctx_t *r13 asm ("r13");
220 otp->activeStack = r13;
221
222 int remainingStack;
223 if (ch0.dbg.isr_cnt > 0) {
224 // ISR context
225 remainingStack = (int)(r13 - 1) - (int)&__main_stack_base__;
226 } else {
227 remainingStack = (int)(r13 - 1) - (int)otp->wabase;
228 }
229 otp->remainingStack = remainingStack;
230 return remainingStack;
231#else
232 UNUSED(otp);
233 return 99999;
234#endif /* CH_DBG_ENABLE_STACK_CHECK */
235}
236
237#if defined(STM32F4)
239 // Device identifier
240 // 0x419 for STM32F42xxx and STM32F43xxx
241 // 0x413 for STM32F405xx/07xx and STM32F415xx/17xx
242 return ((DBGMCU->IDCODE & DBGMCU_IDCODE_DEV_ID_Msk) == 0x419);
243}
244#endif
245
246// Stubs for per-board low power helpers
247PUBLIC_API_WEAK void boardPrepareForStop() {
248 // Default implementation - wake up on PA0 - boards should override this
249 palEnableLineEvent(PAL_LINE(GPIOA, 0), PAL_EVENT_MODE_RISING_EDGE);
250}
251
252/**
253 Standby uses special low power hardware - it always wakes on rising edge
254*/
255
257#ifdef STM32F4XX
258 //Enable Wakeup Pin for PA0
259 PWR->CSR |= PWR_CSR_EWUP;
260
261 // Clear wakeup flag - it may be set if PA0 is already
262 // high when we enable it as a wake source
263 PWR->CR |= PWR_CR_CWUF; //Clear Wakeup Pin flag for PA0
264#endif
265
266#ifdef STM32F7XX
267 PWR->CSR2 |= PWR_CSR2_EWUP1; //EWUP1: Enable Wakeup pin for PA0
268 PWR->CR2 |= PWR_CR2_CWUPF1; //Clear Wakeup Pin flag for PA0
269#endif
270
271#ifdef STM32H7XX
272 // Wake on wakeup pin 0 - PA0
273 PWR->WKUPEPR = PWR_WKUPEPR_WKUPEN1;
274
275 // clear all possible wakeup bits
276 PWR->WKUPCR = 0xFFFFFFFF;
277#endif
278}
279
280PUBLIC_API_WEAK void boardPrepareForStandby() {
282}
283
284#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_None
@ 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.