rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
mpu_util.cpp
Go to the documentation of this file.
1/**
2 * @file mpu_util.cpp
3 *
4 * @date Jul 27, 2014
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8#include "pch.h"
9
10#include "flash_int.h"
11
12static bool isDualBank() {
13#ifdef FLASH_OPTCR_nDBANK
14 // cleared bit indicates dual bank
15 return (FLASH->OPTCR & FLASH_OPTCR_nDBANK) == 0;
16#else
17 return 0;
18#endif
19}
20
21static uint16_t flashSize() {
22 return *reinterpret_cast<const volatile uint16_t*>(FLASHSIZE_BASE);
23}
24
32
34 bool db = isDualBank();
35 uint16_t fs = flashSize();
36
37 if (db) {
38 if (fs == 1024) {
40 } else if (fs == 2048) {
42 }
43 } else {
44 if (fs == 1024) {
45 // Unsupported scenario! Not enough space for program plus two config copies
46 criticalError("1MB single bank MCU detected: please clear nDBANK option bit and reinstall FW.");
48 } else if (fs == 2048) {
50 }
51 }
52
53 criticalError("Unrecognized flash memory layout db=%d, size=%d", db, fs);
55}
56
58 // Allow flash-while-running if dual bank mode is enabled, and we're a 2MB device (ie, no code located in second bank)
60}
61
62// See ST AN4826
64 // 1MB devices have 8 sectors per bank
65 // 2MB devices have 12 sectors per bank
66 // However, the second bank always starts at index 12 (1MB devices have a 4 sector discontinuity between banks)
67
68 if (sector >= 12) {
69 // The second bank has the same structure as the first
70 return flashSectorSize(sector - 12);
71 }
72
73 // On 1MB devices, sectors 8-11 don't exist, therefore have zero size.
74 if (flashSize() == 1024) {
75 if (sector > 7 && sector < 12) {
76 return 0;
77 }
78 }
79
80 // Pages are twice the size when in single bank mode
81 size_t dbMul = isDualBank() ? 1 : 2;
82
83 if (sector <= 3)
84 return 16 * 1024 * dbMul;
85 else if (sector == 4)
86 return 64 * 1024 * dbMul;
87 else if (sector >= 5)
88 return 128 * 1024 * dbMul;
89 return 0;
90}
91
93 switch (determineDevice()) {
95 // Sector 18, second to last 128K sector
96 return 0x080C0000;
98 // Sector 7, last 256K sector
99 return 0x080C0000;
100 case DeviceType::DualBank2MB: /* falls thru */
102#ifdef EFI_FLASH_USE_1500_OF_2MB
103 // Right after the first 1.5 megabytes
104 // Sector 20 for dual bank
105 // Sector 10 for single bank
106 return 0x08180000;
107#else
108 // Start of the second megabyte
109 // Sector 12 for dual bank
110 // Sector 8 for single bank
111 return 0x08100000;
112#endif // EFI_FLASH_USE_1500_OF_2MB
113 default:
114 return 0;
115 }
116}
117
119 switch (determineDevice()) {
121 // Sector 19, last 128K sector, 128K after the first copy
122 return 0x080E0000;
124#ifdef EFI_FLASH_USE_1500_OF_2MB
125 // Sector 21, 128K after the first copy
126 return 0x081A0000;
127#else
128 // Sector 14, 32K after the first copy
129 return 0x08108000;
130#endif // EFI_FLASH_USE_1500_OF_2MB
132#ifdef EFI_FLASH_USE_1500_OF_2MB
133 // Sector 11, 256K after the first copy
134 return 0x081C0000;
135#else
136 // Sector 9, 256K after the first copy
137 return 0x08140000;
138#endif // EFI_FLASH_USE_1500_OF_2MB
140 // We can't fit a second copy in this config, fall thru to failure case
141 default:
142 return 0;
143 }
144}
145
146#define FLASH_ACR (*(volatile uint32_t *)(FLASH_BASE + 0x00))
147#define FLASH_KEYR (*(volatile uint32_t *)(FLASH_BASE + 0x04))
148#define FLASH_OPTKEYR (*(volatile uint32_t *)(FLASH_BASE + 0x08))
149#define FLASH_SR (*(volatile uint32_t *)(FLASH_BASE + 0x0C))
150#define FLASH_CR (*(volatile uint32_t *)(FLASH_BASE + 0x10))
151#define FLASH_OPTCR (*(volatile uint32_t *)(FLASH_BASE + 0x14))
152
153#define FLASH_OPTCR_STRT (1 << 1)
154
155#define FLASH_OPTKEY1 (0x08192A3B)
156#define FLASH_OPTKEY2 (0x4C5D6E7F)
157
158/*
159static void flash_wait_complete()
160{
161 do { __DSB(); } while (FLASH->SR & FLASH_SR_BSY);
162}
163
164static void stm32f7_flash_mass_erase_dual_block()
165{
166 FLASH_CR |= FLASH_CR_MER1 | FLASH_CR_MER2;
167 FLASH_CR |= FLASH_CR_STRT;
168 flash_wait_complete();
169 FLASH_CR &= ~(FLASH_CR_MER1 | FLASH_CR_MER2);
170}
171*/
172
173/*
174Standby for both F4 & F7 works perfectly, with very little current consumption. Downside is that theres a limited amount of pins that can wakeup F7, and only PA0 for F4XX.
175Cannot be used for CAN wakeup without hardware modifications.
176*/
178 SysTick->CTRL = 0;
179 SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
180 PWR->CR1 |= PWR_CR1_PDDS; // PDDS = use standby mode (not stop mode)
181 PWR->CR1 |= PWR_CR1_CSBF; // Clear standby flag
182
183 // Do anything the board wants to prepare for standby mode - enabling wakeup sources!
185
186 __disable_irq();
187 __WFI();
188}
bool mcuCanFlashWhileRunning()
Definition mpu_util.cpp:10
void stm32_standby()
Definition mpu_util.cpp:18
uintptr_t getFlashAddrSecondCopy()
Definition mpu_util.cpp:252
uintptr_t getFlashAddrFirstCopy()
Definition mpu_util.cpp:248
size_t flashSectorSize(flashsector_t sector)
Get the size of sector.
Definition mpu_util.cpp:237
uint8_t flashsector_t
Index of a sector.
Definition flash_int.h:89
void boardPrepareForStandby()
static uint16_t flashSize()
Definition mpu_util.cpp:21
static bool isDualBank()
Definition mpu_util.cpp:12
static DeviceType determineDevice()
Definition mpu_util.cpp:33
DeviceType
Definition mpu_util.cpp:25