×

远程编程Raspberry Pi Pico

消耗积分:0 | 格式:zip | 大小:0.00 MB | 2023-06-16

杨火亭

分享资料个

描述

关于

如果您正在维护一个开源嵌入式项目,可能很难加入新开发人员,因为特定设置的复杂性和个性可能会有很大差异。此外,如果您要接收来自社区的贡献,您可能希望通过自动化测试来确保它们的有效性。出于这个原因,我开始寻找一个工作流程,让我可以远程刷新嵌入式硬件(最初只是一个 Raspberry Pi Pico),并将社区 PR 集成到带有 GitHub 操作的测试框架中。这将自动确保它们在合并更改之前通过一系列测试,从而减少嵌入式项目开发的摩擦。

概述

本指南将重点介绍使用 GitHub 代码空间设置远程刷新设备,它允许我们远程处理现有的嵌入式项目,更改代码,然后直接从在线环境中使用新代码刷新我们的 Raspberry Pi Picos。这是由运行 balenaOS 的 Raspberry Pi 4 实现的,我们从 Codespace 连接到该 Raspberry Pi 4。

好处:

  • 可重现的设置
  • 轻松入职
  • 在目标设备上自动测试

缺点:

- 需要额外的硬件

第 1 部分:balenaOS

首先,使用 balenaOS 设置 Raspberry Pi 4,以便稍后轻松连接。

1. 去这个仓库

2.点击“使用Balena部署”按钮

poYBAGN0MtWAGllSAAELmtQ0IRs805.png
 

3. 填写如图所示的选项:

poYBAGN0MteAMJBOAACXyLGB0l8361.png
 

4. 填写选项(包括您的 Wi-Fi 凭据,以便 Pi 知道如何连接到 Internet,然后连接到 Balena Cloud):

pYYBAGN0MtqAHgprAAE6f99lpsA492.png
 

5.下载balenaOS镜像

6. 用Etcher 刷你的 sd 卡

7. 将您的 Raspberry Pi Pico 插入 Raspberry Pi 4

8. 按照Pico 文档所示连接调试引脚

pYYBAGN0MtyAbMPIAAEcAv3HGSo796.jpg
 

准备好 Raspberry Pi 4 并连接 Pico,我们可以研究如何远程刷写它。

第 2 部分:代码空间

1. 分叉这个 repo

2.为你刚刚 fork 的 repo创建一个Codespace

poYBAGN0Mt-ATfEZAAGHNs5NlI8987.png
 

3.在您的 Codespace 终端上运行chmod +x pico_setup.sh

4. 运行./pico_setup.sh

5. 运行export

现在您应该能够构建一个 Pico 项目,例如此 repo 中包含的 LED 渐变示例:

6. 运行以下命令来构建淡入淡出项目 (pwm_led.c):

mkdir 构建

光盘构建

cmake..

制作

或者,我还包含了一个名为 compile.sh 的 bash 脚本,它会在您对其进行更改后再次编译您的 pwm_led.c 文件。这样,您不必每次都重新执行上述步骤。

第 3 部分:balena CLI

接下来,使用 balena CLI 轻松隧道到 Raspberry Pi 设备,以发送我们刚刚制作的编译文件 (/build/pwm_led.elf) 以远程刷新我们的 Pico。

要添加 Balena CLI,请运行以下命令:

导出

登录

然后选择凭证选项并登录到您的 balena 帐户。

现在我们有了可用的balena CLI,我们应该能够通过隧道进入我们的Raspberry Pi 4(它连接了Pico)并将.elf文件直接传递到Pico,实际上,从我们的代码空间中远程刷新它环境。

1. 运行balena devices --app MCU-remote以查找运行应用程序的设备的 UUID。

>>>https://dashboard.balena-cloud.com/devices/ /summary

2. 运行balena tunnel -p 22222:4321确保我们可以通过防火墙。

3.点击+号打开另一个终端窗口

poYBAGN0MuGAV6RgAADwPFbXUw4535.png
 

从这里开始,我们需要停留在您刚刚在 Codespaces 中打开的第二个终端窗口中。以下是将 pwm_led.elf 文件导入 Pico 的手动步骤。但是,与之前的编译脚本类似,我还提供了一个自动执行此步骤的上传脚本,因此如果您时间紧,请随意跳过此部分。

4. 找到您的容器 ID 并记下它,这将让我们将文件直接复制到在 RPi4 上运行的容器中:

ssh -Tp 4321 root@127.0.0.1 balena ps -aqf "name=闪烁"

>>>

4. 将文件添加到 RPi4 主机操作系统:

scp -P 4321./build/pwm_led.elf root@127.0.0.1:/mnt/data/

5. 将 /mnt/data/pwm_led.elf 中的文件(在主机操作系统中)复制到闪烁的容器中:

ssh -Tp 4321 root@127.0.0.1 balena cp /mnt/data/pwm_led.elf :/pico_flashing/pwm_led.elf

6. 运行此命令以 ssh 进入您的 RPi4 容器并执行获取 .elf 文件并使用 openocd 将其刷新到您的 Pico 的命令:

ssh -p 4321 root@127.0.0.1 'balena exec openocd -f interface/raspberrypi-swd.cfg -f target/rp2040.cfg -c "p​​rogram /pico_flashing/pwm_led.elf verify reset exit"'

要自动执行所有上传步骤,只需运行./upload.sh脚本。

pYYBAGN0MuSAJ7YEAAES5TMtCHE394.jpg
 

回顾一下,您已将映像部署到连接到 Raspberry Pi Pico 的 Raspberry Pi 4 上,然后使用 GitHub 代码空间更改该存储库中的代码,并通过运行 ./compile.sh 和 ./upload 远程刷新板.sh 脚本。

现在,您可以将此项目用作样板模板,以便在嵌入式设备(openocd 支持的任何设备都可以)上轻松地远程运行代码,在本例中为 Raspberry Pi Pico。更改 pwm_led.c 文件上的代码(或添加您自己的 C/C++ Pico 项目)并运行编译和上传脚本以一步远程刷新 Pico。

我希望这对您的嵌入式项目有所帮助,尤其是当您要加入新的贡献者时。我还计划另一个教程,介绍如何在收到 PR 后集成 GitHub 操作以自动在 Pico 本身上运行测试,以及能够远程运行 GDB 以在单步执行我们的代码时查看板的内存内容。请继续关注更新!


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'远程编程Raspberry Pi Pico',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);