Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: или глюк в IAR, или я что- то упускаю
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Метценгерштейн
вот код
Код
void main (void) {
__enable_interrupt();
uint32_t timeStamp =CntT1_ms;

char data [15];
uint8_t num = 0;
  
      
       putString("AT+CSQ\r"); //уровень приема сигнала

      
    for(;;){
      
         if ((CntT1_ms-timeStamp) >= LED_BLINK_PERIOD)
         {
           //off (LED);
           putString("AT\r");
           timeStamp =CntT1_ms;
         }    
      
       if ( hasinput() )
            {    
               data [num] = getchar();
              
               cpl (LED);
            }

  }
}


во- первых, странно, что ИАР ругается на варнинг на объявление массива char data[15];

Warning[Pe550]: variable "data" was set but never used D:\works\projects\Blink_LED mega8 +HT\main.c 102

И как только часть кода
data [num] = getchar();
включаю в работу (убираю комментарии),
отказывается работать часть кода между
main (); и

for (;;)

т.е.
putString("AT+CSQ\r");


Что за странное поведение?
OLEG_BOS
Цитата(Метценгерштейн @ Jan 22 2011, 20:29) *

Цитата
Warning[Pe550]: variable "data" was set but never used D:\works\projects\Blink_LED mega8 +HT\main.c 102

1. Ничего странного - ведь написано же что переменная объявленна, но не используется - Вы же сами ее закоментировали.
2. А Вы не пробовали объявлять char data [15] глобальной переменной по отношению к функции void main (void) ? rolleyes.gif
Dog Pawlowa
Мне даже две первые строчки непонятны.
Разрешить прерывания без всякой инициализации источников прерывания?
Что за прерывания используются в проекте?
Метценгерштейн
прерывания используются для другой ф-ии- вывода строки в USART
putString("AT+CSQ\r");
#pragma vector = USART_RXC_vect

OLEG_BOS, да где же она закомментирована- то?
он ругается на переменную data [],
а это массив у меня, а не переменная. И с чего- это я его не использую?
data [num] = getchar();

это я данные со входа USART кладу в массив.
Dog Pawlowa
Цитата(Метценгерштейн @ Jan 22 2011, 22:59) *
это я данные со входа USART кладу в массив.

Дык не берете ЖЕ!
Метценгерштейн
что значит не беру, еще как беру, смотрите

Код
if ( hasinput() )
            {    
               data [num] = getchar();        
            }


если есть что- то из данных (ф-я hasinput вернула 1- это внешний файл), я вызываю ф-ю getchar, и ее значение кладу в массив.

Не про то речь. Это все прекрасно работает, но не в этом месте у меня- тут мне и не понятно почему.


Объявление массива как глобального помогло- сейчас буду проверять в железе.

Тогда вопрос- а почему нельзя было локально на всю ф-ю main() ее объявлять?
OLEG_BOS
Цитата(Метценгерштейн @ Jan 22 2011, 22:10) *
что значит не беру, еще как беру, смотрите
... тут мне и не понятно почему.


Уважаемый Dog Pawlowa, имел ввиду, что у Вас не видно что data [num] меняет значение. Может нам не видно, а где-то " но не в этом месте " - значение num все таки изменяется ? rolleyes.gif
Метценгерштейн
значение num меняется по плану, оно ++, но закомментировано. По дефолту оно =0. Сути это не меняло, т.к. запись
data [0] = getchar();

ничего не изменила.

Запускаю в железе Ваш вариант с выносом объявления из main()

итак, перенос объявление массива в глобальные переменные- помогло. А почему не хотело быть объявленным внутри main()?
OLEG_BOS
Цитата(Метценгерштейн @ Jan 22 2011, 22:20) *
data [0] = getchar();
ничего не изменила.

А про слово "оптимизация", Вы случаем, ничего не слыхали ? rolleyes.gif Так вот, похоже, что Ваш комплилятор знает об этом слове и использует его по назначению о чем ссобщает в своем warninge rolleyes.gif
Метценгерштейн
вот зараза то wink.gif

и, что он в данном случае наоптимизировал? Выкинул мой массив? Посчитал, что он мне не нужен? Понимаю, если бы это не ИАР был...
sigmaN
Цитата
он ругается на переменную data [],
а это массив у меня, а не переменная. И с чего- это я его не использую?
а массив типа не переменная что ли? ))

и всё-же где инициализация порта? как-то немного странно...

Код
и, что он в данном случае наоптимизировал? Выкинул мой массив? Посчитал, что он мне не нужен?
ну а зачем он нужен, если вы всё кладете в нулевой элемент? его в таком случае можно заменить одной переменной типа char, но это ведь всё равно не объясняет почему перестаёт исполняться putString("AT+CSQ\r"); //уровень приема сигнала
что-то тут не то... может таки по прерыванию проц прыгает Бог знает куда?

Не думаю, что IAR на столько плох, что даёт Warning просто так... что там с hasinput() ?
Может быть она сразу, на этапе компиляции, разворачивается в false и весь if ( hasinput() ) выкидывается?
Это может произойти, к примеру, если флаг(который, как я понимаю, проверяет hasinput()) не объявлен с volatile(поднимается то флажок в прерывании).
В общем, кажется, вы запамятовали, что все глобальные переменные, с которыми ведется работа в обработчике прерывания - должны быть volatile...

Но всё это не объясняет исчезновения putString("AT+CSQ\r");.... тут надо как-то повнимательнее посмотреть что к чему...
Метценгерштейн
на самом деле интересно и не понятно, зачем ИАР выкинул код.

Вот весь проект целиком.
http://files.mail.ru/6WP6WH

я имел ввиду, что если сделать запись
data [0] = getchar();

то программа отказывается выполнять то, что записано сразу после main()
т.е. она сразу глючит.

Ещё раз, глюки прошли как только вынес массив из вне main()

ИАР последней версии 5.51
DpInRock
Наплевать что вы записываете что-т о в переменную. Если эта переменная ДАЛЬШЕ нигде не используется, то в нее что-то записывать нет никакого смысла (ибо ни на что не влияет). И вот об этом вам сообщает компилятор. А если включен оптимизатор, то и выкидывает нафик этот код.
rezident
Насчет putString("AT+CSQ\r"); не уверен, а все остальное в вашей программе из корневого сообщения компилятор имеет право выкинуть, превратив тело блока for(;;) в JMP сам на себя. Первый if никогда не выполняется, если только CntT1_ms не volatile-перменная. Второй if бессмысленный с точки зрения применения результатов. Т.е. в результате его выполнения или невыполнения ничего в данном объекте компиляции не меняется. А раз без разницы выполнять/не выполнять, то и компилировать его не стоит.
zltigo
QUOTE (Метценгерштейн @ Jan 23 2011, 01:51) *
Ещё раз, глюки прошли как только вынес массив из вне main()

Не из main() а из стека. Перед тем, как начинать программировать следует ТВЕРДО усвоить,.что такое стеки и как они используются и соответственно, перед тем, как пихать что попало в стек, надо подумать, сколько памяти для стека/стеков выделить.


OLEG_BOS
Цитата(zltigo @ Jan 23 2011, 01:38) *
Перед тем, как начинать программировать следует ТВЕРДО усвоить,.что такое стеки и как они используются и соответственно,

Я бы уточнил: усвоить что такое переменные, их область видимости, время жизни. И как вызываемые программой функции используют те самые стеки для работы с этими переменными.
Как пример: если б нужно (по каким-то причинам - ограничить область видимости) оставить переменную char data[15] внутри функции main но при этом обозначить ее как static char data[15]. Программа тоже б работала стабильно в указанном случае sm.gif
Метценгерштейн
хорошо, простой пример:

есть некий
Код
void main(void)
{
  char mass [10];
  int a = 3;
  int b = 5;

  if (a < b)
  {
    mass [0] = 'D';
  }
  
}


и, получается, здесь тоже надо массив как статик указывать?

все- равно не понятно.
Dog Pawlowa
Цитата(Метценгерштейн @ Jan 23 2011, 15:32) *
все- равно не понятно.

Чем этот пример отличается от того, что приводилось раньше?
Если Вы не используете данные массива, какое значение имеет, как определен массив ?
Вы бы книжки прочитали, чтобы постичь те несколько десятков правил программирования дополнительно к синтаксису операторов.
Метценгерштейн
читаю, читаю...
пока не разобрался еще.
Если есть ссылка под рукой, где наиболее четко проливается свет на это дело, прошу дать ее.
Спасибо.
zltigo
QUOTE (Метценгерштейн @ Jan 23 2011, 15:32) *
и, получается, здесь тоже надо массив как статик указывать?

Надо делать так, как Вам надо.
При этом, если Вам надо размещать массив в стеке то надо иметь в стеке достаточно места. Где Вам надо размещать массив Вы не знаете, что такое стек Вы не знаете. Размера стека который Вам нагенерил какой-нибудь безумный визард по умолчанию Вы тоже не знаете (подсказываю он у Вас в проекте 32 бвйта из которых Вы лихо 15 отдали под массив). Рановато взялись программировать sad.gif.

Метценгерштейн
Мне как- то лет в 18 инструктор по вождению говорил, что рано я за руль сел... И, что? послушать его надо было? И больше не садиться? Тогда и не научился бы никогда. Сейчас я довольно неплохо езжу- практика, практика... Так что неуместно Ваше замечание. Тем не менее, за помощь спасибо.

Я знаю что такое стек, писал на асме под авры.

То, что таким образом, объявляя массив, загоняю его в стек- признаю, упустил.

Сейчас читаю литературу, пытаюсь найти то, где это написано, что стек у меня 32 байта.

И, напомню, мы в разделе для начинающих... Думаю, многие начинающие на подобные грабли да наступали.
Dog Pawlowa
Цитата(Метценгерштейн @ Jan 23 2011, 16:24) *
И, напомню, мы в разделе для начинающих...

Это не освобождает Вас от необходимости осмысливать вопросы, если Вы хотите получить ответы.
Надеюсь, за рулем Вы более адекватны.
Тут пытаются Вам помочь, но не очень понятно, что Вам нужно.
Массив создать? - зачем, если он не используется?
Что Вы пытаетесь понять, наобум придумывая такие примеры?
Переменные должны разместиться в предназначенной для них памяти.
Все.
zltigo
QUOTE (Метценгерштейн @ Jan 23 2011, 16:24) *
То, что таким образом, объявляя массив, загоняю его в стек- признаю, упустил.

Теперь знаете.
QUOTE
Сейчас читаю литературу, пытаюсь найти то, где это написано, что стек у меня 32 байта.

Читать бесполезно - надо рассматривать картинки Вашего "проекта" - там на одной из картинок выставлено 32 байта. Кем, зачем и почему мне не ведомо, но это так.


QUOTE (Метценгерштейн @ Jan 23 2011, 16:24) *
Я знаю что такое стек, писал на асме под авры.

Ну и как Вы устанавливали размеры стеков на ASM?
Метценгерштейн
На самом деле, спасибо за то, что прояснили ситуацию, пытаюсь осмыслить.

на асме-
push r17

pop r16

Но довольно быстро можно было зарыться в коде, поэтому старался через стек не писать.

zltigo
QUOTE (Метценгерштейн @ Jan 23 2011, 16:48) *
на асме-
push r17
pop r16

Печально. Где установка РАЗМЕРА стека, я спрашивал.

Метценгерштейн
ldi r16, low(RAMEND)
out SPL, r16 ;инициализация стека
zltigo
QUOTE (Метценгерштейн @ Jan 23 2011, 17:00) *
ldi r16, low(RAMEND)
out SPL, r16 ;инициализация стека

Третья часть марлезонского балета - где здесь у Вас РАЗМЕР sm.gif стека sm.gif? Это ТОЛЬКО инициализация указателя. Сколько там места ниже указателя до первых Ваших переменных неведомо. Хватит-ли этого места для, например, размещения желаемых локальных переменных до того, как они наедут на статические переменные это чисто на вашей совести.
Метценгерштейн
Получается, так. Я устанавливал только указатель на память. Размер стека не устанавливал.
В ИАРе стоит размер стека 0х20, т.е. 32 байта как Вы и указали.

Итого, если объявляю массив внутри main (), то он сохранится в стеке, а если в глобальных переменных, то где? Пока не нашел ответа в литературе.

Почему в стартовом коде
Второй if бессмысленный с точки зрения применения результатов. Т.е. в результате его выполнения или невыполнения ничего в данном объекте компиляции не меняется.
?

Очевидно, что бессмысленна запись
data [num] = getchar();

т.к. массив объявлен в стеке, внутри main()

rezident
Метценгерштейн, любая работа должна приносить какой-то результат. В противном случае она становится бессмысленной. Локальные переменные, объявленные внутри функции, имеют срок жизни до момента окончания работы этой функции. Поэтому, если функция работает только с локальными данными и не передает результат своей работы "наружу" или в процессе выполнения не модифицирует никакие внешние (глобальные или volatile) данные, то эта функция нафиг не нужна. И компилятор имеет право вообще ее выкинуть из конечного кода.
Метценгерштейн
rezident

Спасибо, дошло до меня. Я же при вызове ф-ии
data [num] = getchar();

покидаю тело ф-ии main, работаю с внешним файлом. Тут и уничтожается моя переменная (массив).

Сейчас читаю книгу
Философия C++. Введение в стандартный C++

как раз про это дело.
sigmaN
покидание функции main - последняя операция, которую выполняет программа на Си )
Метценгерштейн
хорошо, но программа же выходит из main, для того, чтобы выполнить другую ф-ю вне main. Вот, получается, переменная (массив) и уничтожается при выходе.
sigmaN
Выход из функции и вызов другой функции - разные понятия. При вызове, со стеком вызывающей функции ничего плохого не происходит, а стек вызываемой "дописывается" дальше. При выходе(вообще-то это называется возврат) - стек функции теряется.
Это как-бээ физически. Одкано есть такое понятие, как область видимости. Это означает, что переменные, объявленные локально(в функци) не будут видны другим функциям(в том числе и тем, которые были вызваны этой функцией), хотя при этом эти переменные и присутствуют в стеке и имеют определенные значения. Вот ведь как оно бывает))))))

В вашей программе же не просто так бесконечный цикл используется. Это как раз для того, чтобы возврата из main не было. И вам уже достаточно подробно растолковали почему именно компилятор при оптимизации выбрасывает ваш массив, вместе с ifом.
Метценгерштейн
т.е. вызываемая ф-я
getchar();

не может передать результат локальной переменной, объявленной в main(). Т.к. область ее видимости вне ф-ии getchar();
А раз так, то работа тут бесполезна, и этот код выкидывается. Теперь правильно понял?
sigmaN
Нет. Возврат значения он на то и возврат, чтобы вернуть значение(результат работы) вызывающей функции. Иначе всё это было бы бсполезно.

Вы б с букваря начали....
Вам же объясняют уже сколько: вернула getchar(); значение, присвоили вы его одному из элементов массива(изменили одну ячейку памяти микроконтроллера), а дальше то что? ЗНАЧЕНИЕ ЭТО НИГДЕ НЕ ИСПОЛЬЗУЕТСЯ!
Оптимизация же подразумевает достижение того-же результата с меньшим кол-вом телодвижений. Так если значение функции нам не нужно, то зачем делать всю эту работу? чтобы просто один раз изменить ячейку памяти или регистр контроллера? Если это изменение ни на что в дальнейшем не влияет - то его можно не делать. Вот как думает компилятор. И разжевали вам это уже очень хорошо и живопсисно! Перечитывайте хоть ответы тогда уж по мере продвижения...
Метценгерштейн
Извиняюсь, похоже, торможу я хорошо wink.gif

Я, безусловно все ответы перечитывал, и не раз. Я не игнорирую мне сообщения, пытаюсь вникнуть и понять их. Букварь (K&R) тоже читаю.

Так речь- то про что у нас- про оптимизацию, что вызывающая ф-я бесполезна, т.к. массив я дальше нигде не задействовал?
Хотите сказать, если бы я дальше в коде использовал этот массив, например так:

Код
     if (data [0] == 'S')                
         cpl (LED);


было бы все нормально? Не было у меня все нормально, использовал я массив и имел все- равно глюки.

И причем тогда область видимости переменных?
Если все банально упирается в то, что дальше этот массив мой нигде не использовался?

И как тогда решилась проблема с выносом массива в глобальные переменные?
sigmaN
Цитата
было бы все нормально? Не было у меня все нормально, использовал я массив и имел все- равно глюки.
ну вам же объяснили, что при стеке 32байта, отнимать 15 под массив, а потом ещё и вызывать другие функции(которые тоже хотят стека как минимум для сохранения адреса возврата) было опрометчивым решением и скорее всего приводило к переполнению стека со всеми вытекающими последствиями.
Объявление же массива глобально, позволяет не размещать его в стеке и таким образом обеспечить нормальный вызов и возврат других функций. Это лишь гипотеза.
Также, возможно, у компилятора другая стратегия оптимизации глобальных переменных ибо факт неиспользования уже становится далеко не таким очевидным, как в случае с локальной переменной.
И т.д. и т.п., как говорится ))

Про область видимости рассказывал для того чтобы:
1. подчеркнуть на сколько очевидно, что ваш массив более нигде не используется.
2. немного помочь вам в самообразовании ))
Метценгерштейн
Да, спасибо Вам, и всем кто откликнулся за помощь.

Теперь все прояснилось.

Изучаю литературу дальше.
sigmaN
Да да, главное не сдаваться.
demiurg_spb
to Метценгерштейн:
Вы кстати в курсе что в IAR-AVR есть 2 вида стека:
1) программный стек, используемый для СИ-контекста
2) аппаратный стек, используемый лишь по вынужденной необходимости

Таким образом они несколько увеличивают скорость работы со "стеком"
(гляньте на кол-во тактов нужных для выполнения push + pop и на st Y+,R и ld R,-Y)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.