VS Code + WSL 搭建 RaspberryPi Pico 开发环境
前面老周写一堆 .NET 与树莓派相关的水文。其实使用的是.net的 IOT 库,并不只是树莓派,其他运行 Linux 的开发板都适用,只要有 GPIO 就行。老周好像在哪看到过,有 USB 转GPIO的模块,直接插在电脑上也能使用 IOT 库。
不管是树莓派,还是 Arduino 系列的,或是 ESP 系列的,你会发现,Iot 框架实际都是这几个东东组成(基本都是这套路):
1、GPIO:数字引脚,读写高 / 低电平,即处理数字信号;
2、串口通信;
3、ADC:即读取模拟量(模数转换),Arduino系列、ESP系列、STM32系列都有ADC功能,但作为微型电脑版的树莓派是没有的,前面老周写过,需要使用其他ADC模块;
4、I2C(IIC)协议;
5、SPI 协议;
6、DAC:数字转模拟,这个好像很多板子没有,据老周的有限知识量,ESP32模组有集成 8 位的DAC功能。一般使用输出模拟电压是没问题,但要作为音频信号输出就水了点。所以一般需要外接支持 I2S(IIS)的音频解码板。
-------------------------------------------------------------------------------------------------------------------------------------------
按照老周的折腾习惯,折腾完大草莓,就应该折腾小草莓了。小草莓就是——Raspberry pi Pico。也许树莓派基金会也觉得作为微型电脑的大草莓,搞物联网有些大材小用了。尽管资源挺多,但还真不能英特尔系列的开发板比,毕竟处理器功耗是很关键的,你想节能自然要牺牲执行速度了。
Raspberry Pi Pico 用的是自主研发的 RP2040 处理器,架构是ARM,作为专用 GPIO 控制板,性能肯定能甩 Arduino Uno 五千条高速公路,而且价格比 Uno 低很多。某宝一般售价是 28 - 38 之间。当然,会有个别不会做生意的,一上来就卖 150 元的,这些卖家显然不知道网购是可以货比万家的,他们估计是为了不忘初心,坚守零销量第一阵线。
这里就不得不提 ESP32 开发板,引脚虽然比 RP Pico 少一些,但有 Wifi,有蓝牙,有ADC,有DAC,有霍尔传感器等,价格一般 20 多,是比 rp pico 便宜些。不过,你买的ESP32开发板只有模组是乐鑫的,板子是一些小电子厂做的(也不排除有大厂),乐鑫官方的开发板也挺贵的。
虽然没有 WiFi 没有蓝牙,不过 RP Pico 的性价比还是不错的,而且功耗确实很低。老周曾说过用它做了门铃,在家里已经运行了大半年了,除了中途天线模块烧了(这质量?)换了一个新模块(12元左右),就是一直运行着。由于消耗电流太小了,充电宝供电会自动断电,只能用 5V1A 的充电头供电。日常工作电流都在微安级别,特省电。
小草莓目前是不能用 .NET 开发的(估计以后也不太可能会支持),按官方文档,目前支持C/C++,Micropython。当然也有 Arduino 插件,但功能不完整。刚发布的时候耍了一下,只有一路 UART 可以用,另一路没反应,不知道现在修复了没有。至于 Micropython,我只能用两个字来评价——【无语】。因此,最优方案还是 C 语言(C++也行,但SDK基本是C写的)。
这个SDK,由于官方的定位是希望你买了小草莓,顺便买大草莓,即优先推荐你在 Raspberry Pi3 或者 Raspberry Pi 4 系列上进行开发。但是,老周作为全国人民公认的老实人,不得不说一句实话,你这板子上写代码,能干得我的台式机吗?所以嘛,还是在PC上写代码刺激。其实,SDK是可以在PC上用的,Windows、macOS、Linux上都行,官方和网上都有教程。
可能是老周最近运气不太好,按照文档步骤,在 Windows 上没有弄成功过,试过几次都失败,CMake 报的错误应该是找不到C编译器。反正这个目前没法解决,环境变量也没置正确,路径中也没有空格,也没有中文,也没有长文件名,但还是找不到编译器。毕竟官方是想让你在 Raspberry Pi 上开发的,大概是对Linux比较友好。
等等,这个其实也好办,不是说 Win 10 是最大的 Linux 发行版吗?嗯,这样就OK了,既可以用 Windows,又可以友好。
唉,回头看一看内容,哇,原来上面写了那么多废话,现在才进入主题,这要是放在高考作文,肯定是满分作文无疑,很自豪ing。
======================================================================================
相信各位同学如果玩过大草莓,会知道 Raspbian 其实是 Debian 发行版的变种,所以,老周在 WSL 中优先考虑 Debian。这里老周顺便演示一下如何把 Linux 子系统转移到其他分区,方法很简单,不用改配置,不用改权限。虽然老周把一整块 512 G的SSD都作为系统分区,但软件装多了好像也不怎么够用,故,还是把子系统弄到其他分区上好一些,谁知道它将来会占用多大空间呢,Linux 在安装工具和更新时,经常会依赖安装一大堆东西。
好了,不扯F话了,开工。
1、到Windows商店找到 Debian 君,安装。这个应该会了吧,不会的话可以问班主任。
2、坐和等待。
3、安装完启动它,初始化完后会提示你输入用户名,如demo。
4、回车后,要求你输入密码,比如 123456。反正是子系统,设置个䜭智密码也没关系。
5、关闭它,对,关掉,现在啥也不用干。
6、打开CMD,或者PowerShell,输入以下命令,看看刚刚安装的发行版。
wsl --list --all
看到 Debian 就没错了。
**注:WSL有 1 和 2 两个版本,这个随便选,如果你要跨 Linux 和 Windows 操作文件,就用版本 1,因为版本 2 是用虚拟机的,读写较慢。
7、记下发行名称 Debian,然后使用 export 命令,把它导出备份,假如我存放在E盘,文件类型是 .tar。
wsl --export Debian E:\mydebian.tar
export 表示导出,这命令本来是用来备份的,不过这里可以发挥一下,用作迁移。E:\mydebian.tar就是导出后的文件。因为是初始系统,只有200多M。
8、执行以下WSL命令,注销掉 Debian 子系统。
wsl --unregister Debian
这时候你再执行一次 wsl --list 就啥都没有了。
9、在 D 盘里(你可以选其他盘)建一个目录,名字你喜欢,比如我建了两层目录:Linux/Debian,主要是考虑到可能将来要迁移其他发行版。
10、执行以下命令重新导入 Debian。
wsl --import Debian D:\Linux\Debian E:\mydebian.tar --version 1
Debian 是发行版名称,D:\Linux\Debian 是刚刚建的目录,用来放子系统;后面的.tar 文件就是刚才导出的备份;--version 指定使用 WSL 1。
再执行一次 wsl --list 就能看到子系统又回来了。
11、【可选】把刚从商店安装的 Debian 卸载。不卸也行,反正也不占地方,如果卸了,也不怕,你只需要在任意路径下执行 bash 就能进入子系统了。老周建议不要卸,因为它是一个启动器,而且还可以执行 config 命令进行一些配置(这不,下一步就用上了)。
12、这样导入之后,子系统默认启动到 root 上下文的。咱们一般是没有必要的,所以,我们执行一下 config,重新设置一下默认用户。
debian config --default-user demo
Windows 对大小写不敏感,所以 debian 也能找到 Debian 启动器(你看,幸好刚刚没有把 Debian 卸载,不然执行不了)。“demo” 就是老周前面初始化时设置的用户名。
万一,我说的是万一,你一时手残,把Debian卸了,咋办?如果你有耐心,可以来一句 wsl --unregister Debian,然后从头来过,就是从第一步开始。当然了,补救方法是有的。可以利用一下 wsl.conf 文件。
进入子系统,cd 到 /etc 目录下,默认应该不存在 wsl.conf 文件的,所以咱们手动建一个。
sudo nano /etc/wsl.conf
然后输入以下配置:
[user]
default=demo
【Ctrl+O】保存,【Ctrl+X】退出。
这是典型的 .ini 文件格式,用中括号包起来的是配置节的名称,这里咱们配置了 user 节,接着另起一行,写配置项,格式 key=val。如果有多条配置项,那就一行一条。
13、子系统改成国内源,此处省略 5000 个字,相信你也会了,老周就不F话了。如果网速可以,就不用改国内源了。
安装工具链
在克隆SDK前,必须先安装工具链。按照官方教程,就下面这一句完成。
sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib python3
用 bash 命令打开 Debian 子系统,默认是 root 上下文,所以,如果你启动子系统后是root上下文,就不用加 sudo 了。这个得占约 2 G的空间,慢慢等吧。今天运气好,下载速度 5MB/S ,节约了一些时间。
注意不要漏掉 python3,不然后面会出错。
下载SDK
下载SDK是克隆 github 上面的源代码。所以先安装git。
sudo apt update && sudo apt install git
还要装个 wget。
sudo apt install wget
然而事情不是当初想的那么简单,github 上面的代码能否拉下来,真的需要充值运气。十有八九会失败,就算不是全失败都会有一部分文件下载不了。所以,还要加上 cgit(前面装 wget 就是为了这时候用)。
sudo wget http://cgit.killf.info/cgit_linux_latest -O /usr/local/bin/cgit && sudo chmod 755 /usr/local/bin/cgit
好,现在,尝试克隆一下SDK。先切换到 Home 目录。
cd ~
用刚安装的 cgit 来克隆。
cgit clone https://github.com/raspberrypi/pico-sdk
速度不错,克隆完后,会在你的用户目录下产生个 pico-sdk 目录。如果你是用 root 上下文运行的,那么目录是在 /root 下面,至于如何处理,你自己看着办,可以移到非 root 的用户目录下。
其实到这里就能用了,源代码不多,6到7M的大小。不过它依赖一个 tinyUSB 的库,用来进行USB通信的,这个并不是必须的,如果你不使用 USB 串口,可以不需要这个模块。如果要的话,就加上这两句:
cd pico-sdk
cgit submodule update --init
最后,打开 /etc 下面的 profile,配置一下环境变量,变量名为 PICO_SDK_PATH,指向刚才的 pico-sdk 目录。
sudo nano /etc/profile
export PICO_SDK_PATH=/home/demo/pico-sdk
这一行是加到文件的最后一行。保存退出。
让配置马上生效,执行一下 source 命令。
source /etc/profile
这个环境变量是系统级别的,其他用户也能用,如果只想给当前用户配置,就用 $HOME/.profile 文件(profile 前面有个小数点,在Linux中表示隐藏文件)。
创建项目写代码
打开 VS Code,保证这三个插件已安装:
1、C/C++扩展,微软官方的;
2、CMake Tool,也是微软官方的;
3、Remote-WSL,用来访问子系统的;
4、CMake,这个可选,可以不装,非官方。
在VS Code 中打开子系统中的目录,有个很简单的方法。
假如,我在 home 目录下建个目录,叫 my,用来放项目。
mkdir my
然后进入 my。
cd my
接着输入:
code .
第一次用会安装一些包包,然后就自动启动VSCocde,前提是你得把 VS Code 的路径添加到 PATH 变量中,这个是在Windows中的Code,PATH也是在Windows中配置的,不是Linux子系统。
这时候,C++插件和CMake Tools插件还要在WSL中再安装一次,成功之后会让选编译器。
选择 arm-none-eabi。
在项目目录下建个新文件,名为 CMakeLists.txt,这个名字请区分大小写,而且不要乱改名字,CMake 专属名称。然后在这个文本文件中输入:
cmake_minimum_required(VERSION 3.13) include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake) project(myapp) pico_sdk_init() add_executable(sb "app.c") pico_add_extra_outputs(sb) target_link_libraries(sb pico_stdlib)
这是最简单的项目配置,下面老周解析一下。
第一行,从字面意思猜猜,对了,设定支持的最低 CMake 版本号,可以随便写,不要比当前安装的高就行,比如安装了 3.18,不要设置成 13.25,但可以设置为 3.15。
第二行,include 引入 RPI Pico SDK专用的 cmake 文件,官方教程里是让你先把这个文件复制到项目中,然后再用相对路径引用。这里我懒得复制,直接指向文件原路径,其中 PICO_SDK_PATH 是配置的环境变量指向 /home/demo/pico-sdk 目录。
第三行,project,指定本项目的名称,给它取个你喜欢的名字就行,我这里是“myapp”,双引号可用可不用。
第四行,调用一个宏,叫 pico_sdk_init,这个就是从官方SDK的cmake文件中导入的。
第五行,add_executable 添加咱们项目中的源代码文件,比如 app.c,第一个参数是指定一个 target 的名称,也是可以随便取,不要和cmake保留名称冲突就行(冲突了它会提示的,所以不用怕),这个target在整个项目中必须唯一。这里我取了个很低俗的名字,叫"sb"。
第六行,pico_add_extra_outputs,指定程序编译后导出的二进制文件格式,这里会生成N种格式,如 .bin,.elf,.dis,.hex,.uf2。其中,我们刷到 RPI Pico 上,用 uf2 文件很方便,像U盘一样,直接放进去就行了。uf2 格式可以像U盘/移动硬盘拖文件的方式来为设置更新固件,非常的傻瓜化操作,也是微软的大法之一。
pico_add_extra_outputs 是个函数,在 pico-sdk\src\rp2_common.cmake 文件中,它调用了另外四个函数:
pico_add_hex_output(${TARGET}):生成 hex 格式文件;
pico_add_bin_output(${TARGET}):生成 bin 格式文件;
pico_add_dis_output(${TARGET}):生成 dis 格式文件;
pico_add_uf2_output(${TARGET}):生成 uf2 格式文件。
第七行,target_link_libraries(sb pico_stdlib),sb也是咱们项目中唯一的 target 名称,一定要和上面的命令一致,不然就无法把标准库链接到当前项目中。pico_stdlib,是 pico 的标准库,官方文档把这些名称称为“接口”,它链接了一些常用的库,比如 GPIO,UART 都在里面。
target_link_libraries(pico_stdlib INTERFACE
pico_stdlib_headers
pico_platform
pico_runtime
pico_stdio
pico_time
)
target_link_libraries(pico_stdlib_headers INTERFACE
hardware_gpio
hardware_uart
hardware_divider
pico_time
pico_util
)
所以,你如果要简单操作 GPIO,那么不需要链接其他库,pico_stdlib 已包含,头文件包含的写法是 #include “pico/stdlib”,把下划线换成“/”,整个SDK的库都是这种规律,比如 hardware_uart,头文件为 "hardware/uart.h"。
新建一个 app.c 文件,我们写代码。
#include <stdio.h> #include "pico/stdlib.h" int main() { return 0; }
纯用来演示,所以就写得这么简陋。
在 CMake 的配置阶段,极大的概率会发生这样的错误:
因为 CMake 会先 CTest 一下,看看你配置的工具能不能用。这个错误很让人头痛,虽然网上能找到不少方法,但是那些方法是直接传参数给 arm-none-eabi-gcc 编译器的,而我们这里是用 CMake 来完成整套工作的。
arm-none-eabi-gcc -o XXX XXX.c -g --specs=nosys.specs
故,咱们要在VS Code 里面配置一下 CMake 工个。VS Code 窗口左下角有个【管理】按钮(一个齿轮图标),然后选【设置】,找到 扩展 -- CMake Tools Configuration ,再找到 Configure Settings。
点击“在 settings.json 中编辑”,然后在 JSON 文档中输入:
"cmake.configureSettings": { "CMAKE_EXE_LINKER_FLAGS": "--specs=nano.specs" }
CMAKE_EXE_LINKER_FLAGS 是针对链接器的选项,它的值就是上面的 --specs=nano.specs 参数。
修改后保存关闭文件,再 config 一次 CMake 就没问题了,build 也能顺利通过。
好了,今天的文章就水到这儿了,有空老周将继续水。