diff --git a/cpu/atmega_common/periph/eeprom.c b/cpu/atmega_common/periph/eeprom.c index 2a3827336ddd08532d444a4137837c61fef83052..15129e53f6cc62179fde91858836e0ee875e6064 100644 --- a/cpu/atmega_common/periph/eeprom.c +++ b/cpu/atmega_common/periph/eeprom.c @@ -24,37 +24,52 @@ #include "cpu.h" #include "periph/eeprom.h" -uint8_t eeprom_read_byte(uint32_t pos) +#define ENABLE_DEBUG (0) +#include "debug.h" + +size_t eeprom_read(uint32_t pos, uint8_t *data, size_t len) { - assert(pos < EEPROM_SIZE); + assert(pos + len <= EEPROM_SIZE); + + uint8_t *p = data; - /* Wait for completion of previous operation */ - while (EECR & (1 << EEPE)) {} + DEBUG("Reading data from EEPROM at pos %" PRIu32 ": ", pos); + for (size_t i = 0; i < len; i++) { + while (EECR & (1 << EEPE)) {} - /* Set up address register */ - EEAR = pos; + /* Set up address register */ + EEAR = pos++; - /* Start eeprom read by writing EERE */ - EECR |= (1 << EERE); + /* Start eeprom read by writing EERE */ + EECR |= (1 << EERE); + *p++ = (uint8_t)EEDR; + DEBUG("0x%02X ", EEDR); + } + DEBUG("\n"); - /* Return data from Data Register */ - return EEDR; + return len; } -void eeprom_write_byte(uint32_t pos, uint8_t data) +size_t eeprom_write(uint32_t pos, const uint8_t *data, size_t len) { - assert(pos < EEPROM_SIZE); + assert(pos + len <= EEPROM_SIZE); + + uint8_t *p = (uint8_t *)data; + + for (size_t i = 0; i < len; i++) { + /* Wait for completion of previous operation */ + while (EECR & (1 << EEPE)) {} - /* Wait for completion of previous operation */ - while (EECR & (1 << EEPE)) {} + /* Set up address and Data Registers */ + EEAR = pos++; + EEDR = *p++; - /* Set up address and Data Registers */ - EEAR = pos; - EEDR = data; + /* Write logical one to EEMPE */ + EECR |= (1 << EEMPE); - /* Write logical one to EEMPE */ - EECR |= (1 << EEMPE); + /* Start eeprom write by setting EEPE */ + EECR |= (1 << EEPE); + } - /* Start eeprom write by setting EEPE */ - EECR |= (1 << EEPE); + return len; } diff --git a/cpu/stm32_common/periph/eeprom.c b/cpu/stm32_common/periph/eeprom.c index bef71291b3b02a66bddf4b7aef35639cc387eb2a..962b543babfb5db451694ef034978b1e0c9ef9af 100644 --- a/cpu/stm32_common/periph/eeprom.c +++ b/cpu/stm32_common/periph/eeprom.c @@ -22,12 +22,11 @@ #include <assert.h> #include "cpu.h" +#include "periph/eeprom.h" #define ENABLE_DEBUG (0) #include "debug.h" -#include "periph/eeprom.h" - extern void _lock(void); extern void _unlock(void); @@ -35,20 +34,35 @@ extern void _unlock(void); #error "periph/eeprom: EEPROM_START_ADDR is not defined" #endif -uint8_t eeprom_read_byte(uint32_t pos) +size_t eeprom_read(uint32_t pos, uint8_t *data, size_t len) { - assert(pos < EEPROM_SIZE); + assert(pos + len <= EEPROM_SIZE); + + uint8_t *p = data; + + DEBUG("Reading data from EEPROM at pos %" PRIu32 ": ", pos); + for (size_t i = 0; i < len; i++) { + *p++ = *(uint8_t *)(EEPROM_START_ADDR + pos++); + DEBUG("0x%02X ", *p); + } + DEBUG("\n"); - DEBUG("Reading data from EEPROM at pos %" PRIu32 "\n", pos); - return *(uint8_t *)(EEPROM_START_ADDR + pos); + return len; } -void eeprom_write_byte(uint32_t pos, uint8_t data) +size_t eeprom_write(uint32_t pos, const uint8_t *data, size_t len) { - assert(pos < EEPROM_SIZE); + assert(pos + len <= EEPROM_SIZE); + + uint8_t *p = (uint8_t *)data; - DEBUG("Writing data '%c' to EEPROM at pos %" PRIu32 "\n", data, pos); _unlock(); - *(uint8_t *)(EEPROM_START_ADDR + pos) = data; + + for (size_t i = 0; i < len; i++) { + *(uint8_t *)(EEPROM_START_ADDR + pos++) = *p++; + } + _lock(); + + return len; } diff --git a/drivers/include/periph/eeprom.h b/drivers/include/periph/eeprom.h index 09dd5034ee8b0b30ff031ca2f1762a5e942023c1..affdf13572b2c4a6c860fbf4563692d6a0cf06f1 100644 --- a/drivers/include/periph/eeprom.h +++ b/drivers/include/periph/eeprom.h @@ -46,6 +46,9 @@ uint8_t eeprom_read_byte(uint32_t pos); /** * @brief Read @p len bytes from the given position * + * This function must be implemented by each CPU that provides an internal + * EEPROM. + * * @param[in] pos start position in eeprom * @param[out] data output byte array to write to * @param[in] len the number of bytes to read @@ -65,6 +68,9 @@ void eeprom_write_byte(uint32_t pos, uint8_t data); /** * @brief Write @p len bytes at the given position * + * This function must be implemented by each CPU that provides an internal + * EEPROM. + * * @param[in] pos start position in eeprom * @param[in] data input byte array to read into * @param[in] len the number of bytes to read diff --git a/drivers/periph_common/eeprom.c b/drivers/periph_common/eeprom.c index 07fd94e6db61d3a57566ebb5d6afd3c360c95f56..d22c512701d15df1eb8977dcd940be8abcfe9bcc 100644 --- a/drivers/periph_common/eeprom.c +++ b/drivers/periph_common/eeprom.c @@ -28,26 +28,16 @@ #include "periph/eeprom.h" -size_t eeprom_read(uint32_t pos, uint8_t *data, size_t len) +uint8_t eeprom_read_byte(uint32_t pos) { - assert(pos + len < EEPROM_SIZE); - - for (size_t i = 0; i < len; i++) { - data[i] = eeprom_read_byte(pos++); - } - - return len; + uint8_t byte; + eeprom_read(pos, &byte, 1); + return byte; } -size_t eeprom_write(uint32_t pos, const uint8_t *data, size_t len) +void eeprom_write_byte(uint32_t pos, uint8_t byte) { - assert(pos + len < EEPROM_SIZE); - - for (size_t i = 0; i < len; i++) { - eeprom_write_byte(pos++, data[i]); - } - - return len; + eeprom_write(pos, &byte, 1); } #endif diff --git a/tests/periph_eeprom/main.c b/tests/periph_eeprom/main.c index 0de526c83a5dc3498e0487dff2a190b7809116a1..0eac47877f6c3eb016e180798a39217ead634ad3 100644 --- a/tests/periph_eeprom/main.c +++ b/tests/periph_eeprom/main.c @@ -21,6 +21,7 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <assert.h> #include "shell.h" @@ -65,7 +66,7 @@ static int cmd_read(int argc, char **argv) return 1; } - if (pos + count >= EEPROM_SIZE) { + if (pos + count > EEPROM_SIZE) { puts("Failed: cannot read out of eeprom bounds"); return 1; } @@ -78,6 +79,26 @@ static int cmd_read(int argc, char **argv) return 0; } +static int cmd_read_byte(int argc, char **argv) +{ + if (argc < 2) { + printf("usage: %s <pos>\n", argv[0]); + return 1; + } + + uint32_t pos = atoi(argv[1]); + + if (pos >= EEPROM_SIZE) { + puts("Failed: cannot read out of eeprom bounds"); + return 1; + } + + uint8_t byte = eeprom_read_byte(pos); + printf("Byte read from EEPROM: 0x%02X (%c)\n", byte, byte); + + return 0; +} + static int cmd_write(int argc, char **argv) { if (argc < 3) { @@ -87,7 +108,7 @@ static int cmd_write(int argc, char **argv) uint32_t pos = atoi(argv[1]); - if (pos + strlen(argv[2]) >= EEPROM_SIZE) { + if (pos + strlen(argv[2]) > EEPROM_SIZE) { puts("Failed: cannot write out of eeprom bounds"); return 1; } @@ -98,10 +119,75 @@ static int cmd_write(int argc, char **argv) return 0; } +static int cmd_write_byte(int argc, char **argv) +{ + if (argc < 3) { + printf("usage: %s <pos> <byte>\n", argv[0]); + return 1; + } + + uint32_t pos = atoi(argv[1]); + + if (pos >= EEPROM_SIZE) { + puts("Failed: cannot write out of eeprom bounds"); + return 1; + } + + eeprom_write_byte(pos, *(uint8_t *)argv[2]); + printf("Byte written to EEPROM\n"); + + return 0; +} + +static int cmd_test(int argc, char **argv) +{ + (void)argv; + + if (argc != 1) { + puts("FAILED"); + return 1; + } + + const char *test = "test"; + + /* test read/write function */ + + /* read/write from beginning of EEPROM */ + size_t ret = eeprom_write(0, (uint8_t *)test, 4); + assert(ret == 4); + + char *expected[4]; + ret = eeprom_read(0, (uint8_t *)expected, 4); + assert(strncmp((const char *)expected, (const char *)test, 4) == 0); + assert(ret == 4); + + /* read/write at end of EEPROM */ + ret = eeprom_write(EEPROM_SIZE - 4, (uint8_t *)test, 4); + assert(ret == 4); + ret = eeprom_read(EEPROM_SIZE - 4, (uint8_t *)expected, 4); + assert(strncmp((const char *)expected, test, 4) == 0); + assert(ret == 4); + + /* read/write single byte */ + eeprom_write_byte(0, 'A'); + assert(eeprom_read_byte(0) == 'A'); + eeprom_write_byte(EEPROM_SIZE - 1, 'A'); + assert(eeprom_read_byte(EEPROM_SIZE - 1) == 'A'); + eeprom_write_byte(EEPROM_SIZE / 2, 'A'); + assert(eeprom_read_byte(EEPROM_SIZE / 2) == 'A'); + + puts("SUCCESS"); + return 0; +} + + static const shell_command_t shell_commands[] = { { "info", "Print information about eeprom", cmd_info }, { "read", "Read bytes from eeprom", cmd_read }, - { "write", "Write bytes to eeprom", cmd_write}, + { "write", "Write bytes to eeprom", cmd_write }, + { "read_byte", "Read a single byte from eeprom", cmd_read_byte }, + { "write_byte", "Write a single byte to eeprom", cmd_write_byte }, + { "test", "Test the EEPROM implementation", cmd_test }, { NULL, NULL, NULL } }; diff --git a/tests/periph_eeprom/tests/01-run.py b/tests/periph_eeprom/tests/01-run.py new file mode 100755 index 0000000000000000000000000000000000000000..26c16c36d6889adf59b970ab0dd1a00d71612ac1 --- /dev/null +++ b/tests/periph_eeprom/tests/01-run.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2018 Inria +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +import sys +from testrunner import run + + +def testfunc(child): + child.sendline('test') + child.expect('SUCCESS') + + +if __name__ == "__main__": + sys.exit(run(testfunc))