mptask.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013, 2014 Damien P. George
  7. * Copyright (c) 2015 Daniel Campora
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include <stdint.h>
  28. #include "py/mpconfig.h"
  29. #include "py/stackctrl.h"
  30. #include "py/obj.h"
  31. #include "py/runtime.h"
  32. #include "py/gc.h"
  33. #include "py/mphal.h"
  34. #include "lib/mp-readline/readline.h"
  35. #include "lib/oofatfs/ff.h"
  36. #include "lib/oofatfs/diskio.h"
  37. #include "extmod/vfs.h"
  38. #include "extmod/vfs_fat.h"
  39. #include "inc/hw_memmap.h"
  40. #include "inc/hw_types.h"
  41. #include "inc/hw_ints.h"
  42. #include "inc/hw_memmap.h"
  43. #include "rom_map.h"
  44. #include "pin.h"
  45. #include "prcm.h"
  46. #include "interrupt.h"
  47. #include "pybuart.h"
  48. #include "pybpin.h"
  49. #include "pybrtc.h"
  50. #include "lib/utils/pyexec.h"
  51. #include "gccollect.h"
  52. #include "gchelper.h"
  53. #include "mperror.h"
  54. #include "simplelink.h"
  55. #include "modnetwork.h"
  56. #include "modusocket.h"
  57. #include "modwlan.h"
  58. #include "serverstask.h"
  59. #include "telnet.h"
  60. #include "debug.h"
  61. #include "sflash_diskio.h"
  62. #include "random.h"
  63. #include "pybi2c.h"
  64. #include "pins.h"
  65. #include "mods/pybflash.h"
  66. #include "pybsleep.h"
  67. #include "pybtimer.h"
  68. #include "cryptohash.h"
  69. #include "mpirq.h"
  70. #include "updater.h"
  71. #include "moduos.h"
  72. #include "antenna.h"
  73. #include "task.h"
  74. /******************************************************************************
  75. DECLARE PRIVATE CONSTANTS
  76. ******************************************************************************/
  77. /******************************************************************************
  78. DECLARE PRIVATE FUNCTIONS
  79. ******************************************************************************/
  80. STATIC void mptask_pre_init (void);
  81. STATIC void mptask_init_sflash_filesystem (void);
  82. STATIC void mptask_enter_ap_mode (void);
  83. STATIC void mptask_create_main_py (void);
  84. /******************************************************************************
  85. DECLARE PUBLIC DATA
  86. ******************************************************************************/
  87. #ifdef DEBUG
  88. OsiTaskHandle svTaskHandle;
  89. #endif
  90. /******************************************************************************
  91. DECLARE PRIVATE DATA
  92. ******************************************************************************/
  93. static fs_user_mount_t *sflash_vfs_fat;
  94. static const char fresh_main_py[] = "# main.py -- put your code here!\r\n";
  95. static const char fresh_boot_py[] = "# boot.py -- run on boot-up\r\n"
  96. "# can run arbitrary Python, but best to keep it minimal\r\n"
  97. #if MICROPY_STDIO_UART
  98. "import os, machine\r\n"
  99. "os.dupterm(machine.UART(0, " MP_STRINGIFY(MICROPY_STDIO_UART_BAUD) "))\r\n"
  100. #endif
  101. ;
  102. /******************************************************************************
  103. DECLARE PUBLIC FUNCTIONS
  104. ******************************************************************************/
  105. void TASK_MicroPython (void *pvParameters) {
  106. // get the top of the stack to initialize the garbage collector
  107. uint32_t sp = gc_helper_get_sp();
  108. bool safeboot = false;
  109. mptask_pre_init();
  110. #ifndef DEBUG
  111. safeboot = PRCMGetSpecialBit(PRCM_SAFE_BOOT_BIT);
  112. #endif
  113. soft_reset:
  114. // Thread init
  115. #if MICROPY_PY_THREAD
  116. mp_thread_init();
  117. #endif
  118. // initialise the stack pointer for the main thread (must be done after mp_thread_init)
  119. mp_stack_set_top((void*)sp);
  120. // GC init
  121. gc_init(&_boot, &_eheap);
  122. // MicroPython init
  123. mp_init();
  124. mp_obj_list_init(mp_sys_path, 0);
  125. mp_obj_list_init(mp_sys_argv, 0);
  126. mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
  127. // execute all basic initializations
  128. mp_irq_init0();
  129. pyb_sleep_init0();
  130. pin_init0();
  131. mperror_init0();
  132. uart_init0();
  133. timer_init0();
  134. readline_init0();
  135. mod_network_init0();
  136. rng_init0();
  137. pybsleep_reset_cause_t rstcause = pyb_sleep_get_reset_cause();
  138. if (rstcause < PYB_SLP_SOFT_RESET) {
  139. if (rstcause == PYB_SLP_HIB_RESET) {
  140. // when waking up from hibernate we just want
  141. // to enable simplelink and leave it as is
  142. wlan_first_start();
  143. }
  144. else {
  145. // only if not comming out of hibernate or a soft reset
  146. mptask_enter_ap_mode();
  147. }
  148. // enable telnet and ftp
  149. servers_start();
  150. }
  151. // initialize the serial flash file system
  152. mptask_init_sflash_filesystem();
  153. // append the flash paths to the system path
  154. mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash));
  155. mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash_slash_lib));
  156. // reset config variables; they should be set by boot.py
  157. MP_STATE_PORT(machine_config_main) = MP_OBJ_NULL;
  158. if (!safeboot) {
  159. // run boot.py
  160. int ret = pyexec_file("boot.py");
  161. if (ret & PYEXEC_FORCED_EXIT) {
  162. goto soft_reset_exit;
  163. }
  164. if (!ret) {
  165. // flash the system led
  166. mperror_signal_error();
  167. }
  168. }
  169. // now we initialise sub-systems that need configuration from boot.py,
  170. // or whose initialisation can be safely deferred until after running
  171. // boot.py.
  172. // at this point everything is fully configured and initialised.
  173. if (!safeboot) {
  174. // run the main script from the current directory.
  175. if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
  176. const char *main_py;
  177. if (MP_STATE_PORT(machine_config_main) == MP_OBJ_NULL) {
  178. main_py = "main.py";
  179. } else {
  180. main_py = mp_obj_str_get_str(MP_STATE_PORT(machine_config_main));
  181. }
  182. int ret = pyexec_file(main_py);
  183. if (ret & PYEXEC_FORCED_EXIT) {
  184. goto soft_reset_exit;
  185. }
  186. if (!ret) {
  187. // flash the system led
  188. mperror_signal_error();
  189. }
  190. }
  191. }
  192. // main script is finished, so now go into REPL mode.
  193. // the REPL mode can change, or it can request a soft reset.
  194. for ( ; ; ) {
  195. if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
  196. if (pyexec_raw_repl() != 0) {
  197. break;
  198. }
  199. } else {
  200. if (pyexec_friendly_repl() != 0) {
  201. break;
  202. }
  203. }
  204. }
  205. soft_reset_exit:
  206. // soft reset
  207. pyb_sleep_signal_soft_reset();
  208. mp_printf(&mp_plat_print, "PYB: soft reboot\n");
  209. // disable all callbacks to avoid undefined behaviour
  210. // when coming out of a soft reset
  211. mp_irq_disable_all();
  212. // cancel the RTC alarm which might be running independent of the irq state
  213. pyb_rtc_disable_alarm();
  214. // flush the serial flash buffer
  215. sflash_disk_flush();
  216. // clean-up the user socket space
  217. modusocket_close_all_user_sockets();
  218. // unmount all user file systems
  219. osmount_unmount_all();
  220. // wait for pending transactions to complete
  221. mp_hal_delay_ms(20);
  222. goto soft_reset;
  223. }
  224. /******************************************************************************
  225. DEFINE PRIVATE FUNCTIONS
  226. ******************************************************************************/
  227. __attribute__ ((section (".boot")))
  228. STATIC void mptask_pre_init (void) {
  229. // this one only makes sense after a poweron reset
  230. pyb_rtc_pre_init();
  231. // Create the simple link spawn task
  232. ASSERT (OSI_OK == VStartSimpleLinkSpawnTask(SIMPLELINK_SPAWN_TASK_PRIORITY));
  233. // Allocate memory for the flash file system
  234. ASSERT ((sflash_vfs_fat = mem_Malloc(sizeof(*sflash_vfs_fat))) != NULL);
  235. // this one allocates memory for the nvic vault
  236. pyb_sleep_pre_init();
  237. // this one allocates memory for the WLAN semaphore
  238. wlan_pre_init();
  239. // this one allocates memory for the updater semaphore
  240. updater_pre_init();
  241. // this one allocates memory for the socket semaphore
  242. modusocket_pre_init();
  243. //CRYPTOHASH_Init();
  244. #ifndef DEBUG
  245. OsiTaskHandle svTaskHandle;
  246. #endif
  247. svTaskHandle = xTaskCreateStatic(TASK_Servers, "Servers",
  248. SERVERS_STACK_LEN, NULL, SERVERS_PRIORITY, svTaskStack, &svTaskTCB);
  249. ASSERT(svTaskHandle != NULL);
  250. }
  251. STATIC void mptask_init_sflash_filesystem (void) {
  252. FILINFO fno;
  253. // Initialise the local flash filesystem.
  254. // init the vfs object
  255. fs_user_mount_t *vfs_fat = sflash_vfs_fat;
  256. vfs_fat->flags = 0;
  257. pyb_flash_init_vfs(vfs_fat);
  258. // Create it if needed, and mount in on /flash.
  259. FRESULT res = f_mount(&vfs_fat->fatfs);
  260. if (res == FR_NO_FILESYSTEM) {
  261. // no filesystem, so create a fresh one
  262. uint8_t working_buf[_MAX_SS];
  263. res = f_mkfs(&vfs_fat->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf));
  264. if (res == FR_OK) {
  265. // success creating fresh LFS
  266. } else {
  267. __fatal_error("failed to create /flash");
  268. }
  269. // create empty main.py
  270. mptask_create_main_py();
  271. } else if (res == FR_OK) {
  272. // mount sucessful
  273. if (FR_OK != f_stat(&vfs_fat->fatfs, "/main.py", &fno)) {
  274. // create empty main.py
  275. mptask_create_main_py();
  276. }
  277. } else {
  278. fail:
  279. __fatal_error("failed to create /flash");
  280. }
  281. // mount the flash device (there should be no other devices mounted at this point)
  282. // we allocate this structure on the heap because vfs->next is a root pointer
  283. mp_vfs_mount_t *vfs = m_new_obj_maybe(mp_vfs_mount_t);
  284. if (vfs == NULL) {
  285. goto fail;
  286. }
  287. vfs->str = "/flash";
  288. vfs->len = 6;
  289. vfs->obj = MP_OBJ_FROM_PTR(vfs_fat);
  290. vfs->next = NULL;
  291. MP_STATE_VM(vfs_mount_table) = vfs;
  292. // The current directory is used as the boot up directory.
  293. // It is set to the internal flash filesystem by default.
  294. MP_STATE_PORT(vfs_cur) = vfs;
  295. // create /flash/sys, /flash/lib and /flash/cert if they don't exist
  296. if (FR_OK != f_chdir(&vfs_fat->fatfs, "/sys")) {
  297. f_mkdir(&vfs_fat->fatfs, "/sys");
  298. }
  299. if (FR_OK != f_chdir(&vfs_fat->fatfs, "/lib")) {
  300. f_mkdir(&vfs_fat->fatfs, "/lib");
  301. }
  302. if (FR_OK != f_chdir(&vfs_fat->fatfs, "/cert")) {
  303. f_mkdir(&vfs_fat->fatfs, "/cert");
  304. }
  305. f_chdir(&vfs_fat->fatfs, "/");
  306. // make sure we have a /flash/boot.py. Create it if needed.
  307. res = f_stat(&vfs_fat->fatfs, "/boot.py", &fno);
  308. if (res == FR_OK) {
  309. if (fno.fattrib & AM_DIR) {
  310. // exists as a directory
  311. // TODO handle this case
  312. // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation
  313. } else {
  314. // exists as a file, good!
  315. }
  316. } else {
  317. // doesn't exist, create fresh file
  318. FIL fp;
  319. f_open(&vfs_fat->fatfs, &fp, "/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
  320. UINT n;
  321. f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n);
  322. // TODO check we could write n bytes
  323. f_close(&fp);
  324. }
  325. }
  326. STATIC void mptask_enter_ap_mode (void) {
  327. // append the mac only if it's not the first boot
  328. bool add_mac = !PRCMGetSpecialBit(PRCM_FIRST_BOOT_BIT);
  329. // enable simplelink in ap mode (use the MAC address to make the ssid unique)
  330. wlan_sl_init (ROLE_AP, MICROPY_PORT_WLAN_AP_SSID, strlen(MICROPY_PORT_WLAN_AP_SSID),
  331. MICROPY_PORT_WLAN_AP_SECURITY, MICROPY_PORT_WLAN_AP_KEY, strlen(MICROPY_PORT_WLAN_AP_KEY),
  332. MICROPY_PORT_WLAN_AP_CHANNEL, ANTENNA_TYPE_INTERNAL, add_mac);
  333. }
  334. STATIC void mptask_create_main_py (void) {
  335. // create empty main.py
  336. FIL fp;
  337. f_open(&sflash_vfs_fat->fatfs, &fp, "/main.py", FA_WRITE | FA_CREATE_ALWAYS);
  338. UINT n;
  339. f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n);
  340. f_close(&fp);
  341. }