|
|
  |
Здравствуйте, у меня это.. |
|
|
|
Jan 10 2010, 13:18
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 30-06-07
Пользователь №: 28 806

|
Здравствуйте, у меня это.. 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" на чём и споткнулся
|
|
|
|
|
Jan 10 2010, 21:19
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
С 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! Таким образом, даже без учёта роста производительности, только за счёт переферии у вас никак не может происходить то, что происходит.
|
|
|
|
|
Jan 11 2010, 08:20
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 30-06-07
Пользователь №: 28 806

|
Я делал на LPC хаб, где запросы от трёх уартов ретранслировались на 1 уарт, т.е. 3 потребителя инфы обращались через LPC к подопытному "девайсу"... так решилась проблема одного уарта у "девайса" И всё работает в ~100 экз. раскидано по стране. В проекте не используются прерывания вообще, работа выполняется "пуллингом" в основном цикле. Ничего не дёргается (субъективное восприятие периодичности получаемых пакетов данных) По сути я добавил в новый проект проект прерывания, и началось :-( На скорости 115200, 1 байт это примерно 87мкс - это же бесконечность для 72МНz процессора! Делаю вывод, что прерывание захватившее управление блокирует все остальные (в процессе разбора принятого пакета, это длительная операция)... а мне такого не надо!
|
|
|
|
|
Jan 11 2010, 09:10
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

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

Группа: Участник
Сообщений: 34
Регистрация: 30-06-07
Пользователь №: 28 806

|
Ок! Я хочу чтобы на LPC прерывания допускали вложенность до скончания стека ;-) как это реализовать?
|
|
|
|
|
Jan 12 2010, 09:14
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 30-06-07
Пользователь №: 28 806

|
Почитал (по данному 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 запрограммить?
|
|
|
|
|
Jan 12 2010, 10:19
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Цитата(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. Вводный курс"
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Jan 13 2010, 07:50
|
■ ■ ■ ■
    
Группа: Свой
Сообщений: 1 100
Регистрация: 9-08-06
Пользователь №: 19 443

|
Цитата 99% кода работает в прерываниях А вот это наверное не правильно...
--------------------
Делай что должен и будь что будет.
|
|
|
|
|
Jan 13 2010, 09:43
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(Tanker @ Jan 12 2010, 13:14)  ... 1) Таймер1 (Т1) заходит в прерывание каждые 1 сек и находится в прерывнии 1 сек (если его не прерывают другие) ... Знаете почему так мало ответов? Просто нет слов! Думаю, что другие испытывают схожие чувства. Прочитайте сами своё предложение... Вам не кажется, что это можно записать проще: "находится в этом прерывании непрерывно". Так, а чем оно тогда от головы отличается?! Так назначьте ему найнизший приоритет (собственно это и не надо), и сделайте там лишь одну операцию - взведите там флаг секунды. А обработчик перенесите в голову и обрабатывайте по флагу. И 0.1 сек - гиганское сремя для 60 МГц процессора! Тоже что-то не бъётся. Короче - вам надо полностью переосмыслить логику работы программы!
|
|
|
|
|
Jan 13 2010, 10:23
|
Участник

Группа: Участник
Сообщений: 34
Регистрация: 30-06-07
Пользователь №: 28 806

|
Здравствуйте! всё заработало. В основном цикле while (1); я счастлив. 100% рабочего кода в прерываниях! Помог совет Сергей Борщ (Слава Ему!) в топике Старт c IAR+Sam7x1) Исправил стартап 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! я предлагал СИНТЕТИЧЕСКИЙ ТЕСТ для изучения проблемы.
|
|
|
|
|
Jan 14 2010, 14:44
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(Tanker @ Jan 13 2010, 13:23)  Здравствуйте! всё заработало. Ну что тут можно сказать - костыль Вы нашли и успешно пристроили.  Использование вложенных прерываний без крайней необходимости еще принесет Вам много "приятных" сюрпризов в будущем. Но каждый сам себе "злобный Буратина".
|
|
|
|
|
Jan 15 2010, 22:38
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(SasaVitebsk @ Jan 13 2010, 11:43)  Думаю, что другие испытывают схожие чувства. Один в один, именно как вы и говорите - слов нет... Цитата я предлагал СИНТЕТИЧЕСКИЙ ТЕСТ Афтар ! это не синтетический тест, а еретический. Вы еще delay_ms(1000) в каждый обработчик прерывания не забудьте воткнуть, тогда их все можно будет сделать "__nested" !
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|