в чем практический смысл записать 0 или любое другое значение в нулевой элемент массива g_pfnVectors, а после в коде присвоить регистру SP адрес стека?
В записи 0 смысла никакого, в коде SP присваивается адрес стека при выполнении кода из RAM, т.к. в этом случае флеш может быть чистым.
STM то тут причём? Архитектуру ядер разработала (или скупила, не знаю) ARM. А вообще, странное желание иметь в поекте код, который непонятно что там делает. А стартап никто не заставляет писать самому, в 99% случаев он уже есть либо в IDE, либо на сайте производителя чипа.
Сейчас плотненько сижу на Microblaze. Компилятор GCC, в стандартной библиотеке стартовый код есть и конфигурируется в среде разработки в зависимости от того какие модули процессора имплементированы. А хотелось бы как для ARM в исходниках. Чисто теоретически, можно самому написать, но времени желко.
Стартап от задачи и типа МК зависит, так что - не проканает общее сделать. Кстати, советую стартап на С (или С++ если у вас второе) написать, зачем с этим асмом сношаться?
Да Си мне нравится больше, чем ассемблер . Да в Эклипсе в блинк-проекте есть "startup.c", лежит в папке newlib, пишут что "Следующие файлы расширяют или заменяют некоторые функции библиотеки newlib". Сама newlib как я понимаю, присутствует как стандартная библиотека компилятора arm-none-eabi-gcc. Допустим startup.c создаёт некую стандартную структуру исполняемого файла, но непонятно, зачем в startup.c присутствуют функции инициализации hardware, неужели инициализировать устройства нельзя в коде программы, а также инициализация статических констукторов и деструкторов, зачем мне дестукторы если я пишу на Си?
Как я понял в sections.ld ENTRY(_start) - это запуск функции _start из startup.c. Почему линкер сразу не может указать вход как ENTRY(main) ? Также _exit в микроконтроллера не вызывается, так как МК постоянно работает в цикле, то зачем он вообще? Не ставят же return 0; в AVR main().
То есть startup только очищает память в стандартных секциях, копирует код программы из Flash в RAM и передаёт управление на main() ?
Наверное всё это попытка дать программисту больше контроля, но это пугает после AVR )
Посмотрите VisualGDB. Там под весь STM32 есть неплохие стартапы на С. Если назовёте камень, с которым работаете, могу собственного изготовления подкинуть прикольный.
но непонятно, зачем в startup.c присутствуют функции инициализации hardware, неужели инициализировать устройства нельзя в коде программы,
А теперь представьте, что у вас сегмегты данных, стек или куча находятся в области RAM, которая при включении питания выключена? Или код выполняется из QSPI, которую ещё надо инициализировать для этого.
а также инициализация статических констукторов и деструкторов, зачем мне дестукторы если я пишу на Си?
В том то и прелесть иметь стартап в исходном коде, что вы можете убрать то что вам не надо. Уверены, что нет конструкторов - del. Хотя, ходят слухи, что они и на православном С бывают
То есть startup только очищает память в стандартных секциях, копирует код программы в RAM и передаёт управление на main() и больше ничего?
Ну почему же. Для кортексов в стартапе определяется таблица векторов прерываний, адрес стека, вызов функции инициализации железа. А уже в зависимости от стандартной библиотеки может быть ручная инициализация сегментов данных (занулением и копированием), вызов конструкторов, как это сделано в GCC.
В IAR и Keil, например, инициализацию данных, вызов конструкторов и переход на main делает стандартная библиотека. Такой себе почти AVR-вариант, но таблица векторов прерываний в стартапе.
Тогда не получится запустить программу из ОЗУ использующую прерывания. Насколько помню VTOR нет в M0 (в них много чего нет), а в остальных должен быть.
VladislavS писал(а):
Возьмите готовый и не парьтесь.
Да я уже дал ссылку на бесплатную IDE где все настроено и необходимые файлы добавляются при создании проекта. Но ТС непонятно что ждет...
Адрес начала таблицы векторов прерываний находится в VTOR. Если регистра нет, то как сообщить МК где таблица прерываний? Или предлагаете в ОЗУ размещать только код, а таблицу держать вначале флеша?
Таблица векторов при включении находится и работает по адресу 0. Можете посмотреть содержимое VTOR при старте из флэш. Никаких 0х08000000 там, внезапно, не будет. При старте из флэш адреса 0х08000000 отражаются на 0. Именно поэтому прерывания работают из флэш. А теперь делаем финт ушами - ремапим SRAM 0х20000000 на 0 и получаем работающую из SRAM таблицу векторов. Без всяких VTOR. Без VTOR нельзя сдвинуть таблицу прерываний с нуля, но можно поставить в ноль другую память. Не думал, что это объяснять надо.
Не знаю на счет всех моделей STM32F0, но с теми что имел дело, имеют только один вывод BOOT и для того чтобы отзеркалить ОЗУ в начало адресного пространства, нужно изменить бит конфигурации который заместо BOOT1. То есть все чуть сложнее чем переставить перемычку и так или иначе нужно изменять данные во флеше.
ddr4, если не нравится - не пользуйся ARMянами. Пользуйся восьмибитками: STM8, 5051 и т.д., и т.п. Там по умолчанию ни стартап, ни линкер-скрипт не нужны, т.к. все "знает компилятор". Правда, там убогий sdcc вместо gcc… Да и производительность (+периферия) намного слабей, хотя цена не сильно-то отличается.
Пишите дальше на AVR. Не стоит сравнивать детский трехкалесный велосипед профессиональным мотоциклом! То что прокатывает на велосипеде, не факт что сработает на мотоцикле.
Я с радостью продолжал бы пользоваться AVR (ардуино) и меня там устраивает абсолютно всё, но не хватает RAM. Дип-чипы старших моделей Атмега644/1284 стоят в 3 раза дороже плат stm32. Приобрести платы на stm8 тоже нет возможности, а smd-чипы без разводки без надобности. Поэтому решил попробовать плату с stm32. То что цена Атмега644/1284 в 3 раза выше stm32, видимо свидетельствует о их популярности, которая продиктована в том числе и простотой программирования. Которая включает в себя и отсутствие необходимости наблюдать низкоуровневые коды компилятора (в случае makefile-проекта) . Я согласен что эти коды стандартны и ничем не мешают, однако наблюдать их приходится, а раз наблюдаешь, то появляется желание понять что это и как работает - а с этим проблема, которая вызывает отрицательные эмоции . Возможно в том числе, чтобы не видеть эти низкоуровневые скрипты люди используют Атмеги . Понятно что можно использовать всякие Арудины-IDE в том числе и для stm32, но мне хотелось бы как и раньше, иметь небольшой makefile-проект на Си. У меня прошивка Ардуины использует 2 кБ RAM на Атмега328, но приходится усложнять код, чтобы он влазил. И с целью упрощения кода и приобреталась stm32, однако быстрого упрощения не получилось. И когда наблюдаешь кучу стандартных обёрток (hal, cmsis, newlib) и startup.s + скрипты компоновщика, а hex - блинка весит 27кБ (больше чем hex большой прошивки на Ардуино) - это неприятно удивляет. Это ведь только начало, даже код не начал переводить, а уже столько (пусть и мнимых) проблем.
появляется желание понять что это и как работает - а с этим проблема, которая вызывает отрицательные эмоции
Тогда лучше в это дело не лезть, если от него лишь отрицательные эмоции! Если хочешь разобраться - разбирайся досконально, не хочешь — пользуйся абдуриной или всякими калокубами. Кстати, тебе, наверное, калокуб понравится: там вообще думать не нужно и тупо мышей щелкать...
Цитата:
hex - блинка весит 27кБ
Мегарукожопие. ЕМНИП, самый короткий блинк на STM32 — около 40 байт. Если добавить USB и минимальный функционал (период там изменять) - будет 4кБ. Чтобы родилось 27кБ, нужно сильно постараться.
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Посмотрите VisualGDB. Там под весь STM32 есть неплохие стартапы на С. Если назовёте камень, с которым работаете, могу собственного изготовления подкинуть прикольный.
Камень stm32f401. Я уже попривык к стартапу из Эклипса. В принципе понятно, если не считать описания секций в "sections.ld". Спасибо, да было бы интересно посмотреть на прикольные стартапы. Ниже тоже старт, но не понятно как он работает. Как мне кажется он ничего не инициализирует (RAM), применяется в примере блинк stm32f4.
startup_stm32f4.asm
Код:
global burn2_main global burn2_systick
dd 0x20000678 ;; Установить указатель стека dd 0x08000009 ; Вектор сброса, и прыжок на адрес 8 B burn2_main ; Ветка в main (это фактически в векторе прерываний ??) align 4 dd 0x0 ; undefined 0xc dd 0x0 ; undefined 0x10 dd 0x0 ; undefined 0x14 dd 0x0 ; undefined 0x18 dd 0x0 ; undefined 0x1c dd 0x0 ; undefined 0x20 dd 0x0 ; undefined 0x24 dd 0x0 ; undefined 0x28 dd 0x0 ; undefined 0x2c dd 0x0 ; undefined 0x30 dd 0x0 ; undefined 0x34 dd 0x0 ; undefined 0x38 dd 0x08000041 ; undefined 0x3c --> systick, метод на данный момент, чтобы перейти к следующему адресу B burn2_systick ; неопределённая 0x40 инструкция прыжка к systick обработчику align 4
Для кортексов в стартапе определяется таблица векторов прерываний, адрес стека, вызов функции инициализации железа.
Про векторы прерываний в стартапе сказано только следующее: Чем это может быть полезно сказать сложно.
Код:
/* Определение секций */
SECTIONS { /* * Для устройств Cortex-M начало кода запуска хранится в * разделе .isr_vector, который идет во FLASH. */ .isr_vector : ALIGN(4) { FILL(0xFF)
Про векторы прерываний очень хорошо сказано в Programming Manual на серию Кортексов. Для M3, стоящем в F401 - это будет документ PM0214, стр.40. Табличка с определенной структурой, в которую помещаются значения адресов, по которым располагается тот или иной исполняемый код, вызываемый при наступлении события прерыавния/исключения. Вторая строчка таблички от начала называется reset Vector и она хранит адрес, по которому расположена первая инструкция исполняемого кода, вызываемая сразу после события сброса МК и которая будет выполнена первой инструкцией. Помещаться эта инструкция может в любом месте из диапазона разрешенных адресов для исполнения инструкций. Скрипи загрузчика .ld размещает секции в бинарном файле по определенным адресам. Табличка векторов тоже может быть помещена не в самом начале флеша, а где-нить в другом месте, о чем нужно дополнительно сообщить микроконтроллеру в коде программы, изменив VTOR (там, где он есть). Именно скрипт .ld будет ответственнен за то, что куда кладется на этапе компиляции В зависимости от конкретной IDE и кмопилятора, состав и синтаксис файлов запуска может отличаться.
Про векторы прерываний в стартапе сказано только следующее:
Код:
/* Определение секций */
SECTIONS { /* * Для устройств Cortex-M начало кода запуска хранится в * разделе .isr_vector, который идет во FLASH. */ .isr_vector : ALIGN(4) { FILL(0xFF)
KEEP(*(.cfmconfig)) /* слова конфигурации Freescale */
/* * Этот раздел создан для удобства, чтобы хранить * код запуска в начале области флэш-памяти, надеясь, что * это повысит читабельность листинга. */
*(.after_vectors .after_vectors.*) /* Стартап код и ISR */
} >FLASH
Вы путаете конфигурационный файл (скрипт) линкера и стартап. Первое это правила размещения кода и данных в памяти. Приведённый вами фрагмент рассказывает линкеру куда разместить таблицу. Стартап же это код и данные (та же таблица векторов), которые компилируются компилятором.
Сейчас этот форум просматривают: shalfey и гости: 19
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения