一、定时器任务

创建定时器

TimerHandle_t xTimerCreate(	const char * const pcTimerName,//定时器名
								const TickType_t xTimerPeriodInTicks,//定时周期
								const UBaseType_t uxAutoReload,//周期模式
								void * const pvTimerID,//ID 
                TimerCallbackFunction_t pxCallbackFunction )//回调函数
启动定时器
xTimerStart()

启动定时器(中断)
xTimerStartFromISR()

关闭定时器
xTimerStop()

关闭定时器(中断)
xTimerStopFromISR()

实例

static TimerHandle_t Swtmr1_Handle =NULL;   /* */
static uint32_t TmrCb_Count1 = 0; /* 回调函数调用次数 */

static void AppTaskCreate(void)
{
  taskENTER_CRITICAL(); 
  Swtmr1_Handle=xTimerCreate((const char*		)"AutoReloadTimer",
                            (TickType_t			)1000,/*定时周期 */
                            (UBaseType_t		)pdTRUE,/* 周期模式*/
                            (void*				  )1,/*定时任务ID 唯一 */
                            (TimerCallbackFunction_t)Swtmr1_Callback); //回调函数
  if(Swtmr1_Handle != NULL)                          
  {
    xTimerStart(Swtmr1_Handle,0);	
  }                            
 
  vTaskDelete(AppTaskCreate_Handle);
  taskEXIT_CRITICAL(); 
}

//回调函数
static void Swtmr1_Callback(void* parameter)
{		
  TickType_t tick_num1;
  TmrCb_Count1++;	
  
  tick_num1 = xTaskGetTickCount();	/* 获取滴答计数器值 */
  
  printf("Swtmr1_Callback函数计数 %d ´Î\n", TmrCb_Count1);
  printf("滴答计数=%d\n", tick_num1);
}

二、内存管理

FreeRTOS 的 V9.0.0 提供了 5 种内存管理算法,分别是 heap_1.c、heap_2.c、heap_3.c、heap_4.c、heap_5.c,源文件存放于MemMang 路径下,选择其中一个添加到我们的工程中即可

内存管理模块通过对内存的申请、释放操作,来管理用户和系统对内存的使用,使内存的利用率和使用效率达到最优,同时最大限度地解决系统可能产生的内存碎片问题。

内存管理方案详解

文件 说明
heap_1.c 只能申请不能释放,申请内存的时间是一个常量;没有释放,不会产生内存碎片;内存利用率不高
heap_2.c 支持释放内存,采用最佳匹配算法,在空闲内存中找到合适申请大小的空间,不能把两个小的内存合并成一个大的内存块,容易产生碎片
heap_3.c 简单封装了C库中的malloc,free函数,操作内存前挂起调度器、完成后再恢复调度器
heap_4.c 最佳匹配和合并算法,空闲块以单链表的形式连接起来,可作为有先选择使用
heap_5.c 最佳匹配和合并算法,允许跨多个非连续的内存区(多个物理内存)
获取当前内存大小xPortGetFreeHeapSize()
申请内存pvPortMalloc( size_t xWantedSize );
释放内存vPortFree()
uint8_t *Test_Ptr = NULL;
uint32_t g_memsize;

//获取系统内存
g_memsize = xPortGetFreeHeapSize();
printf("系统内存大小\n",g_memsize);

//申请内存1024
Test_Ptr = pvPortMalloc(1024);

//向内存中写数据
sprintf((char*)Test_Ptr,"TickCount = %d \n",xTaskGetTickCount());
printf("%s \n",(char*)Test_Ptr);

三、中断管理

在中断中使用

void KEY1_IRQHandler(void)
{
    BaseType_t pxHigherPriorityTaskWoken;
    uint32_t ulReturn;
    /* 进入临界段 ,可以嵌套(被另外的中断打断)*/
    ulReturn = taskENTER_CRITICAL_FROM_ISR();
	if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) 
	{
       /*将数据写入队列中,等待时间0 */
		xQueueSendFromISR(Test_Queue, /*消息队列句柄 */
											&send_data1,/* 发送消息内容*/
											&pxHigherPriorityTaskWoken);
		//如果需要进行一次任务切换
		portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
		//清除中断标志位
		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
	}  

	//退出临界段
  taskEXIT_CRITICAL_FROM_ISR( ulReturn );
}

四、CPU使用率统计

输出系统中的每个任务占用 CPU 的时间,从而得知系统设计的是否合理

static void CPU_Task(void* parameter)
{	
	  uint8_t CPU_RunInfo[400];		//任务运行时间信息
	  while (1)
	  {
		    memset(CPU_RunInfo,0,400);	
		    vTaskList((char *)&CPU_RunInfo);  //获取任务运行时间信息
		    printf("---------------------------------------------\r\n");
		    printf("任务名     任务状态   优先级 剩余栈 任务序号\r\n");
		    printf("%s", CPU_RunInfo);
		    printf("---------------------------------------------\r\n");
		    
		    memset(CPU_RunInfo,0,400);	
		    vTaskGetRunTimeStats((char *)&CPU_RunInfo);
		    
		    printf("任务名      运行计数         利用率\r\n");
		    printf("%s", CPU_RunInfo);
		    printf("---------------------------------------------\r\n\n");
		    vTaskDelay(1000); 	
	  }
}

串口输出

---------------------------------------------
任务名      任务状态 优先级   剩余栈 任务序号
CPU_Task       	R	4	361	5
IDLE           	R	0	106	2
LED2_Task      	B	3	468	4
LED1_Task      	B	2	460	3
---------------------------------------------
任务名       运行计数         利用率
CPU_Task       	354		3%
LED1_Task      	47		<1%
IDLE           	8854		95%
LED2_Task      	90		<1%
---------------------------------------------