From 835582b8d1efc1be57074d79a4fa7a10a3cd8b26 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Sep 2018 14:24:30 +0700 Subject: [PATCH 01/19] adding flash_api, qspi flash - also move usb_init() from board_init() to port_init(0 --- ports/nrf/Makefile | 12 ++- .../boards/feather_nrf52840_express/board.c | 3 +- .../feather_nrf52840_express/mpconfigboard.mk | 1 + ports/nrf/boards/pca10056/board.c | 71 +++++++++++++++- ports/nrf/boards/pca10056/mpconfigboard.h | 8 ++ ports/nrf/boards/pca10056/mpconfigboard.mk | 1 + ports/nrf/boards/pca10059/board.c | 2 - ports/nrf/flash_api/flash_api.c | 40 +++++++++ ports/nrf/flash_api/flash_api.h | 50 ++++++++++++ ports/nrf/flash_api/qspi_flash.c | 81 +++++++++++++++++++ ports/nrf/internal_flash.c | 16 ++-- ports/nrf/internal_flash.h | 7 +- ports/nrf/nrfx_config.h | 49 +++++------ ports/nrf/supervisor/filesystem.c | 3 +- ports/nrf/supervisor/port.c | 9 ++- ports/nrf/usb/usb_msc_flash.c | 33 +++----- 16 files changed, 314 insertions(+), 72 deletions(-) create mode 100644 ports/nrf/flash_api/flash_api.c create mode 100644 ports/nrf/flash_api/flash_api.h create mode 100644 ports/nrf/flash_api/qspi_flash.c diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 0e9d224be722d..1345d3dfb9b72 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -87,11 +87,13 @@ LIBS := -L $(dir $(LIBM_FILE_NAME)) -lm LIBS += -L $(dir $(LIBC_FILE_NAME)) -lc LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc -SRC_NRFX = $(addprefix nrfx/,\ +SRC_NRFX += $(addprefix nrfx/,\ drivers/src/nrfx_power.c \ drivers/src/nrfx_spim.c \ drivers/src/nrfx_twim.c \ drivers/src/nrfx_uart.c \ + hal/nrf_nvmc.c \ + mdk/system_$(MCU_SUB_VARIANT).c \ ) SRC_C += \ @@ -105,6 +107,7 @@ SRC_C += \ device/$(MCU_VARIANT)/startup_$(MCU_SUB_VARIANT).c \ drivers/bluetooth/ble_drv.c \ drivers/bluetooth/ble_uart.c \ + flash_api/flash_api.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ lib/oofatfs/ff.c \ @@ -116,14 +119,17 @@ SRC_C += \ lib/utils/pyexec.c \ lib/utils/stdout_helpers.c \ lib/utils/sys_stdio_mphal.c \ - nrfx/hal/nrf_nvmc.c \ - nrfx/mdk/system_$(MCU_SUB_VARIANT).c \ peripherals/nrf/cache.c \ peripherals/nrf/clocks.c \ peripherals/nrf/$(MCU_CHIP)/pins.c \ peripherals/nrf/$(MCU_CHIP)/power.c \ supervisor/shared/memory.c +ifeq ($(QSPI_FLASH_FILESYSTEM),1) +SRC_C += flash_api/qspi_flash.c +SRC_NRFX += nrfx/drivers/src/nrfx_qspi.c +endif + DRIVERS_SRC_C += $(addprefix modules/,\ ubluepy/modubluepy.c \ ubluepy/ubluepy_peripheral.c \ diff --git a/ports/nrf/boards/feather_nrf52840_express/board.c b/ports/nrf/boards/feather_nrf52840_express/board.c index a6d050fce2cd7..5eef0cf050866 100644 --- a/ports/nrf/boards/feather_nrf52840_express/board.c +++ b/ports/nrf/boards/feather_nrf52840_express/board.c @@ -25,10 +25,9 @@ */ #include "boards/board.h" -#include "usb.h" void board_init(void) { - usb_init(); + } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk index caf580ec4d124..0541e03236f44 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk @@ -6,6 +6,7 @@ SD ?= s140 SOFTDEV_VERSION ?= 6.1.0 BOOT_SETTING_ADDR = 0xFF000 +QSPI_FLASH_FILESYSTEM = 1 ifeq ($(SD),) LD_FILE = boards/nrf52840_1M_256k.ld diff --git a/ports/nrf/boards/pca10056/board.c b/ports/nrf/boards/pca10056/board.c index a6d050fce2cd7..4db6b34aa33cc 100644 --- a/ports/nrf/boards/pca10056/board.c +++ b/ports/nrf/boards/pca10056/board.c @@ -25,10 +25,77 @@ */ #include "boards/board.h" -#include "usb.h" +#include "nrfx_qspi.h" + +#define QSPI_STD_CMD_RSTEN 0x66 +#define QSPI_STD_CMD_RST 0x99 +#define QSPI_STD_CMD_WRSR 0x01 + +extern void qspi_flash_complete (void); + +void qflash_hdl (nrfx_qspi_evt_t event, void * p_context) +{ + (void) p_context; + (void) event; + +// qspi_flash_complete(); +} + void board_init(void) { - usb_init(); + // Init QSPI flash + nrfx_qspi_config_t qspi_cfg = { + .xip_offset = 0, + .pins = { + .sck_pin = 19, + .csn_pin = 17, + .io0_pin = 20, + .io1_pin = 21, + .io2_pin = 22, + .io3_pin = 23, + }, + .prot_if = { + .readoc = NRF_QSPI_READOC_READ4IO, + .writeoc = NRF_QSPI_WRITEOC_PP4IO, + .addrmode = NRF_QSPI_ADDRMODE_24BIT, + .dpmconfig = false, // deep power down + }, + .phy_if = { + .sck_freq = NRF_QSPI_FREQ_32MDIV1, + .sck_delay = 1, + .spi_mode = NRF_QSPI_MODE_0, + .dpmen = false + }, + .irq_priority = 7, + }; + +// nrfx_qspi_init(&qspi_cfg, qflash_hdl, NULL); + nrfx_qspi_init(&qspi_cfg, NULL, NULL); + + nrf_qspi_cinstr_conf_t cinstr_cfg = { + .opcode = 0, + .length = 0, + .io2_level = true, + .io3_level = true, + .wipwait = true, + .wren = true + }; + + // Send reset enable + cinstr_cfg.opcode = QSPI_STD_CMD_RSTEN; + cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); + + // Send reset command + cinstr_cfg.opcode = QSPI_STD_CMD_RST; + cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); + + // Switch to qspi mode + uint8_t sr_quad_en = 0x40; + cinstr_cfg.opcode = QSPI_STD_CMD_WRSR; + cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, &sr_quad_en, NULL); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index de4545d6201eb..8b675d8dc0359 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -48,3 +48,11 @@ #define DEFAULT_UART_BUS_RX (&pin_P1_01) #define DEFAULT_UART_BUS_TX (&pin_P1_02) + +// On-board QSPI Flash +#define QSPI_FLASH_CS NRF_GPIO_PIN_MAP(0, 17) +#define QSPI_FLASH_CLK NRF_GPIO_PIN_MAP(0, 19) +#define QSPI_FLASH_D0 NRF_GPIO_PIN_MAP(0, 20) +#define QSPI_FLASH_D1 NRF_GPIO_PIN_MAP(0, 21) +#define QSPI_FLASH_D2 NRF_GPIO_PIN_MAP(0, 22) +#define QSPI_FLASH_D3 NRF_GPIO_PIN_MAP(0, 23) diff --git a/ports/nrf/boards/pca10056/mpconfigboard.mk b/ports/nrf/boards/pca10056/mpconfigboard.mk index caf580ec4d124..0541e03236f44 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.mk +++ b/ports/nrf/boards/pca10056/mpconfigboard.mk @@ -6,6 +6,7 @@ SD ?= s140 SOFTDEV_VERSION ?= 6.1.0 BOOT_SETTING_ADDR = 0xFF000 +QSPI_FLASH_FILESYSTEM = 1 ifeq ($(SD),) LD_FILE = boards/nrf52840_1M_256k.ld diff --git a/ports/nrf/boards/pca10059/board.c b/ports/nrf/boards/pca10059/board.c index cbb4ef3b6db91..c1db7b309a724 100644 --- a/ports/nrf/boards/pca10059/board.c +++ b/ports/nrf/boards/pca10059/board.c @@ -28,10 +28,8 @@ #include #include "boards/board.h" #include "nrfx.h" -#include "usb.h" void board_init(void) { - usb_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c new file mode 100644 index 0000000000000..04a7b6868dfe2 --- /dev/null +++ b/ports/nrf/flash_api/flash_api.c @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * + * 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_api.h" +#include "internal_flash.h" + +mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { + return internal_flash_read_blocks(dst, lba, count); +} + +mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count) { + return internal_flash_write_blocks(src, lba, count); +} + +void flash_flush (void) { + internal_flash_flush(); +} diff --git a/ports/nrf/flash_api/flash_api.h b/ports/nrf/flash_api/flash_api.h new file mode 100644 index 0000000000000..0136ecb31ceb0 --- /dev/null +++ b/ports/nrf/flash_api/flash_api.h @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * + * 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 FLASH_API_H_ +#define FLASH_API_H_ + +#include "extmod/vfs_fat.h" + +#define FLASH_API_BLOCK_SIZE 512 +#define FLASH_API_PAGE_SIZE 4096 +#define FLASH_API_BLOCK_PER_PAGE (FLASH_API_PAGE_SIZE/FLASH_API_BLOCK_SIZE) + +#ifdef __cplusplus + extern "C" { +#endif + +void flash_init_vfs (struct _fs_user_mount_t *vfs); +void flash_flush (void); + +mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count); +mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count); + +#ifdef __cplusplus + } +#endif + +#endif /* FLASH_API_H_ */ diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c new file mode 100644 index 0000000000000..2941b620364ab --- /dev/null +++ b/ports/nrf/flash_api/qspi_flash.c @@ -0,0 +1,81 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * + * 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 +#include "mpconfigboard.h" +#include "nrfx_qspi.h" +#include "flash_api.h" +#include "qspi_flash.h" + +//--------------------------------------------------------------------+ +// Flash caching +//--------------------------------------------------------------------+ +#define FLASH_API_PAGE_SIZE 4096 + +#define NO_CACHE 0xffffffff + +static uint32_t _fl_addr = NO_CACHE; +static uint8_t _fl_buf[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); + +void qspi_flash_flush (void) { + if ( _fl_addr == NO_CACHE ) return; + + if ( !(NRFX_SUCCESS == nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, _fl_addr)) ) return; +// while ( _fl_state != FLASH_STATE_COMPLETE ) +// { +// } +// _fl_state = FLASH_STATE_IDLE; + + if ( !(NRFX_SUCCESS == nrfx_qspi_write(_fl_buf, FLASH_API_PAGE_SIZE, _fl_addr)) ) return; +// while ( _fl_state != FLASH_STATE_COMPLETE ) +// { +// } +// _fl_state = FLASH_STATE_IDLE; + + _fl_addr = NO_CACHE; +} + + +mp_uint_t qspi_flash_write_blocks (uint8_t const *src, uint32_t lba, uint32_t count) { + uint32_t dst = lba * FLASH_API_BLOCK_SIZE; + uint32_t newAddr = dst & ~(FLASH_API_PAGE_SIZE - 1); + + if ( newAddr != _fl_addr ) { + qspi_flash_flush(); + _fl_addr = newAddr; + + qspi_flash_read_blocks(_fl_buf, newAddr / FLASH_API_BLOCK_SIZE, FLASH_API_BLOCK_PER_PAGE); + } + + memcpy(_fl_buf + (dst & (FLASH_API_PAGE_SIZE - 1)), src, count * FLASH_API_BLOCK_SIZE); + return 0; +} + +mp_uint_t qspi_flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { + return nrfx_qspi_read(dst, count * FLASH_API_BLOCK_SIZE, lba * FLASH_API_BLOCK_SIZE); +} + + diff --git a/ports/nrf/internal_flash.c b/ports/nrf/internal_flash.c index 812ef4d3f576d..6f7bc704233af 100644 --- a/ports/nrf/internal_flash.c +++ b/ports/nrf/internal_flash.c @@ -28,8 +28,8 @@ #include #include -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" +#include "flash_api/flash_api.h" + #include "py/mphal.h" #include "py/obj.h" #include "py/runtime.h" @@ -100,15 +100,15 @@ mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num return 0; // success } -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t num_blocks) { +mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t num_blocks) { #ifdef MICROPY_HW_LED_MSC port_pin_set_output_level(MICROPY_HW_LED_MSC, true); #endif while (num_blocks) { - uint32_t const addr = lba2addr(lba); - uint32_t const page_addr = addr & ~(FL_PAGE_SZ - 1); + const uint32_t addr = lba2addr(lba); + const uint32_t page_addr = addr & ~(FL_PAGE_SZ - 1); uint32_t count = 8 - (lba % 8); // up to page boundary count = MIN(num_blocks, count); @@ -145,7 +145,7 @@ mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t // Expose the flash as an object with the block protocol. // there is a singleton Flash object -STATIC const mp_obj_base_t internal_flash_obj = {&internal_flash_type}; +STATIC const mp_obj_base_t internal_flash_obj = { &internal_flash_type }; STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments @@ -220,7 +220,3 @@ void flash_init_vfs(fs_user_mount_t *vfs) { vfs->u.ioctl[0] = (mp_obj_t)&internal_flash_obj_ioctl_obj; vfs->u.ioctl[1] = (mp_obj_t)&internal_flash_obj; } - -void flash_flush(void) { - internal_flash_flush(); -} diff --git a/ports/nrf/internal_flash.h b/ports/nrf/internal_flash.h index 3811815e291b9..28eecdd3fab75 100644 --- a/ports/nrf/internal_flash.h +++ b/ports/nrf/internal_flash.h @@ -31,8 +31,6 @@ #include "mpconfigport.h" -#define FLASH_ROOT_POINTERS - #define FLASH_PAGE_SIZE 0x1000 #define CIRCUITPY_INTERNAL_NVM_SIZE 0 @@ -47,13 +45,10 @@ void internal_flash_flush(void); // these return 0 on success, non-zero on error mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); +mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t block_num, uint32_t num_blocks); extern const struct _mp_obj_type_t internal_flash_type; struct _fs_user_mount_t; -void flash_init_vfs(struct _fs_user_mount_t *vfs); -void flash_flush(void); - #endif // MICROPY_INCLUDED_NRF_INTERNAL_FLASH_H diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index fb603a896da2d..be4a739aec21a 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -2,47 +2,50 @@ #define NRFX_CONFIG_H__ // Power -#define NRFX_POWER_ENABLED 1 -#define NRFX_POWER_CONFIG_IRQ_PRIORITY 7 +#define NRFX_POWER_ENABLED 1 +#define NRFX_POWER_CONFIG_IRQ_PRIORITY 7 // SPI -#define NRFX_SPIM_ENABLED 1 +#define NRFX_SPIM_ENABLED 1 #ifdef NRF52840_XXAA - #define NRFX_SPIM3_ENABLED 1 +#define NRFX_SPIM3_ENABLED 1 #else - #define NRFX_SPIM2_ENABLED 1 +#define NRFX_SPIM2_ENABLED 1 #endif -#define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 -#define NRFX_SPIM_MISO_PULL_CFG 1 +#define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#define NRFX_SPIM_MISO_PULL_CFG 1 + +// QSPI +#define NRFX_QSPI_ENABLED 1 // TWI aka. I2C -#define NRFX_TWIM_ENABLED 1 -#define NRFX_TWIM0_ENABLED 1 +#define NRFX_TWIM_ENABLED 1 +#define NRFX_TWIM0_ENABLED 1 -#define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 -#define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY NRF_TWIM_FREQ_400K -#define NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 +#define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY NRF_TWIM_FREQ_400K +#define NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 // UART -#define NRFX_UART_ENABLED 1 -#define NRFX_UART0_ENABLED 1 +#define NRFX_UART_ENABLED 1 +#define NRFX_UART0_ENABLED 1 -#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 -#define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED -#define NRFX_UART_DEFAULT_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED -#define NRFX_UART_DEFAULT_CONFIG_BAUDRATE NRF_UART_BAUDRATE_115200 +#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 +#define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED +#define NRFX_UART_DEFAULT_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED +#define NRFX_UART_DEFAULT_CONFIG_BAUDRATE NRF_UART_BAUDRATE_115200 // PWM -#define NRFX_PWM0_ENABLED 1 -#define NRFX_PWM1_ENABLED 1 -#define NRFX_PWM2_ENABLED 1 +#define NRFX_PWM0_ENABLED 1 +#define NRFX_PWM1_ENABLED 1 +#define NRFX_PWM2_ENABLED 1 #ifdef NRF_PWM3 -#define NRFX_PWM3_ENABLED 1 +#define NRFX_PWM3_ENABLED 1 #else -#define NRFX_PWM3_ENABLED 0 +#define NRFX_PWM3_ENABLED 0 #endif #endif diff --git a/ports/nrf/supervisor/filesystem.c b/ports/nrf/supervisor/filesystem.c index 1a3165a2d7ad7..c52a58bb51c9c 100644 --- a/ports/nrf/supervisor/filesystem.c +++ b/ports/nrf/supervisor/filesystem.c @@ -29,8 +29,7 @@ #include "lib/oofatfs/diskio.h" #include "py/mpstate.h" - -#include "internal_flash.h" +#include "flash_api/flash_api.h" static mp_vfs_mount_t _mp_vfs; static fs_user_mount_t _internal_vfs; diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c index e6bb2545832dc..5657a934fd294 100644 --- a/ports/nrf/supervisor/port.c +++ b/ports/nrf/supervisor/port.c @@ -32,6 +32,10 @@ #include "nrf/clocks.h" #include "nrf/power.h" +#ifdef NRF52840_XXAA +#include "usb/usb.h" +#endif + #include "shared-module/gamepad/__init__.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/pulseio/PWMOut.h" @@ -59,9 +63,12 @@ safe_mode_t port_init(void) { #endif #endif - // Will do usb_init() if chip supports USB. board_init(); +#ifdef NRF52840_XXAA + usb_init(); +#endif + #if 0 if (board_requests_safe_mode()) { return USER_SAFE_MODE; diff --git a/ports/nrf/usb/usb_msc_flash.c b/ports/nrf/usb/usb_msc_flash.c index 2d0e9bec7f8eb..25c0754096dcf 100644 --- a/ports/nrf/usb/usb_msc_flash.c +++ b/ports/nrf/usb/usb_msc_flash.c @@ -35,6 +35,7 @@ /**************************************************************************/ #include "tusb.h" +#include "flash_api/flash_api.h" #include "internal_flash.h" // For updating fatfs's cache @@ -43,21 +44,11 @@ #include "lib/oofatfs/ff.h" #include "py/mpstate.h" -/*------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM - *------------------------------------------------------------------*/ -#define MSC_FLASH_ADDR_END 0xED000 -#define MSC_FLASH_SIZE (256*1024) -#define MSC_FLASH_ADDR_START (MSC_FLASH_ADDR_END-MSC_FLASH_SIZE) -#define MSC_FLASH_BLOCK_SIZE 512 - -#define FL_PAGE_SZ 4096 - // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { - void const* response = NULL; +int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, uint16_t bufsize) { + const void* response = NULL; uint16_t resplen = 0; switch ( scsi_cmd[0] ) { @@ -110,11 +101,11 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf (void) lun; (void) offset; - uint32_t const block_count = bufsize / MSC_FLASH_BLOCK_SIZE; + const uint32_t block_count = bufsize / FLASH_API_BLOCK_SIZE; - internal_flash_read_blocks(buffer, lba, block_count); + flash_read_blocks(buffer, lba, block_count); - return block_count * MSC_FLASH_BLOCK_SIZE; + return block_count * FLASH_API_BLOCK_SIZE; } // Callback invoked when received WRITE10 command. @@ -123,19 +114,19 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* bu (void) lun; (void) offset; - uint32_t const block_count = bufsize / MSC_FLASH_BLOCK_SIZE; + const uint32_t block_count = bufsize / FLASH_API_BLOCK_SIZE; // bufsize <= CFG_TUD_MSC_BUFSIZE (4096) - internal_flash_write_blocks(buffer, lba, block_count); + flash_write_blocks(buffer, lba, block_count); // update fatfs's cache if address matches fs_user_mount_t* vfs = MP_STATE_VM(vfs_mount_table)->obj; - if ( (lba <= vfs->fatfs.winsect) && (vfs->fatfs.winsect <= (lba + bufsize / MSC_FLASH_BLOCK_SIZE)) ) { - memcpy(vfs->fatfs.win, buffer + MSC_FLASH_BLOCK_SIZE * (vfs->fatfs.winsect - lba), MSC_FLASH_BLOCK_SIZE); + if ( (lba <= vfs->fatfs.winsect) && (vfs->fatfs.winsect <= (lba + bufsize / FLASH_API_BLOCK_SIZE)) ) { + memcpy(vfs->fatfs.win, buffer + FLASH_API_BLOCK_SIZE * (vfs->fatfs.winsect - lba), FLASH_API_BLOCK_SIZE); } - return block_count * MSC_FLASH_BLOCK_SIZE; + return block_count * FLASH_API_BLOCK_SIZE; } // Callback invoked when WRITE10 command is completed (status received and accepted by host). @@ -144,5 +135,5 @@ void tud_msc_write10_complete_cb (uint8_t lun) { (void) lun; // flush pending cache when write10 is complete - internal_flash_flush(); + flash_flush(); } From 81ec1d91685d895cb51e0865544cb7393742133b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Sep 2018 14:32:14 +0700 Subject: [PATCH 02/19] clean up --- ports/nrf/flash_api/flash_api.h | 2 +- ports/nrf/internal_flash.c | 33 +++++++++++++++++---------------- ports/nrf/internal_flash.h | 2 -- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/ports/nrf/flash_api/flash_api.h b/ports/nrf/flash_api/flash_api.h index 0136ecb31ceb0..3a45bf949fad9 100644 --- a/ports/nrf/flash_api/flash_api.h +++ b/ports/nrf/flash_api/flash_api.h @@ -29,7 +29,7 @@ #include "extmod/vfs_fat.h" -#define FLASH_API_BLOCK_SIZE 512 +#define FLASH_API_BLOCK_SIZE FILESYSTEM_BLOCK_SIZE #define FLASH_API_PAGE_SIZE 4096 #define FLASH_API_BLOCK_PER_PAGE (FLASH_API_PAGE_SIZE/FLASH_API_BLOCK_SIZE) diff --git a/ports/nrf/internal_flash.c b/ports/nrf/internal_flash.c index 6f7bc704233af..fbfc561ccfefe 100644 --- a/ports/nrf/internal_flash.c +++ b/ports/nrf/internal_flash.c @@ -23,12 +23,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "internal_flash.h" #include #include #include "flash_api/flash_api.h" +#include "internal_flash.h" #include "py/mphal.h" #include "py/obj.h" @@ -47,9 +47,8 @@ extern uint32_t __fatfs_flash_start_addr[]; extern uint32_t __fatfs_flash_length[]; #define NO_CACHE 0xffffffff -#define FL_PAGE_SZ 4096 -uint8_t _flash_cache[FL_PAGE_SZ] __attribute__((aligned(4))); +uint8_t _flash_cache[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); uint32_t _flash_page_addr = NO_CACHE; @@ -57,7 +56,7 @@ uint32_t _flash_page_addr = NO_CACHE; /* Internal Flash API *------------------------------------------------------------------*/ static inline uint32_t lba2addr(uint32_t block) { - return ((uint32_t)__fatfs_flash_start_addr) + block * FILESYSTEM_BLOCK_SIZE; + return ((uint32_t) __fatfs_flash_start_addr) + block * FLASH_API_BLOCK_SIZE; } void internal_flash_init(void) { @@ -73,11 +72,11 @@ void internal_flash_init(void) { } uint32_t internal_flash_get_block_size(void) { - return FILESYSTEM_BLOCK_SIZE; + return FLASH_API_BLOCK_SIZE; } uint32_t internal_flash_get_block_count(void) { - return ((uint32_t) __fatfs_flash_length) / FILESYSTEM_BLOCK_SIZE ; + return ((uint32_t) __fatfs_flash_length) / FLASH_API_BLOCK_SIZE; } // TODO support flashing with SD enabled @@ -85,10 +84,10 @@ void internal_flash_flush(void) { if (_flash_page_addr == NO_CACHE) return; // Skip if data is the same - if (memcmp(_flash_cache, (void *)_flash_page_addr, FL_PAGE_SZ) != 0) { + if ( memcmp(_flash_cache, (void *) _flash_page_addr, FLASH_API_PAGE_SIZE) != 0 ) { // _is_flashing = true; nrf_nvmc_page_erase(_flash_page_addr); - nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t)); + nrf_nvmc_write_words(_flash_page_addr, (uint32_t *) _flash_cache, FLASH_API_PAGE_SIZE / sizeof(uint32_t)); } _flash_page_addr = NO_CACHE; @@ -96,7 +95,7 @@ void internal_flash_flush(void) { mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { uint32_t src = lba2addr(block); - memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks); + memcpy(dest, (uint8_t*) src, FLASH_API_BLOCK_SIZE * num_blocks); return 0; // success } @@ -108,7 +107,7 @@ mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_ while (num_blocks) { const uint32_t addr = lba2addr(lba); - const uint32_t page_addr = addr & ~(FL_PAGE_SZ - 1); + const uint32_t page_addr = addr & ~(FLASH_API_PAGE_SIZE - 1); uint32_t count = 8 - (lba % 8); // up to page boundary count = MIN(num_blocks, count); @@ -121,14 +120,14 @@ mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_ // if ( _is_flashing ) return; _flash_page_addr = page_addr; - memcpy(_flash_cache, (void *)page_addr, FL_PAGE_SZ); + memcpy(_flash_cache, (void *) page_addr, FLASH_API_PAGE_SIZE); } - memcpy(_flash_cache + (addr & (FL_PAGE_SZ - 1)), src, count * FILESYSTEM_BLOCK_SIZE); + memcpy(_flash_cache + (addr & (FLASH_API_PAGE_SIZE - 1)), src, count * FLASH_API_BLOCK_SIZE); // adjust for next run - lba += count; - src += count * FILESYSTEM_BLOCK_SIZE; + lba += count; + src += count * FLASH_API_BLOCK_SIZE; num_blocks -= count; } @@ -158,7 +157,8 @@ STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_ STATIC mp_obj_t internal_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); + mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), + bufinfo.len / FLASH_API_BLOCK_SIZE); return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_flash_obj_readblocks); @@ -166,7 +166,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_fla STATIC mp_obj_t internal_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); + mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), + bufinfo.len / FLASH_API_BLOCK_SIZE); return MP_OBJ_NEW_SMALL_INT(ret); } STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_writeblocks_obj, internal_flash_obj_writeblocks); diff --git a/ports/nrf/internal_flash.h b/ports/nrf/internal_flash.h index 28eecdd3fab75..5b55397da80aa 100644 --- a/ports/nrf/internal_flash.h +++ b/ports/nrf/internal_flash.h @@ -31,7 +31,6 @@ #include "mpconfigport.h" -#define FLASH_PAGE_SIZE 0x1000 #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms @@ -40,7 +39,6 @@ void internal_flash_init(void); uint32_t internal_flash_get_block_size(void); uint32_t internal_flash_get_block_count(void); -void internal_flash_irq_handler(void); void internal_flash_flush(void); // these return 0 on success, non-zero on error From fae7f50b48efd96eaa945381d35dafba7ee83ecd Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Sep 2018 14:52:14 +0700 Subject: [PATCH 03/19] udate tinyusb msc flash size config --- ports/nrf/boards/pca10056/mpconfigboard.h | 3 ++ ports/nrf/flash_api/flash_api.c | 26 +++++++++++++ ports/nrf/flash_api/flash_api.h | 3 +- ports/nrf/flash_api/qspi_flash.c | 7 +++- ports/nrf/flash_api/qspi_flash.h | 45 +++++++++++++++++++++++ ports/nrf/usb/tusb_config.h | 3 +- 6 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 ports/nrf/flash_api/qspi_flash.h diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index 8b675d8dc0359..b4b88ab794b2d 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -56,3 +56,6 @@ #define QSPI_FLASH_D1 NRF_GPIO_PIN_MAP(0, 21) #define QSPI_FLASH_D2 NRF_GPIO_PIN_MAP(0, 22) #define QSPI_FLASH_D3 NRF_GPIO_PIN_MAP(0, 23) + +#define QSPI_FLASH_SIZE (8*1024*1024) + diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index 04a7b6868dfe2..5a10a3e4a4e8f 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -26,7 +26,9 @@ #include "flash_api.h" #include "internal_flash.h" +#include "qspi_flash.h" +#if 1 mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { return internal_flash_read_blocks(dst, lba, count); } @@ -38,3 +40,27 @@ mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count) void flash_flush (void) { internal_flash_flush(); } + +uint32_t flash_get_block_count (void) { + return internal_flash_get_block_count(); +} + +#else + +mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { + return qspi_flash_read_blocks(dst, lba, count); +} + +mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count) { + return qspi_flash_write_blocks(src, lba, count); +} + +void flash_flush (void) { + qspi_flash_flush(); +} + +uint32_t flash_get_block_count (void) { + return qspi_flash_get_block_count(); +} + +#endif diff --git a/ports/nrf/flash_api/flash_api.h b/ports/nrf/flash_api/flash_api.h index 3a45bf949fad9..7fad2b5dd8247 100644 --- a/ports/nrf/flash_api/flash_api.h +++ b/ports/nrf/flash_api/flash_api.h @@ -38,10 +38,11 @@ #endif void flash_init_vfs (struct _fs_user_mount_t *vfs); -void flash_flush (void); +uint32_t flash_get_block_count (void); mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count); mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count); +void flash_flush (void); #ifdef __cplusplus } diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 2941b620364ab..8e78c0f1638f8 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -40,6 +40,11 @@ static uint32_t _fl_addr = NO_CACHE; static uint8_t _fl_buf[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); +uint32_t qspi_flash_get_block_count (void) +{ + return QSPI_FLASH_SIZE / FLASH_API_BLOCK_SIZE; +} + void qspi_flash_flush (void) { if ( _fl_addr == NO_CACHE ) return; @@ -59,7 +64,7 @@ void qspi_flash_flush (void) { } -mp_uint_t qspi_flash_write_blocks (uint8_t const *src, uint32_t lba, uint32_t count) { +mp_uint_t qspi_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count) { uint32_t dst = lba * FLASH_API_BLOCK_SIZE; uint32_t newAddr = dst & ~(FLASH_API_PAGE_SIZE - 1); diff --git a/ports/nrf/flash_api/qspi_flash.h b/ports/nrf/flash_api/qspi_flash.h new file mode 100644 index 0000000000000..d4417143714f9 --- /dev/null +++ b/ports/nrf/flash_api/qspi_flash.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * + * 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 QSPI_FLASH_H_ +#define QSPI_FLASH_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +uint32_t qspi_flash_get_block_count (void); + +mp_uint_t qspi_flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count); +mp_uint_t qspi_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count); +void qspi_flash_flush (void); + + +#ifdef __cplusplus + } +#endif + +#endif /* QSPI_FLASH_H_ */ diff --git a/ports/nrf/usb/tusb_config.h b/ports/nrf/usb/tusb_config.h index 626b99eeb290f..4cb0b0694bf4e 100644 --- a/ports/nrf/usb/tusb_config.h +++ b/ports/nrf/usb/tusb_config.h @@ -97,7 +97,8 @@ #define CFG_TUD_MSC_MAXLUN 1 // Number of Blocks -#define CFG_TUD_MSC_BLOCK_NUM (256*1024)/512 +extern unsigned long flash_get_block_count (void); +#define CFG_TUD_MSC_BLOCK_NUM flash_get_block_count() // Block size #define CFG_TUD_MSC_BLOCK_SZ 512 From fc80e759ad357d9b89200900f36a1043e954496a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 01:45:29 +0700 Subject: [PATCH 04/19] qspi on pca10056 seems to work but write speed is slow --- ports/nrf/flash_api/flash_api.c | 112 +++++++++++++++++++++++++++++- ports/nrf/flash_api/flash_api.h | 2 + ports/nrf/flash_api/qspi_flash.c | 9 +-- ports/nrf/flash_api/qspi_flash.h | 1 + ports/nrf/internal_flash.c | 112 +----------------------------- ports/nrf/internal_flash.h | 4 -- ports/nrf/supervisor/filesystem.c | 7 +- ports/nrf/usb/usb_msc_flash.c | 9 ++- 8 files changed, 131 insertions(+), 125 deletions(-) diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index 5a10a3e4a4e8f..7361835752867 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -28,7 +28,15 @@ #include "internal_flash.h" #include "qspi_flash.h" -#if 1 +#include "py/mphal.h" +#include "py/obj.h" +#include "py/runtime.h" + +#if 0 +void flash_init (void) { + internal_flash_init(); +} + mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { return internal_flash_read_blocks(dst, lba, count); } @@ -47,6 +55,10 @@ uint32_t flash_get_block_count (void) { #else +void flash_init (void) { + qspi_flash_init(); +} + mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { return qspi_flash_read_blocks(dst, lba, count); } @@ -64,3 +76,101 @@ uint32_t flash_get_block_count (void) { } #endif + +/******************************************************************************/ +// MicroPython bindings +// +// Expose the flash as an object with the block protocol. +// there is a singleton Flash object +extern const struct _mp_obj_type_t _flash_type; // forward declaration + +STATIC const mp_obj_base_t _flash_obj = { &_flash_type }; + +STATIC mp_obj_t flash_obj_make_new (const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // return singleton object + return (mp_obj_t) &_flash_obj; +} + +STATIC mp_obj_t flash_obj_readblocks (mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); + mp_uint_t ret = flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_API_BLOCK_SIZE); + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(flash_obj_readblocks_obj, flash_obj_readblocks); + +STATIC mp_obj_t flash_obj_writeblocks (mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + mp_uint_t ret = flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FLASH_API_BLOCK_SIZE); + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(flash_obj_writeblocks_obj, flash_obj_writeblocks); + +STATIC mp_obj_t flash_obj_ioctl (mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { + mp_int_t cmd = mp_obj_get_int(cmd_in); + switch ( cmd ) { + case BP_IOCTL_INIT: + flash_init(); + return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_DEINIT: + flash_flush(); + return MP_OBJ_NEW_SMALL_INT(0); // TODO properly + case BP_IOCTL_SYNC: + flash_flush(); + return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_SEC_COUNT: + return MP_OBJ_NEW_SMALL_INT(flash_get_block_count()); + case BP_IOCTL_SEC_SIZE: + return MP_OBJ_NEW_SMALL_INT(FLASH_API_BLOCK_SIZE); + default: + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(flash_obj_ioctl_obj, flash_obj_ioctl); + +STATIC const mp_rom_map_elem_t flash_obj_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&flash_obj_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&flash_obj_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&flash_obj_ioctl_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(flash_obj_locals_dict, flash_obj_locals_dict_table); + +const mp_obj_type_t _flash_type = { + { &mp_type_type }, + .name = MP_QSTR_Flash, + .make_new = flash_obj_make_new, + .locals_dict = (mp_obj_t) &flash_obj_locals_dict, +}; + +void flash_init_vfs (fs_user_mount_t *vfs) { + vfs->base.type = &mp_fat_vfs_type; + vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->fatfs.drv = vfs; + +// vfs->fatfs.part = 1; // flash filesystem lives on first partition + vfs->readblocks[0] = (mp_obj_t) &flash_obj_readblocks_obj; + vfs->readblocks[1] = (mp_obj_t) &_flash_obj; + vfs->readblocks[2] = (mp_obj_t) flash_read_blocks; // native version + + vfs->writeblocks[0] = (mp_obj_t) &flash_obj_writeblocks_obj; + vfs->writeblocks[1] = (mp_obj_t) &_flash_obj; + vfs->writeblocks[2] = (mp_obj_t) flash_write_blocks; // native version + + vfs->u.ioctl[0] = (mp_obj_t) &flash_obj_ioctl_obj; + vfs->u.ioctl[1] = (mp_obj_t) &_flash_obj; + + // Activity LED for flash writes. +#ifdef MICROPY_HW_LED_MSC + struct port_config pin_conf; + port_get_config_defaults(&pin_conf); + + pin_conf.direction = PORT_PIN_DIR_OUTPUT; + port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf); + port_pin_set_output_level(MICROPY_HW_LED_MSC, false); +#endif +} diff --git a/ports/nrf/flash_api/flash_api.h b/ports/nrf/flash_api/flash_api.h index 7fad2b5dd8247..1d60420e49f29 100644 --- a/ports/nrf/flash_api/flash_api.h +++ b/ports/nrf/flash_api/flash_api.h @@ -38,6 +38,8 @@ #endif void flash_init_vfs (struct _fs_user_mount_t *vfs); + +void flash_init (void); uint32_t flash_get_block_count (void); mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count); diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 8e78c0f1638f8..74f774d3f6fd3 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -33,15 +33,16 @@ //--------------------------------------------------------------------+ // Flash caching //--------------------------------------------------------------------+ -#define FLASH_API_PAGE_SIZE 4096 - #define NO_CACHE 0xffffffff static uint32_t _fl_addr = NO_CACHE; static uint8_t _fl_buf[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); -uint32_t qspi_flash_get_block_count (void) -{ +void qspi_flash_init (void) { + +} + +uint32_t qspi_flash_get_block_count (void) { return QSPI_FLASH_SIZE / FLASH_API_BLOCK_SIZE; } diff --git a/ports/nrf/flash_api/qspi_flash.h b/ports/nrf/flash_api/qspi_flash.h index d4417143714f9..60babdb4e867d 100644 --- a/ports/nrf/flash_api/qspi_flash.h +++ b/ports/nrf/flash_api/qspi_flash.h @@ -31,6 +31,7 @@ extern "C" { #endif +void qspi_flash_init (void); uint32_t qspi_flash_get_block_count (void); mp_uint_t qspi_flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count); diff --git a/ports/nrf/internal_flash.c b/ports/nrf/internal_flash.c index fbfc561ccfefe..924be5083f4fd 100644 --- a/ports/nrf/internal_flash.c +++ b/ports/nrf/internal_flash.c @@ -28,11 +28,6 @@ #include #include "flash_api/flash_api.h" -#include "internal_flash.h" - -#include "py/mphal.h" -#include "py/obj.h" -#include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "supervisor/shared/rgb_led_status.h" @@ -51,24 +46,12 @@ extern uint32_t __fatfs_flash_length[]; uint8_t _flash_cache[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); uint32_t _flash_page_addr = NO_CACHE; - -/*------------------------------------------------------------------*/ -/* Internal Flash API - *------------------------------------------------------------------*/ static inline uint32_t lba2addr(uint32_t block) { return ((uint32_t) __fatfs_flash_start_addr) + block * FLASH_API_BLOCK_SIZE; } void internal_flash_init(void) { - // Activity LED for flash writes. -#ifdef MICROPY_HW_LED_MSC - struct port_config pin_conf; - port_get_config_defaults(&pin_conf); - - pin_conf.direction = PORT_PIN_DIR_OUTPUT; - port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf); - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); -#endif + } uint32_t internal_flash_get_block_size(void) { @@ -100,11 +83,6 @@ mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num } mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t num_blocks) { - -#ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, true); -#endif - while (num_blocks) { const uint32_t addr = lba2addr(lba); const uint32_t page_addr = addr & ~(FLASH_API_PAGE_SIZE - 1); @@ -131,93 +109,5 @@ mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_ num_blocks -= count; } -#ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); -#endif - return 0; // success } - -/******************************************************************************/ -// MicroPython bindings -// -// Expose the flash as an object with the block protocol. - -// there is a singleton Flash object -STATIC const mp_obj_base_t internal_flash_obj = { &internal_flash_type }; - -STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return singleton object - return (mp_obj_t)&internal_flash_obj; -} - -STATIC mp_obj_t internal_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), - bufinfo.len / FLASH_API_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_flash_obj_readblocks); - -STATIC mp_obj_t internal_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), - bufinfo.len / FLASH_API_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_writeblocks_obj, internal_flash_obj_writeblocks); - -STATIC mp_obj_t internal_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - switch (cmd) { - case BP_IOCTL_INIT: internal_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_size()); - default: return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_ioctl_obj, internal_flash_obj_ioctl); - -STATIC const mp_rom_map_elem_t internal_flash_obj_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&internal_flash_obj_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&internal_flash_obj_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&internal_flash_obj_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(internal_flash_obj_locals_dict, internal_flash_obj_locals_dict_table); - -const mp_obj_type_t internal_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_InternalFlash, - .make_new = internal_flash_obj_make_new, - .locals_dict = (mp_obj_t)&internal_flash_obj_locals_dict, -}; - -/*------------------------------------------------------------------*/ -/* Flash API - *------------------------------------------------------------------*/ - -void flash_init_vfs(fs_user_mount_t *vfs) { - vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; - vfs->fatfs.drv = vfs; - -// vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = (mp_obj_t)&internal_flash_obj_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->readblocks[2] = (mp_obj_t)internal_flash_read_blocks; // native version - - vfs->writeblocks[0] = (mp_obj_t)&internal_flash_obj_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)internal_flash_write_blocks; // native version - - vfs->u.ioctl[0] = (mp_obj_t)&internal_flash_obj_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&internal_flash_obj; -} diff --git a/ports/nrf/internal_flash.h b/ports/nrf/internal_flash.h index 5b55397da80aa..fc3db3dd3410b 100644 --- a/ports/nrf/internal_flash.h +++ b/ports/nrf/internal_flash.h @@ -45,8 +45,4 @@ void internal_flash_flush(void); mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t block_num, uint32_t num_blocks); -extern const struct _mp_obj_type_t internal_flash_type; - -struct _fs_user_mount_t; - #endif // MICROPY_INCLUDED_NRF_INTERNAL_FLASH_H diff --git a/ports/nrf/supervisor/filesystem.c b/ports/nrf/supervisor/filesystem.c index c52a58bb51c9c..e6d426556a567 100644 --- a/ports/nrf/supervisor/filesystem.c +++ b/ports/nrf/supervisor/filesystem.c @@ -32,12 +32,11 @@ #include "flash_api/flash_api.h" static mp_vfs_mount_t _mp_vfs; -static fs_user_mount_t _internal_vfs; - +static fs_user_mount_t _vfs; void filesystem_init(bool create_allowed) { // init the vfs object - fs_user_mount_t *int_vfs = &_internal_vfs; + fs_user_mount_t *int_vfs = &_vfs; int_vfs->flags = 0; flash_init_vfs(int_vfs); @@ -82,7 +81,7 @@ void filesystem_flush(void) { } void filesystem_writable_by_python(bool writable) { - fs_user_mount_t *vfs = &_internal_vfs; + fs_user_mount_t *vfs = &_vfs; if (writable) { vfs->flags |= FSUSER_USB_WRITABLE; diff --git a/ports/nrf/usb/usb_msc_flash.c b/ports/nrf/usb/usb_msc_flash.c index 25c0754096dcf..a1f12c9dead2d 100644 --- a/ports/nrf/usb/usb_msc_flash.c +++ b/ports/nrf/usb/usb_msc_flash.c @@ -36,7 +36,6 @@ #include "tusb.h" #include "flash_api/flash_api.h" -#include "internal_flash.h" // For updating fatfs's cache #include "extmod/vfs.h" @@ -114,6 +113,10 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* bu (void) lun; (void) offset; +#ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, true); +#endif + const uint32_t block_count = bufsize / FLASH_API_BLOCK_SIZE; // bufsize <= CFG_TUD_MSC_BUFSIZE (4096) @@ -126,6 +129,10 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* bu memcpy(vfs->fatfs.win, buffer + FLASH_API_BLOCK_SIZE * (vfs->fatfs.winsect - lba), FLASH_API_BLOCK_SIZE); } +#ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, false); +#endif + return block_count * FLASH_API_BLOCK_SIZE; } From 570b315ed9e2d84ab9265081e7098361c90f4be3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 01:50:23 +0700 Subject: [PATCH 05/19] move internal_flash to flash_api --- ports/nrf/Makefile | 2 +- ports/nrf/{ => flash_api}/internal_flash.c | 0 ports/nrf/{ => flash_api}/internal_flash.h | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename ports/nrf/{ => flash_api}/internal_flash.c (100%) rename ports/nrf/{ => flash_api}/internal_flash.h (100%) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 1345d3dfb9b72..5e2c0116f7e17 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -99,7 +99,6 @@ SRC_NRFX += $(addprefix nrfx/,\ SRC_C += \ background.c \ fatfs_port.c \ - internal_flash.c \ mphalport.c \ tick.c \ boards/$(BOARD)/board.c \ @@ -107,6 +106,7 @@ SRC_C += \ device/$(MCU_VARIANT)/startup_$(MCU_SUB_VARIANT).c \ drivers/bluetooth/ble_drv.c \ drivers/bluetooth/ble_uart.c \ + flash_api/internal_flash.c \ flash_api/flash_api.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ diff --git a/ports/nrf/internal_flash.c b/ports/nrf/flash_api/internal_flash.c similarity index 100% rename from ports/nrf/internal_flash.c rename to ports/nrf/flash_api/internal_flash.c diff --git a/ports/nrf/internal_flash.h b/ports/nrf/flash_api/internal_flash.h similarity index 100% rename from ports/nrf/internal_flash.h rename to ports/nrf/flash_api/internal_flash.h From 2dee81396f0a8e96394d7cf210c1cd6f26dc127f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 12:16:13 +0700 Subject: [PATCH 06/19] add MICROPY_HW_LED_MSC qspi flash is still corrupted occasionally --- ports/nrf/boards/pca10056/board.c | 25 ++++++----- ports/nrf/boards/pca10056/mpconfigboard.h | 51 +++++++++++---------- ports/nrf/flash_api/flash_api.c | 9 ++-- ports/nrf/flash_api/qspi_flash.c | 55 ++++++++++++++--------- ports/nrf/usb/usb_msc_flash.c | 5 ++- 5 files changed, 79 insertions(+), 66 deletions(-) diff --git a/ports/nrf/boards/pca10056/board.c b/ports/nrf/boards/pca10056/board.c index 4db6b34aa33cc..8c60d8ba587a9 100644 --- a/ports/nrf/boards/pca10056/board.c +++ b/ports/nrf/boards/pca10056/board.c @@ -25,22 +25,14 @@ */ #include "boards/board.h" +#include "nrf_gpio.h" #include "nrfx_qspi.h" #define QSPI_STD_CMD_RSTEN 0x66 #define QSPI_STD_CMD_RST 0x99 #define QSPI_STD_CMD_WRSR 0x01 -extern void qspi_flash_complete (void); - -void qflash_hdl (nrfx_qspi_evt_t event, void * p_context) -{ - (void) p_context; - (void) event; - -// qspi_flash_complete(); -} - +void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context); void board_init(void) { // Init QSPI flash @@ -69,8 +61,7 @@ void board_init(void) { .irq_priority = 7, }; -// nrfx_qspi_init(&qspi_cfg, qflash_hdl, NULL); - nrfx_qspi_init(&qspi_cfg, NULL, NULL); + nrfx_qspi_init(&qspi_cfg, qspi_flash_isr, NULL); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = 0, @@ -103,5 +94,15 @@ bool board_requests_safe_mode(void) { } void reset_board(void) { + // LEDs + for ( int i = 13; i <= 16; i++ ) { + nrf_gpio_cfg_output(i); + nrf_gpio_pin_set(i); + } + // Buttons + nrf_gpio_cfg_input(11, NRF_GPIO_PIN_PULLUP); + nrf_gpio_cfg_input(12, NRF_GPIO_PIN_PULLUP); + nrf_gpio_cfg_input(24, NRF_GPIO_PIN_PULLUP); + nrf_gpio_cfg_input(25, NRF_GPIO_PIN_PULLUP); } diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index b4b88ab794b2d..ea97b25e773b3 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -24,38 +24,41 @@ * THE SOFTWARE. */ -#define MICROPY_HW_BOARD_NAME "PCA10056 nRF52840-DK" -#define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "nRF52840-DK" +#define MICROPY_HW_BOARD_NAME "PCA10056 nRF52840-DK" +#define MICROPY_HW_MCU_NAME "nRF52840" +#define MICROPY_PY_SYS_PLATFORM "nRF52840-DK" // See legend on bottom of board -#define MICROPY_HW_UART_RX NRF_GPIO_PIN_MAP(0, 8) -#define MICROPY_HW_UART_TX NRF_GPIO_PIN_MAP(0, 6) -#define MICROPY_HW_UART_HWFC (0) +#define MICROPY_HW_UART_RX NRF_GPIO_PIN_MAP(0, 8) +#define MICROPY_HW_UART_TX NRF_GPIO_PIN_MAP(0, 6) +#define MICROPY_HW_UART_HWFC (0) -#define PORT_HEAP_SIZE (128 * 1024) -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 +#define MICROPY_HW_LED_MSC NRF_GPIO_PIN_MAP(0, 13) +#define MICROPY_HW_LED_MSC_ACTIVE_LEVEL 0 + +#define PORT_HEAP_SIZE (128 * 1024) +#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 // Temp (could be removed) 0: usb cdc (default), 1 : hwuart (jlink) -#define CFG_HWUART_FOR_SERIAL 0 +#define CFG_HWUART_FOR_SERIAL 0 -#define DEFAULT_I2C_BUS_SCL (&pin_P0_27) -#define DEFAULT_I2C_BUS_SDA (&pin_P0_26) +#define DEFAULT_I2C_BUS_SCL (&pin_P0_27) +#define DEFAULT_I2C_BUS_SDA (&pin_P0_26) -#define DEFAULT_SPI_BUS_SCK (&pin_P1_15) -#define DEFAULT_SPI_BUS_MOSI (&pin_P1_13) -#define DEFAULT_SPI_BUS_MISO (&pin_P1_14) +#define DEFAULT_SPI_BUS_SCK (&pin_P1_15) +#define DEFAULT_SPI_BUS_MOSI (&pin_P1_13) +#define DEFAULT_SPI_BUS_MISO (&pin_P1_14) -#define DEFAULT_UART_BUS_RX (&pin_P1_01) -#define DEFAULT_UART_BUS_TX (&pin_P1_02) +#define DEFAULT_UART_BUS_RX (&pin_P1_01) +#define DEFAULT_UART_BUS_TX (&pin_P1_02) // On-board QSPI Flash -#define QSPI_FLASH_CS NRF_GPIO_PIN_MAP(0, 17) -#define QSPI_FLASH_CLK NRF_GPIO_PIN_MAP(0, 19) -#define QSPI_FLASH_D0 NRF_GPIO_PIN_MAP(0, 20) -#define QSPI_FLASH_D1 NRF_GPIO_PIN_MAP(0, 21) -#define QSPI_FLASH_D2 NRF_GPIO_PIN_MAP(0, 22) -#define QSPI_FLASH_D3 NRF_GPIO_PIN_MAP(0, 23) - -#define QSPI_FLASH_SIZE (8*1024*1024) +#define QSPI_FLASH_CS NRF_GPIO_PIN_MAP(0, 17) +#define QSPI_FLASH_CLK NRF_GPIO_PIN_MAP(0, 19) +#define QSPI_FLASH_D0 NRF_GPIO_PIN_MAP(0, 20) +#define QSPI_FLASH_D1 NRF_GPIO_PIN_MAP(0, 21) +#define QSPI_FLASH_D2 NRF_GPIO_PIN_MAP(0, 22) +#define QSPI_FLASH_D3 NRF_GPIO_PIN_MAP(0, 23) + +#define QSPI_FLASH_SIZE (8*1024*1024) diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index 7361835752867..4c6f7fbbd0371 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include "nrf_gpio.h" #include "flash_api.h" #include "internal_flash.h" #include "qspi_flash.h" @@ -166,11 +167,7 @@ void flash_init_vfs (fs_user_mount_t *vfs) { // Activity LED for flash writes. #ifdef MICROPY_HW_LED_MSC - struct port_config pin_conf; - port_get_config_defaults(&pin_conf); - - pin_conf.direction = PORT_PIN_DIR_OUTPUT; - port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf); - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); + nrf_gpio_cfg_output(MICROPY_HW_LED_MSC); + nrf_gpio_pin_write(MICROPY_HW_LED_MSC, 1 - MICROPY_HW_LED_MSC_ACTIVE_LEVEL); #endif } diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 74f774d3f6fd3..7f7f4df79027f 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -25,18 +25,26 @@ */ #include + #include "mpconfigboard.h" #include "nrfx_qspi.h" #include "flash_api.h" #include "qspi_flash.h" -//--------------------------------------------------------------------+ -// Flash caching -//--------------------------------------------------------------------+ #define NO_CACHE 0xffffffff -static uint32_t _fl_addr = NO_CACHE; -static uint8_t _fl_buf[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); +static uint32_t _cache_addr = NO_CACHE; +static uint8_t _cache_buf[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); + +volatile static bool _qspi_complete = false; + +void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context) +{ + (void) p_context; + (void) event; + + _qspi_complete = true; +} void qspi_flash_init (void) { @@ -47,21 +55,19 @@ uint32_t qspi_flash_get_block_count (void) { } void qspi_flash_flush (void) { - if ( _fl_addr == NO_CACHE ) return; + if ( _cache_addr == NO_CACHE ) return; - if ( !(NRFX_SUCCESS == nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, _fl_addr)) ) return; -// while ( _fl_state != FLASH_STATE_COMPLETE ) -// { -// } -// _fl_state = FLASH_STATE_IDLE; + if ( !(NRFX_SUCCESS == nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, _cache_addr)) ) return; + while ( !_qspi_complete ) { + } + _qspi_complete = false; - if ( !(NRFX_SUCCESS == nrfx_qspi_write(_fl_buf, FLASH_API_PAGE_SIZE, _fl_addr)) ) return; -// while ( _fl_state != FLASH_STATE_COMPLETE ) -// { -// } -// _fl_state = FLASH_STATE_IDLE; + if ( !(NRFX_SUCCESS == nrfx_qspi_write(_cache_buf, FLASH_API_PAGE_SIZE, _cache_addr)) ) return; + while ( !_qspi_complete ) { + } + _qspi_complete = false; - _fl_addr = NO_CACHE; + _cache_addr = NO_CACHE; } @@ -69,19 +75,24 @@ mp_uint_t qspi_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t co uint32_t dst = lba * FLASH_API_BLOCK_SIZE; uint32_t newAddr = dst & ~(FLASH_API_PAGE_SIZE - 1); - if ( newAddr != _fl_addr ) { + if ( newAddr != _cache_addr ) { qspi_flash_flush(); - _fl_addr = newAddr; + _cache_addr = newAddr; - qspi_flash_read_blocks(_fl_buf, newAddr / FLASH_API_BLOCK_SIZE, FLASH_API_BLOCK_PER_PAGE); + qspi_flash_read_blocks(_cache_buf, newAddr / FLASH_API_BLOCK_SIZE, FLASH_API_BLOCK_PER_PAGE); } - memcpy(_fl_buf + (dst & (FLASH_API_PAGE_SIZE - 1)), src, count * FLASH_API_BLOCK_SIZE); + memcpy(_cache_buf + (dst & (FLASH_API_PAGE_SIZE - 1)), src, count * FLASH_API_BLOCK_SIZE); return 0; } mp_uint_t qspi_flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { - return nrfx_qspi_read(dst, count * FLASH_API_BLOCK_SIZE, lba * FLASH_API_BLOCK_SIZE); + nrfx_qspi_read(dst, count * FLASH_API_BLOCK_SIZE, lba * FLASH_API_BLOCK_SIZE); + while ( !_qspi_complete ) { + } + _qspi_complete = false; + + return 0; } diff --git a/ports/nrf/usb/usb_msc_flash.c b/ports/nrf/usb/usb_msc_flash.c index a1f12c9dead2d..13a78623905d3 100644 --- a/ports/nrf/usb/usb_msc_flash.c +++ b/ports/nrf/usb/usb_msc_flash.c @@ -35,6 +35,7 @@ /**************************************************************************/ #include "tusb.h" +#include "nrf_gpio.h" #include "flash_api/flash_api.h" // For updating fatfs's cache @@ -114,7 +115,7 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* bu (void) offset; #ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, true); + nrf_gpio_pin_write(MICROPY_HW_LED_MSC, MICROPY_HW_LED_MSC_ACTIVE_LEVEL); #endif const uint32_t block_count = bufsize / FLASH_API_BLOCK_SIZE; @@ -130,7 +131,7 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* bu } #ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); + nrf_gpio_pin_write(MICROPY_HW_LED_MSC, 1 - MICROPY_HW_LED_MSC_ACTIVE_LEVEL); #endif return block_count * FLASH_API_BLOCK_SIZE; From 155ea3ee10b00e1ff055635ed682be64d95e3a9f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 18:26:26 +0700 Subject: [PATCH 07/19] add flash_hal API - move write caching to flash_api for both internal and qspi flash - fix flash write blocks for qspi --- ports/nrf/flash_api/flash_api.c | 99 +++++++++++++++++++++++----- ports/nrf/flash_api/flash_api.h | 21 +++++- ports/nrf/flash_api/internal_flash.c | 58 +++------------- ports/nrf/flash_api/internal_flash.h | 15 ++--- ports/nrf/flash_api/qspi_flash.c | 43 +++--------- ports/nrf/flash_api/qspi_flash.h | 9 ++- 6 files changed, 131 insertions(+), 114 deletions(-) diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index 4c6f7fbbd0371..a52712df6b9ca 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include "nrf_gpio.h" #include "flash_api.h" #include "internal_flash.h" @@ -33,47 +34,110 @@ #include "py/obj.h" #include "py/runtime.h" -#if 0 -void flash_init (void) { - internal_flash_init(); +//--------------------------------------------------------------------+ +// Block API with caching +//--------------------------------------------------------------------+ +#define NO_CACHE 0xffffffff + +static uint32_t _cache_addr = NO_CACHE; +static uint8_t _cache_buf[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); + +static inline uint32_t page_addr_of (uint32_t addr) { + return addr & ~(FLASH_API_PAGE_SIZE - 1); } mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { - return internal_flash_read_blocks(dst, lba, count); + flash_hal_read(dst, lba * FLASH_API_BLOCK_SIZE, count * FLASH_API_BLOCK_SIZE); + return 0; } -mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count) { - return internal_flash_write_blocks(src, lba, count); +mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t num_blocks) { + // Program blocks up to page boundary each loop + while ( num_blocks ) { + const uint32_t dst = lba * FLASH_API_BLOCK_SIZE; + const uint32_t page_addr = page_addr_of(dst); + + uint32_t wr_count = FLASH_API_BLOCK_PER_PAGE - (lba % FLASH_API_BLOCK_PER_PAGE); // up to page boundary + wr_count = MIN(num_blocks, wr_count); + + // Page changes, flush old and update new cache + if ( page_addr != _cache_addr ) { + flash_flush(); + + _cache_addr = page_addr; + flash_read_blocks(_cache_buf, page_addr / FLASH_API_BLOCK_SIZE, FLASH_API_BLOCK_PER_PAGE); + } + + memcpy(_cache_buf + (dst & (FLASH_API_PAGE_SIZE - 1)), src, wr_count * FLASH_API_BLOCK_SIZE); + + // adjust for next run + lba += wr_count; + src += wr_count * FLASH_API_BLOCK_SIZE; + num_blocks -= wr_count; + } + + return 0; } void flash_flush (void) { - internal_flash_flush(); + if ( _cache_addr == NO_CACHE ) return; + + flash_hal_erase(_cache_addr); + flash_hal_program(_cache_addr, _cache_buf, FLASH_API_PAGE_SIZE); + + _cache_addr = NO_CACHE; +} + +uint32_t flash_read_blocks_nonblocking (uint8_t* dst, uint32_t lba, uint32_t count) { + return count; +} + +//--------------------------------------------------------------------+ +// Flash HAL +//--------------------------------------------------------------------+ + +#if 1 + +void flash_init (void) { + internal_flash_init(); } uint32_t flash_get_block_count (void) { return internal_flash_get_block_count(); } +void flash_hal_erase (uint32_t addr) { + internal_flash_hal_erase(addr); +} + +void flash_hal_program (uint32_t dst, const void * src, uint32_t len) { + internal_flash_hal_program(dst, src, len); +} + +void flash_hal_read (void* dst, uint32_t src, uint32_t len) { + internal_flash_hal_read(dst, src, len); +} + #else void flash_init (void) { qspi_flash_init(); } -mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { - return qspi_flash_read_blocks(dst, lba, count); +uint32_t flash_get_block_count (void) { + return qspi_flash_get_block_count(); } -mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count) { - return qspi_flash_write_blocks(src, lba, count); +void flash_hal_erase (uint32_t addr) { + qspi_flash_hal_erase(addr); } -void flash_flush (void) { - qspi_flash_flush(); +void flash_hal_program (uint32_t dst, const void * src, uint32_t len) { + qspi_flash_hal_program(dst, src, len); } -uint32_t flash_get_block_count (void) { - return qspi_flash_get_block_count(); +void flash_hal_read (void* dst, uint32_t src, uint32_t len) { + qspi_flash_hal_read(dst, src, len); } #endif @@ -83,9 +147,10 @@ uint32_t flash_get_block_count (void) { // // Expose the flash as an object with the block protocol. // there is a singleton Flash object +/******************************************************************************/ extern const struct _mp_obj_type_t _flash_type; // forward declaration -STATIC const mp_obj_base_t _flash_obj = { &_flash_type }; +const STATIC mp_obj_base_t _flash_obj = { &_flash_type }; STATIC mp_obj_t flash_obj_make_new (const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments @@ -133,7 +198,7 @@ STATIC mp_obj_t flash_obj_ioctl (mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in } STATIC MP_DEFINE_CONST_FUN_OBJ_3(flash_obj_ioctl_obj, flash_obj_ioctl); -STATIC const mp_rom_map_elem_t flash_obj_locals_dict_table[] = { + const STATIC mp_rom_map_elem_t flash_obj_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&flash_obj_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&flash_obj_writeblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&flash_obj_ioctl_obj) }, diff --git a/ports/nrf/flash_api/flash_api.h b/ports/nrf/flash_api/flash_api.h index 1d60420e49f29..763e06d2b4e34 100644 --- a/ports/nrf/flash_api/flash_api.h +++ b/ports/nrf/flash_api/flash_api.h @@ -33,19 +33,36 @@ #define FLASH_API_PAGE_SIZE 4096 #define FLASH_API_BLOCK_PER_PAGE (FLASH_API_PAGE_SIZE/FLASH_API_BLOCK_SIZE) +enum { + FLASH_STATE_IDLE, + FLASH_STATE_BUSY, + FLASH_STATE_COMPLETE +}; + #ifdef __cplusplus extern "C" { #endif -void flash_init_vfs (struct _fs_user_mount_t *vfs); - +// Low level flash hal void flash_init (void); uint32_t flash_get_block_count (void); +void flash_hal_erase (uint32_t addr); +void flash_hal_program (uint32_t dst, const void* src, uint32_t len); +void flash_hal_read (void* dst, uint32_t src, uint32_t len); +void flash_init_vfs (struct _fs_user_mount_t *vfs); + +// Blocking API for circuitpython mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count); mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count); void flash_flush (void); +// Non-blocking API for usb +uint8_t flash_get_state (void); +uint32_t flash_read_blocks_nonblocking (uint8_t* dst, uint32_t lba, uint32_t count); +//uint32_t flash_write_blocks_nonblocking (const uint8_t *src, uint32_t lba, uint32_t count); + + #ifdef __cplusplus } #endif diff --git a/ports/nrf/flash_api/internal_flash.c b/ports/nrf/flash_api/internal_flash.c index 924be5083f4fd..e07a28c6e90cb 100644 --- a/ports/nrf/flash_api/internal_flash.c +++ b/ports/nrf/flash_api/internal_flash.c @@ -46,68 +46,28 @@ extern uint32_t __fatfs_flash_length[]; uint8_t _flash_cache[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); uint32_t _flash_page_addr = NO_CACHE; -static inline uint32_t lba2addr(uint32_t block) { - return ((uint32_t) __fatfs_flash_start_addr) + block * FLASH_API_BLOCK_SIZE; +static inline uint32_t log2phy_addr (uint32_t addr) { + return ((uint32_t) __fatfs_flash_start_addr) + addr; } void internal_flash_init(void) { } -uint32_t internal_flash_get_block_size(void) { - return FLASH_API_BLOCK_SIZE; -} - uint32_t internal_flash_get_block_count(void) { return ((uint32_t) __fatfs_flash_length) / FLASH_API_BLOCK_SIZE; } // TODO support flashing with SD enabled -void internal_flash_flush(void) { - if (_flash_page_addr == NO_CACHE) return; - - // Skip if data is the same - if ( memcmp(_flash_cache, (void *) _flash_page_addr, FLASH_API_PAGE_SIZE) != 0 ) { -// _is_flashing = true; - nrf_nvmc_page_erase(_flash_page_addr); - nrf_nvmc_write_words(_flash_page_addr, (uint32_t *) _flash_cache, FLASH_API_PAGE_SIZE / sizeof(uint32_t)); - } - - _flash_page_addr = NO_CACHE; +void internal_flash_hal_erase (uint32_t addr) { + nrf_nvmc_page_erase(log2phy_addr(addr)); } -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { - uint32_t src = lba2addr(block); - memcpy(dest, (uint8_t*) src, FLASH_API_BLOCK_SIZE * num_blocks); - return 0; // success +void internal_flash_hal_program (uint32_t dst, const void * src, uint32_t len) { + nrf_nvmc_write_words(log2phy_addr(dst), (uint32_t *) src, len / sizeof(uint32_t)); } -mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t num_blocks) { - while (num_blocks) { - const uint32_t addr = lba2addr(lba); - const uint32_t page_addr = addr & ~(FLASH_API_PAGE_SIZE - 1); - - uint32_t count = 8 - (lba % 8); // up to page boundary - count = MIN(num_blocks, count); - - if (page_addr != _flash_page_addr) { - internal_flash_flush(); - - // writing previous cached data, skip current data until flashing is done - // tinyusb stack will invoke write_block() with the same parameters later on - // if ( _is_flashing ) return; - - _flash_page_addr = page_addr; - memcpy(_flash_cache, (void *) page_addr, FLASH_API_PAGE_SIZE); - } - - memcpy(_flash_cache + (addr & (FLASH_API_PAGE_SIZE - 1)), src, count * FLASH_API_BLOCK_SIZE); - - // adjust for next run - lba += count; - src += count * FLASH_API_BLOCK_SIZE; - num_blocks -= count; - } - - return 0; // success +void internal_flash_hal_read (void* dst, uint32_t src, uint32_t len) { + memcpy(dst, (void*) log2phy_addr(src), len); } + diff --git a/ports/nrf/flash_api/internal_flash.h b/ports/nrf/flash_api/internal_flash.h index fc3db3dd3410b..3855890c60d80 100644 --- a/ports/nrf/flash_api/internal_flash.h +++ b/ports/nrf/flash_api/internal_flash.h @@ -33,16 +33,11 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE 0 -#define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms -#define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2) +void internal_flash_init (void); +uint32_t internal_flash_get_block_count (void); -void internal_flash_init(void); -uint32_t internal_flash_get_block_size(void); -uint32_t internal_flash_get_block_count(void); -void internal_flash_flush(void); - -// these return 0 on success, non-zero on error -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t internal_flash_write_blocks (const uint8_t *src, uint32_t block_num, uint32_t num_blocks); +void internal_flash_hal_erase (uint32_t addr); +void internal_flash_hal_program (uint32_t dst, const void * src, uint32_t len); +void internal_flash_hal_read (void* dst, uint32_t src, uint32_t len); #endif // MICROPY_INCLUDED_NRF_INTERNAL_FLASH_H diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 7f7f4df79027f..89e781ae7e891 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -31,11 +31,6 @@ #include "flash_api.h" #include "qspi_flash.h" -#define NO_CACHE 0xffffffff - -static uint32_t _cache_addr = NO_CACHE; -static uint8_t _cache_buf[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); - volatile static bool _qspi_complete = false; void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context) @@ -54,45 +49,27 @@ uint32_t qspi_flash_get_block_count (void) { return QSPI_FLASH_SIZE / FLASH_API_BLOCK_SIZE; } -void qspi_flash_flush (void) { - if ( _cache_addr == NO_CACHE ) return; +uint8_t qspi_flash_get_state (void) { + return 0; +} - if ( !(NRFX_SUCCESS == nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, _cache_addr)) ) return; +void qspi_flash_hal_erase (uint32_t addr) { + if ( !(NRFX_SUCCESS == nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, addr)) ) return; while ( !_qspi_complete ) { } _qspi_complete = false; +} - if ( !(NRFX_SUCCESS == nrfx_qspi_write(_cache_buf, FLASH_API_PAGE_SIZE, _cache_addr)) ) return; +void qspi_flash_hal_program (uint32_t dst, const void* src, uint32_t len) { + if ( !(NRFX_SUCCESS == nrfx_qspi_write(src, len, dst)) ) return; while ( !_qspi_complete ) { } _qspi_complete = false; - - _cache_addr = NO_CACHE; -} - - -mp_uint_t qspi_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count) { - uint32_t dst = lba * FLASH_API_BLOCK_SIZE; - uint32_t newAddr = dst & ~(FLASH_API_PAGE_SIZE - 1); - - if ( newAddr != _cache_addr ) { - qspi_flash_flush(); - _cache_addr = newAddr; - - qspi_flash_read_blocks(_cache_buf, newAddr / FLASH_API_BLOCK_SIZE, FLASH_API_BLOCK_PER_PAGE); - } - - memcpy(_cache_buf + (dst & (FLASH_API_PAGE_SIZE - 1)), src, count * FLASH_API_BLOCK_SIZE); - return 0; } -mp_uint_t qspi_flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { - nrfx_qspi_read(dst, count * FLASH_API_BLOCK_SIZE, lba * FLASH_API_BLOCK_SIZE); +void qspi_flash_hal_read (void* dst, uint32_t src, uint32_t len) { + nrfx_qspi_read(dst, len, src); while ( !_qspi_complete ) { } _qspi_complete = false; - - return 0; } - - diff --git a/ports/nrf/flash_api/qspi_flash.h b/ports/nrf/flash_api/qspi_flash.h index 60babdb4e867d..423ed587606d5 100644 --- a/ports/nrf/flash_api/qspi_flash.h +++ b/ports/nrf/flash_api/qspi_flash.h @@ -34,9 +34,12 @@ void qspi_flash_init (void); uint32_t qspi_flash_get_block_count (void); -mp_uint_t qspi_flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count); -mp_uint_t qspi_flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count); -void qspi_flash_flush (void); +void qspi_flash_hal_erase (uint32_t addr); +void qspi_flash_hal_program (uint32_t dst, const void * src, uint32_t len); +void qspi_flash_hal_read (void* dst, uint32_t src, uint32_t len); + + +uint8_t qspi_flash_get_state (void); #ifdef __cplusplus From 19abe37cad000f8269c51ea45b5b5b86c0a0e2eb Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 18:26:45 +0700 Subject: [PATCH 08/19] rename vfs to user_vfs --- ports/nrf/supervisor/filesystem.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/nrf/supervisor/filesystem.c b/ports/nrf/supervisor/filesystem.c index e6d426556a567..7705e099be824 100644 --- a/ports/nrf/supervisor/filesystem.c +++ b/ports/nrf/supervisor/filesystem.c @@ -32,11 +32,11 @@ #include "flash_api/flash_api.h" static mp_vfs_mount_t _mp_vfs; -static fs_user_mount_t _vfs; +static fs_user_mount_t _user_vfs; void filesystem_init(bool create_allowed) { // init the vfs object - fs_user_mount_t *int_vfs = &_vfs; + fs_user_mount_t *int_vfs = &_user_vfs; int_vfs->flags = 0; flash_init_vfs(int_vfs); @@ -81,7 +81,7 @@ void filesystem_flush(void) { } void filesystem_writable_by_python(bool writable) { - fs_user_mount_t *vfs = &_vfs; + fs_user_mount_t *vfs = &_user_vfs; if (writable) { vfs->flags |= FSUSER_USB_WRITABLE; From 78a2e4ee4dd178e0dabf9d923eae884a3df1935c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 18:51:34 +0700 Subject: [PATCH 09/19] update qspi config --- ports/nrf/boards/pca10056/board.c | 58 ----------------------- ports/nrf/boards/pca10056/mpconfigboard.h | 54 +++++++++++---------- ports/nrf/flash_api/flash_api.c | 2 +- ports/nrf/flash_api/qspi_flash.c | 56 ++++++++++++++++++++++ 4 files changed, 86 insertions(+), 84 deletions(-) diff --git a/ports/nrf/boards/pca10056/board.c b/ports/nrf/boards/pca10056/board.c index 8c60d8ba587a9..d18a54c95fc27 100644 --- a/ports/nrf/boards/pca10056/board.c +++ b/ports/nrf/boards/pca10056/board.c @@ -26,67 +26,9 @@ #include "boards/board.h" #include "nrf_gpio.h" -#include "nrfx_qspi.h" - -#define QSPI_STD_CMD_RSTEN 0x66 -#define QSPI_STD_CMD_RST 0x99 -#define QSPI_STD_CMD_WRSR 0x01 - -void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context); void board_init(void) { - // Init QSPI flash - nrfx_qspi_config_t qspi_cfg = { - .xip_offset = 0, - .pins = { - .sck_pin = 19, - .csn_pin = 17, - .io0_pin = 20, - .io1_pin = 21, - .io2_pin = 22, - .io3_pin = 23, - }, - .prot_if = { - .readoc = NRF_QSPI_READOC_READ4IO, - .writeoc = NRF_QSPI_WRITEOC_PP4IO, - .addrmode = NRF_QSPI_ADDRMODE_24BIT, - .dpmconfig = false, // deep power down - }, - .phy_if = { - .sck_freq = NRF_QSPI_FREQ_32MDIV1, - .sck_delay = 1, - .spi_mode = NRF_QSPI_MODE_0, - .dpmen = false - }, - .irq_priority = 7, - }; - - nrfx_qspi_init(&qspi_cfg, qspi_flash_isr, NULL); - - nrf_qspi_cinstr_conf_t cinstr_cfg = { - .opcode = 0, - .length = 0, - .io2_level = true, - .io3_level = true, - .wipwait = true, - .wren = true - }; - - // Send reset enable - cinstr_cfg.opcode = QSPI_STD_CMD_RSTEN; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; - nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); - - // Send reset command - cinstr_cfg.opcode = QSPI_STD_CMD_RST; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; - nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); - // Switch to qspi mode - uint8_t sr_quad_en = 0x40; - cinstr_cfg.opcode = QSPI_STD_CMD_WRSR; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B; - nrfx_qspi_cinstr_xfer(&cinstr_cfg, &sr_quad_en, NULL); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index ea97b25e773b3..29fe7d562711c 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -24,41 +24,45 @@ * THE SOFTWARE. */ -#define MICROPY_HW_BOARD_NAME "PCA10056 nRF52840-DK" -#define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "nRF52840-DK" +#define MICROPY_HW_BOARD_NAME "PCA10056 nRF52840-DK" +#define MICROPY_HW_MCU_NAME "nRF52840" +#define MICROPY_PY_SYS_PLATFORM "nRF52840-DK" // See legend on bottom of board -#define MICROPY_HW_UART_RX NRF_GPIO_PIN_MAP(0, 8) -#define MICROPY_HW_UART_TX NRF_GPIO_PIN_MAP(0, 6) -#define MICROPY_HW_UART_HWFC (0) +#define MICROPY_HW_UART_RX NRF_GPIO_PIN_MAP(0, 8) +#define MICROPY_HW_UART_TX NRF_GPIO_PIN_MAP(0, 6) +#define MICROPY_HW_UART_HWFC (0) -#define MICROPY_HW_LED_MSC NRF_GPIO_PIN_MAP(0, 13) -#define MICROPY_HW_LED_MSC_ACTIVE_LEVEL 0 +#define MICROPY_HW_LED_MSC NRF_GPIO_PIN_MAP(0, 13) +#define MICROPY_HW_LED_MSC_ACTIVE_LEVEL 0 -#define PORT_HEAP_SIZE (128 * 1024) -#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 +#define PORT_HEAP_SIZE (128 * 1024) +#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 // Temp (could be removed) 0: usb cdc (default), 1 : hwuart (jlink) -#define CFG_HWUART_FOR_SERIAL 0 +#define CFG_HWUART_FOR_SERIAL 0 -#define DEFAULT_I2C_BUS_SCL (&pin_P0_27) -#define DEFAULT_I2C_BUS_SDA (&pin_P0_26) +#define DEFAULT_I2C_BUS_SCL (&pin_P0_27) +#define DEFAULT_I2C_BUS_SDA (&pin_P0_26) -#define DEFAULT_SPI_BUS_SCK (&pin_P1_15) -#define DEFAULT_SPI_BUS_MOSI (&pin_P1_13) -#define DEFAULT_SPI_BUS_MISO (&pin_P1_14) +#define DEFAULT_SPI_BUS_SCK (&pin_P1_15) +#define DEFAULT_SPI_BUS_MOSI (&pin_P1_13) +#define DEFAULT_SPI_BUS_MISO (&pin_P1_14) -#define DEFAULT_UART_BUS_RX (&pin_P1_01) -#define DEFAULT_UART_BUS_TX (&pin_P1_02) +#define DEFAULT_UART_BUS_RX (&pin_P1_01) +#define DEFAULT_UART_BUS_TX (&pin_P1_02) // On-board QSPI Flash -#define QSPI_FLASH_CS NRF_GPIO_PIN_MAP(0, 17) -#define QSPI_FLASH_CLK NRF_GPIO_PIN_MAP(0, 19) -#define QSPI_FLASH_D0 NRF_GPIO_PIN_MAP(0, 20) -#define QSPI_FLASH_D1 NRF_GPIO_PIN_MAP(0, 21) -#define QSPI_FLASH_D2 NRF_GPIO_PIN_MAP(0, 22) -#define QSPI_FLASH_D3 NRF_GPIO_PIN_MAP(0, 23) +#define QSPI_FLASH_SIZE (8*1024*1024) +#define QSPI_FLASH_FREQ NRF_QSPI_FREQ_32MDIV1 +#define QSPI_FLASH_READ_OPCODE NRF_QSPI_READOC_READ4IO +#define QSPI_FLASH_WRITE_OPCODE NRF_QSPI_WRITEOC_PP4IO + +#define QSPI_FLASH_CS NRF_GPIO_PIN_MAP(0, 17) +#define QSPI_FLASH_SCK NRF_GPIO_PIN_MAP(0, 19) +#define QSPI_FLASH_D0 NRF_GPIO_PIN_MAP(0, 20) +#define QSPI_FLASH_D1 NRF_GPIO_PIN_MAP(0, 21) +#define QSPI_FLASH_D2 NRF_GPIO_PIN_MAP(0, 22) +#define QSPI_FLASH_D3 NRF_GPIO_PIN_MAP(0, 23) -#define QSPI_FLASH_SIZE (8*1024*1024) diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index a52712df6b9ca..38f1fc4e6a00b 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -96,7 +96,7 @@ uint32_t flash_read_blocks_nonblocking (uint8_t* dst, uint32_t lba, uint32_t cou // Flash HAL //--------------------------------------------------------------------+ -#if 1 +#if 0 void flash_init (void) { internal_flash_init(); diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 89e781ae7e891..269b7b49d5267 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -27,10 +27,15 @@ #include #include "mpconfigboard.h" +#include "nrf_gpio.h" #include "nrfx_qspi.h" #include "flash_api.h" #include "qspi_flash.h" +#define QSPI_STD_CMD_RSTEN 0x66 +#define QSPI_STD_CMD_RST 0x99 +#define QSPI_STD_CMD_WRSR 0x01 + volatile static bool _qspi_complete = false; void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context) @@ -42,7 +47,58 @@ void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context) } void qspi_flash_init (void) { + // Init QSPI flash + nrfx_qspi_config_t qspi_cfg = { + .xip_offset = 0, + .pins = { + .sck_pin = QSPI_FLASH_SCK, + .csn_pin = QSPI_FLASH_CS, + .io0_pin = QSPI_FLASH_D0, + .io1_pin = QSPI_FLASH_D1, + .io2_pin = QSPI_FLASH_D2, + .io3_pin = QSPI_FLASH_D3, + }, + .prot_if = { + .readoc = QSPI_FLASH_READ_OPCODE, + .writeoc = QSPI_FLASH_WRITE_OPCODE, + .addrmode = NRF_QSPI_ADDRMODE_24BIT, + .dpmconfig = false + }, + .phy_if = { + .sck_freq = QSPI_FLASH_FREQ, + .sck_delay = 1, + .spi_mode = NRF_QSPI_MODE_0, + .dpmen = false + }, + .irq_priority = 7, + }; + + nrfx_qspi_init(&qspi_cfg, qspi_flash_isr, NULL); + + nrf_qspi_cinstr_conf_t cinstr_cfg = { + .opcode = 0, + .length = 0, + .io2_level = true, + .io3_level = true, + .wipwait = true, + .wren = true + }; + + // Send reset enable + cinstr_cfg.opcode = QSPI_STD_CMD_RSTEN; + cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); + + // Send reset command + cinstr_cfg.opcode = QSPI_STD_CMD_RST; + cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); + // Switch to qspi mode + uint8_t sr_quad_en = 0x40; + cinstr_cfg.opcode = QSPI_STD_CMD_WRSR; + cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, &sr_quad_en, NULL); } uint32_t qspi_flash_get_block_count (void) { From 3661b40d131549b7b42d00aea2bd81afb0f3977d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 18:54:23 +0700 Subject: [PATCH 10/19] clean up --- ports/nrf/flash_api/flash_api.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/nrf/flash_api/flash_api.h b/ports/nrf/flash_api/flash_api.h index 763e06d2b4e34..dc10d2b881e25 100644 --- a/ports/nrf/flash_api/flash_api.h +++ b/ports/nrf/flash_api/flash_api.h @@ -58,8 +58,8 @@ mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count); void flash_flush (void); // Non-blocking API for usb -uint8_t flash_get_state (void); -uint32_t flash_read_blocks_nonblocking (uint8_t* dst, uint32_t lba, uint32_t count); +//uint8_t flash_get_state (void); +//uint32_t flash_read_blocks_nonblocking (uint8_t* dst, uint32_t lba, uint32_t count); //uint32_t flash_write_blocks_nonblocking (const uint8_t *src, uint32_t lba, uint32_t count); From c65de950d9d2055cd0eb5a76f04b7cbdbbfa5ff4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 18:58:52 +0700 Subject: [PATCH 11/19] clean up --- ports/nrf/Makefile | 1 + ports/nrf/flash_api/flash_api.c | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 5e2c0116f7e17..7bf3cf1284dff 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -128,6 +128,7 @@ SRC_C += \ ifeq ($(QSPI_FLASH_FILESYSTEM),1) SRC_C += flash_api/qspi_flash.c SRC_NRFX += nrfx/drivers/src/nrfx_qspi.c +CFLAGS += -DQSPI_FLASH_FILESYSTEM endif DRIVERS_SRC_C += $(addprefix modules/,\ diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index 38f1fc4e6a00b..318c289521a57 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -96,48 +96,48 @@ uint32_t flash_read_blocks_nonblocking (uint8_t* dst, uint32_t lba, uint32_t cou // Flash HAL //--------------------------------------------------------------------+ -#if 0 +#ifdef QSPI_FLASH_FILESYSTEM void flash_init (void) { - internal_flash_init(); + qspi_flash_init(); } uint32_t flash_get_block_count (void) { - return internal_flash_get_block_count(); + return qspi_flash_get_block_count(); } void flash_hal_erase (uint32_t addr) { - internal_flash_hal_erase(addr); + qspi_flash_hal_erase(addr); } void flash_hal_program (uint32_t dst, const void * src, uint32_t len) { - internal_flash_hal_program(dst, src, len); + qspi_flash_hal_program(dst, src, len); } void flash_hal_read (void* dst, uint32_t src, uint32_t len) { - internal_flash_hal_read(dst, src, len); + qspi_flash_hal_read(dst, src, len); } #else void flash_init (void) { - qspi_flash_init(); + internal_flash_init(); } uint32_t flash_get_block_count (void) { - return qspi_flash_get_block_count(); + return internal_flash_get_block_count(); } void flash_hal_erase (uint32_t addr) { - qspi_flash_hal_erase(addr); + internal_flash_hal_erase(addr); } void flash_hal_program (uint32_t dst, const void * src, uint32_t len) { - qspi_flash_hal_program(dst, src, len); + internal_flash_hal_program(dst, src, len); } void flash_hal_read (void* dst, uint32_t src, uint32_t len) { - qspi_flash_hal_read(dst, src, len); + internal_flash_hal_read(dst, src, len); } #endif From c48e5077725b33db2e59ffc4a905be871f4dbd7d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 22:47:19 +0700 Subject: [PATCH 12/19] only read existing flash data that we are not writing --- ports/nrf/flash_api/flash_api.c | 34 ++++++++++++++++++++++++--------- ports/nrf/usb/usb_msc_flash.c | 1 - 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index 318c289521a57..671654916de2a 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -46,34 +46,50 @@ static inline uint32_t page_addr_of (uint32_t addr) { return addr & ~(FLASH_API_PAGE_SIZE - 1); } +static inline uint32_t page_offset_of (uint32_t addr) { + return addr & (FLASH_API_PAGE_SIZE - 1); +} + mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { flash_hal_read(dst, lba * FLASH_API_BLOCK_SIZE, count * FLASH_API_BLOCK_SIZE); return 0; } mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t num_blocks) { + uint32_t dst = lba * FLASH_API_BLOCK_SIZE; + // Program blocks up to page boundary each loop while ( num_blocks ) { - const uint32_t dst = lba * FLASH_API_BLOCK_SIZE; const uint32_t page_addr = page_addr_of(dst); + const uint32_t offset = page_offset_of(dst); + + uint32_t wr_blocks = FLASH_API_BLOCK_PER_PAGE - (lba % FLASH_API_BLOCK_PER_PAGE); // up to page boundary + wr_blocks = MIN(num_blocks, wr_blocks); - uint32_t wr_count = FLASH_API_BLOCK_PER_PAGE - (lba % FLASH_API_BLOCK_PER_PAGE); // up to page boundary - wr_count = MIN(num_blocks, wr_count); + const uint32_t wr_bytes = wr_blocks * FLASH_API_BLOCK_SIZE; // Page changes, flush old and update new cache if ( page_addr != _cache_addr ) { flash_flush(); - _cache_addr = page_addr; - flash_read_blocks(_cache_buf, page_addr / FLASH_API_BLOCK_SIZE, FLASH_API_BLOCK_PER_PAGE); + + // read existing flash to cache except those we are writing + if ( offset ) { + flash_hal_read(_cache_buf, page_addr, offset); + } + + const uint32_t last_byte = offset + wr_bytes; + if ( last_byte < FLASH_API_PAGE_SIZE ) { + flash_hal_read(_cache_buf + last_byte, page_addr + last_byte, FLASH_API_PAGE_SIZE - last_byte); + } } - memcpy(_cache_buf + (dst & (FLASH_API_PAGE_SIZE - 1)), src, wr_count * FLASH_API_BLOCK_SIZE); + memcpy(_cache_buf + offset, src, wr_bytes); // adjust for next run - lba += wr_count; - src += wr_count * FLASH_API_BLOCK_SIZE; - num_blocks -= wr_count; + dst += wr_bytes; + src += wr_bytes; + num_blocks -= wr_blocks; } return 0; diff --git a/ports/nrf/usb/usb_msc_flash.c b/ports/nrf/usb/usb_msc_flash.c index 13a78623905d3..943e684d126ba 100644 --- a/ports/nrf/usb/usb_msc_flash.c +++ b/ports/nrf/usb/usb_msc_flash.c @@ -120,7 +120,6 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* bu const uint32_t block_count = bufsize / FLASH_API_BLOCK_SIZE; - // bufsize <= CFG_TUD_MSC_BUFSIZE (4096) flash_write_blocks(buffer, lba, block_count); // update fatfs's cache if address matches From 1b498c231f96173a8e42be5e03153242f9bff887 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Sep 2018 22:59:32 +0700 Subject: [PATCH 13/19] fix previous commit issue --- ports/nrf/flash_api/flash_api.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index 671654916de2a..673d24eb7cee5 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -56,10 +56,9 @@ mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count) { } mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t num_blocks) { - uint32_t dst = lba * FLASH_API_BLOCK_SIZE; - // Program blocks up to page boundary each loop while ( num_blocks ) { + const uint32_t dst = lba * FLASH_API_BLOCK_SIZE; const uint32_t page_addr = page_addr_of(dst); const uint32_t offset = page_offset_of(dst); @@ -87,8 +86,8 @@ mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t num_blo memcpy(_cache_buf + offset, src, wr_bytes); // adjust for next run - dst += wr_bytes; src += wr_bytes; + lba += wr_blocks; num_blocks -= wr_blocks; } From 6386d3c08baca97aa71782c5521b86a55149107d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Sep 2018 01:48:59 +0700 Subject: [PATCH 14/19] add flash devices --- ports/nrf/boards/pca10056/mpconfigboard.h | 4 +- ports/nrf/flash_api/flash_devices.h | 69 +++++++++++++++++++++++ ports/nrf/flash_api/qspi_flash.c | 16 +++--- 3 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 ports/nrf/flash_api/flash_devices.h diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index 29fe7d562711c..9cf4476631581 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -53,10 +53,8 @@ #define DEFAULT_UART_BUS_TX (&pin_P1_02) // On-board QSPI Flash -#define QSPI_FLASH_SIZE (8*1024*1024) +#define QSPI_FLASH_DEVICE MX25R6435F #define QSPI_FLASH_FREQ NRF_QSPI_FREQ_32MDIV1 -#define QSPI_FLASH_READ_OPCODE NRF_QSPI_READOC_READ4IO -#define QSPI_FLASH_WRITE_OPCODE NRF_QSPI_WRITEOC_PP4IO #define QSPI_FLASH_CS NRF_GPIO_PIN_MAP(0, 17) #define QSPI_FLASH_SCK NRF_GPIO_PIN_MAP(0, 19) diff --git a/ports/nrf/flash_api/flash_devices.h b/ports/nrf/flash_api/flash_devices.h new file mode 100644 index 0000000000000..96b4703bea431 --- /dev/null +++ b/ports/nrf/flash_api/flash_devices.h @@ -0,0 +1,69 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * + * 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 FLASH_DEVICES_H_ +#define FLASH_DEVICES_H_ + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct { + uint32_t total_size; + + // Three response bytes to 0x90 JEDEC REMS ID command. + uint8_t manufacturer_id; + uint8_t device_id; + + // Status register value enable quad mode + uint16_t status_quad_enable; + +} qspi_flash_device_t; + +// Settings for the Gigadevice GD25Q16C 2MiB SPI flash. +// Datasheet: http://www.gigadevice.com/wp-content/uploads/2017/12/DS-00086-GD25Q16C-Rev2.6.pdf +#define GD25Q16C {\ + .total_size = 2*1024*1024, \ + .manufacturer_id = 0xc8, \ + .device_id = 0x14, \ + .status_quad_enable = (1 << 9)\ +} + +#define MX25R6435F {\ + .total_size = 8*1024*1024, \ + .manufacturer_id = 0xc2, \ + .device_id = 0x17, \ + .status_quad_enable = (1 << 6)\ +} + +#ifdef __cplusplus + } +#endif + +#endif /* FLASH_DEVICES_H_ */ diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 269b7b49d5267..26546b828a63e 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -31,11 +31,14 @@ #include "nrfx_qspi.h" #include "flash_api.h" #include "qspi_flash.h" +#include "flash_devices.h" #define QSPI_STD_CMD_RSTEN 0x66 #define QSPI_STD_CMD_RST 0x99 #define QSPI_STD_CMD_WRSR 0x01 +const qspi_flash_device_t _flash_device = QSPI_FLASH_DEVICE; + volatile static bool _qspi_complete = false; void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context) @@ -59,8 +62,8 @@ void qspi_flash_init (void) { .io3_pin = QSPI_FLASH_D3, }, .prot_if = { - .readoc = QSPI_FLASH_READ_OPCODE, - .writeoc = QSPI_FLASH_WRITE_OPCODE, + .readoc = NRF_QSPI_READOC_READ4IO, + .writeoc = NRF_QSPI_WRITEOC_PP4IO, .addrmode = NRF_QSPI_ADDRMODE_24BIT, .dpmconfig = false }, @@ -94,15 +97,14 @@ void qspi_flash_init (void) { cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); - // Switch to qspi mode - uint8_t sr_quad_en = 0x40; + // Switch to quad mode cinstr_cfg.opcode = QSPI_STD_CMD_WRSR; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B; - nrfx_qspi_cinstr_xfer(&cinstr_cfg, &sr_quad_en, NULL); + cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_3B; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, &_flash_device.status_quad_enable, NULL); } uint32_t qspi_flash_get_block_count (void) { - return QSPI_FLASH_SIZE / FLASH_API_BLOCK_SIZE; + return _flash_device.total_size / FLASH_API_BLOCK_SIZE; } uint8_t qspi_flash_get_state (void) { From 0be09f4481f21a057bc294b8865c818c02b876a0 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Sep 2018 02:41:54 +0700 Subject: [PATCH 15/19] clean up --- ports/nrf/flash_api/flash_api.c | 4 --- ports/nrf/flash_api/flash_api.h | 6 ----- ports/nrf/flash_api/internal_flash.c | 5 ---- ports/nrf/flash_api/qspi_flash.c | 39 +++++++++++++++++++++------- ports/nrf/flash_api/qspi_flash.h | 3 --- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index 673d24eb7cee5..bebe84b103efb 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -103,10 +103,6 @@ void flash_flush (void) { _cache_addr = NO_CACHE; } -uint32_t flash_read_blocks_nonblocking (uint8_t* dst, uint32_t lba, uint32_t count) { - return count; -} - //--------------------------------------------------------------------+ // Flash HAL //--------------------------------------------------------------------+ diff --git a/ports/nrf/flash_api/flash_api.h b/ports/nrf/flash_api/flash_api.h index dc10d2b881e25..3dd51c1bb1e83 100644 --- a/ports/nrf/flash_api/flash_api.h +++ b/ports/nrf/flash_api/flash_api.h @@ -52,16 +52,10 @@ void flash_hal_read (void* dst, uint32_t src, uint32_t len); void flash_init_vfs (struct _fs_user_mount_t *vfs); -// Blocking API for circuitpython mp_uint_t flash_read_blocks (uint8_t* dst, uint32_t lba, uint32_t count); mp_uint_t flash_write_blocks (const uint8_t *src, uint32_t lba, uint32_t count); void flash_flush (void); -// Non-blocking API for usb -//uint8_t flash_get_state (void); -//uint32_t flash_read_blocks_nonblocking (uint8_t* dst, uint32_t lba, uint32_t count); -//uint32_t flash_write_blocks_nonblocking (const uint8_t *src, uint32_t lba, uint32_t count); - #ifdef __cplusplus } diff --git a/ports/nrf/flash_api/internal_flash.c b/ports/nrf/flash_api/internal_flash.c index e07a28c6e90cb..1f3b5894194ae 100644 --- a/ports/nrf/flash_api/internal_flash.c +++ b/ports/nrf/flash_api/internal_flash.c @@ -41,11 +41,6 @@ extern uint32_t __fatfs_flash_start_addr[]; extern uint32_t __fatfs_flash_length[]; -#define NO_CACHE 0xffffffff - -uint8_t _flash_cache[FLASH_API_PAGE_SIZE] __attribute__((aligned(4))); -uint32_t _flash_page_addr = NO_CACHE; - static inline uint32_t log2phy_addr (uint32_t addr) { return ((uint32_t) __fatfs_flash_start_addr) + addr; } diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 26546b828a63e..2e35d5cec073d 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -33,13 +33,18 @@ #include "qspi_flash.h" #include "flash_devices.h" -#define QSPI_STD_CMD_RSTEN 0x66 -#define QSPI_STD_CMD_RST 0x99 -#define QSPI_STD_CMD_WRSR 0x01 +enum { + QSPI_CMD_RSTEN = 0x66, + QSPI_CMD_RST = 0x99, + QSPI_CMD_WRSR = 0x01, + QSPI_CMD_READID = 0x90 +}; + const qspi_flash_device_t _flash_device = QSPI_FLASH_DEVICE; volatile static bool _qspi_complete = false; +//static bool _regconized_device = true; void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context) { @@ -88,17 +93,35 @@ void qspi_flash_init (void) { }; // Send reset enable - cinstr_cfg.opcode = QSPI_STD_CMD_RSTEN; + cinstr_cfg.opcode = QSPI_CMD_RSTEN; cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); // Send reset command - cinstr_cfg.opcode = QSPI_STD_CMD_RST; + cinstr_cfg.opcode = QSPI_CMD_RST; cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); +#if 0 + // Send Read ID + 3 zeroes byte + uint8_t dummy[3] = { 0 }; + uint8_t id_resp[4] = { 0 }; + cinstr_cfg.opcode = QSPI_CMD_READID; + cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_4B; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, dummy, id_resp); + + // Check against configured device + if ( !(_flash_device.manufacturer_id == id_resp[2] && _flash_device.device_id == id_resp[3]) ) { + // ID not matched + _regconized_device = false; + } + else { + _regconized_device = true; + } +#endif + // Switch to quad mode - cinstr_cfg.opcode = QSPI_STD_CMD_WRSR; + cinstr_cfg.opcode = QSPI_CMD_WRSR; cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_3B; nrfx_qspi_cinstr_xfer(&cinstr_cfg, &_flash_device.status_quad_enable, NULL); } @@ -107,10 +130,6 @@ uint32_t qspi_flash_get_block_count (void) { return _flash_device.total_size / FLASH_API_BLOCK_SIZE; } -uint8_t qspi_flash_get_state (void) { - return 0; -} - void qspi_flash_hal_erase (uint32_t addr) { if ( !(NRFX_SUCCESS == nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, addr)) ) return; while ( !_qspi_complete ) { diff --git a/ports/nrf/flash_api/qspi_flash.h b/ports/nrf/flash_api/qspi_flash.h index 423ed587606d5..8f004edea8d2d 100644 --- a/ports/nrf/flash_api/qspi_flash.h +++ b/ports/nrf/flash_api/qspi_flash.h @@ -39,9 +39,6 @@ void qspi_flash_hal_program (uint32_t dst, const void * src, uint32_t len); void qspi_flash_hal_read (void* dst, uint32_t src, uint32_t len); -uint8_t qspi_flash_get_state (void); - - #ifdef __cplusplus } #endif From 3297ca5daf225c4b6ba72977b1ed027e35247c51 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Sep 2018 17:01:48 +0700 Subject: [PATCH 16/19] add JEDEC manufacturer & device ID detection, fall back to internal if flash device is not one of supported. change nrf qspi to blocking model --- ports/nrf/flash_api/flash_api.c | 75 ++++++++++++++++---------- ports/nrf/flash_api/qspi_flash.c | 91 +++++++++++++++++--------------- ports/nrf/flash_api/qspi_flash.h | 1 + 3 files changed, 96 insertions(+), 71 deletions(-) diff --git a/ports/nrf/flash_api/flash_api.c b/ports/nrf/flash_api/flash_api.c index bebe84b103efb..619264fa1f54c 100644 --- a/ports/nrf/flash_api/flash_api.c +++ b/ports/nrf/flash_api/flash_api.c @@ -107,51 +107,70 @@ void flash_flush (void) { // Flash HAL //--------------------------------------------------------------------+ -#ifdef QSPI_FLASH_FILESYSTEM void flash_init (void) { +#ifdef QSPI_FLASH_FILESYSTEM qspi_flash_init(); -} - -uint32_t flash_get_block_count (void) { - return qspi_flash_get_block_count(); -} -void flash_hal_erase (uint32_t addr) { - qspi_flash_hal_erase(addr); -} - -void flash_hal_program (uint32_t dst, const void * src, uint32_t len) { - qspi_flash_hal_program(dst, src, len); -} - -void flash_hal_read (void* dst, uint32_t src, uint32_t len) { - qspi_flash_hal_read(dst, src, len); -} - -#else - -void flash_init (void) { - internal_flash_init(); + // Flash device is not detected, fall back to internal flash + if (!qspi_flash_detected() ) +#endif + { + internal_flash_init(); + } } uint32_t flash_get_block_count (void) { - return internal_flash_get_block_count(); +#ifdef QSPI_FLASH_FILESYSTEM + // Flash device is not detected, fall back to internal flash + if ( qspi_flash_detected() ) { + return qspi_flash_get_block_count(); + } + else +#endif + { + return internal_flash_get_block_count(); + } } void flash_hal_erase (uint32_t addr) { - internal_flash_hal_erase(addr); +#ifdef QSPI_FLASH_FILESYSTEM + // Flash device is not detected, fall back to internal flash + if ( qspi_flash_detected() ) { + return qspi_flash_hal_erase(addr); + } + else +#endif + { + internal_flash_hal_erase(addr); + } } void flash_hal_program (uint32_t dst, const void * src, uint32_t len) { - internal_flash_hal_program(dst, src, len); +#ifdef QSPI_FLASH_FILESYSTEM + // Flash device is not detected, fall back to internal flash + if ( qspi_flash_detected() ) { + qspi_flash_hal_program(dst, src, len); + } + else +#endif + { + internal_flash_hal_program(dst, src, len); + } } void flash_hal_read (void* dst, uint32_t src, uint32_t len) { - internal_flash_hal_read(dst, src, len); -} - +#ifdef QSPI_FLASH_FILESYSTEM + // Flash device is not detected, fall back to internal flash + if ( qspi_flash_detected() ) { + qspi_flash_hal_read(dst, src, len); + } + else #endif + { + internal_flash_hal_read(dst, src, len); + } +} /******************************************************************************/ // MicroPython bindings diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 2e35d5cec073d..4659a76cea530 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -40,19 +40,18 @@ enum { QSPI_CMD_READID = 0x90 }; +// If Flash device is not specified, support all devices in flash_devices.h +#ifdef QSPI_FLASH_DEVICE +const qspi_flash_device_t _flash_devices_arr[] = { QSPI_FLASH_DEVICE }; +#else +const qspi_flash_device_t _flash_devices_arr[] = {GD25Q16C, MX25R6435F}; +#endif -const qspi_flash_device_t _flash_device = QSPI_FLASH_DEVICE; - -volatile static bool _qspi_complete = false; -//static bool _regconized_device = true; - -void qspi_flash_isr (nrfx_qspi_evt_t event, void * p_context) -{ - (void) p_context; - (void) event; +enum { + FLASH_DEVICE_COUNT = ARRAY_SIZE(_flash_devices_arr) +}; - _qspi_complete = true; -} +const qspi_flash_device_t* _flash_dev = NULL; void qspi_flash_init (void) { // Init QSPI flash @@ -74,79 +73,85 @@ void qspi_flash_init (void) { }, .phy_if = { .sck_freq = QSPI_FLASH_FREQ, - .sck_delay = 1, + .sck_delay = 1, // min time CS must stay high before going low again. in unit of 62.5 ns .spi_mode = NRF_QSPI_MODE_0, .dpmen = false }, .irq_priority = 7, }; - nrfx_qspi_init(&qspi_cfg, qspi_flash_isr, NULL); + // No callback for blocking API + nrfx_qspi_init(&qspi_cfg, NULL, NULL); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = 0, .length = 0, .io2_level = true, .io3_level = true, - .wipwait = true, - .wren = true + .wipwait = false, + .wren = false }; // Send reset enable cinstr_cfg.opcode = QSPI_CMD_RSTEN; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; + cinstr_cfg.length = 1; nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); // Send reset command cinstr_cfg.opcode = QSPI_CMD_RST; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B; + cinstr_cfg.length = 1; nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); -#if 0 - // Send Read ID + 3 zeroes byte - uint8_t dummy[3] = { 0 }; - uint8_t id_resp[4] = { 0 }; + NRFX_DELAY_US(100); // wait for flash device to reset + + // Send (Read ID + 3 dummy bytes) + Receive 2 bytes of (Manufacture + Device ID) + uint8_t dummy[6] = {0}; + uint8_t id_resp[6] = { 0 }; cinstr_cfg.opcode = QSPI_CMD_READID; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_4B; + cinstr_cfg.length = 6; + + // Bug with -nrf_qspi_cinstrdata_get() didn't combine data. + // https://devzone.nordicsemi.com/f/nordic-q-a/38540/bug-nrf_qspi_cinstrdata_get-didn-t-collect-data-from-both-cinstrdat1-and-cinstrdat0 nrfx_qspi_cinstr_xfer(&cinstr_cfg, dummy, id_resp); - // Check against configured device - if ( !(_flash_device.manufacturer_id == id_resp[2] && _flash_device.device_id == id_resp[3]) ) { - // ID not matched - _regconized_device = false; + // Due to the bug, we collect data manually + uint8_t dev_id = (uint8_t) NRF_QSPI->CINSTRDAT1; + uint8_t mfgr_id = (uint8_t) ( NRF_QSPI->CINSTRDAT0 >> 24); + + // Look up the flash device in supported array + for ( int i = 0; i < FLASH_DEVICE_COUNT; i++ ) { + // Match ID + if ( _flash_devices_arr[i].manufacturer_id == mfgr_id && _flash_devices_arr[i].device_id == dev_id ) { + _flash_dev = &_flash_devices_arr[i]; + break; + } } - else { - _regconized_device = true; + + if ( _flash_dev ) { + // Switch to quad mode + cinstr_cfg.opcode = QSPI_CMD_WRSR; + cinstr_cfg.length = 3; + cinstr_cfg.wipwait = cinstr_cfg.wren = true; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, &_flash_dev->status_quad_enable, NULL); } -#endif +} - // Switch to quad mode - cinstr_cfg.opcode = QSPI_CMD_WRSR; - cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_3B; - nrfx_qspi_cinstr_xfer(&cinstr_cfg, &_flash_device.status_quad_enable, NULL); +bool qspi_flash_detected (void) { + return _flash_dev != NULL; } uint32_t qspi_flash_get_block_count (void) { - return _flash_device.total_size / FLASH_API_BLOCK_SIZE; + return _flash_dev ? (_flash_dev->total_size / FLASH_API_BLOCK_SIZE) : 0; } void qspi_flash_hal_erase (uint32_t addr) { if ( !(NRFX_SUCCESS == nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, addr)) ) return; - while ( !_qspi_complete ) { - } - _qspi_complete = false; } void qspi_flash_hal_program (uint32_t dst, const void* src, uint32_t len) { if ( !(NRFX_SUCCESS == nrfx_qspi_write(src, len, dst)) ) return; - while ( !_qspi_complete ) { - } - _qspi_complete = false; } void qspi_flash_hal_read (void* dst, uint32_t src, uint32_t len) { nrfx_qspi_read(dst, len, src); - while ( !_qspi_complete ) { - } - _qspi_complete = false; } diff --git a/ports/nrf/flash_api/qspi_flash.h b/ports/nrf/flash_api/qspi_flash.h index 8f004edea8d2d..8df0bf90988af 100644 --- a/ports/nrf/flash_api/qspi_flash.h +++ b/ports/nrf/flash_api/qspi_flash.h @@ -32,6 +32,7 @@ #endif void qspi_flash_init (void); +bool qspi_flash_detected (void); uint32_t qspi_flash_get_block_count (void); void qspi_flash_hal_erase (uint32_t addr); From c0c89e300aa3ddf2805de85be4b9d0ff251f479c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Sep 2018 17:20:04 +0700 Subject: [PATCH 17/19] update qspi mpconfigboard.h for feather nrf52840 Rename config pin name from QSPI_FLASH_ --> MICROPY_QSPI_ --- .../feather_nrf52840_express/mpconfigboard.h | 50 +++++++++---------- ports/nrf/boards/pca10056/mpconfigboard.h | 15 +++--- ports/nrf/flash_api/qspi_flash.c | 18 +++---- 3 files changed, 40 insertions(+), 43 deletions(-) diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h index 81818741d1a52..2e0fbb417359c 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h @@ -27,45 +27,43 @@ #define FEATHER52840 -#define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express" -#define MICROPY_HW_MCU_NAME "nRF52840" -#define MICROPY_PY_SYS_PLATFORM "Feather52840Express" +#define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express" +#define MICROPY_HW_MCU_NAME "nRF52840" +#define MICROPY_PY_SYS_PLATFORM "Feather52840Express" -#define MICROPY_HW_NEOPIXEL (&pin_P0_13) +#define MICROPY_HW_NEOPIXEL (&pin_P0_13) -#define MICROPY_QSPI_DATA0 (&pin_P1_09) -#define MICROPY_QSPI_DATA1 (&pin_P0_11) -#define MICROPY_QSPI_DATA2 (&pin_P0_12) -#define MICROPY_QSPI_DATA3 (&pin_P0_14) -#define MICROPY_QSPI_SCK (&pin_P0_08) -#define MICROPY_QSPI_CS (&pin_P1_08) +#define MICROPY_HW_LED_MSC NRF_GPIO_PIN_MAP(0, 13) +#define MICROPY_HW_LED_MSC_ACTIVE_LEVEL 1 + +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 9) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 11) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 12) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 14) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 8) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(1, 8) #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code -#define PORT_HEAP_SIZE (128 * 1024) +#define PORT_HEAP_SIZE (128 * 1024) // TODO #define CIRCUITPY_INTERNAL_NVM_SIZE 8192 -#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) - -// TODO #include "external_flash/devices.h" +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q16C +#define EXTERNAL_FLASH_DEVICES GD25Q16C #define EXTERNAL_FLASH_QSPI_DUAL -// TODO include "external_flash/external_flash.h" - -#define BOARD_HAS_CRYSTAL 1 +#define BOARD_HAS_CRYSTAL 1 -#define DEFAULT_I2C_BUS_SCL (&pin_P1_11) -#define DEFAULT_I2C_BUS_SDA (&pin_P1_12) +#define DEFAULT_I2C_BUS_SCL (&pin_P1_11) +#define DEFAULT_I2C_BUS_SDA (&pin_P1_12) -#define DEFAULT_SPI_BUS_SCK (&pin_P0_20) -#define DEFAULT_SPI_BUS_MOSI (&pin_P0_23) -#define DEFAULT_SPI_BUS_MISO (&pin_P0_22) +#define DEFAULT_SPI_BUS_SCK (&pin_P0_20) +#define DEFAULT_SPI_BUS_MOSI (&pin_P0_23) +#define DEFAULT_SPI_BUS_MISO (&pin_P0_22) -#define DEFAULT_UART_BUS_RX (&pin_P1_0) -#define DEFAULT_UART_BUS_TX (&pin_P0_24) +#define DEFAULT_UART_BUS_RX (&pin_P1_0) +#define DEFAULT_UART_BUS_TX (&pin_P0_24) diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index 9cf4476631581..38b9cfbc35f81 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -53,14 +53,13 @@ #define DEFAULT_UART_BUS_TX (&pin_P1_02) // On-board QSPI Flash -#define QSPI_FLASH_DEVICE MX25R6435F -#define QSPI_FLASH_FREQ NRF_QSPI_FREQ_32MDIV1 +#define EXTERNAL_FLASH_DEVICES MX25R6435F -#define QSPI_FLASH_CS NRF_GPIO_PIN_MAP(0, 17) -#define QSPI_FLASH_SCK NRF_GPIO_PIN_MAP(0, 19) -#define QSPI_FLASH_D0 NRF_GPIO_PIN_MAP(0, 20) -#define QSPI_FLASH_D1 NRF_GPIO_PIN_MAP(0, 21) -#define QSPI_FLASH_D2 NRF_GPIO_PIN_MAP(0, 22) -#define QSPI_FLASH_D3 NRF_GPIO_PIN_MAP(0, 23) +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 21) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 22) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 23) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 17) diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 4659a76cea530..8e82370e5d6ca 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -41,8 +41,8 @@ enum { }; // If Flash device is not specified, support all devices in flash_devices.h -#ifdef QSPI_FLASH_DEVICE -const qspi_flash_device_t _flash_devices_arr[] = { QSPI_FLASH_DEVICE }; +#ifdef EXTERNAL_FLASH_DEVICES +const qspi_flash_device_t _flash_devices_arr[] = { EXTERNAL_FLASH_DEVICES }; #else const qspi_flash_device_t _flash_devices_arr[] = {GD25Q16C, MX25R6435F}; #endif @@ -58,12 +58,12 @@ void qspi_flash_init (void) { nrfx_qspi_config_t qspi_cfg = { .xip_offset = 0, .pins = { - .sck_pin = QSPI_FLASH_SCK, - .csn_pin = QSPI_FLASH_CS, - .io0_pin = QSPI_FLASH_D0, - .io1_pin = QSPI_FLASH_D1, - .io2_pin = QSPI_FLASH_D2, - .io3_pin = QSPI_FLASH_D3, + .sck_pin = MICROPY_QSPI_SCK, + .csn_pin = MICROPY_QSPI_CS, + .io0_pin = MICROPY_QSPI_DATA0, + .io1_pin = MICROPY_QSPI_DATA1, + .io2_pin = MICROPY_QSPI_DATA2, + .io3_pin = MICROPY_QSPI_DATA3, }, .prot_if = { .readoc = NRF_QSPI_READOC_READ4IO, @@ -72,7 +72,7 @@ void qspi_flash_init (void) { .dpmconfig = false }, .phy_if = { - .sck_freq = QSPI_FLASH_FREQ, + .sck_freq = NRF_QSPI_FREQ_32MDIV1, .sck_delay = 1, // min time CS must stay high before going low again. in unit of 62.5 ns .spi_mode = NRF_QSPI_MODE_0, .dpmen = false From 6a3e70a8ff529bc31c984d993eb133257d820add Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 15 Sep 2018 23:37:57 +0700 Subject: [PATCH 18/19] determine QSPI operation mode (quad, dual, single) based on the config of DATAn pin --- .../feather_nrf52840_express/mpconfigboard.h | 8 +++- ports/nrf/boards/pca10056/mpconfigboard.h | 5 +++ ports/nrf/flash_api/qspi_flash.c | 38 ++++++++++++++++--- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h index 2e0fbb417359c..409e6d199ecea 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h @@ -36,6 +36,10 @@ #define MICROPY_HW_LED_MSC NRF_GPIO_PIN_MAP(0, 13) #define MICROPY_HW_LED_MSC_ACTIVE_LEVEL 1 +// Flash operation mode is determined by the value of MICROPY_QSPI_DATAn +// Quad mode: If all DATA0 --> DATA3 are defined and valid (not 0xff) +// Dual mode: If DATA0 and DATA1 are valid while either DATA2 or DATA3 are not +// Single mode: If only DATA0 is defined and valid ( not 0xff) #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 9) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 11) #define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 12) @@ -52,10 +56,10 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) +// On-board QSPI Flash +// If EXTERNAL_FLASH_DEVICES is not defined, all supported devices will be used #define EXTERNAL_FLASH_DEVICES GD25Q16C -#define EXTERNAL_FLASH_QSPI_DUAL - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_P1_11) diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index 38b9cfbc35f81..e5668b095e163 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -53,8 +53,13 @@ #define DEFAULT_UART_BUS_TX (&pin_P1_02) // On-board QSPI Flash +// If EXTERNAL_FLASH_DEVICES is not defined, all supported devices will be used #define EXTERNAL_FLASH_DEVICES MX25R6435F +// Flash operation mode is determined by the value of MICROPY_QSPI_DATAn +// Quad mode: If all DATA0 --> DATA3 are defined and valid (not 0xff) +// Dual mode: If DATA0 and DATA1 are valid while either DATA2 or DATA3 are not +// Single mode: If only DATA0 is defined and valid ( not 0xff) #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 21) #define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 22) diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 8e82370e5d6ca..681a6f3571189 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -33,6 +33,17 @@ #include "qspi_flash.h" #include "flash_devices.h" +#define _VALID_PIN(n) (defined(MICROPY_QSPI_DATA##n) && (MICROPY_QSPI_DATA##n != 0xff)) + +#define QSPI_FLASH_MODE \ + (( _VALID_PIN(0) && _VALID_PIN(1) && _VALID_PIN(2) && _VALID_PIN(3) ) ? 4 : \ + ( _VALID_PIN(0) && _VALID_PIN(1) ) ? 2 : \ + ( _VALID_PIN(0) ) ? 1 : 0) + +#if !QSPI_FLASH_MODE +#error MICROPY_QSPI_DATAn must be defined +#endif + enum { QSPI_CMD_RSTEN = 0x66, QSPI_CMD_RST = 0x99, @@ -61,13 +72,14 @@ void qspi_flash_init (void) { .sck_pin = MICROPY_QSPI_SCK, .csn_pin = MICROPY_QSPI_CS, .io0_pin = MICROPY_QSPI_DATA0, - .io1_pin = MICROPY_QSPI_DATA1, - .io2_pin = MICROPY_QSPI_DATA2, - .io3_pin = MICROPY_QSPI_DATA3, + .io1_pin = NRF_QSPI_PIN_NOT_CONNECTED, + .io2_pin = NRF_QSPI_PIN_NOT_CONNECTED, + .io3_pin = NRF_QSPI_PIN_NOT_CONNECTED, + }, .prot_if = { - .readoc = NRF_QSPI_READOC_READ4IO, - .writeoc = NRF_QSPI_WRITEOC_PP4IO, + .readoc = NRF_QSPI_READOC_FASTREAD, + .writeoc = NRF_QSPI_WRITEOC_PP, .addrmode = NRF_QSPI_ADDRMODE_24BIT, .dpmconfig = false }, @@ -80,6 +92,18 @@ void qspi_flash_init (void) { .irq_priority = 7, }; +#if QSPI_FLASH_MODE > 1 + qspi_cfg.pins.io1_pin = MICROPY_QSPI_DATA1; + qspi_cfg.prot_if.readoc = NRF_QSPI_READOC_READ2IO; + qspi_cfg.prot_if.writeoc = NRF_QSPI_WRITEOC_PP2O; +#if QSPI_FLASH_MODE > 2 + qspi_cfg.pins.io2_pin = MICROPY_QSPI_DATA2; + qspi_cfg.pins.io3_pin = MICROPY_QSPI_DATA3; + qspi_cfg.prot_if.readoc = NRF_QSPI_READOC_READ4IO; + qspi_cfg.prot_if.writeoc = NRF_QSPI_WRITEOC_PP4IO; +#endif +#endif + // No callback for blocking API nrfx_qspi_init(&qspi_cfg, NULL, NULL); @@ -128,11 +152,13 @@ void qspi_flash_init (void) { } if ( _flash_dev ) { - // Switch to quad mode + // Enable quad mode if needed +#if QSPI_FLASH_MODE == 4 cinstr_cfg.opcode = QSPI_CMD_WRSR; cinstr_cfg.length = 3; cinstr_cfg.wipwait = cinstr_cfg.wren = true; nrfx_qspi_cinstr_xfer(&cinstr_cfg, &_flash_dev->status_quad_enable, NULL); +#endif } } From 67161a5ce0daa3e2a8e846ddc16272c4e79049ca Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 Sep 2018 12:42:50 +0700 Subject: [PATCH 19/19] add ALL_EXTERNAL_FLASH_DEVICES define --- .../boards/feather_nrf52840_express/mpconfigboard.h | 10 +++++----- ports/nrf/boards/pca10056/mpconfigboard.h | 10 +++++----- ports/nrf/flash_api/flash_devices.h | 4 ++++ ports/nrf/flash_api/qspi_flash.c | 12 +++++++----- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h index 409e6d199ecea..b689246bfb2eb 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h @@ -36,10 +36,11 @@ #define MICROPY_HW_LED_MSC NRF_GPIO_PIN_MAP(0, 13) #define MICROPY_HW_LED_MSC_ACTIVE_LEVEL 1 -// Flash operation mode is determined by the value of MICROPY_QSPI_DATAn -// Quad mode: If all DATA0 --> DATA3 are defined and valid (not 0xff) -// Dual mode: If DATA0 and DATA1 are valid while either DATA2 or DATA3 are not -// Single mode: If only DATA0 is defined and valid ( not 0xff) +// Flash operation mode is determined by MICROPY_QSPI_DATAn pin configuration. +// A pin config is valid if it is defined and its value is not 0xFF. +// Quad mode: If all DATA0 --> DATA3 are valid +// Dual mode: If DATA0 and DATA1 are valid while either DATA2 and/or DATA3 are invalid +// Single mode: If only DATA0 is valid #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 9) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 11) #define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 12) @@ -57,7 +58,6 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) // On-board QSPI Flash -// If EXTERNAL_FLASH_DEVICES is not defined, all supported devices will be used #define EXTERNAL_FLASH_DEVICES GD25Q16C #define BOARD_HAS_CRYSTAL 1 diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index e5668b095e163..9f266626eb866 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -53,13 +53,13 @@ #define DEFAULT_UART_BUS_TX (&pin_P1_02) // On-board QSPI Flash -// If EXTERNAL_FLASH_DEVICES is not defined, all supported devices will be used #define EXTERNAL_FLASH_DEVICES MX25R6435F -// Flash operation mode is determined by the value of MICROPY_QSPI_DATAn -// Quad mode: If all DATA0 --> DATA3 are defined and valid (not 0xff) -// Dual mode: If DATA0 and DATA1 are valid while either DATA2 or DATA3 are not -// Single mode: If only DATA0 is defined and valid ( not 0xff) +// Flash operation mode is determined by MICROPY_QSPI_DATAn pin configuration. +// A pin config is valid if it is defined and its value is not 0xFF. +// Quad mode: If all DATA0 --> DATA3 are valid +// Dual mode: If DATA0 and DATA1 are valid while either DATA2 and/or DATA3 are invalid +// Single mode: If only DATA0 is valid #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 21) #define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 22) diff --git a/ports/nrf/flash_api/flash_devices.h b/ports/nrf/flash_api/flash_devices.h index 96b4703bea431..1f8edae5ab762 100644 --- a/ports/nrf/flash_api/flash_devices.h +++ b/ports/nrf/flash_api/flash_devices.h @@ -46,6 +46,10 @@ typedef struct { } qspi_flash_device_t; +// All supported devices +#define ALL_EXTERNAL_FLASH_DEVICES GD25Q16C, MX25R6435F + + // Settings for the Gigadevice GD25Q16C 2MiB SPI flash. // Datasheet: http://www.gigadevice.com/wp-content/uploads/2017/12/DS-00086-GD25Q16C-Rev2.6.pdf #define GD25Q16C {\ diff --git a/ports/nrf/flash_api/qspi_flash.c b/ports/nrf/flash_api/qspi_flash.c index 681a6f3571189..12677a9f14198 100644 --- a/ports/nrf/flash_api/qspi_flash.c +++ b/ports/nrf/flash_api/qspi_flash.c @@ -51,12 +51,7 @@ enum { QSPI_CMD_READID = 0x90 }; -// If Flash device is not specified, support all devices in flash_devices.h -#ifdef EXTERNAL_FLASH_DEVICES const qspi_flash_device_t _flash_devices_arr[] = { EXTERNAL_FLASH_DEVICES }; -#else -const qspi_flash_device_t _flash_devices_arr[] = {GD25Q16C, MX25R6435F}; -#endif enum { FLASH_DEVICE_COUNT = ARRAY_SIZE(_flash_devices_arr) @@ -159,6 +154,13 @@ void qspi_flash_init (void) { cinstr_cfg.wipwait = cinstr_cfg.wren = true; nrfx_qspi_cinstr_xfer(&cinstr_cfg, &_flash_dev->status_quad_enable, NULL); #endif + + // Enable high performance mode + uint8_t sts_cfg[] = { 0x40, 0x00, 0x01 }; + cinstr_cfg.opcode = QSPI_CMD_WRSR; + cinstr_cfg.length = 4; + cinstr_cfg.wipwait = cinstr_cfg.wren = true; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, sts_cfg, NULL); } }