如何使用Mac终端给树莓派pico构建C/C++程序进行开发,以及遇到各种问题该怎么处理,不使用任何IDE或编辑器(例如VS Code)
写本文的原因是官方的教程已经过时了,如果你现在按照官方教程来在 Mac 上进行配置,那么会遇到一堆问题,比如我几乎把能踩的“雷”都踩了。所以这里记录了完整过程,以及各种错误的原因和处理方法,不然以后换 Mac 了或者在其他平台遇到同样的问题,忘记怎么处理的就头大了。
接下来先记录一下整体的安装流程,会介绍一些背景知识,对于一些会错误的地方会进行说明和解释。虽然文中对一些可能出现的错误进行了介绍,但是还是单独写了一篇博客进行整理,方便以后查阅:《为树莓派Pico配置交叉编译环境和工具链arm-none-eabi-gcc时可能会遇到的错误以及解决方案》
安装流程
下载 Raspberry Pi Pico SDK
Raspberry Pi Pico SDK 提供为基于 RP2040 的设备(如 Raspberry Pi Pico)编写 C/C++ 或汇编语言程序需要使用的使用的头文件、库和构建系统,这大大提升了开发效率。
这部分的方法可以和官方介绍的方法一样,但是如果你使用 HTTPS 克隆失败了很多次,那么建议使用 SSH 或者更新 Git 试试看,GitHub 在 HTTPS cloning errors 对这个问题有简单的介绍。所以这里两种地址都列出来:
# 使用https
git clone https://github.com/raspberrypi/pico-sdk.git --branch master
# 使用 SSH
git clone git@github.com:raspberrypi/pico-sdk.git --branch master
然后进入pico-sdk
目录,初始化引用的子模块:
$ cd pico-sdk
$ git submodule update --init
这里可能需要等待很长时间,而且经常会出现错误,比如加载失败、连接超时等,需要多试试看,因为都是 HTTPS 下载的,建议根据上文连接中的介绍进行诊断。这部分真的需要耐心!
配置 Raspberry Pi Pico SDK
接下来需要在环境变量PICO_SDK_PATH
中记录pico-sdk
的根地址,这样后面 CMake 就可以找到需要的一些库、头文件等一些工具。这需要在你的 Shell 配置文件里加上这么一句:
export PICO_SDK_PATH=~/Desktop/pico/pico-sdk
接下来你可以关闭终端再次打开,或者使用source
来激活这个更改,比如:
$ source .bash_profile
后面配置其他工具时也需要类似的操作,如果你想进一步了解这步的知识,可以看我的另一篇博客:《macOS在终端上如何直接使用脚本或者下载的程序》。
此外,虽然这里还没提及 CMake,但是还有另一种方法,你还可以在CMakeLists.txt
中的project(...)
部分之前加上这句话也可以设置环境变量PICO_SDK_PATH
:
set(PICO_SDK_PATH ~/Desktop/pico/pico-sdk)
后面的路径用不用双引号包裹都行,一般不会出现解析错误,保险起见可以加。
这种方法的好处在于对不同项目可以设置不同的环境变量,你可以根据自己的需求进行选择。
安装 CMake
CMake 是一个构建、测试、打包的工具,可以生成make
可以构建的makefile
文件。这是因为make
在所有类 Unix 都是自带的,但是makefile
文件编写不是很容易。
这里我们直接使用brew
进行安装即可:
brew install cmake
使用下面的命令查看版本来确认已经安装:
$ cmake --version
cmake version 3.27.1CMake suite maintained and supported by Kitware (kitware.com/cmake).
(介绍CMake的博客还没写完,写完会贴个链接在这)
工具链
为什么需要工具链
在 Mac 上给树莓派 Pico 进行开发是需要交叉编译的。交叉编译就是在系统上编译另一种系统甚至另一个平台的程序,比如我是在 X86 架构的 macOS 上编译 Arm 架构 Linux 的可执行程序。为了实现这个目的需要一套工具来编译,比如目标系统、目标平台的编译器、库,这套工具就是常说的工具链(Toolchain)。因为本机上的编译器clang
和库是给 macOS 编译程序的,编译出来的可执行程序是Mach-O executable
格式,而不是 Linux 需要的格式。顺道一提,这里树莓派 Pico 需要导入的可执行程序格式为UF2 firmware image, family Raspberry Pi RP2040
。
下载工具链
给树莓派 Pico 进行交叉编译的工具链名为:arm-none-eabi-gcc,使用方法和gcc
一样,但是一般很少直接使用 arm-none-eabi-gcc 进行编译,都是使用 CMake 进行安装。
需要注意的是,下载工具链不要直接使用brew
下载。因为brew
安装的版本可能是不是树莓派 Pico 对应的版本或者配置错误,这样会导致一些错误。比如当前brew
下载的版本只有 200MB,而官网的版本有 845MB,如果使用brew
下载的版本,那么虽然也是 12.3 版本,cmake
构建也没有问题,但是到make
这步的时候就会显示以下错误:
-- Build files have been written to: /shared/pico-setup/pico/pico-examples/build/elf2uf2
[ 0%] Performing build step for 'ELF2UF2Build'
Scanning dependencies of target elf2uf2
[ 50%] Building CXX object CMakeFiles/elf2uf2.dir/main.cpp.o
[100%] Linking CXX executable elf2uf2
[100%] Built target elf2uf2
[ 0%] No install step for 'ELF2UF2Build'
[ 0%] Completed 'ELF2UF2Build'
[ 0%] Built target ELF2UF2Build
这时候用下面的命令卸载、清理掉brew
安装的内容:
# 卸载arm-none-eabi-gcc
$ brew uninstall arm-none-eabi-gcc
# 清理掉一些下载文件
$ brew cleanup arm-none-eabi-gcc
# brew默认将二进制文件安装到/usr/local/bin/目录下,虽然前面卸载了,但是可能会有一些残留,手动删一下
$ sudo rm /usr/local/bin/arm-none-eabi-*
这时候再从官网下载即可。
进入 Arm GNU Toolchain Downloads,用页面搜索功能搜一下“macOS”,因为链接太多了。你会看到光是在 macOS 下面就有这么多链接:
选择你对应平台(就是处理器架构)的AArch32 bare-metal target (arm-none-eabi)
中的链接点击下载。选择AArch32
因为树莓派 Pico 的微控制器 RP2040 包含的 Arm Cortex M0 是 32 位的,也就是AArch32
,如果你下成AArch64 bare-metal target (aarch64-none-elf)
是没法编译的。
安装工具链
如果你下载的是 tar.xz 格式的,那么使用下面的指令将其解压:
$ tar xvf arm-gnu-toolchain-版本号-darwin-arm64-arm-none-eabi.tar.xz
然后将其放在一个你喜欢但是不经常动的位置。
如果你下载的是 PKG 格式的,那么安装之后会放在“应用程序”目录/Applications/
下,如下:
这时候这个目录的绝对地址就是/Applications/ArmGNUToolchain/
。
配置工具链
接下来要像之前一样配置一下工具链,好让cmake
构建的时候找到需要的编译器、汇编器等工具以及库。
配置方法是在环境变量PATH
中添加上arm-none-eabi
的二进制目录,这样就可以使用里面的工具了。
如果是使用 PKG 安装的,那么在 Shell 配置文件中添加如下语句(版本不同可以略有变化):
export PATH="$PATH:/Applications/ArmGNUToolchain/版本号/arm-none-eabi/bin"
如果你是下载的 tar.xz
,那么在 Shell 配置文件中添加如下语句(版本不同可以略有变化):
export PATH="$PATH:~/arm-gnu-toolchain-12.3.rel1-darwin-arm64-arm-none-eabi/bin"
~/arm-gnu-toolchain-12.3.rel1-darwin-arm64-arm-none-eabi
是你之前下载解压好之后放的位置,选择里面第一层的bin
目录,该目录应该包含 C/C++ 的编译器arm-none-eabi-gcc
和arm-none-eabi-g++
,内容大致如下:
不要选择arm-none-eabi
里的bin
。
如果你完成了以上步骤,那么就可以为树莓派 Pico 进行交叉编译了。
构建项目
这里我们使用一个自制的例子和官方例子 pico-examples 来介绍一下构建项目中的一些命令。
首先新建一个pico
目录来存放这些例子,并且进入该命令:
$ mkdir pico
$ cd pico
简单的例子
接下来介绍简单的自制例子。按照以下命令新建一个目录blink
,然后在里面新建一些文件和目录:
# 新建一个`blink`目录并进入
$ mkdir blink
$ cd blink
# 创建两个空白文件 blink.c 和 CMakeLists.txt
$ touch blink.c CMakeLists.txt
# 将 pico-sdk 项目中的 pico_sdk_import.cmake 文件复制到当前目录下
# 如果你之前没有设置PICO_SDK_PATH,那么就使用你的pico-sdk路径
$ cp $PICO_SDK_PATH/external/pico_sdk_import.cmake .
然后在blink.c
文件中输入以下内容,这些编译后会让树莓派 Pico 上的 LED 灯开始闪烁:
#include "pico/stdlib.h"const uint LED_PIN = 25;int main() {gpio_init(LED_PIN);gpio_set_dir(LED_PIN, GPIO_OUT);gpio_put(LED_PIN, 0);while (true) {gpio_put(LED_PIN, 1);sleep_ms(250);gpio_put(LED_PIN, 0);sleep_ms(250);}
}
在CMakeLists.txt
文件中输入以下内容:
cmake_minimum_required(VERSION 3.17)include(pico_sdk_import.cmake)# 这两个是设置目标系统和目标平台的,如果不加这两句也行,但是第一次运行 cmake 构建时会需要较长时间寻找合适的编译器,后面再构建就没区别了
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)project(blink)pico_sdk_init()add_executable(blink
blink.c
)target_link_libraries(blink pico_stdlib)pico_add_extra_outputs(blink)
这时候新建一个名为build
的目录来存放构建后的内容,然后进入。
$ mkdir build
$ cd build
这是一个良好的构建项目的习惯,因为会很方便清理一些构建后的文件,也是cmake
的惯例。
然后使用以下命令进行构建:
$ cmake ..
$ make -j4
如果在构建过程中出现任何错误,都建议完全清空build
目录,再进行下次构建!
这里你可能会好奇为什么使用make -j4
这个命令,而不是直接使用make
。其实两个都可以,但是推荐使用选项-j4
,原因在“pico-examples”部分会有说明。
构建成功会显示以下内容:
而此时的build
目录下内容如下:
这时候先继续讲如何构建 pico-examples,如果你想马上知道如何导入可以跳到后面。
pico-examples
回到pico
目录下:
$ cd ../..
首先下载 pico-examples:
# 用 https
$ git clone https://github.com/raspberrypi/pico-examples.git
# 用 SSH
$ git clone git@github.com:raspberrypi/pico-examples.git
同样进入pico-examples
目录,然后新建build
目录,在进入其中:
$ cd pico-examples
$ mkdir build
$ cd build
然后就像简单的例子一样使用下面的命令来构建所有的项目:
$ cmake ..
$ make -j4
为什么make
要使用选项-j
这里解释一下为什么使用make -j4
而不是make
:
- 选项
-j4
意思是“同时运行 4 个任务或者命令”,如果直接使用make
可能会出现fatal error: cannot read spec file ‘nosys.specs’: No such file or directory
的错误,也就是一个好了得等另外一个。 - 不过使用
-j4
的主要目的是为了加快构建速度。
二者的速度差距有多少呢?我进行了测试,可以看到实际花费的时间(real
)减少到三分之一左右,你可以自己尝试看看。
这是因为-j4
利用了更多的进程,而更多的进程意味着更多的线程。这样可以提升 CPU 的利用率和降低程序运行时间,所以你可以看到使用使用-j4
的用户使用 CPU 时间(user
)和系统使用 CPU 时间(sys
)都要高于不使用-j4
的情况。
这里的4
可以根据你的处理器线程数进行调整,由于这个任务的 CPU 利用率很高,阻塞、睡眠的情况少,所以上限大概就是你的线程数,更高的值带来的提升比较少。但是4
的个很不错的选择,因为:
- 如果尝试过多线程编程就知道,
4
线程是一个拐点,很多任务超过4
之后线程数带来的性能提升曲线会放缓,之前增加一个线程带来的提升可能需要增加两到三个线程才能达到。 - 很多处理器可以同时运行的线程数还是不太够,而
4
是很多机器能接受的。
如果你拥有一个核心很多的处理器,可以试试看设置为最高的速度,用time make -jxx
测试一下时间,如果可以的话评论留言让我记录一下哦。
导入编译好后的二进制文件
导入的方法很简单,首先拔下来你的树莓派 Pico,然后按住树莓派上的白色按钮“BOOTSEl”,如下:
然后插上线连接到 Mac 上。这样树莓派 Pico 会进入 USB 大容量存储模式。
这时就会发现出现了这样的一个 USB 存储装置:
然后将我们之前构建好的项目中的.uf2
文件拖入这里即可。拖入后会显示“磁盘没有正常推出”,对此不要紧张,是正常的。
如果将一开始blink
项目中的blink.uf2
拖入,那么就可以看到树莓派 Pico 上的 LED 开始闪烁了。
断开再次插上也会继续闪烁,如果你想重置树莓派 Pico 来让他別闪了,那么再次断开按住按钮进入 USB 存储模式就会重置清空之前的二进制文件。
最后,关于构建中还可能会出现一些问题,这些问题我会单独开一篇来进行整理(已将链接贴到开头了)。
希望能帮到有需要的人~
相关文章:

如何使用Mac终端给树莓派pico构建C/C++程序进行开发,以及遇到各种问题该怎么处理,不使用任何IDE或编辑器(例如VS Code)
写本文的原因是官方的教程已经过时了,如果你现在按照官方教程来在 Mac 上进行配置,那么会遇到一堆问题,比如我几乎把能踩的“雷”都踩了。所以这里记录了完整过程,以及各种错误的原因和处理方法,不然以后换 Mac 了或者…...
linux 关机和重启
关机和重启 关机和重启之前最好先数据数据同步一下 # 将数据由内存同步到硬盘sync 关机 #shutdown [选项] 时间#立即进入维护模式shutdown now#立即重启shutdown -r now#20:00 重新启动计算机shutdown -r 20:00& #立即关机shutdown -h now# 20:00 关闭计算机shutdown -h 20…...

Python(八十三)字符串的比较操作
❤️ 专栏简介:本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中,我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 :本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…...
Java面试
Java面试宝典是一本面向Java开发者的面试准备指南,旨在帮助准备参加Java相关职位面试的人们更好地准备和应对面试。以下是一些可能在Java面试中涉及的主题和问题,供您参考: Java基础知识: 什么是Java虚拟机(JVM&#x…...
基于java的voliate关键字详解
voliate关键字的作用: 一、内存可见性 基于缓存一致性协议,当用voliate关键字修饰的变量改动时,cpu会通知其他线程,缓存已被修改,需要更新缓存。这样每个线程都能获取到最新的变量值。 二、基于内存屏障的防止指令重排 用voli…...

企业计算机服务器中了360后缀勒索病毒怎么办,勒索病毒解密数据恢复
随着计算机技术的不断发展,企业的办公系统得到了很大提升,但是随之而来的网络安全威胁也不断增加,勒索病毒的攻击事件时有发生。近期,我们收到某地连锁超市的求助,企业的计算机服务器遭到了360后缀勒索病毒攻击&#x…...

W6100-EVB-PICO 做TCP Server进行回环测试(六)
前言 上一章我们用W6100-EVB-PICO开发板做TCP 客户端连接服务器进行数据回环测试,那么本章将用开发板做TCP服务器来进行数据回环测试。 TCP是什么?什么是TCP Server?能干什么? TCP (Transmission Control Protocol) 是一种面向连…...
前端小兔鲜儿2
day10-小兔鲜儿 01-banner-轮播图 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1FWNmPpj-1691944251554)(assets/1680344354682.png)] index.css HTML结构 <!-- banner --><div class"banner"><div class"wrappe…...

Pycharm 双击启动失败?
事故 双击 Pycharm 后,出现加载工程,我不想加载这个工程,就点击了弹出的 cancle 取消按钮。然后再到桌面双击 Pycharm 却发现无法启动了。哪怕以管理员权限运行也没用,就是不出界面。 原因未知 CtrlshiftESC 打开后台ÿ…...
spring 事务回滚失败异常
1 背景介绍 事务模板里抛异常,抛异常前的update操作成功,事务没有回滚成功,业务数据还是落db了。debug代码,发现GenericConnectionContext类中derivedConnectionMap是空的,导致回滚代码没有执行 2 解决方案 保证事务…...

Kafka 01——Kafka的安装及简单入门使用
Kafka 01——Kafka的安装及简单入门使用 1. 下载安装1.1 JDK的安装1.2 Zookeeper的安装1.2.1 关于Zookeeper版本的选择1.2.2 下载、安装Zookeeper 1.3 kafka的安装1.3.1 下载1.3.2 解压1.3.3 修改配置文件 2. 启动 kafka2.1 Kafka启动2.2 启动 kafka 遇到的问题2.2.1 问题12.2.…...

【爬虫】爬取旅行评论和评分
以马蜂窝“普达措国家公园”为例,其评论高达3000多条,但这3000多条并非是完全向用户展示的,向用户展示的只有5页,数了一下每页15条评论,也就是75条评论,有点太少了吧! 因此想了个办法尽可能多爬…...

C++ 泛型编程:函数模板
文章目录 前言一、什么是泛型编程二、函数模板三、函数模板的使用四、多参数函数模板五,示例代码:总结 前言 当需要编写通用的代码以处理不同类型的数据时,C 中的函数模板是一个很有用的工具。函数模板允许我们编写一个通用的函数定义&#…...
.NET实现解析字符串表达式
一、引子功能需求 我们创建了一个 School 对象,其中包含了教师列表和学生列表。现在,我们需要计算教师平均年龄和学生平均年龄。 //创建对象 School school new School() {Name "小菜学园",Teachers new List<Teacher>(){new Teach…...

Ae 效果:CC Environment
透视/CC Environment Perspective/CC Environment CC Environment(CC 环境)主要用于创建 3D 环境映射,可以将一个 2D 图像转换为 3D 空间的反射或折射。该效果通常用于模拟真实世界的全景相机镜头和环境反射。 在实际操作中,可将效…...
PotgreSQL 基于时间点恢复
文章目录 前言1. WAL 日志1.1 WAL 配置 2. pg_basebackup2.1 常用命令 3. 全备恢复实验3.1 进行一个全备3.2 写入增量数据3.3 模拟备份恢复 总结 前言 本篇文章介绍 PostgreSQL 基于时间点恢复(point-in-time-recover)需要的条件及恢复过程,…...

③ vue组件
vue组件创建 在App.vue中添加。 技巧:先import,把vue组件地址写出来。然后在template中写名字。剩下的就自动生成。要看下import有没有多生成什么。 注意1: 注意2: 不只是能在App.vue中引入组件。任意组件中都可以引用其他组件…...

政策因子条件列表类型
type:1(多选下拉输入) 目前选项是本地写死得,传参拼接了carOwner这些东西,形式是多选输入 type:2 (普通指定形式) type:3(普通区间形式) type:4 (指定输入) 指定除外得特殊一种&…...

python中yield关键字
yield和return 理解一个东西最好的办法就是找一个和它类似的东西,然后再搞清楚它们之间的区别。 yield最类似的东西就是return,因为他们起到了同样的作用:返回值。 看这个return的函数: def have_some_wine():print(先开一瓶酒&a…...

2023年10款常用的Mac工具合集
Typora Typora 是一款由 Abner Lee 开发的轻量级 Markdown 编辑器,与其他 Markdown 编辑器不同的是,Typora 没有采用源代码和预览双栏显示的方式,而是采用所见即所得的编辑方式,实现了即时预览的功能,但也可切换至源代…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

渗透实战PortSwigger Labs指南:自定义标签XSS和SVG XSS利用
阻止除自定义标签之外的所有标签 先输入一些标签测试,说是全部标签都被禁了 除了自定义的 自定义<my-tag onmouseoveralert(xss)> <my-tag idx onfocusalert(document.cookie) tabindex1> onfocus 当元素获得焦点时(如通过点击或键盘导航&…...

【Java多线程从青铜到王者】单例设计模式(八)
wait和sleep的区别 我们的wait也是提供了一个还有超时时间的版本,sleep也是可以指定时间的,也就是说时间一到就会解除阻塞,继续执行 wait和sleep都能被提前唤醒(虽然时间还没有到也可以提前唤醒),wait能被notify提前唤醒…...

简约商务通用宣传年终总结12套PPT模版分享
IOS风格企业宣传PPT模版,年终工作总结PPT模版,简约精致扁平化商务通用动画PPT模版,素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...

开疆智能Ethernet/IP转Modbus网关连接鸣志步进电机驱动器配置案例
在工业自动化控制系统中,常常会遇到不同品牌和通信协议的设备需要协同工作的情况。本案例中,客户现场采用了 罗克韦尔PLC,但需要控制的变频器仅支持 ModbusRTU 协议。为了实现PLC 对变频器的有效控制与监控,引入了开疆智能Etherne…...