~ruther/qmk_firmware

dd16d3cc7e427c5256f5d2089d0cc2b6bbc776e1 — Purdea Andrei 4 years ago 0e3ae2c
eeprom_i2c driver: added EXTERNAL_EEPROM_WP_PIN configuration option. (#12617)

2 files changed, 25 insertions(+), 1 deletions(-)

M docs/eeprom_driver.md
M drivers/eeprom/eeprom_i2c.c
M docs/eeprom_driver.md => docs/eeprom_driver.md +3 -0
@@ 31,6 31,9 @@ Currently QMK supports 24xx-series chips over I2C. As such, requires a working i
`#define EXTERNAL_EEPROM_PAGE_SIZE`         | Page size of the EEPROM in bytes, as specified in the datasheet                     | 32
`#define EXTERNAL_EEPROM_ADDRESS_SIZE`      | The number of bytes to transmit for the memory location within the EEPROM           | 2
`#define EXTERNAL_EEPROM_WRITE_TIME`        | Write cycle time of the EEPROM, as specified in the datasheet                       | 5
`#define EXTERNAL_EEPROM_WP_PIN`            | If defined the WP pin will be toggled appropriately when writing to the EEPROM.     | _none_

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.

Default values and extended descriptions can be found in `drivers/eeprom/eeprom_i2c.h`.


M drivers/eeprom/eeprom_i2c.c => drivers/eeprom/eeprom_i2c.c +22 -1
@@ 16,6 16,9 @@

#include <stdint.h>
#include <string.h>
#if defined(EXTERNAL_EEPROM_WP_PIN)
#    include "gpio.h"
#endif

/*
    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) {
    }
}

void eeprom_driver_init(void) { i2c_init(); }
void eeprom_driver_init(void) {
    i2c_init();
#if defined(EXTERNAL_EEPROM_WP_PIN)
    /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
    writePin(EXTERNAL_EEPROM_WP_PIN, 1);
    setPinInputHigh(EXTERNAL_EEPROM_WP_PIN);
#endif
}

void eeprom_driver_erase(void) {
#if defined(CONSOLE_ENABLE) && defined(DEBUG_EEPROM_OUTPUT)


@@ 89,6 99,11 @@ void eeprom_write_block(const void *buf, void *addr, size_t len) {
    uint8_t * read_buf    = (uint8_t *)buf;
    uintptr_t target_addr = (uintptr_t)addr;

#if defined(EXTERNAL_EEPROM_WP_PIN)
    setPinOutput(EXTERNAL_EEPROM_WP_PIN);
    writePin(EXTERNAL_EEPROM_WP_PIN, 0);
#endif

    while (len > 0) {
        uintptr_t page_offset  = target_addr % EXTERNAL_EEPROM_PAGE_SIZE;
        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) {
        target_addr += write_length;
        len -= write_length;
    }

#if defined(EXTERNAL_EEPROM_WP_PIN)
    /* We are setting the WP pin to high in a way that requires at least two bit-flips to change back to 0 */
    writePin(EXTERNAL_EEPROM_WP_PIN, 1);
    setPinInputHigh(EXTERNAL_EEPROM_WP_PIN);
#endif
}