реклама на сайте
подробности

 
 
> C++, мучения в освоении и JTAG отладке
Aprox
сообщение Mar 14 2011, 18:42
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 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(). Мне кажется, пережитые мучения пойдут на пользу всем, кто хочет переползти с С на С++.
Go to the top of the page
 
+Quote Post
2 страниц V  < 1 2  
Start new topic
Ответов (15 - 23)
Aprox
сообщение Mar 18 2011, 08:16
Сообщение #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(). Честно говоря, я не понимаю, почему это плохо и неидейно.
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Mar 18 2011, 08:24
Сообщение #17


Знающий
****

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



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

Значит вы писали софт на Си, причем здесь С++?


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
Aprox
сообщение Mar 18 2011, 11:10
Сообщение #18


Местный
***

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



Цитата(Andy Mozzhevilov @ Mar 18 2011, 11:24) *
Значит вы писали софт на Си, причем здесь С++?
Не совсем. Внутри задач я создавал и использовал объекты. Например строки. Правда, они не были глобальными и создавались методом new при запуске каждой задачи UCOS. Сейчас же, как я понимаю, вся проблема в том, что программные модули взаимодействуют напрямую, через общие глобальные объекты.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Mar 18 2011, 18:28
Сообщение #19


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(Aprox @ Mar 18 2011, 15:10) *
Не совсем. Внутри задач я создавал и использовал объекты. Например строки. Правда, они не были глобальными и создавались методом new при запуске каждой задачи UCOS. Сейчас же, как я понимаю, вся проблема в том, что программные модули взаимодействуют напрямую, через общие глобальные объекты.


А кто вам сказал, что обычные объекты можно "запросто" использовать в многозадачных OS? Если объявлены глобальные объекты, совместно используемые в разных задачах (потоках), вам предстоит самому обеспечивать синхронизацию доступа к таким объектам. Для того и сделаны всякие там мьютексы, семафоры, критические секции. Вы почитайте книги про это, очень полезно.
Go to the top of the page
 
+Quote Post
Aprox
сообщение Mar 19 2011, 09:30
Сообщение #20


Местный
***

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



Цитата(sergeeff @ Mar 18 2011, 21:28) *
А кто вам сказал, что обычные объекты можно "запросто" использовать в многозадачных OS? Если объявлены глобальные объекты, совместно используемые в разных задачах (потоках), вам предстоит самому обеспечивать синхронизацию доступа к таким объектам. Для того и сделаны всякие там мьютексы, семафоры, критические секции. Вы почитайте книги про это, очень полезно.
Наверное неверно понимаете. Я писал, что сейчас работаю с проектом, в котором нет многозадачной real-time OS и поэтому взаимодействие программных модулей приходится производить через глобальные объекты. Разговор же про OS происходил по другому поводу- что в случае с многозадачной OS нет нужды городить глобальные объекты и, соответственно, не возникает проблем в С++ со "стартапами" периферии. Пример, в задаче управления UART, вся инициализации необходимой периферии производится в начале процедуры, которую назначили "задачей". Там же, внутри процедуры вызываются конструкторы объектов, например класса string. Получаем локальные, не глобальные объекты, которые созданы после main() и после всех стартапов. А уж передавать эти обьекты, вернее указатели на них, другим задачам, действительно можно через семафоры, очереди OS и прочие фифо.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Mar 19 2011, 09:38
Сообщение #21


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(Aprox @ Mar 19 2011, 13:30) *
Наверное неверно понимаете.


Как пишите, так и понимаю...
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Mar 23 2011, 13:18
Сообщение #22


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Цитата
2. Вызвать из нее функцию статической инициализации iar


Можно по подробней что это за функция что то в мануале не нашел ?
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Mar 23 2011, 17:30
Сообщение #23


Знающий
****

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



Цитата(MALLOY2 @ Mar 23 2011, 16:18) *
Можно по подробней что это за функция что то в мануале не нашел ?

Точку входа можно найти, прошагав в отладчике стартап. Обычно с iar можно найти исходники статической и динамической инициализации, которые используются в startup.
Завтра на работе посмотрю точно, что я вызываю в low_level_init()


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Mar 24 2011, 08:12
Сообщение #24


Знающий
****

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



Код
// __iar_data_init -  функция из библиотеки, выполняющия фазу static segment initialization
// Для разных версий функции инициализации сегмента данных вызываются по разным именам
// __VER__ - предопределенное макро в IAR, см. документацию на компилятор
#if __VER__ <= 5011000
/* Для IAR 5.11 */
extern __interwork  void __iar_data_init(void);
/* Для IAR 5.20 и выше */
#elif __VER__< 5050005
extern __interwork  void __iar_data_init2(void);
#elif __VER__<= 6010001
// Версия Iar с 5.50.5 по 6.10.1
extern void * __iar_cstart_call_ctors(void *ptr);
extern __interwork void __iar_data_init3 (void);
#else   // Версия Iar выше 6.10.1
#error Untested init sequence for this compiler version
#endif


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th July 2025 - 16:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01472 секунд с 7
ELECTRONIX ©2004-2016