summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/main.c')
-rw-r--r--stmhal/main.c285
1 files changed, 171 insertions, 114 deletions
diff --git a/stmhal/main.c b/stmhal/main.c
index 78afe54ef6..566c2db07f 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -27,23 +27,20 @@
#include <stdio.h>
#include <string.h>
-#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/mp-readline/readline.h"
#include "lib/utils/pyexec.h"
-#include "lib/fatfs/ff.h"
-#include "extmod/fsusermount.h"
+#include "lib/oofatfs/ff.h"
+#include "extmod/vfs.h"
+#include "extmod/vfs_fat.h"
#include "systick.h"
#include "pendsv.h"
+#include "pybthread.h"
#include "gccollect.h"
-#include "readline.h"
#include "modmachine.h"
#include "i2c.h"
#include "spi.h"
@@ -66,18 +63,19 @@
void SystemClock_Config(void);
+pyb_thread_t pyb_thread_main;
fs_user_mount_t fs_user_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);
- HAL_Delay(250);
- led_state(PYB_LED_R1, 0);
- led_state(PYB_LED_R2, 1);
- HAL_Delay(250);
+ led_state(PYB_LED_RED, 1);
+ led_state(PYB_LED_GREEN, 0);
+ mp_hal_delay_ms(250);
+ led_state(PYB_LED_RED, 0);
+ led_state(PYB_LED_GREEN, 1);
+ mp_hal_delay_ms(250);
}
- led_state(PYB_LED_R2, 0);
+ led_state(PYB_LED_GREEN, 0);
}
void NORETURN __fatal_error(const char *msg) {
@@ -166,96 +164,91 @@ 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 = &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->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
// 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();
- 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;
+ return false;
}
// 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);
// 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 {
+ fail:
printf("PYB: can't mount flash\n");
- MP_STATE_PORT(fs_user_mount)[0] = NULL;
- return;
+ return false;
+ }
+
+ // mount the flash device (there should be no other devices mounted at this point)
+ // 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);
+ 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
- led_state(PYB_LED_R2, 1);
+ led_state(PYB_LED_GREEN, 1);
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, "/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
@@ -263,9 +256,87 @@ 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);
+ }
+
+ 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) {
+ // 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->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_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");
+ return false;
+ } else {
+ return true;
}
}
+#endif
STATIC uint update_reset_mode(uint reset_mode) {
#if MICROPY_HW_HAS_SWITCH
@@ -278,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;
@@ -293,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)
@@ -312,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;
}
@@ -328,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
@@ -345,11 +416,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
@@ -383,6 +449,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
@@ -428,6 +497,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_set_top(&_estack);
+ mp_stack_set_limit((char*)&_estack - (char*)&_heap_end - 1024);
+
// GC init
gc_init(&_heap_start, &_heap_end);
@@ -435,8 +515,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
@@ -479,53 +557,28 @@ 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()) {
- // create vfs object
- fs_user_mount_t *vfs = m_new_obj_maybe(fs_user_mount_t);
- if (vfs == NULL) {
- goto no_mem_for_sd;
+ // 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);
}
- 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;
-
- FRESULT res = f_mount(&vfs->fatfs, vfs->str, 1);
- 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);
- } else {
- // 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
- f_chdrive("/sd");
- }
- }
- no_mem_for_sd:;
+ // 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));
}
-#endif
// reset config variables; they should be set by boot.py
MP_STATE_PORT(pyb_config_main) = MP_OBJ_NULL;
@@ -534,8 +587,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 +650,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;
@@ -637,6 +690,10 @@ soft_reset_exit:
can_deinit();
#endif
+ #if MICROPY_PY_THREAD
+ pyb_thread_deinit();
+ #endif
+
first_soft_reset = false;
goto soft_reset;
}