aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common_features.mk4
-rw-r--r--docs/eeprom_driver.md12
-rw-r--r--drivers/eeprom/eeprom_stm32_L0_L1.c96
-rw-r--r--drivers/eeprom/eeprom_stm32_L0_L1.h33
4 files changed, 140 insertions, 5 deletions
diff --git a/common_features.mk b/common_features.mk
index fe65974e7..b71dbc77e 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -141,6 +141,10 @@ else
141 SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c 141 SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c
142 OPT_DEFS += -DEEPROM_EMU_STM32F072xB 142 OPT_DEFS += -DEEPROM_EMU_STM32F072xB
143 OPT_DEFS += -DSTM32_EEPROM_ENABLE 143 OPT_DEFS += -DSTM32_EEPROM_ENABLE
144 else ifneq ($(filter $(MCU_SERIES),STM32L0xx STM32L1xx),)
145 OPT_DEFS += -DEEPROM_DRIVER
146 COMMON_VPATH += $(DRIVER_PATH)/eeprom
147 SRC += eeprom_driver.c eeprom_stm32_L0_L1.c
144 else 148 else
145 # This will effectively work the same as "transient" if not supported by the chip 149 # This will effectively work the same as "transient" if not supported by the chip
146 SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c 150 SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c
diff --git a/docs/eeprom_driver.md b/docs/eeprom_driver.md
index dd12d8ec7..5a91a7c2d 100644
--- a/docs/eeprom_driver.md
+++ b/docs/eeprom_driver.md
@@ -2,14 +2,16 @@
2 2
3The EEPROM driver can be swapped out depending on the needs of the keyboard, or whether extra hardware is present. 3The EEPROM driver can be swapped out depending on the needs of the keyboard, or whether extra hardware is present.
4 4
5Driver | Description 5Driver | Description
6--------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 6-----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7`EEPROM_DRIVER = vendor` | Uses the on-chip driver provided by the chip manufacturer. For AVR, this is provided by avr-libc. This is supported on ARM for a subset of chips -- STM32F3xx, STM32F1xx, and STM32F072xB will be emulated by writing to flash. Other chips will generally act as "transient" below. 7`EEPROM_DRIVER = vendor` (default) | Uses the on-chip driver provided by the chip manufacturer. For AVR, this is provided by avr-libc. This is supported on ARM for a subset of chips -- STM32F3xx, STM32F1xx, and STM32F072xB will be emulated by writing to flash. STM32L0xx and STM32L1xx will use the onboard dedicated true EEPROM. Other chips will generally act as "transient" below.
8`EEPROM_DRIVER = i2c` | Supports writing to I2C-based 24xx EEPROM chips. See the driver section below. 8`EEPROM_DRIVER = i2c` | Supports writing to I2C-based 24xx EEPROM chips. See the driver section below.
9`EEPROM_DRIVER = transient` | Fake EEPROM driver -- supports reading/writing to RAM, and will be discarded when power is lost. 9`EEPROM_DRIVER = transient` | Fake EEPROM driver -- supports reading/writing to RAM, and will be discarded when power is lost.
10 10
11## Vendor Driver Configuration 11## Vendor Driver Configuration
12 12
13!> Resetting EEPROM using an STM32L0/L1 device takes up to 1 second for every 1kB of internal EEPROM used.
14
13No configurable options are available. 15No configurable options are available.
14 16
15## I2C Driver Configuration 17## I2C Driver Configuration
diff --git a/drivers/eeprom/eeprom_stm32_L0_L1.c b/drivers/eeprom/eeprom_stm32_L0_L1.c
new file mode 100644
index 000000000..b62e6ffd7
--- /dev/null
+++ b/drivers/eeprom/eeprom_stm32_L0_L1.c
@@ -0,0 +1,96 @@
1/* Copyright 2020 Nick Brassel (tzarc)
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <stdint.h>
18#include <string.h>
19
20#include "hal.h"
21#include "eeprom_driver.h"
22#include "eeprom_stm32_L0_L1.h"
23
24#define EEPROM_BASE_ADDR 0x08080000
25#define EEPROM_ADDR(offset) (EEPROM_BASE_ADDR + (offset))
26#define EEPROM_PTR(offset) ((__IO uint8_t *)EEPROM_ADDR(offset))
27#define EEPROM_BYTE(location, offset) (*(EEPROM_PTR(((uint32_t)location) + ((uint32_t)offset))))
28
29#define BUFFER_BYTE(buffer, offset) (*(((uint8_t *)buffer) + offset))
30
31#define FLASH_PEKEY1 0x89ABCDEF
32#define FLASH_PEKEY2 0x02030405
33
34static inline void STM32_L0_L1_EEPROM_WaitNotBusy(void) {
35 while (FLASH->SR & FLASH_SR_BSY) {
36 __WFI();
37 }
38}
39
40static inline void STM32_L0_L1_EEPROM_Unlock(void) {
41 STM32_L0_L1_EEPROM_WaitNotBusy();
42 if (FLASH->PECR & FLASH_PECR_PELOCK) {
43 FLASH->PEKEYR = FLASH_PEKEY1;
44 FLASH->PEKEYR = FLASH_PEKEY2;
45 }
46}
47
48static inline void STM32_L0_L1_EEPROM_Lock(void) {
49 STM32_L0_L1_EEPROM_WaitNotBusy();
50 FLASH->PECR |= FLASH_PECR_PELOCK;
51}
52
53void eeprom_driver_init(void) {}
54
55void eeprom_driver_erase(void) {
56 STM32_L0_L1_EEPROM_Unlock();
57
58 for (size_t offset = 0; offset < STM32_ONBOARD_EEPROM_SIZE; offset += sizeof(uint32_t)) {
59 FLASH->PECR |= FLASH_PECR_ERASE | FLASH_PECR_DATA;
60
61 *(__IO uint32_t *)EEPROM_ADDR(offset) = (uint32_t)0;
62
63 STM32_L0_L1_EEPROM_WaitNotBusy();
64 FLASH->PECR &= ~(FLASH_PECR_ERASE | FLASH_PECR_DATA);
65 }
66
67 STM32_L0_L1_EEPROM_Lock();
68}
69
70void eeprom_read_block(void *buf, const void *addr, size_t len) {
71 for (size_t offset = 0; offset < len; ++offset) {
72 // Drop out if we've hit the limit of the EEPROM
73 if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) {
74 break;
75 }
76
77 STM32_L0_L1_EEPROM_WaitNotBusy();
78 BUFFER_BYTE(buf, offset) = EEPROM_BYTE(addr, offset);
79 }
80}
81
82void eeprom_write_block(const void *buf, void *addr, size_t len) {
83 STM32_L0_L1_EEPROM_Unlock();
84
85 for (size_t offset = 0; offset < len; ++offset) {
86 // Drop out if we've hit the limit of the EEPROM
87 if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) {
88 break;
89 }
90
91 STM32_L0_L1_EEPROM_WaitNotBusy();
92 EEPROM_BYTE(addr, offset) = BUFFER_BYTE(buf, offset);
93 }
94
95 STM32_L0_L1_EEPROM_Lock();
96}
diff --git a/drivers/eeprom/eeprom_stm32_L0_L1.h b/drivers/eeprom/eeprom_stm32_L0_L1.h
new file mode 100644
index 000000000..a35defca8
--- /dev/null
+++ b/drivers/eeprom/eeprom_stm32_L0_L1.h
@@ -0,0 +1,33 @@
1/* Copyright 2020 Nick Brassel (tzarc)
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#pragma once
18
19/*
20 The size used by the STM32 L0/L1 EEPROM driver.
21*/
22#ifndef STM32_ONBOARD_EEPROM_SIZE
23# ifdef VIA_ENABLE
24# define STM32_ONBOARD_EEPROM_SIZE 1024
25# else
26# include "eeconfig.h"
27# define STM32_ONBOARD_EEPROM_SIZE (((EECONFIG_SIZE + 3) / 4) * 4) // based off eeconfig's current usage, aligned to 4-byte sizes, to deal with LTO and EEPROM page sizing
28# endif
29#endif
30
31#if STM32_ONBOARD_EEPROM_SIZE > 128
32# pragma message("Please note: resetting EEPROM using an STM32L0/L1 device takes up to 1 second for every 1kB of internal EEPROM used.")
33#endif