赞
踩
尝试过CubeMX直接生成HAL库+FreeRTOS;也尝试过CubeMX生成HAL库+手动移植FreeRTOS;正点原子也有手动HAL+手动FreeRTOS;
这里想要记录一下标准库+手动移植FreeRTOS
可以直接在浏览器搜索 “ FreeRTOS ” 下载,或者直接点此条博客的绑定资源。
这个根据自己的已有模板创建使用,这里不做讲解。
在工程文件夹内建立《FreeRTOS
》文件夹,将 资料\FreeRTOS源码\FreeRTOSv9.0.0\FreeRTOS\Source
里的文件全部拷入其中
删除工程 stm32标准库工程模板\FreeRTOS\portable
里的文件,仅保留《keil
》《MemMang
》《RVDS
》三个文件夹(或者在前一步拷贝的时候仅拷贝这三个文件夹)
打开工程,点开箱子图标新建两个Group名为《 FreeRTOS_Core
》《 FreeRTOS_Port
》
在《 FreeRTOS_Core
》中添加源码《FreeRTOS
》文件夹里面的 五个.c文件
stm32标准库工程模板\FreeRTOS\
croutine.c
stm32标准库工程模板\FreeRTOS\event_groups.c
stm32标准库工程模板\FreeRTOS\list.c
stm32标准库工程模板\FreeRTOS\queue.c
stm32标准库工程模板\FreeRTOS\task.c
stm32标准库工程模板\FreeRTOS\timers.c
FreeRTOS_Port
》中添加源码《FreeRTOS
》文件夹里面的 两个.c文件stm32标准库工程模板\FreeRTOS\portable\MemMang\
heap_4.c
stm32标准库工程模板\FreeRTOS\portable\RVDS\ARM_CM4F\port.c
进入工程内的stm32f4xx_it.c
文件
注释 这三个函数或者 改成条件宏定义
// void SysTick_Handler(void){
//};
//void PendSV_Handler(void){
//};
//void SVC_Handler(void){
//};
资料\FreeRTOS源码\FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK\FreeRTOSConfig.h
的.h配置文件到stm32标准库工程模板\FreeRTOS\include
中,并将其添加进工程中(可以放进user的group里)FreeRTOSConfig.h
文件configUSE_IDLE_HOOK 0
configUSE_TICK_HOOK 0
configCHECK_FOR_STACK_OVERFLOW 0
configUSE_MALLOC_FAILED_HOOK 0
__NVIC_PRIO_BITS
的宏定义(可在整个project中直接搜索),如果是 4U
则改为4
FreeRTOSConfig.h
文件 /* Ensure stdint is only used by the compiler, and not the assembler. */
#ifdef __ICCARM__
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
改为:(否则报错SystemCoreClock未定义)
#if defined (__ICCARM__) || defined (__CC_ARM) || defined (__GNUC__)
#include <stdint.h>
extern uint32_t SystemCoreClock;
#endif
.\FreeRTOS\include
.\FreeRTOS\portable\RVDS\ARM_CM4F
#include “FreeRTOS.h”
#include “task.h”
#define START_TASK_PRIO 1 #define START_STK_SIZE 120 void start_task(void * pvParameters); //任务函数 TaskHandle_t StartTask_Handler; //任务句柄 #define TASK1_TASK_PRIO 2 #define TASK1_STK_SIZE 120 void task1_task(void * pvParameters); TaskHandle_t Task1Task_Handler; //任务句柄 #define TASK2_TASK_PRIO 3 #define TASK2_STK_SIZE 120 void task2_task(void * pvParameters); TaskHandle_t Task2Task_Handler; //任务句柄
xTaskCreate((TaskFunction_t ) start_task,
(char* ) "start_task",
(uint16_t ) START_STK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t* ) &StartTask_Handler);
vTaskStartScheduler(); //开启任务调度
void start_task(void * pvParameters) { //创建Task1 taskENTER_CRITICAL(); /* 进入临界区 */ xTaskCreate((TaskFunction_t ) task1_task, (char* ) "task1_task", (uint16_t ) TASK1_STK_SIZE, (void * ) NULL, (UBaseType_t ) TASK1_TASK_PRIO, (TaskHandle_t* ) &Task1Task_Handler); //创建Task2 xTaskCreate((TaskFunction_t ) task2_task, (char* ) "task2_task", (uint16_t ) TASK1_STK_SIZE, (void * ) NULL, (UBaseType_t ) TASK2_TASK_PRIO, (TaskHandle_t* ) &Task2Task_Handler); vTaskDelete(StartTask_Handler); //NULL taskEXIT_CRITICAL(); /* 退出临界区 */ } void task1_task(void * pvParameters){ while(1){ } } void task2_task(void * pvParameters){ while(1){ } }
#include "stm32f4xx.h" // Device header #include "delay.h" #include "usart.h" #include "LED.h" #include "FreeRTOS.h" #include "task.h" #define START_TASK_PRIO 1 #define START_STK_SIZE 120 void start_task(void * pvParameters); //任务函数 TaskHandle_t StartTask_Handler; //任务句柄 #define TASK1_TASK_PRIO 2 #define TASK1_STK_SIZE 120 void task1_task(void * pvParameters); TaskHandle_t Task1Task_Handler; //任务句柄 #define TASK2_TASK_PRIO 3 #define TASK2_STK_SIZE 120 void task2_task(void * pvParameters); TaskHandle_t Task2Task_Handler; //任务句柄 int main(){ delay_init(168); uart_init(9600); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); printf("Start !\r\n"); LED_Init(); xTaskCreate((TaskFunction_t ) start_task, (char* ) "start_task", (uint16_t ) START_STK_SIZE, (void * ) NULL, (UBaseType_t ) START_TASK_PRIO, (TaskHandle_t* ) &StartTask_Handler); vTaskStartScheduler(); //开启任务调度 } void start_task(void * pvParameters) { //创建Task1 taskENTER_CRITICAL(); /* 进入临界区 */ xTaskCreate((TaskFunction_t ) task1_task, (char* ) "task1_task", (uint16_t ) TASK1_STK_SIZE, (void * ) NULL, (UBaseType_t ) TASK1_TASK_PRIO, (TaskHandle_t* ) &Task1Task_Handler); //创建Task2 xTaskCreate((TaskFunction_t ) task2_task, (char* ) "task2_task", (uint16_t ) TASK1_STK_SIZE, (void * ) NULL, (UBaseType_t ) TASK2_TASK_PRIO, (TaskHandle_t* ) &Task2Task_Handler); vTaskDelete(StartTask_Handler); //NULL taskEXIT_CRITICAL(); /* 退出临界区 */ } void task1_task(void * pvParameters){ while(1){ LED1(1); vTaskDelay(1000);//延时函数 LED1(0); vTaskDelay(1000); } } void task2_task(void * pvParameters){ while(1){ LED2(1); vTaskDelay(1000); LED2(0); vTaskDelay(1000); } }
#include “FreeRTOS.h”
#include “task.h”
SysTick_Handler
函数extern void xPortSysTickHandler(void);
/**
* @brief systick中断服务函数,使用OS时用到
* @param ticks : 延时的节拍数
* @retval 无
*/
void SysTick_Handler(void)
{
/* OS 开始跑了,才执行正常的调度处理 */
if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
{
xPortSysTickHandler();
}
}
FreeRTOSConfig.h
文件// #define xPortSysTickHandler SysTick_Handler
#include "delay.h" #include "sys.h" // #include "FreeRTOS.h" #include "task.h" static uint32_t g_fac_us = 0; /* us延时倍乘数 */ extern void xPortSysTickHandler(void); /** * @brief systick中断服务函数,使用OS时用到 * @param ticks : 延时的节拍数 * @retval 无 */ void SysTick_Handler(void) { /* OS 开始跑了,才执行正常的调度处理 */ if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { xPortSysTickHandler(); } } /** * @brief 初始化延迟函数 * @param sysclk: 系统时钟频率, 即CPU频率(rcc_c_ck), 180MHz * @retval 无 */ void delay_init(uint16_t sysclk) { /* 如果需要支持OS */ uint32_t reload; SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); /* SYSTICK使用外部时钟源,频率为HCLK */ g_fac_us = sysclk; /* 不论是否使用OS,g_fac_us都需要使用 */ /* 如果需要支持OS. */ reload = sysclk; /* 每秒钟的计数次数 单位为M */ reload *= 1000000 / configTICK_RATE_HZ; /* 根据delay_ostickspersec设定溢出时间,reload为24位 * 寄存器,最大值:16777216,在180M下,约合0.0932s左右 */ SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; /* 开启SYSTICK中断 */ SysTick->LOAD = reload; /* 每1/delay_ostickspersec秒中断一次 */ SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; /* 开启SYSTICK */ } /** * @brief 延时nus * @param nus: 要延时的us数 * @note 注意: nus的值,不要大于93206us(最大值即2^24 / g_fac_us @g_fac_us = 180) * @retval 无 */ void delay_us(uint32_t nus) { uint32_t ticks; uint32_t told, tnow, tcnt = 0; uint32_t reload = SysTick->LOAD; /* LOAD的值 */ ticks = nus * g_fac_us; /* 需要的节拍数 */ told = SysTick->VAL; /* 刚进入时的计数器值 */ while (1) { tnow = SysTick->VAL; if (tnow != told) { if (tnow < told) { tcnt += told - tnow; /* 这里注意一下SYSTICK是一个递减的计数器就可以了 */ } else { tcnt += reload - tnow + told; } told = tnow; if (tcnt >= ticks) { break; /* 时间超过/等于要延迟的时间,则退出 */ } } } } /** * @brief 延时nms * @param nms: 要延时的ms数 (0< nms <= 65535) * @retval 无 */ void delay_ms(uint16_t nms) { uint32_t i; for (i=0; i<nms; i++) { delay_us(1000); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。