implement msc with internal_flash api
Note: only work with SD is disabled.
This commit is contained in:
parent
3564e98181
commit
0365912e28
|
@ -1 +1 @@
|
|||
Subproject commit fc139b009f4c49d4fdbf1b80097c94c8dabb1ee1
|
||||
Subproject commit 40de723d417e253e3346b58cd2ce8b5dbf60d0ac
|
5
main.c
5
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue