MicroPython 源码结构和初步分析

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



坐沙发

发表评论

你的邮件地址不会公开


*