|
ATmega 16L проблема с UART |
|
|
|
Apr 17 2008, 11:31
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
Выручай всезнающий Олл! ATmega 16L проблема с UART, а именно после посылки всего, когда буфер уже пустой возвращается из интерапта на начало программы (фактически рестарт). Код прерывания Код ISR(USART0_UDRE_INTERRUPT) { uint8_t temp_tail; if ( USART0_TX_Head != USART0_TX_Tail) { temp_tail = (USART0_TX_Tail + 1) & USART_TX_BUFFER_MASK; USART0_TX_Tail = temp_tail; USART0_UDR = USART0_TX_Buffer[temp_tail]; } else { USART0_UCSRB &= ~(1<<USART0_UDRIE); USART0_Enable_Int_Status = 1; } } Что я делаю не так. При просмотре в Студии в режиме ассемблега, видно что в переходе на прерывание все пакуется в стек, потом также аккуратно распаковывается, и возвращается по команде RTI, но почемуто в старт? Може кто с таким эффектом сталкивался?
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 21)
|
Apr 17 2008, 12:09
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
Вот это скорость ответов на форуме! Супер! К теме Код 239: USART0_Enable_Int_Status = 1; +000002D1: E081 LDI R24,0x01 Load immediate +000002D2: 93800167 STS 0x0167,R24 Store direct to data space +000002D4: 91FF POP R31 Pop register from stack +000002D5: 91EF POP R30 Pop register from stack +000002D6: 919F POP R25 Pop register from stack +000002D7: 918F POP R24 Pop register from stack +000002D8: 900F POP R0 Pop register from stack +000002D9: BE0F OUT 0x3F,R0 Out to I/O location +000002DA: 900F POP R0 Pop register from stack +000002DB: 901F POP R1 Pop register from stack +000002DC: 9518 RETI Interrupt return Занятость: Data: 383 bytes (37.4% Full) Чем может переполниться стек, если программа только получает и отсылает по 5-7 Байт?
|
|
|
|
|
Apr 17 2008, 12:32
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
Цитата(Палыч @ Apr 17 2008, 16:22)  Так Вы в Студии и проконтролируйте стек: состояние стека и содержимое его когда вошли в прерывание, и когда выходите (перед RTI). Должно быть одним и тем же. указатель стека при входе и выходе не отличаются, короче. сколько запаковывается, столько же и распаковывается. Содержания стека я в студии не нашел. Может подскажешь, палычь, где оно в студии зарыто?
|
|
|
|
|
Apr 17 2008, 12:35
|
Знающий
   
Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640

|
Цитата(Палыч @ Apr 17 2008, 16:22)  Так Вы в Студии и проконтролируйте стек: состояние стека и содержимое его когда вошли в прерывание, и когда выходите (перед RTI). Должно быть одним и тем же. +1 И регистры должны то-же значение иметь, и адрес возврата в стеке д.б. Вы в прерывание как входите? М.б. вы просто адрес возврата в стек не кладёте? Надо при отладке call/rcall команду на таблицу прерываний делать.
|
|
|
|
|
Apr 17 2008, 12:45
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
Цитата(galjoen @ Apr 17 2008, 16:35)  +1 И регистры должны то-же значение иметь, и адрес возврата в стеке д.б. Вы в прерывание как входите? М.б. вы просто адрес возврата в стек не кладёте? Надо при отладке call/rcall команду на таблицу прерываний делать. Опа?! А вот с этого места по подробнее. Я всю жизнь думал, что при вызове прерывания адрес возврата сохраняется автоматически в стек. Если это не так, то как это делается и в каком месте. Я же не знаю в какой момент прерывание произойдет. Где этот код распологать?
|
|
|
|
|
Apr 17 2008, 13:11
|
Знающий
   
Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640

|
Цитата(ProfessorBraz @ Apr 17 2008, 16:45)  Опа?! А вот с этого места по подробнее. Я всю жизнь думал, что при вызове прерывания адрес возврата сохраняется автоматически в стек. Правильно думали. Цитата(ProfessorBraz @ Apr 17 2008, 16:45)  Если это не так, то как это делается и в каком месте. Я же не знаю в какой момент прерывание произойдет. Где этот код распологать?  Это только для отладки. А как у вас прерывание от USART при отладке вызывается? А чтоб стек проконтролировать - надо ОЗУ начиная с адреса указателя стека посмотреть.
|
|
|
|
|
Apr 17 2008, 14:51
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(ProfessorBraz @ Apr 17 2008, 15:09)  Занятость: Data: 383 bytes (37.4% Full) Чем может переполниться стек, если программа только получает и отсылает по 5-7 Байт?  Действительно, обработчик прерывания, фрагмент кода которого Вы привели использует 9 байт стека. Но стек также использует и основная программа: для адресов возврата из вызываемых подпрограмм, для размещения локальных переменных и массивов, передачи параметров процедурам и функциям... Разные трансляторы используют стек по-разному. Я плохо знаком с WinAVR, и не могу сказать - что со стеком делает он... Но, во всех трансляторах (ИМХО) самые прожорливые до памяти функции - printf, scanf и им подобные. Используете ли Вы подобные процедуры? Есть ли в Вашей программе большие локальные массивы? Цитата(ProfessorBraz @ Apr 17 2008, 15:32)  Содержания стека я в студии не нашел. Может подскажешь, палычь, где оно в студии зарыто? Стек распалагается в памяти - для просмотра можно использовать окно Memory. Цитата(ProfessorBraz @ Apr 17 2008, 15:45)  Я же не знаю в какой момент прерывание произойдет. Где этот код распологать? Делать искуственный вызов процедуры прерывания из программы не надо - достаточно "пошевелить" флаги - само произайдёт. Кстати, Вы ведь умудрились увидеть как-то вот это Цитата(ProfessorBraz @ Apr 17 2008, 14:31)  При просмотре в Студии в режиме ассемблега, видно что в переходе на прерывание все пакуется в стек, потом также аккуратно распаковывается, и возвращается по команде RTI, но почемуто в старт? Как? Ну, так сделайте это же ещё раз с контролем стека. P.S. Последняю цитата, может быть, говорит только о том, что Вы увидели в окне команды push/pop/reti? Тогда, как Вы определили, что именно по reti этого обработчика программа попала на нулевой адрес?
|
|
|
|
|
Apr 18 2008, 06:58
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
Переход осуществляется на адресс указанный в стеке. Странно только,что команда RTI ситает из стека 2 байта (0х20 0хЕ8) а переходит на 0хЕ8. Но такого адресса 0х20Е8 или 0хЕ820 все равно нет. В стеке все нормально, до переполнения ему еще очень долеко, там всего 38 байт.
|
|
|
|
|
Apr 18 2008, 08:20
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
Цитата(Палыч @ Apr 18 2008, 12:03)  Отчего всё же Вы решили, что на адрес 0 попадаете по reti из этого обработчика? потому-что после reti программа переходит вот сюда Код +000000E4: E081 LDI R24,0x01 Load immediate +000000E5: 93800184 STS 0x0184,R24 Store direct to data space +000000E7: CFFF RJMP PC-0x0000 Relative jump теперь это Е7.
|
|
|
|
|
Apr 18 2008, 08:51
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
Цитата(Палыч @ Apr 18 2008, 12:36)  Это не переход на адрес 0. Очень похоже на бесконечный цикл, в конце программы, в который попадают при выходе из main. Сама main у Вас как выглядит? вот так Код int main(void) { //Init UART InitUSART0_Int(); USART_Init_Function(&i16RcvByte, &vOnEvent, &vOnError); InitFD(); InitSM(); // Interrupt erlauben sei(); Global.bShortTaskEnable = true;
while(1){;} }
|
|
|
|
|
Apr 18 2008, 09:21
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
Цитата(Палыч @ Apr 18 2008, 12:58)  Тот rjmp по адресу E7 - это скорее всего while(1){;} Вас, наверное, смутили нули при jmp'е? Так обратите внимание, что они входят в выражение "РС-0х000", что означает "этот адрес", т.е. команда перехода на самою себя. а после этого он переходит вот сюда Код +0000001A: 940C0047 JMP 0x00000047 Jump +0000001C: 940C0047 JMP 0x00000047 Jump а от туда уже Код +00000047: 940C0000 JMP 0x00000000 Jump
|
|
|
|
|
Apr 18 2008, 09:30
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Ну, Вы, блин, даёте! Это не RJMP PC-0x0000 переходит на адрес 1A! Адрес 1А - адрес вектора "USART, Tx Complete". У Вас разрешено прерывание по этому событию, но, обработчика прерывания, скорее всего, - нет. Вот программа и выходит на вектор, куда во избежании всяких неприятностей по-умолчанию занесены переходы, которые приводят на адрес 0.
|
|
|
|
|
Apr 18 2008, 10:13
|
Группа: Новичок
Сообщений: 9
Регистрация: 17-04-08
Пользователь №: 36 821

|
у меня только два прерывания и оба оброботчика присутствуют Код #if defined (__AVR_ATmega16__) || \ defined (__AVR_ATmega32__) #define ATMEGA_USART #define USART0_RECEIVE_INTERRUPT USART_RXC_vect #define USART0_TRANSMIT_INTERRUPT USART_UDRE_vect #define USART0_STATUS UCSRA #define USART0_CONTROL UCSRB #define USART0_DATA UDR #define USART0_UDRIE UDRIE #define USART0_UBRRH UBRRH #define USART0_UBRRL UBRRL Палыч! Вы супер! Найдено. Проблема была в отсутствующем обработчике прерывания. Код ISR(USART0_TX_COMPLETE_INT) { } Не смотря на то, что я это прерывание не разрешал, впрочем и не запрещал, возможно оно разрешилось автоматически вместе с Тх интераптом. Вообщем проблема решена! Огромное всем спасибо! До следующих проблем!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|