Перейти к содержанию
    

vatilin

Новичок
  • Постов

    2
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный
  1. По-моему, проблема в следующем: 1) Сначала мьютекс прикрепляется к прерыванию. Поскольку используется функция mutex_lock_irq, а не mutex_attach_irq, то сразу после выхода из этой функции мьютекс u->receiver захвачен. mutex_lock_irq (&u->receiver, RECEIVE_IRQ(u->port), 0, 0); 2) Поскольку мьютекс захвачен, то после выхода из функции mutex_wait он тоже остаётся захваченным (пока поток находится внутри функции mutex_wait и ожидает события, мьютекс, конечно, освобождается, но обратно автоматически захватывается при выходе из mutex_wait). 3) Далее поток попадает в функцию uart422_rtx_proc, и если выполняется условие: if (test_get_receive_data(u->port, &c)) { mutex_lock(&u->receiver); мьютекс опять захватывается - попытка захватить захваченный мьютекс! Смысла в этой операции нет никакого: мьютекс и так уже захвачен нашей задачей. Это ошибка выполнения при использовании нерекурсивных мьютексов, на этом месте мы должны вылететь по ассерту внутри mutex_lock. Не понимаю, почему этого не происходит. Может быть, в опциях компилятора отключены ассерты. В общем, рекомендация такая: удалить mutex_lock(&u->receiver), mutex_unlock(&u->receiver) из функции uart422_rtx_proc. Мьютекса u->transmitter это не касается, хотя я вижу, что есть вызов mutex_unlock, но не вижу вызова mutex_lock - тоже как-то странно...
  2. Добрый день! В 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(). То есть задача, отработав некий код сама по своей инициативе с помощью этой функции отдаёт управление другой задаче с тем же приоритетом.
×
×
  • Создать...