пятница, 16 марта 2012 г.

I & STM32F4-discovery part3 - blinking leds part0

Начиная изучение любого мк первый пример обычно - зажечь светодиод. Мы же немного изменим условия - мы не просто будем зажигать светодиоды, мы сделаем аналог переливания. В качестве задержки возьмем переменной длины цикл. И так добро пожаловать под кат.



Преже чем писать код поговорим собственно о том с чем же мы будем работать. STM32F407xx является мк на базе arm 32-bit Cortex-M4F ядра (F - с фпу). Ядро имеет достаточно высокую производтельноть при относительно небольшой частоте - 210 МИВС для 168 МГц(при включенном ART акселераторе( но не для А версии чипа!)). Более подробно об особенностях можно почитать в предыдущей статье. А мы продолжаем ознакомление с мк.

Для начала создадим нашу рабочую папку где будут хранится файлы для примеров.

nis@jane ~ $ cd stm32
nis@jane ~/stm32 $ mkdir f4examples
nis@jane ~/stm32 $ cd f4examples/

Затем нам необходимо начать новый проект который станет базовым для всех последующих.

nis@jane ~/stm32/f4examples $ mkdir 00-blink-led
nis@jane ~/stm32/f4examples $ cd 00-blink-led/

Для сборки проекта необходим Make файл в который мы поместим все необходимые правила для сборки и записи прошивок мк:

nis@jane ~/stm32/f4examples/00-blink-led $ touch Makefile

Определим базовые настройки среды сборки прошивки - компилятор и его флаги, сборщик и его флаги а также сервисные утилиты:

# Compilator prefix
CROSS_PREFIX=arm-softfloat-linux-gnueabi-
# Compilators and utils
CC=$(CROSS_PREFIX)gcc
OBJCOPY=$(CROSS_PREFIX)objcopy
# Paths
STM_PATH=../../stlink/example
LIBS_STM_PATH=$(STM_PATH)/libs_stm
# Platform
PLATFORM=stm32f4xx
# Primary compiler flags
CFLAGS=-g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc
CFLAGS+= -mcpu=cortex-m3 -DSTM32F4XX

Далее указываем среде сборки где находятся основные файлы заголовков и правил для сборки прошивки. А также подключаемые правила для сборщика:

# Secondary compiler flags
CFLAGS+= -I.
CFLAGS+= -I$(LIBS_STM_PATH)/inc/base
CFLAGS+= -I$(LIBS_STM_PATH)/inc/core_support
CFLAGS+= -I$(LIBS_STM_PATH)/inc/device_support
CFLAGS+= -Wl,-T,stm32f4xxxg_flash.ld
# Linker flags
LDFLAGS=-L.

Также соберем сведения о всех файлах проекта и создадим правила сборки:

# Sources and objects
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
# Rules for compile
all: firmware.bin

%bin: %elf
    $(OBJCOPY) -O binary $^ $@

firmware.elf: $(OBJS)
    $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDFLAGS)

%.o: $.c
    $(CC) $(CFLAGS) -c -o $@ $^

И напоследок правила для очистки проекта и его загрузки в мк:

# Rules for clean
clean:
    rm -rf *.o *.elf *.bin

# Rules for write firmware to mcu
write:
    st-flash write v2 firmware.bin 0x8000000

.PHONY: all clean

На этом мы закончили написание файла сборки.

В мк помимо большого количества периферии, есть флешь объемом 1МБ и статическая оперативная память общим объемом 192КБ. По сути же у нас блоки независимой памяти различных объемом и скоростей доступа:
  • SRAM 112KB - основная статическая память
  • SRAM 16KB - дополнительная статическая память
  • CCV data RAM 64KB - память данных подключенная напрямую к ядру.
Вот ее мы и используем в своих программах для хранения стека и изменяемых данных. Адреса в общей карте памяти для флешь - 0x8000000, для data RAM - 0x10000000. Для сброки проекта необходим файл stm32f4xxxg_flash.ld в котором мы укажем размеры регионов памяти с которыми будем работать непосредственно, их тип и адрес в памяти:

nis@jane ~/stm32/f4examples/00-blink-led $ touch stm32fxxxg_flash.ld

ENTRY(reset_handler)

MEMORY
{
    FLASH (rx)          : ORIGIN = 0x08000000, LENGTH = 1M
    RAM (rxw)           : ORIGIN = 0x10000000, LENGTH = 64K
}

INCLUDE generic_sections_flash.ld

Также нам необходим файл generic_sections_flash.ld в котором мы укажем расположение секций данных и кода внутри региона.

nis@jane ~/stm32/f4examples/00-blink-led $ touch generic_sections_flash.ld

На этом создание файлов конфигурации и сборки заканчивается. Исполнение начинается с копирования значения конца стека которое находится в начале прошивки, затем осуществляется переход по вектору который идет вслед за размером стека. Создадим начальный стартовый файл где и будет таблица векторов прерывания(о ней поговорим в следующих статьях) и код первичной инициализации.

nis@jane ~/stm32/f4examples/00-blink-led $ touch startup.c

#include "stm32f4xx.h"
/* external vars */
extern unsigned long _estack;
/* reset handler */
void reset_handler(void) {
}
/* table of Cortex vectors */
void *vector_table[] __attribute__ ((section(".vectors"))) = {
    &_estack,
    reset_handler,
};

И соберем проект:

nis@jane ~/stm32/f4examples/00-blink-led $ make
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F4XX -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f4xxxg_flash.ld   -c -o startup.o startup.c
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F4XX -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f4xxxg_flash.ld -o firmware.elf startup.o -L.
arm-softfloat-linux-gnueabi-objcopy -O binary firmware.elf firmware.bin



В результате должен получится файл firmware.bin объемом 12 байт:

nis@jane ~/stm32/f4examples/00-blink-led $ ll
итого 32
-rwxr-xr-x 1 nis nis    12 марта 16 16:37 firmware.bin
-rwxr-xr-x 1 nis nis 34977 марта 16 16:37 firmware.elf
-rw-r--r-- 1 nis nis  1406 марта 16 16:20 generic_sections_flash.ld
-rw-r--r-- 1 nis nis  1263 марта 16 16:37 Makefile
-rw-r--r-- 1 nis nis   511 марта 16 16:35 startup.c
-rw-r--r-- 1 nis nis  3060 марта 16 16:37 startup.o
-rw-r--r-- 1 nis nis   462 марта 16 16:16 stm32f4xxxg_flash.ld

Немного изменим startup.c добавив в функцию reset_handler вызов внешней функции main:

/* prototypes of functions */
main();
/* reset handler */
void reset_handler(void) {
    main();
}
/* table of Cortex vectors */
void *vector_table[] __attribute__ ((section(".vectors"))) = {
    &_estack,
    reset_handler,
};

Также создадим заголовочный файл main.h где определим основные значения и параметры программы:

nis@jane ~/stm32/f4examples/00-blink-led $ touch main.h




#include "stm32f4xx.h"
/* defines */
/** define led port */
#define LED_PORT GPIOD
/** define led pins */
#define LED_GREEN (1 << 12) /* port D, pin 12 */
#define LED_ORANGE (1 << 13) /* port D, pin 13 */
#define LED_RED (1 << 14) /* port D, pin 14 */
#define LED_BLUE (1 << 15) /* port D, pin 15 */

А также создадим главный файл - main.c где у нас будет основной код прошивки:

nis@jane ~/stm32/f4examples/00-blink-led $ touch main.c

#include "main.h"
void main(void) {
}

Соберем полученный проект:

nis@jane ~/stm32/f4examples/00-blink-led $ make
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F4XX -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f4xxxg_flash.ld   -c -o main.o main.c
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F4XX -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f4xxxg_flash.ld   -c -o startup.o startup.c
startup.c:11:1: предупреждение: data definition has no type or storage class
arm-softfloat-linux-gnueabi-gcc -g -O2 -mlittle-endian -mthumb -ffreestanding -nostdlib -nostdinc -mcpu=cortex-m3 -DSTM32F4XX -I. -I../../stlink/example/libs_stm/inc/base -I../../stlink/example/libs_stm/inc/core_support -I../../stlink/example/libs_stm/inc/device_support -Wl,-T,stm32f4xxxg_flash.ld -o firmware.elf main.o startup.o -L.
arm-softfloat-linux-gnueabi-objcopy -O binary firmware.elf firmware.bin

На этом подготовка заканчивается и начинается описание основного кода программы.

Продолжение