互斥信号量与消息队列
static OS_MUTEX AppMutex; //(互斥信号量)
static OS_Q AppQ; //(消息队列)
互斥信号量是一个内核对象(一种数据结构),对于互斥信号量而言,它的共享资源只能被一个任务所访问,
一个任务想要去访问共享的资源必须在它被允许运行前去获得互斥量,并在对资源访问后释放互斥量。
消息队列是中断服务程序和/或其他任务所发送的一个内核对象,发送者将其需要发送的消息送入消息队列之中,而接收者则在消息队列中等待消息的送达,
如果消息一直没有送到,那么接收者将会被一直置于等待与消息队列相关的等待列表之中。
我们可以在主函数中创建互斥量和消息队列,也可以在开始任务中在任务创建之后创建相应的对象。创建代码如下:
/*互斥量创建*/
OSMutexCreate((OS_MUTEX *)&AppMutex,
(CPU_CHAR *)"My App Mutex",
(OS_ERR *)&err);
/* 消息队列的创建 */
OSQCreate((OS_Q *)&AppQ,
(CPU_CHAR *)"My App Queue",
(OS_MSG_QTY )10,
(OS_ERR *)&err);
对于OSMutexCreate(),其第一个参数是互斥量的地址,即在主函数前声明的OS_MUTEX对象,
第二个参数是分配给互斥量的名字,可以方便用户调试使用,
第三个是存放互斥量创建错误标志的返回值。
OSQCreate():第一个参数是消息队列的地址,即OS_Q对象地址。
第二个参数是分配给消息队列的名字,便于调试。
第三个是消息队列允许接收到的消息量的大小,此值必须大于0。如果发送方发送消息的 速度大于接收
方对消息的处理速度的话,那么消息将会丢失。这种情况可以通过对增大消息队列的大小或者增加接收
消息的任务的优先级来进行改正。
/* 向消息队列发送消息并使用共享资源 */
static void Apptask1(void *p_arg)
{
OS_ERR err;
CPU_TS ts;
p_arg = p_arg;
while(1){
/* 延时 */
OSTimeDly((OS_TICK )1,
(OS_OPT )OS_OPT_TIME_DLY,
(OS_ERR *)&err);
/* 向消息队列发送消息 */
OSQPost((OS_Q *)&AppQ,
(void *)1;
(OS_MSG_SIZE )sizeof(void *),
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR *)&err);
/* 等待互斥信号量到达 */
OSMutexPend((OS_MUTEX *)&AppMutex,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS *)&ts,
(OS_ERR *)&err);
/*对共享资源进行操作*/
/* 释放互斥量 */
OSMutexPost((OS_MUTEX *)&AppMutex,
(OS_OPT )OS_OPT_POST_NONE,
(OS_ERR *)&err);
}
}
该任务中使用OSQPost()函数向消息队列AppQ发送消息,发送的内容恒定为1。可根据自己需要设置发送的内容。
然后等待互相信号量,因为互斥信号量与其他任务共享,如果其他任务不释放互斥量那么该任务会永远的等待互斥锁
的释放,第二个参数为(OS_TICK)0即设定永久等待。
当OSMutexPost()返回时,可对共享资源进行操作,此处没有体现出来。当对资源进行操作结束后需要通过
OSMutexPost()释放互斥锁,以便其他任务使用资源。
/* 接收消息队列消息并处理消息 */
static void Apptask2(void *p_arg)
{
OS_ERR err;
void *p_arg;
OS_MSG_SIZE msg_size;
CPU_TS ts;
CPU_TS ts_dalta;
p_arg = p_arg;
while(1){
p_msg = OSQPend((OS_Q *)&AppQ,
(OS_MSG_SIZE *)&msg_size,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS *)&ts,
(OS_ERR *)&err);
ts_dalta = OS_TS_GET() - ts;
}
}
OSQPend()函数第一个参数时消息队列对象的地址,
第二个记录了消息缓存区的大小,
第三个设定为永久等待。
第五个记录消息发送的时间,
第六个时消息接收错误标志的返回值。
对于接收消息任务而言,当消息通过消息队列送达时,p_arg会指向发送过来的消息,即指向发送过来的消息的缓存区,而msg_size则指向该缓冲区的大小,此外我们还可以通过ts(无符号32位数据)与OS_TS_GEt()来确定消息发送到接收过程所需要的时间,其他ts记录了消息发送的时刻而OS_TS_GEt()则获取当前的时刻,此时ts_dalta为两者的差值即接收消息所需要的时间。注意,由于中断服务程序与其他高优先级任务的存在,接收任务并不会里面接收到消息。