BeagleBone Black 网页 LED 闪烁控制器
该项目使用了BeagleBone Black,实现了网页 LED闪烁控制器的设计,它的主要功能为:在 BeagleBone Black 运行一个 Web 服务器,提供一个网页给用户控制 LED 的闪烁。LED 闪烁通过 PRU 实现。。
标签
Funpack活动
FunPack3-5
Rust
BeagleBone Black
学嵌入式的Momo
更新2025-01-13
9

项目介绍

这次项目基于 BeagleBone Black ,通过其 PRU 控制 LED 的闪烁,同时通过 Web 服务提供一个网页给用户控制 LED 闪烁的开关。



BeagleBone Black 是一个低成本、高扩展性、社区支持的开发平台,支持运行 Linux 系统,它配备了最少的外围设备,让用户可以体验处理器的强大功能,还提供了多种外设接口,可以方便扩展和开发。


PRU(Programmable Real-Time Units)是独立在 ARM 核心之后的 32位微处理器,可以单周期地访问内存和外设,可以用来实现复杂的实时控制功能。

环境搭建

这次开发使用了 ArchLinux,没有官方的支持,需要正确配置 PRU 编译器和 ARM 交叉编译器。


Ti 提供了官方的 PRU 编译器,AUR 上有现成的打包脚本,使用下面命令安装:

paru -S ti-pru-cgt

同时需要 Ti 提供的 pru-software-support-package,可以在 Ti 官网下载。


Web 服务使用 Rust 开发,需要用一个 ARM 的交叉编译器进行链接,这里使用了 musl.cc 提供的工具链:

wget https://musl.cc/armv7l-linux-musleabihf-cross.tgz
tar xf armv7l-linux-musleabihf-cross.tgz
fish_add_path ~/armv7l-linux-musleabihf-cross/bin

配置 Cargo 使用上面的工具链进行静态链接,在 cargo 配置文件添加:

[target.armv7-unknown-linux-musleabihf]
linker = "armv7l-linux-musleabihf-gcc"
rustflags = ["-Ctarget-feature=+crt-static"]

通过 rustup 添加 armv7-unknown-linux-musleabihf target:

rustup target add armv7-unknown-linux-musleabihf

程序实现

设计框图

实现分为两个部分:

  • PRU 程序:用来实现 LED 闪烁
  • Web 服务:提供网页和接口给用户控制 PRU 程序,运行在 Linux 系统上面,使用 Rust 开发


PRU 控制 LED 闪烁

PRU 控制参考了 PRU Cookbook 提供例子。首先需要配置编译器和软件支持包的路径。可以在 Makefile 里配置:

PRU_CGT:=/opt/ti-pru-cgt
PRU_SUPPORT:=/home/momo/beagle/pru-software-support-package

因为我是在笔记本上交叉编译,所有 PRU Cookbook 里的检测型号的功能没有用,可以直接在 Makefile 里写上配置:

CHIP=am335x
CHIP_REV=am335x
PRU_DIR=/sys/class/remoteproc/remoteproc1
PRUN=0
PROC=pru

配置完成后,可以直接进行编译:

make TARGET=blink.pru0 


源代码基于 hello.pru0.c 稍作修改,改成无限循环和加快闪烁频率:

#include <stdint.h>
#include <pru_cfg.h>
#include "resource_table_empty.h"
#include "prugpio.h"

volatile register unsigned int __R30;
volatile register unsigned int __R31;

void main(void) {
int i;

uint32_t *gpio1 = (uint32_t *)GPIO1;

/* Clear SYSCFG[STANDBY_INIT] to enable OCP master port */
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;

for(;;) { // 改成无限循环
gpio1[GPIO_SETDATAOUT] = USR3; // The the USR3 LED on

__delay_cycles(500000000/10); // Wait 1/4 second

gpio1[GPIO_CLEARDATAOUT] = USR3;

__delay_cycles(500000000/10);

}
__halt();
}

PRU Cookbook 还提供了一个 write_init_pins.sh 脚本,可以读取 init_pins 段然后配置引脚。我们直接在 BBB 上执行命令就行,不需要用 write_init_pins.sh

把编译得到的 blink.pru0.out :

scp blink.pru0.out  debian@192.168.7.2:/lib/firmware/am335x-pru0-fw

然后在 BBB 上执行下面的命令开启 PRU:

# 先关掉全部的 LED 触发,避免其他模块影响 LED效果
echo none > /sys/class/leds/beaglebone\:green\:usr0/trigger
echo none > /sys/class/leds/beaglebone\:green\:usr1/trigger
echo none > /sys/class/leds/beaglebone\:green\:usr2/trigger
echo none > /sys/class/leds/beaglebone\:green\:usr3/trigger

# 开启 PRU
echo start > /sys/class/remoteproc/remoteproc1/state 

这样就可以看到有一个 LED 在闪了。

关闭 PRU 也是写文件:

echo stop > /sys/class/remoteproc/remoteproc1/state


Web 服务控制 PRU

上面已经实现了 LED 的闪烁和开关,再通过一个 Web 服务提供了一个简单的页面给用户,不需要 ssh 执行命令,更加易用。


Web 服务使用 Rust 开发,提供了 3 个路由:

  • /blink-on 打开 LED, 开始闪烁
  • /blink-off 关闭 LED
  • / 首页,返回一个 HTML 页面
use astra::{Body, Request, Response, ResponseBuilder, Server};

fn main() {
Server::bind("0.0.0.0:3000")
.max_workers(2)
.serve(|req: Request, _info| -> Response {
let path = req.uri().path();

match path {
"/blink-on" => blink_on(),
"/blink-off" => blink_off(),
_ => index(),
}
})
.expect("serve failed");
}

这里使用 astra 框架,主要是简单,编译快,也不需要异步。


下面是三个路由的实现:

// 开始 LED 闪烁
fn blink_on() -> Response {
let mut file = File::options()
.append(true)
.open("/sys/class/remoteproc/remoteproc1/state")
.unwrap();

file.write(b"start").unwrap();

Response::new(Body::new("blink on"))
}

// 关闭 LED
fn blink_off() -> Response {
let mut file = File::options()
.write(true)
.open("/sys/class/remoteproc/remoteproc1/state")
.unwrap();

file.write(b"stop").unwrap();

Response::new(Body::new("blink off"))
}

// 首页
fn index() -> Response {
let body = std::fs::read_to_string("index.html").unwrap();

ResponseBuilder::new()
.header("Content-Type", "text/html")
.body(Body::new(body))
.unwrap()
}

可以看到,开关 LED 其实是上一节一样,都是把 start/stop 写到 /sys/class/remoteproc/remoteproc1/state 文件。首页返回的 HTML 有两个按钮,点击的时候调用对应的接口。

document.getElementById("blinkon").addEventListener('click', () => {
fetch("/blink-on")
})

document.getElementById("blinkoff").addEventListener('click', () => {
fetch("/blink-off")
}

使用 cargo 编译,然后把文件复制到板上:

cargo build --target armv7-unknown-linux-musleabihf --release
scp ./target/armv7-unknown-linux-musleabihf/release/funpack3-5 debian@192.168.7.2:/home/debian
scp index.html debian@192.168.7.2:/home/debian

最后在板上执行 funpack3-5 即可。

总结

BeagleBone Black 已经发布十多年了,依旧是一个非常有趣的平台。在这次项目里接触到了 ARM Linux 的开发(主要是交叉编译 Rust 程序)。PRU 使用还不够深入,可以再看看 PRU Cookbook,以后做些更有趣的项目。



附件下载
funpack3-5.tar.gz
代码
团队介绍
DDL 战士
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号