summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--ports/mimxrt/Makefile1
-rw-r--r--ports/mimxrt/flash.c123
-rw-r--r--ports/mimxrt/flash.h58
-rw-r--r--ports/mimxrt/hal/flexspi_flash_config.h1
-rw-r--r--ports/mimxrt/hal/flexspi_hyper_flash.c5
-rw-r--r--ports/mimxrt/hal/flexspi_hyper_flash.h1
-rw-r--r--ports/mimxrt/hal/flexspi_nor_flash.c31
-rw-r--r--ports/mimxrt/hal/flexspi_nor_flash.h1
-rw-r--r--ports/mimxrt/hal/qspi_nor_flash_config.c8
-rw-r--r--ports/mimxrt/mimxrt_flash.c83
10 files changed, 235 insertions, 77 deletions
diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile
index d9ab4c859b..dd053b3dc1 100644
--- a/ports/mimxrt/Makefile
+++ b/ports/mimxrt/Makefile
@@ -183,6 +183,7 @@ SRC_C += \
drivers/dht/dht.c \
eth.c \
fatfs_port.c \
+ flash.c \
hal/pwm_backport.c \
led.c \
machine_adc.c \
diff --git a/ports/mimxrt/flash.c b/ports/mimxrt/flash.c
new file mode 100644
index 0000000000..3a18f8f51b
--- /dev/null
+++ b/ports/mimxrt/flash.c
@@ -0,0 +1,123 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Philipp Ebensberger
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "flash.h"
+
+void flash_init(void) {
+ // Upload the custom flash configuration
+ // This should be performed by the boot ROM but for some reason it is not.
+ FLEXSPI_UpdateLUT(BOARD_FLEX_SPI, 0,
+ qspiflash_config.memConfig.lookupTable,
+ ARRAY_SIZE(qspiflash_config.memConfig.lookupTable));
+
+ // Configure FLEXSPI IP FIFO access.
+ BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ARDFEN_MASK);
+ BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ATDFEN_MASK);
+ BOARD_FLEX_SPI->MCR0 |= FLEXSPI_MCR0_ARDFEN(0);
+ BOARD_FLEX_SPI->MCR0 |= FLEXSPI_MCR0_ATDFEN(0);
+}
+
+// flash_erase_block(erase_addr)
+// erases the block starting at addr. Block size according to the flash properties.
+__attribute__((section(".ram_functions"))) status_t flash_erase_block(uint32_t erase_addr) {
+ status_t status = kStatus_Fail;
+
+ SCB_CleanInvalidateDCache();
+ SCB_DisableDCache();
+ __disable_irq();
+
+ status = flexspi_nor_flash_erase_block(BOARD_FLEX_SPI, erase_addr);
+
+ __enable_irq();
+ SCB_EnableDCache();
+
+ return status;
+}
+
+// flash_erase_sector(erase_addr_bytes)
+// erases the sector starting at addr. Sector size according to the flash properties.
+__attribute__((section(".ram_functions"))) status_t flash_erase_sector(uint32_t erase_addr) {
+ status_t status = kStatus_Fail;
+
+ SCB_CleanInvalidateDCache();
+ SCB_DisableDCache();
+ __disable_irq();
+
+ status = flexspi_nor_flash_erase_sector(BOARD_FLEX_SPI, erase_addr);
+
+ __enable_irq();
+ SCB_EnableDCache();
+
+ return status;
+}
+
+// flash_write_block(flash_dest_addr_bytes, data_source, length_bytes)
+// writes length_byte data to the destination address
+// the vfs driver takes care for erasing the sector if required
+__attribute__((section(".ram_functions"))) status_t flash_write_block(uint32_t dest_addr, const uint8_t *src, uint32_t length) {
+ status_t status = kStatus_Fail;
+ uint32_t write_length;
+ uint32_t next_addr;
+
+ if (length == 0) {
+ status = kStatus_Success; // Nothing to do
+ } else {
+
+ SCB_CleanInvalidateDCache();
+ SCB_DisableDCache();
+
+ // write data in chunks not crossing a page boundary
+ do {
+ next_addr = dest_addr - (dest_addr % PAGE_SIZE_BYTES) + PAGE_SIZE_BYTES; // next page boundary
+ write_length = next_addr - dest_addr; // calculate write length based on destination address and subsequent page boundary.
+ if (write_length > length) { // compare possible write_length against remaining data length
+ write_length = length;
+ }
+
+ __disable_irq();
+ status = flexspi_nor_flash_page_program(BOARD_FLEX_SPI, dest_addr, (uint32_t *)src, write_length);
+ __enable_irq();
+
+ // Update remaining data length
+ length -= write_length;
+
+ // Move source and destination pointer
+ src += write_length;
+ dest_addr += write_length;
+ } while ((length > 0) && (status == kStatus_Success));
+
+ SCB_EnableDCache();
+
+ }
+ return status;
+}
+
+// flash_read_block(flash_src_addr_bytes, data_dest, length_bytes)
+// read length_byte data to the source address
+// It is just a shim to provide the same structure for read_block and write_block.
+__attribute__((section(".ram_functions"))) void flash_read_block(uint32_t src_addr, uint8_t *dest, uint32_t length) {
+ memcpy(dest, (const uint8_t *)(BOARD_FLEX_SPI_ADDR_BASE + src_addr), length);
+}
diff --git a/ports/mimxrt/flash.h b/ports/mimxrt/flash.h
new file mode 100644
index 0000000000..ad010767c8
--- /dev/null
+++ b/ports/mimxrt/flash.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Philipp Ebensberger
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_MIMXRT_FLASH_H
+#define MICROPY_INCLUDED_MIMXRT_FLASH_H
+
+#include BOARD_FLASH_OPS_HEADER_H
+
+#define SECTOR_SIZE_BYTES (qspiflash_config.sectorSize)
+#define PAGE_SIZE_BYTES (qspiflash_config.pageSize)
+#define BLOCK_SIZE_BYTES (qspiflash_config.blockSize)
+
+#define SECTOR_SIZE_BYTES (qspiflash_config.sectorSize)
+#define PAGE_SIZE_BYTES (qspiflash_config.pageSize)
+
+#ifndef MICROPY_HW_FLASH_STORAGE_BYTES
+#define MICROPY_HW_FLASH_STORAGE_BYTES (((uint32_t)&__vfs_end) - ((uint32_t)&__vfs_start))
+#endif
+
+#ifndef MICROPY_HW_FLASH_STORAGE_BASE
+#define MICROPY_HW_FLASH_STORAGE_BASE (((uint32_t)&__vfs_start) - ((uint32_t)&__flash_start))
+#endif
+
+// Linker symbols
+extern uint8_t __vfs_start;
+extern uint8_t __vfs_end;
+extern uint8_t __flash_start;
+
+void flash_init(void);
+status_t flash_erase_sector(uint32_t erase_addr);
+status_t flash_erase_block(uint32_t erase_addr);
+void flash_read_block(uint32_t src_addr, uint8_t *dest, uint32_t length);
+status_t flash_write_block(uint32_t dest_addr, const uint8_t *src, uint32_t length);
+
+#endif // MICROPY_INCLUDED_MIMXRT_FLASH_H
diff --git a/ports/mimxrt/hal/flexspi_flash_config.h b/ports/mimxrt/hal/flexspi_flash_config.h
index 7eaf3192b5..5320231a14 100644
--- a/ports/mimxrt/hal/flexspi_flash_config.h
+++ b/ports/mimxrt/hal/flexspi_flash_config.h
@@ -222,6 +222,7 @@ typedef struct _FlexSPIConfig
#define NOR_CMD_LUT_SEQ_IDX_ENTERQPI 10
#define NOR_CMD_LUT_SEQ_IDX_CHIPERASE 11
#define NOR_CMD_LUT_SEQ_IDX_EXITQPI 12
+#define NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK 13
#define HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA 0
#define HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA 1
diff --git a/ports/mimxrt/hal/flexspi_hyper_flash.c b/ports/mimxrt/hal/flexspi_hyper_flash.c
index a9f17f2d1c..5e5d87166d 100644
--- a/ports/mimxrt/hal/flexspi_hyper_flash.c
+++ b/ports/mimxrt/hal/flexspi_hyper_flash.c
@@ -175,6 +175,11 @@ status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address) {
return status;
}
+status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address) __attribute__((section(".ram_functions")));
+status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address) {
+ return flexspi_nor_flash_erase_sector(base, address); // HyperFlash does not support block erase!
+}
+
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size) __attribute__((section(".ram_functions")));
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size) {
status_t status;
diff --git a/ports/mimxrt/hal/flexspi_hyper_flash.h b/ports/mimxrt/hal/flexspi_hyper_flash.h
index 3c016bc78e..a6454a1c9a 100644
--- a/ports/mimxrt/hal/flexspi_hyper_flash.h
+++ b/ports/mimxrt/hal/flexspi_hyper_flash.h
@@ -49,6 +49,7 @@ status_t flexspi_nor_hyperflash_cfi(FLEXSPI_Type *base);
void flexspi_hyper_flash_init(void);
void flexspi_nor_update_lut(void);
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
+status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size);
static inline uint32_t flexspi_get_frequency(void) {
diff --git a/ports/mimxrt/hal/flexspi_nor_flash.c b/ports/mimxrt/hal/flexspi_nor_flash.c
index 48792ec487..956fb657db 100644
--- a/ports/mimxrt/hal/flexspi_nor_flash.c
+++ b/ports/mimxrt/hal/flexspi_nor_flash.c
@@ -165,6 +165,37 @@ status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address) {
return status;
}
+status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address) __attribute__((section(".ram_functions")));
+status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address) {
+ status_t status;
+ flexspi_transfer_t flashXfer;
+
+ /* Write enable */
+ status = flexspi_nor_write_enable(base, address);
+
+ if (status != kStatus_Success) {
+ return status;
+ }
+
+ /* Erase sector */
+ flashXfer.deviceAddress = address;
+ flashXfer.port = kFLEXSPI_PortA1;
+ flashXfer.cmdType = kFLEXSPI_Command;
+ flashXfer.SeqNumber = 1;
+ flashXfer.seqIndex = NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK;
+ status = FLEXSPI_TransferBlocking(base, &flashXfer);
+
+ if (status != kStatus_Success) {
+ return status;
+ }
+
+ status = flexspi_nor_wait_bus_busy(base);
+
+ flexspi_nor_reset(base);
+
+ return status;
+}
+
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t size) __attribute__((section(".ram_functions")));
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t size) {
status_t status;
diff --git a/ports/mimxrt/hal/flexspi_nor_flash.h b/ports/mimxrt/hal/flexspi_nor_flash.h
index edc81e37f1..6526142af2 100644
--- a/ports/mimxrt/hal/flexspi_nor_flash.h
+++ b/ports/mimxrt/hal/flexspi_nor_flash.h
@@ -48,6 +48,7 @@ status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId);
status_t flexspi_nor_init(void);
void flexspi_nor_update_lut(void);
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
+status_t flexspi_nor_flash_erase_block(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size);
#endif // MICROPY_INCLUDED_MIMXRT_HAL_FLEXSPI_NOR_FLASH_H
diff --git a/ports/mimxrt/hal/qspi_nor_flash_config.c b/ports/mimxrt/hal/qspi_nor_flash_config.c
index 469a584b87..a6bbd624ed 100644
--- a/ports/mimxrt/hal/qspi_nor_flash_config.c
+++ b/ports/mimxrt/hal/qspi_nor_flash_config.c
@@ -129,11 +129,17 @@ const flexspi_nor_config_t qspiflash_config = {
FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler
FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler
FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler
+
+ // 13 Erase Block (32k) -> 13
+ FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x52, RADDR_SDR, FLEXSPI_1PAD, 24),
+ FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler
+ FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler
+ FLEXSPI_LUT_SEQ(0, 0, 0, 0, 0, 0), // Filler
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
- .blockSize = 64u * 1024u,
+ .blockSize = 32u * 1024u,
.isUniformBlockSize = false,
// .ipcmdSerialClkFreq = kFlexSpiSerialClk_30MHz,
};
diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c
index 536fb60981..d229367e81 100644
--- a/ports/mimxrt/mimxrt_flash.c
+++ b/ports/mimxrt/mimxrt_flash.c
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2020-2021 Damien P. George
- * Copyright (c) 2021 Philipp Ebensberger
+ * Copyright (c) 2021-2023 Philipp Ebensberger
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,23 +30,9 @@
#include "py/runtime.h"
#include "extmod/vfs.h"
#include "modmimxrt.h"
+#include "flash.h"
#include BOARD_FLASH_OPS_HEADER_H
-#define SECTOR_SIZE_BYTES (qspiflash_config.sectorSize)
-#define PAGE_SIZE_BYTES (qspiflash_config.pageSize)
-
-#ifndef MICROPY_HW_FLASH_STORAGE_BYTES
-#define MICROPY_HW_FLASH_STORAGE_BYTES (((uint32_t)&__vfs_end) - ((uint32_t)&__vfs_start))
-#endif
-
-#ifndef MICROPY_HW_FLASH_STORAGE_BASE
-#define MICROPY_HW_FLASH_STORAGE_BASE (((uint32_t)&__vfs_start) - ((uint32_t)&__flash_start))
-#endif
-
-// Linker symbols
-extern uint8_t __vfs_start;
-extern uint8_t __vfs_end;
-extern uint8_t __flash_start;
extern flexspi_nor_config_t qspiflash_config;
@@ -60,67 +46,11 @@ STATIC mimxrt_flash_obj_t mimxrt_flash_obj = {
.base = { &mimxrt_flash_type }
};
-// flash_erase_block(erase_addr_bytes)
-// erases the sector starting at addr. Sector size according to the flash properties.
-status_t flash_erase_block(uint32_t erase_addr) __attribute__((section(".ram_functions")));
-status_t flash_erase_block(uint32_t erase_addr) {
- status_t status;
- SCB_CleanInvalidateDCache();
- SCB_DisableDCache();
- __disable_irq();
- status = flexspi_nor_flash_erase_sector(BOARD_FLEX_SPI, erase_addr);
- __enable_irq();
- SCB_EnableDCache();
- return status;
-}
-
-// flash_write_block(flash_dest_addr_bytes, data_source, length_bytes)
-// writes length_byte data to the destination address
-// the vfs driver takes care for erasing the sector if required
-status_t flash_write_block(uint32_t dest_addr, const uint8_t *src, uint32_t length) __attribute__((section(".ram_functions")));
-status_t flash_write_block(uint32_t dest_addr, const uint8_t *src, uint32_t length) {
- status_t status = 0;
- uint32_t size;
- uint32_t next_addr;
-
- SCB_CleanInvalidateDCache();
- SCB_DisableDCache();
- // write data in chunks not crossing a page boundary
- while (length > 0) {
- next_addr = dest_addr - (dest_addr % PAGE_SIZE_BYTES) + PAGE_SIZE_BYTES; // next page boundary
- size = next_addr - dest_addr; // maximal chunk length
- if (size > length) { // compare against remaining data size
- size = length;
- }
- __disable_irq();
- status = flexspi_nor_flash_page_program(BOARD_FLEX_SPI, dest_addr, (uint32_t *)src, size);
- __enable_irq();
- if (status != kStatus_Success) {
- break;
- }
- length -= size;
- src += size;
- dest_addr += size;
- }
- SCB_EnableDCache();
- return status;
-}
-
STATIC mp_obj_t mimxrt_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
// Check args.
mp_arg_check_num(n_args, n_kw, 0, 0, false);
- // Upload the custom flash configuration
- // This should be performed by the boot ROM but for some reason it is not.
- FLEXSPI_UpdateLUT(BOARD_FLEX_SPI, 0,
- qspiflash_config.memConfig.lookupTable,
- ARRAY_SIZE(qspiflash_config.memConfig.lookupTable));
-
- // Configure BOARD_FLEX_SPI IP FIFO access.
- BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ARDFEN_MASK);
- BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ATDFEN_MASK);
- BOARD_FLEX_SPI->MCR0 |= FLEXSPI_MCR0_ARDFEN(0);
- BOARD_FLEX_SPI->MCR0 |= FLEXSPI_MCR0_ATDFEN(0);
+ flash_init();
// Update information based on linker symbols.
mimxrt_flash_obj.flash_base = MICROPY_HW_FLASH_STORAGE_BASE;
@@ -142,7 +72,8 @@ STATIC mp_obj_t mimxrt_flash_readblocks(size_t n_args, const mp_obj_t *args) {
if (n_args == 4) {
offset += mp_obj_get_int(args[3]);
}
- memcpy(bufinfo.buf, (uint8_t *)(BOARD_FLEX_SPI_ADDR_BASE + self->flash_base + offset), bufinfo.len);
+
+ flash_read_block((self->flash_base + offset), (uint8_t *)bufinfo.buf, (uint32_t)bufinfo.len);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mimxrt_flash_readblocks_obj, 3, 4, mimxrt_flash_readblocks);
@@ -161,7 +92,7 @@ STATIC mp_obj_t mimxrt_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
uint32_t offset = mp_obj_get_int(args[1]) * SECTOR_SIZE_BYTES;
if (n_args == 3) {
- status = flash_erase_block(self->flash_base + offset);
+ status = flash_erase_sector(self->flash_base + offset);
if (status != kStatus_Success) {
mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("flash erase command failed with %d"), status);
@@ -199,7 +130,7 @@ STATIC mp_obj_t mimxrt_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t a
return MP_OBJ_NEW_SMALL_INT(SECTOR_SIZE_BYTES);
case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: {
uint32_t offset = mp_obj_get_int(arg_in) * SECTOR_SIZE_BYTES;
- status = flash_erase_block(self->flash_base + offset);
+ status = flash_erase_sector(self->flash_base + offset);
return MP_OBJ_NEW_SMALL_INT(status != kStatus_Success);
}
default: