summaryrefslogtreecommitdiff
path: root/ports/stm/supervisor
diff options
context:
space:
mode:
authorLucian Copeland <hierophect@gmail.com>2020-03-28 18:30:46 -0400
committerLucian Copeland <hierophect@gmail.com>2020-03-28 18:30:46 -0400
commite2be0696865992cda67f5bdeba5aeb5b4c2fdcd4 (patch)
tree64547a2302df6d301ab0a5e85b461f9d8fe3f38e /ports/stm/supervisor
parent7995bcac4009d2b3e20f42a26de72d5411e7e462 (diff)
Support cached internal flash on the H743
Diffstat (limited to 'ports/stm/supervisor')
-rw-r--r--ports/stm/supervisor/internal_flash.c241
-rw-r--r--ports/stm/supervisor/internal_flash.h28
2 files changed, 150 insertions, 119 deletions
diff --git a/ports/stm/supervisor/internal_flash.c b/ports/stm/supervisor/internal_flash.c
index 46ccd218c..003ccdd90 100644
--- a/ports/stm/supervisor/internal_flash.c
+++ b/ports/stm/supervisor/internal_flash.c
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
- * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -35,6 +35,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "lib/oofatfs/ff.h"
+#include "supervisor/shared/safe_mode.h"
typedef struct {
uint32_t base_address;
@@ -46,7 +47,9 @@ typedef struct {
/* Internal Flash API
*------------------------------------------------------------------*/
-static const flash_layout_t flash_layout[] = {
+#if defined(STM32F4)
+
+STATIC const flash_layout_t flash_layout[] = {
{ 0x08000000, 0x04000, 4 },
{ 0x08010000, 0x10000, 1 },
{ 0x08020000, 0x20000, 3 },
@@ -59,12 +62,45 @@ static const flash_layout_t flash_layout[] = {
{ 0x08120000, 0x20000, 7 },
#endif
};
+STATIC uint8_t _flash_cache[0x4000] __attribute__((aligned(4)));
+
+#elif defined(STM32H7)
+
+STATIC const flash_layout_t flash_layout[] = {
+ { 0x08000000, 0x20000, 16 },
+};
+STATIC uint8_t _flash_cache[0x20000] __attribute__((aligned(4)));
+
+#else
+ #error Unsupported processor
+#endif
#define NO_CACHE 0xffffffff
#define MAX_CACHE 0x4000
-static uint8_t _flash_cache[0x4000] __attribute__((aligned(4)));
-static uint32_t _cache_flash_addr = NO_CACHE;
+
+STATIC uint32_t _cache_flash_addr = NO_CACHE;
+
+#if defined(STM32H7)
+// get the bank of a given flash address
+STATIC uint32_t get_bank(uint32_t addr) {
+ if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_SWAP_BANK) == 0) {
+ // no bank swap
+ if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
+ return FLASH_BANK_1;
+ } else {
+ return FLASH_BANK_2;
+ }
+ } else {
+ // bank swap
+ if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) {
+ return FLASH_BANK_2;
+ } else {
+ return FLASH_BANK_1;
+ }
+ }
+}
+#endif
//Return the sector of a given flash address.
uint32_t flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size) {
@@ -105,50 +141,98 @@ uint32_t supervisor_flash_get_block_count(void) {
void supervisor_flash_flush(void) {
if (_cache_flash_addr == NO_CACHE) return;
+ #if defined(STM32H7)
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2);
+ #else
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
+ FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
+ #endif
+
+ // set up for erase
+ FLASH_EraseInitTypeDef EraseInitStruct;
+ EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
+ EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V
+ // get the sector information
+ uint32_t sector_size;
+ uint32_t sector_start_addr;
+ #if defined(STM32H7)
+ EraseInitStruct.Banks = get_bank(_cache_flash_addr);
+ #endif
+ EraseInitStruct.Sector = flash_get_sector_info(_cache_flash_addr, &sector_start_addr, &sector_size);
+ EraseInitStruct.NbSectors = 1;
+ if (sector_size > sizeof(_flash_cache)) {
+ __ASM volatile ("bkpt");
+ mp_printf(&mp_plat_print, "FLASH ERR: invalid sector\n");
+ reset_into_safe_mode(FLASH_WRITE_FAIL);
+ }
+
// Skip if data is the same
- if (memcmp(_flash_cache, (void *)_flash_page_addr, FLASH_PAGE_SIZE) != 0) {
+ if (memcmp(_flash_cache, (void *)_cache_flash_addr, sector_size) != 0) {
// unlock flash
HAL_FLASH_Unlock();
- // set up for erase
- FLASH_EraseInitTypeDef EraseInitStruct;
- EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
- EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V
- // get the sector information
- uint32_t sector_size;
- uint32_t sector_start_addr;
- EraseInitStruct.Sector = flash_get_sector_info(_cache_flash_addr, &sector_start_addr, &sector_size);
- EraseInitStruct.NbSectors = 1;
- if (sector_size>0x4000) return false;
-
// erase the sector
uint32_t SectorError = 0;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
// error occurred during sector erase
HAL_FLASH_Lock(); // lock the flash
- mp_printf(&mp_plat_print, "FLASH SECTOR ERASE ERROR");
- return false;
+ __ASM volatile ("bkpt");
+ mp_printf(&mp_plat_print, "FLASH ERR: erase failure\n");
+ reset_into_safe_mode(FLASH_WRITE_FAIL);
}
- __HAL_FLASH_DATA_CACHE_DISABLE();
- __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
-
- __HAL_FLASH_DATA_CACHE_RESET();
- __HAL_FLASH_INSTRUCTION_CACHE_RESET();
-
- __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
- __HAL_FLASH_DATA_CACHE_ENABLE();
+ // __HAL_FLASH_DATA_CACHE_DISABLE();
+ // __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
+
+ // __HAL_FLASH_DATA_CACHE_RESET();
+ // __HAL_FLASH_INSTRUCTION_CACHE_RESET();
+
+ // __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
+ // __HAL_FLASH_DATA_CACHE_ENABLE();
+
+ // // reprogram the sector
+ // for (uint32_t i = 0; i < sector_size; i++) {
+ // if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, sector_start_addr, (uint64_t)_flash_cache[i]) != HAL_OK) {
+ // // error occurred during flash write
+ // HAL_FLASH_Lock(); // lock the flash
+ // mp_printf(&mp_plat_print, "FLASH WRITE ERROR");
+ // }
+ // sector_start_addr += 1;
+ // }
+
+ uint32_t * cache_addr = (uint32_t*)_flash_cache;
+
+ #if defined(STM32H7)
+ for (uint32_t i = 0; i < (sector_size / 32); i++) {
+ // Note that the STM32H7 HAL interface differs by taking an address, not 64 bit data
+ // This is because ST's code is written by a large room of chimpanzees
+ if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, sector_start_addr,
+ (uint32_t)cache_addr) != HAL_OK) {
+ // error occurred during flash write
+ HAL_FLASH_Lock(); // lock the flash
+ __ASM volatile ("bkpt");
+ reset_into_safe_mode(FLASH_WRITE_FAIL);
+ }
+ // RAM memory is by word (4 byte), but flash memory is by byte
+ cache_addr += 8;
+ sector_start_addr += 32;
+ }
- // reprogram the sector
- for (uint32_t i = 0; i < sector_size; i++) {
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, sector_start_addr, (uint64_t)_flash_cache[i]) != HAL_OK) {
+ #else // STM32F4
+ // program the flash word by word
+ for (uint32_t i = 0; i < sector_size / 4; i++) {
+ if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, sector_start_addr,
+ (uint64_t)*cache_addr) != HAL_OK) {
// error occurred during flash write
HAL_FLASH_Lock(); // lock the flash
- mp_printf(&mp_plat_print, "FLASH WRITE ERROR");
- return false;
+ __ASM volatile ("bkpt");
+ reset_into_safe_mode(FLASH_WRITE_FAIL);
}
- sector_start_addr += 1;
+ // RAM memory is by word (4 byte), but flash memory is by byte
+ cache_addr += 1;
+ sector_start_addr += 4;
}
+ #endif
// lock the flash
HAL_FLASH_Lock();
@@ -165,6 +249,9 @@ static int32_t convert_block_to_flash_addr(uint32_t block) {
}
mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
+ // Must write out anything in cache before trying to read.
+ supervisor_flash_flush();
+
int32_t src = convert_block_to_flash_addr(block);
if (src == -1) {
// bad block number
@@ -174,88 +261,12 @@ mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t n
return 0; // success
}
-bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) {
- int32_t dest = convert_block_to_flash_addr(block);
- if (dest == -1) {
- // bad block number
- mp_printf(&mp_plat_print, "BAD FLASH BLOCK ERROR");
- return false;
- }
-
- // unlock flash
- HAL_FLASH_Unlock();
-
- // set up for erase
- FLASH_EraseInitTypeDef EraseInitStruct;
- EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
- EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V
- // get the sector information
- uint32_t sector_size;
- uint32_t sector_start_addr;
- EraseInitStruct.Sector = flash_get_sector_info(dest, &sector_start_addr, &sector_size);
- EraseInitStruct.NbSectors = 1;
- if (sector_size>0x4000) return false;
-
- // copy the sector
- memcpy(sector_copy,(void *)sector_start_addr,sector_size);
-
- // // overwrite sector data
- memcpy(sector_copy+(dest-sector_start_addr),src,FILESYSTEM_BLOCK_SIZE);
-
- // find end address, subtract for number of sectors
- // Shouldn't be required since blocks will always fit in a single sector, they should never overlap
- //EraseInitStruct.NbSectors = flash_get_sector_info(dest + FILESYSTEM_BLOCK_SIZE - 1, NULL, NULL) - EraseInitStruct.Sector + 1;
-
- // erase the sector
- uint32_t SectorError = 0;
- if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
- // error occurred during sector erase
- HAL_FLASH_Lock(); // lock the flash
- mp_printf(&mp_plat_print, "FLASH SECTOR ERASE ERROR");
- return false;
- }
-
- __HAL_FLASH_DATA_CACHE_DISABLE();
- __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
-
- __HAL_FLASH_DATA_CACHE_RESET();
- __HAL_FLASH_INSTRUCTION_CACHE_RESET();
-
- __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
- __HAL_FLASH_DATA_CACHE_ENABLE();
-
- // reprogram the sector
- for (uint32_t i = 0; i < sector_size; i++) {
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, sector_start_addr, (uint64_t)sector_copy[i]) != HAL_OK) {
- // error occurred during flash write
- HAL_FLASH_Lock(); // lock the flash
- mp_printf(&mp_plat_print, "FLASH WRITE ERROR");
- return false;
- }
- sector_start_addr += 1;
- }
-
- // lock the flash
- HAL_FLASH_Lock();
-
- return true;
-}
-
-// mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
-
-// for (size_t i = 0; i < num_blocks; i++) {
-// if (!supervisor_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) {
-// return 1; // error
-// }
-// }
-// return 0; // success
-// }
-
mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
while (num_blocks) {
- int32_t dest = convert_block_to_flash_addr(block);
+ int32_t dest = convert_block_to_flash_addr(block_num);
if (dest == -1) {
// bad block number
+ __ASM volatile ("bkpt");
mp_printf(&mp_plat_print, "BAD FLASH BLOCK ERROR");
return false;
}
@@ -263,14 +274,20 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num,
// unlock flash
HAL_FLASH_Unlock();
+ uint32_t sector_size;
+ uint32_t sector_start_addr;
flash_get_sector_info(dest, &sector_start_addr, &sector_size);
// Fail for any sector outside the 16k ones for now
- if (sector_size > 0x4000) return false;
+ if (sector_size > sizeof(_flash_cache)) {
+ __ASM volatile ("bkpt");
+ mp_printf(&mp_plat_print, "FLASH ERR: invalid sector\n");
+ reset_into_safe_mode(FLASH_WRITE_FAIL);
+ }
// Find how many blocks are left in the sector
uint32_t count = (sector_size - (dest - sector_start_addr))/FILESYSTEM_BLOCK_SIZE;
- count = MIN(num_blocks, count); `
+ count = MIN(num_blocks, count);
if (_cache_flash_addr != sector_start_addr) {
// Write out anything in cache before overwriting it.
diff --git a/ports/stm/supervisor/internal_flash.h b/ports/stm/supervisor/internal_flash.h
index 859470ff0..37f0b25e4 100644
--- a/ports/stm/supervisor/internal_flash.h
+++ b/ports/stm/supervisor/internal_flash.h
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
- * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,8 +24,8 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_H
-#define MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_H
+#ifndef MICROPY_INCLUDED_STM32_INTERNAL_FLASH_H
+#define MICROPY_INCLUDED_STM32_INTERNAL_FLASH_H
#include <stdbool.h>
#include <stdint.h>
@@ -35,6 +35,8 @@
#ifdef STM32F401xE
#define STM32_FLASH_SIZE 0x80000 //512KiB
#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
+#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
+#define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE)
#endif
#ifdef STM32F411xE
@@ -43,30 +45,42 @@
#define INTERNAL_FLASH_FILESYSTEM_SIZE 0x8000 //32KiB
#else
#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
+#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
+#define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE)
#endif
#endif
#ifdef STM32F412Zx
#define STM32_FLASH_SIZE 0x100000 //1MB
#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
+#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
+#define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE)
#endif
#ifdef STM32F405xx
#define STM32_FLASH_SIZE 0x100000 //1MB
#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
+#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
+#define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE)
#endif
#ifdef STM32F407xx
#define STM32_FLASH_SIZE 0x100000 //1MB
#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
+#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
+#define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE)
#endif
-#define STM32_FLASH_OFFSET 0x8000000 //All STM32 chips map to this flash location
-
-#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
+#ifdef STM32H743xx
+#define STM32_FLASH_SIZE 0x200000 //2MB
+#define INTERNAL_FLASH_FILESYSTEM_SIZE 0x20000 //128KiB
+#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08020000
#define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE)
+#endif
+
+#define STM32_FLASH_OFFSET 0x8000000 //All STM32 chips map to this flash location
#define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms
#define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2)
-#endif // MICROPY_INCLUDED_STM32F4_INTERNAL_FLASH_H
+#endif // MICROPY_INCLUDED_STM32_INTERNAL_FLASH_H