1、ucos 建立信号量OSSemCreate什么时候计数初值用1,什么时候用0?
我拷贝了之前回答的答案:
OSSemPost 和OSSemPend是成对出现的,在程序OSSemPost 尚未运行到的时候,在等待Sem的
OSSemPend是会把当前的任务挂起,直到另外一个任务的OSSemPost 运行完毕都得到Sem。但是可以通过改变OSSemCreate(x)里面的值x改变这种局面,当x不为0时,OSSemPend会马上得到Sem继续运行当前任务至结束,并将x的数值减一,直到为0。为0后,只有等其他任务的OSSemPost了。
2、在ucos中创建一个信号量 比如ossemcreat(0)。ossemcreat(1)的区别
OSSemPost 和OSSemPend是成对出现的,在程序OSSemPost 尚未运行到的时候,在等待Sem的
OSSemPend是会把当前的任务挂起,直到另外一个任务的OSSemPost 运行完毕都得到Sem。但是可以通过改变OSSemCreate(x)里面的值x改变这种局面,当x不为0时,OSSemPend会马上得到Sem继续运行当前任务至结束,并将x的数值减一,直到为0。为0后,只有等其他任务的OSSemPost了。
3、求助:UCOS互斥信号量的使用
请参考函数说明,初始值,可以取0到65535之间的任何值。===============OSSemCreate()=============== 该函数建立并初始化一个信号量,信号量的作用如下: * 允许一个任务和其他任务或者中断同步 * 取得设备的使用权 * 标志事件的发生 函数原型。
4、在Ucos操作系统下创建信号量的的一个参数(OS_SEM_CTR )1,这个参数设置为1是控制什么的?
是OSSemCreate(0)里面的0吗?
是指信号量的标号,比如任务A等待是信号量是标号为0的信号量,还有标号为1、2......
5、为什么ucos的信号量已经有效了,而等待任务的信号量却不执行
任务2输出5之后,由于等待信号量被挂起,之后任务1输出3,然后发信号量,注意发信号亮并不是简单的+1,OSSemPost中有这几行代码
if (pevent->OSEventGrp != 0) {
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
OS_EXIT_CRITICAL();
OS_Sched();
return (OS_ERR_NONE);
}
此时因为任务2的优先级较1低,所以没有立即运行,而是任务1继续输出4、0然后挂起自己,任务2就运行了,输出678
6、ucos ii建立信号量问题
如果信号量是用来表示一个或者多个事件发生时,初始值通常位0,;当信号量是用来对共享资源的访问,通常为1.如果信号量用来表示任务访问n个相同的资源,初始值为n,n 范围是0-65535
7、ucos的各种信号量都在什么时候调用
#include "INCLUDES.h"
#define TASK_STK_SIZE 512
char *s1="MyTask";
char *s2="YouTask";
INT8U err; //定义一个错误信息
INT8U y=0;
OS_EVENT *Fun_Semp; //声明信号量 是事件控制块ECB类型的
//注意,前面有一个例子2 定义了互斥信号量,定义如下
//BOOLEAN ac_key; //信号量,互斥信号量 实质上就是一个标志位,是一个全局变量,来标志共享资源的访问情况
//这样,当已经有任务访问共享资源时,其他的任务就不能访问,知道该资源未被访问,其他的任务才可以进行访问
//注意这两个信号量的区别和使用情况
OS_STK StartTaskStk[TASK_STK_SIZE]; //定义任务堆栈区
OS_STK MyTaskStk[TASK_STK_SIZE];
OS_STK YouTaskStk[TASK_STK_SIZE];
void Fun(INT8U x,INT8U y);
void StartTask(void *data);
void MyTask(void *data);
void YouTask(void *data);
void main (void)
{
Fun_Semp=OSSemCreate(1); //在主函数中创建信号量 返回值为创建的信号量指针,参数是信号量的计数器的值
//用该参数对信号量计数器OSEventCnt进行初始化
//1即代表只创建一个信号量,代表信号量用于对共享资源的访问(例如,把它当做二值信号量使用),详见P166
OSInit();
PC_DOSSaveReturn();
PC_VectSet(uCOS, OSCtxSw);
OSTaskCreate(StartTask,(void *)0, &StartTaskStk[TASK_STK_SIZE - 1], 0); //创建起始函数
OSStart();
}
void StartTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
INT16S key;
pdata = pdata;
OS_ENTER_CRITICAL();
PC_VectSet(0x08, OSTickISR);
PC_SetTickRate(OS_TICKS_PER_SEC);
OS_EXIT_CRITICAL();
OSStatInit();
OSTaskCreate(MyTask,(void *)0, &MyTaskStk[TASK_STK_SIZE - 1], 1); //创建任务函数
OSTaskCreate(YouTask,(void *)0, &YouTaskStk[TASK_STK_SIZE - 1], 2); //创建任务函数
for (;;)
{
//如果恩下ESC键,则退出UC/OS-II
if (PC_GetKey(&key) == TRUE)
{
if (key == 0x1B)
{
PC_DOSReturn();
}
}
OSTimeDlyHMSM(0,0,3,0);
}
}
//MyTask的函数代码
void MyTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
for (;;)
{
OSSemPend(Fun_Semp,0,&err); //请求信号量 参数Fun_Semp是信号量指针 0那一项是等待时限timeout,0表示无限等待
//err表示错误信息
PC_DispStr(0,++y,s1,DISP_BGND_BLACK+DISP_FGND_WHITE); //显示MyTask字符串
Fun(7,y); //调用Fun函数
OSSemPost(Fun_Semp); //发送信号量 释放信号量,函数的参数Fun_Semp代表信号量的指针
OSTimeDlyHMSM(0,0,1,0);
}
}
void YouTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3 //Allocate storage for CPU status register
OS_CPU_SR cpu_sr;
#endif
pdata=pdata;
for (;;)
{
OSSemPend(Fun_Semp,0,&err); //请求信号量
PC_DispStr(0,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE);
Fun(7,y); //调用FUN函数
OSSemPost(Fun_Semp); //释放信号量
OSTimeDlyHMSM(0,0,2,0); //等待2s
}
}
//公共的函数Fun的代码
void Fun(INT8U x,INT8U y)
{
PC_DispStr(x,y," Calling FUN()",DISP_BGND_BLACK+DISP_FGND_WHITE); //显示字符串,表示调用了Fun函数
}
//创建信号量时,用的参数为1,即Fun_Semp=OSSemCreate(1); ,只创建了一个信号量,这种情况一般是信号量用于对
//共享资源的访问(例如,可以把它当做二值信号量使用)
//在上面的程序中,当MyTask运行时,先请求获得了信号量,对共享资源Fun函数进行访问,由于只创建了一个信号量,
//所以在MyTask的访问期间,即使任务YouTask也进行申请信号量,此时OSEventCnt是值已经为0了,所以会把任务
//YouTask列入任务等代表OSEventTbl[]中,使任务处于等待状态。
//只有等MyTask对Fun函数访问完成了,调用OSSemPost(Fun_Semp);释放了信号量,该释放信号量的函数会先检查任务等待
//表中是否还有等待信号量的任务,如果有,则使任务进入就绪态后,调用调度器OS_Sched()引发一次任务调度,去运行等待
//任务列表中优先级最高的任务。如果没有,则就把信号量计数器OSSemCnt加1.
//所以任务YouTask要想访问Fun()函数,必须等到任务MyTask对Fun访问完毕,释放了信号量之后,才能访问,反之亦然
//所以由上面可以看出,只创建一个信号量,即OSSemCreate(1);,作用就相当于使用一个二值信号量,标志共享资源是否正在
//被访问
//看懂了上面的分析,也就可以解释实验现象了,由于YouTask等待2s,MyTask等待1s,所以有可能在MyTask访问Fan函数期间,YouTask
//也来访问(也有可能是反过来),但是由于信号量已经被MyTask占用了,所YouTask只好等待,MyTask使用完了,释放了信号量,YouTask才能正常使用Fun函数
//这样也就解决了多任务对共享资源的使用的问题,使任务之间得到了同步
//要仔细分析信号量工作的原理,把上面的内容看懂了,基本上也就可以使用信号量了
8、ucosii两任务互发信号量,轮番执行怎么实现?
可以用一个更高优先级的任务来发信号量进行调度,跟你的需求可能不太一样,但是可以实现功能。
9、STM32上运行UCOS建立的信号量为什么最多只有8个?
先看信号量创建函数的源代码
https://doc.micrium.com/display/osiidoc/Semaphore+Management
创建信号量成功与否可以直接从代码里看到
和信号量总数量相关的只有一处就是,从检查 OSEventFreeList表链来判断是否还有可用的资源。由于手头没有完整代码, OSEventFreeList这个表链是什么结构,其初始化代码位置就不确定了。但是可用肯定的是这个表链的初始化长度决定了最多可以分配多少个信号量。
你若需要更多信号量,就需要要修改 OSEventFreeList 初始化代码的相关参数。并且修改该参数后,有可能需要修改其他内存资源分配的部分(没有分析过源代码,所以不确定)。
10、uCOS II的信号量及任务优先级问题求助
任务2输出5之后,由于等待信号量被挂起,之后任务1输出3,然后发信号量,注意发信号亮并不是简单的+1,OSSemPost中有这几行代码
if (pevent->OSEventGrp != 0) {
(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
OS_EXIT_CRITICAL();
OS_Sched();
return (OS_ERR_NONE);
}
此时因为任务2的优先级较1低,所以没有立即运行,而是任务1继续输出4、0然后挂起自己,任务2就运行了,输出678