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);
    }
    
  • 相关阅读:
    Delphi XE5 android 蓝牙通讯传输
    Delphi XE5 android toast
    Delphi XE5 android openurl(转)
    Delphi XE5 如何设计并使用FireMonkeyStyle(转)
    Delphi XE5 android 捕获几个事件
    Delphi XE5 android listview
    Delphi XE5 android 黑屏的临时解决办法
    Delphi XE5 android popumenu
    Delphi XE5 android 获取网络状态
    Delphi XE5 android 获取电池电量
  • 原文地址:https://www.cnblogs.com/lizhuming/p/13783252.html
Copyright © 2011-2022 走看看