1

我是 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);

// ^ 这是传递参数是一个任务。

  • 我知道在普通的 C 编程中定义一个堆栈。但是在 RTOS 中,我不明白您定义的堆栈必须驻留在 CPU 实际可以用作堆栈的区域中吗?
4

2 回答 2

2

看起来您正在使用 embOS - 在 RTOS 中,有 2 种通用方法来启动任务。一个(“Ex”变体)将传递void*您在 API 中指定的参数。启动任务的另一种方式不会将参数传递给您的任务。

由于您所传递的只是一个void*(如果您选择了该方法),通常会发生的是您将使用任务信息填充一个结构并将指向该结构的指针作为参数传递。这使您可以执行诸如管理 UART I/O 的单个任务函数之类的操作,并将指针传递给描述特定 UART 实例的 I/O 端口的结构。这样,单个函数可以处理设备上的所有 UART,方法是为每个 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实际上可以用作堆栈的区域中吗?

这意味着一些微控制器具有不同的内存范围,可能有特殊用途。在某些微控制器上,堆栈仅适用于某些内存范围。例如,这描述了 8051 的堆栈

8 位 8051 堆栈指针被限制在 0x08 和 0xFF 之间的内部 RAM 部分,但要使用所有这些空间,程序员必须放弃使用两个寄存器组以及位寻址区域。因此,将堆栈指针限制为从 0x30 向上的区域是比较正常的,只留下 192 字节的堆栈空间

于 2010-12-16T06:30:01.187 回答
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 匹配。

我们永远不会知道例程将采用什么参数类型,因此我们使用可以是任何指针的 void*。对于只取一个整数并将其强制转换为 void* ,我会有点谨慎,但它是 C。好吧,也许我们应该永远忍受它;-)

似乎您可以将 RAM 的某些区域放入所谓的堆栈中,在下面的示例中,此堆栈指针被命名为 StackLP。在没有看到实际代码的情况下,我们仍然可以假设......

于 2010-12-16T06:28:44.370 回答