8-900-374-94-44
[email protected]
Slide Image
Меню

Программирование stm32f4discovery: STM32F4DISCOVERY — знакомство с возможностями

Мигаем светодиодом (Версия для STM32F4 Discovery, Оптимизация) (Часть 3) / Хабр

Ну что же, новогодние праздники кончились, и начались трудовые будни 🙂 Продолжим разбираться с ассемблером на примере микроконтроллера STM32F4

Обсуждение статьи доступно на платформе VK: vk.com/topic-200545792_46642025

Ссылки на прошлые публикации:
STM32F4: GNU AS: Программирование на ассемблере (Часть 1)
STM32F4: GNU AS: Мигаем светодиодом (Оживление) (Часть 2)

В комментариях никто не отписался о том что ему удалось запустить «мигалку» на STM32F4 Discovery — значит либо не пробовали, либо не удалось. Исправим эту мелочь:

1) Как я уже писал в прошлой публикации для нашего примера разница между моей отладочной платой и STM32F4 Discovery фактически только в других выводах к которым подключены светодиоды. То есть используется другой порт GPIOx и другой выход этого порта.
Узнать куда же все таки подключены светодиоды можно из документации. Я использовал Discovery kit for STM32F407/417 lines.

Информация о подключениях есть как минимум в трех местах:

  1. в параграфе 4.4 LEDs, стр. 16
  2. в таблице с названием Table 5. MCU pin description versus board function стр. 21-32, нужная нам информация на стр. 30
  3. на листе Figure 16. Peripherals, стр. 40

Таким образом все становиться очевидным «до противного»: 4 светодиода подключены к GPIOD выводам 12, 13, 14, 15.
Как говорится выбираем любой, пусть в «мигалке» используется светодиод синего цвет подключенный к GPIOD 15

2) Изменяем программу для использования GPIOD (вместо GPIOH) и вывода 15 (вместо 2)
Первое что мы должны сделать — это включить тактирование GPIOD, тут даже не буду делать новый скриншот, новое значение для настройки есть на старом:

выделено значение для GPIOH

, а для GPIOD нужно использовать: RCC_AHB1ENR_GPIODEN — разница с уже написанным кодом программы ранее в одной букве!!!

Reset:
		@ включим тактирование GPIOD
		MOV32	R0, PERIPH_BASE + RCC_BASE + RCC_AHB1ENR  @ адрес
		MOV32   R1, RCC_AHB1ENR_GPIODEN                   @ значение
		LDR	R2, [R0]       @ прочитали значение регистра
		ORR	R1, R1, R2     @ логическое, побитовое ИЛИ: R1= R1 ИЛИ R2
		STR	R1, [R0]       @ запись R1 по адресу указанному в R0

Теперь необходимо провести настройку вывода 15 GPIOD на выход: тут мы делаем небольшое такое «открытие» — дело в том что каждый GPIO настраивается одним и тем же набором регистров с одними и теми же значениями(!), и именно этим вызвана такая «странная» на первый взгляд конструкция вычисления адреса того или иного регистра
Фактически вместо константы с именем GPIO_MODER_MODER2_0 используем GPIO_MODER_MODER15_0 и не забываем в расчете адреса регистра MODER

указывать смещение GPIOD_BASE (раньше там стояло GPIOH_BASE)

		@ установим режим вывода 15 порта GPIOD "на выход"
		MOV32	R0, PERIPH_BASE + GPIOD_BASE + GPIO_MODER  @ адрес
		MOV32   R1, GPIO_MODER_MODER15_0                   @ значение
		LDR	R2, [R0]       @ прочитали значение регистра
		ORR	R1, R1, R2     @ логическое, побитовое ИЛИ: R1= R1 ИЛИ R2
		STR	R1, [R0]       @ запись R1 по адресу указанному в R0

Аналогичным образом изменяются блоки собственно самого «мигания»: изменяем базу GPIO на GPIOD_BASE (вместо GPIOH_BASE), и в двоичном виде формируем код на включение выключение соответствующего вывода порта, повторюсь: для включения используются младшие 16 бит слова, для выключения старшие 16 бит, нумерация выводов портов идет от 0, поэтому самый старший 15 бит по «счету» будет 16-ым

BLINK_LOOP:
		@ включим светодиод
		MOV32	R0, PERIPH_BASE + GPIOD_BASE + GPIO_BSRR  @ адрес
		MOV32   R1, 0x8000    @ значение в двоичном виде 1000 0000 0000 0000
		STR	R1, [R0]      @ запись R1 по адресу указанному в R0
	
		BL	DELAY         @   пауза
	
		@ выключим светодиод
		MOV32	R0, PERIPH_BASE + GPIOD_BASE + GPIO_BSRR  @ адрес
		MOV32   R1, 0x8000 << 16   @ значение во второе полуслово
		STR	R1, [R0]           @ запись R1 по адресу указанному в R0

Остальная часть программы остается без изменений

Программа полностью

@GNU AS
@ Настройки компилятора
. syntax unified   @ тип синтаксиса
.thumb            @ тип используемых инструкций Thumb
.cpu cortex-m4    @ микроконтроллер
.include "stm32f40x.inc"   @ определения микроконтроллера
@ макрос псевдокоманды MOV32
.macro	MOV32 regnum,number
	MOVW \regnum,:lower16:\number
	MOVT \regnum,:upper16:\number
.endm
@ таблица векторов прерываний
.section .text
.word	0x20020000	@ Вершина стека
.word	Reset+1		@ Вектор сброса
Reset:
		@ включим тактирование GPIO_D
		MOV32	R0, PERIPH_BASE + RCC_BASE + RCC_AHB1ENR  @ адрес
		MOV32   R1, RCC_AHB1ENR_GPIODEN                   @ значение
		LDR	R2, [R0]    @ прочитали значение регистра
		ORR	R1, R1, R2  @ логическое, побитовое ИЛИ: R1= R1 ИЛИ R2
		STR	R1, [R0]    @ запись R1 по адресу указанному в R0
		@ установим режим GPIO_D pin_15
		MOV32	R0, PERIPH_BASE + GPIOD_BASE + GPIO_MODER  @ адрес
		MOV32   R1, GPIO_MODER_MODER15_0                   @ значение
		LDR	R2, [R0]    @ прочитали значение регистра
		ORR	R1, R1, R2  @ логическое, побитовое ИЛИ: R1= R1 ИЛИ R2
		STR	R1, [R0]    @ запись R1 по адресу указанному в R0
BLINK_LOOP:
		@ включим светодиод
		MOV32	R0, PERIPH_BASE + GPIOD_BASE + GPIO_BSRR   @ адрес
		MOV32   R1, 0x8000  @ значение 1000 0000  0000 0000
		STR	R1, [R0]    @ запись R1 по адресу указанному в R0
	
		BL	DELAY       @  пауза
	
		@ выключим светодиод
		MOV32	R0, PERIPH_BASE + GPIOD_BASE + GPIO_BSRR  @ адрес
		MOV32   R1, 0x8000 << 16  @ значение 
		STR	R1, [R0]          @ запись R1 по адресу указанному в R0
		BL	DELAY       @  пауза	
		B	BLINK_LOOP  @ делаем цикл
DELAY:
		MOV32	R2, 0x00100000    @ повтор цикла 0x0010 0000 раз.
Delay_loop: SUBS R2, R2, 1 BNE Delay_loop BX LR

скачать проект (Кто проверит на STM32F4 Discovery «+1» в репутацию от меня (у меня платы STM32F4 Discovery нет)

я надеюсь что после этих примеров вопросов как создать «мигалку» на любое другое подключение светодиодов к микроконтроллеру STM32F4xx у вас не возникнет.


Теперь стоит вникнуть что же все таки у нас получилось с точки зрения сгенерированного файла прошивки.

В новом проекте применяется немного усовершенствованный скрипт компиляции и сборки проекта, например в каталоге /compile/temp вы можете увидеть не только файлы компиляции c расширением «.о» и файл прошивки «.elf», но и справочные:
  1. labels.lst — файл с описанием всех меток с их значениями после сборки компоновщиком (раньше я его называл линковщиком)
  2. sections.lst — файл с описанием секций проекта
  3. main_text.lst — файл скомилированных исходников секции . text

В основном, когда что-то идет не так как хотелось бы, я использую файлы labels.lst — для проверки значений констант, адресов меток, и main_text.lst для контроля за сгенерированным кодом прошивки

Теперь давайте посмотрим, как же выглядит наша программа на этапе компиляции после того как ее обработал компилятор и компоновщик

Первым блоком идет указание меток программы, как я уже говорил во второй публикации — код ARM всегда переносимый, поэтому адреса всегда указываются относительные (относительно

PC)

compile\temp\sys.o:     file format elf32-littlearm
SYMBOL TABLE:
00000000 l    d  .text	00000000 .text
00000008 l       .text	00000000 Reset
00000038 l       .text	00000000 BLINK_LOOP
00000066 l       .text	00000000 DELAY
0000006e l       .text	00000000 Delay_loop

Блок векторов прерываний, в наших программах он идет вначале секции .text

Disassembly of section .text:
00000000 <Reset-0x8>:
   0:	20020000 	. word	0x20020000
   4:	00000009 	.word	0x00000009

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

00000008 <Reset>:
   8:	f643 0030 	movw	r0, #14384	; 0x3830
   c:	f2c4 0002 	movt	r0, #16386	; 0x4002
  10:	f240 0108 	movw	r1, #8
  14:	f2c0 0100 	movt	r1, #0
  18:	6802      	ldr	r2, [r0, #0]
  1a:	ea41 0102 	orr.w	r1, r1, r2
  1e:	6001      	str	r1, [r0, #0]
  20:	f640 4000 	movw	r0, #3072	; 0xc00
  24:	f2c4 0002 	movt	r0, #16386	; 0x4002
  28:	f240 0100 	movw	r1, #0
  2c:	f2c4 0100 	movt	r1, #16384	; 0x4000
  30:	6802      	ldr	r2, [r0, #0]
  32:	ea41 0102 	orr.w	r1, r1, r2
  36:	6001      	str	r1, [r0, #0]
00000038 <BLINK_LOOP>:
  38:	f640 4018 	movw	r0, #3096	; 0xc18
  3c:	f2c4 0002 	movt	r0, #16386	; 0x4002
  40:	f248 0100 	movw	r1, #32768	; 0x8000
  44:	f2c0 0100 	movt	r1, #0
  48:	6001      	str	r1, [r0, #0]
  4a:	f000 f80c 	bl	66 <DELAY>
  4e:	f640 4018 	movw	r0, #3096	; 0xc18
  52:	f2c4 0002 	movt	r0, #16386	; 0x4002
  56:	f240 0100 	movw	r1, #0
  5a:	f2c8 0100 	movt	r1, #32768	; 0x8000
  5e:	6001      	str	r1, [r0, #0]
  60:	f000 f801 	bl	66 <DELAY>
  64:	e7e8      	b.
n 38 <BLINK_LOOP> 00000066 <DELAY>: 66: f240 0200 movw r2, #0 6a: f2c0 0210 movt r2, #16 0000006e <Delay_loop>: 6e: 3a01 subs r2, #1 70: d1fd bne.n 6e <Delay_loop> 72: 4770 bx lr

Именно здесь можно увидеть какие инструкции кодируются при помощи 16 бит, а какие требуют 32 бита.

Первое применение макроса превратилось в заданные в нем две команды загрузки верхних и нижних 16 бит значения размером 32 бита

 8:	f643 0030 	movw     r0, #14384	; 0x3830
 c:	f2c4 0002 	movt     r0, #16386	; 0x4002

Таким образом на загрузку одного 32-ух битного значения нам понадобилось 8 байт (64 бита) программы
Во второй части публикации я описывал инструкцию загрузки 32-ух битного значения в регистр LDR Rx,=#value32bit — давайте попробуем применить ее и посмотреть что получится:

Программа с использованием инструкции LDR

@GNU AS
@ Настройки компилятора
.
syntax unified @ тип синтаксиса .thumb @ тип используемых инструкций Thumb .cpu cortex-m4 @ микроконтроллер .include "stm32f40x.inc" @ определения микроконтроллера @ макрос псевдокоманды MOV32 нам теперь не нужен, я убрал его @ таблица векторов прерываний .section .text .word 0x20020000 @ Вершина стека .word Reset+1 @ Вектор сброса Reset: @ включим тактирование GPIO_D LDR R0, =(PERIPH_BASE + RCC_BASE + RCC_AHB1ENR) @ адрес LDR R1, =RCC_AHB1ENR_GPIODEN @ значение LDR R2, [R0] @ прочитали значение регистра ORR R1, R1, R2 @ логическое, побитовое ИЛИ: R1= R1 ИЛИ R2 STR R1, [R0] @ запись R1 по адресу указанному в R0 @ установим режим GPIO_D pin_15 LDR R0, =(PERIPH_BASE + GPIOD_BASE + GPIO_MODER) @ адрес LDR R1, =GPIO_MODER_MODER15_0 @ значение LDR R2, [R0] @ прочитали значение регистра ORR R1, R1, R2 @ логическое, побитовое ИЛИ: R1= R1 ИЛИ R2 STR R1, [R0] @ запись R1 по адресу указанному в R0 BLINK_LOOP: @ включим светодиод LDR R0, =(PERIPH_BASE + GPIOD_BASE + GPIO_BSRR) @ адрес LDR R1, =0x8000 @ значение 1000 0000 0000 0000 STR R1, [R0] @ запись R1 по адресу указанному в R0 BL DELAY @ пауза @ выключим светодиод LDR R0, =(PERIPH_BASE + GPIOD_BASE + GPIO_BSRR) @ адрес LDR R1, =(0x8000 << 16) @ значение STR R1, [R0] @ запись R1 по адресу указанному в R0 BL DELAY @ пауза B BLINK_LOOP @ делаем цикл DELAY: LDR R2, =0x00100000 @ повтор цикла 0x0010 0000 раз. Delay_loop: SUBS R2, R2, 1 BNE Delay_loop BX LR

откомпилируем проект (запустим make_project.bat), и посмотрим что получилось после компиляции (файл /compile/temp/main_text.lst) — кстати, вы уже наверное заметили что размер программы «каким то образом» уменьшился со 116 до 96 байт, все дело именно в использовании инструкций LDR Rx, =#value32bit
Я уберу весь код который не относится к этим инструкциям

. . .
00000008 <Reset>:
   8:	480d      	ldr	r0, [pc, #52]	; (40 <Delay_loop+0x8>)
   a:	490e      	ldr	r1, [pc, #56]	; (44 <Delay_loop+0xc>)
 . . .
  14:	480c      	ldr	r0, [pc, #48]	; (48 <Delay_loop+0x10>)
  16:	490d      	ldr	r1, [pc, #52]	; (4c <Delay_loop+0x14>)
. . .
00000020 <BLINK_LOOP>:
  20:	480b      	ldr	r0, [pc, #44]	; (50 <Delay_loop+0x18>)
  22:	490c      	ldr	r1, [pc, #48]	; (54 <Delay_loop+0x1c>)
. . .
  2a:	4809      	ldr	r0, [pc, #36]	; (50 <Delay_loop+0x18>)
  2c:	490a      	ldr	r1, [pc, #40]	; (58 <Delay_loop+0x20>)
.  . .
  36:	4a09      	ldr	r2, [pc, #36]	; (5c <Delay_loop+0x24>)
. . .
  3e:	0000      	.short	0x0000
. . .
  40:	40023830 	.word	0x40023830
  44:	00000008 	.word	0x00000008
  48:	40020c00 	.word	0x40020c00
  4c:	40000000 	.word	0x40000000
  50:	40020c18 	.word	0x40020c18
  54:	00008000 	.word	0x00008000
  58:	80000000 	.word	0x80000000
  5c:	00100000 	.word	0x00100000

формат строк: <cмещение адреса инструкции> : <код инструкции> <текст инструкции> ; <комментарий компилятора>
Рассмотрим команду расположенную под адресом 8

   8:	480d      	ldr	r0, [pc, #52]	; (40 <Delay_loop+0x8>)

мы видим что в R0 загружается значение PC увеличенное на #52 (десятичное значение!), в примечании указывается что результирующий адрес будет 40 (это шестнадцатеричное значение)
проверим получившиеся значение:
после загрузки команды, в момент ее исполнения PC содержит в себе [адрес текущей инструкции+4], то есть PC = 0x08 + 0x04=0x0C, адрес данных для загрузки = PC + #52 = 0x0C+#52 = #64 (0x40)

Запоминаем! после загрузки кода инструкции из программной памяти (не пишу FLASH потому что программа может быть загружена и в CCM_RAM — вспоминаем текст первой публикации(!) ) — значение PC увеличивается на 4 вне зависимости от того 16-ти битная или 32-ух битная инструкция была загружена !

Как видно из полученного в main_text. lst дампа компилятор автоматически все константы поместил в конец секции .text, на данном этапе нам важно заметить что фактически использование макроса mov32 не приносит никаких выгод ни с точки зрения наглядности программы, согласитесь что в коде программы строки читаются не хуже и не лучше друг друга

MOV32  R0, 0x10101010
LDR   R0, =0x10101010

ни с точки зрения скорости исполнения (в комментариях к второй публикации мне указали на то что команда LDR с загрузкой из памяти будет выполнена так же за 2 такта), но выиграем в размере программы. С учетом того, что даже в нашей, прямо скажем микроскопической, программе мигания светодиодом постоянно приходиться использовать 32-ух битные значения констант (адреса регистров, значения для записи в регистры) — экономия может оказаться не на столько смехотворной как это кажется на первый взгляд…

Я не буду отдельно выкладывать архив с примером программы с использованием инструкций LDR — думаю с созданием этого примера вы справитесь самостоятельно.


Теперь хочу рассказать об еще одной «фиче» микроконтроллеров на платформе ARM — битбандинге (bitbanding)
Кратко — это возможность получить доступ к определенным битам обращаясь ячейкам расположенным в специальных областях адресного пространства. Доступ может быть и на чтение и на изменение бита.

В «PM0214 Cortex-M4 Programming manual» на стр. 27 приведена следующая схема распределения адресного пространства микроконтроллеров семейства STM32F4

Давайте разберемся со схемой:

  1. Bitband region — область адресного пространства микроконтроллера где находиться контролируемый или проверяемый бит. По другому говоря бит которым мы реально хотим изменить или состояние которого хотим прочитать должен находиться в этом диапазоне адресов
  2. Bitband alias — область адресного пространства проецируемая на bitband region. Говоря русским языком, при обращении к адресам из этой области можно проверить состояние бита из области bitband region или записав данные в эту область можно изменить состояние бита данных из области bitband region

Области bitband region имеют объем 1 мб
Области bitband alias — 32 мб
Как можно видеть из схемы распределения адресного пространства у микроконтроллеров STM32F4xx две области bitband region (связанные с ними bitband alias):

  1. в адресах 0x2000 0000 — 0x200F FFFF — то есть эта область покрывает все адреса SRAM1 и SRAM2 (вспоминаем адреса SRAM из первой части публикации!)
  2. в адресах 0x4000 0000 — 0x400F FFFF — эта область покрывает адреса регистров настройки периферии микроконтроллера + все пространство backup RAM

Теперь разберем формулу по которой сопоставляется адрес бита в bitband region адресу в bitband alias, она приведена на стр. 31 «PM0214 Cortex-M4 Programming manual«

Для простоты запишем ее в одну строчку:

bit_word_adr=bitband_base+ (byte_offset * 32) + bit_number * 4

где,

  1. bitband_base — адрес bitband_alias
  2. byte_offset — смещение адреса регистра относительно начала bitband_alias
  3. bit_number — номер бита к которому нужно получить доступ

Практическое применение bitband:

Возьмем нашу программу «мигалки»: при настройке режимов GPIOD мы сначала включаем этот порт устанавливая нужный нам бит в «1», делаем это строками кода:

		@ включим тактирование GPIO_D
		LDR     R0, =(PERIPH_BASE + RCC_BASE + RCC_AHB1ENR)  @ адрес
		LDR     R1, =RCC_AHB1ENR_GPIODEN                     @ значение
		LDR     R2, [R0]      @ прочитали значение регистра
		ORR     R1, R1, R2    @ логическое, побитовое ИЛИ: R1= R1 ИЛИ R2
		STR     R1, [R0]      @ запись R1 по адресу указанному в R0

Адрес PERIPH_BASE = 0x40000000 — то есть он укладывается в один из bitband region’ов
Адрес bitband_alias для этого bitband region равен 0x42000000 — это значение и используется в качестве bitband_base при обращении к регистрам расположенным в адресах 0x40000000 — 0x400FFFFF

А адрес byte_offset вычисляется так же как и адрес регистра при обычной записи в регистр настройки (в нашем случае RCC_BASE + RCC_AHB1ENR).

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

BIT_ADR=PERIPH_BB_BASE + (RCC_BASE + RCC_AHB1ENR) * 32 + RCC_AHB1ENR_GPIODEN_N * 4

где:
PERIPH_BB_BASE — определено значение 0x42000000, определение находиться в файле stm32f40x.inc нашего проекта

RCC_BASE + RCC_AHB1ENR — это тоже 2 константных значения которые мы уже вычисляли во второй части публикации
RCC_AHB1ENR_GPIODEN_N — номер бита в регистре RCC_AHB1ENR. Этого определения в файле констант не было, я добавил самостоятельно, для того чтобы понимать что константа указывает не на значение, а лишь на порядковый номер бита в слове я всегда добавляю «_N» к имени константы.

Получаем следующий код для включения GPIOD:

		@ включим тактирование GPIO_D
		LDR     R0, =(PERIPH_BB_BASE + (RCC_BASE + RCC_AHB1ENR) * 32 + RCC_AHB1ENR_GPIODEN_N * 4)  @ адрес бита
		MOV     R1, 1        @ значение для бита
		STR     R1, [R0]     @ запись R1 по адресу указанному в R0

Установив в R0 адрес бита в bitband_alias, командой STR R1, [R0] мы записываем не значение 32-ух битного регистра R1 по адресу в регистре R0, а устанавливаем значение одного бита с номером 3 в регистре RCC_AHB1ENR.

При этом нам не нужно проводить операцию: чтение | логическое «ИЛИ» | запись, это все происходит на аппаратном уровне.
К слову, объединение трех операций в одну при bitbanding является важной при некоторых применениях, когда важна «атомарность» (неделимость) действия при изменению значения бита (обычно это оперирование различными «флагами» и «семафорами» в много- задачных или псевдо- многозадачных программах)

Давайте перепишем нашу программу «мигалка» с использованием метода bitband:

@GNU AS
@ Настройки компилятора
.syntax unified   @ тип синтаксиса
.thumb            @ тип используемых инструкций Thumb
.cpu cortex-m4    @ микроконтроллер
.include "stm32f40x.inc"   @ определения микроконтроллера
@ макрос псевдокоманды MOV32 нам теперь не нужен, я убрал его
@ таблица векторов прерываний
.section .text
.word	0x20020000	@ Вершина стека
.word	Reset+1		@ Вектор сброса
Reset:
                MOV     R0, 0  @ Значение 0, будет использоваться для bitband
		MOV     R1, 1  @ значение 1, будет использоваться для bitband
		@ включим тактирование GPIO_D
		LDR     R2, =(PERIPH_BB_BASE + (RCC_BASE + RCC_AHB1ENR) * 32 + RCC_AHB1ENR_GPIODEN_N * 4)  @ адрес
		STR     R1, [R2]    @ запись R1 ("1") по адресу бита указанному в R2
		@ установим режим GPIO_D pin_15
		LDR     R2, =(PERIPH_BASE + GPIOD_BASE + GPIO_MODER)  @ адрес
		LDR     R3, =GPIO_MODER_MODER15_0                     @ значение
		LDR     R4, [R2]    @ прочитали значение регистра
		ORR     R3, R3, R4  @ логическое, побитовое ИЛИ
		STR     R3, [R2]    @ запись обновленного значения в GPIOD_MODER
		LDR     R2, =(PERIPH_BB_BASE + (GPIOD_BASE + GPIO_ODR) * 32 + 15*4)  @ адрес бита
BLINK_LOOP:
		@ включим светодиод
		STR     R1, [R2]   @ запись R1 ("1") по адресу указанному в R2
	
		BL      DELAY      @  пауза
	
		@ выключим светодиод
		STR     R0, [R2]   @ запись R0 ("0") по адресу указанному в R2
		BL      DELAY      @  пауза	
		B       BLINK_LOOP @ делаем цикл
DELAY:
		LDR     R3, =0x00100000   @ повтор цикла 0x0010 0000 раз. 
Delay_loop:	
		SUBS     R3, R3, 1
		BNE     Delay_loop
		BX      LR

Не ожидали столько изменений? Давайте их разберем!

В начало программы я вынес присвоение значений двум регистрам R0 = 0 и R1 = 1 эти значения мы будем записывать при использовании метода bitband, присвоение командой MOV тоже произведено намеренно — при таком присвоении осуществляется загрузка 16-ти битного значения в младшие 16 бит регистра, с обнулением старших 16 бит. Таким образом R0 (в 32ух битах) у нас будет равен «0», а R1 (в 32ух битах) будет равен «1».

                MOV     R0, 0  @ Значение 0, будет использоваться для bitband
		MOV     R1, 1  @ значение 1, будет использоваться для bitband

Далее идет уже разобранный нами блок включения GPIOD методом bitband, я использую регистр R2 поскольку R0 и R1 уже заняты нашими константами («0», «1» соответственно):

		@ включим тактирование GPIO_D
		LDR     R2, =(PERIPH_BB_BASE + (RCC_BASE + RCC_AHB1ENR) * 32 + RCC_AHB1ENR_GPIODEN_N * 4)  @ адрес
		STR     R1, [R2]    @ запись R1 ("1") по адресу бита указанному в R2

Устанавливаем режим работы 15 вывода GPIOD на выход, пока, чтобы не путать повествование, оставил процедуру прежней, хотя ее можно легко переписать на присвоение значения методом bitband тогда она сократиться до 2х строчек кода

		@ установим режим GPIO_D pin_15
		LDR     R2, =(PERIPH_BASE + GPIOD_BASE + GPIO_MODER)  @ адрес
		LDR     R3, =GPIO_MODER_MODER15_0                     @ значение
		LDR     R4, [R2]    @ прочитали значение регистра
		ORR     R3, R3, R4  @ логическое, побитовое ИЛИ
		STR     R3, [R2]    @ запись обновленного значения в GPIOD_MODER

Поскольку в цикле «мигания» адрес регистра управляющего светодиодом меняться не будет — я вынес это значение за пределы цикла. Так же в качестве регистра вывода я использую регистр GPIO_ODR (ищите в Reference manual описание по GPIOx_ODR), с адресацией 15-го бита в режиме bitband (к 15-му биту у нас подключен светодиод).

		LDR     R2, =(PERIPH_BB_BASE + (GPIOD_BASE + GPIO_ODR) * 32 + 15*4)  @ адрес бита

Цикл мигания светодиодом упрощается! теперь нам просто нужно записывать по адресу бита (методом bitband) значение «0» или «1» для включения светодиода, и вызывать между записью паузу

BLINK_LOOP:
		@ включим светодиод
		STR     R1, [R2]   @ запись R1 ("1") по адресу указанному в R2
	
		BL      DELAY      @  пауза
	
		@ выключим светодиод
		STR     R0, [R2]   @ запись R0 ("0") по адресу указанному в R2
		BL      DELAY      @  пауза	
		B       BLINK_LOOP @ делаем цикл

Для паузы я использую значение регистра R3 (R0, R1, R2 уже заняты)

DELAY:
		LDR     R3, =0x00100000   @ повтор цикла 0x0010 0000 раз.
Delay_loop:	
		SUBS     R3, R3, 1
		BNE     Delay_loop
		BX      LR

Запустив компиляцию и сборку нашего проекта мы увидим размер программы — 76 байт (если помните, первоначальный вариант «весил» — 116 байт)
Этот проект можно скачать по ссылке

ВНИМАНИЕ !
Поскольку у меня нет платы STM32F4 Discovery все примеры данной публикации выложены «как есть», без предварительной проверки на работоспособность. В случае если что то не заработало — пишите: посмотрим, послушаем, разберемся (с) «Берегись автомобиля».

В порядке тренировки можете попробовать еще оптимизировать по размеру программу «мигалка» и поделиться результатами в комментариях к статье (можно использовать любые инструкции процессора).

На этом третью публикацию закончим.

продолжение STM32F4: GNU AS: Настраиваем среду компиляции (Часть 4)

STM32F4Discovery — Рубрика — PVSM.RU

Реализация PPPOS на stm32f4-discovery

2018-08-02 в 12:55, , рубрики: cubemx, pppd, pppos, STM32F4Discovery, usart, программирование микроконтроллеров

Однажды передо мной возникла задача обеспечить выход в сеть Интернет на STM32 имея для этого только COM порт. Для решения этой задачи мне понадобился PPP, или, еcли быть точным, PPPoS (англ. Point-to-Point Protocol over Serial — один из способов реализации PPP, используется при подключении через COM-порт).

В процессе решения поставленной передо мной задачи я столкнулся с некоторыми трудностями, одна из которых недостаточное, на мой взгляд, освещение вопросов связанных с PPPoS в сети Интернет. Этим постом я постараюсь закрыть обозначенный пробел, на сколько позволят мои скромные знания.

Статья описывает создание проекта для System Workbench for STM32 с нуля. Показывает пример работы с UART. Есть примеры кода для реализации PPP. Ну и конечно, пример отправки сообщения на соседний компьютер.
Читать полностью »

Почти все, что вы хотели знать про плавающую точку в ARM, но боялись спросить

2018-07-26 в 9:53, , рубрики: C, embox, fpu, neon, simd, STM32F4Discovery, stm32f7discovery, vfp, Блог компании Embox, плавающая точка, системное программирование

Привет! В этой статье я хочу рассказать про работу с плавающей точкой для процессоров с архитектурой ARM. Думаю, эта статья будет полезна прежде всего тем, кто портирует свою ОС на ARM-архитектуру и при этом им нужна поддержка аппаратной плавающей точки (что мы и делали для Embox, в котором до этого использовалась программная реализация операций с плавающей точкой).

Итак, приступим.
Читать полностью »

STM32F4 USB RNDIS драйвер (управление устройством через Web-интерфейс)

2016-01-16 в 14:33, , рубрики: C, dhcp, DNS, ethernet, lwip, rndis, STM32F4, STM32F4Discovery, usb, встраиваемые системы, гаджеты и девайсы, интерфейс, интерфейсы, клиент-сервер, контроллер, программирование микроконтроллеров, разработка, Сетевые технологии, стандарты, метки: rndis

Выводим цифровую фоторамку в интернет

2015-09-28 в 7:17, , рубрики: diy или сделай сам, fat16, hal. usb, mass storage, stm32f107, STM32F4, STM32F4Discovery, программирование микроконтроллеров, фоторамка, метки: stm32f107


Наверное многие, глядя на цифровую фоторамку, задумывались — можно ли выводить на нее собственную информацию, меняющуюся во времени? Поскольку я уже несколько лет являюсь владельцем фоторамки, то такая мысль приходила в голову и мне — рамка отлично подошла бы для отображения прогноза погоды и информации с «умного дома». О том, как же реализовать подобный функционал, не вмешиваясь при этом в конструкцию рамки — читайте под катом.
Читать полностью »

Ethernet поверх USB на STM32F4

2015-02-09 в 22:10, , рубрики: dhcp, DNS, ethernet, http, lwip, rndis, stm32, STM32F4, STM32F4Discovery, usb, интерфейсы, Программирование, программирование микроконтроллеров, разработка, Сетевые технологии

Как мы строили систему аварийной сигнализации дата-центра

2015-02-05 в 8:56, , рубрики: diy или сделай сам, embox, modbus, stm32, STM32F4Discovery, программирование микроконтроллеров, метки: Embox, Modbus, stm32f4discovery


Так получилось, что в команде проекта Embox у меня больше всех опыта в области АСУ: на предыдущем месте работы я разрабатывал промышленные контроллеры. Поэтому не удивительно, что когда возникла задача сделать систему автоматического управления светодиодами в датацентре, именно меня попросили проработать архитектуру проекта. Изначально планировалось закупить готовые контроллеры удаленного управления портами ввода-вывода, но после более тщательной проработки требований стало ясно, что для заказчика более предпочтителен вариант разработки заказного контроллера. Собственно его вы и видите на фотографии.
Тем, кому интересно узнать о том, на какие грабли мы наступили, как выглядят взорвавшиеся микросхемы, как правильно подключать землю на DC/DC конвертере, ну и, конечно, почему мы применили наш проект, прошу под кат. Осторожно, много картинок!
Читать полностью »

Доработка USB-стека в микроконтроллерах STM32 и TivaC

2015-01-24 в 9:29, , рубрики: diy или сделай сам, launchpad, open source, stm32, STM32F4Discovery, texas instruments, tm32f4, usb, интерфейсы, программирование микроконтроллеров

Наличие USB порта в современных микроконтроллерах открывает широкие возможности для самостоятельного изготовления разнообразных управляемых с компьютера устройств. На практике, однако, выясняется, что поставляемые производителем библиотеки для работы с USB нуждаются в доработке. Если вам интересен опыт подобной доработки для двух популярных семейств МК — добро пожаловать под кат.
Читать полностью »

Эмуляция носителя FAT32 на stm32f4

2015-01-12 в 11:50, , рубрики: mass storage, stm32, STM32F4Discovery, usb msc, программирование микроконтроллеров, эмуляция fat32

Недавно возникла данная задача — эмуляция носителя FAT32 на stm32f4.

Её необычность заключается в том, что среди обвязки микроконтроллера вовсе может не быть накопителя.

В моём случае накопитель был, но правила работы с ним не позволяли разместить файловую систему. В ТЗ, тем не менее, присутствовало требование организовать Mass Storage интерфайс для доступа к данным.

Результатом работы явился модуль, который я озаглавил «emfat», состоящий из одноимённого .h и .c файла.

Модуль независим от платформы. В прилагаемом примере он работает на плате stm32f4discovery.

Функция модуля — отдавать куски файловой системы, которые запросит usb-host, подставляя пользовательские данные, если тот пытается считать некоторый файл.
Читать полностью »

Самодельный фазовый лазерный дальномер

2014-02-26 в 18:03, , рубрики: diy или сделай сам, stm32, STM32F4Discovery, лазерный дальномер, Программинг микроконтроллеров, Электроника для начинающих, метки: stm32, STM32F4Discovery, лазерный дальномер


В статье я расскажу о том, как я делал лазерный дальномер и о принципе его работы. Сразу отмечу, что конструкция представляет собой макет, и ее нельзя использовать для практического применения. Делалась она только для того, чтобы убедится в том, что фазовый дальномер реально собрать самому.
Читать полностью »

rusEfi: зажигание и другие плюшки

2013-12-15 в 22:34, , рубрики: automotive, diy или сделай сам, stm32, STM32F4Discovery, Программинг микроконтроллеров, разработка, метки: automotive, stm32, STM32F4Discovery

Для тех кто только присоединился к нам — предыдущая часть здесь habrahabr. ru/post/201472/

Сразу к главной новости — на rusEfi заработали управление бензонасосом и альфа версия зажигания: этого достаточно, чтобы используя только rusEfi управлять двигателем!
Читать полностью »

STM32F4 Discovery Board Programming with Embedded Coder — обмен файлами

  • Вы можете получать электронные письма, в зависимости от ваших предпочтений в общении
  • Версия 1.4.0.1 (4,59 КБ) от MathWorks Embedded Coder Team

    Моделируйте, прототипируйте, настраивайте и развертывайте алгоритмы на плате STM32F4 Discovery.

    5,1 тыс. загрузок За все время: 5092″>

    Обновлено 1 сентября 2016 г.

    Посмотреть лицензию

    • Обзор
    • Примеры
    • История версий
    • Отзывы (1)
    • Обсуждения (0)

    В этом видеоролике показано, как использовать Simulink® и DSP System Toolbox™ для разработки моделей звуковых алгоритмов и создания кода, оптимизированного для ARM® Cortex®-M4F (CMSIS), на основе моделей с помощью Embedded Coder®. Демонстрация включает алгоритм параметрического эквалайзера звука, который создан и настроен в Simulink при выполнении в реальном времени на оборудовании с использованием блоков драйверов устройств ввода и вывода звука.
    https://www.youtube.com/watch?v=qNWsp3TyI1Y

    Цитировать как

    Команда MathWorks Embedded Coder (2023 г.). STM32F4 Discovery Board Programming with Embedded Coder (https://www.mathworks.com/matlabcentral/fileexchange/50373-stm32f4-discovery-board-programming-with-embedded-coder), MATLAB Central File Exchange. Проверено .

    Совместимость версий MATLAB

    Created with R2014b

    Совместимость с любой версией

    Совместимость с платформами
    Windows macOS Linux

    Категории
    • Обработка сигнала >
    • Генерация кода > Встроенный кодер > Развертывание, интеграция и поддерживаемое оборудование > Поддерживаемое оборудование встроенного кодера >
    • Генерация кода > Встроенный кодер > Развертывание, интеграция и поддерживаемое оборудование > Поддерживаемое оборудование встроенного кодера > Процессоры ARM Cortex-M >
    • Генерация кода > Встроенный кодер > Развертывание, интеграция и поддерживаемое оборудование > Поддерживаемое оборудование встроенного кодера > Платы STMicroelectronics Discovery >
    Теги Добавить теги

    плата обнаружения встроенный кодер stm32f4 пакет поддержки f. .. пакет поддержки f…

    Благодарности

    Вдохновлен: Пакет поддержки встроенного кодера для процессоров STMicroelectronics STM32

    Охота за сокровищами сообщества

    Найдите сокровища в MATLAB Central и узнайте, как сообщество может вам помочь!

    На охоту!

    Версия Опубликовано Примечания к выпуску
    1.4.0.1

    Обновленная лицензия

    1.4.0.0

    добавлена ​​ссылка на вдохновение

    1. 3.0.0

    Обновлен файлами .html и .m.

    1.2.0.0

    Общий доступ к файлу .m вместо .html.

    1.1.0.0

    Обновлен отредактированный файл без номеров версий.

    Выберите веб-сайт

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

    Вы также можете выбрать веб-сайт из следующего списка:

    Европа

    Обратитесь в местный офис

    Использование платы обнаружения STM32F4 в качестве программатора и отладчика

    Очень весело писать код на доске Discovery с множеством периферийных устройств для изучения и открытыми заголовками для дальнейших экспериментов. Ничто, однако, не сравнится с удовлетворением, которое можно получить от создания и кодирования собственной доски, и наступает время, когда каждый заядлый гик должен действовать самостоятельно!

    Недавно мне представилась возможность создать новую плату, которая требовала гораздо больше усилий, чем платы на основе PIC, с которыми я обычно имею дело. Нам нужен был гораздо более быстрый процессор, FPU и некоторые возможности DSP. В результате я решил использовать STM32F405RG в качестве микроконтроллера. Следующее, что я хотел сделать, это смешать прототип, но мне нужен был быстрый и простой способ его запрограммировать. Я вспомнил, что на плате Discovery есть раздел ST-LINK с интерфейсом SWD, разбитым на разъемы, поэтому я решил попробовать.

    Настроить Discovery для использования в качестве программатора очень просто. Секция ST-LINK — это верхняя треть платы, и ее можно легко изолировать, удалив две перемычки CN3, показанные выше.

    Вам также явно понадобится открыть интерфейс SWD на вашей плате, чтобы у вас было к чему подключать ST-LINK. На схеме ниже показано, как я это сделал.

    Несколько замечаний по схеме выше. Я поставил BOOT0 на низкий уровень, что означает, что я программирую флэш-память. Если вы хотите запрограммировать другие области памяти, вам нужно иметь возможность изменить состояние этого и вывода BOOT1, который мультиплексирован с PB2 на частях STM32F40x. Подробности можно найти в разделе 2.4 справочного руководства.

    Еще я сделал вывод дополнительных выводов интерфейса JTAG, чтобы дать мне несколько вариантов программирования и отладки. Наконец, я соединил контакт NRST на ST-LINK с контактом NJRST на моем STM32. Это может быть неправильно, возможно, вам лучше подключить его к выводу NRST на STM32. Возможно, кто-то там может дать мне знать в комментариях ниже.

    Интерфейс SWD подключается следующим образом:

    Я решил представить интерфейс в виде ряда разъемов с шагом 0,1 дюйма и соединил две платы вместе соединительными проводами типа «мама-мама».

    Следующий шаг — попытаться запустить какой-нибудь код на устройстве. Я использую для этого Atollic TrueSTUDIO Lite, но я уверен, что процесс почти такой же и для других IDE.

    Этапы создания проекта

    Чтобы запустить и запустить программу на новой плате, вам необходимо создать новый проект, предназначенный для STM32F405 или любой другой части STM32, которую вы используете. Это создаст новый компилируемый и работоспособный проект. Если вы сейчас запустите программу в отладчике, вы сможете пройтись по коду, просмотреть значения переменных и содержимое памяти. Это показывает, что все работает нормально.

    Последний шаг — разобрать часы. TrueSTUDIO создаст для вас файл system_stm32f4xx.c по умолчанию, содержащий конфигурацию часов, но если вы не используете кварц 25 МГц, вы захотите изменить его на другой, предназначенный для вашей собственной платы. Мой, например, использует внешние часы 4 МГц.

    Инструмент настройки часов STM32

    Самый простой способ сделать это (насколько мне известно) — использовать для этой цели инструмент настройки часов, предоставленный STMicroelectronics. Вы можете загрузить инструмент и сопутствующие примечания с их веб-сайта. Я использовал простой режим мастера, очень тщательно следовал инструкциям и там, где я не был уверен в значении, я искал его в исходном файле, созданном TrueSTUDIO. После создания нового файла system_stm32f4xx.c его необходимо заменить в вашем проекте. Просто пересоберите проект, убедитесь, что вы все еще можете запускать и отлаживать его, и вы готовы к работе.

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

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *