Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как с точным периодом выдавать данные в порт работая с FreeRTOS?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
OlegHmt
Помогите, пожалуйста.

Ситуация следующая: на базе примера LwIP для rowley из пакета FreeRTOS разрабатываю свою програму. Одна из основных её задач вывод в порт SPI данные из памяти кристала с заданным периодом. Я организовал это с помощью timer/counter используя прерывание по сравнению с регистром С таймера. Задавая значение регистра C от 400 до 4000 при тактировании таймера в половину частоты ядра (48 МГц) я по прерыванию выбрасываю с помощью DMA 6 значений в порт. Так при значении регистра 700 я, приблизительно, получаю 30 000 посылок в секунду. Прерывание таймера я поставил с приоритетом 7 и понизил прерывание тиков FreeRTOS до 6. То-есть моё прерывание должно бы обрабатываться в первую очередь. В самом прерывании минимум действий - передача данных из памяти в буфер, запуск передачи через DMA и выход. Паралельно исполняються ещё три задачи (две по работе с USB) и одна по выводу картинки на LCD экранчик (у меня плата разработчика Olimex).
Проблема в том, что когда я смотрю осцилографом сигнал на выходе ножки выбора чипа SPI я вижу четкие импульсы с периодом 100 мкс, но, при этом, также видно слабое мельтешение импулься на фоне в диапазоне приблизительно +-20мкс. То-есть, иногда, период не соблюдается, при этом, при весьма ощутимом разбросе. В чём могла бы быть проблема? Как это можна побороть?
Paramon
Цитата(OlegHmt @ Dec 10 2006, 22:22) *
Помогите, пожалуйста.

Ситуация следующая: на базе примера LwIP для rowley из пакета FreeRTOS разрабатываю свою програму. Одна из основных её задач вывод в порт SPI данные из памяти кристала с заданным периодом. Я организовал это с помощью timer/counter используя прерывание по сравнению с регистром С таймера. Задавая значение регистра C от 400 до 4000 при тактировании таймера в половину частоты ядра (48 МГц) я по прерыванию выбрасываю с помощью DMA 6 значений в порт. Так при значении регистра 700 я, приблизительно, получаю 30 000 посылок в секунду. Прерывание таймера я поставил с приоритетом 7 и понизил прерывание тиков FreeRTOS до 6. То-есть моё прерывание должно бы обрабатываться в первую очередь. В самом прерывании минимум действий - передача данных из памяти в буфер, запуск передачи через DMA и выход. Паралельно исполняються ещё три задачи (две по работе с USB) и одна по выводу картинки на LCD экранчик (у меня плата разработчика Olimex).
Проблема в том, что когда я смотрю осцилографом сигнал на выходе ножки выбора чипа SPI я вижу четкие импульсы с периодом 100 мкс, но, при этом, также видно слабое мельтешение импулься на фоне в диапазоне приблизительно +-20мкс. То-есть, иногда, период не соблюдается, при этом, при весьма ощутимом разбросе. В чём могла бы быть проблема? Как это можна побороть?


Работаю с Aduc 7024. как стал использовать вместо _irq _fiq стало нормально. smile.gif
zltigo
Цитата(OlegHmt @ Dec 10 2006, 21:22) *
В чём могла бы быть проблема? Как это можна побороть?

"Проблема" во невложенности прерываний. Вешайте свои 100us на FIQ, как уже советовали.
OlegHmt
Цитата(zltigo @ Dec 11 2006, 14:35) *
"Проблема" во невложенности прерываний. Вешайте свои 100us на FIQ, как уже советовали.


Ну что же, перейду на FIQ.
Но всё таки (для общего образования), почему же не работает вложенность? Может я неправильно понял даташит, но в пункте 23.7.3.2 Interrupt Nesting (а также чуть выше по тексту) расписано, что при появлении прерывания с высшим приоритетом (а я поставил 7, а все остальные понизил) текущее прерывание кидается в стек и его обработка приостанавливается. Там даже стек специальный на 8 прерываний имеется.
zltigo
Цитата(OlegHmt @ Dec 11 2006, 15:30) *
но в пункте 23.7.3.2 Interrupt Nesting (а также чуть выше по тексту) расписано, что

Это в том случае, если Вы лично так все обработчики прерываний написали. Само по себе оно так не работает - аппаратный стек один. Простой и абсолютно правильный как раз для Вашего случая FIQ - и стек свой и регистров собственных немножко имеется.

Тут правда есть одна засада - в штатном варианте ENTER_CRITICAL внутри используется банальный
__disable_interrupt() запрещающий и IRQ и FIQ - в Вашем случае надо заменить на запрет только IRQ, иначе останется джиттер на
критических секциях.
OlegHmt
Цитата(zltigo @ Dec 11 2006, 15:41) *
Это в том случае, если Вы лично так все обработчики прерываний написали. Само по себе оно так не работает - аппаратный стек один. Простой и абсолютно правильный как раз для Вашего случая FIQ - и стек свой и регистров собственных немножко имеется.

Тут правда есть одна засада - в штатном варианте ENTER_CRITICAL внутри используется банальный
__disable_interrupt() запрещающий и IRQ и FIQ - в Вашем случае надо заменить на запрет только IRQ, иначе останется джиттер на
критических секциях.



Понятно. Буду переходить на FIQ. Кстати, похоже, что именно ENTER_CRITICAL и был причиной моих бед. Правда сейчас кода под рукой нету. Вечером приду домой проверю.

Спасибо
OlegHmt
Начал переходить на FIQ с IRQ и столкнулся с проблемой - под операционной системой не хочет работать.
Что переделал по сравнению с работающим IRQ:
- выделил под стек FIQ 100 байт;
- поставил на место вектора FIQ прерывания LDR PC, [PC, -0x20] (пишу по памяти, так как код на другой машине, но скопировал с даташита);
- записал в SVC[0] адрес обработчика прерываний;
- разрешил для прерывания от таймера fast forcing;
- добавил в обработчике запись в ICCR.

Если запускаю прерывание и зацикливаю програму в простом бесконечном цикле - всё работает и периодически выводит в порт. Если же пробую запустить FreeRTOS - то всё зависает. Похоже, что один раз в прерывание заходит, но потом всё виснет. Подозрения что как-то неправильно обрабатываю сохранение/возобновление регистров (оставил как и в IRQ portENTER_SWITCHING_ISR(); ... portEXIT_SWITCHING_ISR(pdFalse)wink.gif, но может и что-то ещё забыл.

В принципе, сейчас с этим пробую разобраться своими силами, но может кто-то уже сталкивался с реализацией FIQ для FreeRTOS и подскажет что я мог забыть.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.