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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

как не о том?! написано же: берет все биты и записывает обратно установенные в 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 :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

как не о том?! написано же: берет все биты и записывает обратно установенные в 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 и атомарности (я кстати нигде это тождественными понятиями не записывал).
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

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

А тут как речь про обычные переменные шла, которые как бы в РОН, как правило, если они локальные. А это ANDI/ORI, достаточно атомарные.
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

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

Тут вот вопрос - актуально ли это для С. Знает ли компилятор на каких "подархитектурах" AVR SBI/CBI работает независимо с битом, а где как RMW.
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 1
Зарегистрирован: Пн май 27, 2019 00:34:25

Сообщение eduard_upk »

Подскажите, в чем дело.
Рабочая среда: 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

Изображение

Изображение

Изображение
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

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

Добавлено after 5 minutes 17 seconds:
Вот вы говорите вбросил. Это разве вбросил? А тем временем GCC 10 теперь вот так умеет.
Изображение
Мопед не мой, пример с офсайта.
Pi.png
(9.95 КБ) 372 скачивания
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

VladislavS писал(а):А тем временем GCC 10 теперь вот так умеет
а вот так умеет?

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

#define правда true
#define брехня false
typedef bool логическое;

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

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

ну, теперь-то заживём! :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Я не об этом. Они ведь серьёзно считают, что Пи это знаковая целая константа, равная 3. Спасибо хоть константа.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 3386
Зарегистрирован: Пн окт 11, 2010 19:00:08

Сообщение Мурик »

VladislavS писал(а):Они ведь серьёзно считают, что Пи это знаковая целая константа, равная 3.
Потом будут думать откуда погрешности в расчетах...
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

Жесть! Я просто думал как нибудь скукожить подпрограммы для индикатора, они непомерно много места занимают, а тиня нерезиновая :)
ПростоНуб писал(а):Ну и кодировку учитывайте при кириллице. Если вдруг в 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
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

int strlegnt = MY_STRING_LEN
И зачем? Зачем под это тратить память, когда размер строки во флэше всё-равно неизменен всегда?
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

NStorm писал(а):И зачем? Зачем под это тратить память, когда размер строки во флэше всё-равно неизменен всегда?
ну надо было передать циклу в качестве значения. Или не надо?

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

for (i = 0; i < (strlegn-1); i ++)
{}
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Внезапно, но точно также:

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

for (i = 0; i < (MY_STRING_LEN-1); i ++)
PS: Я всё-еще точно также не вижу смысл заводить отдельные макросы чисто под sizeof().

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

for (i = 0; i < (sizeof(lcd_data)-1); i ++)
Даст тот же самый эффект, при это сразу видно размер какой строки берется.
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

Понял, спасибо.
А еще такой глупенький вопрос. Я могу функцию main объявить просто main() и это будет работать (я проверил). При этом не уточняя чем она является (void, int, и т.п). Какой тип она имеет, если это явно не указано?
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Shuspano",url="/forum/viewtopic.php?p=3841686#p3841686"]А еще такой глупенький вопрос.[/uquote] Это точно!

[uquote="Shuspano",url="/forum/viewtopic.php?p=3841686#p3841686"]Я могу функцию main объявить просто main() и это будет работать (я проверил).[/uquote]Зачем? Ведь для каждого действия должна быть мотивировка.

[uquote="Shuspano",url="/forum/viewtopic.php?p=3841686#p3841686"]Какой тип она имеет, если это явно не указано?[/uquote]int
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Shuspano писал(а):Какой тип она имеет, если это явно не указано?
в микроконтроллерном программировании практически всегда совершенно все равно, какой тип у функции main, поскольку эта функция никуда результат своей работы не возвращает - некуда просто.

но в Си вообще все, о чем не сказано прямо, имеет тип int

Добавлено after 4 minutes 46 seconds:
Shuspano писал(а):ну надо было передать циклу в качестве значения. Или не надо?
во многих случаях именно не надо.

концепция строк в Си подразумевает, что все они заканчиваются нулем, поэтому можно в цикле перебирать символы строки от начала, пока не дойдешь до нуля. т.е. заранее знать размер строки нет необходимости во многих случаях. а когда это необходимо (для резервирования места в памяти) то для статических переменных лучше применять sizeof, а для динамических - функцию strlen.

Добавлено after 4 minutes 46 seconds:
традиционно вот так работают со строкой посимвольно:

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

void my_func(char *s){
   while(*s){
      // тут обрабатываем очередной символ *s
      s++; // и берем следующий символ
   }
}
для строки в памяти программ надо делать так

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

void my_func(const __flash char *s){
   while(*s){
      // тут обрабатываем очередной символ *s
      s++; // и берем следующий символ
   }
}
а если сделать вот так, то будет все равно, где размещена строка (в ОЗУ или FLASH):

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

void my_func(const __memx char *s){
   while(*s){
      // тут обрабатываем очередной символ *s
      s++; // и берем следующий символ
   }
}
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Грызет канифоль
Аватара пользователя
Сообщения: 275
Зарегистрирован: Вс окт 20, 2019 13:03:56

Сообщение Shuspano »

Спасибо за разъяснения.
Но вот возник вопрос. строка с нулем на конце не может же вмещать 0x00 как данные? Иначе когда этот ноль попадет в сравнивающую подпрограмму, он будет расценен как окончание?
Поставщик валерьянки для Кота
Сообщения: 1978
Зарегистрирован: Ср июл 17, 2013 13:55:57

Сообщение NStorm »

Может. Но, да, \0 будет расценен как конец строки. Это актуально для стандартных функций для текстовых строк. В своих обработчиках вы вольны делать сами как вам надо. Включая тот вариант ,как вы делали ранее - заранее "прошагивая" весь массив (кроме последнего \0) через for. Пример ARV выше остановится на нуле, т.к. соб-но цикл while там идет пока символ не 0. Аналогично делают и всякие стандартные строковые функции, вроде strcmp. Ну как бы считается, что строка - это именно строка и \0 она не может содержать в середине. Если у вас произвольный набор данных, который может этот ноль содержать, то да, надо еще длину отдельно хранить, если строка не константа. Для констант остается sizeof().
Собутыльник Кота
Аватара пользователя
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Сообщение ПростоНуб »

NStorm, самое веселое начинается в юникоде. Если в UTF-8 нулевой байт спокойно можно расценивать, как конец строки, то в UTF-16 это совсем не так.
Ответить

Вернуться в «Разные вопросы по МК»