在 freertos 中,每个执行线程都被称为”任务”。在嵌入式社区中,对此并没有一个公允的术语,但我更喜欢用”任务”而不是”线程”,因为从以前的经验来看,线程具有更多的特定含义。
创建任务的api函数(可以在tasks.c文件中找到)
basetype_t xtaskcreate( taskfunction_t pxtaskcode, const char * const pcname, const uint16_t usstackdepth, void * const pvparameters, ubasetype_t uxpriority, taskhandle_t * const pxcreatedtask )typedef void (*taskfunction_t)( void * );typedef long basetype_ttypedef unsigned long ubasetype_ttypedef void * taskhandle_t;参数:
pxtaskcode:自己创建的任务函数的函数名,用于指向需要运行的任务
pcname:任务的名字,字符串型,名称可以随意起,一般与函数名相同
usstackdepth:任务堆栈大小(实际上申请到的是这里的4倍,单位为字, 4 个字节),设的太小任务 可能无法运行!
pvparameters:任务函数的参数,不需要传参设为null即可
uxpriority:任务优先级,0~(configmax_priorities-1),数值越大优先级越高,0 代表最低优先级
pxcreatedtask:任务句柄,实际是一个指针,也是任务的任务堆栈
返回值:
pdpass:数值1,任务创建成功,且添加到就绪列表
错误代码:负数,任务创建识别
删除任务的api函数(可以在tasks.c文件中找到)
vtaskdelete( taskhandle_t xtasktodelete )xtasktodelete:要删除的任务的任务句柄
临界区
临界区就是一段在执行的时候不能被中断的代码段。在多任务操作系统里面,对全局变量的操作不能被打断,不能执行到一半就被其他任务再次操作。一般被打断,原因就是系统调度或外部中断。对临界区的保护控制,归根到底就是对系统中断的使能控制。在使用临界区时,关闭中断响应,对部分优先级的中断进行屏蔽,因此临界区不允许运行时间过长。为了对临界区进行控制,就需要使用信号量通信,实现同步或互斥操作。
freertos数据类型(可以在portmacro.h文件找到)
#define portchar char #define portfloat float #define portdouble double #define portlong long #define portshort short #define portstack_type uint32_t #define portbase_type long推荐应用时使用下面这样定义数据类型
typedef int int32_t; typedef short int16_t; typedef char int8_t; typedef unsigned int uint32_t; typedef unsigned short uint16_t; typedef unsigned char uint8_t;前缀初识
freertos 中,定义变量的时候往往会把变量的类型当作前缀,可以一眼知其类型。
char 型变量的前缀是 c
short 型变量的前缀是 s
long 型变量的前缀是 l
复杂的结构体,句柄等定义的变量名的前缀是 x
变量是无符号型的再加前缀 u,是指针变量则加前缀 p
函数名包含了函数返回值的类型、函数所在的文件名和函数的功能,如果是私有的函数则会加一个 prv(private)的前缀。
宏内容是由大写字母表示,前缀是小写字母,表示该宏在哪个头文件定义
任务创建
#include stm32f10x.h#include #include freertos.h#include task.h#define start_task_prio 1 //任务优先级#define start_stk_size 128 //任务堆栈大小taskhandle_t starttask_handler; //任务句柄void start_task(void *pvparameters);//任务函数#define led0_task_prio 2 //任务优先级#define led0_stk_size 50 //任务堆栈大小taskhandle_t led0task_handler; //任务句柄void led0_task(void *p_arg); //任务函数void led_init(void){ gpio_inittypedef gpio_initstructure; //定义结构体变量 rcc_apb2periphclockcmd(rcc_apb2periph_gpioc,enable); //开启时钟 gpio_initstructure.gpio_pin=gpio_pin_0; //选择你要设置的io口 gpio_initstructure.gpio_mode=gpio_mode_out_pp; //设置推挽输出模式 gpio_initstructure.gpio_speed=gpio_speed_50mhz; //设置传输速率 gpio_init(gpioc,&gpio_initstructure); //初始化gpio gpio_setbits(gpioc,gpio_pin_0); //将led端口拉高,熄灭led}int main( void ) { nvic_prioritygroupconfig(nvic_prioritygroup_4);//设置系统中断优先级分组 4 led_init(); //初始化 led //创建开始任务 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 //任务句柄 ); vtaskstartscheduler(); //开启调度}//开始任务函数void start_task(void *pvparameters){ taskenter_critical(); //进入临界区 //创建 led0 任务 xtaskcreate( (taskfunction_t )led0_task, (const char* )led0_task, (uint16_t )led0_stk_size, (void* )null, (ubasetype_t )led0_task_prio, (taskhandle_t* )&led0task_handler ); vtaskdelete(starttask_handler); //删除开始任务 taskexit_critical(); //退出临界区}//led0 任务函数void led0_task(void *pvparameters){ while(1) { if(gpio_readinputdatabit( gpioc, gpio_pin_0)) { gpio_resetbits( gpioc, gpio_pin_0); } else { gpio_setbits( gpioc, gpio_pin_0); } vtaskdelay(400); }}--end--
英国取消PHEV补贴对市场的影响
智能座舱包含哪些功能 智能座舱测试包括哪些方面?
半导体行业的良好发展需要什么?
中航光电车载充电插座可满足您不同规格的充电需求
op07引脚及其功能介绍
FreeRTOS的任务创建与删除
基于CVITEK_CV1821+SOI_K302P的IPC方案
MCU技术发展线路大揭秘,且看中国MCU该如何在竞争激烈的市场中取胜?
小米推出首款电视产品Redmi红米电视,首销价3399元
三星CMOS芯片大涨20%
看看保电网安全的“五只大手”
弱电流源是怎么实现的?咱们来仿个真!
中芯国际公布2020年第3季度财报,单季营收首次突破10亿美元
国内智能床垫自主品牌过硬的质量已完胜国外大牌
中芯国际第四季度财报:净利润3860万美元
基于二极管的限幅电路设计
电动汽车研发成为世界性可持续发展的战略性项目
真正的旗舰,一加3T测评
升压器和逆变器的区别和相似之处
半导体三极管放大电路的工作点