Регистры сведений 1с. универсальная «палочка-выручалочка» разработчика

Значение слова «регистр» в 10 онлайн словарях даль, ожегов, ефремова и др. - glosum.ru

Указатель стека SP (R13)[]

Регистр SP предназначен для использования в качестве указателя стека.

Единственной командой набора ARM, неявно использующей SP по прямому назначению, является весьма специфическая команда SRS, доступная только в привилегированных режимах и появившаяся в ARMv6. В остальном же никаких специальных команд для работы со стеком у набора ARM нет; вместо них применяются обычные команды загрузки и записи данных, в которых SP указывается в качестве базового регистра. Благодаря этому возможна организация стека, растущего вверх или вниз, причём SP может указывать как на последнее использованное в стеке слово, так и на первое ещё не использованное. Более того, технически в качестве указателя стека можно использовать любой из регистров общего назначения, кроме PC. Это облегчается тем обстоятельством, что прерывания и вызовы подпрограмм не используют стек, сохраняя адрес возврата в регистре LR, а состояние прерванной программы — в регистре SPSR.

В системе команд Thumb, напротив, имеются специальные команды POP и PUSH, использующие SP как указатель стека. Стек растёт вниз, а значение SP указывает на последнее помещённое в него слово. Заметим, что в унифицированном языке ассемблера для системы команд ARM поддерживаются аналогичные мнемоники, хотя они транслируются в определённые разновидности команд LDM и STM.

Использование SP в 16-разрядных командах обработки данных очень ограничено. В 32-разрядных командах во многих случаях применение SP в качестве приёмника результата запрещено (в аналогичных командах набора ARM он может использоваться свободно).

Когда SP используется по прямому назначению, он должен содержать значение, кратное 4, поскольку обращение к стеку выполняется словами. В некоторых версиях архитектуры, например, в ARMv7-M, при записи в SP два младших разряда принудительно сбрасываются. Однако, если нужна переносимость кода между разными версиями архитектуры, программист должен убедиться, что помещаемые в SP значения никогда не будут содержать единиц в двух младших битах.

Запись/чтение регистра

Существует несколько способов установки битов в регистрах. Мы рассмотрим их все, чтобы столкнувшись с одним из них вы знали, что это вообще такое и как работает данная строчка кода. В предыдущем уроке по битовым операциям мы подробно разобрали всё, что касается манипуляций с битами, поэтому если вы его прочитали и поняли – следующая информация не будет для вас новой.

Давайте вернёмся к регистру таймера, который я показывал выше, и попробуем его сконфигурировать. Первый способ, это явное задание всего байта сразу, со всеми единицами и нулями. Сделать это можно так:

TCCR1B = 0b01010101;

Таким образом мы включили и выключили нужные биты сразу, одним махом. Как вы помните из урока о типах данных и чисел, микроконтроллеру всё равно, в какой системе исчисления вы с ним работаете, то есть число у нас в двоичной системе, в десятичной это будет , а в шестнадцатеричной – . И вот эти три варианта абсолютно одинаковы с точки зрения результата:

TCCR1B = 0b01010101;
TCCR1B = 85;
TCCR1B = 0x55;

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

Гораздо чаще бывает нужно “прицельно” изменить один бит в байте, и тут на помощь приходят логические (битовые) функции и макросы. Рассмотрим все варианты, во всех из них это байт-регистр, и это номер бита, считая с правого края. То есть BIT это цифра от 0 до 7, либо название бита из даташита.

Установка бита в 1 Установка бита в 0 Описание
Битовый сдвиг <<
2 в степени номер бита
Ардуиновский макрос bit(), заменяющий сдвиг
Встроенная функция _BV(), опять же сдвиг
Используем ассемблерные макросы sbi и cbi
Используем Ардуиновские функции bitSet() и bitClear()

Что хочу сказать по перечисленным вариантам: они все по сути являются одним и тем же, а именно – первым, просто обёрнуты в другие функции и макросы. Время выполнения всех вариантов одинаково, т.к. макро-функции не делают лишних действий, а приводят все способы к первому, со сдвигом и и . Все эти способы вы можете встретить в скетчах из интернета, это факт. Лично мне больше всего нравится ардуиновский bitSet и bitClear, потому что они имеют читаемое название и заранее сидят в библиотеке.

Что касается и – то для их использования где-то должны быть созданы макросы:

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

И после этого можно пользоваться и . Давайте рассмотрим пример, где просто подёргаем разными способами:

void setup() {
  TCCR1B = 0;             // обнулили регистр
  bitSet(TCCR1B, CS11);   // включили бит №1
  TCCR1B |= _BV(4);       // включили бит №4
  TCCR1B |= (1 << WGM12); // включили бит №3
  TCCR1B &= ~_BV(WGM13);  // вЫключили бит №4
  bitClear(TCCR1B, 3);    // вЫключили бит №3
}

Можно ещё добавить вариант, где в одной строчке можно “прицельно” установить несколько битов:

void setup() {
  TCCR1B = 0;  // обнулили регистр
  // ставим бит 1, 3 и 4(WGM13)
  TCCR1B |= _BV(1) | _BV(3) | _BV(WGM13);
}

Я думаю тут всё понятно, давайте теперь попробуем “прицельно” прочитать бит  из регистра:

Чтение бита Описание
Вручную через сдвиг
Ардуиновская макро-функция

Два рассмотренных способа возвращают 0 или 1 в зависимости от состояния бита. Пример:

void setup() {
  TCCR1B = 0;             // обнулили регистр
  bitSet(TCCR1B, CS12);   // включили бит №2
  Serial.begin(9600);     // открыли порт
  Serial.println(bitRead(TCCR1B, 2)); // получили 1
}

Ещё больше примеров работы с битами смотри в уроке по битовым операциям.

Полезные страницы

  • Набор GyverKIT – большой стартовый набор Arduino моей разработки, продаётся в России
  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макросы, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
  • Поддержать автора за работу над уроками
  •  – сообщить об ошибке в уроке или предложить дополнение по тексту ()

16-бит регистры

У Ардуинок (AVR) встречаются также сдвоенные 16-битные регистры, состоят из двух 8-битных, например “сдвоенный регистр” АЦП состоит из и , или регистр таймера состоит из и . АЦП у нас 10 битный, но регистры – 8 битные, поэтому часть (8  бит) хранится в одном регистре (), а остальное (2 бита) – в другом (). Смотрите, как это выглядит в виде таблицы:
Вопрос: как нам принять или изменить это самое 10 битное число, если оно разбито на два разных регистра? Очень просто: работа с такими сдвоенными регистрами встроена в компилятор и можно просто работать с ними напрямую как с обычной переменной, например:

int val = ADC; 	// читаем значение
ICR1 = 1234;	// записываем значение

Такую запись почему-то используют редко, возможно для совместимости с другими компиляторами. Чаще всего вы встретите вот такой вариант, в котором значения “склеиваются” через сдвиг:

int val = ADCL + (ADCH << 8);
// возможен вариант ADCL | (ADCH << 8) , см. урок про битовые операции

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

Обратная задача: есть опять же мнимый 16-битный регистр (состоящий из двух 8-битных), в который нам нужно записать значение. Например сдвоенный регистр и , вот таблица:
Микроконтроллер может работать только с одним байтом, а как нам записать двухбайтное число? А вот так: разбить число на два байта при помощи ардуиновских функций и , и уже эти байты записать в соответствующие регистры. Пример:

uint16_t val = 1500;    // просто число типа int
ICR1H = highByte(val);  // пишем старший байт
ICR1L = lowByte(val);   // пишем младший байт

// читаем байты обратно и "склеиваем" в int
byte val_1 = ICR1L;
byte val_2 = ICR1H;
uint16_t value = val_1 + (val_2 << 8);

Записывать нужно со старшего байта. Как только мы записываем младший байт (последний) – МК “защелкивает” оба регистра в память, соответственно если сначала записать младший – в старшем будет 0, и последующая запись старшего будет проигнорирована.

ВАЖНО: запись в 16 бит регистры производится начиная со СТАРШЕГО байта, чтение – с МЛАДШЕГО

Регистры, байты, биты

В прошлом уроке мы освоили битовые операции, а в этом – научимся работать напрямую с регистрами микроконтроллера. Зачем? Я думаю в первую очередь это нужно для того, чтобы понимать чужой код и переделывать его под себя, потому что прямая работа с регистрами в скетчах из Интернета встречается довольно часто.

Что такое регистр? Тут всё весьма просто: это сверхбыстрые блоки оперативной памяти объёмом 1 Байт, находящиеся рядом с ядром МК и периферией. На стороне программы это обычные глобальные переменные, которые можно читать и менять. В регистрах микроконтроллера хранятся “настройки” для различной его периферии: таймеры-счётчики, порты с пинами, АЦП, шина UART, I2C, SPI и прочее железо, встроенное в МК. Меняя регистр, мы даём практически прямую команду микроконтроллеру, что и как нужно сделать. Запись в регистр занимает около 1 такта МК (0.0625 мкс при частоте тактирования 16 МГц) – это ОЧЕНЬ быстро. Имена регистров фиксированные, полный перечень с подробным описанием можно найти в даташите на микроконтроллер (официальный даташит на ATmega328 – Arduino Nano/UNO/Mini).

Работа с регистрами очень непростая, если вы не выучили их все наизусть, потому что названия у них обычно нечитаемые, аббревиатуры. Так называемые “Ардуиновские” функции собственно и занимаются тем, что работают с регистрами, оставляя нам удобную, понятную и читаемую функцию, ничего сверхъестественного в этом нет. Зачем вообще работать с регистрами напрямую? Есть несколько больших преимуществ:

  • Скорость работы: чтение/запись регистра выполняется максимально быстро, что позволяет ускорить работу с МК (например дёргать пины вручную вместо ). Максимальная скорость работы с периферией МК нужна далеко не всегда, поэтому если вам не нужно сэкономить несколько микросекунд – с регистрами можно даже не связываться.
  • Объём памяти: прямая работа с регистрами позволяет максимально компактно работать с периферией МК, читая и записывая только нужные биты, поэтому написанный под свои задачи конкретный код займёт меньше места, чем чьи-то готовые универсальные функции и библиотеки (например тот же digitalWrite или работа с Serial). При работе с Ардуино можно не заморачиваться по этому поводу практически никогда, а вот если делать проект на ATTiny – там придётся ужимать код вплоть до байта.
  • Гибкость настройки: работа с микроконтроллером напрямую при помощи регистров позволяет очень гибко настраивать периферию под свои задачи. Дело в том, что все существующие Ардуино-библиотеки охватывают чуть больше половины всех возможностей микроконтроллера! Огромное количество настроек и полезных трюков не описано нигде, кроме даташита, и для их использования нужно уметь читать этот самый даташит и работать с регистрами.

В микроконтроллерах серии ATmega/ATtiny регистры 8 битные, то есть регистр – это переменная типа . Насколько мы знаем, байт это число от 0 до 255, получается каждый регистр имеет 255 настроек? Нет, логика здесь совсем другая: байт это 8 бит, то есть один регистр хранит 8 настроек, которые можно включить/выключить. Давайте для примера рассмотрим один из регистров таймера 1, под названием . Картинка из даташита на ATmega328p:
Регистр , как и положено здоровому байту, состоит из 8 бит. Почти каждый его бит имеет имя (кроме 5-го, в этом МК он не используется). Что делает каждый бит и регистр – самым подробным образом расписано в даташите. Имена всех битов и регистров заданы в компиляторе, то есть создавать переменные с такими же именами нельзя. Изменять значения битов также нельзя, они являются константами:

int WGM12;  // приведёт к ошибке
CS11 = 5;   // приведёт к ошибке

Но считать значение бита по его названию можно! Причём значение будет равно его номеру в регистре, считая справа. равен 1, равен 4, равен 7 (см. таблицу выше).

Думаю здесь всё понятно: есть регистр (байт), имеющий уникальное имя и состоящий из 8 бит, каждый бит также имеет уникальное имя, по которому можно получить номер этого бита в байте его регистра. Осталось понять, как этим всем пользоваться.

Регистр связи LR (R14)[]

Регистр LR (Link Register) используется в следующих случаях:

  • в командах BL, BLX и BLXNS;
  • при выполнении прерываний.

Перечисленные выше команды применяются для вызова подпрограмм, при этом в LR помещается адрес команды, следующей за BL или BLX, либо код возврата из функции (FNC_RETURN) для команды BLXNS.

В случае возникновения прерывания в процессорах A- и R-профилей в LR заносится значение PC, на 4 или 8 превосходящее адрес команды, выполняемой непосредственно перед прерыванием; подробнее об этом говорится в разделе «Обработка прерываний в A- и R-профилях». В процессоре M-профиля при прерывании в LR заносится специальный код, называемый в документации EXC_RETURN и определяющий, как необходимо выполнять возврат из обработчика данного прерывания (см. раздел «Обработка прерываний в M-профиле)».

Стандартные соглашения о связях

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

  • В качестве указателя стека всегда используется регистр SP (R13). Стек растёт вниз, SP указывает на последнее используемое слово. Эти правила полностью соответствуют аппаратным требованиям набора команд Thumb.
  • Для передачи параметров в вызываемую подпрограмму могут использоваться регистры R0–R3. Если необходимо передать параметр, по размерам превышающий слово, при использовании обычного порядка слов «младший–старший» младшее слово помещается в регистр с меньшим номером; при использовании порядка «старший–младший» — в регистр со старшим номером. Если параметров слишком много, дополнительные параметры передаются через стек. Кроме того, при наличии арифметического сопроцессора для передачи параметров могут использоваться его регистры, но их использование здесь не обсуждается.
  • Возврат результатов осуществляется через регистры R0–R3.
  • Вызываемая подпрограмма обязана сохранять значения регистров R4–R11, а также корректно восстанавливать значение указателя стека.
  • Регистры R0–R3, R12 и LR, а также флаги регистра состояния вызываемой подпрограммой могут свободно изменяться.
  • Компоновщик при связывании вызовов подпрограмм может использовать регистр R12 в качестве рабочего, поэтому подпрограммы не могут рассчитывать на сохранность его содержимого, если используют вызовы подпрограмм из других модулей.
  • В ряде систем R7 хранит значение, зависящее от системы (например, адрес локальной памяти потока — TLS). В таких системах изменять этот регистр обычно запрещается.

Похожие термины:

  • список владельцев зарегистрированных акций, который ведет компания или по ее поручению юридическая фирма-регистратор.

  • (register of members) Список компаний (members of a company), который обязаны иметь все британские компании в зарегистрированном офисе (registered office) или по месту его составления (при условии, что сведения об этом месте

  • (share register) Реестр, ведущийся компаниями с ограниченной ответственностью, содержащий сведения о фамилиях и адресах акционеров, а также тип и число акций, принадлежащих каждому акционеру. Запись в ре

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

  • регистры, которые ведутся в форме регистров учета государственных краткосрочных бескупонных облигаций (ГКО) и облигаций федерального займа (ОФЗ) и регистров учета иных ценных бумаг. Подразделяют

  • См. Регистр акций

  • перечень единиц (объектов наблюдения), создаваемый в соответствии с решаемыми в данной сфере деятельности задачами.

  • регистры, которые ведутся с целью отражения операций с собственными ценными бумагами профессионального участника. Для учета государственных ценных бумаг, с которыми совершается сделка, регистры

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

  • регистры, предназначенные для отражения информации о сделках, совершенных профессиональным участником за счет и по поручению клиентов. Должны содержать следующую информацию: дата совершения сде

  • регистр, в который занесены все коммерческие фирмы.

  • См. Ллойд

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

  • регистры, предназначенные для обобщения информации о расчетах по операциям с клиентами. Ведутся в разрезе аналитических счетов учета расчетов как по денежным средствам, так и по ценным бумагам, п

  • регистры, в которые вносится информация о всех сделках с ценными бумагами, поступлении и выплате денежных средств в течение рабочего дня. Регистры должны содержать следующую информацию: дата сдел

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

  • (charges register) 1. См.: регистрация земли (land registration). 2. См.: регистр залогов (register of charges).

  • Дополнительный бухгалтерский регистр, содержащий детальную информацию об акциях, принадлежащих каждому акционеру.

  • регистр, открытый в клиринговой организации для учета ценных бума, денежных средств, размещенных на торговых счетах, и обязательств участника клиринга по совершенным сделкам с ценными бумагами [27

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

Понравилась статья? Поделиться с друзьями:
Шесть струн
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: