Merge pull request #688 from SmallLars/flash

App/Tool/Example for usage of additional flash on econotag/mc1322x
This commit is contained in:
Mariano Alvira 2015-09-21 10:58:33 -05:00
commit aecb591d12
14 changed files with 1124 additions and 0 deletions

View file

@ -36,6 +36,7 @@ before_script:
tar xjf arm-2008q3*.tar.bz2 -C /tmp/ && tar xjf arm-2008q3*.tar.bz2 -C /tmp/ &&
sudo cp -f -r /tmp/arm-2008q3/* /usr/ && sudo cp -f -r /tmp/arm-2008q3/* /usr/ &&
rm -rf /tmp/arm-2008q3 arm-2008q3*.tar.bz2 && rm -rf /tmp/arm-2008q3 arm-2008q3*.tar.bz2 &&
sudo apt-get -qq install libconfig-dev uuid-dev libqrencode-dev &&
arm-none-eabi-gcc --version ; arm-none-eabi-gcc --version ;
fi fi

View file

@ -0,0 +1,31 @@
CONTIKI = ../..
LIBMC1322X = ../../../libmc1322x
CONTIKI_PROJECT = econotag-flash-test
TARGET = econotag
CLEAN = *.d $(CONTIKI_PROJECT)_e_$(TARGET).bin $(CONTIKI_PROJECT)_e_$(TARGET).txt $(CONTIKI_PROJECT)_e_$(TARGET).pbm
all: $(CONTIKI_PROJECT) blast
CFLAGS += -DFLASH_CONF_B1=30
CFLAGS += -DFLASH_CONF_B2=10
APPS += flash
flash:
$(LIBMC1322X)/tools/mc1322x-load \
-f $(LIBMC1322X)/tests/flasher_$(TARGET).bin \
-s $(CONTIKI_PROJECT)_e_$(TARGET).bin \
-c 'sudo $(LIBMC1322X)/tools/ftditools/bbmc -l $(TARGET) -i 0 reset' \
-t /dev/ttyUSB1 -l
clear:
$(LIBMC1322X)/tools/ftditools/bbmc -l $(TARGET) -i 0 erase
blast: $(CONTIKI)/tools/blaster/blaster
$(CONTIKI)/tools/blaster/blaster $(CONTIKI_PROJECT).cfg
$(CONTIKI)/tools/blaster/blaster: $(CONTIKI)/tools/blaster/blaster.c
(cd $(CONTIKI)/tools/blaster && $(MAKE))
include $(CONTIKI)/Makefile.include

View file

@ -0,0 +1,6 @@
Its important to use -l as a flash parameter for mc1322xload.
Use "make flash" to start upload. Maybe u need
to change the location of libmc1322x in Makefile.
With "make clear" you can erase all flash data.

View file

@ -0,0 +1,195 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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
* Flash test
*
* This file contains tests for econotag flash app
*
* \author
* Lars Schmertmann <SmallLars@t-online.de>
*/
#include "flash.h"
#include "contiki.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "../../tools/blaster/blaster.h"
#include "econotag-flash-test.h"
void
output_result(uint32_t i, uint32_t fail)
{
if(fail) {
printf(" Test %u failed!\n", i);
} else { printf(" Test %u succeed!\n", i);
}
}
void
test_flash_1()
{
uint8_t buffer[12];
uint32_t check_int, my_int = 12345678;
flash_setVar("Hello World!", RES_MY_STRING_1, LEN_MY_STRING_1);
flash_getVar(buffer, RES_MY_STRING_1, LEN_MY_STRING_1);
output_result(1, memcmp(buffer, "Hello World!", 12));
flash_setVar("Heureka!", RES_MY_STRING_2, LEN_MY_STRING_2);
flash_getVar(buffer, RES_MY_STRING_1, LEN_MY_STRING_1);
output_result(2, memcmp(buffer, "Hello World!", 12));
flash_getVar(buffer, RES_MY_STRING_2, LEN_MY_STRING_2);
output_result(3, memcmp(buffer, "Heureka!", 8));
flash_setVar(&my_int, RES_MY_INTEGER, LEN_MY_INTEGER);
flash_getVar(&check_int, RES_MY_INTEGER, LEN_MY_INTEGER);
output_result(4, check_int != my_int);
flash_getVar(buffer, RES_MY_STRING_1, LEN_MY_STRING_1);
output_result(5, memcmp(buffer, "Hello World!", 12));
flash_getVar(buffer, RES_MY_STRING_2, LEN_MY_STRING_2);
output_result(6, memcmp(buffer, "Heureka!", 8));
}
void
test_flash_2()
{
uint8_t buffer[12];
uint32_t check_int, my_int = 12345678;
flash_getVar(&check_int, RES_MY_INTEGER, LEN_MY_INTEGER);
output_result(1, check_int != my_int);
flash_getVar(buffer, RES_MY_STRING_1, LEN_MY_STRING_1);
output_result(2, memcmp(buffer, "Hello World!", 12));
flash_getVar(buffer, RES_MY_STRING_2, LEN_MY_STRING_2);
output_result(3, memcmp(buffer, "Heureka!", 8));
/* Block 1 max usage is 30 Byte -> Optimisation in Makefile */
output_result(4, flash_setVar("test", 0, 1) != gNvmErrInvalidPointer_c);
output_result(5, flash_setVar("test", 30, 1) != gNvmErrInvalidPointer_c);
output_result(6, flash_setVar("test", 29, 2) != gNvmErrAddressSpaceOverflow_c);
/* Block 2 max usage is 10 Byte -> Optimisation in Makefile */
output_result(7, flash_setVar("test", 4096, 1) != gNvmErrInvalidPointer_c);
output_result(8, flash_setVar("test", 4096 + 10, 1) != gNvmErrInvalidPointer_c);
output_result(9, flash_setVar("test", 4096 + 9, 2) != gNvmErrAddressSpaceOverflow_c);
}
void
test_flash_blaster()
{
uint8_t buffer[64];
flash_getVar(buffer, RES_NAME, LEN_NAME);
output_result(1, memcmp(buffer, "Econotag Flash Test Device", 27));
flash_getVar(buffer, RES_MODEL, LEN_MODEL);
output_result(2, memcmp(buffer, "Model 1234 for testing purposes only", 37));
}
void
test_flash_stack()
{
uint8_t buffer[32];
flash_stack_init();
output_result(1, flash_stack_size() != 0);
flash_stack_push("Hello World!", 12);
output_result(2, flash_stack_size() != 12);
flash_stack_read(buffer, 0, 12);
output_result(3, memcmp(buffer, "Hello World!", 12));
flash_stack_push("I love Contiki!", 15);
output_result(4, flash_stack_size() != 27);
flash_stack_read(buffer, 0, 12);
output_result(5, memcmp(buffer, "Hello World!", 12));
flash_stack_read(buffer, 12, 15);
output_result(6, memcmp(buffer, "I love Contiki!", 15));
flash_stack_init();
output_result(7, flash_stack_size() != 0);
uint32_t i;
for(i = 1; i < 256; i++) {
flash_stack_push("I love Contiki! ", 16);
}
output_result(8, flash_stack_size() != 4080);
output_result(9, flash_stack_push("1I love Contiki! ", 17) != gNvmErrAddressSpaceOverflow_c);
}
/* Start Process */
PROCESS(server_firmware, "Server Firmware");
AUTOSTART_PROCESSES(&server_firmware);
PROCESS_THREAD(server_firmware, ev, data) {
PROCESS_BEGIN();
if(flash_cmp("\001", RES_DONTCLEAR, LEN_DONTCLEAR)) {
printf("Initializing flash ... ");
flash_init();
printf("DONE\n");
flash_setVar("\001", RES_DONTCLEAR, LEN_DONTCLEAR);
printf("Starting flash tests 1:\n");
test_flash_1();
int i;
for(i = 0; i < 1024; i++) {
printf("Reboot ...\r");
}
soft_reset();
} else {
printf("Initialization not wished\n");
}
printf("Starting flash tests 2:\n");
test_flash_2();
printf("Starting flash stack tests:\n");
test_flash_stack();
printf("Starting flash blaster tests:\n");
test_flash_blaster();
PROCESS_END();
}

View file

@ -0,0 +1,7 @@
input = "econotag-flash-test_econotag";
output = "econotag-flash-test_e_econotag";
eui = [ 0x2, 0x0, 0x0, 0x0, 0x12, 0x34, 0x56, 0x78 ];
uuid = "cbf9889f-dc0e-4c18-9aa9-93509a6c102a";
psk = "yCh0OXnSkFT-eXKE";
name = "Econotag Flash Test Device";
model = "Model 1234 for testing purposes only";

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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
* Flash Management
*
* This file contains Pointers for manual flash management.
*
* \author
* Lars Schmertmann <SmallLars@t-online.de>
*/
#ifndef ECONOTAG_FLASH_TEST_H_
#define ECONOTAG_FLASH_TEST_H_
/* Pointer for Block 1 --------------- */
#define RES_DONTCLEAR 1
#define LEN_DONTCLEAR 1
#define RES_MY_STRING_1 2
#define LEN_MY_STRING_1 12
#define RES_MY_STRING_2 14
#define LEN_MY_STRING_2 8
/* Pointer for Block 2 --------------- */
#define RES_MY_INTEGER (4096 + 1)
#define LEN_MY_INTEGER 4
/* ------------------------------------ */
#endif /* ECONOTAG_FLASH_TEST_H_ */

View file

@ -0,0 +1 @@
flash_src = flash.c

View file

@ -0,0 +1,207 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*
*/
#include "flash.h"
#define FLASH_BLOCK_SIZE 0x01000
#define FLASH_BLOCK_11 0x18000
#define FLASH_BLOCK_21 0x1A000
#ifndef FLASH_CONF_B1
#define FLASH_CONF_B1 FLASH_BLOCK_SIZE
#endif
#ifndef FLASH_CONF_B2
#define FLASH_CONF_B2 FLASH_BLOCK_SIZE
#endif
#define DEBUG 0
#if DEBUG
#include <stdio.h>
#include "mc1322x.h"
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif
uint16_t stackPointer;
/* private prototypes ----------------------------------------------------- */
flash_addr_t getAddr(flash_addr_t address);
/* public functions -------------------------------------------------------- */
void
flash_init()
{
PRINTF("Initializing flash ... ");
nvm_erase(gNvmInternalInterface_c, gNvmType_SST_c, 0x0F000000);
nvm_write(gNvmInternalInterface_c, gNvmType_SST_c, "\001", FLASH_BLOCK_11, 1);
nvm_write(gNvmInternalInterface_c, gNvmType_SST_c, "\001", FLASH_BLOCK_21, 1);
uint32_t i;
for(i = 1; i < 0x2000; i++) {
#if DEBUG
if(i % 0x400 == 0) {
PRINTF(" .");
}
#endif
nvm_write(gNvmInternalInterface_c, gNvmType_SST_c, "\0", FLASH_BLOCK_11 + i, 1);
nvm_write(gNvmInternalInterface_c, gNvmType_SST_c, "\0", FLASH_BLOCK_21 + i, 1);
}
PRINTF("DONE\n");
}
nvmErr_t
flash_getVar(void *dest, flash_addr_t address, uint32_t numBytes)
{
address = getAddr(address);
if(address >= 0x18000 && address <= 0x1EFFF) {
PRINTF("Read from Adress: %p\n", address);
nvmErr_t err = nvm_read(gNvmInternalInterface_c, gNvmType_SST_c, dest, address, numBytes);
if(err) {
PRINTF("Read error, nmv_error: %u\n", err);
return err;
}
return gNvmErrNoError_c;
}
PRINTF("Read error - Invalid pointer.\n");
return gNvmErrInvalidPointer_c;
}
nvmErr_t
flash_setVar(void *src, flash_addr_t address, uint32_t numBytes)
{
#if DEBUG
printf("SetVar - START . ");
uint32_t time = *MACA_CLK;
#endif
if(address >= 8192) {
PRINTF("Write error - Invalid pointer.\n");
return gNvmErrInvalidPointer_c;
}
uint32_t block_len = (address < 4096 ? FLASH_CONF_B1 : FLASH_CONF_B2);
address = getAddr(address);
flash_addr_t src_block = address & 0xFF000;
flash_addr_t dst_block = src_block ^ 0x01000;
address = address & 0x00FFF;
if(address < 1 || address >= block_len) {
PRINTF("Write error - Invalid pointer.\n");
return gNvmErrInvalidPointer_c;
}
if(address + numBytes > block_len) {
PRINTF("Write error - Var is to long.\n");
return gNvmErrAddressSpaceOverflow_c;
}
nvm_erase(gNvmInternalInterface_c, gNvmType_SST_c, 1 << (dst_block / FLASH_BLOCK_SIZE));
uint32_t i;
uint8_t buf;
for(i = 0; i < address; i++) {
nvm_read(gNvmInternalInterface_c, gNvmType_SST_c, &buf, src_block + i, 1);
nvm_write(gNvmInternalInterface_c, gNvmType_SST_c, &buf, dst_block + i, 1);
}
PRINTF("Write to adress: %p\n", dst_block + i);
nvm_write(gNvmInternalInterface_c, gNvmType_SST_c, src, dst_block + i, numBytes);
for(i += numBytes; i < block_len; i++) {
nvm_read(gNvmInternalInterface_c, gNvmType_SST_c, &buf, src_block + i, 1);
nvm_write(gNvmInternalInterface_c, gNvmType_SST_c, &buf, dst_block + i, 1);
}
nvm_erase(gNvmInternalInterface_c, gNvmType_SST_c, 1 << (src_block / FLASH_BLOCK_SIZE));
#if DEBUG
time = *MACA_CLK - time;
printf("FINISHED AFTER %u MS\n", time / 250);
#endif
return gNvmErrNoError_c;
}
nvmErr_t
flash_cmp(void *src, flash_addr_t address, uint32_t numBytes)
{
address = getAddr(address);
if(address >= 0x18000 && address <= 0x1EFFF) {
return nvm_verify(gNvmInternalInterface_c, gNvmType_SST_c, src, address, numBytes);
}
PRINTF("Read error - Invalid pointer.\n");
return gNvmErrInvalidPointer_c;
}
void
flash_stack_init()
{
stackPointer = 0;
nvm_erase(gNvmInternalInterface_c, gNvmType_SST_c, 1 << (FLASH_STACK / FLASH_BLOCK_SIZE));
}
nvmErr_t
flash_stack_push(uint8_t *src, uint32_t numBytes)
{
if(stackPointer + numBytes > FLASH_BLOCK_SIZE) {
return gNvmErrAddressSpaceOverflow_c;
}
nvm_write(gNvmInternalInterface_c, gNvmType_SST_c, src, FLASH_STACK + stackPointer, numBytes);
stackPointer += numBytes;
return gNvmErrNoError_c;
}
uint32_t
flash_stack_size()
{
return stackPointer;
}
/* private functions ------------------------------------------------------- */
flash_addr_t
getAddr(flash_addr_t address)
{
if(address >= 0x02000) {
return address;
}
flash_addr_t block = (address & 0x01000 ? FLASH_BLOCK_21 : FLASH_BLOCK_11);
uint8_t blockcheck = (flash_cmp("\001", block, 1) == 0 ? 0 : 1);
return block + (blockcheck << 12) + (address & 0x00FFF);
}

View file

@ -0,0 +1,178 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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
* App for easy usage of additional flash memory
*
* Purposes of the different flash blocks
* 1 : 0x18000 - 0x18FFF : Random access block 1.1
* 2 : 0x19000 - 0x19FFF : Random access block 1.2
* 3 : 0x1A000 - 0x1AFFF : Random access block 2.1
* 4 : 0x1B000 - 0x1BFFF : Random access block 2.2
* 5 : 0x1C000 - 0x1CFFF : Stack without pop function
* 6 : 0x1D000 - 0x1DFFF : Read only
* 7 : 0x1E000 - 0x1EFFF : Read only
* 8 : 0x1F000 - 0x1FFFF : System reserved
*
* This app only allows write access to blocks 1 - 5
* and read access to blocks 1 - 7.
*
* To use the stack in block 5 you need: flash_stack_init,
* flash_stack_push, flash_stack_size, flash_stack_read.
*
* To use the random access blocks 1.x and 2.x you need: flash_init,
* flash_getVar, flash_setVar, flash_cmp.
*
* Blocks 1.x and 2.x are accessible with adresses
* 0x0001 - 0x0FFF and 0x1001 - 0x1FFF.
*
* To be able to write to flash memory, its required to delete
* it first, but its only possible to delete a full block. So this
* app copies the data of a block, changing the requested data.
* Copying a block needs time. So when you only use the first N bytes,
* you can set FLASH_CONF_B1=N and FLASH_CONF_B2=N in your makefile
* to optimize speed.
*
* You can find an example in examples/econotag-flash-test.
*
* \author
* Lars Schmertmann <SmallLars@t-online.de>
*/
#ifndef FLASH_H_
#define FLASH_H_
#include <nvm.h>
#define FLASH_STACK 0x1C000
typedef uint32_t flash_addr_t;
/**
* \brief Initialize or clear random access blocks
*
* To use the random access blocks, you need to call this
* function first. You can also use it to delete all data
* in this blocks.
*/
void flash_init();
/**
* \brief Read data from flash memory
*
* Reads data from flash memory and stores it into RAM.
* You can read the flash area 0x18000 - 0x1EFFF. Addresses
* 0x0000 - 0x1FFF will be mapped to 0x18000 - 0x1BFFF.
*
* \param dest Memory area to store the data
* \param address Area in flash memory to read from
* \param numBytes Number of bytes to read
*
* \return gNvmErrNoError_c (0) if read was successfull
*/
nvmErr_t flash_getVar(void *dest, flash_addr_t address, uint32_t numBytes);
/**
* \brief Write data to flash memory
*
* Writes data to flash memory. Valid addresses are
* 0x0001 - 0x0FFF and 0x1001 - 0x1FFF -> Mapped to
* 0x18000 - 0x1BFFF.
*
* \param src Memory area with data to store in flash memory
* \param address Area in flash memory to write
* \param numBytes Number of bytes to write
*
* \return gNvmErrNoError_c (0) if write was successfull
*/
nvmErr_t flash_setVar(void *src, flash_addr_t address, uint32_t numBytes);
/**
* \brief Compares data from RAM with flash memory
*
* Compares data from RAM with flash memory.
* Valid addresses are 0x18000 - 0x1EFFF. Addresses
* 0x0 - 0x1FFF will be mapped to 0x18000 - 0x1BFFF.
*
* \param src Memory area with data to compare
* \param address Area in flash memory
* \param numBytes Number of bytes to compare
*
* \return 0 if data is matching
*/
nvmErr_t flash_cmp(void *src, flash_addr_t address, uint32_t numBytes);
/**
* \brief Stack initialisation
*
* Clears and initializes the stack.
*/
void flash_stack_init();
/**
* \brief Push data to stack
*
* Pushes numBytes from src to stack into flash memory.
*
* \param src Memory area with data to store in flash memory
* \param numBytes Number of bytes to write
*
* \return gNvmErrNoError_c (0) if push was successfull
*/
nvmErr_t flash_stack_push(uint8_t *src, uint32_t numBytes);
/**
* \brief Stacksize
*
* Returns the size of data in stack
*
* \return Number of bytes in stack
*/
uint32_t flash_stack_size();
/**
* \brief Read data from stack
*
* Reads data from stack (without removing it) and stores it into RAM.
*
* \param dest Memory area to store the data
* \param offset Position in stack to read from
* \param numBytes Number of bytes to read
*
* \return gNvmErrNoError_c (0) if read was successfull
*/
#define flash_stack_read(dest, offset, numBytes) flash_getVar(dest, FLASH_STACK + (offset), numBytes)
#endif /* FLASH_H_ */

View file

@ -8,6 +8,7 @@ ipv6/rpl-border-router/econotag \
er-rest-example/econotag \ er-rest-example/econotag \
webserver-ipv6/econotag \ webserver-ipv6/econotag \
ipv6/multicast/econotag \ ipv6/multicast/econotag \
econotag-flash-test/econotag \
TOOLS= TOOLS=

19
tools/blaster/Makefile Normal file
View file

@ -0,0 +1,19 @@
CC = gcc
CFLAGS = -Wall -g
HEADERS =
all: blaster
depend:
sudo apt-get install libconfig8-dev uuid-dev libqrencode-dev
%.o: %.c $(HEADERS)
$(CC) -c $(CFLAGS) -o $@ $<
blaster: blaster.o
$(CC) $(CFLAGS) -o $@ $^ -lconfig -luuid -lqrencode
clean:
rm *.o blaster
.PHONY: all depend clean

10
tools/blaster/README Normal file
View file

@ -0,0 +1,10 @@
Blaster extends the compiled firmware with additional data for
storing into flash memory. See examples/econotag-flash-test for
usage. Its written for Econotag / MC1322X
./blaster <config.cfg> [<config.cfg> <config.cfg> ...]
To Generate a default configuration file, use blaster without parameter.
Its important to use -l as a flash parameter.
mc1322x-load -f flasher_econotag.bin -s firmware.bin -t /dev/ttyUSB1 -l

330
tools/blaster/blaster.c Normal file
View file

@ -0,0 +1,330 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <uuid/uuid.h>
#include <libconfig.h>
#include <time.h>
#include <qrencode.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "blaster.h"
char *anschars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
/* ---------------------------------------------------------------------------- */
FILE *openFile(const char *name, const char *appendix, const char *mode);
void writeStandardConfig();
void writeImg(FILE *file, unsigned char *data, int width);
/* ---------------------------------------------------------------------------- */
int
main(int nArgs, char **argv)
{
unsigned int c, i, config;
unsigned int buf[64];
if(nArgs < 2) {
writeStandardConfig();
fprintf(stderr, "Missing parameter: ./blaster <config.cfg> [<config.cfg> <config.cfg> ...]\n");
fprintf(stderr, "Configuration template was created ib config.cfg.\n");
exit(EXIT_FAILURE);
}
/* qrdata = "UUID:PSK\0" */
char qrdata[54];
qrdata[36] = ':';
qrdata[53] = '\0';
config_t cfg;
for(config = 1; config < nArgs; config++) {
config_init(&cfg);
config_setting_t *setting;
const char *str_val;
if(access(argv[config], F_OK) == 0) {
config_read_file(&cfg, argv[config]);
} else {
fprintf(stderr, "Unable to read config file.\n");
exit(EXIT_FAILURE);
}
fprintf(stdout, "Working on %s ... ", argv[config]);
config_lookup_string(&cfg, "input", &str_val);
FILE *in_bin = openFile(str_val, ".bin", "r");
config_lookup_string(&cfg, "output", &str_val);
FILE *out_bin = openFile(str_val, ".bin", "w");
FILE *out_txt = openFile(str_val, ".txt", "w");
FILE *out_pbm = openFile(str_val, ".pbm", "w");
char output[131072];
for(i = 8; (c = fgetc(in_bin)) != EOF; i++) {
output[i] = (unsigned char)c;
}
/* Set original length of firmware in little endian format ------------------- */
unsigned int length = i - 8;
memcpy(output + 4, (const void *)&length, 4);
fprintf(out_txt, "Length: %u = 0x%08x\n", length, length);
/* Fill additional flash with zeros for initialisation */
for(; i < 0x1F000; i++) {
output[i] = 0x00;
}
/* Example: Write an CoRE-Link-Answer for CoAP -------------------------------- */
char *buffer = "</d/name>;rt=\"dev.info\";if=\"core.rp\","
"</d/model>;rt=\"dev.info\";if=\"core.rp\","
"</d/uuid>;rt=\"dev.info\";if=\"core.rp\"";
memcpy(output + RES_D_CORE, buffer, LEN_D_CORE);
/* Contiki configuration ------------------------------------------------------ */
output[RES_CONFIG + 0] = 0x22;
output[RES_CONFIG + 1] = 0x13;
output[RES_CONFIG + 2] = 1;
output[RES_CONFIG + 3] = 0;
setting = config_lookup(&cfg, "eui");
for(i = 0; i < 8; i++) {
output[RES_CONFIG + 8 + i] = config_setting_get_int_elem(setting, 7 - i);
}
fprintf(out_txt,
"EUI: %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n",
(uint8_t)output[RES_CONFIG + 15],
(uint8_t)output[RES_CONFIG + 14],
(uint8_t)output[RES_CONFIG + 13],
(uint8_t)output[RES_CONFIG + 12],
(uint8_t)output[RES_CONFIG + 11],
(uint8_t)output[RES_CONFIG + 10],
(uint8_t)output[RES_CONFIG + 9],
(uint8_t)output[RES_CONFIG + 8]
);
output[RES_CONFIG + 16] = 15;
output[RES_CONFIG + 17] = 17;
output[RES_CONFIG + 18] = 0;
output[RES_CONFIG + 19] = 0;
output[RES_CONFIG + 20] = 5;
output[RES_CONFIG + 21] = 0;
output[RES_CONFIG + 22] = 0;
output[RES_CONFIG + 23] = 0;
/* Example: Set UUID ---------------------------------------------------------- */
config_lookup_string(&cfg, "uuid", &str_val);
memcpy(qrdata, str_val, 36);
unsigned char uuid_bin[16];
uuid_parse(str_val, uuid_bin);
for(i = 0; i < 16; i++) {
output[RES_UUID + i] = uuid_bin[i];
}
fprintf(out_txt, "UUID: %s\n", str_val);
/* Example: Set PSK ----------------------------------------------------------- */
config_lookup_string(&cfg, "psk", &str_val);
memcpy(qrdata + 37, str_val, 16);
for(i = 0; i < 16; i++) {
output[RES_PSK + i] = str_val[i];
}
fprintf(out_txt, "PSK: %.*s\n", 16, str_val);
memcpy(output + RES_ANSCHARS, anschars, LEN_ANSCHARS);
/* Example: ECC base point and order for secp256r1 ---------------------------- */
uint32_t *base_x = (uint32_t *)(output + RES_ECC_BASE_X);
base_x[0] = 0xd898c296;
base_x[1] = 0xf4a13945;
base_x[2] = 0x2deb33a0;
base_x[3] = 0x77037d81;
base_x[4] = 0x63a440f2;
base_x[5] = 0xf8bce6e5;
base_x[6] = 0xe12c4247;
base_x[7] = 0x6b17d1f2;
uint32_t *base_y = (uint32_t *)(output + RES_ECC_BASE_Y);
base_y[0] = 0x37bf51f5;
base_y[1] = 0xcbb64068;
base_y[2] = 0x6b315ece;
base_y[3] = 0x2bce3357;
base_y[4] = 0x7c0f9e16;
base_y[5] = 0x8ee7eb4a;
base_y[6] = 0xfe1a7f9b;
base_y[7] = 0x4fe342e2;
uint32_t *order = (uint32_t *)(output + RES_ECC_ORDER);
order[0] = 0xFC632551;
order[1] = 0xF3B9CAC2;
order[2] = 0xA7179E84;
order[3] = 0xBCE6FAAD;
order[4] = 0xFFFFFFFF;
order[5] = 0xFFFFFFFF;
order[6] = 0x00000000;
order[7] = 0xFFFFFFFF;
/* Example: Set name ---------------------------------------------------------- */
config_lookup_string(&cfg, "name", &str_val);
snprintf(output + RES_NAME, LEN_NAME, "%s", str_val);
fprintf(out_txt, "Name: %s\n", str_val);
/* Example: Set model---------------------------------------------------------- */
config_lookup_string(&cfg, "model", &str_val);
snprintf(output + RES_MODEL, LEN_MODEL, "%s", str_val);
fprintf(out_txt, "Model: %s\n", str_val);
/* Example: Set time ---------------------------------------------------------- */
time_t my_time = time(NULL);
memcpy(output + RES_FLASHTIME, (void *)&my_time, LEN_FLASHTIME);
struct tm *timeinfo = localtime(&my_time);
fwrite(buf, 1, strftime((char *)buf, 64, "Created on %d.%m.%Y um %H:%M:%S", timeinfo), out_txt);
/* Output result -------------------------------------------------------------- */
for(i = 4; i < 0x1F000; i++) {
fputc(output[i], out_bin);
}
/* Generate QR-Code ----------------------------------------------------------- */
QRcode *code = QRcode_encodeString8bit(qrdata, 3, QR_ECLEVEL_L);
writeImg(out_pbm, code->data, code->width);
fclose(in_bin);
fclose(out_bin);
fclose(out_txt);
fclose(out_pbm);
fprintf(stdout, "DONE\n");
}
exit(EXIT_SUCCESS);
}
/* ---------------------------------------------------------------------------- */
FILE *
openFile(const char *name, const char *appendix, const char *mode)
{
char filename[64];
sprintf(filename, "%s%s", name, appendix);
FILE *file = fopen(filename, mode);
if(file == NULL) {
perror("Wasn't able to open file.");
exit(EXIT_FAILURE);
}
return file;
}
void
writeStandardConfig()
{
unsigned int i;
config_t cfg;
config_init(&cfg);
config_setting_t *setting;
config_setting_t *root = config_root_setting(&cfg);
setting = config_setting_add(root, "input", CONFIG_TYPE_STRING);
config_setting_set_string(setting, "dff_econotag");
setting = config_setting_add(root, "output", CONFIG_TYPE_STRING);
config_setting_set_string(setting, "dff_e_econotag");
uint8_t eui[8] = { 0x02, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78 };
config_setting_t *array = config_setting_add(root, "eui", CONFIG_TYPE_ARRAY);
for(i = 0; i < 8; ++i) {
setting = config_setting_add(array, NULL, CONFIG_TYPE_INT);
config_setting_set_format(setting, CONFIG_FORMAT_HEX);
config_setting_set_int(setting, eui[i]);
}
unsigned char uuid_bin[16];
uuid_generate(uuid_bin);
char uuid[37];
uuid_unparse(uuid_bin, uuid);
setting = config_setting_add(root, "uuid", CONFIG_TYPE_STRING);
config_setting_set_string(setting, uuid);
char psk[17];
psk[16] = '\0';
FILE *fd = fopen("/dev/urandom", "r");
if(fd == NULL) {
perror("Wasn't able to open /dev/urandom: ");
return;
}
for(i = 0; i < 16; i++) {
int c;
while((c = fgetc(fd)) == EOF) ;
psk[i] = anschars[c % 64];
}
if(fclose(fd) == -1) {
perror("Wasn't able to close /dev/urandom: ");
}
setting = config_setting_add(root, "psk", CONFIG_TYPE_STRING);
config_setting_set_string(setting, psk);
setting = config_setting_add(root, "name", CONFIG_TYPE_STRING);
config_setting_set_string(setting, "Blaster Standard Device");
setting = config_setting_add(root, "model", CONFIG_TYPE_STRING);
config_setting_set_string(setting, "Model 1234 for testing purposes only");
config_write_file(&cfg, "config.cfg");
}
void
writeImg(FILE *file, unsigned char *data, int width)
{
unsigned int buf[width];
fprintf(file, "P4\n# %s\n%3u %3u\n", "QR-Code", width * 32, width * 32);
int x, y;
for(y = 0; y < width; y++) {
for(x = 0; x < width; x++) {
if(data[(y * width) + x] & 0x01) {
buf[x] = 0xFFFFFFFF;
} else {
buf[x] = 0x00000000;
}
}
for(x = 0; x < 32; x++) {
fwrite(buf, 4, width, file);
}
}
}

72
tools/blaster/blaster.h Normal file
View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2014, Lars Schmertmann <SmallLars@t-online.de>.
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*
*/
/* Purposes of the different flash blocks */
/* 0x18000 - 0x18FFF : Random access block 1.1 */
/* 0x19000 - 0x19FFF : Random access block 1.2 */
/* 0x1A000 - 0x1AFFF : Random access block 2.1 */
/* 0x1B000 - 0x1BFFF : Random access block 2.2 */
/* 0x1C000 - 0x1CFFF : Stack without pop function */
/* 0x1D000 - 0x1DFFF : Read only <- This is what blaster user */
/* 0x1E000 - 0x1EFFF : Read only <- This is what blaster user */
/* 0x1F000 - 0x1FFFF : System reserved */
#ifndef BLASTER_H_
#define BLASTER_H_
#define RES_D_CORE 0x1D000
#define LEN_D_CORE 0x6F
#define RES_CONFIG 0x1E000
#define LEN_CONFIG 0x12
#define RES_UUID 0x1E020
#define LEN_UUID 0x10
#define RES_PSK 0x1E030
#define LEN_PSK 0x10
#define RES_ANSCHARS 0x1E040
#define LEN_ANSCHARS 0x40
#define RES_ECC_BASE_X 0x1E080
#define LEN_ECC_BASE_X 0x20
#define RES_ECC_BASE_Y 0x1E0A0
#define LEN_ECC_BASE_Y 0x20
#define RES_ECC_ORDER 0x1E0C0
#define LEN_ECC_ORDER 0x20
#define RES_NAME 0x1E0E0
#define LEN_NAME 0x40
#define RES_MODEL 0x1E120
#define LEN_MODEL 0x40
#define RES_FLASHTIME 0x1E160
#define LEN_FLASHTIME 0x04
#endif /* BLASTER_H_ */