|
|
  |
Atmega1281 вектора прерывания, Некорректное поведение при отладке |
|
|
|
Apr 14 2014, 02:00
|
Группа: Участник
Сообщений: 12
Регистрация: 26-06-13
Пользователь №: 77 280

|
Уважаемые форумчане помогите в решении данного вопроса. При отладке в AVR Studio проекта на контроллере Atmega1281 переход по прерыванию происходит не по тому адресу по которому расположен вектор. Читал даташит на данный камушек и обнаружил в нем наличия в памяти сектора загрузки и есть подозрения что вектора прерывания распологаются не на своем месте а в секторе загрузки из за чего вектора прерываний смещаются. Помогите пожалуйста разобраться в данном вопросе. CODE .include "m1281def.inc"
jmp RESET ; Reset Handler reti ;jmp INT0 ; IRQ0 Handler reti ;jmp INT1 ; IRQ1 Handler reti ;jmp INT2 ; IRQ2 Handler reti ;jmp INT3 ; IRQ3 Handler reti ;jmp INT4 ; IRQ4 Handler reti ;jmp INT5 ; IRQ5 Handler reti ;jmp INT6 ; IRQ6 Handler reti ;jmp INT7 ; IRQ7 Handler reti ;jmp PCINT0 ; PCINT0 Handler reti ;jmp PCINT1 ; PCINT1 Handler reti ;jmp PCINT2 ; PCINT2 Handler reti ;jmp WDT ; Watchdog Timeout Handler reti ;jmp TIM2_COMPA ; Timer2 CompareA Handler reti ;jmp TIM2_COMPB ; Timer2 CompareB Handler reti ;jmp TIM2_OVF ; Timer2 Overflow Handler reti ;jmp TIM1_CAPT ; Timer1 Capture Handler reti ;jmp TIM1_COMPA ; Timer1 CompareA Handler reti ;jmp TIM1_COMPB ; Timer1 CompareB Handler reti ;jmp TIM1_COMPC ; Timer1 CompareC Handler reti ;jmp TIM1_OVF ; Timer1 Overflow Handler reti ;jmp TIM0_COMPA ; Timer0 CompareA Handler reti ;jmp TIM0_COMPB ; Timer0 CompareB Handler reti ;jmp TIM0_OVF ; Timer0 Overflow Handler reti ;jmp SPI_STC ; SPI Transfer Complete Handler jmp USART0_RXC ; USART0 RX Complete Handler jmp USART0_UDRE ; USART0,UDR Empty Handler jmp USART0_TXC ; USART0 TX Complete Handler reti ;jmp ANA_COMP ; Analog Comparator Handler reti ;jmp ADC ; ADC Conversion Complete Handler reti ;jmp EE_RDY ; EEPROM Ready Handler reti ;jmp TIM3_CAPT ; Timer3 Capture Handler reti ;jmp TIM3_COMPA ; Timer3 CompareA Handler reti ;jmp TIM3_COMPB ; Timer3 CompareB Handler reti ;jmp TIM3_COMPC ; Timer3 CompareC Handler reti ;jmp TIM3_OVF ; Timer3 Overflow Handler jmp USART1_RXC ; USART1 RX Complete Handler jmp USART1_UDRE ; USART1,UDR Empty Handler jmp USART1_TXC ; USART1 TX Complete Handler reti ;jmp TWI ; 2-wire Serial Handler reti ;jmp SPM_RDY ; SPM Ready Handler reti;jmp TIM4_CAPT ; Timer4 Capture Handler reti;jmp TIM4_COMPA ; Timer4 CompareA Handler reti;jmp TIM4_COMPB ; Timer4 CompareB Handler reti;jmp TIM4_COMPC ; Timer4 CompareC Handler reti;jmp TIM4_OVF ; Timer4 Overflow Handler reti;jmp TIM5_CAPT ; Timer5 Capture Handler reti;jmp TIM5_COMPA ; Timer5 CompareA Handler reti;jmp TIM5_COMPB ; Timer5 CompareB Handler reti;jmp TIM5_COMPC ; Timer5 CompareC Handler reti;jmp TIM5_OVF ; Timer5 Overflow Handler reti;jmp USART2_RXC ; USART2 RX Complete Handler reti;jmp USART2_UDRE ; USART2,UDR Empty Handler reti;jmp USART2_TXC ; USART2 TX Complete Handler reti;jmp USART3_RXC ; USART3 RX Complete Handler reti;jmp USART3_UDRE ; USART3,UDR Empty Handler reti;jmp USART3_TXC ; USART3 TX Complete Handler
RESET: ldi R16, low(RAMEND) ; ??????? ????? ?????? RAMEND out SPL, R16 ; ????????????? SPL ldi R16, high(RAMEND) ; ??????? ????? ?????? RAMEND out SPH, R16 ; ????????????? SPH
uart_init:
.equ XTAL = 8000000 .equ baudrate = 9600 .equ bauddivider = XTAL/(16*baudrate)-1 .equ addr= 11 .equ Command = 0x03
LDI R16, low(bauddivider) STS UBRR0L,R16 LDI R16, high(bauddivider) STS UBRR0H,R16 LDI R16,0 STS UCSR0A, R16 LDI R16, (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<TXCIE0)|(0<<UDRIE0) STS UCSR0B, R16 LDI R16, (1<<UCSZ00)|(1<<UCSZ01)|(0<<UCSZ02) STS UCSR0C, R16 LDI R16, low(bauddivider) STS UBRR1L,R16 LDI R16, high(bauddivider) STS UBRR1H,R16 LDI R16,0 STS UCSR1A, R16 LDI R16, (1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1)|(1<<TXCIE1)|(0<<UDRIE1) STS UCSR1B, R16 LDI R16, (1<<UCSZ10)|(1<<UCSZ11)|(0<<UCSZ12) STS UCSR1C, R16 main1:
ldi R16,1 sts UDR0,R16 sei main: sei sbi DDRB,7 sbi PORTB,7 nop rjmp main
USART1_RXC: ; USART RX Complete Handler nop cli sbi DDRB,0 sbi PORTB,0 ldi R16,1 sts UDR0,R16 ret USART1_UDRE: ; UDR Empty Handler cli sbi DDRB,1 sbi PORTB,1 ldi R16,1 sts UDR0,R16 nop ret USART1_TXC: cli sbi DDRB,2 sbi PORTB,2 ldi R16,1 sts UDR0,R16 ret nop
USART0_RXC: cli sbi DDRB,0 sbi PORTB,0 ldi R16,2 sts UDR0,R16 ret USART0_UDRE: ; USART0,UDR Empty Handler cli sbi DDRB,1 sbi PORTB,1 ldi R16,2 sts UDR0,R16 nop ret USART0_TXC: cli sbi DDRB,2 sbi PORTB,2 ldi R16,2 sts UDR0,R16 ret nop
USART2_RXC: cli sbi DDRB,0 sbi PORTB,0 ldi R16,3 sts UDR0,R16 ret USART2_UDRE: ; USART0,UDR Empty Handler cli sbi DDRB,1 sbi PORTB,1 ldi R16,3 sts UDR0,R16 nop ret USART2_TXC: cli sbi DDRB,2 sbi PORTB,2 ldi R16,3 sts UDR0,R16 ret nop
|
|
|
|
|
Apr 14 2014, 02:45
|
Группа: Участник
Сообщений: 12
Регистрация: 26-06-13
Пользователь №: 77 280

|
Цитата(Палыч @ Apr 14 2014, 06:25)  Процедуры обработки прерываний, обычно, заканчивают своё выполнение командой RETI, а не RET Это несомненно так но как видно из текста выше обработчик переходит черт знает куда но только не по прерыванию т.е. порядка 5 векторов ниже нужного прерывания. Честно говоря я в замешательстве не когда не сталкивался с таким "глюком" т.е. прерывание вызывается jmp USART0_RXC ; USART0 RX Complete Handler а обработчик переходит на вектор reti;jmp TIM4_COMPB ; Timer4 CompareB Handler.
|
|
|
|
|
Apr 14 2014, 02:54
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexxack @ Apr 14 2014, 05:45)  обработчик переходит черт знает куда но только не по прерыванию т.е. порядка 5 векторов ниже нужного прерывания. Никаких чудес. Чтобы понять такое поведение ответьте на пару вопросов: 1) Сколько слов программной памяти занимает команда reti? 2) Сколько слов программной памяти отводится под один вектор в вашем контроллере?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 14 2014, 04:17
|
Группа: Участник
Сообщений: 12
Регистрация: 26-06-13
Пользователь №: 77 280

|
Цитата(Сергей Борщ @ Apr 14 2014, 06:54)  Никаких чудес. Чтобы понять такое поведение ответьте на пару вопросов: 1) Сколько слов программной памяти занимает команда reti? 2) Сколько слов программной памяти отводится под один вектор в вашем контроллере? Честно говоря некогда не задавался данным вопросом из имеющихся источников команда reti занимает 2 байта т.е 1 слово из даташита на Atmega1281 адресация векторов имеет вид $0000,$0002,$0004 т.е по всей видимости адресация занимает 2 слова т.е 4 байта ситуация начинает прояснятся но не до конца! Если не трудно разъясните пожалуйста пути решения.
|
|
|
|
|
Apr 14 2014, 05:01
|
Группа: Участник
Сообщений: 12
Регистрация: 26-06-13
Пользователь №: 77 280

|
Цитата(__Alexander @ Apr 14 2014, 08:50)  если быстро и тупо в лоб то расставьте адресе вручную. типа так
.org 0x0048 rjmp USART1_RXC ; USART1 RX Complete Handler Большое спасибо только что попробовал помогло. Если не трудно разъясните суть (От привычки копать глубоко не могу избавиться) запись вида Код reti;jmp TIM0_OVF; Timer0 Overflow Handler reti;jmp SPI_STC; SPI Transfer Complete Handler .ORG $0032 jmp USART0_RXC; USART0 RX Complete Handler .ORG $0034 jmp USART0_UDRE; USART0,UDR Empty Handler .ORG $0036 jmp USART0_TXC; USART0 TX Complete Handler reti;jmp ANA_COMP; Analog Comparator Handler помогла решить проблему. Хотелось бы разобраться дабы в дальнейшем не устраивать "танцы с бубном на граблях" или пните пожалуйста в сторону какой либо статейки дабы ознакомится. P.S. если не трудно.
|
|
|
|
|
Apr 14 2014, 05:02
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alexxack @ Apr 14 2014, 07:17)  Если не трудно разъясните пожалуйста пути решения. Вектора прибиты гвоздями к своим адресам. Как вы правильно поняли, каждый вектор занимает 2 слова. И пока вы на место вектора вставляете двухсловную команду jmp все красиво - следующая команда jmp попадает на свое правильное место. Как только вы вместо jmp поставили однословную reti - все следующие команды "поджались" и съехали на одно слово. То есть в вашем коде Код jmp RESET; Reset Handler reti;jmp INT0; IRQ0 Handler reti;jmp INT1; IRQ1 Handler комментарий про IRQ1 Handler уже перестал соответствовать действительности. Вам надо принудительно указать, что вторая команда reti должна располагаться по адресу IRQ1 Handler. Я не использую ассемблер Студии и саму студию, поэтому не могу точно сказать, какая именно директива ее ассемблера отвечает за принудительное размещение по определенному адресу. Возможно это будет что-то вроде ".org адрес". Также во избежание путаницы адреса не нужно указывать цифрами - в заголовочном файле студии m1281def.inc этим адресам должны быть присвоены мнемонические (текстовые) имена. И ваш исходник должен выгладеть примерно так: Код .org 0; имя для вектора сброса авторы m1281def.inc забыли jmp RESET .org INT0addr reti;jmp INT0 .org INT1addr reti;jmp INT1 Как видите, комментарии в этом коде уже не нужны и замена любого jmp на reti или rjmp не повлияет на размещение следующих команд
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 14 2014, 05:06
|
Частый гость
 
Группа: Участник
Сообщений: 76
Регистрация: 18-07-07
Из: Киев
Пользователь №: 29 202

|
Цитата(alexxack @ Apr 14 2014, 08:01)  . Хотелось бы разобраться дабы в дальнейшем не устраивать "танцы с бубном на граблях" или пните пожалуйста в сторону какой либо статейки дабы ознакомится. P.S. если не трудно. так тут разбираться особо в не в чем. никто не создает в файле эту таблицу. добавляют эти вектора по мере увеличения нужных прерываний. если у вас их три, то так и запишите только три (адрес+rjpm). Зачем вам та простыня?
|
|
|
|
|
Apr 14 2014, 05:22
|
Группа: Участник
Сообщений: 12
Регистрация: 26-06-13
Пользователь №: 77 280

|
Большое спасибо всем за помощь 3 дня бился с данным вопросом не догадался копнуть в сторону адресации. Надеюсь данный топик окажется полезным начинающим.
|
|
|
|
|
Apr 14 2014, 05:41
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(__Alexander @ Apr 14 2014, 08:06)  Зачем вам та простыня? Довольно распространенное заблуждение, что на неиспользуемый вектор надо поставить заглушку в виде reti. Типа если случайно это прерывание будет разрешено, то попав в него сразу вывалимся обратно и программа будет работать как ни в чем не бывало. Ну, во-первых лучше уж ставить загрушки в виде бесконечных циклов, чтобы программа зависла попав в этот цикл и автор начал разбираться, а почему она туда вообще попала и устранил ошибку. А во-вторых далеко не у всех прерываний флаг сбрасывается просто от перехода по вектору прерывания, часто для его сброса надо прочитать какой-то регистр, а без этого чтения выполнив reti программа на следующей команде снова влетит в этот же обработчик. И отловить такие внезапно наступающие тормоза уже сложнее.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|