1986ВЕ1Т, иногда не работают прерывания

452 views
Skip to first unread message

Максим

unread,
Aug 22, 2013, 7:29:07 AM8/22/13
to uos-em...@googlegroups.com
Здравствуйте!

Использую последнюю версию. В некоторых случаях прерывания работают, в других нет.

Привожу пример, где прерывания у меня не работают.

С Уважением,
Максим
test_irq.c

Дмитрий Подхватилин

unread,
Aug 26, 2013, 4:15:48 AM8/26/13
to uos-em...@googlegroups.com, lyubimo...@gmail.com
Максим, добрый день!

У меня опять нет платы, поэтому не могу запустить этот пример. А если этот пример перевести на таймер 3, например, будет работать?



четверг, 22 августа 2013 г., 15:29:07 UTC+4 пользователь Максим написал:

Максим

unread,
Aug 26, 2013, 4:45:51 AM8/26/13
to uos-em...@googlegroups.com
Нет, не работает. Выводится только counter reload.
Может Вы сможете мне пояснить ситуацию по поводу assert?

Дмитрий Подхватилин

unread,
Aug 26, 2013, 8:36:47 AM8/26/13
to uos-em...@googlegroups.com, lyubimo...@gmail.com
Сейчас посмотрел поподробнее пример. task_test я бы переписал таким образом:

void task_test(void* arg)
{
    debug_printf("test task init\n");

    mutex_lock(&lock);

    while (1)
    {
        mutex_wait(&lock);
        debug_printf("test irq %d\n", counter);
    }
}

В исходном варианте возможны потери прерываний, поскольку ожидание сделано на незаблокированном мьютексе. По идее, должно и так работать, но будут пропуски прерываний.

Во-вторых, в соответствии со спецификацией на контроллер регистр PSG 16-разрядный. Я не знаю, чему равна константа KHZ, но очень может быть, что она больше 65535. Здесь может быть потеря значимых разрядов, хотя это и не должно было отразиться на результате: прерывания всё равно должны идти.



понедельник, 26 августа 2013 г., 12:45:51 UTC+4 пользователь Максим написал:

Максим

unread,
Aug 26, 2013, 10:13:56 AM8/26/13
to uos-em...@googlegroups.com
Прерывания идут, если нет задачи task_test2, которая не возвращает управление. Прерывание не может перехватить управление, оно просто не срабатывает.

lyubimo...@gmail.com

unread,
Aug 26, 2013, 10:16:03 AM8/26/13
to uos-em...@googlegroups.com, lyubimo...@gmail.com
Возможно оно просто запрещено

Дмитрий Подхватилин

unread,
Aug 27, 2013, 4:07:58 AM8/27/13
to uos-em...@googlegroups.com, lyubimo...@gmail.com
Посмотрю, когда доберусь до платы...

понедельник, 26 августа 2013 г., 18:13:56 UTC+4 пользователь Максим написал:

Дмитрий Подхватилин

unread,
Sep 13, 2013, 5:58:20 AM9/13/13
to uos-em...@googlegroups.com, lyubimo...@gmail.com, Сергей Викторович Вакуленко
Действительно, ошибка была. Сейчас я её поправил. Но не факт, что больше нет других ошибок.
Проблема в том, что в архитектуре Cortex-M1 неудобно сделано маскирование прерываний.
Напомню всю историю.
С помощью регистра PRIMASK маскируются все прерываний и исключения, кроме тех, у которых приоритет отрицательный. К сожалению, исключение, используемое для переключения задач, SVC имеет приоритет 0. Кроме того, если вызывается SVC при PRIMASK=1, то происходит Hard Fault. Поэтому (это ещё ты, Максим, делал) пришлось перейти на PendSV для переключения задач.
Но это не решает основной проблемы: при PRIMASK=1 невозможно переключить задачи!

Я переделал (в предыдущих версиях) маскирование прерываний таким образом:
arm_intr_disable сбрасывает в ноль маску контроллера прерываний NVIC, PRIMASK при этом остаётся равным 0, т.е. переключение задач возможно. При этом старая маска контроллера сохраняется в переменную, указанную в параметре arm_intr_disable.
arm_intr_restore восстанавливает маску NVIC из переменной.
Маска NVIC сохраняется в контексте задачи.

Это работало, если всего одна задача в системе (на этом я и тестировал). Но если несколько задач, то получалось, что маска сохранялась только в контексте самой приоритетной задачи, а в контексте других задач она была равна 0. Соответственно, после переключения на такую задачу, все прерывания оказывались замаскированы.

Чтобы обойти эту проблему, нужно сохранить в начальном контексте каждой задачи маску прерываний в том виде, как она есть при выходе из uos_init. Здесь пришлось пойти на непопулярные меры. Я добавил в kernel/main.c в функцию main() вызов uos_post_init (). Сама функция реализована в том же файле - она пустая, со слабой линковкой.
При необходимости эту функцию можно переопределить в machdep (что и сделано для cortex-m). В этой функции инициализируется контекст каждой задачи правильной маской NVIC.

После всего я вернул переключение задач с PendSV на SVC.

Твой тест test-irq.c с небольшими изменениями добавил в examples. Теперь он работает.


 
вторник, 27 августа 2013 г., 12:07:58 UTC+4 пользователь Дмитрий Подхватилин написал:

Максим

unread,
Sep 18, 2013, 10:46:55 PM9/18/13
to uos-em...@googlegroups.com
А возможно использовать PRIMASK и NMI?

Дмитрий Подхватилин

unread,
Sep 19, 2013, 3:40:27 AM9/19/13
to uos-em...@googlegroups.com, lyubimo...@gmail.com
А можно ли программно вызвать NMI?
Я не нашел. Но даже если можно, то всё равно решение будет кривое (как и то, которое есть сейчас), поскольку приоритет переключения задач будет выше, чем приоритет обработчика ошибок Hard Fault.
У меня ещё была мысль использовать Hard Fault для переключения задач. Его-то можно программно вызвать - искусственное деление на 0, например. Но после этого будет очень тяжело отличить ошибку от запроса на переключение задач.
Мне кажется, из всех зол (то бишь вариантов реализации) то, что сейчас реализовано - наименьшее. Но если есть другие решения и аргументы - давайте обсудим.


четверг, 19 сентября 2013 г., 6:46:55 UTC+4 пользователь Максим написал:

Максим

unread,
Sep 19, 2013, 11:51:54 AM9/19/13
to uos-em...@googlegroups.com
Можно, в том же регистре, где вызывается pendsv.

Дмитрий Калеев

unread,
Dec 5, 2016, 2:23:45 AM12/5/16
to uOS embedded, lyubimo...@gmail.com, se...@vak.ru
Добрый день!

А подскажите как писать в таком случае в eeprom вов ремя работы тасков - для этого надо отключать прерывания. достаточно ли просто вызова arch_intr_disable(&x); выполнять функции из ОЗУ для записи в данных ПЗУ и потом возвращать arch_intr_restore(x);
Ведь маска теперь есть в каждой задаче.
Спасибо за ответ.

пятница, 13 сентября 2013 г., 12:58:20 UTC+3 пользователь Дмитрий Подхватилин написал:

Дмитрий Подхватилин

unread,
Dec 5, 2016, 3:29:47 AM12/5/16
to uOS embedded, Maxim Lyubimov, Сергей Викторович Вакуленко
Добрый день!


С точки зрения пользователя ничего не поменялось. Просто реализация корявая, поэтому я её описал поподробнее.
То есть можно использовать arch_intr_disable. В коде с закрытыми прерываниями нельзя вызывать блокирующие функции (например, mutex_wait), потому что мы никогда не дождёмся события при закрытых масках. Системный таймер при закрытых масках тоже не работает, поэтому поводов для перепланирования задач не будет. Но это и раньше так было.


5 декабря 2016 г., 10:01 пользователь Дмитрий Калеев <aod....@gmail.com> написал:

--
Вы получили это сообщение, поскольку подписаны на группу "uOS embedded".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес uos-embedded+unsubscribe@googlegroups.com.
Чтобы отправлять сообщения в эту группу, отправьте письмо на электронный адрес uos-em...@googlegroups.com.
Чтобы зайти в группу, перейдите по ссылке https://groups.google.com/group/uos-embedded.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Дмитрий Калеев

unread,
Dec 5, 2016, 11:16:43 AM12/5/16
to uOS embedded, lyubimo...@gmail.com, se...@vak.ru
Спасибо за ответ!

Решил не создавать отдельной темы, но отметить интересную особенность. В работе с 1986ВЕ1Т при использовании gcc 4.4.4, которая идет "в комплекте" с uOS (https://github.com/sergev/uos-embedded/wiki/gcc_arm_ru) не работают операции над типом double, из-за этого нельзя воспользоваться встроенными исходниками contrib/math. Смена компилятора на версию arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 5.4.1 решило проблему.

понедельник, 5 декабря 2016 г., 11:29:47 UTC+3 пользователь Дмитрий Подхватилин написал:
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес uos-embedded...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages