问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

STM32F103C8T6上基于Keil的FreeRTOS源码移植教程

创作时间:
作者:
@小白创作中心

STM32F103C8T6上基于Keil的FreeRTOS源码移植教程

引用
CSDN
1.
https://m.blog.csdn.net/Mr_ybfqw/article/details/132178458

本文将详细介绍如何在STM32F103C8T6微控制器上使用Keil开发环境移植FreeRTOS。与使用CubeMX自动生成FreeRTOS代码不同,本教程将直接基于FreeRTOS官网的源码构建工程文件。通过创建三个不同闪烁频率的LED任务,验证FreeRTOS的正确运行。

下载FreeRTOS源码

  1. 访问FreeRTOS官网,搜索并下载最新版本的源码(不带LTS后缀)。
  2. 下载完成后,解压得到FreeRTOSv202212.01文件。

构建工程文件夹

总述

将开发所需的FreeRTOS文件分为两类,分别存放在src(存放.c文件)和include(存放.h文件)文件夹中。这两个文件夹都位于名为FreeRTOS的主文件夹下。

src文件夹

  1. 在桌面创建名为FreeRTOS的文件夹。
  2. 在FreeRTOS文件夹中创建include和src子文件夹。
  3. 从FreeRTOSv202212.01\FreeRTOS\Source路径下,将框选的.c文件拷贝到src文件夹。
  4. 进入FreeRTOSv202212.01\FreeRTOS\Source\portable\RVDS\ARM_CM3目录,将其中的.c和.h文件分别拷贝到src和include文件夹。
  5. 进入FreeRTOSv202212.01\FreeRTOS\Source\portable\MemMang目录,将heap_4.c拷贝到src文件夹。

include文件夹

  1. 进入FreeRTOSv202212.01\FreeRTOS\Demo\CORTEX_STM32F103_Keil目录,将FreeRTOSConfig.h文件拷贝到include文件夹。
  2. 进入FreeRTOSv202212.01\FreeRTOS\Source\include目录,将所有文件拷贝到include文件夹。

创建工程文件

使用点灯任务来验证FreeRTOS配置是否正确。硬件驱动配置使用PA0、PA1、PA2三个IO口。选择Serial作为Debug,时基源选择TIM1定时器。

在Keil中进行配置

  1. 将FreeRTOS文件夹拷贝到工程目录中。
  2. 在Keil中,通过魔术棒图标进入C/C++设置,添加src和include文件夹的路径到IncludePath。
  3. 在工程目录中添加组,命名为FreeRTOS,将src和include文件夹中的所有.c和.h文件添加进来。
  4. 在main文件中包含必要的头文件:
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
  1. 修改FreeRTOSConfig.h文件,启用所需的功能:
#define configUSE_PREEMPTION		1
#define configUSE_TICKLESS_IDLE     0
#define configUSE_IDLE_HOOK			0
#define configUSE_TICK_HOOK			0
#define configCPU_CLOCK_HZ			( ( unsigned long ) 72000000 )
#define configTICK_RATE_HZ			( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES		5
#define configMINIMAL_STACK_SIZE	( ( unsigned short ) 128 )
#define configTOTAL_HEAP_SIZE		( ( size_t ) ( 17 * 1024 ) )
#define configMAX_TASK_NAME_LEN		( 16 )
#define configUSE_MUTEXES                       1
#define configUSE_RECURSIVE_MUTEXES             0
#define configUSE_COUNTING_SEMAPHORES           0
#define configQUEUE_REGISTRY_SIZE               10
#define configCHECK_FOR_STACK_OVERFLOW          0
#define configUSE_MALLOC_FAILED_HOOK            0
#define configUSE_TIMERS                        1
#define configTIMER_TASK_PRIORITY               3
#define configTIMER_QUEUE_LENGTH                10
#define configTIMER_TASK_STACK_DEPTH            configMINIMAL_STACK_SIZE
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15
#define configUSE_TRACE_FACILITY	0
#define configUSE_16_BIT_TICKS		0
#define configIDLE_SHOULD_YIELD		1
#define INCLUDE_vTaskPrioritySet                1
#define INCLUDE_uxTaskPriorityGet               1
#define INCLUDE_vTaskDelete                     1
#define INCLUDE_vTaskSuspend                    1
#define INCLUDE_xResumeFromISR                  1
#define INCLUDE_vTaskDelayUntil                 1
#define INCLUDE_vTaskDelay                      1
#define INCLUDE_xTaskGetSchedulerState          1
#define INCLUDE_xTaskGetCurrentTaskHandle       1
#define INCLUDE_uxTaskGetStackHighWaterMark     0
#define INCLUDE_xTaskGetIdleTaskHandle          0
#define INCLUDE_xTimerGetTimerDaemonTaskHandle  0
#define INCLUDE_pcTaskGetTaskName               0
#define INCLUDE_eTaskGetState                   0
#define INCLUDE_xEventGroupSetBitFromISR        1
#define INCLUDE_xTimerPendFunctionCall          0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY      1
#define configKERNEL_INTERRUPT_PRIORITY 		255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 	   191
#define configLIBRARY_KERNEL_INTERRUPT_PRIORITY	15
  1. 在STM32F1XX.it.c文件中添加以下代码:
extern void xPortPendSVHandler(void);
extern void xPortSysTickHandler(void);
extern void vPortSVCHandler(void);

并在相应位置添加中断服务函数调用:

void SVC_Handler(void)
{
  vPortSVCHandler();
}

void PendSV_Handler(void)
{
  xPortPendSVHandler();
}

void SysTick_Handler(void)
{
  xPortSysTickHandler();
}
  1. 在main函数中创建三个LED任务:
void led1_task(void* arg)
{
    while(1)
    {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
        vTaskDelay(300);
    }
}

void led2_task(void* arg)
{
    while(1)
    {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
        vTaskDelay(500);
    }
}

void led3_task(void* arg)
{
    while(1)
    {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2);
        vTaskDelay(1000);
    }
}

并在main函数中创建任务并启动调度器:

xTaskCreate(led1_task, "led1_task", 64, NULL, 3, NULL);
xTaskCreate(led2_task, "led2_task", 64, NULL, 4, NULL);
xTaskCreate(led3_task, "led3_task", 64, NULL, 4, NULL);
vTaskStartScheduler();

连接硬件电路,下载烧录,观察三个LED灯是否按照设定的频率闪烁,以验证FreeRTOS的正确运行。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号