From f4c74920dcd385fb49794c382064559d0ab6d131 Mon Sep 17 00:00:00 2001 From: delphi Date: Sun, 10 Oct 2021 16:21:52 +0300 Subject: [PATCH] [stm32] Flash driver enabled for F1 family Signed-off-by: delphi --- README.md | 2 +- examples/blue_pill_f103/flash/main.cpp | 106 +++++++++++++++++++++ examples/blue_pill_f103/flash/openocd.cfg | 2 + examples/blue_pill_f103/flash/project.xml | 16 ++++ src/modm/platform/flash/stm32/flash.cpp.in | 31 +++++- src/modm/platform/flash/stm32/flash.hpp.in | 14 +-- src/modm/platform/flash/stm32/module.lb | 11 ++- 7 files changed, 171 insertions(+), 11 deletions(-) create mode 100644 examples/blue_pill_f103/flash/main.cpp create mode 100644 examples/blue_pill_f103/flash/openocd.cfg create mode 100644 examples/blue_pill_f103/flash/project.xml diff --git a/README.md b/README.md index ca06abd3e3..18556d8683 100644 --- a/README.md +++ b/README.md @@ -324,7 +324,7 @@ Please [discover modm's peripheral drivers for your specific device][discover]. Internal Flash ○ -○ +✅ ○ ○ ✅ diff --git a/examples/blue_pill_f103/flash/main.cpp b/examples/blue_pill_f103/flash/main.cpp new file mode 100644 index 0000000000..27a4ebac51 --- /dev/null +++ b/examples/blue_pill_f103/flash/main.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020, Niklas Hauser + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include +#include + +using namespace std::chrono_literals; + +modm::IODeviceWrapper< Usart2, modm::IOBuffer::BlockIfFull > loggerDevice; +modm::log::Logger modm::log::info(loggerDevice); + +// Set the log level +#undef MODM_LOG_LEVEL +#define MODM_LOG_LEVEL modm::log::INFO + +// ---------------------------------------------------------------------------- +int +main() +{ + Board::initialize(); + Usart2::connect(); + Usart2::initialize(); + + MODM_LOG_INFO << "\n\nReboot\n"; + if (not Flash::unlock()) { + MODM_LOG_INFO << "Flash unlock failed!" << modm::endl; + } + + for (uintptr_t offset{0}, sector{255}; offset < Flash::Size; offset += 1) + { + const uint8_t nsector = Flash::getSector(offset); + if (sector != nsector) { + MODM_LOG_INFO << "Sector " << nsector << " found at boundary " << + (Flash::Origin + offset) << modm::endl; + sector = nsector; + } + } + + { + uint32_t err{0}; + const uint8_t sector_start = Flash::getSector(Flash::Size / 2); + const uint8_t sector_end = Flash::getSector(Flash::Size); + MODM_LOG_INFO << "Erasing sectors [" << sector_start << ", " << sector_end << ")" << modm::endl; + MODM_LOG_INFO.flush(); + modm::delay(1s); + + const modm::PreciseTimestamp start = modm::PreciseClock::now(); + + for (uint8_t sector{sector_start}; sector < sector_end; sector++){ + err |= Flash::erase(sector); + } + + const auto diff = (modm::PreciseClock::now() - start); + MODM_LOG_INFO << "Erasing done in " << diff << " with errors: " << err << modm::endl; + MODM_LOG_INFO << "Erasing with " << (Flash::Size/2 / (diff.count() >> 10) ) << "kiB/s" << modm::endl; + MODM_LOG_INFO.flush(); + } + + { + uint32_t err{0}; + const modm::PreciseTimestamp start = modm::PreciseClock::now(); + for (uint32_t dst_addr{Flash::OriginAddr + Flash::Size/2}, src_addr{Flash::OriginAddr}; + src_addr < (Flash::OriginAddr + Flash::Size/2); + src_addr += sizeof(Flash::MaxWordType), dst_addr += sizeof(Flash::MaxWordType)) + { + err |= Flash::program(dst_addr, *(Flash::MaxWordType*)src_addr); + } + + const auto diff = (modm::PreciseClock::now() - start); + MODM_LOG_INFO << "Programming done in " << diff << " with errors: " << err << modm::endl; + MODM_LOG_INFO << "Programming with " << (Flash::Size/2 / (diff.count() >> 10) ) << "kiB/s" << modm::endl; + } + { + uint32_t err{0}; + const modm::PreciseTimestamp start = modm::PreciseClock::now(); + for (uint32_t dst_addr{Flash::OriginAddr + Flash::Size/2}, src_addr{Flash::OriginAddr}; + src_addr < (Flash::OriginAddr + Flash::Size/2); + src_addr += sizeof(Flash::MaxWordType), dst_addr += sizeof(Flash::MaxWordType)) + { + auto dst_addr_ptr = reinterpret_cast(static_cast(dst_addr)); + auto src_addr_ptr = reinterpret_cast(static_cast(src_addr)); + auto dst_val = (*dst_addr_ptr); + auto src_val = (*src_addr_ptr); + if(dst_val != src_val){ + MODM_LOG_INFO << "Error during verification!"; + MODM_LOG_INFO << "Dst: " << dst_addr << " value " << dst_val; + MODM_LOG_INFO << "Src: " << src_addr << " value " << src_val; + ++err; + } + } + const auto diff = (modm::PreciseClock::now() - start); + MODM_LOG_INFO << "Verifying done in " << diff << " with errors: " << err << modm::endl; + MODM_LOG_INFO << "Verifying with " << (Flash::Size/2 / (diff.count() >> 10) ) << "kiB/s" << modm::endl; + } + + while(1) ; + return 0; +} diff --git a/examples/blue_pill_f103/flash/openocd.cfg b/examples/blue_pill_f103/flash/openocd.cfg new file mode 100644 index 0000000000..b157e7e432 --- /dev/null +++ b/examples/blue_pill_f103/flash/openocd.cfg @@ -0,0 +1,2 @@ +# Replace this with your custom programmer +source [find interface/stlink-v2.cfg] diff --git a/examples/blue_pill_f103/flash/project.xml b/examples/blue_pill_f103/flash/project.xml new file mode 100644 index 0000000000..31b1ba5de2 --- /dev/null +++ b/examples/blue_pill_f103/flash/project.xml @@ -0,0 +1,16 @@ + + modm:blue-pill-f103 + + + + + + modm:platform:gpio + modm:platform:flash + modm:debug + modm:platform:uart:2 + modm:processing:timer + modm:build:scons + modm:build:compilation_db + + diff --git a/src/modm/platform/flash/stm32/flash.cpp.in b/src/modm/platform/flash/stm32/flash.cpp.in index 72b528f3e2..3d0af4d602 100644 --- a/src/modm/platform/flash/stm32/flash.cpp.in +++ b/src/modm/platform/flash/stm32/flash.cpp.in @@ -84,19 +84,32 @@ Flash::erase(uint8_t index, WordSize size) Flash::erase(uint8_t index) %% endif { +%% if family != "f1" FLASH->SR = FLASH_SR_ERR; +%% endif %% if has_sectors FLASH->CR = FLASH_CR_STRT | FLASH_CR_SER | uint32_t(size) | ((index << FLASH_CR_SNB_Pos) & FLASH_CR_SNB_Msk); %% else +%% if family == "g0" FLASH->CR = FLASH_CR_STRT | FLASH_CR_PER | ((index << FLASH_CR_PNB_Pos) & FLASH_CR_PNB_Msk); +%% else + FLASH->CR &= ~FLASH_CR_STRT; + FLASH->CR |= FLASH_CR_PER; + FLASH->AR = reinterpret_cast(getAddr(index)); + FLASH->CR |= FLASH_CR_STRT; +%% endif %% endif while(isBusy()) ; +%% if family == "f1" + FLASH->CR &= ~FLASH_CR_PER; + return FLASH->SR & FLASH_SR_PGERR; +%% else FLASH->CR = 0; - return FLASH->SR & FLASH_SR_ERR; +%% endif } modm_ramcode uint32_t @@ -106,7 +119,9 @@ Flash::program(uintptr_t addr, MaxWordType data, WordSize size) Flash::program(uintptr_t addr, MaxWordType data) %% endif { +%% if family != "f1" FLASH->SR = FLASH_SR_ERR; +%% endif %% if has_sectors FLASH->CR = FLASH_CR_PG | uint32_t(size); switch(size) @@ -122,14 +137,26 @@ Flash::program(uintptr_t addr, MaxWordType data) break; } %% else + +%% if family == "f1" + while(isBusy()) ; + FLASH->CR |= FLASH_CR_PG; + *(MaxWordType*) addr = data; +%% else FLASH->CR = FLASH_CR_PG; *(uint64_t*) addr = data; +%% endif %% endif while(isBusy()) ; - FLASH->CR = 0; +%% if family == "f1" + FLASH->CR &= ~FLASH_CR_PG; + return FLASH->SR & FLASH_SR_PGERR; +%% else + FLASH->CR = 0; return FLASH->SR & FLASH_SR_ERR; +%% endif } } // namespace modm::platform diff --git a/src/modm/platform/flash/stm32/flash.hpp.in b/src/modm/platform/flash/stm32/flash.hpp.in index a27b530f68..351b851a2d 100644 --- a/src/modm/platform/flash/stm32/flash.hpp.in +++ b/src/modm/platform/flash/stm32/flash.hpp.in @@ -24,7 +24,11 @@ public: static constexpr uintptr_t OriginAddr{ 0x{{ "%0x" | format(start) }} }; static constexpr size_t Size{ 0x{{ "%0x" | format(size) }} }; static inline uint8_t *const Origin{(uint8_t*)OriginAddr}; +%% if family=="f1" + using MaxWordType = uint16_t; +%% else using MaxWordType = uint{{ 32 if has_sectors else 64 }}_t; +%% endif %% if has_sectors enum class @@ -40,7 +44,7 @@ public: inline static void enable() { -%% if not has_sectors +%% if not has_sectors and family == "g0" Rcc::enable(); %% endif } @@ -48,7 +52,7 @@ public: inline static void disable() { -%% if not has_sectors +%% if not has_sectors and family == "g0" Rcc::disable(); %% endif @@ -60,11 +64,7 @@ public: static inline bool isBusy() -%% if has_sectors - { return FLASH->SR & FLASH_SR_BSY; } -%% else - { return FLASH->SR & FLASH_SR_BSY1; } -%% endif + { return FLASH->SR & {{ busy_bit }}; } static bool unlock(); diff --git a/src/modm/platform/flash/stm32/module.lb b/src/modm/platform/flash/stm32/module.lb index f7c266d61c..4d08718477 100644 --- a/src/modm/platform/flash/stm32/module.lb +++ b/src/modm/platform/flash/stm32/module.lb @@ -17,7 +17,7 @@ def init(module): def prepare(module, options): device = options[":target"] - if device.identifier.family not in ["g0", "f4"]: + if device.identifier.family not in ["g0", "f1", "f4"]: return False if not device.has_driver("flash:stm32*"): return False @@ -31,12 +31,19 @@ def build(env): memories = listify(env[":target"].get_driver("core")["memory"]) flash = next(filter(lambda m: m["name"] == "flash", memories)) + family = target.family if target.family in ["f4"]: block_shift = 17 ftype = "sector" + busy_bit = "FLASH_SR_BSY" + elif target.family in ["f1"]: + block_shift = 10 + ftype = "page" + busy_bit = "FLASH_SR_BSY" elif target.family in ["g0"]: block_shift = 11 ftype = "page" + busy_bit = "FLASH_SR_BSY1" env.substitutions = { "start": int(flash["start"], 16), @@ -44,6 +51,8 @@ def build(env): "type": ftype, "shift": block_shift, "has_sectors": ftype == "sector", + "busy_bit": busy_bit, + "family": family } env.outbasepath = "modm/src/modm/platform/flash" env.template("flash.hpp.in")