移植micropython到MCU(以MDK+CORTEX-M平台示例)

原创 嵌入式Lee 2024-12-18 12:46

一. 前言

MicroPythonPython 3的精简高效的实现,包含了一部分经过优化的Python标准库,能在微控制器等资源受限的平台运行。MicroPython也支持一些高级功能,比如交互式提示、任意精度的整数、闭包、列表推导、生成器、异常处理等等。它的实现体积很小,可以在只有 256k的代码空间和16k的内存空间的平台运行,特别适合移植到MCU上使用MicroPython的设计也是尽量和普通的 Python兼容,这样能轻松地把代码从桌面平台等搬到微控制器或者嵌入式系统平台运行个人觉得移植micropython到自己的平台,用于自动化验证测试也是一个非常不错的应用,搭建好micropython环境后,这样可以由验证和测试的同事直接编写python脚本验证测试,而无需软件工程师全程配合了,这样提高了协作效率。

官方提供了各种pyboard的适配,可以直接编译对应的固件使用而对于我们自己的平台,官方可能没有适配,而且其构建环境可能也不是我们使用的,所以一个好的方式是只使用其源码将其移植到我们自己的平台。本文就分享Micropython基于MDK移植到CORTEX-M33平台。开发板使用的是的富芮坤FR3068E-C

.获取源码

下载源码git clone https://github.com/micropython/micropython.git

micropython有自己的构建方式,默认适配了一些平台。而更一般的方式是我们只使用其源码,移植到我们自己的工程中去。

为了了解代码框架等可以先在某一个官方支持的平台上构建一下,了解一下构建过程,这样可以知道需要编译哪些源码,有哪些过程。

可以直接在windows下使用vs打开micropython\mpy-cross\mpy-cross.vcxproj编译编译器。

然后再打开micropython\ports\windows\micropython.vcxproj编译解释器。

了解下其工程架构,注意构建前需要取消所有文件的只读属性。

二. 添加源码

我们来移植一个最下实现,即暂时不添加外部模块,仅使用内建的一些模块,整个代码框架如下

Py源码

其中py目录下是micropyth解释器实现核心代码,我们复制到自己的工程目录中。

复制其下所有c文件到自己的工程中。

并将py路径添加到头文件包含路径。

其中以下文件按照平台选择,我这里是ARM CORTEX-M系列选择asmthumb.c,其他的不需要。

asmarm.c

asmrv32.c

asmthumb.c

asmx64.c

asmx86.c

asmxtensa.c

shared源码

暂时只添加以下内容,其他有需要时再添加

Shared/runtime/pyexec.c pyexec.h

Shared/readline/readline.c readline.h

extmod源码

暂时只添加以下内容,其他的有需要时再添加

modplatform.h

virtpin.h

py_port源码

然后新建一个移植文件夹py_port,我们参考micropython\ports\minimal移植

复制micropython\ports\minimal下的文件到我们的py_port路径下

py_port添加到自己的工程目录

文件如下,其中uart_core.c实现串口输入输出接口,mpconfigport.h是配置文件,mphalport.h是一些hal层接口实现,py_main是解释器入口,qstrdefsport.h

unistd.h是类似unix平台的一个替代。


Py_main.c

py_port/main.c改为py_port/py_main.c

它默认是基于stm32或者pc主机实现的,我们需要按照自己的平台做一些修改。

#if MICROPY_MIN_USE_STM32_MCU

#endif

#if MICROPY_MIN_USE_CORTEX_CPU

#endif

的内容都删掉,因为我们使用自己的平台。

main函数名改为py_main

到时在自己的平台合适的地方调用py_main即可。

先保证其能编译过,后续再来看py_main如何实现。

Uart_core.c

需要实现以下接口,后面再来看实现

@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}#include "py/mpconfig.h" /* * Core UART functions to implement for a port */ // Receive single characterint mp_hal_stdin_rx_chr(void) {    unsigned char c = 0;     return c;} // Send string of given lengthmp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {    mp_uint_t ret = len;     return ret;} void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len){} void mp_hal_stdout_tx_str(const char *str){}

Unistd.h

定义ssize_t,其其他一些宏

@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}#ifndef MICROPY_INCLUDED_UNISTD_H#define MICROPY_INCLUDED_UNISTD_H typedef int ssize_t;#define F_OK 0#define W_OK 2#define R_OK 4 #define STDIN_FILENO  0#define STDOUT_FILENO 1#define STDERR_FILENO 2 #define SEEK_CUR 1#define SEEK_END 2#define SEEK_SET 0 #endif 

mphalport.h

Hal层接口

static inline mp_uint_t mp_hal_ticks_ms(void) {    return 0;}static inline void mp_hal_set_interrupt_char(char c) {}

qstrdefsport.h

// qstrs specific to this port// *FORMAT-OFF*

mpconfigport.h

配置文件,这个我呢金很重要,其中需要关注的是MICROPY_PY_XXX宏配置是否使能某些模块。

@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}#include h> // options to control how MicroPython is built // Use the minimal starting configuration (disables all optional features).#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM) // You can disable the built-in MicroPython compiler by setting the following// config option to 0.  If you do this then you won't get a REPL prompt, but you// will still be able to execute pre-compiled scripts, compiled with mpy-cross.#define MICROPY_ENABLE_COMPILER     (1) //#define MICROPY_QSTR_EXTRA_POOL           mp_qstr_frozen_const_pool#define MICROPY_HELPER_REPL               (1)#define MICROPY_MODULE_FROZEN_MPY         (0)#define MICROPY_ENABLE_EXTERNAL_IMPORT    (0) #define MICROPY_PY_IO                     (0)#define MICROPY_PY_IO_IOBASE              (1)#define MICROPY_PY_ERRNO                  (1)#define MICROPY_PY_MATH                   (1)#define MICROPY_PY_CMATH                  (1)#define MICROPY_PY_BUILTINS_FLOAT         (1)#define MICROPY_PY_BUILTINS_COMPLEX       (1) #define MICROPY_PY_GC                     (1)#define MICROPY_ENABLE_GC                 (1)#define MICROPY_PY_SYS                    (1)#define MICROPY_PY_MICROPYTHON            (1)#define MICROPY_USE_INTERNAL_PRINTF       (0)#define MICROPY_PY_ARRAY                  (1)#define MICROPY_PY_BUILTINS_BYTEARRAY     (1)#define MICROPY_PY_BUILTINS_MEMORYVIEW    (1)#define MICROPY_FLOAT_IMPL                (MICROPY_FLOAT_IMPL_DOUBLE)#define MICROPY_ALLOC_PATH_MAX            (256) // Use the minimum headroom in the chunk allocator for parse nodes.#define MICROPY_ALLOC_PARSE_CHUNK_INIT    (16) // type definitions for the specific machine typedef intptr_t mp_int_t; // must be pointer sizetypedef uintptr_t mp_uint_t; // must be pointer sizetypedef long mp_off_t; // We need to provide a declaration/definition of alloca()#include  #define MICROPY_HW_BOARD_NAME "minimal"#define MICROPY_HW_MCU_NAME "unknown-cpu" #define MICROPY_HEAP_SIZE      (2048) // heap size 2 kilobytes #define MP_STATE_PORT MP_STATE_VM#define MICROPY_USE_INTERNAL_ERRNO 1

四. 移植

标准库依赖

依赖的标准库如下:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include   这个我们在py_port自己实现

errno

如果没有#include

则配置MICROPY_USE_INTERNAL_ERRNO1

#include  这个编译器支持

产生genhdr

我们可以从其他已经构建的,或者使用windows的样例先构建一下,然后复制对应的头文件

moduledefs.h   定义一些模块信息,由于没有使用官方的构建过程,可能没有自动更新对一个,可以手动修改,删减某些模块。后面我们在MDK的工程配置中合适时机手动调用对应的脚本来实现。


mpversion.h
qstrdefs.generated.h
root_pointers.h

生成过程参考ports\windows\msvc\genhdr.targets

中的命令

 <Exec Command="type $(QstrDefsCollected) >> $(DestDir)qstrdefs.preprocessed.h"/>

 <Exec Command="$(PyPython) $(PySrcDir)makeqstrdata.py $(DestDir)qstrdefs.preprocessed.h > $(TmpFile)"/>

其中指定文件qstrdefscollected.h

 <QstrDefsCollected>$(DestDir)qstrdefscollected.hQstrDefsCollected>

该文件由以下命令产生

 <Exec Command="$(PyPython) $(PySrcDir)makeqstrdefs.py split qstr $(DestDir)qstr.i.last $(DestDir)qstr _"/>

 <Exec Command="$(PyPython) $(PySrcDir)makeqstrdefs.py cat qstr _ $(DestDir)qstr $(QstrDefsCollected)"/>

对应如下命令

makeqstrdata.py位于py目录下,在此打开cmd行,

先执行

python makeqstrdefs.py split qstr qstr.i.last qstr _

python makeqstrdefs.py cat qstr _ qstr qstrdefscollected.h

再执行

type qstrdefscollected.h >> qstrdefs.preprocessed.h

再执行

python makeqstrdata.py qstrdefs.preprocessed.h >qstrdefs.generated.h.tmp

适配串口

py_port\uart_core.c中删掉

#include

添加我们自己的串口接口

#includeuart.h

删掉

#if MICROPY_MIN_USE_STM32_MCU

#end

#if MICROPY_MIN_USE_STDOUT

#elif MICROPY_MIN_USE_STM32_MCU

#endif

中的内容

即实现阻塞读一个字符mp_hal_stdin_rx_chr

阻塞发送字符串的接口

mp_hal_stdout_tx_strn

mp_hal_stdout_tx_strn_cooked

mp_hal_stdout_tx_str

串口实现可以参考文章,采用FIFO方式实现

https://mp.weixin.qq.com/s/vzjWu2LxpVGZw-msCooh8Q?token=1312261758&lang=zh_CN 超级精简系列之十六:基于IO模拟+FIFO的串口驱动

Uart.c如下

@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}#include h>#include h>#include "uart.h"#include "fifo.h"#include h> #include "fr30xx.h" #define CriticalAlloc()#define EnterCritical()                              __disable_irq()#define ExitCritical()                              __enable_irq() static uint8_t s_uart_rx_buffer[64]; static fifo_st s_uart_fifo_dev={ .in = 0, .len = 0, .out = 0, .buffer = s_uart_rx_buffer, .buffer_len = sizeof(s_uart_rx_buffer),}; volatile bool g_data_transmit_flag = false;uint8_t rx_buffer[1];  void uart_rx_cb(uint8_t* buff, uint32_t len){	fifo_in(&s_uart_fifo_dev, buff, len);}   uint32_t uart_send(uint8_t* buffer, uint32_t len){    g_data_transmit_flag = false;     for(uint32_t i=0;i    {				putchar(buffer[i]);    }    return len;} uint32_t uart_read(uint8_t* buffer, uint32_t len){    uint32_t rlen;    CriticalAlloc();    EnterCritical();    rlen = fifo_out(&s_uart_fifo_dev, buffer, len);    ExitCritical();    return rlen;}
uart.h如下
@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}#ifndef UART_H#define UART_H #ifdef __cplusplusextern "C" {#endif  #include .h> uint32_t uart_send(uint8_t* buffer, uint32_t len);uint32_t uart_read(uint8_t* buffer, uint32_t len);void uart_rx_cb(uint8_t* buff, uint32_t len); #ifdef __cplusplus}#endif #endif
fifo.c如下
@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}#include #include "fifo.h" #define FIFO_PARAM_CHECK 0 /** * in????? 0~(buffer_len-1)? * out????? 0~(buffer_len-1)? * in == out?????,?????,????len?????????? * ???in??,?????out??? * ????out??,?????in??? * in??out??[out,in)???????? * in??out??[out,buffer_len)?[0,in)???????? *********************************************************** *     0                                 buffer_len-1 buffer_len *     (1)?? in?out??0 *     |                                             | *     in(0) *     out(0) *     len = 0 *     (2)??n???? in??n?out??0 ??in??out??? *     |                                             | *     out(0)————————————>in(n)                      |    *     len = n *     (3)??m????(m *     |                                             | *             out(m)————>in(n) *     len = n-m *     (4)??????,?????,??in??out??? *     |                                             | *             out(m)————————————————————————————————> *     ——>in(k) *     len = k + buffer_len-m */uint32_t fifo_in(fifo_st* dev, uint8_t* buffer, uint32_t len){  uint32_t space = 0;  /* ?????????? */  /* ???? */  #if FIFO_PARAM_CHECK  if((dev == 0) || (buffer == 0) || (len == 0))  {    return 0;  }  if(dev->buffer == 0)  {    return 0;  }  #endif   /* ??len??????buffer?? */  if(len > dev->buffer_len)  {    len = dev->buffer_len;  }   /* ????????    * ??dev->len?????dev->buffer_len   */  if(dev->buffer_len >= dev->len)  {    space = dev->buffer_len - dev->len;   }  else  {    /* ???????, ?????? */    dev->len = 0;    space = dev->buffer_len;   }   /* ???????, ??len???????????????? */  len = (len >= space) ? space : len;    if(len == 0)  {    return 0/* ??????????,???? */  }   /* ??len??????????,?????? */  space = dev->buffer_len - dev->in/* ??????in???????????? */  if(space >= len)  {    /* ??????in??????????? */    memcpy(dev->buffer+dev->in,buffer,len);  }  else  {    /* ??????in???????,????????? */    memcpy(dev->buffer+dev->in,buffer,space);    /* ???tail??  */    memcpy(dev->buffer,buffer+space,len-space);  /* ???????? */  }   /* ????????????? */  dev->in += len;  if(dev->in >= dev->buffer_len)  {    dev->in -= dev->buffer_len;  /* ????? ?? dev->in %= dev->buffer->len */  }  dev->len += len;  /* dev->len??dev->buffer->len,??%= dev->buffer->len */  return len;} uint32_t fifo_out(fifo_st* dev, uint8_t* buffer, uint32_t len){  uint32_t space = 0  /* ???? */  #if FIFO_PARAM_CHECK  if((dev == 0) || (buffer == 0) || (len == 0))  {    return 0;  }  if(dev->buffer == 0)  {    return 0;  }  #endif    /* ??????? */  if(dev->len == 0)  {    return 0;  }   /* ?????????????????? */  len = (dev->len) > len ? len : dev->len;   /* ??len??????????,?????? */  space = dev->buffer_len - dev->out/* ??????out???????????? */  if(space >= len)  {    /* ??????out??????????? */    memcpy(buffer,dev->buffer+dev->out,len);  }  else  {    /* ??????out???????,????????? */    memcpy(buffer,dev->buffer+dev->out,space);    /* ???tail??  */    memcpy(buffer+space,dev->buffer,len-space);   /* ???????? */  }   /* ????????????? */  dev->out += len;  if(dev->out >= dev->buffer_len)  {    dev->out -= dev->buffer_len;  /* ????? ?? dev->out %= dev->buffer->len */  }  dev->len -= len;   /* ??dev->len ?????len,???? */  return len;} uint32_t fifo_getlen(fifo_st* dev){  #if FIFO_PARAM_CHECK  if(dev == 0)  {    return 0;  }  #endif  return dev->len;} void fifo_clean(fifo_st* dev){  #if FIFO_PARAM_CHECK  if(dev == 0)  {    return 0;  }  #endif  dev->len = 0;  dev->in = 0;  dev->out = 0;}
fifo.h如下
@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}#ifndef FIFO_H#define FIFO_H #ifdef __cplusplusextern "C" {#endif  #include .h> /** * \struct fifo_st * FIFO?????. */typedef struct {  uint32_t in;          /**< ????        */   uint32_t out;         /**< ????        */   uint32_t len;         /**< ??????    */   uint32_t buffer_len;  /**< ????        */   uint8_t* buffer;      /**< ??,????   */ } fifo_st;  /** * \fn fifo_in * ?fifo???? * \param[in] dev \ref fifo_st * \param[in] buffer ?????? * \param[in] len ?????? * \retval ?????????? */uint32_t fifo_in(fifo_st* dev, uint8_t* buffer, uint32_t len); /** * \fn fifo_out * ?fifo???? * \param[in] dev \ref fifo_st * \param[in] buffer ?????? * \param[in] len ????????? * \retval ?????????? */uint32_t fifo_out(fifo_st* dev, uint8_t* buffer, uint32_t len);  uint32_t fifo_getlen(fifo_st* dev); void fifo_clean(fifo_st* dev);#ifdef __cplusplus}#endif #endif

最终uart_core.c实现如下

@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}#include <string.h>#include "py/mpconfig.h"#include "uart.h" /* * Core UART functions to implement for a port */ // Receive single characterint mp_hal_stdin_rx_chr(void) {    unsigned char c = 0;		while(0 == uart_read(&c,1))    {		};    return c;} // Send string of given lengthmp_uint_t mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {    mp_uint_t ret = len;    uart_send((uint8_t*)str,len);    return ret;} void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len){	    uart_send((uint8_t*)str,len);} void mp_hal_stdout_tx_str(const char *str){	    uart_send((uint8_t*)str,strlen(str));}

Py_main入口

py_main.c

MICROPY_ENABLE_GC配置为0

MICROPY_ENABLE_COMPILER配置为1

MICROPY_REPL_EVENT_DRIVEN 配置为0

即执行过程如下

mp_init();->pyexec_friendly_repl();

@font-face{font-family:"Times New Roman";}@font-face{font-family:"宋体";}@font-face{font-family:"Calibri";}p.MsoNormal{mso-style-name:正文;mso-style-parent:"";margin:0pt;margin-bottom:.0001pt;mso-pagination:none;text-align:justify;text-justify:inter-ideograph;font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;}span.msoIns{mso-style-type:export-only;mso-style-name:"";text-decoration:underline;text-underline:single;color:blue;}span.msoDel{mso-style-type:export-only;mso-style-name:"";text-decoration:line-through;color:red;}@page{mso-page-border-surround-header:no;	mso-page-border-surround-footer:no;}@page Section0{}div.Section0{page:Section0;}int py_main(int argc, char **argv) {    int stack_dummy;    stack_top = (char *)&stack_dummy;     #if MICROPY_ENABLE_GC    gc_init(heap, heap + sizeof(heap));    #endif    mp_init();    #if MICROPY_ENABLE_COMPILER    #if MICROPY_REPL_EVENT_DRIVEN    pyexec_event_repl_init();    for (;;) {        int c = mp_hal_stdin_rx_chr();        if (pyexec_event_repl_process_char(c)) {            break;        }    }    #else    pyexec_friendly_repl();    #endif    // do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT);    // do_str("for i in range(10):\r\n  print(i)", MP_PARSE_FILE_INPUT);    #else    pyexec_frozen_module("frozentest.py", false);    #endif    mp_deinit();    return 0;} 

创建一个线程运行py_main函数即可。

五. 测试

运行后看到打印如下

进行一个简单的计算


使用了alloca.h从栈分配资源,所以注意栈大小先配置大一点。

六. 总结

网上一些资料最多算是micropython的构建,算不上移植,这里分享完全从0开始移植micropython源码到自己的工程,一通百通。通过此可以了解一个最简的micropython移植需要哪些文件,以及其基本的架构。后续我们再来介绍外部模块的添加,这才是移植的最大头的工作量,要做到实用,实际就是要移植好各种平台相关的资源模块。




评论 (0)
  •   卫星图像智能测绘系统:地理空间数据处理的创新引擎   卫星图像智能测绘系统作为融合卫星遥感、地理信息系统(GIS)、人工智能(AI)以及大数据分析等前沿技术的综合性平台,致力于达成高精度、高效率的地理空间数据采集、处理与应用目标。借助自动化、智能化的技术路径,该系统为国土资源管理、城市规划、灾害监测、环境保护等诸多领域输送关键数据支撑。   应用案例   目前,已有多个卫星图像智能测绘系统在实际应用中取得了显著成效。例如,北京华盛恒辉北京五木恒润卫星图像智能测绘系统。这些成功案例为卫星
    华盛恒辉l58ll334744 2025-04-08 16:19 19浏览
  •     在研究Corona现象时发现:临界电压与介电材料表面的清洁程度有关。表面越清洁的介电材料,临界电压越高;表面污染物越多的地方,越容易“爬电”。关于Corona现象,另见基础理论第007篇。    这里说的“污染物”,定义为——可能影响介电强度或表面电阻率的固体、液体或气体(电离气体)的任何情况。    IEC 60664-1 (对应GB/T 16935.1-2023) 定义了 Pollution Degree,中文术语是“污染等
    电子知识打边炉 2025-04-07 22:06 91浏览
  •     根据 IEC术语,瞬态过电压是指持续时间几个毫秒及以下的过高电压,通常是以高阻尼(快速衰减)形式出现,波形可以是振荡的,也可以是非振荡的。    瞬态过电压的成因和机理,IEC 60664-1给出了以下四种:    1. 自然放电,最典型的例子是雷击,感应到电力线路上,并通过电网配电系统传输,抵达用户端;        2. 电网中非特定感性负载通断。例如热处理工厂、机加工工厂对
    电子知识打边炉 2025-04-07 22:59 119浏览
  • HDMI从2.1版本开始采用FRL传输模式,和2.0及之前的版本不同。两者在物理层信号上有所区别,这就需要在一些2.1版本的电路设计上增加匹配电路,使得2.1版本的电路能够向下兼容2.0及之前版本。2.1版本的信号特性下面截取自2.1版本规范定义,可以看到2.1版本支持直流耦合和交流耦合,其共模电压和AVCC相关,信号摆幅在400mV-1200mV2.0及之前版本的信号特性HDMI2.0及之前版本采用TMDS信号物理层,其结构和参数如下:兼容设计根据以上规范定义,可以看出TMDS信号的共模电压范
    durid 2025-04-08 19:01 127浏览
  • 文/Leon编辑/cc孙聪颖‍转手绢、跳舞、骑车、后空翻,就在宇树、智元等独角兽企业率领“机器人大军”入侵短视频时,却有资本和科技大佬向此产业泼了一盆冷水。金沙江创投管理合伙人朱啸虎近日突然对人形机器人发难,他表示“最近几个月正在批量退出人形机器人公司”。“只是买回去做研究的,或者买回去做展示的,这种都不是我们意义上的商业化,谁会花十几万买一个机器人去干这些活?”朱啸虎吐槽。不过,朱啸虎的观点很快就遭到驳斥,众擎机器人的创始人、董事长赵同阳回怼道:“(朱啸虎)甚至问出了人形机器人在这个阶段有什么
    华尔街科技眼 2025-04-07 19:24 145浏览
  • 贞光科技作为三星电机车规电容代理商,针对电动汽车领域日益复杂的电容选型难题,提供全方位一站式解决方案。面对高温稳定性、高可靠性、高纹波电流和小型化等严苛要求,三星车规电容凭借完整产品矩阵和卓越技术优势,完美满足BMS、电机控制器和OBC等核心系统需求。无论技术选型、供应链保障、样品测试还是成本优化,贞光科技助力客户在电动汽车产业高速发展中占据技术先机。在电动汽车技术高速发展的今天,作为汽车电子系统中不可或缺的关键元器件,电容的选型已成为困扰许多工程师和采购人员的难题。如何在众多参数和型号中找到最
    贞光科技 2025-04-07 17:06 69浏览
  • 医疗影像设备(如CT、MRI、超声诊断仪等)对PCB的精度、可靠性和信号完整性要求极高。这类设备需要处理微伏级信号、高频数据传输,同时需通过严格的EMC/EMI测试。制造此类PCB需从材料选择、层叠设计、工艺控制等多维度优化。以下是关键技术与经验分享。 1. 材料选择:高频与生物兼容性优先医疗影像设备PCB常采用 Rogers RO4000系列 或 Isola FR4高速材料,以降低介电损耗并保证信号稳定性。例如,捷多邦在客户案例中曾为某超声探头厂商推荐 Rogers RO4350B
    捷多邦 2025-04-07 10:22 111浏览
  • 在全球电子产业面临供应链波动、技术迭代和市场需求变化等多重挑战的背景下,安博电子始终秉持“让合作伙伴赢得更多一点”的核心理念,致力于打造稳健、高效、可持续的全球供应链体系。依托覆盖供应商管理、品质检测、智能交付的全链路品控体系,安博电子不仅能确保电子元器件的高可靠性与一致性,更以高透明的供应链管理模式,助力客户降低风险、提升运营效率,推动行业标准升级,与全球合作伙伴共同塑造更具前瞻性的产业生态。动态优选机制:构建纯净供应链生态安博电子将供应商管理视为供应链安全的根基。打造动态优选管控体系,以严格
    电子资讯报 2025-04-07 17:06 90浏览
  • 在万物互联时代,智能化安防需求持续升级,传统报警系统已难以满足实时性、可靠性与安全性并重的要求。WT2003H-16S低功耗语音芯片方案,以4G实时音频传输、超低功耗设计、端云加密交互为核心,重新定义智能报警设备的性能边界,为家庭、工业、公共安防等领域提供高效、稳定的安全守护。一、技术内核:五大核心突破,构建全场景安防基座1. 双模音频传输,灵活应对复杂场景实时音频流传输:内置高灵敏度MIC,支持环境音实时采集,通过4G模块直接上传至云端服务器,响应速度低至毫秒级,适用于火灾警报、紧急呼救等需即
    广州唯创电子 2025-04-08 08:59 129浏览
  • 及时生产 JIT(Just In Time)的起源JIT 起源于 20 世纪 70 年代爆发的全球石油危机和由此引发的自然资源短缺,这对仰赖进口原物料发展经济的日本冲击最大。当时日本的生产企业为了增强竞争力、提高产品利润,在原物料成本难以降低的情况下,只能从生产和流通过程中寻找利润源,降低库存、库存和运输等方面的生产性费用。根据这种思想,日本丰田汽车公司创立的一种具有特色的现代化生产方式,即 JIT,并由此取得了意想不到的成果。由于它不断地用于汽车生产,随后被越来越多的许多行业和企业所采用,为日
    优思学院 2025-04-07 11:56 106浏览
  • 在人工智能技术飞速发展的今天,语音交互正以颠覆性的方式重塑我们的生活体验。WTK6900系列语音识别芯片凭借其离线高性能、抗噪远场识别、毫秒级响应的核心优势,为智能家居领域注入全新活力。以智能风扇为起点,我们开启一场“解放双手”的科技革命,让每一缕凉风都随“声”而至。一、核心技术:精准识别,无惧环境挑战自适应降噪,听懂你的每一句话WTK6900系列芯片搭载前沿信号处理技术,通过自适应降噪算法,可智能过滤环境噪声干扰。无论是家中电视声、户外虫鸣声,还是厨房烹饪的嘈杂声,芯片均能精准提取有效指令,识
    广州唯创电子 2025-04-08 08:40 158浏览
  • 曾几何时,汽车之家可是汽车资讯平台领域响当当的“扛把子”。2005 年成立之初,它就像一位贴心的汽车小助手,一下子就抓住了大家的心。它不仅吸引了海量用户,更是成为汽车厂商和经销商眼中的“香饽饽”,广告投放、合作推广不断,营收和利润一路高歌猛进,2013年成功在纽交所上市,风光无限。2021年更是在香港二次上市,达到了发展的巅峰,当年3月15日上市首日,港股股价一度高达184.6港元,市值可观。然而,如今的汽车之家却陷入了困境,业务下滑明显。业务增长瓶颈从近年来汽车之家公布的财报数据来看,情况不容
    用户1742991715177 2025-04-07 21:48 109浏览
  •   工业自动化领域电磁兼容与接地系统深度剖析   一、电磁兼容(EMC)基础认知   定义及关键意义   电磁兼容性(EMC),指的是设备或者系统在既定的电磁环境里,不但能按预期功能正常运转,而且不会对周边其他设备或系统造成难以承受的电磁干扰。在工业自动化不断发展的当下,大功率电机、变频器等设备被大量应用,现场总线、工业网络等技术也日益普及,致使工业自动化系统所处的电磁环境变得愈发复杂,电磁兼容(EMC)问题也越发严峻。   ​电磁兼容三大核心要素   屏蔽:屏蔽旨在切断电磁波的传播路
    北京华盛恒辉软件开发 2025-04-07 22:55 189浏览
  •   卫星图像智能测绘系统全面解析   一、系统概述   卫星图像智能测绘系统是基于卫星遥感技术、图像处理算法与人工智能(AI)技术的综合应用平台,旨在实现高精度、高效率的地理空间数据获取、处理与分析。该系统通过融合多源卫星数据(如光学、雷达、高光谱等),结合AI驱动的智能算法,实现自动化、智能化的测绘流程,广泛应用于城市规划、自然资源调查、灾害监测等领域。   应用案例   目前,已有多个卫星图像智能测绘系统在实际应用中取得了显著成效。例如,北京华盛恒辉和北京五木恒润卫星图像智能测绘系统
    华盛恒辉l58ll334744 2025-04-08 15:04 17浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦