Если, вдруг, ресурсов контроллера Arduino и 8-битных МК Atmel AVR перестаёт хватать — всегда есть вариант перейти на ARM Cortex-M. Например, на популярные микроконтроллеры STM32.
Переход можно осуществить довольно плавно — при помощи контроллеров:
Leaflabs Maple (STM32F103RB, 72 MHz),
STM32 MCU Nucleo.
А лучше сразу взять какую-нибудь Discovery. Например, STM32F4Discovery (STM32F407VG, 168 MHz).
Начав ковыряться с STM32, вы быстро обнаружите, что они с SPL (Standard Peripheral Library) перешли на HAL (High Access Level) с удобным графическим конфигуратором — STM32CubeMX, что даёт просто турбореактивный старт использования МК STM32.
Для вводного представления, можно посмотреть вебинар «Изучение STM32CubeMX на примере отладочной платы STM32F746G-DISCO»:
http://www.youtube.com/watch?v=iCcJmn5N3R8
HAL работает поверх CMSIS (Cortex Microcontroller Software Interface Standard), который представляет собой единый стандарт описаний ресурсов (стандартную библиотеку).
Например, реализация аналога digitalWrite() — HAL_GPIO_WritePin():
/**
* @brief Sets or clears the selected data port bit.
*
* @note This function uses GPIOx_BSRR register to allow atomic read/modify
* accesses. In this way, there is no risk of an IRQ occurring between
* the read and the modify access.
*
* @param GPIOx: where x can be (A..K) to select the GPIO peripheral for STM32F429X device or
* x can be (A..I) to select the GPIO peripheral for STM32F40XX and STM32F427X devices.
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
* @param PinState: specifies the value to be written to the selected bit.
* This parameter can be one of the GPIO_PinState enum values:
* @arg GPIO_PIN_RESET: to clear the port pin
* @arg GPIO_PIN_SET: to set the port pin
* @retval None
*/
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
assert_param(IS_GPIO_PIN_ACTION(PinState));
if(PinState != GPIO_PIN_RESET)
{
GPIOx->BSRR = GPIO_Pin;
}
else
{
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16;
}
}
- сводится к установке соответствующего бита в регистре BSRR, для соответствующего порта.
Blink зелёным светодиодом для STM32F4DISCOVERY внутри while (1):
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, 1); // LED_GREEN_Pin
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, 0);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
, где
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
- указатель на структуру:
/**
* @brief General Purpose I/O
*/
typedef struct
{
__IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
__IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
__IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
__IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
__IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
__IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
__IO uint32_t BSRR; /*!< GPIO port bit set/reset register, Address offset: 0x18 */
__IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
__IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
} GPIO_TypeDef;
Из адреса:
... #define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */ ... #define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000) ... #define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00) ...
Что в сумме и даёт адрес 0x40020C00, где собственно и располагается GPIO register map для GPIOD (согласно референсу RM0090 для STM32F407/417).
IDE
System Workbench for STM32 - бесплатна - на базе Eclipse - поддерживается ST, для скачивания нужно зарегистрироваться.
Keil uVision - бесплатен до 32 кБ, плюс для L0, F0.
А можно опять-таки использовать сборную солянку из тулчейна, OpenOCD и любой удобной среды.
Например, при помощи QtCreator:
Программируем микроконтроллеры stm32 при помощи QtCreator
Разработка для STM32F4Discovery с помощью mbed в QtCreator
ручной запуск отладчика:
openocd.exe -f ..\scripts\board\stm32f4discovery.cfgчтобы QtCreator не зависал:
Qt Creator -> Инструменты -> Параметры -> Отладчик -> GDB, расширенные -> Использовать асинхронный режим для работы с программой.для прошивки при помощи ST-LINK:
arm-none-eabi-objcopy.exe -Oihex c:\workspace\testqt\.build\qtc_STM32-debug\testqt.elf c:\workspace\testqt\.build\qtc_STM32-debug\testqt.hex
Пример qbs-проекта для простого Blink-проекта
testqt.qbs
import qbs
Product {
type: "application"
consoleApplication: true
cpp.executableSuffix: ".elf"
Depends {name: "cpp" }
property string name: "testqt"
property string vendor: "STM"
property string model: "STM32F4DISCOVERY"
property string toolchain: "ARM_GCC"
property string cortex: "M4"
cpp.positionIndependentCode: false
cpp.debugInformation: true
cpp.commonCompilerFlags: [
"-mcpu=cortex-m4", "-mthumb",
"-mfloat-abi=hard","-mfpu=fpv4-sp-d16",
"-Os","-g3","-Wall","-fmessage-length=0", "-ffunction-sections","-c","-fmessage-length=0",
]
cpp.defines: [
'USE_HAL_DRIVER',
'STM32F407xx'
]
cpp.linkerFlags:[
"-mcpu=cortex-m4", "-mthumb",
"-mfloat-abi=hard", "-mfpu=fpv4-sp-d16",
"--specs=nosys.specs", "--specs=nano.specs",
"-Wl,-Map=output.map", "-Wl,--gc-sections","-lm",
"-T"+path+"/SW4STM32/"+name+" Configuration/STM32F407VGTx_FLASH.ld"
]
cpp.includePaths: [
"Inc",
"Drivers/STM32F4xx_HAL_Driver/Inc",
"Drivers/STM32F4xx_HAL_Driver/Inc/Legacy",
"Drivers/CMSIS/Include",
"Drivers/CMSIS/Device/ST/STM32F4xx/Include"
]
files: [
"Src/*.c",
"Inc/*.h",
"Drivers/CMSIS/Device/ST/STM32F4xx/Include/*.h",
"Drivers/CMSIS/Include/*.h",
"Drivers/STM32F4xx_HAL_Driver/Inc/*.h",
"Drivers/STM32F4xx_HAL_Driver/Inc/Legacy/*.h",
"Drivers/STM32F4xx_HAL_Driver/Src/*.c",
"Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/*.s",
"Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/*.c",
"Src/main.c"
]
Properties {
condition: qbs.buildVariant === "debug"
cpp.defines: outer.concat(["DEBUG=1"])
}
Group {
qbs.install: true
fileTagsFilter: "application"
}
}
Если зачем-то захочется - можно даже Arduino IDE использовать (Arduino STM32 - работает только на версии IDE 1.6.5).
продолжение следует...
Ссылки
STM32CubeMX (STM32CubeF4)
System Workbench for STM32 installer
System Workbench - Importing a STCubeMX generated project
Pre-built GNU toolchain from ARM Cortex-M & Cortex-R processors (Cortex-M0/M0+/M3/M4/M7, Cortex-R4/R5/R7).
STM32CubeMX — продвинутый генератор проектов для STM32
Описание драйверов HAL STM32F4xx, частичный перевод
Библиотека libmaple на STM32VLDiscovery
CMSIS - Cortex Microcontroller Software Interface Standard
ARM. Учебный Курс. Keil + CMSIS. Создание проекта
Микроконтроллеры STM32 «с нуля»
Визуализация возможностей: графический генератор кода STM32CubeMX
CubeMX и Workbench: создание проекта на базе STM32 с помощью бесплатного ПО
STM32
ST-Link, ST-Link/V2, ST-Link/V2-1 USB driver signed for XP, Windows7, Windows8
STM32 ST-LINK utility
STM32 Virtual COM Port Driver
UM1718 - User manual - STM32CubeMX for STM32 configuration and initialization C code generation
STM32F4DISCOVERY
STM32F407VG
STM32F4DISCOVERY
STM32F407xx Datasheet
RM0090 - Reference manual STM32F405/415, STM32F407/417
UM1472 - User manual - Discovery kit for STM32F407/417
UM1725 - User Manual - Description of STM32F4xx HAL drivers
NB:
STM32CubeMX - это развитие утилиты MicroXplorer.
По теме
Знакомство с ARM Cortex-M3 и с STM32, в частности
STM32: Урок 1 - Настраиваем IDE
STM32: Урок 2 - Quickstart
STM32: Урок 3 - Документация
STM32: Урок 4 - GPIO
STM32: Урок 5 - Архитектура
STM32: Урок 6.1 - Базовые таймеры
STM32: Урок 6.2 - Таймеры общего назначения и продвинутые
Stellaris Lm4F120 Launchpad - отладочная плата на ARM Cortex M4 от Texas Instruments
