diff options
author | Purdea Andrei <andrei@purdea.ro> | 2021-06-22 05:34:28 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-21 19:34:28 -0700 |
commit | dd16d3cc7e427c5256f5d2089d0cc2b6bbc776e1 (patch) | |
tree | 7be0f07db5a88c4939354d717e8e600fab6f1ab4 | |
parent | 0e3ae2cde033969507355abcb85f5f7aba2ae978 (diff) | |
download | qmk_firmware-dd16d3cc7e427c5256f5d2089d0cc2b6bbc776e1.tar.gz qmk_firmware-dd16d3cc7e427c5256f5d2089d0cc2b6bbc776e1.zip |
eeprom_i2c driver: added EXTERNAL_EEPROM_WP_PIN configuration option. (#12617)
-rw-r--r-- | docs/eeprom_driver.md | 3 | ||||
-rw-r--r-- | drivers/eeprom/eeprom_i2c.c | 23 |
2 files changed, 25 insertions, 1 deletions
diff --git a/docs/eeprom_driver.md b/docs/eeprom_driver.md index e2c262546..6dcf10c04 100644 --- a/docs/eeprom_driver.md +++ b/docs/eeprom_driver.md | |||
@@ -31,6 +31,9 @@ Currently QMK supports 24xx-series chips over I2C. As such, requires a working i | |||
31 | `#define EXTERNAL_EEPROM_PAGE_SIZE` | Page size of the EEPROM in bytes, as specified in the datasheet | 32 | 31 | `#define EXTERNAL_EEPROM_PAGE_SIZE` | Page size of the EEPROM in bytes, as specified in the datasheet | 32 |
32 | `#define EXTERNAL_EEPROM_ADDRESS_SIZE` | The number of bytes to transmit for the memory location within the EEPROM | 2 | 32 | `#define EXTERNAL_EEPROM_ADDRESS_SIZE` | The number of bytes to transmit for the memory location within the EEPROM | 2 |
33 | `#define EXTERNAL_EEPROM_WRITE_TIME` | Write cycle time of the EEPROM, as specified in the datasheet | 5 | 33 | `#define EXTERNAL_EEPROM_WRITE_TIME` | Write cycle time of the EEPROM, as specified in the datasheet | 5 |
34 | `#define EXTERNAL_EEPROM_WP_PIN` | If defined the WP pin will be toggled appropriately when writing to the EEPROM. | _none_ | ||
35 | |||
36 | Some I2C EEPROM manufacturers explicitly recommend against hardcoding the WP pin to ground. This is in order to protect the eeprom memory content during power-up/power-down/brown-out conditions at low voltage where the eeprom is still operational, but the i2c master output might be unpredictable. If a WP pin is configured, then having an external pull-up on the WP pin is recommended. | ||
34 | 37 | ||
35 | Default values and extended descriptions can be found in `drivers/eeprom/eeprom_i2c.h`. | 38 | Default values and extended descriptions can be found in `drivers/eeprom/eeprom_i2c.h`. |
36 | 39 | ||
diff --git a/drivers/eeprom/eeprom_i2c.c b/drivers/eeprom/eeprom_i2c.c index 4210f06f9..8e80ff544 100644 --- a/drivers/eeprom/eeprom_i2c.c +++ b/drivers/eeprom/eeprom_i2c.c | |||
@@ -16,6 +16,9 @@ | |||
16 | 16 | ||
17 | #include <stdint.h> | 17 | #include <stdint.h> |
18 | #include <string.h> | 18 | #include <string.h> |
19 | #if defined(EXTERNAL_EEPROM_WP_PIN) | ||
20 | # include "gpio.h" | ||
21 | #endif | ||
19 | 22 | ||
20 | /* | 23 | /* |
21 | Note that the implementations of eeprom_XXXX_YYYY on AVR are normally | 24 | Note that the implementations of eeprom_XXXX_YYYY on AVR are normally |
@@ -50,7 +53,14 @@ static inline void fill_target_address(uint8_t *buffer, const void *addr) { | |||
50 | } | 53 | } |
51 | } | 54 | } |
52 | 55 | ||
53 | void eeprom_driver_init(void) { i2c_init(); } | 56 | void eeprom_driver_init(void) { |
57 | i2c_init(); | ||
58 | #if defined(EXTERNAL_EEPROM_WP_PIN) | ||
59 | /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */ | ||
60 | writePin(EXTERNAL_EEPROM_WP_PIN, 1); | ||
61 | setPinInputHigh(EXTERNAL_EEPROM_WP_PIN); | ||
62 | #endif | ||
63 | } | ||
54 | 64 | ||
55 | void eeprom_driver_erase(void) { | 65 | void eeprom_driver_erase(void) { |
56 | #if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) | 66 | #if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT) |
@@ -89,6 +99,11 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) { | |||
89 | uint8_t * read_buf = (uint8_t *)buf; | 99 | uint8_t * read_buf = (uint8_t *)buf; |
90 | uintptr_t target_addr = (uintptr_t)addr; | 100 | uintptr_t target_addr = (uintptr_t)addr; |
91 | 101 | ||
102 | #if defined(EXTERNAL_EEPROM_WP_PIN) | ||
103 | setPinOutput(EXTERNAL_EEPROM_WP_PIN); | ||
104 | writePin(EXTERNAL_EEPROM_WP_PIN, 0); | ||
105 | #endif | ||
106 | |||
92 | while (len > 0) { | 107 | while (len > 0) { |
93 | uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE; | 108 | uintptr_t page_offset = target_addr % EXTERNAL_EEPROM_PAGE_SIZE; |
94 | int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset; | 109 | int write_length = EXTERNAL_EEPROM_PAGE_SIZE - page_offset; |
@@ -116,4 +131,10 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) { | |||
116 | target_addr += write_length; | 131 | target_addr += write_length; |
117 | len -= write_length; | 132 | len -= write_length; |
118 | } | 133 | } |
134 | |||
135 | #if defined(EXTERNAL_EEPROM_WP_PIN) | ||
136 | /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */ | ||
137 | writePin(EXTERNAL_EEPROM_WP_PIN, 1); | ||
138 | setPinInputHigh(EXTERNAL_EEPROM_WP_PIN); | ||
139 | #endif | ||
119 | } | 140 | } |