Перейти к содержанию

Типы доступа к регистрам

В таблице регистра рядом с каждым полем стоит пометка: R/W, RO, WTC, rc_w1. Это тип доступа, и он меняет смысл записи: в одно поле запись 1 устанавливает бит, в другое — сбрасывает, а запись 0 вообще ничего не делает. Ошибиться здесь — значит сбросить чужой флаг прерывания.

Обновлено Редакция GAW

Тип доступа (access type) регистра или поля — правило, по которому на чтение и запись реагирует аппаратура. Его указывают в справочном руководстве у каждого поля: от простого «только чтение» до «сброс записью единицы». От типа зависит, каким кодом правильно менять поле.

Основные типы

Обозначение ESP32Обозначение STM32Что происходит
ROrтолько чтение
R/Wrwчтение и запись
WOwтолько запись; у STM32 чтение возвращает значение после сброса
W1Crc_w1запись 1 в сам бит сбрасывает его, запись 0 не действует
W0Crc_w0запись 0 сбрасывает бит, запись 1 не действует; у STM32 так устроены TIMx_SR и USART_SR
WTrt_w (близкий смысл)запись 1 порождает событие — импульс на шине — или сбрасывает связанное поле WTC
WTC—поле сбрасывается записью 1 в парное поле WT
RCrc_rбит сбрасывается при чтении
W1S, WSrsзапись 1 (у WS — любая запись) устанавливает бит
W1Ttзапись 1 переключает бит
SS, SC—бит устанавливает или сбрасывает сама аппаратура по событию

Источники: глоссарий типов доступа в TRM ESP32-S3 v1.8 и раздел 1.1 RM0090. Пара WT/WTC у Espressif — это флаги прерываний: например, у UART флаг UART_RXFIFO_FULL_INT_RAW имеет тип R/WTC/SS (его ставит аппаратура, а сбрасывает запись), а бит UART_RXFIFO_FULL_INT_CLR в регистре UART_INT_CLR_REG — тип WT: запись в него единицы сбрасывает флаг (TRM ESP32-S3, гл. 26).

Регистры W1TS и W1TC

Для выходов GPIO ESP32 есть отдельные регистры: GPIO_OUT_W1TS_REG (write 1 to set) и GPIO_OUT_W1TC_REG (write 1 to clear). Единица в бите W1TS устанавливает соответствующий бит GPIO_OUT_REG, единица в W1TC — сбрасывает, нули ничего не меняют; Espressif рекомендует именно этот способ (TRM ESP32-S3, гл. 6; регистры — на странице GPIO ESP32-S3). У STM32 ту же роль играет GPIOx_BSRR: ST подчёркивает, что запись в него — одна атомарная операция на шине и запрещать прерывания не нужно (RM0090, разд. 8.3.5).

Типичная ошибка

Флаги прерываний типа W1C сбрасывают прямой записью маски, а не операцией REG |= MASK: чтение-изменение-запись вернёт единицы во все флаги, которые были установлены в момент чтения, и сбросит их, хотя их ещё не обработали. Флаг, пришедший уже после чтения, при этом записывается нулём и не пострадает — для W1C и rc_w1 запись 0 ничего не делает (TRM ESP32-S3, с. 1520–1521; RM0090, разд. 1.1). С флагами rc_w0 у STM32 опасность обратная: REG &= ~MASK запишет 0 и во флаги, которые установились между чтением и записью, и они пропадут; такие флаги сбрасывают записью ~MASK без чтения (наш вывод из определений). Это частный случай состояния гонки. Как устроен доступ к регистрам в коде STM32, разобрано в статье «HAL, LL и регистры», маски полей собирает конструктор регистров.

Не путать

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

Частые вопросы

Что значит W1C или rc_w1?

Бит сбрасывается, если записать в него единицу, а запись нуля его не меняет (TRM ESP32-S3; RM0090, разд. 1.1). Так устроены флаги прерываний и ошибок: чтобы сбросить только один флаг, пишут маску с единицей в его позиции, остальные флаги не трогаются.

Почему нельзя сбросить W1C-флаг через чтение-изменение-запись?

Операция REG |= MASK читает регистр, где могут стоять и другие флаги, и записывает их обратно единицами — тем самым сбрасывает и их, хотя их ещё не обработали (наш вывод из определения W1C). Правильно — прямая запись маски: REG = MASK.

Зачем в ESP32 отдельные регистры W1TS и W1TC?

Чтобы установить или сбросить отдельные выводы одной записью: единица в бите GPIO_OUT_W1TS_REG устанавливает соответствующий бит GPIO_OUT_REG, в GPIO_OUT_W1TC_REG — сбрасывает, нули ничего не меняют (TRM ESP32-S3, гл. 6). Espressif рекомендует именно этот способ. Тот же смысл у GPIOx_BSRR в STM32: ST пишет, что для побитовой записи не нужно запрещать прерывания.

Источники

  1. Espressif. ESP32-S3 Technical Reference Manual, Version 1.8, Glossary «Access Types for Registers» — гл. 26: UART_INT_CLR_REG — WT, флаги *_INT_RAW — R/WTC/SS; с. 1520–1521: RO, WO, R/W, W1 (однократная запись), SS/SC (аппаратная установка/сброс), RC (сброс чтением), WC (сброс любой записью), W1C (сброс записью 1), W0C, W1S, WT (запись 1 — событие или сброс связанного поля WTC), W1T (переключение записью 1); гл. 6: GPIO_OUT_W1TS_REG и GPIO_OUT_W1TC_REG (WO) — запись 1 в бит устанавливает или сбрасывает соответствующий бит GPIO_OUT_REG, рекомендуемый способ
  2. STMicroelectronics. RM0090 Rev 21. Reference manual: STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 — разд. 1.1: rw, r, w, rc_w1 (сброс записью 1, запись 0 без эффекта), rc_w0 (сброс записью 0; так устроены флаги TIMx_SR, разд. 17.4.5 и 18.4.5, и USART_SR, разд. 30.6.1), rc_r (сброс чтением), rs, rt_w, t (переключение записью 1); разд. 8.3.5: GPIOx_BSRR — атомарная побитовая запись, не нужно запрещать прерывания

Нашли ошибку?