diff options
Diffstat (limited to 'watch-library/hardware')
-rwxr-xr-x | watch-library/hardware/linker/saml22j18.ld | 13 | ||||
-rw-r--r-- | watch-library/hardware/watch/watch.c | 4 | ||||
-rw-r--r-- | watch-library/hardware/watch/watch_private.c | 20 | ||||
-rw-r--r-- | watch-library/hardware/watch/watch_storage.c | 94 |
4 files changed, 126 insertions, 5 deletions
diff --git a/watch-library/hardware/linker/saml22j18.ld b/watch-library/hardware/linker/saml22j18.ld index a9801509..211e5346 100755 --- a/watch-library/hardware/linker/saml22j18.ld +++ b/watch-library/hardware/linker/saml22j18.ld @@ -32,11 +32,18 @@ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) SEARCH_DIR(.) -/* Memory Spaces Definitions */ +/* Memory Space Definitions: + * 0x00000000-0x00002000: Bootloader (length 0x2000 or 8192 bytes) + * 0x00002000-0x0003C000: Firmware (length 0x3A000 or 237568 bytes) + * 0x0003C000-0x00040000: EEPROM Emulation (length 0x2000 or 8192 bytes) + * 0x20000000-0x20008000: RAM (length 0x8000 or 32768 bytes) + */ MEMORY { - rom (rx) : ORIGIN = 0x2000, LENGTH = 0x00040000-0x2000 - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 + bootloader (rx) : ORIGIN = 0x0, LENGTH = 0x2000 + rom (rx) : ORIGIN = 0x2000, LENGTH = 0x00040000-0x2000-0x2000 + eeprom (r) : ORIGIN = 0x00040000-0x2000, LENGTH = 0x2000 + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 } /* The stack size used by the application. NOTE: you need to adjust according to your application. */ diff --git a/watch-library/hardware/watch/watch.c b/watch-library/hardware/watch/watch.c index 32bbccbb..b3dc4e8d 100644 --- a/watch-library/hardware/watch/watch.c +++ b/watch-library/hardware/watch/watch.c @@ -41,3 +41,7 @@ void SYSTEM_Handler(void) { bool watch_is_buzzer_or_led_enabled(void){ return hri_mclk_get_APBCMASK_TCC0_bit(MCLK); } + +bool watch_is_usb_enabled(void) { + return USB->DEVICE.CTRLA.bit.ENABLE; +} diff --git a/watch-library/hardware/watch/watch_private.c b/watch-library/hardware/watch/watch_private.c index 4b010d4a..cd607b8e 100644 --- a/watch-library/hardware/watch/watch_private.c +++ b/watch-library/hardware/watch/watch_private.c @@ -255,8 +255,15 @@ int _write(int file, char *ptr, int len) { return 0; } -// this method could be overridden to read stuff from the USB console? but no need rn. -int _read(void) { +static char buf[256] = {0}; + +int _read(int file, char *ptr, int len) { + (void)file; + int actual_length = strlen(buf); + if (actual_length) { + memcpy(ptr, buf, min(len, actual_length)); + return actual_length; + } return 0; } @@ -264,8 +271,17 @@ void USB_Handler(void) { tud_int_handler(0); } +static void cdc_task(void) { + if (tud_cdc_n_available(0)) { + tud_cdc_n_read(0, buf, sizeof(buf)); + } else { + memset(buf, 0, 256); + } +} + void TC0_Handler(void) { tud_task(); + cdc_task(); TC0->COUNT8.INTFLAG.reg |= TC_INTFLAG_OVF; } diff --git a/watch-library/hardware/watch/watch_storage.c b/watch-library/hardware/watch/watch_storage.c new file mode 100644 index 00000000..6c87be53 --- /dev/null +++ b/watch-library/hardware/watch/watch_storage.c @@ -0,0 +1,94 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "watch_storage.h" + +#define RWWEE_ADDR_START NVMCTRL_RWW_EEPROM_ADDR +#define RWWEE_ADDR_END (NVMCTRL_RWW_EEPROM_ADDR + NVMCTRL_PAGE_SIZE * NVMCTRL_RWWEE_PAGES) +#define NVM_MEMORY ((volatile uint16_t *)FLASH_ADDR) + +static bool _is_valid_address(uint32_t addr, uint32_t size) { + if ((addr < NVMCTRL_RWW_EEPROM_ADDR) || (addr > (NVMCTRL_RWW_EEPROM_ADDR + NVMCTRL_PAGE_SIZE * NVMCTRL_RWWEE_PAGES))) { + return false; + } + if ((addr + size > (NVMCTRL_RWW_EEPROM_ADDR + NVMCTRL_PAGE_SIZE * NVMCTRL_RWWEE_PAGES))) { + return false; + } + + return true; +} + +bool watch_storage_read(uint32_t row, uint32_t offset, uint8_t *buffer, uint32_t size) { + uint32_t address = RWWEE_ADDR_START + row * NVMCTRL_ROW_SIZE + offset; + if (!_is_valid_address(address, size)) return false; + + uint32_t nvm_address = address / 2; + uint32_t i; + uint16_t data; + + watch_storage_sync(); + + if (address % 2) { + data = NVM_MEMORY[nvm_address++]; + buffer[0] = data >> 8; + i = 1; + } else { + i = 0; + } + + while (i < size) { + data = NVM_MEMORY[nvm_address++]; + buffer[i] = (data & 0xFF); + if (i < (size - 1)) { + buffer[i + 1] = (data >> 8); + } + i += 2; + } + return true; +} + +bool watch_storage_write(uint32_t row, uint32_t offset, const uint8_t *buffer, uint32_t size) { + uint32_t address = RWWEE_ADDR_START + row * NVMCTRL_ROW_SIZE + offset; + if (!_is_valid_address(address, size)) return false; + + watch_storage_sync(); + + uint32_t nvm_address = address / 2; + uint16_t i, data; + + hri_nvmctrl_write_CTRLA_reg(NVMCTRL, NVMCTRL_CTRLA_CMD_PBC | NVMCTRL_CTRLA_CMDEX_KEY); + watch_storage_sync(); + + for (i = 0; i < size; i += 2) { + data = buffer[i]; + if (i < NVMCTRL_PAGE_SIZE - 1) { + data |= (buffer[i + 1] << 8); + } + NVM_MEMORY[nvm_address++] = data; + } + hri_nvmctrl_write_ADDR_reg(NVMCTRL, address / 2); + hri_nvmctrl_write_CTRLA_reg(NVMCTRL, NVMCTRL_CTRLA_CMD_RWWEEWP | NVMCTRL_CTRLA_CMDEX_KEY); + + return true; +} + +bool watch_storage_erase(uint32_t row) { + uint32_t address = RWWEE_ADDR_START + row * NVMCTRL_ROW_SIZE; + if (!_is_valid_address(address, NVMCTRL_ROW_SIZE)) return false; + + watch_storage_sync(); + hri_nvmctrl_write_ADDR_reg(NVMCTRL, address / 2); + hri_nvmctrl_write_CTRLA_reg(NVMCTRL, NVMCTRL_CTRLA_CMD_RWWEEER | NVMCTRL_CTRLA_CMDEX_KEY); + + return true; +} + +bool watch_storage_sync(void) { + while (!hri_nvmctrl_get_interrupt_READY_bit(NVMCTRL)) { + // wait for flash to become ready + } + + hri_nvmctrl_clear_STATUS_reg(NVMCTRL, NVMCTRL_STATUS_MASK); + + return true; +} |