ARM Cortex M-3 инициализация GCC / newlib

Я только начал вникать в мир микроконтроллеров ARM Cortex-M и решил не использовать существующую плату разработки или простую в использовании IDE, а сразу заняться этими вещами, так что У меня есть STM32F103, припаянный к макетной плате, и теперь я пытаюсь заставить все работать с помощью встроенной в gcc-arm Toolchain от Launchpad. После тяжелого времени чтения руководств по сценариям компоновщика и тому подобному, я теперь написал свой собственный сценарий компоновщика и код запуска, который в основном ничего не делает, кроме копирования раздела .data из ПЗУ в ОЗУ, обнуления .bss, а затем вызова SystemInit () из стандартной периферийной библиотеки ST, чтобы выполнить базовую инициализацию uC и, наконец, вызвать main ().
Теперь, из нескольких найденных мной руководств по разработке Cortex M-3, я увидел, что они используют флаг -nostartfiles для компоновщика, но Теперь мне интересно: нужно ли мне в этом случае инициализировать newlib? Или мне лучше использовать стартовые файлы по умолчанию из GCC / newlib и drop -nostartfiles? Но в этом случае мне все равно придется выполнить некоторую инициализацию, например, скопировать .data в ОЗУ и настроить векторную таблицу, для которой требуется собственный скрипт компоновщика. Так где же мне это сделать?
И я даже не хочу думать о C ++!

Итак, каков рекомендуемый способ инициализации такого микроконтроллера на базе Cortex-M3 и его libc (не считая периферийных устройств)?

Заранее спасибо!


person Alemarius Nexus    schedule 10.11.2013    source источник
comment
github.com/dwelch67 У меня есть кое-что «голое железо», которое может вас заинтересовать. Это не такой высокий уровень, как материал newlib / libc, который вы пытаетесь сделать, это «голый металл». Может быть, вам это пригодится, а может, и нет. У меня может быть какой-то материал newlib в каталоге raspberry pi, также может помочь, а может и не помочь. Если у вас нет готового пакета, получение работы newlib + gcc может быть проблемой, если у вас есть готовый пакет, и это то, что вас интересует (с использованием newlib и других стандартных библиотек), просто используйте его, как задумано авторами.   -  person old_timer    schedule 11.11.2013
comment
В примере newlib0 из вашего репозитория вы определяете в основном функции syscall, необходимые для newlib. Если бы это все, что мне нужно было сделать, это не было бы такой большой проблемой. Но чего я не вижу в вашем коде, так это инициализации микроконтроллера, но это то, что меня интересует. Я использую двоичный дистрибутив gcc-arm-embedded, поэтому GCC и newlib уже созданы и ( якобы) связаны вместе. Моя проблема заключается в смешивании кода запуска newlib (crt0.o и т.п.) с моим собственным.   -  person Alemarius Nexus    schedule 11.11.2013
comment
это чистый металл. ты делаешь это сам. Если вы хотите использовать песочницу ST, используйте ее песочницу. Возьмите их код и используйте его по назначению или объедините функционально со своим собственным ...   -  person old_timer    schedule 11.11.2013
comment
Я инициализирую микроконтроллер по мере необходимости.   -  person old_timer    schedule 11.11.2013
comment
newlib - это библиотека C для замены glibc и т. д. Она предназначена для подключения функций файлового ввода-вывода к вашей встроенной операционной системе. За исключением тех случаев, когда библиотека взаимодействует с оборудованием, в нем нет никакого оборудования, особенно в newlib. Если вы хотите иметь дело с аппаратной инициализацией, ищите hardware init, а не newlib. Для newlib init это зависит от вас, когда вы реализуете бэкэнд syscalls / libcfunc для своей цели. при необходимости создайте init для вашего libcbackend.   -  person old_timer    schedule 11.11.2013
comment
Хорошо, посмотрев немного на источники GCC, я думаю, что моя проблема может быть больше проблемой GCC, чем проблемой newlib. Возможно, я мог бы написать свой собственный crt0.S или еще что-то для инициализации, но проблема, похоже, в других файлах crt * .o (crtbegin.o, crti.o и т. Д.). Похоже, они принадлежат libgcc и делают такие вещи, как вызов статических конструкторов и деструкторов. Полагаю, мне не нужно писать для них собственный код, не так ли? Итак, как они правильно связаны и как выполняется их код?   -  person Alemarius Nexus    schedule 11.11.2013
comment
Я использую -nostdlib -nostartfiles -ffreestanding, и мне не о чем беспокоиться. Все три из них могут испортить то, что вы пытаетесь сделать с другими библиотеками, поэтому вам может понадобиться только одна или две ...   -  person old_timer    schedule 12.11.2013


Ответы (1)


Насколько я знаю, вы не должны вызывать какую-либо функцию stdlib для простого приложения C. Но вам следует использовать приложение C ++, потому что для инициализации существуют статические инициализаторы, vtable для RTTI и т. Д. Сам newlib содержит такие функции из stdlib, как mem*, *printf и т. д., приспособленные для MCU с небольшим размером ROM, насколько мне известно.

Но часто активно инициализировать нечего. Если у std-функции есть глобальные данные, она, надеюсь, объявляет и сохраняет их в некоторых переменных, которые хранятся в разделе .data. Например. __errno является кандидатом на это. Но вы не можете быть уверены в том, что делает ваша newlib-реализация, потому что разработчики должны решать, как они проектируют внутренний рабочий процесс в своей библиотеке.

Взгляните на приведенный ниже фрагмент кода. Это процедура запуска (Reset-Handler), написанная на C. ST доставляет свой файл запуска в виде файла ассемблера (* .s), но вы также можете сделать это на C. NXP, с другой стороны, генерирует свои проекты с .c файл запуска.

Вызов функции под комментарием для C ++ может быть опущен, если ваше приложение является только приложением C. Символы для _data и _idata генерируются компоновщиком (определенным в скрипте компоновщика).

__set_PSP((uint32_t)&_vStackTop);               // set stack pointer
SCB->VTOR = (uint32_t)&VectorTable;             // set the pointer to the vector table

pDest = &_data;
pSrc = &_idata;

// fill .data section
for ( ; pDest < &_edata; )
{
    *pDest = *pSrc;
    ++pSrc;
    ++pDest;
}

// fill .bss section
for (pDest = &_bss; pDest < &_ebss; ++pDest)
{
    *pDest = 0;
}

//
// Call C++ library initialization, if your app is an C++ app
//
__libc_init_array();

main();                                                 // enter main

for(;;)                                                 // you shouldn't land here at anytime
{

}
person MisterMaster    schedule 20.03.2018