diff --git a/MyConfig.h b/MyConfig.h index 95ad82b7..4260682d 100644 --- a/MyConfig.h +++ b/MyConfig.h @@ -261,6 +261,19 @@ // requires the MYSBootloader and disabled MY_OTA_FIRMWARE_FEATURE //#define MY_OTA_FIRMWARE_FEATURE +// Define or uncomment MY_OTA_USE_I2C_EEPROM below if you want I2C EEPROM instead +// of a SPI flash. Used EEPROM needs to be large enough, an 24(L)C256 will do as minimum. +// HW I2C assumed. This will exclude the SPI flash code. +// Note that you also need an updated DualOptiboot supporting I2C EEPROM! +//#define MY_OTA_USE_I2C_EEPROM + +#ifdef MY_OTA_USE_I2C_EEPROM +// I2C address of EEPROM. Wire will shift this left, i.e. 0x50->0xA0 +#ifndef MY_OTA_I2C_ADDR +#define MY_OTA_I2C_ADDR 0x50 +#endif +#endif + /** * @def MY_OTA_FLASH_SS * @brief Slave select pin for external flash. diff --git a/MySensors.h b/MySensors.h index c65fa4e9..8678022b 100644 --- a/MySensors.h +++ b/MySensors.h @@ -172,7 +172,11 @@ MY_DEFAULT_RX_LED_PIN in your sketch instead to enable LEDs // FLASH #if defined(MY_OTA_FIRMWARE_FEATURE) +#if defined(MY_OTA_USE_I2C_EEPROM) +#include "drivers/I2CEeprom/I2CEeprom.cpp" +#else #include "drivers/SPIFlash/SPIFlash.cpp" +#endif #include "core/MyOTAFirmwareUpdate.cpp" #endif diff --git a/core/MyOTAFirmwareUpdate.cpp b/core/MyOTAFirmwareUpdate.cpp index 2d41af68..bfd08267 100644 --- a/core/MyOTAFirmwareUpdate.cpp +++ b/core/MyOTAFirmwareUpdate.cpp @@ -24,7 +24,11 @@ extern MyMessage _msg; extern MyMessage _msgTmp; // local variables +#ifdef MY_OTA_USE_I2C_EEPROM +I2CEeprom _flash(MY_OTA_I2C_ADDR); +#else SPIFlash _flash(MY_OTA_FLASH_SS, MY_OTA_FLASH_JDECID); +#endif nodeFirmwareConfig_t _nodeFirmwareConfig; bool _firmwareUpdateOngoing; uint32_t _firmwareLastRequest; @@ -110,6 +114,21 @@ bool firmwareOTAUpdateProcess(void) firmwareResponse->data, FIRMWARE_BLOCK_SIZE); // wait until flash written while (_flash.busy()) {} +#ifdef OTA_EXTRA_FLASH_DEBUG + { + char prbuf[8]; + uint32_t addr = ((_firmwareBlock - 1) * FIRMWARE_BLOCK_SIZE) + FIRMWARE_START_OFFSET; + OTA_DEBUG(PSTR("OTA:FWP:FL DUMP ")); + sprintf_P(prbuf,PSTR("%04X:"), (uint16_t)addr); + MY_SERIALDEVICE.print(prbuf); + for(uint8_t i=0; i +// +// Original SPI flash driver this is based on: +// Copyright (c) 2013-2015 by Felix Rusu, LowPowerLab.com +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code + +#include +#include "I2CEeprom.h" + +I2CEeprom::I2CEeprom(uint8_t addr) : extEEPROM(I2CEEPROM_CHIP_SIZE, 1, I2CEEPROM_PAGE_SIZE) +{ + m_addr = addr; // we only need this for busy() +} + +/// setup +bool I2CEeprom::initialize() +{ + return extEEPROM::begin(I2CEEPROM_TWI_CLK) ? false : true; +} + +/// read 1 byte +uint8_t I2CEeprom::readByte(uint32_t addr) +{ + uint8_t val; + readBytes(addr, &val, 1); + return val; +} + +/// read multiple bytes +void I2CEeprom::readBytes(uint32_t addr, void* buf, uint16_t len) +{ + extEEPROM::read((unsigned long)addr, (byte *)buf, (unsigned int) len); +} + +/// check if the chip is busy +bool I2CEeprom::busy() +{ + Wire.beginTransmission(m_addr); + Wire.write(0); + Wire.write(0); + if (Wire.endTransmission() == 0) { + return false; + } else { + return true; // busy + } +} + +/// Write 1 byte +void I2CEeprom::writeByte(uint32_t addr, uint8_t byt) +{ + writeBytes(addr, &byt, 1); +} + +/// write multiple bytes +void I2CEeprom::writeBytes(uint32_t addr, const void* buf, uint16_t len) +{ + extEEPROM::write((unsigned long) addr, (byte *)buf, (unsigned int) len); +} diff --git a/drivers/I2CEeprom/I2CEeprom.h b/drivers/I2CEeprom/I2CEeprom.h new file mode 100644 index 00000000..96934c5b --- /dev/null +++ b/drivers/I2CEeprom/I2CEeprom.h @@ -0,0 +1,116 @@ +// Copyright (C) 2016 Krister W. +// +// Original SPI flash driver this is based on: +// Copyright (c) 2013-2015 by Felix Rusu, LowPowerLab.com +// +// I2C EEPROM library for MySensors OTA. Based on SPI Flash memory library for +// arduino/moteino. +// This driver is made to look like the SPI flash driver so changes needed to +// MySensors OTA code is minimized. +// This works with 32 or 64kB I2C EEPROM like an 24(L)C256. AVR HW I2C is assumed +// and error handling is quite minimal. Uses extEEPROM as the underlying driver. +// DEPENDS ON: Arduino Wire library, extEEPROM +// ********************************************************************************** +// License +// ********************************************************************************** +// This program is free software; you can redistribute it +// and/or modify it under the terms of the GNU General +// Public License as published by the Free Software +// Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A +// PARTICULAR PURPOSE. See the GNU General Public +// License for more details. +// +// You should have received a copy of the GNU General +// Public License along with this program. +// If not, see . +// +// Licence can be viewed at +// http://www.gnu.org/licenses/gpl-3.0.txt +// +// Please maintain this license information along with authorship +// and copyright notices in any redistribution of this code + +/// +/// @file I2CEeprom.h +/// +/// @brief I2CEeprom provides access to a I2C EEPROM IC for OTA update or storing data +/// +/// This is a wrapper over extEEPROM to make it look like a flash chip. +/// +#ifndef _I2CEeprom_H_ +#define _I2CEeprom_H_ + +#include +#include + +/// I2C speed +// 400kHz clock as default. Use extEEPROM type +#ifndef I2CEEPROM_TWI_CLK +#define I2CEEPROM_TWI_CLK twiClock400kHz +#endif + +/// EEPROM page size +//Typically 64 (see data sheet for your EEPROM) +// Some 512kbit chips use 128 byte pages (e.g. Atmel AT24C512) +#ifndef I2CEEPROM_PAGE_SIZE +#define I2CEEPROM_PAGE_SIZE 64 +#endif + +/// EEPROM size +// 24C256 is 32kB, minimum that fits code for ATmega328 +// Use extEEPROM type +#ifndef I2CEEPROM_CHIP_SIZE +#define I2CEEPROM_CHIP_SIZE kbits_256 +#endif + +/** I2CEeprom class */ +class I2CEeprom : extEEPROM +{ +public: + + explicit I2CEeprom(uint8_t addr); //!< Constructor + bool initialize(); //!< setup + uint8_t readByte(uint32_t addr); //!< read 1 byte from flash memory + void readBytes(uint32_t addr, void* buf, uint16_t len); //!< read multiple bytes + void writeByte(uint32_t addr, uint8_t byt); //!< Write 1 byte to flash memory + void writeBytes(uint32_t addr, const void* buf, + uint16_t len); //!< write multiple bytes to flash memory (up to 64K), if define SPIFLASH_SST25TYPE is set AAI Word Programming will be used + bool busy(); //!< check if the chip is busy erasing/writing + + // the rest not needed for EEPROMs, but kept so SPI flash code compiles as is (functions are NOP) + + /// dummy function for SPI flash compatibility + uint16_t readDeviceId() + { + return 0xDEAD; + }; + /// dummy function for SPI flash compatibility + void chipErase() {}; + /// dummy function for SPI flash compatibility + void blockErase4K(uint32_t address) + { + (void)address; + }; + /// dummy function for SPI flash compatibility + void blockErase32K(uint32_t address) + { + (void)address; + }; + /// dummy function for SPI flash compatibility + void sleep() {}; + /// dummy function for SPI flash compatibility + void wakeup() {}; + /// dummy function for SPI flash compatibility + void end() {}; + +protected: + + uint8_t m_addr; ///< I2C address for busy() +}; + +#endif