目录
一、源码下载
二、FreeRTOS手把手移植
开始移植:
1.生成HAL库工程
2.添加FreeRTOS源码文件到工程目录下
3.添加FreeRTOS源码到工程中
4.添加FreeRTOSConfig.h
5.修改Systick中断、SVC中断、PendSV中断
6.添加应用程序:验证移植是否成功。
链接:https://pan.baidu.com/s/17fb8ZikQPWNQR945pdwBHQ
提取码:8a9q
这里我提供的是V9.0.0版本内核源码,据了解到,这是一个稳定的版本,若读者需要下载其他版本可去到FreeRTOS官网进行下载,此版本初学者足以。
FreeRTOS源码内容
FreeRTOS源码本尊
移植步骤:
下面我以hal库工程移植为例子,带领各位读者进行FreeRTOS源码的移植。
通过CubeMX 软件进行简单的时钟配置,生成一个基础的HAL库工程。
我以STM32F103RCT6为例进行配置
生成好HAL库工程后,将FreeRTOSv9.0.0文件夹下的FreeRTOS文件夹下的Source源码文件拷贝到生成好HAL库工程文件夹中,重命名为FreeRTOS。
在porttable文件夹中我们只需要保留以下这三个文件。
打开工程,将FreeRTOS源码添加到工程中,添加好后的文件如下
添加好后,还需要添加头文件路径
在RVDS 文件夹下有着不同内核所需要的port.c 文件,这里我们使用的是M3内核的单片机,所以我这里添加的是ARM_CM3 文件夹下的port.c 文件。
在 MemMang 文件夹下存放这不通算法的内存管理文件,对于初学者推荐使用 heap_4.c 文件,大多数的教程都推荐初学者使用的是该文件,笔者我还未去了解是为什么,有兴趣的可以去了解一下。
FreeRTOSConfig.h文件是FreeRTOS的工程配置文件,因为FreeRTOS是可以裁剪的实时操作内核,应用于不同的处理器平台,用户可以通过修改这个FreeRTOS内核的配置头文件来裁剪FreeRTOS的功能。
对于F103的工程 FreeRTOSConfig.h 文件可以在官方源码的Dome文件中找到:FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_STM32F103_Keil。
也可以使用别人裁剪整理好的FreeRTOSConfig.h 文件
在这里我将使用正点原子裁剪整理好的FreeRTOSConfig.h 文件
这里我将该文件直接添加到了 include 文件夹中
将SVC中断、PendSV中断注释。
修改Systick中断
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
#if (INCLUDE_xTaskGetSchedulerState == 1 )
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
#endif /* INCLUDE_xTaskGetSchedulerState */
xPortSysTickHandler();//调用systick中断处理函数
#if (INCLUDE_xTaskGetSchedulerState == 1 )
}
#endif /* INCLUDE_xTaskGetSchedulerState */
/* USER CODE END SysTick_IRQn 1 */
}
到这里FreeRTOS源码就移植好了,进行编译,是 0错误,0警告。若读者有错误或者警告,可自行对应查找解决方案。
在这之前需要先将微库进行勾选,在内核源码中使用了printf ,如不勾选运行程序会卡死,或者重写 printf 相关的函数。
重写printf 相关的函数。这里我直接使用了正点原子编写的程序
#include "stdio.h"
#if (__ARMCC_VERSION >= 6010050)
__asm(".global __use_no_semihosting\n\t"); /* */
__asm(".global __ARM_use_no_argv \n\t"); /* */
#else
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
#endif
int _ttywrch(int ch)
{
ch = ch;
return ch;
}
void _sys_exit(int x)
{
x = x;
}
char *_sys_command_string(char *cmd, int len)
{
return NULL;
}
FILE __stdout;
int fputc(int ch, FILE *f)
{
while ((USART1->SR & 0X40) == 0);
USART1->DR = (uint8_t)ch;
return ch;
}
/* USER CODE END 1 */
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
#define START_TASK_PRIO 1
#define START_STK_SZIE 128
TaskHandle_t START_Handle_t;
#define LED_TASK_PRIO 3
#define LED_STK_SZIE 128
TaskHandle_t LED_Handle_t;
void Start_Task(void *p);
void LED_Task(void *p);
void FreeRTOS_Dome(void)
{
xTaskCreate(Start_Task,"Start_Task",START_STK_SZIE,NULL,START_TASK_PRO,&START_Handle_t);
vTaskStartScheduler();
}
void Start_Task(void *p)
{
taskENTER_CRITICAL();
xTaskCreate(LED_Task,"LED_Task",LED_STK_SZIE,NULL,LED_TASK_PRIO,&LED_Handle_t);
vTaskDelete(START_Handle_t);
taskEXIT_CRITICAL();
}
void LED_Task(void *p)
{
while(1)
{
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
vTaskDelay(500);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
vTaskDelay(500);
}
}