Skip to content

Commit

Permalink
stmhal: Change 0:/ and 1:/ to /flash and /sd; add CWD support.
Browse files Browse the repository at this point in the history
Some important changes to the way the file system is structured on the
pyboard:

1. 0: and 1: drive names are now replaced with POSIX inspired
directories, namely /flash and /sd.

2. Filesystem now supports the notion of a current working directory.
Supports the standard Python way of manipulating it: os.chdir and
os.getcwd.

3. On boot up, current directory is /flash if no SD inserted, else /sd
if SD inserted.  Then runs boot.py and main.py from the current dir.
This is the same as the old behaviour, but is much more consistent and
flexible (eg you can os.chdir in boot.py to change where main.py is run
from).

4. sys.path (for import) is now set to '' (current dir), plus /flash
and /flash/lib, and then /sd and /sd/lib if SD inserted.  This, along
with CWD, means that import now works properly.  You can import a file
from the current directory.

5. os.listdir is fixed to return just the basename, not the full path.

See issue #537 for background and discussion.
  • Loading branch information
dpgeorge committed Jul 31, 2014
1 parent 5aac6aa commit 65dd7bc
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 60 deletions.
1 change: 1 addition & 0 deletions stmhal/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ SRC_C = \
file.c \
sdcard.c \
diskio.c \
ffconf.c \
lcd.c \
accel.c \
servo.c \
Expand Down
27 changes: 21 additions & 6 deletions stmhal/fatfs/src/ff.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@
/ Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code.
/---------------------------------------------------------------------------*/

#include <string.h>

#include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of disk I/O functions */

Expand Down Expand Up @@ -485,7 +487,7 @@ static
WORD Fsid; /* File system mount ID */

#if _FS_RPATH && _VOLUMES >= 2
static
//static
BYTE CurrVol; /* Current drive */
#endif

Expand Down Expand Up @@ -1992,6 +1994,8 @@ void get_fileinfo ( /* No return code */
/* Get logical drive number from path name */
/*-----------------------------------------------------------------------*/

/* now implemented by us for configurability of path names */
#if 0
static
int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */
const TCHAR** path /* Pointer to pointer to the path name */
Expand All @@ -2016,7 +2020,7 @@ int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */

return vol;
}

#endif



Expand Down Expand Up @@ -2131,7 +2135,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */

/* Get logical drive number from the path name */
*rfs = 0;
vol = get_ldnumber(path);
vol = ff_get_ldnumber(path);
if (vol < 0) return FR_INVALID_DRIVE;

/* Check if the file system object is valid or not */
Expand Down Expand Up @@ -2326,7 +2330,7 @@ FRESULT f_mount (
FRESULT res;
const TCHAR *rp = path;

vol = get_ldnumber(&rp);
vol = ff_get_ldnumber(&rp);
if (vol < 0) return FR_INVALID_DRIVE;
cfs = FatFs[vol]; /* Pointer to fs object */

Expand Down Expand Up @@ -2813,7 +2817,7 @@ FRESULT f_chdrive (
int vol;


vol = get_ldnumber(&path);
vol = ff_get_ldnumber(&path);
if (vol < 0) return FR_INVALID_DRIVE;

CurrVol = (BYTE)vol;
Expand Down Expand Up @@ -2912,11 +2916,22 @@ FRESULT f_getcwd (
tp = buff;
if (res == FR_OK) {
#if _VOLUMES >= 2
#if 0
*tp++ = '0' + CurrVol; /* Put drive number */
*tp++ = ':';
#endif
if (CurrVol == 0) {
memcpy(tp, "/flash", 6);
tp += 6;
} else {
memcpy(tp, "/sd", 3);
tp += 3;
}
#endif
if (i == len) { /* Root-directory */
#if 0
*tp++ = '/';
#endif
} else { /* Sub-directroy */
do /* Add stacked path str */
*tp++ = buff[i++];
Expand Down Expand Up @@ -3937,7 +3952,7 @@ FRESULT f_mkfs (


/* Check mounted drive and clear work area */
vol = get_ldnumber(&path);
vol = ff_get_ldnumber(&path);
if (vol < 0) return FR_INVALID_DRIVE;
if (sfd > 1) return FR_INVALID_PARAMETER;
if (au & (au - 1)) return FR_INVALID_PARAMETER;
Expand Down
2 changes: 2 additions & 0 deletions stmhal/fatfs/src/ff.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,8 @@ int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
#endif


/* Returns logical drive number (-1:invalid drive) */
int ff_get_ldnumber(const TCHAR** path);


/*--------------------------------------------------------------*/
Expand Down
69 changes: 69 additions & 0 deletions stmhal/ffconf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* 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 <string.h>

#include "mpconfigport.h"
#include "ff.h"
#include "ffconf.h"

extern BYTE CurrVol;

// "path" is the path to lookup; will advance this pointer beyond the volume name.
// Returns logical drive number (-1 means invalid path).
int ff_get_ldnumber (const TCHAR** path) {
if (!(*path)) {
return -1;
}

if (**path != '/') {
#if _FS_RPATH
return CurrVol;
#else
return -1;
#endif
} else if (strncmp(*path, "/flash", 6) == 0) {
if ((*path)[6] == '/') {
*path += 6;
} else if ((*path)[6] == '\0') {
*path = "/";
} else {
return -1;
}
return 0;
} else if (strncmp(*path, "/sd", 3) == 0) {
if ((*path)[3] == '/') {
*path += 3;
} else if ((*path)[3] == '\0') {
*path = "/";
} else {
return -1;
}
return 1;
} else {
return -1;
}
}
2 changes: 1 addition & 1 deletion stmhal/ffconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
/ This option has no effect when _LFN_UNICODE is 0. */


#define _FS_RPATH 0 /* 0 to 2 */
#define _FS_RPATH 2 /* 0 to 2 */
/* The _FS_RPATH option configures relative path feature.
/
/ 0: Disable relative path feature and remove related functions.
Expand Down
58 changes: 28 additions & 30 deletions stmhal/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,9 @@ int main(void) {
qstr_init();
mp_init();
mp_obj_list_init(mp_sys_path, 0);
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash_slash_lib));
mp_obj_list_init(mp_sys_argv, 0);

readline_init();
Expand All @@ -344,15 +345,15 @@ int main(void) {
// local filesystem init
{
// try to mount the flash
FRESULT res = f_mount(&fatfs0, "0:", 1);
FRESULT res = f_mount(&fatfs0, "/flash", 1);
if (reset_mode == 3 || res == FR_NO_FILESYSTEM) {
// no filesystem, or asked to reset it, so create a fresh one

// LED on to indicate creation of LFS
led_state(PYB_LED_R2, 1);
uint32_t start_tick = HAL_GetTick();

res = f_mkfs("0:", 0, 0);
res = f_mkfs("/flash", 0, 0);
if (res == FR_OK) {
// success creating fresh LFS
} else {
Expand All @@ -361,19 +362,19 @@ int main(void) {

// create empty main.py
FIL fp;
f_open(&fp, "0:/main.py", FA_WRITE | FA_CREATE_ALWAYS);
f_open(&fp, "/flash/main.py", FA_WRITE | FA_CREATE_ALWAYS);
UINT n;
f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n);
// TODO check we could write n bytes
f_close(&fp);

// create .inf driver file
f_open(&fp, "0:/pybcdc.inf", FA_WRITE | FA_CREATE_ALWAYS);
f_open(&fp, "/flash/pybcdc.inf", FA_WRITE | FA_CREATE_ALWAYS);
f_write(&fp, fresh_pybcdc_inf, sizeof(fresh_pybcdc_inf) - 1 /* don't count null terminator */, &n);
f_close(&fp);

// create readme file
f_open(&fp, "0:/README.txt", FA_WRITE | FA_CREATE_ALWAYS);
f_open(&fp, "/flash/README.txt", FA_WRITE | FA_CREATE_ALWAYS);
f_write(&fp, fresh_readme_txt, sizeof(fresh_readme_txt) - 1 /* don't count null terminator */, &n);
f_close(&fp);

Expand All @@ -387,14 +388,14 @@ int main(void) {
}
}

// make sure we have a 0:/boot.py
// make sure we have a /flash/boot.py
{
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
FRESULT res = f_stat("0:/boot.py", &fno);
FRESULT res = f_stat("/flash/boot.py", &fno);
if (res == FR_OK) {
if (fno.fattrib & AM_DIR) {
// exists as a directory
Expand All @@ -411,7 +412,7 @@ int main(void) {
uint32_t start_tick = HAL_GetTick();

FIL fp;
f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
f_open(&fp, "/flash/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
UINT n;
f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n);
// TODO check we could write n bytes
Expand All @@ -424,21 +425,25 @@ int main(void) {
}

// root device defaults to internal flash filesystem
uint root_device = 0;
f_chdrive("/flash");

#if defined(USE_DEVICE_MODE)
usb_storage_medium_t usb_medium = USB_STORAGE_MEDIUM_FLASH;
#endif

#if MICROPY_HW_HAS_SDCARD
// if an SD card is present then mount it on 1:/
// if an SD card is present then mount it on /sd/
if (reset_mode == 1 && sdcard_is_present()) {
FRESULT res = f_mount(&fatfs1, "1:", 1);
FRESULT res = f_mount(&fatfs1, "/sd", 1);
if (res != FR_OK) {
printf("[SD] could not mount SD card\n");
} else {
// use SD card as root device
root_device = 1;
f_chdrive("/sd");

// TODO these should go before the /flash entries in the path
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib));

if (first_soft_reset) {
// use SD card as medium for the USB MSD
Expand All @@ -453,17 +458,12 @@ int main(void) {
(void)first_soft_reset;
#endif

// run <root>:/boot.py, if it exists
// run boot.py, if it exists
if (reset_mode == 1) {
const char *boot_file;
if (root_device == 0) {
boot_file = "0:/boot.py";
} else {
boot_file = "1:/boot.py";
}
FRESULT res = f_stat(boot_file, NULL);
const char *boot_py = "boot.py";
FRESULT res = f_stat(boot_py, NULL);
if (res == FR_OK) {
if (!pyexec_file(boot_file)) {
if (!pyexec_file(boot_py)) {
flash_error(4);
}
}
Expand Down Expand Up @@ -518,20 +518,18 @@ int main(void) {

// now that everything is initialised, run main script
if (reset_mode == 1 && pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
vstr_t *vstr = vstr_new();
vstr_printf(vstr, "%d:/", root_device);
const char *main_py;
if (pyb_config_main == MP_OBJ_NULL) {
vstr_add_str(vstr, "main.py");
main_py = "main.py";
} else {
vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main));
main_py = mp_obj_str_get_str(pyb_config_main);
}
FRESULT res = f_stat(vstr_str(vstr), NULL);
FRESULT res = f_stat(main_py, NULL);
if (res == FR_OK) {
if (!pyexec_file(vstr_str(vstr))) {
if (!pyexec_file(main_py)) {
flash_error(3);
}
}
vstr_free(vstr);
}

#if MICROPY_HW_ENABLE_CC3K
Expand Down
Loading

0 comments on commit 65dd7bc

Please sign in to comment.