- Вычислительные возможности STM32

Вычислительные возможности STM32F4Discovery, ввод – вывод в UART с помощью scanf и printf для IAR

Практика для студентов. Мясищев А.А.

Создание автономных транспортных средств (роботов) связано с решением задач компьютерного зрения. Классической задачей в компьютерном зрении является определение, содержат ли видеоданные некоторый характерный объект, особенность или некоторую активность. Решение таких задач связано с необходимостью проведения вычислительных операций в режиме реального времени. Обычно для этих целей используются вычислительные системы, которые находятся за пределами робота и он из-за этого не является полностью автономным. Однако в настоящее время появляются довольно мощные 32 - разрядные микроконтроллеры, которые имеют даже встроенные сопроцессоры для выполнения операций с вещественными числами. Ниже на простейшем примере, используя микроконтроллер STM32F407VGT6, установленный на плате STM32F4Discovery фирмы STMicroelectronics, оценим его вычислительные возможности при вычислении интеграла методом прямоугольников. При составлении программы рассмотрим также программирование USART с использованием стандартных функций языка Си – printf и scanf.

Для работы с платой STM32F4Discovery заходим по адресу http://supp.iar.com/Download/SW/?item=EWARM-EVAL и копируем пакет программ IAR Embedded Workbench for ARM. Поставляется с лицензией, которая позволяет попробовать эту интегрированную среду разработки и оценить ее эффективность и простоту использования.

Предложены два варианта оценочной лицензии:

1. Ограниченная лицензия 30 днями, но полностью функциональная.

2. Ограниченная по размеру кода 32КБайтами лицензия Kickstart, но которая работает без ограничения во времени.

Вторая лицензия может быть использована для решения широкого круга несложных задач.

Установка среды разработки проводится довольно просто путем запуска на исполнение скопированного файла, имеющий размер 717Мбайт.

Для подключения платы STM32F4Discovery к USB порту компьютера для программирования микроконтроллера необходим ST-LINK/V2 USB driver for Windows, который можно взять по адресу:http://www.st.com/web/en/catalog/tools/PF258167. Он также устанавливается в системе путем запуска на выполнение.

Также необходим STM32F4DISCOVERY board firmware package, including 22 examples(STSW-STM32068), который находится по адресу: http://www.st.com/web/en/catalog/tools/PF257904. Скопированный файл должен быть разархивирован, например, в каталоге, где будет создаваться новый проект.

Описанные ниже действия относится к IAR ver.6.70 (январь 2014г.)

Запускаем IAR Embedded Workbench:

Заходим во вкладку Project:

Создаем новый проект:

Сохраняем его под именем proj1 в заранее созданном каталоге IAR_proj1:

После нажатия на кнопку «сохранить» появляется шаблон программы

Вместо этого шаблона вставляем новый код программы, который будет описан ниже:

Нажимаем клавиши Alt+F7 и устанавливаем опции. Сначала выбираем микроконтроллер, который установлен на плате STM32F4Discovery - STM32F407VG. На этой же вкладке выбираем использование сопроцессора.

В следующей вкладке указываем пути к include файлам. Предполагается, что библиотека CMSIS лежит в каталоге stsw-stm32068, который находится где-то на диске компьютера (может, как указано выше, находиться в каталоге проекта IAR_proj1).

В окне Defined symbols должны быть вписаны строки, как представлено ниже:

Во вкладке Debugger устанавливаем ST-LINK:

и в той же вкладке, но в Download ставим галочку на Use flash loader:

Во вкладке ST-LINK в Interface выбираем SWD:

Нажимаем на кнопку OK каждый раз при выходе из Options.

Теперь в левое окно добавим несколько файлов для того, чтобы можно было выполнить компиляцию программы. Для этого курсор мыши совмещаем с proj1-Debug *, нажимаем правую клавишу мышки и выбираем Add Files… . В каталоге stsw-stm32068 находим необходимые файлы. Так файлыstm32f4xx_gpio.c, stm32f4xx_usart.c и stm32f4xx_rcc.c находятся в каталоге stsw-stm32068\STM32F4-Discovery_FW_V1.1.0\Libraries\STM32F4xx_StdPeriph_Driver\src, а файл system_stm32f4xx.c – например, в каталоге одного из примеров: stsw-stm32068\STM32F4-Discovery_FW_V1.1.0\Project\Peripheral_Examples\IO_Toggle

В результате получим следующее расположение файлов в левой панели:

Выполняем компиляцию, выбрав в закладке Project опцию Make:

Убеждаемся в том, что она прошла без ошибок.

Для передачи откомпилированного файла в плату, выбираем в закладке Project опцию Download, а затем опцию Download active application:

Программа main.cpp, которая была выше вставлена вместо шаблона, с подробными комментариями имеет следующий вид:

#include "stm32f4xx.h"

#include <stdio.h>

#include "stm32f4xx_usart.h"

#include "stm32f4xx_gpio.h"

#include "stm32f4xx_rcc.h"

#include <yfuns.h>

int MyLowLevelPutchar(int x);

int MyLowLevelGetchar(void);

void usart_init(void);

// Для перенаправления вывода printf на USART

// необходимо добавить функцию __ write из файла

// C:\Program Files\IAR Systems\Embedded Workbench 6.5\arm\src\lib\write.c.

// Эта функция предполагает, что используется функция

// MyLowLevelPutchar для пересылки байта на USART.

size_t __write(int handle, const unsigned char * buffer, size_t size)

{

size_t nChars = 0;

if (buffer == 0)

{

return 0;

}

if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR)

{

return _LLIO_ERROR;

}

for (/* Empty */; size != 0; --size)

{

if (MyLowLevelPutchar(*buffer++) < 0)

{

return _LLIO_ERROR;

}

++nChars;

}

return nChars;

}

// Для перенаправления ввода scanf с USART

// необходимо добавить функцию __ read из файла

// C:\Program Files\IAR Systems\Embedded Workbench 6.5\arm\src\lib\read.c.

// Эта функция предполагает, что используется функция

// MyLowLevelGetchar для получения байта с USART.

size_t __read(int handle, unsigned char * buffer, size_t size)

{

int nChars = 0;

if (handle != _LLIO_STDIN)

{

return _LLIO_ERROR;

}

for (/* Empty */; size > 0; --size)

{

int c = MyLowLevelGetchar();

if (c < 0)

break;

*buffer++ = c;

++nChars;

}

return nChars;

}

// Функция передачи байта через USART3

int MyLowLevelPutchar(int x){

while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);

USART_SendData(USART3, x);

return x;

}

// Функция получения байта от USART3

int MyLowLevelGetchar(){

int cc;

while(USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET);

cc= USART_ReceiveData(USART3);

return cc;

}

// Функция настройки USART3

void usart_init(void)

{

// Объявим две структуры для хранения настроек GPIOC и USART3.

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

// Включаем тактирование порта C и UART3

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

// Подключаем 10-й пин GPIOC к USART3 как передающий (Tx)

GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);

// Подключаем 11-й пин GPIOC к USART3 как принимающий (Rx)

GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);

// Конфигурируем 10 и 11 пины GPIOC для работы с USART3

// (альтернативная функция для пинов)

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // Устанавливаем

// только это значение для пинов. Существует также и второе -

// GPIO_OType_OD. Но для него вывод работать не будет

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // Подтягиваем к 3В

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Включаем режим

// альтернативной функции работы пинов специально для USART

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; // Настройка

// только выводов PC10, PC11

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // Устанавливаем

// скорость портов (Можно поставить любую другую но допустимую)

GPIO_Init(GPIOC, &GPIO_InitStructure); // Сохраняем параметры пинов

// Устанавливаем параметры работы USART3

USART_InitStructure.USART_BaudRate = 9600; // Скорость обмена 9600 бод

USART_InitStructure.USART_WordLength = USART_WordLength_8b; // Длина

// слова 8бит

USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1 стоп-бит

USART_InitStructure.USART_Parity = USART_Parity_No; // Без контроля

// четности

USART_InitStructure.USART_HardwareFlowControl =

USART_HardwareFlowControl_None; // Без аппаратного контроля

// Включаем приемник и передатчик

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

// Сохраненяем параметры USART3

USART_Init(USART3, &USART_InitStructure);

// Включаем USART3

USART_Cmd(USART3, ENABLE);

}

int main(void)

{

float dx,xi,yi,sum;

uint32_t j,i,n; //

SystemInit(); // Функцию инициализации нужно вызвать обязательно,

// иначе максимальной производительности не будет

usart_init(); // Настраиваем USART3

while (1)

{

printf("\r\nInput:\r\n");

scanf("%i",&n); // Вводим число прямоугольников, на которое разбиваем

// интервал интегрирования (здесь выбрано значение 100000)

printf("\r\nStart\r\n");

dx = 1.0f/n; // 1.0f - означает, что 1.0 – вещественное число одинарной точности

// Если f в конце не поставить, то 1.0 - вещественное число двойной точности

for( j=1;j<=200;j++) { // 200 раз рассчитываем интеграл

// методом прямоугольников

sum = 0.0f;

for( i = 1;i<=n; i++){

xi = (i - 0.5f ) * dx;

yi = 4.0f/(1.0f + xi * xi);

sum = sum + dx*yi;

}

}

printf("pi=%.16f\r\n",sum); // Выводим число пи

}

}

Программа выполняет расчет определенного интеграла

Согласно правилу прямоугольников интеграл представлен суммой площадей элементарных прямоугольников:

Из программы видно, что для ввода и отображения результатов используется USART3 (всего их шесть у STM32F407VGT6) и пины микроконтроллера PC10 и PC11(Tx и Rx). На рисунке 1 показана схема подключения платы STM32F4Discovery к компьютеру через совершенно любой USART – USB конвертер. Здесь использована функция конвертера от программатора AVR ISP v3.2.

Рис.1. Схема соединений

На компьютере запускается HyperTerminal (рисунок 2) и проводятся экспериментальные расчеты. Для отображения в окне HyperTerminal символов ввода (числа 100000), в настройках необходимо поставить галочку напротив «Отображать введенные символы на экране».

Рис.2. Пример работы программы для одинарной и двойной точности(pi=3.141592653589793238…)

Расчеты выполнялись с максимальной оптимизацией и без оптимизации (устанавливается опциями для компилятора), с сопроцессором(FPU) и без сопроцессора, для одинарной и двойной точности в средах разработки IAR Embedded Workbench for ARM ver. 6.70 и CooCox ver. 1.7.5 с рекомендованным для него GNU Tools for ARM Embedded Processors Version: 4.8. Выполнено сопоставление с процессором AMD Phenom II X6 1090T (3.2ГГц), для которого задача запускалась на одном ядре. Результаты представлены в таблице 1. Дано время выполнения расчетов в секундах.

1. Для расчетов, требующих высокого быстродействия для принятия решения спроектированным устройством предпочтение необходимо отдать среде разработки IAR Embedded Workbench for ARM.

2. Сопроцессор работает только для вещественных чисел с одинарной точностью(4 байта). Для чисел с двойной точностью он не работает, как и указано в характеристиках микроконтроллера STM32F407VGT6.

3. Если достичь частоты работы микроконтроллера, равной тактовой частоты процессора AMD, то их быстродействия почти будут равны, если компилятор gcc не будет запущен с ключом оптимизации (-O3).

Задание.

1. Проанализировать быстродействие микроконтроллера STM32F407VGT6 при решении задачи умножения двух заполненных квадратных матриц. Найти максимальный размер используемых матриц и для них сопоставить быстродействие в MFlops с быстродействием компьютера на одном ядре процессораAMD Phenom II X6 1090T(3.2ГГц).

2. Факультативное задание. Составить программу для решения систем линейных уравнений методом Гаусса. Найти максимальное число уравнений для STM32F407VGT6. Определить производительность системы в MFlops для максимально возможного числа уравнений.

Выводы.