3.2. 支持交互式运行

PikaScript 支持直接读取字符串运行 Python 脚本,因此支持交互式运行只需要制作一个串口接收驱动。

3.2.1. 方案一:按字节读取运行(推荐)

3.2.1.1. 实现一个阻塞的字节读取函数

交互式运行需要一个读取用户输入字节的底层接口 __platform_getchar() ,这个接口是一个 weak 函数,用户需要在自己的代码里面也实现一个 __platform_getchar() 来覆盖这个 weak 函数。

weak 函数原型在 PikaPlatform.c 里面,如果用户没有覆盖,就会在使用交互式运行时报错。

  1. /* PikaPlatform.c */
  2. PIKA_WEAK char __platform_getchar(void) {
  3. __platform_printf("[error]: __platform_getchar need an implement!\r\n");
  4. while(1){
  5. }
  6. }

用户可以直接在工程的 main.c 里面实现一个 __platform_getchar()

如果平台本身支持 getchar() ,那么可以直接接入平台的 getchar()

  1. /* main.c */
  2. char __platform_getchar(){
  3. return getchar();
  4. }

如果平台不支持,就需要自己实现,注意要实现一个阻塞getchar(),也就是说,当没有串口输入字符时,要在 __platform_getchar() 中等待,有输入时返回一个字符。 例如:

  1. /* main.c */
  2. char __platform_getchar(){
  3. char res = 0;
  4. while(rx_char == 0){
  5. };
  6. res = rx_char;
  7. rx_char = 0;
  8. return res;
  9. }

3.2.1.2. 启动 PikaScript Shell,直接运行 pikaScriptShell() 即可启动交互运行。

pikaScriptShell() 入口参数是 pika 的根对象,运行 pikaScriptInit() 就能创建一个根对象。

  1. pikaScriptShell(pikaScriptInit());

3.2.1.3. 示例代码

stm32g070cb: https://gitee.com/Lyon1998/pikascript/blob/master/bsp/stm32g070cb/Booter/main.c

rt-thread: https://gitee.com/Lyon1998/pikascript/blob/master/package/pikaRTThread/rt_pika.c

3.2.1.4. 注意事项:

  • 内核版本需要不低于 v1.3.0

  • 强烈建议使用putty作为串口终端。

_images/1641178790145-2f026e70-4ba1-4e9a-b05f-c602b2bd8cad.png

3.2.2. 方案二:按字节输入运行

obj_runChar 内核 API 可以指定一个对象执行脚本,且输入为一个字节。

在使用 obj_runChar 前,需要先运行 obj_runCharInit()

示例代码:

  1. PikaObj* pikaMain = pikaScriptInit();
  2. obj_runCharInit(pikaMain);
  3. while(1){
  4. char ch = my_get_char();
  5. obj_runChar(pikaMain, ch);
  6. }

3.2.2.1. 注意事项:

内核版本需要不低于 v1.8.3

3.2.3. 方案三:整行输入运行

obj_run 内核 API 可以指定一个对象执行脚本,使用这个 API 可以执行单行或者多行的脚本。 下面以 CH32 的交互式运行驱动为例,这个交互式运行的支持写在固件的主循环内,在 pikaScriptInit() 初始化脚本执行完毕之后,开始执行。 _images/1638495382112-7d45db4b-c1d5-4573-a06e-7b72140a3abf.webp

3.2.3.1. 驱动的内容

  • 轮询接收字符,存入缓冲区。

  • 当超过10ms没有新的字符接收时,认为一次接收完成。

使用空闲时间来判断字符串的传输完成就可以支持交互式运行多行脚本了。如果只需要运行单号脚本,则可以使用换行符 '\n' 来判断字符串接收结束。在运行单行脚本时,可以不带 '\n' 换行符,多行脚本需要带 '\n' 换行符。"\r\n" 形式的换行符也是支持的。

  • 接收完成后回显接收到的字符串。

  • 使用 obj_run 内核API执行脚本。

指定的对象是 pikaScriptInit() 初始化脚本创建的根对象,执行的内容是接收到的字符串。

  • 清理接收缓冲区。

3.2.3.2. 注意事项:

  • 内核版本需要不低于 v1.2.6

  • 在执行多行脚本时,需要传入完整的代码块

例如:下面的脚本是完整的代码块,尤其需要注意的是第 4 行,需要有一个缩进为 0 的行,用来标志代码块的结束。以及最后一行需要有一个空行,这意味着 print('the end') 这行脚本末尾带有换行符。

  1. while a < 10
  2. a = a + 1
  3. print(a)
  4. print('the end')
  5. (空行)

以下的例子也是可以的

  1. while a < 10
  2. a = a + 1
  3. print(a)
  4. (空行)

以下的例子是不行的

  1. # 缺少最后的换行符
  2. while a < 10
  3. a = a + 1
  4. print(a)
  1. # 缺少while代码块的内容
  2. while a < 10

3.2.4. 退出交互运行

输入 exit() 即可退出交互运行。