Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stm32] Flash driver enabled for F1 family #745

Merged
merged 1 commit into from
Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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