Пользователь
0,0
рейтинг
11 января 2014 в 18:36

Разработка → Программируем Raspberry Pi на голом железе из песочницы tutorial

C++*
До сих пор Raspberry Pi остается одним из самых популярных технологических гаджетов.На эту плату Вы можете установить практически любую операционную систему. Но сегодня мы поговорим о том, как писать программы для этой платы без операционной системе, пользуясь лишь аппаратными средствами.

В чем подвох?


На первый взгляд задача кажется тривиальной: скачиваем keil, создаем проект… Но все не так просто. Все среды программирования(keil, IAR, Atolic) поддерживают максимум ARM9.У нас же ARM11. Это связано с негласным правилом, что на голом железе пишут до ARM9, а после на Линуксе. Но все-таки есть одна лазейка: arm-none-eabi-gcc поддерживает любой ARM.
Вторая проблема заключается в том, что под данный процессор(BCM2835) нет никаких конфигурационных файлов, header'ов и т.д. Здесь нам на помощь придет загрузчик Raspberry Pi. И ничего, что он пропритетарный. Он выполняет две функции: инициализирует процессор и его периферию, а также передает управление ядру kernel.img. Мы просто замаскируем свою программу под ядро и загрузчик её запустит.

Что нам понадобится?


1) Сама Raspberry Pi, карта памяти к ней и питание.
2) Даташит на процессор
3) Компьютер с установленным Linux (но может быть можно и на Винде. Не знаю, не пробовал).
4) Кросскомпилятор, установленный на компьютере из пункта 3. Я использую arm-none-eabi-gcc
5) Содержимое этой папочки.

Приготовления.


Нам нужно отформатировать карту памяти в FAT16 и закинуть на нее содержимое этой папки. Это загрузчик плюс ядро. Затем удаляем оттуда файлы kernel.img и kernel_emergency.img. Это ядро Linux, а оно нам не нужно.

Первая программа.


Теперь мы можем приступить к написанию первой программы. Создаем файл main.c и пишем следующий код
int main (void)
{
while(1)
{
}
}
void exit (void)
{
while(1)
{
}
}

Как видите, эта программа ничего не делает. Функция exit зачем-то нужна компилятору.
Теперь соберем её.
arm-none-eabi-gcc -O2 -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -nostartfiles main.c -o kernel.elf
arm-none-eabi-objcopy kernel.elf -O binary kernel.img

Полученный файл kernel.img кидаем на карту памяти. Готово!

GPIO


Вряд ли Вас устроит программа, которая не будет делать абсолютно ничего. Сейчас попробуем зажечь лампочку.
Для начала объявим адрес, по которому лежит GPIO( это можно прочитать в даташите).
#define GPIO_BASE 0x20200000UL

И объявим переменную, которая определяют, что порт настроен на выход (GPIO_GPFSEL1) и переменную, подающую низкий уровень(то есть лампочка горит) на порт (GPIO_GPCLR0).
#define GPIO_GPFSEL1 1
#define GPIO_GPCLR0 10

Ну и наконец модифицируем главную функцию для зажигания лампочки:
volatile unsigned int* gpio;
int main(void)
{
      gpio = (unsigned int*)GPIO_BASE;
    gpio[GPIO_GPFSEL1] |= (1 << 16);   
   gpio[GPIO_GPCLR0] = (1 << 16);
   while(1)
    {

    }
}


Собираем, прошиваем и радуемся.

В следующей части попробуем поиграться с таймерами и прерываниями.
@grikukan
карма
8,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (62)

  • +3
    Вот прямо следит за мной хабр, который раз уже убеждаюсь :)
    Как раз на НГ подарил себе RaspberryPi, поганял немного и задумался: нужен ли мне для поделок линукс, може как и без него можно. Вот и ответ. Пишите еще, пожалуйста, буду изучать с удовольствием Ваши статьи.
    • 0
      Аналогично, посмотрел на линукс там, и задумался…
      Начал было смотреть вот в эту сторону — www.stevebate.net/chibios-rpi/GettingStarted.html — но пока руки не дошли.
      • +1
        Я вот как раз собирался их библиотеку в следующих выпусках юзать.
        Если же говорить об ОСРВ то, ИМХО, лучше FreeRTOS.
    • 0
      Хотелось бы написать еще, но пока времени мало. Но как только — так сразу.
  • 0
    А откуда взялось это правило, что после ARM9 — только линукс? И на чем компилируют линукс, если без него никак?
    • +1
      Видимо я не совсем правильно выразился. Конечно, stand-alone приложения есть и на cortex-a55, но, это довольно редко делают, и из-за этого по данному вопросу мало документации.
    • 0
      Думаю, что логика такая: раз частота хорошая и ресурсов много, то зачем мучиться и писать на низком уровне? Это не столько правило, сколько «народ не заморачивается».
      • +2
        Ну да, сначала «не на хлеб же ее, эту {частоту, память, место} намазывать», а потом интерфейсы тормозят, как и 20 лет назад.
  • +1
    Мне кажется, с Linux можно многое на такой железке сделать. Железо всё подхвачено, используй-не хочу. Но как эксперимент здорово.
    Отформатируйте код с помощью <source>, пожалуйста. Выглядит плоско.
    • 0
      Спасибо, отформатировал
  • +2
    Все среды программирования(keil, IAR, Atolic) поддерживают максимум ARM9.

    Для этих целей существует ARM DS-5 Development Studio.
    • 0
      Ладно, ладно, убедили.
      Просто для меня (и не только меня), привыкшему к Кейлу, переход может быть довольно сложным.
      • 0
        IAR поддерживает все ARM ядра:
        www.iar.com/Products/IAR-Embedded-Workbench/ARM/

        ПС часть с отладкой осталась нераскрытой.
        • 0
          Отладка по JTAG/SWD из списка «Hardware debugging support».
          • 0
            Я не спрашивал про IAR :)

            Я говорю, что статья похоже на сферического коня:
            да, лампочку мы зажгли, но только дальше уйти с помощь скомпилировал->залил->проверил не получится, да можно использовать printf и мигание диодами, но для сложной периферии, типа кодеров/декодеров видео, Ethernet, USB этого как то мало.

            Я думаю можно было раскрыть хотя бы одну связку типа GDB + j-link.

            Да и компилировать, доставать из платы карту, вставлять ее в комп, переписывать файл на карту, вынимать из компа, вставлять в плату — долго, не правда ли?

            Можно было бы рассказать про NFS например.
  • 0
    Огромное спасибо за статью. Вы не поверите, но я ее ждал давно. :)
    Дело в том, что совершенно случайно и совершенно бесплатно мне попал в руки сей девайс. А ни в АРМах, ни в embedded технологиях я особо не знаток; и вообще, что сделать можно с этим «компьютером» — хз. Но и железо даром пылится на полочке. Благодаря Вашей статье — у меня есть отправная точка.
    • 0
      Это копия friendly arm mini 6410?
      • 0
        Впервые услышал о Friendly Arm. Судя по всему, made-in-china-копия, при чем идентичная.
  • 0
    Скажите, а возможно ли написать библиотеку, используя которую можно было бы писать приложения без операционки? Т.е. сделал игру на такой библиотеке, прошил карту, вставил ее в RPi — грузится игра, вставил другую — другая. Как в ретроконсолях.
    • 0
      Можно, но довольно сложно
      • 0
        А не подскажете как было бы удобнее реализовать подобное: вставляем карту с игрой — она тут же начинает грузиться, вытащили — она закрылась. Есть также мысль использовать дополнительный USB-кардридер для карт с играми, а в основной — флешку с линуксом (но вот какую сборку? Raspbian? Как детектировать вставку и вынимание флешки?)
        • +1
          Зачем вам эти картриджи? Есть куча проектов по созданию эмулятора приставок на Raspberry Pi, в систему грузятся ROM и все дела.
          Вот пример: imgur.com/a/mZRWa
          Вот ещё, здесь можно догружать игры через USB: www.igorkromin.net/index.php/2013/01/08/raspberry-pi-in-a-nes-case-part-1-wiring-up-the-front-panel-and-external-connectors/
          • 0
            Just for fun. Очень хочу создать свою игровую консоль (не эмулятор), а по профессии программист. RPi выглядит для этого подходящим решением.
            • НЛО прилетело и опубликовало эту надпись здесь
              • +5
                Что вам не понятно во фразе «Just for fun»?
                • НЛО прилетело и опубликовало эту надпись здесь
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Дело в том, что мне досталось только «железо» и пара даташитов. Не осилил, в общем, с наскоку. Автор сейчас предположил, что девайс может быть копией Friendly Arm. Сейчас погуглил и, судя по всему, так оно и есть. Правда, к FA есть мануалы по установке ОС и прочие интересные штуки.
      • НЛО прилетело и опубликовало эту надпись здесь
  • +2
  • 0
    Извините за нубский вопрос но
    #define GPIO_BASE 0x20200000UL
    Смотрю даташит но не вижу этого адреса а сам GPIO начинается с 0x 7E20 0000 (страница 90 даташита)
    Можете сказать куда именно смотреть?
    • НЛО прилетело и опубликовало эту надпись здесь
  • НЛО прилетело и опубликовало эту надпись здесь
    • +2
      Мда, не зря я автору минус сразу влепил. В оригинале и код человечески выглядит, и про exit объяснено, и расписано всё более подробно. В частности и конечная цель поставлена, и туториалы на ассемблере указаны, которые Brian транслировал на Си.
      • 0
        Появился новый пост автора: habrahabr.ru/post/208780/. Тенденция не печальная. Не торт местами…
  • +2
    Примеры (bare metal) для rasberry pi — github.com/dwelch67/raspberrypi
  • +1
    А можно объяснить зачем это вообще нужно? Вроде как операционные системы как раз придумали, чтобы не писать на голом железе. Все эти #define PIN42 0xDEADBEEF вгоняют в полную печаль…
    • 0
      быстродействие, сэр
      • +1
        Ну например для чего? То есть какая должна быть задача, которая по вычислительной мощи требовала бы процессор уровня rPi и при это её были бы критичны задержки уровня ядра Linux?
        • +1
          Управление двигателями? Да в общем-то многие задачи управления для быстротекущих процессов. Те же роботизированные машинки — управляющий сигнал должен быть сгенерирован гарантированно за определённое, достаточно малое, время. Хотя даже тут на голом железе не пишут, применяют всякие RTOS.
          • 0
            Вам для управления двигателем нужны процессор в 700MHz и 512MB оперативной памяти? Вашим роботом надо же как-то управлять. Ethernet стек сами будете реализовывать?
            • 0
              Ethernet стек сами будете реализовывать?
              Что есть Ethernet-стек? Ethernet MAC+PHY там в виде LAN9512, который по совместительству usb-hub. Вот реализация USB-стека — куда более страшное дело, чем настройка MAC+PHY.

              А TCP/IP стек — дело не страшное: lwIP, например.
              • 0
                Но зачем это всё, если оно уже сто раз написано, отлажено и может быть использовано в готовом виде? Это ж не микроконтроллер!
                • 0
                  Я и не говорю, что это нужно на BCM2835. Это было замечание к вашему «Ethernet-стек».

                  Даже на простейших восьмибитных контроллерах можно написать элементарный драйвер для ethernet (я, например, использовал внешний MAC+PHY ENC28J60 совместно с AVR) и прикрутить минималистичный TCP/IP или UDP/IP стек. Это не говоря уже про какой-нибудь STM32 (F105/F107, F207/F217, F407/F417, F427/F437, F429/F439), где есть Ethernet MAC из коробки, с готовыми к употреблению DMA-каналами для сети. Так что ethernet+tcp/ip — это не rocket science, даже если самому реализовывать весь стек. Читаешь RFC и пишешь =)
                  • 0
                    Ну всё вообще не Rocket Science, зачем только. На микроконтроллер вы OS общего назначения не поставите, поэтому приходится всё ручками. Именно приходится, ничего хорошего в этом нет. Для того чтобы программировать на Bare metal нужна какая-то очень веская причина. В век интернета причина «не можем найти программиста» выглядит как-то не особо.
                    • +1
                      На микроконтроллер вы OS общего назначения не поставите, поэтому приходится всё ручками. Именно приходится, ничего хорошего в этом нет.
                      Зачем так категорично? Если вам не нужна вытесняющая многозадачность, разграничение ресурсов и высокоуровневые абстракции — то ОС не нужна. Те же драйвера без уровней абстракции ядра ОС часто пишутся проще и требуют меньше держать в голове (в силу дырявых абстракций, как минимум). Так что не приходится, а выбираем инструмент в соответствии с задачами.

                      На том же ARM7 (не говоря уже про ARM9, ARM11 и ARM Cortex-A) вполне можно запускать Linux. Вопрос в том, надо ли это: требуется установка внешней RAM и ROM, что повышает требования к железу на порядки (в частности, уже невозможно уместиться на двухслойной плате, требуется куда более тщательное проектирование железа, т. к. используются высокочастотные параллельные интерфейсы и т. п.). Зачем всё это для программы, которая умещается в десяток-другой килобайт?
                      • +1
                        Вы имели ввиду uСLinux, без MMU линукс не запустить.
                        • +1
                          Да, точно, в ARM7 же только MPU, там только uCLinux можно.
            • 0
              Собственно поэтому я и говорю про RTOS.
        • +1
          Операционные системы придумали, чтобы добавить слой абстракции (в т. ч. процессы, например). Но где-то обращение к железу всё равно будет: в драйвере или сервисе, например. И там работа с железом всё равно будет. Другое дело, что эти драйвера уже, вероятно, давно написаны.

          Проблема Linux, как системы с элементами мягкого реального времени — в негарантированном времени отклика.

          Если хочется разумных сроков разработки и необходимо RT, то наиболее простым будет взять RTLinux: сочетание RT-ядра и обычного ядра Linux в качестве процесса. Или QNX Neutrino, например, но не факт, что драйвера под неё есть.
          • 0
            Ну правильно, надо поставить операционную систему реального времени если очень нужно. Под rPi их даже больше чем одна.
        • 0
          В некоторых задачах аудио и видео обработки пишут под bare metal.
          • +1
            В задачах обработки аудио и видео используются DSP. В некоторые ARM процессоры они даже встроены. Зачем использовать для это процессор общего назначения?
            • 0
              Я не говорю, что нужно использовать процессоры общего назначения для реализации любых задач аудио и видео обработки. Я знаю, что так изредка но делают. Как и зачем я не могу сказать точно.
              • +1
                Может потому, что специалиста, знающего ARM найти проще, чем такового, знающего какой-нибудь Blackfin или SHARC?
  • +2
    > Это связано с негласным правилом, что на голом железе пишут до ARM9, а после на Линуксе.

    Это прямо скажем неправда. Даже для Cortex-A5/Cortex-M0 пар вида Vybrid есть специальные RTOS: MQX.

    > 2) Даташит на процессор
    Это не datasheet на процессор, это datasheet на периферию.

    После того как мой RPi сдох я как-то понял, что проект целиком и наглухо проприетарный и ничего глубже, чем datasheet на периферию, на него не найти. В отличии от кучи других процессоров: lpc, stm, vybrid.
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        В том, что оно вообще грузится проприетарным загрузчиком и драйвер для GPU — тоже blob.

        А сдох непонятно по какой причине, и весь форум дружно ответил «ну хз». Не выходит из ресета.
  • НЛО прилетело и опубликовало эту надпись здесь
    • +1
      Во-первых, мимо.

      Во-вторых, я присмотрел себе Beagle Bone Black или сразу PandaBoard ES. Вообще, я вполне мог бы взять доски той компании, в которой работаю, но к несчастью, мне это запрещено NDA. У BBB есть PRU, что некоторый плюс.
      • 0
        А в какой компании работаете? И почему такое странное ограничение, что нельзя пользоваться продукцией компании, в которой работаешь?
        • 0
          Ограничение вполне разумное: потому-что багаж знаний разработчика — собственность компании.

          Название не скажу, извините.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.