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