From 84c614e7290804e8b8d7ebff03ca35a4a4c5fcf1 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 27 Jan 2017 23:11:59 +1100 Subject: stmhal: Convert to use VFS sub-system and new ooFatFs component. This patch makes the following configuration changes: - MICROPY_FSUSERMOUNT is disabled, removing old mounting infrastructure - MICROPY_VFS is enabled, giving new VFS sub-system - MICROPY_VFS_FAT is enabled, giving uos.VfsFat type - MICROPY_FATFS_OO is enabled, to use new ooFatFs lib, R0.12b User facing API should be almost unchanged. Most notable changes are removal of os.mkfs (use os.VfsFat.mkfs instead) and pyb.mount doesn't allow unmounting by passing None as the device. --- stmhal/main.c | 99 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 50 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index 78afe54ef..1918658b7 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -37,7 +37,8 @@ #include "py/mphal.h" #include "lib/utils/pyexec.h" -#include "lib/fatfs/ff.h" +#include "lib/oofatfs/ff.h" +#include "extmod/vfs.h" #include "extmod/fsusermount.h" #include "systick.h" @@ -67,6 +68,7 @@ void SystemClock_Config(void); fs_user_mount_t fs_user_mount_flash; +mp_vfs_mount_t mp_vfs_mount_flash; void flash_error(int n) { for (int i = 0; i < n; i++) { @@ -168,17 +170,14 @@ static const char fresh_readme_txt[] = // avoid inlining to avoid stack usage within main() MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // init the vfs object - fs_user_mount_t *vfs = &fs_user_mount_flash; - vfs->str = "/flash"; - vfs->len = 6; - vfs->flags = 0; - pyb_flash_init_vfs(vfs); - - // put the flash device in slot 0 (it will be unused at this point) - MP_STATE_PORT(fs_user_mount)[0] = vfs; + fs_user_mount_t *vfs_fat = &fs_user_mount_flash; + vfs_fat->str = NULL; + vfs_fat->len = 0; + vfs_fat->flags = 0; + pyb_flash_init_vfs(vfs_fat); // try to mount the flash - FRESULT res = f_mount(&vfs->fatfs, vfs->str, 1); + FRESULT res = f_mount(&vfs_fat->fatfs); if (reset_mode == 3 || res == FR_NO_FILESYSTEM) { // no filesystem, or asked to reset it, so create a fresh one @@ -187,33 +186,33 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { led_state(PYB_LED_R2, 1); uint32_t start_tick = HAL_GetTick(); - res = f_mkfs("/flash", 0, 0); + uint8_t working_buf[_MAX_SS]; + res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); if (res == FR_OK) { // success creating fresh LFS } else { printf("PYB: can't create flash filesystem\n"); - MP_STATE_PORT(fs_user_mount)[0] = NULL; return; } // set label - f_setlabel("/flash/pybflash"); + f_setlabel(&vfs_fat->fatfs, "pybflash"); // create empty main.py FIL fp; - f_open(&fp, "/flash/main.py", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &fp, "/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, "/flash/pybcdc.inf", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &fp, "/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, "/flash/README.txt", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &fp, "/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); @@ -224,30 +223,25 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // mount sucessful } else { printf("PYB: can't mount flash\n"); - MP_STATE_PORT(fs_user_mount)[0] = NULL; return; } + // mount the flash device (there should be no other devices mounted at this point) + mp_vfs_mount_t *vfs = &mp_vfs_mount_flash; + vfs->str = "/flash"; + vfs->len = 6; + vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); + vfs->next = NULL; + MP_STATE_VM(vfs_mount_table) = vfs; + // The current directory is used as the boot up directory. // It is set to the internal flash filesystem by default. - f_chdrive("/flash"); + MP_STATE_PORT(vfs_cur) = vfs; // Make sure we have a /flash/boot.py. Create it if needed. FILINFO fno; -#if _USE_LFN - fno.lfname = NULL; - fno.lfsize = 0; -#endif - res = f_stat("/flash/boot.py", &fno); - if (res == FR_OK) { - if (fno.fattrib & AM_DIR) { - // exists as a directory - // TODO handle this case - // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation - } else { - // exists as a file, good! - } - } else { + res = f_stat(&vfs_fat->fatfs, "/boot.py", &fno); + if (res != FR_OK) { // doesn't exist, create fresh file // LED on to indicate creation of boot.py @@ -255,7 +249,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { uint32_t start_tick = HAL_GetTick(); FIL fp; - f_open(&fp, "/flash/boot.py", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &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 @@ -485,24 +479,29 @@ soft_reset: // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { // create vfs object - fs_user_mount_t *vfs = m_new_obj_maybe(fs_user_mount_t); - if (vfs == NULL) { + fs_user_mount_t *vfs_fat = m_new_obj_maybe(fs_user_mount_t); + mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); + if (vfs == NULL || vfs_fat == NULL) { goto no_mem_for_sd; } - vfs->str = "/sd"; - vfs->len = 3; - vfs->flags = FSUSER_FREE_OBJ; - sdcard_init_vfs(vfs); - - // put the sd device in slot 1 (it will be unused at this point) - MP_STATE_PORT(fs_user_mount)[1] = vfs; + vfs_fat->str = NULL; + vfs_fat->len = 0; + vfs_fat->flags = FSUSER_FREE_OBJ; + sdcard_init_vfs(vfs_fat); - FRESULT res = f_mount(&vfs->fatfs, vfs->str, 1); + FRESULT res = f_mount(&vfs_fat->fatfs); if (res != FR_OK) { printf("PYB: can't mount SD card\n"); - MP_STATE_PORT(fs_user_mount)[1] = NULL; - m_del_obj(fs_user_mount_t, vfs); + m_del_obj(fs_user_mount_t, vfs_fat); + m_del_obj(mp_vfs_mount_t, vfs); } else { + // mount the sd device after the internal flash + vfs->str = "/sd"; + vfs->len = 3; + vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); + vfs->next = NULL; + MP_STATE_VM(vfs_mount_table)->next = vfs; + // 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)); @@ -520,7 +519,7 @@ soft_reset: #endif { // use SD card as current directory - f_chdrive("/sd"); + MP_STATE_PORT(vfs_cur) = vfs; } } no_mem_for_sd:; @@ -534,8 +533,8 @@ soft_reset: // TODO perhaps have pyb.reboot([bootpy]) function to soft-reboot and execute custom boot.py if (reset_mode == 1 || reset_mode == 3) { const char *boot_py = "boot.py"; - FRESULT res = f_stat(boot_py, NULL); - if (res == FR_OK) { + mp_import_stat_t stat = mp_import_stat(boot_py); + if (stat == MP_IMPORT_STAT_FILE) { int ret = pyexec_file(boot_py); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; @@ -597,8 +596,8 @@ soft_reset: } else { main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main)); } - FRESULT res = f_stat(main_py, NULL); - if (res == FR_OK) { + mp_import_stat_t stat = mp_import_stat(main_py); + if (stat == MP_IMPORT_STAT_FILE) { int ret = pyexec_file(main_py); if (ret & PYEXEC_FORCED_EXIT) { goto soft_reset_exit; -- cgit v1.2.3 From c3cd46e5c2dc110d6f0f9f1803f60f8832d156f2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 29 Jan 2017 15:09:36 +1100 Subject: stmhal: Fix name of automatically created boot.py. --- stmhal/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index 1918658b7..9eab50061 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -249,7 +249,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { uint32_t start_tick = HAL_GetTick(); FIL fp; - f_open(&vfs_fat->fatfs, &fp, "/flash/boot.py", FA_WRITE | FA_CREATE_ALWAYS); + f_open(&vfs_fat->fatfs, &fp, "/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 -- cgit v1.2.3 From b697c890096805d9ccaf7553dbff5b82f5332609 Mon Sep 17 00:00:00 2001 From: Damien George Date: Sun, 29 Jan 2017 19:20:27 +1100 Subject: extmod: Merge old fsusermount.h header into vfs.h and vfs_fat.h. vfs.h is for generic VFS declarations, and vfs_fat.h is for VfsFat specific things. --- cc3200/ftp/ftp.c | 2 +- cc3200/mods/pybflash.c | 1 - cc3200/mods/pybsd.c | 2 +- cc3200/mptask.c | 2 +- extmod/fsusermount.h | 62 ------------------------------------------------- extmod/vfs.c | 5 +++- extmod/vfs.h | 7 ++++++ extmod/vfs_fat.c | 1 - extmod/vfs_fat.h | 26 ++++++++++++++++++++- extmod/vfs_fat_diskio.c | 2 +- extmod/vfs_fat_file.c | 1 - extmod/vfs_fat_misc.c | 1 - stmhal/main.c | 2 +- stmhal/modmachine.c | 2 +- stmhal/sdcard.c | 1 - stmhal/storage.c | 1 - 16 files changed, 42 insertions(+), 76 deletions(-) delete mode 100644 extmod/fsusermount.h (limited to 'stmhal/main.c') diff --git a/cc3200/ftp/ftp.c b/cc3200/ftp/ftp.c index c8a52149c..679c32561 100644 --- a/cc3200/ftp/ftp.c +++ b/cc3200/ftp/ftp.c @@ -32,7 +32,7 @@ #include "py/obj.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" -#include "extmod/fsusermount.h" +#include "extmod/vfs_fat.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" diff --git a/cc3200/mods/pybflash.c b/cc3200/mods/pybflash.c index 0779f4a05..f5af79dbf 100644 --- a/cc3200/mods/pybflash.c +++ b/cc3200/mods/pybflash.c @@ -31,7 +31,6 @@ #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs_fat.h" -#include "extmod/fsusermount.h" #include "fatfs/src/drivers/sflash_diskio.h" #include "mods/pybflash.h" diff --git a/cc3200/mods/pybsd.c b/cc3200/mods/pybsd.c index bac5a270c..937b8599d 100644 --- a/cc3200/mods/pybsd.c +++ b/cc3200/mods/pybsd.c @@ -29,7 +29,7 @@ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" -#include "extmod/fsusermount.h" +#include "extmod/vfs_fat.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "inc/hw_ints.h" diff --git a/cc3200/mptask.c b/cc3200/mptask.c index 476561c6d..c7c1832ed 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -36,7 +36,7 @@ #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs.h" -#include "extmod/fsusermount.h" +#include "extmod/vfs_fat.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" diff --git a/extmod/fsusermount.h b/extmod/fsusermount.h deleted file mode 100644 index af6867d23..000000000 --- a/extmod/fsusermount.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 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. - */ - -// these are the values for fs_user_mount_t.flags -#define FSUSER_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func -#define FSUSER_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount -#define FSUSER_HAVE_IOCTL (0x0004) // new protocol with ioctl - -// constants for block protocol ioctl -#define BP_IOCTL_INIT (1) -#define BP_IOCTL_DEINIT (2) -#define BP_IOCTL_SYNC (3) -#define BP_IOCTL_SEC_COUNT (4) -#define BP_IOCTL_SEC_SIZE (5) - -typedef struct _fs_user_mount_t { - mp_obj_base_t base; - const char *str; - uint16_t len; // length of str - uint16_t flags; - mp_obj_t readblocks[4]; - mp_obj_t writeblocks[4]; - // new protocol uses just ioctl, old uses sync (optional) and count - union { - mp_obj_t ioctl[4]; - struct { - mp_obj_t sync[2]; - mp_obj_t count[2]; - } old; - } u; - FATFS fatfs; -} fs_user_mount_t; - -fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs); -mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in); - -MP_DECLARE_CONST_FUN_OBJ_KW(fsuser_mount_obj); -MP_DECLARE_CONST_FUN_OBJ_1(fsuser_umount_obj); -MP_DECLARE_CONST_FUN_OBJ_KW(fsuser_mkfs_obj); diff --git a/extmod/vfs.c b/extmod/vfs.c index 97c9077a2..1eb26acf1 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -31,10 +31,13 @@ #include "py/objstr.h" #include "py/mperrno.h" #include "extmod/vfs.h" -#include "extmod/vfs_fat.h" #if MICROPY_VFS +#if MICROPY_VFS_FAT +#include "extmod/vfs_fat.h" +#endif + // path is the path to lookup and *path_out holds the path within the VFS // object (starts with / if an absolute path). // Returns MP_VFS_ROOT for root dir (and then path_out is undefined) and diff --git a/extmod/vfs.h b/extmod/vfs.h index 92e53b305..4a1c225a0 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -35,6 +35,13 @@ #define MP_VFS_NONE ((mp_vfs_mount_t*)1) #define MP_VFS_ROOT ((mp_vfs_mount_t*)0) +// constants for block protocol ioctl +#define BP_IOCTL_INIT (1) +#define BP_IOCTL_DEINIT (2) +#define BP_IOCTL_SYNC (3) +#define BP_IOCTL_SEC_COUNT (4) +#define BP_IOCTL_SEC_SIZE (5) + typedef struct _mp_vfs_mount_t { const char *str; // mount point with leading / size_t len; diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index ecbbdb59a..b32bf7ad9 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -38,7 +38,6 @@ #include "py/mperrno.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs_fat.h" -#include "extmod/fsusermount.h" #include "timeutils.h" #if _MAX_SS == _MIN_SS diff --git a/extmod/vfs_fat.h b/extmod/vfs_fat.h index bc5be0c67..fefae776c 100644 --- a/extmod/vfs_fat.h +++ b/extmod/vfs_fat.h @@ -25,8 +25,32 @@ */ #include "py/lexer.h" +#include "py/obj.h" +#include "lib/oofatfs/ff.h" +#include "extmod/vfs.h" -struct _fs_user_mount_t; +// these are the values for fs_user_mount_t.flags +#define FSUSER_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func +#define FSUSER_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount +#define FSUSER_HAVE_IOCTL (0x0004) // new protocol with ioctl + +typedef struct _fs_user_mount_t { + mp_obj_base_t base; + const char *str; + uint16_t len; // length of str + uint16_t flags; + mp_obj_t readblocks[4]; + mp_obj_t writeblocks[4]; + // new protocol uses just ioctl, old uses sync (optional) and count + union { + mp_obj_t ioctl[4]; + struct { + mp_obj_t sync[2]; + mp_obj_t count[2]; + } old; + } u; + FATFS fatfs; +} fs_user_mount_t; extern const byte fresult_to_errno_table[20]; extern const mp_obj_type_t mp_fat_vfs_type; diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c index e12c4597e..7efcc22f2 100644 --- a/extmod/vfs_fat_diskio.c +++ b/extmod/vfs_fat_diskio.c @@ -38,7 +38,7 @@ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" -#include "extmod/fsusermount.h" +#include "extmod/vfs_fat.h" #if _MAX_SS == _MIN_SS #define SECSIZE(fs) (_MIN_SS) diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index bb5903575..0f2a7a1aa 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -35,7 +35,6 @@ #include "py/stream.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" -#include "extmod/fsusermount.h" #include "extmod/vfs_fat.h" #if MICROPY_VFS_FAT diff --git a/extmod/vfs_fat_misc.c b/extmod/vfs_fat_misc.c index ba513ef92..97d2675cd 100644 --- a/extmod/vfs_fat_misc.c +++ b/extmod/vfs_fat_misc.c @@ -32,7 +32,6 @@ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs_fat.h" -#include "extmod/fsusermount.h" #include "py/lexer.h" // TODO: actually, the core function should be ilistdir() diff --git a/stmhal/main.c b/stmhal/main.c index 9eab50061..3a0bd7a6b 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -39,7 +39,7 @@ #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" -#include "extmod/fsusermount.h" +#include "extmod/vfs_fat.h" #include "systick.h" #include "pendsv.h" diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c index aec8e29c5..b10bca819 100644 --- a/stmhal/modmachine.c +++ b/stmhal/modmachine.c @@ -37,7 +37,7 @@ #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" -#include "extmod/fsusermount.h" +#include "extmod/vfs_fat.h" #include "gccollect.h" #include "irq.h" #include "rng.h" diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c index 52ede492b..b1d67f62a 100644 --- a/stmhal/sdcard.c +++ b/stmhal/sdcard.c @@ -30,7 +30,6 @@ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs_fat.h" -#include "extmod/fsusermount.h" #include "mphalport.h" #include "sdcard.h" diff --git a/stmhal/storage.c b/stmhal/storage.c index 6130d6fb8..c1daad4c2 100644 --- a/stmhal/storage.c +++ b/stmhal/storage.c @@ -31,7 +31,6 @@ #include "py/runtime.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs_fat.h" -#include "extmod/fsusermount.h" #include "systick.h" #include "led.h" -- cgit v1.2.3 From 220abca311063e736489adb675c18a25ff725932 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 30 Jan 2017 13:01:21 +1100 Subject: stmhal: Use LED constants from PYBv4 onwards. --- stmhal/main.c | 18 +++++++++--------- stmhal/storage.c | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index 3a0bd7a6b..94b8bd7f7 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -72,14 +72,14 @@ mp_vfs_mount_t mp_vfs_mount_flash; void flash_error(int n) { for (int i = 0; i < n; i++) { - led_state(PYB_LED_R1, 1); - led_state(PYB_LED_R2, 0); + led_state(PYB_LED_RED, 1); + led_state(PYB_LED_GREEN, 0); HAL_Delay(250); - led_state(PYB_LED_R1, 0); - led_state(PYB_LED_R2, 1); + led_state(PYB_LED_RED, 0); + led_state(PYB_LED_GREEN, 1); HAL_Delay(250); } - led_state(PYB_LED_R2, 0); + led_state(PYB_LED_GREEN, 0); } void NORETURN __fatal_error(const char *msg) { @@ -183,7 +183,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // 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); + led_state(PYB_LED_GREEN, 1); uint32_t start_tick = HAL_GetTick(); uint8_t working_buf[_MAX_SS]; @@ -218,7 +218,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // keep LED on for at least 200ms sys_tick_wait_at_least(start_tick, 200); - led_state(PYB_LED_R2, 0); + led_state(PYB_LED_GREEN, 0); } else if (res == FR_OK) { // mount sucessful } else { @@ -245,7 +245,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // doesn't exist, create fresh file // LED on to indicate creation of boot.py - led_state(PYB_LED_R2, 1); + led_state(PYB_LED_GREEN, 1); uint32_t start_tick = HAL_GetTick(); FIL fp; @@ -257,7 +257,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // keep LED on for at least 200ms sys_tick_wait_at_least(start_tick, 200); - led_state(PYB_LED_R2, 0); + led_state(PYB_LED_GREEN, 0); } } diff --git a/stmhal/storage.c b/stmhal/storage.c index c1daad4c2..0a5b50739 100644 --- a/stmhal/storage.c +++ b/stmhal/storage.c @@ -149,7 +149,7 @@ static uint8_t *flash_cache_get_addr_for_write(uint32_t flash_addr) { flash_cache_sector_size = flash_sector_size; } flash_flags |= FLASH_FLAG_DIRTY; - led_state(PYB_LED_R1, 1); // indicate a dirty cache with LED on + led_state(PYB_LED_RED, 1); // indicate a dirty cache with LED on flash_tick_counter_last_write = HAL_GetTick(); return (uint8_t*)CACHE_MEM_START_ADDR + flash_addr - flash_sector_start; } @@ -261,7 +261,7 @@ void storage_irq_handler(void) { // clear the flash flags now that we have a clean cache flash_flags = 0; // indicate a clean cache with LED off - led_state(PYB_LED_R1, 0); + led_state(PYB_LED_RED, 0); } #endif -- cgit v1.2.3 From 3667ee1b8870ddc76f47260eb87d7d13736c9ad2 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 31 Jan 2017 12:18:08 +1100 Subject: stmhal: On boot, mount all available partitions of the SD card. The first partition is mounted as "/sd" and subsequent partitions are mounted as "/sd". This is backwards compatible with the previous behaviour, which just mounted the first partition on "/sd". At this point, only FatFs filesystems are mounted. --- stmhal/main.c | 125 ++++++++++++++++++++++++++++++++++++-------------------- stmhal/sdcard.c | 4 +- stmhal/sdcard.h | 2 +- 3 files changed, 83 insertions(+), 48 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index 94b8bd7f7..e19adb3dd 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -261,6 +261,85 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { } } +STATIC void init_sdcard_fs(bool first_soft_reset) { + bool first_part = true; + for (int part_num = 1; part_num <= 4; ++part_num) { + // create vfs object + fs_user_mount_t *vfs_fat = m_new_obj_maybe(fs_user_mount_t); + mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); + if (vfs == NULL || vfs_fat == NULL) { + break; + } + vfs_fat->str = NULL; + vfs_fat->len = 0; + vfs_fat->flags = FSUSER_FREE_OBJ; + sdcard_init_vfs(vfs_fat, part_num); + + // try to mount the partition + FRESULT res = f_mount(&vfs_fat->fatfs); + + if (res != FR_OK) { + // couldn't mount + m_del_obj(fs_user_mount_t, vfs_fat); + m_del_obj(mp_vfs_mount_t, vfs); + } else { + // mounted via FatFs, now mount the SD partition in the VFS + if (first_part) { + // the first available partition is traditionally called "sd" for simplicity + vfs->str = "/sd"; + vfs->len = 3; + } else { + // subsequent partitions are numbered by their index in the partition table + if (part_num == 2) { + vfs->str = "/sd2"; + } else if (part_num == 2) { + vfs->str = "/sd3"; + } else { + vfs->str = "/sd4"; + } + vfs->len = 4; + } + vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); + vfs->next = NULL; + for (mp_vfs_mount_t **m = &MP_STATE_VM(vfs_mount_table);; m = &(*m)->next) { + if (*m == NULL) { + *m = vfs; + break; + } + } + + if (first_part) { + // 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 + #if defined(USE_DEVICE_MODE) + pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_SDCARD; + #endif + } + + #if defined(USE_DEVICE_MODE) + // only use SD card as current directory if that's what the USB medium is + if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_SDCARD) + #endif + { + if (first_part) { + // use SD card as current directory + MP_STATE_PORT(vfs_cur) = vfs; + } + } + first_part = false; + } + } + + if (first_part) { + printf("PYB: can't mount SD card\n"); + } +} + STATIC uint update_reset_mode(uint reset_mode) { #if MICROPY_HW_HAS_SWITCH if (switch_get()) { @@ -478,51 +557,7 @@ soft_reset: #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { - // create vfs object - fs_user_mount_t *vfs_fat = m_new_obj_maybe(fs_user_mount_t); - mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); - if (vfs == NULL || vfs_fat == NULL) { - goto no_mem_for_sd; - } - vfs_fat->str = NULL; - vfs_fat->len = 0; - vfs_fat->flags = FSUSER_FREE_OBJ; - sdcard_init_vfs(vfs_fat); - - FRESULT res = f_mount(&vfs_fat->fatfs); - if (res != FR_OK) { - printf("PYB: can't mount SD card\n"); - m_del_obj(fs_user_mount_t, vfs_fat); - m_del_obj(mp_vfs_mount_t, vfs); - } else { - // mount the sd device after the internal flash - vfs->str = "/sd"; - vfs->len = 3; - vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); - vfs->next = NULL; - MP_STATE_VM(vfs_mount_table)->next = vfs; - - // 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 -#if defined(USE_DEVICE_MODE) - pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_SDCARD; -#endif - } - - #if defined(USE_DEVICE_MODE) - // only use SD card as current directory if that's what the USB medium is - if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_SDCARD) - #endif - { - // use SD card as current directory - MP_STATE_PORT(vfs_cur) = vfs; - } - } - no_mem_for_sd:; + init_sdcard_fs(first_soft_reset); } #endif diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c index f4ad98504..6e9c46df5 100644 --- a/stmhal/sdcard.c +++ b/stmhal/sdcard.c @@ -443,11 +443,11 @@ const mp_obj_type_t pyb_sdcard_type = { .locals_dict = (mp_obj_t)&pyb_sdcard_locals_dict, }; -void sdcard_init_vfs(fs_user_mount_t *vfs) { +void sdcard_init_vfs(fs_user_mount_t *vfs, int part) { vfs->base.type = &mp_fat_vfs_type; vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; vfs->fatfs.drv = vfs; - vfs->fatfs.part = 0; // autodetect partition + vfs->fatfs.part = part; vfs->readblocks[0] = (mp_obj_t)&pyb_sdcard_readblocks_obj; vfs->readblocks[1] = (mp_obj_t)&pyb_sdcard_obj; vfs->readblocks[2] = (mp_obj_t)sdcard_read_blocks; // native version diff --git a/stmhal/sdcard.h b/stmhal/sdcard.h index ccc24927e..237e48d8b 100644 --- a/stmhal/sdcard.h +++ b/stmhal/sdcard.h @@ -41,4 +41,4 @@ extern const struct _mp_obj_type_t pyb_sdcard_type; extern const struct _mp_obj_base_t pyb_sdcard_obj; struct _fs_user_mount_t; -void sdcard_init_vfs(struct _fs_user_mount_t *vfs); +void sdcard_init_vfs(struct _fs_user_mount_t *vfs, int part); -- cgit v1.2.3 From 80dfd650908eaac9a9c8601c655990812e879f7f Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 31 Jan 2017 12:30:18 +1100 Subject: stmhal/main: Put /sd directory before /flash in sys.path. If the SD card is mounted then its libraries (ie those that are imported) should override any in /flash. --- stmhal/main.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index e19adb3dd..989e7da76 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -168,7 +168,7 @@ static const char fresh_readme_txt[] = ; // avoid inlining to avoid stack usage within main() -MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { +MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // init the vfs object fs_user_mount_t *vfs_fat = &fs_user_mount_flash; vfs_fat->str = NULL; @@ -192,7 +192,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // success creating fresh LFS } else { printf("PYB: can't create flash filesystem\n"); - return; + return false; } // set label @@ -223,7 +223,7 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { // mount sucessful } else { printf("PYB: can't mount flash\n"); - return; + return false; } // mount the flash device (there should be no other devices mounted at this point) @@ -259,9 +259,11 @@ MP_NOINLINE STATIC void init_flash_fs(uint reset_mode) { sys_tick_wait_at_least(start_tick, 200); led_state(PYB_LED_GREEN, 0); } + + return true; } -STATIC void init_sdcard_fs(bool first_soft_reset) { +STATIC bool init_sdcard_fs(bool first_soft_reset) { bool first_part = true; for (int part_num = 1; part_num <= 4; ++part_num) { // create vfs object @@ -308,12 +310,6 @@ STATIC void init_sdcard_fs(bool first_soft_reset) { } } - if (first_part) { - // 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 #if defined(USE_DEVICE_MODE) @@ -337,6 +333,9 @@ STATIC void init_sdcard_fs(bool first_soft_reset) { if (first_part) { printf("PYB: can't mount SD card\n"); + return false; + } else { + return true; } } @@ -508,8 +507,6 @@ soft_reset: mp_init(); mp_obj_list_init(mp_sys_path, 0); 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); // Initialise low-level sub-systems. Here we need to very basic things like @@ -552,15 +549,26 @@ soft_reset: // Initialise the local flash filesystem. // Create it if needed, mount in on /flash, and set it as current dir. - init_flash_fs(reset_mode); + bool mounted_flash = init_flash_fs(reset_mode); + bool mounted_sdcard = false; #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { - init_sdcard_fs(first_soft_reset); + mounted_sdcard = init_sdcard_fs(first_soft_reset); } #endif + // set sys.path based on mounted filesystems (/sd is first so it can override /flash) + if (mounted_sdcard) { + 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 (mounted_flash) { + 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)); + } + // reset config variables; they should be set by boot.py MP_STATE_PORT(pyb_config_main) = MP_OBJ_NULL; -- cgit v1.2.3 From 7d8c79ab6d6b714f60ad07189f29e526cc0aee9a Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 31 Jan 2017 13:04:32 +1100 Subject: stmhal/main: Guard init_sdcard_fs with MICROPY_HW_HAS_SDCARD. --- stmhal/main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index 989e7da76..722ca41b4 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -263,6 +263,7 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { return true; } +#if MICROPY_HW_HAS_SDCARD STATIC bool init_sdcard_fs(bool first_soft_reset) { bool first_part = true; for (int part_num = 1; part_num <= 4; ++part_num) { @@ -338,6 +339,7 @@ STATIC bool init_sdcard_fs(bool first_soft_reset) { return true; } } +#endif STATIC uint update_reset_mode(uint reset_mode) { #if MICROPY_HW_HAS_SWITCH -- cgit v1.2.3 From 882ec01e42227445a63f6d5b38cac14d8635f2ad Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 31 Jan 2017 13:59:53 +1100 Subject: stmhal: Initial implementation of multithreading, currently disabled. This patch brings the _thread module to stmhal/pyboard. There is a very simple round-robin thread scheduler, which is disabled if there is only one thread (for efficiency when threading is not used). The scheduler currently switches threads at a rate of 250Hz using the systick timer and the pend-SV interrupt. The GIL is disabled so one must be careful to use lock objects to prevent concurrent access of objects. The threading is disabled by default, one can enabled it with the config option MICROPY_PY_THREAD to test it out. --- stmhal/Makefile | 2 + stmhal/gccollect.c | 11 +++++ stmhal/main.c | 19 ++++++-- stmhal/mpconfigport.h | 2 + stmhal/mpthreadport.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++ stmhal/mpthreadport.h | 45 ++++++++++++++++++ stmhal/pendsv.c | 30 ++++++++++++ stmhal/pybthread.c | 97 +++++++++++++++++++++++++++++++++++++++ stmhal/pybthread.h | 62 +++++++++++++++++++++++++ stmhal/stm32_it.c | 6 +++ 10 files changed, 392 insertions(+), 5 deletions(-) create mode 100644 stmhal/mpthreadport.c create mode 100644 stmhal/mpthreadport.h create mode 100644 stmhal/pybthread.c create mode 100644 stmhal/pybthread.h (limited to 'stmhal/main.c') diff --git a/stmhal/Makefile b/stmhal/Makefile index 3431c3105..a83f2c495 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -131,9 +131,11 @@ SRC_C = \ usbd_hid_interface.c \ usbd_msc_storage.c \ mphalport.c \ + mpthreadport.c \ irq.c \ pendsv.c \ systick.c \ + pybthread.c \ timer.c \ led.c \ pin.c \ diff --git a/stmhal/gccollect.c b/stmhal/gccollect.c index de76b71ac..8a7bbf27f 100644 --- a/stmhal/gccollect.c +++ b/stmhal/gccollect.c @@ -27,8 +27,10 @@ #include #include +#include "py/mpstate.h" #include "py/obj.h" #include "py/gc.h" +#include "py/mpthread.h" #include "gccollect.h" #include "systick.h" @@ -48,7 +50,16 @@ void gc_collect(void) { mp_uint_t sp = gc_helper_get_regs_and_sp(regs); // trace the stack, including the registers (since they live on the stack in this function) + #if MICROPY_PY_THREAD + gc_collect_root((void**)sp, ((uint32_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t)); + #else gc_collect_root((void**)sp, ((uint32_t)&_ram_end - sp) / sizeof(uint32_t)); + #endif + + // trace root pointers from any threads + #if MICROPY_PY_THREAD + mp_thread_gc_others(); + #endif // end the GC gc_collect_end(); diff --git a/stmhal/main.c b/stmhal/main.c index 722ca41b4..4ffa0d9ba 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -43,6 +43,7 @@ #include "systick.h" #include "pendsv.h" +#include "pybthread.h" #include "gccollect.h" #include "readline.h" #include "modmachine.h" @@ -67,6 +68,7 @@ void SystemClock_Config(void); +pyb_thread_t pyb_thread_main; fs_user_mount_t fs_user_mount_flash; mp_vfs_mount_t mp_vfs_mount_flash; @@ -419,11 +421,6 @@ STATIC uint update_reset_mode(uint reset_mode) { int main(void) { // TODO disable JTAG - // Stack limit should be less than real stack size, so we have a chance - // to recover from limit hit. (Limit is measured in bytes.) - mp_stack_ctrl_init(); - mp_stack_set_limit((char*)&_ram_end - (char*)&_heap_end - 1024); - /* STM32F4xx HAL library initialization: - Configure the Flash prefetch, instruction and Data caches - Configure the Systick to generate an interrupt each 1 msec @@ -457,6 +454,7 @@ int main(void) { #endif // basic sub-system init + pyb_thread_init(&pyb_thread_main); pendsv_init(); led_init(); #if MICROPY_HW_HAS_SWITCH @@ -502,6 +500,17 @@ soft_reset: storage_init(); } + // Python threading init + #if MICROPY_PY_THREAD + mp_thread_init(); + #endif + + // Stack limit should be less than real stack size, so we have a chance + // to recover from limit hit. (Limit is measured in bytes.) + // Note: stack control relies on main thread being initialised above + mp_stack_ctrl_init(); + mp_stack_set_limit((char*)&_ram_end - (char*)&_heap_end - 1024); + // GC init gc_init(&_heap_start, &_heap_end); diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 873215458..083f75418 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -102,6 +102,8 @@ #define MICROPY_PY_SYS_PLATFORM "pyboard" #endif #define MICROPY_PY_UERRNO (1) +#define MICROPY_PY_THREAD (0) +#define MICROPY_PY_THREAD_GIL (0) // extended modules #define MICROPY_PY_UCTYPES (1) diff --git a/stmhal/mpthreadport.c b/stmhal/mpthreadport.c new file mode 100644 index 000000000..97c19647c --- /dev/null +++ b/stmhal/mpthreadport.c @@ -0,0 +1,123 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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 + +#include "py/mpconfig.h" +#include "py/mpstate.h" +#include "py/gc.h" +#include "py/mpthread.h" +#include "gccollect.h" + +#if MICROPY_PY_THREAD + +// the mutex controls access to the linked list +STATIC mp_thread_mutex_t thread_mutex; + +void mp_thread_init(void) { + mp_thread_mutex_init(&thread_mutex); + mp_thread_set_state(&mp_state_ctx.thread); +} + +void mp_thread_gc_others(void) { + mp_thread_mutex_lock(&thread_mutex, 1); + gc_collect_root((void**)&pyb_thread_cur, 1); + for (pyb_thread_t *th = pyb_thread_cur;; th = th->next) { + gc_collect_root(&th->arg, 1); + if (th != pyb_thread_cur) { + gc_collect_root(th->stack, th->stack_len); + } + if (th->next == pyb_thread_cur) { + break; + } + } + mp_thread_mutex_unlock(&thread_mutex); +} + +void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { + if (*stack_size == 0) { + *stack_size = 4096; // default stack size + } else if (*stack_size < 2048) { + *stack_size = 2048; // minimum stack size + } + + // round stack size to a multiple of the word size + size_t stack_len = *stack_size / sizeof(uint32_t); + *stack_size = stack_len * sizeof(uint32_t); + + // allocate stack and linked-list node (must be done outside thread_mutex lock) + uint32_t *stack = m_new(uint32_t, stack_len); + pyb_thread_t *th = m_new_obj(pyb_thread_t); + + mp_thread_mutex_lock(&thread_mutex, 1); + + // create thread + uint32_t id = pyb_thread_new(th, stack, stack_len, entry, arg); + if (id == 0) { + mp_thread_mutex_unlock(&thread_mutex); + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); + } + + mp_thread_mutex_unlock(&thread_mutex); + + // adjust stack_size to provide room to recover from hitting the limit + *stack_size -= 1024; +} + +void mp_thread_start(void) { +} + +void mp_thread_finish(void) { +} + +void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { + *mutex = 0; +} + +int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { + uint32_t irq_state = disable_irq(); + if (*mutex) { + // mutex is locked + if (!wait) { + enable_irq(irq_state); + return 0; // failed to lock mutex + } + while (*mutex) { + enable_irq(irq_state); + pyb_thread_yield(); + irq_state = disable_irq(); + } + } + *mutex = 1; + enable_irq(irq_state); + return 1; // have mutex +} + +void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { + *mutex = 0; +} + +#endif // MICROPY_PY_THREAD diff --git a/stmhal/mpthreadport.h b/stmhal/mpthreadport.h new file mode 100644 index 000000000..4fef323eb --- /dev/null +++ b/stmhal/mpthreadport.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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. + */ +#ifndef __MICROPY_INCLUDED_STMHAL_MPTHREADPORT_H__ +#define __MICROPY_INCLUDED_STMHAL_MPTHREADPORT_H__ + +#include "py/mpthread.h" +#include "pybthread.h" + +typedef uint32_t mp_thread_mutex_t; + +void mp_thread_init(void); +void mp_thread_gc_others(void); + +static inline void mp_thread_set_state(void *state) { + pyb_thread_set_local(state); +} + +static inline struct _mp_state_thread_t *mp_thread_get_state(void) { + return pyb_thread_get_local(); +} + +#endif // __MICROPY_INCLUDED_STMHAL_MPTHREADPORT_H__ diff --git a/stmhal/pendsv.c b/stmhal/pendsv.c index 61fe95439..e6df84b29 100644 --- a/stmhal/pendsv.c +++ b/stmhal/pendsv.c @@ -89,6 +89,35 @@ void pendsv_isr_handler(void) { // sp[1]: 0xfffffff9 // sp[0]: ? +#if MICROPY_PY_THREAD + __asm volatile ( + "ldr r1, pendsv_object_ptr\n" + "ldr r0, [r1]\n" + "cmp r0, 0\n" + "beq .no_obj\n" + "str r0, [sp, #0]\n" // store to r0 on stack + "mov r0, #0\n" + "str r0, [r1]\n" // clear pendsv_object + "ldr r0, nlr_jump_ptr\n" + "str r0, [sp, #24]\n" // store to pc on stack + "bx lr\n" // return from interrupt; will return to nlr_jump + + ".no_obj:\n" // pendsv_object==NULL + "push {r4-r11, lr}\n" + "vpush {s16-s31}\n" + "mov r0, sp\n" // pass sp to save + "mov r4, lr\n" // save lr because we are making a call + "bl pyb_thread_next\n" // get next thread to execute + "mov lr, r4\n" // restore lr + "mov sp, r0\n" // switch stacks + "vpop {s16-s31}\n" + "pop {r4-r11, lr}\n" + "bx lr\n" // return from interrupt; will return to new thread + ".align 2\n" + "pendsv_object_ptr: .word pendsv_object\n" + "nlr_jump_ptr: .word nlr_jump\n" + ); +#else __asm volatile ( "ldr r0, pendsv_object_ptr\n" "ldr r0, [r0]\n" @@ -108,6 +137,7 @@ void pendsv_isr_handler(void) { "pendsv_object_ptr: .word pendsv_object\n" "nlr_jump_ptr: .word nlr_jump\n" ); +#endif /* uint32_t x[2] = {0x424242, 0xdeaddead}; diff --git a/stmhal/pybthread.c b/stmhal/pybthread.c new file mode 100644 index 000000000..9f9f82a45 --- /dev/null +++ b/stmhal/pybthread.c @@ -0,0 +1,97 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 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 +#include + +#include "py/obj.h" +#include "gccollect.h" +#include "irq.h" +#include "pybthread.h" + +#if MICROPY_PY_THREAD + +int pyb_thread_enabled; +pyb_thread_t *pyb_thread_cur; + +void pyb_thread_init(pyb_thread_t *thread) { + pyb_thread_cur = thread; + pyb_thread_cur->sp = NULL; // will be set when this thread switches out + pyb_thread_cur->local_state = 0; // will be set by mp_thread_init + pyb_thread_cur->arg = NULL; + pyb_thread_cur->stack = &_heap_end; + pyb_thread_cur->stack_len = ((uint32_t)&_estack - (uint32_t)&_heap_end) / sizeof(uint32_t); + pyb_thread_cur->prev = thread; + pyb_thread_cur->next = thread; +} + +STATIC void pyb_thread_terminate(void) { + uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + pyb_thread_cur->prev->next = pyb_thread_cur->next; + pyb_thread_cur->next->prev = pyb_thread_cur->prev; + if (pyb_thread_cur->next == pyb_thread_cur->prev) { + pyb_thread_enabled = 0; + } + restore_irq_pri(irq_state); + pyb_thread_yield(); // should not return +} + +uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, void *entry, void *arg) { + uint32_t *stack_top = (uint32_t*)stack + stack_len; // stack is full descending + *--stack_top = 0x01000000; // xPSR (thumb bit set) + *--stack_top = (uint32_t)entry & 0xfffffffe; // pc (must have bit 0 cleared, even for thumb code) + *--stack_top = (uint32_t)pyb_thread_terminate; // lr + *--stack_top = 0; // r12 + *--stack_top = 0; // r3 + *--stack_top = 0; // r2 + *--stack_top = 0; // r1 + *--stack_top = (uint32_t)arg; // r0 + *--stack_top = 0xfffffff9; // lr (return to thread mode, non-FP, use MSP) + stack_top -= 8; // r4-r11 + stack_top -= 16; // s16-s31 (we assume all threads use FP registers) + thread->sp = stack_top; + thread->local_state = 0; + thread->arg = arg; + thread->stack = stack; + thread->stack_len = stack_len; + uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + pyb_thread_enabled = 1; + thread->next = pyb_thread_cur->next; + thread->prev = pyb_thread_cur; + pyb_thread_cur->next->prev = thread; + pyb_thread_cur->next = thread; + restore_irq_pri(irq_state); + return (uint32_t)thread; // success +} + +// should only be called from pendsv_isr_handler +void *pyb_thread_next(void *sp) { + pyb_thread_cur->sp = sp; + pyb_thread_cur = pyb_thread_cur->next; + return pyb_thread_cur->sp; +} + +#endif // MICROPY_PY_THREAD diff --git a/stmhal/pybthread.h b/stmhal/pybthread.h new file mode 100644 index 000000000..d4310c66a --- /dev/null +++ b/stmhal/pybthread.h @@ -0,0 +1,62 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 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. + */ + +#ifndef MICROPY_INCLUDED_STMHAL_PYBTHREAD_H +#define MICROPY_INCLUDED_STMHAL_PYBTHREAD_H + +typedef struct _pyb_thread_t { + void *sp; + uint32_t local_state; + void *arg; // thread Python args, a GC root pointer + void *stack; // pointer to the stack + size_t stack_len; // number of words in the stack + struct _pyb_thread_t *prev; + struct _pyb_thread_t *next; +} pyb_thread_t; + +extern int pyb_thread_enabled; +extern pyb_thread_t *pyb_thread_cur; + +void pyb_thread_init(pyb_thread_t *th); +uint32_t pyb_thread_new(pyb_thread_t *th, void *stack, size_t stack_len, void *entry, void *arg); + +static inline uint32_t pyb_thread_get_id(void) { + return (uint32_t)pyb_thread_cur; +} + +static inline void pyb_thread_set_local(void *value) { + pyb_thread_cur->local_state = (uint32_t)value; +} + +static inline void *pyb_thread_get_local(void) { + return (void*)pyb_thread_cur->local_state; +} + +static inline void pyb_thread_yield(void) { + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; +} + +#endif // MICROPY_INCLUDED_STMHAL_PYBTHREAD_H diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c index e1129ac39..a6503d310 100644 --- a/stmhal/stm32_it.c +++ b/stmhal/stm32_it.c @@ -73,6 +73,7 @@ #include "py/obj.h" #include "pendsv.h" #include "irq.h" +#include "pybthread.h" #include "extint.h" #include "timer.h" #include "uart.h" @@ -287,6 +288,11 @@ void SysTick_Handler(void) { if (DMA_IDLE_ENABLED() && DMA_IDLE_TICK(uwTick)) { dma_idle_handler(uwTick); } + + // signal a thread switch at 4ms=250Hz + if (pyb_thread_enabled && (uwTick & 0x03) == 0x03) { + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + } } /******************************************************************************/ -- cgit v1.2.3 From 00e717662449cacdb2bc40988b12831749a7369b Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 31 Jan 2017 16:02:54 +1100 Subject: stmhal/main: Use _estack value to initialise stack extents. --- stmhal/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index 4ffa0d9ba..ebab88509 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -508,8 +508,8 @@ soft_reset: // Stack limit should be less than real stack size, so we have a chance // to recover from limit hit. (Limit is measured in bytes.) // Note: stack control relies on main thread being initialised above - mp_stack_ctrl_init(); - mp_stack_set_limit((char*)&_ram_end - (char*)&_heap_end - 1024); + mp_stack_set_top(&_estack); + mp_stack_set_limit((char*)&_estack - (char*)&_heap_end - 1024); // GC init gc_init(&_heap_start, &_heap_end); -- cgit v1.2.3 From 8e008449298d95addf6bd56f448b0d100b163399 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 31 Jan 2017 19:52:50 +1100 Subject: stmhal: Fix build issue when MICROPY_PY_THREAD is disabled. --- stmhal/main.c | 2 ++ stmhal/stm32_it.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index ebab88509..7bf6f6a3a 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -454,7 +454,9 @@ int main(void) { #endif // basic sub-system init + #if MICROPY_PY_THREAD pyb_thread_init(&pyb_thread_main); + #endif pendsv_init(); led_init(); #if MICROPY_HW_HAS_SWITCH diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c index a6503d310..4dddc5e0b 100644 --- a/stmhal/stm32_it.c +++ b/stmhal/stm32_it.c @@ -289,10 +289,12 @@ void SysTick_Handler(void) { dma_idle_handler(uwTick); } + #if MICROPY_PY_THREAD // signal a thread switch at 4ms=250Hz if (pyb_thread_enabled && (uwTick & 0x03) == 0x03) { SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; } + #endif } /******************************************************************************/ -- cgit v1.2.3 From 9779c99317f229435c07f11fd18223956de77b41 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 7 Feb 2017 12:35:39 +1100 Subject: stmhal: Add ability to skip booting from SD card via /flash/SKIPSD file. --- docs/pyboard/general.rst | 5 +++++ stmhal/main.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'stmhal/main.c') diff --git a/docs/pyboard/general.rst b/docs/pyboard/general.rst index 107bae69a..48e014644 100644 --- a/docs/pyboard/general.rst +++ b/docs/pyboard/general.rst @@ -11,6 +11,11 @@ is inserted into the slot, it is available as ``/sd``. When the pyboard boots up, it needs to choose a filesystem to boot from. If there is no SD card, then it uses the internal filesystem ``/flash`` as the boot filesystem, otherwise, it uses the SD card ``/sd``. +If needed, you can prevent the use of the SD card by creating an empty file +called ``/flash/SKIPSD``. If this file exists when the pyboard boots +up then the SD card will be skipped and the pyboard will always boot from the +internal filesystem (in this case the SD card won't be mounted but you can still +mount and use it later in your program using ``os.mount``). (Note that on older versions of the board, ``/flash`` is called ``0:/`` and ``/sd`` is called ``1:/``). diff --git a/stmhal/main.c b/stmhal/main.c index 7bf6f6a3a..7bfdc52c3 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -568,7 +568,10 @@ soft_reset: #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on /sd/ if (sdcard_is_present()) { - mounted_sdcard = init_sdcard_fs(first_soft_reset); + // if there is a file in the flash called "SKIPSD", then we don't mount the SD card + if (!mounted_flash || f_stat(&fs_user_mount_flash.fatfs, "/SKIPSD", NULL) != FR_OK) { + mounted_sdcard = init_sdcard_fs(first_soft_reset); + } } #endif -- cgit v1.2.3 From 05a4859585c4e0a55fca2e7467ba70da6453fdcb Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 6 Feb 2017 15:13:30 +1100 Subject: stmhal: Implement a proper thread scheduler. This patch changes the threading implementation from simple round-robin with busy waits on mutexs, to proper scheduling whereby threads that are waiting on a mutex are only scheduled when the mutex becomes available. --- stmhal/main.c | 4 ++ stmhal/modmachine.c | 5 ++ stmhal/mpconfigport.h | 14 ++++ stmhal/mpthreadport.c | 35 +--------- stmhal/mpthreadport.h | 14 +++- stmhal/pybthread.c | 179 +++++++++++++++++++++++++++++++++++++++++++------- stmhal/pybthread.h | 26 ++++++-- stmhal/stm32_it.c | 12 +++- stmhal/systick.c | 10 +++ 9 files changed, 236 insertions(+), 63 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index 7bfdc52c3..bcc429df2 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -695,6 +695,10 @@ soft_reset_exit: can_deinit(); #endif + #if MICROPY_PY_THREAD + pyb_thread_deinit(); + #endif + first_soft_reset = false; goto soft_reset; } diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c index 4a3fe1ec9..16c50079d 100644 --- a/stmhal/modmachine.c +++ b/stmhal/modmachine.c @@ -41,6 +41,7 @@ #include "extmod/vfs_fat.h" #include "gccollect.h" #include "irq.h" +#include "pybthread.h" #include "rng.h" #include "storage.h" #include "pin.h" @@ -159,6 +160,10 @@ STATIC mp_obj_t machine_info(mp_uint_t n_args, const mp_obj_t *args) { } } + #if MICROPY_PY_THREAD + pyb_thread_dump(); + #endif + if (n_args == 1) { // arg given means dump gc allocation table gc_dump_alloc_table(); diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 5828f07c7..38a5ac5da 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -299,7 +299,21 @@ static inline mp_uint_t disable_irq(void) { #define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq() #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) + +#if MICROPY_PY_THREAD +#define MICROPY_EVENT_POLL_HOOK \ + do { \ + if (pyb_thread_enabled) { \ + MP_THREAD_GIL_EXIT(); \ + pyb_thread_yield(); \ + MP_THREAD_GIL_ENTER(); \ + } else { \ + __WFI(); \ + } \ + } while (0); +#else #define MICROPY_EVENT_POLL_HOOK __WFI(); +#endif // There is no classical C heap in bare-metal ports, only Python // garbage-collected heap. For completeness, emulate C heap via diff --git a/stmhal/mpthreadport.c b/stmhal/mpthreadport.c index 97c19647c..d7c5b569b 100644 --- a/stmhal/mpthreadport.c +++ b/stmhal/mpthreadport.c @@ -44,15 +44,13 @@ void mp_thread_init(void) { void mp_thread_gc_others(void) { mp_thread_mutex_lock(&thread_mutex, 1); - gc_collect_root((void**)&pyb_thread_cur, 1); - for (pyb_thread_t *th = pyb_thread_cur;; th = th->next) { + for (pyb_thread_t *th = pyb_thread_all; th != NULL; th = th->all_next) { + gc_collect_root((void**)&th, 1); gc_collect_root(&th->arg, 1); + gc_collect_root(&th->stack, 1); if (th != pyb_thread_cur) { gc_collect_root(th->stack, th->stack_len); } - if (th->next == pyb_thread_cur) { - break; - } } mp_thread_mutex_unlock(&thread_mutex); } @@ -93,31 +91,4 @@ void mp_thread_start(void) { void mp_thread_finish(void) { } -void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { - *mutex = 0; -} - -int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { - uint32_t irq_state = disable_irq(); - if (*mutex) { - // mutex is locked - if (!wait) { - enable_irq(irq_state); - return 0; // failed to lock mutex - } - while (*mutex) { - enable_irq(irq_state); - pyb_thread_yield(); - irq_state = disable_irq(); - } - } - *mutex = 1; - enable_irq(irq_state); - return 1; // have mutex -} - -void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { - *mutex = 0; -} - #endif // MICROPY_PY_THREAD diff --git a/stmhal/mpthreadport.h b/stmhal/mpthreadport.h index 4fef323eb..3d8b4ef01 100644 --- a/stmhal/mpthreadport.h +++ b/stmhal/mpthreadport.h @@ -29,7 +29,7 @@ #include "py/mpthread.h" #include "pybthread.h" -typedef uint32_t mp_thread_mutex_t; +typedef pyb_mutex_t mp_thread_mutex_t; void mp_thread_init(void); void mp_thread_gc_others(void); @@ -42,4 +42,16 @@ static inline struct _mp_state_thread_t *mp_thread_get_state(void) { return pyb_thread_get_local(); } +static inline void mp_thread_mutex_init(mp_thread_mutex_t *m) { + pyb_mutex_init(m); +} + +static inline int mp_thread_mutex_lock(mp_thread_mutex_t *m, int wait) { + return pyb_mutex_lock(m, wait); +} + +static inline void mp_thread_mutex_unlock(mp_thread_mutex_t *m) { + pyb_mutex_unlock(m); +} + #endif // __MICROPY_INCLUDED_STMHAL_MPTHREADPORT_H__ diff --git a/stmhal/pybthread.c b/stmhal/pybthread.c index 9f9f82a45..51e9a738d 100644 --- a/stmhal/pybthread.c +++ b/stmhal/pybthread.c @@ -34,29 +34,80 @@ #if MICROPY_PY_THREAD -int pyb_thread_enabled; -pyb_thread_t *pyb_thread_cur; +#define PYB_MUTEX_UNLOCKED ((void*)0) +#define PYB_MUTEX_LOCKED ((void*)1) + +extern void __fatal_error(const char*); + +volatile int pyb_thread_enabled; +pyb_thread_t *volatile pyb_thread_all; +pyb_thread_t *volatile pyb_thread_cur; + +static inline void pyb_thread_add_to_runable(pyb_thread_t *thread) { + thread->run_prev = pyb_thread_cur->run_prev; + thread->run_next = pyb_thread_cur; + pyb_thread_cur->run_prev->run_next = thread; + pyb_thread_cur->run_prev = thread; +} + +static inline void pyb_thread_remove_from_runable(pyb_thread_t *thread) { + if (thread->run_next == thread) { + __fatal_error("deadlock"); + } + thread->run_prev->run_next = thread->run_next; + thread->run_next->run_prev = thread->run_prev; +} void pyb_thread_init(pyb_thread_t *thread) { + pyb_thread_enabled = 0; + pyb_thread_all = thread; pyb_thread_cur = thread; - pyb_thread_cur->sp = NULL; // will be set when this thread switches out - pyb_thread_cur->local_state = 0; // will be set by mp_thread_init - pyb_thread_cur->arg = NULL; - pyb_thread_cur->stack = &_heap_end; - pyb_thread_cur->stack_len = ((uint32_t)&_estack - (uint32_t)&_heap_end) / sizeof(uint32_t); - pyb_thread_cur->prev = thread; - pyb_thread_cur->next = thread; + thread->sp = NULL; // will be set when this thread switches out + thread->local_state = 0; // will be set by mp_thread_init + thread->arg = NULL; + thread->stack = &_heap_end; + thread->stack_len = ((uint32_t)&_estack - (uint32_t)&_heap_end) / sizeof(uint32_t); + thread->all_next = NULL; + thread->run_prev = thread; + thread->run_next = thread; + thread->queue_next = NULL; +} + +void pyb_thread_deinit() { + uint32_t irq_state = disable_irq(); + pyb_thread_enabled = 0; + pyb_thread_all = pyb_thread_cur; + pyb_thread_cur->all_next = NULL; + pyb_thread_cur->run_prev = pyb_thread_cur; + pyb_thread_cur->run_next = pyb_thread_cur; + enable_irq(irq_state); } STATIC void pyb_thread_terminate(void) { - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); - pyb_thread_cur->prev->next = pyb_thread_cur->next; - pyb_thread_cur->next->prev = pyb_thread_cur->prev; - if (pyb_thread_cur->next == pyb_thread_cur->prev) { + uint32_t irq_state = disable_irq(); + pyb_thread_t *thread = pyb_thread_cur; + // take current thread off the run list + pyb_thread_remove_from_runable(thread); + // take current thread off the list of all threads + for (pyb_thread_t **n = (pyb_thread_t**)&pyb_thread_all;; n = &(*n)->all_next) { + if (*n == thread) { + *n = thread->all_next; + break; + } + } + // clean pointers as much as possible to help GC + thread->all_next = NULL; + thread->queue_next = NULL; + thread->stack = NULL; + if (pyb_thread_all->all_next == NULL) { + // only 1 thread left pyb_thread_enabled = 0; } - restore_irq_pri(irq_state); - pyb_thread_yield(); // should not return + // thread switch will occur after we enable irqs + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + enable_irq(irq_state); + // should not return + __fatal_error("could not terminate"); } uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, void *entry, void *arg) { @@ -77,21 +128,105 @@ uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, voi thread->arg = arg; thread->stack = stack; thread->stack_len = stack_len; - uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV); + thread->queue_next = NULL; + uint32_t irq_state = disable_irq(); pyb_thread_enabled = 1; - thread->next = pyb_thread_cur->next; - thread->prev = pyb_thread_cur; - pyb_thread_cur->next->prev = thread; - pyb_thread_cur->next = thread; - restore_irq_pri(irq_state); + thread->all_next = pyb_thread_all; + pyb_thread_all = thread; + pyb_thread_add_to_runable(thread); + enable_irq(irq_state); return (uint32_t)thread; // success } +void pyb_thread_dump(void) { + if (!pyb_thread_enabled) { + printf("THREAD: only main thread\n"); + } else { + printf("THREAD:\n"); + for (pyb_thread_t *th = pyb_thread_all; th != NULL; th = th->all_next) { + bool runable = false; + for (pyb_thread_t *th2 = pyb_thread_cur;; th2 = th2->run_next) { + if (th == th2) { + runable = true; + break; + } + if (th2->run_next == pyb_thread_cur) { + break; + } + } + printf(" id=%p sp=%p sz=%u", th, th->stack, th->stack_len); + if (runable) { + printf(" (runable)"); + } + printf("\n"); + } + } +} + // should only be called from pendsv_isr_handler void *pyb_thread_next(void *sp) { pyb_thread_cur->sp = sp; - pyb_thread_cur = pyb_thread_cur->next; + pyb_thread_cur = pyb_thread_cur->run_next; + pyb_thread_cur->timeslice = 4; // in milliseconds return pyb_thread_cur->sp; } +void pyb_mutex_init(pyb_mutex_t *m) { + *m = PYB_MUTEX_UNLOCKED; +} + +int pyb_mutex_lock(pyb_mutex_t *m, int wait) { + uint32_t irq_state = disable_irq(); + if (*m == PYB_MUTEX_UNLOCKED) { + // mutex is available + *m = PYB_MUTEX_LOCKED; + enable_irq(irq_state); + } else { + // mutex is locked + if (!wait) { + enable_irq(irq_state); + return 0; // failed to lock mutex + } + if (*m == PYB_MUTEX_LOCKED) { + *m = pyb_thread_cur; + } else { + for (pyb_thread_t *n = *m;; n = n->queue_next) { + if (n->queue_next == NULL) { + n->queue_next = pyb_thread_cur; + break; + } + } + } + pyb_thread_cur->queue_next = NULL; + // take current thread off the run list + pyb_thread_remove_from_runable(pyb_thread_cur); + // thread switch will occur after we enable irqs + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + enable_irq(irq_state); + // when we come back we have the mutex + } + return 1; // have mutex +} + +void pyb_mutex_unlock(pyb_mutex_t *m) { + uint32_t irq_state = disable_irq(); + if (*m == PYB_MUTEX_LOCKED) { + // no threads are blocked on the mutex + *m = PYB_MUTEX_UNLOCKED; + } else { + // at least one thread is blocked on this mutex + pyb_thread_t *th = *m; + if (th->queue_next == NULL) { + // no other threads are blocked + *m = PYB_MUTEX_LOCKED; + } else { + // at least one other thread is still blocked + *m = th->queue_next; + } + // put unblocked thread on runable list + pyb_thread_add_to_runable(th); + } + enable_irq(irq_state); +} + #endif // MICROPY_PY_THREAD diff --git a/stmhal/pybthread.h b/stmhal/pybthread.h index d4310c66a..6edb2400e 100644 --- a/stmhal/pybthread.h +++ b/stmhal/pybthread.h @@ -33,15 +33,23 @@ typedef struct _pyb_thread_t { void *arg; // thread Python args, a GC root pointer void *stack; // pointer to the stack size_t stack_len; // number of words in the stack - struct _pyb_thread_t *prev; - struct _pyb_thread_t *next; + uint32_t timeslice; + struct _pyb_thread_t *all_next; + struct _pyb_thread_t *run_prev; + struct _pyb_thread_t *run_next; + struct _pyb_thread_t *queue_next; } pyb_thread_t; -extern int pyb_thread_enabled; -extern pyb_thread_t *pyb_thread_cur; +typedef pyb_thread_t *pyb_mutex_t; + +extern volatile int pyb_thread_enabled; +extern pyb_thread_t *volatile pyb_thread_all; +extern pyb_thread_t *volatile pyb_thread_cur; void pyb_thread_init(pyb_thread_t *th); +void pyb_thread_deinit(); uint32_t pyb_thread_new(pyb_thread_t *th, void *stack, size_t stack_len, void *entry, void *arg); +void pyb_thread_dump(void); static inline uint32_t pyb_thread_get_id(void) { return (uint32_t)pyb_thread_cur; @@ -56,7 +64,15 @@ static inline void *pyb_thread_get_local(void) { } static inline void pyb_thread_yield(void) { - SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + if (pyb_thread_cur->run_next == pyb_thread_cur) { + __WFI(); + } else { + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + } } +void pyb_mutex_init(pyb_mutex_t *m); +int pyb_mutex_lock(pyb_mutex_t *m, int wait); +void pyb_mutex_unlock(pyb_mutex_t *m); + #endif // MICROPY_INCLUDED_STMHAL_PYBTHREAD_H diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c index 4152050a9..d8fcc59ce 100644 --- a/stmhal/stm32_it.c +++ b/stmhal/stm32_it.c @@ -70,6 +70,7 @@ #include "stm32_it.h" #include STM32_HAL_H +#include "py/mpstate.h" #include "py/obj.h" #include "py/mphal.h" #include "pendsv.h" @@ -315,9 +316,14 @@ void SysTick_Handler(void) { } #if MICROPY_PY_THREAD - // signal a thread switch at 4ms=250Hz - if (pyb_thread_enabled && (uwTick & 0x03) == 0x03) { - SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + if (pyb_thread_enabled) { + if (pyb_thread_cur->timeslice == 0) { + if (pyb_thread_cur->run_next != pyb_thread_cur) { + SCB->ICSR = SCB_ICSR_PENDSVSET_Msk; + } + } else { + --pyb_thread_cur->timeslice; + } } #endif } diff --git a/stmhal/systick.c b/stmhal/systick.c index aed5b9690..ade05d74d 100644 --- a/stmhal/systick.c +++ b/stmhal/systick.c @@ -29,9 +29,11 @@ #include "py/obj.h" #include "irq.h" #include "systick.h" +#include "pybthread.h" // We provide our own version of HAL_Delay that calls __WFI while waiting, in // order to reduce power consumption. +// Note: Upon entering this function we may or may not have the GIL. void HAL_Delay(uint32_t Delay) { if (query_irq() == IRQ_STATE_ENABLED) { // IRQs enabled, so can use systick counter to do the delay @@ -40,7 +42,15 @@ void HAL_Delay(uint32_t Delay) { // Wraparound of tick is taken care of by 2's complement arithmetic. while (uwTick - start < Delay) { // Enter sleep mode, waiting for (at least) the SysTick interrupt. + #if MICROPY_PY_THREAD + if (pyb_thread_enabled) { + pyb_thread_yield(); + } else { + __WFI(); + } + #else __WFI(); + #endif } } else { // IRQs disabled, so need to use a busy loop for the delay. -- cgit v1.2.3 From c9b0f0b248ffc95545abc2347106fc3684d3c002 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 17 Feb 2017 13:07:42 +1100 Subject: stmhal/main: Remove unnecessary header includes. --- stmhal/main.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index bcc429df2..c6d482f3c 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -27,15 +27,10 @@ #include #include -#include "py/nlr.h" -#include "py/lexer.h" -#include "py/parse.h" -#include "py/obj.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" #include "py/mphal.h" - #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" -- cgit v1.2.3 From 6ab5512132d5b3d19a5bf029cb27829d41e76f8e Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 2 Mar 2017 15:02:57 +1100 Subject: stmhal: Use mp_hal_delay_ms instead of HAL_Delay. --- stmhal/accel.c | 6 +++--- stmhal/i2c.c | 2 +- stmhal/lcd.c | 6 +++--- stmhal/led.c | 2 +- stmhal/main.c | 24 ++++++++++++------------ stmhal/modmachine.c | 2 +- stmhal/modnwcc3k.c | 2 +- stmhal/modnwwiznet5k.c | 8 ++++---- stmhal/sdcard.c | 2 +- 9 files changed, 27 insertions(+), 27 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/accel.c b/stmhal/accel.c index 827e9177a..2e3504b06 100644 --- a/stmhal/accel.c +++ b/stmhal/accel.c @@ -76,9 +76,9 @@ STATIC void accel_start(void) { // turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again mp_hal_pin_low(&MICROPY_HW_MMA_AVDD_PIN); // turn off - HAL_Delay(30); + mp_hal_delay_ms(30); mp_hal_pin_high(&MICROPY_HW_MMA_AVDD_PIN); // turn on - HAL_Delay(30); + mp_hal_delay_ms(30); HAL_StatusTypeDef status; @@ -98,7 +98,7 @@ STATIC void accel_start(void) { status = HAL_I2C_Mem_Write(&I2CHandle1, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200); // wait for MMA to become active - HAL_Delay(30); + mp_hal_delay_ms(30); } /******************************************************************************/ diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 29c350d22..412a8e363 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -346,7 +346,7 @@ STATIC void i2c_reset_after_error(I2C_HandleTypeDef *i2c) { // stop bit was generated and bus is back to normal return; } - HAL_Delay(1); + mp_hal_delay_ms(1); } // bus was/is busy, need to reset the peripheral to get it to work again i2c_deinit(i2c); diff --git a/stmhal/lcd.c b/stmhal/lcd.c index e73b6e16d..cde6c36f6 100644 --- a/stmhal/lcd.c +++ b/stmhal/lcd.c @@ -274,11 +274,11 @@ STATIC mp_obj_t pyb_lcd_make_new(const mp_obj_type_t *type, size_t n_args, size_ mp_hal_pin_output(lcd->pin_bl); // init the LCD - HAL_Delay(1); // wait a bit + mp_hal_delay_ms(1); // wait a bit mp_hal_pin_low(lcd->pin_rst); // RST=0; reset - HAL_Delay(1); // wait for reset; 2us min + mp_hal_delay_ms(1); // wait for reset; 2us min mp_hal_pin_high(lcd->pin_rst); // RST=1; enable - HAL_Delay(1); // wait for reset; 2us min + mp_hal_delay_ms(1); // wait for reset; 2us min lcd_out(lcd, LCD_INSTR, 0xa0); // ADC select, normal lcd_out(lcd, LCD_INSTR, 0xc0); // common output mode select, normal (this flips the display) lcd_out(lcd, LCD_INSTR, 0xa2); // LCD bias set, 1/9 bias diff --git a/stmhal/led.c b/stmhal/led.c index 357aed407..be98aa4a4 100644 --- a/stmhal/led.c +++ b/stmhal/led.c @@ -275,7 +275,7 @@ void led_debug(int n, int delay) { led_state(2, n & 2); led_state(3, n & 4); led_state(4, n & 8); - HAL_Delay(delay); + mp_hal_delay_ms(delay); } /******************************************************************************/ diff --git a/stmhal/main.c b/stmhal/main.c index c6d482f3c..e07f6cf8c 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -71,10 +71,10 @@ void flash_error(int n) { for (int i = 0; i < n; i++) { led_state(PYB_LED_RED, 1); led_state(PYB_LED_GREEN, 0); - HAL_Delay(250); + mp_hal_delay_ms(250); led_state(PYB_LED_RED, 0); led_state(PYB_LED_GREEN, 1); - HAL_Delay(250); + mp_hal_delay_ms(250); } led_state(PYB_LED_GREEN, 0); } @@ -349,7 +349,7 @@ STATIC uint update_reset_mode(uint reset_mode) { if (!switch_get()) { break; } - HAL_Delay(20); + mp_hal_delay_ms(20); if (i % 30 == 29) { if (++reset_mode > 3) { reset_mode = 1; @@ -364,13 +364,13 @@ STATIC uint update_reset_mode(uint reset_mode) { led_state(2, 0); led_state(3, 0); led_state(4, 0); - HAL_Delay(50); + mp_hal_delay_ms(50); led_state(2, reset_mode & 1); led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); - HAL_Delay(50); + mp_hal_delay_ms(50); } - HAL_Delay(400); + mp_hal_delay_ms(400); #elif defined(MICROPY_HW_LED1) @@ -383,11 +383,11 @@ STATIC uint update_reset_mode(uint reset_mode) { break; } led_state(1, 1); - HAL_Delay(100); + mp_hal_delay_ms(100); led_state(1, 0); - HAL_Delay(200); + mp_hal_delay_ms(200); } - HAL_Delay(400); + mp_hal_delay_ms(400); if (!switch_get()) { break; } @@ -399,11 +399,11 @@ STATIC uint update_reset_mode(uint reset_mode) { for (uint i = 0; i < 2; i++) { for (uint j = 0; j < reset_mode; j++) { led_state(1, 1); - HAL_Delay(100); + mp_hal_delay_ms(100); led_state(1, 0); - HAL_Delay(200); + mp_hal_delay_ms(200); } - HAL_Delay(400); + mp_hal_delay_ms(400); } #else #error Need a reset mode update method diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c index 16c50079d..d615a0f2b 100644 --- a/stmhal/modmachine.c +++ b/stmhal/modmachine.c @@ -324,7 +324,7 @@ STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) { //printf("%lu %lu %lu %lu %lu\n", sysclk_source, m, n, p, q); // let the USB CDC have a chance to process before we change the clock - HAL_Delay(5); + mp_hal_delay_ms(5); // desired system clock source is in sysclk_source RCC_ClkInitTypeDef RCC_ClkInitStruct; diff --git a/stmhal/modnwcc3k.c b/stmhal/modnwcc3k.c index 19aeabf5c..753ab7528 100644 --- a/stmhal/modnwcc3k.c +++ b/stmhal/modnwcc3k.c @@ -120,7 +120,7 @@ STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uin if (retry == 0 || CC3000_EXPORT(errno) != -95) { return CC3000_EXPORT(errno); } - HAL_Delay(50); + mp_hal_delay_ms(50); } if (ip == 0) { diff --git a/stmhal/modnwwiznet5k.c b/stmhal/modnwwiznet5k.c index 04d37ccee..e3d5c6370 100644 --- a/stmhal/modnwwiznet5k.c +++ b/stmhal/modnwwiznet5k.c @@ -202,7 +202,7 @@ STATIC int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_ *_errno = MP_ENOTCONN; // ?? return -1; } - HAL_Delay(1); + mp_hal_delay_ms(1); } } @@ -348,9 +348,9 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size mp_hal_pin_output(wiznet5k_obj.rst); mp_hal_pin_low(wiznet5k_obj.rst); - HAL_Delay(1); // datasheet says 2us + mp_hal_delay_ms(1); // datasheet says 2us mp_hal_pin_high(wiznet5k_obj.rst); - HAL_Delay(160); // datasheet says 150ms + mp_hal_delay_ms(160); // datasheet says 150ms reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit); reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect); @@ -371,7 +371,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size ctlnetwork(CN_SET_NETINFO, (void*)&netinfo); // seems we need a small delay after init - HAL_Delay(250); + mp_hal_delay_ms(250); // register with network module mod_network_register_nic(&wiznet5k_obj); diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c index 6e9c46df5..c93b98b51 100644 --- a/stmhal/sdcard.c +++ b/stmhal/sdcard.c @@ -145,7 +145,7 @@ bool sdcard_power_on(void) { if (retry == 0) { goto error; } - HAL_Delay(50); + mp_hal_delay_ms(50); } // configure the SD bus width for wide operation -- cgit v1.2.3 From 8236d18338f6d8db25dcc5e81b176b006d56f39d Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 10 Mar 2017 19:02:20 +1100 Subject: stmhal/main: Allocate flash's VFS struct on the heap to trace root ptrs. --- stmhal/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'stmhal/main.c') diff --git a/stmhal/main.c b/stmhal/main.c index e07f6cf8c..3c9906ad2 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -65,7 +65,6 @@ void SystemClock_Config(void); pyb_thread_t pyb_thread_main; fs_user_mount_t fs_user_mount_flash; -mp_vfs_mount_t mp_vfs_mount_flash; void flash_error(int n) { for (int i = 0; i < n; i++) { @@ -219,12 +218,17 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { } else if (res == FR_OK) { // mount sucessful } else { + fail: printf("PYB: can't mount flash\n"); return false; } // mount the flash device (there should be no other devices mounted at this point) - mp_vfs_mount_t *vfs = &mp_vfs_mount_flash; + // we allocate this structure on the heap because vfs->next is a root pointer + mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t); + if (vfs == NULL) { + goto fail; + } vfs->str = "/flash"; vfs->len = 6; vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); -- cgit v1.2.3 From 12d0731b91d8e58ba20ec28adf2d6c1aa995d74a Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 10 Mar 2017 19:09:42 +1100 Subject: extmod/vfs_fat: Remove obsolete and unused str/len members. --- cc3200/mptask.c | 2 -- extmod/vfs_fat.c | 2 -- extmod/vfs_fat.h | 2 -- stmhal/main.c | 4 ---- 4 files changed, 10 deletions(-) (limited to 'stmhal/main.c') diff --git a/cc3200/mptask.c b/cc3200/mptask.c index 41264fbd0..3c49a5603 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -302,8 +302,6 @@ STATIC void mptask_init_sflash_filesystem (void) { // Initialise the local flash filesystem. // init the vfs object fs_user_mount_t *vfs_fat = sflash_vfs_fat; - vfs_fat->str = NULL; - vfs_fat->len = 0; vfs_fat->flags = 0; pyb_flash_init_vfs(vfs_fat); diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 82dd312b8..8cd5a4674 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -55,8 +55,6 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_ fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t); vfs->base.type = type; vfs->flags = FSUSER_FREE_OBJ; - vfs->str = NULL; - vfs->len = 0; vfs->fatfs.drv = vfs; // load block protocol methods diff --git a/extmod/vfs_fat.h b/extmod/vfs_fat.h index a5e3c604b..7eb865254 100644 --- a/extmod/vfs_fat.h +++ b/extmod/vfs_fat.h @@ -36,8 +36,6 @@ typedef struct _fs_user_mount_t { mp_obj_base_t base; - const char *str; - uint16_t len; // length of str uint16_t flags; mp_obj_t readblocks[4]; mp_obj_t writeblocks[4]; diff --git a/stmhal/main.c b/stmhal/main.c index 3c9906ad2..8d076a08b 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -167,8 +167,6 @@ static const char fresh_readme_txt[] = MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) { // init the vfs object fs_user_mount_t *vfs_fat = &fs_user_mount_flash; - vfs_fat->str = NULL; - vfs_fat->len = 0; vfs_fat->flags = 0; pyb_flash_init_vfs(vfs_fat); @@ -274,8 +272,6 @@ STATIC bool init_sdcard_fs(bool first_soft_reset) { if (vfs == NULL || vfs_fat == NULL) { break; } - vfs_fat->str = NULL; - vfs_fat->len = 0; vfs_fat->flags = FSUSER_FREE_OBJ; sdcard_init_vfs(vfs_fat, part_num); -- cgit v1.2.3 From b6c7e4b143d96ff9f84ccb22d83b1e15ab084250 Mon Sep 17 00:00:00 2001 From: Damien George Date: Fri, 31 Mar 2017 22:29:39 +1100 Subject: all: Use full path name when including mp-readline/timeutils/netutils. This follows the pattern of how all other headers are now included, and makes it explicit where the header file comes from. This patch also removes -I options from Makefile's that specify the mp-readline/timeutils/ netutils directories, which are no longer needed. --- cc3200/application.mk | 3 --- cc3200/ftp/ftp.c | 2 +- cc3200/mods/moduos.c | 2 +- cc3200/mods/modusocket.c | 2 +- cc3200/mods/modutime.c | 2 +- cc3200/mods/pybrtc.c | 2 +- cc3200/mptask.c | 2 +- esp8266/Makefile | 3 --- esp8266/fatfs_port.c | 2 +- esp8266/machine_rtc.c | 2 +- esp8266/modnetwork.c | 2 +- esp8266/modutime.c | 2 +- examples/embedding/Makefile.upylib | 1 - extmod/modlwip.c | 2 +- lib/mp-readline/readline.c | 2 +- lib/netutils/netutils.c | 2 +- lib/timeutils/timeutils.c | 2 +- minimal/Makefile | 1 - pic16bit/Makefile | 1 - pic16bit/main.c | 2 +- py/py.mk | 3 --- stmhal/Makefile | 3 --- stmhal/input.c | 2 +- stmhal/main.c | 2 +- stmhal/modnwcc3k.c | 2 +- stmhal/modnwwiznet5k.c | 2 +- stmhal/moduos.c | 2 +- stmhal/modusocket.c | 2 +- stmhal/modutime.c | 2 +- teensy/Makefile | 1 - teensy/main.c | 2 +- unix/Makefile | 1 - 32 files changed, 23 insertions(+), 40 deletions(-) (limited to 'stmhal/main.c') diff --git a/cc3200/application.mk b/cc3200/application.mk index b15dbde7f..5d25424e1 100644 --- a/cc3200/application.mk +++ b/cc3200/application.mk @@ -18,9 +18,6 @@ APP_INC += -Iutil APP_INC += -Ibootmgr APP_INC += -I$(BUILD) APP_INC += -I$(BUILD)/genhdr -APP_INC += -I../lib/mp-readline -APP_INC += -I../lib/netutils -APP_INC += -I../lib/timeutils APP_INC += -I../stmhal APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS diff --git a/cc3200/ftp/ftp.c b/cc3200/ftp/ftp.c index 22035d6b3..1febe291f 100644 --- a/cc3200/ftp/ftp.c +++ b/cc3200/ftp/ftp.c @@ -29,6 +29,7 @@ #include "py/mpstate.h" #include "py/obj.h" +#include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" @@ -48,7 +49,6 @@ #include "fifo.h" #include "socketfifo.h" #include "updater.h" -#include "timeutils.h" #include "moduos.h" /****************************************************************************** diff --git a/cc3200/mods/moduos.c b/cc3200/mods/moduos.c index 5523c887f..add10ec6c 100644 --- a/cc3200/mods/moduos.c +++ b/cc3200/mods/moduos.c @@ -33,6 +33,7 @@ #include "py/objtuple.h" #include "py/objstr.h" #include "py/runtime.h" +#include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "genhdr/mpversion.h" @@ -43,7 +44,6 @@ #include "random.h" #include "mpexception.h" #include "version.h" -#include "timeutils.h" #include "pybsd.h" #include "pybuart.h" diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c index 4e2da6737..ca28bf7ba 100644 --- a/cc3200/mods/modusocket.c +++ b/cc3200/mods/modusocket.c @@ -34,7 +34,7 @@ #include "py/objstr.h" #include "py/runtime.h" #include "py/stream.h" -#include "netutils.h" +#include "lib/netutils/netutils.h" #include "modnetwork.h" #include "modusocket.h" #include "mpexception.h" diff --git a/cc3200/mods/modutime.c b/cc3200/mods/modutime.c index 8e3c71402..48fde67e7 100644 --- a/cc3200/mods/modutime.c +++ b/cc3200/mods/modutime.c @@ -33,8 +33,8 @@ #include "py/obj.h" #include "py/smallint.h" #include "py/mphal.h" +#include "lib/timeutils/timeutils.h" #include "extmod/utime_mphal.h" -#include "timeutils.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" diff --git a/cc3200/mods/pybrtc.c b/cc3200/mods/pybrtc.c index 13d7a49cb..134bd440e 100644 --- a/cc3200/mods/pybrtc.c +++ b/cc3200/mods/pybrtc.c @@ -29,6 +29,7 @@ #include "py/obj.h" #include "py/runtime.h" #include "py/mperrno.h" +#include "lib/timeutils/timeutils.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" @@ -37,7 +38,6 @@ #include "pybrtc.h" #include "mpirq.h" #include "pybsleep.h" -#include "timeutils.h" #include "simplelink.h" #include "modnetwork.h" #include "modwlan.h" diff --git a/cc3200/mptask.c b/cc3200/mptask.c index 3c49a5603..d446711a2 100644 --- a/cc3200/mptask.c +++ b/cc3200/mptask.c @@ -33,6 +33,7 @@ #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" +#include "lib/mp-readline/readline.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs.h" @@ -51,7 +52,6 @@ #include "lib/utils/pyexec.h" #include "gccollect.h" #include "gchelper.h" -#include "readline.h" #include "mperror.h" #include "simplelink.h" #include "modnetwork.h" diff --git a/esp8266/Makefile b/esp8266/Makefile index 28dbf08a6..a3da9d398 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -25,9 +25,6 @@ ESP_SDK = $(shell $(CC) -print-sysroot)/usr INC += -I. INC += -I.. INC += -I../stmhal -INC += -I../lib/mp-readline -INC += -I../lib/netutils -INC += -I../lib/timeutils INC += -I$(BUILD) INC += -I$(ESP_SDK)/include diff --git a/esp8266/fatfs_port.c b/esp8266/fatfs_port.c index 20c3235d4..02384f605 100644 --- a/esp8266/fatfs_port.c +++ b/esp8266/fatfs_port.c @@ -25,8 +25,8 @@ */ #include "py/obj.h" +#include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" -#include "timeutils.h" #include "modmachine.h" DWORD get_fattime(void) { diff --git a/esp8266/machine_rtc.c b/esp8266/machine_rtc.c index 8c1fe0779..019b705ba 100644 --- a/esp8266/machine_rtc.c +++ b/esp8266/machine_rtc.c @@ -30,7 +30,7 @@ #include "py/nlr.h" #include "py/obj.h" #include "py/runtime.h" -#include "timeutils.h" +#include "lib/timeutils/timeutils.h" #include "user_interface.h" #include "modmachine.h" diff --git a/esp8266/modnetwork.c b/esp8266/modnetwork.c index 762717b35..627655b36 100644 --- a/esp8266/modnetwork.c +++ b/esp8266/modnetwork.c @@ -32,7 +32,7 @@ #include "py/objlist.h" #include "py/runtime.h" #include "py/mphal.h" -#include "netutils.h" +#include "lib/netutils/netutils.h" #include "queue.h" #include "user_interface.h" #include "espconn.h" diff --git a/esp8266/modutime.c b/esp8266/modutime.c index 117720e6f..bdeb3bb45 100644 --- a/esp8266/modutime.c +++ b/esp8266/modutime.c @@ -34,8 +34,8 @@ #include "py/runtime.h" #include "py/mphal.h" #include "py/smallint.h" +#include "lib/timeutils/timeutils.h" #include "modmachine.h" -#include "timeutils.h" #include "user_interface.h" #include "extmod/utime_mphal.h" diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib index 8b506e95e..873c0fd34 100644 --- a/examples/embedding/Makefile.upylib +++ b/examples/embedding/Makefile.upylib @@ -14,7 +14,6 @@ INC += -I. INC += -I.. INC += -I$(MPTOP) INC += -I$(MPTOP)/unix -#INC += -I../lib/timeutils INC += -I$(BUILD) # compiler settings diff --git a/extmod/modlwip.c b/extmod/modlwip.c index 5709413de..fffabb98a 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -36,7 +36,7 @@ #include "py/mperrno.h" #include "py/mphal.h" -#include "netutils.h" +#include "lib/netutils/netutils.h" #include "lwip/init.h" #include "lwip/timers.h" diff --git a/lib/mp-readline/readline.c b/lib/mp-readline/readline.c index cbb99cc94..4b9875136 100644 --- a/lib/mp-readline/readline.c +++ b/lib/mp-readline/readline.c @@ -31,7 +31,7 @@ #include "py/mpstate.h" #include "py/repl.h" #include "py/mphal.h" -#include "readline.h" +#include "lib/mp-readline/readline.h" #if 0 // print debugging info #define DEBUG_PRINT (1) diff --git a/lib/netutils/netutils.c b/lib/netutils/netutils.c index 3a4c600dc..a2ea31cf3 100644 --- a/lib/netutils/netutils.c +++ b/lib/netutils/netutils.c @@ -31,7 +31,7 @@ #include "py/obj.h" #include "py/nlr.h" -#include "netutils.h" +#include "lib/netutils/netutils.h" // Takes an array with a raw IPv4 address and returns something like '192.168.0.1'. mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian) { diff --git a/lib/timeutils/timeutils.c b/lib/timeutils/timeutils.c index 19d3ddbdd..0af39a295 100644 --- a/lib/timeutils/timeutils.c +++ b/lib/timeutils/timeutils.c @@ -27,7 +27,7 @@ #include "py/obj.h" -#include "timeutils.h" +#include "lib/timeutils/timeutils.h" // LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately // after Feb 29. We calculate seconds as a signed integer relative to that. diff --git a/minimal/Makefile b/minimal/Makefile index 3b446beae..d61515797 100644 --- a/minimal/Makefile +++ b/minimal/Makefile @@ -14,7 +14,6 @@ endif INC += -I. INC += -I.. -INC += -I../lib/mp-readline INC += -I../stmhal INC += -I$(BUILD) diff --git a/pic16bit/Makefile b/pic16bit/Makefile index add9a8495..8c0c1c999 100644 --- a/pic16bit/Makefile +++ b/pic16bit/Makefile @@ -14,7 +14,6 @@ PART = 33FJ256GP506 INC += -I. INC += -I.. -INC += -I../lib/mp-readline INC += -I../stmhal INC += -I$(BUILD) INC += -I$(XC16)/include diff --git a/pic16bit/main.c b/pic16bit/main.c index f2a9debab..7de790069 100644 --- a/pic16bit/main.c +++ b/pic16bit/main.c @@ -35,7 +35,7 @@ #include "py/mphal.h" #include "py/mperrno.h" #include "lib/utils/pyexec.h" -#include "readline.h" +#include "lib/mp-readline/readline.h" #include "board.h" #include "modpyb.h" diff --git a/py/py.mk b/py/py.mk index 37bb5d023..5ff1fd6a6 100644 --- a/py/py.mk +++ b/py/py.mk @@ -16,9 +16,6 @@ endif # some code is performance bottleneck and compiled with other optimization options CSUPEROPT = -O3 -INC += -I../lib -INC += -I../lib/netutils - # this sets the config file for FatFs CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" diff --git a/stmhal/Makefile b/stmhal/Makefile index 51aa07f3c..09643be94 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -47,9 +47,6 @@ INC += -I$(CMSIS_DIR)/ INC += -I$(HAL_DIR)/inc INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc #INC += -I$(USBHOST_DIR) -INC += -I../lib/mp-readline -INC += -I../lib/netutils -INC += -I../lib/timeutils CFLAGS_CORTEX_M = -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion CFLAGS_MCU_f4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -DMCU_SERIES_F4 diff --git a/stmhal/input.c b/stmhal/input.c index 07e7ba35c..c78525cc9 100644 --- a/stmhal/input.c +++ b/stmhal/input.c @@ -26,7 +26,7 @@ #include "py/nlr.h" #include "py/obj.h" -#include "readline.h" +#include "lib/mp-readline/readline.h" STATIC mp_obj_t mp_builtin_input(uint n_args, const mp_obj_t *args) { if (n_args == 1) { diff --git a/stmhal/main.c b/stmhal/main.c index 8d076a08b..566c2db07 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -31,6 +31,7 @@ #include "py/stackctrl.h" #include "py/gc.h" #include "py/mphal.h" +#include "lib/mp-readline/readline.h" #include "lib/utils/pyexec.h" #include "lib/oofatfs/ff.h" #include "extmod/vfs.h" @@ -40,7 +41,6 @@ #include "pendsv.h" #include "pybthread.h" #include "gccollect.h" -#include "readline.h" #include "modmachine.h" #include "i2c.h" #include "spi.h" diff --git a/stmhal/modnwcc3k.c b/stmhal/modnwcc3k.c index ae403cacd..26c6cd48c 100644 --- a/stmhal/modnwcc3k.c +++ b/stmhal/modnwcc3k.c @@ -37,7 +37,7 @@ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" -#include "netutils.h" +#include "lib/netutils/netutils.h" #include "modnetwork.h" #include "pin.h" #include "genhdr/pins.h" diff --git a/stmhal/modnwwiznet5k.c b/stmhal/modnwwiznet5k.c index e3d5c6370..b32f16913 100644 --- a/stmhal/modnwwiznet5k.c +++ b/stmhal/modnwwiznet5k.c @@ -33,7 +33,7 @@ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" -#include "netutils.h" +#include "lib/netutils/netutils.h" #include "modnetwork.h" #include "pin.h" #include "genhdr/pins.h" diff --git a/stmhal/moduos.c b/stmhal/moduos.c index 0af682612..745c0d5d7 100644 --- a/stmhal/moduos.c +++ b/stmhal/moduos.c @@ -31,12 +31,12 @@ #include "py/runtime.h" #include "py/objtuple.h" #include "py/objstr.h" +#include "lib/timeutils/timeutils.h" #include "lib/oofatfs/ff.h" #include "lib/oofatfs/diskio.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "genhdr/mpversion.h" -#include "timeutils.h" #include "rng.h" #include "uart.h" #include "portmodules.h" diff --git a/stmhal/modusocket.c b/stmhal/modusocket.c index d066501d0..fd60c5ad4 100644 --- a/stmhal/modusocket.c +++ b/stmhal/modusocket.c @@ -32,7 +32,7 @@ #include "py/objlist.h" #include "py/runtime.h" #include "py/mperrno.h" -#include "netutils.h" +#include "lib/netutils/netutils.h" #include "modnetwork.h" #if MICROPY_PY_USOCKET diff --git a/stmhal/modutime.c b/stmhal/modutime.c index 2c7245080..97af35c49 100644 --- a/stmhal/modutime.c +++ b/stmhal/modutime.c @@ -31,9 +31,9 @@ #include "py/nlr.h" #include "py/smallint.h" #include "py/obj.h" +#include "lib/timeutils/timeutils.h" #include "extmod/utime_mphal.h" #include "systick.h" -#include "timeutils.h" #include "portmodules.h" #include "rtc.h" diff --git a/teensy/Makefile b/teensy/Makefile index e613b8f27..9f52cc3c7 100644 --- a/teensy/Makefile +++ b/teensy/Makefile @@ -32,7 +32,6 @@ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -mfloat INC += -I. INC += -I.. INC += -I../stmhal -INC += -I../lib/mp-readline INC += -I$(BUILD) INC += -Icore diff --git a/teensy/main.c b/teensy/main.c index d62ae3bdb..41bbeb5d9 100644 --- a/teensy/main.c +++ b/teensy/main.c @@ -10,7 +10,7 @@ #include "py/mphal.h" #include "gccollect.h" #include "lib/utils/pyexec.h" -#include "readline.h" +#include "lib/mp-readline/readline.h" #include "lexermemzip.h" #include "Arduino.h" diff --git a/unix/Makefile b/unix/Makefile index f28a4bcae..546985306 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -17,7 +17,6 @@ include ../py/py.mk INC += -I. INC += -I.. -INC += -I../lib/timeutils INC += -I$(BUILD) # compiler settings -- cgit v1.2.3