Адрес одного пина

STM32F103C8T6 · МПС · лабораторная 1

Адрес одного пина

Откуда берётся 0x4001 0C10 и почему запись именно по этому адресу зажигает светодиод на PB15. Пять уровней: от четырёх гигабайт адресного пространства до одного бита.

Уровень 1 · всё адресное пространство

4 ГБ, из которых используется горстка

У Cortex-M3 адреса 32-битные, то есть пространство от 0x00000000 до 0xFFFFFFFF — 4 ГБ. Памяти столько нет и близко: пространство поделено на области, и большинство адресов ни к чему не ведут. Периферия живёт в своей области, начиная с 0x40000000.

флеш ОЗУ периферия не используется ядро 0x0000 0000 0x0800 0000 0x2000 0000 0x6000 0000 0xE000 0000 сюда мы и пишем
Схема не в масштабе: флеш занимает 128 КБ, ОЗУ 20 КБ, а под периферию отведены сотни мегабайт адресов, из которых реально заняты первые полмегабайта.

Важно понимать: это не «память, где лежат регистры». Никакой памяти по адресу 0x40010C10 нет. Там сидит схема, которая слушает шину: увидела запись по своему адресу — переключила транзисторы на выводе. Приём называется «отображение периферии на память» и позволяет управлять железом обычными командами LDR и STR.

Уровень 2 · внутри периферии

Три шины, три диапазона

Периферия разложена по шинам. Медленная APB1 и быстрая APB2 отличаются предельной частотой (36 и 72 МГц), и у каждой свой кусок адресов. Порты GPIO сидят на APB2 — поэтому их тактирование включается в регистре RCC_APB2ENR.

область периферии, начало 0x4000 0000 APB1 · таймеры 2–4, USART2/3, I²C APB2 · GPIO, АЦП, TIM1, USART1 AHB · DMA, RCC, флеш 0x4000 0000 0x4001 0000 0x4001 8000 0x4002 3400 +0x0001 0000 к базе периферии
Первые четыре цифры адреса уже определились: всё, что начинается с 0x4001, — это APB2.

Уровень 3 · блоки на шине

Каждому блоку — свой километр

Внутри APB2 блоки разложены по фиксированным смещениям, по 1 КБ адресов на блок. Отсюда «круглые» адреса портов.

AFIOEXTIGPIOA GPIOBGPIOCGPIOD, ADC… +0x000+0x400+0x800 +0xC00+0x1000+0x1400… 0x4001 00000x4001 0800 0x4001 0C000x4001 1000 на блок отведён ровно 1 КБ адресов (0x400)
Порты идут подряд через 0x400, поэтому GPIOB ровно на 0x400 дальше GPIOA. Это же расстояние удобно использовать в коде, когда порт выбирается переменной.
Зачем нужен AFIO. Он стоит первым в этом ряду и заведует тем, какому блоку достаётся вывод. В твоём варианте именно через него освобождается PB3, занятый отладочным интерфейсом JTAG: запись SWJ_CFG = 010 в 0x4001 0004.

Уровень 4 · регистры блока

Семь регистров по 32 бита

Внутри килобайта, отведённого порту, заняты первые 28 байт — семь регистров подряд. Адрес регистра складывается из базы порта и смещения.

СмещениеРегистрДоступЧто делаетАдрес в GPIOB
+0x00CRLчтение и записьрежимы пинов 0–70x4001 0C00
+0x04CRHчтение и записьрежимы пинов 8–150x4001 0C04
+0x08IDRтолько чтениеуровни на выводах0x4001 0C08
+0x0CODRчтение и записьчто выдаём; во входном режиме — направление подтяжки0x4001 0C0C
+0x10BSRRтолько записьустановить и сбросить биты ODR одной командой0x4001 0C10
+0x14BRRтолько записьтолько сбросить0x4001 0C14
+0x18LCKRчтение и записьзаморозить настройку до перезагрузки0x4001 0C18

Смещения кратны четырём, потому что регистр — это 32-битное слово, а слово занимает 4 байта. Обращаться к нему нужно целиком: адреса «половины регистра» не существует.

Уровень 5 · биты внутри регистра

Где в слове живёт твой пин

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

РегистрСколько разрядов на пинГде искать пин n
CRL / CRH4CRL для пинов 0–7, сдвиг 4·n; CRH для 8–15, сдвиг 4·(n−8). Внутри тетрады: старшие два бита CNF, младшие два MODE
IDR, ODR1бит n; старшая половина слова не используется
BSRR2бит n устанавливает, бит n+16 сбрасывает
BRR1бит n сбрасывает

Четыре бита на пин в CRL и CRH — это не прихоть: режимов восемь, и двух битов на них не хватило бы. 16 пинов по 4 бита дают 64 бита, в одно слово не помещаются, поэтому регистра два.

Сборка

Собери адрес сам

Выбери порт, регистр и пин — страница покажет, из чего складывается адрес и какие разряды отвечают за этот вывод. По умолчанию открыт синий канал твоего варианта: PB15 через BSRR.

Вариант 8

Все адреса, которые понадобятся

Светодиод с общим катодом: R = PA7, G = PB3, B = PB15. Кнопки: PA3, PA10, PB5, все с высоким уровнем при нажатии.

ВыводРольРегистр режимаАдресРазрядыBSRR: вкл / выкл
PA7красныйGPIOA_CRL0x4001 080031…281<<7 / 1<<23
PB3зелёныйGPIOB_CRL0x4001 0C0015…121<<3 / 1<<19
PB15синийGPIOB_CRH0x4001 0C0431…281<<15 / 1<<31
PA3кнопка 1GPIOA_CRL0x4001 080015…12подтяжка вниз: BR3
PA10кнопка 2GPIOA_CRH0x4001 080411…8подтяжка вниз: BR10
PB5кнопка 3GPIOB_CRL0x4001 0C0023…20подтяжка вниз: BR5
Порт B настраивается дважды. PB3 и PB5 лежат в CRL, а PB15 — в CRH. Это разные адреса, и маски к ним считаются отдельно.

Проверка

Посмотреть эти адреса на живой плате

Адреса не абстрактные: их можно прочитать отладчиком, пока плата работает. С подключённым ST-Link:

openocd -f interface/stlink.cfg -c "transport select hla_swd" \
  -f target/stm32f1x.cfg -c "init" -c "mdw 0x40010C00" -c "mdw 0x40010C0C" -c "shutdown"

Первое значение — GPIOB_CRL, режимы пинов 0–7. После сброса там 0x44444444: все восемь пинов вход без подтяжки, по цифре 4 на каждый. Второе — GPIOB_ODR, там нули. Запустишь программу лабы — цифры поменяются, и это лучший способ убедиться, что маски посчитаны верно.

Без тактирования адреса «немые». Пока в RCC_APB2ENR не включён бит порта, чтение вернёт нули, а запись пропадёт бесследно. Регистр тактирования лежит по адресу 0x4002 1018 — уже не на APB2, а в блоке RCC на шине AHB.