реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Обнуление указателя стека
IF_P
сообщение Aug 30 2013, 15:13
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



После небольшой модернизации программы начала вылетать ошибка стека ("Err_SP.GIF"). Начал разбираться и пришел вот к чему.
В программе MAIN в самом начале есть команда:

SBIW R29:R28, 20

Здесь уменшается р-р Y на 20. (0x80 - 20 = 0x6C). Впоследствии этот р-р используется для адресации стека.
При входе в п/п прерывания таймера сохраняются 20 р-ров ("ISR_Save.GIF").
В результате указатель стека получается равным 0x58, чего быть не должно. В дальнейшем при первом же вызове п/п в этом месте

37 ADC_7741[N_chan_7741][step7741]=TCNT1;
\ 0000003A B44C IN R4, 0x2C
\ 0000003C B45D IN R5, 0x2D
\ 0000003E .... LDI R26, LOW(ADC_7741)
\ 00000040 .... LDI R27, (ADC_7741) >> 8
\ 00000042 9140.... LDS R20, N_chan_7741
\ 00000046 E050 LDI R21, 0
\ 00000048 E00A LDI R16, 10
\ 0000004A E010 LDI R17, 0
\ 0000004C .... RCALL ?S_EC_MUL_L02

указатель стека обнуляется и начинают выдаваться вышеуказанные ошибки.

Посмотрел предыдущую версию программы. Там нет команды

SBIW R29:R28, 20

Почему она появилась?

В рабочей версии программы использовал свою п/п обработки прерывания I2C.
В программе с ошибками обработка прерываний I2C от ATMEL.
В прицепе два варианта программы.
IAR 4.30A
Proteus 7.10.0

Сообщение отредактировал IF_P - Aug 30 2013, 15:15
Эскизы прикрепленных изображений
Прикрепленное изображение
Прикрепленное изображение
 

Прикрепленные файлы
Прикрепленный файл  Norm.RAR ( 58.78 килобайт ) Кол-во скачиваний: 11
Прикрепленный файл  Err.RAR ( 76.88 килобайт ) Кол-во скачиваний: 11
 
Go to the top of the page
 
+Quote Post
Xenia
сообщение Aug 30 2013, 15:53
Сообщение #2


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(IF_P @ Aug 30 2013, 19:13) *
После небольшой модернизации программы начала вылетать ошибка стека ("Err_SP.GIF"). Начал разбираться и пришел вот к чему.
В программе MAIN в самом начале есть команда:
SBIW R29:R28, 20
Здесь уменшается р-р Y на 20. (0x80 - 20 = 0x6C). Впоследствии этот р-р используется для адресации стека.
При входе в п/п прерывания таймера сохраняются 20 р-ров ("ISR_Save.GIF").
В результате указатель стека получается равным 0x58, чего быть не должно. В дальнейшем при первом же вызове п/п в этом месте

Посмотрел предыдущую версию программы. Там нет команды
SBIW R29:R28, 20
Почему она появилась?


Появилась она оттого, что вы заводите
char messageBuf[TWI_BUFFER_SIZE];
на стеке! Вот компилятор и резервирует этой командой 20 байт, отъедая их из стека. А стека у вас кот наплакал (0x20).
Заведите буфер глобально (вне main) и ваши проблемы исчезнут.
А в "нормальной" программе этого не было потому, что там вы TWI не использовали и под буфер стек не изводили.
Go to the top of the page
 
+Quote Post
IF_P
сообщение Aug 30 2013, 16:35
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Цитата(Xenia @ Aug 30 2013, 18:53) *
Появилась она оттого, что вы заводите
char messageBuf[TWI_BUFFER_SIZE];
на стеке! Вот компилятор и резервирует этой командой 20 байт, отъедая их из стека. А стека у вас кот наплакал (0x20).
Заведите буфер глобально (вне main) и ваши проблемы исчезнут.
А в "нормальной" программе этого не было потому, что TWI вы не использовали и под буфер стек не изводили.

TWI я там тоже использовал, только программа ISR TWI была моя и там немного другой принцип обработки информации. А здесь я просто скопировал у ATMEL (AVR311). Но у них буфер 4 байта в примере и это не критично.
Сейчас попробую разобраться и переделать.
Go to the top of the page
 
+Quote Post
IF_P
сообщение Aug 30 2013, 17:43
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Xenia спасибо за помощь.
Сделал глобальную переменную и ошибка стека исчезла. Но вот обмен по I2C виснет на второй секунде. Видимо, где-то это описание вылезат "боком". Копаю дальше.

Сообщение отредактировал IF_P - Aug 30 2013, 17:44
Go to the top of the page
 
+Quote Post
IF_P
сообщение Aug 31 2013, 09:22
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Попутно еще вопрос. у меня в п/п прерываня таймера сохраняется в стеке 20 р-ров, а используется только 12. Это особенности компилятора или я чего-то не углядел. Ведь это все влияет на размер стека.
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 31 2013, 10:24
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(IF_P @ Aug 31 2013, 12:22) *
Попутно еще вопрос. у меня в п/п прерываня таймера сохраняется в стеке 20 р-ров, а используется только 12. Это особенности компилятора или я чего-то не углядел. Ведь это все влияет на размер стека.


IAR сохраняет регистры в стек при входе в прерывание если пытаться вызывать в нём (в прерывании) различные функции. Компилятор не знает какие именно регистры понадобятся, поэтому сохраняет большую их часть в стек. Попробуйте переписать обработчик прерывания без вызова функций и посмотрите в листинге как изменится Ваш обработчик прерывания.
Go to the top of the page
 
+Quote Post
IF_P
сообщение Aug 31 2013, 11:37
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Так я ведь никаких функций в обработчике не вызываю. Всего лишь запись значения таймера в массив, анализ и модификация счетчика. Компилятор на этапе компиляции уже знает какие р-ры он будет использовать.
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 31 2013, 12:06
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(IF_P @ Aug 31 2013, 14:37) *
Так я ведь никаких функций в обработчике не вызываю. Всего лишь запись значения таймера в массив, анализ и модификация счетчика. Компилятор на этапе компиляции уже знает какие р-ры он будет использовать.


У Вас в листинге видно вызов функции умножения

Код
     27                  ADC_7741[N_chan_7741][step7741]=TCNT1;            
   \   00000026   B5AC               IN      R26, 0x2C
   \   00000028   B5BD               IN      R27, 0x2D
   \   0000002A   9140....           LDS     R20, (addr_byte + 3)
   \   0000002E   E050               LDI     R21, 0
   \   00000030   E208               LDI     R16, 40
   \   00000032   E010               LDI     R17, 0
   \   00000034   ....               [b]RCALL   ?S_EC_MUL_L02[/b]


Надо подумать как оптимизировать все ваши манипуляции с N_chan_7741 и т.п. переменными.
Ещё Вы самостоятельно сохраняете SREG в то врем я как IAR заботится об этом сам. Это видно из листинга.
Если Вам нужно вызывать прерывание с постоянным периодом, то посмотрите на режим работы таймера CTC (clear to compire).
Я с M8535 давно работал, поэтому не подскажу сразу есть ли в ней у Т0 такой режим работы.

У Вас по обработчику прерываний видно что 1 цикл это 20 мС - т.е. Вам раз в 20 мС необходимо сохранять значение TCNT1 в буффер
По меркам МК это довольно большой период. Вы можете разделить процесс получения данных и сохранения результата в буффер. В обработчике прерывания взводите флаг прерывания и сохраняйте значение TCNT1 в промежуточный регистр. А восновном цикле мониторте флаг прерывания и манипулируйте с сохранёнными данными.

Код
volatile unsigned char tc0_int_flag;
unsigned int tcnt1_val;

#pragma vector=TIMER0_OVF_vect
__interrupt void Timer0_Interrupt(void)
{
    
  tc0_int_flag= 1;
  tcnt1_val= TCNT1;
  TCNT1 = 0;
}


В основном цикле программы опрашивайте флаг tc0_int_flag
Код
if(tc0_int_flag)
{
__disable_interrupt();
tc0_int_flag = 0;

//тут вставить манипуляции с сохранением результата tcnt1_va
__enable_interrupt();
}


Если Вам нужна быстрая реакция на возможные прерывания, то измените так:
Код
if(tc0_int_flag)
{
unsigned int temp;
__disable_interrupt();
tc0_int_flag = 0;
temp = tcnt1_val;
__enable_interrupt();

//тут вставить манипуляции с сохранением результата temp
}


И не забудьте сменить режим работы таймера на СТС чтобы он генерировал прерывание и самостоятельно сбрасывал свой счётный регистр.
Go to the top of the page
 
+Quote Post
IF_P
сообщение Aug 31 2013, 17:23
Сообщение #9


Частый гость
**

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Спасибо за подсказки. Так значительно лучше. По крайней мере в ISR T0 в стеке сохраняется только 4 р-ра.
Что касается таймера T0, то я режим поменяю только после полной отладки программы. Дело в том, что я отлаживаю программу в Proteus'е. А там TWI в ATMega8535 немного глючит (касательно того, что мне надо). Пришлось использовать ATMega8. А у неё нет режима таймера CTC. Но это уже мелочи.
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 31 2013, 18:42
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(IF_P @ Aug 31 2013, 20:23) *
Пришлось использовать ATMega8. А у неё нет режима таймера CTC. Но это уже мелочи.

А таймер 2 слабо задействовать в атмега8? wink.gif
Go to the top of the page
 
+Quote Post
IF_P
сообщение Aug 31 2013, 18:49
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 136
Регистрация: 2-01-06
Пользователь №: 12 772



Конечно можно. Я что-то упустил из виду это.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 19:31
Рейтинг@Mail.ru


Страница сгенерированна за 0.02302 секунд с 7
ELECTRONIX ©2004-2016