freertos学习
freertos的基本框架如下
注意有三点很重要:
1.任务的资源
(1)任务优先级:freertos 能够调度的任务优先级在freertosConfig.h中的configMAX_PRIORITIES中定义,每一个任务的优先级都在0~configMAX_PRIORITIES -1 中取值 优先级是数值越小,优先级越小,空闲任务的优先级为0.高优先级的任务必须有延时,低优先级的任务才能获得人物使用权。
任务优先级在定义时,可参考以下的规则:
① IRQ 任务:IRQ 任务是指通过中断服务程序进行触发的任务,此类任务应该设置为所有任务里面优先级最高的。
② 高优先级后台任务:比如按键检测,触摸检测,USB 消息处理,串口消息处理等,都可以归为这一类任务。
③ 低优先级的时间片调度任务:比如 emWin 的界面显示,LED 数码管的显示等不需要实时执行的都可以归为这一类任务。 实际应用中用户不必拘泥于将这些任务都设置为优先级 1 的同优先级任务,可以设置多个优先级,只需注意这类任务不需要高实时性。
(2)任务栈的大小:在freertosConfig.h中定义了一个总的堆栈的大小configTOTAL_HEAP_SIZE。如何这个值不够使用的话可以增大这个值。每个任务的栈都是特别要注意的。如果任务出现不运行,很大可能是任务栈不够用了。在freertos中有一个API可以获取在程序运行到现在,栈的接近历史最高水平线的值。我们需要在配置头文件将宏configCHECK_FOR_STACK_OVERFLOW 打开,这宏可定义为两个值1或者2,这两个值有着不同的检测方法,这两个方法不在赘叙。我们还需要调用任务栈溢出的时候,将溢出的任务的名字打印出来,或者进行其他处理。
2.线程间的通讯
(1)信号量 :二值信号量、计数信号量、互斥信号量。在多个任务等待同一个信号量来进行同步时,当这些任务优先级相等时,他们依次交叉获取 ,当这些任务优先级不同时,就会只有高优先级的任务会获取。
(2)队列:注意取队列的速度和发送队列的速度,与他们的等待时长。注意判断返回值
(3)事件组:事件组相当于一个软件寄存器,每一位都有一个标志。常用于当一个任务同时满足多个条件(与的关系)或者满足多个条件的某一个条件(或的关系)时使用。
3.所有的API都要注意是不是在中断中调用。
其他:软件定时器:本质上就是队列,需要自己注册定时到后的回调函数。
1 #include "mytask.h" 2 #include "task.h" 3 #include "timers.h" 4 5 6 /* TASK HANDLERS */ 7 TaskHandle_t startHandle; 8 TaskHandle_t ledHandle; 9 TaskHandle_t printfHandle; 10 TaskHandle_t writeQueueHandle; 11 TaskHandle_t SemaphoreBinaryHandle; 12 TaskHandle_t eventgrupHandle; 13 TimerHandle_t timer; 14 /* TASK INPUT VARIABLES */ 15 u32 led_params = 500; 16 char *databuf = "hello world"; 17 u8 queue_buff[11]; 18 u8 TIMER_ID = 1; 19 /* thread commutication variables */ 20 xQueueHandle myqueue; 21 xSemaphoreHandle semphorebinary; 22 EventGroupHandle_t eventgroup; 23 /* task status */ 24 portBASE_TYPE status; 25 26 void start_task(void *param) 27 { 28 printf("start task\r\n"); 29 30 myqueue = xQueueCreate(5,11*sizeof(char)); 31 32 vSemaphoreCreateBinary(semphorebinary); 33 timer = xTimerCreate("timer test",1000/portTICK_PERIOD_MS,pdTRUE,(void*)&TIMER_ID,AutoReloadTimer_Handle_callback); 34 eventgroup = xEventGroupCreate(); 35 36 taskENTER_CRITICAL(); 37 xTaskCreate(led_task,"led task",START_STA_SIZE,(void*)&led_params,LED_TASK_PRTO,ledHandle); 38 xTaskCreate(printf_task,"printf task",PRINTF_STA_SIZE,(void *)databuf,PRTINF_TASK_PRIO,printfHandle); 39 xTaskCreate(writeQueue_task,"write queue task",WRITEQUEUE_STA_SIZE,NULL,WRITEQUEUE_TASK_PRIO,writeQueueHandle); 40 xTaskCreate(SemaphoreBinary_task,"xsemphorebinary task",BINARY_STA_SIZE,NULL,PRTINF_TASK_PRIO,SemaphoreBinaryHandle); 41 xTaskCreate(eventgrup_task,"eventgrup task",EVENT_STA_SIZE,NULL,EVENT_TASK_PRIO,eventgroup); 42 taskEXIT_CRITICAL(); 43 //xTimerStart(timer,0); 44 vTaskDelete(NULL); 45 } 46 47 void led_task(void*param) 48 { 49 50 while(1) 51 { 52 53 HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_13,GPIO_PIN_SET); //PB1置1 54 HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_5, GPIO_PIN_RESET); //PB1置1 55 vTaskDelay(*(u32*)param); 56 HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_13,GPIO_PIN_RESET); //PB1置1 57 HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_5, GPIO_PIN_SET); //PB1置1 58 vTaskDelay(*(u32*)param); 59 xEventGroupSetBits(eventgroup,0x1); 60 } 61 62 } 63 64 void printf_task(void*param) 65 { 66 while(1) 67 { 68 status = xQueueReceive(myqueue,queue_buff,portMAX_DELAY); 69 if(status == pdPASS) 70 { 71 taskENTER_CRITICAL(); 72 printf("%s\r\n",queue_buff); 73 74 taskEXIT_CRITICAL(); 75 } 76 else printf("queue null \r\n"); 77 vTaskDelay(1000); 78 } 79 } 80 81 void writeQueue_task(void *param) 82 { 83 u8 i =0; 84 while(1) 85 { 86 status = xQueueSend(myqueue,queue_buff,0); 87 if(status!= pdPASS) printf("queue full\r\n"); 88 i++; 89 if(!(i%10)) 90 { 91 // xSemaphoreTake(semphorebinary,portMAX_DELAY); 92 // printf("get once baniry\r\n"); 93 xEventGroupSetBits(eventgroup,0x4); 94 } 95 vTaskDelay(1000); 96 } 97 } 98 99 void SemaphoreBinary_task(void*param) 100 { 101 u8 i =0; 102 while(1) 103 { 104 i++; 105 if(!(i%5)) 106 { 107 xSemaphoreGive(semphorebinary); 108 109 } 110 vTaskDelay(1000); 111 xEventGroupSetBits(eventgroup,0x2); 112 } 113 114 115 } 116 117 void eventgrup_task(void*param) 118 { 119 while(1) 120 { 121 xEventGroupWaitBits(eventgroup,0x7,pdTRUE,pdFALSE,portMAX_DELAY); 122 printf(" event groups test!!! \r\n"); 123 } 124 125 } 126 127 void vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName ) 128 { 129 printf("task overflow name :%s\r\n",pcTaskName); 130 131 } 132 void AutoReloadTimer_Handle_callback(TimerHandle_t xTimer) 133 { 134 static u32 count = 0; 135 count++; 136 if(count>20) 137 { 138 // xTimerReset(timer,0); 139 xTimerStop(timer,0); 140 } 141 printf("timer count: %d\r\n",count); 142 } 143 144 145 void print_high_stack_mark_value(void) 146 { 147 if(STACK_DEBUG) 148 { 149 u8 num =0; 150 num = uxTaskGetStackHighWaterMark(ledHandle); 151 printf("%s : %d\r\n",pcTaskGetTaskName(ledHandle),num); 152 num = uxTaskGetStackHighWaterMark(ledHandle); 153 printf("%s : %d\r\n",pcTaskGetTaskName(ledHandle),num); 154 num = uxTaskGetStackHighWaterMark(ledHandle); 155 printf("%s : %d\r\n",pcTaskGetTaskName(ledHandle),num); 156 157 } 158 159 }