一、准备工作
二、开始移植
首先在裸机工程Project_3目录中建立一个Middlewares文件夹存放FreeRTOS源码,如下图一所示。
接下来对源码进行取舍,需要删减的文件存放在portable文件夹中,如下图二所示,只保留GCC和MemMang文件夹。
首先删减GCC文件夹中的文件,因为我使用的是STM32F429内核是M4,就只保留了ARM_CM4F文件夹,里面的文件不用动,如下图三所示。
接着删减MemMang文件夹的文件,这里只保留heap_4.c文件。
刷新工程(选中工程-->点击右键-->点击Refresh),会发现多了一个Middlewares夹,即为我们添加的FreeRTOS的源码,如下图五所示。
再在Project_3工程中建立两个文件夹Bsp用来存放bsp.c和bsp.h文件、Driver用来存放外设驱动程序,如下图六和图七所示。
分别向bsp.c和bsp.h文件中添加代码。
#include "bsp.h"
void bsp_Init(void)
{
/* 分配优先级分组,以后不再分配. */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
/* 更新系统时钟 */
SystemCoreClockUpdate();
/* 下面添加外设驱动程序初始化函数 */
}
#ifndef _BSP_H
#define _BSP_H
#include "FreeRTOS.h"
#include "task.h"
#define DISABLE_INT() taskENTER_CRITICAL()
#define ENABLE_INT() taskEXIT_CRITICAL()
#include "stm32f4xx.h"
#include
#include
#include
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* 下面可以添加外设驱动程序的头文件 */
void bsp_Init(void);
#endif
在这里添加两个文件分别是FreeRTOSConfig.h和includes.h,如下图八所示,并在该两个文件中添加如下代码。
/* USER CODE BEGIN Includes */
/* Section where include file can be added */
/* USER CODE END Includes */
/* Ensure stdint is only used by the compiler, and not the assembler. */
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include
extern uint32_t SystemCoreClock;
#endif
#define configUSE_PREEMPTION 1
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES ( 32 )
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
#define configTOTAL_HEAP_SIZE ((size_t)36*1024)
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
/* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
/* USER CODE END 1 */
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
/* IMPORTANT: This define is commented when used with STM32Cube firmware, when timebase is systick,
to prevent overwriting SysTick_Handler defined within STM32Cube HAL */
/* #define xPortSysTickHandler SysTick_Handler */
/* USER CODE BEGIN Defines */
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
/* USER CODE END Defines */
#endif /* FREERTOS_CONFIG_H */
#ifndef _INCLUDES_H
#define _INCLUDES_H
/*
********************************************************************************
* 标准库
********************************************************************************
*/
#include
#include
#include
#include
/*
********************************************************************************
* 其它库
********************************************************************************
*/
/*
********************************************************************************
* OS
********************************************************************************
*/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "croutine.h"
#include "semphr.h"
#include "event_groups.h"
/*
********************************************************************************
* 宏定义
********************************************************************************
*/
/*
********************************************************************************
* APP / BSP
********************************************************************************
*/
#include "bsp.h"
#endif /* _INCLUDES_H */
清空main.c文件中的代码,编写FreeRTOS系统代码,这里我只创建了两个任务。
/* Includes */
#include "includes.h"
#include "GUI.h"
/* Private macro */
/* 任务优先级. */
#define mainTASK_TASK1_PRIORITY ( tskIDLE_PRIORITY + 4 )
#define mainTASK_TASK2_PRIORITY ( tskIDLE_PRIORITY + 5 )
/* 任务栈大小. */
#define mainTASK_TASK1_SIZE ( configMINIMAL_STACK_SIZE + 384 )
#define mainTASK_TASK2_SIZE ( configMINIMAL_STACK_SIZE + 384 )
/* Private variables */
/* Private functions */
static void vTaskTASK1 (void *pvParameters);
static void vTaskTASK2 (void *pvParameters);
static void AppTaskCreate (void);
/* 任务句柄. */
static TaskHandle_t xHandleTaskTASK1 = NULL;
static TaskHandle_t xHandleTaskTANS2 = NULL;
/**
**===========================================================================
**
** Abstract: main program
**
**===========================================================================
*/
int main(void)
{
__set_PRIMASK(1);
bsp_Init();
AppTaskCreate();
vTaskStartScheduler();
while(1);
}
/**
**===========================================================================
**
** Abstract: TASK1
**
**===========================================================================
*/
static void vTaskTASK1 (void *pvParameters)
{
while(1)
{
vTaskDelay(50);
}
}
/**
**===========================================================================
**
** Abstract: TASK2
**
**===========================================================================
*/
static void vTaskTASK2 (void *pvParameters)
{
while(1)
{
vTaskDelay(50);
}
}
static void AppTaskCreate (void)
{
xTaskCreate(vTaskTASK1,
"vTaskTASK1",
mainTASK_TASK1_SIZE,
NULL,
mainTASK_TASK1_PRIORITY,
&xHandleTaskTASK1);
xTaskCreate(vTaskTASK2,
"vTaskTASK2",
mainTASK_TASK2_SIZE,
NULL,
mainTASK_TASK2_PRIORITY,
&xHandleTaskTANS2);
}
找到stm32f4xx_it.c,需要删除下面几个函数:SysTick_Handler(void)、PendSV_Handler(void)、SVC_Handler(void)。
最后一步也是最重要的一步操作就是把添加的文件夹的头文件包含进去。
添加添加到工程中的主目录路径,这一点千万别忘记了。
到此为止移植工作已经完成,在任务中分别添加点亮不同led灯的驱动程序即可实现灯的闪烁,验证任务切换是否成功。
下载程序及调试请注意:要注意裸机工程建的时候要选对你使用的下载器,如果你使用的是STLINK可如下图十一操作,选中工程默认操作即可。笔者一开始用的是山寨版的J-LINK发现不管怎么样都无法下载成功,不知道是不是该软件不适用山寨版J-LINK,如果你也有类似的情况建议换成正版的STLINK,笔者用的是STLINKV2。