Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: uOS и MultiCore
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы
Digi
Пытаюсь запустить несколько различных задач на uOS которая поставляется совместно с пакетом MCStudio, но работает не так как ожидалось.

Собственно никакой многозадачности не наблюдаю. Работает только та задача у которой наивысший приоритет. (В данном случае task ).

Что я хотел получить: должны мигать три светодиода, и по приходу данных с UART должен заходить в обработчик uart_intr_hdl.

Вроде как такая конструкция на RTOS STM32 работает корректно, но тут, на uOS никак не желает.

Что я делаю не так ???


Код
bool_t uart_intr_hdl(void *arg)
{
    ch = get_received_byte(1);
    LedTgl(1);
    return 1;
}

void task1 (void *arg)
{
    for(;;)
    {
        LedTgl(8);
        udelay(30000);
    }
}

void task2 (void *arg)
{
    for(;;)
    {
        LedTgl(4);
        udelay(40000);
    }
}



void task (void *arg)
{
    setup_baud_rate (1, KHZ, 115200);

    mutex_lock_irq (&receiver, RECEIVE_IRQ (1), &uart_intr_hdl, 0);
    enable_receiver (1);
    enable_receive_interrupt (1);

    transmit_byte(1, '*');

    for (;;)
    {
        udelay(50000);
        LedTgl(2);
    } // for(;;)
}




void uos_init (void)
{
    SYS_REG.CLK_EN.data = 0xFFFFFFFF; // включение тактовой частоты  _init_ включает только минимум частот

    LedInit();
    MFBSP2.DIR.data = 0x3ff;       // переключаем LDAT2[7:4] в режим выхода

    task_create (task1, 0, "task1", 1,  task1_space, sizeof (task1_space));
    task_create (task2, 0, "task2", 2,  task2_space, sizeof (task2_space));

    task_create (task, "task", "task", 3, task_space, sizeof (task_space));
}
Tarbal
Для того чтобы переключались задачи надо, чтобы ядро получало управление и задачи с более высоким приоритетом засыпали.
Я лет 15 назад работал с этой операционкой и не помню: udelay() вызывает ядро?
vatilin
Добрый день!


В uOS реализован только приоритетный планировщик. Это значит, что никакой "карусели" ("round robin") нет. То есть всегда работает задача с наивысшим приоритетом. Если нет таких, то - фоновая задача.
Есть объяснение, почему именно так:
1) это сокращает время реакции на событие для приоритетных задач;
2) системный таймер не является обязательной частью прикладных программ под uOS; есть проекты, где он успешно не используется.

Теперь конкретно, что в Вашем примере не так. Функция udelay отмеряет время "в коротком цикле", то есть процессор при этом постоянно задействован. uOS считает, что у приоритетной задачи есть работа, и поэтому не переключается на другие задачи. Ещё другими словами напишу, udelay (так же, как и mdelay) не является "точкой ожидания".
Что делать - заменить на функцию задержки, которая является точкой ожидания - timer_delay(). Для этого нужно сначала проинициализировать системный таймер - см. код ниже.

Код
#include <timer/timer.h>

timer_t timer;

void task1 (void *arg)
{
    for(;;)
    {
        LedTgl(8);
        timer_delay(&timer, 30);  // Вместо udelay(30000), для других задач - аналогично.
    }
}

void uos_init()
{
     timer_init(&timer, KHZ, 10);  // период тика - 10 мс.

     // ...
}


Второй параметр timer_init - константа KHZ, которая выражает частоту ядра в килогерцах и задаётся в настройках проекта. Практически всегда на месте второго параметра должна стоять именно эта константа. Ещё можно было бы выбросить из интерфейса функции, но исторически уже так сложилось.
Третий параметр - период тика таймера в миллисекундах. Это величина должна быть меньше используемых в коде задержек.

Функции задержки "в коротком цикле" (udelay, mdelay) нужны для отработки коротких задержек без переключения задачи. Надо понимать, что они не очень точные, особенно при малых временах задержки. И, наоборот, если величина в микросекундах сильно больше 1000, то очень желательно применять mdelay вместо udelay, поскольку на разных архитектурах не гарантируется, что большие величины поместятся в тип параметра функции и что корректно написан код udelay для больших значений параметра.

P.S. Скажу ещё, что на самом деле, можно реализовать "карусель", но на основе коллективной многозадачности задач с одинаковым приоритетом с помощью функции task_yield(). То есть задача, отработав некий код сама по своей инициативе с помощью этой функции отдаёт управление другой задаче с тем же приоритетом.
jcxz
Цитата(Digi @ Feb 21 2018, 14:13) *
Что я делаю не так ???
for(;;)
{
LedTgl(8);
udelay(30000);
}

Так писать под ОС нельзя. Ни под какую ОС. Задача должна отдавать неиспользуемое время системе.
Digi
С этим разобрался. Заработало. Спасибо всем ответившим. Отдельное спасибо vatilin за подробные объяснения.
По поводу задержки, я ее ставил просто как задержку. В реальной программе так не пишу. Ну и посмотрел я реализацию udelay в uOS, оказалось что она просто тупо ждет, и к сожалению она не аналог Sleep в RTOS.
Теперь разбираюсь с прерываниями.... вроде как работают, но пока еще не привычно для меня.
jcxz
Цитата(Digi @ Feb 26 2018, 08:48) *
к сожалению она не аналог Sleep в RTOS.

OSTimeDly()

Цитата(Digi @ Feb 26 2018, 08:48) *
Теперь разбираюсь с прерываниями.... вроде как работают, но пока еще не привычно для меня.

К прерываниям uCOS вообще никакого отношения не имеет. Кроме PendSV и немножко SysTick.
Digi
Цитата(jcxz @ Feb 26 2018, 15:35) *
К прерываниям uCOS вообще никакого отношения не имеет. Кроме PendSV и немножко SysTick.


У меня uOS а не uCOS, они немного разные как мне кажется.

В uOS за обработку прерываний отвечают функции:
mutex_lock_irq () Захват прерывания
mutex_unlock_irq () Освобождение прерывания
mutex_wait () Ожидание прерывания
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.