1
+ /*
2
+ This file is part of the ArduinoIoTCloud library.
3
+
4
+ Copyright (c) 2024 Arduino SA
5
+
6
+ This Source Code Form is subject to the terms of the Mozilla Public
7
+ License, v. 2.0. If a copy of the MPL was not distributed with this
8
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
+ */
10
+
11
+ #include " AIoTC_Config.h"
12
+ #if defined(BOARD_STM32H7) && OTA_ENABLED
13
+ #include " OTASTM32H7.h"
14
+
15
+ #include " utility/watchdog/Watchdog.h"
16
+ #include < STM32H747_System.h>
17
+
18
+ static bool findProgramLength (DIR * dir, uint32_t & program_length);
19
+
20
+ const char STM32H7OTACloudProcess::UPDATE_FILE_NAME[] = " /fs/UPDATE.BIN" ;
21
+
22
+ STM32H7OTACloudProcess::STM32H7OTACloudProcess (MessageStream *ms, Client* client)
23
+ : OTADefaultCloudProcessInterface(ms, client)
24
+ , decompressed(nullptr )
25
+ , _bd_raw_qspi(nullptr )
26
+ , _program_length(0 )
27
+ , _bd(nullptr )
28
+ , _fs(nullptr ) {
29
+
30
+ }
31
+
32
+ STM32H7OTACloudProcess::~STM32H7OTACloudProcess () {
33
+ if (decompressed != nullptr ) {
34
+ fclose (decompressed);
35
+ decompressed = nullptr ;
36
+ }
37
+
38
+ storageClean ();
39
+ }
40
+
41
+ OTACloudProcessInterface::State STM32H7OTACloudProcess::resume (Message* msg) {
42
+ return OtaBegin;
43
+ }
44
+
45
+ void STM32H7OTACloudProcess::update () {
46
+ OTADefaultCloudProcessInterface::update ();
47
+ watchdog_reset (); // FIXME this should npot be performed here
48
+ }
49
+
50
+ int STM32H7OTACloudProcess::writeFlash (uint8_t * const buffer, size_t len) {
51
+ if (decompressed == nullptr ) {
52
+ return -1 ;
53
+ }
54
+ return fwrite (buffer, sizeof (uint8_t ), len, decompressed);
55
+ }
56
+
57
+ OTACloudProcessInterface::State STM32H7OTACloudProcess::startOTA () {
58
+ if (!isOtaCapable ()) {
59
+ return NoCapableBootloaderFail;
60
+ }
61
+
62
+ /* Initialize the QSPI memory for OTA handling. */
63
+ if (!storageInit ()) {
64
+ return OtaStorageInitFail;
65
+ }
66
+
67
+ // this could be useless, since we are writing over it
68
+ remove (UPDATE_FILE_NAME);
69
+
70
+ decompressed = fopen (UPDATE_FILE_NAME, " wb" );
71
+
72
+ // start the download if the setup for ota storage is successful
73
+ return OTADefaultCloudProcessInterface::startOTA ();
74
+ }
75
+
76
+
77
+ OTACloudProcessInterface::State STM32H7OTACloudProcess::flashOTA () {
78
+ fclose (decompressed);
79
+ decompressed = nullptr ;
80
+
81
+ /* Schedule the firmware update. */
82
+ if (!storageOpen ()) {
83
+ return OtaStorageOpenFail;
84
+ }
85
+
86
+ // this sets the registries in RTC to load the firmware from the storage selected at the next reboot
87
+ STM32H747::writeBackupRegister (RTCBackup::DR0, 0x07AA );
88
+ STM32H747::writeBackupRegister (RTCBackup::DR1, storage);
89
+ STM32H747::writeBackupRegister (RTCBackup::DR2, data_offset);
90
+ STM32H747::writeBackupRegister (RTCBackup::DR3, _program_length);
91
+
92
+ return Reboot;
93
+ }
94
+
95
+ OTACloudProcessInterface::State STM32H7OTACloudProcess::reboot () {
96
+ // TODO save information about the progress reached in the ota
97
+
98
+ // This command reboots the mcu
99
+ NVIC_SystemReset ();
100
+
101
+ return Resume; // This won't ever be reached
102
+ }
103
+
104
+ void STM32H7OTACloudProcess::reset () {
105
+ OTADefaultCloudProcessInterface::reset ();
106
+
107
+ remove (UPDATE_FILE_NAME);
108
+
109
+ storageClean ();
110
+ }
111
+
112
+ void STM32H7OTACloudProcess::storageClean () {
113
+ DEBUG_VERBOSE (F (" storage clean" ));
114
+
115
+ if (decompressed != nullptr ) {
116
+ fclose (decompressed);
117
+ decompressed = nullptr ;
118
+ }
119
+
120
+ if (_fs != nullptr ) {
121
+ _fs->unmount ();
122
+ delete _fs;
123
+ _fs = nullptr ;
124
+ }
125
+
126
+ if (_bd != nullptr ) {
127
+ delete _bd;
128
+ _bd = nullptr ;
129
+ }
130
+ }
131
+
132
+ bool STM32H7OTACloudProcess::isOtaCapable () {
133
+ #define BOOTLOADER_ADDR (0x8000000 )
134
+ uint32_t bootloader_data_offset = 0x1F000 ;
135
+ uint8_t * bootloader_data = (uint8_t *)(BOOTLOADER_ADDR + bootloader_data_offset);
136
+ uint8_t currentBootloaderVersion = bootloader_data[1 ];
137
+ if (currentBootloaderVersion < 22 )
138
+ return false ;
139
+ else
140
+ return true ;
141
+ }
142
+
143
+ bool STM32H7OTACloudProcess::storageInit () {
144
+ int err_mount=1 ;
145
+
146
+ if (_bd_raw_qspi == nullptr ) {
147
+ _bd_raw_qspi = mbed::BlockDevice::get_default_instance ();
148
+
149
+ if (_bd_raw_qspi->init () != QSPIF_BD_ERROR_OK) {
150
+ DEBUG_VERBOSE (F (" Error: QSPI init failure." ));
151
+ return false ;
152
+ }
153
+ }
154
+
155
+ if (storage == portenta::QSPI_FLASH_FATFS) {
156
+ _fs = new mbed::FATFileSystem (" fs" );
157
+ err_mount = _fs->mount (_bd_raw_qspi);
158
+ } else if (storage == portenta::QSPI_FLASH_FATFS_MBR) {
159
+ _bd = new mbed::MBRBlockDevice (_bd_raw_qspi, data_offset);
160
+ _fs = new mbed::FATFileSystem (" fs" );
161
+ err_mount = _fs->mount (_bd);
162
+ }
163
+
164
+ if (!err_mount) {
165
+ return true ;
166
+ }
167
+ DEBUG_VERBOSE (F (" Error while mounting the filesystem. Err = %d" ), err_mount);
168
+ return false ;
169
+ }
170
+
171
+ bool STM32H7OTACloudProcess::storageOpen () {
172
+ DIR * dir = NULL ;
173
+ if ((dir = opendir (" /fs" )) != NULL )
174
+ {
175
+ if (findProgramLength (dir, _program_length))
176
+ {
177
+ closedir (dir);
178
+ return true ;
179
+ }
180
+ closedir (dir);
181
+ }
182
+
183
+ return false ;
184
+ }
185
+
186
+ bool findProgramLength (DIR * dir, uint32_t & program_length) {
187
+ struct dirent * entry = NULL ;
188
+ while ((entry = readdir (dir)) != NULL ) {
189
+ if (strcmp (entry->d_name , " UPDATE.BIN" ) == 0 ) { // FIXME use constants
190
+ struct stat stat_buf;
191
+ stat (" /fs/UPDATE.BIN" , &stat_buf);
192
+ program_length = stat_buf.st_size ;
193
+ return true ;
194
+ }
195
+ }
196
+
197
+ return false ;
198
+ }
199
+
200
+ // extern uint32_t __stext = ~0;
201
+ extern uint32_t __etext;
202
+ extern uint32_t _sdata;
203
+ extern uint32_t _edata;
204
+
205
+ void * STM32H7OTACloudProcess::appStartAddress () {
206
+ return (void *)0x8040000 ;
207
+ // return &__stext;
208
+ }
209
+
210
+ uint32_t STM32H7OTACloudProcess::appSize () {
211
+ return ((&__etext - (uint32_t *)appStartAddress ()) + (&_edata - &_sdata))*sizeof (void *);
212
+ }
213
+
214
+
215
+ #endif // defined(BOARD_STM32H7) && OTA_ENABLED
0 commit comments