查看: 5236|回复: 8

[原创] 【IRD-LPC1768-DEV】操作系统移植

[复制链接]
  • TA的每日心情
    开心
    2024-4-5 11:15
  • 签到天数: 1061 天

    连续签到: 1 天

    [LV.10]以坛为家III

    29

    主题

    1517

    帖子

    31

    金牌会员

    Rank: 6Rank: 6

    积分
    4979
    最后登录
    2024-5-31
    发表于 2019-3-25 16:52:06 | 显示全部楼层 |阅读模式
    本帖最后由 story_xjj 于 2019-3-26 08:10 编辑

    报告5
    ——终极计划完成
    1.    简介
    终极计划准备移植一个KEIL MDK 版本的FreeRTOS操作系统,并完成以太网级别的外部设备管理,包括UART,CAN1和CAN2。
    2.    协议
    协议仍然遵循初级计划中的通讯协议。
    3.    FreeRTOS移植3.1.   准备工作
    开始移植前,首先下载FreeRTOS源代码。官网网址:http://www.freertos.org/,我们可以下载到最新版本的FreeRTOS源代码,当前版本为V10.2.0版。
    FreeRTOS目前研究的人挺多的,官方给出的例子和支持的芯片都非常多,但是遗憾的是,官方的移植中不包含基于MDK版本的LPC1768芯片的支持。
    首先我们来看一下FreeRTOS的目录结构,目录中包含FreeRTOS和FreeRTOS-Plus两个目录。
    mulu-1.jpg
    FreeRTOS目录中包含的文件是我们本次移植的重点内容,FreeRTOS-Plus中包含所有FreeRTOS支持的功能附件,包括以太网,文件系统等,但这个本次不是我们的重点。我们下面的移植重点针对FreeRTOS。
           FreeRTOS的目录树:
    .
    ├── FreeRTOS
    ├── Demo
    │   ├── ARM7_AT91FR40008_GCC
    │   ├── ARM7_AT91SAM7S64_IAR
    │   ├── ARM7_AT91SAM7X256_Eclipse
    │   ├── ARM7_LPC2106_GCC
    │   ├── WizNET_DEMO_TERN_186
    … …
    │   └── Xilinx_FreeRTOS_BSP
    ├── License
    │   └── license.txt
    ├── links_to_doc_pages_for_the_demo_projects.url
    ├── readme.txt
    └── Source
    ├── croutine.c
    ├── event_groups.c
    ├── include
    │   ├── croutine.h
    │   ├── deprecated_definitions.h
    │   ├── event_groups.h
    │   ├── FreeRTOS.h
    │   ├── list.h
    │   ├── message_buffer.h
    │   ├── mpu_prototypes.h
    │   ├── mpu_wrappers.h
    │   ├── portable.h
    │   ├── projdefs.h
    │   ├── queue.h
    │   ├── semphr.h
    │   ├── stack_macros.h
    │   ├── StackMacros.h
    │   ├── stdint.readme
    │   ├── stream_buffer.h
    │   ├── task.h
    │   └── timers.h
    ├── list.c
    ├── portable
    │   ├── ARMv8M
    │   ├── BCC
    │   ├── CCS
    │   ├── CodeWarrior
    │   ├── Common
    │   ├── GCC
    │   ├── IAR
    │   ├── Keil
    │   ├── MemMang
    │   ├── MikroC
    │   ├── MPLAB
    │   ├── MSVC-MingW
    │   ├── oWatcom
    │   ├── Paradigm
    │   ├── readme.txt
    │   ├── Renesas
    │   ├── Rowley
    │   ├── RVDS
    │   ├── SDCC
    │   ├── Softune
    │   ├── Tasking
    │   ├── ThirdParty
    │   └── WizC
    ├── queue.c
    ├── readme.txt
    ├── stream_buffer.c
    ├── tasks.c
    └── timers.c
    通过目录树我们可以看到,FreeRTOS本身支持的芯片种类非常多,支持的编译器种类也非常丰富,其中包括Keil的支持,这说明移植本身应该不难。
    3.2.   构建自己的目录结构
    为了脱离FreeRTOS的目录结构,简化目录层数,我打算自己构建一个目录结构。
    mulu-2.jpg
    如图中所示, app:     放置我们自己开发的应用程序;
                         Freertos: 放置FreeRTOS中不需要我们编辑的源码;
                         Lib:        放置LPC1768的驱动库和头文件;
                     Portable: 放置FreeRTOS与移植有关的部分,
    mulu-3.jpg
                 Prj:      keil工程文件,输出等

                        Uip:     放置uip源码。
    3.3.   移植过程
    步骤1,工程建立和文件添加

    按照正常的mdk方式建立一个空的工程,并添加工程文件如下图所示:
    keilprj.jpg
    步骤2,freertoscofig.h的配置
    这个文件用来配置FreeRTOS将按照什么形式配置和运行。其中值得注意的地方有:
    1、 CPU时钟
    #define configCPU_CLOCK_HZ                 ( ( unsigned long ) 100000000 )
    CPU时钟的选定需要和真实CPU所执行的时钟相同。IRD-LPC1768-DEV的CPU晶振为12MHz,因此选定的PLL0的参数如下。
    keil-1.jpg
    2、 任务切换速率
    #define configTICK_RATE_HZ                    ( ( TickType_t ) 1000 )
    这个数值配置的越大,意味着任务切换的次数在单位时间内越多,如果设置为1000,表示1秒时间内,会切换1000此认为,也就是任务的实时效果为1ms。数值太大会造成任务切换导致的开销太大,数值太小导致任务间切换时间上升,需要根据实际情况自己选择。
    步骤3,startup_LPC17xx.s的移植
           在
    __Vectors       DCD     __initial_sp              ; Top of Stack部分,我们需要用freertos的调度函数替换原有的中断入口函数。

                                    EXTERN         vPortSVCHandler
                                    DCD     vPortSVCHandler                   ; SVCall Handler
    ;                DCD     SVC_Handler               ; SVCall Handler
                    DCD     DebugMon_Handler          ; Debug Monitor Handler
                    DCD     0                         ; Reserved
                                    EXTERN  xPortPendSVHandler
                                    DCD     xPortPendSVHandler          ; PendSV Handler
                                    EXTERN  xPortSysTickHandler
                                    DCD     xPortSysTickHandler         ; SysTick Handler
    ;                DCD     PendSV_Handler            ; PendSV Handler
    ;                DCD     SysTick_Handler           ; SysTick Handler



    步骤4,内存管理的选择
            Freertos中提供了5中管理方法,
    • heap_1 - the very simplest, does not permit memory to be freed
    • heap_2 - permits memory to be freed, but does not coalescence adjacent free blocks.
    • heap_3 - simply wraps the standard malloc() and free() for thread safety
    • heap_4 - coalescences adjacent free blocks to avoid fragmentation. Includes absolute address placement option
    • heap_5 - as per heap_4, with the ability to span the heap across multiple non-adjacent memory areas

    根据官方对于这5种管理方法的说明,先选择了第1种,最简单的,所有东西都自己定义。

    4.    软件基本应用
    简单介绍一下我的应用中所需的几种多任务需要。
    1) 基本过程:
           硬件初始化->任务创建->启动调度->开始任务调度执行。
    2) 任务:
           任务就是一个个的死循环(也有执行一次就退出的),我们就考虑在任务内执行的任务和任务间配合就可以了。例如下面的代码。
    1. <font size="3">static void prvFlashTask( void *pvParameters )
    2. {
    3.    TickType_t xLastFlashTime;

    4.   /* We need to initialise xLastFlashTime prior to the first call to
    5.   vTaskDelayUntil(). */
    6.   xLastFlashTime = xTaskGetTickCount();

    7.   for(;;)             //死循环
    8.   {
    9.         /* Simply toggle the LED between delays. */
    10.        vTaskDelayUntil( &xLastFlashTime, mainLED_TOGGLE_RATE );      延时等待
    11.        vParTestToggleLED( 0 );                                                               小灯闪烁
    12.    }
    13. }</font>
    复制代码

    3) 软件定时器:
               配置定时器服务任务
         程序中需要使用到软件定时器, 需要先在 FreeRTOSConfig.h 中正确配置如下宏 :
            #define  configUSE_TIMERS           1 //编译定时器相关代码, 如需要使用定时器, 设置为 1
           #define    configTIMER_TASK_PRIORITY  1
    //设置定时器Daemon 任务优先级, 如果优先级太低, 可能导致定时器无法及时执行
           #define  configTIMER_QUEUE_LENGTH     10
    //设置定时器Daemon 任务的命令队列深度, 设置定时器都是通过发送消息到该队列实现的。
           #define  configTIMER_TASK_STACK_DEPTH   ( configMINIMAL_STACK_SIZE * 2 )
    //设置定时器Daemon 任务的栈大小
         创建 启动 停止定时器 示例代码
    TimerHandle_t xTimerUser; // 定义句柄
    // 定时器回调函数格式
    void vTimerCallback( TimerHandle_t xTimer )
    {
        // do something no block
        // 获取溢出次数
        static uin32_t ulCount = ( uint32_t ) pvTimerGetTimerID( xTimer );
        // 累积溢出次数
        ++ulCount;
        // 更新溢出次数
        vTimerSetTimerID( xTimer, ( void * ) ulCount );
        if (ulCount == 10) {
            // 停止定时器
            xTimerStop( xTimer, 0 );
        }
    }
    void fun()
    {
        // 申请定时器, 配置
        xTimerUser = xTimerCreate
                       /*调试用, 系统不用*/
                       ("Timer's name",
                       /*定时溢出周期, 单位是任务节拍数*/
                       100,  
                       /*是否自动重载, 此处设置周期性执行*/
                       pdTRUE,
                       /*记录定时器溢出次数, 初始化零, 用户自己设置*/
                      ( void * ) 0,
                       /*回调函数*/
                      vTimerCallback);
         if( xTimerUser != NULL ) {
            // 启动定时器, 0 表示不阻塞
            xTimerStart( xTimerUser, 0 );
        }
    }
    如上所示, 调用函数 xTimerCreate申请,配置定时器, 通过 xTimerStart 启动定时器, 当定时器计数溢出时, 系统回调注册的函数。
    定时器可以设置为一次性 One-shot 或者自动重载 Auto-reload 两种, 第一种溢出后停止定时器, 第二种溢出后会再次启动定时器。
         修改定时器

    在申请定时器的时候设置的定时器周期, 可以通过函数 xTimerChangePeriod 修改, 如下示例 :
    void vAFunction_2( TimerHandle_t xTimer )
    {
         // 判断定时器是否处于运行状态
         if( xTimerIsTimerActive( xTimer ) != pdFALSE )
         {
             /* xTimer is active, do something. */
         }
         else
         {
             // 处于这个状态的定时器, 可能由于 :
             // 1 定时器 create 后没有start
             // 2 一次性定时器执行溢出后
             // 修改定时器周期
             if( xTimerChangePeriod( xTimer,
                    /*修改定时周期*/
                    500 / portTICK_PERIOD_MS,
                /*允许阻塞最大时间 100 ticks*/
                100 ) == pdPASS )
             {
                 // update fail
                 // 阻塞 100 tick 仍然无法发送命令
                 // 删除定时器 释放对应内存!
                 xTimerDelete( xTimer );
             }
             else
             {
                 // 定时器配置更新成功, 并已经启动 !!
             }
        }
    }
         如上, 该函数会修改定时器并使定时器 开始运行!!!
        另外, 可以通过函数 xTimerReset 重启定时器, 如果已经启动计数, 重新开始计数; 如果没有启动,启动定时器。
    获取定时器状态
        // 获取名称 , 申请是设置的字符串
         pcTimerGetName()
      // 定时器溢出周期
         xTimerGetPeriod()
      // 返回定时器溢出的时间点 (--> xTaskGetTickCount())
            xTimerGetExpiryTime()

    附上我的测试代码: rtostest.rar (7.88 MB, 下载次数: 21)
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-5 11:15
  • 签到天数: 1061 天

    连续签到: 1 天

    [LV.10]以坛为家III

    29

    主题

    1517

    帖子

    31

    金牌会员

    Rank: 6Rank: 6

    积分
    4979
    最后登录
    2024-5-31
     楼主| 发表于 2019-3-25 16:58:21 | 显示全部楼层
    这是我测试的内容,包括程序和上位软件,
    虽然整个软件不能工程化使用,可以作为原理测试使用
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2025-6-10 23:03
  • 签到天数: 1502 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    97

    主题

    4688

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    10080
    最后登录
    2025-7-2
    发表于 2019-3-25 21:13:27 | 显示全部楼层
    这个完美移植过来也是一件不容易的事情了
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2025-7-11 08:53
  • 签到天数: 301 天

    连续签到: 2 天

    [LV.8]以坛为家I

    3868

    主题

    7472

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    39232
    最后登录
    2025-7-18
    发表于 2019-3-27 08:53:13 | 显示全部楼层
    厉害了!
    qiandao qiandao
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-5 11:15
  • 签到天数: 1061 天

    连续签到: 1 天

    [LV.10]以坛为家III

    29

    主题

    1517

    帖子

    31

    金牌会员

    Rank: 6Rank: 6

    积分
    4979
    最后登录
    2024-5-31
     楼主| 发表于 2019-3-27 13:46:19 | 显示全部楼层
    谢谢大家鼓励
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2019-9-17 13:22
  • 签到天数: 238 天

    连续签到: 1 天

    [LV.7]常住居民III

    30

    主题

    905

    帖子

    6

    金牌会员

    Rank: 6Rank: 6

    积分
    2251
    最后登录
    2024-10-8
    发表于 2019-4-3 13:23:32 | 显示全部楼层
    点赞666
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    昨天 10:11
  • 签到天数: 1846 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    203

    主题

    3万

    帖子

    64

    超级版主

    Rank: 8Rank: 8

    积分
    112622
    最后登录
    2025-7-19
    发表于 2019-4-4 15:56:34 | 显示全部楼层
    支持一下~~
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    0

    新手上路

    Rank: 1

    积分
    22
    最后登录
    2023-9-1
    发表于 2019-4-11 15:57:11 | 显示全部楼层
    66666666666666666666666666666666
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2019-5-1 06:15
  • 签到天数: 5 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    0

    主题

    91

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    207
    最后登录
    2021-8-4
    发表于 2019-4-29 11:13:35 | 显示全部楼层
    谢谢分享
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-20 16:45 , Processed in 0.109356 second(s), 28 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表