diff options
author | Damien George <damien.p.george@gmail.com> | 2014-07-31 23:44:04 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-07-31 23:44:04 +0100 |
commit | 65dd7bc13d2083a7db5a974bf6480b1652a35c82 (patch) | |
tree | af18c5f8ad6c33a33d7a57e8d495b1890655f15b /stmhal | |
parent | 5aac6aa445d343074b64bb7fa3ddc9184b0c65be (diff) | |
download | micropython-65dd7bc13d2083a7db5a974bf6480b1652a35c82.tar.gz micropython-65dd7bc13d2083a7db5a974bf6480b1652a35c82.zip |
stmhal: Change 0:/ and 1:/ to /flash and /sd; add CWD support.
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.
Diffstat (limited to 'stmhal')
-rw-r--r-- | stmhal/Makefile | 1 | ||||
-rw-r--r-- | stmhal/fatfs/src/ff.c | 27 | ||||
-rw-r--r-- | stmhal/fatfs/src/ff.h | 2 | ||||
-rw-r--r-- | stmhal/ffconf.c | 69 | ||||
-rw-r--r-- | stmhal/ffconf.h | 2 | ||||
-rw-r--r-- | stmhal/main.c | 58 | ||||
-rw-r--r-- | stmhal/modos.c | 91 | ||||
-rw-r--r-- | stmhal/modpyb.c | 2 | ||||
-rw-r--r-- | stmhal/qstrdefsport.h | 10 |
9 files changed, 202 insertions, 60 deletions
diff --git a/stmhal/Makefile b/stmhal/Makefile index 64e38e122a..892ed74b3a 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -104,6 +104,7 @@ SRC_C = \ file.c \ sdcard.c \ diskio.c \ + ffconf.c \ lcd.c \ accel.c \ servo.c \ diff --git a/stmhal/fatfs/src/ff.c b/stmhal/fatfs/src/ff.c index 75b58718b4..5b0ba240c6 100644 --- a/stmhal/fatfs/src/ff.c +++ b/stmhal/fatfs/src/ff.c @@ -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 */
@@ -485,7 +487,7 @@ static WORD Fsid; /* File system mount ID */
#if _FS_RPATH && _VOLUMES >= 2
-static
+//static
BYTE CurrVol; /* Current drive */
#endif
@@ -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 */
@@ -2016,7 +2020,7 @@ int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ return vol;
}
-
+#endif
@@ -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 */
@@ -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 */
@@ -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;
@@ -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++];
@@ -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;
diff --git a/stmhal/fatfs/src/ff.h b/stmhal/fatfs/src/ff.h index 726d899a97..a56161da49 100644 --- a/stmhal/fatfs/src/ff.h +++ b/stmhal/fatfs/src/ff.h @@ -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);
/*--------------------------------------------------------------*/
diff --git a/stmhal/ffconf.c b/stmhal/ffconf.c new file mode 100644 index 0000000000..8f24ae822e --- /dev/null +++ b/stmhal/ffconf.c @@ -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; + } +} diff --git a/stmhal/ffconf.h b/stmhal/ffconf.h index 955d4e505e..4e01423ef8 100644 --- a/stmhal/ffconf.h +++ b/stmhal/ffconf.h @@ -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. diff --git a/stmhal/main.c b/stmhal/main.c index 2cc463462d..183f11b7a0 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -332,8 +332,9 @@ soft_reset: 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(); @@ -344,7 +345,7 @@ soft_reset: // 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 @@ -352,7 +353,7 @@ soft_reset: 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 { @@ -361,19 +362,19 @@ soft_reset: // 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); @@ -387,14 +388,14 @@ soft_reset: } } - // 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 @@ -411,7 +412,7 @@ soft_reset: 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 @@ -424,21 +425,25 @@ soft_reset: } // 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 @@ -453,17 +458,12 @@ soft_reset: (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); } } @@ -518,20 +518,18 @@ soft_reset: // 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 diff --git a/stmhal/modos.c b/stmhal/modos.c index 35979ae972..67daf92504 100644 --- a/stmhal/modos.c +++ b/stmhal/modos.c @@ -38,22 +38,64 @@ #include "storage.h" #include "ff.h" #include "file.h" +#include "sdcard.h" #include "portmodules.h" #if _USE_LFN static char lfn[_MAX_LFN + 1]; /* Buffer to store the LFN */ #endif +STATIC mp_obj_t os_chdir(mp_obj_t path_in) { + const char *path; + path = mp_obj_str_get_str(path_in); + + FRESULT res = f_chdrive(path); + + if (res == FR_OK) { + res = f_chdir(path); + } + + if (res != FR_OK) { + // TODO should be mp_type_FileNotFoundError + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path)); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir); + +STATIC mp_obj_t os_getcwd(void) { + char buf[MICROPY_ALLOC_PATH_MAX + 1]; + FRESULT res = f_getcwd(buf, sizeof buf); + + if (res != FR_OK) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res]))); + } + + return mp_obj_new_str(buf, strlen(buf), false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd); + STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) { - const mp_obj_type_t *local_str_type = &mp_type_str; + bool is_str_type = true; const char *path; if (n_args == 1) { if (mp_obj_get_type(args[0]) == &mp_type_bytes) { - local_str_type = &mp_type_bytes; + is_str_type = false; } path = mp_obj_str_get_str(args[0]); } else { - path = "0:"; + path = ""; + } + + // "hack" to list root directory + if (path[0] == '/' && path[1] == '\0') { + mp_obj_t dir_list = mp_obj_new_list(0, NULL); + mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_flash)); + if (sdcard_is_present()) { // TODO this is not the correct logic to check for /sd + mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_sd)); + } + return dir_list; } FRESULT res; @@ -72,11 +114,6 @@ STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) { mp_obj_t dir_list = mp_obj_new_list(0, NULL); - uint path_len = strlen(path); - if (path[path_len - 1] == '/') { - path_len--; - } - for (;;) { res = f_readdir(&dir, &fno); /* Read a directory item */ if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ @@ -89,20 +126,24 @@ STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) { char *fn = fno.fname; #endif - if (fno.fattrib & AM_DIR) { /* It is a directory */ - } else { /* It is a file. */ + /* + if (fno.fattrib & AM_DIR) { + // dir + } else { + // file } + */ // make a string object for this entry - byte *data; - uint fn_len = strlen(fn); - mp_obj_t entry_o = mp_obj_str_builder_start(local_str_type, path_len + 1 + fn_len, &data); - memcpy(data, path, path_len); - data[path_len] = '/'; - memcpy(data + path_len + 1, fn, fn_len); + mp_obj_t entry_o; + if (is_str_type) { + entry_o = mp_obj_new_str(fn, strlen(fn), false); + } else { + entry_o = mp_obj_new_bytes((const byte*)fn, strlen(fn)); + } // add the entry to the list - mp_obj_list_append(dir_list, mp_obj_str_builder_end(entry_o)); + mp_obj_list_append(dir_list, entry_o); } f_closedir(&dir); @@ -161,9 +202,17 @@ STATIC mp_obj_t os_stat(mp_obj_t path_in) { fno.lfsize = 0; #endif - FRESULT res = f_stat(path, &fno); - if (res != FR_OK) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res]))); + if (path[0] == '/' && path[1] == '\0') { + // stat root directory + fno.fsize = 0; + fno.fdate = 0; + fno.ftime = 0; + fno.fattrib = AM_DIR; + } else { + FRESULT res = f_stat(path, &fno); + if (res != FR_OK) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res]))); + } } mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL); @@ -216,6 +265,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); STATIC const mp_map_elem_t os_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_os) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&os_chdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&os_getcwd_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&os_listdir_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&os_remove_obj }, diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index ace0020f77..4b81d51e32 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -141,7 +141,7 @@ STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) { { DWORD nclst; FATFS *fatfs; - f_getfree("0:", &nclst, &fatfs); + f_getfree("/flash", &nclst, &fatfs); printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512)); } diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index f1f84999f5..719a81d124 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -63,8 +63,10 @@ Q(SDcard) Q(FileIO) Q(flush) // Entries for sys.path -Q(0:/) -Q(0:/lib) +Q(/flash) +Q(/flash/lib) +Q(/sd) +Q(/sd/lib) Q(millis) // for file class @@ -239,6 +241,10 @@ Q(speed) // for os module Q(os) Q(/) +Q(flash) +Q(sd) +Q(chdir) +Q(getcwd) Q(listdir) Q(mkdir) Q(remove) |