From d4ebe64af05e2fa163bcea0dd699ae9c8934cc6f Mon Sep 17 00:00:00 2001 From: Joey Castillo Date: Fri, 6 May 2022 17:06:27 -0400 Subject: add support for a small filesystem on the watch --- apps/eeprom-emulation-upgrade/Makefile | 10 +++ apps/eeprom-emulation-upgrade/app.c | 62 ++++++++++++++++ apps/flash-test/Makefile | 13 ++++ apps/flash-test/app.c | 131 +++++++++++++++++++++++++++++++++ 4 files changed, 216 insertions(+) create mode 100755 apps/eeprom-emulation-upgrade/Makefile create mode 100644 apps/eeprom-emulation-upgrade/app.c create mode 100755 apps/flash-test/Makefile create mode 100644 apps/flash-test/app.c (limited to 'apps') diff --git a/apps/eeprom-emulation-upgrade/Makefile b/apps/eeprom-emulation-upgrade/Makefile new file mode 100755 index 00000000..5534c178 --- /dev/null +++ b/apps/eeprom-emulation-upgrade/Makefile @@ -0,0 +1,10 @@ +TOP = ../.. +include $(TOP)/make.mk + +INCLUDES += \ + -I./ + +SRCS += \ + ./app.c + +include $(TOP)/rules.mk diff --git a/apps/eeprom-emulation-upgrade/app.c b/apps/eeprom-emulation-upgrade/app.c new file mode 100644 index 00000000..edd73e44 --- /dev/null +++ b/apps/eeprom-emulation-upgrade/app.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include "watch.h" + +void app_init(void) { +} + +void app_wake_from_backup(void) { +} + +void app_setup(void) { + delay_ms(5000); + while (!(NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY)); + uint32_t user_row = (*((uint32_t *)NVMCTRL_AUX0_ADDRESS)); + uint8_t eeprom = (user_row >> NVMCTRL_FUSES_EEPROM_SIZE_Pos) & 7; + printf("User row read successfully: 0x%lx\n", user_row); + + if (eeprom != 1) { + user_row &= ~NVMCTRL_FUSES_EEPROM_SIZE_Msk; + user_row |= NVMCTRL_FUSES_EEPROM_SIZE(1); + if (NVMCTRL->STATUS.reg & NVMCTRL_STATUS_SB) { + printf("Secured bit was set; cannot perform upgrade.\n"); + return; + } + printf("EEPROM configuration was %d.\nApplying change...\n", eeprom); + + uint32_t temp = NVMCTRL->CTRLB.reg; // Backup settings + NVMCTRL->CTRLB.reg = temp | NVMCTRL_CTRLB_CACHEDIS; // Disable Cache + NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear error flags + NVMCTRL->ADDR.reg = NVMCTRL_AUX0_ADDRESS / 2; // Set address, command will be issued elsewhere + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_EAR | NVMCTRL_CTRLA_CMDEX_KEY; // Erase the user page + while (!(NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY)); // Wait for NVM command to complete + NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear error flags + NVMCTRL->ADDR.reg = NVMCTRL_AUX0_ADDRESS / 2; // Set address, command will be issued elsewhere + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_PBC | NVMCTRL_CTRLA_CMDEX_KEY; // Erase the page buffer before buffering new data + while (!(NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY)); // Wait for NVM command to complete + NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear error flags + NVMCTRL->ADDR.reg = NVMCTRL_AUX0_ADDRESS / 2; // Set address, command will be issued elsewhere + *((uint32_t *)NVMCTRL_AUX0_ADDRESS) = user_row; // write the new fuse values to the memory buffer + NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_WAP | NVMCTRL_CTRLA_CMDEX_KEY; // Write the user page + NVMCTRL->CTRLB.reg = temp; // Restore settings + + printf("Done! Resetting...\n"); + delay_ms(1000); + NVIC_SystemReset(); + } else { + printf("EEPROM configuration was %d (8192 bytes). Upgrade successful!\n", eeprom); + } + printf("%d %d\n", eeprom, NVMCTRL->PARAM.bit.RWWEEP); +} + +void app_prepare_for_standby(void) { +} + +void app_wake_from_standby(void) { +} + +bool app_loop(void) { + return true; +} diff --git a/apps/flash-test/Makefile b/apps/flash-test/Makefile new file mode 100755 index 00000000..1e552265 --- /dev/null +++ b/apps/flash-test/Makefile @@ -0,0 +1,13 @@ +TOP = ../.. +include $(TOP)/make.mk + +INCLUDES += \ + -I$(TOP)/littlefs/ \ + -I./ + +SRCS += \ + $(TOP)/littlefs/lfs.c \ + $(TOP)/littlefs/lfs_util.c \ + ./app.c + +include $(TOP)/rules.mk diff --git a/apps/flash-test/app.c b/apps/flash-test/app.c new file mode 100644 index 00000000..17b1d0aa --- /dev/null +++ b/apps/flash-test/app.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include "watch.h" +#include "lfs.h" +#include "hpl_flash.h" + +int lfs_storage_read(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size); +int lfs_storage_prog(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size); +int lfs_storage_erase(const struct lfs_config *cfg, lfs_block_t block); +int lfs_storage_sync(const struct lfs_config *cfg); + +int lfs_storage_read(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) { + (void) cfg; + return !watch_storage_read(block, off, (void *)buffer, size); +} + +int lfs_storage_prog(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) { + (void) cfg; + return !watch_storage_write(block, off, (void *)buffer, size); +} + +int lfs_storage_erase(const struct lfs_config *cfg, lfs_block_t block) { + (void) cfg; + return !watch_storage_erase(block); +} + +int lfs_storage_sync(const struct lfs_config *cfg) { + (void) cfg; + return !watch_storage_sync(); +} + +const struct lfs_config cfg = { + // block device operations + .read = lfs_storage_read, + .prog = lfs_storage_prog, + .erase = lfs_storage_erase, + .sync = lfs_storage_sync, + + // block device configuration + .read_size = 16, + .prog_size = NVMCTRL_PAGE_SIZE, + .block_size = NVMCTRL_ROW_SIZE, + .block_count = NVMCTRL_RWWEE_PAGES / 4, + .cache_size = NVMCTRL_PAGE_SIZE, + .lookahead_size = 16, + .block_cycles = 100, +}; + +lfs_t lfs; +lfs_file_t file; + +static int _traverse_df_cb(void *p, lfs_block_t block){ + (void) block; + uint32_t *nb = p; + *nb += 1; + return 0; +} + +static int get_free_space(void){ + int err; + + uint32_t free_blocks = 0; + err = lfs_fs_traverse(&lfs, _traverse_df_cb, &free_blocks); + if(err < 0){ + return err; + } + + uint32_t available = cfg.block_count * cfg.block_size - free_blocks * cfg.block_size; + + return available; +} + +static void cb_tick(void) { + watch_date_time date_time = watch_rtc_get_date_time(); + if (date_time.unit.second == 0) { + int err = lfs_mount(&lfs, &cfg); + if (err) { + printf("Mount failed: %d\n", err); + } + // read current count + uint32_t loop_count = 0; + lfs_file_open(&lfs, &file, "loop_count", LFS_O_RDWR | LFS_O_CREAT); + lfs_file_read(&lfs, &file, &loop_count, sizeof(loop_count)); + + // update loop count + loop_count += 1; + lfs_file_rewind(&lfs, &file); + lfs_file_write(&lfs, &file, &loop_count, sizeof(loop_count)); + + // remember the storage is not updated until the file is closed successfully + lfs_file_close(&lfs, &file); + + // release any resources we were using + lfs_unmount(&lfs); + + // print the boot count + printf("loop_count: %ld\n", loop_count); + printf("free space: %d\n", get_free_space()); + } +} + +void app_init(void) { +} + +void app_wake_from_backup(void) { +} + +void app_setup(void) { + // mount the filesystem + int err = lfs_mount(&lfs, &cfg); + + // reformat if we can't mount the filesystem + // this should only happen on the first boot + if (err) { + lfs_format(&lfs, &cfg); + lfs_mount(&lfs, &cfg); + } + watch_rtc_register_tick_callback(cb_tick); +} + +void app_prepare_for_standby(void) { +} + +void app_wake_from_standby(void) { +} + +bool app_loop(void) { + return true; +} -- cgit v1.2.3