mirror of
https://github.com/Keychron/qmk_firmware.git
synced 2024-11-22 16:37:58 +06:00
Add new features for keychron keyboards.
This commit is contained in:
parent
81d2218cee
commit
f80692c140
|
@ -197,6 +197,12 @@ else
|
|||
# True EEPROM on STM32L0xx, L1xx
|
||||
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_L0_L1
|
||||
SRC += eeprom_driver.c eeprom_stm32_L0_L1.c
|
||||
else ifneq ($(filter $(MCU_SERIES),STM32L4xx),)
|
||||
# Emulated EEPROM
|
||||
OPT_DEFS += -DEEPROM_DRIVER -DEEPROM_STM32_FLASH_EMULATED
|
||||
COMMON_VPATH += $(PLATFORM_PATH)/$(PLATFORM_KEY)/$(DRIVER_DIR)/flash
|
||||
COMMON_VPATH += $(DRIVER_PATH)/flash
|
||||
SRC += eeprom_driver.c eeprom_stm32_L4.c flash_stm32.c
|
||||
else ifneq ($(filter $(MCU_SERIES),KL2x K20x),)
|
||||
# Teensy EEPROM implementations
|
||||
OPT_DEFS += -DEEPROM_TEENSY
|
||||
|
|
|
@ -30,6 +30,11 @@
|
|||
# define PHASE_CHANNEL MSKPHASE_12CHANNEL
|
||||
#endif
|
||||
|
||||
#ifndef CONSTANT_CURRENT_STEP
|
||||
# define CONSTANT_CURRENT_STEP \
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
||||
#endif
|
||||
|
||||
// Transfer buffer for TWITransmitData()
|
||||
uint8_t g_twi_transfer_buffer[20];
|
||||
|
||||
|
@ -96,6 +101,8 @@ bool CKLED2001_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
|
|||
}
|
||||
|
||||
void CKLED2001_init(uint8_t addr) {
|
||||
uint8_t led_current_tune[LED_CURRENT_TUNE_LENGTH] = CONSTANT_CURRENT_STEP;
|
||||
|
||||
// Select to function page
|
||||
CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, FUNCTION_PAGE);
|
||||
// Setting LED driver to shutdown mode
|
||||
|
@ -125,16 +132,7 @@ void CKLED2001_init(uint8_t addr) {
|
|||
// Set CURRENT PAGE (Page 4)
|
||||
CKLED2001_write_register(addr, CONFIGURE_CMD_PAGE, CURRENT_TUNE_PAGE);
|
||||
for (int i = 0; i < LED_CURRENT_TUNE_LENGTH; i++) {
|
||||
switch (i) {
|
||||
case 2:
|
||||
case 5:
|
||||
case 8:
|
||||
case 11:
|
||||
CKLED2001_write_register(addr, i, 0xA0);
|
||||
break;
|
||||
default:
|
||||
CKLED2001_write_register(addr, i, 0xFF);
|
||||
}
|
||||
CKLED2001_write_register(addr, i, led_current_tune[i]);
|
||||
}
|
||||
|
||||
// Enable LEDs ON/OFF
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
# ifndef FEE_PAGE_COUNT
|
||||
# define FEE_PAGE_COUNT 2 // How many pages are used
|
||||
# endif
|
||||
# elif defined(STM32F103xE) || defined(STM32F303xC) || defined(STM32F303xE) || defined(STM32F072xB) || defined(STM32F070xB)
|
||||
# elif defined(STM32F103xE) || defined(STM32F303xC) || defined(STM32F303xE) || defined(STM32F072xB) || defined(STM32F070xB) || defined(STM32L432xx)
|
||||
# ifndef FEE_PAGE_SIZE
|
||||
# define FEE_PAGE_SIZE 0x800 // Page size = 2KByte
|
||||
# endif
|
||||
|
@ -47,7 +47,7 @@
|
|||
# define FEE_MCU_FLASH_SIZE 32 // Size in Kb
|
||||
# elif defined(GD32VF103C8)
|
||||
# define FEE_MCU_FLASH_SIZE 64 // Size in Kb
|
||||
# elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) || defined(GD32VF103CB)
|
||||
# elif defined(STM32F103xB) || defined(STM32F072xB) || defined(STM32F070xB) || defined(STM32L432xx) || defined(GD32VF103CB)
|
||||
# define FEE_MCU_FLASH_SIZE 128 // Size in Kb
|
||||
# elif defined(STM32F303xC) || defined(STM32F401xC)
|
||||
# define FEE_MCU_FLASH_SIZE 256 // Size in Kb
|
||||
|
@ -100,9 +100,19 @@
|
|||
# pragma message STR(FEE_DENSITY_BYTES) " > " STR(FEE_ADDRESS_MAX_SIZE)
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES is greater than FEE_ADDRESS_MAX_SIZE allows
|
||||
# endif
|
||||
# if defined(STM32L432xx)
|
||||
# if ((FEE_DENSITY_BYTES) % 8) != 0
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES must be a multiple of 8
|
||||
# endif
|
||||
# else
|
||||
# if ((FEE_DENSITY_BYTES) % 2) == 1
|
||||
# error emulated eeprom: FEE_DENSITY_BYTES must be even
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# if defined(STM32L432xx)
|
||||
/* Only one page of allocated space used for emulated eeprom, 3 pages for write log */
|
||||
# define FEE_DENSITY_BYTES FEE_PAGE_SIZE
|
||||
# else
|
||||
/* Default to half of allocated space used for emulated eeprom, half for write log */
|
||||
# define FEE_DENSITY_BYTES (FEE_PAGE_COUNT * FEE_PAGE_SIZE / 2)
|
||||
|
@ -114,9 +124,15 @@
|
|||
# pragma message STR(FEE_DENSITY_BYTES) " + " STR(FEE_WRITE_LOG_BYTES) " > " STR(FEE_DENSITY_MAX_SIZE)
|
||||
# error emulated eeprom: FEE_WRITE_LOG_BYTES exceeds remaining FEE_DENSITY_MAX_SIZE
|
||||
# endif
|
||||
# if defined(STM32L432xx)
|
||||
# if ((FEE_WRITE_LOG_BYTES) % 8) != 0
|
||||
# error emulated eeprom: FEE_WRITE_LOG_BYTES must be a multiple of 8
|
||||
# endif
|
||||
# else
|
||||
# if ((FEE_WRITE_LOG_BYTES) % 2) == 1
|
||||
# error emulated eeprom: FEE_WRITE_LOG_BYTES must be even
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
/* Default to use all remaining space */
|
||||
# define FEE_WRITE_LOG_BYTES (FEE_PAGE_COUNT * FEE_PAGE_SIZE - FEE_DENSITY_BYTES)
|
||||
|
|
500
platforms/chibios/drivers/eeprom/eeprom_stm32_l4.c
Normal file
500
platforms/chibios/drivers/eeprom/eeprom_stm32_l4.c
Normal file
|
@ -0,0 +1,500 @@
|
|||
/*
|
||||
* 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 STM32L432 by lalalademaxiya1 & lokher
|
||||
*
|
||||
* TODO: Add ECC correction interrupt handler.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "flash_stm32.h"
|
||||
#include "eeprom_stm32_l4.h"
|
||||
#include "print.h"
|
||||
/*
|
||||
* We emulate eeprom by writing a snapshot compacted view of eeprom contents,
|
||||
* followed by a write log of any change since that snapshot:
|
||||
*
|
||||
* === SIMULATED EEPROM CONTENTS ===
|
||||
*
|
||||
* ┌─ Compacted─┬─ Write Log ──┐
|
||||
* │............│[DWord][DWord]│
|
||||
* │FFFF....FFFF│[DWord][DWord]│
|
||||
* │FFFFFFFFFFFF│[DWord][DWord]│
|
||||
* │....FFFFFFFF│[DWord][DWord]│
|
||||
* ├────────────┼──────────────┤
|
||||
* └──PAGE_BASE │ │
|
||||
* PAGE_LAST─┴─WRITE_BASE │
|
||||
* WRITE_LAST ──┘
|
||||
*
|
||||
* Compacted contents are the 1's complement of the actual EEPROM contents.
|
||||
* e.g. An 'FFFF' represents a '0000' value.
|
||||
*
|
||||
* The size of the 'compacted' area is equal to the size of the 'emulated' eeprom.
|
||||
* The size of the compacted-area and write log are configurable, and the combined
|
||||
* size of Compacted + WriteLog is a multiple FEE_PAGE_SIZE, which is MCU dependent.
|
||||
* Simulated Eeprom contents are located at the end of available flash space.
|
||||
*
|
||||
* The following configuration defines can be set:
|
||||
*
|
||||
* FEE_PAGE_COUNT # Total number of pages to use for eeprom simulation (Compact + Write log)
|
||||
* FEE_DENSITY_BYTES # Size of simulated eeprom. (Defaults to one pages of FEE_PAGE_COUNT)
|
||||
* NOTE: The current implementation does not include page swapping,
|
||||
* and FEE_DENSITY_BYTES will consume that amount of RAM as a cached view of actual EEPROM contents.
|
||||
*
|
||||
* The maximum size of FEE_DENSITY_BYTES is currently 8192. The write log size equals
|
||||
* FEE_PAGE_COUNT * FEE_PAGE_SIZE - FEE_DENSITY_BYTES.
|
||||
* The larger the write log, the less frequently the compacted area needs to be rewritten.
|
||||
*
|
||||
*
|
||||
* *** General Algorithm ***
|
||||
*
|
||||
* During initialization:
|
||||
* The contents of the Compacted-flash area are loaded and the 1's complement value
|
||||
* is cached into memory (e.g. 0xFFFF in Flash represents 0x0000 in cache).
|
||||
* Write log entries are processed until a 0xFFFF is reached.
|
||||
* Each log entry updates 1/2/4 byte(s) in the cache.
|
||||
*
|
||||
* During reads:
|
||||
* EEPROM contents are given back directly from the cache in memory.
|
||||
*
|
||||
* During writes:
|
||||
* The contents of the cache is updated first.
|
||||
* If the Compacted-flash area corresponding to the write address is unprogrammed, the 1's complement of the value is written directly into Compacted-flash
|
||||
* Otherwise:
|
||||
* If the write log is full, erase both the Compacted-flash area and the Write log, then write cached contents to the Compacted-flash area.
|
||||
* Otherwise a Write log entry is constructed and appended to the next free position in the Write log.
|
||||
*
|
||||
*
|
||||
* *** Write Log Structure ***
|
||||
*
|
||||
* Each log entry compose of double word (2 x 32-bit) due to the minimum program size of STM32L432 flash.
|
||||
*
|
||||
* === WRITE LOG ENTRY FORMATS ===
|
||||
*
|
||||
* ╔══════════ Byte-Entry ═════════╗
|
||||
* ║ 00 01 XX XX ║ FF FF FF YY ║
|
||||
* ║ └─┬─┘ └─┬─┘ ║ └┘ ║
|
||||
* ║ Len Address ║ ~Value ║
|
||||
* ╚═══════════════╩═══════════════╝
|
||||
*
|
||||
* ╔══════════ Word-Entry ═════════╗
|
||||
* ║ 00 02 XX XX ║ FF FF YY YY ║
|
||||
* ║ └─┬─┘ └─┬─┘ ║ └─┬─┘ ║
|
||||
* ║ Len Address ║ ~Value ║
|
||||
* ╚═══════════════╩═══════════════╝
|
||||
*
|
||||
* ╔══════════ DWord-Entry ═══════╗
|
||||
* ║ 00 04 XX XX ║ FF FF FF FF ║
|
||||
* ║ └─┬─┘ └─┬─┘ ║ └───┬────┘ ║
|
||||
* ║ Len Address ║ ~Value ║
|
||||
* ╚═══════════════╩═══════════════╝
|
||||
*
|
||||
*/
|
||||
|
||||
#include "eeprom_stm32_defs.h"
|
||||
#if !defined(FEE_PAGE_SIZE) || !defined(FEE_PAGE_COUNT) || !defined(FEE_MCU_FLASH_SIZE) || !defined(FEE_PAGE_BASE_ADDRESS)
|
||||
# error "not implemented."
|
||||
#endif
|
||||
|
||||
/* These bits indicate that the length of data which was wrote to log space */
|
||||
#define FEE_BYTE_FLAG 0x00010000
|
||||
#define FEE_WORD_FLAG 0x00020000
|
||||
#define FEE_DWORD_FLAG 0x00040000
|
||||
|
||||
/* Flash byte value after erase */
|
||||
#define FEE_EMPTY_BYTE ((uint8_t)0xFF)
|
||||
/* Flash double byte value after erase */
|
||||
#define FEE_EMPTY_DBYTE ((uint16_t)0xFFFF)
|
||||
/* Flash word value after erase */
|
||||
#define FEE_EMPTY_WORD ((uint32_t)0xFFFFFFFF)
|
||||
/* Flash double word value after erase */
|
||||
#define FEE_EMPTY_DWORD ((uint64_t)0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
/* In-memory contents of emulated eeprom for faster access */
|
||||
/* *TODO: Implement page swapping */
|
||||
static uint64_t DWordBuf[FEE_DENSITY_BYTES / 8];
|
||||
static uint8_t *DataBuf = (uint8_t *)DWordBuf;
|
||||
|
||||
/* Pointer to the first available slot within the write log */
|
||||
static uint32_t *empty_slot;
|
||||
|
||||
/* Start of the emulated eeprom compacted flash area */
|
||||
#define FEE_COMPACTED_BASE_ADDRESS FEE_PAGE_BASE_ADDRESS
|
||||
/* End of the emulated eeprom compacted flash area */
|
||||
#define FEE_COMPACTED_LAST_ADDRESS (FEE_COMPACTED_BASE_ADDRESS + FEE_DENSITY_BYTES)
|
||||
/* Start of the emulated eeprom write log */
|
||||
#define FEE_WRITE_LOG_BASE_ADDRESS FEE_COMPACTED_LAST_ADDRESS
|
||||
/* End of the emulated eeprom write log */
|
||||
#define FEE_WRITE_LOG_LAST_ADDRESS (FEE_WRITE_LOG_BASE_ADDRESS + FEE_WRITE_LOG_BYTES)
|
||||
|
||||
uint16_t EEPROM_Init(void) {
|
||||
/* Load emulated eeprom contents from compacted flash into memory */
|
||||
uint32_t *src = (uint32_t *)FEE_COMPACTED_BASE_ADDRESS;
|
||||
uint32_t *dest = (uint32_t *)DataBuf;
|
||||
for (; src < (uint32_t *)FEE_COMPACTED_LAST_ADDRESS; ++src, ++dest) {
|
||||
*dest = ~*src;
|
||||
}
|
||||
|
||||
/* Replay write log */
|
||||
uint32_t *log_addr;
|
||||
for (log_addr = (uint32_t *)FEE_WRITE_LOG_BASE_ADDRESS; log_addr < (uint32_t *)FEE_WRITE_LOG_LAST_ADDRESS; log_addr += 2) {
|
||||
uint32_t address = *log_addr;
|
||||
uint32_t data = ~*(log_addr + 1);
|
||||
if (address == FEE_EMPTY_WORD) {
|
||||
break;
|
||||
}
|
||||
/* Check if value is in bytes */
|
||||
else if ((address & FEE_BYTE_FLAG) == FEE_BYTE_FLAG) {
|
||||
uint8_t value = (uint8_t)(data & 0xFF);
|
||||
uint16_t addr = (uint16_t)address;
|
||||
DataBuf[addr] = value;
|
||||
}
|
||||
/* Check if value is in words */
|
||||
else if ((address & FEE_WORD_FLAG) == FEE_WORD_FLAG) {
|
||||
uint16_t value = (uint16_t)(data & 0xFFFF);
|
||||
uint16_t addr = (uint16_t)address;
|
||||
*(uint16_t *)(&DataBuf[addr]) = value;
|
||||
}
|
||||
/* Check if value is in double words */
|
||||
else if ((address & FEE_DWORD_FLAG) == FEE_DWORD_FLAG) {
|
||||
uint32_t value = data;
|
||||
uint16_t addr = (uint16_t)address;
|
||||
*(uint32_t *)(&DataBuf[addr]) = value;
|
||||
}
|
||||
}
|
||||
|
||||
empty_slot = log_addr;
|
||||
|
||||
return FEE_DENSITY_BYTES;
|
||||
}
|
||||
|
||||
/* Clear flash contents (doesn't touch in-memory DataBuf) */
|
||||
static void eeprom_clear(void) {
|
||||
FLASH_Unlock();
|
||||
|
||||
for (uint16_t page_num = 0; page_num < FEE_PAGE_COUNT; ++page_num) {
|
||||
FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE));
|
||||
}
|
||||
|
||||
FLASH_Lock();
|
||||
|
||||
empty_slot = (uint32_t *)FEE_WRITE_LOG_BASE_ADDRESS;
|
||||
}
|
||||
|
||||
/* Erase emulated eeprom */
|
||||
void EEPROM_Erase(void) {
|
||||
/* Erase compacted pages and write log */
|
||||
eeprom_clear();
|
||||
/* re-initialize to reset DataBuf */
|
||||
EEPROM_Init();
|
||||
}
|
||||
|
||||
/* Compact write log */
|
||||
static uint8_t eeprom_compact(void) {
|
||||
/* Erase compacted pages and write log */
|
||||
eeprom_clear();
|
||||
|
||||
FLASH_Unlock();
|
||||
|
||||
FLASH_Status final_status = FLASH_COMPLETE;
|
||||
|
||||
/* Write emulated eeprom contents from memory to compacted flash */
|
||||
uint64_t *src = (uint64_t *)DataBuf;
|
||||
uint32_t dest = FEE_COMPACTED_BASE_ADDRESS;
|
||||
uint64_t value;
|
||||
for (; dest < FEE_COMPACTED_LAST_ADDRESS; ++src, dest += 8) {
|
||||
value = *src;
|
||||
if (value) {
|
||||
FLASH_Status status = FLASH_ProgramDoubleWord(dest, ~value);
|
||||
if (status != FLASH_COMPLETE) final_status = status;
|
||||
}
|
||||
}
|
||||
|
||||
FLASH_Lock();
|
||||
|
||||
return final_status;
|
||||
}
|
||||
|
||||
static uint8_t eeprom_write_direct_entry(uint16_t Address) {
|
||||
/* Check if we can just write this directly to the compacted flash area */
|
||||
uint32_t directAddress = FEE_COMPACTED_BASE_ADDRESS + (Address & 0xFFF8);
|
||||
|
||||
/* Write the value directly to the compacted area without a log entry */
|
||||
if (*(uint64_t *)directAddress == FEE_EMPTY_DWORD) {
|
||||
/* Write the value directly to the compacted area without a log entry */
|
||||
uint64_t value = ~*(uint64_t *)(&DataBuf[Address & 0xFFF8]);
|
||||
|
||||
/* Early exit if a write isn't needed */
|
||||
if (value == FEE_EMPTY_DWORD) return FLASH_COMPLETE;
|
||||
|
||||
FLASH_Unlock();
|
||||
|
||||
/* write to flash */
|
||||
FLASH_Status status = FLASH_ProgramDoubleWord(directAddress, value);
|
||||
|
||||
FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t eeprom_write_log_byte_entry(uint16_t Address) {
|
||||
/* if we can't find an empty spot, we must compact emulated eeprom */
|
||||
if (empty_slot >= (uint32_t *)FEE_WRITE_LOG_LAST_ADDRESS) {
|
||||
/* compact the write log into the compacted flash area */
|
||||
return eeprom_compact();
|
||||
}
|
||||
|
||||
FLASH_Unlock();
|
||||
|
||||
/* Pack address and value into the same word */
|
||||
uint64_t value = (((uint64_t)(~DataBuf[Address])) << 32) | (FEE_BYTE_FLAG) | Address;
|
||||
|
||||
/* write to flash */
|
||||
FLASH_Status status = FLASH_ProgramDoubleWord((uint32_t)empty_slot, value);
|
||||
|
||||
empty_slot += 2;
|
||||
|
||||
FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint8_t eeprom_write_log_word_entry(uint16_t Address) {
|
||||
/* if we can't find an empty spot, we must compact emulated eeprom */
|
||||
if (empty_slot >= (uint32_t *)FEE_WRITE_LOG_LAST_ADDRESS) {
|
||||
/* compact the write log into the compacted flash area */
|
||||
return eeprom_compact();
|
||||
}
|
||||
|
||||
FLASH_Unlock();
|
||||
|
||||
/* Pack address and value into the same word */
|
||||
uint64_t value = (((uint64_t)(~(*(uint16_t *)&DataBuf[Address]))) << 32) | (FEE_WORD_FLAG) | Address;
|
||||
|
||||
/* write to flash */
|
||||
FLASH_Status status = FLASH_ProgramDoubleWord((uint32_t)empty_slot, value);
|
||||
|
||||
empty_slot += 2;
|
||||
|
||||
FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static uint8_t eeprom_write_log_dword_entry(uint16_t Address) {
|
||||
/* if we can't find an empty spot, we must compact emulated eeprom */
|
||||
if (empty_slot >= (uint32_t *)FEE_WRITE_LOG_LAST_ADDRESS) {
|
||||
/* compact the write log into the compacted flash area */
|
||||
return eeprom_compact();
|
||||
}
|
||||
|
||||
FLASH_Unlock();
|
||||
|
||||
/* Pack address and value into the same word */
|
||||
uint64_t value = (((uint64_t)(~(*(uint32_t *)&DataBuf[Address]))) << 32) | (FEE_DWORD_FLAG) | Address;
|
||||
|
||||
/* write to flash */
|
||||
FLASH_Status status = FLASH_ProgramDoubleWord((uint32_t)empty_slot, value);
|
||||
|
||||
empty_slot += 2;
|
||||
|
||||
FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte) {
|
||||
/* if the address is out-of-bounds, do nothing */
|
||||
if (Address >= (FEE_DENSITY_BYTES)) {
|
||||
return FLASH_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
/* if the value is the same, don't bother writing it */
|
||||
if (DataBuf[Address] == DataByte) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* keep DataBuf cache in sync */
|
||||
DataBuf[Address] = DataByte;
|
||||
|
||||
/* perform the write into flash memory */
|
||||
/* First, attempt to write directly into the compacted flash area */
|
||||
FLASH_Status status = eeprom_write_direct_entry(Address);
|
||||
|
||||
if (!status) {
|
||||
eeprom_write_log_byte_entry(Address);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t EEPROM_WriteDataWord(uint16_t Address, uint16_t DataWord) {
|
||||
/* if the address is out-of-bounds, do nothing */
|
||||
if (Address >= (FEE_DENSITY_BYTES)) {
|
||||
return FLASH_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
/* if the value is the same, don't bother writing it */
|
||||
if (*(uint16_t *)&DataBuf[Address] == DataWord) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* keep DataBuf cache in sync */
|
||||
*(uint16_t *)(&DataBuf[Address]) = DataWord;
|
||||
|
||||
/* perform the write into flash memory */
|
||||
/* First, attempt to write directly into the compacted flash area */
|
||||
FLASH_Status status = eeprom_write_direct_entry(Address);
|
||||
|
||||
if (!status) {
|
||||
eeprom_write_log_word_entry(Address);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t EEPROM_WriteDataDWord(uint16_t Address, uint32_t DataDWord) {
|
||||
/* if the address is out-of-bounds, do nothing */
|
||||
if (Address >= (FEE_DENSITY_BYTES)) {
|
||||
return FLASH_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
/* if the value is the same, don't bother writing it */
|
||||
if (*(uint32_t *)&DataBuf[Address] == DataDWord) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* keep DataBuf cache in sync */
|
||||
*(uint32_t *)&DataBuf[Address] = DataDWord;
|
||||
|
||||
/* perform the write into flash memory */
|
||||
/* First, attempt to write directly into the compacted flash area */
|
||||
FLASH_Status status = eeprom_write_direct_entry(Address);
|
||||
|
||||
if (!status) {
|
||||
eeprom_write_log_dword_entry(Address);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t EEPROM_ReadDataByte(uint16_t Address) {
|
||||
uint8_t DataByte = 0xFF;
|
||||
|
||||
if (Address < FEE_DENSITY_BYTES) {
|
||||
DataByte = DataBuf[Address];
|
||||
}
|
||||
|
||||
return DataByte;
|
||||
}
|
||||
|
||||
uint16_t EEPROM_ReadDataWord(uint16_t Address) {
|
||||
uint16_t DataWord = 0xFFFF;
|
||||
|
||||
if (Address < FEE_DENSITY_BYTES - 1) {
|
||||
/* Check word alignment */
|
||||
if (Address % 2) {
|
||||
DataWord = DataBuf[Address] | (DataBuf[Address + 1] << 8);
|
||||
} else {
|
||||
DataWord = *(uint16_t *)(&DataBuf[Address]);
|
||||
}
|
||||
}
|
||||
|
||||
return DataWord;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Bind to eeprom_driver.c
|
||||
*******************************************************************************/
|
||||
void eeprom_driver_init(void) { EEPROM_Init(); }
|
||||
|
||||
void eeprom_driver_erase(void) { EEPROM_Erase(); }
|
||||
|
||||
void eeprom_read_block(void *buf, const void *addr, size_t len) {
|
||||
const uint8_t *src = (const uint8_t *)addr;
|
||||
uint8_t * dest = (uint8_t *)buf;
|
||||
|
||||
/* Check word alignment */
|
||||
if (len && (uint32_t)src % 2) {
|
||||
/* Read the unaligned first byte */
|
||||
*dest++ = EEPROM_ReadDataByte((const uintptr_t)((uint16_t *)src));
|
||||
--len;
|
||||
}
|
||||
|
||||
uint16_t value;
|
||||
bool aligned = ((uint32_t)dest % 2 == 0);
|
||||
while (len > 1) {
|
||||
value = EEPROM_ReadDataWord((const uintptr_t)((uint16_t *)src));
|
||||
if (aligned) {
|
||||
*(uint16_t *)dest = value;
|
||||
dest += 2;
|
||||
} else {
|
||||
*dest++ = value;
|
||||
*dest++ = value >> 8;
|
||||
}
|
||||
src += 2;
|
||||
len -= 2;
|
||||
}
|
||||
if (len) {
|
||||
*dest = EEPROM_ReadDataByte((const uintptr_t)src);
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_write_block(const void *buf, void *addr, size_t len) {
|
||||
uint8_t * dest = (uint8_t *)addr;
|
||||
const uint8_t *src = (const uint8_t *)buf;
|
||||
uint8_t write_len;
|
||||
|
||||
while (len > 0) {
|
||||
/* Check and try to write double word fisrt */
|
||||
if ((uintptr_t)dest % 4 == 0 && len >= 4) {
|
||||
uint32_t dwvalue;
|
||||
bool dwaligned = ((uint32_t)src % 4 == 0);
|
||||
|
||||
if (dwaligned) {
|
||||
dwvalue = *(uint32_t *)src;
|
||||
} else {
|
||||
dwvalue = *(uint8_t *)src | (*(uint8_t *)(src + 1) << 8) | (*(uint8_t *)(src + 2) << 16) | (*(uint8_t *)(src + 3) << 24);
|
||||
}
|
||||
EEPROM_WriteDataDWord((uintptr_t)((uint16_t *)dest), dwvalue);
|
||||
write_len = 4;
|
||||
}
|
||||
/* Check and try to write word */
|
||||
else if ((uintptr_t)dest % 2 == 0 && len >= 2) {
|
||||
uint16_t wvalue;
|
||||
bool waligned = ((uintptr_t)src % 2 == 0);
|
||||
|
||||
if (waligned) {
|
||||
wvalue = *(uint16_t *)src;
|
||||
} else {
|
||||
wvalue = *(uint8_t *)src | (*(uint8_t *)(src + 1) << 8);
|
||||
}
|
||||
EEPROM_WriteDataWord((uintptr_t)((uint16_t *)dest), wvalue);
|
||||
write_len = 2;
|
||||
} else {
|
||||
/* Write the unaligned or single byte */
|
||||
EEPROM_WriteDataByte((uintptr_t)dest++, *src++);
|
||||
write_len = 1;
|
||||
}
|
||||
|
||||
dest += write_len;
|
||||
src += write_len;
|
||||
len -= write_len;
|
||||
}
|
||||
}
|
34
platforms/chibios/drivers/eeprom/eeprom_stm32_l4.h
Normal file
34
platforms/chibios/drivers/eeprom/eeprom_stm32_l4.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 STM32L432 by lalalademaxiya1 & lokher
|
||||
*
|
||||
* 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 at least two. Only one page for the total EEPROM size.
|
||||
* It is recommend to set the number of log page to 3~5 times of data page for better Wear leveling.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
uint16_t EEPROM_Init(void);
|
||||
void EEPROM_Erase(void);
|
||||
uint8_t EEPROM_WriteDataByte(uint16_t Address, uint8_t DataByte);
|
||||
uint8_t EEPROM_WriteDataWord(uint16_t Address, uint16_t DataWord);
|
||||
uint8_t EEPROM_WriteDataDWord(uint16_t Address, uint32_t DataDWord);
|
||||
uint8_t EEPROM_ReadDataByte(uint16_t Address);
|
||||
uint16_t EEPROM_ReadDataWord(uint16_t Address);
|
|
@ -16,7 +16,6 @@
|
|||
* Modifications for QMK and STM32F303 by Yiancar
|
||||
*/
|
||||
|
||||
#include <hal.h>
|
||||
#include "flash_stm32.h"
|
||||
|
||||
#if defined(STM32F1XX)
|
||||
|
@ -51,6 +50,17 @@ static uint8_t ADDR2PAGE(uint32_t Page_Address) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(STM32L4XX)
|
||||
# define FLASH_SR_PGERR FLASH_SR_PROGERR
|
||||
# define FLASH_OBR_OPTERR FLASH_SR_OPERR
|
||||
# define FLASH_KEY1 0x45670123U
|
||||
# define FLASH_KEY2 0xCDEF89ABU
|
||||
|
||||
static uint32_t ADDR2PAGE(uint32_t Page_Address) {
|
||||
return (Page_Address - FLASH_BASE) / 0x800;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Delay definition */
|
||||
#define EraseTimeout ((uint32_t)0x00000FFF)
|
||||
#define ProgramTimeout ((uint32_t)0x0000001F)
|
||||
|
@ -128,6 +138,9 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
|
|||
#if defined(FLASH_CR_SNB)
|
||||
FLASH->CR &= ~FLASH_CR_SNB;
|
||||
FLASH->CR |= FLASH_CR_SER | (ADDR2PAGE(Page_Address) << FLASH_CR_SNB_Pos);
|
||||
#elif defined(FLASH_CR_PNB)
|
||||
FLASH->CR &= ~FLASH_CR_PNB;
|
||||
FLASH->CR |= FLASH_CR_PER | (ADDR2PAGE(Page_Address) << FLASH_CR_PNB_Pos);
|
||||
#else
|
||||
FLASH->CR |= FLASH_CR_PER;
|
||||
FLASH->AR = Page_Address;
|
||||
|
@ -140,6 +153,8 @@ FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
|
|||
/* if the erase operation is completed, disable the configured Bits */
|
||||
#if defined(FLASH_CR_SNB)
|
||||
FLASH->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);
|
||||
#elif defined(FLASH_CR_PNB)
|
||||
FLASH->CR &= ~(FLASH_CR_PER | FLASH_CR_PNB);
|
||||
#else
|
||||
FLASH->CR &= ~FLASH_CR_PER;
|
||||
#endif
|
||||
|
@ -184,6 +199,39 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
|
|||
return status;
|
||||
}
|
||||
|
||||
#if defined(STM32L4XX)
|
||||
/**
|
||||
* @brief Programs double words at a specified address.
|
||||
* @param Address: specifies the address to be programmed.
|
||||
* @param Data: specifies the data to be programmed.
|
||||
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
|
||||
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
|
||||
*/
|
||||
FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data) {
|
||||
FLASH_Status status = FLASH_BAD_ADDRESS;
|
||||
|
||||
if (IS_FLASH_ADDRESS(Address)) {
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
if (status == FLASH_COMPLETE) {
|
||||
/* if the previous operation is completed, proceed to program the new data */
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
*(__IO uint32_t*)Address = (uint32_t)Data;
|
||||
__ISB();
|
||||
*(__IO uint32_t*)(Address + 4U) = (uint32_t)(Data >> 32);
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(ProgramTimeout);
|
||||
if (status != FLASH_TIMEOUT) {
|
||||
/* if the program operation is completed, disable the PG Bit */
|
||||
FLASH->CR &= ~FLASH_CR_PG;
|
||||
}
|
||||
FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Unlocks the FLASH Program Erase Controller.
|
||||
* @param None
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <hal.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -35,6 +37,9 @@ typedef enum { FLASH_BUSY = 1, FLASH_ERROR_PG, FLASH_ERROR_WRP, FLASH_ERROR_OPT,
|
|||
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);
|
||||
FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
|
||||
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
|
||||
#if defined(STM32L4XX)
|
||||
FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_t Data);
|
||||
#endif
|
||||
|
||||
void FLASH_Unlock(void);
|
||||
void FLASH_Lock(void);
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
static pin_t dip_switch_pad[] = DIP_SWITCH_PINS;
|
||||
#endif
|
||||
|
||||
#ifndef SCAN_COUNT_MAX
|
||||
# define SCAN_COUNT_MAX 500
|
||||
#endif
|
||||
|
||||
#ifdef DIP_SWITCH_MATRIX_GRID
|
||||
typedef struct matrix_index_t {
|
||||
uint8_t row;
|
||||
|
@ -95,7 +99,7 @@ void dip_switch_read(bool forced) {
|
|||
#ifdef DIP_SWITCH_MATRIX_GRID
|
||||
bool read_raw = false;
|
||||
|
||||
if (scan_count < 500) {
|
||||
if (scan_count < SCAN_COUNT_MAX) {
|
||||
scan_count++;
|
||||
if (scan_count == 10) {
|
||||
read_raw = true;
|
||||
|
|
|
@ -190,6 +190,18 @@ static bool encoder_update(uint8_t index, uint8_t state) {
|
|||
return changed;
|
||||
}
|
||||
|
||||
#if defined(PAL_USE_CALLBACKS) || defined(AVR_USE_INT)
|
||||
bool encoder_read(void) {
|
||||
bool changed = false;
|
||||
for (uint8_t i = 0; i < thisCount; i++) {
|
||||
uint8_t new_status = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
|
||||
encoder_state[i] <<= 2;
|
||||
encoder_state[i] |= new_status;
|
||||
changed |= encoder_update(i, encoder_state[i]);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
#else
|
||||
bool encoder_read(void) {
|
||||
bool changed = false;
|
||||
for (uint8_t i = 0; i < thisCount; i++) {
|
||||
|
@ -202,6 +214,7 @@ bool encoder_read(void) {
|
|||
}
|
||||
return changed;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
void last_encoder_activity_trigger(void);
|
||||
|
@ -241,3 +254,11 @@ void encoder_update_raw(uint8_t *slave_state) {
|
|||
if (changed) last_encoder_activity_trigger();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PAL_USE_CALLBACKS) || defined(AVR_USE_INT)
|
||||
void encoder_insert_state(uint8_t index) {
|
||||
encoder_state[index] <<= 2;
|
||||
encoder_state[index] |= (readPin(encoders_pad_a[index]) << 0) | (readPin(encoders_pad_b[index]) << 1);
|
||||
encoder_pulses[index] += encoder_LUT[encoder_state[index] & 0xF];
|
||||
}
|
||||
#endif
|
|
@ -26,6 +26,10 @@ bool encoder_read(void);
|
|||
bool encoder_update_kb(uint8_t index, bool clockwise);
|
||||
bool encoder_update_user(uint8_t index, bool clockwise);
|
||||
|
||||
#if defined(PAL_USE_CALLBACKS) || defined(AVR_USE_INT)
|
||||
void encoder_insert_state(uint8_t index);
|
||||
#endif
|
||||
|
||||
#ifdef SPLIT_KEYBOARD
|
||||
|
||||
void encoder_state_raw(uint8_t* slave_state);
|
||||
|
|
Loading…
Reference in New Issue
Block a user