南昌大学FreeRTOS实验5-8知识点

合集下载

干货FreeRTOS学习笔记——实验:串口后台打印

干货FreeRTOS学习笔记——实验:串口后台打印

干货FreeRTOS学习笔记——实验:串口后台打印EEWorld电子资讯犀利解读技术干货每日更新现在来探讨一下如何利用FreeRTOS 的服务来为单片机程序设计提供方便,也感受下引入FreeRTOS 后系统处理效率的变化。

我想了个简单的常用需求:串口的“后台”打印输出(单片机开发时常用于调试信息输出),来进行实验。

串口(异步串行通讯口的简称, UART)相对于 CPU 是一个低速的设备,一般较高通信速率为115200bit/s,在此速率下输出一个8-bit 字符(假设用1个起始位,1个停止位,无校验)用的时间为87us. CPU 将字符写入串口的发送数据寄存器需要的时间可以忽略,但是由于串口硬件FIFO很小,务必要等待发送数据寄存器允许写入时才可以进行写操作。

于是,简单的程序设计中就不断查询标志位,等待寄存器可以写了就写一个字符,直到要发送的字符串写完。

要照顾执行效率的时候一定不能这么做,特别是在多任务环境下,因为这种循环重复查询标志位的做法让其它任务也只能等待,没有利用CPU处理能力。

于是我们需要一种“后台”输出的方法,让当前任务将要从串口输出的字符串提交到系统之后,程序往下执行,不用等待字符串从串口发送完;或者是当前任务等待字符串发送完,但是其它任务可以执行。

以下我的实验代码在ST Nucleo-L4R5ZI 板子上运行,也很容易改动一下以在其它 STM32 上运行(不过 STM32L4R5 的SRAM大,方便挥霍)。

在这块开发板上,USB串口连接到了STM32L4R5 的LPUART1, 我就编写一个 uart_puts(char *) 函数来从 LPUART1 输出字符串。

LPUART1 的TDR 寄存器时候用来写要发送的数据的,发送完成等状态可以从ISR 寄存器获取。

当然为了实现后台工作,中断是需要用到的了。

1简单直接的办法——字符队列不能反复查询,那么就让 LPUART1 的 TDR 寄存器可以写的时候,产生一个中断来告诉CPU,该写字符了。

STM32-FreeRTOS快速学习之总结1

STM32-FreeRTOS快速学习之总结1

STM32-FreeRTOS快速学习之总结11. 基础知识注意:在RTOS中是优先值越⾼则优先级越⾼(和ucos/linux的相反)在移植的时候,主要裁剪FreeRTOS/Source/portable⽂件夹,该⽂件夹⽤来针对不同MCU做的⼀些处理,如下图所⽰,我们只需要使⽤:1.1配置⼯程时,选择memMang时,⼀般使⽤heap_4.cheap_4: 优点在于可以有效的利⽤内存碎⽚来合并为⼀个⼤内存.缺点在于只能⽤来⼀个ram⾥.heap_5: ⼀般针对有外部RAM才⽤到,优点在于可以同时利⽤内部ram和外部ram来进⾏内存碎⽚合并.最终添加的库⽂件有:然后我们在分配释放内存的时候,就尽量使⽤RTOS带的函数来实现,分配/释放函数如下所⽰:void *pvPortMalloc( size_t xWantedSize );void vPortFree( void *pv );1.2 添加头⽂件路径添加FreeRTOS\include添加FreeRTOS\portable\RVDS\ARM_CM3并将原⼦中的FreeRTOSConfig.h也复制到我们项⽬的FreeRTOS\include中(⽤来配置RTOS系统)2. FreeRTOSConfig.h配置介绍⼀般会写configXXXXX或者INCLUDE_XXXX类似的宏,这两个宏区别在于:configXXXXX⽤来实现不同功能,⽐如定义configUSE_COUNTING_SEMAPHORES为1时,表⽰使⽤计数信号量INCLUDE_XXXX⽤来是否将某个API函数编译进程序中.⽐如定义INCLUDE_xTaskGetSchedulerState为1 时,则将会编译xTaskGetSchedulerState()函数,如下图所⽰:3. FreeRTOS任务状态3.1 运⾏态指当前任务正在运⾏.3.2 就绪态指当前任务正在等待调度,因为有个⾼优先级/同优先级的任务正在运⾏中3.3 阻塞态当前任务处于等待外部事件通知或通过vTaskDelay()函数进⼊休眠了,外部事件通知常见有信号量、等待队列、事件标志组、任务通知.3.4 挂起态类似于暂停,表⽰不会再参与任务调度了,通过vTaskSuspend()实现,重新恢复调度则使⽤xTaskResume()4. FreeRTOS中断配置4.1 回忆stm32 NVIC中断Stm32可以设置NVIC中断组数为0~4,其中0~4区别在于如下图所⽰:、⽐如我们设置为NVIC_PriorityGroup_4时:表⽰抢占优先级为4bit(即为2^4,为0~15个抢占优先级),副优先级为0bit(表⽰没有).4.2 抢占优先级和副优先级的区别:1. 抢占优先级和副优先级的值越低,则优先级越⾼2.⾼的抢占优先级的中断可以直接打断低的抢占优先级的中断3.⾼的副优先级的中断不可以打断低的副优先级的中断(只是两个相同抢占优先级的中断同时来的时候,只会优先选择⾼的副优先级)4.3 FreeRTOS中断配置宏configKERNEL_INTERRUPT_PRIORITY⽤来配置中断最低抢占优先级,也就是可以FreeRTOS可以管理的最⼩抢占优先级,所以使⽤FreeRTOS时,我们尽量设置stm32为NVIC_PriorityGroup_4,这样就可以管理16个优先级了.configMAX_SYSCALL_INTERRUPT_PRIORITY⽤来配置FreeRTOS能够安全管理的的最⾼优先级.⽐如原⼦的FreeRTOSConfig.h⾥就设置为5,⽽0~4的优先级中断就不会被FreeRTOS因为开关中断⽽禁⽌掉(⼀直都会有),并且不能调⽤RTOS中的”FromISR”结尾的API函数.⽐如喂看门狗中断函数就需要设置为0~4如下图所⽰(来⾃原⼦⼿册):4.3 FreeRTOS中断开关函数portENABLE_INTERRUPTS();//开中断,将configMAX_SYSCALL_INTERRUPT_PRIORITY⾄ configKERNEL_INTERRUPT_PRIORITY之间的优先级中断打开portDISABLE_INTERRUPTS();//关中断,将configMAX_SYSCALL_INTERRUPT_PRIORITY⾄ configKERNEL_INTERRUPT_PRIORITY之间的优先级中断禁⽌掉5.任务常⽤API函数5.1 xTaskCreate创建任务函数定义如下:xTaskCreate( TaskFunction_t pxTaskCode, //任务函数,⽤来供给函数指针调⽤的const char * const pcName, //任务的字符串别名const uint16_t usStackDepth, //任务堆栈深度,实际申请到的堆栈是该参数的4倍void * const pvParameters, //函数参数,⽤来供给指针调⽤的UBaseType_t uxPriority, //优先级,越⾼优先级⾼,范围为0~configMAX_PRIORITIES-1 //注意优先级0会创建为空闲任务, 优先级configMAX_PRIORITIES-1会创建⼀个软件定时器服务任务(管理定时器的) TaskHandle_t * const pxCreatedTask ); //任务句柄,该句柄可以⽤于挂起/恢复/删除对应的任务//返回值 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY(-1):表⽰创建任务堆空间不⾜pdPASS(1):创建成功5.2 taskENTER_CRITICAL()和taskEXIT_CRITICAL()⽤于任务中进⼊/退出临界区,调⽤taskENTER_CRITICAL()主要会关闭其他任务调度.⽽taskEXIT_CRITICAL()则会恢复任务调度,⼀般⽤于初始化外设等.5.3 taskENTER_CRITICAL_FROM_ISR()和taskEXIT_CRITICAL_FROM_ISR()⽤于在中断函数中进⼊/退出临界区,作⽤和上⾯⼀样5.4 挂起/恢复/删除任务函数void vTaskSuspend( TaskHandle_t xTaskToSuspend ); //挂起⼀个任务,参数为挂起任务的句柄,如果为NULL则表⽰挂起⾃⾝任务void vTaskResume( TaskHandle_t xTaskToResume ); //恢复⼀个任务BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume);//从中断函数中恢复⼀个任务,返回1表⽰恢复成功void vTaskDelete( TaskHandle_t xTaskToDelete ); //删除⼀个任务,如果从任务函数中退出的话,则需要调⽤vTaskDelete(NULL)来删除⾃⾝任务5.5 vTaskDelay()延时函数void vTaskDelay( const TickType_t xTicksToDelay ); //参数表⽰延时的系统滴答数⽐如延时500ms可以写为: vTaskDelay( 500/portTICK_RATE_MS );portTICK_RATE_MS是个宏,表⽰当前系统的1个滴答需要多少ms,⽽500/portTICK_RATE_MS则表⽰当前500ms需要多少个系统滴答数.6. 队列6.1简介队列⽤于任务与任务或者任务与中断之间的通信.⽐如key任务检测到按键按下时,则可以通过队列向lcd显⽰任务发送信息,使得lcd切换界⾯.队列采⽤先进先出存储机制.队列发送数据可以有两种⽅式:浅拷贝、深拷贝.数据量不⼤的情况下,都使⽤深拷贝(会分配新的空间,并进⾏数据拷贝,缺点在于耗时)数据量⼤的情况下,都使⽤浅拷贝(通过指针⽅式,前提是要发送的数据必须不会被释放的)6.2队列的优点队列可以通过任何任务或者中断进⾏访问,可以随时存取数据消息.并且出⼊队的时候可以进⾏任务阻塞,⽐如某个任务进⾏读消息出队时,如果没有消息,则可以实现进⼊休眠状态,直到有消息才唤醒任务.6.3队列创建删除相关APIQueueHandle_t xQueueCreate( uxQueueLength, uxItemSize );//动态创建队列,内存会交给RTOS⾃动分配// uxQueueLength:队列长度(表⽰队列中最⼤多少条消息),uxItemSize:每个队列消息的长度(以字节为单位)//返回值: NULL(0, 表⽰分配失败),⾮0(表⽰返回该队列分配好的地址)//注意:使⽤⾃动分配时,需要配置configSUPPORT_DYNAMIC_ALLOCATION宏为1,否则只能由⽤户来分配.QueueHandle_t xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer );//静态创建队列,内存需要由⽤户事先分配好// uxQueueLength:队列长度(表⽰队列中最⼤多少条消息),uxItemSize:每个队列消息的长度(以字节为单位)// pucQueueStorage:指向⽤户事先分配好的存储区内存(必须为uint8_t型)// pxQueueBuffer:指向队列结构体,⽤来提供给RTOS初始化.然后给⽤户使⽤//返回值: NULL(0, 表⽰分配失败),⾮0(表⽰返回该队列分配好的地址)vQueueDelete( QueueHandle_t xQueue );//删除队列,并释放空间xQueueReset( xQueue );//将队列⾥的消息清空⼀次,也就是恢复初始状态6.4队列出⼊队相关APIxQueueSend( xQueue, pvItemToQueue, xTicksToWait );//插⼊队尾,和xQueueSendToBack函数效果⼀致// xQueue:队列句柄//PvItemToQueue:消息数据,会通过数据拷贝到队列中,如果想使⽤浅拷贝,则可以发送⼀个变量来存储要真正发送的缓冲区地址即可.// xTicksToWait:阻塞时间,单位为RTOS时钟滴答值,如果configTICK_RATE_HZ是1000,则填⼊的值表⽰阻塞的是多少ms,否则的话需要通过X/portTICK_RATE_MS来转换⼀下,才能实现阻塞Xms. //xTicksToWait==0:表⽰⼊队满了,则直接退出该函数// xTicksToWait==portMAX_DELAY:表⽰⼀直阻塞,直到队列有空位为⽌.//注意: INCLUDE_vTaskSuspend宏必须为1,否则任务⽆法进⼊休眠状态实现阻塞效果.//返回值: errQUEUE_FULL(队列已满) pdPASS(通过)xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait );//插⼊队头,参数和上⾯描述⼀致xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait );//插⼊队尾,参数和上⾯描述⼀致xQueueOverwrite( xQueue, pvItemToQueue );//将之前未出队的旧数据全部清空,然后再⼊队,该函数适⽤于长度为1的队列xQueueReceive( xQueue, pvBuffer, xTicksToWait );//从队列头部读出⼀个消息,并且这个消息会出队(删除掉)xQueuePeek( xQueue, pvBuffer, xTicksToWait );//从队列头部读出⼀个消息,但是这个消息不会出队(不会删除)PS:这些API函数只能⽤于任务⾥调⽤,如果要在中断服务函数中调⽤,则在函数名后添加FromQueue即可,⽐如xQueueSendFromQueue()函数6.5 中断发送/读取消息队列时,要注意的事情使⽤中断相关的读写队列相关的API时,第3个参数是不⼀样的,⽐如xQueueSendFromISR():PxHigherPriorityTaskWoken⽤来标记退出该函数后是否需要进⾏任务切换,因为我们发送队列时,有可能会将某个阻塞任务退出阻塞态,⽽此时⼜在中断中,所以当PxHigherPriorityTaskWoken为pdTRUE时,我们则必须进⾏⼀次任务切换.可以通过portYIELD_FROM_ISR()来进⾏任务切换,并且我们不需要去判断PxHigherPriorityTaskWoken是否为pdTRUE,因为该函数内部有判断的,如下图所⽰:来个中断函数发送队列⽰例:extern QueueHandle_t Message_Queue; //信息队列句柄void USART1_IRQHandler(void) //串⼝1中断服务程序{BaseType_t xHigherPriorityTaskWoken; //定义任务切换标志位if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){//处理中断接收数据}if (Message_Queue!=NULL) //判断Message_Queue是否已创建{xQueueSendFromISR(Message_Queue, RX_BUF,&xHigherPriorityTaskWoken);//向队列Message_Queue中发送RX_BUFportYIELD_FROM_ISR(xHigherPriorityTaskWoken);//通过portYIELD_FROM_ISR()判断是否需要切换任务}}PS:尽量将portYIELD_FROM_ISR()写在中断函数末尾处6.6⽰例-任务之间的伪代码按键任务向打印任务发送按键消息队列,代码如下:QueueHandle_t Key_Queue; //按键值消息队列句柄int main(){//...省略N⾏代码Key_Queue=xQueueCreate(1,sizeof(u8)); //创建消息Key_Queue,长度为1//创建两个任务:key_task()、print_task()//...省略N⾏代码}key_task() //获取按键值{ while(1) { key=KEY_Scan(0); //扫描按键 if((Key_Queue!=NULL)&&(key)) //消息队列Key_Queue创建成功,并且按键被按下 { err=xQueueSend(Key_Queue,&key,10); if(err==errQUEUE_FULL) //发送按键值 { printf("队列Key_Queue已满,数据发送失败!\r\n"); } } vTaskDelay(10); //延时10个时钟节拍 }}print_task() //打印按键值{ u8 key; while(1) { if(Key_Queue!=NULL) { if(xQueueReceive(Key_Queue,&key,portMAX_DELAY))//请求消息Key_Queue { printf("key=%d\r\n",key); } } vTaskDelay(10); //延时10个时钟节拍 }}7. RTOS软件定时器7.1简介在之前的任务创建的时候有讲到过,RTOS会⾃动创建⼀个优先级configMAX_PRIORITIES-1的软件定时器服务任务(管理定时器的).所以我们写⼀个定时器回调函数时,则会被该定时器服务任务调⽤,所以在我们软件定时器函数中不能使⽤vTaskDelay()阻塞之类的API函数,否则会将系统中的定时器服务函数给阻塞掉.7.2 FreeRTOSConfig.h相关的定时器配置#define configUSE_TIMERS 1 //为1时启⽤软件定时器#define configTIMER_TASK_PRIORITY 31 //设置软件定时器优先级可设置的值范围为0~31#define configTIMER_QUEUE_LENGTH 5 //软件定时器队列长度#define configTIMER_TASK_STACK_DEPTH 200 //设置每个软件定时器任务堆栈⼤⼩7.3定时创建相关APITimerHandle_t xTimerCreateStatic(const char * const pcTimerName, //定时器字符串别名 const TickType_t xTimerPeriodInTicks, //需要定时的周期值,⽐如通过200/ portTICK_RATE_MS来转换实现定时200毫秒 const UBaseType_t uxAutoReload, //是否重载(周期性/单次性),若为pdTRUE(1)表⽰为周期性,为pdFALSE(0)表⽰为单次 void * const pvTimerID, //定时器ID号,⼀般⽤于多个定时器共⽤⼀个定时器回调函数,否则填0即可 TimerCallbackFunction_t pxCallbackFunction);//定时器回调函数xTimerDelete( xTimer, xTicksToWait );//删除定时器//xTicksToWait:指定该定时器在多少时钟节拍数之前删除掉,为0则⽴即删除,⼀般设为100(如果设为0,则如果在该操作之前还有其它设置定时器操作的话,则不会进⾏阻塞等待,从⽽返回false)7.4 定时器其它常⽤APIxTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait );//修改定时器周期,在中断中则使⽤xTimerChangePeriodFromISR()// xNewPeriod:要修改的周期值//xTicksToWait:指定该定时器在多少时钟节拍数之前修改好,为0则⽴即删除//xTimerReset( xTimer, xTicksToWait );//复位定时器,让定时器重新计数,在中断中则使⽤xTimerResetFromISR()// xTicksToWait:和上⾯内容类似xTimerStart( xTimer, xTicksToWait );//启动定时器,如果定时器正在运⾏的话调⽤该函数的结果和xTimerReset()⼀样, 在中断中则使⽤xTimerResetFromISR ()xTimerStop( xTimer, xTicksToWait );//停⽌定时器, 在中断中则使⽤xTimerStopFromISR ()PS:在中断中使⽤定时器API时,同样和队列⼀样,也需要在函数末尾通过portYIELD_FROM_ISR()进⾏⼀次任务切换判断8. 信号量在项⽬中我们⼀般⽤⼆值信号量,⽤来同步数据的.⽐如任务A要向任务B发送⼀个很⼤的数据buf,⽽⽤队列的话会进⾏复制拷贝,从⽽占⽤⼤量时间.此时我们不妨定义⼀个全局数据buf,任务A修改这个buf,发送⼀个信号量给任务B,任务B就去读取这个全局数据buf即可.从⽽省去了队列复制拷贝的时间. 8.1定义信号量举例SemaphoreHandle_t BinarySemaphore; //⼆值信号量句柄BinarySemaphore=xSemaphoreCreateBinary(); //创建⼆值信号量8.2在中断中发送信号量过程BaseType_t xHigherPriorityTaskWoken;xSemaphoreGiveFromISR(BinarySemaphore,&xHigherPriorityTaskWoken);//发送⼆值信号量portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进⾏⼀次任务切换8.3在任务中发送信号量过程xSemaphoreGive(BinarySemaphore);//返回值: pdPASS(0, 表⽰发送成功,如果信号量⼀直未处理,则会返回值失败FULL)8.4 在任务中接收信号量过程err=xSemaphoreTake(BinarySemaphore,portMAX_DELAY); //获取信号量// portMAX_DELAY:进⼊阻塞态⼀直等待获取//返回值为pdTRUE(OK) pdFALSE(err)。

FreeRTOS原理与实现

FreeRTOS原理与实现

嵌入式操作系统FreeRTOS的原理与实现在嵌入式领域中,嵌入式实时操作系统正得到越来越广泛的应用。

采用嵌入式实时操作系统(RTOS)可以更合理、更有效地利用CPU的资源,简化应用软件的设计,缩短系统开发时间,更好地保证系统的实时性和可靠性。

由于RTOS需占用一定的系统资源(尤其是RAM资源),只有μC/OS-II、embOS、Salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。

相对于μC/OS-II、embOS等商业操作系统,FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。

1.FreeRTOS操作系统功能作为一个轻量级的操作系统,FreeRTOS提供的功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能等,可基本满足较小系统的需要。

FreeRTOS内核支持优先级调度算法,每个任务可根据重要程度的不同被赋予一定的优先级,CPU总是让处于就绪态的、优先级最高的任务先运行。

FreeRTOS内核同时支持轮换调度算法,系统允许不同的任务使用相同的优先级,在没有更高优先级任务就绪的情况下,同一优先级的任务共享CPU的使用时间。

FreeRTOS的内核可根据用户需要设置为可剥夺型内核或不可剥夺型内核。

当FreeRTOS被设置为可剥夺型内核时,处于就绪态的高优先级任务能剥夺低优先级任务的CPU使用权,这样可保证系统满足实时性的要求;当FreeRTOS被设置为不可剥夺型内核时,处于就绪态的高优先级任务只有等当前运行任务主动释放CPU的使用权后才能获得运行,这样可提高CPU的运行效率。

2.FreeRTOS操作系统的原理与实现2. 1任务调度机制的实现任务调度机制是嵌入式实时操作系统的一个重要概念,也是其核心技术。

对于可剥夺型内核,优先级高的任务一旦就绪就能剥夺优先级较低任务的CPU使用权,提高了系统的实时响应能力。

(2024年)FreeRTOS从入门到精通1

(2024年)FreeRTOS从入门到精通1

现已成为最受欢迎的嵌入式实 时操作系统之一
广泛应用于各种行业,包括汽 车、医疗、工业控制等
不断更新迭代,加入新功能和 优化性能
2024/3/26
5
主要特点与优势
可靠性
经过严格测试和验 证,具有高度的稳 定性
开放性
源代码公开,易于 学习和定制
2024/3/26
实时性
提供可预测的响应 时间,适合对时间 要求严格的应用
安装必要的驱动程序和组件
如串口驱动、JTAG驱动等,确保电脑与开发板正常 通信。
15
第一个FreeRTOS程序示例
创建FreeRTOS工程
在IDE中创建一个新的FreeRTOS工程,并配置相关参数。
编写任务代码
创建多个任务,并编写相应的任务处理函数,实现任务间的切换和通信。
编译和下载程序
将编写好的代码编译成可执行文件,并下载到开发板中进行测试。
功耗管理策略
分享多种功耗管理策略,如动态调 整系统时钟、关闭未使用外设、使 用低功耗模式等,降低系统功耗。
2024/3/26
功耗管理API介绍
介绍FreeRTOS提供的功耗管理相 关API,如tickless模式、低功耗模 式切换等,方便开发者进行功耗优
化。
功耗管理实践案例
分享在FreeRTOS中进行功耗优化 的实践案例,包括硬件平台选择、 软件架构设计、功耗测试方法等,
2024/3/26
备份和恢复
设计备份和恢复机制,确保系统数据安全和 可恢复性。
31
企业级应用部署注意事项
硬件兼容性
确保FreeRTOS与目标硬件兼容,充分发挥 硬件性能。
可扩展性规划
考虑系统未来扩展需求,设计可扩展的架构 和接口。

深入理解FreeRTOS的任务机制和消息队列+附完整项目代码

深入理解FreeRTOS的任务机制和消息队列+附完整项目代码
--uxTopReadyPriority; //得到最高优先级数
}
listGET_OWNER_OF_NEXT_ENTRY(pxCurrentTCB,&( pxReadyTasksLists[ uxTopReadyPriority ] ) ); // pxCurrentTCB指向最高优先级任务
//抢占同一优先级的下一个任务。
4.消息队列:
FreeRTOS中消息队列是任务间数据交换的常用手段(中断服务程序同样使用队列来通信与同步),消息队列是生产者消费者模型的重要组成部分
消息队列的数据结构如下:
typedef struct QueueDefinition
{
signed char *pcHead;//队头
signed char *pcTail;//队尾
任务一向消息队列填充数字,任务二从消息队列提取数据并发送到串口1,同时有LED灯跟随数据传送亮灭。
下载地址:
STM32搭载RTOS实现任务+消息队列+串口通信完整项目代码
主要讲讲任务和消息队列
1.任务控制模块(TCB被创建,并放入就绪列表。就绪列表是一个双向链表,在链表中每个任务按优先级排列,并且设置有记录相关信息的变量和进行各种操作的指针。
2.任务优先级
RTOS的基本工作单元是任务,所有任务都有一个用户优先级,如:从0到最高,如:0(最低),1,2,3 (最高) 在FreeRTOSConfig.h中设置优先级个数。
signed char *pcWriteTo;
signed char *pcReadFrom;
xList xTasksWaitingToSend;//等待发送的任务列表
xList xTasksWaitingToReceive;//等待接收的任务列表

freertos的课程设计

freertos的课程设计

freertos的课程设计一、教学目标本课程旨在让学生了解和掌握FreeRTOS实时操作系统的基本原理和应用方法。

通过本课程的学习,学生将能够:1.理解实时操作系统的基本概念,包括任务、调度、同步等。

2.掌握FreeRTOS的关键特性,如多任务、抢占式调度、时间管理、内存管理等。

3.能够运用FreeRTOS进行嵌入式系统的开发,实现实时任务的管理和调度。

4.培养学生的动手实践能力和团队协作精神,提高他们解决实际问题的能力。

二、教学内容本课程的教学内容主要包括以下几个部分:1.实时操作系统基础:介绍实时操作系统的概念、特点和应用领域,让学生了解实时操作系统的基本原理。

2.FreeRTOS概述:讲解FreeRTOS的核心功能、架构和关键特性,使学生对FreeRTOS有一个整体的认识。

3.FreeRTOS编程:详细讲解FreeRTOS的编程接口,包括任务创建、任务调度、事件处理等,让学生能够熟练使用FreeRTOS进行编程。

4.嵌入式系统设计:介绍如何使用FreeRTOS设计嵌入式系统,包括硬件选择、系统架构设计、驱动开发等,帮助学生掌握嵌入式系统的设计方法。

5.实践项目:安排学生进行实践项目,让学生将所学知识应用到实际项目中,提高他们的动手实践能力。

三、教学方法为了提高教学效果,本课程将采用多种教学方法相结合的方式进行教学:1.讲授法:讲解实时操作系统和FreeRTOS的基本概念、原理和编程方法。

2.案例分析法:分析典型的嵌入式系统设计案例,让学生了解FreeRTOS在实际项目中的应用。

3.实验法:安排学生进行实验,让学生动手实践,加深对FreeRTOS的理解。

4.讨论法:学生进行课堂讨论,鼓励学生提问、发表见解,提高他们的思考和表达能力。

四、教学资源为了支持本课程的教学,我们将准备以下教学资源:1.教材:选用权威、实用的FreeRTOS教材,为学生提供系统的学习资料。

2.参考书:提供相关的嵌入式系统设计和实时操作系统方面的参考书,丰富学生的知识体系。

FreeRTOS详解

FreeRTOS详解

Selecting the API to Use∙Only those API functions specifically designated for use from within an ISR should be used from within an ISR.∙Tasks and co-routines use different API functions to access queues.A queue cannot be used to communicate between a task and a co-routineor visa versa.∙Intertask communication can be achieved using the full featured API functions, the alternative API functions, and the light weight API functions (those with "FromISR" in their name).∙Use of the light weight functions outside of an ISR requires special consideration, as described under the heading "Performance tips and tricks - using the light weight API".Task APIA task may call any API function listed in the menu frame on the left other than those under the co-routine specific section.Co-Routine APIIn addition to the API functions listed under the co-routine specific section, a co-routine may use the following API calls.∙taskYIELD() - will yield the task in which the co-routines are running.∙taskENTER_CRITICAL().∙taskEXIT_CRITICAL().∙vTaskStartScheduler() - this is still used to start the scheduler even if the application only includes co-routines and no tasks.∙vTaskSuspendAll() - can still be used to lock the scheduler.∙xTaskResumeAll()∙xTaskGetTickCount()∙uxTaskGetNumberOfTasks()Customisation[Configuration]A number of configurable parameters exist that allow the FreeRTOS kernel to be tailored to your particular application. These items are located in a file called FreeRTOSConfig.h. Each demo application included in the FreeRTOS source code download has its own FreeRTOSConfig.h file. Here is a typical example, followed by an explanation of each parameter:#ifndef FREERTOS_CONFIG_H#define FREERTOS_CONFIG_H/* Here is a good place to include header files that are required across your application. */#include "something.h"#define configUSE_PREEMPTION 1#define configUSE_IDLE_HOOK 0#define configUSE_TICK_HOOK 0#define configCPU_CLOCK_HZ 58982400#define configTICK_RATE_HZ 250#define configMAX_PRIORITIES 5#define configMINIMAL_STACK_SIZE 128#define configTOTAL_HEAP_SIZE 10240#define configMAX_TASK_NAME_LEN 16#define configUSE_TRACE_FACILITY 0#define configUSE_16_BIT_TICKS 0#define configIDLE_SHOULD_YIELD 1#define configUSE_MUTEXES 0#define INCLUDE_vTaskPrioritySet 1#define INCLUDE_uxTaskPriorityGet 1#define INCLUDE_vTaskDelete 1#define INCLUDE_vTaskCleanUpResources 0#define INCLUDE_vTaskSuspend 1#define INCLUDE_vResumeFromISR 1#define INCLUDE_vTaskDelayUntil 1#define INCLUDE_vTaskDelay 1#define INCLUDE_xTaskGetSchedulerState 1#define INCLUDE_xTaskGetCurrentTaskHandle 1#define configUSE_CO_ROUTINES 0#define configMAX_CO_ROUTINE_PRIORITIES 1#define configKERNEL_INTERRUPT_PRIORITY [dependent of processor] #endif /* FREERTOS_CONFIG_H */'config' ParametersconfigUSE_PREEMPTIONSet to 1 to use the preemptive kernel, or 0 to use the cooperative kernel.configUSE_IDLE_HOOKSet to 1 if you wish to use an idle hook, or 0 to omit an idle hook.configUSE_TICK_HOOKSet to 1 if you wish to use an tick hook, or 0 to omit an tick hook.configCPU_CLOCK_HZEnter the frequency in Hz at which the internal processor core will be executing. This value is required in order to correctly configure timer peripherals.configTICK_RATE_HZThe frequency of the RTOS tick interrupt.The tick interrupt is used to measure time. Therefore a higher tick frequency means time can be measured to a higher resolution. However, a high tick frequency also means that the kernel will use more CPU time so be less efficient. The RTOS demo applications all use a tick rate of 1000Hz. This is used to test the kernel and is higher than would normally be required.More than one task can share the same priority. The kernel will share processor time between tasks of the same priority by switching between the tasks during each RTOS tick. A high tick rate frequency will therefore also have the effect of reducing the 'time slice' given to each task.configMAX_PRIORITIESThe number of priorities available to the application tasks. Any number of tasks can share the same priority. Co-routines are prioritised separately - see configMAX_CO_ROUTINE_PRIORITIES.Each available priority consumes RAM within the kernel so this value should not be set any higher than actually required by your application. configMINIMAL_STACK_SIZEThe size of the stack used by the idle task. Generally this should not be reduced from the value set in the FreeRTOSConfig.h file provided with the demo application for the port you are using.configTOTAL_HEAP_SIZEThe total amount of RAM available to the kernel.This value will only be used if your application makes use of one of the sample memory allocation schemes provided in the FreeRTOS source code download. See the memory configuration section for further details.configMAX_TASK_NAME_LENThe maximum permissible length of the descriptive name given to a task when the task is created. The length is specified in the number of characters including the NULL termination byte.configUSE_TRACE_FACILITYSet to 1 if you wish the trace visualisation functionality to be available, or 0 if the trace functionality is not going to be used. If you use the trace functionality a trace buffer must also be provided.configUSE_16_BIT_TICKSTime is measured in 'ticks' - which is the number of times the tick interrupt has executed since the kernel was started. The tick count is held in a variable of type portTickType.Defining configUSE_16_BIT_TICKS as 1 causes portTickType to be defined (typedef'ed) as an unsigned 16bit type. Defining configUSE_16_BIT_TICKS as 0 causes portTickType to be defined (typedef'ed) as an unsigned 32bit type. Using a 16 bit type will greatly improve performance on 8 and 16 bit architectures, but limits the maximum specifiable time period to 65535 'ticks'. Therefore, assuming a tick frequency of 250Hz, the maximum time a task can delay or block when a 16bit counter is used is 262 seconds, compared to 17179869 seconds when using a 32bit counter.configIDLE_SHOULD_YIELDThis parameter controls the behaviour of tasks at the idle priority. It only has an effect if:1. The preemptive scheduler is being used.2. The users application creates tasks that run at the idle priority.T asks that share the same priority will time slice. Assuming none of the tasks get preempted, it might be assumed that each task of at a given priority will be allocated an equal amount of processing time - and if the shared priority is above the idle priority then this is indeed the case.When tasks share the idle priority the behaviour can be slightly different. When configIDLE_SHOULD_YIELD is set to 1 the idle task will yield immediately should any other task at the idle priority be ready to run. This ensures the minimum amount of time is spent in the idle task when application tasks are available for scheduling. This behaviour can however have undesirable effects (depending on the needs of your application) as depicted below:This diagram shows the execution pattern of four tasks at the idle priority. Tasks A, B and C are application tasks. Task I is the idle task. A context switch occurs with regular period at times T0, T1, ..., T6. When the idle task yields task A starts to execute - but the idle task has already taken up some of the current time slice. This results in task I and task A effectively sharing a time slice. The application tasks B and C therefore get more processing time than the application task A.This situation can be avoided by:∙If appropriate, using an idle hook in place of separate tasks at the idle priority.∙Creating all application tasks at a priority greater than the idle priority.∙Setting configIDLE_SHOULD_YIELD to 0.Setting configIDLE_SHOULD_YIELD prevents the idle task from yielding processing time until the end of its time slice. This ensure all tasks at the idle priority are allocated an equal amount of processing time - but at the cost of a greater proportion of the total processing time being allocated to the idle task.configUSE_USE_MUTEXESSet to 1 to include mutex functionality in the build, or 0 to omit mutex functionality from the build. Readers should familiarise themselves with the differences between mutexes and binary semaphores in relation to the functionality.configUSE_CO_ROUTINESSet to 1 to include co-routine functionality in the build, or 0 to omit co-routine functionality from the build. To include co-routines croutine.c must be included in the project.configMAX_CO_ROUTINE_PRIORITIESThe number of priorities available to the application co-routines. Any number of co-routines can share the same priority. T asks are prioritised separately - see configMAX_PRIORITIES.configKERNEL_INTERRUPT_PRIORITYCurrently only in Cortex-M3/IAR, PIC24 and dsPIC ports. Other ports will get upgraded shortly. This sets the interrupt priority used by the kernel. The kernel should use a low interrupt priority, allowing higher priority interrupts to be unaffected by the kernel entering critical sections. Instead of critical sections globally disabling interrupts, they only disable interrupts that are below the kernel interrupt priority.This permits very flexible interrupt handling:∙At the kernel priority level interrupt handling 'tasks' can be written and prioritised as per any other task in the system. These are tasks that are woken by aninterrupt. The interrupt service routine (ISR) itself should be written to be as short as it possibly can be - it just grabs the data then wakes the high priority handlertask. The ISR then returns directly into the woken handler task - so interruptprocessing is contiguous in time just as if it were all done in the ISR itself. Thebenefit of this is that all interrupts remain enabled while the handler task executes.∙ISR's running above the kernel priority are never masked out by the kernel itself, so their responsiveness is not effected by the kernel functionality. However, such ISR's cannot use the API functions.T o utilize this scheme your application design must adhere to the following rule: Any interrupt that uses the API must be set to the same priority as the kernel (as configured by the configKERNEL_INTERRUPT_PRIORITY macro).INCLUDE ParametersThe macros starting 'INCLUDE' allow those components of the real time kernel not utilized by your application to be excluded from your build. This ensures the RTOS does not use any more ROM or RAM than necessary for your particular embedded application.Each macro takes the form ...INCLUDE_FunctionName... where FunctionName indicates the API function (or set of functions) that can optionally be excluded. To include the API function set the macro to 1, to exclude the function set the macro to 0. For example, to include the vT askDelete() API function use:#define INCLUDE_vTaskDelete 1To exclude vTaskDelete() from your build use:#define INCLUDE_vTaskDelete 0Memory Management[Configuration]The RTOS kernel has to allocate RAM each time a task, queue or semaphore is created. The malloc() and free() functions can sometimes be used for this purpose, but ...1. they are not always available on embedded systems,2. take up valuable code space,3. are not thread safe, and4. are not deterministic (the amount of time taken to execute the function will differfrom call to call)... so more often than not an alternative scheme is required.One embedded / real time system can have very different RAM and timing requirements to another - so a single RAM allocation algorithm will only ever be appropriate for a subset of applications.To get around this problem the memory allocation API is included in the RTOS portable layer - where an application specific implementation appropriate for the real time system being developed can be provided. When the real time kernel requires RAM, instead of calling malloc() it makes a call to pvPortMalloc(). When RAM is being freed, instead of calling free() the real time kernel makes a call to vPortFree().Schemes included in the source code downloadThree sample RAM allocation schemes are included in the FreeRTOS source code download (V2.5.0 onwards). These are used by the various demo applications as appropriate. The following subsections describe the available schemes, when they should be used, and highlight the demo applications that demonstrate their use.Each scheme is contained in a separate source file (heap_1.c, heap_2.c and heap_3.c respectively) which can be located in the Source/Portable/MemMang directory. Other schemes can be added if required.Scheme 1 - heap_1.cThis is the simplest scheme of all. It does not permit memory to be freed once it has been allocated, but despite this is suitable for a surprisingly large number of applications.The algorithm simply subdivides a single array into smaller blocks as requests for RAM are made. The total size of the array is set by the definition configTOTAL_HEAP_SIZE - which is defined in FreeRTOSConfig.h.This scheme:∙Can be used if your application never deletes a task or queue (no calls to vT askDelete() or vQueueDelete() are ever made).∙Is always deterministic (always takes the same amount of time to return a block).∙Is used by the PIC, AVR and 8051 demo applications - as these do not dynamically create or delete tasks after vT askStartScheduler() has been called.heap_1.c is suitable for a lot of small real time systems provided that all tasks and queues are created before the kernel is started.Scheme 2 - heap_2.cThis scheme uses a best fit algorithm and, unlike scheme 1, allows previously allocated blocks to be freed. It does not however combine adjacent free blocks into a single large block.Again the total amount of available RAM is set by the definition configTOTAL_HEAP_SIZE - which is defined in FreeRTOSConfig.h.This scheme:∙Can be used even when the application repeatedly callsvT askCreate()/vT askDelete() or vQueueCreate()/vQueueDelete() (causingmultiple calls to pvPortMalloc() and vPortFree()).∙Should not be used if the memory being allocated and freed is of a random size - this would only be the case if tasks being deleted each had a different stack depth, or queues being deleted were of different lengths.∙Could possible result in memory fragmentation problems should your application create blocks of queues and tasks in an unpredictable order. This would beunlikely for nearly all applications but should be kept in mind.∙Is not deterministic - but is also not particularly inefficient.∙Is used by the ARM7, and Flashlite demo applications - as these dynamically create and delete tasks.heap_2.c is suitable for most small real time systems that have to dynamically create tasks.Scheme 3 - heap_3.cThis is just a wrapper for the standard malloc() and free() functions. It makes them thread safe.This scheme:∙Requires the linker to setup a heap, and the compiler library to provide malloc() and free() implementations.∙Is not deterministic.∙Will probably considerably increase the kernel code size.∙Is used by the PC (x86 single board computer) demo application.Task Creation[API] Modules∙xT askCreate∙vT askDeleteDetailed DescriptionxTaskHandletask. hType by which tasks are referenced. For example, a call to xTaskCreate returns (via a pointer parameter) an xTaskHandle variable that can then be used as a parameter to vTaskDelete to delete the taskxTaskCreate[Task Creation]task. hportBASE_TYPE xTaskCreate(pdTASK_CODE pvTaskCode,const portCHAR * const pcName,unsigned portSHORT usStackDepth,void *pvParameters,unsigned portBASE_TYPE uxPriority,xTaskHandle *pvCreatedTask);Create a new task and add it to the list of tasks that are ready to run.Parameters:pvTaskCode Pointer to the task entry function. Tasks must be implemented to never return (i.e. continuous loop).pcName A descriptive name for the task. This is mainly used to facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN.usStackDepth The size of the task stack specified as the number of variables the stack can hold - not the number of bytes. For example, if the stack is 16 bitswide and usStackDepth is defined as 100, 200 bytes will be allocated forstack storage. The stack depth multiplied by the stack width must notexceed the maximum value that can be contained in a variable of typesize_t.pvParameters Pointer that will be used as the parameter for the task being created.uxPriority The priority at which the task should run.pvCreatedTask Used to pass back a handle by which the created task can be referenced. Returns:pdPASS if the task was successfully created and added to a ready list, otherwise an error code defined in the file projdefs. hExample usage:// Task to be created.void vTaskCode( void * pvParameters ){for( ;; ){// Task code goes here.}}// Function that creates a task.void vOtherFunction( void ){unsigned char ucParameterToPass;xTaskHandle xHandle;// Create the task, storing the handle.xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );// Use the handle to delete the task.vTaskDelete( xHandle );}vTaskDelete[Task Creation]task. hvoid vTaskDelete( xTaskHandle pxTask );INCLUDE_vTaskDelete must be defined as 1 for this function to be available. See the configuration section for more information.Remove a task from the RTOS real time kernels management. The task being deleted will be removed from all ready, blocked, suspended and event lists.NOTE: The idle task is responsible for freeing the kernel allocated memory from tasks that have been deleted. It is therefore important that the idle task is not starved of microcontroller processing time if your application makes any calls to vTaskDelete (). Memory allocated by the task code is not automatically freed, and should be freed before the task is deleted.See the demo application file death. c for sample code that utilises vTaskDelete ().Parameters:pxTask The handle of the task to be deleted. Passing NULL will cause the calling task to be deleted.Example usage:void vOtherFunction( void ){xTaskHandle xHandle;// Create the task, storing the handle.xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );// Use the handle to delete the task.vTaskDelete( xHandle );}vTaskDelay[Task Control]task. hvoid vTaskDelay( portTickType xTicksToDelay );INCLUDE_vTaskDelay must be defined as 1 for this function to be available. See the configuration section for more information.Delay a task for a given number of ticks. The actual time that the task remains blocked depends on the tick rate. The constant portTICK_RATE_MS can be used to calculate real time from the tick rate - with the resolution of one tick period.Parameters:xTicksToDelay The amount of time, in tick periods, that the calling task should block. Example usage:// Perform an action every 10 ticks.// NOTE:// This is for demonstration only and would be better achieved// using vTaskDelayUntil().void vTaskFunction( void * pvParameters ){portTickType xDelay, xNextTime;// Calc the time at which we want to perform the action// next.xNextTime = xTaskGetTickCount () + ( portTickType ) 10;for( ;; ){xDelay = xNextTime - xTaskGetTickCount ();xNextTime += ( portTickType ) 10;// Guard against overflowif( xDelay <= ( portTickType ) 10 ){vTaskDelay( xDelay );}// Perform action here.}}vTaskDelayUntil[Task Control]task. hvoid vTaskDelayUntil( portTickType *pxPreviousWakeTime, portTickType xTimeIncrement );INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. See the configuration section for more information.Delay a task until a specified time. This function can be used by cyclical tasks to ensure a constant execution frequency.This function differs from vTaskDelay() in one important aspect: vTaskDelay() specifies a time at which the task wishes to unblock relative to the time at which vTaskDelay() is called, whereas vTaskDelayUntil() specifies an absolute time at which the task wishes to unblock.vTaskDelay() will cause a task to block for the specified number of ticks from the time vTaskDelay() is called. It is therefore difficult to use vTaskDelay() by itself to generate a fixed execution frequency as the time between a task unblocking following a call to vTaskDelay() and that task next calling vTaskDelay() may not be fixed [the task may take a different path though the code between calls, or may get interrupted or preempted a different number of times each time it executes].Whereas vTaskDelay() specifies a wake time relative to the time at which the function is called, vTaskDelayUntil() specifies the absolute (exact) time at which it wishes to unblock.It should be noted that vTaskDelayUntil() will return immediately (without blocking) if it is used to specify a wake time that is already in the past. Therefore a task using vTaskDelayUntil() to execute periodically will have to re-calculate its required wake time if the periodic execution is halted for any reason (for example, the task is temporarily placed into the Suspended state) causing the task to miss one or more periodic executions. This can be detected by checking the variable passed by reference as the pxPreviousWakeTime parameter against the current tick count. This is however not necessary under most usage scenarios.The constant portTICK_RATE_MS can be used to calculate real time from the tick rate - with the resolution of one tick period.Parameters:pxPreviousWakeTime Pointer to a variable that holds the time at which the task was lastunblocked. The variable must be initialised with the current timeprior to its first use (see the example below). Following this thevariable is automatically updated within vTaskDelayUntil().xTimeIncrement The cycle time period. The task will be unblocked at time(*pxPreviousWakeTime + xTimeIncrement). CallingvTaskDelayUntil with the same xTimeIncrement parameter valuewill cause the task to execute with a fixed interval period. Example usage:// Perform an action every 10 ticks.void vTaskFunction( void * pvParameters ){portTickType xLastWakeTime;const portTickType xFrequency = 10;// Initialise the xLastWakeTime variable with the current time. xLastWakeTime = xTaskGetTickCount();for( ;; ){// Wait for the next cycle.vTaskDelayUntil( &xLastWakeTime, xFrequency );// Perform action here.}}uxTaskPriorityGet[Task Control]task. hunsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask ); INCLUDE_vTaskPriorityGet must be defined as 1 for this function to be available. See the configuration section for more information.Obtain the priority of any task.Parameters:pxTask Handle of the task to be queried. Passing a NULL handle results in the priority of the calling task being returned.Returns:The priority of pxT ask.Example usage:void vAFunction( void ){xTaskHandle xHandle;// Create a task, storing the handle.xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );// ...// Use the handle to obtain the priority of the created task.// It was created with tskIDLE_PRIORITY, but may have changed// it itself.if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY ){// The task has changed it's priority.}// ...// Is our priority higher than the created task?if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) ){// Our priority (obtained using NULL handle) is higher.}}vTaskPrioritySet[Task Control]task. hvoid vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. See the configuration section for more information.Set the priority of any task.A context switch will occur before the function returns if the priority being set is higher than the currently executing task.Parameters:pxTask Handle to the task for which the priority is being set. Passing a NULLhandle results in the priority of the calling task being set.uxNewPriority The priority to which the task will be set.Example usage:void vAFunction( void ){xTaskHandle xHandle;// Create a task, storing the handle.xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );// ...// Use the handle to raise the priority of the created task.vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );// ...// Use a NULL handle to raise our priority to the same value.vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );}vTaskSuspend[Task Control]task. hvoid vTaskSuspend( xTaskHandle pxTaskToSuspend );INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. See the configuration section for more information.Suspend any task. When suspended a task will never get any microcontroller processing time, no matter what its priority.Calls to vTaskSuspend are not accumulative - i.e. calling vTaskSuspend () twice on the same task still only requires one call to vTaskResume () to ready the suspended task.Parameters:pxTaskToSuspend Handle to the task being suspended. Passing a NULL handle will causethe calling task to be suspended.Example usage:void vAFunction( void ){xTaskHandle xHandle;// Create a task, storing the handle.xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );// ...// Use the handle to suspend the created task.vTaskSuspend( xHandle );// ...// The created task will not run during this period, unless// another task calls vTaskResume( xHandle ).//...// Suspend ourselves.vTaskSuspend( NULL );// We cannot get here unless another task calls vTaskResume// with our handle as the parameter.}vTaskResume[Task Control]task. hvoid vTaskResume( xTaskHandle pxTaskToResume );INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. See the configuration section for more information.Resumes a suspended task.A task that has been suspended by one of more calls to vTaskSuspend () will be made available for running again by a single call to vTaskResume ().Parameters:pxTaskToResume Handle to the task being readied.Example usage:void vAFunction( void ){xTaskHandle xHandle;// Create a task, storing the handle.xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );// ...// Use the handle to suspend the created task.vTaskSuspend( xHandle );// ...// The created task will not run during this period, unless// another task calls vTaskResume( xHandle ).//...// Resume the suspended task ourselves.vTaskResume( xHandle );// The created task will once again get microcontroller processing // time in accordance with it priority within the system.}vTaskResumeFromISR[Task Control]task. hportBASE_TYPE vTaskResumeFromISR( xTaskHandle pxTaskToResume ); INCLUDE_vTaskSuspend and INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be available. See the configuration section for more information.A function to resume a suspended task that can be called from within an ISR.A task that has been suspended by one of more calls to vTaskSuspend() willbe made available for running again by a single call to xTaskResumeFromISR().。

【FreeRTOS操作系统教程】第8章 FreeRTOS调试方法(打印任务执行情况)

【FreeRTOS操作系统教程】第8章  FreeRTOS调试方法(打印任务执行情况)
else if (TIMx == TIM5) irq = TIM5_IRQn;
2016年06月30日
版本:1.0
第 3 页 共 22 页
武汉安富莱电子有限公司
else if (TIMx == TIM6) irq = TIM6_IRQn;
else if (TIMx == TIM7) irq = TIM7_IRQn;
//PCLK2 = HCLK RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
//PCLK1 = HCLK RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM7, TIM12, TIM13,TIM14 APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
1
#define configGENERATE_RUN_TIME_STATS
1
#define configUSE_STATS_FORMATTING_FUNCTIONS
1
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() (ulHighFrequencyTimerTicks = 0ul)
#include <stdint.h> extern volatile uint32_t ulHighFrequencyTimerTicks; #endif
/* Run time and task stats gathering related definitions. */
#define configUSE_TRACE_FACILITY

FreeRTOS实时内核使用指南-中文

FreeRTOS实时内核使用指南-中文

当任务创建时,内核会分为每个任务分配属于任务自己的唯一状态。 usStackDepth 值用于告诉内核为它分配多大的栈空间。
这个值指定的是栈空间可以保存多少个字(word),而不是多少个字 节(byte)。比如说,如果是 32 位宽的栈空间,传入的 usStackDepth 值为 100,则将会分配 400 字节的栈空间(100 * 4bytes)。栈深度乘 以栈宽度的结果千万不能超过一个 size_t 类型变量所能表达的最大 值。
大多数嵌入式系统不仅能满足硬实时要求,也能满足软实时要求。
FreeRTOS
4
Designed For Microcontrollers;
© 2009 Richard Barry. Distribution or publication in any form is strictly prohibited.
xTaskCreate() API 函数 创建任务使用 FreeRTOS 的 API 函数 xTaskCreate()。这可能是所有 API 函数中最
复杂的函数,但不幸的是这也是我们第一个遇到的 API 函数。但我们必须首先掌控任务, 因为它们是多任务系统中最基本的组件。本书中的所有示例程序都会用到 xTaskCreate(),所以会有大量的例子可以参考。
仅仅从单处理器运行多线程这一点来说,实时嵌入式系统中的多任务与桌面电脑的 多任务从概念上来讲是相似的。但实时嵌入式系统的侧重点却不同于桌面电脑——特别 是当嵌入式系统期望提供”硬实时”行为的时候。
硬实时功能必须在给定的时间限制之内完成——如果无法做到即意味着整个系统 的绝对失败。汽车的安全气囊触发机制就是一个硬实时功能的例子。安全气囊在撞击发 生后给定时间限制内必须弹出。如果响应时间超出了这个时间限制,会使得驾驶员受到 伤害,而这原本是可以避免的。

[FreeRTOS入门]1.CubeMX中FreeRTOS配置参数及理解

[FreeRTOS入门]1.CubeMX中FreeRTOS配置参数及理解

[FreeRTOS⼊门]1.CubeMX中FreeRTOS配置参数及理解1.有关优先级 1.1 Configuration --> FreeRTOSMAX_PRIORITIES 设置任务优先级的数量:配置应⽤程序有效的优先级数⽬。

任何数量的任务都可以共享⼀个优先级,使⽤协程可以单独的给与它们优先权。

见MAX_CO_ROUTINE_PRIORITIES。

在RTOS内核中,每个有效优先级都会消耗⼀定量的RAM,因此这个值不要超过你的应⽤实际需要的优先级数⽬。

每⼀个任务都会被分配⼀个优先级,优先级值从0~(MAX_PRIORITIES - 1)之间。

低优先级数表⽰低优先级任务。

空闲任务的优先级为0(PriorityIdle),因此它是最低优先级任务。

FreeRTOS调度器将确保处于就绪状态(Ready)或运⾏状态(Running)的⾼优先级任务⽐同样处于就绪状态的低优先级任务优先获取处理器时间。

换句话说,处于运⾏状态的任务永远是⾼优先级任务。

处于就绪状态的相同优先级任务使⽤时间⽚调度机制共享处理器时间。

Interrupt nesting behaviour configuration 断⾔配置LIBRARY_LOWEST_INTERRUPT_PRIORITY此宏定义是⽤来配置 FreeRTOS中⽤到的SysTick中断和PendSV中断的优先级reeRTOSreeRTOSreeRTOSreeRTOS ⽤到的 SysTSysT ick 中断和 PendSV中断的优先级。

在 NVIC分组设置为4的情况下,此宏定义的范围就是 0-15 ,即专门配置抢占优先级。

这⾥即专门配置抢占优先级。

这⾥配置为了 15,即 SysTick和 PendSV 都配配置为了最低优先级,实际项⽬中也建议配置为最低优先级。

LIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY定义了受FreeRTOS管理的最⾼优先级中断。

笔记:FreeRTOS要点总结

笔记:FreeRTOS要点总结

笔记:FreeRTOS要点总结⼀、基本配置1.1 数据类型FreeRTOS 使⽤的数据类型主要分为 stdint.h ⽂件中定义的和⾃⼰定义的两种FreeRTOS 主要⾃定义了以下四种数据类型:TickType_t----32 位⽆符号数( 32位MCU,配置configUSE_16_BIT_TICKS = 0)BaseType_t----32 位有符号数(32位MCU)UBaseType_t---32 位⽆符号数(BaseType_t类型⽆符号版本)StackType_t----32 位变量(栈变量数据类型定义,32位MCU)1.2 代码风格变量uint32_t 定义的变量都加上前缀 ul。

u 代表 unsigned ⽆符号,l 代表 long 长整型。

uint16_t 定义的变量都加上前缀 us。

u 代表 unsigned ⽆符号,s 代表 short 短整型。

uint8_t 定义的变量都加上前缀 uc。

u 代表 unsigned ⽆符号,c 代表 char 字符型。

stdint.h ⽂件中未定义的变量类型,在定义变量时需要加上前缀 x,⽐如 BaseType_t 和TickType_t 定义的变量。

stdint.h ⽂件中未定义的⽆符号变量类型,在定义变量时要加上前缀 u,⽐如 UBaseType_t 定义的变量要加上前缀 ux。

size_t 定义的变量也要加上前缀 ux。

枚举变量会加上前缀 e。

指针变量会加上前缀 p,⽐如 uint16_t 定义的指针变量会加上前缀 pus。

根据 MISRA 代码规则,char 定义的变量只能⽤于 ASCII 字符,前缀使⽤ c。

根据 MISRA 代码规则,char *定义的指针变量只能⽤于 ASCII 字符串,前缀使⽤ pc。

函数加上了 static 声明的函数,定义时要加上前缀 prv,这个是单词 private 的缩写。

带有返回值的函数,根据返回值的数据类型,加上相应的前缀,如果没有返回值,即 void 类型,函数的前缀加上字母 v。

RTOS操作系统讲解--FreeRTOS

RTOS操作系统讲解--FreeRTOS

RTOS操作系统讲解--FreeRTOS一、操作系统背景讲解操作系统有实时操作系统和分时操作系统。

通常使用的实时操作系统(RTOS)有如MQXLite、MQX、FreeRTOS、uCOS-III、uCLinux、VxWorks、eCos实时操作系统:在一定时间限制内完成特定功能,并控制所有实时任务协调一致工作的操作系统,提供及时响应并具备高可靠性。

实时操作系统分为两种,硬实时(规定时间内完成操作),软实时(按照任务优先级完成操作)。

特征:多任务、有线程优先级、多种中断级别。

使用非实时嵌入式操作系统,例分时操作系统(Time-sharing Operating System),如Android、Linxu、iOS、Windows CE分时操作系统:将系统处理机时间和内存空间按照一定的时间间隔,轮流地切换给各终端用户的程序使用。

特征:交互性、多路性、独立性、及时性。

那么实时操作系统和分时操作系统的主要区别的第一性是什么呢?本质就在于设计操作系统的时候,架构机制必须支持是否需要在特定的时间内完成某项任务。

if yes,real-time os,otherwise no.英文称Real Time Operating System,简称RTOS。

二、实时操作系统讲解1.实时操作系统定义实时操作系统(RTOS)是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的操作系统。

因而,提供及时响应和高可靠性是其主要特点。

实时操作系统有硬实时和软实时之分,硬实时要求在规定的时间内必须完成操作,这是在操作系统设计时保证的;软实时则只要按照任务的优先级,尽可能快地完成操作即可。

我们通常使用的操作系统在经过一定改变之后就可以变成实时操作系统。

实时操作系统是保证在一定时间限制内完成特定功能的操作系统。

例如,可以为确保生产线上的机器人能获取某个物体而设计一个操作系统。

【FreeRTOS操作系统教程】第15章 FreeRTOS临界段和开关中断

【FreeRTOS操作系统教程】第15章   FreeRTOS临界段和开关中断

接下来继续说明开关中断的实现,我们要打破砂锅问到底:
#define portDISABLE_INTERRUPTS()
vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS()
vPortSetBASEPRI( 0 )
函数 vPortRaiseBASEPRI 和 vPortSetBASEPRI 的源码实现如下:
是因为直接的开关中断方式不支持在开关中断之间的代码里再次执行开关中断的嵌套处理,假如当前我们
2016年06月30日
版本:1.0
第 2 页 共 34 页
武汉安富莱电子有限公司
安富莱 STM32-V6 开发板 FreeRTOS 教程
的代码是关闭中断的,嵌套了一个含有开关中断的临界区代码后,退出时中断就成开的了,这样就出问题
使用举例:
使用的时候一定要保证成对使用
/* ********************************************************************************************************* * 函 数 名: vTaskLED * 功能说明: LED 闪烁和串口打印 * 形 参: pvParameters 是在创建该任务时传递的形参 * 返 回 值: 无 * 优 先 级: 2 ********************************************************************************************************* */ static void vTaskLED(void *pvParameters) {
函数调用开关中断函数 portENABLE_INTERRUPTS 和 portDISABLE_INTERRUPTS 实现的。细心的读者

FreeRTOS学习笔记5——Interrupt

FreeRTOS学习笔记5——Interrupt

FreeRTOS学习笔记5——InterruptFreeRTOS Interrupt ManagementFreeRTOS在任务和中断中使⽤两个版本API,以必免造成阻塞,中断使⽤的API以FromISR结尾xHigherPriorityTaskWoken如果在中断中应⽤上下⽂切换(xHigherPriorityTaskWoken=pdTRUE),中断将中断⼀个进程,⽽退出中断后切换到另⼀个进程中去。

如果被唤醒的进程的优先级⼤于当前运⾏的进程时,将切换⾄优先级⾼的进程,抢占策略线程安全API(以FromISR结尾的API),有⼀个指针参数pxHigherPriorityTaskWoken,⽤以指⽰当前中断是否需要进⾏上下⽂切换当需要进⾏上下⽂切换时,API(FromISR)会将*pxHigherPriorityTaskWoken=pdTRUE, 在使⽤API(FromISR)之前,必需将pxHigherPriorityTaskWoken 初使化为pdFALSE若ISR中调⽤多个API(FromISR),时,必须在调⽤每个API之前将pxHigherPriorityTaskWoken初使化为pdFALSE pxHigherPriorityTaskWoken 是可选的,当不⽤时可以将pxHigherPriorityTaskWoken 设为NULL。

portYIELD_FROM_ISR() and portEND_SWITCHING_ISR()taskYIELD()是宏⽤于在task中请求context切换portYIELD_FROM_ISR(), portEND_SWITCHING_ISR()⽤法相同,都是taskYIELD()的 safe version.portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );portYIELD_FROM_ISR( xHigherPriorityTaskWoken );The xHigherPriorityTaskWoken parameter passed out of an interrupt safe API function can beused directly as the parameter in a call to portYIELD_FROM_ISR()⼤部分FreeRTOS ports允许在ISR中的任何位置调⽤portYIELD_FROM_ISR()有⼀⼩部分 ports 只允许在ISR尾部调⽤portYIELD_FROM_ISR()延迟中断处理Deferred Interrupt Processing中断处理要尽可能短An interrupt service routine must record the cause of the interrupt, and clear the interrupt. Any other processing necessitated by the interrupt can often be performed in a task, allowing the interrupt service routine to exit as quickly as is practical. This is called deferred interrupt processing, because the processing necessitated by the interrupt is deferred from the ISR to a taskBinary Semaphores Used for Synchronization⼆进制信号量⽤于同步Binary Semaphores 通常⽤于将中断处理程序延迟⾄task中处理的⽬的。

freertos资料整理

freertos资料整理

用了半天时间对FreeRTOS有了一个初步的认识,大概总结一下,其中混杂了系统实现和实际应用方面的问题。

现只是以应用为目的,实现方面待以后进一步研究。

1.FreeRTOS提供的功能包括:任务管理、时间管理、信号量、消息队列、内存管理。

与平台有关的文件包含在portable文件夹中,主要是port.c, portmacro.h 两个文件。

平台无关的文件主要是:list.c(基本链表结构), queue.c(包括消息队列,信号量的实现), croutine.c,tasks.c(任务管理,时间管理)。

命名协定RTOS内核与范例程序源代码使用下面的协定:变量char类型的变量以c 为前缀short类型的变量以s 为前缀long类型的变量以l 为前缀float类型的变量以f 为前缀double类型的变量以d 为前缀枚举变量以e 为前缀其他类型(如结构体)以x 为前缀指针有一个额外的前缀p , 例如short类型的指针前缀为ps无符号类型的变量有一个额外的前缀u , 例如无符号short类型的变量前缀为us函数文件内部函数以prv为前缀API函数以其返回值类型为前缀,按照前面对变量的定义函数的名字以其所在的文件名开头。

如vTaskDelete函数在Task.c文件中定义数据类型数据类型并不直接在RTOS内核内部引用。

相反,每个平台都有其自身的定义方式。

例如,char类型定义为portCHAR,short类型定义为portSHORT等。

范例程序源代码使用的就是这种符号,但这并不是必须的,你可以在你的程序中使用任何你喜欢的符号。

此外,有两种额外的类型要为每种平台定义。

分别是:portTickType可配置为16位的无符号类型或32位的无符号类型。

参考API文档中的定制部分获取详细信息。

portBASE_TYPE为特定体系定义的最有效率的数据类型。

如果portBASE_TYPE定义为char则必须要特别小心的保证用来作为函数返回值的signed char可以为负数,用于指示错误。

干货FreeRTOS学习笔记——中断与任务切换

干货FreeRTOS学习笔记——中断与任务切换

干货FreeRTOS学习笔记——中断与任务切换EEWorld电子资讯犀利解读技术干货每日更新在FreeRTOS具备了任务的内存资源——堆栈管理机制,能根据任务状态和优先级进行CPU执行的上下文切换,并提供了任务间通信渠道以实现必要的任务同步和互斥之后,多个任务可以协同起来工作了。

不过,既然名称叫做Real-Time (实时)的操作系统,还需要能对外部(硬件)事件作出快速的响应。

尤其是对于单片机上的应用,在一个硬件中断(IRQ)产生以后,立即唤醒某个任务来处理这个事件是操作系统必须要支持的。

从任务的角度来看,其实有很多任务是需要根据硬件上的事件(比如传输完成,设备就绪,接收到数据等)来被调度的,否则它将不停测试硬件设备状态寄存器标志位,浪费CPU时间。

FreeRTOS 的时间片管理,其实背后就是借用了定时器中断。

不然不可能一个任务执行时没有申请调度就被打断,去执行其它同一优先级的任务。

类似的,任何硬件中断发生时都会执行相应的中断服务程序(Interrupt Service Routine, ISR, 又叫IRQ Handler),在ISR执行完之后是返回当前任务,还是调度执行其它任务?这完全由ISR来决定。

1. ISR 独立于所有任务尽管从效果上看,ISR,即中断服务程序是为了某个任务的功能在服务的,务必先强调一下:ISR 的代码不属于FreeRTOS 任何一个任务代码的部分。

每个ISR 都是一个C语言函数,但它不是一个任务,也不会被任何一个任务所调用。

ISR 对堆栈的使用与任务不同。

前面的连载中已经介绍过,FreeRTOS 对每个任务分配了独立的堆栈空间,用于保存函数的局部变量等等。

在发生中断时,CPU的某些寄存器会被保存到当前的堆栈里(而不是指定某任务的堆栈),然后开始执行ISR程序。

如果当前是某个任务的代码正被执行,则会占用该任务的堆栈;如果当前是另外一个ISR 的代码正在执行即发生中断嵌套,那么可能继续用更早被中断的任务的堆栈(注:这与平台有关。

FreeRTOS学习笔记——系统配置

FreeRTOS学习笔记——系统配置

FreeRTOS学习笔记——系统配置FreeRTOS的系统配置⽂件是“FreeRTOSConfig.h”,通过此⽂件可以对系统进⾏裁剪和配置。

FreeRTOS的配置基本都是通过“FreeRTOSConfig.h”中的#define语句来定义宏定义实现的。

⼀、“INCLUDE_”开始的宏使⽤“INCLUDE_”开始的宏表⽰使能或除能对应的FreeRTOS的API函数,作⽤就是⽤来配置FreeRTOS的可选API函数。

⽐如当宏INCLUDE_vTaskPrioritySet配置为0的时候不能表⽰不能使⽤vTaskPrioritySet()函数。

如图所⽰:只有当宏INCLUDE_vTaskPrioritySet配置为1的时候,vTaskPrioritySet()函数才会被编译。

不⽌FreeRTOS这么⼲,其他的很多协议栈、GUI库和RTOS系统也都是使⽤条件编译来实现配置和剪裁的,条件编译的好处就是节省空间,不需要的功能就不⽤编译,根据实际需求减少系统占⽤的RAM和ROM⼤⼩,根据⾃⼰使⽤的MCU来调整系统消耗,降低成本。

其他的⼏个INCLUDE_开头的宏也是相同的道理:⼆、“config”开始的宏1.configAPPLICATION_ALLOCATED_HEAP“config”开始的宏也是⽤来完成FreeRTOS配置和裁剪的,例如,configAPPLICATION_ALLOCATED_HEAP定义为1的话,堆内存可以由⽤户⾃⾏配置,堆内存在heap1.c、heap2.c、heap3.c、heap4.c和heap5.c中有定义,具体在哪⼀个⽂件,取决于选择的内存管理⽅式。

例如我们使⽤了heap4.c,在heap4.c中就有如图所⽰的定义:当宏configAPPLICATION_ALLOCATED_HEAP配置为1的时候,需要⽤户⾃⾏配置堆内存ucHeap,否则由编译器分配。

2.configASSERT断⾔,类似C库中的assert()函数,调试代码的时候判断传⼊的参数是否合理。

正点原子freertos开发指南_概述及解释说明

正点原子freertos开发指南_概述及解释说明

正点原子freertos开发指南概述及解释说明1. 引言1.1 概述在嵌入式系统领域,实时操作系统(RTOS)成为了开发者必备的工具之一。

正点原子freertos是一种流行的RTOS,广泛应用于嵌入式设备的开发和设计中。

本文旨在提供一份详尽的指南,帮助读者理解和使用正点原子freertos。

1.2 文章结构本文将按照以下结构进行介绍和讲解。

首先,我们将在引言部分对文章进行概述,并阐明文章的目的。

然后,在正文部分,将深入讨论正点原子freertos的开发指南。

接着,在解释说明部分,我们将详细解析正点原子freertos中的核心概念,并展开讲解任务调度器以及任务通信与同步机制。

最后,在结论部分对整个开发指南进行总结。

1.3 目的本文的目的是提供读者全面而又易于理解的资料,来帮助初学者迅速上手并熟练使用正点原子freertos。

通过本文,读者将了解到这款RTOS的基本概念、特点与优势,并能够掌握它在嵌入式设备开发中所扮演的角色和功能。

同时,本文还旨在通过详细的解释说明部分,帮助读者深入理解正点原子freertos中的核心概念以及相关机制的运作原理。

最后,本文将通过总结部分,使读者对于整个开发指南有一个完整而清晰的认识。

这篇文章将成为初学者入门正点原子freertos开发所不可或缺的书籍,并且也非常适合已经有一定基础知识的开发人员参考和进一步提高。

我们相信,在阅读本文后,读者将能够充分了解并掌握正点原子freertos的开发过程和相关概念,从而在嵌入式系统领域取得更好的成果。

2. 正文:正文部分将详细介绍正点原子freertos的开发相关内容。

主要包括以下几个方面:2.1 什么是正点原子freertos正点原子freertos是一款基于实时操作系统(RTOS)的开发平台,专注于嵌入式系统开发。

它提供了一套完整且易于使用的工具和库,帮助开发者快速构建可靠、高效的嵌入式应用程序。

2.2 freertos的架构和特性我们将介绍freertos的整体架构和核心特性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验5-8知识点
实验5:时间片调度/任务信息状态查询与统计
实验6:信号量
实验7:软件定时器/事件标志组
实验8:任务通知
回答下列问题时,尽量通过读代码得到答案,这有助于你理解和记住代码。

1.《11-1 FreeRTOS任务状态或信息查询实验》
本实验同时用到了TIM3和TIM5。

TIM5可以换成TIM4。

但是,如果我们想把这一实验和以前的实验合并成一个工程时,TIM3/TIM4和实验6-1中断测试实验冲突,这个该如何解决?给出思路即可。

??
uxTaskGetNumberOfTasks函数的作用和用法?
P156获取当前系统中存在的任务的个数
uxTaskGetSystemState函数的作用和用法?
P151获取系统中任务状态
uxTaskGetSystemState中的TaskStatus_t结构体的成员变量有哪些?
作业20180521/1:
typedef struct xTASK_STATUS
{
TaskHandle_t xHandle; //任务句柄
const char *pcTaskName; //任务名字
UBaseType_t xTaskNumber; //任务编号
eTaskState eCurrentState; //当前任务状态
UBaseType_tuxCurrentPriority; //任务当前优先级
UBaseType_t uxBasePriority; //任务基础优先级
uint32_t ulRunTimeCounter; //任务运行的总时间
StackType_t *pxStackBase; //堆栈基地址
uint16_tusStackHighWaterMark; //从任务创建以来任务堆栈剩余的最小大小
} TaskStatus_t;
xTaskGetHandle函数的作用和用法?
P154根据任务名字查找某个任务的句柄
vTaskGetInfo函数的作用和用法?
P152获取某个任务信息
eTaskGetState函数的作用和用法?
P154获取某个任务的状态(eTaskState类型)
pvPortMalloc函数的作用和用法?
P161内存申请函数
vPortFree函数的作用和用法?
P161内存释放函数
memset函数的作用和用法?
P162内存设置函数
2.《FreeRTOS实验11-2 FreeRTOS任务运行时间统计实验》
统计任务运行时间功能的问题:
(1)使用统计功能需要开放哪几个宏?
P164一共要开放3个宏
(2)配置统计时钟基准的函数是什么?其内容是什么?
P165其实就是初始化定时器
(3)要能够正常统计,统计时间基准和OS时间节拍的关系是什么?
P165时钟基准的精度要比系统时钟高10-20倍
(4)tasks.c中的哪个函数中计算了每个任务的运行时间?
P169vTaskGetRunTimeStats()
调试的问题:
在软件仿真状态下,当设置一个管脚为上拉输入时,它的初始值是什么?
设置完GPIO状态为上拉输入时,发现ODR里对应值为1,而PIN和IDR里为0。

3.《FreeRTOS实验13-1 FreeRTOS队列操作实验》
uxQueueSpacesAvailable函数的作用和用法
13-1main.c&queue.c用于求队列剩余大小
uxQueueMessagesWaiting函数的作用和用法
13-1main.c&queue.c用于求当前已使用队列大小
xQueueCreate函数的作用和用法
P189队列创建函数,本质上是一个宏,用来动态创建队列,最终会调用xQueueGenericCreate ()
my_mem_init函数的作用
P213初始化内部内存池
mymalloc函数的作用和用法
P212申请内存
myfree函数的作用和用法
P212释放内存
xQueueSend函数的作用和用法
P196用于向队列中发送消息,本质上是一个宏,后向入队,新消息插入到队列后面,最终会调用xQueueGenericSend(),只能用于任务函数中
xQueueReceiveFromISR函数的作用和用法
P209用于在中断服务函数中从队列读取一条信息,读取成功后会将队列中这条数据删除
定时器的定时中断周期与自动重装值、预分频数、定时器时钟源之间的计算公式是什么?
中断周期(s)=[(自动重装载值+1)×(预分频数+1) ]/定时器时钟源(MHz)
*补充:已知中断周期和定时器时钟源频率,假定预分频数,求自动重装值。

例:已知时钟源频率72MHz,中断周期1.75s,假定时钟源2000分频,预分频数即为1999,分频后的时钟频率为72MHz/(1999+1)=36000Hz,
则装载值=1.75/(1/36000)=63000。

重装载值越大,误差越小。

这一实验中的内存动态分配方式与13-1中的不同,差别体现在哪里?
??
4.《FreeRTOS实验14-1 FreeRTOS二值信号量实验》
什么是二值信号量?
P220
如何创建一个二值信号量?
P222
信号量的P操作和V操作分别体现在哪两个函数中?
如何释放一个信号量?
P224
任务中如何取一个信号量?当取不到时会如何?
P226
STM32F103的USART1的发送和接收引脚分别是哪一个?
文字或流程图描述DataProcess_task函数的作用和流程。

P230-P231答:指令处理任务,根据接收到的指令来控制不同的外设
文字或流程图描述USART1_IRQHandler函数的作用和流程。

P232答:作用:释放二值信号量
变量USART_RX_STA的作用是什么?
P232中最后一个if有调用答:获取接收到的数据
5.《FreeRTOS实验14-2 FreeRTOS计数型信号量实验》
什么是计数型信号量?
P234答:长度大于1的队列
如何创建一个计数型信号量?
P234分为静态和动态创建
如何获取一个计数型信号量的当前计数值?
P226获取信号量
6.《FreeRTOS实验14-3 FreeRTOS优先级翻转实验》
举例说明什么是优先级反转。

P241优先级翻转概念及例子
分析是否发生了优先级反转。

??
什么是优先级继承?
在优先级翻转实验代码的基础上设计一个信号量互锁。

先建立两个信号量S1和S2,high_task获取S1后,只有在获取到S2后才释放S1。

相反,low_task 获取S2后,只有在获取到S1后才释放S2。

设计程序实现一个信号量互锁的现象,分析互锁出现的条件。

??
7.《FreeRTOS实验14-4 FreeRTOS互斥信号量操作实验》
什么是互斥信号量?它与二值信号量的区别是什么?
P248
如何创建一个互斥信号量?
P248
允许使用互斥信号量的宏是哪一个?
configUSE_MUTEXES == 1
比较14-3反转实验和14-4互斥实验的main中的代码差别,以及实验结果的差别。

差别:14-4的第60-61,102-103,146,150,182,188行与14-3不同。

8.FreeRTOS实验15-1 FreeRTOS软件定时器实验
什么是软件定时器?
P268
软件定时器和硬件定时器的主要区别是什么?
在硬件定时器中,我们是在定时器中断中实现需要的功能,而使用软件定时器时,我们是在创建软件定时器时指定软件定时器的回调函数,在回调函数中实现相应的功能。

xTimerCreate函数的作用和用法?
P272 函数原型+参数解释
变量uxAutoReload的true和false会对定时器带来什么影响?
当参数为pdture时,创建的是周期定时器(P270);当参数为pdfalse时,创建的是单次定时器(P270)
如何启动和停止软件定时器?
P274
定时器1和定时器2的输出有什么规律?
P270
定时器1和2的回调(callback)函数的核心内容是什么?
P279
9.FreeRTOS实验16-1 FreeRTOS事件标志组实验
什么是事件标志组?
P281
如何创建一个事件标志组?
P282
如何定义事件位?
P283
xEventGroupSetBits函数的作用和用法
P284
xEventGroupWaitBits函数的作用和用法
P286
xEventGroupGetBits函数的作用和用法
P285
10.《FreeRTOS实验17-1 FreeRTOS任务通知模拟二值信号量实验》
本实验中的xTaskNotify的作用对应了14-1实验中的哪一个函数?
P239倒数第二段P306相当于xSemaphoreGive()
用于发送任务通知,与xTaskNotifyGive()函数作用相同
xTaskWait对应了14-1实验中的哪一个函数?
??
使用任务通知会有什么优势?
P306时间快/所需的RAM少
如何设计一个实验比较任务通知和二值信号量的性能差异???。

相关文档
最新文档