zoukankan      html  css  js  c++  java
  • 【LiteOS】Liteos移植篇


    前言

    OpenHarmony来势汹汹,第一次开源,仅支持LiteOS-a,所以,在此有必要学习一下LiteOS。或许工作上用不上Harmony,但是,星星之火可以燎原,助力完善 lot 生态应该可以。那就从 MCU 开始吧,移植 LiteOS。

    链接

    参考

    • 野火
    • 上面链接

    笔录草稿

    • los_init.c中的大部分内容已经移到了los_config.c里面了,可以看那里面的内容
    • 使用软件定时器则必须要使用消息队列,否则不会使用软件定时器。

    移植(2018)

    • 在移植的时候暂时不建议获取最新(不要使用202003)后推送的版本)的版本默认只支持 GCC ,且 MDK 官方移植教程未出。所以只能在 github 获取源码来移植 LiteRTOS。(时间截止于 20200922*)

    • 移植方案分为两种:

      • 硬中断接管方案
      • 不接管中断方案
    • 由于硬中断接管方案移植难度比不接管中断方案大,所以,本次笔记记录不接管中断方案。

    移植获取 (Cortex-M 内核

    * RAM 大于 8K
    * ROM 大于 20K
    
    • 裸机空工程
      • 能正常运行 main 函数
      • 本次移植基于 STM32F103VCT6
    • LiteOS 源码
      • 时间截止于 20200922 ,不推荐获取官方最新推送的源码,因为最新版本默认只支持 GCC ,且 MDK 官方移植教程未出。(可尝试获取最新版本+旧版本补全
      • 建议获取 2018 年左右推送的版本。
    • 本教程源码源于2018年版本,也会对比新版本做说明。

    主要文件夹分析

    官方代码导读 *该链接为最新版本的文件分析,与下面的会有所不同,具体按照实际下载版本导读 *

    • arch
      • arm
        • arm-m:M 核中断、调度、tick 相关代码
        • common:arm 核公用的 cmsis core 接口
    • components
      • cmsis:LiteOS 提供的 cmsis os 接口实现
    • kernel
      • base
        • core:LiteOS 基础内核代码文件,包括队列、task 调度、软 timer、时间片等功能
        • OM:与错误处理相关的文件
        • include:LiteOS 内核内部使用的头文件
        • ipc:LiteOS 中 ipc 通讯相关的代码文件,包括事件、信号量、消息队列、互斥量等
        • mem:LiteOS 中的内核内存管理的相关代码
        • misc:内存对齐功能以及毫秒级休眠 sleep 功能
      • include:LiteOS 开源内核头文件
      • extenden
        • ticless:低功耗框架代码

    移植过程

    1. 拷贝文件

    • 在工程路径上创建 LiteOS 文件夹
    • 拷贝 LiteOS 源码中的 arch、cmsisLiteOS 提供的 cmsis os 接口实现
      kernel 三个文件夹到 工程 LiteOS 文件夹中。
    • 拷贝 LiteOS源码下对应 demosOS_CONFIG 文件夹到上述路径。
      • OS_CONFIG 该文件夹主要配置文件,用于内核配置和裁剪。
    • 拷贝 keil 安装目录下的一个文件夹到工程 工程\Libraries\CMSIS
      • 安装路径目录下的一个文件夹,其参考路径为:D:\Keil_v5\ARM\Pack\ARM\CMSIS\4.2.0\CMSIS\Include
      • 移植理由
        • 避免其它电脑在移植过程中没有相关头文件而引起的编译错误。

    2. 创建工程分组

    新建 4 个工程分组:

    • LiteOS/cmsis
      • 添加 cmsis_LiteOS.c 文件
    • LiteOS/kernel所有需要用到的 .c 文件
      • \LiteOS\kernel\base\core 所有.c 文件
      • \LiteOS\kernel\base\ipc 所有.c 文件
      • \LiteOS\kernel\base\mem\bestfit_little 所有.c 文件
      • \LiteOS\kernel\base\mem\common 所有.c 文件
      • \LiteOS\kernel\base\mem\membox 所有.c 文件
      • \LiteOS\kernel\base\misc 所有.c 文件
      • \LiteOS\kernel\base\om 所有.c 文件
      • \LiteOS\kernel\extended\tickless 所有.c 文件
      • \LiteOS\kernel los_init.c
    • LiteOS/arch
      • \LiteOS\arch\arm\arm-m\src 所有.c 文件
      • \LiteOS\arch\arm\arm-m\cortex-m?\keil los_dispatch_keil.S
        • ?:代表当前需要移植到哪一种内核的chip上。如cortex-m3。
    • LiteOS/config
      • \LiteOS\OS_CONFIG
        • los_builddef.h(可选
        • los_printf.h(可选
        • target_config.h

    3. 添加头文件路径

    参考图片:

    4. 兼容 C99 模式

    • 在 target->C/C++->Language/Code Generation 中勾选 C99 Mode
    • 在 target->C/C++->MiscControls 框中输入 --diag_suppress=1,47,177,186,223,1295
      • 意思是忽略这些编号的警号

    5. 内核配置与裁剪(非接管中断的stm32f103vct6)

    • 主要在 target_config.h 文件上配置,具体内容直接看源码,这里列出几个主要的点:
      • 修改头文件 #include "stm32f1xx.h"#include "stm32f10x.h"
      • OS_SYS_CLOCK
        • 表示 CPU 主频
        • 如STM32VCT6 配置为 72MHz,即是 72000000
      • LOSCFG_BASE_CORE_TICK_PER_SECOND
        • RTOS 心跳
          • 对于 STM32F10x,一般设置 1ms-10ms,如设置为 1ms,则配置为 1000UL
      • 内存地址
        • BOARD_SRAM_START_ADDR

          • 根据编译器中 RAM 配置的其实地址设置,这里为 0x20000000。
        • BOARD_SRAM_SIZE_KB

          • 分配给系统使用的内存,即是RTOS管理的总堆栈。这里设置为 20。

    6. 屏蔽裸机中的两个中断

    在 stm32fxxx_it.c 文件中注释掉 PendSVSysTick 中断即可。

    • SysTick
      • 主要提供心跳
    • PendSV
      • 该异常可以进入任务调度检测并进行调度。

    7. 完善代码

    本工程基于本人编写的裸机框架,需要的可以参考。

    • 在 LssAppConfig.h 文件中添加以下头文件:
    /*
    *********************************************************************************************************
    *                                                 OS
    *********************************************************************************************************
    */
    #include "target_config.h" 
    #include "los_sys.h"
    #include "los_typedef.h"
    #include "los_task.ph" 
    #include "los_sem.h" 
    
    • 不废话,直接上写好的 main.c 文件(看源码比文字教程方便多了)
      • 主要参考源码中的
        • 任务创建函数
        • 启动流程
      • 该源码的启动流程采用的是 任务创建任务 的方案。
    /**
     ******************************************************************************
     * @file    main.c
     * @author  lss
     * @version V1.0
     * @date    2020-xx-xx
     * @brief  主函数文件
     ******************************************************************************
     * @attention 
     *
     * 实验平台:LZM
     * Wechat:qabc132321
     ******************************************************************************
     */
      
    /*
    *********************************************************************************************************
    *                                          INCLUDE  
    *********************************************************************************************************
    */
    /* APP Config File */
    #include "LssAppConfig.h"
    /* prv */
    #include "userMemoryConfig.h"
    
    /* task */
    #include "LedTask.h"
    /***********************************************************************************************************
    *                               板子信息 [注]实时修改
    ***********************************************************************************************************/
    BoardInfo_t BoardInfo = {    .name = "LSS TEST",
                                            .boardType = 0,
                                            .boardNum = 0,
                                            };
    
    /***********************************************************************************************************
    *                               固件版本
    ***********************************************************************************************************/
    #if defined(__CC_ARM) // 编译器相关
    const unsigned MCU_VERSION1_ENTRY __attribute__((at(ParameterSectionVEntry))) = SystemProgramAddressEntry;
    const unsigned MCU_VERSION1_SIZE     __attribute__((at(ParameterSectionVEntry+0X04))) = SystemProgramAddressSize;
    const unsigned CRP_VERSION1_NUM     __attribute__((at(ParameterSectionVEntry+0X08))) = (0x01000000);
    #endif
    
    /***********************************************************************************************************
    *                               函数声明
    ***********************************************************************************************************/
    void vStartTask (void );
                                            
    /*
    **********************************************************************************************************
    							句柄变量声明
    **********************************************************************************************************
    */
    static UINT32 xStartTask_Handle           = NULL;
    UINT32 xLedTask_Handle                      = NULL;  //LED任务
    
    
    /**
    * @brief  创建vStartTask任务
    * @param 
    * @retval 
    * @author lzm
    */
    static UINT32 Creat_vStartTask_Task()
    {
    	//定义一个创建任务的返回类型,初始化为创建成功的返回值
    	UINT32 uwRet = LOS_OK;			
    	//定义一个用于创建任务的参数结构体
    	TSK_INIT_PARAM_S task_init_param;	
    
    	task_init_param.usTaskPrio = lssConfigvStartTaskPRIO;	/* 任务优先级,数值越小,优先级越高 */
    	task_init_param.pcName = "Start_Task";/* 任务名 */
    	task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)vStartTask;/* 任务函数入口 */
    	task_init_param.uwStackSize = lssConfigvStartTaskSIZE;		/* 堆栈大小 */
    
    	uwRet = LOS_TaskCreate(&xStartTask_Handle, &task_init_param);/* 创建任务 */
    	return uwRet;
    }
                                            
    /**
    * @brief  创建vLedTask任务
    * @param 
    * @retval 
    * @author lzm
    */
    static UINT32 Creat_vLedTask_Task()
    {{
    	//定义一个创建任务的返回类型,初始化为创建成功的返回值
    	UINT32 uwRet = LOS_OK;			
    	
    	TSK_INIT_PARAM_S task_init_param;	
    
    	task_init_param.usTaskPrio = lssConfigvLedTaskPRIO;
    	task_init_param.pcName = "Led Task";
    	task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)vLedTask;
    	task_init_param.uwStackSize = lssConfigvLedTaskSIZE;
    
    	uwRet = LOS_TaskCreate(&xLedTask_Handle, &task_init_param);
    	return uwRet;
    }
                                            
    /**
    * @brief  创建应用任务
    * @param 
    * @retval 
    * @author lzm
    */
    void vStartTask (void )
    {
        UINT32 uwRet = LOS_OK;
        UINTPTR uvIntSave;    
        // 进入临界
        taskENTER_CRITICAL(uvIntSave);   
        uwRet = Creat_vLedTask_Task();
    	if (uwRet != LOS_OK)
        {
            ;
        }   
        // 删除本任务
        LOS_TaskDelete(xStartTask_Handle);     
        // 退出临界
        taskEXIT_CRITICAL(uvIntSave);    
    }
                                            
                                                                           
                                            
    /**
    * @brief  mian函数
    * @param 
    * @retval 
    * @author lzm
    */
    int main(void)
    {	
        uint32_t uwRet = LOS_OK;  //定义一个任务创建的返回值,默认为创建成功
        
    	//bsp初始化
    	bspInit();	
        
        /* LiteOS 内核初始化 */
    	uwRet = LOS_KernelInit();
        if (uwRet != LOS_OK)
        {
            ;
        }
        
    	/* 创建创建任务 */
        uwRet = Creat_vStartTask_Task();
        if (uwRet != LOS_OK)
        {
            ;
        }
            
        /* 开启LiteOS任务调度 */
        LOS_Start();
        
    	while(1);
    }
    
  • 相关阅读:
    HomeBrew安装MongoDB如何启动
    Express + Mongoose 极简入门
    Express + Mongoose 极简入门
    浅谈 PHP 与手机 APP 开发(API 接口开发)
    浅谈 PHP 与手机 APP 开发(API 接口开发)
    统计与分布之伯努利分布与二项分布
    统计分布之泊松分布
    统计与分布之高斯分布
    Python 2 和 3 的区别及兼容技巧
    组合与排列
  • 原文地址:https://www.cnblogs.com/lizhuming/p/13783252.html
Copyright © 2011-2022 走看看