木兰花 发表于 2018-11-6 22:08:05

多个串口中断中发送多个不同的信号量,怎么在一个任务中处理这多个信号量呢?


如题,3个串口中断中发送了3个信号量,我的做法是建立了3个任务来处理这3个信号量,见下面的程序
这样做的好处是简单,明了。只要某个信号量send了相关任务就执行,缺点是建立了3个任务。有没有其他的方式实现下面的功能呢?即把3个任务合成1个,信号send后能及时的执行相关操作
void USART1_IRQHandler(void)
{
if(USART1->SR & (BIT5))                  //接收到数据
{
    isr_sem_send (&semaphore1);
}
}
void USART2_IRQHandler(void)
{
if(USART2->SR & (BIT5))                  //接收到数据
{
    isr_sem_send (&semaphore2);
}
}
void USART3_IRQHandler(void)
{
if(USART3->SR & (BIT5))                  //接收到数据
{
    isr_sem_send (&semaphore3);
}
}

__task void task1(void)
{
while(1)
{
    os_sem_wait (&semaphore1, 0xffff);
    //执行相关操作
    ......
}
}
__task void task2(void)
{
while(1)
{
    os_sem_wait (&semaphore2, 0xffff);
    //执行相关操作
    ......
}
}
__task void task3(void)
{
while(1)
{
    os_sem_wait (&semaphore3, 0xffff);
    //执行相关操作
    ......
}
}

木兰花 发表于 2018-11-7 09:51:20

呼叫各位OS的高手啊

byccc 发表于 2018-11-7 11:05:53

一个任务处理就好了,发事件标志。

myxiaonia 发表于 2018-11-7 11:32:41

byccc 发表于 2018-11-7 11:05
一个任务处理就好了,发事件标志。

完美

木兰花 发表于 2018-11-7 11:44:07

byccc 发表于 2018-11-7 11:05
一个任务处理就好了,发事件标志。


改成这个样子?
这样的话3个消息是轮询每个100ms处理一次的,时效性上比建立3个任务是不是差了点呢?
void USART1_IRQHandler(void)
{
if(USART1->SR & (BIT5))                  //接收到数据
{
    isr_evt_set (0x0001,&task_id);
}
}
void USART2_IRQHandler(void)
{
if(USART2->SR & (BIT5))                  //接收到数据
{
    isr_evt_set (0x0002,&task_id);
}
}
void USART3_IRQHandler(void)
{
if(USART3->SR & (BIT5))                  //接收到数据
{
    isr_evt_set (0x0004,&task_id);
}
}

__task void task(void)
{
OS_RESULT result;
while(1)
{
    result=os_evt_wait_and (0x0001, 0);
    if(result == OS_R_EVT)
    {
      //执行相关操作1
      ......
    }
   
    result=os_evt_wait_and (0x0002, 0);
    if(result == OS_R_EVT)
    {
      //执行相关操作2
      ......
    }
   
    result=os_evt_wait_and (0x0004, 0);
    if(result == OS_R_EVT)
    {
      //执行相关操作3
      ......
    }
    os_dly_wait(100);
}
}

木兰花 发表于 2018-11-7 11:46:17

myxiaonia 发表于 2018-11-7 11:32
完美

这样做效率和时效性上似乎没有建立多个任务要好啊,见我楼上的代码。。

byccc 发表于 2018-11-7 11:54:41

本帖最后由 byccc 于 2018-11-7 11:56 编辑

木兰花 发表于 2018-11-7 11:44
改成这个样子?
这样的话3个消息是轮询每个100ms处理一次的,时效性上比建立3个任务是不是差了点呢?
...
os_evt_wait_or (标志1 | 标志2 | 标志3 | 标志4 .......,延迟时间);

把你的os_dly_wait(100);删掉。

木兰花 发表于 2018-11-7 12:02:48

byccc 发表于 2018-11-7 11:54
os_evt_wait_or (标志1 | 标志2 | 标志3 | 标志4 .......,延迟时间);

把你的os_dly_wait(100);删掉 ...

使用这个函数的话,我不知道具体是哪个标志置位了呢,os_evt_wait_or 只返回:OS_R_EVT,不返回触发这个函数的是哪个标志呢?
result=os_evt_wait_or (标志1 | 标志2 | 标志3 | 标志4 .......,延迟时间);

这里result值一直是OS_R_EVT 啊,怎么得到 标志1或2呢?

byccc 发表于 2018-11-7 12:09:56

木兰花 发表于 2018-11-7 12:02
使用这个函数的话,我不知道具体是哪个标志置位了呢,os_evt_wait_or 只返回:OS_R_EVT,不返回触发这个 ...

悟性略差一下啊。:lol

肯定有函数啊。

木兰花 发表于 2018-11-7 12:44:37

byccc 发表于 2018-11-7 12:09
悟性略差一下啊。

肯定有函数啊。

谢谢谢谢,找到这个函数了:lol
这么做也挺好,少建立一个任务
void USART1_IRQHandler(void)
{
if(USART1->SR & (BIT5))                  //接收到数据
{
    isr_evt_set (0x0001,&task_id);
}
}
void USART2_IRQHandler(void)
{
if(USART2->SR & (BIT5))                  //接收到数据
{
    isr_evt_set (0x0002,&task_id);
}
}
void USART3_IRQHandler(void)
{
if(USART3->SR & (BIT5))                  //接收到数据
{
    isr_evt_set (0x0004,&task_id);
}
}

__task void task(void)
{
u16 flags;
while(1)
{
    if(os_evt_wait_or (0x0007, 10) == OS_R_EVT)
    {
      flags=os_evt_get();
      switch(flags)
      {
      case 0x0001:
      {
          //执行相关操作1
          break;
      }
      case 0x0002:
      {
          //执行相关操作2
          break;
      }
      case 0x0004:
      {
          //执行相关操作3
          break;
      }
      default:break;
      }
    }
}
}




myxiaonia 发表于 2018-11-8 02:04:00

木兰花 发表于 2018-11-7 12:44
谢谢谢谢,找到这个函数了
这么做也挺好,少建立一个任务
收到的可能是多个事件组合

木兰花 发表于 2018-11-8 08:50:11

myxiaonia 发表于 2018-11-8 02:04
收到的可能是多个事件组合

是的,然后再分析是哪个事件发生了,再做相关的动作

laofa 发表于 2018-11-8 09:11:33

用队列消息,然后不同的消息代码代表不同的串口消息。

木兰花 发表于 2018-11-9 08:56:20

laofa 发表于 2018-11-8 09:11
用队列消息,然后不同的消息代码代表不同的串口消息。

嗯,这种方法也挺好,和os_evt_wait_or比哪个更好呢

laofa 发表于 2018-11-9 12:39:29

木兰花 发表于 2018-11-9 08:56
嗯,这种方法也挺好,和os_evt_wait_or比哪个更好呢

我目前就是用这种方法处理不同的消息,把不同功能的消息分类,每个任务处理一类消息,当消息处理完成就进入继续等待消息,这时如果没有消息就会自动阻塞而让出CPU给别的任务,效率很高的。

木兰花 发表于 2018-11-9 15:47:17

laofa 发表于 2018-11-9 12:39
我目前就是用这种方法处理不同的消息,把不同功能的消息分类,每个任务处理一类消息,当消息处理完成就进 ...

是的,和os_evt_wait_or比呢?

laofa 发表于 2018-11-10 00:04:26

木兰花 发表于 2018-11-9 15:47
是的,和os_evt_wait_or比呢?

这个主要是为了同步吧,我只是看过,没有用过这个

木兰花 发表于 2018-11-10 22:43:05

laofa 发表于 2018-11-10 00:04
这个主要是为了同步吧,我只是看过,没有用过这个

嗯,有时间了比较下这2个东西

wkler 发表于 2019-5-23 20:31:02

效率应该是一样的,都是阻塞,等内核通知有事件到来,然后恢复运行,差别在于队列的消息是有先后之分的,然后队列可以保存大量历史消息,事件标志不能保存,可以把标志组看成有1个成员的队列。。

wkler 发表于 2019-5-23 20:31:42

木兰花 发表于 2018-11-10 22:43
嗯,有时间了比较下这2个东西

效率应该是一样的,都是阻塞,等内核通知有事件到来,然后恢复运行,差别在于队列的消息是有先后之分的,然后队列可以保存大量历史消息,事件标志不能保存,可以把标志组看成有1个成员的队列。。
页: [1]
查看完整版本: 多个串口中断中发送多个不同的信号量,怎么在一个任务中处理这多个信号量呢?