Два языка при работе с регистрами

Кто любит RISC в жизни, заходим, не стесняемся.
junior_t
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Вс ноя 13, 2022 17:41:26

Два языка при работе с регистрами

Сообщение junior_t »

Всем привет, уважаемые коты!

Прошу не кидать в меня тапками за тупой вопрос, но я действительно кое-что не догоняю.
Я пытаюсь разбирать чужие коды и с удивлением обнаруживаю, что при работе с регистрами разные люди используют разный код, мне приходится "переводить" с одного языка (понимаю, что везде Си, но я не знаю, как корректно выразиться) на другой. Например, человек инициализирует I2C и пишет:

Код: Выделить всё

	SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN); //Запуск тактирование порта B
	SET_BIT(RCC->APB2ENR, RCC_APB2ENR_AFIOEN); //Запуск тактирования альтернативных функций
	SET_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN); //Запуск тактирования I2C1
....
	//Настройки ножек SDA и SCL
	//PB7 SDA (I2C Data I/O) Alternate function open drain
	MODIFY_REG(GPIOB->CRL, GPIO_CRL_CNF7_Msk, 0b11 << GPIO_CRL_CNF7_Pos); //Alternate function open drain
	MODIFY_REG(GPIOB->CRL, GPIO_CRL_MODE7_Msk, 0b11 << GPIO_CRL_MODE7_Pos); //Maximum output speed 50 MHz
или

Код: Выделить всё

 tmpreg = READ_BIT(RCC->APB1ENR, RCC_APB1ENR_I2C1EN);
  //Disable  acknowledge on Own Address2 match address
  CLEAR_BIT(I2C1->OAR2, I2C_OAR2_ENDUAL);
Окей, но другой человек при инициализации I2C пишет

Код: Выделить всё

	RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;	// enable GPIOB

	GPIOB->AFR[1] |= (4 << (4 * 0));	// PB8 - I2C1_SCL - for AF4
	GPIOB->AFR[1] |= (4 << (4 * 1));	// PB9 - I2C1_SDA - for AF4

	GPIOB->MODER &= ~(GPIO_MODER_MODER9 |GPIO_MODER_MODER8);	// AF open drain mode, external pull-ups
	GPIOB->MODER |= (GPIO_MODER_MODER9_1 |  GPIO_MODER_MODER8_1);
	GPIOB->OTYPER |=(GPIO_OTYPER_OT_9 |GPIO_OTYPER_OT_8);
То есть в одном случае используются команды SET_BIT, MODIFY_REG, CLEAR_BIT, READ_BIT и т.д. В другом загадочное |=, &= ~ и иже с ними.
Как же соотносятся между собой эти команды?
Реклама
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение Martian »

пишем #define SET_BIT(a, b) a |= b https://learn.microsoft.com/ru-ru/cpp/p ... w=msvc-170

и теперь запись вида SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN);
при компиляции станет согласно этому define в нормальном виде RCC->APB1ENR |= RCC_APB2ENR_IOPBEN
О том, что такое #define и прочие подобные штучки и как они применяются лучше прочитать в учебниках (справке) среды разработки и языкам С и С++, например, по ссылке выше в частности и ниже - более глобально.
Там много полезного. Например, посмотрите на такое: #ifdef

https://learn.microsoft.com/ru-ru/cpp/p ... w=msvc-170

Добавлено after 14 minutes 13 seconds:
Но вообще, оба примера примерно равны, и в первом применение #define не максимально удобно: программисту и так понятно, как установить бит. Зато он может забыть, что делает установка этого бита. Поэтому, конструкция вида

#define ENABLE_I2C RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;

намного информативней, упрощает чтение, написание и отладку кода, снижает вероятность ошибки и необходимость комментариев. Достаточно теперь написать ENABLE_I2C и всем понятно, что это.
Реклама
junior_t
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Вс ноя 13, 2022 17:41:26

Re: Два языка при работе с регистрами

Сообщение junior_t »

Спасибо, но из этой ссылки мне не очевидно, например, то, чем станет при компиляции запись MODIFY_REG(GPIOB->CRL, GPIO_CRL_CNF7_Msk, 0b11 << GPIO_CRL_CNF7_Pos) или CLEAR_BIT(I2C1->OAR2, I2C_OAR2_ENDUAL);
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение Martian »

Конечно не очевидно, не только Вам, но и любому другому. Но где-то у Вас в проекте есть заголовочный файл, где всем этим CLEAR_BIT описано определение. Я не знаю, какую среду Вы используете, но в большинстве можно на CLEAR_BIT кликнуть правой кнопкой мышки и посмотреть, где он и как определен (и прочие свойства)

Добавлено after 5 minutes 47 seconds:
В CubeIDE достаточно навести мышкой курсор на него и подождать
Реклама
Эиком - электронные компоненты и радиодетали
junior_t
Первый раз сказал Мяу!
Сообщения: 27
Зарегистрирован: Вс ноя 13, 2022 17:41:26

Re: Два языка при работе с регистрами

Сообщение junior_t »

Вы подразумеваете это?
Вложения
ESW0hPbenXE.jpg
(68.92 КБ) 113 скачиваний
Реклама
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение Martian »

да
Реклама
jcxz
Мудрый кот
Сообщения: 1726
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Два языка при работе с регистрами

Сообщение jcxz »

[uquote="Martian",url="/forum/viewtopic.php?p=4450167#p4450167"]пишем #define SET_BIT(a, b) a |= b[/uquote]Безграмотная запись.

[uquote="Martian",url="/forum/viewtopic.php?p=4450167#p4450167"]#define ENABLE_I2C RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;[/uquote]Аналогично.
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение Martian »

ну так не ленись, напиши про скобочки, области видимости и про идиотов, которые начнут вставлять так, что умудрятся напортачить. Мне вот лень было, я лишь описал принцип и дал ссылки. Приступай, брякало, а я потом почитаю :tea:
Аватара пользователя
>TEHb<
Друг Кота
Сообщения: 5744
Зарегистрирован: Ср ноя 11, 2009 17:19:30
Откуда: Воронеж
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение >TEHb< »

Где-то внутри вот этого
junior_t писал(а):SET_BIT(RCC->APB2ENR, RCC_APB2ENR_IOPBEN)
рано или поздно происходит вот это
junior_t писал(а):RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
В первом случае вызывается функция (ну или псевдофункция), которая призвана распихать байтики. Как и что она при этом делает программиста в общем случае волновать не должно. А во втором просто происходит запись в регистр. Вот так вот просто и бесхитростно.
"Привет!" - соврал он.
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение Martian »

не совсем корректное название: если назовешь это функцией (а не макросом), то придется считать, что скомпилируется как функция, с вызовом, возвратом, пушпопом всего и вся и т. д.
а в данном случае работает препроцессор.
Аватара пользователя
>TEHb<
Друг Кота
Сообщения: 5744
Зарегистрирован: Ср ноя 11, 2009 17:19:30
Откуда: Воронеж
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение >TEHb< »

Препроцессор это вообще лучше всего. А ещё может быть inline функция, вызов которой тоже не произойдёт. Тут уж всякие тонкости. Я лишь хотел сказать, что всё это всё равно приводит к записи в регистр и многие предпочитают не плодить сущности (функции, макросы и тд), а тупо сразу писать по адресам и капец.
"Привет!" - соврал он.
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение Martian »

ну... тут спорно что лучше. jcxz выше сделал мне замечание, что я написал безграмотно, и это верно: есть риск ошибки, которая легко пролезет через компилятор. Недостатков у макросов хватает. На мой взгляд, всё хорошо в меру. Написать # Motor_On гораздо удобнее, чем писать безликую установку бита, но запихивать громадный кусок кода, с условиями и проч. - эт мне как-то не нравится, а вот микрософт по ссылке выше считает, что норм.
jcxz
Мудрый кот
Сообщения: 1726
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Два языка при работе с регистрами

Сообщение jcxz »

[uquote=">TEHb<",url="/forum/viewtopic.php?p=4451480#p4451480"]
junior_t писал(а):RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
А во втором просто происходит запись в регистр. Вот так вот просто и бесхитростно.[/uquote]Ничего подобного. Не "просто запись", а 3 операции: чтение, модификация, запись.
И скорей всего бессмысленные. Так как наверняка можно обойтись одной только записью. Но миллион мух привыкли лететь одним общим путём, не думая куда и зачем....
Аватара пользователя
>TEHb<
Друг Кота
Сообщения: 5744
Зарегистрирован: Ср ноя 11, 2009 17:19:30
Откуда: Воронеж
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение >TEHb< »

Есть хорошая альтернатива? Это же не GPIO со специальными регистрами для этого.
"Привет!" - соврал он.
jcxz
Мудрый кот
Сообщения: 1726
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Два языка при работе с регистрами

Сообщение jcxz »

В большинстве случаев программы не манипулируют этими битами (разрешения тактирования) в процессе своей работы. Просто включают их все в нужное положение при старте. Зачем тогда эти |= отдельно для каждого бита? Просто - одна запись всех бит в регистр сразу.
Аватара пользователя
>TEHb<
Друг Кота
Сообщения: 5744
Зарегистрирован: Ср ноя 11, 2009 17:19:30
Откуда: Воронеж
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение >TEHb< »

jcxz писал(а):Зачем тогда эти |= отдельно для каждого бита?
Очевидно, чтобы не затереть другие биты. В каждом кусочке программы включается и настраивается своя система. Можно и все сразу записать, если хочется сэкономить пару тактов. Кроме каких-нибудь особых случаев, когда порядок важен, конечно. Тут уж думать надо стоит ли наглядность программы такого незначительного ускорения.
"Привет!" - соврал он.
jcxz
Мудрый кот
Сообщения: 1726
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Два языка при работе с регистрами

Сообщение jcxz »

[uquote=">TEHb<",url="/forum/viewtopic.php?p=4451848#p4451848"]Очевидно, чтобы не затереть другие биты. В каждом кусочке программы включается и настраивается своя система.[/uquote]Посмотрите внимательнее на его код: у него там рядом два бита в одном регистре таким образом устанавливаются. А значит это не потому что "именно так надо", а потому что автор не дал себе труда включить голову. Потому что все мухи так летают. 8)
Да и если бы реально "в каждом кусочке программы включается и настраивается своя система", то модификация этих битов должна была быть завёрнута в критическую секцию. Или в запрет прерываний. Или модификация осуществлялась бы с использованием эксклюзивного доступа. А ничего этого нет.
Поэтому тут как обычно: "так все делают и я так сделал". :dont_know:
Аватара пользователя
>TEHb<
Друг Кота
Сообщения: 5744
Зарегистрирован: Ср ноя 11, 2009 17:19:30
Откуда: Воронеж
Контактная информация:

Re: Два языка при работе с регистрами

Сообщение >TEHb< »

Судя по всему, речь идёт об СТМ32. Буду придерживаться этой версии. Так вот.
jcxz писал(а):у него там рядом два бита в одном регистре таким образом устанавливаются
И соглашусь и нет. Что И2Ц и порты висят на одной шине это просто так удачно совпало. А вот если надо будет связь по УСАПП? Придётся разваливать код обратно на запись двух регистров. Аналогично с регистром AFR. Условно, ноги 7 и 9 уже потребуют запись в два регистра. В данном конкретном случае можно и объединить, но стоит ли оно того? Ну вот мне лично кажется, что далеко не всегда.
jcxz писал(а):модификация этих битов должна была быть завёрнута в критическую секцию. Или в запрет прерываний.
Зачем? Запись в эти регистры возможна в прерываниях? Тогда согласен, нужно. Если прерывания вообще уже включены на данном этапе.
"Привет!" - соврал он.
jcxz
Мудрый кот
Сообщения: 1726
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Два языка при работе с регистрами

Сообщение jcxz »

[uquote=">TEHb<",url="/forum/viewtopic.php?p=4451869#p4451869"]Зачем? Запись в эти регистры возможна в прерываниях? Тогда согласен, нужно. Если прерывания вообще уже включены на данном этапе.[/uquote]Вы же сами писали: "В каждом кусочке программы включается и настраивается своя система". Эти кусочки могут быть в разных задачах или даже в ISR. Вот если программа разбита на отдельные драйвера устройств, каждый из которых включает/выключает нужную ему периферию, то нужно обязательно позаботиться об атомарности модификации битов в общих регистрах (тем или иным способом).
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Два языка при работе с регистрами

Сообщение COKPOWEHEU »

Ничего подобного. Не "просто запись", а 3 операции: чтение, модификация, запись.
И скорей всего бессмысленные.
В большинстве случаев программы не манипулируют этими битами (разрешения тактирования) в процессе своей работы.
Вы сами же и озвучили причину, почему ради чтиаемости кода почти всегда жертвуют парой тактов на старте, где это все равно никого не волнует.
Ответить

Вернуться в «ARM»