Pull to refresh

Программируем Raspberry Pi на голом железе

Reading time 2 min
Views 99K
До сих пор 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)
    {

    }
}


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

В следующей части попробуем поиграться с таймерами и прерываниями.
Tags:
Hubs:
+64
Comments 62
Comments Comments 62

Articles