前言:
FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。
FreeRTOS功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等。
本期首先将FreeRTOS源码移植到ARM Cortex-M0,然后增加任务创建。
移植平台:ARM Cortex-M0
移植对象:FreeRTOS
编译环境:Keil MDK
移植准备: 下载FreeRTOS源码(官方网站下载:http://www.freertos.org)
一、基于ARM Cortex-M0的FreeRTOS移植步骤
步骤1:将FreeRTOS加载到M0软件工程中
- 加载内核源文件,源文件路径:
FreeRTOS\Source
- 加载与处理器相关的硬件接口层源码,源文件路径:
FreeRTOS\Source\portable\GCC\ARM_CM0
- 加载各种类型的堆栈分配方案(只需要选1种)源码,源文件路径:
FreeRTOS\Source\portable\MemMang
- 加载内核源文件的头文件,源文件路径:
FreeRTOS\Source\include
软件工程环境下,加载以上源码的截图如下:
步骤2:修改FreeRTOSConfig.h
#if 0 //Designed by FDG
#ifdef __ICCARM__
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
#else
#include "STM32xxxxx.h" // 调用你的芯片底层定义头文件
#include <stdint.h>
extern uLONG SystemFrequency_SysClk; // 声明系统时钟#endif
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0 //Designed by FDG
#define configCPU_CLOCK_HZ ( SystemFrequency_SysClk ) //Designed by FDG
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 4 ) //Designed by FDG
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 128) //Designed by FDG
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( SRAMTOP - 512) ) //Designed by FGD
#define configMAX_TASK_NAME_LEN ( 16 ) //Designed by FDG
#define configUSE_TRACE_FACILITY 0 //Designed by FDG
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 10
#define configCHECK_FOR_STACK_OVERFLOW 0 //Designed by FDG
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_MALLOC_FAILED_HOOK 0 //Designed by FDG
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configGENERATE_RUN_TIME_STATS 0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
#define configUSE_TIMERS 0 //Designed by FDG
#define configTIMER_TASK_PRIORITY ( 2 )
#define configTIMER_QUEUE_LENGTH 5
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE ) //Designed by FDG
/* Set the following definitions to 1 to include the API function, or zeroto 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
/* Normal assert() semantics without relying on the provision of an assert.hheader file. */
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSISstandard names - or at least those used in the unmodified vector table. */ #if 0 //Designed by FDG
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif
步骤3:修改portmacro.h
#if 1 //Designed by FDG
extern void xPortPendSVHandler(void);
extern void xPortSysTickHandler(void);
extern void vPortSVCHandler(void);
#endif
步骤4:修改 startup.s 或者 startup.c(有的芯片公司是.s有的是.c,用于定义中断向量表。我移植的这颗芯片是.c)
#if 1 //Designed by FDG
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#endif
#if 0 //Designed by FDG
__weak void SVC_Handler(void){}
__weak void PendSV_Handler(void){}
__weak void SysTick_Handler(void){}
#endif
#if 0 //Designed by FDG
(vect_t) SVC_Handler, // SVCall Handler
#else
(vect_t) vPortSVCHandler, // vPortSVCHandler
#endif
#if 0 //Designed by FDG
(vect_t) PendSV_Handler, // PendSV Handler
(vect_t) SysTick_Handler, // SysTick Handler#else
(vect_t) xPortPendSVHandler, // xPortPendSVHandler Handler
(vect_t) xPortSysTickHandler, // xPortSysTickHandler Handler
#endif
移植完毕!编译如下:
二、基于ARM Cortex-M0的FreeRTOS任务创建
- 宏定义
#define M_TestSemaphore 1
2. 主函数中创建任务0
#include "semphr.h"
//---------------------------
void TASK0(void *pdata);
void TASK1(void *pdata);
void TASK2(void *pdata); //
SemaphoreHandle_t xTestSemaphore = NULL;
TaskHandle_t xHandleTask0 = NULL,xHandleTask1 = NULL,xHandleTask2 = NULL;
//
int main(void)
{
/*芯片初始化,略*/
//creates a new binary semaphore xTestSemaphore = xSemaphoreCreateBinary(); //creat task 0 xTaskCreate(TASK0,
"Task0",
configMINIMAL_STACK_SIZE,
NULL,
1,
&xHandleTask0);
//start to schedule
vTaskStartScheduler();
return 0;
}
3. 任务0功能定义,并在任务0中创建任务1和任务2
//*****************************************************************************
//!\brief Task 0
//!\param pdata:
//!\retvalNone //*****************************************************************************
void TASK0 (void *pdata)
{
pdata = pdata;
//creat task 1
xTaskCreate(TASK1,
"Task1",
configMINIMAL_STACK_SIZE,
NULL,
2,
&xHandleTask1 );
//creat task 2
xTaskCreate(TASK2,
"Task2",
configMINIMAL_STACK_SIZE,
NULL,
3,
&xHandleTask2 );
//
while(1) {
//---- Add task 0 function here -----------
#if M_TestSemaphore == 1
if( xTestSemaphore != NULL )
{
if(xSemaphoreTake(xTestSemaphore, 0 ) == pdTRUE ) //to obtain a semaphore. portMAX_DELAY, 10 / portTICK_RATE_MS,0
{
taskENTER_CRITICAL();
printf("task 0\r\n");
taskEXIT_CRITICAL();
}
}
#else
vTaskDelay( 200 / portTICK_RATE_MS );
taskENTER_CRITICAL();
printf("task 0\r\n");
taskEXIT_CRITICAL();
#endif
}
}
4.任务1和任务2功能定义
//*****************************************************************************
//!\brief Task 1
//!\param pdata:
//!\retvalNone //*****************************************************************************
void TASK1 (void *pdata)
{
pdata = pdata;
while(1) {
//---- Add task 1 function here -----------
vTaskDelay( 100 / portTICK_RATE_MS );
taskENTER_CRITICAL();
printf("task 1\r\n");
taskEXIT_CRITICAL();
}
}
//*****************************************************************************
//!\brief Task 2
//!\param pdata:
//!\retvalNone //*****************************************************************************
void TASK2 (void *pdata)
{
pdata = pdata;
while(1) {
//---- Add task 2 function here -----------
vTaskDelay( 50 / portTICK_RATE_MS );
taskENTER_CRITICAL();
printf("task 2\r\n");
taskEXIT_CRITICAL();
}
}
3个任务创建完毕!收工!!