From 0365912e28ed4da8b8bca65ea68be1324ab441cb Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 5 Jul 2018 16:19:04 +0700 Subject: [PATCH] implement msc with internal_flash api Note: only work with SD is disabled. --- lib/tinyusb | 2 +- main.c | 5 -- ports/nrf/internal_flash.c | 156 +++++++++++++++------------------- ports/nrf/internal_flash.h | 2 - ports/nrf/usb/usb_msc_flash.c | 71 +++------------- 5 files changed, 83 insertions(+), 153 deletions(-) diff --git a/lib/tinyusb b/lib/tinyusb index fc139b009f..40de723d41 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit fc139b009f4c49d4fdbf1b80097c94c8dabb1ee1 +Subproject commit 40de723d417e253e3346b58cd2ce8b5dbf60d0ac diff --git a/main.c b/main.c index 868a7b7528..cbc0b093c3 100644 --- a/main.c +++ b/main.c @@ -230,11 +230,6 @@ bool start_mp(safe_mode_t safe_mode) { serial_connected_before_animation = serial_connected(); tick_rgb_status_animation(&animation); - - #ifdef NRF52840_XXAA - extern void tusb_task(void); - tusb_task(); - #endif } } diff --git a/ports/nrf/internal_flash.c b/ports/nrf/internal_flash.c index 2f069a2f95..56377c9734 100644 --- a/ports/nrf/internal_flash.c +++ b/ports/nrf/internal_flash.c @@ -36,16 +36,34 @@ #include "lib/oofatfs/ff.h" #include "supervisor/shared/rgb_led_status.h" -#include "nrf.h" +#include "nrf_nvmc.h" #ifdef BLUETOOTH_SD #include "nrf_sdm.h" #endif +/*------------------------------------------------------------------*/ +/* VARIABLES + *------------------------------------------------------------------*/ + // defined in linker extern uint32_t __fatfs_flash_start_addr[]; extern uint32_t __fatfs_flash_length[]; +#define NO_CACHE 0xffffffff +#define FL_PAGE_SZ 4096 + +uint8_t _fl_cache[FL_PAGE_SZ] __attribute__((aligned(4))); +uint32_t _fl_pg_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; +} + void internal_flash_init(void) { // Activity LED for flash writes. #ifdef MICROPY_HW_LED_MSC @@ -67,101 +85,63 @@ uint32_t internal_flash_get_block_count(void) { return ((uint32_t) __fatfs_flash_length) / FILESYSTEM_BLOCK_SIZE ; } +// TODO support flashing with SD enabled void internal_flash_flush(void) { -} + if (_fl_pg_addr == NO_CACHE) return; -void flash_flush(void) { - internal_flash_flush(); -} - -static uint32_t convert_block_to_flash_addr(uint32_t block) { - return ((uint32_t)__fatfs_flash_start_addr) + block * FILESYSTEM_BLOCK_SIZE; -} - -bool internal_flash_write_block(const uint8_t *src, uint32_t block) { - uint8_t sd_en = 0; - -#ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, true); -#endif - temp_status_color(ACTIVE_WRITE); - // non-MBR block, copy to cache - - uint32_t dest = convert_block_to_flash_addr(block); - - uint32_t pagenum = dest / FLASH_PAGE_SIZE; - uint32_t* flash_align = (uint32_t*) (pagenum*FLASH_PAGE_SIZE); - - // Read back current page to update only 512 portion - __ALIGN(4) uint8_t buf[FLASH_PAGE_SIZE]; - memcpy(buf, flash_align, FLASH_PAGE_SIZE); - memcpy(buf + (dest%FLASH_PAGE_SIZE), src, FILESYSTEM_BLOCK_SIZE); - -#ifdef BLUETOOTH_SD - (void) sd_softdevice_is_enabled(&sd_en); - - if (sd_en) { - if (NRF_SUCCESS != sd_flash_page_erase(pagenum)) { - return false; + // Skip if data is the same + if (memcmp(_fl_cache, (void *)_fl_pg_addr, FL_PAGE_SZ) != 0) { +// _is_flashing = true; + nrf_nvmc_page_erase(_fl_pg_addr); + nrf_nvmc_write_words(_fl_pg_addr, (uint32_t *)_fl_cache, FL_PAGE_SZ / sizeof(uint32_t)); } - if (NRF_SUCCESS != sd_flash_write(flash_align, (uint32_t*) buf, FLASH_PAGE_SIZE / sizeof(uint32_t))) { - return false; - } - } -#endif - - if (!sd_en) { - // Erase - NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos); - while (NRF_NVMC->READY == NVMC_READY_READY_Busy); - - NRF_NVMC->ERASEPAGE = dest; - while (NRF_NVMC->READY == NVMC_READY_READY_Busy); - - NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); - while (NRF_NVMC->READY == NVMC_READY_READY_Busy); - - // Write - uint32_t *p_src = (uint32_t*) buf; - uint32_t *p_dest = flash_align; - uint32_t i = 0; - - while (i < (FLASH_PAGE_SIZE / sizeof(uint32_t))) { - NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); - while (NRF_NVMC->READY == NVMC_READY_READY_Busy); - - *p_dest++ = *p_src++; - - while (NRF_NVMC->READY == NVMC_READY_READY_Busy); - - NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); - while (NRF_NVMC->READY == NVMC_READY_READY_Busy); - - ++i; - } - } - - clear_temp_status(); -#ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); -#endif - return true; + _fl_pg_addr = NO_CACHE; } mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { - uint32_t src = convert_block_to_flash_addr(block); - memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks); - return 0; // success + uint32_t src = lba2addr(block); + memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks); + return 0; // success } -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { - for (size_t i = 0; i < num_blocks; i++) { - if (!internal_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { - return 1; // error +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); + + uint32_t count = 8 - (lba%8); // up to page boundary + count = MIN(num_blocks, count); + + if (page_addr != _fl_pg_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; + + _fl_pg_addr = page_addr; + memcpy(_fl_cache, (void *)page_addr, FL_PAGE_SZ); + } + + memcpy(_fl_cache + (addr & (FL_PAGE_SZ - 1)), src, count*FILESYSTEM_BLOCK_SIZE); + + // adjust for next run + lba += count; + src += count*FILESYSTEM_BLOCK_SIZE; + num_blocks -= count; } - } - return 0; // success + + #ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, false); + #endif + + return 0; // success } /******************************************************************************/ @@ -241,3 +221,7 @@ 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 79b786555f..e83b39d573 100644 --- a/ports/nrf/internal_flash.h +++ b/ports/nrf/internal_flash.h @@ -44,8 +44,6 @@ 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); -bool internal_flash_read_block(uint8_t *dest, uint32_t block); -bool internal_flash_write_block(const uint8_t *src, uint32_t block); // 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); diff --git a/ports/nrf/usb/usb_msc_flash.c b/ports/nrf/usb/usb_msc_flash.c index 22cc689885..dc88d031c7 100644 --- a/ports/nrf/usb/usb_msc_flash.c +++ b/ports/nrf/usb/usb_msc_flash.c @@ -37,7 +37,7 @@ #ifdef NRF52840_XXAA #include "tusb.h" -#include "nrf_nvmc.h" +#include "internal_flash.h" /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM @@ -71,11 +71,6 @@ static scsi_mode_parameters_t const msc_dev_mode_para = /* *------------------------------------------------------------------*/ -static inline uint32_t lba2addr(uint32_t lba) -{ - return MSC_FLASH_ADDR_START + lba*MSC_FLASH_BLOCK_SIZE; -} - //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ @@ -141,72 +136,30 @@ int32_t tud_msc_scsi_cb (uint8_t rhport, uint8_t lun, uint8_t const scsi_cmd[16] return len; } -/*------------------------------------------------------------------*/ -/* Internal Flash - *------------------------------------------------------------------*/ -#define NO_CACHE 0xffffffff - -uint8_t _fl_cache[FL_PAGE_SZ] ATTR_ALIGNED(4); -uint32_t _fl_addr = NO_CACHE; - - -static void fl_flush() { - if (_fl_addr == NO_CACHE) return; - - // Skip if data is the same - if (memcmp(_fl_cache, (void *)_fl_addr, FL_PAGE_SZ) != 0) { -// _is_flashing = true; - nrf_nvmc_page_erase(_fl_addr); - nrf_nvmc_write_words(_fl_addr, (uint32_t *)_fl_cache, FL_PAGE_SZ / sizeof(uint32_t)); - } - - _fl_addr = NO_CACHE; -} - -static bool fl_write(uint32_t addr, uint8_t* buf, uint16_t bufsize) -{ - uint32_t new_addr = addr & ~(FL_PAGE_SZ - 1); - - if (new_addr != _fl_addr) { - fl_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; - - _fl_addr = new_addr; - memcpy(_fl_cache, (void *)new_addr, FL_PAGE_SZ); - } - - memcpy(_fl_cache + (addr & (FL_PAGE_SZ - 1)), buf, bufsize); - - return true; -} - - /*------------------------------------------------------------------*/ /* Tinyusb Flash READ10 & WRITE10 *------------------------------------------------------------------*/ int32_t tud_msc_read10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { - (void) rhport; - (void) lun; + (void) rhport; (void) lun; (void) offset; - uint32_t addr = lba2addr(lba) + offset; - memcpy(buffer, (uint8_t*) addr, bufsize); + uint32_t const block_count = bufsize/MSC_FLASH_BLOCK_SIZE; - return bufsize; + internal_flash_read_blocks(buffer, lba, block_count); + + return block_count*MSC_FLASH_BLOCK_SIZE; } int32_t tud_msc_write10_cb (uint8_t rhport, uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { - (void) rhport; (void) lun; - uint32_t addr = lba2addr(lba) + offset; + (void) rhport; (void) lun; (void) offset; + + uint32_t const block_count = bufsize/MSC_FLASH_BLOCK_SIZE; // bufsize <= CFG_TUD_MSC_BUFSIZE (4096) - fl_write(addr, buffer, bufsize); + internal_flash_write_blocks(buffer, lba, block_count); - return bufsize; + return block_count*MSC_FLASH_BLOCK_SIZE; } void tud_msc_write10_complete_cb(uint8_t rhport, uint8_t lun) @@ -214,7 +167,7 @@ void tud_msc_write10_complete_cb(uint8_t rhport, uint8_t lun) (void) rhport; (void) lun; // flush pending cache when write10 is complete - fl_flush(); + internal_flash_flush(); } #endif