First stab at OTA-update
Introduce new testing-app example. Add a new coap error code for blockwise transfer. Add include-file for bootloader callbacks (jumptable). Note that only the bootloader for osd-merkur-256 will support OTA-update, the -128 simply has not enough flash memory, so only in the -256 we have the bootloader functions in the jump-table of the bootloader and in the bootloader-if.h include-file.
This commit is contained in:
parent
1a57b55d8f
commit
c35be7c066
|
@ -94,6 +94,7 @@ typedef enum {
|
||||||
NOT_FOUND_4_04 = 132, /* NOT_FOUND */
|
NOT_FOUND_4_04 = 132, /* NOT_FOUND */
|
||||||
METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */
|
METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */
|
||||||
NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */
|
NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */
|
||||||
|
REQUEST_ENTITY_INCOMPLETE_4_08 = 136, /* REQUEST_ENTITY_INCOMPLETE */
|
||||||
PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */
|
PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */
|
||||||
REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */
|
REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */
|
||||||
UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */
|
UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */
|
||||||
|
|
|
@ -482,6 +482,7 @@ const struct rest_implementation coap_rest_implementation = {
|
||||||
NOT_FOUND_4_04,
|
NOT_FOUND_4_04,
|
||||||
METHOD_NOT_ALLOWED_4_05,
|
METHOD_NOT_ALLOWED_4_05,
|
||||||
NOT_ACCEPTABLE_4_06,
|
NOT_ACCEPTABLE_4_06,
|
||||||
|
REQUEST_ENTITY_INCOMPLETE_4_08,
|
||||||
REQUEST_ENTITY_TOO_LARGE_4_13,
|
REQUEST_ENTITY_TOO_LARGE_4_13,
|
||||||
UNSUPPORTED_MEDIA_TYPE_4_15,
|
UNSUPPORTED_MEDIA_TYPE_4_15,
|
||||||
INTERNAL_SERVER_ERROR_5_00,
|
INTERNAL_SERVER_ERROR_5_00,
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct rest_implementation_status {
|
||||||
const unsigned int NOT_FOUND; /* NOT_FOUND_4_04, NOT_FOUND_404 */
|
const unsigned int NOT_FOUND; /* NOT_FOUND_4_04, NOT_FOUND_404 */
|
||||||
const unsigned int METHOD_NOT_ALLOWED; /* METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_405 */
|
const unsigned int METHOD_NOT_ALLOWED; /* METHOD_NOT_ALLOWED_4_05, METHOD_NOT_ALLOWED_405 */
|
||||||
const unsigned int NOT_ACCEPTABLE; /* NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_406 */
|
const unsigned int NOT_ACCEPTABLE; /* NOT_ACCEPTABLE_4_06, NOT_ACCEPTABLE_406 */
|
||||||
|
const unsigned int REQUEST_ENTITY_INCOMPLETE; /* REQUEST_ENTITY_INCOMPLETE_4_08, REQUEST_ENTITY_INCOMPLETE_408 */
|
||||||
const unsigned int REQUEST_ENTITY_TOO_LARGE; /* REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_413 */
|
const unsigned int REQUEST_ENTITY_TOO_LARGE; /* REQUEST_ENTITY_TOO_LARGE_4_13, REQUEST_ENTITY_TOO_LARGE_413 */
|
||||||
const unsigned int UNSUPPORTED_MEDIA_TYPE; /* UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_415 */
|
const unsigned int UNSUPPORTED_MEDIA_TYPE; /* UNSUPPORTED_MEDIA_TYPE_4_15, UNSUPPORTED_MEDIA_TYPE_415 */
|
||||||
|
|
||||||
|
|
49
examples/osd/ota-update/Makefile
Normal file
49
examples/osd/ota-update/Makefile
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
# Set this to the name of your sketch (without extension .pde)
|
||||||
|
SKETCH=sketch
|
||||||
|
EXE=ota
|
||||||
|
|
||||||
|
|
||||||
|
all: $(EXE)
|
||||||
|
|
||||||
|
CONTIKI=../../..
|
||||||
|
|
||||||
|
# Contiki IPv6 configuration
|
||||||
|
CONTIKI_WITH_IPV6 = 1
|
||||||
|
|
||||||
|
CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\"
|
||||||
|
|
||||||
|
PROJECT_SOURCEFILES += res_upload_image.c ${SKETCH}.cpp
|
||||||
|
|
||||||
|
# variable for Makefile.include
|
||||||
|
ifneq ($(TARGET), minimal-net)
|
||||||
|
CFLAGS += -DUIP_CONF_IPV6_RPL=1
|
||||||
|
else
|
||||||
|
# minimal-net does not support RPL under Linux and is mostly used to test CoAP only
|
||||||
|
${info INFO: compiling without RPL}
|
||||||
|
CFLAGS += -DUIP_CONF_IPV6_RPL=0
|
||||||
|
CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\"
|
||||||
|
${info INFO: compiling with large buffers}
|
||||||
|
CFLAGS += -DUIP_CONF_BUFFER_SIZE=2048
|
||||||
|
CFLAGS += -DREST_MAX_CHUNK_SIZE=1024
|
||||||
|
CFLAGS += -DCOAP_MAX_HEADER_SIZE=640
|
||||||
|
endif
|
||||||
|
|
||||||
|
# linker optimizations
|
||||||
|
SMALL=1
|
||||||
|
|
||||||
|
# REST Engine shall use Erbium CoAP implementation
|
||||||
|
APPS += er-coap
|
||||||
|
APPS += rest-engine
|
||||||
|
APPS += arduino #json-resource #time json arduino
|
||||||
|
|
||||||
|
include $(CONTIKI)/Makefile.include
|
||||||
|
include $(CONTIKI)/apps/arduino/Makefile.include
|
||||||
|
|
||||||
|
avr-size: $(EXE).$(TARGET).sz
|
||||||
|
|
||||||
|
flash: $(EXE).$(TARGET).u # $(EXE).$(TARGET).eu
|
||||||
|
|
||||||
|
.PHONY: flash avr-size
|
||||||
|
.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep
|
||||||
|
|
||||||
|
AVRDUDE_PORT=/dev/ttyUSB1
|
81
examples/osd/ota-update/README.rst
Normal file
81
examples/osd/ota-update/README.rst
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
==========
|
||||||
|
OTA Update
|
||||||
|
==========
|
||||||
|
|
||||||
|
OTA stands for "Over the Air". OTA update is used to flash a new
|
||||||
|
firmware to a device over the air. This document (some of) the
|
||||||
|
requirements for OTA.
|
||||||
|
|
||||||
|
Security
|
||||||
|
========
|
||||||
|
|
||||||
|
Position Independent Code
|
||||||
|
=========================
|
||||||
|
|
||||||
|
The new contiki-osd-merkur-256 target should have enough memory for two
|
||||||
|
independent application images. An application image should include the
|
||||||
|
code for over-the-air update to ensure it can be upgraded in the field.
|
||||||
|
|
||||||
|
Upgrading an image means writing a new image into the other half of the
|
||||||
|
flash memory (the part which does not run the current image). Since an
|
||||||
|
image has internal addresses and is usually linked to fixed addresses we
|
||||||
|
have two options:
|
||||||
|
|
||||||
|
- Find a way to generate position independent code for the Atmel
|
||||||
|
microcontrollers so that an image can be used in the lower- or upper
|
||||||
|
half of flash memory
|
||||||
|
- Generate two images, one linked for the lower, one linked for the
|
||||||
|
upper half of flash memory.
|
||||||
|
|
||||||
|
It seems the GCC Atmel compiler cannot generate position independent
|
||||||
|
code. So we have to modify the first option to make it work: We can use
|
||||||
|
some magic during loading of an image to link it to the correct half of
|
||||||
|
flash-memory during loading. This can either mean full relocation of the
|
||||||
|
image (the same job that is normally done before runtime by the linker)
|
||||||
|
or offline-generation of a jump-table for all objects (functions) that
|
||||||
|
are accessed and the bootloader then only relocates the addresses in the
|
||||||
|
jump-table.
|
||||||
|
|
||||||
|
The first implementation will use two images (one for upper-, one for
|
||||||
|
lower half).
|
||||||
|
|
||||||
|
Memory Layout
|
||||||
|
=============
|
||||||
|
|
||||||
|
+--------------------------------------+
|
||||||
|
| 3E000-3FFFF Bootloader |
|
||||||
|
+--------------------------------------+
|
||||||
|
| 3DE00-3DFFF Flash image directory |
|
||||||
|
+--------------------------------------+
|
||||||
|
| 3DC00-3DDFF IRQVec copy upper image |
|
||||||
|
+--------------------------------------+
|
||||||
|
| 1F100-3DBFF |
|
||||||
|
| Upper Image (w/o first two pages) |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
+--------------------------------------+
|
||||||
|
| 1EF00-1F0FF IRQVec upper image |
|
||||||
|
+--------------------------------------+
|
||||||
|
| 1ED00-1EEFF IRQVec copy lower image |
|
||||||
|
+--------------------------------------+
|
||||||
|
| 00200-1ECFF |
|
||||||
|
| Lower Image (w/o first two pages) |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
+--------------------------------------+
|
||||||
|
| 00000-001FF IRQVec running image |
|
||||||
|
+--------------------------------------+
|
||||||
|
|
||||||
|
We have two identical images. Each image contains the IRQ vectors (and
|
||||||
|
some code after the vector table) in the lower two pages. A copy of
|
||||||
|
these two pages is kept in two pages after the image. The reason is that
|
||||||
|
the IRQ vectors are fixed at address 00000 in this processor
|
||||||
|
architecture. So for running an image we need to copy the irq-vectors to
|
||||||
|
the fixed location (and therefore we keep a backup to be able to restore
|
||||||
|
the original image at that location).
|
||||||
|
Note that in the table above an image as generated by the compiler
|
||||||
|
consists of the IRQ vectors in the first two pages (00000-001FF for the
|
||||||
|
first and 1EF00-1F0FF for the second image) plus the rest of the code
|
||||||
|
for that image.
|
||||||
|
|
||||||
|
|
2
examples/osd/ota-update/ota.c
Normal file
2
examples/osd/ota-update/ota.c
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#include <arduino-process.h>
|
||||||
|
AUTOSTART_PROCESSES(&arduino_sketch);
|
101
examples/osd/ota-update/project-conf.h
Normal file
101
examples/osd/ota-update/project-conf.h
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 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.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PROJECT_RPL_WEB_CONF_H_
|
||||||
|
#define PROJECT_RPL_WEB_CONF_H_
|
||||||
|
|
||||||
|
#define PLATFORM_HAS_LEDS 1
|
||||||
|
//#define PLATFORM_HAS_BUTTON 1
|
||||||
|
#define PLATFORM_HAS_BATTERY 1
|
||||||
|
|
||||||
|
#define SICSLOWPAN_CONF_FRAG 1
|
||||||
|
|
||||||
|
/* For Debug: Dont allow MCU sleeping between channel checks */
|
||||||
|
#undef RDC_CONF_MCU_SLEEP
|
||||||
|
#define RDC_CONF_MCU_SLEEP 0
|
||||||
|
|
||||||
|
/* Disabling RDC for demo purposes. Core updates often require more memory. */
|
||||||
|
/* For projects, optimize memory and enable RDC again. */
|
||||||
|
// #undef NETSTACK_CONF_RDC
|
||||||
|
//#define NETSTACK_CONF_RDC nullrdc_driver
|
||||||
|
|
||||||
|
/* Increase rpl-border-router IP-buffer when using more than 64. */
|
||||||
|
#undef REST_MAX_CHUNK_SIZE
|
||||||
|
#define REST_MAX_CHUNK_SIZE 64
|
||||||
|
|
||||||
|
/* Estimate your header size, especially when using Proxy-Uri. */
|
||||||
|
/*
|
||||||
|
#undef COAP_MAX_HEADER_SIZE
|
||||||
|
#define COAP_MAX_HEADER_SIZE 70
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The IP buffer size must fit all other hops, in particular the border router. */
|
||||||
|
|
||||||
|
#undef UIP_CONF_BUFFER_SIZE
|
||||||
|
#define UIP_CONF_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
|
||||||
|
/* Multiplies with chunk size, be aware of memory constraints. */
|
||||||
|
#undef COAP_MAX_OPEN_TRANSACTIONS
|
||||||
|
#define COAP_MAX_OPEN_TRANSACTIONS 4
|
||||||
|
|
||||||
|
/* Must be <= open transaction number, default is COAP_MAX_OPEN_TRANSACTIONS-1. */
|
||||||
|
/*
|
||||||
|
#undef COAP_MAX_OBSERVERS
|
||||||
|
#define COAP_MAX_OBSERVERS 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Filtering .well-known/core per query can be disabled to save space. */
|
||||||
|
/*
|
||||||
|
#undef COAP_LINK_FORMAT_FILTERING
|
||||||
|
#define COAP_LINK_FORMAT_FILTERING 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Save some memory for the sky platform. */
|
||||||
|
/*
|
||||||
|
#undef NBR_TABLE_CONF_MAX_NEIGHBORS
|
||||||
|
#define NBR_TABLE_CONF_MAX_NEIGHBORS 10
|
||||||
|
#undef UIP_CONF_MAX_ROUTES
|
||||||
|
#define UIP_CONF_MAX_ROUTES 10
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Reduce 802.15.4 frame queue to save RAM. */
|
||||||
|
/*
|
||||||
|
#undef QUEUEBUF_CONF_NUM
|
||||||
|
#define QUEUEBUF_CONF_NUM 4
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
#undef SICSLOWPAN_CONF_FRAG
|
||||||
|
#define SICSLOWPAN_CONF_FRAG 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* PROJECT_RPL_WEB_CONF_H_ */
|
175
examples/osd/ota-update/res_upload_image.c
Normal file
175
examples/osd/ota-update/res_upload_image.c
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Marcus Priesch, Ralf Schlatterbeck
|
||||||
|
* with code from the res-plugtest-large-update.c by
|
||||||
|
* Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich
|
||||||
|
* 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
|
||||||
|
* Over-the-air update using blockwise transfer
|
||||||
|
* \author
|
||||||
|
* Marcus Priesch <marcus@priesch.co.at>
|
||||||
|
* Ralf Schlatterbeck <rsc@runtux.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "sys/cc.h"
|
||||||
|
#include "rest-engine.h"
|
||||||
|
#include "er-coap.h"
|
||||||
|
#include "contiki.h"
|
||||||
|
#include "contiki-net.h"
|
||||||
|
#include "er-coap.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include "bootloader_if.h"
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#include <stdio.h>
|
||||||
|
#define PRINTF(x) printf x
|
||||||
|
#else
|
||||||
|
#define PRINTF(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const uint32_t partition_start = 0x1ef00; //bootloader_get_part_start ();
|
||||||
|
static const uint32_t partition_size = 5000; //bootloader_get_part_size ();
|
||||||
|
|
||||||
|
// We allocate this statically, otherwise we cannot flash a new image
|
||||||
|
// when ram is exhausted!
|
||||||
|
static uint8_t current_page [256];
|
||||||
|
static size_t current_offset = 0;
|
||||||
|
#define PAGESIZE (sizeof (current_page))
|
||||||
|
|
||||||
|
static void
|
||||||
|
res_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset)
|
||||||
|
{
|
||||||
|
coap_packet_t *const packet = (coap_packet_t *)request;
|
||||||
|
uint8_t *in_data = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
uint8_t sreg = SREG;
|
||||||
|
|
||||||
|
unsigned int ct = -1;
|
||||||
|
|
||||||
|
REST.get_header_content_type(request, &ct);
|
||||||
|
|
||||||
|
/* Require content_type APPLICATION_OCTET_STREAM */
|
||||||
|
if (ct != REST.type.APPLICATION_OCTET_STREAM) {
|
||||||
|
REST.set_response_status(response, REST.status.BAD_REQUEST);
|
||||||
|
const char *error_msg = "ContentType";
|
||||||
|
REST.set_response_payload(response, error_msg, strlen(error_msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = REST.get_request_payload (request, (const uint8_t **)&in_data);
|
||||||
|
PRINTF (("cur: %lu len: %lu, offset: %lu\n",
|
||||||
|
(uint32_t)current_offset, (uint32_t)len, (uint32_t)*offset));
|
||||||
|
PRINTF (("b1-offs: %lu, b1-size: %u, b1-num: %lu b1-more: %d b1-size1: %lu\n",
|
||||||
|
packet->block1_offset, packet->block1_size, packet->block1_num,
|
||||||
|
packet->block1_more, packet->size1));
|
||||||
|
if (len == 0 || NULL == in_data) {
|
||||||
|
REST.set_response_status(response, REST.status.BAD_REQUEST);
|
||||||
|
const char *error_msg = "NoPayload";
|
||||||
|
REST.set_response_payload(response, error_msg, strlen(error_msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet->block1_offset > current_offset) {
|
||||||
|
REST.set_response_status(response, REST.status.REQUEST_ENTITY_INCOMPLETE);
|
||||||
|
const char *error_msg = "OutOfSequence";
|
||||||
|
REST.set_response_payload(response, error_msg, strlen(error_msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Old packet or retransmission, immediately confirm */
|
||||||
|
if (packet->block1_offset + len <= current_offset) {
|
||||||
|
REST.set_response_status(response, REST.status.CHANGED);
|
||||||
|
coap_set_header_block1
|
||||||
|
(response, packet->block1_num, 0, packet->block1_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: blocksize may be larger than our flash page size
|
||||||
|
if (len > PAGESIZE) {
|
||||||
|
REST.set_response_status(response, REST.status.INTERNAL_SERVER_ERROR);
|
||||||
|
const char *error_msg = "GRMPF: PageSize";
|
||||||
|
REST.set_response_payload(response, error_msg, strlen(error_msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// FIXME: blocksize may be larger than our flash page size
|
||||||
|
// So we should handle this case and repeatedly flash a block until the
|
||||||
|
// received data is written.
|
||||||
|
if (current_offset % PAGESIZE + len > PAGESIZE) {
|
||||||
|
REST.set_response_status(response, REST.status.INTERNAL_SERVER_ERROR);
|
||||||
|
const char *error_msg = "GRMPF: blocksize";
|
||||||
|
REST.set_response_payload(response, error_msg, strlen(error_msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Should never happen, we test for < and > earlier.
|
||||||
|
if (packet->block1_offset != current_offset) {
|
||||||
|
REST.set_response_status(response, REST.status.INTERNAL_SERVER_ERROR);
|
||||||
|
const char *error_msg = "GRMPF: Offset";
|
||||||
|
REST.set_response_payload(response, error_msg, strlen(error_msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(packet->block1_offset + len > partition_size) {
|
||||||
|
REST.set_response_status(response,
|
||||||
|
REST.status.REQUEST_ENTITY_TOO_LARGE);
|
||||||
|
REST.set_response_payload(
|
||||||
|
response,
|
||||||
|
buffer,
|
||||||
|
sprintf((char *)buffer, "%luB max.", partition_size));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (current_page + current_offset % PAGESIZE, in_data, len);
|
||||||
|
if (current_offset % PAGESIZE == 0 || !packet->block1_more) {
|
||||||
|
// WRITE Flash here
|
||||||
|
PRINTF (("Flashing: %lu\n", (uint32_t)len));
|
||||||
|
sreg = SREG;
|
||||||
|
cli ();
|
||||||
|
bootloader_write_page_to_flash
|
||||||
|
(partition_start + current_offset, len, current_page);
|
||||||
|
SREG = sreg;
|
||||||
|
}
|
||||||
|
current_offset += len;
|
||||||
|
|
||||||
|
REST.set_response_status(response, REST.status.CHANGED);
|
||||||
|
coap_set_header_block1(response, packet->block1_num, 0, packet->block1_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
RESOURCE(
|
||||||
|
res_upload_image
|
||||||
|
, "title=\"Flash memory upgrade\";rt=\"block\""
|
||||||
|
, NULL
|
||||||
|
, NULL
|
||||||
|
, res_put_handler
|
||||||
|
, NULL
|
||||||
|
);
|
||||||
|
|
28
examples/osd/ota-update/sketch.pde
Normal file
28
examples/osd/ota-update/sketch.pde
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Gardena 9V Magnet-Valve
|
||||||
|
* We have a CoAP Resource for the Valve, it can be in state 1 (on) and
|
||||||
|
* 0 (off).
|
||||||
|
* Transition on-off outputs a negative pulse
|
||||||
|
* Transition off-on outputs a positive pulse
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "contiki.h"
|
||||||
|
#include "contiki-net.h"
|
||||||
|
#include "er-coap.h"
|
||||||
|
extern resource_t res_upload_image;
|
||||||
|
char resname[] = "update";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setup (void)
|
||||||
|
{
|
||||||
|
rest_init_engine ();
|
||||||
|
rest_activate_resource (&res_upload_image, resname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop (void)
|
||||||
|
{
|
||||||
|
//printf ("Huhu\n");
|
||||||
|
}
|
6
platform/osd-merkur-128/bootloader_if.h
Normal file
6
platform/osd-merkur-128/bootloader_if.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef BOOTLOADER_IF_H_
|
||||||
|
#define BOOTLOADER_IF_H_
|
||||||
|
|
||||||
|
extern uint8_t bootloader_get_mac(uint8_t);
|
||||||
|
|
||||||
|
#endif /* BOOTLOADER_IF_H_ */
|
|
@ -39,6 +39,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "contiki.h"
|
#include "contiki.h"
|
||||||
|
#include "bootloader_if.h"
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -85,8 +86,6 @@ const uint8_t default_domain_name[] PROGMEM = PARAMS_DOMAINNAME;
|
||||||
#if PARAMETER_STORAGE==0
|
#if PARAMETER_STORAGE==0
|
||||||
/* 0 Hard coded, minmal program and eeprom usage. */
|
/* 0 Hard coded, minmal program and eeprom usage. */
|
||||||
|
|
||||||
extern uint8_t bootloader_get_mac(uint8_t);
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
params_get_eui64(uint8_t *eui64) {
|
params_get_eui64(uint8_t *eui64) {
|
||||||
#if CONTIKI_CONF_RANDOM_MAC
|
#if CONTIKI_CONF_RANDOM_MAC
|
||||||
|
|
8
platform/osd-merkur-256/bootloader_if.h
Normal file
8
platform/osd-merkur-256/bootloader_if.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef BOOTLOADER_IF_H_
|
||||||
|
#define BOOTLOADER_IF_H_
|
||||||
|
|
||||||
|
extern uint8_t bootloader_get_mac(uint8_t);
|
||||||
|
extern int bootloader_write_page_to_flash
|
||||||
|
(uint32_t address, unsigned int size, unsigned char *p);
|
||||||
|
|
||||||
|
#endif /* BOOTLOADER_IF_H_ */
|
|
@ -39,6 +39,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "contiki.h"
|
#include "contiki.h"
|
||||||
|
#include "bootloader_if.h"
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -85,8 +86,6 @@ const uint8_t default_domain_name[] PROGMEM = PARAMS_DOMAINNAME;
|
||||||
#if PARAMETER_STORAGE==0
|
#if PARAMETER_STORAGE==0
|
||||||
/* 0 Hard coded, minmal program and eeprom usage. */
|
/* 0 Hard coded, minmal program and eeprom usage. */
|
||||||
|
|
||||||
extern uint8_t bootloader_get_mac(uint8_t);
|
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
params_get_eui64(uint8_t *eui64) {
|
params_get_eui64(uint8_t *eui64) {
|
||||||
#if CONTIKI_CONF_RANDOM_MAC
|
#if CONTIKI_CONF_RANDOM_MAC
|
||||||
|
|
Loading…
Reference in a new issue