登录发现更多内容
首页
分类
发帖
账号
自动登录
找回密码
密码
登录
立即注册
立即登录
立即注册
其他登录
QQ
微信
首页
Portal
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
产品教程
BBS
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
开发资料
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
样品购买
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
IoT云平台
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
GitHub
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
技术博客
求助问答
Xiuno资源
Xiuno教程
Xiuno插件
Xiuno主题
休闲茶馆
定制主题
搜索
搜索
热搜:
LoRa
ESP8266
安信可
本版
帖子
用户
请
登录
后使用快捷导航
没有账号?
立即注册
每日签到
任务
广播
导读
排行榜
设置
我的收藏
退出
19
0
0
首页
小安派&M61基本系统教程
›
Ai-M61-32S-Kit 开发板 Rust 裸机编程指南:PAC ...
1
2
/ 2 页
下一页
返回列表
Ai-M61-32S-Kit 开发板 Rust 裸机编程指南:PAC
[ 复制链接 ]
发布帖子
instead
中级会员
4
主题
6
回帖
407
积分
中级会员
中级会员, 积分 407, 距离下一级还需 93 积分
中级会员, 积分 407, 距离下一级还需 93 积分
积分
407
私信
18人留言
楼主
小安派&M61基本系统教程
4263
19
2024-2-26 19:01:02
[i=s] 本帖最后由 instead 于 2024-2-26 19:01 编辑 [/i]
> 全文 10574 字,预计阅读时间 7-9 分钟 ## 开发资料一览 - [Ai-M61 系列模组专题 | 安信可科技 (ai-thinker.com)]([https://docs.ai-thinker.com/ai_m61](https://docs.ai-thinker.com/ai_m61)) - [Ai-M61-32S 模组规格书]([https://docs.ai-thinker.com/_media/ai-m61-32s_v1.1.1_product_specification_cn.pdf](https://docs.ai-thinker.com/_media/ai-m61-32s_v1.1.1_product_specification_cn.pdf)) - [Ai-M61-32S-Kit 开发板规格书]([https://docs.ai-thinker.com/_media/ai-m61-32s-kit_v1.1.1_product_specification_cn.pdf](https://docs.ai-thinker.com/_media/ai-m61-32s-kit_v1.1.1_product_specification_cn.pdf)) - [BL616/BL618参考手册 · bouffalolab/bl_docs (github.com)]([https://github.com/bouffalolab/bl_docs/blob/main/BL616_RM/zh_CN/BL616_BL618_RM_zh_CN_0.95.pdf](https://github.com/bouffalolab/bl_docs/blob/main/BL616_RM/zh_CN/BL616_BL618_RM_zh_CN_0.95.pdf)) - [BL616/BL618数据手册 · bouffalolab/bl_docs (github.com)]([https://github.com/bouffalolab/bl_docs/blob/main/BL616_DS/zh_CN/BL616_BL618_DS_1.5_zh_CN.pdf](https://github.com/bouffalolab/bl_docs/blob/main/BL616_DS/zh_CN/BL616_BL618_DS_1.5_zh_CN.pdf)) - [文档 | 博流智能开发者社区 (bouffalolab.com)]([https://dev.bouffalolab.com/document](https://dev.bouffalolab.com/document)) 下文中的大部分内容都会参考以上官方手册的内容,有需要的可以下载到本地看。 ## 了解手上的硬件 手上开发板的基础信息可以通过屏蔽罩丝印表示,例如我手上的这个开发板屏蔽罩上的丝印是 `BLOFN8IR4`,对照规格书后可以知道其表示的是: - BL:BL618 - O:外置 - F:FLASH - N:模组温度版本为常温 - 8:FLASH 大小为 8MB - I:内置 - R:PSRAM - 4:PSRAM 大小为 4MB 这代表着我手上这个板子有 4MB 的 PSRAM(不是内存,但可以扩展为内存)和 8MB 的 FLASH。 ### 确定 RAM 和 FLASH 的起始地址 通过查阅参考手册中的 `1.4 地址映射`,可以得到如下的内存地址映射表: | 模块 | 大小 | Cache 开始地址 | Non-cache 开始地址 | | :---: | :---: | :------------: | :----------------: | | OCRAM | 320KB | 0x62FC0000 | 0x22FC0000 | | WRAM | 160KB | 0x63010000 | 0x23010000 | 以及如下的地址表(部分): | 模块 | 目标 | 开始地址 | 大小 | 描述 | | :---: | :-----: | :--------: | :---: | :---------------------------------------------: | | FLASH | Flash | 0xA0000000 | 128MB | 应用程序地址空间 | | PSRAM | pSRAM | 0xA8000000 | 128MB | pSRAM 存储器地址空间 (可选项,依赖芯片具体型号) | | RAM | HBN RAM | 0x20010000 | 4KB | HBN RAM, 主要用于超低功耗模式下的数据保存 | | ROM | ROM | 0x90000000 | 128KB | Bootrom 区域地址空间 | > * **OCRAM**(On-Chip RAM):OCRAM 是集成在芯片(SoC,System-on-Chip)上的内部 RAM,通常位于处理器或其他核心周围。它的优势在于对于处理器等核心来说,它位于芯片内部,访问速度较快,可以更轻松地与其他芯片内部组件进行通信。由于它是在芯片上的 RAM,因此也称为内嵌式 RAM。 对照一下规格书中的地址映射表可以知道,Flash 的起始地址是 `0xA0000000`,大小为 8MB;OCRAM 的起始地址是 `0x62FC0000`,大小为 320KB。 (有人看见映射表里面的 RAM 可能会疑惑为什么不用这个,因为那个 RAM 是 HBN RAM,一般情况下用不上它) ### 确定外设 Ai-M61-32S-Kit 开发板给的外设其实还挺多的,不过这里因为只是入个门,所以那些复杂的外设我们不碰它,只是玩玩它上面的那个 RGB Logo 灯。通过规格书可知: - 红色灯:IO12 - 绿色灯:IO14 - 蓝色灯:IO15 这几盏灯都接在 12、14 和 15 GPIO 口上,并且是高电平有效。 ## PAC PAC 全称是 Peripheral Access Crate,可以用于访问嵌入式系统外设寄存器。PAC 提供了对硬件寄存器和外设功能的类型安全的抽象,使得在嵌入式系统上进行编程更加方便和可靠。 在嵌入式系统中,通常会有一些外设(如 GPIO、UART、SPI 等),这些外设的控制寄存器位于特定的内存地址。PAC 就是为了方便地访问这些寄存器而创建的。PAC 提供了一个类型安全的 API,使得在编写嵌入式系统代码时,可以避免使用裸指针和不安全的代码。 PAC 通常是由芯片厂商或社区创建的,以支持特定的芯片或开发板。通过使用 PAC,开发者可以使用 Rust 的安全性和表达力,同时又能够方便地访问底层硬件。在 Rust 中,PAC 通常是一个代码生成工具生成的库,根据硬件描述文件自动生成对应的寄存器访问代码。 ### 如何获取 PAC 拿手上的这块 Ai-M61-32S 为例,它所搭载的芯片是 BL618,通过翻阅博通官方库可以知道找到官方发布的[bl616-pac - crates.io: Rust Package Registry]([https://crates.io/crates/bl616-pac](https://crates.io/crates/bl616-pac)),~~因此可以直接拿这个来用~~并不,摸鱼的时候用它写的我焦头烂额,仔细看了看 C 源码和隔壁公司为 bl602 维护的 pac 后发现,里面用于生成的 SVD 文件里寄存器不全,至少我目前看着缺少 AON,以及一部分 GPIO 控制寄存器的,因此我这边要先补上缺失的寄存器再重新用最新的版本来生成一遍。[^1] #### 生成 PAC ##### 环境准备 由于需要修补厂商提供的 SVD 文件,这里用到的是[rust-embedded/svdtools]([https://github.com/rust-embedded/svdtools](https://github.com/rust-embedded/svdtools)),执行如下命令安装: ``` cargo install svdtools ``` 生成 PAC 需要使用 `svd2rust` 与 `form`,使用如下命令安装: ``` cargo install svd2rust form ``` 同时我们还需要用到 SVD 文件,这个文件可以在官方 PAC 的[仓库]([https://github.com/bouffalolab/bl-pac/tree/main/bl616](https://github.com/bouffalolab/bl-pac/tree/main/bl616))中找到。 ##### 修补 SVD 文件 找一个合适的位置执行以下命令来生成一个空的 Rust 库: ``` cargo new bl61x-pac --lib ``` 上面的 `bl61x-pac` 可以是自己觉得方便的名称,在执行完成后会生成该名称的目录。进入该目录后创建 svd 子文件夹,将前面取得的 SVD 文件放入该目录内。 而后创建 `bl618-pac/peripherals` 文件夹,在里面放入修补文件。然后在 `bl61x-pac` 下新建文件 `bl61x.yaml` 作为修补的配置文件即可。 例如,我这边创建了 `AON` 寄存器的修补文件 `AON.yaml`,则配置文件的内容如下: ```yaml # Path to the SVD file we're targeting. Relative to this file. # This must be included only in the device YAML file. _svd: "./svd/bl616.svd" # Include other YAML files. Path relative to this file. _include: - "./peripherals/AON.yaml" ``` 完成了这些工作后,目录的结构大概是这样: ``` bl61x-pac ├─ .gitignore ├─ bl61x.yaml ├─ Cargo.toml ├─ svd │ └─ bl616.svd ├─ src │ └─ lib.rs └─ peripherals └─ AON.yaml ``` 随后我们便运行如下的命令生成修补后的 SVD 文件即可: ``` svdtools patch bl61x.yaml ``` ##### 生成 Rust 文件 编辑一下 `Cargo.toml` 文件,使得其应该具有如下的内容:[^2] ```toml [package] name = "bl61x-pac" version = "0.1.0" edition = "2021" # See more keys and their definitions at [https://doc.rust-lang.org/cargo/reference/manifest.html](https://doc.rust-lang.org/cargo/reference/manifest.html) [dependencies] riscv = "0.11.1" vcell = "0.1.3" [dependencies.critical_section] package = "critical-section" optional = true version = "1.1.2" [features] critical-section = ["critical_section", "riscv/critical-section-single-hart"] rt = [] ``` 并在目录内执行: ``` svd2rust -i svd/bl616.svd.patched --target=riscv rm -rf src form -i lib.rs -o src/ && rm lib.rs cargo fmt ``` 到这,你便可以调用该 PAC 库进行开发了。如果你们不想自己生成,也可以使用我上面生成的 PAC 库:[wsndshx/bl61x-pac (github.com)]([https://github.com/wsndshx/bl61x-pac](https://github.com/wsndshx/bl61x-pac))。 ## Hello World! 这里就按照老规矩,先把板子给点亮(物理)。 ### 创建 Rust 项目 随便找个目录,输入如下的命令创建新 Rust 项目: ``` cargo new blinky --bin ``` 执行后,会生成具有如下结构的目录: ``` blinky ├── Cargo.toml └── src └── main.rs ``` 在 blinky 目录内创建 `.cargo` 文件夹,并在里面创建配置文件 `config.toml`,配置文件的内容如下: ``` [target.riscv32imac-unknown-none-elf] rustflags = [ "-C", "link-arg=-Tmemory.x", "-C", "link-arg=-Tlink.x", ] [build] target = "riscv32imac-unknown-none-elf" ``` 上面的配置文件指定了编译时使用 riscv32imac-unknown-none-elf 作为编译时的目标平台,并且使用 `memory.x` 作为链接脚本。因此接下来在 blinky 目录下新建一个 `memory.x` 文件,内容如下: ``` MEMORY { RAM : ORIGIN = 0x62FC0000, LENGTH = 320K FLASH : ORIGIN = 0xA0000000, LENGTH = 8M } REGION_ALIAS("REGION_TEXT", FLASH); REGION_ALIAS("REGION_RODATA", FLASH); REGION_ALIAS("REGION_DATA", RAM); REGION_ALIAS("REGION_BSS", RAM); REGION_ALIAS("REGION_HEAP", RAM); REGION_ALIAS("REGION_STACK", RAM); ``` 在链接脚本中我定义了 RAM 和 FLASH 的起始地址与长度为文章所确定的数值。但很明显仅靠这小段脚本还不足以声明好运行所需的所有段,不过 riscv-rt 运行库已经内置了通用的链接脚本,我们仅仅再创建一段编译时自动拷贝 `memory.x` 的 build script 即可。为此需要新建一个 `build.rs` 文件,并将如下的内容写入到 `build.rs` 中: ```rust use std::env; use std::fs::File; use std::io::Write; use std::path::PathBuf; fn main() { // Put the linker script somewhere the linker can find it let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); File::create(out.join("memory.x")) .unwrap() .write_all(include_bytes!("memory.x")) .unwrap(); println!("cargo:rustc-link-search={}", out.display()); // Only re-run the build script when memory.x is changed, // instead of when any part of the source code changes. println!("cargo:rerun-if-changed=memory.x"); } ``` ### 处理依赖 该项目需要如下的依赖: - riscv:CPU 寄存器访问与内联汇编函数 - riscv-rt:启动代码和中断处理程序 - panic-halt:设置恐慌行为为停止 - bl61x-pac:用于 BL616/BL618 微控制器的嵌入式 Rust 外设访问库 执行如下命令添加: ``` cargo add riscv --features critical-section-single-hart cargo add riscv-rt --features single-hart cargo add panic-halt cargo add bl61x-pac --features critical-section ``` ### 编写 PAC 点灯代码 在用 Rust 点灯之前,先去看看在官方 SDK 中是怎么用 C 实现的。在 SDK 中找到 GPIO 口的[输入输出例程]([https://github.com/bouffalolab/bouffalo_sdk/tree/master/examples/peripherals/gpio/gpio_input_output](https://github.com/bouffalolab/bouffalo_sdk/tree/master/examples/peripherals/gpio/gpio_input_output)),可以看见其中关键的代码是如下的几行: ```c // 获取名为 gpio 的外设 gpio = bflb_device_get_by_name("gpio"); // 初始化指定 gpio 端口 // 分别对指定的 gpio_config_xx 寄存器中的如下位进行了操作: // - GPIO_OUTPUT:将 reg_gpio_xx_oe 置 1,使能 gpio 输出 // - GPIO_PULLUP:将 reg_gpio_xx_pu 置 1,使能内部上拉功能 // - GPIO_SMT_EN:将 reg_gpio_xx_smt 置 1,功能不明,使能 SMT // - GPIO_DRV_0:将 reg_gpio_xx_drv 置 0,输出能力最低 bflb_gpio_init(gpio, GPIO_PIN_0, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0); // 指定 gpio 口高电平 // 该函数对寄存器 gpio_cfg138 与 gpio_cfg139 进行操作 // 这两个寄存器共有 35 个有效位,分别设置 35 个 GPIO 口的输出值 // 只有在 GPIO 口处于设置/清除模式时生效 // 若同时进行设置和清除操作,仅设置操作生效 bflb_gpio_set(gpio, GPIO_PIN_0); // 指定 gpio 口低电平 // 该函数对寄存器 gpio_cfg140 与 gpio_cfg141 进行操作 // 这两个寄存器共有 35 个有效位,分别清除 35 个 GPIO 口的输出值 // 只有在 GPIO 口处于设置/清除模式时生效 // 若同时进行设置和清除操作,仅设置操作生效 bflb_gpio_reset(gpio, GPIO_PIN_0); ``` 分析完上面的例程后,便可以根据例程编写如下的 Rust 代码: ```rust #![no_std] #![no_main] extern crate panic_halt; use riscv_rt::entry; use bl61x_pac as pac; #[entry] fn main() -> ! { // 获取外设 let peripherals = pac::Peripherals::take().unwrap(); // 配置 GPIO 口第 15 引脚为 GPIO 输出模式,进入 SW-GPIO 模式,使能设置/清除输出模式,并且使能内部上拉功能 peripherals.GLB.gpio_config(15).write(|w| { w.output_function() .set_bit() .alternate() .gpio() .pin_mode() .set_clear() .pull_up() .set_bit() }); loop { // 将 15 引脚设置为高电平 peripherals.GLB.gpio_set_0().write(|w| w.gpio_15_set().set_bit()); peripherals.GLB.gpio_clear_0().write(|w| w.gpio_15_clr().clear_bit()); // BL618 默认的主频为 320MHz,即每秒 320,000,000 个周期 // 则如果需要延迟 1 毫秒最多需要消耗 320,000 个周期 // 并且延迟时间过短会导致常亮 // 这里延迟 500 毫秒 for _ in 0..500{ riscv::asm::delay(320000); } // 将 15 引脚设置为低电平 peripherals.GLB.gpio_set_0().write(|w| w.gpio_15_set().clear_bit()); peripherals.GLB.gpio_clear_0().write(|w| w.gpio_15_clr().set_bit()); for _ in 0..500{ riscv::asm::delay(320000); } } } ``` 编写完之后,使用如下的命令编译项目: ``` cargo build -r ``` 并使用如下的命令生成固件镜像: ``` rust-objcopy --strip-all target/riscv32imac-unknown-none-elf/release/blinky -O binary target/riscv32imac-unknown-none-elf/release/blinky.bin ``` ## 烧录固件(首次) 为什么是首次呢,因为你此时不清楚板子内部到底烧录了什么程序,因此先完整跑一次烧录流程。[^3] 这里需要用到博流的图形化工具 Bouffalo Lab Dev Cube 烧录编译出来的固件,下载地址见:[下载 | 博流智能开发者社区 (bouffalolab.com)]([https://dev.bouffalolab.com/download](https://dev.bouffalolab.com/download))。 下载并解压后,双击 BLDevCube.exe,选择 BL616/BL618:  进入软件主界面后,按照下图的说明进行配置:  其中: - partition table:分区表,这里直接用软件自带的,点击 Browse 弹出来的窗口中选择 partition_cfg_4M - boot2:boot2 需要去博流的 bouffalo_sdk 处下载,下载地址:[bouffalo_sdk/bsp/board/bl616dk/config at master · bouffalolab/bouffalo_sdk (github.com)]([https://github.com/bouffalolab/bouffalo_sdk/tree/master/bsp/board/bl616dk/config](https://github.com/bouffalolab/bouffalo_sdk/tree/master/bsp/board/bl616dk/config)) - firmware:前面生成的固件镜像,位置在 target/riscv32imac-unknown-none-elf/release/blinky.bin 配置完成后,将开发板使用 USB 连接线连接至电脑,并在按着下图中的③按键的同时短按②按键进入烧录模式。  进入烧录模式后,点击软件的 `Refresh`,刷新端口,再点击 `Create & Download` 开始烧录。当软件里面的那个大大的进度条跑到 100% 并且是绿色的时候,固件便烧录成功了。 再次短按开发板上的复位键,此时就可以观察到开发板上的蓝灯以一秒一次的速度亮起来了~ [^1]: [STM32F4 Embedded Rust at the PAC: svd2rust - DEV Community]([https://dev.to/apollolabsbin/stm32f4-embedded-rust-at-the-pac-svd2rust-457d](https://dev.to/apollolabsbin/stm32f4-embedded-rust-at-the-pac-svd2rust-457d)) [^2]: [svd2rust - Rust (docs.rs)]([https://docs.rs/svd2rust/latest/svd2rust/#other-targets](https://docs.rs/svd2rust/latest/svd2rust/#other-targets)) [^3]: [BL618 评估板程序烧录 - VeriMake]([https://verimake.com/d/282-bl618](https://verimake.com/d/282-bl618))
点赞
0
收藏
0
淘帖
0
────
0
人觉得很赞
────
百回「可愛い」って言うまで放さないい!
回复
使用道具
举报
18 回复
电梯直达
正序浏览
倒序浏览
正序浏览
沙发
干簧管
回复
使用道具
举报
2024-2-26 19:02:06
赞👍
回复
评论
使用道具
举报
板凳
7788
回复
使用道具
举报
2024-2-26 20:10:49
赞
回复
评论
使用道具
举报
地板
物联网
回复
使用道具
举报
2024-2-26 20:22:29
回复
评论
使用道具
举报
5
#
sansui
回复
使用道具
举报
2024-2-26 22:39:09
赞一下
回复
评论
使用道具
举报
6
#
bzhou830
回复
使用道具
举报
2024-2-27 08:42:48
不错不错!
回复
评论
使用道具
举报
选择去发光,而不是被照亮
7
#
1084504793
回复
使用道具
举报
2024-2-27 08:47:55
赞
回复
评论
使用道具
举报
8
#
lazy
回复
使用道具
举报
2024-2-27 08:57:37
很专业呀
回复
评论
使用道具
举报
9
#
bzhou830
回复
使用道具
举报
2024-2-27 09:08:39
赞一下
回复
评论
使用道具
举报
选择去发光,而不是被照亮
10
#
WT_0213
回复
使用道具
举报
2024-2-27 09:16:39
赞一下
回复
评论
使用道具
举报
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
立即登录
手机登录
点评
高级模式
本版积分规则
回帖并转播
回帖后跳转到最后一页
下一页 »
1
2
/ 2 页
下一页
今日推荐
AiPi-PalChatV1_“湾湾小何”提示音测试固件V2.9_UART-MCP
[WB2] 实现自动发现局域网下的设备
热帖排行
ra-01sc-p发射功率大小的使用问题
[AiPi-PalchatV1] [Windows] 克隆仓库和在线烧录遇到的一些小问
AT+MQTTPUBRAW指令所支持的最大数据传输量是多少
AiPi-PalChatV1_UART-MCP_v2.8 UART-MCP 协议配置 问题
Ai-WB2蓝牙怎么连接打印机
AI-WB2-12F电脑蓝牙连接秒断,手机搜索不到
AiPi-PalChatV1_“湾湾小何”提示音测试固件V2.9_UART-MCP
从零搭建 Ai-WB2 开发板的 Linux 开发环境—— 基于 VMware 虚拟
统计信息
会员数: 30475 个
话题数: 44644 篇
首页
分类
我的