我是RTOS的新手,在C / C ++的系统端(应用程序端)编程方面有几个月的经验。但是进入这个嵌入式领域,我几乎没有遇到任何问题。
将参数传递给任务是什么意思?我不明白下面给出的例子。
static void TaskEx(void* pData) {
while (1) {
OS_Delay ((OS_TIME) pData);
}
}
void OS_CreateTask ( OS_TASK * pTask,char * pName,unsigned char Priority,voidRoutine * pRoutine,void * pStack,unsigned StackSize,unsigned char TimeSlice );
OS_CreateTask(&TaskMain, NULL, 50, TaskEx, StackMain, sizeof(StackMain), 2);
// ^这不是传递参数是一项任务。
void OS_CreateTaskEx ( OS_TASK * pTask, char * pName, unsigned char Priority, voidRoutine *pRoutine, void * pStack, unsigned StackSize, unsigned char TimeSlice, void * pContext );
OS_CREATETASK_EX(&TCBLP, "LP Task", TaskEx, 50, StackLP, (void*) 200);
// ^这是传递一个参数是一个任务。
答案 0 :(得分:2)
看起来你正在使用embOS - 在RTOS中有两种开始任务的通用方法。一个(“Ex”变体)将传递您在API中指定的void*
参数。启动任务的另一种方法是不会将参数传递给您的任务。
由于您只能传递void*
(如果您选择了该方法),通常会发生的事情是您将使用该任务的信息填充结构并将指针作为参数传递给该结构。这使您可以执行诸如管理UART I / O的单个任务功能,并将指针传递给描述特定UART实例的I / O端口的结构。这样,单个函数可以通过为每个UART启动单独的任务来处理设备上的所有UART,将指针传递给不同的UART描述符(以及任务堆栈的不同内存块)。
令人困惑的是,每个启动任务的机制都有2个API:
在您显示的小示例中,所有任务都是在无限循环中重复延迟。延迟由传递的参数指定(它用作int而不是指向结构的指针)。因此,您可以通过向每个实例传递不同的延迟超时来启动多个任务,每个任务延迟不同的时间段。显然不是一项有用的工作,但它只是为了展示这项技术。
使用此示例的一些代码可能如下所示:
OS_TASK TCB_Task1;
OS_TASK TCB_Task2;
#define SHORT_DELAY 10
#define LONG_DELAY 1000
unsigned int task1_stack[64];
unsigned int task2_stack[64];
// start a task that delays only for 10ms
OS_CreateTaskEx ( &TCB_Task1, "short delay", 20, &TaskEx,
&task1_stack, sizeof(task1_stack), 2, (void*)SHORT_DELAY);
// start a task (using same task function) that delays for 1000ms
OS_CreateTaskEx ( &TCB_Task2, "long delay", 20, &TaskEx,
&task2_stack, sizeof(task2_stack), 2, (void*)LONG_DELAY);
关于你的第二个问题:
我不明白你定义的堆栈必须驻留在CPU实际可以用作堆栈的区域吗?
这意味着一些微控制器具有可能具有特殊用途的不同存储器范围。在某些微控制器上,堆栈仅适用于某些内存范围。例如,this describes the 8051's stack:
8位8051堆栈指针仅限于0x08和0xFF之间的内部RAM部分,但要使用所有这些空间,程序员必须放弃使用两个寄存器库和位可寻址区域。因此,更常见的是将堆栈指针限制在0x30以上的区域,只留下192个字节的堆栈空间
答案 1 :(得分:0)
您省略了一些部分。如您所见,OS_CREATETASK_EX没有原型 OS_CreateTaskEx上面的原型需要更多参数。
很明显,大写的东西是某种宏
OS_TASK * pTask,char * pName,unsigned char Priority,voidRoutine * pRoutine,void * pStack,unsigned StackSize,unsigned char TimeSlice,void * pContext);
如果我们看起来认为我们看到: 指向不返回任何内容的函数的指针是必需的 比我们有一个StackSize(它似乎是保留堆栈空间的地方)。 但是没有名为argumentVorVoidRoutine * arg的参数,唯一有pContext的东西。我假设这将与上面的(void *)200匹配。
我们永远不会知道Routine将采用什么参数类型,因此我们使用void *,它可以是任何指针。关于取一个整数并将其转换为无效,我有点谨慎,但它是C.所以也许我们应该永远忍受它; - )
似乎你可以把一些RAM区域分成所谓的Stack,在下面的例子中,这个Stack指针名为StackLP。在没有看到实际代码的情况下,我们仍然可以假设......