среда, 24 апреля 2013 г.

STM32F407(STM32F4-DISCOVERY) - Нестандартный подход - Стандартная библиотека ч2

Часть 2 - Практика

После теории можно рассмотреть обе части библиотеки с практической точки зрения. При этом надо заметить, что помимо явного указания достоинств каждой части, я также укажу недостатки, с большинством из которых вы наверное даже и не столкнётесь до той поры, пока не копнёте чуть глубже чем обычные проекты с использованием МК.


"Hello Led"
В качестве примера возьмём простое включение 4х цветных светодиодов на плате (которые вокруг акселерометра).

CMSIS
Проект - 000-libs-cmsis. Помимо констант (удобство использования которых не вызывает сомнения) в файле work.h:
/** Led port */

#define LED_PORT GPIOD

/** Led pins */

#define GREEN_LED (1 << 12)

#define ORANGE_LED (1 << 13)

#define RED_LED (1 << 14)

#define BLUE_LED (1 << 15)

#define ALL_LEDS (GREEN_LED | ORANGE_LED | RED_LED | BLUE_LED)
Код в файле work.c не занимает много места и достаточно прост:
/* enable led port */

RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;

/* set led pins to output state */

LED_PORT->MODER |=

    GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 |

    GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0;

/* enable leds */

LED_PORT->ODR |= ALL_LEDS;

/* infinity loop */

while (1);
Начиная с инициализации и заканчивая собственно переводом выводов в активное состояние.
Для настройки хватило 2 регистров, т.к. значения по умолчанию соответствуют тем, которые нам нужны.

SPL
Проект - 001-libs-spl. Немного изменились константы(которые правильней называть объявлениями) в файле work.h:
/** Led port */

#define LED_PORT GPIOD

///** Led pins */

#define GREEN_LED GPIO_Pin_12

#define ORANGE_LED GPIO_Pin_13

#define RED_LED GPIO_Pin_14

#define BLUE_LED GPIO_Pin_15

#define ALL_LEDS (GREEN_LED | ORANGE_LED | RED_LED | BLUE_LED)
А вот с точки зрения кода (work.c) мы поменяли полностью всю логику:
GPIO_InitTypeDef GPIO_InitStructure;


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);


GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Pin = ALL_LEDS;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_Init(LED_PORT, &GPIO_InitStructure);


GPIO_SetBits(LED_PORT, ALL_LEDS);

/* infinity loop */

while (1);
В SPL мы оперируем не отдельными регистрами, а блоками. Т.е. проще говоря код из указательного превратился в декларативный. В примере мы объявили структуру для порта ввода-вывода. Затем включили тактирование нужного нам порта в/в. Настройка порта осуществляется полностью через его структуру. Для установки-снятия битов существуют соответствующие функции, одной из которых мы и воспользовались. Для иллюстрации фото работы этого примера:
Теперь собственно поговорим чем же различаются эти два подхода к написанию кода. CMSIS даёт непосредственный доступ к периферии, сочетающийся с тем, что при непосредственной записи в регистры мы получаем максимально возможную скорость. Однако вместе с этим мы получаем кучу геморроя определенные трудности при настройке блока сложнее чем базовый порт ввода-вывода (GPIO). Это в первую очередь связанно с тем что регистров и битов в них для той же системы тактирования составляет более десятка. Необходимо помнить не только регистры но и биты в них, а также порядок действий для конкретной операции. Код по большей степени становится ассемблеро-подобным. Что же касается SPL, то несомненно видно, что все операции по настройки оборачиваются в красивые функции. Также флаги ответственные за одинаковые подблоки в разных регистрах объявлены одной константой (на примере включения светодиодов это хорошо видно). Но не стоит забывать то, что не все так гладко. У SPL первый недостаток в том, что прежде чем записать новое значение принудительно сбрасывается старое - т.е. происходит явление джиттера. На высоких частотах работы периферии это особенно заметно. Также можно заметить, что помимо увеличения времени работы - т.к. большинство функций имеет "защиту от дурака" проверку на входные параметры, есть ещё фактор автоматизма. Так не совсем точно вычисляются коэффициенты для USART на высоких нектарных стандартным частотах основной шины. Вывод можно сделать следующий: инициализацию периферии (за исключением определенных случаев) можно полностью осуществлять с помощью SPL, CMSIS же использовать там, где требуется критическое время выполнения или определенные изменения одного-двух битов регистра без перезагрузки. Стандартная библиотека ч1