forked from qmk/qmk_firmware
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enables the master branch to also use the EEPROM of Stm32F4
- Loading branch information
Showing
17 changed files
with
1,671 additions
and
32 deletions.
There are no files selected for viewing
217 changes: 217 additions & 0 deletions
217
keyboards/yandrstudio/tdcq64_2s/f401/eep/eeprom_stm32.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
/* | ||
* This software is experimental and a work in progress. | ||
* Under no circumstances should these files be used in relation to any critical system(s). | ||
* Use of these files is at your own risk. | ||
* | ||
* 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. | ||
* | ||
* This files are free to use from http://engsta.com/stm32-flash-memory-eeprom-emulator/ by | ||
* Artur F. | ||
* | ||
* Modifications for QMK and STM32F303 by Yiancar | ||
* update for STM32F4 support and the the flashing algorithm by yulei | ||
* Adjust the file structure to custom EEPROM_DRIVER by jiaxin96 for support stm32f401cc | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <string.h> | ||
#include "eeprom_stm32_custom.h" | ||
#include "eeprom_driver.h" | ||
/***************************************************************************** | ||
* Allows to use the internal flash to store non volatile data. To initialize | ||
* the functionality use the EEPROM_Init() function. Be sure that by reprogramming | ||
* of the controller just affected pages will be deleted. In other case the non | ||
* volatile data will be lost. | ||
******************************************************************************/ | ||
|
||
/* Private macro -------------------------------------------------------------*/ | ||
/* Private variables ---------------------------------------------------------*/ | ||
/* Functions -----------------------------------------------------------------*/ | ||
|
||
#define IS_VALID_ADDRESS(x) ((x) < FEE_MAX_BYTES) | ||
|
||
uint8_t DataBuf[FEE_MAX_BYTES]; | ||
static void EEPROM_Backup(void); | ||
static FLASH_Status EEPROM_Restore(void); | ||
static uint32_t EEPROM_FindValidAddress(void); | ||
static void EEPROM_Clear(void); | ||
|
||
/***************************************************************************** | ||
* Unlock the FLASH programming and initialized the DataBuf | ||
******************************************************************************/ | ||
uint16_t EEPROM_Init(void) { | ||
// unlock flash | ||
FLASH_Unlock(); | ||
|
||
// initialize DataBuf | ||
EEPROM_Backup(); | ||
|
||
// Clear Flags | ||
// FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR); | ||
|
||
return FEE_DENSITY_BYTES; | ||
} | ||
void eeprom_driver_init(void) { | ||
EEPROM_Init(); | ||
} | ||
|
||
/***************************************************************************** | ||
* Erase the whole reserved Flash Space used for user Data | ||
******************************************************************************/ | ||
void EEPROM_Erase(void) { | ||
// erase all flash pages | ||
EEPROM_Clear(); | ||
|
||
// reset the content of the buffer | ||
memset(&DataBuf[0], FEE_EMPTY_BYTE, sizeof(DataBuf)); | ||
} | ||
void eeprom_driver_erase(void) { | ||
EEPROM_Erase(); | ||
} | ||
/***************************************************************************** | ||
* Write data with its eeprom address to flash if there has empty words, | ||
* otherwise backup the current valid data, erase all flash pages, | ||
* and finally restore the valid data. | ||
*******************************************************************************/ | ||
uint16_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) { | ||
FLASH_Status FlashStatus = FLASH_COMPLETE; | ||
|
||
uint32_t addr; | ||
// exit if not a valid address | ||
if (!IS_VALID_ADDRESS(Address)) { | ||
return 0; | ||
} | ||
|
||
// we are sure the address will not be out of bound | ||
#pragma GCC diagnostic ignored "-Warray-bounds" | ||
// same value, do not need program | ||
if (DataBuf[Address] == DataByte) { | ||
return FlashStatus; | ||
} | ||
|
||
// find the address can be written | ||
addr = EEPROM_FindValidAddress(); | ||
DataBuf[Address] = DataByte; | ||
#pragma GCC diagnostic pop | ||
if (addr == FEE_EMPTY_VALUE) { | ||
// EEPROM is full, need to erase and reprogramming | ||
EEPROM_Clear(); | ||
EEPROM_Restore(); | ||
} else { | ||
FLASH_ProgramHalfWord(FEE_ADDR_ADDRESS(addr), Address); | ||
FLASH_ProgramHalfWord(FEE_DATA_ADDRESS(addr), DataByte); | ||
} | ||
|
||
return FlashStatus; | ||
} | ||
/***************************************************************************** | ||
* Read once data byte from a specified address. | ||
*******************************************************************************/ | ||
uint8_t EEPROM_ReadDataByte(uint16_t Address) { | ||
if (!IS_VALID_ADDRESS(Address)) { | ||
return FEE_EMPTY_BYTE; | ||
} | ||
|
||
// Get Byte from caches | ||
return DataBuf[Address]; | ||
} | ||
|
||
/***************************************************************************** | ||
* helper functions | ||
*******************************************************************************/ | ||
// backup the current data | ||
void EEPROM_Backup(void) | ||
{ | ||
uint32_t begin = FEE_PAGE_BASE_ADDRESS; | ||
uint32_t end = FEE_PAGE_END_ADDRESS; | ||
memset(&DataBuf[0], FEE_EMPTY_BYTE, sizeof(DataBuf)); | ||
while( begin < end) { | ||
uint16_t addr = *(__IO uint16_t*)(FEE_ADDR_ADDRESS(begin)); | ||
if (IS_VALID_ADDRESS(addr)) { | ||
DataBuf[addr] = *(__IO uint16_t*)(FEE_DATA_ADDRESS(begin)); | ||
} else if( addr == FEE_EMPTY_WORD) { | ||
uint16_t data = *(__IO uint16_t*)(FEE_DATA_ADDRESS(begin)); | ||
if (data == FEE_EMPTY_WORD) { | ||
// we reached the end of valid data | ||
break; | ||
} | ||
} | ||
begin += 4; | ||
} | ||
} | ||
// restore data from DataBuf | ||
FLASH_Status EEPROM_Restore(void) { | ||
uint32_t cur = FEE_PAGE_BASE_ADDRESS; | ||
for (uint8_t i = 0; i < FEE_MAX_BYTES; i++) { | ||
if (DataBuf[i] != FEE_EMPTY_BYTE) { | ||
FLASH_ProgramHalfWord(FEE_ADDR_ADDRESS(cur), i); | ||
FLASH_ProgramHalfWord(FEE_DATA_ADDRESS(cur), DataBuf[i]); | ||
cur += 4; | ||
} | ||
} | ||
return FLASH_COMPLETE; | ||
} | ||
// find an empty place for programming | ||
uint32_t EEPROM_FindValidAddress(void) { | ||
uint32_t begin = FEE_PAGE_BASE_ADDRESS; | ||
uint32_t end = FEE_PAGE_END_ADDRESS; | ||
while( begin < end) { | ||
uint32_t data = *(__IO uint32_t*)(begin); | ||
if (data == FEE_EMPTY_VALUE) { | ||
return begin; | ||
} | ||
begin += 4; | ||
} | ||
return FEE_EMPTY_VALUE; | ||
} | ||
|
||
void EEPROM_Clear(void) | ||
{ | ||
#if defined(EEPROM_EMU_STM32F401xC) | ||
FLASH_ErasePage(FEE_SECTOR_ID); | ||
#else | ||
int page_num = 0; | ||
|
||
// delete all pages from specified start page to the last page | ||
do { | ||
FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE)); | ||
page_num++; | ||
} while (page_num < FEE_DENSITY_PAGES); | ||
#endif | ||
} | ||
/***************************************************************************** | ||
* Wrap library in AVR style functions. | ||
*******************************************************************************/ | ||
uint8_t eeprom_read_byte_f4(const uint8_t *Address) { | ||
const uint16_t p = (const uint32_t)Address; | ||
return EEPROM_ReadDataByte(p); | ||
} | ||
|
||
void eeprom_write_byte_f4(uint8_t *Address, uint8_t Value) { | ||
uint16_t p = (uint32_t)Address; | ||
EEPROM_WriteDataByte(p, Value); | ||
} | ||
|
||
|
||
void eeprom_read_block(void *buf, const void *addr, size_t len) { | ||
const uint8_t *p = (const uint8_t *)addr; | ||
uint8_t * dest = (uint8_t *)buf; | ||
while (len--) { | ||
*dest++ = eeprom_read_byte_f4(p++); | ||
} | ||
} | ||
|
||
void eeprom_write_block(const void *buf, void *addr, size_t len) { | ||
uint8_t * p = (uint8_t *)addr; | ||
const uint8_t *src = (const uint8_t *)buf; | ||
while (len--) { | ||
eeprom_write_byte_f4(p++, *src++); | ||
} | ||
} | ||
|
||
|
104 changes: 104 additions & 0 deletions
104
keyboards/yandrstudio/tdcq64_2s/f401/eep/eeprom_stm32_custom.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/* | ||
* This software is experimental and a work in progress. | ||
* Under no circumstances should these files be used in relation to any critical system(s). | ||
* Use of these files is at your own risk. | ||
* | ||
* 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. | ||
* | ||
* This files are free to use from http://engsta.com/stm32-flash-memory-eeprom-emulator/ by | ||
* Artur F. | ||
* | ||
* Modifications for QMK and STM32F303 by Yiancar | ||
* | ||
* This library assumes 8-bit data locations. To add a new MCU, please provide the flash | ||
* page size and the total flash size in Kb. The number of available pages must be a multiple | ||
* of 2. Only half of the pages account for the total EEPROM size. | ||
* This library also assumes that the pages are not used by the firmware. | ||
* Adjust the file structure to custom EEPROM_DRIVER by jiaxin96 for support stm32f401cc | ||
*/ | ||
|
||
#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 | ||
#elif defined(EEPROM_EMU_STM32F401xC) | ||
# define MCU_STM32F401xC | ||
#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 4 // 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 | ||
# elif defined(MCU_STM32F401xC) | ||
# define FEE_PAGE_SIZE (uint32_t)0x20000 // Page size = 128KByte | ||
# define FEE_DENSITY_PAGES 1 // How many pages are used | ||
# define FEE_SECTOR_ID 5 // sector id of the flash | ||
# 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 | ||
# elif defined(MCU_STM32F401xC) | ||
# 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 | ||
|
||
#define FEE_PAGE_END_ADDRESS ((uint32_t)(0x08000000 + FEE_MCU_FLASH_SIZE * 1024)) | ||
#define FEE_PAGE_BASE_ADDRESS ((uint32_t)((FEE_PAGE_END_ADDRESS) - FEE_DENSITY_PAGES * FEE_PAGE_SIZE)) | ||
#define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 4) * FEE_DENSITY_PAGES - 1) // 4 Bytes for address, value pair | ||
//#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES)) | ||
#define FEE_EMPTY_BYTE ((uint8_t)0xFF) | ||
#define FEE_EMPTY_WORD ((uint16_t)0xFFFF) | ||
#define FEE_EMPTY_VALUE ((uint32_t)0xFFFFFFFF) | ||
//#define FEE_ADDR_OFFSET(Address) (Address * 2) // 1 Byte per Word will be saved to preserve Flash | ||
#define FEE_DATA_ADDRESS(Address) ((Address)+2) // flash address of the eeprom data | ||
#define FEE_ADDR_ADDRESS(Address) (Address) // flash address of the eeprom address | ||
#define FEE_MAX_BYTES ((FEE_DENSITY_BYTES+1) > 1024 ? 1024 : (FEE_DENSITY_BYTES+1)) // eeprom size | ||
|
Oops, something went wrong.