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:
Scott Shawcroft 2017-06-26 14:04:22 -07:00
parent 8251d8cb2a
commit e87a61ffb4
5 changed files with 56 additions and 50 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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));