STM32 новичку в ARM что к чему

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

VladislavS, на компе можно просто popcnt вызвать же!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Изображение
Topic.png
(25.65 КБ) 728 скачиваний
И на этапе компиляции.
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18677
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Я так и не понял восторгов: если программист вызывает функцию для того, чтобы посчитать биты в заранее известной константе, разумно ли вводить это в стандарт? Или просто константы будут запрещены?
Что-то я не понимаю восторга: вплоть до 64-битных констант число единичных бит вычисляется не-двоешником практически в уме...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="ARV",url="/forum/viewtopic.php?p=3924331#p3924331"]Я так и не понял восторгов: если программист вызывает функцию для того, чтобы посчитать биты в заранее известной константе, разумно ли вводить это в стандарт? Или просто константы будут запрещены?[/uquote]
Такая функция используется в либе портов, допустим есть такой список:

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

PinList<PA5, PA6, PA7, PB10, PA0, PA1> pins;
Будет найдено две последовательности, в обoих пины идут в обратном порядке: PA0, PA1 и PA5, PA6, PA7. Для каждой последовательности находятся маски 0x03 и 0xE0, если в маске больше двух бит, то будет использована реверсная инструкция RBIT, иначе ее применение не оправдано. Все это происходит на этапе компиляции и никакие константы заранее не известны :)
Реклама
Эиком - электронные компоненты и радиодетали
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18677
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

мда... занятно.

этак скоро дисциплину "программирование" в ВУЗах преподавать перестанут, ибо эфект обучения будет нулевой: достаточно функцию вычисления корней квадратного уравнения (классика!) обозвать constexpr, и получить на выходе что-то типа mov ax, 12 ret вместо всего алгоритма... :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

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

Сообщение VladislavS »

[uquote="ARV",url="/forum/viewtopic.php?p=3924331#p3924331"]посчитать биты в заранее известной константе, разумно ли вводить это в стандарт?[/uquote]Во-первых, константа может быть неизвестна, а быть результатом сложных преобразований типов и данных. Во-вторых, это может быть и не константа вовсе, тогда компилятор будет сам разбираться что с ней делать - вызовет ли что-то похожее на мою функцию в рантайме или у процессора есть специальная инструкция для этого. Главное, что мне не надо думать об этом, а думать о бизнеслогике.

Добавлено after 8 minutes 37 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=3924351#p3924351"]достаточно функцию вычисления корней квадратного уравнения (классика!) обозвать constexpr, и получить на выходе что-то типа mov ax, 12 ret вместо всего алгоритма... :)))[/uquote]Если на входе функции константные данные, то результат её "известен" до запуска программы. Так зачем тратить время программы на её выполнение? И C++ позволяет переложить это на плечи компилятора уже сейчас, а не "скоро".
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18677
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

VladislavS писал(а):И C++ позволяет переложить это на плечи компилятора уже сейчас, а не "скоро".
давным-давно в другой ветке я говорил, что мечта всех программистов заключается в том, чтобы было можно написать "сделай мне хорошо" - и это вся программа, а компилятор разберется, что именно будет хорошо... но это оффтоп и я больше не буду
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

Надеюсь, таки инструкцию popcnt и ей подобные внедрят в более свежие армы. Уж очень она хороша!
А еще инструкции, которые выдают самый старший единичный бит и самый младший единичный бит.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3924368#p3924368"]А еще инструкции, которые выдают самый старший единичный бит и самый младший единичный бит.[/uquote]
Уже есть CLZ, предварительно можно биты развернуть при помощи RBIT.
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

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

VladislavS писал(а):А вот так она у меня в библиотеке на С++ работает. Вычисляется на этапе компиляции, если аргумент позволяет.
В большинстве случаев не позволяет. Покажите что сгенерирует компиль если значение не константно, а например считывается из порта.

И думаю вы знаете что const в Си вовсе не делает переменную константой. Попробуйте в Си-коде заменить const на #define.
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="Мурик",url="/forum/viewtopic.php?p=3924574#p3924574"]В большинстве случаев не позволяет. Покажите что сгенерирует компиль если значение не константно, а например считывается из порта.[/uquote]
В том коде не может быть не константа - это будет ошибка компиляции.
Стоп, это другой пример, я думал это все еще про либу портов :) Тогда развернется в приличную функцию, но она такой в любом случае будет...
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 342
Зарегистрирован: Чт ноя 21, 2013 14:05:26
Откуда: Україна

Сообщение DJZEM »

Ох уж эти замудреные дядьки ))
Контактная информация:
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

Бонус для Eddy_Em :)
Спойлер

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

uint32_t getMinPriority(uint32_t value)
{
#ifdef __ARM_ARCH_6M__
	static const uint8_t table[32] = { 0, 1, 2, 24, 3, 19, 6, 25, 22, 4, 20, 10, 16, 7, 12, 26, 31, 23, 18, 5, 21, 9, 15, 11, 30, 17, 8, 14, 29, 13, 28, 27 };

	value = (value & -value) * 0x04D7'651F;
	return table[value >> 27];
#else
	return  __CLZ(__RBIT(value));
#endif
}

getMinPriority(0x0F00'00F0); // 4
getMinPriority(0x0F00'0000); // 24
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Мурик",url="/forum/viewtopic.php?p=3924574#p3924574"]
VladislavS писал(а):А вот так она у меня в библиотеке на С++ работает. Вычисляется на этапе компиляции, если аргумент позволяет.
В большинстве случаев не позволяет.[/uquote]Попытался вспомнить весь свой программистский опыт и не вспомнил когда бы я эту функцию применял на неконстантных данных. Наиболее близко это бит чётности в UART, который считается аппаратно.

[uquote="Мурик",url="/forum/viewtopic.php?p=3924574#p3924574"]Покажите что сгенерирует компиль если значение не константно, а например считывается из порта.[/uquote]Будет такой же вызов функции, как под первым спойлером. Природу не обманешь.

[uquote="Мурик",url="/forum/viewtopic.php?p=3924574#p3924574"]И думаю вы знаете что const в Си вовсе не делает переменную константой.[/uquote]Посмотрите ещё раз листинг. Самая натуральная константа, лежит себе в сегменте кода. Не константа будет вот так
СпойлерИзображение
C0.png
(64.5 КБ) 93 скачивания
[uquote="Мурик",url="/forum/viewtopic.php?p=3924574#p3924574"]Попробуйте в Си-коде заменить const на #define.[/uquote]Легко. Ничего это в данном случае не меняет.
СпойлерИзображение
C1.png
(57.12 КБ) 89 скачиваний
Если честно, другие компиляторы всё же могут вычислить эту функцию в С режиме в компайлтайме. Но вот конкретно для ARM на Compiler Exploer вот так. Увы и ах, он льёт воду на нашу мельницу :)

Надеюсь, предложения саму функцию заменить макросом не последует?

Добавлено after 10 minutes 17 seconds:
[uquote="Reflector",url="/forum/viewtopic.php?p=3924614#p3924614"]Бонус для Eddy_Em :)[/uquote]Опять ты со своими крестами. Он апострофы не понимает :)

Добавлено after 2 minutes 55 seconds:
[uquote="Reflector",url="/forum/viewtopic.php?p=3924614#p3924614"]

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

return __CLZ(__RBIT(value));
[/uquote]Не знаешь, GCC так и не научили __RBIT в компайлтайме считать?
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3924649#p3924649"]Не знаешь, GCC так и не научили __RBIT в компайлтайме считать?[/uquote]
Вроде нет. 10-й в этом или следующем месяце появится, может там будет.

Добавлено after 1 hour 31 minute 30 seconds:
Хм, а превью gcc 10 для ARM оказывается еще в начале лета появился...
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Сообщение a797945 »

[uquote="Reflector",url="/forum/viewtopic.php?p=3919380#p3919380"]...
Я в похожей ситуации его ловил на F1/F3, если volatile не добавлять:

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

for (int x = 0; x < 32; x++)
{
	uint8_t pixels = VRAM[pixelsOffset++];
	uint8_t attr = VRAM[attrOffset++];
	uint32_t index = scrTableIndex[pixels];
	uint32_t addr = (uint32_t)scrTable8 + 564 * (attr & 0x7F) + index;

	auto p = (volatile uint64_t*)addr;
	*buf++ = p[0];
	*buf++ = p[1];
}
[/uquote]

поясните, пожалуйста, почему приключился hardfault ?
и к чему здесь принуждает компилятор применение volatile ?
размещению p в озу?
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="a797945",url="/forum/viewtopic.php?p=3924833#p3924833"]поясните, пожалуйста, почему приключился hardfault ?
и к чему здесь принуждает компилятор применение volatile ?[/uquote]
Там использовалась большая таблица, внутри 16-ти битные значения, соответственно адрес выровнен по границе 2-х байт, но копирование происходит сразу по 32 бита, потому нужна поддержка невыровненного доступа или придется увеличивать таблицу в 2 раза, а она и так 70КБ. M3/M4 поддерживают невыровненный доступ не для всех инструкций копирования и компилятор как раз генерил LDRD где такой поддержки нет. А с volatile он подставлял пару LDR и все работало. Возможно это непосредственно связано с ограничениями налагаемыми на volatile переменные, но думаю другой компилятор может руководиться другими правилами кодогенерации, так что по нормальному тут нужно задействовать инлайн ассм, но т.к. это был тестовый проект, то оставил как есть... Для WS2812 нужно 24 байта на диод, там можно выровнять массив с таблицей и не переживать :)

ps. Да, на самом деле адрес был (volatile uint32_t*)addr и 4 копирования.
pps. Там, на мой взгляд, сама таблица достаточно интересная... Кто догадается как использовалась такая строка? :)

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

00000000100000001100000011100000111100001111100011111100111111101111111
11010101001010101101010111010100000101111101001000011010111101101000010
01011100010001001100101100100100111001101001101101111001000111010001101
110010100010110110011101110110001010110000101001111010110001100110001
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

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

VladislavS писал(а):Легко. Ничего это в данном случае не меняет.
У вас "неправильный" компилятор и он дает неправильный мед!
Вот GCC.
СпойлерИзображение
С константой тоже самое.
СпойлерИзображение
VladislavS писал(а):Надеюсь, предложения саму функцию заменить макросом не последует?
В этом нет необходимости. Будет предложение сменить компилятор на нормальный, а не то что вы используете, чтобы не вводить людей в заблуждение.
Собутыльник Кота
Аватара пользователя
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Reflector",url="/forum/viewtopic.php?p=3924614#p3924614"]

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

return  __CLZ(__RBIT(value));
[/uquote]Смотри какая красота!
СпойлерИзображение
CLZ.png
(51.3 КБ) 100 скачиваний
Добавлено after 10 minutes 11 seconds:
[uquote="Мурик",url="/forum/viewtopic.php?p=3924878#p3924878"]Будет предложение сменить компилятор на нормальный, а не то что вы используете, чтобы не вводить людей в заблуждение.[/uquote]У вас есть методика поделить компиляторы на нормальные и нет? Судя по логам, Compiler Exploer использует "/opt/compiler-explorer/arm/gcc-arm-none-eabi-9-2019-q4-major/" - официально раздаваемый ARM компилятор. И версия всего на одну ступень ниже последней.
СпойлерИзображение
gcc.png
(59.65 КБ) 83 скачивания
И как узнать, что ваш пример не в режиме C++ скомпилирован?
Друг Кота
Аватара пользователя
Сообщения: 3385
Зарегистрирован: Пн окт 11, 2010 19:00:08

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

VladislavS писал(а):У вас есть методика поделить компиляторы на нормальные и нет?
Сравните асм мой и ваш и найдите разницу.
Вы утверждаете что C++ генерирует лучший код чем Си https://radiokot.ru/forum/viewtopic.php ... 5#p3924275
И при этом зачем-то использовали разные версии CGG (8.2 для Си и 9.2.1 для C++).
На деле оказалось что между асм кодом Си и C++ разницы вообще нет.
VladislavS писал(а):И как узнать, что ваш пример не в режиме C++ скомпилирован?
У вас на компе нет компиля что не можете проверить?
Ответить

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