Перейти к содержанию
    

Контроллер впадает в ступор..

Имеется проект для IAR'a под Атмегу32А, он компилится и работает нормально..

 

Решил перенести проект в AVR Studio 5.1, не сразу, но получилось, компилится нормально, без ошибок и предупреждений. Однако в железе работать не хочет, микроконтроллер впадает в ступор :(

 

Опытным путем выяснилось, что происходит это во время инициализации UART, а именно после записи в регистр UCSRB. Причем контроллеру не нравится запись именно бита UDRIE - если его оставить нулем, то ступора не будет (но при этом не будет работать правильно железо)

 

Сам исходник большой, наверно нет смысла его тут приводить, а функция инициализации UART'a выглядит вот так :

 

void InitUART()
{

    UCSRA=0x00; 

    UCSRB = (1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN)|(1<<UDRIE);  

        UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); 

        UBRRH=0;
  
        UBRRL=12;//BAUD=57692.31 (+0.16%) <-baudrate for Fosc=12 MHz и 6 MHz.
  
        UART_RxBufIndex=0;
  
  
}

 

Даташит на Мегу32А читал, насколько понял, есть особенность только при записи в регистры UCSRC и UBRRH, в остальном все нормально..

 

Что делать, не понимаю :( Помогите пжлста..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что значит в ступор? где он зацикливается ? на прерывании по опустошению регистра UDR ? или по резету ?

Проверте в компиляторе alt+f7 / Toolchain/ AVR/GNU C Linker / Memory Settings -> поле Initial Stack Address. Должно быть пустым (или впишите RAMend для своего контроллера)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...Сам исходник большой, наверно нет смысла его тут приводить...

 

если термин "ступор" - это зависание , то....

 

как раз наоборот :) если Вы не видите проблем при инициализации в ввиде циклов, ифов и прочей лабуды - то проблемы в другом. это же очевидно вам или нет?

 

если Вы бы пошли дальше в своих рассуждениях, то достаточно комментировать вашу супер-пупер секретную мигалку светодиодами по блочно и смотреть когда эффект исчезнет(или проявится). дальше делите подозрительный блок лапополам и повторяете тест. и так вы дойдёте до действительно проблемного куска кода. и он будет не в этих строчках скорее всего.

 

если напрячь телепатию - то скорее всего идёт выше инициализация неких прерываний, обработчиков и иже. попробуйте отключить всё кроме вызова этой функции и вы увидите что она тут не причём.

 

 

(круглый)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что значит в ступор? где он зацикливается ? на прерывании по опустошению регистра UDR ? или по резету ?

Проверте в компиляторе alt+f7 / Toolchain/ AVR/GNU C Linker / Memory Settings -> поле Initial Stack Address. Должно быть пустым (или впишите RAMend для своего контроллера)

 

 

Ступор - зависание.

 

Поле Initial Stack Address проверял (как раз прочитал ваш пост об этом на форуме) - было пустым, прописал Ramend - не помогло.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По моему, Вам правильно намекнули на счет прерываний - похоже дело не в бите UDRIE а в том, что он разрешает прерывание из за которого и возникает "ступор"

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если Вы бы пошли дальше в своих рассуждениях, то достаточно комментировать вашу супер-пупер секретную мигалку светодиодами по блочно и смотреть когда эффект исчезнет(или проявится). дальше делите подозрительный блок лапополам и повторяете тест. и так вы дойдёте до действительно проблемного куска кода. и он будет не в этих строчках скорее всего.

 

У меня есть пищалка, включается программно, чтобы определять переход устройства из одного состояния в другое. Ее и использовал для определения проблемного места.

Если включать пищалку до записи в регистр UCSRB - пищит, если после записи в этот регистр - уже не пищит.

 

если напрячь телепатию - то скорее всего идёт выше инициализация неких прерываний, обработчиков и иже. попробуйте отключить всё кроме вызова этой функции и вы увидите что она тут не причём.

 

Выше идет вот это (сразу после этих строк вызов InitUART) :

 

 SREG=0x80;
  GICR=0x00;
  GIFR=0x00;

  MCUCR = 0x80; 
  
  
  MCUCSR=0x00;
  
  WDTCR=0x10;
  
  SFIOR=0x00;

  DDRA =0x00; // if '1' --> PORTAn --> OUT;   if '0' --> PORTAn --> IN
  DDRB =0xFF; // if '1' --> PORTBn --> OUT;   if '0' --> PORTBn --> IN
  DDRC =0xFF; // if '1' --> PORTCn --> OUT;   if '0' --> PORTCn --> IN
  DDRD =0x0C; // if '1' --> PORTDn --> OUT;   if '0' --> PORTDn --> IN
  

//******************************************************************************  
  PORTA=0xDF;   // ножку 5 порта А переводим в Z-состояние, на остальных Pull-up
//******************************************************************************  
  
  PORTB=0x00;
  PORTC=0xFF;
  PORTD=PORTD | 0xFC;

  SPCR=0x00;//F0;
  SPSR=0x01;
  //-------     Настройка таймера TIMER0  --------------------------------------
  
  ASSR  = 0x00; 
               
  TIMSK = 0x42; 
  TCNT0 = 0x00; 

  
  TCCR0 = 0x0D; 
                
  
  //-------  Кварцевый резонатор  12 МГц  --------------------------------------
  OCR0  = 11;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если включать пищалку до записи в регистр UCSRB - пищит, если после записи в этот регистр - уже не пищит.
Контроллер после записи в этот регистр уходит в прерывание UDR. Сразу. Ибо глобально прерывания разрешены, а UDR пуст. Обработчик прерывания написан? Имя его правильное? Он располагается по правильному адресу? Посмотрите в дизассемблере, куда указывает вектор этого прерывания? Что делает обработчик этого прерывания, если учесть, что у вас еще нет данных для передачи? Очень странным выглядит взведение UDRIE в инициализации - обычно его взводят перед отправкой данных, чтобы в обработчике осуществить загрузку UDR из буфера передачи, и сбрасывают после опустошения буфера.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Контроллер после записи в этот регистр уходит в прерывание UDR. Сразу. Ибо глобально прерывания разрешены, а UDR пуст. Обработчик прерывания написан? Имя его правильное? Он располагается по правильному адресу? Посмотрите в дизассемблере, куда указывает вектор этого прерывания? Что делает обработчик этого прерывания, если учесть, что у вас еще нет данных для передачи? Очень странным выглядит взведение UDRIE в инициализации - обычно его взводят перед отправкой данных, чтобы в обработчике осуществить загрузку UDR из буфера передачи, и сбрасывают после опустошения буфера.

 

 

Обработчик прерывания (USART__UDRE_vect - правильно понимаю?) не написан..

 

Взведение бита UDRIE сделано потому, что так было в исходнике, который мне достался по наследству, как уже писал выше, этот проект изначально был сделан в IAR'e, я же решил его перенести в среду AVR Studio. Удивительно, что этот же код работает после IAR'а - hex-файл прошил в контроллер, все функционирует..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Удивительно, что этот же код работает после IAR'а - hex-файл прошил в контроллер, все функционирует..

В IAR-е возможно все неиспользуемые прерывания заполняются RETI.

В AVRGCC jmp BAD_VECTOR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Обработчик прерывания (USART__UDRE_vect - правильно понимаю?) не написан..

 

Оень плохая практика включать прерывания, на которые не реализованы обработчики. Более того, раз обработчика нету, значит программе то прерывание вообще не нужно.

Либо уберите тот бит, либо реализуйте обработчик.

Иначе всегда будете зависеть от каких-то "подковёрных" особенностей разных компиляторов.

И даже не факт, что выйдет какая-то другая версия IARа и в ней будет всё по-старому ....

Изменено пользователем hd44780

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оень плохая практика включать прерывания, на которые не реализованы обработчики. Более того, раз обработчика нету, значит программе то прерывание вообще не нужно.

Либо уберите тот бит, либо реализуйте обработчик.

Иначе всегда будете зависеть от каких-то "подковёрных" особенностей разных компиляторов.

И даже не факт, что выйдет какая-то другая версия IARа и в ней будет всё по-старому ....

Делается немного проще при отладке - по вектору ставится сброс флага и возврат, а сам обработчик можно дописать позднее, зато не надо лишний раз перепахивать инициализацию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оень плохая практика включать прерывания, на которые не реализованы обработчики. Более того, раз обработчика нету, значит программе то прерывание вообще не нужно.

Либо уберите тот бит, либо реализуйте обработчик.

 

 

Если бит убираю - устройство работает неправильно, но похоже, что причина где-то в другом месте.. Видимо, код был написан без учета существования других компиляторов.

Буду разбираться дальше. Спасибо всем ответившим, пока есть куда копать :)

Изменено пользователем Charoit

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В IAR-е возможно все неиспользуемые прерывания заполняются RETI.
Возможно (но маловероятно). И что бы нам это дало? Попадаем в обработчик, но поскольку в обработчике не было записи в UDR - флаг не сбрасывается, возвращаемся в основной цикл, выполняем одну ассемблерную инструкцию и снова улетаем в обработчик и так по кругу. Не, это конечно довольно оригинальный способ замедлить выполнение программы в пару десятков раз и запретить все прерывания с более низким приоритетом, но как-то это странно.

 

 

Если бит убираю - устройство работает неправильно
Может быть этот обработчик там есть, но спрятан в каком-то другом файле?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Взять и написать обработчик UDR одной строкой - тупо отсылать туда 0x00 или 0xFF / Запищит значит в нём дело.

И скорее всего дело именно в нём

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно (но маловероятно).

50 на 50.

Если задано IAR-у заполнить - заполнит, не задано - не заполнит.

 

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

Да, оригинально. Но работать будет.

Пока watchdog не сбросит.

 

Может быть этот обработчик там есть, но спрятан в каком-то другом файле?

Вариант.

 

 

Взять и написать обработчик UDR одной строкой - тупо отсылать туда 0x00 или 0xFF / Запищит значит в нём дело.

И скорее всего дело именно в нём

 

Или запретить в нём прерывание USART_UDRE.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...