From dcd72a87f9338ee0af89f9b7d01c1ea417beaf08 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Fri, 26 Feb 2021 12:38:17 -1000 Subject: [PATCH] H7 flash (#2408) * enable * defines and mpu util * implement flash for h7 * format --- firmware/config/stm32h7ems/efifeatures.h | 3 - firmware/hw_layer/flash_int.h | 2 +- firmware/hw_layer/ports/stm32/flash_int.c | 125 ++++++++++++++---- firmware/hw_layer/ports/stm32/stm32h7/board.h | 6 + .../hw_layer/ports/stm32/stm32h7/mpu_util.cpp | 21 +++ 5 files changed, 130 insertions(+), 27 deletions(-) diff --git a/firmware/config/stm32h7ems/efifeatures.h b/firmware/config/stm32h7ems/efifeatures.h index 58fd2c64f9..7766d6467f 100644 --- a/firmware/config/stm32h7ems/efifeatures.h +++ b/firmware/config/stm32h7ems/efifeatures.h @@ -2,9 +2,6 @@ #pragma once -#undef EFI_INTERNAL_FLASH -#define EFI_INTERNAL_FLASH FALSE - #undef EFI_MC33816 #define EFI_MC33816 FALSE diff --git a/firmware/hw_layer/flash_int.h b/firmware/hw_layer/flash_int.h index 8b658c00aa..4b41ef3588 100644 --- a/firmware/hw_layer/flash_int.h +++ b/firmware/hw_layer/flash_int.h @@ -35,7 +35,7 @@ extern "C" { * 11 to program 64 bits per step */ // Warning, flashdata_t must be unsigned!!! -#if defined(STM32F4XX) || defined(STM32F7XX) +#if defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32H7XX) #define FLASH_CR_PSIZE_MASK FLASH_CR_PSIZE_0 | FLASH_CR_PSIZE_1 #if ((STM32_VDD >= 270) && (STM32_VDD <= 360)) #define FLASH_CR_PSIZE_VALUE FLASH_CR_PSIZE_1 diff --git a/firmware/hw_layer/ports/stm32/flash_int.c b/firmware/hw_layer/ports/stm32/flash_int.c index 76954d4d74..0a4de81967 100644 --- a/firmware/hw_layer/ports/stm32/flash_int.c +++ b/firmware/hw_layer/ports/stm32/flash_int.c @@ -15,6 +15,30 @@ #include "flash_int.h" #include +#ifdef STM32H7XX + // Use bank 2 on H7 + #define FLASH_CR FLASH->CR2 + #define FLASH_SR FLASH->SR2 + #define FLASH_KEYR FLASH->KEYR2 + + // I have no idea why ST changed the register name from STRT -> START + #define FLASH_CR_STRT FLASH_CR_START + + #undef FLASH_BASE + // This is the start of the second bank, since H7 sector numbers are bank relative + #define FLASH_BASE 0x08100000 + + // QW bit supercedes the older BSY bit + #define intFlashWaitWhileBusy() { while (FLASH_SR & FLASH_SR_QW) {} } +#else + #define FLASH_CR FLASH->CR + #define FLASH_SR FLASH->SR + #define FLASH_KEYR FLASH->KEYR + + // Wait for the flash operation to finish + #define intFlashWaitWhileBusy() { while (FLASH->SR & FLASH_SR_BSY) {} } +#endif + flashaddr_t intFlashSectorBegin(flashsector_t sector) { flashaddr_t address = FLASH_BASE; while (sector > 0) { @@ -35,11 +59,6 @@ flashsector_t intFlashSectorAt(flashaddr_t address) { return sector; } -/** - * @brief Wait for the flash operation to finish. - */ -#define intFlashWaitWhileBusy() { while (FLASH->SR & FLASH_SR_BSY) {} } - /** * @brief Unlock the flash memory for write access. * @return HAL_SUCCESS Unlock was successful. @@ -47,15 +66,15 @@ flashsector_t intFlashSectorAt(flashaddr_t address) { */ static bool intFlashUnlock(void) { /* Check if unlock is really needed */ - if (!(FLASH->CR & FLASH_CR_LOCK)) + if (!(FLASH_CR & FLASH_CR_LOCK)) return HAL_SUCCESS; /* Write magic unlock sequence */ - FLASH->KEYR = 0x45670123; - FLASH->KEYR = 0xCDEF89AB; + FLASH_KEYR = 0x45670123; + FLASH_KEYR = 0xCDEF89AB; /* Check if unlock was successful */ - if (FLASH->CR & FLASH_CR_LOCK) + if (FLASH_CR & FLASH_CR_LOCK) return HAL_FAILED; return HAL_SUCCESS; } @@ -63,7 +82,7 @@ static bool intFlashUnlock(void) { /** * @brief Lock the flash memory for write access. */ -#define intFlashLock() { FLASH->CR |= FLASH_CR_LOCK; } +#define intFlashLock() { FLASH_CR |= FLASH_CR_LOCK; } int intFlashSectorErase(flashsector_t sector) { /* Unlock flash for write access */ @@ -74,8 +93,8 @@ int intFlashSectorErase(flashsector_t sector) { intFlashWaitWhileBusy(); /* Setup parallelism before any program/erase */ - FLASH->CR &= ~FLASH_CR_PSIZE_MASK; - FLASH->CR |= FLASH_CR_PSIZE_VALUE; + FLASH_CR &= ~FLASH_CR_PSIZE_MASK; + FLASH_CR |= FLASH_CR_PSIZE_VALUE; /* Start deletion of sector. * SNB(4:1) is defined as: @@ -87,31 +106,35 @@ int intFlashSectorErase(flashsector_t sector) { * ... * 10111 sector 23 (the end of 2nd bank, 2Mb border) * others not allowed */ -#ifndef FLASH_CR_SNB_4 - FLASH->CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3); +#ifndef FLASH_CR_SNB_3 + FLASH_CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2); +#elif !defined(FLASH_CR_SNB_4) + FLASH_CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3); #else - FLASH->CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3 | FLASH_CR_SNB_4); + FLASH_CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3 | FLASH_CR_SNB_4); #endif if (sector & 0x1) - FLASH->CR |= FLASH_CR_SNB_0; + FLASH_CR |= FLASH_CR_SNB_0; if (sector & 0x2) - FLASH->CR |= FLASH_CR_SNB_1; + FLASH_CR |= FLASH_CR_SNB_1; if (sector & 0x4) - FLASH->CR |= FLASH_CR_SNB_2; + FLASH_CR |= FLASH_CR_SNB_2; +#ifdef FLASH_CR_SNB_4 if (sector & 0x8) - FLASH->CR |= FLASH_CR_SNB_3; + FLASH_CR |= FLASH_CR_SNB_3; +#endif #ifdef FLASH_CR_SNB_4 if (sector & 0x10) - FLASH->CR |= FLASH_CR_SNB_4; + FLASH_CR |= FLASH_CR_SNB_4; #endif - FLASH->CR |= FLASH_CR_SER; - FLASH->CR |= FLASH_CR_STRT; + FLASH_CR |= FLASH_CR_SER; + FLASH_CR |= FLASH_CR_STRT; /* Wait until it's finished. */ intFlashWaitWhileBusy(); /* Sector erase flag does not clear automatically. */ - FLASH->CR &= ~FLASH_CR_SER; + FLASH_CR &= ~FLASH_CR_SER; /* Lock flash again */ intFlashLock() @@ -187,6 +210,61 @@ int intFlashRead(flashaddr_t address, char* buffer, size_t size) { return FLASH_RETURN_SUCCESS; } +#ifdef STM32H7XX +int intFlashWrite(flashaddr_t address, const char* buffer, size_t size) { + /* Unlock flash for write access */ + if (intFlashUnlock() == HAL_FAILED) + return FLASH_RETURN_NO_PERMISSION; + + /* Wait for any busy flags */ + intFlashWaitWhileBusy(); + + /* Setup parallelism before program */ + FLASH_CR &= ~FLASH_CR_PSIZE_MASK; + FLASH_CR |= FLASH_CR_PSIZE_VALUE; + + // Round up to the next number of full 32 byte words + size_t flashWordCount = (size - 1) / 32 + 1; + + // Read units of flashdata_t from the buffer, writing to flash + const flashdata_t* pRead = (const flashdata_t*)buffer; + flashdata_t* pWrite = (flashdata_t*)address; + + for (size_t word = 0; word < flashWordCount; word++) { + /* Enter flash programming mode */ + FLASH_CR |= FLASH_CR_PG; + + // Flush pipelines + __ISB(); + __DSB(); + + // Write 32 bytes + for (size_t i = 0; i < 8; i++) { + *pWrite++ = *pRead++; + } + + // Flush pipelines + __ISB(); + __DSB(); + + /* Wait for completion */ + intFlashWaitWhileBusy(); + + /* Exit flash programming mode */ + FLASH_CR &= ~FLASH_CR_PG; + + // Flush pipelines + __ISB(); + __DSB(); + } + + /* Lock flash again */ + intFlashLock(); + + return FLASH_RETURN_SUCCESS; +} + +#else // not STM32H7XX static void intFlashWriteData(flashaddr_t address, const flashdata_t data) { /* Enter flash programming mode */ FLASH->CR |= FLASH_CR_PG; @@ -276,5 +354,6 @@ int intFlashWrite(flashaddr_t address, const char* buffer, size_t size) { return FLASH_RETURN_SUCCESS; } +#endif #endif /* EFI_INTERNAL_FLASH */ diff --git a/firmware/hw_layer/ports/stm32/stm32h7/board.h b/firmware/hw_layer/ports/stm32/stm32h7/board.h index 97af35b48b..27f5d9a31d 100644 --- a/firmware/hw_layer/ports/stm32/stm32h7/board.h +++ b/firmware/hw_layer/ports/stm32/stm32h7/board.h @@ -76,6 +76,12 @@ #define STM32_HSE_BYPASS #endif /* EFI_USE_OSC */ +/* + * Board voltages. + * Required for performance limits calculation. + */ +#define STM32_VDD 330U + /* * MCU type as defined in the ST header. */ diff --git a/firmware/hw_layer/ports/stm32/stm32h7/mpu_util.cpp b/firmware/hw_layer/ports/stm32/stm32h7/mpu_util.cpp index 8b13789179..f880cbab0a 100644 --- a/firmware/hw_layer/ports/stm32/stm32h7/mpu_util.cpp +++ b/firmware/hw_layer/ports/stm32/stm32h7/mpu_util.cpp @@ -1 +1,22 @@ +/** + * @file mpu_util.cpp + * + * @date Feb 26, 2021 + * @author Matthew Kennedy, (c) 2021 + */ +#include "flash_int.h" + +size_t flashSectorSize(flashsector_t sector) { + // All sectors on H7 are 128k + return 128 * 1024; +} + +uintptr_t getFlashAddrFirstCopy() { + return 0x08100000; +} + +uintptr_t getFlashAddrSecondCopy() { + // Second copy is one sector past the first + return getFlashAddrFirstCopy() + 128 * 1024; +}