Что такое передача параметра в стек в RTOS? - PullRequest
1 голос
/ 16 декабря 2010

Я новичок в 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);

// ^ Передача параметра является задачей.

  • Я знаю, как определить стек в обычном программировании на Си. Но в RTOS я не понял, что стек, который вы определяете, должен находиться в области, которую процессор может использовать в качестве стека ?

Ответы [ 2 ]

2 голосов
/ 16 декабря 2010

Похоже, вы используете embOS - в этой RTOS есть 2 основных способа запуска задачи.Один (вариант «Ex») передаст параметр void*, указанный вами в API.Другой способ запуска задачи не будет передавать параметр в вашу задачу.

Поскольку все, что вам нужно пройти, это void* (если вы выбрали этот метод), обычно происходит заполнение.структура с информацией для задачи и передачей указателя на эту структуру в качестве параметра.Это позволяет вам делать что-то вроде одной задачи, которая управляет вводом / выводом UART, и передавать указатель на структуру, которая описывает порты ввода / вывода для конкретного экземпляра 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);

Для вашего второго вопроса:

По стеку я не понял, что вы определяете, должен ли он находиться в области, которую ЦП может фактически использовать в качестве стека?

Все, что подразумевается под этим, состоит в том, чторазличные диапазоны памяти, которые могут иметь специальное использование.На некоторых микроконтроллерах стек будет работать только на определенных диапазонах памяти.Например, это описывает стек 8051 :

8-битный указатель стека 8051 ограничен частью внутренней оперативной памяти между 0x08 и 0xFF, хотя для использования всехВ этом месте программист должен отказаться от использования двух банков регистров, а также области с битовой адресацией.Поэтому более нормально ограничивать указатель стека областью от 0x30 и выше, оставляя только 192 байта стекового пространства

0 голосов
/ 16 декабря 2010

Вы пропустили некоторые части. Как вы можете видеть, нет прототипа для OS_CREATETASK_EX и прототип выше OS_CreateTaskEx нуждается в большем количестве параметров.

Очевидно, что верхний регистр - это что-то вроде макроса

OS_TASK * pTask, char * pName, приоритет без знака, voidRoutine * pRoutine, void * pStack, без знака StackSize, без знака char TimeSlice, void * pContext);

если мы посмотрим, подумаем, то увидим: указатель на функцию, которая не возвращает ничего не требуется чем у нас есть StackSize (который, кажется, место для резервирования пространства стека. однако, нет параметра с именем argumentsVorVoidRoutine * arg, единственное, что есть, - это pContext. Я предполагаю, что это будет соответствовать вышеуказанному (void *) 200.

Мы никогда не узнаем, какой тип параметра примет процедура, поэтому мы используем void *, который может быть любым указателем. Я бы немного предостерегал насчет того, чтобы просто взять целое число и привести его к void *, но это C. Так что, может быть, мы должны жить с ним вечно; -)

Кажется, вы можете выделить некоторую область ОЗУ в так называемый стек, и в нижнем примере этот указатель стека называется StackLP. Не видя реального кода, мы все еще можем предположить ...

...