Skip to content

Commit 70db498

Browse files
committed
STM32 - support for all STM32F series
only F103 and F411 tested
1 parent 11031e4 commit 70db498

File tree

6 files changed

+97
-11
lines changed

6 files changed

+97
-11
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ The library is a modification of the Arduino WiFi101OTA library.
2828
* Arduino SAMD boards like Zero, M0 or MKR and the new "Nano 33 IoT"
2929
* nRF5 board supported by [nRF5 core](https://github.com/sandeepmistry/arduino-nRF5).
3030
* RP2040 boards with [Pico core](https://github.com/earlephilhower/arduino-pico)
31-
* STM32F1 boards with [STM32 core](https://github.com/stm32duino/Arduino_Core_STM32)
31+
* STM32F boards with [STM32 core](https://github.com/stm32duino/Arduino_Core_STM32)
3232
* boards supported by ESP8266 and ESP32 Arduino boards package
3333
* any board with MCU with SD bootloader
3434

@@ -196,8 +196,9 @@ Does the OTA uploaded sketch have ArduinoOTA?
196196
- [Seeed Wio Terminal](https://github.com/jandrassy/ArduinoOTA/pull/104) (with Blynk.Edgent)
197197
* RP2040
198198
- Raspberry Pi Pico
199-
* STM32F1
199+
* STM32
200200
- BluePill F103CB (128kB flash)
201+
- BlackPill F411CE
201202
* nRF5
202203
- Seeed Arch Link (nRF51 board)
203204
- [nrf52832 board](https://github.com/jandrassy/ArduinoOTA/issues/1)

src/ArduinoOTA.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#if FLASHEND >= 0xFFFF
2525
#include "InternalStorageAVR.h"
2626
#endif
27-
#elif defined(STM32F1xx)
27+
#elif defined(ARDUINO_ARCH_STM32)
2828
#include <InternalStorageSTM32.h>
2929
#elif defined(ARDUINO_ARCH_RP2040)
3030
#include <InternalStorageRP2.h>

src/InternalStorageSTM32.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,37 @@
1717

1818
*/
1919

20-
#if defined(STM32F1xx)
20+
#ifdef ARDUINO_ARCH_STM32
21+
22+
#ifndef OTA_STORAGE_STM32_SECTOR
23+
#define OTA_STORAGE_STM32_SECTOR 5
24+
#endif
2125

2226
#include <Arduino.h>
2327

2428
#include "InternalStorageSTM32.h"
2529
#include "utility/stm32_flash_boot.h"
2630

27-
InternalStorageSTM32Class::InternalStorageSTM32Class() {
31+
#if defined(STM32F7xx)
32+
const uint32_t SECTOR_SIZE = 0x40000; // from sector 5
33+
#elif defined(STM32F2xx) || defined(STM32F4xx)
34+
const uint32_t SECTOR_SIZE = 0x20000; // from sector 5 (for F2, F4)
35+
#endif
36+
37+
InternalStorageSTM32Class::InternalStorageSTM32Class(uint8_t _sector) {
38+
sector = _sector < 5 ? 5 : _sector;
39+
#ifdef FLASH_TYPEERASE_SECTORS
40+
maxSketchSize = SECTOR_SIZE * (sector - 4); // sum of sectors 0 to 4 is 128kB, starting sector 5 the sector size is 128kB
41+
storageStartAddress = FLASH_BASE + maxSketchSize;
42+
maxSketchSize -= SKETCH_START_ADDRESS;
43+
if (MAX_FLASH - maxSketchSize < maxSketchSize) {
44+
maxSketchSize = MAX_FLASH - maxSketchSize;
45+
}
46+
#else
2847
maxSketchSize = (MAX_FLASH - SKETCH_START_ADDRESS) / 2;
2948
maxSketchSize = (maxSketchSize / PAGE_SIZE) * PAGE_SIZE; // align to page
3049
storageStartAddress = FLASH_BASE + SKETCH_START_ADDRESS + maxSketchSize;
50+
#endif
3151
pageAlignedLength = 0;
3252
writeIndex = 0;
3353
flashWriteAddress = storageStartAddress;
@@ -43,10 +63,19 @@ int InternalStorageSTM32Class::open(int length) {
4363
writeIndex = 0;
4464

4565
FLASH_EraseInitTypeDef EraseInitStruct;
66+
#ifdef FLASH_TYPEERASE_SECTORS
67+
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
68+
EraseInitStruct.Sector = sector;
69+
EraseInitStruct.NbSectors = 1 + (length / SECTOR_SIZE);
70+
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
71+
#else
4672
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
47-
EraseInitStruct.Banks = FLASH_BANK_1;
4873
EraseInitStruct.PageAddress = flashWriteAddress;
4974
EraseInitStruct.NbPages = pageAlignedLength / PAGE_SIZE;
75+
#endif
76+
#ifdef FLASH_BANK_1
77+
EraseInitStruct.Banks = FLASH_BANK_1;
78+
#endif
5079

5180
uint32_t pageError = 0;
5281
return (HAL_FLASH_Unlock() == HAL_OK //
@@ -82,6 +111,6 @@ void InternalStorageSTM32Class::apply() {
82111
copy_flash_pages(FLASH_BASE + SKETCH_START_ADDRESS, (uint8_t*) storageStartAddress, pageAlignedLength, true);
83112
}
84113

85-
InternalStorageSTM32Class InternalStorage;
114+
InternalStorageSTM32Class InternalStorage(OTA_STORAGE_STM32_SECTOR);
86115

87116
#endif

src/InternalStorageSTM32.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
class InternalStorageSTM32Class : public OTAStorage {
2626
public:
2727

28-
InternalStorageSTM32Class();
28+
InternalStorageSTM32Class(uint8_t sector);
2929

3030
virtual int open(int length);
3131
virtual size_t write(uint8_t);
@@ -40,6 +40,7 @@ class InternalStorageSTM32Class : public OTAStorage {
4040
uint8_t u8[4];
4141
} addressData;
4242

43+
uint8_t sector; // for models with flash organized into sectors
4344
uint32_t maxSketchSize;
4445
uint32_t storageStartAddress;
4546
uint32_t pageAlignedLength;

src/OTAStorage.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ char * __text_start__(); // 0x2000, 0x0 without bootloader and 0x4000 for M0 ori
1515
extern "C" {
1616
char * __isr_vector();
1717
}
18-
#elif defined(STM32F1xx)
18+
#elif defined(ARDUINO_ARCH_STM32)
1919
#include "stm32yyxx_ll_utils.h"
2020
extern "C" char * g_pfnVectors; // at first address of the binary. 0x0000 without bootloader. 0x2000 with Maple bootloader
2121
#elif defined(ARDUINO_ARCH_RP2040)
@@ -39,9 +39,13 @@ OTAStorage::OTAStorage() :
3939
SKETCH_START_ADDRESS((uint32_t) __isr_vector),
4040
PAGE_SIZE((size_t) NRF_FICR->CODEPAGESIZE),
4141
MAX_FLASH(PAGE_SIZE * (uint32_t) NRF_FICR->CODESIZE)
42-
#elif defined(STM32F1xx)
42+
#elif defined(ARDUINO_ARCH_STM32)
4343
SKETCH_START_ADDRESS((uint32_t) &g_pfnVectors - FLASH_BASE), // start address depends on bootloader size
44+
#ifdef FLASH_PAGE_SIZE
4445
PAGE_SIZE(FLASH_PAGE_SIZE),
46+
#else
47+
PAGE_SIZE(4), //for FLASH_TYPEPROGRAM_WORD
48+
#endif
4549
MAX_FLASH((min(LL_GetFlashSize(), 512ul) * 1024)) // LL_GetFlashSize returns size in kB. 512 is max for a bank
4650
#elif defined(ARDUINO_ARCH_RP2040)
4751
SKETCH_START_ADDRESS(0),

src/utility/stm32_flash_boot.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,48 @@
1616
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1717
*/
1818

19-
#if defined(STM32F1xx)
19+
#ifdef ARDUINO_ARCH_STM32
2020

2121
#include "stm32_flash_boot.h"
22+
#if defined(STM32F0xx)
23+
#include <stm32f0xx_hal_flash_ex.h> // FLASH_PAGE_SIZE is in hal.h
24+
#elif defined(STM32F1xx)
2225
#include <stm32f1xx_hal_flash_ex.h> // FLASH_PAGE_SIZE is in hal.h
26+
#elif defined(STM32F2xx)
27+
#include <stm32f2xx.h>
28+
#elif defined(STM32F3xx)
29+
#include <stm32f3xx_hal_flash_ex.h> // FLASH_PAGE_SIZE is in hal.h
30+
#elif defined(STM32F4xx)
31+
#include "stm32f4xx.h"
32+
#elif defined(STM32F7xx)
33+
#include <stm32f7xx.h>
34+
#define SMALL_SECTOR_SIZE 0x8000 // sectors 0 to 3
35+
#define LARGE_SECTOR_SIZE 0x40000 // from sector 5
36+
#endif
37+
38+
#if defined(STM32F2xx) || defined(STM32F4xx)
39+
#define SMALL_SECTOR_SIZE 0x4000 // sectors 0 to 3
40+
#define LARGE_SECTOR_SIZE 0x20000 // from sector 5
41+
#endif
2342

2443
/**
2544
* function for bootload flash to flash
2645
* this function runs exclusively in RAM.
2746
* note: interrupts must be disabled.
2847
* note: parameters must be multiple of FLASH_PAGE_SIZE
48+
* note: for models with sectors, flash_offs must be start address of a sector
2949
*/
3050
void copy_flash_pages(uint32_t flash_offs, const uint8_t *data, uint32_t count, uint8_t reset) {
3151

3252
uint32_t page_address = flash_offs;
3353
while (FLASH->SR & FLASH_SR_BSY);
54+
55+
#ifdef FLASH_CR_PSIZE
56+
CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
57+
FLASH->CR |= 0x00000200U; // FLASH_PSIZE_WORD;
58+
FLASH->CR |= FLASH_CR_PG;
59+
#endif
60+
#ifdef FLASH_PAGE_SIZE
3461
SET_BIT(FLASH->CR, FLASH_CR_PER);
3562
for (uint16_t i = 0; i < count / FLASH_PAGE_SIZE; i++) {
3663
WRITE_REG(FLASH->AR, page_address);
@@ -39,11 +66,35 @@ void copy_flash_pages(uint32_t flash_offs, const uint8_t *data, uint32_t count,
3966
while (FLASH->SR & FLASH_SR_BSY);
4067
}
4168
CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
69+
#else
70+
uint8_t startSector = (flash_offs == FLASH_BASE) ? 0 : 1; // 1 if bootloader is in sector 0
71+
uint8_t endSector = 1 + startSector + ((count - 1) / SMALL_SECTOR_SIZE); // size of the first 4 sectors is 0x4000 kB
72+
if (endSector > 4) { // if more than 4 sectors are needed (including bootloader)
73+
if (endSector < 8) { // size of sector 4 is (4 * SMALL_SECTOR_SIZE)
74+
endSector = 5;
75+
} else { // let's divide with the count of large sectors and add the first 5 sectors as one large sector
76+
endSector = 5 + (((count - 1) + (startSector * SMALL_SECTOR_SIZE)) / LARGE_SECTOR_SIZE);
77+
}
78+
}
79+
for (uint8_t sector = startSector; sector < endSector; sector++) {
80+
CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
81+
FLASH->CR |= FLASH_CR_SER | (sector << FLASH_CR_SNB_Pos);
82+
FLASH->CR |= FLASH_CR_STRT;
83+
while (FLASH->SR & FLASH_SR_BSY);
84+
}
85+
CLEAR_BIT(FLASH->CR, (FLASH_CR_SER | FLASH_CR_SNB));
86+
#endif
4287

4388
page_address = flash_offs;
4489
uint16_t* ptr = (uint16_t*) data;
4590
while (FLASH->SR & FLASH_SR_BSY);
91+
#ifdef FLASH_CR_PSIZE
92+
CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
93+
FLASH->CR |= 0x00000100U; // FLASH_PSIZE_HALF_WORD
94+
FLASH->CR |= FLASH_CR_PG;
95+
#else
4696
SET_BIT(FLASH->CR, FLASH_CR_PG);
97+
#endif
4798
while (count) {
4899
*(volatile uint16_t*)page_address = *ptr;
49100
page_address += 2;

0 commit comments

Comments
 (0)