企业网站建设计划书,html什么意思,长沙房产网最新楼盘地图,四川住房建设和城乡建设厅新网站文章目录 前言系统配置任务创建任务创建删除实践 前言
接着学习正点原子的FreeRTOS教程#xff0c;涉及到一些详细的系统内文件代码 系统配置
可以通过各种的宏定义来实现我们自己的RTOS配置#xff08;在FreeRTOSconfig.h#xff09;
“INCLUDE”#xff1a;配置API函数… 文章目录 前言系统配置任务创建任务创建删除实践 前言
接着学习正点原子的FreeRTOS教程涉及到一些详细的系统内文件代码 系统配置
可以通过各种的宏定义来实现我们自己的RTOS配置在FreeRTOSconfig.h
“INCLUDE”配置API函数”config“完成功能配置和裁剪其他配置项LPendSV宏定义SVC宏定义
任务创建
分为静态和动态创建
动态任务创建任务的任务控制块以及任务的栈空间所需的内存均由自动从堆中分配
静态创建任务任务的任务控制块以及任务的栈空间所需的内存需用户分配提供 任务创建 返回值 pdPASS创建成功 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY创建失败内存分配失败
如何成功创建
将宏configSUPPORT_DYNAMIC_ALLOCATION 配置为 1定义函数入口参数编写任务函数 任务控制块 每个任务都有属于自己的任务控制块类似身份证。 静态创建任务 返回值 NULL用户没有提供相应的内存任务创建失败 其他值任务句柄任务创建成功
如何成功创建
需将宏configSUPPORT_STATIC_ALLOCATION 配置为 1定义空闲任务定时器任务的任务堆栈及TCB实现两个接口函数vApplicationGetIdleTaskMemory( ) vApplicationGetTimerTaskMemory ( )定义函数入口参数编写任务函数 任务删除 void vTaskDelete(TaskHandle_t xTaskToDelete); 参数是待删除任务的任务句柄用于删除已被创建的任务被删除的任务将从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除
要点
当传入的参数为NULL则代表删除任务自身当前正在运行的任务空闲任务会负责释放被删除任务中由系统分配的内存但是由用户在任务删除前申请的内存 则需要由用户在任务被删除前提前释放否则将导致内存泄露
如何删除
使用删除任务函数需将宏INCLUDE_vTaskDelete 配置为 1入口参数输入需要删除的任务句柄NULL代表删除本身
任务创建删除实践
1.任务创建删除正点原子的代码 xTaskCreate((TaskFunction_t ) task1,(char * ) task1,(configSTACK_DEPTH_TYPE ) TASK1_STACK_SIZE,(void * ) NULL,(UBaseType_t ) TASK1_PRIO,(TaskHandle_t * ) task1_handler );利用该函数创建任务从上到下分别是指向任务函数的指针任务名堆栈大小任务指针参数优先级任务句柄。但是我感觉不需要强制类型转换有时写错也不容易发现
一般系统初始化的操作是先创建一个任务这个任务完成系统所有任务的创建创建完成后把自己删除掉的结构这样代码比较简洁结构清晰。
/* START_TASK 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task( void * pvParameters );/* TASK1 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1( void * pvParameters );/* TASK2 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2( void * pvParameters );/* TASK3 任务 配置* 包括: 任务句柄 任务优先级 堆栈大小 创建任务*/
#define TASK3_PRIO 4
#define TASK3_STACK_SIZE 128
TaskHandle_t task3_handler;
void task3( void * pvParameters );
void freertos_demo(void) //先创建一个任务{ xTaskCreate((TaskFunction_t ) start_task,(char * ) start_task,(configSTACK_DEPTH_TYPE ) START_TASK_STACK_SIZE,(void * ) NULL,(UBaseType_t ) START_TASK_PRIO,(TaskHandle_t * ) start_task_handler );vTaskStartScheduler(); //开始调度否则不会执行start_task任务
}void start_task( void * pvParameters ) //这个任务完成所有任务的创建
{taskENTER_CRITICAL(); /* 进入临界区 */xTaskCreate((TaskFunction_t ) task1,(char * ) task1,(configSTACK_DEPTH_TYPE ) TASK1_STACK_SIZE,(void * ) NULL,(UBaseType_t ) TASK1_PRIO,(TaskHandle_t * ) task1_handler );xTaskCreate((TaskFunction_t ) task2,(char * ) task2,(configSTACK_DEPTH_TYPE ) TASK2_STACK_SIZE,(void * ) NULL,(UBaseType_t ) TASK2_PRIO,(TaskHandle_t * ) task2_handler );xTaskCreate((TaskFunction_t ) task3,(char * ) task3,(configSTACK_DEPTH_TYPE ) TASK3_STACK_SIZE,(void * ) NULL,(UBaseType_t ) TASK3_PRIO,(TaskHandle_t * ) task3_handler );........................vTaskDelete(NULL);taskEXIT_CRITICAL(); /* 退出临界区 */
}/* 任务一实现LED0每500ms翻转一次 */
void task1( void * pvParameters )
{while(1){printf(task1正在运行\r\n);LED0_TOGGLE();vTaskDelay(500);}
}
.................
.................
................这里vTaskStartScheduler()函数执行后系统就会开始执行任务但是很明显真正的任务都没开始创建且因为系统按照从上往下执行所以会先创建的任务先执行不按照优先级走等所有任务创建完成后系统才开始真正按照优先级开始执行任务。
我觉得FreeRTOS的执行过程就是一个一个任务的执行他是通过执行完一个任务后再执行下一个遇到优先级比它高的任务会被打断这也就是为什么创建task1后系统就停下了start_task工作执行task1的代码了执行完task1后又回去初始化task2。感觉 vTaskDelay()函数是系统调度的一个灵活工具。让系统从循环执行任务还是很像裸机开始进行灵活分配cpu了
这里用到了临界区FreeRTOS临界区是指那些必须完整运行不能被打断的代码段比如有的外设的初始化需要严格的时序初始化过程中不能被打断。进入临界区代码的时候需要关闭中断当处理完临界区代码以后再打开中断。起到一个代码保护的作用。
感觉这个FreeRTOS和之间裸机开发时看到很多人的程序利用uwTick的数值来执行程序很像但当然FreeRTOS强大的多如下
__weak void HAL_IncTick(void) //利用滴答定时器一般1ms累加一次
{uwTick uwTickFreq;
}void deme()
{if(uwTick-led_tick1000) //实现每隔1000个计数执行一次代码{led_tickuwTick;..................}}2.HAL库创建任务 利用STM32CubeMX生成的FreeRTOS来实现与正点原子手动移植有些区别
我这里简单写了一个点灯任务进行测试可以正常运行
TaskHandle_t task1_handler;void vTaskCode( void * pvParameters ){while(1){HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4); vTaskDelay(500);}}void vOtherFunction( void ){xTaskCreate( vTaskCode, tak1, 128, NULL, 1, task1_handler );//vTaskStartScheduler();}int main(void)
{/* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* Configure the system clock */SystemClock_Config();/* Initialize all configured peripherals */MX_GPIO_Init();/* Init scheduler */osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */MX_FREERTOS_Init(); vOtherFunction(); //放在操作系统内核启动前/* Start scheduler */ osKernelStart();while (1){}
}有些不懂的地方首先我自己不需要启动任务调度了当然执行这个函数vTaskStartScheduler()也没啥问题但是这个任务创建放的位置需要在osKernelStart()前面正点原子的如下不是特别理解为啥放在操作系统内核启动开始任务调度后就不能运行了。
查了查资料可能是任务调度开启之后就正式进入FreeRTOS系统接管领域之后程序只会跑在中断和任务函数中也就是说如果放在后面根本就不会执行一个任务都没创建。而正点原子手动开启任务调度前已经创建了一个任务所以他才成功了。
int main(void)
{HAL_Init(); /* 初始化HAL库 */sys_stm32_clock_init(360, 25, 2, 8); /* 设置时钟,180Mhz */delay_init(180); /* 延时初始化 */usart_init(115200); /* 串口初始化为115200 */led_init(); /* 初始化LED */key_init(); /* 初始化按键 */sdram_init(); /* SRAM初始化 */lcd_init(); /* 初始化LCD */my_mem_init(SRAMIN); /* 初始化内部内存池 */my_mem_init(SRAMEX); /* 初始化外部内存池 */my_mem_init(SRAMCCM); /* 初始化CCM内存池 */ freertos_demo(); //任务创建
}终于算开始入门了之后继续学习。