Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: hard fault stm32
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
dimanisu
Здравствуйте!

Столкнулся со следующей проблемой.
Разрабатываю в keil под stm32. Раньше все проекты писал на си. Сейчас решил опробовать с++.
В проекте много сишных файлов. Включил в проект один .cpp файл. Все работало. Решил немного усложнить используемый класс. Ввел наследование. И программа посыпалась – вылетает в hard_fault прерывание. Причем не там, где вызываются мои объекты с их методами, а гораздо раньше и в совершенно другом месте.
Объекты создаются как обычно, а не через new:
TItem item((const u8*)”текст”);
Причем обнаружил следующую закономерность:
Если уменьшить количество создаваемых объектов, то программа вроде как работает. Но вот если добавить несколько строчек кода в любое другое место, программа опять вылетает в hard_fault.
Пробовал увеличивать размер стека и кучи. Это не помогло.
Раньше с таким не сталкивался
Подскажите пожалуйста, в чем может быть загвоздка?

Вылетает при обращении к жки. Он висит на fsmc шине. Раньше все работало нормально.
CODE
Код
typedef struct
{
volatile u16 reg;
volatile u16 ram;
} Tlcd;


// Note: LCD /CS is CE4 - Bank 4 of NOR/SRAM Bank 1~4
#define LCD_BASE ((u32)(0x60000000 | 0x0C000000))
#define LCD ((Tlcd *) LCD_BASE)


#define WRITE_CMD(value) LCD->reg=value
#define WRITE_DATA8(value) LCD->ram=value

*************************************************

void init_lcd (void)
{

//разный код

WRITE_CMD(LCD_SOFT_RESET);
WRITE_CMD(LCD_SOFT_RESET); // вылетает здесь
WRITE_CMD(LCD_SOFT_RESET);

}

// вот что творит keil
Код
199: WRITE_CMD(SSD1963_SOFT_RESET);
0x08003E88 2001 MOVS r0,#0x01
0x08003E8A F04F41D8 MOV r1,#0x6C000000
0x08003E8E 8008 STRH r0,[r1,#0x00]
200: WRITE_CMD(SSD1963_SOFT_RESET);
0x08003E90 8008 STRH r0,[r1,#0x00]
201: WRITE_CMD(SSD1963_SOFT_RESET);
202:
0x08003E92 8008 STRH r0,[r1,#0x00]
klen
объекты создаются глобально или на стеке?
dimanisu
Объекты создаются глобально.
dimanisu
У меня такое ощущение, что затык как раз в том, что объекты глобальные. Насколько я понял они создаются до вызова main и тем самым как то поганят программу.
Нужно еще выполнять какие либо танцы с бубном, чтобы использовать с++ файлы совместно с сишними (ну там выставлять опции компилятора, править стартапы и т.д. и т.п)?

Forger
Цитата(dimanisu @ Oct 26 2011, 17:17) *
У меня такое ощущение, что затык как раз в том, что объекты глобальные.

Посмотрите тут мою реализацию. Может поможет.
До того, как я стал делать так, как описал, то сталкивался с проблемой, очень похожей на вашу: при статическом создании экэмпляров классов их порядок имел значение.
А вообще, код перед кодированием приходится всегда вначеле проектировать, иначе получится каша, которую по-просту уже невозможно отлаживать.
А у вас есть структура (дерево) классов проекта или что-то подобное?
dimanisu
Цитата
А у вас есть структура (дерево) классов проекта или что-то подобное?

Есть, структуру я уже продумал. Я сейчас создаю простой gui. И решил испробовать c++ реализацию. Пока создал два класса. TItem и наследника TMenu. Если без наследования(т.е. все в одном классе) то все работает, но вот с наследованием и случается эта беда.

Классы немного упрощены и все поля объявлены как public (потом раскидаю по секциям как надо)
CODE
class TItem;

class TItem
{
public:
u16 id;
const u8* text;
TItem* parent;
TItem* prev; // предыдущий сосед
TItem* next; // следующий сосед
TItem* child;
TItem* selected; //выбранный пункт меню
u16 count; // счетчик узлов

static TItem* active;

TItem (const u8* text);
void activate(TItem* item); // установка активным друго пункта меню

virtual void add(TItem* item);
virtual void draw();
virtual void event(u32 event, u32 param1=0, u32 param2=0){}
};


class TMenu : public TItem
{
public:
TItem* visible_first_child; //первый отображаемый пункт
TItem* visible_last_child; //последний отображаемый пункт

TMenu (const u8* text, u16 num_visible_items=1);
virtual void add(TItem* item);
virtual void draw();
virtual void event(u32 event, u32 param1=0, u32 param2=0);
};
Forger
Цитата(dimanisu @ Oct 27 2011, 10:11) *
Классы немного упрощены и все поля объявлены как public (потом раскидаю по секциям как надо)

Пара дельных советов из моего печального опыта:
поля класса (это объекты-данные класса) НИКОГДА не ставьте в секцию public, даже для целей отладки
Для полей допустимо только private, в особых случаях protected.
Это - пагубная привычка, потому что потом так и останется :-))
Через методы можно ограничить доступ к полям, там же защитить их мьютексами/критическими секциями...
Т.е. доступ к полям должен прозводится ТОЛЬКО через методы класса.
А если все же требуется прямое обращение к полям, то это уже не класс, а обычная структура (разумеется без методов).

Где возможно расставлять const - это защищает от лени программиста искать правильные пути.

Вообще мне не понятно, зачем вы пишите свой GUI, для изучения С++?
Есть же ведь готовые реализации GUI в исходниках и на C++. Берите их и изучайте.
Благо щас готового и даже полностью бесплатного софта море, вот лет 5..10 назад такого увы не было...

dimanisu
Цитата
Т.е. доступ к полям должен прозводится ТОЛЬКО через методы класса.

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

Цитата
Вообще мне не понятно, зачем вы пишите свой GUI, для изучения С++?


С++ мне не нужно изучать. Мне не нужны навороченные gui библиотеки. GUI будет простой. Я начал его писать на си, но потом решил попробовать c++. Под arm ранее писал только на си. Использование С++ для контроллеров для меня в диковинку, вот и решил попробовать.
И Сразу грабли biggrin.gif.

Под дебагером смотрел - сначала вызываются конструкторы, потом только main.

Цитата
Есть же ведь готовые реализации GUI в исходниках и на C++.

Если не не сложно киньте ссылочкой на с++ реализацию под arm.


Forger
Цитата(dimanisu @ Oct 27 2011, 12:01) *
Под дебагером смотрел - сначала вызываются конструкторы, потом только main.


Все верно, так и должно быть, однако порядок вызова конструкторов определяет линковщик.
Ясное дело объекты в пределах одного cpp файла создаются в порядке их объявления (хотя я в этом не особо уверен).
А вот в каком порядке линковщих собирает откомпилированные срр файлы - неизвестно,
а это создает немалые сложности, которые зависят от компилятора.
А в классе объекты-поля ВСЕГДА создаются в порядке их перечисления - это стандарт С++.
Все это важно, когда все объекты создаются статически, т.е. до вызова main.
Но если использовать кучу - эта проблема отпадает, но возникает другая - сама куча.
Например, я стараюсь избегать использования кучи везде, где это возможно, а взамен нее использовать пулы (fixed size memory pool) или стек.
Разумеется, тут я имею ввиду embedded приложения - под виндой все это намного прозаичнее, хотя тоже требует осмысленных действий.

Я еще частенько использую другой способ - отложенная инициализация,
это когда взамен конструктора (или только часть его реализации) заменяется спец. методом, у меня он называется initialize(),
который вызывает уже в коде, это дает возможность в нужном порядке инициализировать объейты классов.

Цитата
Если не не сложно киньте ссылочкой на с++ реализацию под arm.

Для примера вот конкретно под Win X.
Есть весьма популярная Qt, но она мне кажется монстроподобной для небольших embedded.
Ну и стандартно: google :-))
Переписать драйвер под свой проц и железо - проблем нет.
Потом есть масса С реализаций GUI платформонезависимые, а не тока "под ARM" или что-то еще.
C++ "обертку" под C реализацию тоже можно создать. Не так сложно, как кажется - главное, сначала спроектировать все.
Например, я так сделал обертку под RTOS, теперь в ЛЮБОМ проекте мне по-барабану, какая ось стоит,
Это оказалось весьма удобной штукой как при сопровождении так и создании новых проектов на базе других.
Я бы попробовал именно такой путь (возможно, скоро этим и сам займусь )))).
klen
раз объекты создаются глобально, то надо удостоверится что crt код вызывает их конструкторы, иначе естественно ничего работать не будет.
dimanisu
Цитата
раз объекты создаются глобально, то надо удостоверится что crt код вызывает их конструкторы, иначе естественно ничего работать не будет.


Я в дебаге ставил точки останова в конструкторе - они вызываются. Прошу прощения, что за crt код? И если удостоверюсь, то как исправить?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.