From 2cabb5cb66ced1976e3cb85c6751bee532cf5385 Mon Sep 17 00:00:00 2001 From: Felipe Martinez Date: Tue, 17 Dec 2024 20:51:54 +0100 Subject: [PATCH] All the states --- include/bus_spi.h | 3 +- include/components/i2c/bma425.h | 3 +- include/components/i2c/cst816s.h | 3 +- include/components/i2c/hrs3300.h | 3 +- include/components/spi/spinorflash.h | 3 +- include/components/spi/st7789.h | 2 +- include/config.h | 2 +- include/cpu.h | 3 +- include/nrf52832.h | 5 +- include/peripherals/dcb.h | 2 +- include/peripherals/dwt.h | 2 +- include/peripherals/nvic.h | 2 +- include/peripherals/scb.h | 2 +- include/peripherals/scb_fp.h | 2 +- include/pinetime.h | 3 ++ include/pins.h | 4 +- include/state_store.h | 23 +++++++-- include/util.h | 30 ++++++++++++ src/bus_spi.c | 13 +++-- src/component/i2c/bma425.c | 4 +- src/component/i2c/cst816s.c | 19 +++++--- src/component/i2c/hrs3300.c | 8 +++- src/component/spi/spinorflash.c | 40 +++++++++------- src/component/spi/st7789.c | 14 +++--- src/cpu.c | 71 +++++++++++++++------------- src/main.c | 41 +++++++++------- src/memory.c | 2 +- src/nrf52832.c | 19 +++++--- src/peripherals/dcb.c | 10 ++-- src/peripherals/dwt.c | 10 ++-- src/peripherals/nrf52832/rtc.c | 20 ++++++-- src/peripherals/nrf52832/timer.c | 18 ++++++- src/peripherals/nvic.c | 20 ++++---- src/peripherals/scb.c | 19 +++++--- src/peripherals/scb_fp.c | 10 ++-- src/pinetime.c | 30 +++++++++--- src/pins.c | 8 +++- src/state_store.c | 2 +- 38 files changed, 322 insertions(+), 153 deletions(-) create mode 100644 include/util.h diff --git a/include/bus_spi.h b/include/bus_spi.h index 0a50b8a..f14826e 100644 --- a/include/bus_spi.h +++ b/include/bus_spi.h @@ -5,6 +5,7 @@ #include #include "pins.h" +#include "state_store.h" typedef struct bus_spi_t bus_spi_t; @@ -28,7 +29,7 @@ typedef struct spi_cs_changed_f cs_changed; } spi_slave_t; -bus_spi_t *bus_spi_new(pins_t *pins, uint8_t *ram, size_t ram_size); +bus_spi_t *bus_spi_new(pins_t *pins, uint8_t *ram, size_t ram_size, state_store_t *store); void bus_spi_reset(bus_spi_t *); void bus_spi_free(bus_spi_t *); void bus_spi_step(bus_spi_t *); diff --git a/include/components/i2c/bma425.h b/include/components/i2c/bma425.h index fdc69af..2325315 100644 --- a/include/components/i2c/bma425.h +++ b/include/components/i2c/bma425.h @@ -1,5 +1,6 @@ #pragma once #include "bus_i2c.h" +#include "state_store.h" -i2c_slave_t bma425_new(); +i2c_slave_t bma425_new(state_store_t *store); diff --git a/include/components/i2c/cst816s.h b/include/components/i2c/cst816s.h index 9c978e9..dca84ca 100644 --- a/include/components/i2c/cst816s.h +++ b/include/components/i2c/cst816s.h @@ -2,6 +2,7 @@ #include "bus_i2c.h" #include "pins.h" +#include "state_store.h" typedef enum { @@ -17,7 +18,7 @@ typedef enum typedef struct cst816s_t cst816s_t; -cst816s_t *cst816s_new(pins_t *pins, int irqPin); +cst816s_t *cst816s_new(pins_t *pins, state_store_t *store, int irqPin); i2c_slave_t cst816s_get_slave(cst816s_t *); void cst816s_do_touch(cst816s_t *, touch_gesture_t gesture, uint16_t x, uint16_t y); diff --git a/include/components/i2c/hrs3300.h b/include/components/i2c/hrs3300.h index d9e162b..d161333 100644 --- a/include/components/i2c/hrs3300.h +++ b/include/components/i2c/hrs3300.h @@ -1,10 +1,11 @@ #pragma once #include "bus_i2c.h" +#include "state_store.h" typedef struct hrs3300_t hrs3300_t; -hrs3300_t *hrs3300_new(); +hrs3300_t *hrs3300_new(state_store_t *store); i2c_slave_t hrs3300_get_slave(hrs3300_t *); void hrs3300_set_ch0(hrs3300_t *, uint32_t value); diff --git a/include/components/spi/spinorflash.h b/include/components/spi/spinorflash.h index 81ce796..b907893 100644 --- a/include/components/spi/spinorflash.h +++ b/include/components/spi/spinorflash.h @@ -1,12 +1,13 @@ #pragma once #include "bus_spi.h" +#include "state_store.h" #include typedef struct spinorflash_t spinorflash_t; -spinorflash_t *spinorflash_new(size_t size, size_t sector_size); +spinorflash_t *spinorflash_new(state_store_t *store, size_t size, size_t sector_size); spi_slave_t spinorflash_get_slave(spinorflash_t *); size_t spinorflash_get_write_count(spinorflash_t *); diff --git a/include/components/spi/st7789.h b/include/components/spi/st7789.h index 08556f3..4c49c46 100644 --- a/include/components/spi/st7789.h +++ b/include/components/spi/st7789.h @@ -8,7 +8,7 @@ typedef struct st7789_t st7789_t; #define DISPLAY_BUFFER_HEIGHT 320 #define BYTES_PER_PIXEL 2 // We assume 16bpp format -st7789_t* st7789_new(); +st7789_t* st7789_new(state_store_t *store); spi_slave_t st7789_get_slave(st7789_t *); void st7789_read_screen(st7789_t *, uint8_t *data, size_t width, size_t height); diff --git a/include/config.h b/include/config.h index 0cc4674..294e79e 100644 --- a/include/config.h +++ b/include/config.h @@ -35,7 +35,7 @@ #endif #ifndef ENABLE_MEASUREMENT -#define ENABLE_MEASUREMENT 0 +#define ENABLE_MEASUREMENT 1 #endif #ifndef ABORT_ON_INVALID_MEM_ACCESS diff --git a/include/cpu.h b/include/cpu.h index 88597fa..093844a 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -7,13 +7,14 @@ #include "arm.h" #include "memory.h" #include "runlog.h" +#include "state_store.h" typedef struct cpu_inst_t cpu_t; typedef void (*branch_cb_t)(cpu_t *, uint32_t old_pc, uint32_t new_pc, void *userdata); typedef void (*mem_watchpoint_cb_t)(cpu_t *, bool isWrite, uint32_t addr, size_t size, uint32_t value_old, uint32_t value_new, void *userdata); -cpu_t *cpu_new(const uint8_t *program, size_t program_size, memory_map_t *mem, size_t max_external_interrupts, size_t priority_bits); +cpu_t *cpu_new(const uint8_t *program, size_t program_size, memory_map_t *mem, state_store_t *store, size_t max_external_interrupts, size_t priority_bits); void cpu_free(cpu_t *); void cpu_reset(cpu_t *); // Returns the number of cycles that the CPU ran for diff --git a/include/nrf52832.h b/include/nrf52832.h index bc3af46..1e08e31 100644 --- a/include/nrf52832.h +++ b/include/nrf52832.h @@ -4,6 +4,7 @@ #include "bus_i2c.h" #include "bus_spi.h" #include "program.h" +#include "state_store.h" #include "peripherals/nrf52832/rtc.h" #define NRF52832_SRAM_SIZE 0x10000 @@ -84,7 +85,7 @@ enum typedef struct NRF52832_inst_t NRF52832_t; -NRF52832_t *nrf52832_new(const program_t *flash, size_t sram_size); +NRF52832_t *nrf52832_new(const program_t *flash, size_t sram_size, state_store_t *store); void nrf52832_reset(NRF52832_t *); int nrf52832_step(NRF52832_t *); @@ -99,3 +100,5 @@ size_t nrf52832_get_sram_size(NRF52832_t *); uint64_t nrf52832_get_cycle_counter(NRF52832_t *); bool nrf52832_flash_write(NRF52832_t *, uint32_t addr, uint8_t value); + +void nrf52832_reload_state(NRF52832_t *); diff --git a/include/peripherals/dcb.h b/include/peripherals/dcb.h index 7c6aa24..92d2c57 100644 --- a/include/peripherals/dcb.h +++ b/include/peripherals/dcb.h @@ -2,4 +2,4 @@ #include "peripherals/peripheral.h" -PERIPHERAL(DCB, dcb) +PERIPHERAL(DCB, dcb, state_store_t *store) diff --git a/include/peripherals/dwt.h b/include/peripherals/dwt.h index 2c23f59..6ccf972 100644 --- a/include/peripherals/dwt.h +++ b/include/peripherals/dwt.h @@ -4,6 +4,6 @@ #define DWT_CYCCNTENA 0 -PERIPHERAL(DWT, dwt) +PERIPHERAL(DWT, dwt, state_store_t *store) void dwt_increment_cycle(DWT_t *dwt, unsigned int count); diff --git a/include/peripherals/nvic.h b/include/peripherals/nvic.h index 66e2da4..f4d8867 100644 --- a/include/peripherals/nvic.h +++ b/include/peripherals/nvic.h @@ -4,4 +4,4 @@ #include "cpu.h" -PERIPHERAL(NVIC, nvic, cpu_t *cpu, size_t priority_bits) \ No newline at end of file +PERIPHERAL(NVIC, nvic, cpu_t *cpu, state_store_t *store, size_t priority_bits) \ No newline at end of file diff --git a/include/peripherals/scb.h b/include/peripherals/scb.h index 92355aa..462dcbf 100644 --- a/include/peripherals/scb.h +++ b/include/peripherals/scb.h @@ -27,7 +27,7 @@ typedef union static_assert(sizeof(SCB_CCR_t) == 4, "SCB_CCR_t size is incorrect"); -PERIPHERAL(SCB, scb, cpu_t *cpu) +PERIPHERAL(SCB, scb, cpu_t *cpu, state_store_t *store) uint32_t scb_get_prigroup(SCB_t *); SCB_CCR_t scb_get_ccr(SCB_t *); diff --git a/include/peripherals/scb_fp.h b/include/peripherals/scb_fp.h index bd39413..9cf9159 100644 --- a/include/peripherals/scb_fp.h +++ b/include/peripherals/scb_fp.h @@ -2,7 +2,7 @@ #include "arm.h" -PERIPHERAL(SCB_FP, scb_fp) +PERIPHERAL(SCB_FP, scb_fp, state_store_t *store) FPCCR_t scb_fp_get_fpccr(SCB_FP_t *scb_fp); uint32_t scb_fp_get_fpscr(SCB_FP_t *scb_fp); diff --git a/include/pinetime.h b/include/pinetime.h index e9ec6b6..e2ce92e 100644 --- a/include/pinetime.h +++ b/include/pinetime.h @@ -31,3 +31,6 @@ st7789_t *pinetime_get_st7789(pinetime_t *); cst816s_t *pinetime_get_cst816s(pinetime_t *); hrs3300_t *pinetime_get_hrs3300(pinetime_t *); spinorflash_t *pinetime_get_spinorflash(pinetime_t *pt); + +uint8_t *pinetime_save_state(pinetime_t *pt, size_t *size); +bool pinetime_load_state(pinetime_t *pt, uint8_t *data, size_t size); diff --git a/include/pins.h b/include/pins.h index 3fd9a38..d3ab5ba 100644 --- a/include/pins.h +++ b/include/pins.h @@ -2,6 +2,8 @@ #define PINS_COUNT 32 +#include "state_store.h" + #include #include @@ -34,7 +36,7 @@ typedef enum #define pins_set_input(pins, pin) pins_set_dir(pins, pin, pins_get_dir(pins, pin) & ~PIN_OUTPUT) #define pins_set_output(pins, pin) pins_set_dir(pins, pin, pins_get_dir(pins, pin) | PIN_OUTPUT) -pins_t *pins_new(void); +pins_t *pins_new(state_store_t *store); void pins_free(pins_t *); void pins_reset(pins_t *); diff --git a/include/state_store.h b/include/state_store.h index b9c7dde..a920d44 100644 --- a/include/state_store.h +++ b/include/state_store.h @@ -11,11 +11,26 @@ typedef uint16_t state_key_t; enum { - STATE_KEY_POWER = 1, + STATE_KEY_CPU = 1, + STATE_KEY_MEMORY, + STATE_KEY_PINS, + STATE_KEY_BUS_SPI, + STATE_KEY_DCB, + STATE_KEY_DWT, + STATE_KEY_NVIC, + STATE_KEY_SCB_FP, + STATE_KEY_SCB, + STATE_KEY_BMA425, + STATE_KEY_CST816S, + STATE_KEY_HRS3300, + STATE_KEY_SPINORFLASH, + STATE_KEY_ST7789, + + STATE_KEY_POWER = 0x0100, STATE_KEY_CLOCK, - STATE_KEY_SPIM0 = 0x0100, - STATE_KEY_TWIM0 = 0x0200, + STATE_KEY_SPIM0 = 0x0200, + STATE_KEY_TWIM0 = 0x0300, }; state_store_t *state_store_new(); @@ -25,4 +40,4 @@ void state_store_register(state_store_t *store, state_key_t key, void *data, siz void state_store_freeze(state_store_t *); uint8_t *state_store_save(state_store_t *, size_t *size); -bool state_store_load(state_store_t *, uint8_t *data, size_t size); +bool state_store_load(state_store_t *, const uint8_t *data, size_t size); diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..0c30a22 --- /dev/null +++ b/include/util.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +static inline uint8_t *read_file_u8(const char *path, size_t *size) +{ + FILE *f = fopen(path, "rb"); + if (f == NULL) + { + fprintf(stderr, "Failed to open %s\n", path); + return NULL; + } + + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + uint8_t *data = malloc(fsize); + if (fread(data, 1, fsize, f) != (size_t)fsize) + { + fprintf(stderr, "Failed to read %s\n", path); + return NULL; + } + fclose(f); + + *size = fsize; + return data; +} diff --git a/src/bus_spi.c b/src/bus_spi.c index 80b0632..d3543e5 100644 --- a/src/bus_spi.c +++ b/src/bus_spi.c @@ -15,10 +15,14 @@ struct bus_spi_t { + struct state + { + bool was_selected[MAX_SLAVES]; + }; + uint8_t *ram; size_t ram_size; - bool was_selected[MAX_SLAVES]; spi_slave_t *slaves[MAX_SLAVES]; uint8_t slave_pin[MAX_SLAVES]; size_t slave_count; @@ -26,12 +30,15 @@ struct bus_spi_t pins_t *pins; }; -bus_spi_t *bus_spi_new(pins_t *pins, uint8_t *ram, size_t ram_size) +bus_spi_t *bus_spi_new(pins_t *pins, uint8_t *ram, size_t ram_size, state_store_t *store) { - bus_spi_t *spi = (bus_spi_t *)calloc(1, sizeof(bus_spi_t)); + bus_spi_t *spi = calloc(1, sizeof(bus_spi_t)); spi->pins = pins; spi->ram = ram; spi->ram_size = ram_size; + + state_store_register(store, STATE_KEY_BUS_SPI, spi, sizeof(struct state)); + return spi; } diff --git a/src/component/i2c/bma425.c b/src/component/i2c/bma425.c index bfe7883..b8cca4c 100644 --- a/src/component/i2c/bma425.c +++ b/src/component/i2c/bma425.c @@ -238,10 +238,12 @@ size_t bma425_read(uint8_t *data, size_t data_size, void *userdata) return data_size; } -i2c_slave_t bma425_new() +i2c_slave_t bma425_new(state_store_t *store) { bma425_t *bma425 = malloc(sizeof(bma425_t)); + state_store_register(store, STATE_KEY_BMA425, bma425, sizeof(bma425_t)); + return (i2c_slave_t){ .userdata = bma425, .write = bma425_write, diff --git a/src/component/i2c/cst816s.c b/src/component/i2c/cst816s.c index a5e617e..95a2ff0 100644 --- a/src/component/i2c/cst816s.c +++ b/src/component/i2c/cst816s.c @@ -25,14 +25,17 @@ typedef struct __attribute__((packed)) struct cst816s_t { - pins_t *pins; - int irqPin; + struct state + { + uint8_t next_read[MAX_READ_SIZE]; + size_t next_read_size; - uint8_t next_read[MAX_READ_SIZE]; - size_t next_read_size; + touchdata_t touchdata; + bool has_touch; + }; - touchdata_t touchdata; - bool has_touch; + pins_t *pins; + int irqPin; }; void cst816s_reset(void *userdata) @@ -114,12 +117,14 @@ size_t cst816s_read(uint8_t *data, size_t data_size, void *userdata) return data_size; } -cst816s_t *cst816s_new(pins_t *pins, int irqPin) +cst816s_t *cst816s_new(pins_t *pins, state_store_t *store, int irqPin) { cst816s_t *cst816s = calloc(1, sizeof(cst816s_t)); cst816s->pins = pins; cst816s->irqPin = irqPin; + state_store_register(store, STATE_KEY_CST816S, cst816s, sizeof(struct state)); + return cst816s; } diff --git a/src/component/i2c/hrs3300.c b/src/component/i2c/hrs3300.c index ae47c4c..60732e6 100644 --- a/src/component/i2c/hrs3300.c +++ b/src/component/i2c/hrs3300.c @@ -102,9 +102,13 @@ size_t hrs3300_read(uint8_t *data, size_t data_size, void *userdata) return data_size; } -hrs3300_t *hrs3300_new() +hrs3300_t *hrs3300_new(state_store_t *store) { - return calloc(1, sizeof(hrs3300_t)); + hrs3300_t *hrs = calloc(1, sizeof(hrs3300_t)); + + state_store_register(store, STATE_KEY_HRS3300, hrs, sizeof(hrs3300_t)); + + return hrs; } i2c_slave_t hrs3300_get_slave(hrs3300_t *hrs3300) diff --git a/src/component/spi/spinorflash.c b/src/component/spi/spinorflash.c index 266ef49..63807a2 100644 --- a/src/component/spi/spinorflash.c +++ b/src/component/spi/spinorflash.c @@ -68,31 +68,33 @@ typedef union struct spinorflash_t { - uint8_t *data; - size_t size, sector_size; + struct state + { + size_t write_count; - bool should_free_data; + statusreg_t statusreg; + securityreg_t securityreg; - size_t write_count; + uint8_t last_write[MAX_COMMAND_SIZE]; + size_t last_write_size; + bool handled_command; - statusreg_t statusreg; - securityreg_t securityreg; + bool is_reading_data; + uint32_t data_read_address; - uint8_t last_write[MAX_COMMAND_SIZE]; - size_t last_write_size; - bool handled_command; + uint32_t pp_address; + }; - bool is_reading_data; - uint32_t data_read_address; + uint8_t *data; + size_t size, sector_size; + bool should_free_data; circular_buffer_t *out_buffer; - - uint32_t pp_address; }; void spinorflash_write_internal(uint8_t byte, void *userdata) { - spinorflash_t *flash = (spinorflash_t *)userdata; + spinorflash_t *flash = userdata; if (flash->statusreg.WIP) { @@ -227,7 +229,7 @@ uint8_t spinorflash_read_internal(void *userdata) void spinorflash_cs_changed(bool selected, void *userdata) { - spinorflash_t *flash = (spinorflash_t *)userdata; + spinorflash_t *flash = userdata; if (!selected) { @@ -255,7 +257,7 @@ void spinorflash_cs_changed(bool selected, void *userdata) void spinorflash_reset(void *userdata) { - spinorflash_t *flash = (spinorflash_t *)userdata; + spinorflash_t *flash = userdata; flash->statusreg.value = 0; flash->securityreg.value = 0; @@ -265,14 +267,16 @@ void spinorflash_reset(void *userdata) circular_buffer_clear(flash->out_buffer); } -spinorflash_t *spinorflash_new(size_t size, size_t sector_size) +spinorflash_t *spinorflash_new(state_store_t *store, size_t size, size_t sector_size) { spinorflash_t *flash = malloc(sizeof(spinorflash_t)); flash->data = malloc(size); flash->should_free_data = true; flash->size = size; flash->sector_size = sector_size; - flash->out_buffer = circular_buffer_new(READ_QUEUE_SIZE); + flash->out_buffer = circular_buffer_new(READ_QUEUE_SIZE); // TODO: Store this in state + + state_store_register(store, STATE_KEY_SPINORFLASH, flash, sizeof(struct state)); return flash; } diff --git a/src/component/spi/st7789.c b/src/component/spi/st7789.c index b12a750..834f5d7 100644 --- a/src/component/spi/st7789.c +++ b/src/component/spi/st7789.c @@ -70,6 +70,8 @@ typedef union uint16_t value; } value16_t; +#define SCREEN_BUFFER_SIZE (4 * 1024) + struct st7789_t { bool on; @@ -88,7 +90,7 @@ struct st7789_t uint8_t data_buffer[2048]; uint8_t screen[DISPLAY_BUFFER_WIDTH * DISPLAY_BUFFER_HEIGHT * BYTES_PER_PIXEL]; - uint8_t *screen_buffer; + uint8_t screen_buffer[SCREEN_BUFFER_SIZE]; size_t screen_buffer_ptr; }; @@ -151,8 +153,6 @@ void st7789_write(uint8_t byte, void *userdata) memcpy(&st7789->screen[start], &st7789->screen_buffer[row * stride], stride); } - - free(st7789->screen_buffer); } break; } @@ -271,10 +271,9 @@ void st7789_write(uint8_t byte, void *userdata) uint16_t height = st7789->yend.value - st7789->ystart.value + 1; size_t bytes = width * height * BYTES_PER_PIXEL; - assert(bytes > 0); + assert(bytes > 0 && bytes < SCREEN_BUFFER_SIZE); st7789->expecting_data = bytes; - st7789->screen_buffer = malloc(bytes); st7789->screen_buffer_ptr = 0; st7789->write_counter++; break; @@ -303,9 +302,12 @@ void st7789_cs_changed(bool selected, void *userdata) { } -st7789_t *st7789_new() +st7789_t *st7789_new(state_store_t *store) { st7789_t *st7789 = malloc(sizeof(st7789_t)); + + state_store_register(store, STATE_KEY_ST7789, st7789, sizeof(st7789_t)); + return st7789; } diff --git a/src/cpu.c b/src/cpu.c index 00fc5d3..4d76fd3 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -183,10 +183,39 @@ arm_reg check_exc_registers[] = { struct cpu_inst_t { + struct state + { + bool is_locked_up; + + uint32_t core_regs[ARM_REG_ENDING - 1]; + uint32_t sp_main, sp_process; + vreg_t d[32]; + + uint32_t faultmask, basepri, primask; + CONTROL_t control; + xPSR_t xpsr; + + itstate_t itstate; + bool must_advance_it; + + arm_mode mode; + + size_t exception_count, pending_exception_count; + exception_t exceptions[ARM_EXC_EXTERNAL_END + 1]; + arm_exception running_exceptions[MAX_EXECUTING_EXCEPTIONS]; // Stack + uint32_t pending_exceptions[ARM_EXCEPTION_COUNT / 32]; // Bitfield + size_t running_exception_count; + int execution_priority; + + size_t sleep_fuel; + + bool branched; + }; + jmp_buf *fault_jmp_buf; bool has_fault_jmp; - bool is_locked_up; + state_store_t *state_store; #if ENABLE_RUNLOG runlog_t *runlog; @@ -203,19 +232,6 @@ struct cpu_inst_t void *userdata; } memory_watchpoint; - uint32_t core_regs[ARM_REG_ENDING - 1]; - uint32_t sp_main, sp_process; - vreg_t d[32]; - - uint32_t faultmask, basepri, primask; - CONTROL_t control; - xPSR_t xpsr; - - itstate_t itstate; - bool must_advance_it; - - arm_mode mode; - csh cs; const uint8_t *program; size_t program_size; @@ -225,22 +241,11 @@ struct cpu_inst_t cs_insn *last_external_inst; - size_t exception_count, pending_exception_count; - exception_t exceptions[ARM_EXC_EXTERNAL_END + 1]; - arm_exception running_exceptions[MAX_EXECUTING_EXCEPTIONS]; // Stack - uint32_t pending_exceptions[ARM_EXCEPTION_COUNT / 32]; // Bitfield - size_t running_exception_count; - int execution_priority; - - size_t sleep_fuel; - #if ASSERT_EXCEPTION_REGISTERS uint32_t exception_regs[sizeof(check_exc_registers) / sizeof(arm_reg)][MAX_EXECUTING_EXCEPTIONS]; size_t exception_regs_count; #endif - bool branched; - memory_map_t *mem; DWT_t *dwt; @@ -1202,11 +1207,11 @@ static void do_store(cpu_t *cpu, cs_arm *detail, byte_size_t size, bool dual) static void add_arm_memregs(cpu_t *cpu, size_t priority_bits) { - NEW_PERIPH(cpu, DWT, dwt, dwt, x(E000, 1000), 0x1000); - NEW_PERIPH(cpu, SCB, scb, scb, x(E000, ED00), 0x90, cpu); - NEW_PERIPH(cpu, DCB, dcb, dcb, x(E000, EDF0), 0x110); - NEW_PERIPH(cpu, SCB_FP, scb_fp, scb_fp, x(E000, EF00), 0x90); - NEW_PERIPH(cpu, NVIC, nvic, nvic, x(E000, E100), 0xBFF, cpu, priority_bits); + NEW_PERIPH(cpu, DWT, dwt, dwt, x(E000, 1000), 0x1000, cpu->state_store); + NEW_PERIPH(cpu, SCB, scb, scb, x(E000, ED00), 0x90, cpu, cpu->state_store); + NEW_PERIPH(cpu, DCB, dcb, dcb, x(E000, EDF0), 0x110, cpu->state_store); + NEW_PERIPH(cpu, SCB_FP, scb_fp, scb_fp, x(E000, EF00), 0x90, cpu->state_store); + NEW_PERIPH(cpu, NVIC, nvic, nvic, x(E000, E100), 0xBFF, cpu, cpu->state_store, priority_bits); } static void do_stmdb(cpu_t *cpu, arm_reg base_reg, bool writeback, cs_arm_op *reg_operands, uint8_t reg_count) @@ -1259,15 +1264,17 @@ static inline void decode_arithmetic(cpu_t *cpu, cs_insn *i, uint32_t *op0_val, } } -cpu_t *cpu_new(const uint8_t *program, size_t program_size, memory_map_t *mem, size_t max_external_interrupts, size_t priority_bits) +cpu_t *cpu_new(const uint8_t *program, size_t program_size, memory_map_t *mem, state_store_t *store, size_t max_external_interrupts, size_t priority_bits) { cpu_t *cpu = calloc(1, sizeof(cpu_t)); - + cpu->state_store = store; cpu->program = program; cpu->program_size = program_size; cpu->mem = mem; cpu->exception_count = 16 + max_external_interrupts; + state_store_register(store, STATE_KEY_CPU, cpu, sizeof(struct state)); + add_arm_memregs(cpu, priority_bits); if (cs_open(CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_MCLASS, &cpu->cs) != CS_ERR_OK) diff --git a/src/main.c b/src/main.c index 7c74462..9755c9f 100644 --- a/src/main.c +++ b/src/main.c @@ -11,6 +11,7 @@ #include "pcap.h" #include "program.h" #include "segger_rtt.h" +#include "util.h" #include "peripherals/nrf52832/radio.h" void commander_output(const char *msg, void *userdata) @@ -72,24 +73,10 @@ int main(int argc, char **argv) return -1; } - FILE *f = fopen(program_path, "rb"); - if (f == NULL) - { - fprintf(stderr, "Failed to open %s\n", program_path); + size_t fsize; + uint8_t *program_data = read_file_u8(program_path, &fsize); + if (program_data == NULL) return -1; - } - - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - - uint8_t *program_data = malloc(fsize); - if (fread(program_data, 1, fsize, f) != (size_t)fsize) - { - fprintf(stderr, "Failed to read %s\n", program_path); - return -1; - } - fclose(f); program_t *program = program_new(big_ram ? 0x800000 : NRF52832_FLASH_SIZE); if (!program_load_elf(program, 0, program_data, fsize)) @@ -137,6 +124,14 @@ int main(int argc, char **argv) pcap_t *pcap = pcap_create("bluetooth.pcap"); radio_set_pcap(nrf52832_get_peripheral(nrf, INSTANCE_RADIO), pcap); + size_t state_size; + uint8_t *state = read_file_u8("state.bin", &state_size); + if (state) + { + pinetime_load_state(pt, state, state_size); + free(state); + } + free(program); if (run_gdb) @@ -166,6 +161,18 @@ int main(int argc, char **argv) if (inst_counter++ % 60 == 0) time_increment_fake_microseconds(1); + if (inst_counter == 100000000) + { + printf("saving state\n"); + + size_t size; + uint8_t *state = pinetime_save_state(pt, &size); + + FILE *f = fopen("state.bin", "wb"); + fwrite(state, 1, size, f); + fclose(f); + } + #if ENABLE_SEGGER_RTT if (found_rtt || rtt_counter < 1000000) { diff --git a/src/memory.c b/src/memory.c index 57c8f91..a5e6e08 100644 --- a/src/memory.c +++ b/src/memory.c @@ -259,7 +259,7 @@ void memory_map_do_operation(memory_map_t *map, uint32_t addr, memreg_op_t op, u } } - if (handled) + if (handled || op == OP_LOAD_DATA) // OP_LOAD_DATA is optional return; switch (result) diff --git a/src/nrf52832.c b/src/nrf52832.c index 1cfde6e..d8ba9cd 100644 --- a/src/nrf52832.c +++ b/src/nrf52832.c @@ -85,21 +85,23 @@ struct NRF52832_inst_t memory_map_add_region((chip)->mem, memreg_new_operation(0x40000000 | (((idn) & 0xFF) << 12), 0x1000, name##_operation, (chip)->field)); \ } while (0) -NRF52832_t *nrf52832_new(const program_t *flash, size_t sram_size) +NRF52832_t *nrf52832_new(const program_t *flash, size_t sram_size, state_store_t *store) { uint8_t *sram = malloc(sram_size); memset(sram, SRAM_FILL_BYTE, sram_size); NRF52832_t *chip = malloc(sizeof(NRF52832_t)); - chip->state_store = state_store_new(); + chip->state_store = store; chip->sram = sram; chip->sram_size = sram_size; - chip->pins = pins_new(); - chip->bus_spi = bus_spi_new(chip->pins, sram, sram_size); + chip->pins = pins_new(store); + chip->bus_spi = bus_spi_new(chip->pins, sram, sram_size, store); chip->bus_i2c = i2c_new(sram, sram_size); chip->ticker = ticker_new(NRF52832_HFCLK_FREQUENCY / NRF52832_LFCLK_FREQUENCY); chip->dma = dma_new(ARM_SRAM_START, sram, sram_size); + state_store_register(store, STATE_KEY_MEMORY, sram, sram_size); + chip->flash_size = program_size(flash); chip->flash = malloc(chip->flash_size); program_write_to(flash, chip->flash, chip->flash_size); @@ -120,7 +122,7 @@ NRF52832_t *nrf52832_new(const program_t *flash, size_t sram_size) .i2c = chip->bus_i2c, .spi = chip->bus_spi, .dma = chip->dma, - .state_store = chip->state_store, + .state_store = store, }; NEW_NRF52_PERIPH(chip, NVMC, nvmc, nvmc, INSTANCE_NVMC, chip->flash, program_size(flash)); @@ -159,7 +161,7 @@ NRF52832_t *nrf52832_new(const program_t *flash, size_t sram_size) memory_map_add_region(chip->mem, memreg_new_simple_copy(x(1000, 0000), dumps_ficr_bin, dumps_ficr_bin_len)); memory_map_add_region(chip->mem, memreg_new_simple_copy(x(1000, 1000), dumps_uicr_bin, dumps_uicr_bin_len)); - chip->cpu = cpu_new(chip->flash, program_size(flash), chip->mem, NRF52832_MAX_EXTERNAL_INTERRUPTS, NRF52832_PRIORITY_BITS); + chip->cpu = cpu_new(chip->flash, program_size(flash), chip->mem, store, NRF52832_MAX_EXTERNAL_INTERRUPTS, NRF52832_PRIORITY_BITS); return chip; } @@ -254,3 +256,8 @@ uint64_t nrf52832_get_cycle_counter(NRF52832_t *nrf) { return nrf->cycle_counter; } + +void nrf52832_reload_state(NRF52832_t *nrf) +{ + memory_map_do_operation(nrf->mem, 0, OP_LOAD_DATA, NULL); +} diff --git a/src/peripherals/dcb.c b/src/peripherals/dcb.c index 3627a3b..cadbcd0 100644 --- a/src/peripherals/dcb.c +++ b/src/peripherals/dcb.c @@ -12,7 +12,7 @@ struct DCB_inst_t OPERATION(dcb) { - DCB_t *dcb = (DCB_t *)userdata; + DCB_t *dcb = userdata; if (op == OP_RESET) { @@ -37,7 +37,11 @@ OPERATION(dcb) return MEMREG_RESULT_UNHANDLED; } -DCB_t *dcb_new() +DCB_t *dcb_new(state_store_t *store) { - return malloc(sizeof(DCB_t)); + DCB_t *dcb = malloc(sizeof(DCB_t)); + + state_store_register(store, STATE_KEY_DCB, dcb, sizeof(DCB_t)); + + return dcb; } diff --git a/src/peripherals/dwt.c b/src/peripherals/dwt.c index f37fb8e..c0c19ef 100644 --- a/src/peripherals/dwt.c +++ b/src/peripherals/dwt.c @@ -12,7 +12,7 @@ struct DWT_inst_t OPERATION(dwt) { - DWT_t *dwt = (DWT_t *)userdata; + DWT_t *dwt = userdata; if (op == OP_RESET) { @@ -35,9 +35,13 @@ OPERATION(dwt) return MEMREG_RESULT_UNHANDLED; } -DWT_t *dwt_new() +DWT_t *dwt_new(state_store_t *store) { - return malloc(sizeof(DWT_t)); + DWT_t *dwt = malloc(sizeof(DWT_t)); + + state_store_register(store, STATE_KEY_DWT, dwt, sizeof(DWT_t)); + + return dwt; } void dwt_increment_cycle(DWT_t *dwt, unsigned int count) diff --git a/src/peripherals/nrf52832/rtc.c b/src/peripherals/nrf52832/rtc.c index f091b0c..c312b65 100644 --- a/src/peripherals/nrf52832/rtc.c +++ b/src/peripherals/nrf52832/rtc.c @@ -44,7 +44,7 @@ struct RTC_inst_t size_t cc_num; }; -void rtc_tick(void *userdata) +static void rtc_tick(void *userdata) { RTC_t *rtc = userdata; @@ -66,15 +66,29 @@ void rtc_tick(void *userdata) } } +static inline void rtc_add_ticker(RTC_t *rtc) +{ + ticker_add(rtc->ticker, CLOCK_LFCLK, rtc_tick, rtc, rtc->prescaler + 1, true); +} + OPERATION(rtc) { - state_t *rtc = userdata; + RTC_t *rtc = userdata; if (op == OP_RESET) { memset(rtc, 0, sizeof(state_t)); return MEMREG_RESULT_OK; } + if (op == OP_LOAD_DATA) + { + ticker_remove(rtc->ticker, CLOCK_LFCLK, rtc_tick); + + if (rtc->running) + rtc_add_ticker(rtc); + + return MEMREG_RESULT_OK; + } OP_ASSERT_SIZE(op, WORD); @@ -140,7 +154,7 @@ PPI_TASK_HANDLER(rtc_task_handler) case TASK_ID(RTC_TASKS_START): if (!rtc->running) { - ticker_add(rtc->ticker, CLOCK_LFCLK, rtc_tick, rtc, rtc->prescaler + 1, true); + rtc_add_ticker(rtc); rtc->running = true; } diff --git a/src/peripherals/nrf52832/timer.c b/src/peripherals/nrf52832/timer.c index 4bdac8a..51db257 100644 --- a/src/peripherals/nrf52832/timer.c +++ b/src/peripherals/nrf52832/timer.c @@ -93,9 +93,14 @@ void timer_tick(void *userdata) timer_increase_counter(timer); } +void timer_add_timer(TIMER_t *timer) +{ + ticker_add(timer->ticker, CLOCK_HFCLK, timer_tick, timer, TICK_INTERVAL, true); +} + OPERATION(timer) { - TIMER_t *timer = (TIMER_t *)userdata; + TIMER_t *timer = userdata; if (op == OP_RESET) { @@ -107,6 +112,15 @@ OPERATION(timer) }; return MEMREG_RESULT_OK; } + if (op == OP_LOAD_DATA) + { + ticker_remove(timer->ticker, CLOCK_HFCLK, timer_tick); + + if (timer->running) + timer_add_timer(timer); + + return MEMREG_RESULT_OK; + } OP_ASSERT_SIZE(op, WORD); @@ -175,7 +189,7 @@ PPI_TASK_HANDLER(timer_task_handler) if (timer->mode == MODE_TIMER) { if (!timer->running) - ticker_add(timer->ticker, CLOCK_HFCLK, timer_tick, timer, TICK_INTERVAL, true); + timer_add_timer(timer); timer->running = true; } diff --git a/src/peripherals/nvic.c b/src/peripherals/nvic.c index 4e4bded..083bb74 100644 --- a/src/peripherals/nvic.c +++ b/src/peripherals/nvic.c @@ -8,23 +8,19 @@ #include #include -typedef struct -{ - bool enabled; - uint32_t priority; -} interrupt_t; - -#define INTERRUPT_COUNT 512 - struct NVIC_inst_t { + struct state + { + uint32_t priority_mask; + }; + cpu_t *cpu; - uint32_t priority_mask; }; OPERATION(nvic) { - NVIC_t *nvic = (NVIC_t *)userdata; + NVIC_t *nvic = userdata; if (op == OP_RESET) { @@ -144,7 +140,7 @@ OPERATION(nvic) return MEMREG_RESULT_UNHANDLED; } -NVIC_t *nvic_new(cpu_t *cpu, size_t priority_bits) +NVIC_t *nvic_new(cpu_t *cpu, state_store_t *store, size_t priority_bits) { assert(priority_bits >= 3 && priority_bits <= 8); @@ -152,5 +148,7 @@ NVIC_t *nvic_new(cpu_t *cpu, size_t priority_bits) nvic->cpu = cpu; nvic->priority_mask = (0xFF << (8 - priority_bits)) & 0xFF; + state_store_register(store, STATE_KEY_NVIC, nvic, sizeof(struct state)); + return nvic; } diff --git a/src/peripherals/scb.c b/src/peripherals/scb.c index 011c943..8d89b7f 100644 --- a/src/peripherals/scb.c +++ b/src/peripherals/scb.c @@ -9,18 +9,21 @@ struct SCB_inst_t { - uint32_t cpacr; - uint32_t prigroup; - uint32_t scr; - SCB_CCR_t ccr; - uint32_t vtor; + struct state + { + uint32_t cpacr; + uint32_t prigroup; + uint32_t scr; + SCB_CCR_t ccr; + uint32_t vtor; + }; cpu_t *cpu; }; OPERATION(scb) { - SCB_t *scb = (SCB_t *)userdata; + SCB_t *scb = userdata; if (op == OP_RESET) { @@ -135,11 +138,13 @@ OPERATION(scb) return MEMREG_RESULT_UNHANDLED; } -SCB_t *scb_new(cpu_t *cpu) +SCB_t *scb_new(cpu_t *cpu, state_store_t *store) { SCB_t *scb = malloc(sizeof(SCB_t)); scb->cpu = cpu; + state_store_register(store, STATE_KEY_SCB, scb, sizeof(struct state)); + return scb; } diff --git a/src/peripherals/scb_fp.c b/src/peripherals/scb_fp.c index 463af0a..d01cce6 100644 --- a/src/peripherals/scb_fp.c +++ b/src/peripherals/scb_fp.c @@ -15,7 +15,7 @@ struct SCB_FP_inst_t OPERATION(scb_fp) { - SCB_FP_t *scb_fp = (SCB_FP_t *)userdata; + SCB_FP_t *scb_fp = userdata; if (op == OP_RESET) { @@ -35,9 +35,13 @@ OPERATION(scb_fp) return MEMREG_RESULT_UNHANDLED; } -SCB_FP_t *scb_fp_new() +SCB_FP_t *scb_fp_new(state_store_t *store) { - return malloc(sizeof(SCB_FP_t)); + SCB_FP_t *scb_fp = malloc(sizeof(SCB_FP_t)); + + state_store_register(store, STATE_KEY_SCB_FP, scb_fp, sizeof(SCB_FP_t)); + + return scb_fp; } FPCCR_t scb_fp_get_fpccr(SCB_FP_t *scb_fp) diff --git a/src/pinetime.c b/src/pinetime.c index 5b1ace6..3c0eeac 100644 --- a/src/pinetime.c +++ b/src/pinetime.c @@ -9,6 +9,7 @@ struct pinetime_t { NRF52832_t *nrf; + state_store_t *state_store; st7789_t *lcd; cst816s_t *touch; @@ -28,16 +29,17 @@ pinetime_t *pinetime_new(const program_t *program) sram_size = NRF52832_SRAM_SIZE; pinetime_t *pt = malloc(sizeof(pinetime_t)); - pt->nrf = nrf52832_new(program, sram_size); - pt->lcd = st7789_new(); - pt->touch = cst816s_new(nrf52832_get_pins(pt->nrf), PINETIME_CST816S_IRQ_PIN); - pt->hrs = hrs3300_new(); - pt->extflash = spinorflash_new(PINETIME_EXTFLASH_SIZE, PINETIME_EXTFLASH_SECTOR_SIZE); + pt->state_store = state_store_new(); + pt->nrf = nrf52832_new(program, sram_size, pt->state_store); + pt->lcd = st7789_new(pt->state_store); + pt->touch = cst816s_new(nrf52832_get_pins(pt->nrf), pt->state_store, PINETIME_CST816S_IRQ_PIN); + pt->hrs = hrs3300_new(pt->state_store); + pt->extflash = spinorflash_new(pt->state_store, PINETIME_EXTFLASH_SIZE, PINETIME_EXTFLASH_SECTOR_SIZE); bus_spi_add_slave(nrf52832_get_spi(pt->nrf), PINETIME_EXTFLASH_CS_PIN, spinorflash_get_slave(pt->extflash)); bus_spi_add_slave(nrf52832_get_spi(pt->nrf), PINETIME_LCD_CS_PIN, st7789_get_slave(pt->lcd)); i2c_add_slave(nrf52832_get_i2c(pt->nrf), PINETIME_CST816S_I2C_ADDR, cst816s_get_slave(pt->touch)); - i2c_add_slave(nrf52832_get_i2c(pt->nrf), PINETIME_BMA425_I2C_ADDR, bma425_new()); + i2c_add_slave(nrf52832_get_i2c(pt->nrf), PINETIME_BMA425_I2C_ADDR, bma425_new(pt->state_store)); i2c_add_slave(nrf52832_get_i2c(pt->nrf), PINETIME_HRS3300_I2C_ADDR, hrs3300_get_slave(pt->hrs)); nrf52832_reset(pt->nrf); @@ -84,3 +86,19 @@ spinorflash_t *pinetime_get_spinorflash(pinetime_t *pt) { return pt->extflash; } + +uint8_t *pinetime_save_state(pinetime_t *pt, size_t *size) +{ + return state_store_save(pt->state_store, size); +} + +bool pinetime_load_state(pinetime_t *pt, uint8_t *data, size_t size) +{ + if (state_store_load(pt->state_store, data, size)) + { + nrf52832_reload_state(pt->nrf); + return true; + } + + return false; +} diff --git a/src/pins.c b/src/pins.c index 0d9f901..8ff1b9e 100644 --- a/src/pins.c +++ b/src/pins.c @@ -21,9 +21,13 @@ struct pins_t uint32_t latch; }; -pins_t *pins_new() +pins_t *pins_new(state_store_t *store) { - return (pins_t *)calloc(1, sizeof(pins_t)); + pins_t *pins = calloc(1, sizeof(pins_t)); + + state_store_register(store, STATE_KEY_PINS, pins, sizeof(pins_t)); + + return pins; } void pins_free(pins_t *pins) diff --git a/src/state_store.c b/src/state_store.c index 2acb7aa..b54f44b 100644 --- a/src/state_store.c +++ b/src/state_store.c @@ -93,7 +93,7 @@ uint8_t *state_store_save(state_store_t *store, size_t *size) return data; } -bool state_store_load(state_store_t *store, uint8_t *data, size_t size) +bool state_store_load(state_store_t *store, const uint8_t *data, size_t size) { entry_header_t header;