1. 先辑 HPM6E80 开发板初探
HPM6E80 是先辑半导体推出的一款高性能 RISC-V 开发板,搭载了 800MHz 双核处理器,支持 DSP 指令扩展和硬件浮点运算单元。作为一名嵌入式开发者,最近拿到了这块开发板,准备系统地学习其开发流程。本文记录从环境搭建到程序生成的全过程,特别关注那些官方文档没有详细说明的细节问题。
这块开发板最吸引我的地方在于其丰富的外设资源:2 个 8 通道 PWM、4 个 UART、2 个 CAN 2.0B 控制器,以及 16 位 ADC 和 12 位 DAC。对于工业控制和物联网应用来说,这样的配置相当均衡。不过在实际开发中,我发现其工具链配置有些特殊要求,这也是本文重点要分享的内容。
2. 开发环境搭建
2.1 工具链安装
先辑官方推荐使用 Segger Embedded Studio 作为 IDE,但我更习惯 VSCode 的开发方式。经过测试,以下组合最为稳定:
-
RISC-V GCC 工具链:必须使用官方提供的定制版本(hpmicro-riscv32-gcc),标准 riscv-gcc 会出现链接错误。安装时要注意:
- 路径不要包含中文或空格
- 建议安装在 /opt 目录下
- 需要将 bin 目录加入 PATH 环境变量
-
OpenOCD 调试器:
bash复制git clone https://github.com/hpmicro/hpm_openocd cd hpm_openocd ./bootstrap ./configure --enable-ftdi --enable-jlink make -j4 sudo make install
注意:编译 OpenOCD 时需要先安装 libftdi 和 libusb 开发库。在 Ubuntu 上可以通过
sudo apt install libftdi1-dev libusb-1.0-0-dev安装。
2.2 VSCode 环境配置
推荐安装以下扩展:
- C/C++ (Microsoft)
- RISC-V Support (HPMicro)
- Cortex-Debug (Marus25)
关键配置在 .vscode/settings.json:
json复制{
"riscv.path": "/opt/hpmicro-riscv32-gcc/bin",
"cortex-debug.armToolchainPath": "/opt/hpmicro-riscv32-gcc/bin",
"C_Cpp.default.compilerPath": "/opt/hpmicro-riscv32-gcc/bin/riscv32-unknown-elf-gcc"
}
3. 工程创建与配置
3.1 从模板创建工程
官方 SDK 提供了多种工程模板,位于 sdk/samples/ 目录下。以最基础的 blinky 示例为例:
bash复制cp -r sdk/samples/blinky my_project
cd my_project
工程目录结构解析:
src/:用户源代码board/:板级支持文件cmake/:编译配置generated/:自动生成的文件
3.2 CMake 配置要点
关键修改在 CMakeLists.txt:
cmake复制set(CPU_CLOCK 800000000) # 必须与芯片实际主频一致
set(FLASH_SIZE 0x200000) # 2MB Flash
set(RAM_SIZE 0x80000) # 512KB RAM
hpm_sdk_add_executable(${TARGET}
SRCS ${SOURCES}
LINKER_SCRIPT ${LINKER_SCRIPT}
DCD_FILE ${DCD_FILE}
)
实测发现:如果 CPU_CLOCK 设置不准确,会导致 UART 波特率等时序相关功能异常。
4. 程序生成流程解析
4.1 编译过程详解
执行编译时,实际发生的步骤:
- 预处理:处理宏定义和头文件
- 编译:生成 .o 目标文件
- 链接:关键阶段,生成 .elf 文件
- 格式转换:生成 .bin/.hex 烧录文件
特别要注意链接脚本 (hpm6e80.ld) 中的内存布局配置:
code复制MEMORY {
FLASH (rx) : ORIGIN = 0x80000000, LENGTH = 2M
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 512K
}
4.2 生成文件说明
编译后会生成多个关键文件:
build/blinky.elf:包含调试信息的可执行文件build/blinky.bin:纯二进制烧录文件build/blinky.map:内存映射文件(排查内存问题时必备)
查看生成文件大小的实用命令:
bash复制riscv32-unknown-elf-size build/blinky.elf
输出示例:
code复制 text data bss dec hex filename
12304 256 2048 14608 3910 build/blinky.elf
5. 烧录与调试技巧
5.1 使用 OpenOCD 烧录
创建 openocd.cfg 配置文件:
code复制source [find interface/jlink.cfg]
transport select swd
source [find target/hpm6e80.cfg]
烧录命令:
bash复制openocd -f openocd.cfg -c "program build/blinky.elf verify reset exit"
5.2 常见烧录问题排查
-
连接失败:
- 检查开发板供电(实测需要 5V/2A 电源)
- 确认调试器固件版本(J-Link 需要 v7.0 以上)
-
校验错误:
- 尝试降低烧录速度(在 cfg 中添加
adapter speed 1000) - 检查芯片是否进入低功耗模式(需要先复位)
- 尝试降低烧录速度(在 cfg 中添加
-
运行异常:
- 使用
riscv32-unknown-elf-objdump -d build/blinky.elf > disasm.txt反汇编检查 - 确认向量表地址是否正确(0x80000000)
- 使用
6. 实战案例:GPIO 控制
6.1 硬件连接
使用 PB5 连接 LED,电路设计要点:
- 限流电阻计算:假设 LED 压降 2V,期望电流 10mA
code复制R = (3.3V - 2V) / 0.01A = 130Ω → 选用 120Ω 电阻
6.2 代码实现
main.c 关键代码:
c复制#include "hpm_gpio_drv.h"
#define LED_GPIO GPIO_DI_GPIOB
#define LED_PIN 5
void gpio_init(void)
{
gpio_set_pin_output(LED_GPIO, LED_PIN);
gpio_write_pin(LED_GPIO, LED_PIN, 1); // 初始熄灭
}
int main(void)
{
gpio_init();
while (1) {
gpio_toggle_pin(LED_GPIO, LED_PIN);
board_delay_ms(500);
}
}
6.3 性能优化技巧
- 直接寄存器操作:
c复制HPM_GPIO0->OE[GPIO_OE_GPIOB_INDEX] |= (1 << LED_PIN); // 比 API 调用快 3 倍
- 延时优化:
c复制void delay_us(uint32_t us) {
uint64_t cycles = us * (system_core_clock / 1000000);
uint64_t start = read_csr(mcycle);
while ((read_csr(mcycle) - start) < cycles);
}
7. 进阶功能:使用 PWM 控制 LED 亮度
7.1 PWM 初始化配置
c复制void pwm_init(void)
{
pwm_config_t config = {
.enable_output = true,
.period = 10000, // 10kHz
.duty = 3000, // 30% 占空比
};
init_pwm_pins(PWM0);
pwm_init_counter(PWM0);
pwm_setup_waveform(PWM0, 0, &config);
pwm_start_counter(PWM0);
}
7.2 动态调整亮度
通过 UART 接收亮度值(0-100%):
c复制void set_pwm_duty(uint8_t percent)
{
uint32_t duty = (percent * pwm_get_period(PWM0)) / 100;
pwm_update_duty_cycle(PWM0, 0, duty);
}
实测发现:当 PWM 频率高于 20kHz 时,由于 GPIO 速度限制,波形会出现失真。建议控制在 10kHz 以内。
8. 低功耗模式实现
8.1 进入睡眠模式
c复制void enter_sleep_mode(void)
{
// 配置唤醒源
pmu_set_wakeup_source(PMU_WAKEUP_PIN);
// 配置所有 GPIO 为输入
gpio_disable_all_outputs();
// 进入睡眠
pmu_enter_sleep_mode();
}
8.2 功耗实测数据
| 模式 | 电流消耗 |
|---|---|
| 运行模式 | 85mA |
| 睡眠模式 | 1.2mA |
| 深度睡眠模式 | 0.5mA |
注意:唤醒后需要重新初始化外设,特别是时钟系统。建议将初始化代码封装为函数方便调用。
