9月30日,OpenHarmony 3.0 LTS版本发布。
本文将介绍如何移植OpenHarmony 3.0到星空派开发板上。
1. 星空派开发板介绍
星空派(GD)开发板是由旗点科技推出的一款GD32开发板,板载GD32F303ZET6芯片,可直接替代STM32F103和GD32F103系列。
支持WiFi、4G、loRa等物联通信接口。板载Flash、eeprom等,支持3.2寸的TFT - LCD屏幕。所有IO口均引出,可完整地进行外设开发,包括:JTAG、RTC、I2C、UART、SPI、SDIO、EXMC、DAC、ADC、USB、TFT-LCD等。
2. ARM芯片移植轻量系统基础知识
在做芯片移植工作之前,我们需要掌握一点点基础知识。
(1)适配LiteOS-M轻量系统
GD32F303系列器件是基于Arm® Cortex®-M4处理器的32位通用微控制器。所以我们使用的是内核是LiteOS-M,对应的是OpenHarmony轻量系统。
事实上,OpenHarmony已经做好了Cortex®-M4 核相关的通用移植工作,具体代码可以查看文件夹:“kernel\liteos_m\kernel\arch\arm”。
可以看到目前已经支持了cortex-m4核。所以内核移植工作基本不需要,减少了我们很多工作量,但是我们仍然需要移植GD32F303芯片相关的。
(2)哈佛架构
GD32F303采用的是哈佛架构,哈佛架构的特点是代码指令和数据分开存储。对于GD32F303而言,代码是存放在片内flash上,地址是0x8000000。
数据(也就是代码中用到的各种变量、内存等)是存放在芯片内部内存RAM上,地址是0x20000000,总共64K,即0x10000。
(3)编译结果分析
对于GD32F303而言,编译出来的固件一般是bin格式、或者hex格式。通常编译最后的结果会产生4种不同的内容,有时我们也称为4段:
1)code:即程序代码部分,该内容由所有程序指令组成,也是代码运行的主体,通常是要烧录到GD32F303片内flash上。
2)RO-data:只读数据段,例如我们在程序中所定义的全局常量数据和字符串都位于此处。由于这些数据都是只读,不会改变的,那这些只读的全局就没必要放到内存种,可以直接放到flash中,可以节省内存。
3)RW-data:已初始化的读写数据,程序中定义并且初始化的全局变量和静态变量位于此处。由于内存刚上电后,内存上的数据是未知,所以我们需要事先把这些全局变量、静态变量的初始值先存放到flash中,然后上电后,由CPU将flash中的初始值赋予到内存中的变量中。
4)ZI-data:未初始化的全局变量或者初始化为0的全局变量,这些变量默认都是0,我们只需要CPU上电后,将这些内存都清零即可。
由上我们可以的出来2个结论:
1)我们编译出来的固件要烧录到GD32F303的片内flash,需要由3段数据:code、RO-data、RW-data。
2)芯片上电后,GD32F303需要将RW-data的内容复制到内存对应位置,从而保证初始化的全局变量和静态变量的值正确;还要对内存中的ZI-data段进行清零操作,最后才能执行main函数。
(4)程序如何启动
对于ARM Cortex-M系列的芯片而言,当芯片上电后,ARM核会将地址为0x8000000的数据映射到0地址,然后从0地址开始读取程序指令。
而0x8000000地址是芯片内部flash的起始地址。也就是编译生成的固件最终要烧录到的地址。所以我们的固件前面的代码非常重要,它是我们芯片启动后执行的第一条指令。
(5)中断向量表
对于ARM Cortex-M系列的芯片而言,0x8000000地址第一个字节是栈指针,由于栈是从高往下增长的,所以该栈指向芯片最大内存处即可。
接下来从0x8000000的第2个字节开始是中断向量表,存放着所有中断处理函数指针。前面16个是内核中断,其中第一个中断指针存放的是Reset_Handler复位中断处理函数。芯片一上电、或者复位,都会先从该中断函数开始运行,所以这个函数是我们最重要的,我们需要在该函数中完成RW-data、ZI-data数据的操作,同时初始化好芯片时钟、最后进入main函数。
3. 移植GD32F303芯片到OpenHarmony3.0
这里提供移植好的相关代码,下载链接:https://gitee.com/qidiyun/gd32-f303-for-open-harmony-3.0
(1)先按官网教程搭建好Ubuntu下的开发环境。
下载arm交叉编译器:
git clone https://gitee.com/harylee/gcc-arm-none-eabi-10-2020-q4-major.git ,将交叉编译器环境变量bin目录配置到.bashrc文件中或者配置device/st/stm32l4r9i_disco/liteos_m/config.gni文件中board_toolchain_path宏为交叉编译器bin路径。
(2)下载上方移植好的代码,文件夹如下:
将device文件夹下的gd文件夹复制到OpenHarmony3.0代码的device文件夹下。
将vendor文件夹下的gd文件夹复制到OpenHarmony3.0代码的vendor文件夹下。
复制后,OpenHarmony3.0的device文件夹内容如下:
OpenHarmony3.0的vendor文件夹内容如下:
(3)编译
进入OpenHarmony3.0源码根目录,输入 hb set 可以看到由gd32f303_qidian的编译选项。选择。
输入 hb build -f开始全编译:
有看到 [OHOS INFO] gd32f303_qidian build success 表示编译成功。
编译完成后,可以在“out\gd32f303_qidian\gd32f303_qidian”文件夹下看到编译结果,其中“gd32f303_qidian_ninjia.hex”就是可以直接烧录到开发板的固件。
4. vendor文件夹
该文件下最重要的文件是“config.json”。
内如如下,主要是配置相关组件:
5. device代码
(1)device文件夹:
该文件夹下是星空派开发板的重要代码部分,其中就有启动文件、main函数、中断处理等。
由于移植内容较长,本文重点介绍启动文件、链接脚本。
(2)启动文件
启动文件startup_gd32f30x.s 。最重要的是将RW-data的内容复制到内存对应位置,从而保证初始化的全局变量和静态变量的值正确;还要对内存中的ZI-data段进行清零操作,最后才能执行main函数。
代码都是汇编,参考自st和gd相关启动文件,重要代码如下:
(3)链接脚本
链接脚本是“gd32f30x_qidian.ld”,用于指定code、RO-data、RW-data、ZI-data如何分布。
首先指定内存地址为0x20000000,大小为64K。
片上flash地址为:0x8000000,大小为512K。
这里跟芯片相关,需要正确修改,否则可能起不来。
这里跟芯片相关,需要正确修改,否则可能起不来。
(4)固件生成规则。
同时链接脚本也指定了固件的生成规则:
这里只截取了部分,可以看到生成的固件最开始存放的isr_vector,这个是中断向量表,在启动文件中定义:
接下来就是text,也就是代码段。
还有rodata,只读数据段。
后面还有其它定义,我们下一篇再细节。
至此我们的启动文件、链接脚本中比较关键的部分已经说明完。
6. liteos-m内核配置
进入“device\gd\gd32f303_qidian\liteos_m”文件夹,可以看到有这个文件“config.gni”。
该文件用于配置 liteos-m内核。
其中比较重要部分是指定我们的处理器架构和交叉编译工具链,如下:
我们使用的交叉编译工具链是 “arm-none-eabi-”。
下面还配置了相关宏定义和gd标准库头文件路径,需要大家修改。
好了~~~,初步移植要点讲完了,下一篇文章讲openharmony内核配置文件、main函数启动后如何进入鸿蒙轻量内核。