#define CONFIG_UART_BUFFER_SIZE 6144
#define CONFIG_QUEUE_SIZE 6144
#define CONFIG_QUEUE_MAX_LENGTH 200
- #define EEPROM_SIZE 4096
- #define EEPROM_OFFSET EEPROM_SIZE+0xED000-EEPROM_RESERVED
+ #define EEPROM_SIZE 200
+ //#define EEPROM_OFFSET EEPROM_SIZE+0xED000-EEPROM_RESERVED
+ #define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
// following pins are for the sx1262
const int pin_rxen = 37;
Serial.setRxBufferSize(CONFIG_UART_BUFFER_SIZE);
#endif
+ #if MCU_VARIANT == MCU_NRF52
+ if (!eeprom_begin()) {
+ Serial.write("EEPROM initialisation failed.\r\n");
+ }
+ #endif
+
// Seed the PRNG
randomSeed(analogRead(0));
#if HAS_EEPROM
#include <EEPROM.h>
#elif PLATFORM == PLATFORM_NRF52
- #include "flash_nrf5x.h"
- int written_bytes = 0;
+ #include <Adafruit_LittleFS.h>
+ #include <InternalFileSystem.h>
+ using namespace Adafruit_LittleFS_Namespace;
+ #define EEPROM_FILE "eeprom"
+ bool file_exists = false;
+ int written_bytes = 4;
+ File file(InternalFS);
#endif
#include <stddef.h>
#include "LoRa.h"
}
#if !HAS_EEPROM && MCU_VARIANT == MCU_NRF52
+ bool eeprom_begin() {
+ InternalFS.begin();
+
+ file.open(EEPROM_FILE, FILE_O_READ);
+
+ // if file doesn't exist
+ if (!file) {
+ if (file.open(EEPROM_FILE, FILE_O_WRITE)) {
+ // initialise the file with empty content
+ uint8_t empty_content[EEPROM_SIZE] = {0};
+ file.write(empty_content, EEPROM_SIZE);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ file.close();
+ file.open(EEPROM_FILE, FILE_O_WRITE);
+ return true;
+ }
+ }
+
uint8_t eeprom_read(uint32_t mapped_addr) {
uint8_t byte;
void* byte_ptr = &byte;
- flash_nrf5x_read(byte_ptr, mapped_addr, 1);
+ file.seek(mapped_addr);
+ file.read(byte_ptr, 1);
return byte;
}
#endif
#elif !HAS_EEPROM && MCU_VARIANT == MCU_NRF52
uint8_t read_byte;
void* read_byte_ptr = &read_byte;
- void const * byte_ptr = &byte;
- flash_nrf5x_read(read_byte_ptr, mapped_addr, 1);
+ file.seek(mapped_addr);
+ file.read(read_byte_ptr, 1);
+ file.seek(mapped_addr);
if (read_byte != byte) {
- flash_nrf5x_write(mapped_addr, byte_ptr, 1);
+ file.write(byte);
}
-
written_bytes++;
- // flush the cache every 4 bytes to make sure everything is synced
- if (written_bytes == 4) {
+ if (written_bytes >= 8) {
+ file.close();
+ file.open(EEPROM_FILE, FILE_O_WRITE);
written_bytes = 0;
- flash_nrf5x_flush();
}
#endif
+++ /dev/null
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach for Adafruit Industries
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifdef NRF52840_XXAA
-#include <string.h>
-#include "flash_cache.h"
-#include "common_func.h"
-#include "variant.h"
-#include "wiring_digital.h"
-
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM DECLARATION
-//--------------------------------------------------------------------+
-static inline uint32_t page_addr_of (uint32_t addr)
-{
- return addr & ~(FLASH_CACHE_SIZE - 1);
-}
-
-static inline uint32_t page_offset_of (uint32_t addr)
-{
- return addr & (FLASH_CACHE_SIZE - 1);
-}
-
-int flash_cache_write (flash_cache_t* fc, uint32_t dst, void const * src, uint32_t len)
-{
- uint8_t const * src8 = (uint8_t const *) src;
- uint32_t remain = len;
-
- // Program up to page boundary each loop
- while ( remain )
- {
- uint32_t const page_addr = page_addr_of(dst);
- uint32_t const offset = page_offset_of(dst);
-
- uint32_t wr_bytes = FLASH_CACHE_SIZE - offset;
- wr_bytes = min32(remain, wr_bytes);
-
- // Page changes, flush old and update new cache
- if ( page_addr != fc->cache_addr )
- {
- flash_cache_flush(fc);
- fc->cache_addr = page_addr;
-
- // read a whole page from flash
- fc->read(fc->cache_buf, page_addr, FLASH_CACHE_SIZE);
- }
-
- memcpy(fc->cache_buf + offset, src8, wr_bytes);
-
- // adjust for next run
- src8 += wr_bytes;
- remain -= wr_bytes;
- dst += wr_bytes;
- }
-
- return len - remain;
-}
-
-void flash_cache_flush (flash_cache_t* fc)
-{
- if ( fc->cache_addr == FLASH_CACHE_INVALID_ADDR ) return;
-
- // skip erase & program if verify() exists, and memory matches
- if ( !(fc->verify && fc->verify(fc->cache_addr, fc->cache_buf, FLASH_CACHE_SIZE)) )
- {
- // indicator TODO allow to disable flash indicator
- ledOn(LED_BUILTIN);
-
- fc->erase(fc->cache_addr);
- fc->program(fc->cache_addr, fc->cache_buf, FLASH_CACHE_SIZE);
-
- ledOff(LED_BUILTIN);
- }
-
- fc->cache_addr = FLASH_CACHE_INVALID_ADDR;
-}
-
-int flash_cache_read (flash_cache_t* fc, void* dst, uint32_t addr, uint32_t count)
-{
- // there is no check for overflow / wraparound for dst + count, addr + count.
- // this might be a useful thing to add for at least debug builds.
-
- // overwrite with cache value if available
- if ( (fc->cache_addr != FLASH_CACHE_INVALID_ADDR) && // cache is not valid
- !(addr < fc->cache_addr && addr + count <= fc->cache_addr) && // starts before, ends before cache area
- !(addr >= fc->cache_addr + FLASH_CACHE_SIZE) ) // starts after end of cache area
- {
- // This block is entered only when the read overlaps the cache area by at least one byte.
- // If the read starts before the cache area, it's further guaranteed
- // that count is large enough to cause the read to enter
- // the cache area by at least 1 byte.
- uint32_t dst_off = 0;
- uint32_t src_off = 0;
- if (addr < fc->cache_addr)
- {
- dst_off = fc->cache_addr - addr;
- // Read the bytes prior to the cache address
- fc->read(dst, addr, dst_off);
- }
- else
- {
- src_off = addr - fc->cache_addr;
- }
-
- // Thus, after the above code block executes:
- // *** AT MOST ***, only one of src_off and dst_off are non-zero;
- // (Both may be zero when the read starts at the start of the cache area.)
- // dst_off corresponds to the number of bytes already read from PRIOR to the cache area.
- // src_off corresponds to the byte offset to start reading at, from WITHIN the cache area.
-
- // How many bytes to memcpy from flash area?
- // Remember that, AT MOST, one of src_off and dst_off are non-zero.
- // If src_off is non-zero, then dst_off is zero, representing that the
- // read starts inside the cache. In this case:
- // PARAM1 := FLASH_CACHE_SIZE - src_off == maximum possible bytes to read from cache
- // PARAM2 := count
- // Thus, taking the minimum of the two gives the number of bytes to read from cache,
- // in the range [ 1 .. FLASH_CACHE_SIZE-src_off ].
- // Else if dst_off is non-zero, then src_off is zero, representing that the
- // read started prior to the cache area. In this case:
- // PARAM1 := FLASH_CACHE_SIZE == full size of the cache
- // PARAM2 := count - dst_off == total bytes requested, minus the count of those already read
- // Because the original request is guaranteed to overlap the cache, the range for
- // PARAM2 is ensured to be [ 1 .. count-1 ].
- // Thus, taking the minimum of the two gives the number of bytes to read from cache,
- // in the range [ 1 .. FLASH_CACHE_SIZE ]
- // Else both src_off and dst_off are zero, representing that the read is starting
- // exactly aligned to the cache.
- // PARAM1 := FLASH_CACHE_SIZE
- // PARAM2 := count
- // Thus, taking the minimum of the two gives the number of bytes to read from cache,
- // in the range [ 1 .. FLASH_CACHE_SIZE ]
- //
- // Therefore, in all cases, there is assurance that cache_bytes
- // will be in the final range [1..FLASH_CACHE_SIZE].
- uint32_t cache_bytes = minof(FLASH_CACHE_SIZE-src_off, count - dst_off);
-
- // Use memcpy to read cached data into the buffer
- // If src_off is non-zero, then dst_off is zero, representing that the
- // read starts inside the cache. In this case:
- // PARAM1 := dst
- // PARAM2 := fc->cache_buf + src_off
- // PARAM3 := cache_bytes
- // Thus, all works as expected when starting in the midst of the cache.
- // Else if dst_off is non-zero, then src_off is zero, representing that the
- // read started prior to the cache. In this case:
- // PARAM1 := dst + dst_off == destination offset by number of bytes already read
- // PARAM2 := fc->cache_buf
- // PARAM3 := cache_bytes
- // Thus, all works as expected when starting prior to the cache.
- // Else both src_off and dst_off are zero, representing that the read is starting
- // exactly aligned to the cache.
- // PARAM1 := dst
- // PARAM2 := fc->cache_buf
- // PARAM3 := cache_bytes
- // Thus, all works as expected when starting exactly at the cache boundary
- //
- // Therefore, in all cases, there is assurance that cache_bytes
- // will be in the final range [1..FLASH_CACHE_SIZE].
- memcpy(dst + dst_off, fc->cache_buf + src_off, cache_bytes);
-
- // Read any final bytes from flash
- // As noted above, dst_off represents the count of bytes read prior to the cache
- // while cache_bytes represents the count of bytes read from the cache;
- // This code block is guaranteed to overlap the cache area by at least one byte.
- // Thus, copied will correspond to the total bytes already copied,
- // and is guaranteed to be in the range [ 1 .. count ].
- uint32_t copied = dst_off + cache_bytes;
-
- //
- if ( copied < count )
- {
- fc->read(dst + copied, addr + copied, count - copied);
- }
- }
- else
- {
- // not using the cache, so just forward to read from flash
- fc->read(dst, addr, count);
- }
-
- return (int) count;
-}
-#endif
+++ /dev/null
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach for Adafruit Industries
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifdef NRF52840_XXAA
-#ifndef FLASH_CACHE_H_
-#define FLASH_CACHE_H_
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#define FLASH_CACHE_SIZE 4096 // must be a erasable page size
-#define FLASH_CACHE_INVALID_ADDR 0xffffffff
-
-typedef struct
-{
- bool (*erase) (uint32_t addr);
- uint32_t (*program) (uint32_t dst, void const * src, uint32_t len);
- uint32_t (*read) (void* dst, uint32_t src, uint32_t len);
- bool (*verify) (uint32_t addr, void const * buf, uint32_t len);
-
- uint32_t cache_addr;
- uint8_t* cache_buf;
-} flash_cache_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int flash_cache_write (flash_cache_t* fc, uint32_t dst, void const *src, uint32_t count);
-void flash_cache_flush (flash_cache_t* fc);
-int flash_cache_read (flash_cache_t* fc, void* dst, uint32_t addr, uint32_t count);
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* FLASH_CACHE_H_ */
-#endif
+++ /dev/null
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach for Adafruit Industries
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifdef NRF52840_XXAA
-#include "flash_nrf5x.h"
-#include "flash_cache.h"
-#include "nrf_sdm.h"
-#include "nrf_soc.h"
-#include "delay.h"
-#include "rtos.h"
-
-
-#ifdef NRF52840_XXAA
- #define BOOTLOADER_ADDR 0xF4000
-#else
- #define BOOTLOADER_ADDR 0x74000
-#endif
-
-// defined in linker script
-extern uint32_t __flash_arduino_start[];
-//extern uint32_t __flash_arduino_end[];
-
-//--------------------------------------------------------------------+
-// MACRO TYPEDEF CONSTANT ENUM DECLARATION
-//--------------------------------------------------------------------+
-static SemaphoreHandle_t _sem = NULL;
-
-void flash_nrf5x_event_cb (uint32_t event)
-{
-// if (event != NRF_EVT_FLASH_OPERATION_SUCCESS) LOG_LV1("IFLASH", "Flash op Failed");
- if ( _sem ) xSemaphoreGive(_sem);
-}
-
-// Flash Abstraction Layer
-static bool fal_erase (uint32_t addr);
-static uint32_t fal_program (uint32_t dst, void const * src, uint32_t len);
-static uint32_t fal_read (void* dst, uint32_t src, uint32_t len);
-static bool fal_verify (uint32_t addr, void const * buf, uint32_t len);
-
-static uint8_t _cache_buffer[FLASH_CACHE_SIZE] __attribute__((aligned(4)));
-
-static flash_cache_t _cache =
-{
- .erase = fal_erase,
- .program = fal_program,
- .read = fal_read,
- .verify = fal_verify,
-
- .cache_addr = FLASH_CACHE_INVALID_ADDR,
- .cache_buf = _cache_buffer
-};
-
-//--------------------------------------------------------------------+
-// Application API
-//--------------------------------------------------------------------+
-void flash_nrf5x_flush (void)
-{
- flash_cache_flush(&_cache);
-}
-
-int flash_nrf5x_write (uint32_t dst, void const * src, uint32_t len)
-{
- // Softdevice region
- VERIFY(dst >= ((uint32_t) __flash_arduino_start), -1);
-
- // Bootloader region
- VERIFY(dst < BOOTLOADER_ADDR, -1);
-
- return flash_cache_write(&_cache, dst, src, len);
-}
-
-int flash_nrf5x_read (void* dst, uint32_t src, uint32_t len)
-{
- return flash_cache_read(&_cache, dst, src, len);
-}
-
-bool flash_nrf5x_erase(uint32_t addr)
-{
- return fal_erase(addr);
-}
-
-//--------------------------------------------------------------------+
-// HAL for caching
-//--------------------------------------------------------------------+
-static bool fal_erase (uint32_t addr)
-{
- // Init semaphore for first call
- if ( _sem == NULL )
- {
- _sem = xSemaphoreCreateCounting(10, 0);
- VERIFY(_sem);
- }
-
- // retry if busy
- uint32_t err;
- while ( NRF_ERROR_BUSY == (err = sd_flash_page_erase(addr / FLASH_NRF52_PAGE_SIZE)) )
- {
- delay(1);
- }
- VERIFY_STATUS(err, false);
-
- // wait for async event if SD is enabled
- uint8_t sd_en = 0;
- (void) sd_softdevice_is_enabled(&sd_en);
-
- if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);
-
- return true;
-}
-
-static uint32_t fal_program (uint32_t dst, void const * src, uint32_t len)
-{
- // wait for async event if SD is enabled
- uint8_t sd_en = 0;
- (void) sd_softdevice_is_enabled(&sd_en);
-
- uint32_t err;
-
- // Somehow S140 v6.1.1 assert an error when writing a whole page
- // https://devzone.nordicsemi.com/f/nordic-q-a/40088/sd_flash_write-cause-nrf_fault_id_sd_assert
- // Workaround: write half page at a time.
-#if NRF52832_XXAA
- while ( NRF_ERROR_BUSY == (err = sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/4)) )
- {
- delay(1);
- }
- VERIFY_STATUS(err, 0);
-
- if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);
-#else
- while ( NRF_ERROR_BUSY == (err = sd_flash_write((uint32_t*) dst, (uint32_t const *) src, len/8)) )
- {
- delay(1);
- }
- VERIFY_STATUS(err, 0);
- if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);
-
- while ( NRF_ERROR_BUSY == (err = sd_flash_write((uint32_t*) (dst+ len/2), (uint32_t const *) (src + len/2), len/8)) )
- {
- delay(1);
- }
- VERIFY_STATUS(err, 0);
- if ( sd_en ) xSemaphoreTake(_sem, portMAX_DELAY);
-#endif
-
- return len;
-}
-
-static uint32_t fal_read (void* dst, uint32_t src, uint32_t len)
-{
- memcpy(dst, (void*) src, len);
- return len;
-}
-
-static bool fal_verify (uint32_t addr, void const * buf, uint32_t len)
-{
- return 0 == memcmp((void*) addr, buf, len);
-}
-#endif
+++ /dev/null
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach for Adafruit Industries
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifdef NRF52840_XXAA
-#ifndef FLASH_NRF52_H_
-#define FLASH_NRF52_H_
-
-#include "common_inc.h"
-
-#define FLASH_NRF52_PAGE_SIZE 4096
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-void flash_nrf5x_flush (void);
-bool flash_nrf5x_erase(uint32_t addr);
-
-int flash_nrf5x_write (uint32_t dst, void const * src, uint32_t len);
-int flash_nrf5x_read (void* dst, uint32_t src, uint32_t len);
-
-//--------------------------------------------------------------------+
-// Write helper
-//--------------------------------------------------------------------+
-static inline int flash_nrf5x_write8 (uint32_t dst, uint8_t num)
-{
- return flash_nrf5x_write(dst, &num, sizeof(num));
-}
-
-static inline int flash_nrf5x_write16 (uint32_t dst, uint8_t num)
-{
- return flash_nrf5x_write(dst, &num, sizeof(num));
-}
-static inline int flash_nrf5x_write32 (uint32_t dst, uint8_t num)
-{
- return flash_nrf5x_write(dst, &num, sizeof(num));
-}
-
-//--------------------------------------------------------------------+
-// Read helper
-//--------------------------------------------------------------------+
-static inline uint8_t flash_nrf5x_read8 (uint32_t src)
-{
- uint8_t num;
- flash_nrf5x_read(&num, src, sizeof(num));
- return num;
-}
-
-static inline uint16_t flash_nrf5x_read16 (uint32_t src)
-{
- uint16_t num;
- flash_nrf5x_read(&num, src, sizeof(num));
- return num;
-}
-
-static inline uint16_t flash_nrf5x_read32 (uint32_t src)
-{
- uint32_t num;
- flash_nrf5x_read(&num, src, sizeof(num));
- return num;
-}
-
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* FLASH_NRF52_H_ */
-#endif