|
C++, мучения в освоении и JTAG отладке |
|
|
|
Mar 14 2011, 18:42
|

Местный
  
Группа: Участник
Сообщений: 374
Регистрация: 7-11-07
Из: Moscow
Пользователь №: 32 131

|
Расскажу один назидательный случай, который случился со мной в освоении и отладке программ на С++. После того, как разобрался с помощью гуру, как разместить константы во Flash, а нев SRAM, со мной случилась другая проблема, связанная с загрузкой и JTAJ отладкой. Когда программа на С++ блистала своей красотой и лаконичностью, когда все прекрасно показывал симулятор IAR, настала пора грузить ее в кристалл. И вот тут-то началось! Отладчик JTAG упорно не хотел добегать до метки main, программа ускакивала в ловушку на векторе UndefinedHandler. Опускаю процесс поисков, сразу к сути. Оказывается, нельзя ни в коем случае в глобальных объектах заниматься инициализацией периферии кристалла. Вообще касаться периферии нельзя! Резонов два: -1. порядок вызовов конструкторов не определен, и -2 при JTAG отладке ARM после загрузки FLASH успевает промолотить еще достаточное количество инструкций прежде, чем сработает break по RESET и сдернет программу обратно в address_reset. Последнее меня и погубило. Дело в том, что я записал в конструктор куски инициализации Flash, а отладчик сдергивал кристалл как раз в момент этой инициализации. Возвращался по Reset он уже в испорченное содержимое сегмента-векторов. Победить удалось следующим приемом- из конструкторов глобальных объектов убрал любое обращение к периферии кристалла. Вместо этого, ввел в классы с периферией методы инициализации периферии типа obj.Start() с вызовом этих методов после входа в main(). Мне кажется, пережитые мучения пойдут на пользу всем, кто хочет переползти с С на С++.
|
|
|
|
|
 |
Ответов
|
Mar 17 2011, 17:28
|

Местный
  
Группа: Участник
Сообщений: 374
Регистрация: 7-11-07
Из: Moscow
Пользователь №: 32 131

|
Цитата(Andy Mozzhevilov @ Mar 16 2011, 11:36)  Обращайтесь, если что. Можно в аську. Спасибо. Потыркался целый день, искал кого куда и в какой момент вызывать - сильно утомился. Решил, как обычно- "лучшее враг хорошего" и остановился на своем варианте- инициализировать периферию и C-библиотеки после входа в main(). Так проще прикладнику, которому важнее сделать работающую вещь, чем погрязнуть в тонкостях стартапов. У меня работает, а больше ничего и не надо. Вы говорили , что ucos инициализируют в low_leve_init. Я вспоминаю, когда года четыре назад возился с модулями Ethernet фирмы NetBurner, - там ucos инициализировалась вызовом Start_UCOS() сразу после входа в main(). Также инициализировался и TCP/IP стек вызовом Start_Enet(), тоже после main(). Все они написаны на C. А приложение пользователя писалось на C++. Компилятор был GCC. Собственно, те четырехлетние воспоминания и спасли меня от мучений с реал-тайм JTAG отладкой на IAR.
|
|
|
|
|
Mar 18 2011, 04:37
|

Знающий
   
Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206

|
Цитата(Aprox @ Mar 17 2011, 20:28)  Вы говорили , что ucos инициализируют в low_leve_init. Я вспоминаю, когда года четыре назад возился с модулями Ethernet фирмы NetBurner, - там ucos инициализировалась вызовом Start_UCOS() сразу после входа в main(). Я говорил, что я так делаю. Как делают другие, не знаю. Если uCOS инициализировать стандартным способом, т.е. вызовом из main(), то в ПО на С++ теряется возможность создавать объекты, использующие сервисы uCOS в конструкторах объектов, объявленных глобально, т.е. необходимо каждый раз прибегать к вызову дополнительной функции инициализации. С моей точки зрения, если внутри объекта к примеру используется семафор, логично, чтобы этот семафор создавался (выделялся) в конструкторе объекта. В этом случае после создания объекта он готов к использованию без дополнительных вызовов. Это как раз и решается нужной организацией стартапа (в части low_level_init()). Поэтому способ, который я описал, он полностью рабочий и проверенный на практике. Конечно, если ПО написано полностью на Си, то эти заморочки ни к чему.
--------------------
Пасу котов...
|
|
|
|
|
Mar 18 2011, 08:16
|

Местный
  
Группа: Участник
Сообщений: 374
Регистрация: 7-11-07
Из: Moscow
Пользователь №: 32 131

|
Цитата(Andy Mozzhevilov @ Mar 18 2011, 07:37)  Если uCOS инициализировать стандартным способом, т.е. вызовом из main(), то в ПО на С++ теряется возможность создавать объекты, использующие сервисы uCOS в конструкторах объектов, объявленных глобально, т.е. необходимо каждый раз прибегать к вызову дополнительной функции инициализации. С моей точки зрения, если внутри объекта к примеру используется семафор, логично, чтобы этот семафор создавался (выделялся) в конструкторе объекта. В этом случае после создания объекта он готов к использованию без дополнительных вызовов. Это как раз и решается нужной организацией стартапа (в части low_level_init()). Вспоминаю, что в примерах C++ приложений для тех модулей с UCOS и TCP/IP стеком, объекты вообще не применялись. Это были примеры, как использовать готовые библиотеки на C. Мне потребовалось только дописать свои задачи управления I2C, SPI и UART, связать их средствами UCOS. Инициализация периферии происходила в момент создания задач через UCOS, т.е. после main(). Честно говоря, я не понимаю, почему это плохо и неидейно.
|
|
|
|
|
Mar 18 2011, 08:24
|

Знающий
   
Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206

|
Цитата(Aprox @ Mar 18 2011, 11:16)  Вспоминаю, что в примерах C++ приложений для тех модулей с UCOS и TCP/IP стеком, объекты вообще не применялись. Это были примеры, как использовать готовые библиотеки на C. Мне потребовалось только дописать свои задачи управления I2C, SPI и UART, связать их средствами UCOS. Инициализация периферии происходила в момент создания задач через UCOS, т.е. после main(). Честно говоря, я не понимаю, почему это плохо и неидейно. Значит вы писали софт на Си, причем здесь С++?
--------------------
Пасу котов...
|
|
|
|
|
Mar 18 2011, 11:10
|

Местный
  
Группа: Участник
Сообщений: 374
Регистрация: 7-11-07
Из: Moscow
Пользователь №: 32 131

|
Цитата(Andy Mozzhevilov @ Mar 18 2011, 11:24)  Значит вы писали софт на Си, причем здесь С++? Не совсем. Внутри задач я создавал и использовал объекты. Например строки. Правда, они не были глобальными и создавались методом new при запуске каждой задачи UCOS. Сейчас же, как я понимаю, вся проблема в том, что программные модули взаимодействуют напрямую, через общие глобальные объекты.
|
|
|
|
Сообщений в этой теме
Aprox C++ Mar 14 2011, 18:42 sergeeff Цитата(Aprox @ Mar 14 2011, 22:42) Расска... Mar 14 2011, 19:11 Aprox Цитата(sergeeff @ Mar 14 2011, 22:11) Вам... Mar 15 2011, 08:26  Сергей Борщ Вставьте в low_level_init задержку чтобы отладчик ... Mar 15 2011, 10:04   Aprox Цитата(Сергей Борщ @ Mar 15 2011, 13:04) ... Mar 15 2011, 11:20    Andy Mozzhevilov Цитата(Aprox @ Mar 15 2011, 14:20) Я рабо... Mar 15 2011, 12:19     Aprox Цитата(Andy Mozzhevilov @ Mar 15 2011, 15... Mar 15 2011, 14:49      Andy Mozzhevilov Цитата(Aprox @ Mar 15 2011, 17:49) Да, я ... Mar 15 2011, 16:08       sergeeff Цитата(Andy Mozzhevilov @ Mar 15 2011, 20... Mar 15 2011, 22:01       Aprox Цитата(Andy Mozzhevilov @ Mar 15 2011, 19... Mar 16 2011, 07:23    Сергей Борщ QUOTE (Aprox @ Mar 15 2011, 13:20) А в бо... Mar 15 2011, 14:01  Andy Mozzhevilov Цитата(Aprox @ Mar 15 2011, 11:26) Я проб... Mar 15 2011, 10:10      sergeeff Цитата(Aprox @ Mar 18 2011, 15:10) Не сов... Mar 18 2011, 18:28       Aprox Цитата(sergeeff @ Mar 18 2011, 21:28) А к... Mar 19 2011, 09:30        sergeeff Цитата(Aprox @ Mar 19 2011, 13:30) Наверн... Mar 19 2011, 09:38 MALLOY2 Цитата2. Вызвать из нее функцию статической инициа... Mar 23 2011, 13:18 Andy Mozzhevilov Цитата(MALLOY2 @ Mar 23 2011, 16:18) Можн... Mar 23 2011, 17:30  Andy Mozzhevilov Код// __iar_data_init - функция из библиотеки, вы... Mar 24 2011, 08:12
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|