|
Начальная инициализация статических переменных. |
|
|
|
Jul 9 2012, 06:36
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 17-01-12
Пользователь №: 69 604

|
Среда - Keil Arm. Контроллер STM32F103. В Keil имеется функция SystemInit(), которая выполняется перед main().
Описание эффекта. В функции SystemInit() инициализируется несколько указателей-параметров объекта. При входе в функцию main() эти параметры обнуляются.
Вопрос. Что это? Возможно начальная инициализация статических переменных происходит после выполнения SystemInit()? Не похоже. Какие-то "заморочки со стеком?" может я какую-то "галочку" в опциях проекта не поставил?
|
|
|
|
|
Jul 9 2012, 07:09
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 17-01-12
Пользователь №: 69 604

|
Цитата(ViKo @ Jul 9 2012, 09:49)  Например? typedef struct TExtADCResult { bool Exist; unsigned long Value; } TExtADCResult; typedef struct TExtADC { TSPI *SPIPtr; void (*Select)(void); void (*Unselect)(void); void (*Start)(void); void (*Stop)(void); bool (*Ready)(void); void (*Reset)(void); TExtADCResult Result[8]; bool Exist; } TExtADC; #define ExtADC_CHAN_NUMBER 2 TExtADC ExtADCChanel[ExtADC_CHAN_NUMBER]; void SystemInit(void) { PeriferInit(); } void PeriferInit(void) { TExtADC_Create(&ExtADCChanel[0],&SPIChanel[0],&ExtADC1_Select,&ExtADC1_Unselect,&ExtADC_Start,&ExtADC_Stop,ExtADC1_Ready,ExtADC_Reset); TExtADC_Create(&ExtADCChanel[1],&SPIChanel[0],&ExtADC2_Select,&ExtADC2_Unselect,&ExtADC_Start,&ExtADC_Stop,ExtADC2_Ready,ExtADC_Reset); } В TExtADC_Create() идёт обыкновенное присвоение указателям ссылок на функции. Смотрю объект ExtADCChanel[0].
|
|
|
|
|
Jul 9 2012, 07:36
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 17-01-12
Пользователь №: 69 604

|
Цитата(ViKo @ Jul 9 2012, 10:30)  Смотрите, что есть в startup. Код Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP Видите __main - вот там все и устанавливается. Вы сами добавили кода в SystemInit()? А чем не устроило сделать это в main? Вот мой startup: Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP По-моему не отличается ничем.
|
|
|
|
|
Jul 9 2012, 08:05
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 17-01-12
Пользователь №: 69 604

|
Цитата(ViKo @ Jul 9 2012, 10:50)  И это правильно. Еще раз прочитайте мой ответ.
Не "не похоже", а именно так! Не понял, а где именно выполняется инициализация переменных? Где вызов подпрограммы? В приведенном ассемблерном коде я его не вижу. Ну и что из того, что сначала выполняется SystemInit(), а потом main()? Или инициализация выполняется в начале работы main()?
|
|
|
|
|
Jul 9 2012, 08:20
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 17-01-12
Пользователь №: 69 604

|
Цитата(ViKo @ Jul 9 2012, 11:11)  где же main(), если __main()? А... Теперь понял. Спасибо, учту в программе.
|
|
|
|
|
Jul 11 2012, 04:58
|
Участник

Группа: Участник
Сообщений: 71
Регистрация: 17-01-12
Пользователь №: 69 604

|
Цитата(kan35 @ Jul 10 2012, 13:16)  в 20х числах июня, Томас Дреслер из ST совместно с дистрибьюторами проводил семинары (Москва, Питер, Ебург) на тему STM32F4... и как раз это все разжевал. Многие при этом возмущались - зачем типа нам это все знать. В том числе почему SystemInit вызывается до __main и что еще инициализируется в __main... С удовольствием съездил бы послушал. Но попасть на эти семинары в те города, которые Вы перечислили, из моего провинциального украинского городка и небольшой частной фирмы - это всё равно, что слетать на Луну. Так что пока единственное спасение - это вот такие конференции и бескорыстная помощь моих уважаемых коллег.
|
|
|
|
|
Jul 12 2012, 04:11
|
Знающий
   
Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594

|
Цитата(AHTOXA @ Jul 12 2012, 01:10)  А по-моему, всё гораздо проще. SystemInit - это от ST, а __main - от кейла. И ST банально не может вызвать SystemInit после __main, потому что оттуда нет возврата  Эти рассуждения не выдерживают никакой критики. Почему бы тогда по вашей логиге банально не вызывать SystemInit в сомом main()? Инициализация на 16МГц и на 168МГц - чувствуете разницу?
|
|
|
|
|
Jul 12 2012, 09:05
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(kan35 @ Jul 12 2012, 10:11)  Почему бы тогда по вашей логиге банально не вызывать SystemInit в сомом main()? Потому что main - это уже пользовательское приложение. А ST пыталась сделать шаблон. Как раз для того, чтобы пользователю в main ничего не надо было писать. Цитата(kan35 @ Jul 12 2012, 10:11)  Инициализация на 16МГц и на 168МГц - чувствуете разницу? А при использовании GCC, по вашей "логиге", проц стартует сразу на 168МГц?  Я понимаю, что вы послушали "спецов" из ST, и прониклись. Но голову-то включать иногда надо?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 12 2012, 19:42
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(kan35 @ Jul 12 2012, 17:45)  Вы сказали, что в GCC сначала происходит инициализация, а "SystemInit"после. Если это так, то это неправильно как раз. Производить инициализацию в 10 раз медленнее чем позволяет проц - не всегда позволительно. Суть в том, что в трёх вариантах из пяти сделано так. То есть, при наличии возможности выбрать, что делать сначала, инициализацию переменных или вызов SystemInit() (это gcc_ride7, TASKING и TrueSTUDIO) -- сначала идёт инициализация переменных. А в двух случаях, где этого выбора нет (keil и IAR) - сделали как смогли. И получилось, кстати, не по стандарту Си. (Но тут я не особо силён, и могу ошибаться.) Так что товарищ из ST, который вам это обосновывал - скорее всего "импровизировал"
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 13 2012, 11:50
|
Местный
  
Группа: Участник
Сообщений: 356
Регистрация: 9-06-07
Пользователь №: 28 315

|
Цитата А вы уверены что SystemInit делает то что вы написали? Да уверен. Я посмотрел исходник от ST из комплекта Keil (v4.23) для серии ST32F10X. Не особо вдаваясь в код, бегло просмотрел коментарии и сделал выводы. Насчет HSI поторопился немного. Сперва сбрасывается на внутренний генератор, затем выставляется системная частота в зависимости от дефайна. Цитата И получилось, кстати, не по стандарту Си. Поскольку стандарт описывает поведение программы, а не поведение железа, то предварительную (дефолтовую) ноастройку можно отнести как к подготовительным операциям (типа инициализации статических переменных), так и к исполнению пользовательского кода. Инженеры ST придерживаются первого варианта.
Сообщение отредактировал редактор - Jul 13 2012, 12:25
--------------------
Хорошую систему делают из стандартных блоков нестандартно мыслящие инженеры.
|
|
|
|
|
Jul 14 2012, 21:06
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(ViKo @ Jul 14 2012, 21:07)  Напомню, что переменные могут располагаться и во внешней памяти. А встроенный контроллер к ней перед этим нужно еще инициализировать. Иначе - никак. Поэтому объяснение инженера из ST мне представляется верным. Поддерживаю kan35. А в случае с gcc_ride7, TASKING и TrueSTUDIO объяснения инженера из ST надо просто инвертировать?  Если честно, то не ожидал, что моё очевидное наблюдение вызовет столько возражений. Ещё раз: да, могут быть случаи, когда надо сначала инициализировать тактирование и/или внешнюю память, а уже потом - статические переменные. Но, (и это - соль моего наблюдения) программисты из ST совершенно не думали ни о чём таком. Если бы думали, то сделали бы во всех вариантах одинаковый порядок.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 15 2012, 05:20
|
Знающий
   
Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594

|
АНТОХА, действительно, разница в шаблонах имеется, сейчас я специально тоже посмотрел. И обратил внимание, что в TASKING сделано как в IAR и KEIL, хотя можно было сделать как в GCC, но не было сделано! Из всех тобою перечисленных только GCC (TRUEStudio и gcc_ride7 - одно и то же, даже sturtup у них практически копии). Итого пропорция складывается 3:1 не в твою пользу и не в пользу бесплатного средства. И, конечно остается вопрос, почему ST в варианте GCC сделали иной порядок, возможно для GCC пишут не те же программеры, что для коммерческих сред. Правдоподобно?
|
|
|
|
|
Jul 16 2012, 09:55
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(ViKo @ Jul 16 2012, 13:59)  Все, что делается до main, принадлежит операционной системе. Язык Си совершенно ортогонален операционной системе. Вы наверное имели в виду что-то типа "принадлежит библиотеке времени исполнения языка си, aka CRT"? Тогда да. Но тут опять-таки возникает вопрос, допустимо ли писать эту библиотеку на си? Вернее, можно ли писать на си её функции, которые будут вызываться до инициализации статических переменных и bss? Мне кажется, что это не совсем корректно. Цитата(ViKo @ Jul 16 2012, 13:59)  Вообще, не вижу предмета для разговора, тем более, спора. Но вы же зачем-то разговариваете?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jul 16 2012, 10:50
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(AHTOXA @ Jul 16 2012, 12:55)  Язык Си совершенно ортогонален операционной системе. Вы наверное имели в виду что-то типа "принадлежит библиотеке времени исполнения языка си, aka CRT"? Тогда да. Но тут опять-таки возникает вопрос, допустимо ли писать эту библиотеку на си? Вернее, можно ли писать на си её функции, которые будут вызываться до инициализации статических переменных и bss? Мне кажется, что это не совсем корректно. Имел в виду что-то типа http://en.wikipedia.org/wiki/Run-time_systemНасчет допустимости - если представить, что SystemInit - это часть RTS, а main и остальное - свой отдельный проект, то и противоречий не наблюдается.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|