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

 
 
> Инициализация периферии до входа в main() - возможно ли?, RealView compiler
sonycman
сообщение Jan 8 2009, 17:39
Сообщение #1


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Run-time библиотека Си++ вызывает конструкторы глобальных объектов ещё до начала выполнения функции main().
Хотелось бы, чтобы в этот момент необходимая периферия контроллера уже была проинициализирована, дабы код конструкторов не был ничем ограничен.
Но как это сделать в RealView? Никаких __low_level_init() я в руководстве компилятора не увидел... unsure.gif

ЗЫ: приятно обновился интерфейс форума a14.gif
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 21)
zltigo
сообщение Jan 8 2009, 17:47
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(sonycman @ Jan 8 2009, 20:39) *
Но как это сделать в RealView? Никаких __low_level_init() я в руководстве компилятора не увидел... unsure.gif

Вставьте вызов иеициализирующей функции в startup после инициализации стека. Все.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jan 8 2009, 18:33
Сообщение #3


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(zltigo @ Jan 8 2009, 21:47) *
Вставьте вызов иеициализирующей функции в startup после инициализации стека. Все.

Ага, спасибо.
Я уже подумал про асмовый стартап. Можно, наверное, поставить BL прямо перед вызовом __main. Даже стёк инитить не надо - он грузится автоматически с нулевого адреса таблицы векторов.

А есть ли какие-то ограничения у такого способа? В смысле не лишкануть бы чего в подпрограмме пре-инициализации rolleyes.gif
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Jan 8 2009, 18:35
Сообщение #4


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

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



На сайте atmel'a лежат свежие версии soft'a для sam процессоров (http://www.atmel.com/dyn/general/tech_doc.asp?doc_id=11318&family_id=605). Там, например, есть проект basic-emac-uip-telnetd-project-at91sam9263-ek-keil, а в нем файл - board_cstartup_keil.s. Из него вызывается функция LowLevelInit() как раз до вызова main().
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jan 8 2009, 19:04
Сообщение #5


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(sergeeff @ Jan 8 2009, 22:35) *
На сайте atmel'a лежат свежие версии soft'a для sam процессоров (http://www.atmel.com/dyn/general/tech_doc.asp?doc_id=11318&family_id=605). Там, например, есть проект basic-emac-uip-telnetd-project-at91sam9263-ek-keil, а в нем файл - board_cstartup_keil.s. Из него вызывается функция LowLevelInit() как раз до вызова main().

А можно привести здесь эти строки? А то качать 40 метров слишком накладно...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 8 2009, 19:14
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(sonycman @ Jan 8 2009, 21:33) *
Даже стёк инитить не надо - он грузится автоматически с нулевого адреса таблицы векторов.

Типа Cortex-M3 smile.gif?
Цитата
А есть ли какие-то ограничения у такого способа?

Ничего необычного нет.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 8 2009, 19:35
Сообщение #7


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



А чем не устраивает main рассматривать как ту самую функцию настройки периферии, из нее уже запускать что-то еще.

Цитата
А можно привести здесь эти строки? А то качать 40 метров слишком накладно...

Вам оно не пригодится. Между SAM'ом и Cortex'ом пропасть как раз в стартапе.

Цитата
Можно, наверное, поставить BL прямо перед вызовом __main. Даже стёк инитить не надо - он грузится автоматически с нулевого адреса таблицы векторов.

Конечно, можно. ;>

Для кортекса:
Код
Reset_Handler
        IMPORT  LowLevelInit
        IMPORT  __main
        BL      LowLevelInit
        LDR     R0, =__main
        BX      R0


Сам же LowLevelInit объявите как void LowLevelInit(void) в любом .c файле.
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jan 8 2009, 20:15
Сообщение #8


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(zltigo @ Jan 8 2009, 23:14) *
Типа Cortex-M3 smile.gif?

Ага disco.gif

Цитата(defunct @ Jan 8 2009, 23:35) *
А чем не устраивает main рассматривать как ту самую функцию настройки периферии, из нее уже запускать что-то еще.

Немного не устраивает то, что приходится вводить в классы доп. функцию для инициализации, так как часть работы не может быть выполнена в конструкторе, когда периферия не сконфигурирована... sad.gif
Мелочь, в принципе...
Цитата
Для кортекса:
Код
Reset_Handler
        IMPORT  LowLevelInit
        IMPORT  __main
        BL      LowLevelInit
        LDR     R0, =__main
        BX      R0


Сам же LowLevelInit объявите как void LowLevelInit(void) в любом .c файле.

Спасибо, так и поступлю.
Ещё вот интересно, для чего при переходе на __main юзать R0? А если просто B __main?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 8 2009, 20:29
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(sonycman @ Jan 8 2009, 23:15) *
А если просто B __main?

Если уверены, что сможете дотянуться до main 256*2 байтовым смещением, то можете.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 8 2009, 20:30
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(defunct @ Jan 8 2009, 22:35) *
А чем не устраивает main рассматривать как ту самую функцию настройки периферии, из нее уже запускать что-то еще.

До main хотя бы память должна ожить. Кроме того, тоскливо получается копировать/инициализировать эту память на медленных клоках, например.

Цитата(sonycman @ Jan 8 2009, 23:15) *
Ещё вот интересно, для чего при переходе на __main юзать R0? А если просто B __main?

А если __main далеко?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 8 2009, 21:23
Сообщение #11


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(defunct @ Jan 8 2009, 22:35) *
А чем не устраивает main рассматривать как ту самую функцию настройки периферии, из нее уже запускать что-то еще.

Лично я делаю так:

Вначале надо прописать ввод-вывод. Сколько гемора бывает из-за "неспешной" инициализации порта(ов),


потом - стек, типа low_level_init(), потом - секции, ремап и main()
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 8 2009, 23:24
Сообщение #12


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(aaarrr @ Jan 8 2009, 22:30) *
До main хотя бы память должна ожить. Кроме того, тоскливо получается копировать/инициализировать эту память на медленных клоках, например.

Согласен, актуально для МК с кешем, внешним RAM, либо толстым Init RW сегментом.

В контексте кортекса, внешней шины часто вообще нет (оживлять нечего), а внутреннего RAM'a - с гулькин нос, поэтому и PLL настраивать до main'a ради инициализации пары KB переменных смысла особого нет.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 8 2009, 23:34
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(defunct @ Jan 9 2009, 02:24) *
Согласен, актуально для процессоров с MMU и кешем и внешним SDRAM'ом.

Ну, еще для атмеловских SAM'ов, которые с 32kHz запускаются, тоже весьма актуально.

Цитата(defunct @ Jan 9 2009, 02:24) *
внутреннего RAM'a - с гулькин нос, поэтому и PLL настраивать до main'a ради инициализации пары KB переменных смысла особого нет.

Если это пара десятков килобайт и пара десятков килогерц, то совсем даже не мало получается.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 8 2009, 23:35
Сообщение #14


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(aaarrr @ Jan 9 2009, 01:32) *
Ну, еще для атмеловских SAM'ов, которые с 32kHz запускаются, тоже весьма актуально.

Угу, что правда, то правда.
Цитата
Если это пара десятков килобайт и пара десятков килогерц, то совсем даже не мало получается.

Везде свой подход. Мне что-то подсказывает (соседние ветки), что проц, который использует автор топика стартует на нормальной частоте (явно больше 32kHz) smile.gif
Иначе бы и не заикался на счет инициализации в main smile.gif
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jan 8 2009, 23:59
Сообщение #15


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(defunct @ Jan 9 2009, 03:35) *
Везде свой подход. Мне что-то подсказывает, что проц, который использует автор топика стартует на нормальной частоте (явно больше 32kHz) smile.gif
Иначе бы и не заикался на счет инициализации в main smile.gif

Да у меня STM32. Стартует на внутреннем RC 8 МГц - вполне хватает, чтобы не слишком торопиться с PLL.
До этого был LM3S601, который я угробил, переназначив вывод житага на GPIO... есть ещё оказывается камни, которые убиваются софтовой ошибкой 01.gif
Кстати, какая разница между внутренними RC генераторами этих контроллеров - с одной стороны 8 МГц +- 1%, с которого чип запускается после ресета.
С другой - 15 МГц +- 50%, запуск с которого невозможен, только после софтового переключения... на кой нужен такой генератор? laughing.gif
Видать, нет у Luminary индивидуальной калибровки... экономят-с...
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Jan 9 2009, 05:32
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Не полагайся на порядок вызовов конструкторов, инициализаторов периферии и тд - легко словить грабли в дальнейшем.

У меня все сервисы имеют три стадии инициализации:

1) Собственно сами конструкторы классов. В них я предполагаю, что класс автономен, соответственно и не обращаюсь к другим классам и ресурсам. Здесь же инициализируется периферия (естественно, два класса не могут юзать одну и ту же периферию)

2) Стадия Init - здесь уже налаживаются связи между классами (к этому моменту все необходимые объекты уже созданы)

3) Стадия Run - запускается таски, разрешаются прерывания от периферии и тд - в общем, нормальная работа приложения

объекты глобальные, соответственно создаются до main. А в main я уже вызываю init и run.

Суть в чем - не полагайся, что кто-то что-то сделал заранее smile.gif
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jan 9 2009, 11:27
Сообщение #17


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(Dima_G @ Jan 9 2009, 09:32) *
Не полагайся на порядок вызовов конструкторов, инициализаторов периферии и тд - легко словить грабли в дальнейшем.

У меня все сервисы имеют три стадии инициализации:

1) Собственно сами конструкторы классов. В них я предполагаю, что класс автономен, соответственно и не обращаюсь к другим классам и ресурсам. Здесь же инициализируется периферия (естественно, два класса не могут юзать одну и ту же периферию)

2) Стадия Init - здесь уже налаживаются связи между классами (к этому моменту все необходимые объекты уже созданы)

3) Стадия Run - запускается таски, разрешаются прерывания от периферии и тд - в общем, нормальная работа приложения

объекты глобальные, соответственно создаются до main. А в main я уже вызываю init и run.

Суть в чем - не полагайся, что кто-то что-то сделал заранее smile.gif

Понятно, спасибо!
Хотя не всегда объект может иметь свою собственную периферию - в случае её совместного использования невозможно ввести полную инициализацию внутрь одного класса.
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Jan 10 2009, 17:30
Сообщение #18


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(sonycman @ Jan 9 2009, 14:27) *
Понятно, спасибо!
Хотя не всегда объект может иметь свою собственную периферию - в случае её совместного использования невозможно ввести полную инициализацию внутрь одного класса.

Это уже следующий шаг smile.gif. Тут уже соблюдаю правило - на каждую периферию - свой объект (можно назвать драйвером).
Те работа всех объектов с УАРТом идет не напрямую, а через объект - драйвер УАРТ.
Или работа с езернетом - получен кадр - сервис-драйвер езернета отправляет его всем желающим (фактически в моем Enviromnet это выглядит как broadcast пакет. Чем-то идеология на CANbus похожа smile.gif )

Сам понимаешь, при таком подходе легче обходятся грабли с синхронизацией доступа к ресурсу..
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jan 10 2009, 20:51
Сообщение #19


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(Dima_G @ Jan 10 2009, 21:30) *
Сам понимаешь, при таком подходе легче обходятся грабли с синхронизацией доступа к ресурсу..

Да, синхронизация - дело хитрое.
Вот, к примеру думал тут недавно над одной задачкой...

В общем, есть два канала SPI. И три объекта, "висящие" на них.
Первый - цветной ЖКИ, скорость 12 Мбит, огромные объёмы данных, способен занять канал на длительное время. Самый низкий приоритет.
Второй - диск на флешке. Скорость высокая, но пакеты небольшие - сектора по несколько сот/тысяч байт. Средний приоритет.
И третий - к примеру - декодер МП3 (или ЦАП) или другой девайс с относительно маленьким каналом, но требующий быстрой реакции на запрос.

Как их уместить на одном/двух каналах SPI, чтобы не умереть от геморроя с разделением ресурсов?
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 11 2009, 03:12
Сообщение #20


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(sonycman @ Jan 10 2009, 22:51) *
Как их уместить на одном/двух каналах SPI, чтобы не умереть от геморроя с разделением ресурсов?

Два варианта:

A) ЖКИ транзакцию прервать никак нельзя:
SPI1 - ЦАП и FS. (в худшем случае ЦАПу придется дождаться завершения передачи текущего сектора FS, но скорость FS выская поэтому ждать не долго).
SPI2 - ЖКИ.
Приоритет ЦАПа сделать более высоким чем приоритет FS.

Б) ЖКИ транзакцию прервать без потерь можно.
SPI1 - FS
SPI2 - ЦАП и ЖКИ
обмен с ЖКИ моментально прерывается процессом обслуживающим ЦАП, и возобновляется после.



FS и ЖКИ я бы старался не цеплять на один интерфейс, во-первых чтобы скорость SPI не переключать (SPI флеш может и на 25Mhz и выше свистеть), ну и чтобы снизить нагрузку на интерфейс, т.к. потоки данных (по суммарному объему) сравнимые.
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Jan 11 2009, 03:26
Сообщение #21


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(sonycman @ Jan 11 2009, 00:51) *
Да, синхронизация - дело хитрое.
Вот, к примеру думал тут недавно над одной задачкой...

В общем, есть два канала SPI. И три объекта, "висящие" на них.
Первый - цветной ЖКИ, скорость 12 Мбит, огромные объёмы данных, способен занять канал на длительное время. Самый низкий приоритет.
Второй - диск на флешке. Скорость высокая, но пакеты небольшие - сектора по несколько сот/тысяч байт. Средний приоритет.
И третий - к примеру - декодер МП3 (или ЦАП) или другой девайс с относительно маленьким каналом, но требующий быстрой реакции на запрос.

Как их уместить на одном/двух каналах SPI, чтобы не умереть от геморроя с разделением ресурсов?


Я бы сделал так: два объекта драйвера - ClSPI_Driver<SPI0> и ClSPI_Driver<SPI1>. Следующий шаг - выяснить, необходима ли атомарность передачи больших объемов к ЖКИ (те можно ли бить данные на мелкие пакеты). Если можно передавать только здоровыми кусками (соответственно, остальные девайсы на SPI будут курить бабмбук в это время, что недопустимо), то под ЖКИ придется выделять отдельный канал SPI. А остальные девайсы повесил бы на второй SPI.

Разделение приоритетов передачи данных на одном порту:
Создаешь в драйвере очереди запросов с различными приоритетами. И драйвер, закончив очередную транзакцию начинает проверять очереди и высылать данные в порядке порядке приоритетов. Те пока не высланы данные для декодера (real-time приоритет), не трогать данные для флешки - low-prioritet для этого канала.


Те в общем, механизм был бы такой - ЖКИ единолично работает со своим SPI + канал DMA (драйвер<1>). На втором канале драйвер<2> выгребает данные из low-priority очереди (для флешки). А отдельный таск (или обработчик таймера) периодически подкидывает драйверу<2> блоки данных для декодера, который он отправляет за время не худшее, чем максимальный_объем_пакета_для_флешки / скорость_SPI + время реакции драйвера.

В общем, как-то так smile.gif
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jan 11 2009, 10:52
Сообщение #22


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(defunct @ Jan 11 2009, 07:12) *
FS и ЖКИ я бы старался не цеплять на один интерфейс, во-первых чтобы скорость SPI не переключать (SPI флеш может и на 25Mhz и выше свистеть), ну и чтобы снизить нагрузку на интерфейс, т.к. потоки данных (по суммарному объему) сравнимые.

Цитата(Dima_G @ Jan 11 2009, 07:26) *
В общем, как-то так smile.gif

Спасибо большое! Буду руководствоваться вашими советами, когда, наконец, руки до этого проекта дойдут.
Вы мне очень помогли cheers.gif
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 03:32
Рейтинг@Mail.ru


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