Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: __low_level_init (void)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
condor
Для чего стоит использовать функцию __low_level_init?
В EW430_CompilerReference.pdf я нашел такое:
Customizing system initialization
It is likely that you need to customize the code for system initialization. For example,
your application might need to initialize memory-mapped peripheral units, or omit the
default initialization of data segments performed by cstartup.
You can do this by providing a customized version of the routine __low_level_init,
which is called from cmain before the data segments are initialized. Avoid modifying
the cstartup file directly.


Судя из этого, всю периферию надо инициализировать в __low_level_init.
Объясните, плз, правильно ли я понял?
rezident
СИшный main это тоже функция, которая может иметь вход и выход, несмотря на то, что ее обычно зацикливают (делают бесконечный цикл). В секции __low_level_init вы можете разместить какой-то кусок программы, который будет выполняться ДО начала выполнения main. Например, процедуру, которая будет определять причину сброса и/или процедуру, которая будет выполнять функции начального загрузчика системы и/или процедуру проверки целостности (контрольной суммы) программы, хранящейся во Flash и/или процедуру, которая будет ремаппить вектора прерываний в ОЗУ и/или ... ну мало ли что вам захочется выполнить до начала выполнения main smile.gif
IgorKossak
Цитата(rezident @ Dec 2 2005, 00:16) *
...В секции __low_level_init вы можете разместить какой-то кусок программы, который будет выполняться ДО начала выполнения main. ...

И не только раньше main, но и до инициализаци всех глобальных переменных и исполнения конструкторов глобальных экземпляров классов (последнее при использовании C++).
Danilov
..мало ли что вам захочется выполнить до начала выполнения main.

И есть еще кое что, что вам вроде бы захочеться сделать в main, но в main вы просто не попадете!
Так как Watch dog по умолчанию включен и время его срабатывания запросто
может оказаться меньше времени инициализации (например если область переменных в RAM требующих инициализации достаточно большая). То он успешно сработает еще до входа в main!
поэтому ПРИДЕТЬСЯ (а не захочеться) его остановить именно в этой функции. Также если при програмном сбросе нужно сохранить значение некоторых переменных (показания часов например)
а не затирать их значением по умолчанию, то сделать это можно только в этой функции.
Danilov
Пример, когда вам вроде бы не хочеться использовать __low_level_init, но придется
http://electronix.ru/forum/index.php?showtopic=4298

Проблема оказалась именно в инициализации большого блока памяти.
Во время которой сработал watchdog.
rezident
Цитата(Danilov @ Aug 21 2006, 21:50) *
Пример, когда вам вроде бы не хочеться использовать __low_level_init, но придется
http://electronix.ru/forum/index.php?showtopic=4298

Проблема оказалась именно в инициализации большого блока памяти.
Во время которой сработал watchdog.

В той ветке не было подтверждения, что причиной подвисания был WDT. У вас у самого были реальные случаи срабатывания WDT при инициализации памяти? По моим грубым прикидкам получается, что инициализация даже 10кБайт занимает времени меньше (примерно на 20%) периода срабатывания WDT при его настройках и тактировании по умолчанию (то бишь после PUC или POR).
Kurt
Цитата(rezident @ Aug 21 2006, 22:05) *
В той ветке не было подтверждения, что причиной подвисания был WDT. У вас у самого были реальные случаи срабатывания WDT при инициализации памяти? По моим грубым прикидкам получается, что инициализация даже 10кБайт занимает времени меньше (примерно на 20%) периода срабатывания WDT при его настройках и тактировании по умолчанию (то бишь после PUC или POR).

Вот запустил в симуляторе программу для 1611. Поставил точку останову на main(). По бряку имеем 77842 cycles (при этом это не С++, т.е. без вызова конструкторов глобальных объектов). Таким образом, получается 77842 * 800kHz = ~97мс. Учитывая дефолтные ~32мс для watchdog, гарантированно имеем PUC, если не настроим/отключим тактирование/ватчдог в __low_level_init
rezident
Цитата(Kurt @ Aug 22 2006, 19:35) *
Цитата(rezident @ Aug 21 2006, 22:05) *

В той ветке не было подтверждения, что причиной подвисания был WDT. У вас у самого были реальные случаи срабатывания WDT при инициализации памяти? По моим грубым прикидкам получается, что инициализация даже 10кБайт занимает времени меньше (примерно на 20%) периода срабатывания WDT при его настройках и тактировании по умолчанию (то бишь после PUC или POR).

Вот запустил в симуляторе программу для 1611. Поставил точку останову на main(). По бряку имеем 77842 cycles (при этом это не С++, т.е. без вызова конструкторов глобальных объектов). Таким образом, получается 77842 * 800kHz = ~97мс. Учитывая дефолтные ~32мс для watchdog, гарантированно имеем PUC, если не настроим/отключим тактирование/ватчдог в __low_level_init

ОК. Спасибо. Буду иметь в виду.
Danilov
>>В той ветке не было подтверждения, что причиной подвисания был WDT. У вас у самого были реальные случаи срабатывания WDT при инициализации памяти?

На уроке:
- Гоги, докажи теорему.
- МАМОЙ КЛЯНУС!

Если бы не было, я бы об этой функции тоже ничего не знал, не нужна была бы она нам.
Самое неприятное тут что пока программа относительно небольшая, то все ОК, но в один прекрасный день когда ты ее полгода уже пишешь и все железо отлажено, а все порты давно
корректно проинциализированы это случаештся и ты сидишь и думаешь "А ГДЕ ГРАБЛИ ТО?"
ну добавил очередную глобальную или статическую переменную и БАЦ (вернее PUC) - висим, убрал и опять работает.

Где точная граница мы выяснять не стали, (тем более что зависит от версии библиотеки)
но у меня это МЕНЕЕ половины RAM на MSP430F169.

Да, еще инициализация массивов одним значением идет гораздо быстрее, чем
отдельных переменных, находящихся по разным адресам и разными значениями.
Так что, если ваш тест был с большими массивами, то его нельзя считать корректным,
и вообще врят ли имеет смысл искать эту границу.
and_pp
Что-то я так и не смог подлинковать lowinit.c к своему проекту. Вроде бы все сделал так, как написано в инструкциях - в отдельном файле и т.д. Компилит замечательно, а в итоговом проекте - нету.
В итоговом проекте идут инициализация стека, потом call #__data16_memzer и следом за ним call #main

Не мог бы кто-нибудь объяснить, как все же прикомпилировать __low_lewel_init к проекту. Компилятор V3.40A/W32 (3.40.1.1)
А то я с этим ватчдогом уже поимел проблем.
VAI
Сейчас в один из файлов проекта вставил
Код
/* --- __low_level_init() --------------------------------------------------------------------------------- **
*
* -------------------------------------------------------------------------------------------------------- */
int __low_level_init( void )
{
  /* Insert your low-level initializations here */
  WDTCTL = WDTPW + WDTHOLD;             // Stop WDT


  /*==================================*/
  /* Choose if segment initialization */
  /* should be done or not.  */
  /* Return: 0 to omit seg_init */
  /*        1 to run seg_init */
  /*==================================*/
  return ( 1 );
}

в мар файле появилась строка
Код
  Segment part 21. ROOT.
           ENTRY                   ADDRESS         REF BY
           =====                   =======         ======
           __low_level_init        506A            ?cstart_call_low_level_init (?cstart)
               stack 1 = 00000000 ( 00000002 )

и для main нашел, чтоб ее адрес знать
Код
CODE
  Relative segment, address: 1A10 - 1BA5 (0x196 bytes), align: 1
  Segment part 16.
           ENTRY                   ADDRESS         REF BY
           =====                   =======         ======
           main                    1A10            Segment part 12 (?cstart)
               calls direct
               stack 1 = 00000000 ( 0000000C )


в симуляторе вижу:
Код
001400   3140000A      mov.w   #0xA00,SP
001404   B0126A50      call    #0x506A                 [b]это вызов __low_level_init[/b]
001408   0C93          tst.w   R12
00140A   0F24          jeq     0x142A
00140C   3C400C02      mov.w   #0x20C,R12
001410   3E40B303      mov.w   #0x3B3,R14
001414   B0120A6B      call    #0x6B0A            
001418   3C400002      mov.w   #0x200,R12
00141C   3E40F894      mov.w   #0x94F8,R14
001420   30120C00      push.w  #0xC
001424   B0121C6B      call    #0x6B1C
001428   2153          incd.w  SP
00142A   B012101A      call    #0x1A10                 [b]это вызов main[/b]

Все появилось
ig_z
Цитата(and_pp @ Sep 4 2006, 11:49) *
Что-то я так и не смог подлинковать lowinit.c к своему проекту. Вроде бы все сделал так, как написано в инструкциях - в отдельном файле и т.д. Компилит замечательно, а в итоговом проекте - нету.
В итоговом проекте идут инициализация стека, потом call #__data16_memzer и следом за ним call #main

Не мог бы кто-нибудь объяснить, как все же прикомпилировать __low_lewel_init к проекту. Компилятор V3.40A/W32 (3.40.1.1)
А то я с этим ватчдогом уже поимел проблем.


Обратите внимание на проект. Если он сделан на с++, то нужно добавить екстерн с или его аналог в ввиде макроса.
and_pp
Цитата(ig_z @ Sep 4 2006, 15:10) *
Обратите внимание на проект. Если он сделан на с++, то нужно добавить екстерн с или его аналог в ввиде макроса.

А ведь действительно у меня проект был на С++

Добавил extern "C" { ... } - все заработало. Огромное спасибо!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.