Skip to content
Snippets Groups Projects
Unverified Commit f1324de9 authored by Sebastian Meiling's avatar Sebastian Meiling Committed by GitHub
Browse files

Merge pull request #8862 from aabadie/pr/periph/eeprom

drivers/periph: add basic API to read/write data to EEPROM
parents 6f2f9abe f3c3818f
No related branches found
No related tags found
No related merge requests found
Showing
with 392 additions and 19 deletions
......@@ -43,6 +43,13 @@ extern "C" {
#endif
/** @} */
/**
* @name EEPROM configuration
* @{
*/
#define EEPROM_SIZE (4096U) /* 4kB */
/** @} */
#ifdef __cplusplus
}
#endif
......
......@@ -44,6 +44,13 @@ extern "C" {
#define THREAD_STACKSIZE_IDLE (128)
/** @} */
/**
* @name EEPROM configuration
* @{
*/
#define EEPROM_SIZE (4096U) /* 4kB */
/** @} */
#ifdef __cplusplus
}
#endif
......
......@@ -42,6 +42,14 @@ extern "C" {
#define THREAD_STACKSIZE_IDLE (128)
/** @} */
/**
* @name EEPROM configuration
* @{
*/
#define EEPROM_SIZE (4096U) /* 4kB */
/** @} */
#ifdef __cplusplus
}
#endif
......
......@@ -47,5 +47,13 @@ extern "C" {
#ifdef __cplusplus
}
#endif
/**
* @name EEPROM configuration
* @{
*/
#define EEPROM_SIZE (8192U) /* 8kB */
/** @} */
#endif /* CPU_CONF_H */
/** @} */
......@@ -42,6 +42,13 @@ extern "C" {
#define THREAD_STACKSIZE_IDLE (128)
/** @} */
/**
* @name EEPROM configuration
* @{
*/
#define EEPROM_SIZE (1024U) /* 1kB */
/** @} */
#ifdef __cplusplus
}
#endif
......
FEATURES_PROVIDED += periph_pm
FEATURES_PROVIDED += periph_eeprom
/*
* 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.
*/
/**
* @ingroup cpu_atmega_common
* @ingroup drivers_periph_eeprom
* @{
*
* @file
* @brief Low-level EEPROM driver implementation for ATmega family
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
* @}
*/
#include <stdint.h>
#include <assert.h>
#include "cpu.h"
#include "periph/eeprom.h"
uint8_t eeprom_read_byte(uint32_t pos)
{
assert(pos < EEPROM_SIZE);
/* Wait for completion of previous operation */
while (EECR & (1 << EEPE)) {}
/* Set up address register */
EEAR = pos;
/* Start eeprom read by writing EERE */
EECR |= (1 << EERE);
/* Return data from Data Register */
return EEDR;
}
void eeprom_write_byte(uint32_t pos, uint8_t data)
{
assert(pos < EEPROM_SIZE);
/* Wait for completion of previous operation */
while (EECR & (1 << EEPE)) {}
/* Set up address and Data Registers */
EEAR = pos;
EEDR = data;
/* Write logical one to EEMPE */
EECR |= (1 << EEMPE);
/* Start eeprom write by setting EEPE */
EECR |= (1 << EEPE);
}
......@@ -8,6 +8,12 @@ USEMODULE += periph_common
# include stm32 common functions and stm32 common periph drivers
USEMODULE += stm32_common stm32_common_periph
# flashpage and eeprom periph implementations share flash lock/unlock functions
# in periph_flash_common
ifneq (,$(filter periph_flashpage periph_eeprom,$(FEATURES_REQUIRED)))
FEATURES_REQUIRED += periph_flash_common
endif
# For stm32 cpu's we use the stm32_common.ld linker script
export LINKFLAGS += -L$(RIOTCPU)/stm32_common/ldscripts
LINKER_SCRIPT ?= stm32_common.ld
......
/*
* 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.
*/
/**
* @ingroup cpu_stm32_common
* @ingroup drivers_periph_eeprom
* @{
*
* @file
* @brief Low-level eeprom driver implementation
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*
* @}
*/
#include <assert.h>
#include "cpu.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "periph/eeprom.h"
extern void _lock(void);
extern void _unlock(void);
#ifndef EEPROM_START_ADDR
#error "periph/eeprom: EEPROM_START_ADDR is not defined"
#endif
uint8_t eeprom_read_byte(uint32_t pos)
{
assert(pos < EEPROM_SIZE);
DEBUG("Reading data from EEPROM at pos %lu\n", pos);
return *(uint8_t *)(EEPROM_START_ADDR + pos);
}
void eeprom_write_byte(uint32_t pos, uint8_t data)
{
assert(pos < EEPROM_SIZE);
DEBUG("Writing data '%c' to EEPROM at pos %lu\n", data, pos);
_unlock();
*(uint8_t *)(EEPROM_START_ADDR + pos) = data;
_lock();
}
/*
* 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.
*/
/**
* @ingroup cpu_stm32_common
* @{
*
* @file
* @brief Low-level flash lock/unlock implementation
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*
* @}
*/
#include "cpu.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
/* Data EEPROM and control register unlock keys */
#define FLASH_KEY1 ((uint32_t)0x89ABCDEF)
#define FLASH_KEY2 ((uint32_t)0x02030405)
#define CNTRL_REG (FLASH->PECR)
#define CNTRL_REG_LOCK (FLASH_PECR_PELOCK)
#define KEY_REG (FLASH->PEKEYR)
#else
#define CNTRL_REG (FLASH->CR)
#define CNTRL_REG_LOCK (FLASH_CR_LOCK)
#define KEY_REG (FLASH->KEYR)
#endif
void _unlock(void)
{
DEBUG("[flash-common] unlocking the flash module\n");
if (CNTRL_REG & CNTRL_REG_LOCK) {
KEY_REG = FLASH_KEY1;
KEY_REG = FLASH_KEY2;
}
}
void _lock(void)
{
DEBUG("[flash-common] locking the flash module\n");
CNTRL_REG |= CNTRL_REG_LOCK;
}
......@@ -32,32 +32,26 @@
#include "periph/flashpage.h"
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
/* Data EEPROM and control register unlock keys */
#define FLASH_KEY1 ((uint32_t)0x89ABCDEF)
#define FLASH_KEY2 ((uint32_t)0x02030405)
/* Program memory unlock keys */
#define FLASH_PRGKEY1 ((uint32_t)0x8C9DAEBF)
#define FLASH_PRGKEY2 ((uint32_t)0x13141516)
#define CNTRL_REG (FLASH->PECR)
#define CNTRL_REG_LOCK (FLASH_PECR_PELOCK)
#define KEY_REG (FLASH->PEKEYR)
#define FLASH_CR_PER (FLASH_PECR_ERASE | FLASH_PECR_PROG)
#define FLASH_CR_PG (FLASH_PECR_FPRG | FLASH_PECR_PROG)
#define FLASHPAGE_DIV (4U) /* write 4 bytes in one go */
#else
#define CNTRL_REG (FLASH->CR)
#define CNTRL_REG_LOCK (FLASH_CR_LOCK)
#define KEY_REG (FLASH->KEYR)
#define FLASHPAGE_DIV (2U)
#endif
static void _unlock(void)
extern void _lock(void);
extern void _unlock(void);
static void _unlock_flash(void)
{
DEBUG("[flashpage] unlocking the flash module\n");
if (CNTRL_REG & CNTRL_REG_LOCK) {
KEY_REG = FLASH_KEY1;
KEY_REG = FLASH_KEY2;
}
_unlock();
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
DEBUG("[flashpage] unlocking the flash program memory\n");
......@@ -71,12 +65,6 @@ static void _unlock(void)
#endif
}
static void _lock(void)
{
DEBUG("[flashpage] locking the flash module\n");
CNTRL_REG |= CNTRL_REG_LOCK;
}
static void _erase_page(void *page_addr)
{
#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
......@@ -90,7 +78,7 @@ static void _erase_page(void *page_addr)
#endif
/* unlock the flash module */
_unlock();
_unlock_flash();
/* make sure no flash operation is ongoing */
DEBUG("[flashpage] erase: waiting for any operation to finish\n");
......@@ -153,7 +141,7 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len)
#endif
DEBUG("[flashpage_raw] unlocking the flash module\n");
_unlock();
_unlock_flash();
DEBUG("[flashpage] write: now writing the data\n");
#if !(defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1))
......
ifeq (,$(filter nucleo-f031k6,$(BOARD)))
FEATURES_PROVIDED += periph_flash_common
FEATURES_PROVIDED += periph_flashpage
FEATURES_PROVIDED += periph_flashpage_raw
endif
......
FEATURES_PROVIDED += periph_flash_common
FEATURES_PROVIDED += periph_flashpage
FEATURES_PROVIDED += periph_flashpage_raw
......
FEATURES_PROVIDED += periph_flash_common
FEATURES_PROVIDED += periph_flashpage
FEATURES_PROVIDED += periph_flashpage_raw
FEATURES_PROVIDED += periph_eeprom
FEATURES_PROVIDED += periph_hwrng
BOARDS_WITHOUT_HWRNG += nucleo-l031k6
......
......@@ -79,6 +79,20 @@ extern "C" {
#define FLASHPAGE_RAW_ALIGNMENT (4U)
/** @} */
/**
* @name EEPROM configuration
* @{
*/
#define EEPROM_START_ADDR (0x08080000)
#if defined(CPU_MODEL_STM32L073RZ) || defined(CPU_MODEL_STM32L072CZ)
#define EEPROM_SIZE (6144U) /* 6kB */
#elif defined(CPU_MODEL_STM32L053R8)
#define EEPROM_SIZE (2048U) /* 2kB */
#elif defined(CPU_MODEL_STM32L031K6)
#define EEPROM_SIZE (1024U) /* 1kB */
#endif
/** @} */
#ifdef __cplusplus
}
#endif
......
FEATURES_PROVIDED += periph_flash_common
FEATURES_PROVIDED += periph_flashpage
FEATURES_PROVIDED += periph_flashpage_raw
FEATURES_PROVIDED += periph_eeprom
-include $(RIOTCPU)/stm32_common/Makefile.features
......@@ -93,6 +93,18 @@ extern "C" {
#define FLASHPAGE_RAW_ALIGNMENT (4U)
/** @} */
/**
* @name EEPROM configuration
* @{
*/
#define EEPROM_START_ADDR (0x08080000)
#if defined(CPU_MODEL_STM32L152RE)
#define EEPROM_SIZE (16384UL) /* 16kB */
#elif defined(CPU_MODEL_STM32L151RC)
#define EEPROM_SIZE (8192U) /* 8kB */
#endif
/** @} */
#ifdef __cplusplus
}
#endif
......
/*
* 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.
*/
/**
* @defgroup drivers_periph_eeprom EEPROM driver
* @ingroup drivers_periph
* @brief Low-level EEPROM interface
*
* @{
* @file
* @brief Low-level eeprom driver interface
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*
*/
#ifndef PERIPH_EEPROM_H
#define PERIPH_EEPROM_H
#include <stdint.h>
#include "cpu.h"
#include "periph_cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef EEPROM_SIZE
#error "periph/eeprom: EEPROM_SIZE is not defined"
#endif
/**
* @brief Read a byte at the given position in eeprom
*
* @param[in] pos position to read
*
* @return the byte read
*/
uint8_t eeprom_read_byte(uint32_t pos);
/**
* @brief Read @p len bytes from the given position
*
* @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
*
* @return the number of bytes read
*/
size_t eeprom_read(uint32_t pos, uint8_t *data, size_t len);
/**
* @brief Write a byte at the given position
*
* @param[in] pos position to write
* @param[in] data byte address to write to
*/
void eeprom_write_byte(uint32_t pos, uint8_t data);
/**
* @brief Write @p len bytes at the given position
*
* @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
*
* @return the number of bytes written
*/
size_t eeprom_write(uint32_t pos, const uint8_t *data, size_t len);
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_EEPROM_H */
/** @} */
/*
* 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.
*/
/**
* @ingroup drivers
* @{
*
* @file
* @brief Common eeprom functions implementation
*
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
*
* @}
*/
#include <string.h>
#include "cpu.h"
#include "assert.h"
/* guard this file, must be done before including periph/eeprom.h */
#if defined(EEPROM_SIZE)
#include "periph/eeprom.h"
size_t eeprom_read(uint32_t pos, uint8_t *data, size_t len)
{
assert(pos + len < EEPROM_SIZE);
for (size_t i = 0; i < len; i++) {
data[i] = eeprom_read_byte(pos++);
}
return len;
}
size_t eeprom_write(uint32_t pos, const uint8_t *data, size_t len)
{
assert(pos + len < EEPROM_SIZE);
for (size_t i = 0; i < len; i++) {
eeprom_write_byte(pos++, data[i]);
}
return len;
}
#endif
BOARD ?= b-l072z-lrwan1
include ../Makefile.tests_common
FEATURES_REQUIRED += periph_eeprom
USEMODULE += shell
USEMODULE += shell_commands # provides reboot command
include $(RIOTBASE)/Makefile.include
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment