STM32F103ZE移植FreeRTOS(在有LVGL的基础上进行移植,附源码)

目录

1.准备资料

1.1 基础工程获取

1.2 FreeRTOS源码获取

1.3 精简FreeRTOS源码

2.移植步骤

2.1添加FreeRTOS源码

2.1.1添加源码

2.1.3添加路径

2.2.添加FreeRTOSConfig.h配置文件

2.2.1生成FreeRTOSConfig.h文件

2.2.2配置FreeRTOSConfig.h文件

2.3修改系统文件

2.3.1修改sys.h

2.3.2修改delay.c

2.3.2.1替换头文件:

2.3.2.2删除uC/OS使用但不适合FreeRTOS的相关代码:

2.3.2.3修改SysTick_Handler函数:

2.3.2.4修改delay_init函数,用configTICK_RATE_HZ替换delay_ostickspersec:

2.3.2.5修改delay_us函数,删除uC/OS相关的代码:

2.3.2.6修改delay_ms函数:

2.3.3修改usart.c

2.4修改中断相关文件

2.5修改stm32f103xe.h文件

3.功能测试

3.1编写应用程序

3.1.1更改lvgl时钟源(针对LVGL)

3.1.2新建lvgl_demo.c/.h文件,创建OS任务,编写测试代码

3.1.3修改在main.c

3.1.3.1删除多余代码:

3.1.3.2包含lvgl_demo.h头文件,调用lvgl_demo函数:

3.2烧录程序测试功能

4.可能出现的问题

5.源码下载


1.准备资料

1.1 基础工程获取

《lvgl裸机》源码(详情参考上篇LVGL移植到STM32F103ZE裸机流程演示(附源码)-CSDN博客)

并改名为“STM32F103ZE移植FreeRTOS”。

1.2 FreeRTOS源码获取

方式1,通过官网下载

方式2,通过正点原子开发板A盘资料获取

方式3,通过百度网盘下载 

1.3 精简FreeRTOS源码

首先复制一份\FreeRTOSv202112.00\FreeRTOS\路径下的Source文件夹,更名为“FreeRTOS”,并删除多余的“.gitmodules”文件:

接着,删除\portable\路径下除了Keil、MemMang、RVDS外的所有文件夹:

最后,将精简后的FreeRTOS文件夹复制到基础工程的\Middlewares\路径下:

2.移植步骤

2.1添加FreeRTOS源码

2.1.1添加源码

新增分组Middlewares/FreeRTOS_CORE,并添加相应文件:

接着,再新增分组Middlewares\FreeRTOS_PORT,并添加相应文件:

2.1.3添加路径

添加以下路径:
..\Middlewares\FreeRTOS\include
..\Middlewares\FreeRTOS\portable\RVDS\ARM_CM3

2.2.添加FreeRTOSConfig.h配置文件

2.2.1生成FreeRTOSConfig.h文件

(建议放到\Middlewares\FreeRTOS\include\路径下)

方式1,从FreeRTOS源码中复制过来(路径:\FreeRTOSv202112.00\FreeRTOS\Demo\CORTEX_STM32F103_Keil\FreeRTOSConfig.h)

方式2:自己编新建一个(不建议,高手自便)

方式3:直接从正点原子资料移植好的工程中复制(推荐)

2.2.2配置FreeRTOSConfig.h文件

由于我选了上述方式3,故此步骤跳过。

2.3修改系统文件

2.3.1修改sys.h

2.3.2修改delay.c
2.3.2.1替换头文件:

2.3.2.2删除uC/OS使用但不适合FreeRTOS的相关代码:

2.3.2.3修改SysTick_Handler函数:

2.3.2.4修改delay_init函数,用configTICK_RATE_HZ替换delay_ostickspersec:

2.3.2.5修改delay_us函数,删除uC/OS相关的代码:

2.3.2.6修改delay_ms函数:

2.3.3修改usart.c

删除关于uCOS相关的代码:

2.4修改中断相关文件

由于Systick、SVC、PendSV这三个中断函数已经在FreeRTOS中定义,因此需要屏蔽stm32f1xx_it.c文件中的这三个函数,为方便,采用宏定义方式屏蔽:

2.5修改stm32f103xe.h文件

对于不芯片修改的文件,请参考下表:

将“#define __NVIC_PRIO_BITS 4U”改成“#define __NVIC_PRIO_BITS 4”:

3.功能测试

3.1编写应用程序

3.1.1更改lvgl时钟源(针对LVGL)

在lvgl.h文件中配置自定义时钟源:

删除定时器提供时基的部分代码:

3.1.2新建lvgl_demo.c/.h文件,创建OS任务,编写测试代码

在\USER\路径下新建lvgl_demo.c/.h文件:

在lvgl_demo.c文件创建OS任务,编写测试代码:

#include "lvgl_demo.h"
#include "FreeRTOS.h"
#include "task.h"
#include "lvgl.h"
#include "lv_port_disp_template.h"
#include "lv_port_indev_template.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO     1           /* 任务优先级 */
#define START_STK_SIZE      128         /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler;         /* 任务句柄 */
void start_task(void *pvParameters);    /* 任务函数 */

/* LV_DEMO_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define LV_DEMO_TASK1_PRIO   3           /* 任务优先级 */
#define LV_DEMO1_STK_SIZE    1024        /* 任务堆栈大小 */
TaskHandle_t LV_DEMOTask1_Handler;       /* 任务句柄 */
void lv_demo_task1(void *pvParameters);  /* 任务函数 */

/* LED_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define LV_DEMO_TASK2_PRIO       4           /* 任务优先级 */
#define LV_DEMO2_STK_SIZE        1024         /* 任务堆栈大小 */
TaskHandle_t LV_DEMOTask2_Handler;           /* 任务句柄 */
void lv_demo_task2(void *pvParameters);      /* 任务函数 */
/******************************************************************************************************/

/**
 * @brief       lvgl_demo入口函数
 * @param       无
 * @retval      无
 */
void lvgl_demo(void)
{
    lv_init();                                          /* lvgl系统初始化 */
    lv_port_disp_init();                                /* lvgl显示接口初始化,放在lv_init()的后面 */
    lv_port_indev_init();                               /* lvgl输入接口初始化,放在lv_init()的后面 */

    xTaskCreate((TaskFunction_t )start_task,            /* 任务函数 */
                (const char*    )"start_task",          /* 任务名称 */
                (uint16_t       )START_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传递给任务函数的参数 */
                (UBaseType_t    )START_TASK_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&StartTask_Handler);   /* 任务句柄 */

    vTaskStartScheduler();                              /* 开启任务调度 */
}

/**
 * @brief       start_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void start_task(void *pvParameters)
{
    pvParameters = pvParameters;
    
    taskENTER_CRITICAL();           /* 进入临界区 */

    /* 创建LVGL任务1 */
    xTaskCreate((TaskFunction_t )lv_demo_task1,
                (const char*    )"lv_demo_task1",
                (uint16_t       )LV_DEMO1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LV_DEMO_TASK1_PRIO,
                (TaskHandle_t*  )&LV_DEMOTask1_Handler);

    /* 创建LVGL任务2 */
    xTaskCreate((TaskFunction_t )lv_demo_task2,
                (const char*    )"lv_demo_task2",
                (uint16_t       )LV_DEMO2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )LV_DEMO_TASK2_PRIO,
                (TaskHandle_t*  )&LV_DEMOTask2_Handler);

    taskEXIT_CRITICAL();            /* 退出临界区 */
    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
}

/**
 * @brief       LVGL运行例程
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void lv_demo_task1(void *pvParameters)
{
    int task_cnt = 0;
    char *pBuf[3] = {"LVGL task1 running0...","LVGL task1 running1...","LVGL task1 running2..."};
    pvParameters = pvParameters;
    lv_obj_t *label = lv_label_create(lv_scr_act());
    lv_label_set_text(label, "LVGL task1 running...");
    lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 0);
    while(1)
    {
        task_cnt++;
        if (task_cnt>=3) task_cnt = 0;
        lv_label_set_text(label, (const char*)pBuf[task_cnt]);
        lv_timer_handler(); /* LVGL计时器 */
        vTaskDelay(1000);
        
    }
}

/**
 * @brief       led_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void lv_demo_task2(void *pvParameters)
{
    int task_cnt = 0;
    char *pBuf[3] = {"LVGL task2 running0...","LVGL task2 running1...","LVGL task2 running2..."};
    pvParameters = pvParameters;
    lv_obj_t *label = lv_label_create(lv_scr_act());
    lv_label_set_text(label, "LVGL task2 running...");
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
    while(1)
    {
        task_cnt++;
        if (task_cnt>=3) task_cnt = 0;
        lv_label_set_text(label, (const char*)pBuf[task_cnt]);
        lv_timer_handler(); /* LVGL计时器 */
        vTaskDelay(2000);
    }
}
3.1.3修改在main.c
3.1.3.1删除多余代码:

3.1.3.2包含lvgl_demo.h头文件,调用lvgl_demo函数:

3.2烧录程序测试功能

烧录程序后看到:LCD上方依次循环显示“LVGL task1 running0...”、“LVGL task1 running1...”、“LVGL task1 running2...”;LCD中间依次循环显示“LVGL task2 running0...”、“LVGL task2 running1...”、“LVGL task2 running2...”:

4.可能出现的问题

问题1:如果发现RAM内存不足,则需要调整内存分配

解决方法1:缩减FreeRTOS的内存

在FreeRTOSConfig.h中降低configTOTAL_HEAP_SIZE的大小:

解决方法2:缩减LVGL的内存LV_MEM_SIZE的大小:

问题2:运行时程序卡死在HardFault_Handler函数

解决方法1:可能是任务堆栈大小不够,可尝试增大堆栈大小

问题3:如果调用延时函数后任务不切换

解决方法1:可能原因有任务创建失败,要解决此问题,需要在FreeRTOSConfig.h中增大configTOTAL_HEAP_SIZE的大小。

5.源码下载

百度网盘下载: https://pan.baidu.com/s/1OYzZCEubGpH0_4geJxHX5g?pwd=kjcn 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值