1. 前言
本篇将会从FreeRTOS官网下载内核源码,移植到MM32F320处理器的工程中,验证方法是创建一个任务,在任务中闪烁LED。
下载版本:

2.2 移植源文件
先在工程目录下面新建Middleware/FreeRTOS文件夹,把源根目录下的FreeRTOS-Kernel复制到这个目录下。

新建项目分组,将源文件根目录下的所有的.c添加到工程中:

添加port.c到工程中,由于我们使用的是VC6所以需要将FreeRTOS\portable\GCC\ARM_CM33_NTZ\non_secure目录下面的port.c、portasm.c添加进工程。当然如果你使用vc5那就添加keil下面的库
添加内存管理文件,这里选择portable/MemMang下面的heap_4.c

设置FreeRTOS的配置文件,他在example下面有一个,我将他复到的FreeRTOS目录下面并添加进工程。
添加完工程后,工程如下:

添加好后,将编译的头文件路径也添加如下:

【配置文件】
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
#include "platform.h"
extern uint32_t SystemCoreClock;
/* Star-MC1 port configuration. */
#define configENABLE_MPU 0
#define configENABLE_FPU 1
#define configENABLE_TRUSTZONE 0
/* Constants related to the behaviour or the scheduler. */
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configUSE_PREEMPTION 1
#define configUSE_TIME_SLICING 1
#define configMAX_PRIORITIES ( 5 )
#define configIDLE_SHOULD_YIELD 1
#define configUSE_16_BIT_TICKS 0 /* Only for 8 and 16-bit hardware. */
/* Constants that describe the hardware and memory usage. */
#define configCPU_CLOCK_HZ SystemCoreClock//系统时钟
#define configMINIMAL_STACK_SIZE ( ( uint16_t ) 128 ) // 定义空闲任务使用的堆栈大小。
#define configMAX_TASK_NAME_LEN ( 12 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) )//配置FreeRTOS任务栈可用的RAM总量。
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
/* Constants that build features in or out. */
#define configUSE_MUTEXES 1
#define configUSE_TICKLESS_IDLE 1
#define configUSE_APPLICATION_TASK_TAG 0
#define configUSE_NEWLIB_REENTRANT 0
#define configUSE_CO_ROUTINES 0
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_QUEUE_SETS 0
#define configUSE_TASK_NOTIFICATIONS 1
#define configUSE_TRACE_FACILITY 1
/* Constants that define which hook (callback) functions should be used. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configUSE_MALLOC_FAILED_HOOK 0
/* Constants provided for debugging and optimisation assistance. */
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
#define configQUEUE_REGISTRY_SIZE 0
/* Software timer definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY ( 3 )
#define configTIMER_QUEUE_LENGTH 5
#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
/* Set the following definitions to 1 to include the API function, or zero
* to exclude the API function. NOTE: Setting an INCLUDE_ parameter to 0 is
* only necessary if the linker does not automatically remove functions that are
* not referenced anyway. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_eTaskGetState 1
#define INCLUDE_xTaskResumeFromISR 0
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_xTaskGetSchedulerState 0
#define INCLUDE_xSemaphoreGetMutexHolder 0
#define INCLUDE_xTimerPendFunctionCall 1
/* This demo makes use of one or more example stats formatting functions. These
* format the raw data provided by the uxTaskGetSystemState() function in to
* human readable ASCII form. See the notes in the implementation of vTaskList()
* within FreeRTOS/Source/tasks.c for limitations. */
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
/* Dimensions a buffer that can be used by the FreeRTOS+CLI command interpreter.
* See the FreeRTOS+CLI documentation for more information:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_CLI/ */
#define configCOMMAND_INT_MAX_OUTPUT_SIZE 4096
/* Interrupt priority configuration follows...................... */
/* Use the system definition, if there is one. */
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 3 /* 8 priority levels. */
#endif
/* The lowest interrupt priority that can be used in a call to a "set priority"
* function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x07
/* 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 ) )
/* The #ifdef guards against the file being included from IAR assembly files. */
#ifndef __IASMARM__
/* Constants related to the generation of run time stats. */
#define configGENERATE_RUN_TIME_STATS 0
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#define portGET_RUN_TIME_COUNTER_VALUE() 0
// #define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#endif /* __IASMARM__ */
/* Enable static allocation. */
#define configSUPPORT_STATIC_ALLOCATION 0
/* System Handler */
#define SVC_Handler SVCall_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
#endif /* FREERTOS_CONFIG_H */具体的配置文件还需要看具体自己需要的什么功能来配置
【注意】
由于freertos实现了SVCall_Handler、PendSV_Handler、SysTick_Handler,所以我们需要在mm32f5260_it.c中注释掉这三个函数,要不会编译报错。

【测试程序】
修改main.c如下:
#define _MAIN_C_
/* Files include */
#include "platform.h"
#include "gpio_led_toggle.h"
#include "main.h"
#include "FreeRTOS.h"
#include "task.h"
/***********************************************************************************************************************
* @brief This function is main entrance
* @note main
* @param none
* @retval none
*********************************************************************************************************************/
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 256
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 256
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
//任务优先级
#define LED2_TASK_PRIO 3
//任务堆栈大小
#define LED2_STK_SIZE 256
//任务句柄
TaskHandle_t LED2Task_Handler;
//任务函数
void led2_task(void *pvParameters);
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
PLATFORM_InitConsole(115200);
PLATFORM_InitLED();
//创建开始任务
xTaskCreate( start_task , //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
while (1)
{
}
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED0任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建LED1任务
xTaskCreate((TaskFunction_t )led2_task,
(const char* )"led2_task",
(uint16_t )LED2_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED2_TASK_PRIO,
(TaskHandle_t* )&LED2Task_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED0任务函数
void led1_task(void *pvParameters)
{
while(1)
{
GPIO_WriteBit(GPIOB, GPIO_Pin_15, 0);
vTaskDelay(500);
GPIO_WriteBit(GPIOB, GPIO_Pin_15, 1);
vTaskDelay(500);
}
}
//LED1任务函数
void led2_task(void *pvParameters)
{
while(1)
{
// printf("task2\r\n");
GPIO_WriteBit(GPIOB, GPIO_Pin_14, 0);
vTaskDelay(200);
GPIO_WriteBit(GPIOB, GPIO_Pin_14, 1);
vTaskDelay(200);
}
}
/********************************************** (C) Copyright MindMotion **********************************************/下载到开发板上,可以可看到板载的两个LED灯会按不同的频率闪烁。
【printf卡死的问题】
经过查找资料,因为printf需要申请大的内存空间,因此必须把总栈分配大一些:
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 20 * 1024 ) )//配置FreeRTOS任务栈可用的RAM总量。
然后就可以正常的打印了。


我要赚赏金
