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

Глюки программирования mega128

Программирую систему на ATmega128

и неважно на СИ или Паскале в WinAvr или МикроПаскале

 

Но возникает ситуация когда прошу, например,

подпрограмме вывести на LCD текст, а она вываливается (перезапускает main);

или не выполняются переходы при работе с прерываниями.

 

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

Мои эксперименты со стеком ничего не дали.

Как добиться логичности, чтобы переходы были такие, как написаны в программе, а не с глюками?

Не могут же разные компиляторы иметь похожие проблемы!

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


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

Вы название темы правильно указывайте - "Глюки моей программы для мега128" :)

 

Что значит "не видел в реальных программах даже обращений к стеку"? Как только в программе появляется функция, так сразу там есть обращение к стеку.

 

А по теме - отлаживайте. Если есть отладчик - после появления проблемы останавливайте выполнение и смотрите, где вы оказались и почему, какое состояние стека, глобальных данных. Дальше ставите бряки (в т.ч. на изменение данных) и выясняете проблемное место.

 

Если отладчика нет - делаете минимально работающую программу и постепенно добавляете в нее функционал. Когда появляются проблемы - тщательно изучаете добавленное последним...

 

Причину перезагрузки (сброс, вотчдог и т.п.) можно выяснить, в меге128 помнится есть соотв. регистр.

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


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

 

Непомнящий Евгений, спасибо за корректировку выражений.

 

Почему-то не могу настроить WinAvr совместно с AvrStudio

 

Как поймать неправильный выход из подпрограмм?

По программе я после Break должен выйти из for,

а реально начинается перезагруз заново main.

 

Может есть для мега128 какой-то общий подход, в том числе и контроля стека?

 

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


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

Может есть для мега128 какой-то общий подход, в том числе и контроля стека?

 

Заполните стек неким паттерном (0xdeadbeaf или на ваш вкус) и гляньте, что с ним сразу после перезагрузки. Дальше можно поставить бряк на изменение памяти вблизи низа стека - по идее в нормально режиме работы ваша программа туда доходить не должна.

 

Узнайте причину перезагрузки (см даташит, есть какой-то регистр с соотв. флагами). Если это вотчдог - отключите его, так проще выловить зависания ПО.

 

А так - получите минимальную рабочую программу и постепенно добавляйте кусочки.

 

 

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


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

вотчдог - отключен

 

программа большая, но была рабочая: LCD- работа с меню

Добавляю кусочками

 

Все работало пока не всунул работу с портом по прерыванию.

Прерывание настроил, но в некоторых случаях из глубины меню

нет выхода по программе, а реально начинается перезагруз заново main.

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


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

Вначале функции main прочитайте регистр MCUSR: в нем побитовые источники перегрузки контроллера.

 

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

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

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


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

Все работало пока не всунул работу с портом по прерыванию.

Прерывание настроил, но в некоторых случаях из глубины меню

нет выхода по программе, а реально начинается перезагруз заново main.

 

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

 

Засеките размер используемого стека до и после прерывания, вставьте проверку - если стека осталось мало - повиснуть, выдав наружу сигнал об этом

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


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

Проверьте на всякий случай фьюзы.

Не установлен ли фьюз совместимости с 103.

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


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

Я в чем не прав?

 

#define   BUFFER_SIZE  255 // 
unsigned char RxBuf [BUFFER_SIZE];  // 

// void LCD_WriteText (char font, char * text)   

void PRFMenu (void)  //
{

char *buffer="0";
char cchh;
unsigned char rank[3] = {0,0,0};

cchh = (char)RxBuf[7];                          LCD_WriteText (8,&cchh); // 1
            
itoa (RxBuf[3],buffer,10);                       LCD_WriteText (8,buffer);  // 2
itoa (rank[2], buffer, 10);                       LCD_WriteText (8,buffer);  // 3
}

 

объявление указателя buffer на строку из 2 байтов

// 1 - в RxBuf[7] - символ

а во 2 и 3 случае в buffer запихивается байт или больше

или нужно присвоение через cchh = RxBuf[3],

чтобы стек не вводить в казус?

 

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


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

Я в чем не прав?

 

ну вообще говоря при чем тут стек?

 char *buffer="0"; // это указатель на константу в памяти. Си дает так сделать? Может и дает, но менять ее нельзя. Для avr это по факту будет 2 байта в ОЗУ
itoa (RxBuf[3],buffer,10); // вы меняете константу  :maniac: Более того, если RxBuf[3] скажем 123, то вы меняете 4 байта (1,2,3,\0), т.е.  расстреливаете 2 байта ОЗУ после этой константы

 

Лучше как-то так

 char buffer[4];
itoa (RxBuf[3],buffer,10);

 

 

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


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

ну вообще говоря при чем тут стек?

объявление переменной в подпрограмме занимает место в стеке

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


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

 cchh = (char)RxBuf[7];                          LCD_WriteText (8,&cchh); // 1

 

Этот код тоже неаккуратный и он рабочий лишь потому, что в результате построения фрейма стека по соседству с cchh счастливым образом оказался завершающий строку ноль.

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


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

Почему в 1) случае выводится не всегда указанный текст,

а во 2) случае все четко

 

// void Text_Menu_String (char font, unsigned char x, unsigned char y, char * text) //

1)

Код:

Text_Menu_String (8,20,1, "Error_RS422: "); //

 

2)

Код:

char ER [] = "Error_RS422: ")

Text_Menu_String (8,20,1, ER); //

 

Разрешены прерывания только по UART ну и sei();

 

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


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

Зависит от компилятора, но обычно для первого случая он генерирует такую же переменную, как и во втором случае:

char _сгенерируемая_компилятором_метка_ [] = "Error_RS422: ";
Text_Menu_String (8,20,1, _сгенерируемая_компилятором_метка_);

только вот складирует эти переменные в самостоятельно определенном сегменте памяти.

Скорее всего именно эта память и портится.

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

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


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

Почему в 1) случае выводится не всегда указанный текст,

а во 2) случае все четко

потому что у avr классическая гарвардская архитектура (и флеш отмаплен только на адресное пространство команд, а озу только на данные) и константы из флеша загружаются специальными командами

во 2 случае данные из флеша копируются в переменную размещенную в ОЗУ.

А в 1, размещаются в стеке

 

В любом случае происходит лишнее копирование данных!

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

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


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

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

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

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

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

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

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

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

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

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