1 为什么移植?

嵌入式设备的芯片型号和外设的差异较大,资源有限。而RTOS无法适配集成所有的驱动,因此会先适配部分开发板,然后通过移植使得适配更多的开发板。

可移植性是嵌入式操作系统与普通操作系统的显著区别之一,而所谓移植就是通过一定的代码修改使得该操作系统适配自己的开发板,以使得自己的开发板可以运行一些手头开发板没有配套的编译工程。

2 移植的分类

移植通常分为系统移植和驱动移植,驱动移植需要依赖具体的外设,本文主要介绍操作系统的移植。采用的主要方案是硬中断接管和不接管中断中的更加简便快捷的不接管中断方式。

3 开发环境

软件环境:Windows系统、Keil5、J-Link对应驱动;

硬件环境:GD32450i-EVAL开发板、J-Link下载器、串口线、数据线;

注意:上述环境也可根据自己需求进行修改,如使用IAR、GCC等。

4 移植流程

4.1 准备工作

(1)下载LiteOS源码

在github上下载最新的LiteOS源码,地址:https://github.com/LiteOS/LiteOS,下载任意版本皆可,其源码核心一致,我这里使用的是dev-deserted,其工程目录详情如图1所示。

图1 LiteOS源码工程目录以及对应描述

(2)提取LiteOS核心移植文件

对LiteOS源码做一个简单的提取便于后续操作的简洁性,当然也可以不提取,新建文件夹命名为LiteOS,将 LiteOS源码中的arch文件、components/cmsis文件、kernel文件、以及targets文件中的示例工程中拷贝两个OS_CONFIG文件,其中一个为接管中断(如Standard_GD32F103C_START工程中的OS_CONFIG文件)一个为非接管中断(如Standard_STM32F103VC_TAIBI工程中的OS_CONFIG文件)。具体如下表1所示。

表1 LiteOS核心文件提取

一级目录

一级目录

一级目录

描述

arch

arm

arm-m

M   核中断、调度、tick相关代码

common

arm核公用的 cmsis core 接口

cmsis

   

LiteOS   提供的 cmsis os接口实现

kernel

base

core

LiteOS   基础内核代码文件,包括队列、

task   调度、软 timer、时间片等功能

OM

与错误处理相关的文件

Include

LiteOS   内核内部使用的头文件

ipc

LiteOS   中 ipc 通讯相关的代码文件,包括事件、信号量、消息队列、互斥锁等

mem

LiteOS   中的内核内存管理的相关代码

misc

内存对齐功能以及毫秒级休眠   sleep 功能

include

 

LiteOS   开源内核头文件

extended

tickless

低功耗框架代码

OS_CONFIG

 

非接管中断

OS_CONFIG_Take

 

接管中断

(3)创建裸机工程

使用前面的串口示例代码作为裸机工程,当然也可以使用keil自己创建裸机工程,自己创建的裸机工程一定要进行简单的功能测试。将步骤(2)中的LiteOS文件拷贝到裸机工程根目录下,具体如图2所示。

图2 LiteOS目录概图

4.2 添加内核源码

在裸机工程中,添加LiteOS相关文件夹,分别命名为LiteOS/cmsis、LiteOS/arch、LiteOS/kernel、LiteOS/config(可有可无,便于后期操作而已),并分别将cmsis os代码、kernel代码、arch代码、OS_CONFIG文件等添加到对应的文件夹,具体如图3所示。

图3 添加工程分组

其中需要添加的源码以及对应的文件所在位置具体如下表所示。添加后的文件目录详情,具体如图4所示。

图4 添加Lite OS源码

4.3 添加头文件

添加源码之后,需要添加对应应用的头文件,具体如图5所示。

图5 添加头文件

4.4 修改target.h文件

由于采用非接管中断方式移植LiteOS,因此修改文件较少。首先修改target.h文件的头文件应用,其头文件如图6所示。第43行,需要修改为开发板相对应的系列头文件。

图6 target.h头文件修改

在target.h文件中的开发板内存模块配置的位置,找到下列代码,其中一个是参数是起始地址,一个是开发板实际的SRAM的大小,但是该值一般设置略小于实际SRAM大小,因为工程存储需要占用一定空间。我们可以使用keil的pack Installer查看开发板的SRAM大小,具体如图7所示。可见GD32450i-EVAL(2019)其SRAM大小为256K。

  1. #define BOARD_SRAM_START_ADDR     0x20000000
  2. #define BOARD_SRAM_SIZE_KB        128

图7 查看开发板SRAM大小

target.h文件具体修改方式如图8所示。注意其中的起始地址设置要与工程配置中的IRAM起始地址保持一致。

图8 修改内存起始地址

4.5 注释回调函数代码

由于PendSV_Handler以及SysTick_Handler(void)函数在LiteOS源码以及裸机工程中的gd32f4xx_it.c文件中都有定义,因此如果直接编译会出现重定义的错误,如图9所示。此时我们需要将对应gd32f4xx_it.c中代码注释掉或删除即可。

图9 运行错误详情

5 测试

上面已经将移植工作基本完成,后面只需要做一下测试即可,具体包括硬件测试以及LiteOS测试。

5.1 硬件启动测试

对于测试,首先需要将串口调试好,便于后续的调试,此处我以串口函数以及LED灯进行测试。在使用LiteOS系统之前首先需要将开发板启动起来,具体如下所示。但是需要注意的是初始化的时候不要调用delay函数,因为SysTick_Handler(void)函数被注释掉了,如果调用该函数会导致,程序卡死在delay处。测试的时候一定要注意main函数中要有while循环使其卡停在此处。

  1. #include "gd32f4xx.h"
  2. #include "gd32f450i_eval.h"
  3. #include "systick.h"
  4. #include <stdio.h>
  5.  
  6. void Hardware_Init(void);
  7. void led_init(void);
  8. int main()
  9. {
  10.   Hardware_Init();
  11.   printf("\r\n USART printf example: please press the Tamper key \r\n");
  12.        
  13.   while(1){
  14.       gd_eval_led_on(LED1);
  15.   }
  16. }
  17.  
  18. void Hardware_Init(void)
  19. {
  20.   led_init();
  21.   systick_config();
  22.   gd_eval_com_init(EVAL_COM1);
  23. }
  24.  
  25. void led_init(void)
  26. {
  27.   gd_eval_led_init(LED1);
  28. }
  29.  
  30. int fputc(int ch, FILE *f)
  31. {
  32.   usart_data_transmit(EVAL_COM1, (uint8_t)ch);
  33.   while(RESET == usart_flag_get(EVAL_COM1, USART_FLAG_TBE)); 
  34.   return ch;
  35. }

5.2 移植功能测试

接下来只需要对Lite OS移植进行测试,对主函数进行修改实现任务的创建于调用即可,主函数具体如下所示。

  1. #include "gd32f4xx.h"
  2. #include "gd32f450i_eval.h"
  3. #include "systick.h"
  4. #include <stdio.h>
  5. #include "los_sys.h "
  6. #include "los_typedef.h"
  7. #include "los_task.ph" 
  8.  
  9. UINT32 g_TskHandle;
  10.  
  11. void Hardware_Init(void);
  12. void led_init(void);
  13. UINT32 creat_task1();
  14. UINT32 creat_task2();
  15.  
  16. int main(){
  17.   Hardware_Init();
  18.   printf("\r\n USART printf example: please press the Tamper key \r\n");
  19.   UINT32 uwRet = 0;
  20.   uwRet = LOS_KernelInit();
  21.   if (uwRet != LOS_OK){
  22.     return LOS_NOK;
  23.   }
  24.   uwRet = creat_task1();
  25.   if (uwRet != LOS_OK){
  26.     return LOS_NOK;
  27.   }
  28.   uwRet = creat_task2();
  29.   if (uwRet != LOS_OK){
  30.     return LOS_NOK;
  31.   }
  32.   LOS_Start();
  33.   while(1){
  34.     gd_eval_led_on(LED1);
  35.   }
  36. }
  37.  
  38. void Hardware_Init(void){
  39.   led_init();
  40.   systick_config();
  41.   gd_eval_com_init(EVAL_COM1);
  42. }
  43.  
  44. void led_init(void){
  45.   gd_eval_led_init(LED1);
  46. }
  47.  
  48. int fputc(int ch, FILE *f){
  49.   usart_data_transmit(EVAL_COM1, (uint8_t)ch);
  50.   while(RESET == usart_flag_get(EVAL_COM1, USART_FLAG_TBE));   
  51.   return ch;
  52. }
  53.  
  54. void task1(void){
  55.   int count = 1;
  56.   while(1){
  57.     printf("This is task1, count is %d\r\n", count++);
  58.     LOS_TaskDelay(1000);
  59.   }
  60. }
  61.  
  62. UINT32 creat_task1(){
  63.     UINT32 uwRet = LOS_OK;
  64.   TSK_INIT_PARAM_S task_init_param;
  65.        
  66.   task_init_param.usTaskPrio = 0;
  67.   task_init_param.pcName = "task1";
  68.   task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)task1;
  69.   task_init_param.uwStackSize = 0x200;
  70.        
  71.   uwRet = LOS_TaskCreate(&g_TskHandle, &task_init_param);
  72.   if(LOS_OK != uwRet){
  73.     return uwRet;
  74.   }
  75.   return uwRet;
  76. }
  77.  
  78. void task2(void){
  79.   int count = 1;
  80.   while (1){
  81.       printf("This is task2,count is %d\r\n",count++);
  82.       LOS_TaskDelay(2000);
  83.   }
  84. }
  85.  
  86. UINT32 creat_task2(){
  87.   UINT32 uwRet = LOS_OK;
  88.   TSK_INIT_PARAM_S task_init_param;
  89.  
  90.   task_init_param.usTaskPrio = 1;
  91.   task_init_param.pcName = "task2";
  92.   task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)task2;
  93.   task_init_param.uwStackSize = 0x200;
  94.  
  95.   uwRet = LOS_TaskCreate(&g_TskHandle, &task_init_param);
  96.   if(LOS_OK != uwRet){
  97.     return uwRet;
  98.   }
  99.   return uwRet;
  100. }

运行结果如图10所示,可以看见两个任务在交替打印。移植完成,本例程使用的是非接管中断的方式,如果使用接管中断方式的,需要拷贝结果中断的OS_CONFIG文件,同时对于target.h文件需要额外的修改,同时修改.sct文件(在keil工程下的Objects文件夹下),而不是使用自动生成的.sct文件.

图10 Lite OS移植成功运行结果

添加华为IoT小助手(微信号:huawei-iot,回复“博客园”)获取更多LiteOS课程。

漫谈LiteOS之开发板-LiteOS移植(基于GD32450i-EVAL)的更多相关文章

  1. 漫谈LiteOS之开发板-串口(基于GD32450i-EVAL)

    [摘要] ​主要讲解物联网的技术积累,本期我们先带领大家学习漫谈LiteOS之漫谈开发板第一集-串口,本文基于GD32450i-EVAL对串口以及其通信做了一个简要的分析,以及开发过程中遇到的一些技术 ...

  2. 漫谈LiteOS之开发板-GPIO(基于GD32450i-EVAL)

    [摘要] 本文主要从GPIO的定义.工作模式.特色.工作场合.以及GD32450i-EVAL开发板的引脚.对应的寄存器以及GPIO的流水灯示例对GPIO加以介绍,希望对你有所帮助. 1定义 GPIO( ...

  3. 在秉火STM32F429挑战者开发板上移植Huawei LiteOS指南

    昨天在B站上突然看到了一个短视频,是在正点原子的战舰V3开发板上移植华为的Huawei LiteOS操作系统,就是这个视频:看完鸿蒙OS发布会,试用华为的物联网操作系统Lite OS(B站),于是呢, ...

  4. 【分享】iTOP4412开发板-Bluetooth移植文档

    [分享]iTOP4412开发板-Bluetooth移植文档 最近须要把Bluetooth移植到iTOP-4412 开发平台.查阅了相关资料,经过一段时间的研究.调试,最终成功的将蓝牙功能移植到了开发板 ...

  5. u-boot-2011.06在基于s3c2440开发板的移植之引导内核与加载根文件系统

    http://www.linuxidc.com/Linux/2012-09/70510.htm  来源:Linux社区  作者:赵春江 uboot最主要的功能就是能够引导内核启动.本文就介绍如何实现该 ...

  6. zedboard开发板上移植opencv代码(立体匹配)

    前言 公司要做立体匹配相关的项目,已有matlab和c++版本,可是不能做到实时显示立体信息,想要硬件实现实时,无奈本渣也是个硬件的新手,先按照实验室lyq同学的思路在zedboard开发板的纯ARM ...

  7. ARM开发板系统移植-----rootfs的制作

    前面两篇文章分别介绍了mini2440开发板上运行的bootloader和kernel,到这里系统启动后其实是停留在一个“僵死”的状态---无法挂载根文件系统. 这里将介绍如何制作一个根文件系统,并且 ...

  8. ARM开发板系统移植-----u-boot的编译

    本文和另外两篇姊妹篇都是为了说明如何裁剪出适合在mini2440 开发板上运行的Linux系统,以记录自己的学习成果.其中本文先介绍了嵌入式系统的软件组成部分,然后介绍编译出适合在mini2440开发 ...

  9. 嵌入式开发 迅为4418开发板Qt移植移动4G模块第一部分

    本文转自迅为论坛:http://topeetboard.com 了解更多:https://item.taobao.com/item.htm?spm=a1z10.1-c.w4004-7744162139 ...

随机推荐

  1. Linux基础篇学习——Linux文件系统之文件存储与读取:inode,block,superblock

    Linux文件类型 代表符号 含义 - 常规文件,即file d directory,目录文件 b block device,块设备文件,支持以"block"为单位进行随机访问 c ...

  2. 微信APP支付-java后台实现

    不说废话,直接上代码 先是工具类(注意签名时要排序): import java.io.BufferedReader; import java.io.ByteArrayInputStream; impo ...

  3. reset slave all更彻底

    reset slave是各版本Mysql都有的功能,可以让slave忘记自己在master binary log中的复制位置. reset slave命令主要完成以下工作内容: -删除master.i ...

  4. MySQL datetime类型详解

    研发反馈问题,数据库中datetime数据类型存储的值末尾会因四舍五入出现不一致数据,影响查询结果,比如:程序中自动获取带毫秒精度的日期'2019-03-05 01:53:55.63',存入数据库后变 ...

  5. TensorFlow系列专题(三):深度学习简介

    一.深度学习的发展历程 深度学习的起源阶段 深度学习的发展阶段 深度学习的爆发阶段 二.深度学习的应用 自然语言处理 语音识别与合成 图像领域 三.参考文献   一.深度学习的发展历程 作为机器学习最 ...

  6. Benelux Algorithm Programming Contest 2019

    J. Jazz it Up!题目要求,n*m的因子中不能含有平方形式,且题目中已经说明n是一个无平方因子的数, 那么只要m是无平方因子的数,并且n和m没有共同的因子即可.要注意时间复杂度!代码:#in ...

  7. ConcurrentHashMap1.7和1.8的源码分析比较

    ConcurrentHashMap 在多线程环境下,使用HashMap进行put操作时存在丢失数据的情况,为了避免这种bug的隐患,强烈建议使用ConcurrentHashMap代替HashMap,为 ...

  8. 原生js焦点轮播图的实现

    继续学习打卡,武汉加油,逆战必胜!今日咱们主要探讨一下原生js写轮播图的问题, 简单解析一下思路: 1,首先写好css样式问题 2,考虑全局变量:自动播放的定时器,以及记录图片位置的角标Index 2 ...

  9. Java多线程工具类之循环栅栏计数器

    Java多线程下循环计数器 本文主要内容:CyclicBarrier(下文中凯哥就用cycBar来代替)定义介绍:举例说明:代码演示:从源码来看原理及总结:CyclicBarrier与CountDow ...

  10. Vertica的这些事(八)——-Vertica-管理

    1.版本信息 dbadmin=> SELECT version(); version ------------------------------------ Vertica Analytic ...