Если, вдруг, ресурсов контроллера 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