|
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, но почемуто в старт? Може кто с таким эффектом сталкивался?
|
|
|
|
|
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.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|