在图中标注黄色的部分是我们需要制作的,而绿色部分是跨平台的,我们只需要拉取源码进行编译即可,不需要修改。
从下往上看,首先是需要一份PikaScript的BSP,BSP也就是板级支持包,这通常只要将厂商提供的MCU的标准库稍加整理即可获得。然后是PikaScript的启动器,这包含了固件入口main.c,以及基本的设备初始化代码,包括对printf的支持。
有了BSP和启动器,就已经可以运行PikaScript的固件了,只不过还只能使用PikaScript提供的标准库功能和Python的基本语法,还不能使用MCU上搭载的外设资源。
为了使用CH32V103的外设资源,我们还需要开发CH32V103的驱动模块,在这个项目中,我们开发了GPIO的驱动模块和基于rt-thread
tick定时器的延时模块。
最上层的就是我们要运行的Python脚本了,模块预编译器也可以处理Python脚本,根据脚本中导入的模块来自动裁剪固件,在脚本中没有import的固件会被自动裁剪掉,我们可以在main.py中选择要加入固件的模块,以及编写系统初始化后最先运行的Python脚本,将其烧录进固件中。
2.制作BSP和启动器——先跑起来再说
BSP通常是用芯片的原厂提供的例程制作的,在这个项目中,我们就使用CH32V103的官方例程中的uart_printf和MounRiver River Studio生成的rt-thread模板来制作。完成了对rt-thread模板的一些剪裁之后,再加入printf的初始化函数,对项目稍作整理,BSP部分就完成了。
PikaScript的启动器的制作也比较简单,在main.c中添加#include “pikaScript.h”并调用pikaScriptInit()函数即可启动PikaScript。pikaScript.h和pikaScriptInit()都是由预编译器自动生成的,在制作启动器之前,需要拉取PikaScript的源码。
PikaScript官方(其实就是我自己)提供了一个包管理工具,只需要编写requestment.txt,就可以从gitee中自动拉取相应版本的源码和模块。在拉取内核源码时,预编译器也会自动被拉取下来,我们在main.py中写入import PikaStdLib,然后用我们使用拉取下来的预编译器进行预编译,就能得到pikaScriptInit()函数了。
包管理工具不仅可以拉取内核,还可以拉取模块,也就是说我们自己制作的CH32V103的驱动模块,也可以挂到PikaScript模块库中,进行自动拉取。
BSP和启动器的制作我录制了一个视频教程,想要了解细节或者想自己制作BSP的大佬可以看视频了解。
https://www.bilibili.com/video/BV1Cq4y1G7Tj
3.制作CH32V103的驱动模块
接下来我们制作CH32V103的驱动模块,使得CH32V103上面的外设资源能够被Python脚本调用到。
在这个项目中,我们制作了一个PikaScript的标准设备驱动,什么是标准设备驱动呢?我们先从其他的脚本技术说起,比如MicroPython,并没有统一的外设调用API,这使得用户在使用不同的平台时,都需要重新学习API,比如下面这个是MicroPython在
STM32F4平台驱动GPIO的代码。
这个是ESP8266的
可以明显看到在选择pin的管脚时,一个用的是字符串,而另一个用的是整型数,驱动的API标准很混乱。有没有什么办法,能够统一外设的API,使得用户只需要熟悉一套API,就能够在任意平台通用呢?
方法是有的,就是PikaStdDevice标准设备驱动模块!
PikaStdDevice是一个抽象的设备驱动模块,定义了所有的用户API,而各个平台的驱动模块只要从PikaStdDevice继承,就能够获得一模一样的用户API,而PikaStdDevice内部会间接调用平台驱动,通过多态特性重写底层的平台驱动,就可以在不同的平台工作了!
以GPIO模块为例,以下是PikaStdDevice定义的用户API。
以下是PikaStdDevice需要重写的平台驱动
而我们要制作的CH32V103的GPIO模块,就从标准驱动模块中继承。
通过这个方法,我们就可以让STM32的驱动模块、CH32的驱动模块、ESP32的驱动模块有着一模一样的用户API!用户只要熟悉了一套API,就可以轻松使用支持了PikaScript标准驱动模块的所有平台!这才是真正的跨平台!
下面是部分被注册在驱动模块里面C原生驱动函数。