|
Как с точным периодом выдавать данные в порт работая с FreeRTOS?, на кристале AT91SAM7X256 |
|
|
|
Dec 10 2006, 22:22
|
Участник

Группа: Участник
Сообщений: 70
Регистрация: 5-12-06
Пользователь №: 23 146

|
Помогите, пожалуйста.
Ситуация следующая: на базе примера 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мкс. То-есть, иногда, период не соблюдается, при этом, при весьма ощутимом разбросе. В чём могла бы быть проблема? Как это можна побороть?
|
|
|
|
|
 |
Ответов
(1 - 6)
|
Dec 11 2006, 08:01
|
Частый гость
 
Группа: Участник
Сообщений: 128
Регистрация: 5-10-06
Пользователь №: 20 997

|
Цитата(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 стало нормально.
|
|
|
|
|
Dec 11 2006, 16:30
|
Участник

Группа: Участник
Сообщений: 70
Регистрация: 5-12-06
Пользователь №: 23 146

|
Цитата(zltigo @ Dec 11 2006, 14:35)  "Проблема" во невложенности прерываний. Вешайте свои 100us на FIQ, как уже советовали. Ну что же, перейду на FIQ. Но всё таки (для общего образования), почему же не работает вложенность? Может я неправильно понял даташит, но в пункте 23.7.3.2 Interrupt Nesting (а также чуть выше по тексту) расписано, что при появлении прерывания с высшим приоритетом (а я поставил 7, а все остальные понизил) текущее прерывание кидается в стек и его обработка приостанавливается. Там даже стек специальный на 8 прерываний имеется.
|
|
|
|
|
Dec 11 2006, 16:41
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(OlegHmt @ Dec 11 2006, 15:30)  но в пункте 23.7.3.2 Interrupt Nesting (а также чуть выше по тексту) расписано, что Это в том случае, если Вы лично так все обработчики прерываний написали. Само по себе оно так не работает - аппаратный стек один. Простой и абсолютно правильный как раз для Вашего случая FIQ - и стек свой и регистров собственных немножко имеется. Тут правда есть одна засада - в штатном варианте ENTER_CRITICAL внутри используется банальный __disable_interrupt() запрещающий и IRQ и FIQ - в Вашем случае надо заменить на запрет только IRQ, иначе останется джиттер на критических секциях.
Сообщение отредактировал zltigo - Dec 11 2006, 17:20
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 11 2006, 17:23
|
Участник

Группа: Участник
Сообщений: 70
Регистрация: 5-12-06
Пользователь №: 23 146

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

Группа: Участник
Сообщений: 70
Регистрация: 5-12-06
Пользователь №: 23 146

|
Начал переходить на FIQ с IRQ и столкнулся с проблемой - под операционной системой не хочет работать. Что переделал по сравнению с работающим IRQ: - выделил под стек FIQ 100 байт; - поставил на место вектора FIQ прерывания LDR PC, [PC, -0x20] (пишу по памяти, так как код на другой машине, но скопировал с даташита); - записал в SVC[0] адрес обработчика прерываний; - разрешил для прерывания от таймера fast forcing; - добавил в обработчике запись в ICCR. Если запускаю прерывание и зацикливаю програму в простом бесконечном цикле - всё работает и периодически выводит в порт. Если же пробую запустить FreeRTOS - то всё зависает. Похоже, что один раз в прерывание заходит, но потом всё виснет. Подозрения что как-то неправильно обрабатываю сохранение/возобновление регистров (оставил как и в IRQ portENTER_SWITCHING_ISR(); ... portEXIT_SWITCHING_ISR(pdFalse)  , но может и что-то ещё забыл. В принципе, сейчас с этим пробую разобраться своими силами, но может кто-то уже сталкивался с реализацией FIQ для FreeRTOS и подскажет что я мог забыть.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|