目标示例开发板:STM32F103ZET6,Cotex-m3架构

移植目标:基本任务运行,tick时钟实现任务周期睡眠,基本串口打印

版本:基于AOS-R-2.1.0版本,其他版本可能存在具体的目录和规范不一样,整体流程相同。

1.1、使用ST CubeMX自动生成AliOS Things工程

ST CubeMX工程中集成了AliOS Things的组件功能,用户可以在CubeMX中通过组件选择的方式生成对应的keil或iar工程。具体操作指导参考网址:https://github.com/alibaba/AliOS-Things/wiki/Generate-Keil-IAR-Project-via-ST-CubeMX.zh

1.2、使用IDE命令自动生成keil\iar工程介绍

AliOS Things支持在aos make 编译的时候使用IDE=keil 或 IDE=iar命令来自动生成对应的keil\iar工程。此功能的前提是已经基于该单板建立了gcc的编译体系。具体参考:https://github.com/alibaba/AliOS-Things/wiki/Auto-generate-keil-iar-project 如,通过命令aos make rhinorun@stm32f103ze IDE=keil可以在project目录下,生成如下的内核keil工程: 生成的工程相关的编译文件、编译选项等都已经配置好,可以直接编译和使用;如果存在较少的编译问题,直接按照提示解决具体问题即可。

2、手动建立kei\iar示例指导

上面提到的自动化工具,参考相应的指导说明操作即可;本章节主要提供手动建立基本的内核keil\iar工程的示例指导。按照实际工程搭建的过程来说明。

2.1、基本代码准备

单板相关的所有代码放入AliOS Things系统时,都需要遵从《AliOS Things板级支持目录规范》,包括app\board\mcu等目录结构内的文件和目录布局,具体细节见wiki:https://github.com/alibaba/AliOS-Things/wiki/AliOS-Things%E6%9D%BF%E7%BA%A7%E6%94%AF%E6%8C%81%E7%9B%AE%E5%BD%95%E8%A7%84%E8%8C%83本文档侧重于介绍keil\iar工程相关的工程建立,涉及到具体的系统代码实现细节可参考《AliOS Things内核驱动移植指导》:https://github.com/alibaba/AliOS-Things/wiki/AliOS-Things%E5%86%85%E6%A0%B8%E9%A9%B1%E5%8A%A8%E7%A7%BB%E6%A4%8D%E6%8C%87%E5%AF%BC

2.1.1、STM32CubeF1系列Drivers驱动程序

下载安装STM32CubeMX,选择生成STM32F103ZET6驱动程序,或者官网直接下载STM32CubeF1软件包。驱动包下载更新地址:http://www.st.com/content/st_com/en.html选择搜索STM32CubeMX或者STM32CubeF1关键字。

STM32CubeMX下载后直接安装使用。下面是通过STM32CubeMX生成驱动源码的基本流程参考。

  • STM32CubeMX选择“New Project”,MCU选择STM32F103ZE系列,参考开发板为STM32F103ZET6,选择对应的MCU名;

  • 设置Pinout查看对应的芯片手册,选择USART1作为打印串口,并配置相关时钟,对应的PA9\PA10分别为发送和接收接口。

  • 设置系统频率:

生成code,keil工程选择MDK-ARM V5,iar工程选择EWARM:

点击确定后,相关keil工程的所有文件则生成在指定目录,如:

生成工程时,选择EWARM:

在生成目录下,会产生iar的工程文件,其他文件和Keil生成相同:

Drivers下面为该stm32f1xx系列的通用驱动;MDK-ARM中为keil工程文件;EWARM下为iar工程文件;Src和Inc为stm32f103ze单板的系统初始化程序。生成代码后,相关代码需要拷贝到AliOS Things工程。相关SDK驱动统一放在:platform\mcu\stm32f1xx\drivers下;Keil工程统一放在:projects\Keil\rhinorun@stm32f103ze\keil_project目录下;iar工程统一放在:projects\IAR\rhinorun@stm32f103ze\iar_project目录下。其中rhinorun表示需要运行的实例;stm32f103ze为单板名。其他文件待放入board目录下。

2.1.2、rhino内核源码

源码路径:kernel\rhino

2.1.3、Cortex-m3相关代码

实现代码路径:Cortex-m3实现:platform\arch\arm\armv7m\armcc\m3arch公共文件:platform\arch\arm\armv7m\common

2.1.4、Mcu相关代码

2.1.4.1、mcu下drivers目录

在platform\mcu下建立stm32f1xx代表该MCU体系的目录,下面包含drivers和hal目录。按照2.1.1章节描述,将CubeMX生成的sdk放入platform\mcu\stm32f1xx\drivers目录下,不做任何修改。

2.1.4.2、mcu下hal目录

对于基本的打印功能,首先需要实现uart的hal接口,在mcu\stm32f1xx下面建立hal目录,专门存放hal相关的实现,建立hal_uart_stm32f1.c文件,实现相关的hal_uart_init以及hal_uart_send接口。Hal层代码具体的实现参考:https://github.com/alibaba/AliOS-Things/wiki/AliOS-Things-HAL-Porting-Guide#1%E7%A1%AC%E4%BB%B6%E6%8A%BD%E8%B1%A1%E5%B1%82%E7%A7%BB%E6%A4%8D

2.1.5、Board相关系统启动初始化

在board下面建立stm32f103ze单板目录,并按照如下目录结构规范建立相应的目录文件:

Dir\File                          Description                              Necessary for kernel run
|-- drivers                  # board peripheral driver                                N
|-- config
|   |-- board.h              # board config file, such as uart port num               Y
|   |-- k_config.c           # user's kernel hook and mm memory region define         Y
|   |-- k_config.h           # kernel config file .h                                  Y
|   |-- partition_conf.c     # board flash config file                                N
|-- startup
|   |-- board.c              # board_init implement                                   Y
|   |-- startup.c            # main entry file                                        Y
|   |-- startup_gcc.s        # board startup assember for gcc                         Y
|   |-- startup_iar.s        # board startup assember for iar                         Y
|   |-- startup_keil.s       # board startup assember for keil                        Y
|-- stm32f103ze.icf          # linkscript file for iar                                Y
|-- stm32f103ze.ld           # linkscript file for gcc                                Y
|-- stm32f103ze.sct          # linkscript file for sct                                Y
|-- aos.mk                   # board makefile                                         Y
|-- Config.in                # menuconfig component config                            Y

当然对于只建立keil\iar工程来说,aos.mk、gcc相关的文件都是不必要的。

2.1.5.1、Board下drivers目录

此处drivers目录下驱动的相关实现都来源于CubeMX生成的keil\iar工程中Src和Inc目录:生成的Src目录: 生成的Inc目录: 将main.c修改为stm32f1xx_main.c,main.h修改为stm32f1xx_main.h,注释掉内部生成的系统默认main函数。后续将会在board\stm32f103ze\startup\startup.c中建立OS系统级的main函数。所有文件统一放在board\stm32f103ze\drivers下作为板级驱动。修改后文件列表:

2.1.5.2、Board下config目录

|-- config
|   |-- board.h     
|   |-- k_config.c           
|   |-- k_config.h           
|   |-- partition_conf.c

其中,board.h为具体的设备逻辑port定义;k_config.c内为内核相关的配置接口实现;k_config.h为内核的配置头文件;partition_conf.c为flash分区配置。此部分代码可以直接参考其他board单板实现,进行相应的参数修改。

2.1.5.3、Board下startup目录

|-- startup
|   |-- board.c                                        
|   |-- startup.c                                       
|   |-- startup_gcc.s         
|   |-- startup_iar.s          
|   |-- startup_keil.s

其中,board.c中实现板级的初始化board_init,可参考原有main.c中的main函数初始化相关硬件;startup.c为OS级的启动代码,基本可以实现通用,可直接参考其他实现;关于keil的启动汇编代码startup_keil.s,在生成keil工程时已经自动生成;iar的启动汇编startup_iar.s在生成iar工程时产生。

2.1.5.4、单板初始化示例代码(startup.c)

(1)、系统初始化示例:

int main(void)
{
    /*irq initialized is approved here.But irq triggering is forbidden, which will enter CPU scheduling.
    Put them in sys_init which will be called after aos_start.
    Irq for task schedule should be enabled here, such as PendSV for cortex-M4.
    */
    board_init();   //including aos_heap_set();  flash_partition_init();
    /*kernel init, malloc can use after this!*/
    krhino_init();
    /*main task to run */
    krhino_task_dyn_create(&g_main_task, "main_task", 0, OS_MAIN_TASK_PRI, 0, OS_MAIN_TASK_STACK, (task_entry_t)sys_init, 1);
    /*kernel start schedule!*/
    krhino_start();
    /*never run here*/
    return 0;
}

(2)、主任务初始化示例:

static void sys_init(void)
{
    /* user code start*/
    /*insert driver to enable irq for example: starting to run tick time.
     drivers to trigger irq is forbidden before aos_start, which will start core schedule.
    */
    /*user_trigger_irq();*/  //for example
    /*aos components init including middleware and protocol and so on !*/
    aos_components_init(&kinit);
    #ifndef AOS_BINS
    application_start(kinit.argc, kinit.argv);  /* jump to app/example entry */
    #endif
}

(3)、用户app入口示例(参考test\develop\rhinorun\rhinorun.c):

int application_start(int argc, char *argv[])
{
    int count = 0;
    printf("nano entry here!\r\n");
    while(1) {
        printf("hello world! count %d \r\n", count++);
        aos_msleep(1000);
    };
}

2.2、基本内核代码适配

目标建立一个基本的延时打印任务,需要的代码修改包括:

· 基本的任务处理和调度在2.1.2和2.1.3代码中已经提供;

· stm32f1xx_it.c中修改tick时钟:

SysTick_Handler中断处理调用krhino处理函数krhino_tick_proc;

HAL_InitTick设置每秒Tick数时,使用宏RHINO_CONFIG_TICKS_PER_SECOND;

· board_init.c基本驱动初始化:系统时钟、uart以及tick等的初始化。

· rhinorun.c中实现用户app入口函数:application_start,内部实现循环睡眠打印。

· hal_uart*.c打印接口:见章节2.1.4.2中hal介绍。

· main函数初始化:章节2.1.5.4已介绍

2.3、keil\iar工程配置

2.3.1、内核工程依赖源文件

下述为新增一个单板支持,必须关注的几个目录项:

App\example 通用用户运行实例,如helloworld实例,可直接使用,无特殊情况不修改
test\develop 用户自定义特殊运行实例,满足某一特定场景时添加,和上面example同用途
board 用户需要适配、可配置board级代码,系统启动相关代码
Platform\arch 该CPU架构内核调度适配接口,可直接使用
Platform\mcu 该MCU通用SDK以及对应的hal适配层
Rhino 内核源码
utility\libc C库适配接口:newlib_stub.c(gcc)、armcc_libc.c(armcc)、iar_libc.c(icc)

原则上基本内核工程使用上述组件,即可组成完整的闭环系统;但是由于具体接口实现方式,可能会引入其他关联依赖模块,主要包括:

kernel\debug模块 platform\arch中异常处理代码需要使用调试接口;系统资源紧张时,可以将arch下面的panic*.c和该debug模块整体从工程中删除。
Osal模块 C库适配接口中实现依赖aos API接口
Ulog 系统记录日志功能,如果只使用printf,该模块可删除。
Kernel\init 系统初始化后,如果调用中间件和协议层初始化接口aos_components_init,即会引入。可删除。

上表中都是被引入的依赖模块,如果在系统资源紧张的情况下,用户可以按照自己的需求,去掉依赖关系,并将上述模块不加入编译体系。例如去掉aos_components_init的引用,即不会引入Kernel\init。

2.3.2、keil工程建立示例

2.3.2.1、keil工程配置

基于生成的Keil工程路径,配置需要编译的源文件,需要包含的头文件,需要使用的编译选项,以及需要的链接选项等。章节2.1.1中已经将CubeMX生成的Keil工程拷贝到AliOS Things的project目录下 打开该keil工程,开始相关的配置操作。主要配置项包括:· 加入编译.c.S源文件:右击工程,选择“Manage Project Items”;或通过工具栏快捷键选择:

“Manage Project Items” 中建立相关groups名,一般按照子目录或者组件取名,命名直观;并包含该目录需要编译的.c以及汇编.s.S文件;

参考2.3.1内核工程依赖源文件的描述,对于目前基本的kernel工程,建立如下Groups分组:

rhinorun test/develop/rhinorun
board_stm32f103ze board/stm32f103ze
arch_armv7m platform/arch/arm/armv7m中m3相关
mcu_stm32f1xx platform/mcu/stm32f1xx下drivers和hal目录;其中drivers按照具体厂商需要包含的实际驱动文件为准;hal下面优先包含hal_uart*.c,其他hal按需增删。
rhino kernel/rhino下所有文件
newlib_stub utility/libc/compilers/armlibc
debug kernel/debug
osal osal/aos基本的common.c和rhino.c
ulog middleware/uagent/ulog
kernel_init kernel/init

添加对应的文件后,如下图所示:

· 右击工程,选择“Options for Target”,内部集成了所有相关的配置项;或通过工具栏快捷键选择,如下图。用户也可以设置具体“Groups”或者具体某个文件的配置项;建议没有特殊需求,统一使用project项目的总配置。

首先要确认“Device”选项卡中,Device型号选择正确:

“C/C++”和asm选项卡设置编译选项、建立编译依赖头文件;对于AliOS Things工程需要的编译选项,可以参照已有board的实现来添加。对于引用的头文件,在上一章节中所有包含目录下的头文件目录,理论上都需要增加进入” Include Paths”。 · 选择工程“Options for Target”,“Linker”选项,用户可以自设置链接sct文件,如果不设置则采用系统默认链接文件; 在” Misc controls”中设置对应的链接选项。

其他选项采用默认配置,也可按需调整。工程建立后编译工程到编译OK。

2.3.2.2、keil单板调试

· 右击工程,选择“Options for Target”,“Debug”选择ST-Linker Debugger。

· Load 烧录bin文件:通过菜单栏Flash->download,或者工具栏快捷键完成代码烧写。 · Debug调试代码:通过菜单栏通过Debug->Start/Stop Debug Sesion,或者工具栏快捷键打开调试界面。

· 连接串口工具,查看打印Logapplication_start中每周期打印一次串口,并将当前任务睡眠,运行OK后如下图所示:

2.3.3、iar工程建立示例

2.3.3.1、iar工程配置

基于生成的iar工程路径,配置需要编译的源文件,需要包含的头文件,需要使用的编译选项,以及需要的链接选项等。章节2.1.1中已经将CubeMX生成的iar工程拷贝到AliOS Things的project目录下 打开该iar工程,开始相关的配置操作。主要配置项包括:· 加入编译.c.S源文件,依然按照先建立Group,再建立Files的方式:

右击workspace区域,弹出菜单中选择add,可以添加Group;选中对应的Group右击,选择Add Files,可以选择属于该Group的源文件。参考2.3.1内核工程依赖源文件的描述,对于目前基本的kernel工程,同keil工程,也建立2.3.2.1中描述的Groups分组;添加对应的文件后,如下图所示:· 右击工程名,弹出菜单选择“Options”,打开整体工程配置项;用户也可以选中某个Group或者文件右击,单独给其修改配置。

打开”Options”窗口后,首先要确认设备Device类型是否正确:

“C/C++ Compiler”和”Assembler”选项卡设置编译选项、建立编译依赖头文件;对于AliOS Things工程需要的编译选项,可以参照已有board的实现来添加。对于引用的头文件,在所有包含目录下的头文件目录,理论上都需要增加进入”Additional include directories”。在“Defined symbols”选项中增加预编译宏定义;”Extra Options”标签中增加编译选项定义。

· 选择选项卡“Linker”,在标签“Config”设置链接脚本;在”Extra Options”标签中增加链接选项定义。

其他选项采用默认配置,也可按需调整。工程建立后编译,可能存在具体的编译问题,解决后直到工程编译完成。

2.3.3.2、iar单板调试

· 右击工程,选择“Options”,弹出配置窗口后,打开选项卡“Debugger”,点击标签“Setup”,”Driver”选择ST-LINK。

· 选择工具栏“Download and Debug”快捷键,进行烧录调试。

· 连接串口工具,查看打印Log