MrLeekon 发表于 2023-9-1 23:31:10

8月学习心得:没有太多关于STM32,倒是学会了通过STM32玩蛇

8月没有太多学习,还在玩NUCLEO-F401RE,没玩透。

至于如何玩蛇(Python),我是用了一个开源的框架?组件?作者称为“跨平台的超轻量级嵌入式 Python 引擎”——Pikapython。

今天分享一下关于移植的做法,如果各位觉得没什么内容或者简单,请轻拍。

#### 步骤一:用STM32CubeMX建立一个工程

1. 打开STM32CubeMX后通过“ACCESS TO BOARD SELECTOR”
2. 选择 `NUCLEO-F401RE`
3. 进入 `Project Manager` 选项卡

   1. 设定 `Project Name` ,我设置成 `STM32F401RE_Nucleo_PikaPython_Keil`
   2. 设定 `Toolchain/IDE` 为 `MDK-ARM`(使用Keil)
   3. 设定 `Minimum Heap Size` 为 `0x4000` (16K 的堆空间),设定`Minimum Stack Size` 为 `0x1000`(4K 的栈空间)[^1]
   4. 建议设置:进入 `Code Generator` 子选项卡,勾选 `Generate peripheral initalization as a pair of '.c/.h' files per peripheral`
4. 点击右上角 `GENERATE CODE` 完成工程创建

#### 步骤二:移植前工作

由于需要使用库函数,准确来说是使用库函数重定向至串口,使用串口交互,所以需要先做串口重定向。

此处有个坑,本来用STM32CubeIDE报错才改为用MDK的,MDK莫名其妙的定义了 `__GUNC__`,导致我直接网上拷来的重定向函数有问题。也是参考网上教程[^2]改成 `#if defined ( __GNUC__ ) && !defined (__clang__)` 即可,由于不想用 MicroLib ,搜了一下,需要避免使用半主机模式[^3],胡乱咔咔的复制一通,得到下面的代码,顺便把`fgetc`也实现了。

```C
//STM32F401RE

#if !defined(__MICROLIB)
//#pragma import(__use_no_semihosting)   //AC5
__asm(".global __use_no_semihosting\n\t"); //AC6
void _sys_exit(int x) //避免使用半主机模式
{
    x = x;
}
//__use_no_semihosting被要求使用,但是_ttywrch被定义为空函数
void _ttywrch(int ch) //该函数是在半主机模式下使用的,所以要对函数 _ttywrch 覆写
{
    // 什么都不做,只是为了满足要求
    ch = ch;
}
FILE __stdout;
FILE __stdin;
#endif

#if defined ( __GNUC__ ) && !defined (__clang__)
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
    while((USART2->SR & 0X40) == 0);

    USART2->DR = (uint8_t) ch;
    return ch;
}

int fgetc(FILE* f)
{
    uint8_t ch = 0;

    while(HAL_UART_Receive(&huart2, &ch, 1, 0) != HAL_OK);

    return ch;
}
```


编译下载,测试一下 `printf` 反正能用了,至于哪部分有用,哪部分没用,后面再看了(基础不扎实的心虚[^4])。

由于需要使用Pikapython的Shell(REPL),所以需要实现一个函数 `__platform_getchar`,用于Pikapython获取输入的字符,由于是使用串口,而上面已经实现了`fgetc`,所以适配后的代码如下:

```C
char __platform_getchar(void)
{
   return getchar();
}
```

至此,移植的前提已经具备。


#### 移植

1. 在工程下,建立文件夹,名称随意,我设置为`PikaScript`
2. 下载文件包管理工具到上述目录中,打开官网(http://pikapython.com/),点击[包管理器](http://pikapython.com/doc//%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8%E4%B8%8E%E6%A8%A1%E5%9D%97%E7%AE%A1%E7%90%86.html),然后点击[点击下载包管理器](https://gitee.com/Lyon1998/pikapython/attach_files/1467185/download)即可
3. 建立`requestment.txt`,最少需要两个模块,`pikascript-core 和`PikaStdLib`,输入文档中各占一行,然后保存
4. 建立`main.py`文件,简单的引入标准库`import PikaStdLib`和打印个Hello World,`print("Hello World")`
5. 双击打开包管理器,进入自动下载所需文件,并且自动编译
6. 将`PikaScript`文件夹里包含子目录里的C文件全部加入到工程中,并把对应的目录加入到编译头文件的查找路径。
7. 在`main.c`中加入`#include "pikascript.h"`
8. 在`main`函数初始化结束后增加一句`PikaObj* pikaMain = pikaScriptInit();`即可完成移植,接上串口,复位一下就能看到信息了
9. 如果要进行REPL交互,要在上述步骤建立`pikaMain`对象后,添加一句` pikaScriptShell(pikaMain);`即可通过脚本进行交互




[^1]: (http://pikapython.com/doc/%E5%8D%81%E5%88%86%E9%92%9F%E9%83%A8%E7%BD%B2%E5%88%B0%E6%96%B0%E5%B9%B3%E5%8F%B0.html)中建议分配 4K 的栈空间和 16K 的堆空间,最少需要分配 1K 的栈空间和 4K 的堆空间
   
[^2]: (https://blog.csdn.net/xiaoyuanwuhui/article/details/110538555)
   
[^3]: 什么是半主机模式,我不懂,问了一下ChatGPT,回复见下图
   
    ![半主机模式.png](data/attachment/forum/202309/01/233020t1lytltpxejxi3cb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "半主机模式.png")
   
[^4]: 具体需要参考ARM、STM、以及编译器的官方资料了

STMCU-管管 发表于 2023-9-26 08:18:35

需要你这种心得,慢慢积累,真不错

背影101 发表于 2024-3-5 11:05:49

页: [1]
查看完整版本: 8月学习心得:没有太多关于STM32,倒是学会了通过STM32玩蛇