Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Здравствуйте, у меня это..
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Tanker
Здравствуйте, у меня это.. LPC2364 и IAR 4.42A (32kB лимит)

В программе, 2 UARTa тянут данные из одной области памяти (каждый интерфейс использует MODBUS RTU, в связи с чем, есть прерывания от UART (RX,TX) и от таймера (считает FrameEnd,TimeOut, DIR - переключение драйвера RS485 с приёма на передачу), т.е. образуется группа UART/TIMER) самая длительная операция - разбор принятого пакета (ну там CRC16 посчитать и т.п.)
Добавятся прерывания от АЦП, ШИМа и ещё 2-х таймеров.
Само собой запросы данных поступают асинхронно, и я вижу (наблюдаю на монике осциллограммы полученные от разных интерфейсов) что когда настроенный на более высокий приритет группа UART/TIMER включается в работу, та что с менее высоким- заметно подтормаживает, если задать им одинаковый приоритер, то "дёргаются" оба - теряют байты в основном. По отдельности работают отлично.
Перевожу прогу с MCS51-го, там всё работает идеально (и на асме была прога, и вот сейчас на Сях, одинаково отличный результат) и в основном цикле почти пусто, 99% кода работает в прерываниях.
Если я сейчас 4-ре прерывания подружить не могу, что дальше будет? На 51-м же они друг другу не мешают, ни разу ни где в проге прерывния не запрещал (только при записи флэшки)
Смотрел и много читал о __nested
В арме я так понял пока выполняется IRQ, другие обработчики не могут выполнятся, что теоретически приводит к пропаданиям события прерывания и сбою алгоритма что я у себя и наблюдаю. Пока надежда на __nested и Ваши советы.
Быстродействия АРМа должно с огромным запасом хватать для этой задачи.
Хочу начать с того, как в стартапе прописать код "прыгающий" сразу на мои вектора? тут был пример для SAM
но в асме пока не силён поковырял cstartup.s79 куда там что добавить?
сделал
EXTERN VICADDRESS
..................................................................
org 0x18
; ldr pc,[pc,#24] ; Branch to irq_handler
ldr pc,VICADDRESS ; Branch to irq_handler VICADDRESS-содержит адрес обработчика
при линковке получил ошибку
Warning[w52]: More than one definition for the byte at address 0x18 in common segment INTVEC. It is defined in module "main" as well as in module "?RESET"
на чём и споткнулся
SasaVitebsk
С AT91 не работал - работал с LPC. В принципе должно быть похоже.

ARM7 как минимум не хуже архитектуры x51 в области прерываний и, в принципе получше в области USART.

1) Прерывания:
В x51 у вас было 2 уровня прерываний. В ARM собственно тоже. FIQ и IRQ. FIQ - быстрое (Fast IRQ). Оно вызывается из IRQ без всякого гимора. Можно и nested использовать. Я как раз задавал вопрос в ветке ARM и мне подробно отвечали - поищите. Но если вас устраивает 2 уровня, то это без надобности.

2) Посмотрите внимательно сам UART как устроен. Там есть встроенное FIFO. Это даёт возможность задерживать обработку до 16(!!!!) символов. Как при таком раскладе можно что-то потерять - ума не приложу. У меня, к примеру, наоборот произошло. Если на AVR я теоретически мог потерять символ при скорости свыше 56к, то на ARM7 нет вообще никаких ограничений. Так на AVR 2 символа буфер - какой-никакой. На х51 (стандартном) - только 1! Таким образом, даже без учёта роста производительности, только за счёт переферии у вас никак не может происходить то, что происходит.
Tanker
Я делал на LPC хаб, где запросы от трёх уартов ретранслировались на 1 уарт, т.е. 3 потребителя инфы обращались через LPC к подопытному "девайсу"... так решилась проблема одного уарта у "девайса"
И всё работает в ~100 экз. раскидано по стране.
В проекте не используются прерывания вообще, работа выполняется "пуллингом" в основном цикле.
Ничего не дёргается (субъективное восприятие периодичности получаемых пакетов данных)
По сути я добавил в новый проект проект прерывания, и началось :-(
На скорости 115200, 1 байт это примерно 87мкс - это же бесконечность для 72МНz процессора!
Делаю вывод, что прерывание захватившее управление блокирует все остальные (в процессе разбора принятого пакета, это длительная операция)... а мне такого не надо!
Qwertty
Цитата(Tanker @ Jan 11 2010, 11:20) *
Делаю вывод, что прерывание захватившее управление блокирует все остальные (в процессе разбора принятого пакета, это длительная операция)... а мне такого не надо!

Естественно блокирует. Только лечить надо не вложенными прерываниями, а пересмотром алгоритма. В прерываниях не должно быть 99% работы, там должны быть маленькие быстрые обработчики. Основная работа выполняется в основном цикле, а из прерывания только сообщается о событиях. В случае с UART - в прерывании извлекается принятое, помещается в буфер и взводится соответствующий флажок. Все - никаких обсчетов CRC в прерывании не ведется. Можно разве что еще таймер запустить, для определения 3,5 байтового интервала для modbus. Хотя вполне возможно, что таймер и не потребуется - в LPC имеется свое прерывание через 3,5-4,5 байтовых интервала. Я не пользуюсь modbus rtu, так что это лишь предположение. Но при правильно спроектированном алгоритме все должно и с таймерами работать.
Tanker
Ок! Я хочу чтобы на LPC прерывания допускали вложенность до скончания стека ;-) как это реализовать?
IgorKossak
Цитата(Tanker @ Jan 11 2010, 14:04) *
Ок! Я хочу чтобы на LPC прерывания допускали вложенность до скончания стека ;-) как это реализовать?

Здесь описано.
И вообще, полезно сюда заглядывать.
Tanker
Почитал (по данному pdf я в 2003-м впервые получил опыт на LPC (вообще ARM) моргания светиком по прер. таймера и впервые на GCC!! ностальжи), в т.ч. забугорные форумы (понравилось как на кейле, одного индуса, с аналогичным вопросом, оставили без ответа, при этом куча советов "так программировать нельзя!!!")
Думаю мой трабл в том, что такие низкоуровневые вещи в разных компиляторах достигаются разными путями... в итоге в голове полная каша.
Нужен яркий пример.
Возьмем синтетический тест
0) Прерывание до выхода из своего обработчика не может сработать повторно (скажем таймер 2 останавливает свою работу при входе в обработчик, и возобновляет перед выходом их обработчика)
1) Таймер1 (Т1) заходит в прерывание каждые 1 сек и находится в прерывнии 1 сек (если его не прерывают другие)
2) Таймер2 (Т2) заходит в прерывание каждые 0,1 сек и находится в прерывнии 0,1 сек (если его не прерывают другие)
3) Таймер3 (Т3) заходит в прерывание каждые 0,1 сек и находится в прерывнии 0,1 сек (если его не прерывают другие)
4) нужно чтобы во время нахождения Т1(T2,T3) в обработчике прерывания, Т2(T1,T3) мог войти в свой обработчик, выполнить его, вернуться в обработчик Т1(T2,T3)
Как это в терминах IAR запрограммить?
dimka76
Цитата(Tanker @ Jan 10 2010, 16:18) *
Здравствуйте, у меня это.. LPC2364 и IAR 4.42A (32kB лимит)

Хочу начать с того, как в стартапе прописать код "прыгающий" сразу на мои вектора? тут был пример для SAM
но в асме пока не силён поковырял cstartup.s79 куда там что добавить?
сделал
EXTERN VICADDRESS
..................................................................
org 0x18
; ldr pc,[pc,#24] ; Branch to irq_handler
ldr pc,VICADDRESS ; Branch to irq_handler VICADDRESS-содержит адрес обработчика
при линковке получил ошибку
Warning[w52]: More than one definition for the byte at address 0x18 in common segment INTVEC. It is defined in module "main" as well as in module "?RESET"
на чём и споткнулся


Код
PROGRAM    ?RESET
        RSEG    INTRAMSTART_REMAP
        RSEG    INTRAMEND_REMAP

        RSEG    ICODE:CODE:ROOT(2)
        CODE32; Always ARM mode after reset    
        org    0    
reset        

                B           InitReset          ; 0x00 Reset handler
undefvec:
                B           undefvec_Hand           ; 0x04 Undefined Instruction
swivec:
                B           swivec_Hand             ; 0x08 Software Interrupt
pabtvec:
                B           pabtvec_Hand            ; 0x0C Prefetch Abort
dabtvec:
                B           dabtvec_Hand            ; 0x10 Data Abort
rsvdvec:
                B           rsvdvec            ; 0x14 reserved
irqvec:
                   ldr PC, [PC, #-0xF20]    ;[b]Здесь вместо #-0xF20 надо подставить другую цифирку( но тоже с минусом), что в результате в РС оказался VICADDRESS[/b]

fiqvec:         ldr PC, [PC, #-0xF20]                  ; 0x1c FIQ


О вложенных прерываниях, и не только, почитайте книгу "Тревор Мартин. Микроконтроллеры ARM7. Семейство LPC2000 компании Philips. Вводный курс"
skripach
Цитата
99% кода работает в прерываниях

А вот это наверное не правильно...
SasaVitebsk
Цитата(Tanker @ Jan 12 2010, 13:14) *
...
1) Таймер1 (Т1) заходит в прерывание каждые 1 сек и находится в прерывнии 1 сек (если его не прерывают другие)
...

Знаете почему так мало ответов? Просто нет слов! Думаю, что другие испытывают схожие чувства.

Прочитайте сами своё предложение... Вам не кажется, что это можно записать проще: "находится в этом прерывании непрерывно". Так, а чем оно тогда от головы отличается?!

Так назначьте ему найнизший приоритет (собственно это и не надо), и сделайте там лишь одну операцию - взведите там флаг секунды. А обработчик перенесите в голову и обрабатывайте по флагу.

И 0.1 сек - гиганское сремя для 60 МГц процессора! Тоже что-то не бъётся.

Короче - вам надо полностью переосмыслить логику работы программы!
Tanker
Здравствуйте!
всё заработало.
В основном цикле while (1); я счастлив. 100% рабочего кода в прерываниях!
Помог совет Сергей Борщ (Слава Ему!) в топике Старт c IAR+Sam7x
1) Исправил стартап
EXTERN VICADDRESS
...
org 0x18
LDR PC, VICADDRESS
2) все обработчики обозначил __irq __arm
3) а то тормозное прерывание которое я не хочу переводить в основной цикл! описал как __irq __nested __arm. И в нём же, сделал __enable_interrupt(); - именно перед тем местом где заходит на длительный разбор пакетов, естественно приняты меры, чтобы небыло повторного вызова до окончания обработки
4) расставил приоритеты прерываниям: быстрым 0, чуть приторможенным 1, а тому тормозному 2

5) планирую в юартах использовать FIFO 16байт, для саморазвития, острая необходимость отпала

Про ошибку Warning[w52]: More than one definition for the byte at address 0x18 in common segment INTVEC. It is defined in module "main" as well as in module "?RESET" которую я получал, всё просто, у меня в main был "типовой" обработчик с соответствующими атрибутами размещения # pragma vector=IRQV
__irq __arm void irq_handler (void){....}
убрал его, ошибка пропала.

SasaVitebsk! я предлагал СИНТЕТИЧЕСКИЙ ТЕСТ для изучения проблемы.
Qwertty
Цитата(Tanker @ Jan 13 2010, 13:23) *
Здравствуйте!
всё заработало.

Ну что тут можно сказать - костыль Вы нашли и успешно пристроили. smile.gif
Использование вложенных прерываний без крайней необходимости еще принесет Вам много "приятных" сюрпризов в будущем.
Но каждый сам себе "злобный Буратина".
defunct
Цитата(SasaVitebsk @ Jan 13 2010, 11:43) *
Думаю, что другие испытывают схожие чувства.

Один в один, именно как вы и говорите - слов нет...


Цитата
я предлагал СИНТЕТИЧЕСКИЙ ТЕСТ

Афтар !
это не синтетический тест, а еретический.
Вы еще delay_ms(1000) в каждый обработчик прерывания не забудьте воткнуть, тогда их все можно будет сделать "__nested" !
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.