MicroPython是运行在微控制器上的Python。遵守MIT协议。由剑桥大学的理论物理学家乔治·达明设计。
MicroPython的软件特点
Python 3 语法。
完整的Python词法分析器、解析器、编译器、虚拟机和运行时。
包含命令行接口,可离线运行。
Python 字节码由内置虚拟机编译运行。
有效的内部存储算法,能带来高效的内存利用率。整数变量存储在内存堆中,而不是栈中。
使用Python decorators特性,函数可以被编译成原生机器码,虽然这一特性会带来大约2倍的内存消耗,但也使python有更快的执行速度。
函数编译可设置使用底层整数代替python内建对象作为数字使用。有些代码的运行效率可以媲美c的效率,并且可以被python直接调用,适合做时间紧迫性,运算复杂度高的应用。
通过内联汇编功能,应用可以完全接入底层运行时,内联汇编器也可以像普通的python函数一样调用。
基于简单和快速标记的内存垃圾回收算法,运行周期少于4ms,许多函数都可以避免使用栈内存段,因此也不需要垃圾回收功能。
源码分析
MicroPython实现了基本的python的词法分析器, 解析器,编译器,虚拟机和运行时。在github上获得代码:https://github.com/micropython/micropython
解压之后目录大概如下:
主要目录的解释也可在根目录的README.md中找到。
本文以STM32 MicroPython为例。目前MicroPython可运行于类unix系统,PIC16,ARM等平台。
首先,需要了解Python的运行机制,可以参考:http://tech.uc.cn/?p=1932。
然后,micropython-master\py目录下个人认为是最核心的发动机,也就是MicroPython的实现,C语言实现的python的解析器,运行时,虚拟机组建。
最后我们来看STM32是如何实现Python编程与控制的:
源码图中绿色注释的部分是STM32 MicroPython的主要代码,STM32(以下简称MCU)main函数位于stmhal/main.c,MCU启动后进入main函数,那么我们看main函数里干了什么事情:
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 - Set NVIC Group Priority to 4 - Global MSP (MCU Support Package) initialization */ HAL_Init(); // set the system clock to be HSE SystemClock_Config(); ......... port init, LED init, switch init , sdcard initµÈ°åÉÏÍâÉè³õʼ»¯ ...... // GC init gc_init(&_heap_start, &_heap_end); // MicroPython init 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); // zero out the pointers to the mounted devices memset(MP_STATE_PORT(fs_user_mount), 0, sizeof(MP_STATE_PORT(fs_user_mount))); // Initialise low-level sub-systems. Here we need to very basic things like // zeroing out memory and resetting any of the sub-systems. Following this // we can run Python scripts (eg boot.py), but anything that is configurable // by boot.py must be set after boot.py is run. readline_init0(); pin_init0(); extint_init0(); timer_init0(); uart_init0(); // Define MICROPY_HW_UART_REPL to be PYB_UART_6 and define // MICROPY_HW_UART_REPL_BAUD in your mpconfigboard.h file if you want a // REPL on a hardware UART as well as on USB VCP #if defined(MICROPY_HW_UART_REPL) { mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(MICROPY_HW_UART_REPL), MP_OBJ_NEW_SMALL_INT(MICROPY_HW_UART_REPL_BAUD), }; MP_STATE_PORT(pyb_stdio_uart) = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, MP_ARRAY_SIZE(args), 0, args); } #else MP_STATE_PORT(pyb_stdio_uart) = NULL; #endif i2c_init0(); soft_reset_exit: }
在main函数中大概是初始化MCU的时钟,初始化各个外设,然后调用python的垃圾回收器gc_init(), 初始化python对象列表,相当于启动了python的虚拟机(本人暂时对python的实现机制理解有限)。后面紧接着启动了python的REPL,bind到uart6,这也就允许你通过串口来执行python代码了。
https://blog.csdn.net/whble/article/details/78213361
发表评论