diff --git a/include/memory.h b/include/memory.h index ca55101..558d1cf 100644 --- a/include/memory.h +++ b/include/memory.h @@ -22,6 +22,7 @@ static inline uint32_t size_mask(byte_size_t size) typedef enum { OP_RESET = 0, + OP_LOAD_DATA = 0xFF, OP_READ_BYTE = SIZE_BYTE, OP_READ_HALFWORD = SIZE_HALFWORD, OP_READ_WORD = SIZE_WORD, diff --git a/include/peripherals/nrf52832/ppi.h b/include/peripherals/nrf52832/ppi.h index 87bbea6..f53f3ee 100644 --- a/include/peripherals/nrf52832/ppi.h +++ b/include/peripherals/nrf52832/ppi.h @@ -31,6 +31,7 @@ typedef void (*ppi_task_cb_t)(PPI_t *, uint8_t peripheral, uint8_t task, void *u PPI_t *ppi_new(cpu_t **cpu); void ppi_add_peripheral(PPI_t *, uint8_t id, ppi_task_cb_t cb, void *userdata); +void ppi_replace_peripheral(PPI_t *, uint8_t id, ppi_task_cb_t cb, void *userdata); void ppi_remove_peripheral(PPI_t *, uint8_t id); void ppi_fire_task(PPI_t *, uint8_t peripheral_id, uint8_t task_id); diff --git a/include/state_store.h b/include/state_store.h index 5dcfdc2..b9c7dde 100644 --- a/include/state_store.h +++ b/include/state_store.h @@ -9,10 +9,19 @@ typedef uint16_t state_key_t; #define PERIPHERAL_KEY(id) (0xFF00 | (id)) +enum +{ + STATE_KEY_POWER = 1, + STATE_KEY_CLOCK, + + STATE_KEY_SPIM0 = 0x0100, + STATE_KEY_TWIM0 = 0x0200, +}; + state_store_t *state_store_new(); void state_store_free(state_store_t *); -void *state_store_alloc(state_store_t *, state_key_t key, size_t size); +void state_store_register(state_store_t *store, state_key_t key, void *data, size_t size); void state_store_freeze(state_store_t *); uint8_t *state_store_save(state_store_t *, size_t *size); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 71bd5c3..1fcc5e6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -88,7 +88,7 @@ set(WASM_EXPORTS set(LIBS m tiny-aes capstone) -add_compile_options(-Werror -Wall -Wextra -Wno-unused-parameter) +add_compile_options(-Werror -Wall -Wextra -Wno-unused-parameter -fms-extensions) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) diff --git a/src/peripherals/nrf52832/clock.c b/src/peripherals/nrf52832/clock.c index 94fe6d5..0f32544 100644 --- a/src/peripherals/nrf52832/clock.c +++ b/src/peripherals/nrf52832/clock.c @@ -48,7 +48,7 @@ enum OPERATION(clock) { - CLOCK_t *clock = (CLOCK_t *)userdata; + CLOCK_t *clock = userdata; if (op == OP_RESET) { @@ -150,6 +150,8 @@ NRF52_PERIPHERAL_CONSTRUCTOR(CLOCK, clock) { CLOCK_t *clock = malloc(sizeof(CLOCK_t)); + state_store_register(ctx.state_store, STATE_KEY_CLOCK, clock, sizeof(*clock)); + ppi_add_peripheral(ctx.ppi, ctx.id, clock_task_handler, clock); return clock; diff --git a/src/peripherals/nrf52832/ecb.c b/src/peripherals/nrf52832/ecb.c index 59f9923..7cb1e54 100644 --- a/src/peripherals/nrf52832/ecb.c +++ b/src/peripherals/nrf52832/ecb.c @@ -16,7 +16,6 @@ enum EVENTS_ERRORECB = 0x104, // ECB block encrypt aborted because of a STOPECB task or due to an error }; - typedef struct { union @@ -27,7 +26,6 @@ typedef struct uint32_t value; } inten_t; - typedef struct { uint8_t key[16]; @@ -36,12 +34,17 @@ typedef struct } ecbdata_t; static_assert(sizeof(ecbdata_t) == 48, "ecbdata_t size is not 48 bytes"); -struct ECB_inst_t +typedef struct { - dma_t *dma; - uint32_t ecbdataptr; inten_t inten; +} state_t; + +struct ECB_inst_t +{ + state_t; + + dma_t *dma; }; OPERATION(ecb) @@ -113,6 +116,8 @@ NRF52_PERIPHERAL_CONSTRUCTOR(ECB, ecb) ECB_t *ecb = malloc(sizeof(ECB_t)); ecb->dma = ctx.dma; + state_store_register(ctx.state_store, PERIPHERAL_KEY(ctx.id), ecb, sizeof(state_t)); + ppi_add_peripheral(ctx.ppi, ctx.id, ecb_task_handler, ecb); return ecb; diff --git a/src/peripherals/nrf52832/gpiote.c b/src/peripherals/nrf52832/gpiote.c index c51f420..1e4f4f0 100644 --- a/src/peripherals/nrf52832/gpiote.c +++ b/src/peripherals/nrf52832/gpiote.c @@ -91,14 +91,19 @@ typedef union uint32_t value; } inten_t; -struct GPIOTE_inst_t +typedef struct { - pins_t *pins; - inten_t inten; config_t config[8]; uint32_t latch_old; +} state_t; + +struct GPIOTE_inst_t +{ + state_t; + + pins_t *pins; }; OPERATION(gpiote) @@ -203,6 +208,8 @@ NRF52_PERIPHERAL_CONSTRUCTOR(GPIOTE, gpiote) GPIOTE_t *gpiote = malloc(sizeof(GPIOTE_t)); gpiote->pins = ctx.pins; + state_store_register(ctx.state_store, PERIPHERAL_KEY(ctx.id), gpiote, sizeof(state_t)); + ppi_add_peripheral(current_ppi, ctx.id, gpiote_task_handler, gpiote); return gpiote; diff --git a/src/peripherals/nrf52832/nvmc.c b/src/peripherals/nrf52832/nvmc.c index 9ea7a17..742bd77 100644 --- a/src/peripherals/nrf52832/nvmc.c +++ b/src/peripherals/nrf52832/nvmc.c @@ -14,10 +14,10 @@ typedef union struct NVMC_inst_t { + config_t config; + uint8_t *data; size_t size; - - config_t config; }; OPERATION(nvmc) @@ -90,5 +90,8 @@ NRF52_PERIPHERAL_CONSTRUCTOR(NVMC, nvmc, uint8_t *data, size_t size) NVMC_t *nvmc = malloc(sizeof(NVMC_t)); nvmc->data = data; nvmc->size = size; + + state_store_register(ctx.state_store, PERIPHERAL_KEY(ctx.id), nvmc, sizeof(config_t)); + return nvmc; } diff --git a/src/peripherals/nrf52832/power.c b/src/peripherals/nrf52832/power.c index 1e69971..6249545 100644 --- a/src/peripherals/nrf52832/power.c +++ b/src/peripherals/nrf52832/power.c @@ -40,5 +40,9 @@ OPERATION(power) NRF52_PERIPHERAL_CONSTRUCTOR(POWER, power) { - return malloc(sizeof(POWER_t)); + POWER_t *power = malloc(sizeof(POWER_t)); + + state_store_register(ctx.state_store, STATE_KEY_POWER, power, sizeof(POWER_t)); + + return power; } diff --git a/src/peripherals/nrf52832/ppi.c b/src/peripherals/nrf52832/ppi.c index becca4f..7ead7de 100644 --- a/src/peripherals/nrf52832/ppi.c +++ b/src/peripherals/nrf52832/ppi.c @@ -256,6 +256,19 @@ void ppi_add_peripheral(PPI_t *ppi, uint8_t id, ppi_task_cb_t cb, void *userdata ppi->peripherals[id] = peripheral; } +void ppi_replace_peripheral(PPI_t *ppi, uint8_t id, ppi_task_cb_t cb, void *userdata) +{ + assert(id <= PERIPHERALS_COUNT - 1); + + peripheral_t *peripheral = ppi->peripherals[id]; + + if (!peripheral) + ppi->peripherals[id] = peripheral = malloc(sizeof(peripheral_t)); + + peripheral->cb = cb; + peripheral->userdata = userdata; +} + void ppi_remove_peripheral(PPI_t *ppi, uint8_t id) { assert(id < PERIPHERALS_COUNT); diff --git a/src/peripherals/nrf52832/rtc.c b/src/peripherals/nrf52832/rtc.c index dafa41a..f091b0c 100644 --- a/src/peripherals/nrf52832/rtc.c +++ b/src/peripherals/nrf52832/rtc.c @@ -36,7 +36,7 @@ typedef struct struct RTC_inst_t { - state_t *s; + state_t; cpu_t **cpu; ticker_t *ticker; @@ -48,31 +48,31 @@ void rtc_tick(void *userdata) { RTC_t *rtc = userdata; - rtc->s->counter++; + rtc->counter++; - ppi_fire_event(current_ppi, rtc->id, EVENT_ID(RTC_EVENTS_TICK), rtc->s->inten.TICK); + ppi_fire_event(current_ppi, rtc->id, EVENT_ID(RTC_EVENTS_TICK), rtc->inten.TICK); - if (rtc->s->counter == (1 << 24)) + if (rtc->counter == (1 << 24)) { - rtc->s->counter = 0; + rtc->counter = 0; - ppi_fire_event(current_ppi, rtc->id, EVENT_ID(RTC_EVENTS_OVRFLW), rtc->s->inten.OVRFLW); + ppi_fire_event(current_ppi, rtc->id, EVENT_ID(RTC_EVENTS_OVRFLW), rtc->inten.OVRFLW); } for (size_t i = 0; i < rtc->cc_num; i++) { - if (rtc->s->counter == rtc->s->cc[i]) - ppi_fire_event(current_ppi, rtc->id, EVENT_ID(RTC_EVENTS_COMPARE0) + i, rtc->s->inten.COMPARE & (1 << i)); + if (rtc->counter == rtc->cc[i]) + ppi_fire_event(current_ppi, rtc->id, EVENT_ID(RTC_EVENTS_COMPARE0) + i, rtc->inten.COMPARE & (1 << i)); } } OPERATION(rtc) { - state_t *state = ((RTC_t *)userdata)->s; + state_t *rtc = userdata; if (op == OP_RESET) { - memset(state, 0, sizeof(state_t)); + memset(rtc, 0, sizeof(state_t)); return MEMREG_RESULT_OK; } @@ -90,32 +90,32 @@ OPERATION(rtc) OP_EVENT(RTC_EVENTS_COMPARE2) OP_EVENT(RTC_EVENTS_COMPARE3) - OP_INTENSET(state) - OP_INTENCLR(state) + OP_INTENSET(rtc) + OP_INTENCLR(rtc) case 0x340: // EVTEN - OP_RETURN_REG(state->evten.value, WORD); + OP_RETURN_REG(rtc->evten.value, WORD); case 0x344: // EVTENSET - OP_RETURN_REG_SET(state->evten.value, WORD); + OP_RETURN_REG_SET(rtc->evten.value, WORD); case 0x348: // EVTENCLR - OP_RETURN_REG_CLR(state->evten.value, WORD); + OP_RETURN_REG_CLR(rtc->evten.value, WORD); case 0x504: // COUNTER - OP_RETURN_REG(state->counter, WORD); + OP_RETURN_REG(rtc->counter, WORD); case 0x508: // PRESCALER if (OP_IS_READ(op)) { - *value = state->prescaler; + *value = rtc->prescaler; } else { - if (state->running) + if (rtc->running) fault_take(FAULT_RTC_INVALID_STATE); - state->prescaler = *value; + rtc->prescaler = *value; } return MEMREG_RESULT_OK; @@ -125,7 +125,7 @@ OPERATION(rtc) { uint32_t idx = (offset - 0x540) / 4; - OP_RETURN_REG(state->cc[idx], WORD); + OP_RETURN_REG(rtc->cc[idx], WORD); } return MEMREG_RESULT_UNHANDLED; @@ -133,31 +133,31 @@ OPERATION(rtc) PPI_TASK_HANDLER(rtc_task_handler) { - RTC_t *rtc = (RTC_t *)userdata; + RTC_t *rtc = userdata; switch (task) { case TASK_ID(RTC_TASKS_START): - if (!rtc->s->running) + if (!rtc->running) { - ticker_add(rtc->ticker, CLOCK_LFCLK, rtc_tick, rtc, rtc->s->prescaler + 1, true); + ticker_add(rtc->ticker, CLOCK_LFCLK, rtc_tick, rtc, rtc->prescaler + 1, true); - rtc->s->running = true; + rtc->running = true; } break; case TASK_ID(RTC_TASKS_STOP): - if (rtc->s->running) + if (rtc->running) { ticker_remove(rtc->ticker, CLOCK_LFCLK, rtc_tick); - rtc->s->running = false; + rtc->running = false; } break; case TASK_ID(RTC_TASKS_CLEAR): - rtc->s->counter = 0; - rtc->s->prescaler_counter = 0; + rtc->counter = 0; + rtc->prescaler_counter = 0; break; } } @@ -171,7 +171,8 @@ NRF52_PERIPHERAL_CONSTRUCTOR(RTC, rtc, size_t cc_num) rtc->cpu = ctx.cpu; rtc->id = ctx.id; rtc->ticker = ctx.ticker; - rtc->s = state_store_alloc(ctx.state_store, PERIPHERAL_KEY(ctx.id), sizeof(state_t)); + + state_store_register(ctx.state_store, PERIPHERAL_KEY(ctx.id), rtc, sizeof(state_t)); ppi_add_peripheral(ctx.ppi, ctx.id, rtc_task_handler, rtc); @@ -180,15 +181,15 @@ NRF52_PERIPHERAL_CONSTRUCTOR(RTC, rtc, size_t cc_num) uint32_t rtc_is_running(RTC_t *rtc) { - return rtc->s->running; + return rtc->running; } uint32_t rtc_get_counter(RTC_t *rtc) { - return rtc->s->counter; + return rtc->counter; } double rtc_get_tick_interval_us(RTC_t *rtc) { - return ((double)(rtc->s->prescaler + 1) * 1e6) / 32768.0; + return ((double)(rtc->prescaler + 1) * 1e6) / 32768.0; } diff --git a/src/peripherals/nrf52832/spi.c b/src/peripherals/nrf52832/spi.c index 7a6d39c..0b1f1b6 100644 --- a/src/peripherals/nrf52832/spi.c +++ b/src/peripherals/nrf52832/spi.c @@ -10,11 +10,17 @@ enum #define READ_BUFFER_SIZE 50 +typedef struct +{ + bool enabled; +} state_t; + struct SPI_inst_t { + state_t; + uint8_t id; bus_spi_t *bus; - bool enabled; }; PPI_TASK_HANDLER(spi_task_handler) @@ -112,7 +118,8 @@ NRF52_PERIPHERAL_CONSTRUCTOR(SPI, spi) SPI_t *spi = malloc(sizeof(SPI_t)); spi->bus = ctx.spi; spi->id = ctx.id; - spi->enabled = false; + + state_store_register(ctx.state_store, PERIPHERAL_KEY(ctx.id), spi, sizeof(state_t)); return spi; } diff --git a/src/peripherals/nrf52832/spim.c b/src/peripherals/nrf52832/spim.c index 794a609..153da24 100644 --- a/src/peripherals/nrf52832/spim.c +++ b/src/peripherals/nrf52832/spim.c @@ -49,10 +49,8 @@ typedef union uint32_t value; } inten_t; -struct SPIM_inst_t +typedef struct { - uint8_t id; - bus_spi_t *bus; bool enabled; uint32_t psel_sck, psel_mosi, psel_miso; @@ -62,11 +60,19 @@ struct SPIM_inst_t config_t config; inten_t inten; +} state_t; + +struct SPIM_inst_t +{ + state_t; + + uint8_t id; + bus_spi_t *bus; }; PPI_TASK_HANDLER(spim_task_handler) { - SPIM_t *spim = (SPIM_t *)userdata; + SPIM_t *spim = userdata; assert(task == TASK_ID(TASKS_START)); @@ -90,7 +96,7 @@ PPI_TASK_HANDLER(spim_task_handler) OPERATION(spim) { - SPIM_t *spim = (SPIM_t *)userdata; + SPIM_t *spim = userdata; if (op == OP_RESET) { @@ -102,6 +108,13 @@ OPERATION(spim) return MEMREG_RESULT_OK; } + if (op == OP_LOAD_DATA) + { + if (spim->enabled) + ppi_replace_peripheral(current_ppi, spim->id, spim_task_handler, spim); + + return MEMREG_RESULT_OK; + } OP_ASSERT_SIZE(op, WORD); @@ -188,5 +201,7 @@ NRF52_PERIPHERAL_CONSTRUCTOR(SPIM, spim) spim->bus = ctx.spi; spim->id = ctx.id; + state_store_register(ctx.state_store, STATE_KEY_SPIM0 + ctx.id, spim, sizeof(state_t)); + return spim; } diff --git a/src/peripherals/nrf52832/temp.c b/src/peripherals/nrf52832/temp.c index c75fb0f..ecc412b 100644 --- a/src/peripherals/nrf52832/temp.c +++ b/src/peripherals/nrf52832/temp.c @@ -40,10 +40,9 @@ OPERATION(temp) NRF52_PERIPHERAL_CONSTRUCTOR(TEMP, temp) { - return malloc(sizeof(TEMP_t)); -} + TEMP_t *temp = malloc(sizeof(TEMP_t)); -void temp_reset(TEMP_t *temp) -{ - -} \ No newline at end of file + state_store_register(ctx.state_store, PERIPHERAL_KEY(ctx.id), temp, sizeof(TEMP_t)); + + return temp; +} diff --git a/src/peripherals/nrf52832/timer.c b/src/peripherals/nrf52832/timer.c index 8db2fe0..4bdac8a 100644 --- a/src/peripherals/nrf52832/timer.c +++ b/src/peripherals/nrf52832/timer.c @@ -24,13 +24,8 @@ enum BITMODE_32BIT = 3, }; -struct TIMER_inst_t +typedef struct { - size_t cc_num; - uint8_t id; - ticker_t *ticker; - cpu_t **cpu; - bool running; uint32_t mode, bitmode; @@ -40,6 +35,16 @@ struct TIMER_inst_t uint32_t counter, prescaler_counter; uint32_t cc[TIMER_MAX_CC]; +} state_t; + +struct TIMER_inst_t +{ + state_t; + + size_t cc_num; + uint8_t id; + ticker_t *ticker; + cpu_t **cpu; }; void timer_increase_counter(TIMER_t *timer) @@ -229,6 +234,8 @@ NRF52_PERIPHERAL_CONSTRUCTOR(TIMER, timer, size_t cc_num) timer->ticker = ctx.ticker; timer->cpu = ctx.cpu; + state_store_register(ctx.state_store, PERIPHERAL_KEY(ctx.id), timer, sizeof(state_t)); + ppi_add_peripheral(ctx.ppi, ctx.id, timer_task_handler, timer); return timer; diff --git a/src/peripherals/nrf52832/twim.c b/src/peripherals/nrf52832/twim.c index 6af1885..2c33b47 100644 --- a/src/peripherals/nrf52832/twim.c +++ b/src/peripherals/nrf52832/twim.c @@ -41,10 +41,8 @@ typedef struct uint32_t value; } inten_t; -struct TWIM_inst_t +typedef struct { - uint8_t id; - bus_i2c_t *i2c; bool enabled; inten_t inten; @@ -52,6 +50,14 @@ struct TWIM_inst_t uint32_t address; easydma_reg_t tx, rx; +} state_t; + +struct TWIM_inst_t +{ + state_t; + + uint8_t id; + bus_i2c_t *i2c; }; PPI_TASK_HANDLER(twim_task_handler) @@ -108,6 +114,13 @@ OPERATION(twim) return MEMREG_RESULT_OK; } + if (op == OP_LOAD_DATA) + { + if (twim->enabled) + ppi_replace_peripheral(current_ppi, twim->id, twim_task_handler, twim); + + return MEMREG_RESULT_OK; + } switch (offset) { @@ -128,7 +141,7 @@ OPERATION(twim) OP_INTENSET(twim) OP_INTENCLR(twim) - case 0x4C4: // ERRORSRC + case 0x4C4: // ERRORSRC if (OP_IS_READ(op)) // Stub *value = 0; return MEMREG_RESULT_OK; @@ -172,9 +185,11 @@ OPERATION(twim) NRF52_PERIPHERAL_CONSTRUCTOR(TWIM, twim) { - TWIM_t *twim = (TWIM_t *)calloc(1, sizeof(TWIM_t)); + TWIM_t *twim = calloc(1, sizeof(TWIM_t)); twim->i2c = ctx.i2c; twim->id = ctx.id; + state_store_register(ctx.state_store, STATE_KEY_TWIM0 + ctx.id, twim, sizeof(state_t)); + return twim; } diff --git a/src/peripherals/nrf52832/wdt.c b/src/peripherals/nrf52832/wdt.c index 9d36113..643171d 100644 --- a/src/peripherals/nrf52832/wdt.c +++ b/src/peripherals/nrf52832/wdt.c @@ -55,5 +55,9 @@ OPERATION(wdt) NRF52_PERIPHERAL_CONSTRUCTOR(WDT, wdt) { - return malloc(sizeof(WDT_t)); + WDT_t *wdt = malloc(sizeof(WDT_t)); + + state_store_register(ctx.state_store, PERIPHERAL_KEY(ctx.id), wdt, sizeof(WDT_t)); + + return wdt; } diff --git a/src/state_store.c b/src/state_store.c index 74e1362..2acb7aa 100644 --- a/src/state_store.c +++ b/src/state_store.c @@ -1,6 +1,7 @@ #include "state_store.h" #include +#include typedef struct { @@ -50,20 +51,19 @@ static entry_t *find_entry(state_store_t *store, state_key_t key) return NULL; } -void *state_store_alloc(state_store_t *store, state_key_t key, size_t size) +void state_store_register(state_store_t *store, state_key_t key, void *data, size_t size) { if (store->frozen) abort(); - void *data = malloc(size); + if (find_entry(store, key)) + abort(); store->entries[store->entries_count++] = (entry_t){ .header.key = key, .header.size = size, .data = data, }; - - return data; } void state_store_freeze(state_store_t *store) @@ -83,10 +83,10 @@ uint8_t *state_store_save(state_store_t *store, size_t *size) size_t offset = 0; for (size_t i = 0; i < store->entries_count; i++) { - memcpy(*data + offset, &store->entries[i].header, sizeof(entry_header_t)); + memcpy(data + offset, &store->entries[i].header, sizeof(entry_header_t)); offset += sizeof(entry_header_t); - memcpy(*data + offset, store->entries[i].data, store->entries[i].header.size); + memcpy(data + offset, store->entries[i].data, store->entries[i].header.size); offset += store->entries[i].header.size; } @@ -104,7 +104,7 @@ bool state_store_load(state_store_t *store, uint8_t *data, size_t size) offset += sizeof(entry_header_t); entry_t *entry = find_entry(store, header.key); - if (!entry) { + if (!entry || entry->header.size != header.size) { return false; }