Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 09:30:01

Имхо, с атомарностью многострочность никак не связана.

А SBI, если я не ошибаюсь (давно асм в руки брал), инструкция одна, но работает именно в три этапа со всеми побочными эффектами.

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 09:54:51

ARV, связана. Если a объявлена volatile, то для этих примеров компилятор сформирует разный код.

Код:
a = (a | ((1<<2) | (1<<0))) & ~((1<<4) | (1<<1));

Код:
a |= ((1<<2) | (1<<0));
a &= ~((1<<4) | (1<<1));


А если не volatile, то, скоре всего, код сфорируется одинаковый.

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 09:55:52

Нет там никаких 3х этапов, путаете что-то.
И конечно не совсем атомарно, будет всё-равно RMW, при этом M в 2 операции - AND, OR. Но запись будет именно в 1 операцию уже.

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 13:06:42

А вот такой вопросик. Как узнать длину строки в такой конструкции, не считая это вручную:
Код:
const __flash char lcd_data[] = "строка";

В ассемблере, транслятор может посчитать расстояние между метками, которыми ограничена строка, и так можно узнать ее длину. А тут как это делается?

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 13:18:41

Shuspano,

Код:
#define MY_STRING "строка"
#define MY_STRING_LEN sizeof(MY_STRING)

const __flash char lcd_data[] = MY_STRING;

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 13:26:54

Shuspano, просто sizeof(lcd_data) тоже будет работать.

Добавлено after 2 minutes 13 seconds:
Только ес-но реальный размер, с учетом терминирующего \0 в конца:
Код:
volatile uint8_t a = 1;
const __flash char lcd_data[] = "stroka";

int main() {
  a = sizeof(lcd_data);
  56:   87 e0           ldi     r24, 0x07       ; 7
  58:   80 93 60 00     sts     0x0060, r24     ; 0x800060 <__data_start>

Возвращает 7 байт (stroka + \0). Если надо именно длину текста посчитать - sizeof() - 1 :)

Добавлено after 1 minute 8 seconds:
Ну и кодировку учитывайте при кириллице. Если вдруг в utf-8 запишите, будет 13 байт соотв, по 2 байта на символ.

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 13:32:29

ПростоНуб писал(а):связана
я сказал "напрямую", т.е. невозможно заранее предсказать, какой именно код получится от 1, 2 или 3 строчной записи одного и того же действия. например, в случае не-volatile может и 100500 строк превратиться в одну команду :)))
NStorm писал(а):Нет там никаких 3х этапов, путаете что-то.
не поленился, поднял документы... ошибаетесь вы:
Изображение
Shuspano писал(а):Как узнать длину строки в такой конструкции, не считая это вручную:
в конкретно вашем примере, как вам посоветовали, через sizeof. но вообще-то для этого есть в модуле avr/pgmspace.h специальная функция strlen_P, которая вычислит длину любой строки в памяти программ.
Вложения
screenshot-file2.dzsc.com-2020.05.png
(64.35 KiB) Скачиваний: 369

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 13:39:53

ARV, это не о том. Полностью же написано всё. Речь идет о том, что в Status Flags нельзя с помощью инструкций CBI/SBI записать, т.к. они работают только с регистрами с 0х00 по 0х1F. Поэтому чтобы записать в Status Flags будет операция RMW - считается Status в один из этих регистров, затем он меняется с помощью CBI/SBI и записывается назад. Если будете менять регистр с 0x00 по 0x1F - он поменяется напрямую SBI/CBI атомарно и в одну операцию (которая 2 такта Fclk выполняется).

EDIT: Тут выше я уже сам запутался и не так перевел. Действительно, в некоторых старых AVR возможно эти инструкции так криво работали. В новых - неактуально, ниже в комментарии описал.
Последний раз редактировалось NStorm Чт май 14, 2020 18:33:14, всего редактировалось 1 раз.

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 14:08:33

как не о том?! написано же: берет все биты и записывает обратно установенные в 1 - чистое RMW
еще тут https://electronix.ru/forum/index.php?a ... ent=275082 было доказательство от уважаемого ReAl

Добавлено after 4 minutes 41 second:
кстати, RMW и атомарность тут тоже не совсем связаны. атомарность - это то, что не может быть прервано по ходу исполнения, так? RMW-операция не может быть прервана, но выолняется в три этапа, что может давать побочные эффекты, если состояние бита меняется от чтения регистра.

Добавлено after 2 minutes 22 seconds:
кстати, даже стало любопытно, что будет, если послать в USART байт 0xFF, а в обработчике прерываний сделать CBI UDR, 1 ? :))) хотя, конечно, это не совсем то, о чем мы тут говорим, но зато убедительно докажет RMW или не-RMW команда CBI/SBI :)))

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 15:14:58

как не о том?! написано же: берет все биты и записывает обратно установенные в 1 - чистое RMW

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

кстати, даже стало любопытно, что будет, если послать в USART байт 0xFF, а в обработчике прерываний сделать CBI UDR, 1 ? :))) хотя, конечно, это не совсем то, о чем мы тут говорим, но зато убедительно докажет RMW или не-RMW команда CBI/SBI :)))

Тут не выйдет ) UDR всего лишь буфер. Регистры там внутренние другие RXB, TXB. Поэтому UDR в принципе не поддерживает RMW. Потому что читать вы будете из другого регистра входящего буфера.

Добавлено after 10 minutes 53 seconds:
Короче не всё так однозначно. По ссылке же следующий пост сразу где эти фраза из ДШ уже по-другому звучит:
Цитата из ДШ мега48

Some of the Status Flags are cleared by writing a logical one to them. Note that, unlike most other AVRs, the CBI and SBI instructions will only operate on the specified bit, and can therefore be used on registers containing such Status Flags. The CBI and SBI instructions work with registers 0x00 to 0x1F only.

И такое поведение команд CBI и SBI свойственно для всех АВРок, начиная с тини13, то есть, все выпущенные за последние 3 года модели. Неужели некоторые уже 3 года не читали даташитов? А вера здесь не при чём.

Т.е. уже чистый сброс/установке без всяких RMW.

И вот еще: https://www.avrfreaks.net/forum/sbicbi-readmodifywrite
I believe that these are actually incorrect. In older AVRs the sbi/cbi opcodes did indeed affect other bits in the register and therefore one had to be careful not to use them in registers that contained interrupt flags. However, as the line I quoted above says, in newer AVRs these opcodes only affect the desired bit. Likely these are just copy-paste errors from older datasheets.


В общем для "новых" (те, что после tiny13 были) AVR не актуально. Для старых тоже надо смотреть, как бы не ошибочная копипаста в ДШ.

В древних AVR да, получается было когда-то CBI/SBI не прямой записью, а атомарным RMW получается по сути. Т.е. они атомарны (не могут прерываться), но при этом RMW. Соб-но и есть ответ на вопрос не связи RMW и атомарности (я кстати нигде это тождественными понятиями не записывал).

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 15:36:27

Странно вообще, что речь пошла про SBI/CBI. VladislavS вбросил, и пошло-поехало.

А тут как речь про обычные переменные шла, которые как бы в РОН, как правило, если они локальные. А это ANDI/ORI, достаточно атомарные.

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 18:36:34

WiseLord, ну как обычно, углубились. Интересно на самом деле получается. Я не знал, что где-то оно так работало и вопрос не так просто про CBI/SBI инструкции. ARV правильно написал сначала, признаю, что я сам уже с переводом напутал и действительно скрин из мануала выше имеет отношение к тому, что SBI/CBI на каких-то AVR могут выполняться как RMW. Но на новых AVR это уже не так. Тоже стоит учитывать такие различия.

Тут вот вопрос - актуально ли это для С. Знает ли компилятор на каких "подархитектурах" AVR SBI/CBI работает независимо с битом, а где как RMW.

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 19:15:06

Подскажите, в чем дело.
Рабочая среда: Keil, участок кода:
......
#define TICK_PER_CURRENT_PERIOD (200)
......
const uint8_t VALUE_TICK_PER_CURRENT_PERIOD = TICK_PER_CURRENT_PERIOD;
......
const uint8_t SCHEDULE1 = (VALUE_TICK_PER_CURRENT_PERIOD + 1);


Проблема:
VALUE_TICK_PER_CURRENT_PERIOD != TICK_PER_CURRENT_PERIOD;
SCHEDULE1 != (VALUE_TICK_PER_CURRENT_PERIOD + 1);
и т.д.

VALUE_TICK_PER_CURRENT_PERIOD == 40 вместо 200
TICK_PER_CURRENT_PERIOD == 200 как и должно быть
SCHEDULE1 == 40 вместо 201

Изображение

Изображение

Изображение

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 20:15:33

А если всё же запустить программу?

Добавлено after 5 minutes 17 seconds:
Вот вы говорите вбросил. Это разве вбросил? А тем временем GCC 10 теперь вот так умеет.
Изображение
Мопед не мой, пример с офсайта.
Pi.png
(9.95 KiB) Скачиваний: 259

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 22:36:56

VladislavS писал(а):А тем временем GCC 10 теперь вот так умеет
а вот так умеет?
Код:
#define правда true
#define брехня false
typedef bool логическое;

логическое значение = брехня;
:)))

Добавлено after 4 minutes 58 seconds:
сцуко, умеет! сам выяснил...

ну, теперь-то заживём! :)))

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 22:42:50

Я не об этом. Они ведь серьёзно считают, что Пи это знаковая целая константа, равная 3. Спасибо хоть константа.

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 23:05:28

В военное время Пи может достигать значения 4 и даже более, подумаешь...

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 23:18:49

VladislavS писал(а):Они ведь серьёзно считают, что Пи это знаковая целая константа, равная 3.
Потом будут думать откуда погрешности в расчетах...

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 23:41:51

Жесть! Я просто думал как нибудь скукожить подпрограммы для индикатора, они непомерно много места занимают, а тиня нерезиновая :)

ПростоНуб писал(а):Ну и кодировку учитывайте при кириллице. Если вдруг в utf-8 запишите, будет 13 байт соотв, по 2 байта на символ.
,

Разумеется. Индикатор по ходу только US-ASCII понимает. Ну еще что-то японокитайское, я увидел это, когда накосячил с передачей тетрад. Есть с кириллицей, но он новый.
ПростоНуб писал(а):
Shuspano,
Код:
#define MY_STRING "строка"
#define MY_STRING_LEN sizeof(MY_STRING)

const __flash char lcd_data[] = MY_STRING;


спасибо большое, все заработало.
добавил еще такое:
int strlegnt = MY_STRING_LEN

Re: Вопросы по С/С++ (СИ)

Чт май 14, 2020 23:50:56

int strlegnt = MY_STRING_LEN

И зачем? Зачем под это тратить память, когда размер строки во флэше всё-равно неизменен всегда?
Ответить