今天简单测评以下沁恒 CH32V208 开发板开发板。
这块开发板上集成2Mbps低功耗蓝牙BLE 通讯模块、10M以太网MAC+PHY模块、USB2.0全速设备+主机/设备接口、CAN控制器等。
产品以下若干特点:
产品特点
(1)青稞V4C处理器,最高144MHz系统主频
(2)支持单周期乘法和硬件除法
(3)64KB SRAM,128KB Flash
(4)供电电压:2.5/3.3V,GPIO单元独立供电
(5)多种低功耗模式:睡眠、停止、待机
(6)低功耗蓝牙5.3
(7)10M以太网控制器(MAC+PHY)
(8)上/下电复位、可编程电压检测器
(9)2组运放比较器
(10)16通道12位ADC转换,16路触摸按键TouchKey
(11)5组定时器
(12)USB2.0全速主机/设备+设备接口
(13)4个USART接口
(14)1个CAN接口(2.0B主动)
(15)2组IIC接口、2组SPI接口
(16)53个I/O口,可以映射到16外部中断
(17)CRC计算单元,96位芯片唯一ID
(18)串行2线调试接口
(19)封装形式:LQFP64M、QFN68、QFN48、QFN28
开发板和下载器接口的英文说明:
下载器:
这个板子比较大,尺寸8.6cm*9.5cm,上面集成了蓝牙天线,RJ45网口,两个USB-A母口。
以下做了示例测试: CH32V208 运行FreeRTOS示例
硬件部分
- CH32V208WBU6 评估板
- WCH-LinkE 或 WCH-Link
软件部分
本节以沁恒的FreeRTOS示例项目为例进行说明.
示例代码位于 CH32V20xEVT 压缩包的 EVT/EXAM/FreeRTOS 目录.
对应 GCC 环境的项目代码位于 https://github.com/IOsetting/ch32v208-template/tree/main/Examples/FreeRTOS/Task/Blink
青稞V4的手册下载地址 https://www.wch.cn/downloads/QingKeV4_Processor_Manual_PDF.html
编译和烧录
这里只介绍 GCC & Makefile 环境的编译和烧录. 参考上一节进行 GCC 环境的配置
- 修改 Makefile 中的
USE_FREERTOS
选项, 设置为USE_FREERTOS ?= y
, 打开这个选项, 在编译时会包含 FreeRTOS 库相关文件
- 修改 Makefile 中的
AFILES := Libraries/Startup/startup_ch32v20x_D8W.S
, 将其替换为 AFILES := Libraries/Startup/startup_ch32v20x_D8W_RTOS.S
后者禁用了硬件堆栈, 禁用了机器模式下的中断, 如果不禁用, FreeRTOS 无法正常工作
- 清空 User 目录, 将 FreeRTOS/Task/Blink 目录下的文件复制到 User 目录, 运行
make
编译项目
- 连接好 WCH-Link 和 CH32V208 评估板, 运行
make flash
烧录
运行示例
将 PA0, PA1 分别连接到 LED1 和 LED2, 观察两个GPIO任务的输出.
将评估板的串口输出连接到 WCH-Link, 在PC端使用串口工具, 波特率115200打开 /dev/ttyACM0 观察两个GPIO任务的printf输出
运行时, 除了 LED1 间隔半秒 和 LED2 间隔一秒闪烁外, 串口会打印以下内容(忽略其中的时间戳部分)
SystemClk:96000000
FreeRTOS Kernel Version:V10.4.6
task2 entry
task1 entry
32:33.611 task1 entry
32:34.611 task2 entry
task1 entry
32:35.611 task1 entry
32:36.610 task2 entry
task1 entry
32:37.611 task1 entry
32:38.611 task2 entry
task1 entry
32:39.611 task1 entry
涉及的代码改动
中断处理变动
CH32V20x 运行 FreeRTOS 时不支持硬件压栈, 中断只能使用软件压栈
在无系统场景时的中断处理
void NMI_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
就要换成不带WCH-Interrupt-fast
的中断处理
void NMI_Handler(void) __attribute__((interrupt()));
void HardFault_Handler(void) __attribute__((interrupt()));
Startup 文件变动
在 startup 文件中需要禁用硬件堆栈, 并在机器模式下禁用中断,
在无系统场景时的 0x804 和 mstatus 设置
/* Enable nested and hardware stack */
li t0, 0x3
csrw 0x804, t0/* Enable interrupt */
li t0, 0x88
csrs mstatus, t0
csrs mstatus, t0
就要替换为下面的设置
/* Enable nested stack, no hardware stack */
li t0, 0x2
csrw 0x804, t0/* Machine mode, no interrupt */
li t0, 0x1800
csrs mstatus, t0
csrs mstatus, t0
804寄存器
CSR 0x804地址对应的是 INTSYSCR, 中断系统控制寄存器. 青稞V4手册第13页.
位 |
名称 |
读写 |
描述 |
复位值 |
---|
1 |
INESTEN |
RW |
中断嵌套使能, 0:关闭, 1:开启 |
0 |
0 |
HWSTKEN |
RW |
硬件压栈使能, 0:关闭, 1:开启 |
0 |
运行 FreeRTOS 时, 需要关闭硬件压栈使能, 因此上面对 0x804 写入 0x2.
mstatus寄存器
mstatus 是 机器模式状态寄存器, 青稞V4手册第30页, 每一位的定义为
位 |
名称 |
读写 |
描述 |
复位值 |
---|
[31:15] |
– |
|
|
|
[14:13] |
FS |
RW |
浮点单元状态, 00:OFF, 01:Initial, 10:Clean, 11:Dirty |
00 |
[12:11] |
MPP |
RW |
进中断前特权模式 |
00 |
[10:8] |
– |
|
|
|
[7] |
MPIE |
RW |
进中断之前中断使能状态 |
00 |
[6:4] |
– |
|
|
|
[3] |
MIE |
RW |
机器模式中断使能 |
00 |
[2:0] |
– |
|
|
|
- FS
用于描述和维护浮点单元状态, 所以该域只有在含有硬件浮点功能的青稞 V4F 微处理器上才有意义. 当其值为 0 时, 表示浮点单元为关闭状态, 且如果此时使用浮点指令, 将触发异常;若其值为 1 或 2, 当执行了浮点指令后, 该域会被更新为 3. 若用户在使用 V4F 微处理器时, 不期望使用硬件浮点功能, 可在机器模式下, 手动清除该两位, 以关闭硬件浮点并降低功耗.
- MPP
用于保存进入异常或中断前的特权模式, 用于退出异常或中断后的特权模式恢复
- MPIE
用于保存进入异常或中断前的中断使能状态(MIE的值), 用于退出异常或中断后中断使能状态恢复
- MIE
全局中断使能位, 当进入异常或中断时, MPIE 的值被更新为 MIE 值, 需要注意的是青稞 V4 在最后一级嵌套中断前 MIE 不会被更新为 0, 以保证机器模式下的中断嵌套继续执行.
当退出异常或中断后, 处理器恢复为 MPP 保存的机器模式, MIE 恢复为 MPIE 保存的使能状态.
运行FreeRTOS时, 对 mstatus 使用 csrs 指令写入 0x1800, 即将 MPP bit[12,11]设置为 0x11, 使其返回后始终保持在机器模式.
LD 脚本
需要增加 __freertos_irq_stack_top
锚定栈顶地址
.stack ORIGIN(RAM) + LENGTH(RAM) - __stack_size :{PROVIDE( _heap_end = . );. = ALIGN(4);PROVIDE(_susrstack = . );. = . + __stack_size;PROVIDE( _eusrstack = .);__freertos_irq_stack_top = .;} >RAM
运行 FreeRTOS 任务
这部分就是正常的 FreeRTOS 调用了
xTaskCreate((TaskFunction_t )task2_task,(const char* )"task2",(uint16_t )TAS