From 5c582c35d82d73cfe16430d5d67268528e08b576 Mon Sep 17 00:00:00 2001 From: cpq Date: Tue, 16 Dec 2025 05:10:34 +0000 Subject: [PATCH] ota_frdm -> ota_rw612 --- mongoose.c | 736 ++++++++++++++++---------------- mongoose.h | 74 ++-- src/ota.h | 4 +- src/{ota_frdm.c => ota_rw612.c} | 2 +- 4 files changed, 408 insertions(+), 408 deletions(-) rename src/{ota_frdm.c => ota_rw612.c} (99%) diff --git a/mongoose.c b/mongoose.c index 6ff5a96a..756909a0 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7136,374 +7136,6 @@ bool mg_ota_end(void) { #endif -#ifdef MG_ENABLE_LINES -#line 1 "src/ota_frdm.c" -#endif - - - - -#if MG_OTA == MG_OTA_FRDM - -MG_IRAM static bool mg_frdm_write(void *, const void *, size_t); -static bool mg_frdm_swap(void); - -static struct mg_flash s_mg_flash_frdm = {(void *) 0x08000000, // Start, - 0x200000, // Size - 0x1000, // Sector size - 0x100, // Align - mg_frdm_write, - mg_frdm_swap}; - -struct mg_flexspi_lut_seq { - uint8_t seqNum; - uint8_t seqId; - uint16_t reserved; -}; - -struct mg_flexspi_mem_config { - uint32_t tag; - uint32_t version; - uint32_t reserved0; - uint8_t readSampleClkSrc; - uint8_t csHoldTime; - uint8_t csSetupTime; - uint8_t columnAddressWidth; - uint8_t deviceModeCfgEnable; - uint8_t deviceModeType; - uint16_t waitTimeCfgCommands; - struct mg_flexspi_lut_seq deviceModeSeq; - uint32_t deviceModeArg; - uint8_t configCmdEnable; - uint8_t configModeType[3]; - struct mg_flexspi_lut_seq configCmdSeqs[3]; - uint32_t reserved1; - uint32_t configCmdArgs[3]; - uint32_t reserved2; - uint32_t controllerMiscOption; - uint8_t deviceType; - uint8_t sflashPadType; - uint8_t serialClkFreq; - uint8_t lutCustomSeqEnable; - uint32_t reserved3[2]; - uint32_t sflashA1Size; - uint32_t sflashA2Size; - uint32_t sflashB1Size; - uint32_t sflashB2Size; - uint32_t csPadSettingOverride; - uint32_t sclkPadSettingOverride; - uint32_t dataPadSettingOverride; - uint32_t dqsPadSettingOverride; - uint32_t timeoutInMs; - uint32_t commandInterval; - uint16_t dataValidTime[2]; - uint16_t busyOffset; - uint16_t busyBitPolarity; - uint32_t lookupTable[64]; - struct mg_flexspi_lut_seq lutCustomSeq[12]; - uint32_t reserved4[4]; -}; - -struct mg_flexspi_nor_config { - struct mg_flexspi_mem_config memConfig; - uint32_t pageSize; - uint32_t sectorSize; - uint8_t ipcmdSerialClkFreq; - uint8_t isUniformBlockSize; - uint8_t isDataOrderSwapped; - uint8_t reserved0[1]; - uint8_t serialNorType; - uint8_t needExitNoCmdMode; - uint8_t halfClkForNonReadCmd; - uint8_t needRestoreNoCmdMode; - uint32_t blockSize; - uint32_t flashStateCtx; - uint32_t reserve2[10]; -}; - -struct mg_flexspi_nor_driver_interface { - uint32_t version; - uint32_t (*init)(uint32_t instance, struct mg_flexspi_nor_config *config); - uint32_t (*wait_busy)(uint32_t instance, struct mg_flexspi_nor_config *config, - uint32_t address, bool keepState); - uint32_t (*page_program)(uint32_t instance, - struct mg_flexspi_nor_config *config, - uint32_t dstAddr, const uint32_t *src, - bool keepState); - uint32_t (*erase_all)(uint32_t instance, - struct mg_flexspi_nor_config *config); - uint32_t (*erase)(uint32_t instance, struct mg_flexspi_nor_config *config, - uint32_t start, uint32_t length); - uint32_t (*erase_sector)(uint32_t instance, - struct mg_flexspi_nor_config *config, - uint32_t address); - uint32_t (*erase_block)(uint32_t instance, - struct mg_flexspi_nor_config *config, - uint32_t address); - uint32_t (*read)(uint32_t instance, struct mg_flexspi_nor_config *config, - uint32_t *dst, uint32_t start, uint32_t bytes); - void (*config_clock)(uint32_t instance, uint32_t freqOption, - uint32_t sampleClkMode); - uint32_t (*set_clock_source)(uint32_t clockSrc); - uint32_t (*get_config)(uint32_t instance, - struct mg_flexspi_nor_config *config, - uint32_t *option); - void (*hw_reset)(uint32_t instance, uint32_t reset_logic); - uint32_t (*xfer)(uint32_t instance, char *xfer); - uint32_t (*update_lut)(uint32_t instance, uint32_t seqIndex, - const uint32_t *lutBase, uint32_t numberOfSeq); - uint32_t (*partial_program)(uint32_t instance, - struct mg_flexspi_nor_config *config, - uint32_t dstAddr, const uint32_t *src, - uint32_t length, bool keepState); -}; - -#define MG_FLEXSPI_CFG_BLK_TAG (0x42464346UL) -#define MG_FLEXSPI_BASE 0x40134000UL - -#define MG_CMD_SDR 0x01 -#define MG_RADDR_SDR 0x02 -#define MG_WRITE_SDR 0x08 -#define MG_READ_SDR 0x09 -#define MG_DUMMY_SDR 0x0C -#define MG_STOP_EXE 0 - -#define MG_FLEXSPI_1PAD 0 -#define MG_FLEXSPI_4PAD 2 - -#define MG_FLEXSPI_LUT_OPERAND0(x) (((x) &0xFF) << 0) -#define MG_FLEXSPI_LUT_NUM_PADS0(x) (((x) &0x3) << 8) -#define MG_FLEXSPI_LUT_OPCODE0(x) (((x) &0x3F) << 10) -#define MG_FLEXSPI_LUT_OPERAND1(x) (((x) &0xFF) << 16) -#define MG_FLEXSPI_LUT_NUM_PADS1(x) (((x) &0x3) << 24) -#define MG_FLEXSPI_LUT_OPCODE1(x) (((x) &0x3F) << 26) - -#define MG_FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ - (MG_FLEXSPI_LUT_OPERAND0(op0) | MG_FLEXSPI_LUT_NUM_PADS0(pad0) | \ - MG_FLEXSPI_LUT_OPCODE0(cmd0) | MG_FLEXSPI_LUT_OPERAND1(op1) | \ - MG_FLEXSPI_LUT_NUM_PADS1(pad1) | MG_FLEXSPI_LUT_OPCODE1(cmd1)) - -struct mg_flexspi_nor_config default_config = { - .memConfig = - { - .tag = MG_FLEXSPI_CFG_BLK_TAG, - .version = 0, - .readSampleClkSrc = 1, - .csHoldTime = 3, - .csSetupTime = 3, - .deviceModeCfgEnable = 1, - .deviceModeSeq = {.seqNum = 1, .seqId = 2}, - .deviceModeArg = 0x0740, - .configCmdEnable = 0, - .deviceType = 0x1, - .sflashPadType = 4, - .serialClkFreq = 4, - .sflashA1Size = 0x4000000U, - .sflashA2Size = 0, - .sflashB1Size = 0, - .sflashB2Size = 0, - .lookupTable = - { - [0] = - MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0xEB, - MG_RADDR_SDR, MG_FLEXSPI_4PAD, 0x18), - [1] = - MG_FLEXSPI_LUT_SEQ(MG_DUMMY_SDR, MG_FLEXSPI_4PAD, 0x06, - MG_READ_SDR, MG_FLEXSPI_4PAD, 0x04), - [4 * 1 + 0] = - MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x05, - MG_READ_SDR, MG_FLEXSPI_1PAD, 0x04), - [4 * 2 + 0] = - MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x01, - MG_WRITE_SDR, MG_FLEXSPI_1PAD, 0x02), - [4 * 3 + 0] = - MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x06, - MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00), - [4 * 5 + 0] = - MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x20, - MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), - [4 * 8 + 0] = - MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x52, - MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), - [4 * 9 + 0] = - MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x02, - MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), - [4 * 9 + 1] = - MG_FLEXSPI_LUT_SEQ(MG_WRITE_SDR, MG_FLEXSPI_1PAD, 0x00, - MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00), - [4 * 11 + 0] = - MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x60, - MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00), - }, - }, - .pageSize = 0x100, - .sectorSize = 0x1000, - .ipcmdSerialClkFreq = 0, - .blockSize = 0x8000, -}; - -#define MG_FLEXSPI_NOR_INSTANCE 0 -#define MG_ROMAPI_ADDRESS 0x13030000U -#define flexspi_nor \ - ((struct mg_flexspi_nor_driver_interface *) (( \ - (uint32_t *) MG_ROMAPI_ADDRESS)[5])) - -MG_IRAM static bool flash_page_start(volatile uint32_t *dst) { - char *base = (char *) s_mg_flash_frdm.start, - *end = base + s_mg_flash_frdm.size; - volatile char *p = (char *) dst; - return p >= base && p < end && ((p - base) % s_mg_flash_frdm.secsz) == 0; -} - -MG_IRAM static int flexspi_nor_get_config( - struct mg_flexspi_nor_config *config) { - uint32_t option = 0xc0000004; - return flexspi_nor->get_config(MG_FLEXSPI_NOR_INSTANCE, config, &option); -} - -MG_IRAM static int flash_init(void) { - static bool initialized = false; - if (!initialized) { - struct mg_flexspi_nor_config config; - memset(&config, 0, sizeof(config)); - flexspi_nor->set_clock_source(0); - flexspi_nor->config_clock(MG_FLEXSPI_NOR_INSTANCE, 1, 0); - if (flexspi_nor->init(MG_FLEXSPI_NOR_INSTANCE, &default_config)) { - return 1; - } - flexspi_nor_get_config(&config); - if (flexspi_nor->init(MG_FLEXSPI_NOR_INSTANCE, &config)) { - return 1; - } - initialized = true; - } - return 0; -} - -MG_IRAM static bool flash_erase(struct mg_flexspi_nor_config *config, - void *addr) { - if (flash_page_start(addr) == false) { - MG_ERROR(("%p is not on a sector boundary", addr)); - return false; - } - - void *dst = (void *) ((char *) addr - (char *) s_mg_flash_frdm.start); - bool ok = (flexspi_nor->erase_sector(MG_FLEXSPI_NOR_INSTANCE, config, - (uint32_t) dst) == 0); - MG_INFO(("Sector starting at %p erasure: %s", addr, ok ? "ok" : "fail")); - return ok; -} - -MG_IRAM bool mg_frdm_swap(void) { - return true; -} - -MG_IRAM static void flash_wait(void) { - while ((*((volatile uint32_t *) (MG_FLEXSPI_BASE + 0xE0)) & MG_BIT(1)) == 0) - (void) 0; -} - -static bool s_flash_irq_disabled; - -MG_IRAM static bool mg_frdm_write(void *addr, const void *buf, size_t len) { - struct mg_flexspi_nor_config config; - bool ok = false; - MG_ARM_DISABLE_IRQ(); - if (flash_init() != 0) goto fwxit; - if (flexspi_nor_get_config(&config) != 0) goto fwxit; - if ((len % s_mg_flash_frdm.align) != 0) { - MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_frdm.align)); - goto fwxit; - } - if ((char *) addr < (char *) s_mg_flash_frdm.start) { - MG_ERROR(("Invalid flash write address: %p", addr)); - goto fwxit; - } - - uint32_t *dst = (uint32_t *) addr; - uint32_t *src = (uint32_t *) buf; - uint32_t *end = (uint32_t *) ((char *) buf + len); - ok = true; - - while (ok && src < end) { - if (flash_page_start(dst) && flash_erase(&config, dst) == false) { - ok = false; - break; - } - uint32_t status; - uint32_t dst_ofs = (uint32_t) dst - (uint32_t) s_mg_flash_frdm.start; - if ((char *) buf >= (char *) s_mg_flash_frdm.start && - (char *) buf < - (char *) (s_mg_flash_frdm.start + s_mg_flash_frdm.size)) { - // If we copy from FLASH to FLASH, then we first need to copy the source - // to RAM - size_t tmp_buf_size = s_mg_flash_frdm.align / sizeof(uint32_t); - uint32_t tmp[tmp_buf_size]; - - for (size_t i = 0; i < tmp_buf_size; i++) { - flash_wait(); - tmp[i] = src[i]; - } - status = flexspi_nor->page_program(MG_FLEXSPI_NOR_INSTANCE, &config, - (uint32_t) dst_ofs, tmp, false); - } else { - status = flexspi_nor->page_program(MG_FLEXSPI_NOR_INSTANCE, &config, - (uint32_t) dst_ofs, src, false); - } - src = (uint32_t *) ((char *) src + s_mg_flash_frdm.align); - dst = (uint32_t *) ((char *) dst + s_mg_flash_frdm.align); - if (status != 0) { - ok = false; - } - } - MG_INFO(("Flash write %lu bytes @ %p: %s.", len, dst, ok ? "ok" : "fail")); -fwxit: - if (!s_flash_irq_disabled) MG_ARM_ENABLE_IRQ(); - return ok; -} - -// just overwrite instead of swap -MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) { - // no stdlib calls here - for (size_t ofs = 0; ofs < s; ofs += ss) { - mg_frdm_write(p1 + ofs, p2 + ofs, ss); - } - *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; -} - -bool mg_ota_begin(size_t new_firmware_size) { - return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_frdm); -} - -bool mg_ota_write(const void *buf, size_t len) { - return mg_ota_flash_write(buf, len, &s_mg_flash_frdm); -} - -bool mg_ota_end(void) { - if (mg_ota_flash_end(&s_mg_flash_frdm)) { - if (0) { // is_dualbank() - // TODO(): no devices so far - *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; - } else { - // Swap partitions. Pray power does not go away - MG_INFO(("Swapping partitions, size %u (%u sectors)", - s_mg_flash_frdm.size, - s_mg_flash_frdm.size / s_mg_flash_frdm.secsz)); - MG_INFO(("Do NOT power off...")); - mg_log_level = MG_LL_NONE; - s_flash_irq_disabled = true; - // Runs in RAM, will reset when finished - single_bank_swap( - (char *) s_mg_flash_frdm.start, - (char *) s_mg_flash_frdm.start + s_mg_flash_frdm.size / 2, - s_mg_flash_frdm.size / 2, s_mg_flash_frdm.secsz); - } - } - return false; -} - -#endif - #ifdef MG_ENABLE_LINES #line 1 "src/ota_imxrt.c" #endif @@ -8486,6 +8118,374 @@ bool mg_ota_end(void) { } #endif +#ifdef MG_ENABLE_LINES +#line 1 "src/ota_rw612.c" +#endif + + + + +#if MG_OTA == MG_OTA_RW612 + +MG_IRAM static bool mg_frdm_write(void *, const void *, size_t); +static bool mg_frdm_swap(void); + +static struct mg_flash s_mg_flash_frdm = {(void *) 0x08000000, // Start, + 0x200000, // Size + 0x1000, // Sector size + 0x100, // Align + mg_frdm_write, + mg_frdm_swap}; + +struct mg_flexspi_lut_seq { + uint8_t seqNum; + uint8_t seqId; + uint16_t reserved; +}; + +struct mg_flexspi_mem_config { + uint32_t tag; + uint32_t version; + uint32_t reserved0; + uint8_t readSampleClkSrc; + uint8_t csHoldTime; + uint8_t csSetupTime; + uint8_t columnAddressWidth; + uint8_t deviceModeCfgEnable; + uint8_t deviceModeType; + uint16_t waitTimeCfgCommands; + struct mg_flexspi_lut_seq deviceModeSeq; + uint32_t deviceModeArg; + uint8_t configCmdEnable; + uint8_t configModeType[3]; + struct mg_flexspi_lut_seq configCmdSeqs[3]; + uint32_t reserved1; + uint32_t configCmdArgs[3]; + uint32_t reserved2; + uint32_t controllerMiscOption; + uint8_t deviceType; + uint8_t sflashPadType; + uint8_t serialClkFreq; + uint8_t lutCustomSeqEnable; + uint32_t reserved3[2]; + uint32_t sflashA1Size; + uint32_t sflashA2Size; + uint32_t sflashB1Size; + uint32_t sflashB2Size; + uint32_t csPadSettingOverride; + uint32_t sclkPadSettingOverride; + uint32_t dataPadSettingOverride; + uint32_t dqsPadSettingOverride; + uint32_t timeoutInMs; + uint32_t commandInterval; + uint16_t dataValidTime[2]; + uint16_t busyOffset; + uint16_t busyBitPolarity; + uint32_t lookupTable[64]; + struct mg_flexspi_lut_seq lutCustomSeq[12]; + uint32_t reserved4[4]; +}; + +struct mg_flexspi_nor_config { + struct mg_flexspi_mem_config memConfig; + uint32_t pageSize; + uint32_t sectorSize; + uint8_t ipcmdSerialClkFreq; + uint8_t isUniformBlockSize; + uint8_t isDataOrderSwapped; + uint8_t reserved0[1]; + uint8_t serialNorType; + uint8_t needExitNoCmdMode; + uint8_t halfClkForNonReadCmd; + uint8_t needRestoreNoCmdMode; + uint32_t blockSize; + uint32_t flashStateCtx; + uint32_t reserve2[10]; +}; + +struct mg_flexspi_nor_driver_interface { + uint32_t version; + uint32_t (*init)(uint32_t instance, struct mg_flexspi_nor_config *config); + uint32_t (*wait_busy)(uint32_t instance, struct mg_flexspi_nor_config *config, + uint32_t address, bool keepState); + uint32_t (*page_program)(uint32_t instance, + struct mg_flexspi_nor_config *config, + uint32_t dstAddr, const uint32_t *src, + bool keepState); + uint32_t (*erase_all)(uint32_t instance, + struct mg_flexspi_nor_config *config); + uint32_t (*erase)(uint32_t instance, struct mg_flexspi_nor_config *config, + uint32_t start, uint32_t length); + uint32_t (*erase_sector)(uint32_t instance, + struct mg_flexspi_nor_config *config, + uint32_t address); + uint32_t (*erase_block)(uint32_t instance, + struct mg_flexspi_nor_config *config, + uint32_t address); + uint32_t (*read)(uint32_t instance, struct mg_flexspi_nor_config *config, + uint32_t *dst, uint32_t start, uint32_t bytes); + void (*config_clock)(uint32_t instance, uint32_t freqOption, + uint32_t sampleClkMode); + uint32_t (*set_clock_source)(uint32_t clockSrc); + uint32_t (*get_config)(uint32_t instance, + struct mg_flexspi_nor_config *config, + uint32_t *option); + void (*hw_reset)(uint32_t instance, uint32_t reset_logic); + uint32_t (*xfer)(uint32_t instance, char *xfer); + uint32_t (*update_lut)(uint32_t instance, uint32_t seqIndex, + const uint32_t *lutBase, uint32_t numberOfSeq); + uint32_t (*partial_program)(uint32_t instance, + struct mg_flexspi_nor_config *config, + uint32_t dstAddr, const uint32_t *src, + uint32_t length, bool keepState); +}; + +#define MG_FLEXSPI_CFG_BLK_TAG (0x42464346UL) +#define MG_FLEXSPI_BASE 0x40134000UL + +#define MG_CMD_SDR 0x01 +#define MG_RADDR_SDR 0x02 +#define MG_WRITE_SDR 0x08 +#define MG_READ_SDR 0x09 +#define MG_DUMMY_SDR 0x0C +#define MG_STOP_EXE 0 + +#define MG_FLEXSPI_1PAD 0 +#define MG_FLEXSPI_4PAD 2 + +#define MG_FLEXSPI_LUT_OPERAND0(x) (((x) &0xFF) << 0) +#define MG_FLEXSPI_LUT_NUM_PADS0(x) (((x) &0x3) << 8) +#define MG_FLEXSPI_LUT_OPCODE0(x) (((x) &0x3F) << 10) +#define MG_FLEXSPI_LUT_OPERAND1(x) (((x) &0xFF) << 16) +#define MG_FLEXSPI_LUT_NUM_PADS1(x) (((x) &0x3) << 24) +#define MG_FLEXSPI_LUT_OPCODE1(x) (((x) &0x3F) << 26) + +#define MG_FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \ + (MG_FLEXSPI_LUT_OPERAND0(op0) | MG_FLEXSPI_LUT_NUM_PADS0(pad0) | \ + MG_FLEXSPI_LUT_OPCODE0(cmd0) | MG_FLEXSPI_LUT_OPERAND1(op1) | \ + MG_FLEXSPI_LUT_NUM_PADS1(pad1) | MG_FLEXSPI_LUT_OPCODE1(cmd1)) + +struct mg_flexspi_nor_config default_config = { + .memConfig = + { + .tag = MG_FLEXSPI_CFG_BLK_TAG, + .version = 0, + .readSampleClkSrc = 1, + .csHoldTime = 3, + .csSetupTime = 3, + .deviceModeCfgEnable = 1, + .deviceModeSeq = {.seqNum = 1, .seqId = 2}, + .deviceModeArg = 0x0740, + .configCmdEnable = 0, + .deviceType = 0x1, + .sflashPadType = 4, + .serialClkFreq = 4, + .sflashA1Size = 0x4000000U, + .sflashA2Size = 0, + .sflashB1Size = 0, + .sflashB2Size = 0, + .lookupTable = + { + [0] = + MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0xEB, + MG_RADDR_SDR, MG_FLEXSPI_4PAD, 0x18), + [1] = + MG_FLEXSPI_LUT_SEQ(MG_DUMMY_SDR, MG_FLEXSPI_4PAD, 0x06, + MG_READ_SDR, MG_FLEXSPI_4PAD, 0x04), + [4 * 1 + 0] = + MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x05, + MG_READ_SDR, MG_FLEXSPI_1PAD, 0x04), + [4 * 2 + 0] = + MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x01, + MG_WRITE_SDR, MG_FLEXSPI_1PAD, 0x02), + [4 * 3 + 0] = + MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x06, + MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00), + [4 * 5 + 0] = + MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x20, + MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), + [4 * 8 + 0] = + MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x52, + MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), + [4 * 9 + 0] = + MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x02, + MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), + [4 * 9 + 1] = + MG_FLEXSPI_LUT_SEQ(MG_WRITE_SDR, MG_FLEXSPI_1PAD, 0x00, + MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00), + [4 * 11 + 0] = + MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x60, + MG_STOP_EXE, MG_FLEXSPI_1PAD, 0x00), + }, + }, + .pageSize = 0x100, + .sectorSize = 0x1000, + .ipcmdSerialClkFreq = 0, + .blockSize = 0x8000, +}; + +#define MG_FLEXSPI_NOR_INSTANCE 0 +#define MG_ROMAPI_ADDRESS 0x13030000U +#define flexspi_nor \ + ((struct mg_flexspi_nor_driver_interface *) (( \ + (uint32_t *) MG_ROMAPI_ADDRESS)[5])) + +MG_IRAM static bool flash_page_start(volatile uint32_t *dst) { + char *base = (char *) s_mg_flash_frdm.start, + *end = base + s_mg_flash_frdm.size; + volatile char *p = (char *) dst; + return p >= base && p < end && ((p - base) % s_mg_flash_frdm.secsz) == 0; +} + +MG_IRAM static int flexspi_nor_get_config( + struct mg_flexspi_nor_config *config) { + uint32_t option = 0xc0000004; + return flexspi_nor->get_config(MG_FLEXSPI_NOR_INSTANCE, config, &option); +} + +MG_IRAM static int flash_init(void) { + static bool initialized = false; + if (!initialized) { + struct mg_flexspi_nor_config config; + memset(&config, 0, sizeof(config)); + flexspi_nor->set_clock_source(0); + flexspi_nor->config_clock(MG_FLEXSPI_NOR_INSTANCE, 1, 0); + if (flexspi_nor->init(MG_FLEXSPI_NOR_INSTANCE, &default_config)) { + return 1; + } + flexspi_nor_get_config(&config); + if (flexspi_nor->init(MG_FLEXSPI_NOR_INSTANCE, &config)) { + return 1; + } + initialized = true; + } + return 0; +} + +MG_IRAM static bool flash_erase(struct mg_flexspi_nor_config *config, + void *addr) { + if (flash_page_start(addr) == false) { + MG_ERROR(("%p is not on a sector boundary", addr)); + return false; + } + + void *dst = (void *) ((char *) addr - (char *) s_mg_flash_frdm.start); + bool ok = (flexspi_nor->erase_sector(MG_FLEXSPI_NOR_INSTANCE, config, + (uint32_t) dst) == 0); + MG_INFO(("Sector starting at %p erasure: %s", addr, ok ? "ok" : "fail")); + return ok; +} + +MG_IRAM bool mg_frdm_swap(void) { + return true; +} + +MG_IRAM static void flash_wait(void) { + while ((*((volatile uint32_t *) (MG_FLEXSPI_BASE + 0xE0)) & MG_BIT(1)) == 0) + (void) 0; +} + +static bool s_flash_irq_disabled; + +MG_IRAM static bool mg_frdm_write(void *addr, const void *buf, size_t len) { + struct mg_flexspi_nor_config config; + bool ok = false; + MG_ARM_DISABLE_IRQ(); + if (flash_init() != 0) goto fwxit; + if (flexspi_nor_get_config(&config) != 0) goto fwxit; + if ((len % s_mg_flash_frdm.align) != 0) { + MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_frdm.align)); + goto fwxit; + } + if ((char *) addr < (char *) s_mg_flash_frdm.start) { + MG_ERROR(("Invalid flash write address: %p", addr)); + goto fwxit; + } + + uint32_t *dst = (uint32_t *) addr; + uint32_t *src = (uint32_t *) buf; + uint32_t *end = (uint32_t *) ((char *) buf + len); + ok = true; + + while (ok && src < end) { + if (flash_page_start(dst) && flash_erase(&config, dst) == false) { + ok = false; + break; + } + uint32_t status; + uint32_t dst_ofs = (uint32_t) dst - (uint32_t) s_mg_flash_frdm.start; + if ((char *) buf >= (char *) s_mg_flash_frdm.start && + (char *) buf < + (char *) (s_mg_flash_frdm.start + s_mg_flash_frdm.size)) { + // If we copy from FLASH to FLASH, then we first need to copy the source + // to RAM + size_t tmp_buf_size = s_mg_flash_frdm.align / sizeof(uint32_t); + uint32_t tmp[tmp_buf_size]; + + for (size_t i = 0; i < tmp_buf_size; i++) { + flash_wait(); + tmp[i] = src[i]; + } + status = flexspi_nor->page_program(MG_FLEXSPI_NOR_INSTANCE, &config, + (uint32_t) dst_ofs, tmp, false); + } else { + status = flexspi_nor->page_program(MG_FLEXSPI_NOR_INSTANCE, &config, + (uint32_t) dst_ofs, src, false); + } + src = (uint32_t *) ((char *) src + s_mg_flash_frdm.align); + dst = (uint32_t *) ((char *) dst + s_mg_flash_frdm.align); + if (status != 0) { + ok = false; + } + } + MG_INFO(("Flash write %lu bytes @ %p: %s.", len, dst, ok ? "ok" : "fail")); +fwxit: + if (!s_flash_irq_disabled) MG_ARM_ENABLE_IRQ(); + return ok; +} + +// just overwrite instead of swap +MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) { + // no stdlib calls here + for (size_t ofs = 0; ofs < s; ofs += ss) { + mg_frdm_write(p1 + ofs, p2 + ofs, ss); + } + *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; +} + +bool mg_ota_begin(size_t new_firmware_size) { + return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_frdm); +} + +bool mg_ota_write(const void *buf, size_t len) { + return mg_ota_flash_write(buf, len, &s_mg_flash_frdm); +} + +bool mg_ota_end(void) { + if (mg_ota_flash_end(&s_mg_flash_frdm)) { + if (0) { // is_dualbank() + // TODO(): no devices so far + *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; + } else { + // Swap partitions. Pray power does not go away + MG_INFO(("Swapping partitions, size %u (%u sectors)", + s_mg_flash_frdm.size, + s_mg_flash_frdm.size / s_mg_flash_frdm.secsz)); + MG_INFO(("Do NOT power off...")); + mg_log_level = MG_LL_NONE; + s_flash_irq_disabled = true; + // Runs in RAM, will reset when finished + single_bank_swap( + (char *) s_mg_flash_frdm.start, + (char *) s_mg_flash_frdm.start + s_mg_flash_frdm.size / 2, + s_mg_flash_frdm.size / 2, s_mg_flash_frdm.secsz); + } + } + return false; +} + +#endif + #ifdef MG_ENABLE_LINES #line 1 "src/ota_stm32f.c" #endif diff --git a/mongoose.h b/mongoose.h index b22da1d0..c9889cbb 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3064,8 +3064,8 @@ void mg_rpc_list(struct mg_rpc_req *r); #define MG_OTA_RT1060 302 // IMXRT1060 #define MG_OTA_RT1064 303 // IMXRT1064 #define MG_OTA_RT1170 304 // IMXRT1170 -#define MG_OTA_MCXN 310 // MCXN947 -#define MG_OTA_FRDM 320 // FRDM-RW612 +#define MG_OTA_MCXN 310 // MCXN947 +#define MG_OTA_RW612 320 // FRDM-RW612 #define MG_OTA_FLASH 900 // OTA via an internal flash #define MG_OTA_ESP32 910 // ESP32 OTA implementation #define MG_OTA_PICOSDK 920 // RP2040/2350 using Pico-SDK hardware_flash @@ -3932,41 +3932,6 @@ struct mg_tcpip_driver_tms570_data { -#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7 - -struct mg_tcpip_driver_xmc7_data { - int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5 - uint8_t phy_addr; -}; - -#ifndef MG_TCPIP_PHY_ADDR -#define MG_TCPIP_PHY_ADDR 0 -#endif - -#ifndef MG_DRIVER_MDC_CR -#define MG_DRIVER_MDC_CR 3 -#endif - -#define MG_TCPIP_DRIVER_INIT(mgr) \ - do { \ - static struct mg_tcpip_driver_xmc7_data driver_data_; \ - static struct mg_tcpip_if mif_; \ - driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \ - driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \ - mif_.ip = MG_TCPIP_IP; \ - mif_.mask = MG_TCPIP_MASK; \ - mif_.gw = MG_TCPIP_GW; \ - mif_.driver = &mg_tcpip_driver_xmc7; \ - mif_.driver_data = &driver_data_; \ - MG_SET_MAC_ADDRESS(mif_.mac); \ - mg_tcpip_init(mgr, &mif_); \ - MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \ - } while (0) - -#endif - - - #if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC struct mg_tcpip_driver_xmc_data { @@ -4013,6 +3978,41 @@ struct mg_tcpip_driver_xmc_data { #endif + +#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7 + +struct mg_tcpip_driver_xmc7_data { + int mdc_cr; // Valid values: -1, 0, 1, 2, 3, 4, 5 + uint8_t phy_addr; +}; + +#ifndef MG_TCPIP_PHY_ADDR +#define MG_TCPIP_PHY_ADDR 0 +#endif + +#ifndef MG_DRIVER_MDC_CR +#define MG_DRIVER_MDC_CR 3 +#endif + +#define MG_TCPIP_DRIVER_INIT(mgr) \ + do { \ + static struct mg_tcpip_driver_xmc7_data driver_data_; \ + static struct mg_tcpip_if mif_; \ + driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \ + driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \ + mif_.ip = MG_TCPIP_IP; \ + mif_.mask = MG_TCPIP_MASK; \ + mif_.gw = MG_TCPIP_GW; \ + mif_.driver = &mg_tcpip_driver_xmc7; \ + mif_.driver_data = &driver_data_; \ + MG_SET_MAC_ADDRESS(mif_.mac); \ + mg_tcpip_init(mgr, &mif_); \ + MG_INFO(("Driver: xmc7, MAC: %M", mg_print_mac, mif_.mac)); \ + } while (0) + +#endif + + #ifdef __cplusplus } #endif diff --git a/src/ota.h b/src/ota.h index 1c856b3e..81417fb6 100644 --- a/src/ota.h +++ b/src/ota.h @@ -17,8 +17,8 @@ #define MG_OTA_RT1060 302 // IMXRT1060 #define MG_OTA_RT1064 303 // IMXRT1064 #define MG_OTA_RT1170 304 // IMXRT1170 -#define MG_OTA_MCXN 310 // MCXN947 -#define MG_OTA_FRDM 320 // FRDM-RW612 +#define MG_OTA_MCXN 310 // MCXN947 +#define MG_OTA_RW612 320 // FRDM-RW612 #define MG_OTA_FLASH 900 // OTA via an internal flash #define MG_OTA_ESP32 910 // ESP32 OTA implementation #define MG_OTA_PICOSDK 920 // RP2040/2350 using Pico-SDK hardware_flash diff --git a/src/ota_frdm.c b/src/ota_rw612.c similarity index 99% rename from src/ota_frdm.c rename to src/ota_rw612.c index a7e81524..ee441d30 100644 --- a/src/ota_frdm.c +++ b/src/ota_rw612.c @@ -2,7 +2,7 @@ #include "log.h" #include "ota.h" -#if MG_OTA == MG_OTA_FRDM +#if MG_OTA == MG_OTA_RW612 MG_IRAM static bool mg_frdm_write(void *, const void *, size_t); static bool mg_frdm_swap(void);