野火FreeRTOS相关笔记(未完成)

创建任务

创建 静态任务 和 动态任务

如果要求系统稳定(军工产品之类的)则利用静态任务创建函数

如果一般的工业要求则可以利用动态创建任务函数,效率高

静态任务  xTaskCreateStatic():

创建静态任务需要在全局变量中定义的东西很多:

1.任务栈(Stack):用于存任务的一些变量、参数等数据

2.任务控制块(TCB):相当于任务的身份证,控制块结构体中含有节点,可以挂在链表中;

链表可以指的是 任务就绪列表、任务阻塞列表等等

3.任务句柄(Handle):创建任务后 create函数返回的数值用句柄来接。

	AppTaskCreate_Handle = xTaskCreateStatic((TaskFunction_t)AppTaskCreate,//任务函数
											(const char*)"AppTaskCreate",//任务名称
											(uint32_t)128,	//任务堆栈大小
										    (void*)NULL,//传递给任务函数的参数
											(UBaseType_t)3,//任务优先级
											(StackType_t*)AppTaskCreate_Stack,//任务堆栈
										(StaticTask_t*)&AppTaskCreate_TCB);	//任务控制块   
															
	if(NULL != AppTaskCreate_Handle)/* 创建成功 */
    vTaskStartScheduler();   /* 启动任务,开启调度 */

动态任务xTaskCreate():

创建之前只需要创建一个:

1.任务句柄:用于函数参数

  xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate,  /* 任务入口函数 */
                        (const char*    )"AppTaskCreate",/* 任务名字 */
                        (uint16_t       )512,  /* 任务栈大小 */
                        (void*          )NULL,/* 任务入口函数参数 */
                        (UBaseType_t    )1, /* 任务的优先级 */
                        (TaskHandle_t*  )&AppTaskCreate_Handle);/* 任务控制块指针 */ 
  /* 启动任务调度 */           
  if(pdPASS == xReturn)
    vTaskStartScheduler();   /* 启动任务,开启调度 */

动态和静态的差别:

1.全局变量参数创建

1.静态在全局变量中要创建好 1.任务栈 2.任务控制块 3.任务句柄 等各个参数

2.而动态创建函数只需要创建好1.任务句柄。

2.返回函数不同

1.静态:返回的是 任务控制块指针:也就是任务句柄 

2.动态:返回的是 信息返回值 在mian函数中创建。

3.形参不一样

自己对比一下。

消息队列、信号量、互斥量

1. 消息队列:

可以传递某些消息 创建时首先定义消息队列的长度和大小还有消息队列句柄

  /* 创建Test_Queue */
  Test_Queue = xQueueCreate((UBaseType_t ) QUEUE_LEN,/* 消息队列的长度 */
                                                     (UBaseType_t ) QUEUE_SIZE);/* 消息的大小 */

消息队列的长度和大小与发送接收的阻塞有关

1.消息队列发送函数:

    uint32_t send_data4 = 4;

      xReturn = xQueueSend( Test_Queue, /* 消息队列的句柄 */
                                              &send_data4,/* 发送的消息内容 */
                                               0 );        /* 等待时间 0 */

发送时:等待时间为 如果队列已满则等待,0则不等待直接返回队列已满。

2.消息队列接收函数:

  uint32_t r_queue;    /* 定义一个接收消息的变量 */

    xReturn = xQueueReceive( Test_Queue,    /* 消息队列的句柄 */
                                                  &r_queue,      /* 发送的消息内容 */
                                                portMAX_DELAY); /* 等待时间 一直等 */
    if(pdTRUE == xReturn)
      printf("本次接收到的数据是%d\n\n",r_queue);
    else
      printf("数据接收出错,错误代码0x%lx\n",xReturn);

接收时:等待时间为 消息队列为空时 ,portMAX_DELAY为一直等待 直到有数据时才进行接收。

2.信号量(可以理解为消息队列的简化版 ):

信号量的 xSemaphoreTake() = 消息队列的 xQueueReceive()

信号量的 xSemaphoreGive() = 消息队列的  xQueueSend()

1.二值信号量:(主要用于同步)

二值信号量主要用于同步信号

1.创建二值信号量:(要先创建二值信号量句柄)

    BinarySem_Handle = xSemaphoreCreateBinary();

2.二值信号量的接收:xSemaphoreTake()(+ISR在中断使用)

    //获取二值信号量 xSemaphore,没获取到则一直等待
        xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
                                                        portMAX_DELAY); /* 等待时间 */

    if(pdTRUE == xReturn)
      printf("BinarySem_Handle二值信号量获取成功!\n\n");

如果没有接收到则一直等待,任务出于堵塞状态,接收到后,任务执行。

3.二值信号量的发送:xSemaphoreGive()(+ISR在中断使用)

      xReturn = xSemaphoreGive( BinarySem_Handle );//给出二值信号量
      if( xReturn == pdTRUE )
        printf("BinarySem_Handle二值信号量释放成功!\r\n");
      else
        printf("BinarySem_Handle二值信号量释放失败!\r\n");
    } 

2.计数信号量(give(释放)相当于+1,take(获取)相当于-1)

用于计数之类的吧! 

1.创建计数信号量:

  /* 创建Test_Queue */
  CountSem_Handle = xSemaphoreCreateCounting(5,5);  

 xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) 

第一个参数是 总共的计数数值, 第二是初始化多少个计数值

2.释放(发送/获取)一个计数信号量(give 相当于+1)

            /* 获取一个计数信号量 */
      xReturn = xSemaphoreGive(CountSem_Handle);//给出计数信号量                  
            if ( pdTRUE == xReturn ) 
                printf( "KEY2被按下,释放1个停车位。\n" );
            else
                printf( "KEY2被按下,但已无车位可以释放!\n" );    

3.接收(获取)一个计数信号量(take相当于 -1)

            /* 获取一个计数信号量 */
      xReturn = xSemaphoreTake(CountSem_Handle,    /* 计数信号量句柄 */
                                                      0);     /* 等待时间:0 */

            if ( pdTRUE == xReturn ) 
                printf( "KEY1被按下,成功申请到停车位。\n" );
            else
                printf( "KEY1被按下,不好意思,现在停车场已满!\n" );    

3. 二值信号量与计数信号量的异同:

相同:

1.两个函数的 接收和发送信号量的函数相同均是xSemaphoreTake() 和 xSemaphoreGive()。

不同:

1.创建函数不同。

2.形参不同

4.互斥量(有个递归的互斥量我不太懂 所以这里不做分析)

讲解

互斥量主要是有 任务优先级继承机制

消息队列和信号量,会容易导致优先级翻转机制,使得处理更高级任务没那么及时。

互斥量需要自己接收后自己释放,有占有权

互斥量创建函数 xSemaphoreCreateMutex()

  /* 创建MuxSem */
  MuxSem_Handle = xSemaphoreCreateMutex();     

释放互斥量   xSemaphoreGive()

xReturn = xSemaphoreGive( MuxSem_Handle );//给出互斥量.

获取互斥量xSemaphoreTake()

    //获取互斥量 MuxSem,没获取到则一直等待
        xReturn = xSemaphoreTake(MuxSem_Handle,/* 互斥量句柄 */
                                                       portMAX_DELAY); /* 等待时间 */

互斥量与二值信号量的区别:

1.互斥信号量需要 先take获取到了 再自己释放give,释放后,再通过高优先级任务的take获得。

 计数信号量 是 先释放give后,再同步获取take到,并且可以再任何任务中释放give。

2.互斥量油优先级继承机制而 二值信号量会有优先级翻转现象。

翻转现象主要表现在 如果低优先级和高优先级的任务是获取同一个二值信号量,低优先级的先获取到了则会先运行低优先级的,在运行低优先级任务时可能会被中间优先级的抢占,高优先级的任务不能运行。

事件(如果说信号量是一对一则事件则是一对多)

信号量可能只能一个任务释放一个信号量 一个任务接收。

而事件则是可以 几个任务释放几个信号量, 再一个任务进行接收。

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值