atmel-samd: Fix running off of the new VFS filesystem including
an issue at startup leading to safe mode and mass storage support not working.
This commit is contained in:
parent
8251d8cb2a
commit
e87a61ffb4
|
@ -42,6 +42,17 @@
|
|||
|
||||
#define VFS_INDEX 0
|
||||
|
||||
static fs_user_mount_t* get_vfs(int index) {
|
||||
mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table);
|
||||
for (uint8_t i = 0; current_mount != NULL; i++) {
|
||||
if (i == VFS_INDEX) {
|
||||
return (fs_user_mount_t *) current_mount->obj;
|
||||
}
|
||||
current_mount = current_mount->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//! This function tests memory state, and starts memory initialization
|
||||
//! @return Ctrl_status
|
||||
//! It is ready -> CTRL_GOOD
|
||||
|
@ -50,12 +61,9 @@
|
|||
//! An error occurred -> CTRL_FAIL
|
||||
Ctrl_status vfs_test_unit_ready(void)
|
||||
{
|
||||
mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table);
|
||||
for (uint8_t i = 0; current_mount != NULL; i++) {
|
||||
if (i == VFS_INDEX) {
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
current_mount = current_mount->next;
|
||||
fs_user_mount_t* current_mount = get_vfs(VFS_INDEX);
|
||||
if (current_mount != NULL) {
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
return CTRL_NO_PRESENT;
|
||||
}
|
||||
|
@ -69,7 +77,9 @@ Ctrl_status vfs_test_unit_ready(void)
|
|||
//! An error occurred -> CTRL_FAIL
|
||||
Ctrl_status vfs_read_capacity(uint32_t *last_valid_sector)
|
||||
{
|
||||
if (disk_ioctl(VFS_INDEX, GET_SECTOR_COUNT, last_valid_sector) != RES_OK) {
|
||||
fs_user_mount_t * vfs = get_vfs(VFS_INDEX);
|
||||
if (vfs == NULL ||
|
||||
disk_ioctl(vfs, GET_SECTOR_COUNT, last_valid_sector) != RES_OK) {
|
||||
return CTRL_FAIL;
|
||||
}
|
||||
// Subtract one from the sector count to get the last valid sector.
|
||||
|
@ -83,20 +93,9 @@ Ctrl_status vfs_read_capacity(uint32_t *last_valid_sector)
|
|||
//!
|
||||
bool vfs_wr_protect(void)
|
||||
{
|
||||
mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table);
|
||||
for (uint8_t i = 0; current_mount != NULL; i++) {
|
||||
if (i == VFS_INDEX) {
|
||||
break;
|
||||
}
|
||||
current_mount = current_mount->next;
|
||||
}
|
||||
if (current_mount == NULL) {
|
||||
return true;
|
||||
}
|
||||
fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj;
|
||||
|
||||
fs_user_mount_t * vfs = get_vfs(VFS_INDEX);
|
||||
// This is used to determine the writeability of the disk from USB.
|
||||
if (vfs->writeblocks[0] == MP_OBJ_NULL ||
|
||||
if (vfs == NULL || vfs->writeblocks[0] == MP_OBJ_NULL ||
|
||||
(vfs->flags & FSUSER_USB_WRITEABLE) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
@ -112,11 +111,6 @@ bool vfs_removal(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool vfs_unload(bool unload)
|
||||
{
|
||||
return unload;
|
||||
}
|
||||
|
||||
// TODO(tannewt): Transfer more than a single sector at a time if we need more
|
||||
// speed.
|
||||
//! This function transfers the memory data to the USB MSC interface
|
||||
|
@ -132,9 +126,10 @@ bool vfs_unload(bool unload)
|
|||
//!
|
||||
Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
|
||||
{
|
||||
fs_user_mount_t * vfs = get_vfs(VFS_INDEX);
|
||||
uint8_t sector_buffer[FILESYSTEM_BLOCK_SIZE];
|
||||
for (uint16_t sector = 0; sector < nb_sector; sector++) {
|
||||
DRESULT result = disk_read(VFS_INDEX, sector_buffer, addr + sector, 1);
|
||||
DRESULT result = disk_read(vfs, sector_buffer, addr + sector, 1);
|
||||
if (result == RES_PARERR) {
|
||||
return CTRL_NO_PRESENT;
|
||||
}
|
||||
|
@ -161,13 +156,17 @@ Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
|
|||
//!
|
||||
Ctrl_status vfs_usb_write_10(uint32_t addr, volatile uint16_t nb_sector)
|
||||
{
|
||||
if (vfs_wr_protect()) {
|
||||
return CTRL_FAIL;
|
||||
}
|
||||
fs_user_mount_t * vfs = get_vfs(VFS_INDEX);
|
||||
uint8_t sector_buffer[FILESYSTEM_BLOCK_SIZE];
|
||||
for (uint16_t sector = 0; sector < nb_sector; sector++) {
|
||||
if (!udi_msc_trans_block(false, sector_buffer, FILESYSTEM_BLOCK_SIZE, NULL)) {
|
||||
return CTRL_FAIL; // transfer aborted
|
||||
}
|
||||
uint32_t sector_address = addr + sector;
|
||||
DRESULT result = disk_write(VFS_INDEX, sector_buffer, sector_address, 1);
|
||||
DRESULT result = disk_write(vfs, sector_buffer, sector_address, 1);
|
||||
if (result == RES_PARERR) {
|
||||
return CTRL_NO_PRESENT;
|
||||
}
|
||||
|
@ -176,18 +175,6 @@ Ctrl_status vfs_usb_write_10(uint32_t addr, volatile uint16_t nb_sector)
|
|||
}
|
||||
// Since by getting here we assume the mount is read-only to MicroPython
|
||||
// lets update the cached FatFs sector if its the one we just wrote.
|
||||
mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table);
|
||||
for (uint8_t i = 0; current_mount != NULL; i++) {
|
||||
if (i == VFS_INDEX) {
|
||||
break;
|
||||
}
|
||||
current_mount = current_mount->next;
|
||||
}
|
||||
if (current_mount == NULL) {
|
||||
return CTRL_NO_PRESENT;
|
||||
}
|
||||
fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj;
|
||||
|
||||
#if _MAX_SS != _MIN_SS
|
||||
if (vfs->ssize == FILESYSTEM_BLOCK_SIZE) {
|
||||
#else
|
||||
|
|
|
@ -36,7 +36,6 @@ Ctrl_status vfs_test_unit_ready(void);
|
|||
Ctrl_status vfs_read_capacity(uint32_t *u32_nb_sector);
|
||||
bool vfs_wr_protect(void);
|
||||
bool vfs_removal(void);
|
||||
bool vfs_unload(bool);
|
||||
Ctrl_status vfs_usb_read_10(uint32_t addr, uint16_t nb_sector);
|
||||
Ctrl_status vfs_usb_write_10(uint32_t addr, uint16_t nb_sector);
|
||||
|
||||
|
|
|
@ -104,10 +104,7 @@ void init_flash_fs(void) {
|
|||
} else if (res != FR_OK) {
|
||||
return;
|
||||
}
|
||||
mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t);
|
||||
if (vfs == NULL) {
|
||||
return;
|
||||
}
|
||||
mp_vfs_mount_t *vfs = &mp_vfs_mount_flash;
|
||||
vfs->str = "/";
|
||||
vfs->len = 1;
|
||||
vfs->obj = MP_OBJ_FROM_PTR(vfs_fat);
|
||||
|
@ -584,9 +581,6 @@ int main(void) {
|
|||
mp_stack_ctrl_init();
|
||||
mp_stack_set_limit((char*)&_estack - (char*)&_ebss - 1024);
|
||||
|
||||
// Initialise the local flash filesystem after the gc in case we need to
|
||||
// grab memory from it. Create it if needed, mount in on /flash, and set it
|
||||
// as current dir.
|
||||
init_flash_fs();
|
||||
|
||||
// Reset everything and prep MicroPython to run boot.py.
|
||||
|
@ -599,7 +593,7 @@ int main(void) {
|
|||
|
||||
// If not in safe mode, run boot before initing USB and capture output in a
|
||||
// file.
|
||||
if (safe_mode == NO_SAFE_MODE) {
|
||||
if (safe_mode == NO_SAFE_MODE && MP_STATE_VM(vfs_mount_table) != NULL) {
|
||||
new_status_color(BOOT_RUNNING);
|
||||
#ifdef CIRCUITPY_BOOT_OUTPUT_FILE
|
||||
FIL file_pointer;
|
||||
|
@ -680,6 +674,10 @@ void gc_collect(void) {
|
|||
// pointers from CPU registers, and thus may function incorrectly.
|
||||
void *dummy;
|
||||
gc_collect_start();
|
||||
// This collects root pointers from the first VFS entry which is statically
|
||||
// allocated. This way we can do VFS operations prior to setting up the heap.
|
||||
// This also means it can be done once on boot and not repeatedly.
|
||||
gc_collect_root((void**)&mp_vfs_mount_flash, sizeof(mp_vfs_mount_t) / sizeof(mp_uint_t));
|
||||
// This naively collects all object references from an approximate stack
|
||||
// range.
|
||||
gc_collect_root(&dummy, ((mp_uint_t)&_estack - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
|
||||
|
@ -687,11 +685,13 @@ void gc_collect(void) {
|
|||
}
|
||||
|
||||
void NORETURN nlr_jump_fail(void *val) {
|
||||
while (1);
|
||||
HardFault_Handler();
|
||||
while (true) {}
|
||||
}
|
||||
|
||||
void NORETURN __fatal_error(const char *msg) {
|
||||
while (1);
|
||||
HardFault_Handler();
|
||||
while (true) {}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -662,7 +662,10 @@ const mp_obj_type_t spi_flash_type = {
|
|||
};
|
||||
|
||||
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)&spi_flash_obj_readblocks_obj;
|
||||
vfs->readblocks[1] = (mp_obj_t)&spi_flash_obj;
|
||||
vfs->readblocks[2] = (mp_obj_t)spi_flash_read_blocks; // native version
|
||||
|
|
17
py/runtime.c
17
py/runtime.c
|
@ -29,6 +29,8 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "extmod/vfs.h"
|
||||
|
||||
#include "py/mpstate.h"
|
||||
#include "py/nlr.h"
|
||||
#include "py/parsenum.h"
|
||||
|
@ -114,10 +116,25 @@ void mp_init(void) {
|
|||
#endif
|
||||
|
||||
#if MICROPY_VFS
|
||||
#if MICROPY_FATFS_NUM_PERSISTENT > 0
|
||||
mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table);
|
||||
if (vfs != NULL) {
|
||||
MP_STATE_VM(vfs_cur) = vfs;
|
||||
}
|
||||
// Skip forward until the vfs->next pointer is the first vfs that shouldn't
|
||||
// persist.
|
||||
uint8_t i = 1;
|
||||
while (vfs != NULL && i < MICROPY_FATFS_NUM_PERSISTENT) {
|
||||
vfs = vfs->next;
|
||||
i++;
|
||||
}
|
||||
vfs->next = NULL;
|
||||
#else
|
||||
// initialise the VFS sub-system
|
||||
MP_STATE_VM(vfs_cur) = NULL;
|
||||
MP_STATE_VM(vfs_mount_table) = NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_THREAD_GIL
|
||||
mp_thread_mutex_init(&MP_STATE_VM(gil_mutex));
|
||||
|
|
Loading…
Reference in New Issue