cpu/native: Add file-backed simulated EEPROM to native cpu.

This patch removes a defunct EEPROM implementation from the native
platform and provides a new EEPROM implementation for the native cpu.
The previous implementation appears to be vestigal.

This is useful for testing code which uses the EEPROM without running
the code on the actual hardware.

By default the code will create a new temporary file as the EEPROM
backing, reinitializing each time. If you would like to preserve the
EEPROM contents or specify a specific EEPROM file to use, you can set the
`CONTIKI_EEPROM` environment variable to the name of the EEPROM file you
wish to use instead. If it already exists, its contents will be used.
If it does not already exist, it will be created and initialized by
filling it with `0xFF`---just like a real EEPROM.

A new example is also included, which was used to verify the correctness
of the implementation. It can easily be used to verify the EEPROM
implementations of other targets.
This commit is contained in:
Robert Quattlebaum 2013-01-10 09:34:48 -08:00
parent 5af6540980
commit b8c0f2de6c
10 changed files with 298 additions and 69 deletions

View File

@ -55,8 +55,21 @@
#define __EEPROM_H__
typedef unsigned short eeprom_addr_t;
#define EEPROM_NULL 0
#ifdef EEPROM_CONF_SIZE
#define EEPROM_SIZE (EEPROM_CONF_SIZE)
#else
#define EEPROM_SIZE 0 /* Default to no EEPROM */
#endif
#ifdef EEPROM_CONF_END_ADDR
#define EEPROM_END_ADDR (EEPROM_CONF_END_ADDR)
#else
#define EEPROM_END_ADDR (EEPROM_SIZE - 1)
#endif
/**
* Write a buffer into EEPROM.
*

View File

@ -1,6 +1,6 @@
CONTIKI_CPU_DIRS = . net
CONTIKI_CPU_DIRS = . net dev
CONTIKI_SOURCEFILES += mtarch.c rtimer-arch.c elfloader-stub.c watchdog.c
CONTIKI_SOURCEFILES += mtarch.c rtimer-arch.c elfloader-stub.c watchdog.c eeprom.c
### Compiler definitions
CC ?= gcc

167
cpu/native/dev/eeprom.c Normal file
View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2013, Robert Quattlebaum.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
* Author: Robert Quattlebaum <darco@deepdarc.com>
*
*/
#include "contiki.h"
#include "dev/eeprom.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static FILE *eeprom_file;
/*---------------------------------------------------------------------------*/
static void
eeprom_fill(eeprom_addr_t addr, unsigned char value, int size)
{
if((addr > EEPROM_END_ADDR) || (addr+size > EEPROM_END_ADDR+1) || size < 0) {
fprintf(stderr, "eeprom_fill: Bad address and/or size (addr = %04x, size = %d)\n", addr, size);
/* Abort here so that we break into the debugger. If a debugger isn't
* attached, well we might as well crash anyway.
*/
abort();
}
if(!eeprom_file) {
eeprom_init();
}
fseek(eeprom_file, addr, SEEK_SET);
while(size--) {
if(fputc(value, eeprom_file) != value) {
perror("fputc() failed");
exit(EXIT_FAILURE);
}
}
}
/*---------------------------------------------------------------------------*/
void
eeprom_init(void)
{
long length;
char *eeprom_filename = getenv("CONTIKI_EEPROM");
if(eeprom_filename) {
eeprom_file = fopen(eeprom_filename, "r+");
if(!eeprom_file) {
/* File does exist yet, so let's create it. */
eeprom_file = fopen(eeprom_filename, "w+");
if(!eeprom_file) {
perror("Unable to create EEPROM file");
exit(EXIT_FAILURE);
}
}
fprintf(stderr, "eeprom_init: Using \"%s\".\n", eeprom_filename);
} else {
eeprom_file = tmpfile();
if(!eeprom_file) {
perror("Unable to create temporary EEPROM file");
exit(EXIT_FAILURE);
}
}
/* Make sure that the file is the correct size by seeking
* to the end and checking the file position. If it is
* less than what we expect, we pad out the rest of the file
* with 0xFF, just like a real EEPROM. */
fseek(eeprom_file, 0, SEEK_END);
length = ftell(eeprom_file);
if(length < 0) {
perror("ftell failed");
exit(EXIT_FAILURE);
}
if(length < EEPROM_END_ADDR) {
/* Fill with 0xFF, just like a real EEPROM. */
eeprom_fill(length, 0xFF, EEPROM_SIZE - length);
}
}
/*---------------------------------------------------------------------------*/
void
eeprom_write(eeprom_addr_t addr, unsigned char *buf, int size)
{
if((addr > EEPROM_END_ADDR) || (addr+size > EEPROM_END_ADDR+1) || size < 0) {
fprintf(stderr, "eeprom_write: Bad address and/or size (addr = %04x, size = %d)\n", addr, size);
/* Abort here so that we break into the debugger. If a debugger isn't
* attached, well we might as well crash anyway.
*/
abort();
}
if(!eeprom_file) {
eeprom_init();
}
fseek(eeprom_file, addr, SEEK_SET);
if(fwrite(buf, 1, size, eeprom_file) != size) {
perror("fwrite() failed");
exit(EXIT_FAILURE);
}
}
/*---------------------------------------------------------------------------*/
void
eeprom_read(eeprom_addr_t addr, unsigned char *buf, int size)
{
if((addr > EEPROM_END_ADDR) || (addr+size > EEPROM_END_ADDR+1) || size < 0) {
fprintf(stderr, "eeprom_read: Bad address and/or size (addr = %04x, size = %d)\n", addr, size);
/* Abort here so that we break into the debugger. If a debugger isn't
* attached, well we might as well crash anyway. */
abort();
}
if(!eeprom_file) {
eeprom_init();
}
fseek(eeprom_file, addr, SEEK_SET);
if(fread(buf, 1, size, eeprom_file) != size) {
perror("fread() failed");
exit(EXIT_FAILURE);
}
}

View File

@ -0,0 +1,5 @@
CONTIKI_PROJECT = eeprom-test
all: $(CONTIKI_PROJECT)
CONTIKI = ../..
include $(CONTIKI)/Makefile.include

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2013, Robert Quattlebaum
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* A very simple Contiki application showing how to read and write
* data using Contiki's EEPROM API.
* \author
* Robert Quattlebaum <darco@deepdarc.com>
*/
#include "contiki.h"
#include "dev/eeprom.h"
#include <stdio.h> /* For printf() */
/*---------------------------------------------------------------------------*/
PROCESS(eeprom_test_process, "EEPROM Test Process");
AUTOSTART_PROCESSES(&eeprom_test_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(eeprom_test_process, ev, data)
{
static uint8_t counter = 0;
static eeprom_addr_t addr = 0;
PROCESS_BEGIN();
printf("eeprom-test: Size = %d bytes\n", EEPROM_SIZE);
/* Check to see if the EEPROM is empty */
for(addr = 0; addr < EEPROM_SIZE; ++addr) {
uint8_t byte;
eeprom_read(addr, &byte, 1);
if(byte != 0xFF) {
break;
}
}
if(addr == EEPROM_SIZE) {
printf("eeprom-test: EEPROM is empty. Proceding with write test...\n");
counter = 0;
for(addr = 0; addr < EEPROM_SIZE; ++addr) {
eeprom_write(addr, &counter, 1);
counter += 1;
}
counter = 0;
for(addr = 0; addr < EEPROM_SIZE; ++addr) {
uint8_t byte;
eeprom_read(addr, &byte, 1);
if(byte != counter) {
printf("eeprom-test: EEPROM write failure!\n");
break;
}
counter += 1;
}
printf("eeprom-test: EEPROM write test success!\n");
} else {
printf("eeprom-test: EEPROM is NOT empty! Skipping write test.\n");
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View File

@ -39,6 +39,10 @@
#define COOJA 1
#ifndef EEPROM_CONF_SIZE
#define EEPROM_CONF_SIZE 1024
#endif
#define w_memcpy memcpy
#if WITH_UIP

View File

@ -44,6 +44,10 @@
#define CCIF
#define CLIF
#ifndef EEPROM_CONF_SIZE
#define EEPROM_CONF_SIZE 1024
#endif
/* These names are deprecated, use C99 names. */
typedef uint8_t u8_t;
typedef uint16_t u16_t;

View File

@ -50,6 +50,9 @@ int select_set_callback(int fd, const struct select_callback *callback);
#define CC_CONF_VA_ARGS 1
/*#define CC_CONF_INLINE inline*/
#ifndef EEPROM_CONF_SIZE
#define EEPROM_CONF_SIZE 1024
#endif
#define CCIF
#define CLIF

View File

@ -1,66 +0,0 @@
/*
* Copyright (c) 2004, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
#include "dev/eeprom.h"
#include "node.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
static unsigned char eeprom[65536];
void
eeprom_write(eeprom_addr_t addr, unsigned char *buf, int size)
{
int f;
char name[400];
snprintf(name, sizeof(name), "eeprom.%d.%d", node_x(), node_y());
f = open(name, O_WRONLY | O_APPEND | O_CREAT, 0644);
lseek(f, addr, SEEK_SET);
write(f, buf, size);
close(f);
printf("eeprom_write(addr 0x%02x, buf %p, size %d);\n", addr, buf, size);
memcpy(&eeprom[addr], buf, size);
}
void
eeprom_read(eeprom_addr_t addr, unsigned char *buf, int size)
{
/* printf("eeprom_read(addr 0x%02x, buf %p, size %d);\n", addr, buf, size);*/
memcpy(buf, &eeprom[addr], size);
}

View File

@ -15,6 +15,7 @@ hello-world/wismote \
hello-world/z1 \
hello-world/sensinode \
hello-world/cc2530dk \
eeprom-test/native \
ipv6/rpl-border-router/econotag \
collect/sky \
er-rest-example/sky \