Skip to content

Commit

Permalink
[stm32] Flash driver enabled for F1 family
Browse files Browse the repository at this point in the history
Signed-off-by: delphi <cpp.create@gmail.com>
  • Loading branch information
ASMfreaK committed Oct 10, 2021
1 parent 38120ec commit f4c7492
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 11 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -324,7 +324,7 @@ Please [discover modm's peripheral drivers for your specific device][discover].
</tr><tr>
<td align="left">Internal Flash</td>
<td align="center">○</td>
<td align="center"></td>
<td align="center"></td>
<td align="center">○</td>
<td align="center">○</td>
<td align="center">✅</td>
Expand Down
106 changes: 106 additions & 0 deletions 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 <modm/board.hpp>
#include <modm/debug.hpp>
#include <modm/processing.hpp>

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<GpioOutputA2::Tx, GpioOutputA3::Rx>();
Usart2::initialize<Board::SystemClock, 115200_Bd>();

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<uint8_t*>(static_cast<std::uintptr_t>(dst_addr));
auto src_addr_ptr = reinterpret_cast<uint8_t*>(static_cast<std::uintptr_t>(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;
}
2 changes: 2 additions & 0 deletions examples/blue_pill_f103/flash/openocd.cfg
@@ -0,0 +1,2 @@
# Replace this with your custom programmer
source [find interface/stlink-v2.cfg]
16 changes: 16 additions & 0 deletions examples/blue_pill_f103/flash/project.xml
@@ -0,0 +1,16 @@
<library>
<extends>modm:blue-pill-f103</extends>
<options>
<option name="modm:build:build.path">../../../build/blue_pill_f103/flash</option>
<option name="modm:build:openocd.cfg">openocd.cfg</option>
</options>
<modules>
<module>modm:platform:gpio</module>
<module>modm:platform:flash</module>
<module>modm:debug</module>
<module>modm:platform:uart:2</module>
<module>modm:processing:timer</module>
<module>modm:build:scons</module>
<module>modm:build:compilation_db</module>
</modules>
</library>
31 changes: 29 additions & 2 deletions src/modm/platform/flash/stm32/flash.cpp.in
Expand Up @@ -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<std::uintptr_t>(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
Expand All @@ -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)
Expand All @@ -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
14 changes: 7 additions & 7 deletions src/modm/platform/flash/stm32/flash.hpp.in
Expand Up @@ -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
Expand All @@ -40,15 +44,15 @@ public:
inline static void
enable()
{
%% if not has_sectors
%% if not has_sectors and family == "g0"
Rcc::enable<Peripheral::Flash>();
%% endif
}

inline static void
disable()
{
%% if not has_sectors
%% if not has_sectors and family == "g0"
Rcc::disable<Peripheral::Flash>();
%% endif

Expand All @@ -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();
Expand Down
11 changes: 10 additions & 1 deletion src/modm/platform/flash/stm32/module.lb
Expand Up @@ -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
Expand All @@ -31,19 +31,28 @@ 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),
"size": int(flash["size"]),
"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")
Expand Down

0 comments on commit f4c7492

Please sign in to comment.