Arm. stm32 быстрый старт

STM32F407: быстрый старт

Источник: http://microsin.net/programming/ARM/stm32f407-quick-start.html

STM32F103C8T6 aka Blue Pill + STM32duino + IAR ARM: быстрый старт

разделы: STM32 , STM32duino , дата: 08 сентября 2017г

Отладочная плата на микроконтроллере stm32f103c8t6, является одной из самых популярных в любительской среде “электронщиков”. Это одна из самых удачных плат в соотношении “цена/функционал”, а сам stm32f103xxxx, который выпускается уже 10 лет, является ветераном и первопроходцем микроконтроллеров на ядрах ARM Cortex M3.

    Для быстрого знакомства с платой я предлагаю пройтись по следующим пунктам:
  • Краткий обзор платы;
  • Исправление аппаратного бага с помощью термофена и паяльника;
  • Прошивка загрузчика STM32duino;
  • “Подъем” виртуального COM порта на USB-модуле микроконтроллера stm32f103c8t6 с помощью STM32Cube MX и IAR ARM. Подключение микроконтроллера к планшету на Android.
  • Подключение и написание программы опроса I2C модуля RTC DS3231 с помощью STM32duino.

Вроде не много.

  • В отличии от Maple Mini, данная плата имеет штыревой разъем для подключения китайского клона ST-Link. Что на мой взгляд является большим плюсом, т.к. на проверку, загрузчик Leafmaple/STM32duino из-за постоянного переключения между DFU-загрузчиком и виртуальным COM-портом, оказался довольно проблемным.
  • Плата имеет на борту два кварца: на 8 MHz для тактирования HSE и на 32768 Hz для LSE. Для сравнения, на Maple Mini установлен только кварц на 8 MHz.
  • Сам микроконтроллер stm32f103c8t6, несмотря на то что по документации поставляется с флешпамятью на 64KБайта, фактически поставляется с флеш-памятью на 128КБайт(!) Хотя, гарантии на это никто не дает конечно.
  • Также имеется два джампика для прошивки микроконтроллера через USB-TTL конвертер, кнопка сброса Reset, два светодиода: красный для индикации питания и зеленый подключенный к выводу PC13. Причем загорается он при логическом нуле.
  • Цифровые выводы имеют маркировку в соответствии с даташитом, за тем исключением, что из их обозначения отброшена литера “P”.
  • Довершает “обвес” микро-USB разъем, который мы сегодня попытаемся задействовать.
  • Сфера применения микроконтроллера, на мой взгляд- это коммутация по USB-интерфейсу с традиционными компьютерами, одноплатными компьютерами, устройствам на Android которые возможно использовать как дисплеи(вторая жизнь для устаревших телефонов и планшетов) и т.д. Также думаю, что будет неплохая связка микроконтроллеров STM32 с SPI-дисплеями.

Полезная информация о плате собрана на страничке проекта STM32duino.

Для начала взглянем на раcпиновку платы:

и принципиальную схему:

На схеме нас будет интересовать резистор R10. На вики STM32duino, относительно этого резистора утверждается следующее:

The USB standard requires a 1.5 kΩ pullup resistor on D+, but this board is known to have a wrong value (R10 on the board). It ships with either a 10 kΩ resistor or a 4.7 kΩ resistor, but it should be replaced with a 1.5 kΩ resistor, or put an appropriate resistor value (e.g 1.8 kΩ) in between PA12 and 3.3V. It is also true that some PCs are tolerant of incorrect value so, before you change the resistance, you can try if it works in your case.

Т.е. они пишут, что согласно спецификации USB, на линии D+ должен быть установлен резистор номиналом 1.5K в то время как китайцы ставят резисторы на 4.7К или 10К. И далее предлагается поменять его на резистор требуемого номинала. Там даже прилагается фото с результатом переделки:

Еще там сказано, что несмотря на неправильный номинал резистора, USB-хостами наш микроконтроллер все же может восприниматься корректно. Нужно пробовать, но никакой гарантии нет.

На моей версии платы был установлен резистор на 10K:

Протестировав плату на паре стационарных компьютеров и на одном планшете с Android я могу сказать, что плата скорее всего будет работать и без переделки, но возможно будет подглючивать. У меня она не всегда распознавалась в Windows, а в Android не отображалась в списке подключенных устройств, хотя терминальная программа при этом устройство видела и принимала с него данные.

Поэтому, если есть такая возможность, то резистор все же лучше поменять:

Ну и заодно я впаял штыревой разъем, что бы в лишний раз не мараться. Получилось как-то так:

Ок. теперь когда отремонтирован USB, можно начать программировать.

Прошивка и программирование Blue Pill

Подключаем плату к ST-Link и запускаем “STM32 ST-LINK Utility”:

Жмем “Connect to the target” и если в графе Device чип определился правильно, значит все Оk, чип живой и готов к работе. Хотя, это конечно следовало проверить ДО того как браться за паяльник 😉

Попробуем прошить Blink через ST-Link из Arduino. Для этого запустим Arduino с установленным паком Arduino_STM32. В меню выбора платы щелкнем по Generic-STM32F103C series

Из примеров загрузим вариант Blink'а для STM32:

В тексте скетча исправим номер пина PB1 на PC13, т.е. на пин с зеленым светодиодом.

В меню выбора программатора выберем ST-Link:

После чего пробуем прошить:

В итоге имеем вес прошивки в 13 КБайт, и успешный лог выполнения. К конце прошивка немного подвисает, на этапе “waiting for tty device”, т.е. в ожидании последовательного порта, как будто бы прошивка происходила через USB-загрузчик, но в целом, все ОК.

Установка USB загрузчика STM32duino

Попробуем поставить загрузчик STM32duino для прошивки через USB-кабель. Для этого скачиваем отсюда прошивку с суффиксом PC13(пин со светодиодом):

Далее загружаем скачанную прошивку в микроконтроллер:

Откладываем в сторону ST-Link, и подключаем микроконтроллер к компьютеру через microUSB разъем. Затем снова запускаем Arduino IDE и в опции “Upload Method” указываем “STM32duino bootlooder”.

После чего снова пробуем прошить скетч, но уже через USB. Если все сложится удачно, то выйдет такой лог:

Замечу, что прошивалось через Linux версию Arduino IDE.

Здесь есть один нюанс. Джампики на плате должны находиться в положении “ноль”. Если они, допустим, будут вообще сняты, то Arduino не сможет перезагрузить микроконтроллер перед прошивкой, и он не сможет войти в режим загрузчика. Так же должно быть понятно, что если теперь прошить микроконтроллер через ST-LINK, то загрузчик затрётся.

Теперь я отложу эту плату в сторону чтобы не затереть загрузчик STM32duino, который еще понадобится, и возьму другую. Попробуем поднять на микроконтроллере Virtual COM Port c помощью STM32Cube MX и IAR ARM.

Прошивка в Virtual COM PORT

Запускаем “куб” и открываем новый проект:

Выбираем смою модель микроконтроллера:

Выставляем тактирование от кварца, и включаем отладку по SWD:

Включаем USB Full-Speed модуль:

Выставляем режим работы USB модуля как Virtual COM Port:

Для индикации рабочего цикла задействуем светодиод на PC13 ножке:

С конфигурацией GPIO покончено, переходим к настройке тактирования. Сразу же откажемся от автоматических настроек:

Настроим тактирование например так:

Осталось дело за малым, задать идентификатор для ножки PC13:

С “кубом” закончили, экспортируем проект в IAR ARM:

Настройка параметров экспорта: имя проекта, среда разработки, рабочие каталоги:

После чего открываем проект в IAR:

В главный цикл добавим следующий код:

HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); HAL_Delay(1000); HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); HAL_Delay(1000); CDC_Transmit_FS(“Hello World!
“,13);

В начало main.c нужно еще будет добавить заголовочный файл usbd_cdc_if.h:

Все, можно нажимать на компиляцию и загружать прошивку в микроконтроллер. “Весит” она кстати тоже не мало, десять килобайт. Можно убирать в стол ST-Link, он больше не понадобится. Подключаем микроконтроллер через USB к компьютеру, если речь идет о Linux, то больше ничего делать не надо, драйвер уже имеется в ядре и при подключении выдает такой лог:

[15928.181626] usb 6-3: new full-speed USB device number 124 using ohci-pci
[15928.338706] usb 6-3: New USB device found, idVendor=0483, idProduct=5740
[15928.338717] usb 6-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[15928.338724] usb 6-3: Product: STM32 Virtual ComPort
[15928.338730] usb 6-3: Manufacturer: STMicroelectronics
[15928.338735] usb 6-3: SerialNumber: 00000000001A
[15928.340836] cdc_acm 6-3:1.0: ttyACM0: USB ACM device

Можно открывать терминальную программку и смотреть на всплывающие строки: “hello world!”

Если же речь идет о Windows, то потребуется еще поставить драйвер com-порта. Для этого зайдем на my.st.com, залогинимся и в строке поиска ведем запрос: “stm32 virtual com port”

В выпадающем списке нам сразу предлагается STSW-ST32102, он то нам и нужен. Скачиваем, распаковываем, находим инсталятор:

Подводный камень кроется в том, что после установки драйвера его еще нужно будет установить 😉

Т.к. у меня виртуальная машина, я пробрасываю в нее свое устройство:

Операционка обнаруживает новое устройство и предлагает установить драйвер:

Нам нужно указать папку в которую распаковались драйвера.

Они должны быть в “Program FilesSTMicroelectronicsVirtual comport driverWin7”. Я не знаю, чем руководствовались парни из STM кидая драйвера от WinXP в папку Win7. Если у вас операционка Win7 или Win8, то в соответствующих папках будут находиться инталяторы для этих операционок, их нужно запустить. А делать так как я показываю, не надо. Это только для Win2000/XP/Vista.

Щелкаем на установку драйвера:

В случае успеха, система выдаст соответствующий репорт:

Теперь устройство можно будет найти в диспетчере устройств:

Теперь можно запустить терминальную программку, чтобы посмотреть на выводимые микроконтроллером через USB данные:

Подключение микроконтроллера STM32F103C8T6 к Android-планшету

Микроконтроллер с USB портом можно подключить не только к стационарному компьютеру, но и Ardroid устройству.

На моем планшете с root-доступом, устройство прекрасно видно:

Скачанная наугад программка usb-терминал, сразу нашла устройство:

прием данных:

В принципе, даже не изучая Java и AndroidStudio, используя лишь NDK, можно написать хороший код для сопряжения Android-девайсов и STM32-микроконтроллеров. Это может дать новую жизнь старым смартфонам и планшетам, которые можно использовать для отображения информации или управления чем-то.

Подключение I2C модуля DS3231

Теперь я снова беру плату с прошитым загрузчиком STM32duino, и попробую сделать, как говориться, без лишней пыли, что-то более полезное чем hello_world, а именно подключить RTC DS3231 через интерфейс I2C.

Микроконтроллер stm32f103c8t6 имеет два аппаратных I2C интерфейса. Дефолтовый интерфейс в Medium_Density чипах висит на пинах PB6 и PB7:

Подключаем модуль к микроконтроллеру:

В Arduno IDE копируем этот скетч, компилируем, загружаем, смотрим на результат работы:

По-моему, проще не бывает)

поделиться:

Источник: http://www.count-zero.ru/2017/bluepill/

ARM. STM32 быстрый старт

Данная статья, которая является еще одним “быстрым стартом” в освоении ARM-контроллеров, возможно поможет сделать первые шаги в освоении 32-битных контроллеров ARM на базе ядра Cortex-M3 – STM32F1xxx серии. Возможно данная статья (которых на эту тему появляется как грибов после дождя) станет для кого-то полезной.

Введение

Почему ARM? 1. Есть из чего выбрать (разными производителями сегодня выпускается более 240 ARM-контроллеров)

2. Низкая цена (например за 1$ можно получить 37хI / O, 16K Flash, 4K RAM, 2xUART, 10x12bitADC, 6x16bitPWM).

А начнем нашу работу с контроллеров фирмы ST Microelectronics. Контроллеры на основе ядра ARM Cortex-M3 характеризуются широким набором периферии, высоким уровнем рабочих характеристик, низкой цене P.S. В самом начале создается впечатление, что ARM'ы это какие-то страшные (в пайке, разводке, программировании) существа. Но это только на первый взгляд 🙂 и вы в этом сами убедитесь.

Итак, изучать ARMы будем на примере контроллеров STM32F1. Одновременно эта серия имеет несколько линеек:

  • Value line STM32F100 – 24 МГц CPU, motor control, CEC.
  • Access line STM32F101 – 36 МГц CPU, до 1 Mб Flash
  • USB access line STM32F102 – 48 МГц CPU with USB FS
  • Performance line STM32F103 – 72 МГц, до 1 Mб Flash, motor control, USB, CAN
  • Connectivity line STM32F105/107 – 72 МГц CPU, Ethernet MAC, CAN, USB 2.0 OTG

Также существует следующая классификация:

[Что нужно для работы и отладки]

1. Установите IAR Embedded Workbench 6.30, это можно сделать на Windows 7 и Windows 8 (к сожалению, Windows XP не поддерживается).

2. Купите на ebay.com китайский J-LINK (строка для поиска JLINK Emulator V8 site:ebay.com).

3. Купите отладочную плату. Замечательный кандидат – STM32-P407 от Olimex (используется микроконтроллер STM32F407ZGT6).

[STM32F407ZGT6 – как сделать новый проект]

В качестве стартовой точки для нового проекта можно просто открыть пример, который предоставлен IAR или Olimex, и начать редактировать и изменять его. Так сделать проще всего, но недостаток в том, что появляются длинные пути к файлам, и название проекта не соответствует Вашему техзаданию.

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

Этот проект будет просто мигать светодиодом.

1. Создание нового проекта C. Создайте в любом удобном месте диска каталог для нового рабочего пространства (workspace). Предположим, это будет каталог MyWorkspace. Запустите IAR 6.30, выберите пункт меню Project – Create New Project…, откроется окно выбора типа нового проекта. Выберите C -> main и нажмите OK.

Далее откроется окно, где предложат выбрать папку для нового проекта и имя файла проекта (файл с расширением *.ewp). Перейдите в папку MyWorkspace, создайте в ней новую папку HelloWorld, зайдите в неё и в поле имени файла введите имя проекта HelloWorld, нажмите кнопку Сохранить.

Выберите в меню IAR пункт File -> Save all. Откроется окно, где будет предложено выбрать папку и имя файла для рабочего пространства (файл с расширением *.eww). Выберите папку MyWorkspace, зайдите в неё, и в качестве имени файла введите MyWorkspace. Затем нажмите Открыть.

После этого действия новый проект будет успешно создан, ему будут присвоены настройки по умолчанию, и будут созданы две новые конфигурации проекта Debug и Release.

Корневой каталог проекта будет MyWorkspaceHelloWorld, а корневой каталог Workspace MyWorkspace (в этот Workspace Вы при желании можете добавлять другие проекты).

В каталоге MyWorkspaceHelloWorldтакже будут созданы подкаталоги Debug (туда по умолчанию попадают выходные и временные файлы результата компиляции), settings (папка для дополнительных настроек проекта), а также будут созданы файлы HelloWorld.dep, HelloWorld.ewd, HelloWorld.ewp и main.c.

2. Настройка проекта. Как ни странно, новый проект будет даже успешно компилироваться (если выбрать Project -> Rebuild all), но это вовсе не означает, что в результате компиляции будет получено именно то, что нам нужно. Необходимо выбрать тип процессора,

Откройте свойства проекта (Project -> Options…), на закладке General Options выберите Processor variant -> Device, нажмите кнопочку справа и выберите процессор ST -> STM32F407 -> STM32F407ZG.

Перейдите в раздел опций Debugger, и в выпадающем списке Driver выберите J-Link/J-Trace (если у Вас подключен именно этот аппаратный отладчик). Нажмите OK.

На этом минимальная настройка проекта закончена, его можно даже запустить в отладчике (Project -> Download and Debug). Но пока проект ничего не умеет, потому что в теле функции main (модуль main.c) нет никакого кода, стоит просто заглушка возврата нулевого значения:

3. Добавление модулей для управления периферией. В состав библиотеки ST есть готовые модули, которые предоставляют удобные макросы и функции для управление периферией микроконтроллера. Не будем выдумывать велосипед, просто давайте воспользуемся этой прекрасной возможностью.

Сделайте копию файла C: Program Files (x86) IAR Systems Embedded Workbench 6.5 arm examples ST STM32F4xx STM32F4xx_DSP_StdPeriph_Lib Project STM32F4xx_StdPeriph_Examples GPIO IO_Toggle stm32f4xx_conf.h, и поместите его в корень проекта, в папку MyWorkspaceHelloWorld.

Добавите в корень проекта HelloWorld новую группу, куда мы будем подключать библиотечные модули для управления периферией. Для этого нажмите правой кнопкой на имя проекта, выберите Add -> Add Group… -> и введите имя группы STM32F4xx_StdPeriph_Driver.

В каталоге рабочего пространства (у нас это папка MyWorkspace) сделайте копию папки Libraries, которую можно найти в папке примеров IAR C: Program Files (x86) IAR Systems Embedded Workbench 6.5 arm examples ST STM32F4xx IAR-STM32F407ZG-SK.

После этого добавьте в папку проекта STM32F4xx_StdPeriph_Driver готовый модуль Libraries STM32F4xx_StdPeriph_Driver src stm32f4xx_gpio.c. Для этого нажмите правую кнопку на папке проекта STM32F4xx_StdPeriph_Driver и выберите Add -> Add Files…

, и выберите нужный файл.

Добавьте в настройки проекта пути поиска для заголовочных файлов. Для этого откройте Project -> Options -> C/C++ Compiler -> закладка Preprocessor, и добавьте в Additional include directories пути поиска:

$PROJ_DIR$ $PROJ_DIR$..LibrariesSTM32F4xx_StdPeriph_Driverinc $PROJ_DIR$..LibrariesCMSISDeviceSTSTM32F4xxInclude $TOOLKIT_DIR$CMSISInclude

Здесь $PROJ_DIR$ макрос, который раскрывает абсолютный путь до папки, в которой находится файл проекта HelloWorld.ewp. Макрос $TOOLKIT_DIR$ раскрывает полный путь до рабочего каталога текущего инструментария IAR (C: Program Files (x86) IAR Systems Embedded Workbench 6.5 arm).

Добавьте в окно Defined symbols символы (они используются в заголовочных файлах):

STM32F40XX USE_STDPERIPH_DRIVER

4. Мигание светодиодом. Давайте сделаем проект более осмысленным – научимся мигать светодиодом STAT1, который установлен на отладочной плате STM32-P407.

Добавьте в папку проекта STM32F4xx_StdPeriph_Driver модуль stm32f4xx_rcc.c (Add -> Add Files…, выберите файл MyWorkspace Libraries STM32F4xx_StdPeriph_Driver src stm32f4xx_rcc.c).

Добавьте код инициализации ядра процессора. Создайте в Workspace группу EWARM (Add -> Add Group… -> введите имя группу EWARM -> OK) и добавьте туда файл startup_stm32f40xx.s (Add -> Add Files… -> выберите файл MyWorkspace Libraries CMSIS Device ST STM32F4xx Source Templates iar startup_stm32f40xx.s).

Также добавьте группу CMSIS, и добавьте туда модуль MyWorkspace Libraries CMSIS Device ST STM32F4xx Source Templates system_stm32f4xx.c.

Откройте файл исходного кода main.c, и замените его старый код на следующий:

/* Простейший пример мигания светодиодом для платы Olimex STM32-P407. Пример мигает светодиодом STAT1. */ #include “stm32f4xx.h”
GPIO_InitTypeDef GPIO_InitStructure;
//Простейшая функция задержки void Delay(__IO uint32_t nCount) { while(nCount–) {} } void main() { /* Разрешить тактирование GPIOF */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); /* Конфигурирование ножки PF6, туда подключен светодиод STAT1      платы разработчика Olimex STM32-P407 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOF, &GPIO_InitStructure); /* Бесконечный цикл мигания */ while(1) { GPIOF->BSRRL = GPIO_Pin_6; //STAT==1, светодиод горит Delay(3000000L); GPIOF->BSRRH = GPIO_Pin_6; //STAT==0, светодиод погас Delay(3000000L); } }

Светодиод STAT1 подключен к порту PF6 микроконтроллера (см. схему в архиве [2]).

Примечание: есть на мой взгляд некая несуразица в именовании регистров BSRRL и BSRRH, предназначенных для управления состоянием портов GPIO. Ведь по идее L значит Low, т. е. лог. 0, а H означает High, т. е. логическую единицу.

Но здесь почему-то происходит все с точностью до наоборот – установка бита в регистре BSRRL почему-то приводит не к сбросу порта в 0, а в установку его в 1. Аналогично установка бита в регистре BSRRH почему-то приводит не к установке порта в 1, а к его сбросу в 0.

Запись 0 никакого влияния на состояние порта не оказывает.

[Работа с портами ввода/вывода GPIO, примеры IOToggle и JTAG_Remap]

Запустите IAR 6.30, на стартовой странице выберите EXAMPLE PROJECTS -> ST -> STM32F4xx -> CMSIS and STM32F4xx stdperiph lib 1.1.0 -> GPIO, далее выберите папку, куда будет копирован пример. Откроется окно Workspace, где будет два примера работы с портами ввода-вывода: “IOToggle – STM324x7I_EVAL” и “JTAG_Remap – STM324x7I_EVAL”.

Порты GPIO подключены к шине микроконтроллера AHB. С использованием регистров BSRRH и BSRRL требуется только один цикл, чтобы установить в лог. 1 любой вывод микроконтроллера, и еще 1 цикл чтобы сбросить в его 0. Таким образом, ножки GPIO можно переключать с частотой шины AHB, поделенной на 2.

В этих примерах показывается, как использовать BSRRH и BSRRL (аббревиатуры расшифровываются как Port Bit Set/Reset Register High and Low) для переключения выводов IO.

Порты PG6 и PG8 (сконфигурированные в режиме output pushpull) переключаются в бесконечном цикле:- PG6 и PG8 устанавливаются в лог. 1 путем установки соответствующих бит в регистре BSRRL.

– PG6 и PG8 сбрасываются в лог. 0 путем установки соответствующих бит в регистре BSRRH.

В этом примере HCLK сконфигурирована на 168 МГц, так что PG6 и PG8 переключаются с частотой 84 МГц (на плате STM324xG-EVAL/STM32437I-EVAL туда подключены светодиоды LED1 и LED2). Чтобы достичь максимально возможной частоты переключения IO, опции Вашего компилятора должны быть сконфигурированы на максимальную оптимизацию по скорости.

Таблица 1. Содержимое папок примера GPIO IO Toggle.

GPIO/IOToggle/stm32f4xx_conf.h Файл конфигурации библиотеки.
GPIO/IOToggle/stm32f4xx_it.c Обработчики прерывания.
GPIO/IOToggle/stm32f4xx_it.h Заголовочный файл для stm32f4xx_it.c.
GPIO/IOToggle/main.h Заголовочный файл для main.c.
GPIO/IOToggle/main.c Основная программа.
GPIO/IOToggle/system_stm32f4xx.c Системный файл кода STM32F4xx (настройка тактовой частоты).

Примечание: файл system_stm32f4xx.c сгенерирован автоматически инструментарием конфигурации тактовой частоты (clock configuration tool), и может быть просто откорректирован с учетом Ваших потребностей. Чтобы выбрать другие настройки тактирования, используйте файл STM32F4xx_Clock_Configuration_V1.1.0.xls, предоставленный в апноуте AN3988, доступном на сайте ST [4].

По умолчанию проект настроен на запуск в симуляторе, но его легко можно перенастроить на загрузку через JTAG, и он будет работать на реальном железе (Options -> Debugger -> в выпадающем списке выберите J-Link/J-Trace). Проект GPIO IO Toggle можно с успехом использовать как стартовую точку для своих собственных проектов, особенно если Вы только начинаете разбираться с платформой STM32.

Low-density devices STM32F101xx, STM32F102xx, STM32F103xx
Medium-density devices STM32F101xx, STM32F102xx, STM32F103xx
High-density devices STM32F101xx, STM32F103xx
XL-density devices STM32F101xx, STM32F103xx
Connectivity line devices STM32F105xx, STM32F107xx

Придется часто лазить здесь
Еще скажу несколько слов об этом ресурсе. Ясное дело, выбираем нужный контроллер и попадаем на страницу с кучей файлов в формате. рdf. (вкладка Design support).

Можно читать все, но достаточно ознакомиться с такими файлами: 1. REFERENCE MANUAL (содержит полную спецификацию на контроллер). 2.

ERRATA SHEET (содержит описание ошибок, которые могут возникать при работе с периферией).

3. Остальные документы содержат примеры работы с периферией, вопросы, связанные с программированием, описание некоторых библиотек, а с самого низа страницы можно найти EVARM-проекты демоплат и подобное ПО.

Архитектура

Итак, наш контроллер STM32 содержит в себе Cortex-M3 процессор (M означает серию для бюджетных устройств). Для того, чтобы начать программировать ARMы и не пользоваться только default'ными примерам и настройками нужно иметь представление об их архитектуре.

Для начала: 1) 32-битный МК, выполненный по Гарвардской архитектуре (память программ и данных разделены), 2) имеет несколько отдельных шин и 3-ступенчатый конвейер и более 10 регистров общего назначения, что позволяет выполнять операции параллельно и (большинство) – за один такт.

3) набор инструкций – Thumb-2 (смесь 16 – и 32-битных команд, ориентированный на компиляторы C / C + +).

Рассмотрим упрощенную блок-схему шинной архитектуры STM32:

Архитектура на примере линейки Connectivity devices Итак, давайте коротко пройдемся по основам основ:

Матрица шин (bus matrix) – контроллер высокоскоростных шин, обеспечивающий независимую связь и арбитраж (в случае одновременного доступа к одному ресурсу) между системной шиной и шиной данных ядра, DMA, Ethernet (masters) и периферией – SRAM, FLASH, AHB (slaves) .

Шины ядра:
ICode bus – 32-битная шина инструкций — обеспечивает связь ядра с интерфейсом инструкций Flash.
DCode bus – шина данных — обеспечивает связь ядра с интерфейсом данных во Flash.

System bus – системная шина ядра — обеспечивает связь ядра и периферии
Flash interface (FLITF) интерфейс Flash-памяти — обеспечивает чтение, запись, стирание, чтение с буфером предварительной выборки, защиту памяти (от записи или чтения).

AHB system bus (Advanced High-performance Bus) — шина, которая связывает матрицу шин и периферийные шины APB (Advanced Peripheral Bus (Bridge)). Шина AHB, предназначена для управления, например, регистрами системной периферии (GPIO ЦАП и т.п.).

Надо сказать, что шины APB1,2 работают на разных частотах: так APB2 может работать на частоте ядра, а быстродействие APB1 ограничено 36 МГц. Поэтому, на APB2 и висит скоростная периферия (АЦП, некоторые таймеры порты ввода / вывода и т.д.

Читайте также:  Клон avr jtag ice

)
DMA (Direct Memory Access) — обеспечивает прямой доступ к памяти в обход ядра (нужно лишь задать что, откуда и куда передать, а DMA сам все возьмет и передаст кому надо через матрицу шин)
Reset & Clock Control (RCC) — обеспечивает тактирование ядра и периферии (которая по дефолту отключена от тактового сигнала) и сброс контроллера.

Стандартная схема подключения

И здесь для начинающих возникает вопрос в чем и как рисовать и разводить печатные платы для, например, 144-ногого микроконтроллера (48-ноги еще куда не шло). Однако ничего страшного в рисовании схемы, разводке и пайке данных контроллеров нет.

Для этого можно пользоваться программой Eagle (она содержит библиотеку компонентов ST или в крайнем случае можно поискать в Интернете или скачать внизу статьи), можно попробовать рисовать платы в старом добром Sprint-е (хотя, первый вариант мне кажется более надежным).

Ниже приведены стандартные схемы включения контроллеров семейства Value line STM32F100С4 и Connectivity line STM32F105

Привожу базовую схему подключения контроллеров STM32F1 и некоторые их нюансы:

  1. Корпус: контроллеры STM32 помещены в корпусах LQFP с числом лапок от 48 до 144, при этом распиновка ножек контроллеров в одинаковых корпусах – совпадает, что не может не радовать.
  2. Питание:
    1.  Контроллер питается от источника в 3.3 В (хотя можно подключать 2-3.6 В).
    2. Хотя напряжение питания равно 3.3В, много ножек контроллера толерантны к 5В сигналов (см. в спецификации лапки с пометкой FT).
    3. Vbat – используется для подключения резервного источника питания. Если в схеме резервный источник не используется, то Vbat надо посадить на общий источник питания.
    4. Vdd_1 … 4 подтягиваем к «+», Vss_1 … 4 сажаем на «-» источника питания.
    5. Спецификация на контроллер советует поставить параллельно источнику питания 5 конденсаторов в 100нФ (поближе к контроллеру) и один на 4.7мкФ (ближе к Vdd_3). Во многих схемах авторы часто не ставят их, думаю, если контроллер питается от чистого стабилизированного источника их можно не ставить.
    6. Питание АЦП (он питается напряжением 2,4-3,6 В) и цифровой части схемы в STM32 разделены (для большей надежности, очевидно) и если мы не используем отдельный источник для АЦП, Vdda / Vssa сажаем на соответствующие выводы общего источника, иначе схема может работать некорректно и непредсказуемо. В 100-пиновых корпусах есть еще дополнительные лапки опорного источника АЦП Vref + / Vref-. Vref- нужно повесить на Vdda, а на Vref + можно бросить от 2,4 В до Vdda.
  3. Резонатор. STM32 может тактироваться от:
    1. Внутреннего высокочастотного генератора на 8 МГц (HSI).
    2. Внутреннего низкочастотного источника тактовых импульсов 40 кГц (LSI).
    3. Внешнего высокочастотного осциллятора (HSE).
    4. Внешнего низкочастотного осциллятора на 32,768 кГц (LSE-генератор может работать вместе с HSE или синхросигналом и обеспечивает синхронизацию часов реального времени и работу оконного сторожевого таймера).
    5. Внешнего сигнала синхронизации (его частота должна быть целым делителем максимальной рабочей частоты контроллера).
  4. Сброс контроллера можно провести:
    1. «заземлив» лапку NRST. Стоит сказать, что разработчик постарался и уже включил подтягивающий резистор этой лапки. (external reset)
    2. С помощью одного из сторожевых таймеров независимого или оконного (IWDG или WWDG reset).
    3. С помощью схемы слежения за низким напряжением (low-power management reset)
    4. при входе в режим Standby
    5. при входе в режим Stop
    6. Программно – установкой определенного бита

Для удобства пайки LQFP корпусов, существуют переходники. Продаются на eBay, бывают универсальные и под фиксированное количество ножек. Средняя цена: 1$ за штуку, посмотреть можно здесь.

Программирование. Отладка

BOOT1 BOOT0 Boot mode
X Flash память
1 Системная память (bootloader)
1 1 Память SRAM

Контроллеры STM32 можно заставить загружаться с 3-х областей памяти (в зависимости от состояния ножек BOOT0 и BOOT1 при старте контроллера или после его сброса). Записать программу в память контроллера можно следующими способами:

1 способ:
Используя загрузчик (он уже записан в системную память) и USART1 (USART2 remaped): использует внутренний тактовый сигнал 8 МГц.

Чтобы запустить встроенный загрузчик, зашитый в контроллер производителем, достаточно просто бросить на лапки контроллера TX1, RX1 сигнал с преобразователя RS232-3.

3В (например на базе FT232RL) и выставить перед этим BOOT0 = 1 и BOOT1 = 0 жмем RESET и можем шить программу в контроллер. А зашивается она в программе Flash Loader Demonstartor от STM (для Windows).

PS. Если вы сидите под LINUX и не имеете отладочной платы типа дискавери, можно заливать прошивку в контроллер через всеми любимый rs-232 (собственно — через преобразователь rs-232-3,3В). Для этого нужно использовать python-скрипт (Ivan A-R) (для LINUX или MACOSX).

Для начала у вас должен быть установлен Python 2.6 версии и библиотека для работы с последовательным портом — PySerial library. Теперь, чтобы запустить скрипт stmloader.py (из терминала, разумеется) нужно его немного подправить под свой компьютер: откроем его в текстовом редакторе.

Набираем в командной строке

~$ dmesg | grep tty

чтобы увидеть все последовательные порты ПК. и после набора…

 ~$ setserial -g /dev/ttyS[0123]

мы узнаем путь к нашему 232-му порту. Если система ругается на setserial, установим его

~$ sudo apt-get install setserial

мы узнаем путь к нашему физическому порту (например, у меня — /dev/ttyS0). Теперь нужно записать этот путь в файл скрипта stm32loader.py вместо дефолтного «/dev/tty.usbserial-…». Набираем в терминале

~$ python stm32loader.py -h

…для вызова справки и заливаем прошивку в наш контроллер.

2 способ:
Через USB OTG, используя DFU-режим, требует внешнего кварца на 8 МГц, 14.7456 МГц или 25 МГц (этот загрузчик есть не у всех контроллерах с USB OTG надо внимательно смотреть на маркировку вашего контроллера)

3 способ:
JTAG/SWD. Ну и для тех, кто имеет демоплату типа Discovery или самопальный JTAG/SWD программатор, можно заливать код и уже отлаживать свой микроконтроллер этим способом. Для JTAG в микроконтроллере отведено 6 лапок (TRST, TDI, TMS, TCK, TDO, RST) + 2 на питание. SWD использует 4 сигнала (SWDIO, SWCLK SWO, RESET) и 2 на питание.

PS. В среде EAGLE я набросал несколько схем-заготовок для 48-ми, 64-х и 100-ногих контроллеров (папка eagle), а stm32loader содержит скрипт stm32loader.py

Прикрепленные файлы:

Источник: http://cxem.net/mc/mc143.php

STM32-VLDiscovery: мой вариант быстрого старта

Внимание, статья обновлена. См. примечание в конце. ***

Предисловие.

Некоторое время назад, я, как и многие другие, принял участие в акции EBV, заказав себе упомянутую в названии платку. Моя первая попытка поковырять ее не увенчалась успехом, да и буквально одновременно с ней мне в руки попал LaunchPad… Одним словом, лежал STM32-Discovery буквально до сегодняшнего дня и пылился.

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

Однако, несмотря на большое количество статей, все они показались мне слишком разрозненными, а некоторые из более цельных — излишне объемными для начала. Возможно, я плохо искал, но так нигде и не нашел текста, прямо и без тучи лишней информации повествующего о том, как с нуля помигать светодиодом на STM32-Discovery.

Полезные части встречались в разных местах, и вот я решил объединить их в по возможности лаконичное и законченное повествование.

Создание и настройка проекта.

Итак, что мы имеем: микроконтроллер STM32F100RB, установленный на плате с отладчиком; два светодиода, подключенных к PC8 (синий) и PC9 (зеленый). В качестве инструмента для написания кода я выбрал IAR.

Задача: помигать ими, попутно разобравшись, как настроить проект в IAR, что такое CMSIS и как в этих условиях организуется доступ к периферии. Итак, наченем. Быстро и в картинках.

Запускаем IAR:Создаем новый проект:Просим IAR самостоятельно написать шаблон для main() и сохраняем:
И теперь начинается самое интересное – надо настроить опции проекта, чтобы у оного был шанс заработать.

Если для AVR настройки проекта трогать почти не приходилось, для MSP430 дело ограничивалось небольшим вмешательством, то здесь все будет более глобально.Первое, что нужно сделать – указать тип используемого контроллера. Как уже говорилось, в STM32-Discovery стоит STM32F100RB.

Далее надо поправить настройки линковщика. В них надо указать начало таблицы векторов прерываний, а также начало и конец областей памяти программы (ROM) и оперативной памяти (RAM). Рассчитываются они следующим образом: в STM32F100RB 128Kb памяти кода и 8Kb оперативной памяти.

Начало у этих областей фиксировано на всей линейке – 0x08000000 (INTVEC) 0x08000000 (ROM) и 0x20000000 (RAM). Нам надо посчитать конечные адреса областей. Очевидно, что они получаются по следующей формуле:

[начало области] + ([размер области в килобайтах] * 1024) — 1.

Для STM32F100RB соответственно:

ROM: 0x08000000 + (0x80 * 0x400) — 1 = 0x0801FFFF
RAM: 0x20000000 + (0x8 * 0x400) — 1 = 0x20001FFF

Стек и кучу пока трогать не будем. Действуем: ставим галку Override default, жмем Edit…Вводим значения:
Жмем Save, сохраняем конфиг:С линковщиком все. Теперь надо настроить отладчик, чтобы при попытке запуска программы IAR подключался к ST-LINK на плате Discovery.

Выбираем отладчиком ST-LINK:Для корректной работы на следующей вкладке ставим галку Use flash loader:И далее указываем режим SWD:Все. Проект настроен, жмем OK. Теперь надо подключить CMSIS.

Что такое CMSIS, и вообще для чего она нужна? Каждый, кто уже писал под какой-нибудь МК, знает, что, прежде чем писать код, очень полезно подключить специальный заголовочный файл, в котором описаны имена регистров, модулей, констант и прочие обозначения, используемые в документации – без всего этого написание кода отдает мазохизмом. Естесственно, тут надо сделать то же самое. Только вместо одного файла надо добавить в проект шесть. Вот эти шесть файлов и есть CMSIS. Почему так много? Дело в том, что многие вещи, которые для, например, MSP430 компилятор генерирует сам – стартовый код, таблица прерываний, и т.п. здесь нужно писать руками. А этого делать, разумеется, неохота. Вот все это и входит в CMSIS.

Где добыть CMSIS? Для этого качаем STM32VLDISCOVERY firmware package – там все есть. Распаковываем, находим в stm32vldiscovery_packageLibraries папку CMSIS – это оно. Еще там есть папка STM32F10x_StdPeriph_Driver – этого добра нам не надо. В этой папке лежит т.н. стандартный драйвер периферии, представляющий собой набор функций для тех, кому лень читать даташит. Нас же, повторюсь, интересует исключительно CMSIS. Итак, нам нужны следующие файлы:

stm32vldiscovery_packageLibrariesCMSISCM3CoreSupportcore_cm3.c stm32vldiscovery_packageLibrariesCMSISCM3CoreSupportcore_cm3.h tm32vldiscovery_packageLibrariesCMSISCM3DeviceSupportSTSTM32F10xsystem_stm32f10x.c

tm32vldiscovery_packageLibrariesCMSISCM3DeviceSupportSTSTM32F10xsystem_stm32f10x.h

— собственно, сама CMSIS

tm32vldiscovery_packageLibrariesCMSISCM3DeviceSupportSTSTM32F10xstm32f10x.h

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

stm32vldiscovery_packageLibrariesCMSISCM3DeviceSupportSTSTM32F10xstartupiarstartup_stm32f10x_md_vl.s

— код начальной инициализации микроконтроллера. На будущее отмечу, что файл system_stm32f10x.c содержит функцию SystemInit(), которая вызывается до main() и проводит первичную настройку. Изначально там содержится код настройки системы тактирования. Пока необходимости что-либо менять там нет. Все перечисленные файлы кидаем в директорию проекта и добавляем в него:

Эстеты могут разложить их все по красивым папочкам, это дела не меняет.

Теперь последний шаг – небольшое допиливание CMSIS напильником. В начале файла stm32f10x.h надо раскомментировать дефайн, соответствующий используемому контроллеру. Для нас это #define STM32F10X_MD_VL, ибо STM32F100RB отностися к Medium density Value Line devices. Но не только раскомментировать нужный дефайн, но и закомментировать ненужный — #define STM32F10X_XL !

Все! Теперь действительно можно писать код!

Первая программа.

Для начала я предлагаю написать простую программу, которая будет перемигиваться синим и зеленым светодиодами. Для этого из конфигурационных действий нам надо выполнить только одно – настроить порт. Блоки периферии в STM32 имеют количество конфигурационных регистров, поражающее воображение человека, пришедшего с не настолько продвинутых платформ. Порты также не являют собой исключения, но в данный момент нам понадобятся только следующие регистры: GPIOC_CRH, (настройка на ввод-вывод, настройка скорости работы), GPIOC_ODR (собственно, сам выходной регистр порта) и RCC_APB2ENR. Вообще говоря, RCC_APB2ENR не относится к регистрам порта – это регистр системы тактирования. Но у периферии STM32 есть одна особенность – она не заработает (!), пока для нее не будет явно включено тактирование. В упомянутом же регистре расположен бит, отвечающий за порт C. Несколько слов о доступе к регистрам, он организован несколько необычно. Блоки периферии здесь представлены в виде структур, полями которых как раз и являются регистры. Как по мне, решение чрезвычайно необычное, но, по крайней мере, не вызывающее особого дискомфорта, и, в каком-то смысле, даже логичное. Итак, собственно программа (подробности относительно записываемых значений можно найти в даташите):#include “stm32f10x.h” void main(void) { unsigned long d; //Enabling clock for GPIOC RCC->APB2ENR|=RCC_APB2ENR_IOPCEN; //Configuring GPIO8 and GPIO9 as push-pull output //refer to datasheet for details GPIOC->CRH&=~(GPIO_CRH_CNF8_0 | GPIO_CRH_CNF9_0); GPIOC->CRH|=(GPIO_CRH_MODE8_1 | GPIO_CRH_MODE9_1); while (1) { //switching the LEDs if (GPIOC->ODR & GPIO_ODR_ODR8) { GPIOC->ODR&=~GPIO_ODR_ODR8; GPIOC->ODR|=GPIO_ODR_ODR9; } else { GPIOC->ODR|=GPIO_ODR_ODR8; GPIOC->ODR&=~GPIO_ODR_ODR9; } //simple delay for (d=0; d

Источник: http://we.easyelectronics.ru/blog/STM32/469.html

Быстрый старт STM32F103C8T6 + Arduino IDE

Подробности Создано: 25 февраля 2016

Отладочная плата F103C8T6 на базе STM32 по параметрам значительно опережает аналогочные по размеру Arduino Nano или Leonardo, а по скорости близка к Arduino DUE. Есть интерес попробовать, но у новичка могут возникнуть трудности с первым запуском и программированием данной платы. Теперь есть возможность заливать скетчи через Arduino IDE. Подробности далее…

Содержание

1. Отличия STM32F103C8T6 от Arduino Nano v3.0

STM32F103C8T6ArduinoNano v3.0
Частота ядра 72 МГц 16 МГц
Память для кода (Flash) 64 кбайта 32 кбайта
Память для переменных ОЗУ (SRAM) 20 кбайт 2 кбайта
Рабочее напряжение 3.3В
Память EEPROM отсутствует, но существуютпрограммные эмуляторы 1 кбайт

2. Подготовка железа

Для работы нам понадобится:

Для активации режима программирования на плате STM следует преставить перемычки: первая на 1, вторая на 0.

Конвертер FTDI переключить на питание 3.3 Вольта (перемычкой/джампером)

Соединить проводами плату (П) и конвертер (К):

П(A9) -> K(RX)

П(А10) -> К(TX)

П(GND) -> K(GND)

П(3.3) -> K(VCC)

3. Подготовка ПО

  1. Скачать дополнение для Arduino IDE, которое будет поддерживать платы STM32
  2. Распаковать архив в папаку HARDWARE, которую можно найти в папке вашей Arduino IDE
  3. Запустить Arduino IDE (или перезапустить если была открыта) и проверить появился ли раздел STM32 Boards в списке Плат

4. Закачка скетча (blink) в плату

В папке которую мы распаковали в п.3.б заходим по следующему пути: Arduino_STM32examplesDigitalBlink  и через Arduino IDE открываем файл blink.ino либо можете взять текст отсюда:

void setup() {  // initialize digital pin PB1 as an output.  pinMode(PC13, OUTPUT); } // the loop function runs over and over again forever void loop() {  digitalWrite(PC13, HIGH);   // turn the LED on (HIGH is the voltage level)  delay(1000);              // wait for a second  digitalWrite(PC13, LOW);    // turn the LED off by making the voltage LOW  delay(1000);              // wait for a second }

Далее в Arduino IDE:

  • Выбрать плату Generic STM32F103C series
  • Выбрать Variant: (20k RAM. 64k Flash)
  • Выбрать Upload method: “Serial”
  • Выбрать Порт: (порт сооответствующий FTDI конвертеру)

Жмем кнопку Вгрузить и результат сразу должен быть виден.

Источник: http://www.2150692.ru/faq/112-quick-start-stm32f103c8t6

Программирование ARM-контроллеров STM32 на ядре Cortex-M3. Часть 4. Регистры, старт и режимы работы контроллеров STM32

Понимаю, что статья уже получилась довольно длинной и всем хочется поскорее написать какую-нибудь программулину, делающую хоть что-то полезное, и залить её в контроллер, но так уж вышло, что контроллеры STM32 несколько сложнее простейших восьмибитных железяк, поэтому сейчас речь снова пойдёт, как пишут некоторые нетерпеливые читатели, «не о том».

В этой части мы поговорим о том, с чем нам чаще всего придётся оперировать при работе с контроллером — о рабочих регистрах ядра Cortex-M3, о режимах его работы и о том, как контроллер включается.

Итак, в ядре Cortex-M3 имеется 13 регистров общего назначения — R0..R12, регистр, используемый для хранения указателя стека, — R13, регистр связи — R14, счётчик команд — R15 и 5 регистров специального назначения.

Регистры общего назначения разделяются на младшие регистры — R0..R7 и старшие регистры — R8..R12. Разница между ними в том, что некоторые 16-тибитные команды набора thumb-2 умеют работать только с младшими регистрами, а со старшими — не умеют.

Регистров R13 вообще-то говоря два, а не один. Первый называется MSP — указатель основного стека, а второй PSP — указатель стека процесса. Однако в каждый момент доступен только один из этих регистров. Какой именно — определяется в одном из регистров специального назначения.

Зачем такое надо? Это сделано для возможности организации защиты операционной системы (ага, на этот контроллер можно поставить ОС, если хочется) от кривых прикладных программ.

MSP используется обработчиками исключительных ситуаций и всеми программами, использующими привилегированный уровень выполнения (например ядро ОС), а PSP — используется программами, не требующими привилегированного уровня выполнения (например, прикладными программами от которых мы хотим защитить ядро ОС). Указатели стека всегда должны быть выровнены на границу 32-хбитного слова, т.е. два их младших бита всегда должны быть сброшены в ноль.

Регистр R14 называется LR (link register) — регистр связи и используется для запоминания адреса возврата при вызове подпрограмм.

Регистр R15 называется PC (program counter) — счётчик команд и используется для хранения адреса текущей выполняемой команды.

Теперь о специальных регистрах.

Регистр xPSR содержит флаги результатов выполнения арифметических и логических операций, состояние выполнения программы и номер обрабатываемого в данный момент прерывания. Иногда об этом регистре пишут во множественном числе.

Это сделано потому, что к трём его частям можно обращаться как к отдельным регистрам.

Эти «подрегистры» называются: APSR — регистр состояния приложения (тут как раз хранятся флаги), IPSR — регистр состояния прерывания (содержит номер обрабатываемого прерывания) и EPSR — регистр состояния выполнения. Полностью структура регистра xPSR приведена на рисунке ниже.

Флаги в регистре APSR стандартные:

  1. N (negative flag) — отрицательный результат операции
  2. Z (zero flag) — нулевой результат операции
  3. C (carry flag) — флаг переноса/займа
  4. V (overflow flag) — флаг переполнения
  5. Q (saturation flag) — флаг насыщения

В регистре PRIORITY MASK используется только нулевой бит (PRIMASK), который будучи установлен в единицу запрещает все прерывания с конфигурируемым приоритетом. После включения бит PRIMASK сброшен в ноль — все прерывания разрешены.

В регистре FAULT MASK также использует только нулевой бит (FAULTMASK), который будучи установлен в единицу запрещает все прерывания и исключения, кроме немаскируемого прерывания (NMI). После включения бит FAULTMASK сброшен в ноль — все прерывания разрешены.

Регистр BASEPRI используется для запрещения всех прерываний, значение приоритета которых больше или равно, чем записано в этом регистре. Тут надо сказать, что чем меньше значение — тем выше уровень приоритета. В регистре BASEPRI используются только младшие 8 бит.

Регистр CONTROL используется для управления одним из режимов процессора — режимом потока.

Нулевой бит этого регистра (nPRIV) определяет уровень выполнения (привилегированный — Privilegied, или непривилегированный — Unprivilegied), а первый бит (SPSEL) — используемый указатель стека (MSP или PSP).

Разница между привилегированным и непривилегированным уровнями выполнения состоит в том, что для привилегированного уровня доступны все области памяти и все команды процессора, а для непривилегированного уровня некоторые области памяти закрыты (например, регистры специального назначения, кроме APSR, системная область) и, соответственно, команды для доступа в эти обасти — запрещены. Попытка выполнения запрещённых команд, пытающихся обратиться в закрытые области памяти вызывает генерацию исключения отказа.

Теперь о режимах работы процессора.

Процессор Cortex-M3 имеет два режима работы: режим потока (Thread) и режим обработчика (Handle). Режим Handle используется для обработки исключительных ситуаций, а режим Thread — для выполнения всего остального кода. Переключение из одного режима в другой происходит автоматически.

Как мы уже говорили, когда разбирались с регистром CONTROL, в режиме Thread процессор может использовать как привилегированный уровень выполнения, так и непривилегированный, в режиме Handle — только привилегированный.

Аналогично, в режиме Thread может использоваться как основной стек (MSP), так и стек процесса (PSP), а в режиме Handle — только основной стек.

Важно понимать, что, например, переключившись в режиме Thread с привилегированного уровня в непривилегированный, мы потеряем доступ в регистр CONTROL и обратно сможем переключиться только в режиме Handle. В режиме Handle бит nPRIV регистра CONTROL доступен для чтения/записи, но не влияет на текущий режим выполнения.

Это позволяет изменить уровень выполнения, который будет у программы, когда процессор выйдет из режима обработчика в режим потока. Бит SPSEL в режиме Handle для записи недоступен и всегда читается как ноль, а при выходе из режима обработчика в режим потока восстанавливается автоматически.

Все варианты переходов между различными режимами и уровнями выполнения иллюстрирует ориентированный граф, представленный на рисунке ниже:

Далее поговорим о том, как контроллер стартует.

Стартует контроллер всегда на внутреннем генераторе, на частоте 8 Мгц. Откуда брать тактовый сигнал в дальнейшем, на сколько его умножать или делить — настраивается в программе. Если в программе этого не сделать, то хоть десять внешних кварцев повесьте, контроллер так и будет работать от внутреннего генератора 8 МГц.

При старте контроллер анализирует сочетание уовней на двух своих ногах — BOOT0, BOOT1, и, в зависимости от этого сочетания, начинает загрузку либо из flash-памяти, либо из ОЗУ, либо из системной области памяти. Это делается с помощью уже описанного нами ранее механизма псевдонимизации.

По идее загрузка всегда начинается с нулевого адреса, просто в зависимости от
сочетания на ногах BOOT0, BOOT1 начальные адреса памяти назначаются псевдонимами одной из трёх областей: flash, встроенного ОЗУ или системной области.

Справа приведена табличка, в которой указано, какая именно область проецируется в начальные адреса памяти в зависимости от сочетания ног BOOT0, BOOT1.

При этом в системной области производителем зашита специальная программа (bootloader), которая позволяет запрограммировать flash-память. Но об этом позже.

Первым делом контроллер считывает 32-х битное слово по адресу 0x00000000 и помещает его в регистр R13 (указатель стека). Далее он считывает 32-х битное слово по адресу 0x00000004 и помещает его в регистр R15 (счётчик команд). Последнее действие вызывает переход на начало программного кода и дальше начинается выполнение программы.

Слово по адресу 0x00000004 (адрес начала основной программы) называется вектор сброса.

Вообще в памяти контроллера после указателя стека по адресу 0x00000000, начиная с адреса 0x00000004 должна лежать таблица векторов исключений и прерываний, первый вектор в которой — это вектор сброса, а остальные вектора — адреса процедур обработчиков различных исключений и прерываний.

В простейших программах, если вы не собираетесь обрабатывать исключения и прерывания, все остальные вектора, кроме вектора сброса, могут отсутствовать. Хотелось бы обратить внимание, что в таблице векторов указываются именно адреса начала обработчиков, а не команды перехода на эти обработчики, как, например, в 8-ми битных пиках или атмелах.

Надеюсь понятно, что если ногами BOOT0, BOOT1 начальная область памяти установлена псевдонимом, например, flash-памяти, то считывание по адресу 0x00000000 реально приведёт к считыванию адреса 0x08000000 (начало flash-памяти), а считывание адреса 0x00000004 — к считыванию адреса 0x08000004 и так далее.

Ну и в завершение скажу, что стартует контроллер всегда в режиме потока с привилегированным уровнем выполнения.

Источник: http://radiohlam.ru/?p=1345

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}