Embedded 嵌入式代码中的事件处理
我想知道嵌入式系统代码中如何使用事件 主要目的是了解如何准确地在代码中设置/重置事件标志。以及如何识别哪个任务正在使用哪个事件标志,以及每个任务正在设置/重置标志的哪些位 请提出你的建议或意见 提前谢谢Embedded 嵌入式代码中的事件处理,embedded,event-handling,Embedded,Event Handling,我想知道嵌入式系统代码中如何使用事件 主要目的是了解如何准确地在代码中设置/重置事件标志。以及如何识别哪个任务正在使用哪个事件标志,以及每个任务正在设置/重置标志的哪些位 请提出你的建议或意见 提前谢谢 (编辑1:从以下答案中的澄清中复制) 抱歉,没有指定所需的详细信息。实际上,我对使用vxworks/Itron/OSEK操作系统用C语言编写的任何应用程序的分析都感兴趣。例如,vxworks中有支持事件处理的eventLib库。我想知道如何利用这样的系统例程来处理任务中的事件。什么是事件标志(
(编辑1:从以下答案中的澄清中复制)
抱歉,没有指定所需的详细信息。实际上,我对使用vxworks/Itron/OSEK操作系统用C语言编写的任何应用程序的分析都感兴趣。例如,vxworks中有支持事件处理的eventLib库。我想知道如何利用这样的系统例程来处理任务中的事件。什么是事件标志(是全局/本地…还是什么?),如何设置任何事件标志的位,以及任务和事件标志之间的可能关系 任务如何在AND或模式下等待多个事件?? 我遇到了一个例子,下面给出的场景看起来很危险,但为什么
Scenarios is ==> *[Task1 : Set(e1), Task2 : Wait(e1) and Set(e2), Task3 : Wait(e2) ]*
我知道一个任务等待的多个事件标志或多个任务之间的循环依赖(死锁)在任务-事件关系中是危险的情况,但上述情况有多危险,我不明白……请解释一下
(Are there any more such scenarios possible in task-event handling which should be reviewed in code ?? )
我希望以上信息足够……这个问题需要提供更多的背景。嵌入式系统可以使用多种语言、操作系统(包括非操作系统)、框架等创建。嵌入式系统中事件的创建和处理方式没有通用性,正如在一般的计算中如何创建和处理事件并没有通用性一样。这个问题需要提供更多的上下文。嵌入式系统可以使用多种语言、操作系统(包括非操作系统)、框架等创建。嵌入式系统中事件的创建和处理方式没有通用性,正如在一般的计算中如何创建和处理事件没有通用性一样。许多嵌入式系统使用中断服务例程(ISR)来处理事件。您可以为给定的“标志”定义ISR,并在处理事件后重置该标志 例如,假设您有一个执行模数转换(ADC)的设备。在设备上,您可以有一个ISR,每次ADC完成转换时触发,然后在ISR内处理,或者通知其他任务数据可用(如果您希望通过某些通信协议发送数据)。完成后,您将重置ADC标志,以便它可以在下一次转换时再次触发
通常,设备手册中定义了一组ISR。有时,它们提供通用标志,您也可以根据需要处理这些标志。每次重置导致例程触发的标志时。许多嵌入式系统使用中断服务例程(ISR)来处理事件。您可以为给定的“标志”定义ISR,并在处理事件后重置该标志 例如,假设您有一个执行模数转换(ADC)的设备。在设备上,您可以有一个ISR,每次ADC完成转换时触发,然后在ISR内处理,或者通知其他任务数据可用(如果您希望通过某些通信协议发送数据)。完成后,您将重置ADC标志,以便它可以在下一次转换时再次触发
通常,设备手册中定义了一组ISR。有时,它们提供通用标志,您也可以根据需要处理这些标志。每次重置导致例程触发的标志时。很抱歉没有指定所需的详细信息。实际上,我对使用vxworks/Itron/OSEK操作系统用C语言编写的任何应用程序的分析都感兴趣。 例如,vxworks中有支持事件处理的eventLib库。 我想知道如何利用这样的系统例程来处理任务中的事件。什么是事件标志(是全局/本地…还是什么?),如何设置任何事件标志的位,以及任务和事件标志之间的可能关系
我希望以上信息足够……很抱歉没有指定所需的详细信息。实际上,我对使用vxworks/Itron/OSEK操作系统用C语言编写的任何应用程序的分析都感兴趣。 例如,vxworks中有支持事件处理的eventLib库。 我想知道如何利用这样的系统例程来处理任务中的事件。什么是事件标志(是全局/本地…还是什么?),如何设置任何事件标志的位,以及任务和事件标志之间的可能关系
我希望上面的信息足够了……VxWorks中的eventLib类似于unix中的signal()——它可以向不同的线程指示发生了什么。如果需要随事件传递数据,则可能需要使用消息队列 事件在发送方和接收方之间是“全局”的。由于每个发送方都指示事件用于哪个任务,因此系统中可能有多个事件掩码,每个发送方/接收方对都有自己的解释 一个基本的例子:
#define EVENT1 0x00000001
#define EVENT2 0x00000002
#define EVENT3 0x00000004
...
#define EVENT_EXIT 0x80000000
/* Spawn the event handler task (event receiver) */
rcvTaskId = taskSpawn("tRcv",priority,0,stackSize,handleEvents,0,0,0,0,0,0,0,0,0,0);
...
/* Receive thread: Loop to receive events */
STATUS handleEvents(void)
{
UINT32 rcvEventMask = 0xFFFFFFFF;
while(1)
{
UINT32 events = 0;
if (eventReceive(rcvEventMask. EVENTS_WAIT_ANY, WAIT_FOREVER, &events) == OK)
{
/* Process events */
if (events & EVENT1)
handleEvent1();
if (events & EVENT2)
handleEvent2();
...
if (events & EVENT_EXIT)
break;
}
}
return OK;
}
事件发送器通常是硬件驱动程序(BSP)或其他线程。当期望的操作发生时,驱动程序构建所有相关事件的掩码,并将它们发送给接收方任务
发送方需要获取接收方的taskID。taskID可以是全局
int RcvTaskID = ERROR;
...
eventSend(RcvTaskID, eventMask);
接收方可以将其注册到驱动程序/发送方任务中
static int RcvTaskID = ERROR;
void DRIVER_setRcvTaskID(int rcvTaskID)
{
RcvTaskID = rcvTaskID;
}
...
eventSend(RcvTaskID, eventMask);
或者,驱动程序/发送方任务可以调用接收方API方法来发送事件(包装器)
VxWorks中的eventLib类似于unix中的signal()——它可以向不同的线程指示发生了什么。如果需要随事件传递数据,可能需要使用消息队列
static int RcvTaskID;
void RECV_sendEvents(UINT32 eventMask)
{
eventSend(RcvTaskID, eventMask);
}
unsigned char bit_flags = 0;
#define TIMER_EXPIRED 0x01 // 0000 0001
#define DATA_READY 0x02 // 0000 0010
#define BUFFER_OVERFLOW 0x04 // 0000 0100
// Bitwise OR: bit_flags | 00000001 sets the first bit.
bit_flags |= TIMER_EXPIRED; // Set TIMER_EXPIRED bit.
// Bitwise AND w/complement clears bits: flags & 11111101 clears the 2nd bit.
bit_flags &= ~DATA_READY; // Clear DATA_READY bit.
// Bitwise AND tests a bit. The result is BUFFER_OVERFLOW
// if the bit is set, 0 if the bit is clear.
had_ovflow = bit_flags & BUFFER_OVERFLOW;
// Set DATA_READY and BUFFER_OVERFLOW bits.
bit_flags |= (DATA_READY | BUFFER_OVERFLOW);
#define SET_BITS(bits, data) data |= (bits)
#define CLEAR_BITS(bits, data) data &= ~(bits)
#define CHECK_BITS(bits, data) (data & (bits))