笔者有空学习了GD32的RSICV芯片,故来总结一下。
GD32 RISCV芯片系列
GD:GidaDeivce,兆易创新,生产的MCU的内核架构系列如下图所述,主要是ARM架构的,Cortex-M23、M3、M4、M33以及M7,然后也涉及到了RISC-V架构的,笔者今天就来聊一下RISCV架构的MCU产品。
GD32的RISC-V的芯片类型主要有以下几种:
特点如下:
GD32VF103系列MCU采用了全新的基于开源指令集架构RISC-V的Bumblebee处理器内核,是兆易创新(Gigadevice)携手中国领先的RISC-V处理器内核IP和解决方案厂商芯来科技(Nuclei System Technology),面向物联网及其它超低功耗场景应用自主联合开发的一款商用RISC-V处理器内核。
- GD32VF103系列RISC-V MCU提供了108MHz的运算主频,
- 16KB到128KB的片上闪存和6KB到32KB的SRAM缓存,
- gFlash®专利技术支持内核访问闪存高速零等待。
- Bumblebee内核还内置了单周期硬件乘法器、硬件除法器和加速单元应对高级运算和数据处理的挑战。
GD32 RISCV VF103芯片
来具体看一下VF103 芯片的一些特点:RISC-V处理器适用于低能耗、小面积的嵌入式应用,具有简单的动态分支预测、指令预取缓冲区 和 本 地 内 存 等 多 种 高 效 微 架 构 特 点 。它支持32个通用寄存器(GPRs)和用于性能/面积权衡的快速乘法器:
- RISC-V兼容小端RV32 IMAC(32 GPRS) ;
- 可配置的2级管道,针对低门数和高频率进行了优化;
- 机器(M)和用户(U)权限级别支持;
- 支持单周期硬件乘法器和多周期硬件除法器;
- 硬件支持加载/存储未对齐;
- 硬件支持原子指令;
- 支持不可屏蔽中断(NMI) ;
- 动态分支预测和指令预取缓冲器用于加速控制代码;
- 目前最先进的微架构设计以权衡面积和性能要求;
- 支持WFI(等待中断) ;
- WFE(等待事件)支持;
- 中断优先级可配置/可编程;
- 适用于实时性能的增强矢量中断处理;
- 支持中断优先抢占;
- 支持咬尾中断;
- 标准4线JTAG调试端口;
- 支持交互式调试功能;
- 支持4个硬件断点触发器
具体架构如下图:
ICode和DCode用来访问Flash的数据,系统总线通过AHB矩阵访问,SRAM、AHB、APB1和APB2总线。 - DMA可以通过AHB矩阵访问memory,可以做内存拷贝。
- AHB挂载一些高速外设:FMC、USB_FS、CRC以及RCU
- APB2挂载一些次高速外设:GPIO、USART0,SPI0、Timer0,EXIT以及ADC0和1
- APB1挂载一些低俗外设:USART1和2,UART2和UART3,CAN0/1、RTC、TIMER1-6等等
- ECLIC:中断控制器,外设的中断可以到这里。
memory map位置:与GD32其他系列类似:
- Flash位置:0x08000000
- SRAM位置:0x20000000
- 外设地址:0x40000000开始
启动boot设置也一样:
接着有两个地址可以读一些Flash以及Device id的信息。 - 0x1FFF F7E0:Flash以及SRAM大小
- 0x1FFF F7E8:device ID信息(96位)
Flash通过FMC去操作,从上图的架构图也可以看出,主要写和擦,读可以直接通过memory map的方式,以1KB为一个page。
接着介绍一下时钟:与GD32其他芯片类似,与STM32的时钟图也类似,这列不多介绍。
GD32 RISCV VF103中断机制
这个中断机制属于芯片架构内部的部分,需要介绍一下。采用ECLIC中断模式,改进型内核中断控制器(Enhanced Core Local Interrupt
Controller, ECLIC)。
中断类型:
其支持外部中断和内部中断。
- 外部中断主要是外设比如UART、Timer的一些中断。
- 内部中断主要是软件中断以及定时器中断。
中断屏蔽、中断级别、 优先级与仲裁
根据中断级别(Level)和中断优先级(Priority)进行确定。,两种级别的位数可以通过先关的寄存器确定。
- 中断级别(level)决定了中断是否可以嵌套,
- 中断优先级(priority)以及中断ID 会进行中断裁决,不参与中断嵌套的抉择。
- 中断阈值也可以设置。裁决出的中断高于阈值才会被CPU响应。
- 前提条件是,中断被使能,且中断已经产生了,才可以参与裁决。
中断ID编码如下:
中断处理模式
支持向量模式以及非向量模式。
- 向量模式:中断向量表,CPU根据中断ID和偏移直接 去中断向量基地址去拿地址,然后跳到中断地址(即中断函数)去执行。主要需要加关键字__attribute__((interrupt))),编译器可以加一些上下文保护。
- 非向量模式:即不是直接跳到中断函数地址,而是跳到统一的函数入口,然后再跳到对应的中断函数。
向量模式下的处理流程:
如果需要处理中断嵌套,则需要在中断开始加入处理,因为进入中断前,全局中断已经关闭。
中断向量模式的设置,通过clicintattr[i]的比特域
//sets vector-mode or non-vector mode
void eclic_set_vmode(unsigned int source) {
//read the current attr
unsigned char old_intattr = eclic_get_intattr(source);
// Keep other bits unchanged and only set the LSB bit
unsigned char new_intattr = (old_intattr | 0x1);
eclic_set_intattr(source,new_intattr);
}
void eclic_set_nonvmode(unsigned int source) {
//read the current attr