Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение AVI-crak »

[uquote="Reflector",url="/forum/viewtopic.php?p=3937925#p3937925"]меня 23КБ отожрала[/uquote]
Я вот думал как принудительно заставить GCC считать заранее, но увы нулевая оптимизация раскрывает макросы по умолчанию.
К тому-же этот вариант записи только для быстрой настройки во время создания проекта. После полировки, вместо всего этого безобразия - остаётся массив 32b регистров, и простейший цикл. Работает быстрее, но не настолько наглядно.
VladislavS писал(а):Но когда это на 20-100 ног умножится, то за гранью добра и зла получится.
Наоборот, получится всего 20-100 строк - с предельно понятной записью. А не 800-4000, как в стандартном варианте (по 40 линий на пин).
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Reflector »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3937929#p3937929"]Что такое -O0 ??? :)))[/uquote]
Достаточно популярный уровень оптимизации учитывая, что у нас мк с 2-х долларовым отладчиком и людям хочется пошагово отлаживать C/C++ код, а не только по ассму шагать :) Хотя я видел достаточно сложные либы портов на C++ которые с отключенной оптимизацией вообще не компилировались.
Реклама
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение VladislavS »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3937933#p3937933"]Я вот думал как принудительно заставить GCC считать заранее[/uquote]Вы уже одной ногой на тёмной стороне силы. Не мучайтесь, сделайте этот шаг.

Добавлено after 8 minutes 47 seconds:
[uquote="Reflector",url="/forum/viewtopic.php?p=3937935#p3937935"]Хотя я видел достаточно сложные либы портов на C++ которые с отключенной оптимизацией вообще не компилировались.[/uquote]Я видел целую IDE c компилятором, который на -O0 делал нерабочий код :)
Последний раз редактировалось VladislavS Пн дек 07, 2020 16:56:28, всего редактировалось 1 раз.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3937933#p3937933"]Я вот думал как принудительно заставить GCC считать заранее, но увы нулевая оптимизация раскрывает макросы по умолчанию[/uquote]
Как минимум можно для дебага инлайнинг отключать добавив перед функцией zap_gpio_nomer():

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

#ifndef DEBUG
	__attribute__((always_inline))
#endif
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение AVI-crak »

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

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение VladislavS »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3937962#p3937962"]Да мне наоборот нужно, чтобы при любом уровне компиляции - часть кода всегда просчитывалась на компе.[/uquote]расширение файла .cpp, ключ компилятора -std=C++2a и constexpr, consteval, constinit в вашем распоряжении :)
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3937962#p3937962"]Да мне наоборот нужно, чтобы при любом уровне компиляции - часть кода всегда просчитывалась на компе.
Потому как предварительная ловля багов уже закончилась.[/uquote]
Компилируем простейший код без глобальной оптимизации(_inline_ - это always_inline + O2):

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

int _inline_ sum(int x, int y) { return x + y; }
GPIOC->ODR = sum(10, 20);
Чтобы компилятор смог такой вызов заинлайнить и, соответственно, свернуть до константы, вызов должен происходить из оптимизированного контекста, обычно это функция которой тоже добавлен атрибут оптимизации. В противном случае инлайнинга не будет и получим передачу параметров в регистрах:

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

movs r3, #10 
str.w r3, [r7, #144]
movs r3, #20 
str.w r3, [r7, #140]
ldr.w r2, [r7, #144]
ldr.w r3, [r7, #140]
add r2, r3 
ldr r3, [pc, #364]
str r2, [r3, #20]
И ничего тут не сделаешь, однако на C++ простое превращение sum() в шаблонную функцию, даже без всяких consxtepr и т.д., проблему решает и вместо вызова функции компилятор подставит 30. То же самое будет если обычную функцию пометить как consteval, тогда и атрибуты оптимизации никакие не нужны:

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

consteval int sum(int x, int y) { return x + y; }
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Reflector »

AVI-crak, зацени вариацию твоего подхода :)
LTDC, режим RGB444, передаем в функцию 14 пинов, она вызывает более общий инит для RGB666 куда передает принятые пины, а вместо 6-ти недостающих добавляются PinDummy<> которые везде игнорируются, но в списке пинов место все равно занимают, т.е. суммарно выходит 20 пинов. Все эти пины передаются в еще один класс который знает какие для конкретного мк допустимы LTDC пины и какие должны быть AF, он все проверяет и если ошибок нет, то возвращается такой-же список пинов, но теперь в нем правильные AF. Принимающая сторона берет у списка тип и запоминает, к этому моменту ничего кроме нового типа не существует и в рантайме компилятору генерить нечего, даже если очень захочется. Остается вызывать для типа списка mode(), она отсеивает все PinDummy<> и для оставшихся пинов формирует массив во флеше. Итого для -O0 получаем такую картину(естественно это все скрыто и в функцию инициализации передаются только пины):

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

using pins = decltype(AltFuncMap<>::ltdc<Hsync, Vsync, R7, R6, R5, R4, R3, R2, G7, G6, G5, G4, G3, G2, B7, B6, B5, B4, B3, B2>());
pins::template mode<PinMode::AF_PushPull>();

// ldr r0, [pc, #256]
// bl 0x24000900

// 00 0e e4 0e ca 0e e3 0e eb ff
// 01 0e eb 0e e8 0e e9 0e ea 0e 91 ff 
// 02 0e e7 0e e6 0e e0 ff 
// 03 0e e3 ff 
// 04 0e ef ff ff
6-ть байт на пару инструкций плюс 4 байта на константу во флеше плюс массив во флеше размером 39 байт :) Первый байт в каждой строке - это номер порта, затем идет байт режима и байт AF/Pin, эти два байта повторяются сколько потребуется, в конце описания каждого порта и в самом конце идет 0xFF. Класс который формирует массив по сути является усложненной версия класса сортировки массива, который я уже показывал:
Спойлер

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

template<uint32_t N>
class PinModePack
{
	struct Pack
	{
		uint32_t gpio;
		uint32_t portNum;
		uint32_t pin;
		AltFunc  af;
		PinMode  mode;
	};
	
public:
	template<typename... Ps>
	consteval PinModePack(TypeList<Ps...> ps)
	{
		Pack pins[] = { { Ps::gpio, Ps::portNumber, Ps::pin, Ps::af, Ps::mode_ }... };

		std::ranges::sort(pins, [](auto& p1, auto& p2) { return p1.portNum < p2.portNum; });

		auto p = arr;
		auto prevPortNum = 0xFF;

		for(auto& pin : pins)
		{
			if (!pin.gpio) continue;
			
			if (prevPortNum != pin.portNum)
			{
				if(prevPortNum != 0xFF) *p++ = 0xFF;
				*p++ = prevPortNum = pin.portNum;
			}
			*p++ = uint8_t(pin.mode);
			*p++ = (uint8_t(pin.af) << 4) | pin.pin;
		}
		*p++ = 0xFF;
		*p++ = 0xFF;

		size = p - arr;
	}

	uint8_t arr[N * 4 + 1]{};
	uint32_t size;
};

template<uint32_t N>
struct PinModePackResize
{
	consteval PinModePackResize(const uint8_t* ptr) { std::copy(ptr, ptr + N, arr); }

	uint8_t arr[N]{};
};

template<PinMode Mode>
static void _inline_ mode()
{
	static constexpr auto pinModePack = PinModePack<size(realPins_)>(combinePinsWithModes(pins_, PinModeList<Mode, Size>::modes));
	static constexpr auto resize = PinModePackResize<pinModePack.size>(pinModePack.arr);
		
	gpioMode(resize.arr);
}
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение AVI-crak »

[uquote="Reflector",url="/forum/viewtopic.php?p=3938798#p3938798"]затем идет байт режима и байт AF/Pin, эти два байта повторяются сколько потребуется[/uquote]
Не всё так просто, для RGB интерфейса есть варианты AF. С таким направлением движения -весь кубик от st имеет реальный шанс переехать в программную реализацию. Вот только при работе с кубиком ломаться нечему, он только предлагает варианты и отображает ограничения. А программный вариант будет материться непонятной ошибкой, без наглядного и простого представления альтернативного варианта.

Кстати, подобный вариант можно написать на регионы памяти mpu. Эти регистры в разных мк - имеют отличие только в общем количестве, но структура и способ применения - совпадают. Там проблема в том что некоторые комбинации запрещены, есть комбинации которые не имеют смысла, и комбинации приводящие к критической ошибке. То-есть очень ограниченное состояние регистров программирующих поведение кеша ядра мк, буквально 64 варианта - которые работают, и приносят пользу.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3938838#p3938838"]Не всё так просто, для RGB интерфейса есть варианты AF. С таким направлением движения -весь кубик от st имеет реальный шанс переехать в программную реализацию. Вот только при работе с кубиком ломаться нечему, он только предлагает варианты и отображает ограничения. А программный вариант будет материться непонятной ошибкой, без наглядного и простого представления альтернативного варианта.[/uquote]
Все пины и AF известны, например, такой код компилируется на STM32H750VB:

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

ltdc.initRgb444<PC6, PA4, PE15, PB1, PC0, PA11, PD3, PC7, PB11, PB10, PB9, PB8, PA3, PA10>(...);
Тут я поменял пины для R6 и R5, он тоже компилируется(у R6 был AF9, стал AF14):

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

ltdc.initRgb444<PC6, PA4, PE15, PA8, PA12, PA11, PD3, PC7, PB11, PB10, PB9, PB8, PA3, PA10>(...);
А здесь я наугад поменял пару пинов из середины списка и получил 3 ошибки:

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

ltdc.initRgb444<PC6, PA4, PE15, PA8, PA12, PA11, PD3, PC4, PB10, PB10, PB9, PB8, PA3, PA10>(...);

// static assertion failed: G5 pin is Invalid!
// static assertion failed: G6 pin is Invalid!
// static assertion failed: PinList has Duplicates!
При таком раскладе даже не нужно подробно расписывать где какой пин, это и так даже во всплывающей подсказке видно, ошибку все равно совершить невозможно.
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение AVI-crak »

Reflector - Не, слишком сложно. Компактный ввод данных всегда граничит некоторой потерей информации. Одно дело когда оно раздуто непомерно на несколько десятков строк - с этим можно и нужно бороться. Но когда теряется часть важной информации - то уже поздно бороться, перестарались.
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Dimon456 »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3937811#p3937811"]Я даже не буду просить повторить нижеследующий пример. Берём две группы пинов на разных портах. Читаем одну группу как байт, инвертируем и записываем во вторую группу.

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

PinList<PC7, PC6, PC5, PC4, PC3, PA0, PA1, PA5> pins1;
PinList<PB1, PB2, PB3, PB4, PB5, PD5, PD1, PD0> pins2;

pins2 = ~pins1;
Сколько вы это будете руками ковырять... Компилятор делает за долю секунды.[/uquote]Какая жалость

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

error: 'PinList' does not name a type
error: 'pins2' was not declared in this scope
видать чего-то не хватает, даже и не знаю сколько же буду ковырять это.

Ну да ладно, господа высокоинтеллектуальные программисты, вопрос не в этом, хотя тема называется
Ассемблер для STM32. Сложно ли, стоит ли пытаться?
но спрошу в этой.

stm32f030 я использую xprintf, с какого-то сайта уже не помню, не важно, но xprintf не работает без printf,
из printf всего одна строка printf("\n");

Проблема в этом, если писать xprintf("HELL"); - то работает.
А если xprintf("HELLO"); - не работает, сразу с ходу падает в hard fault.

Проблема в этом, HELL во флеш располагается так HELL FFFFFFFF
а HELLO так HELL FFFFFFO, здесь еще ноль должен быть но это не важно.
Если бинарничек вот с этим HELL FFFFFFO отредактировать так HELL 123O - то работает.

printf("\n") решает эту проблему, но дает лишние 2,5к коду, да на F100 работает без printf("\n").

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

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение VladislavS »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3939294#p3939294"]Ну да ладно, господа высокоинтеллектуальные программисты, вопрос не в этом, хотя тема называется
Ассемблер для STM32. Сложно ли, стоит ли пытаться?
но спрошу в этой.[/uquote]Наши примеры показывают, возможности инструмента отличного от асма и С. Что в большой степени является ответом на вопоос "а стоит ли". А вот ваш непоймикемнаписанный глючный xprintf тут явно злобный оффтопик.

Добавлено after 5 minutes 57 seconds:
[uquote="Dimon456",url="/forum/viewtopic.php?p=3939294#p3939294"]Кто что подскажет?[/uquote]Ах, да, про главное то забыл. Курите невыровненый доступ к памяти.
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение a797945 »

Dimon456, может ответ надо искать там:
http://www.elm-chan.org/fsw/strf/xprintf.html
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Dimon456 »

VladislavS писал(а):Наши примеры показывают, возможности инструмента отличного от асма и С. Что в большой степени является ответом на вопоос "а стоит ли".
В первую очередь это возможности вашего класса, но не как не возможности С++.
Это не входит в стандартный набор С++, cmsis, а такой ответ как "У меня есть класс который может ..." это не пойдет.
Если хвастаетесь, то хвастайтесь более подробно, что бы другой человек мог ваш пример попробовать, оценить, и сказать - да, действительно это что-то значит, это проще, на С++ стоит переходить и т.п. Вот это и есть помощь, а так пока это только пиар.

a797945, ответ я нашел, мне просто интересно было что высокоинтеллектуальные специалисты скажут. А специалисты сказали - курите мануал.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение VladislavS »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3939425#p3939425"]А специалисты сказали - курите мануал.[/uquote]Не мануал, а невыровненый доступ!

Не припомню, чтобы задолжал вам ни в выкладывании кода, ни в обучении, ни в поиске ошибок.
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3939081#p3939081"]Reflector - Не, слишком сложно. Компактный ввод данных всегда граничит некоторой потерей информации. Одно дело когда оно раздуто непомерно на несколько десятков строк - с этим можно и нужно бороться. Но когда теряется часть важной информации - то уже поздно бороться, перестарались.[/uquote]
Информация не потерялась в следствии стремления к компактности, я сам целенаправленно ее опускаю, потому что она излишня. Можно добавить 14 строк и расписать где какой пин, но зачем если функция и так защищена на 100%... Пины LTDC могут быть разными, сначала пришлось помучаться с их выбором, далее я беру пины со схемы, если там для HSYNC нужен PC6, то проще и вписать PC6 вместо целой строки:

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

gpio_one_pin(zap_gpio.H.pin05.v_af14_ltdc_hsync.speed4.pull_up.lock_on);
Набирая 14 таких строк, где все сливается, можно запросто случайно выбрать HSYNC от DCMI и все скомпилируется:

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

gpio_one_pin(zap_gpio.A.pin04.v_af13_dcmi_hsync.speed4.pull_up.lock_on);
И со speed1 скомпилируется или можно пропустить в конце lock_on, тоже компилируется и при этом размер вырастает на полторы сотни байт, что весьма вероятно указывает на ошибку... Опять же будет существенный проигрыш по размеру, 14*8 vs 49 байт(для -O0 разница в 500+ раз). Кстати, я потестил на разных проектах и далеко не везде даже с моим компактным кодом функция принимающая массив выигрывает у заинлайненых обращений к регистрам портов...

[uquote="Dimon456",url="/forum/viewtopic.php?p=3939425#p3939425"]такой ответ как "У меня есть класс который может ..." это не пойдет.
Если хвастаетесь, то хвастайтесь более подробно, что бы другой человек мог ваш пример попробовать, оценить, и сказать - да, действительно это что-то значит, это проще, на С++ стоит переходить и т.п. Вот это и есть помощь, а так пока это только пиар.[/uquote]
Мой пример с сортировкой можно скомпилировать без дополнительных библиотек и убедиться, что действительно на этапе компиляции можно получить во флеше массив практически любой сложности. И такой пример - это не то, что можно найти на каждом углу, потому для тех кому интересен C++ - это таки помощь. Для остальных - это пиар С++, ничего не могу поделать с тем, что большинство по-прежнему видит непонятные иероглифы там, где могло бы увидеть выдающие возможности языка и стимул к самосовершенствованию :)
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение VladislavS »

[uquote="Reflector",url="/forum/viewtopic.php?p=3939526#p3939526"]Пины LTDC могут быть разными, сначала пришлось помучаться с их выбором, далее я беру пины со схемы[/uquote]Я бы где-нибудь в одном месте в заголовочном файле все ноги со схемы перерисовал

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

using Hsync = PC6;
using Vsync = PA4;
...
using B2    = PA10;
и уже по коду вызывал вполне понятное

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

ltdc.initRgb444<Hsync, Vsync, R7, R6, R5, R4, R3, R2, G7, G6, G5, G4, G3, G2, B7, B6, B5, B4, B3, B2>(...);
[uquote="Reflector",url="/forum/viewtopic.php?p=3939526#p3939526"]И такой пример - это не то, что можно найти на каждом углу, потому для тех кому интересен C++ - это таки помощь.[/uquote]100% - хоть конспектируй!
Аватара пользователя
AVI-crak
Прорезались зубы
Сообщения: 202
Зарегистрирован: Сб янв 09, 2016 15:51:17
Контактная информация:

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение AVI-crak »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3939559#p3939559"]Я бы где-нибудь в одном месте в заголовочном файле все ноги со схемы перерисовал[/uquote]

А потом после многократных переделок окажется что на одну физическую ногу подключены сразу несколько девайсов, и функция это проглотит. Потому как не различает символьное имя Hsync, Vsync, или spi_cl. Зато знает что такое A0, A2, A2, и умеет с ними обращаться.

Не в том месте бороться нужно, после запуска периферии - это уже не отдельные ноги, а вполне конкретный интерфейс. И вот не нужно тащить ноги в этот интерфейс, ни сверху ни снизу. Если работаете с ногами - работайте с ними, интерфейс уже потом.

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

Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?

Сообщение Reflector »

[uquote="AVI-crak",url="/forum/viewtopic.php?p=3939580#p3939580"]А потом после многократных переделок окажется что на одну физическую ногу подключены сразу несколько девайсов, и функция это проглотит. Потому как не различает символьное имя Hsync, Vsync, или spi_cl. Зато знает что такое A0, A2, A2, и умеет с ними обращаться.[/uquote]
Берем PC9, для H750 на него можно заремапить LTDC G3/B2 или DCMI D3, следовательно теоретически я могу использовать этот пин для обоих интерфейсов и ошибки не получу, однако не выйдет PC9 использовать одновременно для G3 и B2, т.к. список пинов проверяется на дубликаты. А если инитить каждый пин по отдельности, то без ошибки скомпилируется код где PC9 используется сразу для G3/B2/D3, причем вовсе не обязательно пины должны быть именно такими, использование любых других пинов вместо требуемых - это также не ошибка. Можно проинитить B1 для которого невозможно подставить неверный AF, но толку от этого, если сам пин другой :) От тотального контроля компилятором перешли к контролю, пусть и не тотальному, со стороны программиста... У VladislavS другой подход, там все пины инитятся в одном месте одним списком, в таком случае уже проверяются дубликаты во всем проекте.

ps. Если бы функция не различала Hsync и Vsync, то как бы она могла требовать передачи только подходящих пинов?
Ответить

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