diff --git a/mongoose.c b/mongoose.c index ae7c0c31..010d10b9 100644 --- a/mongoose.c +++ b/mongoose.c @@ -11028,7 +11028,7 @@ bool mg_ota_end(void) { -#if MG_OTA >= MG_OTA_RT1020 && MG_OTA <= MG_OTA_RT1170 +#if MG_OTA >= MG_OTA_RT1020 && MG_OTA <= MG_OTA_RT1180 static bool mg_imxrt_write(void *, const void *, size_t); static bool mg_imxrt_swap(void); @@ -11039,9 +11039,12 @@ static bool mg_imxrt_swap(void); #elif MG_OTA == MG_OTA_RT1064 #define MG_IMXRT_FLASH_START 0x70000000 #define FLEXSPI_NOR_INSTANCE 1 -#else // RT1170 +#elif MG_OTA == MG_OTA_RT1170 #define MG_IMXRT_FLASH_START 0x30000000 #define FLEXSPI_NOR_INSTANCE 1 +#else // RT1180 FlexSPI2 +#define MG_IMXRT_FLASH_START 0x04000000 +#define FLEXSPI_NOR_INSTANCE 2 #endif #if MG_OTA == MG_OTA_RT1050 @@ -11350,7 +11353,7 @@ struct mg_flexspi_nor_driver_interface { uint32_t *option); }; #else -// RT117x support ROM API version 1.7 +// RT117x and RT118x struct mg_flexspi_nor_driver_interface { uint32_t version; int (*init)(uint32_t instance, struct mg_flexspi_nor_config *config); @@ -11385,11 +11388,16 @@ struct mg_flexspi_nor_driver_interface { #define flexspi_nor \ (*((struct mg_flexspi_nor_driver_interface **) (*(uint32_t *) 0x0020001c + \ 16))) -#else +#elif MG_OTA == MG_OTA_RT1170 #define MG_FLEXSPI_BASE 0x400CC000 #define flexspi_nor \ (*((struct mg_flexspi_nor_driver_interface **) (*(uint32_t *) 0x0021001c + \ 12))) +#else +#define MG_FLEXSPI_BASE 0x445E0000 +#define flexspi_nor \ + (*((struct mg_flexspi_nor_driver_interface **) (*(uint32_t *) 0x1000001c + \ + 12))) #endif static bool s_flash_irq_disabled; @@ -11434,6 +11442,13 @@ static struct mg_flexspi_nor_config default_config = { #else // Note: this QSPI configuration works for RTs supporting QSPI // Configuration for QSPI memory +#if MG_OTA == MG_OTA_RT1180 +#define MG_FLEXSPI_QSPI_SERIAL_CLK_FREQ 5 // 100MHz +#define MG_FLEXSPI_QSPI_FLASH_SIZE (16 * 1024 * 1024) +#else +#define MG_FLEXSPI_QSPI_SERIAL_CLK_FREQ 7 // 133MHz +#define MG_FLEXSPI_QSPI_FLASH_SIZE (8 * 1024 * 1024) +#endif static struct mg_flexspi_nor_config default_config = { .memConfig = {.tag = MG_FLEXSPI_CFG_BLK_TAG, .version = MG_FLEXSPI_CFG_BLK_VERSION, @@ -11443,8 +11458,8 @@ static struct mg_flexspi_nor_config default_config = { .controllerMiscOption = MG_BIT(4), .deviceType = 1, // serial NOR .sflashPadType = 4, - .serialClkFreq = 7, // 133MHz - .sflashA1Size = 8 * 1024 * 1024, + .serialClkFreq = MG_FLEXSPI_QSPI_SERIAL_CLK_FREQ, + .sflashA1Size = MG_FLEXSPI_QSPI_FLASH_SIZE, .lookupTable = MG_FLEXSPI_QSPI_LUT}, .pageSize = 256, .sectorSize = 4 * 1024, @@ -11479,6 +11494,7 @@ MG_IRAM static int flexspi_nor_get_config( } #endif +#if MG_OTA == MG_OTA_RT1020 || MG_OTA == MG_OTA_RT1050 MG_IRAM static void mg_spin(volatile uint32_t count) { while (count--) (void) 0; } @@ -11487,6 +11503,7 @@ MG_IRAM static void flash_wait(void) { while ((*((volatile uint32_t *) (MG_FLEXSPI_BASE + 0xE0)) & MG_BIT(1)) == 0) mg_spin(1); } +#endif MG_IRAM static bool flash_erase(struct mg_flexspi_nor_config *config, void *addr) { @@ -11535,6 +11552,8 @@ MG_IRAM static bool mg_imxrt_write(void *addr, const void *buf, size_t len) { uint32_t *dst = (uint32_t *) addr; uint32_t *src = (uint32_t *) buf; uint32_t *end = (uint32_t *) ((char *) buf + len); + char *flash_start = (char *) s_mg_flash_imxrt.start; + char *flash_end = flash_start + s_mg_flash_imxrt.size; ok = true; while (ok && src < end) { @@ -11542,20 +11561,32 @@ MG_IRAM static bool mg_imxrt_write(void *addr, const void *buf, size_t len) { ok = false; break; } - uint32_t status; + uint32_t status = 0; uint32_t dst_ofs = (uint32_t) dst - (uint32_t) s_mg_flash_imxrt.start; - if ((char *) buf >= (char *) s_mg_flash_imxrt.start) { + if ((char *) buf >= flash_start && (char *) buf < flash_end) { // 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_imxrt.align / sizeof(uint32_t); uint32_t tmp[tmp_buf_size]; +#if MG_OTA == MG_OTA_RT1020 || MG_OTA == MG_OTA_RT1050 + // ROM API 1.4 does not provide flexspi_nor_flash_read(). + // Manually copy byte by byte into the RAM buffer. for (size_t i = 0; i < tmp_buf_size; i++) { flash_wait(); tmp[i] = src[i]; } - status = flexspi_nor->program(FLEXSPI_NOR_INSTANCE, config_ptr, - (uint32_t) dst_ofs, tmp); +#else + // When supported, prefer the read API call. + uint32_t src_ofs = + (uint32_t) src - (uint32_t) s_mg_flash_imxrt.start; + status = flexspi_nor->read(FLEXSPI_NOR_INSTANCE, config_ptr, tmp, + src_ofs, s_mg_flash_imxrt.align); +#endif + if (status == 0) { + status = flexspi_nor->program(FLEXSPI_NOR_INSTANCE, config_ptr, + dst_ofs, tmp); + } } else { status = flexspi_nor->program(FLEXSPI_NOR_INSTANCE, config_ptr, (uint32_t) dst_ofs, src); diff --git a/mongoose.h b/mongoose.h index 7f29dd4e..00880880 100644 --- a/mongoose.h +++ b/mongoose.h @@ -447,7 +447,7 @@ static inline uint32_t mg_ota_esp32_state_set(uint32_t state) { #endif #if MG_ENABLE_TCPIP && !defined(MG_ENABLE_DRIVER_IMXRT10) && \ - !defined(MG_ENABLE_DRIVER_IMXRT11) + !defined(MG_ENABLE_DRIVER_IMXRT11) && !defined(MG_ENABLE_DRIVER_NETC) #if defined(CPU_MIMXRT1021DAG5A) || defined(CPU_MIMXRT1024DAG5A) || \ defined(CPU_MIMXRT1042XJM5B) || defined(CPU_MIMXRT1052DVL6B) || \ defined(CPU_MIMXRT1062DVL6B) || defined(CPU_MIMXRT1064DVL6B) || \ @@ -462,6 +462,8 @@ static inline uint32_t mg_ota_esp32_state_set(uint32_t state) { defined(_MIMXRT1176_cm7_H_) || defined(_MIMXRT1176_cm4_H_) || \ defined(_MIMXRT1176_H_) #define MG_ENABLE_DRIVER_IMXRT11 1 +#elif defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_) +#define MG_ENABLE_DRIVER_NETC 1 #else #error Select an Ethernet driver in mongoose_config.h #endif @@ -493,13 +495,31 @@ static inline uint32_t mg_ota_esp32_state_set(uint32_t state) { defined(_MIMXRT1176_cm7_H_) || defined(_MIMXRT1176_cm4_H_) || \ defined(_MIMXRT1176_H_)) #define MG_OTA MG_OTA_RT1170 +#elif !defined(MG_OTA) && \ + (defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_)) +#define MG_OTA MG_OTA_RT1180 #endif #ifndef MG_IRAM +#if defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_) +#define MG_IRAM \ + __attribute__((noinline, section(".data.$SRAM_ITC_cm33"))) +#else #define MG_IRAM __attribute__((noinline, section(".data_RAM2"))) #endif +#endif + +#ifndef MG_ETH_RAM +#if defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_) +#define MG_ETH_RAM __attribute__((section(".bss.$ETH_RAM"))) +#endif +#endif #ifndef MG_SET_MAC_ADDRESS +#if defined(MG_ENABLE_DRIVER_NETC) && MG_ENABLE_DRIVER_NETC +// No OCOTP_FUSES present on RT1186 to generate the UUID +#define MG_SET_MAC_ADDRESS(mac) (void) (mac) +#else #if defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11 #define MG_OCOTP_FUSES ((volatile uint32_t *) 0x40cac900) #else @@ -515,11 +535,70 @@ static inline uint32_t mg_ota_esp32_state_set(uint32_t state) { mac[5] = (MG_OCOTP_FUSES[4] >> 0) & 255; \ } while (0) #endif +#endif #ifndef MG_IMXRT_WDOG1_TIMEOUT_MS -#define MG_IMXRT_WDOG1_TIMEOUT_MS 10000 +#define MG_IMXRT_WDOG1_TIMEOUT_MS 10000U #endif +#if defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_) + +#define MG_IMXRT_RTWDOG1_UNLOCK() \ + do { \ + if ((RTWDOG1->CS & RTWDOG_CS_CMD32EN_MASK) != 0U) { \ + RTWDOG1->CNT = RTWDOG_UPDATE_KEY; \ + } else { \ + RTWDOG1->CNT = RTWDOG_UPDATE_KEY & 0xffffU; \ + RTWDOG1->CNT = RTWDOG_UPDATE_KEY >> 16; \ + } \ + while ((RTWDOG1->CS & RTWDOG_CS_ULK_MASK) == 0U) (void) 0; \ + } while (0) + +#define MG_IMXRT_RTWDOG1_FEED() \ + do { \ + uint32_t primask_ = __get_PRIMASK(); \ + __disable_irq(); \ + if ((RTWDOG1->CS & RTWDOG_CS_CMD32EN_MASK) != 0U) { \ + RTWDOG1->CNT = RTWDOG_REFRESH_KEY; \ + } else { \ + RTWDOG1->CNT = RTWDOG_REFRESH_KEY & 0xffffU; \ + RTWDOG1->CNT = RTWDOG_REFRESH_KEY >> 16; \ + } \ + if (primask_ == 0U) __enable_irq(); \ + } while (0) + +#ifndef MG_OTA_ROLLBACK_TIMER_START +#define MG_OTA_ROLLBACK_TIMER_START() \ + do { \ + uint32_t primask_ = __get_PRIMASK(); \ + SRC_GENERAL_REG->SRMASK &= ~SRC_GENERAL_SRMASK_WDOG1_MASK_MASK; \ + __disable_irq(); \ + MG_IMXRT_RTWDOG1_UNLOCK(); \ + RTWDOG1->WIN = 0U; \ + RTWDOG1->TOVAL = (MG_IMXRT_WDOG1_TIMEOUT_MS + 7U) / 8U; \ + RTWDOG1->CS = RTWDOG_CS_EN_MASK | RTWDOG_CS_UPDATE_MASK | \ + RTWDOG_CS_CLK(1U) | RTWDOG_CS_PRES_MASK | \ + RTWDOG_CS_CMD32EN_MASK; \ + while ((RTWDOG1->CS & RTWDOG_CS_RCS_MASK) == 0U) (void) 0; \ + if (primask_ == 0U) __enable_irq(); \ + } while (0) +#endif + +#ifndef MG_OTA_ROLLBACK_TIMER_FEED +#define MG_OTA_ROLLBACK_TIMER_FEED() MG_IMXRT_RTWDOG1_FEED() +#endif + +// GPR5 survives RTWDOG global resets and is not reserved by the boot ROM. +#ifndef MG_OTA_STATE_GET +#define MG_OTA_STATE_GET() SRC_GENERAL_REG->GPR[5] +#endif + +#ifndef MG_OTA_STATE_SET +#define MG_OTA_STATE_SET(v) (SRC_GENERAL_REG->GPR[5] = (uint32_t) (v)) +#endif + +#else + #define MG_IMXRT_WDOG1_FEED() \ do { \ WDOG1->WSR = 0x5555; \ @@ -562,6 +641,8 @@ static inline uint32_t mg_ota_esp32_state_set(uint32_t state) { #endif +#endif + #if MG_ARCH == MG_ARCH_PICOSDK #if !defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP @@ -4667,6 +4748,7 @@ extern void mg_mqtt_poll(struct mg_mgr *); #define MG_OTA_RT1060 302 // IMXRT1060 #define MG_OTA_RT1064 303 // IMXRT1064 #define MG_OTA_RT1170 304 // IMXRT1170 +#define MG_OTA_RT1180 305 // IMXRT1180 #define MG_OTA_MCXN 310 // MCXN947 #define MG_OTA_RW612 320 // FRDM-RW612 #define MG_OTA_FLASH 900 // OTA via internal flash diff --git a/src/arch_mcuxpresso.h b/src/arch_mcuxpresso.h index 89f2252e..18a29b61 100644 --- a/src/arch_mcuxpresso.h +++ b/src/arch_mcuxpresso.h @@ -36,7 +36,7 @@ #endif #if MG_ENABLE_TCPIP && !defined(MG_ENABLE_DRIVER_IMXRT10) && \ - !defined(MG_ENABLE_DRIVER_IMXRT11) + !defined(MG_ENABLE_DRIVER_IMXRT11) && !defined(MG_ENABLE_DRIVER_NETC) #if defined(CPU_MIMXRT1021DAG5A) || defined(CPU_MIMXRT1024DAG5A) || \ defined(CPU_MIMXRT1042XJM5B) || defined(CPU_MIMXRT1052DVL6B) || \ defined(CPU_MIMXRT1062DVL6B) || defined(CPU_MIMXRT1064DVL6B) || \ @@ -51,6 +51,8 @@ defined(_MIMXRT1176_cm7_H_) || defined(_MIMXRT1176_cm4_H_) || \ defined(_MIMXRT1176_H_) #define MG_ENABLE_DRIVER_IMXRT11 1 +#elif defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_) +#define MG_ENABLE_DRIVER_NETC 1 #else #error Select an Ethernet driver in mongoose_config.h #endif @@ -82,13 +84,31 @@ defined(_MIMXRT1176_cm7_H_) || defined(_MIMXRT1176_cm4_H_) || \ defined(_MIMXRT1176_H_)) #define MG_OTA MG_OTA_RT1170 +#elif !defined(MG_OTA) && \ + (defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_)) +#define MG_OTA MG_OTA_RT1180 #endif #ifndef MG_IRAM +#if defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_) +#define MG_IRAM \ + __attribute__((noinline, section(".data.$SRAM_ITC_cm33"))) +#else #define MG_IRAM __attribute__((noinline, section(".data_RAM2"))) #endif +#endif + +#ifndef MG_ETH_RAM +#if defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_) +#define MG_ETH_RAM __attribute__((section(".bss.$ETH_RAM"))) +#endif +#endif #ifndef MG_SET_MAC_ADDRESS +#if defined(MG_ENABLE_DRIVER_NETC) && MG_ENABLE_DRIVER_NETC +// No OCOTP_FUSES present on RT1186 to generate the UUID +#define MG_SET_MAC_ADDRESS(mac) (void) (mac) +#else #if defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11 #define MG_OCOTP_FUSES ((volatile uint32_t *) 0x40cac900) #else @@ -104,11 +124,70 @@ mac[5] = (MG_OCOTP_FUSES[4] >> 0) & 255; \ } while (0) #endif +#endif #ifndef MG_IMXRT_WDOG1_TIMEOUT_MS -#define MG_IMXRT_WDOG1_TIMEOUT_MS 10000 +#define MG_IMXRT_WDOG1_TIMEOUT_MS 10000U #endif +#if defined(CPU_MIMXRT1186CVJ8C_cm33) || defined(MIMXRT1186_cm33_H_) + +#define MG_IMXRT_RTWDOG1_UNLOCK() \ + do { \ + if ((RTWDOG1->CS & RTWDOG_CS_CMD32EN_MASK) != 0U) { \ + RTWDOG1->CNT = RTWDOG_UPDATE_KEY; \ + } else { \ + RTWDOG1->CNT = RTWDOG_UPDATE_KEY & 0xffffU; \ + RTWDOG1->CNT = RTWDOG_UPDATE_KEY >> 16; \ + } \ + while ((RTWDOG1->CS & RTWDOG_CS_ULK_MASK) == 0U) (void) 0; \ + } while (0) + +#define MG_IMXRT_RTWDOG1_FEED() \ + do { \ + uint32_t primask_ = __get_PRIMASK(); \ + __disable_irq(); \ + if ((RTWDOG1->CS & RTWDOG_CS_CMD32EN_MASK) != 0U) { \ + RTWDOG1->CNT = RTWDOG_REFRESH_KEY; \ + } else { \ + RTWDOG1->CNT = RTWDOG_REFRESH_KEY & 0xffffU; \ + RTWDOG1->CNT = RTWDOG_REFRESH_KEY >> 16; \ + } \ + if (primask_ == 0U) __enable_irq(); \ + } while (0) + +#ifndef MG_OTA_ROLLBACK_TIMER_START +#define MG_OTA_ROLLBACK_TIMER_START() \ + do { \ + uint32_t primask_ = __get_PRIMASK(); \ + SRC_GENERAL_REG->SRMASK &= ~SRC_GENERAL_SRMASK_WDOG1_MASK_MASK; \ + __disable_irq(); \ + MG_IMXRT_RTWDOG1_UNLOCK(); \ + RTWDOG1->WIN = 0U; \ + RTWDOG1->TOVAL = (MG_IMXRT_WDOG1_TIMEOUT_MS + 7U) / 8U; \ + RTWDOG1->CS = RTWDOG_CS_EN_MASK | RTWDOG_CS_UPDATE_MASK | \ + RTWDOG_CS_CLK(1U) | RTWDOG_CS_PRES_MASK | \ + RTWDOG_CS_CMD32EN_MASK; \ + while ((RTWDOG1->CS & RTWDOG_CS_RCS_MASK) == 0U) (void) 0; \ + if (primask_ == 0U) __enable_irq(); \ + } while (0) +#endif + +#ifndef MG_OTA_ROLLBACK_TIMER_FEED +#define MG_OTA_ROLLBACK_TIMER_FEED() MG_IMXRT_RTWDOG1_FEED() +#endif + +// GPR5 survives RTWDOG global resets and is not reserved by the boot ROM. +#ifndef MG_OTA_STATE_GET +#define MG_OTA_STATE_GET() SRC_GENERAL_REG->GPR[5] +#endif + +#ifndef MG_OTA_STATE_SET +#define MG_OTA_STATE_SET(v) (SRC_GENERAL_REG->GPR[5] = (uint32_t) (v)) +#endif + +#else + #define MG_IMXRT_WDOG1_FEED() \ do { \ WDOG1->WSR = 0x5555; \ @@ -150,3 +229,5 @@ #endif #endif + +#endif diff --git a/src/ota.h b/src/ota.h index c8a861cd..4c2761d7 100644 --- a/src/ota.h +++ b/src/ota.h @@ -41,6 +41,7 @@ #define MG_OTA_RT1060 302 // IMXRT1060 #define MG_OTA_RT1064 303 // IMXRT1064 #define MG_OTA_RT1170 304 // IMXRT1170 +#define MG_OTA_RT1180 305 // IMXRT1180 #define MG_OTA_MCXN 310 // MCXN947 #define MG_OTA_RW612 320 // FRDM-RW612 #define MG_OTA_FLASH 900 // OTA via internal flash diff --git a/src/ota_imxrt.c b/src/ota_imxrt.c index 1c389de7..fdf20ce0 100644 --- a/src/ota_imxrt.c +++ b/src/ota_imxrt.c @@ -2,7 +2,7 @@ #include "log.h" #include "ota.h" -#if MG_OTA >= MG_OTA_RT1020 && MG_OTA <= MG_OTA_RT1170 +#if MG_OTA >= MG_OTA_RT1020 && MG_OTA <= MG_OTA_RT1180 static bool mg_imxrt_write(void *, const void *, size_t); static bool mg_imxrt_swap(void); @@ -13,9 +13,12 @@ static bool mg_imxrt_swap(void); #elif MG_OTA == MG_OTA_RT1064 #define MG_IMXRT_FLASH_START 0x70000000 #define FLEXSPI_NOR_INSTANCE 1 -#else // RT1170 +#elif MG_OTA == MG_OTA_RT1170 #define MG_IMXRT_FLASH_START 0x30000000 #define FLEXSPI_NOR_INSTANCE 1 +#else // RT1180 FlexSPI2 +#define MG_IMXRT_FLASH_START 0x04000000 +#define FLEXSPI_NOR_INSTANCE 2 #endif #if MG_OTA == MG_OTA_RT1050 @@ -324,7 +327,7 @@ struct mg_flexspi_nor_driver_interface { uint32_t *option); }; #else -// RT117x support ROM API version 1.7 +// RT117x and RT118x struct mg_flexspi_nor_driver_interface { uint32_t version; int (*init)(uint32_t instance, struct mg_flexspi_nor_config *config); @@ -359,11 +362,16 @@ struct mg_flexspi_nor_driver_interface { #define flexspi_nor \ (*((struct mg_flexspi_nor_driver_interface **) (*(uint32_t *) 0x0020001c + \ 16))) -#else +#elif MG_OTA == MG_OTA_RT1170 #define MG_FLEXSPI_BASE 0x400CC000 #define flexspi_nor \ (*((struct mg_flexspi_nor_driver_interface **) (*(uint32_t *) 0x0021001c + \ 12))) +#else +#define MG_FLEXSPI_BASE 0x445E0000 +#define flexspi_nor \ + (*((struct mg_flexspi_nor_driver_interface **) (*(uint32_t *) 0x1000001c + \ + 12))) #endif static bool s_flash_irq_disabled; @@ -408,6 +416,13 @@ static struct mg_flexspi_nor_config default_config = { #else // Note: this QSPI configuration works for RTs supporting QSPI // Configuration for QSPI memory +#if MG_OTA == MG_OTA_RT1180 +#define MG_FLEXSPI_QSPI_SERIAL_CLK_FREQ 5 // 100MHz +#define MG_FLEXSPI_QSPI_FLASH_SIZE (16 * 1024 * 1024) +#else +#define MG_FLEXSPI_QSPI_SERIAL_CLK_FREQ 7 // 133MHz +#define MG_FLEXSPI_QSPI_FLASH_SIZE (8 * 1024 * 1024) +#endif static struct mg_flexspi_nor_config default_config = { .memConfig = {.tag = MG_FLEXSPI_CFG_BLK_TAG, .version = MG_FLEXSPI_CFG_BLK_VERSION, @@ -417,8 +432,8 @@ static struct mg_flexspi_nor_config default_config = { .controllerMiscOption = MG_BIT(4), .deviceType = 1, // serial NOR .sflashPadType = 4, - .serialClkFreq = 7, // 133MHz - .sflashA1Size = 8 * 1024 * 1024, + .serialClkFreq = MG_FLEXSPI_QSPI_SERIAL_CLK_FREQ, + .sflashA1Size = MG_FLEXSPI_QSPI_FLASH_SIZE, .lookupTable = MG_FLEXSPI_QSPI_LUT}, .pageSize = 256, .sectorSize = 4 * 1024, @@ -453,6 +468,7 @@ MG_IRAM static int flexspi_nor_get_config( } #endif +#if MG_OTA == MG_OTA_RT1020 || MG_OTA == MG_OTA_RT1050 MG_IRAM static void mg_spin(volatile uint32_t count) { while (count--) (void) 0; } @@ -461,6 +477,7 @@ MG_IRAM static void flash_wait(void) { while ((*((volatile uint32_t *) (MG_FLEXSPI_BASE + 0xE0)) & MG_BIT(1)) == 0) mg_spin(1); } +#endif MG_IRAM static bool flash_erase(struct mg_flexspi_nor_config *config, void *addr) { @@ -509,6 +526,8 @@ MG_IRAM static bool mg_imxrt_write(void *addr, const void *buf, size_t len) { uint32_t *dst = (uint32_t *) addr; uint32_t *src = (uint32_t *) buf; uint32_t *end = (uint32_t *) ((char *) buf + len); + char *flash_start = (char *) s_mg_flash_imxrt.start; + char *flash_end = flash_start + s_mg_flash_imxrt.size; ok = true; while (ok && src < end) { @@ -516,20 +535,32 @@ MG_IRAM static bool mg_imxrt_write(void *addr, const void *buf, size_t len) { ok = false; break; } - uint32_t status; + uint32_t status = 0; uint32_t dst_ofs = (uint32_t) dst - (uint32_t) s_mg_flash_imxrt.start; - if ((char *) buf >= (char *) s_mg_flash_imxrt.start) { + if ((char *) buf >= flash_start && (char *) buf < flash_end) { // 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_imxrt.align / sizeof(uint32_t); uint32_t tmp[tmp_buf_size]; +#if MG_OTA == MG_OTA_RT1020 || MG_OTA == MG_OTA_RT1050 + // ROM API 1.4 does not provide flexspi_nor_flash_read(). + // Manually copy byte by byte into the RAM buffer. for (size_t i = 0; i < tmp_buf_size; i++) { flash_wait(); tmp[i] = src[i]; } - status = flexspi_nor->program(FLEXSPI_NOR_INSTANCE, config_ptr, - (uint32_t) dst_ofs, tmp); +#else + // When supported, prefer the read API call. + uint32_t src_ofs = + (uint32_t) src - (uint32_t) s_mg_flash_imxrt.start; + status = flexspi_nor->read(FLEXSPI_NOR_INSTANCE, config_ptr, tmp, + src_ofs, s_mg_flash_imxrt.align); +#endif + if (status == 0) { + status = flexspi_nor->program(FLEXSPI_NOR_INSTANCE, config_ptr, + dst_ofs, tmp); + } } else { status = flexspi_nor->program(FLEXSPI_NOR_INSTANCE, config_ptr, (uint32_t) dst_ofs, src);