diff --git a/Makefile b/Makefile index 2d3bdf92..583d8221 100644 --- a/Makefile +++ b/Makefile @@ -176,7 +176,7 @@ mongoose.c: Makefile $(wildcard src/*.c) $(wildcard src/drivers/*.c) (cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c src/drivers/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@ mongoose.h: $(HDRS) Makefile - (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/sys.h src/net_builtin.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@ + (cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_ft.h src/net_lwip.h src/net_rl.h src/config.h src/str.h src/queue.h src/fmt.h src/printf.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h src/ota.h src/device.h src/net_builtin.h src/drivers/*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@ clean: clean_examples clean_embedded diff --git a/examples/device-dashboard/net.c b/examples/device-dashboard/net.c index a6423409..9155964e 100644 --- a/examples/device-dashboard/net.c +++ b/examples/device-dashboard/net.c @@ -222,7 +222,7 @@ static void handle_firmware_upload(struct mg_connection *c, mg_http_reply(c, 200, s_json_header, "true\n"); if (data.len == 0) { // Successful mg_ota_end() called, schedule device reboot - mg_timer_add(c->mgr, 500, 0, (void (*)(void *)) mg_sys_reset, NULL); + mg_timer_add(c->mgr, 500, 0, (void (*)(void *)) mg_device_reset, NULL); } } } @@ -250,9 +250,9 @@ static void handle_firmware_status(struct mg_connection *c) { MG_FIRMWARE_CURRENT, print_status, MG_FIRMWARE_PREVIOUS); } -static void handle_sys_reset(struct mg_connection *c) { +static void handle_device_reset(struct mg_connection *c) { mg_http_reply(c, 200, s_json_header, "true\n"); - mg_timer_add(c->mgr, 500, 0, (void (*)(void *)) mg_sys_reset, NULL); + mg_timer_add(c->mgr, 500, 0, (void (*)(void *)) mg_device_reset, NULL); } // HTTP request handler function @@ -292,8 +292,8 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { handle_firmware_rollback(c); } else if (mg_http_match_uri(hm, "/api/firmware/status")) { handle_firmware_status(c); - } else if (mg_http_match_uri(hm, "/api/sys/reset")) { - handle_sys_reset(c); + } else if (mg_http_match_uri(hm, "/api/device/reset")) { + handle_device_reset(c); } else { struct mg_http_serve_opts opts; memset(&opts, 0, sizeof(opts)); diff --git a/examples/device-dashboard/web_root/main.js b/examples/device-dashboard/web_root/main.js index d08406bb..d7b87f4c 100644 --- a/examples/device-dashboard/web_root/main.js +++ b/examples/device-dashboard/web_root/main.js @@ -211,7 +211,7 @@ function FirmwareUpdate({}) { const oncommit = ev => fetch('api/firmware/commit') .then(r => r.json()) .then(refresh); - const onreboot = ev => fetch('api/sys/reset') + const onreboot = ev => fetch('api/device/reset') .then(r => r.json()) .then(r => new Promise(r => setTimeout(ev => { refresh(); r(); }, 3000))); const onrollback = ev => fetch('api/firmware/rollback') diff --git a/examples/stm32/nucleo-h563zi-make-baremetal-builtin/mongoose_custom.h b/examples/stm32/nucleo-h563zi-make-baremetal-builtin/mongoose_custom.h index 09860117..e751b193 100644 --- a/examples/stm32/nucleo-h563zi-make-baremetal-builtin/mongoose_custom.h +++ b/examples/stm32/nucleo-h563zi-make-baremetal-builtin/mongoose_custom.h @@ -2,7 +2,7 @@ #define MG_ARCH MG_ARCH_NEWLIB #define MG_OTA MG_OTA_FLASH -#define MG_SYS MG_SYS_STM32H5 +#define MG_DEVICE MG_DEVICE_STM32H5 #define MG_ENABLE_TCPIP 1 #define MG_ENABLE_CUSTOM_MILLIS 1 diff --git a/examples/stm32/nucleo-h743zi-make-baremetal-builtin/mongoose_custom.h b/examples/stm32/nucleo-h743zi-make-baremetal-builtin/mongoose_custom.h index c965bdca..29a55da2 100644 --- a/examples/stm32/nucleo-h743zi-make-baremetal-builtin/mongoose_custom.h +++ b/examples/stm32/nucleo-h743zi-make-baremetal-builtin/mongoose_custom.h @@ -2,7 +2,7 @@ #define MG_ARCH MG_ARCH_NEWLIB #define MG_OTA MG_OTA_FLASH -#define MG_SYS MG_SYS_STM32H7 +#define MG_DEVICE MG_DEVICE_STM32H7 #define MG_ENABLE_TCPIP 1 #define MG_ENABLE_CUSTOM_MILLIS 1 diff --git a/mongoose.c b/mongoose.c index 08aaa0aa..6fdd7444 100644 --- a/mongoose.c +++ b/mongoose.c @@ -112,6 +112,505 @@ size_t mg_base64_decode(const char *src, size_t n, char *dst, size_t dl) { return len; } +#ifdef MG_ENABLE_LINES +#line 1 "src/device_dummy.c" +#endif + + +#if MG_DEVICE == MG_DEVICE_NONE +void *mg_flash_start(void) { + return NULL; +} +size_t mg_flash_size(void) { + return 0; +} +size_t mg_flash_sector_size(void) { + return 0; +} +size_t mg_flash_write_align(void) { + return 0; +} +int mg_flash_bank(void) { + return 0; +} +bool mg_flash_erase(void *location) { + (void) location; + return false; +} +bool mg_flash_swap_bank(void) { + return true; +} +bool mg_flash_write(void *addr, const void *buf, size_t len) { + (void) addr, (void) buf, (void) len; + return false; +} +void mg_device_reset(void) { +} +#endif + +#ifdef MG_ENABLE_LINES +#line 1 "src/device_flash.c" +#endif + + +#if MG_DEVICE == MG_DEVICE_STM32H7 || MG_DEVICE == MG_DEVICE_STM32H5 +// Flash can be written only if it is erased. Erased flash is 0xff (all bits 1) +// Writes must be mg_flash_write_align() - aligned. Thus if we want to save an +// object, we pad it at the end for alignment. +// +// Objects in the flash sector are stored sequentially: +// | 32-bit size | 32-bit KEY | ..data.. | ..pad.. | 32-bit size | ...... +// +// In order to get to the next object, read its size, then align up. + +// Traverse the list of saved objects +size_t mg_flash_next(char *p, char *end, uint32_t *key, size_t *size) { + size_t aligned_size = 0, align = mg_flash_write_align(), left = end - p; + uint32_t *p32 = (uint32_t *) p, min_size = sizeof(uint32_t) * 2; + if (p32[0] != 0xffffffff && left > MG_ROUND_UP(min_size, align)) { + if (size) *size = (size_t) p32[0]; + if (key) *key = p32[1]; + aligned_size = MG_ROUND_UP(p32[0] + sizeof(uint32_t) * 2, align); + if (left < aligned_size) aligned_size = 0; // Out of bounds, fail + } + return aligned_size; +} + +// Return the last sector of Bank 2 +static char *flash_last_sector(void) { + size_t ss = mg_flash_sector_size(), size = mg_flash_size(); + char *base = (char *) mg_flash_start(), *last = base + size - ss; + if (mg_flash_bank() == 2) last -= size / 2; + return last; +} + +// Find a saved object with a given key +bool mg_flash_load(void *sector, uint32_t key, void *buf, size_t len) { + char *base = (char *) mg_flash_start(), *s = (char *) sector, *res = NULL; + size_t ss = mg_flash_sector_size(), ofs = 0, n, sz; + bool ok = false; + if (s == NULL) s = flash_last_sector(); + if (s < base || s >= base + mg_flash_size()) { + MG_ERROR(("%p is outsize of flash", sector)); + } else if (((s - base) % ss) != 0) { + MG_ERROR(("%p is not a sector boundary", sector)); + } else { + uint32_t k, scanned = 0; + while ((n = mg_flash_next(s + ofs, s + ss, &k, &sz)) > 0) { + // MG_DEBUG((" > obj %lu, ofs %lu, key %x/%x", scanned, ofs, k, key)); + // mg_hexdump(s + ofs, n); + if (k == key && sz == len) { + res = s + ofs + sizeof(uint32_t) * 2; + memcpy(buf, res, len); // Copy object + ok = true; // Keep scanning for the newer versions of it + } + ofs += n, scanned++; + } + MG_DEBUG(("Scanned %u objects, key %x is @ %p", scanned, key, res)); + } + return ok; +} + +static bool mg_flash_writev(char *location, struct mg_str *strings, size_t n) { + size_t align = mg_flash_write_align(), i, j, k = 0, nwritten = 0; + char buf[align]; + bool ok = true; + for (i = 0; ok && i < n; i++) { + for (j = 0; ok && j < strings[i].len; j++) { + buf[k++] = strings[i].ptr[j]; + if (k >= sizeof(buf)) { + ok = mg_flash_write(location + nwritten, buf, sizeof(buf)); + k = 0, nwritten += sizeof(buf); + } + } + } + if (k > 0) { + while (k < sizeof(buf)) buf[k++] = 0xff; + ok = mg_flash_write(location + nwritten, buf, sizeof(buf)); + } + return ok; +} + +// For all saved objects in the sector, delete old versions of objects +static void mg_flash_sector_cleanup(char *sector) { + // Buffer all saved objects into an IO buffer (backed by RAM) + // erase sector, and re-save them. + struct mg_iobuf io = {0, 0, 0, 2048}; + size_t ss = mg_flash_sector_size(); + size_t n, size, size2, ofs = 0, hs = sizeof(uint32_t) * 2; + uint32_t key; + // Traverse all objects + MG_DEBUG(("Cleaning up sector %p", sector)); + while ((n = mg_flash_next(sector + ofs, sector + ss, &key, &size)) > 0) { + // Delete an old copy of this object in the cache + for (size_t o = 0; o < io.len; o += size2 + hs) { + uint32_t k = *(uint32_t *) (io.buf + o + sizeof(uint32_t)); + size2 = *(uint32_t *) (io.buf + o); + if (k == key) { + mg_iobuf_del(&io, o, size2 + hs); + break; + } + } + // And add the new copy + mg_iobuf_add(&io, io.len, sector + ofs, size + hs); + ofs += n; + } + // All objects are cached in RAM now + if (mg_flash_erase(sector)) { // Erase sector. If successful, + for (ofs = 0; ofs < io.len; ofs += size + hs) { // Traverse cached objects + size = *(uint32_t *) (io.buf + ofs); + key = *(uint32_t *) (io.buf + ofs + sizeof(uint32_t)); + mg_flash_save(sector, key, io.buf + ofs + hs, size); // Save to flash + } + } + mg_iobuf_free(&io); +} + +// Save an object with a given key - append to the end of an object list +bool mg_flash_save(void *sector, uint32_t key, const void *buf, size_t len) { + char *base = (char *) mg_flash_start(), *s = (char *) sector; + size_t ss = mg_flash_sector_size(), ofs = 0, n; + bool ok = false; + if (s == NULL) s = flash_last_sector(); + if (s < base || s >= base + mg_flash_size()) { + MG_ERROR(("%p is outsize of flash", sector)); + } else if (((s - base) % ss) != 0) { + MG_ERROR(("%p is not a sector boundary", sector)); + } else { + size_t needed = sizeof(uint32_t) * 2 + len; + size_t needed_aligned = MG_ROUND_UP(needed, mg_flash_write_align()); + while ((n = mg_flash_next(s + ofs, s + ss, NULL, NULL)) > 0) ofs += n; + + // If there is not enough space left, cleanup sector and re-eval ofs + if (ofs + needed_aligned > ss) { + mg_flash_sector_cleanup(s); + ofs = 0; + while ((n = mg_flash_next(s + ofs, s + ss, NULL, NULL)) > 0) ofs += n; + } + + if (ofs + needed_aligned <= ss) { + // Enough space to save this object + uint32_t hdr[2] = {(uint32_t) len, key}; + struct mg_str data[] = {mg_str_n((char *) hdr, sizeof(hdr)), + mg_str_n(buf, len)}; + ok = mg_flash_writev(s + ofs, data, 2); + MG_DEBUG(("Saving %lu bytes @ %p, key %x: %d", len, s + ofs, key, ok)); + MG_DEBUG(("Sector space left: %lu bytes", ss - ofs - needed_aligned)); + } else { + MG_ERROR(("Sector is full")); + } + } + return ok; +} +#else +bool mg_flash_save(void *sector, uint32_t key, const void *buf, size_t len) { + (void) sector, (void) key, (void) buf, (void) len; + return false; +} +bool mg_flash_load(void *sector, uint32_t key, void *buf, size_t len) { + (void) sector, (void) key, (void) buf, (void) len; + return false; +} +#endif + +#ifdef MG_ENABLE_LINES +#line 1 "src/device_stm32h5.c" +#endif + + + +#if MG_DEVICE == MG_DEVICE_STM32H5 + +#define FLASH_BASE 0x40022000 // Base address of the flash controller +#define FLASH_KEYR (FLASH_BASE + 0x4) // See RM0481 7.11 +#define FLASH_OPTKEYR (FLASH_BASE + 0xc) +#define FLASH_OPTCR (FLASH_BASE + 0x1c) +#define FLASH_NSSR (FLASH_BASE + 0x20) +#define FLASH_NSCR (FLASH_BASE + 0x28) +#define FLASH_NSCCR (FLASH_BASE + 0x30) +#define FLASH_OPTSR_CUR (FLASH_BASE + 0x50) +#define FLASH_OPTSR_PRG (FLASH_BASE + 0x54) + +void *mg_flash_start(void) { + return (void *) 0x08000000; +} +size_t mg_flash_size(void) { + return 2 * 1024 * 1024; // 2Mb +} +size_t mg_flash_sector_size(void) { + return 8 * 1024; // 8k +} +size_t mg_flash_write_align(void) { + return 16; // 128 bit +} +int mg_flash_bank(void) { + return MG_REG(FLASH_OPTCR) & MG_BIT(31) ? 2 : 1; +} + +static void flash_unlock(void) { + static bool unlocked = false; + if (unlocked == false) { + MG_REG(FLASH_KEYR) = 0x45670123; + MG_REG(FLASH_KEYR) = 0Xcdef89ab; + MG_REG(FLASH_OPTKEYR) = 0x08192a3b; + MG_REG(FLASH_OPTKEYR) = 0x4c5d6e7f; + unlocked = true; + } +} + +static int flash_page_start(volatile uint32_t *dst) { + char *base = (char *) mg_flash_start(), *end = base + mg_flash_size(); + volatile char *p = (char *) dst; + return p >= base && p < end && ((p - base) % mg_flash_sector_size()) == 0; +} + +static bool flash_is_err(void) { + return MG_REG(FLASH_NSSR) & ((MG_BIT(8) - 1) << 17); // RM0481 7.11.9 +} + +static void flash_wait(void) { + while ((MG_REG(FLASH_NSSR) & MG_BIT(0)) && + (MG_REG(FLASH_NSSR) & MG_BIT(16)) == 0) { + (void) 0; + } +} + +static void flash_clear_err(void) { + flash_wait(); // Wait until ready + MG_REG(FLASH_NSCCR) = ((MG_BIT(9) - 1) << 16U); // Clear all errors +} + +static bool flash_bank_is_swapped(void) { + return MG_REG(FLASH_OPTCR) & MG_BIT(31); // RM0481 7.11.8 +} + +bool mg_flash_erase(void *location) { + bool ok = false; + if (flash_page_start(location) == false) { + MG_ERROR(("%p is not on a sector boundary")); + } else { + uintptr_t diff = (char *) location - (char *) mg_flash_start(); + uint32_t sector = diff / mg_flash_sector_size(); + flash_unlock(); + flash_clear_err(); + MG_REG(FLASH_NSCR) = 0; + if ((sector < 128 && flash_bank_is_swapped()) || + (sector > 127 && !flash_bank_is_swapped())) { + MG_REG(FLASH_NSCR) |= MG_BIT(31); // Set FLASH_CR_BKSEL + } + if (sector > 127) sector -= 128; + MG_REG(FLASH_NSCR) |= MG_BIT(2) | (sector << 6); // Erase | sector_num + MG_REG(FLASH_NSCR) |= MG_BIT(5); // Start erasing + flash_wait(); + ok = !flash_is_err(); + MG_DEBUG(("Erase sector %lu @ %p: %s. CR %#lx SR %#lx", sector, location, + ok ? "ok" : "fail", MG_REG(FLASH_NSCR), MG_REG(FLASH_NSSR))); + // mg_hexdump(location, 32); + } + return ok; +} + +bool mg_flash_swap_bank(void) { + uint32_t desired = flash_bank_is_swapped() ? 0 : MG_BIT(31); + flash_unlock(); + flash_clear_err(); + // printf("OPTSR_PRG 1 %#lx\n", FLASH->OPTSR_PRG); + MG_SET_BITS(MG_REG(FLASH_OPTSR_PRG), MG_BIT(31), desired); + // printf("OPTSR_PRG 2 %#lx\n", FLASH->OPTSR_PRG); + MG_REG(FLASH_OPTCR) |= MG_BIT(1); // OPTSTART + while ((MG_REG(FLASH_OPTSR_CUR) & MG_BIT(31)) != desired) (void) 0; + return true; +} + +bool mg_flash_write(void *addr, const void *buf, size_t len) { + if ((len % mg_flash_write_align()) != 0) { + MG_ERROR(("%lu is not aligned to %lu", len, mg_flash_write_align())); + return false; + } + uint32_t *dst = (uint32_t *) addr; + uint32_t *src = (uint32_t *) buf; + uint32_t *end = (uint32_t *) ((char *) buf + len); + bool ok = true; + flash_unlock(); + flash_clear_err(); + MG_ARM_DISABLE_IRQ(); + // MG_DEBUG(("Starting flash write %lu bytes @ %p", len, addr)); + while (ok && src < end) { + if (flash_page_start(dst) && mg_flash_erase(dst) == false) break; + MG_REG(FLASH_NSCR) = MG_BIT(1); // Set programming flag + *(volatile uint32_t *) dst++ = *src++; + flash_wait(); + if (flash_is_err()) ok = false; + } + MG_DEBUG(("Flash write %lu bytes @ %p: %s. CR %#lx SR %#lx", len, dst, + flash_is_err() ? "fail" : "ok", MG_REG(FLASH_NSCR), + MG_REG(FLASH_NSSR))); + if (flash_is_err()) ok = false; + // mg_hexdump(addr, len > 32 ? 32 : len); + // MG_REG(FLASH_NSCR) &= ~MG_BIT(1); // Set programming flag + MG_REG(FLASH_NSCR) = 0; // Clear flags + MG_ARM_ENABLE_IRQ(); + return ok; +} + +void mg_device_reset(void) { + // SCB->AIRCR = ((0x5fa << SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk); + *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; +} +#endif + +#ifdef MG_ENABLE_LINES +#line 1 "src/device_stm32h7.c" +#endif + + + +#if MG_DEVICE == MG_DEVICE_STM32H7 + +#define FLASH_BASE1 0x52002000 // Base address for bank1 +#define FLASH_BASE2 0x52002100 // Base address for bank2 +#define FLASH_KEYR 0x04 // See RM0433 4.9.2 +#define FLASH_OPTKEYR 0x08 +#define FLASH_OPTCR 0x18 +#define FLASH_SR 0x10 +#define FLASH_CR 0x0c +#define FLASH_CCR 0x14 +#define FLASH_OPTSR_CUR 0x1c +#define FLASH_OPTSR_PRG 0x20 + +void *mg_flash_start(void) { + return (void *) 0x08000000; +} +size_t mg_flash_size(void) { + return 2 * 1024 * 1024; // 2Mb +} +size_t mg_flash_sector_size(void) { + return 128 * 1024; // 128k +} +size_t mg_flash_write_align(void) { + return 32; // 256 bit +} +int mg_flash_bank(void) { + return MG_REG(FLASH_BASE1 + FLASH_OPTCR) & MG_BIT(31) ? 2 : 1; +} + +static void flash_unlock(void) { + static bool unlocked = false; + if (unlocked == false) { + MG_REG(FLASH_BASE1 + FLASH_KEYR) = 0x45670123; + MG_REG(FLASH_BASE1 + FLASH_KEYR) = 0xcdef89ab; + MG_REG(FLASH_BASE2 + FLASH_KEYR) = 0x45670123; + MG_REG(FLASH_BASE2 + FLASH_KEYR) = 0xcdef89ab; + MG_REG(FLASH_BASE1 + FLASH_OPTKEYR) = 0x08192a3b; // opt reg is "shared" + MG_REG(FLASH_BASE1 + FLASH_OPTKEYR) = 0x4c5d6e7f; // thus unlock once + unlocked = true; + } +} + +static bool flash_page_start(volatile uint32_t *dst) { + char *base = (char *) mg_flash_start(), *end = base + mg_flash_size(); + volatile char *p = (char *) dst; + return p >= base && p < end && ((p - base) % mg_flash_sector_size()) == 0; +} + +static bool flash_is_err(uint32_t bank) { + return MG_REG(bank + FLASH_SR) & ((MG_BIT(11) - 1) << 17); // RM0433 4.9.5 +} + +static void flash_wait(uint32_t bank) { + while (MG_REG(bank + FLASH_SR) & (MG_BIT(0) | MG_BIT(2))) (void) 0; +} + +static void flash_clear_err(uint32_t bank) { + flash_wait(bank); // Wait until ready + MG_REG(bank + FLASH_CCR) = ((MG_BIT(11) - 1) << 16U); // Clear all errors +} + +static bool flash_bank_is_swapped(uint32_t bank) { + return MG_REG(bank + FLASH_OPTCR) & MG_BIT(31); // RM0433 4.9.7 +} + +// Figure out flash bank based on the address +static uint32_t flash_bank(void *addr) { + size_t ofs = (char *) addr - (char *) mg_flash_start(); + return ofs < mg_flash_size() / 2 ? FLASH_BASE1 : FLASH_BASE2; +} + +bool mg_flash_erase(void *addr) { + bool ok = false; + if (flash_page_start(addr) == false) { + MG_ERROR(("%p is not on a sector boundary", addr)); + } else { + uintptr_t diff = (char *) addr - (char *) mg_flash_start(); + uint32_t sector = diff / mg_flash_sector_size(); + uint32_t bank = flash_bank(addr); + + flash_unlock(); + if (sector > 7) sector -= 8; + // MG_INFO(("Erasing @ %p, sector %lu, bank %#x", addr, sector, bank)); + + flash_clear_err(bank); + MG_REG(bank + FLASH_CR) |= (sector & 7U) << 8U; // Sector to erase + MG_REG(bank + FLASH_CR) |= MG_BIT(2); // Sector erase bit + MG_REG(bank + FLASH_CR) |= MG_BIT(7); // Start erasing + ok = !flash_is_err(bank); + MG_DEBUG(("Erase sector %lu @ %p %s. CR %#lx SR %#lx", sector, addr, + ok ? "ok" : "fail", MG_REG(bank + FLASH_CR), + MG_REG(bank + FLASH_SR))); + // mg_hexdump(addr, 32); + } + return ok; +} + +bool mg_flash_swap_bank() { + uint32_t bank = FLASH_BASE1; + uint32_t desired = flash_bank_is_swapped(bank) ? 0 : MG_BIT(31); + flash_unlock(); + flash_clear_err(bank); + // printf("OPTSR_PRG 1 %#lx\n", FLASH->OPTSR_PRG); + MG_SET_BITS(MG_REG(bank + FLASH_OPTSR_PRG), MG_BIT(31), desired); + // printf("OPTSR_PRG 2 %#lx\n", FLASH->OPTSR_PRG); + MG_REG(bank + FLASH_OPTCR) |= MG_BIT(1); // OPTSTART + while ((MG_REG(bank + FLASH_OPTSR_CUR) & MG_BIT(31)) != desired) (void) 0; + return true; +} + +bool mg_flash_write(void *addr, const void *buf, size_t len) { + if ((len % mg_flash_write_align()) != 0) { + MG_ERROR(("%lu is not aligned to %lu", len, mg_flash_write_align())); + return false; + } + uint32_t bank = flash_bank(addr); + uint32_t *dst = (uint32_t *) addr; + uint32_t *src = (uint32_t *) buf; + uint32_t *end = (uint32_t *) ((char *) buf + len); + bool ok = true; + flash_unlock(); + flash_clear_err(bank); + MG_ARM_DISABLE_IRQ(); + MG_REG(bank + FLASH_CR) = MG_BIT(1); // Set programming flag + // MG_INFO(("Writing flash @ %p, %lu bytes", addr, len)); + while (ok && src < end) { + if (flash_page_start(dst) && mg_flash_erase(dst) == false) break; + *(volatile uint32_t *) dst++ = *src++; + flash_wait(bank); + if (flash_is_err(bank)) ok = false; + } + MG_DEBUG(("Flash write %lu bytes @ %p: %s. CR %#lx SR %#lx", len, dst, + ok ? "ok" : "fail", MG_REG(bank + FLASH_CR), + MG_REG(bank + FLASH_SR))); + // mg_hexdump(addr, len > 32 ? 32 : len); + MG_REG(bank + FLASH_CR) &= ~MG_BIT(1); // Clear programming flag + MG_ARM_ENABLE_IRQ(); + return ok; +} + +void mg_device_reset(void) { + // SCB->AIRCR = ((0x5fa << SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk); + *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; +} +#endif + #ifdef MG_ENABLE_LINES #line 1 "src/dns.c" #endif @@ -4989,7 +5488,7 @@ size_t mg_ota_size(int fw) { -// This OTA implementation uses the internal flash API outlined in sys.h +// This OTA implementation uses the internal flash API outlined in device.h // It splits flash into 2 equal partitions, and stores OTA status in the // last sector of the partition. @@ -6693,505 +7192,6 @@ bool mg_path_is_sane(const char *path) { return true; } -#ifdef MG_ENABLE_LINES -#line 1 "src/sys_dummy.c" -#endif - - -#if MG_SYS == MG_SYS_NONE -void *mg_flash_start(void) { - return NULL; -} -size_t mg_flash_size(void) { - return 0; -} -size_t mg_flash_sector_size(void) { - return 0; -} -size_t mg_flash_write_align(void) { - return 0; -} -int mg_flash_bank(void) { - return 0; -} -bool mg_flash_erase(void *location) { - (void) location; - return false; -} -bool mg_flash_swap_bank(void) { - return true; -} -bool mg_flash_write(void *addr, const void *buf, size_t len) { - (void) addr, (void) buf, (void) len; - return false; -} -void mg_sys_reset(void) { -} -#endif - -#ifdef MG_ENABLE_LINES -#line 1 "src/sys_flash.c" -#endif - - -#if MG_SYS == MG_SYS_STM32H7 || MG_SYS == MG_SYS_STM32H5 -// Flash can be written only if it is erased. Erased flash is 0xff (all bits 1) -// Writes must be mg_flash_write_align() - aligned. Thus if we want to save an -// object, we pad it at the end for alignment. -// -// Objects in the flash sector are stored sequentially: -// | 32-bit size | 32-bit KEY | ..data.. | ..pad.. | 32-bit size | ...... -// -// In order to get to the next object, read its size, then align up. - -// Traverse the list of saved objects -size_t mg_flash_next(char *p, char *end, uint32_t *key, size_t *size) { - size_t aligned_size = 0, align = mg_flash_write_align(), left = end - p; - uint32_t *p32 = (uint32_t *) p, min_size = sizeof(uint32_t) * 2; - if (p32[0] != 0xffffffff && left > MG_ROUND_UP(min_size, align)) { - if (size) *size = (size_t) p32[0]; - if (key) *key = p32[1]; - aligned_size = MG_ROUND_UP(p32[0] + sizeof(uint32_t) * 2, align); - if (left < aligned_size) aligned_size = 0; // Out of bounds, fail - } - return aligned_size; -} - -// Return the last sector of Bank 2 -static char *flash_last_sector(void) { - size_t ss = mg_flash_sector_size(), size = mg_flash_size(); - char *base = (char *) mg_flash_start(), *last = base + size - ss; - if (mg_flash_bank() == 2) last -= size / 2; - return last; -} - -// Find a saved object with a given key -bool mg_flash_load(void *sector, uint32_t key, void *buf, size_t len) { - char *base = (char *) mg_flash_start(), *s = (char *) sector, *res = NULL; - size_t ss = mg_flash_sector_size(), ofs = 0, n, sz; - bool ok = false; - if (s == NULL) s = flash_last_sector(); - if (s < base || s >= base + mg_flash_size()) { - MG_ERROR(("%p is outsize of flash", sector)); - } else if (((s - base) % ss) != 0) { - MG_ERROR(("%p is not a sector boundary", sector)); - } else { - uint32_t k, scanned = 0; - while ((n = mg_flash_next(s + ofs, s + ss, &k, &sz)) > 0) { - // MG_DEBUG((" > obj %lu, ofs %lu, key %x/%x", scanned, ofs, k, key)); - // mg_hexdump(s + ofs, n); - if (k == key && sz == len) { - res = s + ofs + sizeof(uint32_t) * 2; - memcpy(buf, res, len); // Copy object - ok = true; // Keep scanning for the newer versions of it - } - ofs += n, scanned++; - } - MG_DEBUG(("Scanned %u objects, key %x is @ %p", scanned, key, res)); - } - return ok; -} - -static bool mg_flash_writev(char *location, struct mg_str *strings, size_t n) { - size_t align = mg_flash_write_align(), i, j, k = 0, nwritten = 0; - char buf[align]; - bool ok = true; - for (i = 0; ok && i < n; i++) { - for (j = 0; ok && j < strings[i].len; j++) { - buf[k++] = strings[i].ptr[j]; - if (k >= sizeof(buf)) { - ok = mg_flash_write(location + nwritten, buf, sizeof(buf)); - k = 0, nwritten += sizeof(buf); - } - } - } - if (k > 0) { - while (k < sizeof(buf)) buf[k++] = 0xff; - ok = mg_flash_write(location + nwritten, buf, sizeof(buf)); - } - return ok; -} - -// For all saved objects in the sector, delete old versions of objects -static void mg_flash_sector_cleanup(char *sector) { - // Buffer all saved objects into an IO buffer (backed by RAM) - // erase sector, and re-save them. - struct mg_iobuf io = {0, 0, 0, 2048}; - size_t ss = mg_flash_sector_size(); - size_t n, size, size2, ofs = 0, hs = sizeof(uint32_t) * 2; - uint32_t key; - // Traverse all objects - MG_DEBUG(("Cleaning up sector %p", sector)); - while ((n = mg_flash_next(sector + ofs, sector + ss, &key, &size)) > 0) { - // Delete an old copy of this object in the cache - for (size_t o = 0; o < io.len; o += size2 + hs) { - uint32_t k = *(uint32_t *) (io.buf + o + sizeof(uint32_t)); - size2 = *(uint32_t *) (io.buf + o); - if (k == key) { - mg_iobuf_del(&io, o, size2 + hs); - break; - } - } - // And add the new copy - mg_iobuf_add(&io, io.len, sector + ofs, size + hs); - ofs += n; - } - // All objects are cached in RAM now - if (mg_flash_erase(sector)) { // Erase sector. If successful, - for (ofs = 0; ofs < io.len; ofs += size + hs) { // Traverse cached objects - size = *(uint32_t *) (io.buf + ofs); - key = *(uint32_t *) (io.buf + ofs + sizeof(uint32_t)); - mg_flash_save(sector, key, io.buf + ofs + hs, size); // Save to flash - } - } - mg_iobuf_free(&io); -} - -// Save an object with a given key - append to the end of an object list -bool mg_flash_save(void *sector, uint32_t key, const void *buf, size_t len) { - char *base = (char *) mg_flash_start(), *s = (char *) sector; - size_t ss = mg_flash_sector_size(), ofs = 0, n; - bool ok = false; - if (s == NULL) s = flash_last_sector(); - if (s < base || s >= base + mg_flash_size()) { - MG_ERROR(("%p is outsize of flash", sector)); - } else if (((s - base) % ss) != 0) { - MG_ERROR(("%p is not a sector boundary", sector)); - } else { - size_t needed = sizeof(uint32_t) * 2 + len; - size_t needed_aligned = MG_ROUND_UP(needed, mg_flash_write_align()); - while ((n = mg_flash_next(s + ofs, s + ss, NULL, NULL)) > 0) ofs += n; - - // If there is not enough space left, cleanup sector and re-eval ofs - if (ofs + needed_aligned > ss) { - mg_flash_sector_cleanup(s); - ofs = 0; - while ((n = mg_flash_next(s + ofs, s + ss, NULL, NULL)) > 0) ofs += n; - } - - if (ofs + needed_aligned <= ss) { - // Enough space to save this object - uint32_t hdr[2] = {(uint32_t) len, key}; - struct mg_str data[] = {mg_str_n((char *) hdr, sizeof(hdr)), - mg_str_n(buf, len)}; - ok = mg_flash_writev(s + ofs, data, 2); - MG_DEBUG(("Saving %lu bytes @ %p, key %x: %d", len, s + ofs, key, ok)); - MG_DEBUG(("Sector space left: %lu bytes", ss - ofs - needed_aligned)); - } else { - MG_ERROR(("Sector is full")); - } - } - return ok; -} -#else -bool mg_flash_save(void *sector, uint32_t key, const void *buf, size_t len) { - (void) sector, (void) key, (void) buf, (void) len; - return false; -} -bool mg_flash_load(void *sector, uint32_t key, void *buf, size_t len) { - (void) sector, (void) key, (void) buf, (void) len; - return false; -} -#endif - -#ifdef MG_ENABLE_LINES -#line 1 "src/sys_stm32h5.c" -#endif - - - -#if MG_SYS == MG_SYS_STM32H5 - -#define FLASH_BASE 0x40022000 // Base address of the flash controller -#define FLASH_KEYR (FLASH_BASE + 0x4) // See RM0481 7.11 -#define FLASH_OPTKEYR (FLASH_BASE + 0xc) -#define FLASH_OPTCR (FLASH_BASE + 0x1c) -#define FLASH_NSSR (FLASH_BASE + 0x20) -#define FLASH_NSCR (FLASH_BASE + 0x28) -#define FLASH_NSCCR (FLASH_BASE + 0x30) -#define FLASH_OPTSR_CUR (FLASH_BASE + 0x50) -#define FLASH_OPTSR_PRG (FLASH_BASE + 0x54) - -void *mg_flash_start(void) { - return (void *) 0x08000000; -} -size_t mg_flash_size(void) { - return 2 * 1024 * 1024; // 2Mb -} -size_t mg_flash_sector_size(void) { - return 8 * 1024; // 8k -} -size_t mg_flash_write_align(void) { - return 16; // 128 bit -} -int mg_flash_bank(void) { - return MG_REG(FLASH_OPTCR) & MG_BIT(31) ? 2 : 1; -} - -static void flash_unlock(void) { - static bool unlocked = false; - if (unlocked == false) { - MG_REG(FLASH_KEYR) = 0x45670123; - MG_REG(FLASH_KEYR) = 0Xcdef89ab; - MG_REG(FLASH_OPTKEYR) = 0x08192a3b; - MG_REG(FLASH_OPTKEYR) = 0x4c5d6e7f; - unlocked = true; - } -} - -static int flash_page_start(volatile uint32_t *dst) { - char *base = (char *) mg_flash_start(), *end = base + mg_flash_size(); - volatile char *p = (char *) dst; - return p >= base && p < end && ((p - base) % mg_flash_sector_size()) == 0; -} - -static bool flash_is_err(void) { - return MG_REG(FLASH_NSSR) & ((MG_BIT(8) - 1) << 17); // RM0481 7.11.9 -} - -static void flash_wait(void) { - while ((MG_REG(FLASH_NSSR) & MG_BIT(0)) && - (MG_REG(FLASH_NSSR) & MG_BIT(16)) == 0) { - (void) 0; - } -} - -static void flash_clear_err(void) { - flash_wait(); // Wait until ready - MG_REG(FLASH_NSCCR) = ((MG_BIT(9) - 1) << 16U); // Clear all errors -} - -static bool flash_bank_is_swapped(void) { - return MG_REG(FLASH_OPTCR) & MG_BIT(31); // RM0481 7.11.8 -} - -bool mg_flash_erase(void *location) { - bool ok = false; - if (flash_page_start(location) == false) { - MG_ERROR(("%p is not on a sector boundary")); - } else { - uintptr_t diff = (char *) location - (char *) mg_flash_start(); - uint32_t sector = diff / mg_flash_sector_size(); - flash_unlock(); - flash_clear_err(); - MG_REG(FLASH_NSCR) = 0; - if ((sector < 128 && flash_bank_is_swapped()) || - (sector > 127 && !flash_bank_is_swapped())) { - MG_REG(FLASH_NSCR) |= MG_BIT(31); // Set FLASH_CR_BKSEL - } - if (sector > 127) sector -= 128; - MG_REG(FLASH_NSCR) |= MG_BIT(2) | (sector << 6); // Erase | sector_num - MG_REG(FLASH_NSCR) |= MG_BIT(5); // Start erasing - flash_wait(); - ok = !flash_is_err(); - MG_DEBUG(("Erase sector %lu @ %p: %s. CR %#lx SR %#lx", sector, location, - ok ? "ok" : "fail", MG_REG(FLASH_NSCR), MG_REG(FLASH_NSSR))); - // mg_hexdump(location, 32); - } - return ok; -} - -bool mg_flash_swap_bank(void) { - uint32_t desired = flash_bank_is_swapped() ? 0 : MG_BIT(31); - flash_unlock(); - flash_clear_err(); - // printf("OPTSR_PRG 1 %#lx\n", FLASH->OPTSR_PRG); - MG_SET_BITS(MG_REG(FLASH_OPTSR_PRG), MG_BIT(31), desired); - // printf("OPTSR_PRG 2 %#lx\n", FLASH->OPTSR_PRG); - MG_REG(FLASH_OPTCR) |= MG_BIT(1); // OPTSTART - while ((MG_REG(FLASH_OPTSR_CUR) & MG_BIT(31)) != desired) (void) 0; - return true; -} - -bool mg_flash_write(void *addr, const void *buf, size_t len) { - if ((len % mg_flash_write_align()) != 0) { - MG_ERROR(("%lu is not aligned to %lu", len, mg_flash_write_align())); - return false; - } - uint32_t *dst = (uint32_t *) addr; - uint32_t *src = (uint32_t *) buf; - uint32_t *end = (uint32_t *) ((char *) buf + len); - bool ok = true; - flash_unlock(); - flash_clear_err(); - MG_ARM_DISABLE_IRQ(); - // MG_DEBUG(("Starting flash write %lu bytes @ %p", len, addr)); - while (ok && src < end) { - if (flash_page_start(dst) && mg_flash_erase(dst) == false) break; - MG_REG(FLASH_NSCR) = MG_BIT(1); // Set programming flag - *(volatile uint32_t *) dst++ = *src++; - flash_wait(); - if (flash_is_err()) ok = false; - } - MG_DEBUG(("Flash write %lu bytes @ %p: %s. CR %#lx SR %#lx", len, dst, - flash_is_err() ? "fail" : "ok", MG_REG(FLASH_NSCR), - MG_REG(FLASH_NSSR))); - if (flash_is_err()) ok = false; - // mg_hexdump(addr, len > 32 ? 32 : len); - // MG_REG(FLASH_NSCR) &= ~MG_BIT(1); // Set programming flag - MG_REG(FLASH_NSCR) = 0; // Clear flags - MG_ARM_ENABLE_IRQ(); - return ok; -} - -void mg_sys_reset(void) { - // SCB->AIRCR = ((0x5fa << SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk); - *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; -} -#endif - -#ifdef MG_ENABLE_LINES -#line 1 "src/sys_stm32h7.c" -#endif - - - -#if MG_SYS == MG_SYS_STM32H7 - -#define FLASH_BASE1 0x52002000 // Base address for bank1 -#define FLASH_BASE2 0x52002100 // Base address for bank2 -#define FLASH_KEYR 0x04 // See RM0433 4.9.2 -#define FLASH_OPTKEYR 0x08 -#define FLASH_OPTCR 0x18 -#define FLASH_SR 0x10 -#define FLASH_CR 0x0c -#define FLASH_CCR 0x14 -#define FLASH_OPTSR_CUR 0x1c -#define FLASH_OPTSR_PRG 0x20 - -void *mg_flash_start(void) { - return (void *) 0x08000000; -} -size_t mg_flash_size(void) { - return 2 * 1024 * 1024; // 2Mb -} -size_t mg_flash_sector_size(void) { - return 128 * 1024; // 128k -} -size_t mg_flash_write_align(void) { - return 32; // 256 bit -} -int mg_flash_bank(void) { - return MG_REG(FLASH_BASE1 + FLASH_OPTCR) & MG_BIT(31) ? 2 : 1; -} - -static void flash_unlock(void) { - static bool unlocked = false; - if (unlocked == false) { - MG_REG(FLASH_BASE1 + FLASH_KEYR) = 0x45670123; - MG_REG(FLASH_BASE1 + FLASH_KEYR) = 0xcdef89ab; - MG_REG(FLASH_BASE2 + FLASH_KEYR) = 0x45670123; - MG_REG(FLASH_BASE2 + FLASH_KEYR) = 0xcdef89ab; - MG_REG(FLASH_BASE1 + FLASH_OPTKEYR) = 0x08192a3b; // opt reg is "shared" - MG_REG(FLASH_BASE1 + FLASH_OPTKEYR) = 0x4c5d6e7f; // thus unlock once - unlocked = true; - } -} - -static bool flash_page_start(volatile uint32_t *dst) { - char *base = (char *) mg_flash_start(), *end = base + mg_flash_size(); - volatile char *p = (char *) dst; - return p >= base && p < end && ((p - base) % mg_flash_sector_size()) == 0; -} - -static bool flash_is_err(uint32_t bank) { - return MG_REG(bank + FLASH_SR) & ((MG_BIT(11) - 1) << 17); // RM0433 4.9.5 -} - -static void flash_wait(uint32_t bank) { - while (MG_REG(bank + FLASH_SR) & (MG_BIT(0) | MG_BIT(2))) (void) 0; -} - -static void flash_clear_err(uint32_t bank) { - flash_wait(bank); // Wait until ready - MG_REG(bank + FLASH_CCR) = ((MG_BIT(11) - 1) << 16U); // Clear all errors -} - -static bool flash_bank_is_swapped(uint32_t bank) { - return MG_REG(bank + FLASH_OPTCR) & MG_BIT(31); // RM0433 4.9.7 -} - -// Figure out flash bank based on the address -static uint32_t flash_bank(void *addr) { - size_t ofs = (char *) addr - (char *) mg_flash_start(); - return ofs < mg_flash_size() / 2 ? FLASH_BASE1 : FLASH_BASE2; -} - -bool mg_flash_erase(void *addr) { - bool ok = false; - if (flash_page_start(addr) == false) { - MG_ERROR(("%p is not on a sector boundary", addr)); - } else { - uintptr_t diff = (char *) addr - (char *) mg_flash_start(); - uint32_t sector = diff / mg_flash_sector_size(); - uint32_t bank = flash_bank(addr); - - flash_unlock(); - if (sector > 7) sector -= 8; - // MG_INFO(("Erasing @ %p, sector %lu, bank %#x", addr, sector, bank)); - - flash_clear_err(bank); - MG_REG(bank + FLASH_CR) |= (sector & 7U) << 8U; // Sector to erase - MG_REG(bank + FLASH_CR) |= MG_BIT(2); // Sector erase bit - MG_REG(bank + FLASH_CR) |= MG_BIT(7); // Start erasing - ok = !flash_is_err(bank); - MG_DEBUG(("Erase sector %lu @ %p %s. CR %#lx SR %#lx", sector, addr, - ok ? "ok" : "fail", MG_REG(bank + FLASH_CR), - MG_REG(bank + FLASH_SR))); - // mg_hexdump(addr, 32); - } - return ok; -} - -bool mg_flash_swap_bank() { - uint32_t bank = FLASH_BASE1; - uint32_t desired = flash_bank_is_swapped(bank) ? 0 : MG_BIT(31); - flash_unlock(); - flash_clear_err(bank); - // printf("OPTSR_PRG 1 %#lx\n", FLASH->OPTSR_PRG); - MG_SET_BITS(MG_REG(bank + FLASH_OPTSR_PRG), MG_BIT(31), desired); - // printf("OPTSR_PRG 2 %#lx\n", FLASH->OPTSR_PRG); - MG_REG(bank + FLASH_OPTCR) |= MG_BIT(1); // OPTSTART - while ((MG_REG(bank + FLASH_OPTSR_CUR) & MG_BIT(31)) != desired) (void) 0; - return true; -} - -bool mg_flash_write(void *addr, const void *buf, size_t len) { - if ((len % mg_flash_write_align()) != 0) { - MG_ERROR(("%lu is not aligned to %lu", len, mg_flash_write_align())); - return false; - } - uint32_t bank = flash_bank(addr); - uint32_t *dst = (uint32_t *) addr; - uint32_t *src = (uint32_t *) buf; - uint32_t *end = (uint32_t *) ((char *) buf + len); - bool ok = true; - flash_unlock(); - flash_clear_err(bank); - MG_ARM_DISABLE_IRQ(); - MG_REG(bank + FLASH_CR) = MG_BIT(1); // Set programming flag - // MG_INFO(("Writing flash @ %p, %lu bytes", addr, len)); - while (ok && src < end) { - if (flash_page_start(dst) && mg_flash_erase(dst) == false) break; - *(volatile uint32_t *) dst++ = *src++; - flash_wait(bank); - if (flash_is_err(bank)) ok = false; - } - MG_DEBUG(("Flash write %lu bytes @ %p: %s. CR %#lx SR %#lx", len, dst, - ok ? "ok" : "fail", MG_REG(bank + FLASH_CR), - MG_REG(bank + FLASH_SR))); - // mg_hexdump(addr, len > 32 ? 32 : len); - MG_REG(bank + FLASH_CR) &= ~MG_BIT(1); // Clear programming flag - MG_ARM_ENABLE_IRQ(); - return ok; -} - -void mg_sys_reset(void) { - // SCB->AIRCR = ((0x5fa << SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk); - *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; -} -#endif - #ifdef MG_ENABLE_LINES #line 1 "src/timer.c" #endif diff --git a/mongoose.h b/mongoose.h index 7fb5fb9b..de7debda 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1701,13 +1701,13 @@ bool mg_ota_rollback(void); // Rollback to the previous firmware -#define MG_SYS_NONE 0 // Dummy system -#define MG_SYS_STM32H5 1 // STM32 H5 -#define MG_SYS_STM32H7 2 // STM32 H7 -#define MG_SYS_CUSTOM 100 // Custom implementation +#define MG_DEVICE_NONE 0 // Dummy system +#define MG_DEVICE_STM32H5 1 // STM32 H5 +#define MG_DEVICE_STM32H7 2 // STM32 H7 +#define MG_DEVICE_CUSTOM 100 // Custom implementation -#ifndef MG_SYS -#define MG_SYS MG_SYS_NONE +#ifndef MG_DEVICE +#define MG_DEVICE MG_DEVICE_NONE #endif // Flash information @@ -1727,7 +1727,7 @@ bool mg_flash_swap_bank(void); bool mg_flash_load(void *sector, uint32_t key, void *buf, size_t len); bool mg_flash_save(void *sector, uint32_t key, const void *buf, size_t len); -void mg_sys_reset(void); // Reboot device immediately +void mg_device_reset(void); // Reboot device immediately diff --git a/src/sys.h b/src/device.h similarity index 76% rename from src/sys.h rename to src/device.h index f384a488..d73397e4 100644 --- a/src/sys.h +++ b/src/device.h @@ -5,13 +5,13 @@ #include "arch.h" -#define MG_SYS_NONE 0 // Dummy system -#define MG_SYS_STM32H5 1 // STM32 H5 -#define MG_SYS_STM32H7 2 // STM32 H7 -#define MG_SYS_CUSTOM 100 // Custom implementation +#define MG_DEVICE_NONE 0 // Dummy system +#define MG_DEVICE_STM32H5 1 // STM32 H5 +#define MG_DEVICE_STM32H7 2 // STM32 H7 +#define MG_DEVICE_CUSTOM 100 // Custom implementation -#ifndef MG_SYS -#define MG_SYS MG_SYS_NONE +#ifndef MG_DEVICE +#define MG_DEVICE MG_DEVICE_NONE #endif // Flash information @@ -31,4 +31,4 @@ bool mg_flash_swap_bank(void); bool mg_flash_load(void *sector, uint32_t key, void *buf, size_t len); bool mg_flash_save(void *sector, uint32_t key, const void *buf, size_t len); -void mg_sys_reset(void); // Reboot device immediately +void mg_device_reset(void); // Reboot device immediately diff --git a/src/sys_dummy.c b/src/device_dummy.c similarity index 85% rename from src/sys_dummy.c rename to src/device_dummy.c index 80834e6e..8eb5a759 100644 --- a/src/sys_dummy.c +++ b/src/device_dummy.c @@ -1,6 +1,6 @@ -#include "sys.h" +#include "device.h" -#if MG_SYS == MG_SYS_NONE +#if MG_DEVICE == MG_DEVICE_NONE void *mg_flash_start(void) { return NULL; } @@ -27,6 +27,6 @@ bool mg_flash_write(void *addr, const void *buf, size_t len) { (void) addr, (void) buf, (void) len; return false; } -void mg_sys_reset(void) { +void mg_device_reset(void) { } #endif diff --git a/src/sys_flash.c b/src/device_flash.c similarity index 98% rename from src/sys_flash.c rename to src/device_flash.c index a764a5d9..70d759af 100644 --- a/src/sys_flash.c +++ b/src/device_flash.c @@ -1,6 +1,6 @@ -#include "sys.h" +#include "device.h" -#if MG_SYS == MG_SYS_STM32H7 || MG_SYS == MG_SYS_STM32H5 +#if MG_DEVICE == MG_DEVICE_STM32H7 || MG_DEVICE == MG_DEVICE_STM32H5 // Flash can be written only if it is erased. Erased flash is 0xff (all bits 1) // Writes must be mg_flash_write_align() - aligned. Thus if we want to save an // object, we pad it at the end for alignment. diff --git a/src/sys_stm32h5.c b/src/device_stm32h5.c similarity index 98% rename from src/sys_stm32h5.c rename to src/device_stm32h5.c index eaa74b74..e4c5d332 100644 --- a/src/sys_stm32h5.c +++ b/src/device_stm32h5.c @@ -1,7 +1,7 @@ #include "log.h" -#include "sys.h" +#include "device.h" -#if MG_SYS == MG_SYS_STM32H5 +#if MG_DEVICE == MG_DEVICE_STM32H5 #define FLASH_BASE 0x40022000 // Base address of the flash controller #define FLASH_KEYR (FLASH_BASE + 0x4) // See RM0481 7.11 @@ -135,7 +135,7 @@ bool mg_flash_write(void *addr, const void *buf, size_t len) { return ok; } -void mg_sys_reset(void) { +void mg_device_reset(void) { // SCB->AIRCR = ((0x5fa << SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk); *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; } diff --git a/src/sys_stm32h7.c b/src/device_stm32h7.c similarity index 98% rename from src/sys_stm32h7.c rename to src/device_stm32h7.c index ae3b93e9..b33ca15d 100644 --- a/src/sys_stm32h7.c +++ b/src/device_stm32h7.c @@ -1,7 +1,7 @@ #include "log.h" -#include "sys.h" +#include "device.h" -#if MG_SYS == MG_SYS_STM32H7 +#if MG_DEVICE == MG_DEVICE_STM32H7 #define FLASH_BASE1 0x52002000 // Base address for bank1 #define FLASH_BASE2 0x52002100 // Base address for bank2 @@ -141,7 +141,7 @@ bool mg_flash_write(void *addr, const void *buf, size_t len) { return ok; } -void mg_sys_reset(void) { +void mg_device_reset(void) { // SCB->AIRCR = ((0x5fa << SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk); *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; } diff --git a/src/ota_flash.c b/src/ota_flash.c index 5e4e5490..da10757a 100644 --- a/src/ota_flash.c +++ b/src/ota_flash.c @@ -1,9 +1,9 @@ #include "arch.h" #include "log.h" #include "ota.h" -#include "sys.h" +#include "device.h" -// This OTA implementation uses the internal flash API outlined in sys.h +// This OTA implementation uses the internal flash API outlined in device.h // It splits flash into 2 equal partitions, and stores OTA status in the // last sector of the partition.