OTA Bootloader

- including adjustments to  library header files to allow usage across C
(bootloader) and C++ (firmware sketches)
- including definition of new message types for firmware config and
firmware code
This commit is contained in:
ToSa27
2014-07-24 13:37:44 +02:00
parent cdf4d6ab52
commit 1c475da8d0
8 changed files with 781 additions and 8 deletions
+3
View File
@@ -0,0 +1,3 @@
*.o
*.hex
*.elf
+66
View File
@@ -0,0 +1,66 @@
PROJECT = MyOtaBootloader
INCLUDES = ../libraries/MySensors
MCU = atmega328p
CLK = 16000000L
ISP_PORT = com5
ISP_SPEED = 115200
ISP_PROTOCOL = stk500v2
ISP_MCU = m328p
# HFUSE = D8 - 4096 byte boot
ISP_HFUSE = D8
# LFUSE = 4E - Low power resonator (16MHz), fast start, clkdiv/8
ISP_LFUSE = FF
# EFUSE = 06 - 1.8V brownout
ISP_EFUSE = 06
ISP_ARGS = -c$(ISP_PROTOCOL) -P$(ISP_PORT) -b$(ISP_SPEED) -p$(ISP_MCU)
ifeq ($(OS),Windows_NT)
BINPATH = C:/Program Files (x86)/Arduino/hardware/tools/avr/bin/
JAVAPATH = C:/Program Files/Java/jdk1.7.0_40/bin/
JAVAC = $(JAVAPATH)javac.exe
JAVA = $(JAVAPATH)java.exe
else
UNAME_S := $(shell uname -s)
UNAME_P := $(shell uname -p)
UNAME_M := $(shell uname -m)
ifeq ($(UNAME_S),Linux)
ifeq ($(UNAME_P),x86_64)
BINPATH = ../arduino/bin-linux64/bin/
else ifneq ($(filter %86,$(UNAME_P)),)
BINPATH = ../arduino/bin-linux32/bin/
else ifneq ($(filter arm%,$(UNAME_M)),)
BINPATH = /usr/bin/
endif
endif
endif
CFLAGS = -c -g -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls -Wall -mmcu=$(MCU) -DF_CPU=$(CLK) -std=gnu99
LDFLAGS = -Os -Wl,--section-start=.text=0x7000 -nostartfiles -mmcu=$(MCU)
all: clean out
clean:
- rm *.o
- rm *.elf
- rm *.hex
$(PROJECT).o: $(PROJECT).c
"$(BINPATH)avr-gcc" $(CFLAGS) -I$(INCLUDES) $< -o $@
$(PROJECT).elf: $(PROJECT).o
"$(BINPATH)avr-gcc" $(LDFLAGS) -o $@ $< -lm
$(PROJECT).hex: $(PROJECT).elf
"$(BINPATH)avr-objcopy" -O ihex -R .eeprom $< $@
out: $(PROJECT).hex
"$(BINPATH)avr-size" $(PROJECT).elf
load: clean out isp
isp: $(PROJECT).hex
"$(BINPATH)avrdude" $(ISP_ARGS) -e -u -Ulock:w:0x3f:m -qq -Uefuse:w:0x$(ISP_EFUSE):m -Uhfuse:w:0x$(ISP_HFUSE):m -Ulfuse:w:0x$(ISP_LFUSE):m -Ulock:w:0x0f:m
"$(BINPATH)avrdude" $(ISP_ARGS) -V -q -s -Uflash:w:$(PROJECT).hex
"$(BINPATH)avrdude" $(ISP_ARGS)
+207
View File
@@ -0,0 +1,207 @@
#include "MyOtaBootloader.h"
int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
volatile char dummy;
EMPTY_INTERRUPT(WDT_vect);
static uint16_t calcCRCrom (const void* ptr, uint16_t len) {
uint16_t crc = ~0;
for (uint16_t i = 0; i < len; ++i)
crc = _crc16_update(crc, pgm_read_byte((uint16_t) ptr + i));
return crc;
}
static uint8_t validFirmware () {
return calcCRCrom(0, fc.blocks * FIRMWARE_BLOCK_SIZE) == fc.crc;
}
static void reboot() {
wdt_enable(WDTO_15MS);
for (;;);
}
static void startup() {
if (validFirmware()) {
wdt_disable();
clock_prescale_set(orgClockDiv);
((void(*)()) 0)();
} else
reboot();
}
static void boot_program_page(uint32_t page, uint8_t *buf) {
uint8_t sreg = SREG;
cli();
eeprom_busy_wait();
boot_page_erase(page);
boot_spm_busy_wait();
for (uint16_t i = 0; i < SPM_PAGESIZE; i += 2) {
uint16_t w = *buf++;
w += (*buf++) << 8;
boot_page_fill(page + i, w);
}
boot_page_write(page);
boot_spm_busy_wait();
boot_rww_enable();
SREG = sreg;
}
static boolean sendWrite(MyMessage message) {
return write(nc.parentNodeId, message.array, HEADER_SIZE + mGetLength(message), (message.destination == BROADCAST_ADDRESS));
}
static uint8_t sendAndWait(uint8_t reqType, uint8_t resType) {
msg.type = reqType;
for (uint8_t i = 0; i < 10; i++) {
sendWrite(msg);
for (uint16_t j = 0; j < 20; j++) {
wdt_reset();
for (uint16_t j = 0; j < 100; j++) {
wdt_reset();
uint8_t pipe;
boolean avail = available(&pipe);
if (avail && pipe<=6) {
read(rmsg.array,pipe);
if(!(mGetVersion(rmsg) == PROTOCOL_VERSION))
continue;
if (rmsg.destination == nc.nodeId) {
if (mGetCommand(rmsg) == C_INTERNAL) {
if (rmsg.type == I_PING_ACK) {
if (rmsg.data[0] < nc.distance - 1) {
nc.distance = rmsg.data[0] + 1;
nc.parentNodeId = rmsg.sender;
eeprom_write_byte((uint8_t*)EEPROM_PARENT_NODE_ID_ADDRESS, nc.parentNodeId);
eeprom_write_byte((uint8_t*)EEPROM_DISTANCE_ADDRESS, nc.distance);
}
}
}
if ((mGetCommand(rmsg) == mGetCommand(msg)) && (rmsg.type == resType))
return 1;
}
}
delaym(1);
}
}
}
return 0;
}
int main () {
asm volatile ("clr __zero_reg__");
// switch to 4 MHz
orgClockDiv = clock_prescale_get();
clock_prescale_set(F_CPU_DIV);
MCUSR = 0;
// enable watchdog to avoid deadlock
wdt_enable(WDTO_8S);
#ifdef LED_DEBUG
// enable LEDs for debugging and blink once as visual "bootloader started" sign
led_init();
blink(LED_MBOTH, 250);
#endif
#ifdef UART_DEBUG
// enable UART for debugging and send start message
uart_init();
uart_puts("Go\n");
#endif
wdt_reset();
// initialize RF module
begin();
wdt_reset();
// Read settings from EEPROM
eeprom_read_block((void*)&nc, (void*)EEPROM_NODE_ID_ADDRESS, sizeof(struct NodeConfig));
wdt_reset();
msg.sender = nc.nodeId;
msg.last = nc.nodeId;
address(nc.nodeId);
msg.sensor = NODE_SENSOR_ID;
mSetLength(msg, 0);
mSetPayloadType(msg, P_STRING);
mSetAck(msg,false);
mSetVersion(msg, PROTOCOL_VERSION);
nc.distance = 255;
mSetCommand(msg, C_INTERNAL);
msg.destination = BROADCAST_ADDRESS;
if (!sendAndWait(I_PING, I_PING_ACK))
// starting existing firmware if no ping response (if firmware is valid)
// reboot();
startup();
msg.destination = GATEWAY_ADDRESS;
if (nc.nodeId == AUTO) {
openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(nc.nodeId));
if (!sendAndWait(I_ID_REQUEST, I_ID_RESPONSE))
reboot();
if (mGetPayloadType(rmsg) == P_BYTE)
nc.nodeId = rmsg.data[0];
else if (mGetPayloadType(rmsg) == P_STRING)
nc.nodeId = atoi(rmsg.data);
if (nc.nodeId == AUTO)
reboot();
eeprom_write_byte((uint8_t*)EEPROM_NODE_ID_ADDRESS, nc.nodeId);
msg.sender = nc.nodeId;
msg.last = nc.nodeId;
address(nc.nodeId);
}
// Read settings from EEPROM
eeprom_read_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(struct FirmwareConfig));
mSetPayloadType(msg,P_CUSTOM);
FirmwareConfigRequest *firmwareConfigRequest = (FirmwareConfigRequest *)msg.data;
mSetLength(msg, sizeof(FirmwareConfigRequest));
mSetCommand(msg, C_STREAM);
firmwareConfigRequest->type = fc.type;
firmwareConfigRequest->version = fc.version;
if (!sendAndWait(ST_FIRMWARE_CONFIG_REQUEST, ST_FIRMWARE_CONFIG_RESPONSE))
// starting existing firmware if no firmware config response (if firmware is valid)
// reboot();
startup();
FirmwareConfigResponse *firmwareConfigResponse = (FirmwareConfigResponse *)rmsg.data;
if (firmwareConfigResponse->version == fc.version)
if (firmwareConfigResponse->blocks == fc.blocks)
if (firmwareConfigResponse->crc == fc.crc)
if (validFirmware())
startup();
fc.type = firmwareConfigResponse->type;
fc.version = firmwareConfigResponse->version;
fc.blocks = firmwareConfigResponse->blocks;
fc.crc = firmwareConfigResponse->crc;
FirmwareRequest *firmwareRequest = (FirmwareRequest *)msg.data;
mSetLength(msg, sizeof(FirmwareRequest));
firmwareRequest->type = fc.type;
firmwareRequest->version = fc.version;
for (uint16_t block = 0; block < fc.blocks; block++) {
firmwareRequest->block = block;
if (!sendAndWait(ST_FIRMWARE_REQUEST, ST_FIRMWARE_RESPONSE))
reboot();
FirmwareResponse *firmwareResponse = (FirmwareResponse *)rmsg.data;
uint8_t offset = (block * FIRMWARE_BLOCK_SIZE) % SPM_PAGESIZE;
memcpy(progBuf + offset, firmwareResponse->data, FIRMWARE_BLOCK_SIZE);
if (offset == SPM_PAGESIZE - FIRMWARE_BLOCK_SIZE)
boot_program_page((block * FIRMWARE_BLOCK_SIZE) - offset, progBuf);
}
wdt_reset();
if (validFirmware()) {
eeprom_write_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(struct FirmwareConfig));
#ifdef UART_DEBUG
uart_puts("fw ok\n");
} else {
uart_puts("fw nok\n");
#endif
}
reboot();
}
+67
View File
@@ -0,0 +1,67 @@
#ifndef MyOtaBootloader_H
#define MyOtaBootloader_H
#include <avr/boot.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <stdint.h>
#include <string.h>
#include <util/crc16.h>
#include "MyMessage.h"
#include "MySensor.h"
#include "MyOtaBootloaderRF24.h"
#define FIRMWARE_BLOCK_SIZE 16
struct FirmwareConfig
{
uint16_t type;
uint16_t version;
uint16_t blocks;
uint16_t crc;
};
typedef struct
{
uint16_t type;
uint16_t version;
} FirmwareConfigRequest;
typedef struct
{
uint16_t type;
uint16_t version;
uint16_t blocks;
uint16_t crc;
} FirmwareConfigResponse;
typedef struct
{
uint16_t type;
uint16_t version;
uint16_t block;
} FirmwareRequest;
typedef struct
{
uint16_t type;
uint16_t version;
uint16_t block;
uint8_t data[FIRMWARE_BLOCK_SIZE];
} FirmwareResponse;
static struct NodeConfig nc;
static struct FirmwareConfig fc;
static MyMessage msg;
static MyMessage rmsg;
static clock_div_t orgClockDiv = 0;
static uint8_t progBuf[SPM_PAGESIZE];
#endif // MyOtaBootloader_H
+154
View File
@@ -0,0 +1,154 @@
#ifndef MyOtaBootloaderHW_H
#define MyOtaBootloaderHW_H
#include <stdlib.h>
#include <avr/power.h>
//#define LED_DEBUG
//#define UART_DEBUG
// hardware
// ********
#define F_CPU_DIV clock_div_4
#define F_CPU_REAL F_CPU / (1 << F_CPU_DIV)
#define UART_BAUD 9600UL
#define DELAY_M 125 * (1 << F_CPU_DIV)
// boolean definition
// ******************
typedef uint8_t bool;
typedef uint8_t boolean;
#define false 0x0
#define true 0x1
#define LOW 0x0
#define HIGH 0x1
// delay
// *****
static void delayu() {
asm("nop");
}
static void delaym(uint16_t t) {
uint16_t d, a;
for (d = 0; d < t; d++)
for (a = 0; a < DELAY_M; a++)
asm("nop");
}
// LED debug
// *********
#ifdef LED_DEBUG
#define LED_DDR DDRD
#define LED_PORT PORTD
#define LED_RED 6 // Arduino Pin 6 <-> Bit 6 of port D
#define LED_GREEN 7 // Arduino Pin 7 <-> Bit 7 of port D
#define LED_MRED (1 << LED_RED)
#define LED_MGREEN (1 << LED_GREEN)
#define LED_MBOTH (LED_MRED | LED_MGREEN)
static void led_init() {
LED_DDR |= LED_MBOTH;
LED_PORT &= ~LED_MBOTH;
}
static void blink(uint8_t mask, uint16_t time) {
LED_PORT |= mask;
if (time > 0)
{
delaym(time);
LED_PORT &= ~mask;
delaym(time);
}
}
#endif
// UART debug
// **********
#ifdef UART_DEBUG
static void uart_init()
{
UCSR0A = _BV(U2X0); //Double speed mode USART0
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
UBRR0L = (uint8_t)( (F_CPU_REAL + UART_BAUD * 4L) / (UART_BAUD * 8L) - 1 );
}
static void uart_putc(char ch) {
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = ch;
}
static void uart_puts(char *s)
{
while (*s)
uart_putc(*s++);
}
static void uart_puti(uint8_t i)
{
char s[5];
itoa( i, s, 10 );
uart_puts( s );
}
#endif
// SPI communication
// *****************
#define SPI_DDR DDRB
#define SPI_PORT PORTB
#define SPI_PIN PINB
#define SPI_SCLK 5 // Arduino Pin 13 <-> Bit 5 of port B
#define SPI_MISO 4 // Arduino Pin 12 <-> Bit 4 of port B
#define SPI_MOSI 3 // Arduino Pin 11 <-> Bit 3 of port B
#define SPI_CSN 2 // Arduino Pin 10 <-> Bit 2 of port B
#define SPI_CE 1 // Arduino Pin 9 <-> Bit 1 of port B
#define csnlow() SPI_PORT &= ~(1<<SPI_CSN);delaym(1)
#define csnhigh() SPI_PORT |= (1<<SPI_CSN);delaym(1)
#define celow() SPI_PORT &= ~(1<<SPI_CE);delaym(1)
#define cehigh() SPI_PORT |= (1<<SPI_CE);delaym(1)
static void SPIinit()
{
SPI_DDR |= (1 << SPI_MOSI) + (1 << SPI_SCLK) + (1 << SPI_CE) + (1 << SPI_CSN);
SPI_DDR &= ~(1 << SPI_MISO);
SPI_PORT &= ~((1 << SPI_MOSI) + (1 << SPI_SCLK) + (1 << SPI_CE));
SPI_PORT |= (1 << SPI_CSN);
}
static uint8_t SPItransfer(uint8_t value)
{
uint8_t i;
for(i = 0 ;i < 8;i++) {
delayu();
if ((value & 0x80) == 0x00)
SPI_PORT &= ~(1 << SPI_MOSI);
else
SPI_PORT |= (1 << SPI_MOSI);
value = (value << 1); // shift next bit into MSB..
delayu();
SPI_PORT |= (1 << SPI_SCLK);
value |= ((SPI_PIN >> SPI_MISO) & 0x01); // capture current MISO bit
delayu();
SPI_PORT &= ~(1 << SPI_SCLK);
delayu();
}
return value;
}
static uint8_t spiTrans(uint8_t cmd){
uint8_t status;
csnlow();
status = SPItransfer( cmd );
csnhigh();
return status;
}
#endif // MyOtaBootloaderHW_H
+253
View File
@@ -0,0 +1,253 @@
#ifndef MyOtaBootloaderRF24_H
#define MyOtaBootloaderRF24_H
#include "MyOtaBootloaderHW.h"
#include "../libraries/MySensors/utility/nRF24L01.h"
#include <stdlib.h>
// hardware-agnostic interface to transceiver
// ******************************************
// static void begin()
// static void address(uint8_t addr)
// static boolean write(uint8_t next, uint8_t* packet, uint8_t length, boolean multicast)
// static bool available(uint8_t* pipe_num)
// static void read(uint8_t* buf, uint8_t pipe)
typedef enum { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR } rf24_pa_dbm_e ;
typedef enum { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS } rf24_datarate_e;
uint64_t pipe0_reading_address; /**< Last address set on pipe 0 for reading. */
static uint8_t read_register(uint8_t reg)
{
csnlow();
SPItransfer( R_REGISTER | ( REGISTER_MASK & reg ) );
uint8_t result = SPItransfer(0xff);
csnhigh();
return result;
}
static uint8_t write_registers(uint8_t reg, const uint8_t* buf, uint8_t len)
{
uint8_t status;
csnlow();
status = SPItransfer( W_REGISTER | ( REGISTER_MASK & reg ) );
while ( len-- )
SPItransfer(*buf++);
csnhigh();
return status;
}
static uint8_t write_register(uint8_t reg, uint8_t value)
{
uint8_t status;
csnlow();
status = SPItransfer( W_REGISTER | ( REGISTER_MASK & reg ) );
SPItransfer(value);
csnhigh();
return status;
}
static uint8_t read_payload(uint8_t* buf, uint8_t data_len)
{
#ifdef UART_DEBUG
uart_puts("-> ");
#endif
uint8_t status;
uint8_t* current = buf;
csnlow();
status = SPItransfer( R_RX_PAYLOAD );
while ( data_len-- ) {
*current = SPItransfer(0xFF);
#ifdef UART_DEBUG
uart_puti(*current);
uart_putc(',');
#endif
current++;
}
csnhigh();
#ifdef UART_DEBUG
uart_putc('\n');
#endif
return status;
}
#define get_status() spiTrans(NOP)
static void powerUp(void)
{
if (!(read_register(CONFIG) & _BV(PWR_UP))){
write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP));
delaym(5);
}
}
#define convert_64_bit_to_byte_array(value, data) ((*(uint64_t *)(data)) = (uint64_t)(value))
static void startListening(void)
{
powerUp();
write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX));
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
if (pipe0_reading_address){
uint8_t addressa[8];
convert_64_bit_to_byte_array(pipe0_reading_address, addressa);
write_registers(RX_ADDR_P0, addressa, 5);
}
spiTrans(FLUSH_RX);
spiTrans(FLUSH_TX);
cehigh();
}
static void stopListening(void)
{
celow();
spiTrans(FLUSH_TX);
spiTrans(FLUSH_RX);
write_register(CONFIG, read_register(CONFIG) & ~_BV(PRIM_RX));
}
static void write_payload(const uint8_t* buf, uint8_t data_len, const uint8_t writeType)
{
#ifdef UART_DEBUG
uart_puts("<- ");
#endif
const uint8_t* current = buf;
csnlow();
SPItransfer(writeType);
while ( data_len-- ) {
#ifdef UART_DEBUG
uart_puti(*current);
uart_putc(',');
#endif
SPItransfer(*current++);
}
csnhigh();
#ifdef UART_DEBUG
uart_putc('\n');
#endif
}
static bool writem( const uint8_t* buf, uint8_t len, const bool multicast )
{
write_payload( buf, len, multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD) ;
cehigh();
celow();
while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { }
uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) );
if( status & _BV(MAX_RT)){
spiTrans(FLUSH_TX);
return 0;
}
return 1;
}
static uint8_t getDynamicPayloadSize(void)
{
uint8_t result = 0;
csnlow();
SPItransfer( R_RX_PL_WID );
result = SPItransfer(0xff);
csnhigh();
if(result > 32) {
spiTrans(FLUSH_RX);
return 0;
}
return result;
}
static bool available(uint8_t* pipe_num)
{
if (!(read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){
if (pipe_num) {
uint8_t status = get_status();
*pipe_num = ( status >> RX_P_NO ) & 0b111;
}
return 1;
}
return 0;
}
static void writeAckPayload(uint8_t pipe, const uint8_t* buf, uint8_t len)
{
const uint8_t* current = buf;
uint8_t data_len = len;
csnlow();
SPItransfer(W_ACK_PAYLOAD | ( pipe & 0b111 ) );
while ( data_len-- )
SPItransfer(*current++);
csnhigh();
}
static void read( uint8_t* buf, uint8_t pipe ){
read_payload(buf, getDynamicPayloadSize());
write_register(STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS));
writeAckPayload(pipe,&pipe, 1 );
}
static void openWritingPipe(uint64_t value)
{
uint8_t valuea[8];
convert_64_bit_to_byte_array(value, valuea);
write_registers(RX_ADDR_P0, valuea, 5);
write_registers(TX_ADDR, valuea, 5);
}
static void openReadingPipe(uint8_t child, uint64_t address)
{
if (child == 0)
pipe0_reading_address = address;
uint8_t addressa[8];
convert_64_bit_to_byte_array(address, addressa);
if ( child < 2 )
write_registers(RX_ADDR_P0 + child, addressa, 5);
write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(ERX_P0 + child));
}
static boolean write(uint8_t next, uint8_t* packet, uint8_t length, boolean multicast) {
powerUp();
stopListening();
openWritingPipe(TO_ADDR(next));
bool ok = writem(packet, length, multicast);
startListening();
return ok;
}
static void address(uint8_t addr)
{
if (addr != BROADCAST_ADDRESS) {
openReadingPipe(WRITE_PIPE, TO_ADDR(addr));
openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(addr));
}
}
static void begin(void)
{
pipe0_reading_address = 0;
SPIinit();
delaym( 10 ) ;
write_register(SETUP_RETR, 5 << ARD | 15 << ARC);
write_register(EN_AA, 0b00111111 & ~_BV(BROADCAST_PIPE)) ;
write_register(RF_CH, RF24_CHANNEL);
write_register(RF_SETUP, (read_register(RF_SETUP) & 0b11010000) | ((RF24_PA_LEVEL << 1) + 1) | ((RF24_DATARATE & 0b00000010 ) << 4) | ((RF24_DATARATE & 0b00000001 ) << 3));
write_register(CONFIG, read_register(CONFIG) | _BV(CRCO) | _BV(EN_CRC)) ;
write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT));
csnlow();
SPItransfer(ACTIVATE);
SPItransfer(0x73);
csnhigh();
write_register(FEATURE, read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) );
write_register(DYNPD, read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0));
spiTrans(FLUSH_RX);
spiTrans(FLUSH_TX);
powerUp(); //Power up by default when begin() is called
write_register(CONFIG, read_register(CONFIG) & ~_BV(PRIM_RX));
openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS));
}
#endif // MyOtaBootloaderRF24_H
+19 -3
View File
@@ -12,9 +12,11 @@
#ifndef MyMessage_h
#define MyMessage_h
#include <SPI.h>
#ifdef __cplusplus
#include <Arduino.h>
#include <string.h>
#include <stdint.h>
#endif
#define PROTOCOL_VERSION 2
#define MAX_MESSAGE_LENGTH 32
@@ -56,7 +58,8 @@ typedef enum {
// Type of data stream (for streamed message)
typedef enum {
ST_FIRMWARE, ST_SOUND, ST_IMAGE
ST_FIRMWARE_CONFIG_REQUEST, ST_FIRMWARE_CONFIG_RESPONSE, ST_FIRMWARE_REQUEST, ST_FIRMWARE_RESPONSE,
ST_SOUND, ST_IMAGE
} stream;
typedef enum {
@@ -101,7 +104,7 @@ typedef enum {
#define miSetLength(_length) BF_SET(version_length, _length, 3, 5)
#define miSetPayloadType(_pt) BF_SET(command_ack_payload, _pt, 4, 4)
#ifdef __cplusplus
class MyMessage
{
public:
@@ -144,6 +147,13 @@ public:
MyMessage& set(unsigned int value);
MyMessage& set(int value);
#else
typedef union {
struct
{
#endif
uint8_t version_length; // 3 bit - Protocol version
// 5 bit - Length of payload
@@ -167,6 +177,12 @@ public:
int iValue;
char data[MAX_PAYLOAD + 1];
} __attribute__((packed));
#ifdef __cplusplus
} __attribute__((packed));
#else
};
uint8_t array[HEADER_SIZE + MAX_PAYLOAD + 1];
} __attribute__((packed)) MyMessage;
#endif
#endif
+12 -5
View File
@@ -15,16 +15,19 @@
#include "Version.h" // Auto generated by bot
#include "MyConfig.h"
#include "MyMessage.h"
#include <Arduino.h>
#include <stddef.h>
#include <SPI.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <stdarg.h>
#ifdef __cplusplus
#include <Arduino.h>
#include <SPI.h>
#include "utility/LowPower.h"
#include "utility/RF24.h"
#include "utility/RF24_config.h"
#endif
#ifdef DEBUG
#define debug(x,...) debugPrint(x, ##__VA_ARGS__)
@@ -47,7 +50,11 @@
#define EEPROM_DISTANCE_ADDRESS (EEPROM_PARENT_NODE_ID_ADDRESS+1)
#define EEPROM_ROUTES_ADDRESS (EEPROM_DISTANCE_ADDRESS+1) // Where to start storing routing information in EEPROM. Will allocate 256 bytes.
#define EEPROM_CONTROLLER_CONFIG_ADDRESS (EEPROM_ROUTES_ADDRESS+256) // Location of controller sent configuration (we allow one payload of config data from controller)
#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS+24) // First free address for sketch static configuration
#define EEPROM_FIRMWARE_TYPE_ADDRESS (EEPROM_CONTROLLER_CONFIG_ADDRESS+24)
#define EEPROM_FIRMWARE_VERSION_ADDRESS (EEPROM_FIRMWARE_TYPE_ADDRESS+2)
#define EEPROM_FIRMWARE_BLOCKS_ADDRESS (EEPROM_FIRMWARE_VERSION_ADDRESS+2)
#define EEPROM_FIRMWARE_CRC_ADDRESS (EEPROM_FIRMWARE_BLOCKS_ADDRESS+2)
#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2) // First free address for sketch static configuration
// This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data).
// This is also act as base value for sensor nodeId
@@ -74,8 +81,7 @@ struct ControllerConfig {
uint8_t isMetric;
};
#ifdef __cplusplus
class MySensor : public RF24
{
public:
@@ -267,5 +273,6 @@ class MySensor : public RF24
void removeChildRoute(uint8_t childId);
void internalSleep(int ms);
};
#endif
#endif