From d6daa720f563825f35bf347dfd6948109e40bc5f Mon Sep 17 00:00:00 2001 From: Tilman Sauerbeck Date: Sun, 10 Nov 2019 18:58:44 +0100 Subject: [PATCH] bootloader: Reimplement flash::run_command() in C. While running a flash command that operates on a given flash block, executing code from that same flash block will cause read-while-write errors that lock up the core. Thus we need to ensure that no interrupt handler will execute during that time, and we also need to relocate the respective flash code to RAM. --- SConscript.libcommon | 1 + src/bootloader/flash.rs | 19 ++++--------- src/common/flash.c | 59 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 src/common/flash.c diff --git a/SConscript.libcommon b/SConscript.libcommon index a8534c8..3e229c2 100644 --- a/SConscript.libcommon +++ b/SConscript.libcommon @@ -18,6 +18,7 @@ source_files_c = [ 'src/common/startup.c', 'src/common/systick.c', 'src/common/ringbuf.c', + 'src/common/flash.c', 'src/common/usb_device_ch9.c', 'src/common/usb_device_dci.c', 'src/common/usb_device_descriptor.c', diff --git a/src/bootloader/flash.rs b/src/bootloader/flash.rs index f6c00d9..7d0d294 100644 --- a/src/bootloader/flash.rs +++ b/src/bootloader/flash.rs @@ -41,7 +41,6 @@ const FTFA_FSTAT_MGSTAT0 : u8 = 1 << 0; const FTFA_FSTAT_FPVIOL : u8 = 1 << 4; const FTFA_FSTAT_ACCERR : u8 = 1 << 5; const FTFA_FSTAT_RDCOLERR: u8 = 1 << 6; -const FTFA_FSTAT_CCIF : u8 = 1 << 7; const FCMD_RD1SEC : u8 = 0x01; const FCMD_PGM4 : u8 = 0x06; @@ -49,6 +48,10 @@ const FCMD_ERSSCR : u8 = 0x09; pub const SECTOR_SIZE : usize = 1024; +extern { + fn flash_run_command() -> u8; +} + // The hardware refuses to run another command (or even take the new command's // parameters) until the errors reported by a previous command have been // acknowledged (see KL26P121M48SF4RM.pdf p. 445). @@ -59,19 +62,7 @@ fn prepare_command() { } fn run_command() -> u8 { - let mut fstat = Reg8::new(FTFA_FSTAT); - - // Start command. - fstat.write(FTFA_FSTAT_CCIF); - - // Wait for it to finish. - loop { - let v = fstat.read(); - - if (v & FTFA_FSTAT_CCIF) != 0 { - return v; - } - } + unsafe { flash_run_command() } } fn erase_check(sector: u32) -> bool { diff --git a/src/common/flash.c b/src/common/flash.c new file mode 100644 index 0000000..3dff454 --- /dev/null +++ b/src/common/flash.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 Tilman Sauerbeck (tilman at code-monkey de) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +static const uint32_t FTFA_FSTAT = 0x40020000; + +static const uint8_t FTFA_FSTAT_CCIF = 1 << 7; + +__attribute__((section(".data"))) +static uint8_t +run_command(void) +{ + volatile uint8_t *fstat = (uint8_t *) FTFA_FSTAT; + + /* Start command. */ + *fstat = FTFA_FSTAT_CCIF; + + /* Wait for it to finish. */ + for (;;) { + uint8_t v = *fstat; + + if ((v & FTFA_FSTAT_CCIF) != 0) { + return v; + } + } +} + +uint8_t +flash_run_command(void) +{ + asm volatile ("cpsid i"); + + uint8_t status = run_command(); + + asm volatile ("cpsie i"); + + return status; +} -- 2.30.2