summaryrefslogtreecommitdiff
path: root/platforms
diff options
context:
space:
mode:
authorJoel Beckmeyer <joel@beckmeyer.us>2025-02-26 06:25:01 -0500
committerGitHub <noreply@github.com>2025-02-26 22:25:01 +1100
commit63b095212b157c4522bdeda3de144fb87213085d (patch)
tree7456a65b007d4acd35d76382a4d6bf297890cb59 /platforms
parent63daf94ee60a629afcce2de623f22ae6777682c5 (diff)
fix EEPROM driver for STM32L0/1 cat.1 devices (#24928)
Diffstat (limited to 'platforms')
-rw-r--r--platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c b/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c
index 628137a0b3..31062a4816 100644
--- a/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c
+++ b/platforms/chibios/drivers/eeprom/eeprom_stm32_L0_L1.c
@@ -25,6 +25,7 @@
25#define EEPROM_ADDR(offset) (EEPROM_BASE_ADDR + (offset)) 25#define EEPROM_ADDR(offset) (EEPROM_BASE_ADDR + (offset))
26#define EEPROM_PTR(offset) ((__IO uint8_t *)EEPROM_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)))) 27#define EEPROM_BYTE(location, offset) (*(EEPROM_PTR(((uint32_t)location) + ((uint32_t)offset))))
28#define EEPROM_WORD(location) (*(__IO uint32_t *)EEPROM_PTR(location))
28 29
29#define BUFFER_BYTE(buffer, offset) (*(((uint8_t *)buffer) + offset)) 30#define BUFFER_BYTE(buffer, offset) (*(((uint8_t *)buffer) + offset))
30 31
@@ -62,12 +63,16 @@ void eeprom_driver_erase(void) {
62 STM32_L0_L1_EEPROM_Unlock(); 63 STM32_L0_L1_EEPROM_Unlock();
63 64
64 for (size_t offset = 0; offset < STM32_ONBOARD_EEPROM_SIZE; offset += sizeof(uint32_t)) { 65 for (size_t offset = 0; offset < STM32_ONBOARD_EEPROM_SIZE; offset += sizeof(uint32_t)) {
66#ifdef QMK_MCU_SERIES_STM32L0XX
65 FLASH->PECR |= FLASH_PECR_ERASE | FLASH_PECR_DATA; 67 FLASH->PECR |= FLASH_PECR_ERASE | FLASH_PECR_DATA;
68#endif
66 69
67 *(__IO uint32_t *)EEPROM_ADDR(offset) = (uint32_t)0; 70 EEPROM_WORD(offset) = (uint32_t)0;
68 71
69 STM32_L0_L1_EEPROM_WaitNotBusy(); 72 STM32_L0_L1_EEPROM_WaitNotBusy();
73#ifdef QMK_MCU_SERIES_STM32L0XX
70 FLASH->PECR &= ~(FLASH_PECR_ERASE | FLASH_PECR_DATA); 74 FLASH->PECR &= ~(FLASH_PECR_ERASE | FLASH_PECR_DATA);
75#endif
71 } 76 }
72 77
73 STM32_L0_L1_EEPROM_Lock(); 78 STM32_L0_L1_EEPROM_Lock();
@@ -86,17 +91,39 @@ void eeprom_read_block(void *buf, const void *addr, size_t len) {
86} 91}
87 92
88void eeprom_write_block(const void *buf, void *addr, size_t len) { 93void eeprom_write_block(const void *buf, void *addr, size_t len) {
89 STM32_L0_L1_EEPROM_Unlock(); 94 // use word-aligned write to overcome issues with writing null bytes
95 uint32_t start_addr = (uint32_t)addr;
96 if (start_addr >= (STM32_ONBOARD_EEPROM_SIZE)) {
97 return;
98 }
99 uint32_t max_len = (STM32_ONBOARD_EEPROM_SIZE)-start_addr;
100 if (len > max_len) {
101 len = max_len;
102 }
103 uint32_t end_addr = start_addr + len;
90 104
91 for (size_t offset = 0; offset < len; ++offset) { 105 uint32_t aligned_start = start_addr & ~0x3;
92 // Drop out if we've hit the limit of the EEPROM 106 uint32_t aligned_end = (end_addr + 3) & ~0x3;
93 if ((((uint32_t)addr) + offset) >= STM32_ONBOARD_EEPROM_SIZE) { 107
94 break; 108 STM32_L0_L1_EEPROM_Unlock();
109 for (uint32_t word_addr = aligned_start; word_addr < aligned_end; word_addr += 4) {
110 uint32_t existing_word = EEPROM_WORD(word_addr);
111 uint32_t new_word = existing_word;
112
113 // Update the relevant bytes in the word
114 for (int i = 0; i < 4; i++) {
115 uint32_t byte_addr = word_addr + i;
116 if (byte_addr >= start_addr && byte_addr < end_addr) {
117 uint8_t new_byte = BUFFER_BYTE(buf, byte_addr - start_addr);
118 new_word = (new_word & ~(0xFFU << (i * 8))) | ((uint32_t)new_byte << (i * 8));
119 }
95 } 120 }
96 121
97 STM32_L0_L1_EEPROM_WaitNotBusy(); 122 // Only write if the word has changed
98 EEPROM_BYTE(addr, offset) = BUFFER_BYTE(buf, offset); 123 if (new_word != existing_word) {
124 STM32_L0_L1_EEPROM_WaitNotBusy();
125 EEPROM_WORD(word_addr) = new_word;
126 }
99 } 127 }
100
101 STM32_L0_L1_EEPROM_Lock(); 128 STM32_L0_L1_EEPROM_Lock();
102} 129}