【liteOS】小白进阶之移植 LiteOS 到 STM32

1、LiteOS 简介

Huawei LiteOS 是华为轻量级物联网操作系统,其体系架构如下图所示:

【liteOS】小白进阶之移植 LiteOS 到 STM32_第1张图片

Huawei LiteOS由Huawei LiteOS kernel、互联互通中间件、开放API以及安全组成:

1)Huawei LiteOS Kernel为Huawei LiteOS基础内核,属于最精简RTOS。

包括任务管理、内存管理、时间管理、通信机制、中断管理、队列管理、事件管理、定时器、异常管理等操作系统基础组件,可以单独运行;

2)Huawei LiteOS互联互通中间件,可覆盖短距(Wifi、 BT等)/广域(4G/NB-IoT)协议,可解决不同协议架构间互联互通、互操作问题;

3)Huawei LiteOS提供面向不同IoT领域的业务Profile,并以开放API的方式提供给第三方开发者;

4)Huawei LiteOS构建完备的设备侧安全、轻量级E2E传输安全能力。

1.1、LiteOS 特性

【liteOS】小白进阶之移植 LiteOS 到 STM32_第2张图片

1.2、移植环境

开发板:

可选STM32F103、 STM32F4、 STM32F7全系列芯片。

仿真器:

J-Link V9 或者ST-Link

软件环境:

主流的ARM cortex M系列微控制器集成开发环境主要有MDK、 IAR;

由于华为开发者社区已经提供IAR版本的Huawei LiteOS源码,集成开发环境为MDK5.21 ,在 MDK5 安装完成后,要让 MDK5 支持 STM32F103 的开发,还要安装 STM32F103的器件支持包: Keil.STM32F1xx_DFP.2.1.0.pack(STM32F1 系列的器件包)。

下载地址: STM32 器件包

2、源码目录结构介绍

LiteOS 下载地址:

LiteOS

新建工程目录:

在电脑上新建一个目录,这里命名为Huawei LiteOS_STM32_DEMO,将STM32的LED灯例程的文件全部拷贝到该目录下,并将Huawei LiteOSKernel源码文件夹Huawei_LiteOS也拷贝到该目录下,删除Listing、 Output两个文件夹,并将Project文件夹目录下面的文件全部删除。

源码中共有 6 个目录,移植需要使用到的代码在下面用红色标记:

/arch/arm/arm-m     M核中断、调度、tick相关代码
         /common    arm核公用的cmsis core接口(这个可以在keil直接设置)
/components/cmsis                           LiteOS提供的cmsis os接口实现
           /connectivity/agent_tiny         agent_tiny端云互通组件
                        /lwm2m              lwm2m协议实现
           /net/lwip_port                   lwip驱动及OS适配代码
               /lwip-2.0.3                  lwip协议实现
          /security/mbedtls/mbedtls_port    MBEDTLS的OS适配代码
                           /mbedtl-2.6.0    MBEDTLS协议实现
/doc        此目录存放的是LiteOS的使用文档和API说明等文档
/examples   供开发者测试LiteOS内核的demo示例,此目录存放的是内核功能测试用的相关用例的代码
/kernel/base/core               LiteOS基础内核代码,包括队列、task调度、软timer、时间片计算等功能
            /om                 与错误处理相关的文件
            /include            LiteOS内核内部使用的头文件
            /ipc                LiteOS中task间通讯的相关接口,包括事件、信号量、消息队列、互斥锁等
            /mem                LiteOS中的内核内存管理的相关代码
            /misc               内存对齐功能以及毫秒级休眠sleep功能
       /extended/tickless       低功耗框架代码
       /include                 LiteOS开源内核头文件
/targets   不同内核的板端工程代码(含原厂芯片驱动)

由于这里移植的是stm32f1,系统中需要使用到配置文件,在移植时需要复制以下目录中的三个头文件:

/targets/STM32F103RB_NUCLEO/OS_CONFIG/(los_builddef.h, los_printf.h, target_config.h)

/targets/STM32F103RB_NUCLEO也将作为的例程工程进行移植的参考和学习。

3、建立工程

工程可分为三个文件夹 Libraries、Project 和 User。

Libraries 存放的是 stm32 的标准库文件,包括源文件和头文件。

Project存放的是工程相关的文件;

User文件夹下包括了main.c,自己写的bsp,以及移植系统需要用到的源码文件。

若使用到stm32的库函数,则需要添加"stm32f10x_conf.h"这一头文件,并在工程中定义宏“USE_STDPERIPH_DRIVER”和"STM32F10X_HD"。

4、修改启动文件和 .sct 文件

移植中的启动文件和.sct文件对比源码的例程工程并没有进行大幅度的修改简化,保证程序运行的稳定性。

但是这两个文件相比较于裸机工程修改的幅度还是很大的,.sct文件添加了若干个加载域进行分散加载,启动文件也进行了大规模的修改。

在例程工程中的启动文件中,与裸机的启动文件不同,使用符号"Image$ $ARM_LIB_STACKHEAP$ $Base",合并的堆栈/堆区的方法,对堆栈进行划分,从而产生了LOS_HEAP_ADDR_END和LOS_HEAP_ADDR_START两个地址变量。

而原来的启动文件是将堆栈分开进行设置的。

另外,例程工程中的启动文件将中断向量表省略,改成了"boot向量表",缩减了很多,只存有堆栈和Reset_Handler,而将其他的中断向量成员的定义工作完成在"los_hwi.c"文件中,因此.sct也随之变动。

启动文件的代码如下:

Heap_Size       EQU     0x00000400
 
                AREA    LOS_HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit
 
                AREA    LOS_HEAP_INFO, DATA, READONLY, ALIGN=2
                IMPORT  |Image$$ARM_LIB_STACKHEAP$$ZI$$Base|
                EXPORT  __LOS_HEAP_ADDR_START__
                EXPORT  __LOS_HEAP_ADDR_END__
__LOS_HEAP_ADDR_START__
                DCD     __heap_base
__LOS_HEAP_ADDR_END__
                DCD     |Image$$ARM_LIB_STACKHEAP$$ZI$$Base| - 1
 
                PRESERVE8
                THUMB
                AREA    RESET, CODE, READONLY
                IMPORT  ||Image$$ARM_LIB_STACKHEAP$$ZI$$Limit||
                IMPORT  osPendSV
                EXPORT  _BootVectors
                EXPORT  Reset_Handler
_BootVectors       DCD     ||Image$$ARM_LIB_STACKHEAP$$ZI$$Limit||               ; Top of Stack
                DCD     Reset_Handler                                         ; Reset Handler
                
; Reset handler
Reset_Handler   
                IMPORT  __main
                IMPORT  SystemInit
                LDR     R0, =SystemInit
                BLX     R0               
                LDR     R0, =__main
                BX      R0
                                
                ALIGN
                END

.sct文件对应启动文件的改变主要增加了两个加载域:VECTOR和ARM_LIB_STACKHEAP

.sct文件代码如下(地址对应自己的芯片做了修改):

LR_IROM1 0x08000000 0x00080000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00080000  {  ; load address = execution address
        *.o (RESET, +First)
        *(InRoot$$Sections)
        .ANY (+RO)
        * (LOS_HEAP_INFO)
  }
  VECTOR 0x20000000 0x400  {    ; Vector
        * (.data.vector)
  }
  RW_IRAM1 0x20000400 0x0000F800  {  ; RW data
        * (.data, .bss)
        * (LOS_HEAP)
  }
  ARM_LIB_STACKHEAP 0x2000FC00 EMPTY 0x400  {    ;LiteOS MSP
 
  }
}

5、配置参数和任务

在 los_config.h 中修改相应参数:

常用参数如下,这里示例采用的是STM32F103芯片,因此将OS_SYS_CLOCK设为系统主频72Mhz。

#DEFINE OS_SYS_CLOCK 72000000
#DEFINE LOSCFG_BASE_CORE_TSK_LIMIT 15
#DEFINE OS_SYS_MEM_SIZE 0X00008000
#DEFINE LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE SIZE(0X2D0)
#DEFINE LOSCFG_BASE_CORE_SWTMR_LIMIT 16

内核代码移植完毕后,main()函数就可以跑起来了。贴出用来测试的main()函数的代码及相应的解释:

int main(void)
{
    UINT32 uwRet = LOS_OK;
 
    LED_Init();                       //硬件驱动初始化
 
    uwRet = LOS_KernelInit();         //OS内核初始化
    if (uwRet != LOS_OK)
    {
        return LOS_NOK;
    }
        
    uwRet = create_task1();           //创建任务
    if (uwRet != LOS_OK)
    {
        return LOS_NOK;
    }
 
    LOS_Start();                      //启动OS
}

其中,create_task1()如下所示,主要是填满TSK_INIT_PARAM_S类型结构体,调用LOS_TaskCreate函数进行创建:

UINT32 create_task1(void)
{
    UINT32 uwRet = LOS_OK;
    TSK_INIT_PARAM_S task_init_param;
    task_init_param.usTaskPrio = 1;//任务优先级
    task_init_param.pcName = "task1";//任务名
    task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)task1;//指定任务入口函数
    task_init_param.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;//设置任务堆栈大小
    uwRet = LOS_TaskCreate(&g_TestTskHandle,&task_init_param);//调用任务创建函数
    if(uwRet !=LOS_OK)
    {
        return uwRet;
    }
    return uwRet;
}

task1主要做的工作是指示灯的状态切换:

VOID task1(void)
{
    UINT32 uwRet = LOS_OK;
    
    while(1)
    {
        macLED1_TOGGLE();
        uwRet = LOS_TaskDelay(1000);//操作系统延时
        if(uwRet !=LOS_OK)
        return;
    }
}

 

 

refer:

https://blog.csdn.net/sinat_27066063/article/details/84320579 

你可能感兴趣的:(LiteOS系统开发)