为了方便与UCOS对比,顺序按照UCOS那篇编写。

0、一些移植、系统相关

1、框架写法(个人习惯相关)

1-1、main 函数里创建一个开始任务

int main(void)
{
初始化外设 xTaskCreate(); //创建开始任务 vTaskStartScheduler(); //开启任务调度
}

1-2、开始任务里,创建我们要运行的多个任务

void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区 xTaskCreate(); //创建任务 1
xTaskCreate(); //创建任务 2
xTaskCreate(); //创建任务 3 vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}

2、任务创建、挂起、删除

2-0、相关配置

#define configSUPPORT_DYNAMIC_ALLOCATION        1                       //支持动态内存申请
//#define configSUPPORT_STATIC_ALLOCATION 1 //支持静态内存申请
#define configTOTAL_HEAP_SIZE ((size_t)(20*1024)) //系统所有总的堆大小,heap_x.h需要,动态申请

2-1、任务创建(动态)

//==================任务创建宏定义,便于修改==================

#define START_TASK_PRIO			1		//任务优先级
#define START_STK_SIZE 256 //任务堆栈大小 TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters); //任务函数 //==================任务创建函数================== xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄

2-2、任务挂起

vTaskSuspend(Task1Task_Handler);	//挂起任务1

2-3、任务解挂

2-3-1、任务内任务解挂

vTaskResume(Task1Task_Handler);	//恢复任务1

2-3-2、中断内任务解挂

BaseType_t YieldRequired;

YieldRequired=xTaskResumeFromISR(Task1Task_Handler);    //恢复任务1

portYIELD_FROM_ISR(YieldRequired);    //判断是否需要调度到恢复的任务

2-4、任务删除

vTaskDelete(Task1Task_Handler);    //删除任务1

2-5、任务创建(静态)

2-5-1、静态任务创建

//==================任务创建宏定义,便于修改==================

#define START_TASK_PRIO		1				//任务优先级
#define START_STK_SIZE 128 //任务堆栈大小 StackType_t StartTaskStack[START_STK_SIZE]; //任务堆栈
StaticTask_t StartTaskTCB; //任务控制块 TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters); //任务函数 //==================任务创建函数================== StartTask_Handler=xTaskCreateStatic((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint32_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(StackType_t* )StartTaskStack, //任务堆栈
(StaticTask_t* )&StartTaskTCB); //任务控制块

2-5-2、静态创建任务还需实现 空闲任务、定时任务

//==================任务创建宏定义,便于修改==================

static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];			//空闲任务任务堆栈
static StaticTask_t IdleTaskTCB; //空闲任务控制块 static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH]; //定时器服务任务堆栈
static StaticTask_t TimerTaskTCB; //定时器服务任务控制块 //==================任务创建函数================== //获取空闲任务地任务堆栈和任务控制块内存
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer=&IdleTaskTCB;
*ppxIdleTaskStackBuffer=IdleTaskStack;
*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
} //获取定时器服务任务的任务堆栈和任务控制块内存
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize)
{
*ppxTimerTaskTCBBuffer=&TimerTaskTCB;
*ppxTimerTaskStackBuffer=TimerTaskStack;
*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}

  

3、时间片轮转

3-0、相关配置(时间片片长 即 1/Tick中断频率)

#define configUSE_PREEMPTION					1                       //1使用抢占式内核,0使用协程
#define configUSE_TIME_SLICING 1 //1使能时间片调度(默认式使能的)
#define configTICK_RATE_HZ (20) //时钟节拍频率,20HZ = 50ms

3-1、两个任务优先级相等

#define TASK1_TASK_PRIO		2
#define TASK1_STK_SIZE 128
TaskHandle_t Task1Task_Handler;
void task1_task(void *pvParameters); #define TASK2_TASK_PRIO 2
#define TASK2_STK_SIZE 128
TaskHandle_t Task2Task_Handler;
void task2_task(void *pvParameters);

4、钩子函数。

4-0、相关配置

#define configUSE_IDLE_HOOK						1                       //1,使用空闲钩子;0,不使用
#define configUSE_TICK_HOOK 1 //1,使用时间片钩子;0,不使用

4-1、自己实现钩子函数

void vApplicationIdleHook( void );        //空闲钩子函数
void vApplicationTickHook( void ); //时钟节拍钩子函数

5、软件定时器

5-1、软件定时器创建

//==============定时器结构体、函数声明==============

TimerHandle_t 	MyTimer_Handle;    //定时器句柄
void ReloadCallback(TimerHandle_t xTimer); //定时器回调函数 //==============定时器创建============== MyTimer_Handle=xTimerCreate((const char* )"ReloadTimer", //定时器名称
(TickType_t )1000, //周期1s(1000个时钟节拍)
(UBaseType_t )pdTRUE, //周期模式
(void* )1, //定时器ID
(TimerCallbackFunction_t)ReloadCallback); //定时器回调函数

5-2、定时器“中断服务函数”,回调函数

void ReloadCallback(TimerHandle_t xTimer)
{
//do something
}

5-3、定时器开启(也有复位效果)

xTimerStart(MyTimer_Handle,0);	//开启定时器

5-4、定时器停止

xTimerStop(MyTimer_Handle,0); 	//关闭定时器

5-5、定时器复位

xTimerReset(MyTimer_Handle, 0)

6、消息队列

6-1、消息队列创建

//================消息队列宏定义================

#define MESSAGE_Q_NUM   4   		//发送数据的消息队列的数量
#define MESSAGE_Q_ITEM_NUM 200 //每个消息的空间大小
QueueHandle_t Message_Queue; //信息队列句柄 //================消息队列创建================ Message_Queue=xQueueCreate(MESSAGE_Q_NUM,MESSAGE_Q_ITEM_NUM);

6-2、消息发送

6-2-1、任务内消息发送

u8 sendData[MESSAGE_Q_ITEM_NUM];
BaseType_t err; err=xQueueSend(Message_Queue,&senddata,10); //10为发送等待时间,有可能队列已满,err = errQUEUE_FULL 或 err = pdPASS

6-2-2、中断内消息发送

u8 sendData[MESSAGE_Q_ITEM_NUM];
BaseType_t xHigherPriorityTaskWoken; xQueueSendFromISR(Message_Queue,sendData,&xHigherPriorityTaskWoken); //向队列中发送数据,返回值,依然是 满了或Pass,第三个参数是判断高优先级接受到队列后,退出中断,是否需要调度 portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换

6-3、消息接收

6-3-1、任务内消息接收

u8 *receiveData;

xQueueReceive(Message_Queue,receiveData,portMAX_DELAY)    //返回值为pdPASS 或 errQUEUE_EMPTY,这里等待时间用了portMAX_DELAY阻塞,所以不用再判断了。

6-3-2、中断内消息接收

u8 *receiveData;

err=xQueueReceiveFromISR(Message_Queue,receiveData,&xTaskWokenByReceive); //向队列中接受数据,返回值, FAIL或Pass,第三个参数是判断高优先级接受到队列后,退出中断,是否需要调度

portYIELD_FROM_ISR(xTaskWokenByReceive);//如果需要的话进行一次任务切换

6-4、队列剩余大小

u8 remain_size;		//消息队列剩余大小

remain_size=uxQueueSpacesAvailable(Message_Queue);	//得到队列剩余大小

6-5、队列使用大小

u8 used_size;		//消息队列使用大小

used_size=uxQueueMessagesWaiting(Message_Queue);	//得到队列使用大小

7、二值信号量(还有静态创建函数、中断内接受/发送函数,基本同上,不再重复)

7-1、二值信号量创建

SemaphoreHandle_t BinarySemaphore;	//二值信号量句柄

BinarySemaphore=xSemaphoreCreateBinary();	//创建二值信号量

7-2、二值信号量等待

BaseType_t err;

err = xSemaphoreTake(BinarySemaphore,portMAX_DELAY);	//获取信号量

7-3、二值信号量发送

BaseType_t err;

err = xSemaphoreGive(BinarySemaphore);	//释放二值信号量

  

8、计数信号量(还有静态创建函数、中断内接受/发送函数,基本同上,不再重复)

8-1、计数信号量创建

SemaphoreHandle_t CountSemaphore;//计数型信号量

CountSemaphore=xSemaphoreCreateCounting(255,0);		//创建计数型信号量,最大计数和初始化计数,参数没改动的话,为long,所以最大值可以设计为不止255

8-2、计数信号量等待

UBaseType_t semavalue;

xSemaphoreTake(CountSemaphore,portMAX_DELAY); 	//等待数值信号量,阻塞

semavalue=uxSemaphoreGetCount(CountSemaphore); 	//获取数值信号量值

8-3、计数信号量发送

BaseType_t err;

err=xSemaphoreGive(CountSemaphore);//释放计数型信号量

 

9、互斥信号量(还有静态创建函数,在中断不能用互斥信号量)

9-1、互斥信号量创建

SemaphoreHandle_t MutexSemaphore;	//互斥信号量

MutexSemaphore=xSemaphoreCreateMutex();		//创建互斥信号量

9-2、互斥信号量等待

xSemaphoreTake(MutexSemaphore,portMAX_DELAY);	//获取互斥信号量,因为是阻塞,也就不需要查看什么返回值

9-3、互斥信号量发送

xSemaphoreGive(MutexSemaphore);					//释放互斥信号量

  

10、递归互斥信号量(还有静态创建函数,在中断不能用递归互斥信号量)

10-1、递归互斥信号量创建

SemaphoreHandle_t RecursiveMutex;

RecursiveMutex = xSemaphoreCreateRecursiveMutex();        //创建递归互斥信号量

10-2、递归互斥信号量等待

xSemaphoreTakeRecursive(RecursiveMutex,10);        //10为等待节拍

10-3、递归互斥信号量发送

xSemaphoreGiveRecursive(RecursiveMutex);        //发送递归互斥信号量

11、事件标记组(还有静态创建函数、中断内接受/发送函数,基本同上,不再重复)

11-1、事件标记组创建

//例子:3个事件
#define EVENTBIT_0 (1<<0)
#define EVENTBIT_1 (1<<1)
#define EVENTBIT_2 (1<<2)
#define EVENTBIT_ALL (EVENTBIT_0|EVENTBIT_1|EVENTBIT_2) EventGroupHandle_t EventGroupHandler; //事件标志组句柄 EventGroupHandler=xEventGroupCreate(); //创建事件标志组

11-2、事件标记组置位

xEventGroupSetBits(EventGroupHandler,EVENTBIT_1);        //事件1置位

11-3、事件标记组清除置位

xEventGroupClearBits(EventGroupHandler,EVENTBIT_1);        //事件1清除

11-4、事件标记组值获取

EventBits_t NewValue;

NewValue = xEventGroupGetBits(EventGroupHandler);	//获取事件组的

11-5、事件标记位组等待

EventValue=xEventGroupWaitBits((EventGroupHandle_t	)EventGroupHandler,		//句柄
(EventBits_t )EVENTBIT_ALL, //标志位
(BaseType_t )pdTRUE, //获取成功后 清除
(BaseType_t )pdTRUE, //等待所有标志位 置位
(TickType_t )portMAX_DELAY); //阻塞

12、内存管理

12-1、内存申请

u8 *buffer;

buffer=pvPortMalloc(30);			//申请内存,30个字节

12-2、内存释放

vPortFree(buffer);	//释放内存

12-3、获取内存剩余空间

u32 freeSize;

freeSize = xPortGetFreeHeapSize();		//获取剩余内存大小

13、通知

13-1、通知事件发送(++)

xTaskNotifyGive(task_Handler);    //给task_Handler发送个通知

13-2、通知事件获取(--,并根据参数是否清0)

u32 NotifyValue;

NotifyValue=ulTaskNotifyTake(pdTRUE,portMAX_DELAY);	    //获取任务通知,参数1,读完清0,参数2阻塞

13-3、通知值发送

13-3-1、通知值发送(设置通知值,可发送一个数据)

u8 data;
BaseType_t err; err=xTaskNotify((TaskHandle_t )Task_Handler, //接收任务通知的任务句柄
(uint32_t )data, //任务通知值
(eNotifyAction )eSetValueWithOverwrite); //覆写的方式发送任务通知

13-3-2、通知值发送(设置通知值,可做标记位组)

#define EVENTBIT_1	(1<<1)

xTaskNotify((TaskHandle_t	)Task_Handler,		//接收任务通知的任务句柄
(uint32_t )EVENTBIT_1, //要更新的bit
(eNotifyAction )eSetBits); //更新指定的bit

13-4、通知值获取(获取通知值,并判断是否需要清0)

BaseType_t err;
uint32_t NotifyValue; err=xTaskNotifyWait((uint32_t )0x00, //进入函数,没有接受到通知,不清除任何bit
(uint32_t )ULONG_MAX, //退出函数,接受到通知,清除所有(0xffffffffUL)位的bit,
(uint32_t* )&NotifyValue, //保存任务通知值
(TickType_t )portMAX_DELAY); //阻塞时间

  

  

================================================ 为了好与UCOS的文章对比,这些内容也放下面================================================

1、中断

1-0、相关配置

#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS //STM32库自带
#else
#define configPRIO_BITS 4 //STM32提供4Bit的中断优先级
#endif #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //系统可管理的最高中断优先级
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) //内核中断优先级,用来配置上下文切换、时钟节拍优先级,因为STM32优先级寄存器用高4位,所以要左移
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) //用来屏蔽中断的阈值,左移原因同上 #define xPortPendSVHandler PendSV_Handler
#define vPortSVCHandler SVC_Handler

1-1、中断处理

无需特殊处理

2、临界段处理

2-1、任务内临界段处理

taskEXIT_CRITICAL();

//任务处理

taskEXIT_CRITICAL();

2-2、中断内临界段处理

taskENTER_CRITICAL_FROM_ISR();

//中断内处理

taskEXIT_CRITICAL_FROM_ISR();

3、引起调度函数

3-1、延时

 vTaskDelay(1000);                           //延时1000个时钟节拍,也就是1s

嵌入式:FreeRTOS的使用(未完)的更多相关文章

  1. javascript有用小功能总结(未完待续)

    1)javascript让页面标题滚动效果 代码如下: <title>您好,欢迎访问我的博客</title> <script type="text/javasc ...

  2. ASP.NET MVC 系列随笔汇总[未完待续……]

    ASP.NET MVC 系列随笔汇总[未完待续……] 为了方便大家浏览所以整理一下,有的系列篇幅中不是很全面以后会慢慢的补全的. 学前篇之: ASP.NET MVC学前篇之扩展方法.链式编程 ASP. ...

  3. 关于DOM的一些总结(未完待续......)

    DOM 实例1:购物车实例(数量,小计和总计的变化) 这里主要是如何获取页面元素的节点: document.getElementById("...") cocument.query ...

  4. 我的SQL总结---未完待续

    我的SQL总结---未完待续 版权声明:本文为博主原创文章,未经博主允许不得转载. 总结: 主要的SQL 语句: 数据操作(select, insert, delete, update) 访问控制(g ...

  5. virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续)

    virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续) 第一次接触到 linux,不知道linux的确很强大,然后用virtualbox ...

  6. MVC丶 (未完待续······)

         希望你看了此小随 可以实现自己的MVC框架     也祝所有的程序员身体健康一切安好                                                     ...

  7. 一篇文章让Oracle程序猿学会MySql【未完待续】

    一篇文章让Oracle DB学会MySql[未完待续] 随笔前言: 本篇文章是针对已经能够熟练使用Oracle数据库的DB所写的快速学会MySql,为什么敢这么说,是因为本人认为Oracle在功能性方 ...

  8. [教程] [承風雅傳HSU]用ES4封裝Win7---ES4 Win7封裝教程(未完待續)

    [教程] [承風雅傳HSU]用ES4封裝Win7---ES4 Win7封裝教程(未完待續) a10036it 发表于 2015-7-27 21:11:19 https://www.itsk.com/t ...

  9. golang在linux下的开发环境部署[未完]

    uname -a Linux symons_laptop 4.8.2-1-ARCH #1 SMP PREEMPT Mon Oct 17 08:11:46 CEST 2016 x86_64 GNU/Li ...

  10. [python]爬代理ip v2.0(未完待续)

    爬代理ip 所有的代码都放到了我的github上面, HTTP代理常识 HTTP代理按匿名度可分为透明代理.匿名代理和高度匿名代理. 特别感谢:勤奋的小孩 在评论中指出我文章中的错误. REMOTE_ ...

随机推荐

  1. sql时间区间查询性能测试

    这个测试针对"一个月"的区间来查询数据.分datetime类型和nvachar类型. 先比较datetime类型: 一.datediff函数 declare @beginTime ...

  2. sql查询结果多对多转为一对多返回前端

    企业表 ent_EnterpriseArchives  有id,企业名称 entName veh_Vehicle 车辆表,有所属企业id  companyId,车辆id,车牌号licPlate 目的是 ...

  3. echarts解决一些大屏图形配置方案汇总

    本文主要记录使用echarts解决各种大屏图形配置方案. 1.说在前面 去年经常使用echarts解决一些可视化大屏项目,一直想记录下使用经验,便于日后快速实现.正好最近在整理文档,顺道一起记录在博客 ...

  4. sass文件处理

    sass注释方式有两种: 1.标准的css注释/**/: 2.//双斜杠形式的单行注释(不会被转译): 标准的css注释 双斜杆单行注释 sass文件后缀名有两种: 1.后缀名为sass,不适用用大括 ...

  5. 关于React的生命周期的解释

    ---恢复内容开始--- ---恢复内容结束---

  6. css 小常识

    一.vertical-align可以采用负值(正/负值根据基线上下移动),也可以采用百分比值,而这个百分比值不是相对于字体大小或者其他什么属性计算的,而是相对于line-height计算的. 此外,w ...

  7. Appium 如何模拟返回按键

    from appium.webdriver import Remote driver.keyevent(4) python中点击返回键是这样写的 附录 keycode 电话键 KEYCODE_CALL ...

  8. java中加密的方式概述

    加密是用一种特殊的算法改变原有的数据,使未经授权的用户即使获得了已经加密的信息,但不知其解密的方法,仍然无法了解信息的内容.     大体上分为单向加密和双向加密,双向加密又可分为对称加密和非对称加密 ...

  9. Siebel Tools配置

    默认安装的Siebel+Tools,Tools登陆时有3个选项:Local.Sample.Server,具体涵义如下: Local:指本地数据库.按照Siebel开发建议,开发人员需要从Siebel ...

  10. Linux下Vue项目搭建karma测试框架

    前提:vue项目已创建,node.js.npm已安装 1.全局安装karma脚手架 karma-cli  [貌似可以不安装] #npm i -g karma-cli 2.转到Vue项目目录,项目下安装 ...