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总量。
然后就可以正常的打印了。