eeprom_stm32: implement high density wear leveling (#12567)

* eeprom_stm32: implement wear leveling
Update EECONFIG_MAGIC_NUMBER
eeprom_stm32: check emulated eeprom size is large enough
* eeprom_stm32: Increasing simulated EEPROM density on stm32
* Adding utility script to decode emulated eeprom
* Adding unit tests
* Applying qmk cformat changes
* cleaned up flash mocking
* Fix for stm32eeprom_parser.py checking via signature with wrong base
* Fix for nk65 keyboard

Co-authored-by: Ilya Zhuravlev <whatever@xyz.is>
Co-authored-by: zvecr <git@zvecr.com>
This commit is contained in:
Donald Kjer
2021-08-23 23:15:34 +01:00
committed by GitHub
co-authored by Ilya Zhuravlev zvecr
parent 2481e109a0
commit e756a21636
12 changed files with 1549 additions and 197 deletions
+1
View File
@@ -56,6 +56,7 @@ include $(TMK_PATH)/common.mk
include $(QUANTUM_PATH)/debounce/tests/rules.mk
include $(QUANTUM_PATH)/sequencer/tests/rules.mk
include $(QUANTUM_PATH)/serial_link/tests/rules.mk
include $(TMK_PATH)/common/test/rules.mk
ifneq ($(filter $(FULL_TESTS),$(TEST)),)
include build_full_test.mk
endif
+3
View File
@@ -148,6 +148,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* both 128kb and 256kb versions of F303.
* Register 0x1FFFF7CC holds the size of the flash memory.
*/
#ifndef FLASHSIZE_BASE
# define FLASHSIZE_BASE ((uint32_t)0x1FFFF7CCU) /*!< FLASH Size register base address */
#endif
#define EEPROM_START_ADDRESS
#define FEE_MCU_FLASH_SIZE \
({ \
+1 -1
View File
@@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdbool.h>
#ifndef EECONFIG_MAGIC_NUMBER
# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEEA // When changing, decrement this value to avoid future re-init issues
# define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEE9 // When changing, decrement this value to avoid future re-init issues
#endif
#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF
+1
View File
@@ -4,6 +4,7 @@ FULL_TESTS := $(TEST_LIST)
include $(ROOT_DIR)/quantum/debounce/tests/testlist.mk
include $(ROOT_DIR)/quantum/sequencer/tests/testlist.mk
include $(ROOT_DIR)/quantum/serial_link/tests/testlist.mk
include $(ROOT_DIR)/tmk_core/common/test/testlist.mk
define VALIDATE_TEST_LIST
ifneq ($1,)
File diff suppressed because it is too large Load Diff
+5 -56
View File
@@ -23,62 +23,11 @@
#pragma once
#include <ch.h>
#include <hal.h>
#include "flash_stm32.h"
// HACK ALERT. This definition may not match your processor
// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc
#if defined(EEPROM_EMU_STM32F303xC)
# define MCU_STM32F303CC
#elif defined(EEPROM_EMU_STM32F103xB)
# define MCU_STM32F103RB
#elif defined(EEPROM_EMU_STM32F072xB)
# define MCU_STM32F072CB
#elif defined(EEPROM_EMU_STM32F042x6)
# define MCU_STM32F042K6
#else
# error "not implemented."
#endif
#ifndef EEPROM_PAGE_SIZE
# if defined(MCU_STM32F103RB) || defined(MCU_STM32F042K6)
# define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte
# define FEE_DENSITY_PAGES 2 // How many pages are used
# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE) || defined(MCU_STM32F103RD) || defined(MCU_STM32F303CC) || defined(MCU_STM32F072CB)
# define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte
# define FEE_DENSITY_PAGES 4 // How many pages are used
# else
# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
# endif
#endif
#ifndef EEPROM_START_ADDRESS
# if defined(MCU_STM32F103RB) || defined(MCU_STM32F072CB)
# define FEE_MCU_FLASH_SIZE 128 // Size in Kb
# elif defined(MCU_STM32F042K6)
# define FEE_MCU_FLASH_SIZE 32 // Size in Kb
# elif defined(MCU_STM32F103ZE) || defined(MCU_STM32F103RE)
# define FEE_MCU_FLASH_SIZE 512 // Size in Kb
# elif defined(MCU_STM32F103RD)
# define FEE_MCU_FLASH_SIZE 384 // Size in Kb
# elif defined(MCU_STM32F303CC)
# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
# else
# error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
# endif
#endif
// DONT CHANGE
// Choose location for the first EEPROM Page address on the top of flash
#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE))
#define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1)
#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES))
#define FEE_EMPTY_WORD ((uint16_t)0xFFFF)
#define FEE_ADDR_OFFSET(Address) (Address * 2) // 1Byte per Word will be saved to preserve Flash
// Use this function to initialize the functionality
uint16_t EEPROM_Init(void);
void EEPROM_Erase(void);
uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte);
uint8_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte);
uint8_t EEPROM_WriteDataWord(uint16_t Address, uint16_t DataWord);
uint8_t EEPROM_ReadDataByte(uint16_t Address);
uint16_t EEPROM_ReadDataWord(uint16_t Address);
void print_eeprom(void);
+5 -2
View File
@@ -22,8 +22,11 @@
extern "C" {
#endif
#include <ch.h>
#include <hal.h>
#include <stdint.h>
#ifdef FLASH_STM32_MOCKED
extern uint8_t FlashBuf[MOCK_FLASH_SIZE];
#endif
typedef enum { FLASH_BUSY = 1, FLASH_ERROR_PG, FLASH_ERROR_WRP, FLASH_ERROR_OPT, FLASH_COMPLETE, FLASH_TIMEOUT, FLASH_BAD_ADDRESS } FLASH_Status;
File diff suppressed because it is too large Load Diff
+50
View File
@@ -0,0 +1,50 @@
/* Copyright 2021 by Don Kjer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdbool.h>
#include "flash_stm32.h"
uint8_t FlashBuf[MOCK_FLASH_SIZE] = {0};
static bool flash_locked = true;
FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
if (flash_locked) return FLASH_ERROR_WRP;
Page_Address -= (uintptr_t)FlashBuf;
Page_Address -= (Page_Address % FEE_PAGE_SIZE);
if (Page_Address >= MOCK_FLASH_SIZE) return FLASH_BAD_ADDRESS;
memset(&FlashBuf[Page_Address], '\xff', FEE_PAGE_SIZE);
return FLASH_COMPLETE;
}
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
if (flash_locked) return FLASH_ERROR_WRP;
Address -= (uintptr_t)FlashBuf;
if (Address >= MOCK_FLASH_SIZE) return FLASH_BAD_ADDRESS;
uint16_t oldData = *(uint16_t*)&FlashBuf[Address];
if (oldData == 0xFFFF || Data == 0) {
*(uint16_t*)&FlashBuf[Address] = Data;
return FLASH_COMPLETE;
} else {
return FLASH_ERROR_PG;
}
}
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) { return FLASH_COMPLETE; }
void FLASH_Unlock(void) { flash_locked = false; }
void FLASH_Lock(void) { flash_locked = true; }
void FLASH_ClearFlag(uint32_t FLASH_FLAG) {}
+23
View File
@@ -0,0 +1,23 @@
eeprom_stm32_DEFS := -DFLASH_STM32_MOCKED -DNO_PRINT -DFEE_FLASH_BASE=FlashBuf
eeprom_stm32_tiny_DEFS := $(eeprom_stm32_DEFS) \
-DFEE_MCU_FLASH_SIZE=1 \
-DMOCK_FLASH_SIZE=1024 \
-DFEE_PAGE_SIZE=512 \
-DFEE_DENSITY_PAGES=1
eeprom_stm32_large_DEFS := $(eeprom_stm32_DEFS) \
-DFEE_MCU_FLASH_SIZE=64 \
-DMOCK_FLASH_SIZE=65536 \
-DFEE_PAGE_SIZE=2048 \
-DFEE_DENSITY_PAGES=16
eeprom_stm32_INC := \
$(TMK_PATH)/common/chibios/
eeprom_stm32_tiny_INC := $(eeprom_stm32_INC)
eeprom_stm32_large_INC := $(eeprom_stm32_INC)
eeprom_stm32_SRC := \
$(TMK_PATH)/common/test/eeprom_stm32_tests.cpp \
$(TMK_PATH)/common/test/flash_stm32_mock.c \
$(TMK_PATH)/common/chibios/eeprom_stm32.c
eeprom_stm32_tiny_SRC := $(eeprom_stm32_SRC)
eeprom_stm32_large_SRC := $(eeprom_stm32_SRC)
+1
View File
@@ -0,0 +1 @@
TEST_LIST += eeprom_stm32_tiny eeprom_stm32_large
+317
View File
File diff suppressed because it is too large Load Diff