1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <aos/errno.h>
8 #include <aos/kernel.h>
9 #include <stdarg.h>
10 // #include "aos/init.h"
11 // #include "board.h"
12 #include "ulog/ulog.h"
13 #include "amp_task.h"
14
15 #include <aos/kernel.h>
16
17 #include "py/compile.h"
18 #include "py/runtime.h"
19 #include "py/repl.h"
20 #include "py/gc.h"
21 #include "py/mperrno.h"
22 #include "shared/runtime/pyexec.h"
23 #include "py/mphal.h"
24 #include "py/stackctrl.h"
25
26 #include "sys/stat.h"
27 #include "aos/vfs.h"
28 #include "py_defines.h"
29
30 #if AOS_COMP_CLI
31 #include "aos/cli.h"
32 #endif
33 #include "miniunz.h"
34 #include "haas_main.h"
35 #include "mpsalport.h"
36
37 #define LOG_TAG "HAAS-MAIN"
38
39 static char *stack_top = NULL;
40
41 #if MICROPY_ENABLE_GC
42 static char *heap = NULL;
43 #ifndef MICROPY_GC_HEAP_SIZE
44 #define MICROPY_GC_HEAP_SIZE (1024 * 64)
45 #endif
46 #endif
47
alloc_mpy_thread_args(int argc,char ** argv)48 static mpy_thread_args *alloc_mpy_thread_args(int argc, char **argv)
49 {
50 mpy_thread_args *temp_args = (mpy_thread_args *)calloc(1, sizeof(mpy_thread_args));
51 if (temp_args == NULL) {
52 LOGE(LOG_TAG, "%s;malloc mpy_thread_args failed\n", __func__);
53 return NULL;
54 }
55
56 if (argc == 0) {
57 temp_args->is_bootup = true;
58 temp_args->argc = 2;
59 } else {
60 temp_args->is_bootup = false;
61 temp_args->argc = argc;
62 }
63
64 temp_args->argv = (char **)calloc(1, sizeof(char *) * temp_args->argc);
65 if (temp_args->argv == NULL) {
66 LOGE(LOG_TAG, "%s:temp_args->argv alloc memory failed\n", __func__);
67 free(temp_args);
68 return NULL;
69 }
70
71 for (int i = 0; i < argc; i++) {
72 temp_args->argv[i] = strdup(argv[i]);
73 }
74
75 return temp_args;
76 }
77
free_mpy_thread_args(mpy_thread_args * args)78 static int free_mpy_thread_args(mpy_thread_args *args)
79 {
80 if (args == NULL) {
81 LOGE(LOG_TAG, "args is illegal\n");
82 return -1;
83 }
84
85 for (int i = 0; i < args->argc; i++) {
86 if (args->argv[i] != NULL) {
87 free(args->argv[i]);
88 }
89 }
90
91 free(args->argv);
92 free(args);
93 return 0;
94 }
95
python_entry(void * p)96 static void python_entry(void *p)
97 {
98 mpy_thread_args *args = (mpy_thread_args *)p;
99 if (args == NULL) {
100 LOGE(LOG_TAG, "%s:args is illegal\n", __func__);
101 return;
102 }
103
104 aos_set_log_level(AOS_LL_ERROR);
105 // check borad cli mode
106 // haas600 and haas510 not support cli mode
107 args->board_cli_support = true;
108 mpy_init(args);
109 if(args->board_cli_support == false) {
110 printf("Devices not support cli, inter repl mode!\n");
111 free_mpy_thread_args(args);
112 args = NULL;
113 }
114
115 // run python thread
116 if(args == NULL) {
117 printf("Inter repl mode! \n");
118 mpy_run(0, NULL);
119 } else {
120 printf("Inter Cli mode!\n");
121 mpy_run(args->argc, args->argv);
122 }
123 mpy_deinit();
124
125 if(args != NULL) {
126 free_mpy_thread_args(args);
127 args = NULL;
128 }
129 }
130
python_task(void * p)131 static void python_task(void *p)
132 {
133 printf("********AOS_PY_MSG******\r\n");
134
135 printf("*************start*******\r\n");
136 py_task_init();
137 printf("*************end*******\r\n");
138
139 while (1) {
140 /* loop for asynchronous operation */
141 if(py_task_yield(200) == 1) {
142 printf("pyengine task yield exit! \r\n");
143 break;
144 }
145 }
146 aos_task_exit(0);
147
148 }
149
haas_main(int argc,char ** argv)150 void haas_main(int argc, char **argv)
151 {
152 mp_sal_taskhandler_obj_t python_task_obj;
153 mp_sal_taskhandler_obj_t python_entry_obj;
154 void *stack_addr = NULL;
155
156 printf(" Welcome to MicroPython\n");
157
158 #if PY_BUILD_BOOT
159 pyamp_boot_main();
160 #endif
161
162 mpy_thread_args *args = alloc_mpy_thread_args(argc, argv);
163
164 if (mp_sal_task_create(&python_task_obj, python_task, (void *)args, stack_addr, 1024 * 20, AOS_DEFAULT_APP_PRI, "python_engine_task") != 0)
165 {
166 printf("Error: Failed to create python entry thread.\r\n");
167 goto init_err;
168 }
169
170 // haas600 and haas510 need init uart input
171 mp_hal_uart_init();
172 //
173 if (mp_sal_task_create(&python_entry_obj, python_entry, (void *)args, stack_addr, 1024 * 20, AOS_DEFAULT_APP_PRI, "python_entry") != 0)
174 {
175 printf("Error: Failed to create python entry thread.\r\n");
176 goto init_err;
177 }
178
179 return;
180
181 init_err:
182 if (args != NULL)
183 {
184 free_mpy_thread_args(args);
185 args = NULL;
186 }
187
188 return;
189 }
190
handle_unzip_cmd(int argc,char ** argv)191 static void handle_unzip_cmd(int argc, char **argv)
192 {
193 char *zippath ;
194 char *destpath ;
195 int ret = 0 ;
196 if(argc < 2) {
197 LOGE(LOG_TAG, "Error params,Usage: unzip /data/src.zip /sdcard \r\n");
198 return ;
199 }
200
201 if(argc == 2) {
202 destpath ="/data";
203 }else {
204 destpath = argv[2] ;
205 }
206 zippath = argv[1] ;
207 ret = miniUnzip(zippath,destpath);
208 if(ret) {
209 LOGE(LOG_TAG, "unzip failed ,errno is %d \r\n",ret);
210 }else {
211 LOGD(LOG_TAG, "unzip succeed \r\n");
212 }
213 }
214
215 #if MICROPY_ENABLE_COMPILER
do_str(const char * src,mp_parse_input_kind_t input_kind)216 void do_str(const char *src, mp_parse_input_kind_t input_kind) {
217 nlr_buf_t nlr;
218 if (nlr_push(&nlr) == 0) {
219 mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
220 qstr source_name = lex->source_name;
221 mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
222 mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true);
223 mp_call_function_0(module_fun);
224 nlr_pop();
225 } else {
226 // uncaught exception
227 mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
228 }
229 }
230 #endif
231
mpy_init(mpy_thread_args * args)232 int mpy_init(mpy_thread_args *args)
233 {
234 uint32_t stack_size = 1024;
235
236 #if MICROPY_PY_THREAD
237 void *stack_addr = mp_sal_get_stack_addr();
238 stack_size = mp_sal_get_stack_size();
239 mp_thread_init(stack_addr, stack_size);
240 #endif
241
242 mp_stack_set_top(stack_top);
243
244 // adjust the stack_size to provide room to recover from hitting the limit
245 #if MICROPY_STACK_CHECK
246 mp_stack_ctrl_init();
247 mp_stack_set_limit(stack_size * sizeof(cpu_stack_t) - 1024);
248 #endif
249
250 #if MICROPY_ENABLE_GC
251 heap = (char *)malloc(MICROPY_GC_HEAP_SIZE);
252 if(NULL == heap){
253 printf("mpy_main:heap alloc fail!\r\n");
254 return -1;
255 }
256 gc_init(heap, heap + MICROPY_GC_HEAP_SIZE);
257 #endif
258
259 mp_init();
260
261 /*set default mp_sys_path*/
262 mp_obj_list_init(mp_sys_path, 0);
263 mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
264
265 char *path_root = MP_FS_ROOT_DIR"/lib/micropython";
266 mp_obj_list_append(mp_sys_path, mp_obj_new_str_via_qstr(path_root, strlen(path_root)));
267
268 char *path_sdcard = "/sdcard/lib/micropython";
269 mp_obj_list_append(mp_sys_path, mp_obj_new_str_via_qstr(path_sdcard, strlen(path_sdcard)));
270
271 mp_obj_list_init(mp_sys_argv, 0);
272
273 if(args->is_bootup == true) {
274 FILE *fd = fopen(AMP_PY_ENTRY_DEFAULE, "r");
275 if( fd != NULL) {
276 args->argc = 2;
277 args->argv[0] = strdup("python");
278 args->argv[1] = strdup(AMP_PY_ENTRY_DEFAULE);
279 printf(" ==== python execute main.py from sdcard ====\n");
280 fclose(fd);
281 } else {
282 fd = fopen(AMP_PY_ENTRY_BAK, "r");
283 if( fd != NULL) {
284 args->argc = 2;
285 args->argv[0] = strdup("python");
286 args->argv[1] = strdup(AMP_PY_ENTRY_BAK);
287 printf(" ==== python execute main.py from data ====\n");
288 fclose(fd);
289 } else {
290 args->board_cli_support = false;
291 }
292 }
293 }
294 return 0 ;
295 }
296
mpy_deinit(void)297 int mpy_deinit(void)
298 {
299 // need relese python run mem
300 #if MICROPY_ENABLE_GC
301 if(NULL != heap){
302 // printf("free python heap mm\r\n");
303 free(heap);
304 heap == NULL;
305 }
306 #endif
307 }
308
set_sys_argv(char * argv[],int argc,int start_arg)309 static void set_sys_argv(char *argv[], int argc, int start_arg) {
310 for (int i = start_arg; i < argc; i++) {
311 mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
312 }
313 }
314
mpy_run(int argc,char * argv[])315 int mpy_run(int argc, char *argv[]) {
316
317 if (argc >= 2) {
318 char *filename = argv[1] ;
319 char filepath[256] = {0};
320
321 if(filename[0] != '/') {
322 // getcwd(filepath, sizeof(filepath));
323 strcat(filepath, "/");
324 strcat(filepath, filename);
325 } else {
326 strcpy(filepath, filename);
327 }
328
329 char *p = strrchr(filepath, '/');
330
331 size_t len = 0;
332 mp_obj_t *path_items = NULL;
333 mp_obj_list_get(mp_sys_path, &len, &path_items);
334
335 if(p >= filepath) {
336 path_items[0] = mp_obj_new_str_via_qstr(filepath, p - filepath);
337 } else {
338 path_items[0] = mp_obj_new_str_via_qstr(filepath, filepath - p);
339 }
340
341 set_sys_argv(argv, argc, 1);
342
343 if (filepath != NULL) {
344 pyexec_file(filepath);
345 }
346 } else {
347 for (;;) {
348 if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
349 if (pyexec_raw_repl() != 0) {
350 break;
351 }
352 } else {
353 if (pyexec_friendly_repl() != 0) {
354 break;
355 }
356 }
357 }
358 }
359 mp_deinit();
360 return 0;
361 }
362
mp_lexer_new_from_file(const char * filename)363 MP_WEAK mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
364 mp_raise_OSError(MP_ENOENT);
365 }
366
mp_import_stat(const char * path)367 mp_import_stat_t mp_import_stat(const char *path) {
368 int len;
369 char * sys_path;
370 struct aos_stat pst;
371 int32_t ret;
372
373 if(NULL == path){
374 return MP_IMPORT_STAT_NO_EXIST;
375 }
376
377 ret = aos_stat(path, &pst);
378 if(0 == ret){
379 if(pst.st_mode & S_IFDIR){
380 return MP_IMPORT_STAT_DIR;
381 }else{
382 return MP_IMPORT_STAT_FILE;
383 }
384 }
385
386 return MP_IMPORT_STAT_NO_EXIST;
387 }
388
mp_builtin_open(size_t n_args,const mp_obj_t * args,mp_map_t * kwargs)389 mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
390 ) {
391 return mp_const_none;
392 }
393 MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
394
nlr_jump_fail(void * val)395 void nlr_jump_fail(void *val) {
396 while (1);
397 }
398
__fatal_error(const char * msg)399 void NORETURN __fatal_error(const char *msg) {
400 while (1);
401 }
402
403 #ifndef NDEBUG
__assert_func(const char * file,int line,const char * func,const char * expr)404 void MP_WEAK __assert_func(const char *file, int line, const char *func,
405 const char *expr) {
406 printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
407 __fatal_error("Assertion failed");
408 }
409 #endif
410
411
412
413
DEBUG_printf(const char * fmt,...)414 int DEBUG_printf(const char *fmt, ...)
415 {
416 va_list args;
417
418 va_start(args, fmt);
419 int ret = vprintf(fmt, args);
420 va_end(args);
421
422 fflush(stdout);
423
424 return ret;
425 }
426
427 #ifdef AOS_COMP_CLI
428 /* reg args: fun, cmd, description*/
429 ALIOS_CLI_CMD_REGISTER(haas_main, python, start micropython)
430 ALIOS_CLI_CMD_REGISTER(handle_unzip_cmd, unzip, start unzip)
431 #endif
432