Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: От HELP MEGA8 к вопрос по IAR!
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Sergio66
Я два дня назад создал тему HELP MEGA8. Спасибо всем, кто откликнулся. Однако, проблема оказалась совсем не в подключении кристалла, в совершенно в другом месте! Проблема оказалась в IAR 4.10B/W32 (4.10.2.5).
Вот такой код на С:
#include <iom8.h>

int main( void )
{
long unsigned int i;
DDRB|= (1<<1);

while(1)
{

PORTB^=(1<<1);
i=0xffff;
while (i--);
}
}
все догадались, что должно произойти. Диод на PB1 должен моргать.
Однако, камень запускается раз на 4 - 5 включений питания. (Все подтянуто, все сглажено).

Меняем проект на:
.include "m8def1.inc"

begin:


ldi r16,low(RAMEND)
out spl,r16
ldi r16,high(RAMEND)
out sph,r16


ldi r16,(1<<1)
out DDRB,r16

; основной цикл программы
loop:
ldi r16,(1<<1) ; светится один светодиод
out PORTB,r16
rcall delay ; задержка
ldi r16,(0<<1) ; теперь гасим его
out PORTB,r16
rcall delay ; задержка

rjmp loop ; повторение цикла

; процедура задержки
; примерно полсекунды при частоте 7,37 МГц
; три пустых вложенных цикла соответственно
delay:
ldi r16,30 ; 30
delay1:
ldi r17,200 ; 200
delay2:
ldi r18,200 ; и еще 200 итераций
delay3:
dec r18
brne delay3
dec r17
brne delay2
dec r16
brne delay1
ret
вот такая нехитрая замена, сгенеренная в AVRStudio 4.
Все работает как часы!!!Вопросов нет!!!
То есть есть, но уже к знатокам IAR!!!
Компилю проект с опциями:
оптимизация отключена
кристалл - м8
модель Small
Подскажите, ведь не может быть, что IAR не может работать с этим типом контроллеров!!! Понимаю, что сам дурак, но в чем???
yung
Только сейчас бросилось в глаза. А почему main описан как int, а не void? Не здесь ли собака зарыта?
Miron
Цитата(yung @ Jun 21 2005, 15:59)
Только сейчас бросилось в глаза. А почему main описан как int, а не void? Не здесь ли собака зарыта?
*

Я суда тоже сразу посмотрел но yung меня опередил
хотя ведь программа то всеравно встает в цикл
while(1)
{

PORTB^=(1<<1);
i=0xffff;
while (i--);
}
}
и по идее никаких возвратов в никуда
быть не должно
может быть правда компилятор это как то не коректно
интерпритирует у меня всегда было void main(void) {}
Sergio66
Цитата(Miron @ Jun 21 2005, 15:14)
Цитата(yung @ Jun 21 2005, 15:59)
Только сейчас бросилось в глаза. А почему main описан как int, а не void? Не здесь ли собака зарыта?
*

Я суда тоже сразу посмотрел но yung меня опередил
хотя ведь программа то всеравно встает в цикл
while(1)
{

PORTB^=(1<<1);
i=0xffff;
while (i--);
}
}
и по идее никаких возвратов в никуда
быть не должно
может быть правда компилятор это как то не коректно
интерпритирует у меня всегда было void main(void) {}
*


Да, эта ошибочка вкралась, т.к. это была тестовая функция, самафорящая, что программа дошла до определенной точки. Вот int и осталось в наследство. Это решило проблему локально в этой коротенькой программке, но не решило в проекте. Там main объявлена как void. А весь сыр - бор проистекает именно от того, что не пускается проект...
Хотя, наверное, у меня на что-тот еще глаз замылился. Ведь чудес не бывает...
Посмотрим... Отпишу что и как...
NickB
Надобно посмотреть что за код генерирует компилятор
Ну и настройки стека
NickB
Напишите вместо
while (i--);
таким образом
while (--i);

и будет вам счастье
(Проверил в версии 3.20.С)
Olegovich
Цитата(yung @ Jun 21 2005, 14:59)
Только сейчас бросилось в глаза. А почему main описан как int, а не void? Не здесь ли собака зарыта?
*


main надо описывать как int в случае, если в опциях проекта указан режим C++, а как void, если просто C.
smile.gif
Sergio66
Цитата(NickB @ Jun 21 2005, 15:39)
Напишите вместо
while (i--);
таким образом
while (--i);

и будет вам счастье
(Проверил в версии 3.20.С)
*

Не, не будет счастья... Потому, что хрен редьки не толще...
ничего не поменялось...
Микросхема запускается через раз, моргает диодом почему-то в четверть накала, иногда в полный накал... Не понимаю, чтот происходит.
Микросхема запрограммирована, один раз запускаю - работаеет в четверть накала, другой раз - нормально. На асме таких проблем нет!
Sergio66
Цитата(NickB @ Jun 21 2005, 15:28)
Надобно посмотреть что за код генерирует компилятор
Ну и настройки стека
*

Вот код на С:
void main( void ){
unsigned int pause;
DDRB|= (1<<PB1);
for(;;)
{
PORTB^=(1<<PB1);
pause = 0xffff;
while(--pause);
}
}
вот перевод на асм:
// 19 DDRB|= (1<<PB1);
SBI 0x17, 0x01
// 20
// 21 for(;;)
// 22 {
// 23 PORTB^=(1<<PB1);
??main_0:
LDI R16, 2
IN R17, 0x18
EOR R17, R16
OUT 0x18, R17
// 24
// 25 pause = 0xffff;
LDI R24, 255
LDI R25, 255
// 26 while(--pause);
??main_1:
SBIW R25:R24, 1
MOVW R31:R30, R25:R24
MOVW R25:R24, R31:R30
OR R30, R31
BRNE ??main_1
RJMP ??main_0
ничего крамольного...
вроде, все логично...
но камень запускается через раз, и не всегда ярко моргает диод.
NickB
А что асм в листинге показывает ?
Может глюк какой ?
dxp
Цитата(Sergio66 @ Jun 21 2005, 17:40)
Я два дня назад создал тему HELP MEGA8. Спасибо всем, кто откликнулся. Однако, проблема оказалась совсем не в подключении кристалла, в совершенно в другом месте! Проблема оказалась в IAR 4.10B/W32 (4.10.2.5).
Вот такой код на С:
#include <iom8.h>

int main( void )
{
    long unsigned int i;
    DDRB|= (1<<1);

  while(1)
{

    PORTB^=(1<<1);
    i=0xffff;
    while (i--);
}
}
все догадались, что должно произойти. Диод на PB1 должен моргать.
Однако, камень запускается раз на 4 - 5 включений питания. (Все подтянуто, все сглажено).
*

Этот код (в цикле который) порождает:
Код
  while(1)
  {

      PORTB^=(1<<1);
      ??main_0:
E002               LDI     R16, 2
B318               IN      R17, 0x18
2710               EOR     R17, R16
BB18               OUT     0x18, R17
      i=0xffff;
      while (i--);
CFFB               RJMP    ??main_0
  }

Т.е. реально задержки, как видно, никаой нет. Просто компилятор посмотрел тут, что ничего содержательного в цикле while (i--); не делается, поэтому решил, что этот цикл надо заоптимизировать, с чем он успешно справился. smile.gif

А вот если объявить i как volatile, то тогда он (компилятор) уже не будет иметь права делать какие-либо оптимизации на ее счет и получится реальный цикл:
Код
int main( void )
{
   volatile unsigned int i;
   DDRB|= (1<<1);

   while(1)
   {      
           
       PORTB^=(1<<1);
       i=0xffff;          
       while (i--);            
   }                          
}

РЕЗУЛЬТАТ:

  while(1)
  {

      PORTB^=(1<<1);
      ??main_0:
E002               LDI     R16, 2
B318               IN      R17, 0x18
2710               EOR     R17, R16
BB18               OUT     0x18, R17
      i=0xffff;
EF0F               LDI     R16, 255
8308               ST      Y, R16
8309               STD     Y+1, R16
      while (i--);
      ??main_1:
8108               LD      R16, Y
8119               LDD     R17, Y+1
01C8               MOVW    R25:R24, R17:R16
9701               SBIW    R25:R24, 1
8388               ST      Y, R24
8399               STD     Y+1, R25
2B01               OR      R16, R17
F7C1               BRNE    ??main_1
CFF0               RJMP    ??main_0
  }

Как видно, цикл тут получился не в две инструкции. Т.е. если цель была сформировать задержку, то тут придется конкретно подбирать количество циклов. Сие не есть гуд и для оной цели у IAR'а есть специальная функция __delay_cycles(unsigned long), которая заставляет компилятор корректно сгенерировать задержку из указанного количества циклов.

Кстати, что за тип такой странный - long unsigned int i;?

И еще не понял, почему то запускалось, то нет. Не вижу связи с кодом. По логике оно просто должно было маслать в цикле без задержки, т.е. на ноге должны были быть переключения с периодом цикла инверсии состояния пина. Что-то там еще есть, что не попало в наше поле зрения. smile.gif
Sergio66
long unsigned int i;
long - случайно попало при копировании в конфу. На самом деле, там стоит самое, что ни на есть unsigned int i;
И дело тут не в volatile, т.к. я отключил всякую оптимизацию.
И цикл отрабатывается компилятором верно, чтот видно из листинга.
NickB
так чтобы получился цикл задержки надо либо убрать оптимизацию
либо включить в цикл __no_operation()
Volatile тоже годится но переменная становится глобальной
Sergio66
И еще, я убрал из программы все, что может косвенно служить источником неприятностей, это касается функции задержки. То, что сделал я - по крайней мере, видно, как работает.
NickB
А чем Вы грузите устр в первом и во втором случае?
Sergio66
Цитата(NickB @ Jun 21 2005, 16:59)
А чем Вы грузите устр в первом и во втором случае?
*

AS-2 Argussoft на других проектах проблем не было. Кстати, откомпиллированный код на асме (который работает без вопросов) я шью этим же программатором.
Sergio66
Еще один прикол от IAR?
Пишем:
DDRB|= (1<<PB1);

for(;;) {
PORTB^=(1<<PB1);
Delay(500);
}
где Delay() - библиотечная ф-я
и эта прога пускается не всегда, и чаще всего, диод моргает в четверть накала.
А вот код

for(;;)
{
DDRB|= (1<<PB1);
PORTB^=(1<<PB1);
Delay(500);
}
пускается, правда, тоже не всегда, но диод моргает в полный рост!
Выходит, команда DDRB|= (1<<PB1); в первом случае не успевает выполняться (ну не выполняется она!!!) И диод оказывается подключен к ноге, опрределенной на ввод, с подтянутым резистором!
Как такое может быть???
indela
Цитата(Sergio66 @ Jun 21 2005, 18:07)
Еще один прикол от IAR?
Пишем:
    DDRB|= (1<<PB1);

    for(;;)    {
        PORTB^=(1<<PB1);
        Delay(500);
    }
где Delay() - библиотечная ф-я
и эта прога пускается не всегда, и чаще всего, диод моргает в четверть накала.
А вот код
   
    for(;;)
    {
        DDRB|= (1<<PB1);
        PORTB^=(1<<PB1);
        Delay(500);
    }
пускается, правда, тоже не всегда, но диод моргает в полный рост!
Выходит, команда  DDRB|= (1<<PB1); в первом случае не успевает выполняться (ну не выполняется она!!!) И диод оказывается подключен к ноге, опрределенной на ввод, с подтянутым резистором!
Как такое может быть???
*


4.10 все работает только что проверил
Sergio66
Есть!!!!! Заработало!!!
Обратил внимание на то, что не выполняется первая команда программы. Оказалось, что в нулевом слове зашиты 00, т.е. по ресету выполняется NOP, и далее - по всем векторам. А вектора инициализированы RETI, далее - понятно.
Начал искать, как инициализировать RST_VECT, и оказалось, что в опциях линкера, почему то указан выходной формат intel-extended, а он в свою очередь (это тоже оказалось) 4 прервых байта просто меняет на 0!!!
Вот и все!!! И это целый день коллективного мозгового штурма. Спасибо всем, кто принял участие!
NickB
Похоже что ваш программатор неверно понимает формат Intel Extended
Там в первой строке должен быть адрес сегмента Вот он то и равет нулю
yung
Зато сколько информативных постов! biggrin.gif biggrin.gif biggrin.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.