Merge pull request #11939 from blckmn/flash-fix
[betaflight.git] / src / main / drivers / persistent.c
blobb7998adcfc3c6b9f2ae45789269c5a4e13879b31
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
22 * An implementation of persistent data storage utilizing RTC backup data register.
23 * Retains values written across software resets and boot loader activities.
26 #include <stdint.h>
27 #include "platform.h"
29 #include "drivers/persistent.h"
30 #include "drivers/system.h"
32 #define PERSISTENT_OBJECT_MAGIC_VALUE (('B' << 24)|('e' << 16)|('f' << 8)|('1' << 0))
34 #ifdef USE_HAL_DRIVER
36 uint32_t persistentObjectRead(persistentObjectId_e id)
38 RTC_HandleTypeDef rtcHandle = { .Instance = RTC };
40 uint32_t value = HAL_RTCEx_BKUPRead(&rtcHandle, id);
42 return value;
45 void persistentObjectWrite(persistentObjectId_e id, uint32_t value)
47 RTC_HandleTypeDef rtcHandle = { .Instance = RTC };
49 HAL_RTCEx_BKUPWrite(&rtcHandle, id, value);
51 #ifdef USE_SPRACING_PERSISTENT_RTC_WORKAROUND
52 // Also write the persistent location used by the bootloader to support DFU etc.
53 if (id == PERSISTENT_OBJECT_RESET_REASON) {
54 // SPRACING firmware sometimes enters DFU mode when MSC mode is requested
55 if (value == RESET_MSC_REQUEST) {
56 value = RESET_NONE;
58 HAL_RTCEx_BKUPWrite(&rtcHandle, PERSISTENT_OBJECT_RESET_REASON_FWONLY, value);
60 #endif
63 void persistentObjectRTCEnable(void)
65 #if !defined(STM32G4)
66 // G4 library V1.0.0 __HAL_RTC_WRITEPROTECTION_ENABLE/DISABLE macro does not use handle parameter
67 RTC_HandleTypeDef rtcHandle = { .Instance = RTC };
68 #endif
70 #if !defined(STM32H7)
71 __HAL_RCC_PWR_CLK_ENABLE(); // Enable Access to PWR
72 #endif
74 HAL_PWR_EnableBkUpAccess(); // Disable backup domain protection
76 #if defined(STM32G4)
77 /* Enable RTC APB clock */
78 __HAL_RCC_RTCAPB_CLK_ENABLE();
80 /* Peripheral clock enable */
81 __HAL_RCC_RTC_ENABLE();
83 #else // !STM32G4, F7 and H7 case
85 #if defined(__HAL_RCC_RTC_CLK_ENABLE)
86 // For those MCUs with RTCAPBEN bit in RCC clock enable register, turn it on.
87 __HAL_RCC_RTC_CLK_ENABLE(); // Enable RTC module
88 #endif
90 #endif // STM32G4
92 // We don't need a clock source for RTC itself. Skip it.
94 __HAL_RTC_WRITEPROTECTION_ENABLE(&rtcHandle); // Reset sequence
95 __HAL_RTC_WRITEPROTECTION_DISABLE(&rtcHandle); // Apply sequence
98 #else
99 uint32_t persistentObjectRead(persistentObjectId_e id)
101 uint32_t value = RTC_ReadBackupRegister(id);
103 return value;
106 void persistentObjectWrite(persistentObjectId_e id, uint32_t value)
108 RTC_WriteBackupRegister(id, value);
111 void persistentObjectRTCEnable(void)
113 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // Enable Access to PWR
114 PWR_BackupAccessCmd(ENABLE); // Disable backup domain protection
116 // We don't need a clock source for RTC itself. Skip it.
118 RTC_WriteProtectionCmd(ENABLE); // Reset sequence
119 RTC_WriteProtectionCmd(DISABLE); // Apply sequence
121 #endif
123 void persistentObjectInit(void)
125 // Configure and enable RTC for backup register access
127 persistentObjectRTCEnable();
129 // XXX Magic value checking may be sufficient
131 uint32_t wasSoftReset;
133 #ifdef STM32H7
134 wasSoftReset = RCC->RSR & RCC_RSR_SFTRSTF;
135 #else
136 wasSoftReset = RCC->CSR & RCC_CSR_SFTRSTF;
137 #endif
139 if (!wasSoftReset || (persistentObjectRead(PERSISTENT_OBJECT_MAGIC) != PERSISTENT_OBJECT_MAGIC_VALUE)) {
140 for (int i = 1; i < PERSISTENT_OBJECT_COUNT; i++) {
141 persistentObjectWrite(i, 0);
143 persistentObjectWrite(PERSISTENT_OBJECT_MAGIC, PERSISTENT_OBJECT_MAGIC_VALUE);