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

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

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

Сообщение dosikus »

Мурик писал(а):А если нужен не только F0?
Лучше уж ломанный Keil чем эти недоделыши ...
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

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

Сообщение a5021 »

Как обычно, одне общие слова. Что бы тут не говорили, EmBitz весьма неплох для полностью бесплатной среды программирования:
СпойлерИзображение
Последний раз редактировалось a5021 Вс окт 23, 2016 03:35:36, всего редактировалось 1 раз.
Аватара пользователя
Andrew Martin
Вымогатель припоя
Сообщения: 606
Зарегистрирован: Вт июн 25, 2013 18:45:07

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

Сообщение Andrew Martin »

По поводу кода.
GCC использует больше LDR, грузит две 32-битные константы из памяти программ, поэтому по размеру кода выигрыша не будет, а будет проигрыш минимум на одну инструкцию. По скорости - 32 такта против 33, если считать с Zero wait state. На высоких тактовых частотах, где wait state <> 0 LDR из флеша может занимать более 2х тактов, и тогда вариант ГЦЦ может даже проиграть.

А вообще нифига этот код не оптимальный. Посмотрите бегло на листинг - там идут два раза подряд загрузки-выгрузки по одним и тем же адресам. Можно убрать два LDR и два STR, итого сэкономим минимум 8 тактов и 8 байт. Это только БЕГЛАЯ прикидка, но и она показывает несостоятельность баек сишников про супер-пупер оптимизаторы 8) Вручную написанный ассемблерный код всё равно будет лучше.
Аватара пользователя
aam
Собутыльник Кота
Сообщения: 2994
Зарегистрирован: Сб фев 20, 2010 14:00:12
Откуда: Москва

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

Сообщение aam »

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

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

Сообщение Reflector »

Andrew Martin писал(а):А вообще нифига этот код не оптимальный. Посмотрите бегло на листинг - там идут два раза подряд загрузки-выгрузки по одним и тем же адресам. Можно убрать два LDR и два STR, итого сэкономим минимум 8 тактов и 8 байт. Это только БЕГЛАЯ прикидка, но и она показывает несостоятельность баек сишников про супер-пупер оптимизаторы 8) Вручную написанный ассемблерный код всё равно будет лучше.
Компилятор делает ровно то, что от него хотят. Он видит, что нужно два раза прочесть из AFR[0](AFR[1]) и сохранить обратно, но также он знает, что AFR объявлен как volatile, потому объединять команды чтение и записи он не имеет права.
Если что, вот мой вариант с gcc для F407, он покороче, можешь попробовать его оптимизировать :)
Спойлер

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

	SET_AF(GPIOA, 2, 2);
0x08001272  ldr r6, [pc, #564]	; (0x80014a8 <main()+616>) 
0x08001274  ldr r3, [r6, #32] 
0x08001276  bic.w r3, r3, #3840	; 0xf00 
0x0800127a  orr.w r3, r3, #512	; 0x200 
0x0800127e  str r3, [r6, #32] 
	SET_AF(GPIOA, 4, 4);
0x08001280  ldr r3, [r6, #32] 
0x08001282  bic.w r3, r3, #983040	; 0xf0000 
0x08001286  orr.w r3, r3, #262144	; 0x40000 
0x0800128a  str r3, [r6, #32] 
	SET_AF(GPIOA, 9, 1);
0x0800128c  ldr r3, [r6, #36]	; 0x24 
0x0800128e  bic.w r3, r3, #240	; 0xf0 
0x08001292  orr.w r3, r3, #16 
0x08001296  str r3, [r6, #36]	; 0x24 
	SET_AF(GPIOA, 10, 1);
0x08001298  ldr r3, [r6, #36]	; 0x24 
0x0800129a  bic.w r3, r3, #3840	; 0xf00 
0x0800129e  orr.w r3, r3, #256	; 0x100 
0x080012a2  str r3, [r6, #36]	; 0x24 
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

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

Сообщение dosikus »

Reflector писал(а): он покороче, можешь попробовать его оптимизировать :)

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

;;;100    			GPIOA->AFR[1] |=(1<<(4*1)) |(1<<(4*2))|(1<<(4*3)) |(1<<(4*4));
000040  6a41              LDR      r1,[r0,#0x24]
000042  4a10              LDR      r2,|L4.132|
000044  4311              ORRS     r1,r1,r2
000046  6241              STR      r1,[r0,#0x24]
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

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

Сообщение a5021 »

aam писал(а):Я конечно понимаю всю важность религиозных противостояний, но я разве задал слишком тупой вопрос?
Так совпало, что на скриншоте EmBitz-а, что я тут запостил, как раз кусок процедуры, которая оцифровывает по 256 семплов с сохранением в буфере через прямой доступ к памяти. :)
А вообще, в снайпетах это подробно разжевано. Я могу кусок своего кода сюда запостить, но у меня немного специфичная задачка, от вашей отличающаяся.
dosikus писал(а):

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

;;;100    			GPIOA->AFR[1] |=(1<<(4*1)) |(1<<(4*2))|(1<<(4*3)) |(1<<(4*4));
000040  6a41              LDR      r1,[r0,#0x24]
000042  4a10              LDR      r2,|L4.132|
000044  4311              ORRS     r1,r1,r2
000046  6241              STR      r1,[r0,#0x24]
Опять пальцем в небо. По сравнению с оригинальным выражением отсутствует операция логического "И" (сброс битов), от чего код, разумеется, стал короче. GCC выдает почти то же самое, кстати:

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

(268)  GPIOA->AFR[1] |=(1<<(4*1)) |(1<<(4*2))|(1<<(4*3)) |(1<<(4*4));
080003E0	ldr	r0, [pc, #760]	; (0x80006dc <main+888>)
08000414	ldr	r1, [r2, #36]	; 0x24
08000418	orrs	r1, r0
0800041A	str	r1, [r2, #36]	; 0x24
Аватара пользователя
oleg110592
Друг Кота
Сообщения: 3832
Зарегистрирован: Сб сен 10, 2011 17:46:25

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

Сообщение oleg110592 »

aam писал(а):Я конечно понимаю всю важность религиозных противостояний...
Вполне возможно никто из участников форума не решал подобной задачи, гораздо интересней хвастать у кого длиннее. :lol:
Может поможет пример из снипетсов "07_DMA_CircularMode", там правда 4 канала в массив пишется.
Еще тут http://tomeko.net/miniscope_v2e/ есть ацп оцифровка в большой буфер через DMA
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

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

Сообщение Reflector »

dosikus писал(а):

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

;;;100    			GPIOA->AFR[1] |=(1<<(4*1)) |(1<<(4*2))|(1<<(4*3)) |(1<<(4*4));
000040  6a41              LDR      r1,[r0,#0x24]
000042  4a10              LDR      r2,|L4.132|
000044  4311              ORRS     r1,r1,r2
000046  6241              STR      r1,[r0,#0x24]
Имелась в виду оптимизация с учетом того, что я говорил про volatile :) И пины в оригинальном примере шли вразброс, а тут 4 идут подряд и умещаются в одну половинку AFR. Про очистку битов уже говорили, итого вместо 4 команд будет минимум 10, что конечно меньше моих 17-ти, но только потому, что предложенный макрос SET_AF ориентирован на работу с одиночными пинами. Если нужна работа с группами, то нужен и другой подход. Например, вот мой код инициализации пинов для FSMC:

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

GpioD<0xC8B3>(PinMode::AF_PushPull_VeryHighSpeed, 12);
GpioE<0x0780>(PinMode::AF_PushPull_VeryHighSpeed, 12);
Оставим только AF:

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

GpioD<0xC8B3>::altFunc(12);
GpioE<0x0780>::altFunc(12);
Выхлоп gcc:
Спойлер

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

0x200008ac  ldr r1, [pc, #588]
0x200008ae  ldr r2, [pc, #592]

0x200008b0  ldr r3, [r1, #32] 
0x200008b2  bic.w r3, r3, #4026531840	; 0xf0000000 
0x200008b6  and.w r3, r3, #4278255360	; 0xff00ff00 
0x200008ba  orr.w r3, r3, #3221225472	; 0xc0000000 
0x200008be  orr.w r3, r3, #13369548	; 0xcc00cc 
0x200008c2  str r3, [r1, #32] 

0x200008c4  ldr r3, [r1, #36]	; 0x24 
0x200008c6  bic.w r3, r3, #4278190080	; 0xff000000 
0x200008ca  bic.w r3, r3, #61440	; 0xf000 
0x200008ce  orr.w r3, r3, #3422552064	; 0xcc000000 
0x200008d2  orr.w r3, r3, #49152	; 0xc000 
0x200008d6  str r3, [r1, #36]	; 0x24 

0x200008d8  ldr r3, [r2, #32] 
0x200008da  bic.w r3, r3, #4026531840	; 0xf0000000 
0x200008de  orr.w r3, r3, #3221225472	; 0xc0000000 
0x200008e2  str r3, [r2, #32] 

0x200008e4  ldr r3, [r2, #36]	; 0x24 
0x200008e6  bic.w r3, r3, #4080	; 0xff0 
0x200008ea  bic.w r3, r3, #15 
0x200008ee  orr.w r3, r3, #3264	; 0xcc0 
0x200008f2  orr.w r3, r3, #12 
0x200008f6  str r3, [r2, #36]	; 0x24 
Эквивалентный ему фрагмент кода на чистых регистрах(оба варианта по 76 байт) выглядит не самым привлекательным образом, а многие еще и маску разворачивают...

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

GPIOD->AFR[0] = GPIOD->AFR[0] & ~0xF0FF00FF | (12 << (4 * 0)) | (12 << (4 * 1)) | (12 << (4 * 4)) | (12 << (4 * 5)) | (12 << (4 * 7));
GPIOD->AFR[1] = GPIOD->AFR[1] & ~0xFF00F000 | (12 << (4 * 3)) | (12 << (4 * 6)) | (12 << (4 * 7));
GPIOE->AFR[0] = GPIOE->AFR[0] & ~0xFF000000 | (12 << (4 * 7));
GPIOE->AFR[1] = GPIOE->AFR[1] & ~0x00000FFF | (12 << (4 * 0)) | (12 << (4 * 1)) | (12 << (4 * 2));
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

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

Сообщение dosikus »

Reflector писал(а): Имелась в виду оптимизация с учетом того, что я говорил про volatile :)
Да я в принципе не тебе писал. :))) Есть тут открыватели велосипедов...

А на счет конфига кучи пинов на разных портах, меня больше прикалывает сие - http://en.radzio.dxp.pl/stm32f429idiscovery/sdram.html

Ну и оттуда же ...

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

void gpio_conf(GPIO_TypeDef * GPIO, uint8_t pin, uint8_t mode, uint8_t type, uint8_t speed, uint8_t pullup, uint8_t af)
{
		GPIO->MODER 	= (GPIO->MODER   & MASK2BIT(pin))   | (mode << (pin * 2));
		GPIO->OTYPER 	= (GPIO->OTYPER  & MASK1BIT(pin))   | (type << pin);
		GPIO->OSPEEDR = (GPIO->OSPEEDR & MASK2BIT(pin))   | (speed << (pin * 2));
		GPIO->PUPDR		= (GPIO->PUPDR   & MASK2BIT(pin))		| (pullup << (pin * 2));
		if(pin > 7)
			{
				GPIO->AFR[1] = (GPIO->AFR[1] & AFMASKH(pin)) | (af << ((pin - 8) * 4));
			}
		else
			{
				GPIO->AFR[0] = (GPIO->AFR[0] & AFMASKL(pin)) | (af << ((pin) * 4));
			}
}
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

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

Сообщение a5021 »

oleg110592 писал(а):Вполне возможно никто из участников форума не решал подобной задачи, гораздо интересней хвастать у кого длиннее. :lol:
Канэшна не решал. Скрин вон с нерешенной задачей засветил случайно, предложение поделиться кодом от нее же. Впрочем, это уже не первый случай, когда иным участникам кажется офигенной идеей отрицать очевидные вещи, находящегося у них прямо перед глазами.
Reflector писал(а):Эквивалентный ему фрагмент кода на чистых регистрах(оба варианта по 76 байт) выглядит не самым привлекательным образом, а многие еще и маску разворачивают...

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

GPIOD->AFR[0] = GPIOD->AFR[0] & ~0xF0FF00FF | (12 << (4 * 0)) | (12 << (4 * 1)) | (12 << (4 * 4)) | (12 << (4 * 5)) | (12 << (4 * 7));
GPIOD->AFR[1] = GPIOD->AFR[1] & ~0xFF00F000 | (12 << (4 * 3)) | (12 << (4 * 6)) | (12 << (4 * 7));
GPIOE->AFR[0] = GPIOE->AFR[0] & ~0xFF000000 | (12 << (4 * 7));
GPIOE->AFR[1] = GPIOE->AFR[1] & ~0x00000FFF | (12 << (4 * 0)) | (12 << (4 * 1)) | (12 << (4 * 2));
Подозреваю, что особо рьяные поклонники Кернигана и Ричи опять не увидят здесь никаких волшебных цифр, а одни только самодокументирующиеся операции с битами, но я бы все-таки привел это дело к более читабельному виду. Что-то вроде такого:
Спойлер

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

#define ASSIGN_AF(PIN, AF) (AF << (4 * (PIN & 7)))

GPIOD->AFR[0] = (GPIOD->AFR[0] & ~0xF0FF00FF) | (
  ASSIGN_AF(0, 12)    |   // PD0: AF12 -- FSMC_D2
  ASSIGN_AF(1, 12)    |   // PD1: AF12 -- FSMC_D3
  ASSIGN_AF(4, 12)    |   // PD4: AF12 -- FSMC_NOE
  ASSIGN_AF(5, 12)    |   // PD5: AF12 -- FSMC_NWE
  ASSIGN_AF(7, 12)        // PD7: AF12 -- FSMC_NE1
);

GPIOD->AFR[1] = (GPIOD->AFR[1] & ~0xFF00F000) | (
  ASSIGN_AF(11, 12)   |   // PD11: AF12 -- FSMC_A16
  ASSIGN_AF(14, 12)   |   // PD14: AF12 -- FSMC_D0
  ASSIGN_AF(15, 12)       // PD15: AF12 -- FSMC_D1
);

// и т.п.

#undef ASSIGN_AF
По сути то же самое, но вспоминать, что там напрограммировалось года полтора назад, будет легче. :)
dosikus писал(а):Да я в принципе не тебе писал. :))) Есть тут открыватели велосипедов...
Это их вы обыкновенно пытаетесь кормить откровенной горбухой под видом величайших откровений?
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

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

Сообщение Reflector »

a5021 писал(а): По сути то же самое, но вспоминать, что там напрограммировалось года полтора назад, будет легче. :)
Ага, еще добавить сюда инициализацию остальных 4-х GPIO регистров для двух портов и будет почти то же самое, что у меня, только на два экрана вместо двух строк :)
Аватара пользователя
scorpi_0n
Вымогатель припоя
Сообщения: 616
Зарегистрирован: Вс ноя 01, 2015 13:13:49

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

Сообщение scorpi_0n »

a5021 писал(а): Канэшна не решал.
А попробуйте! Может и дурных вопросов будет меньше.
Скрин вон с нерешенной задачей засветил случайно, предложение поделиться кодом от нее же.
А оно ещё кому-то нужно, кроме вас?
Впрочем, это уже не первый случай, когда иным участникам кажется офигенной идеей отрицать очевидные вещи, находящегося у них прямо перед глазами.
Да вы америку уже в 1796590006-й раз открыли, а мир от этого и не рухнул. Но вот почему-то это никого не удивляет, ну кроме вас конечно.
Подозреваю, что особо рьяные поклонники Кернигана и Ричи опять не увидят здесь никаких волшебных цифр, а одни только самодокументирующиеся операции с битами, но я бы все-таки привел это дело к более читабельному виду.

По сути то же самое, но вспоминать, что там напрограммировалось года полтора назад, будет легче. :)
С каких это пор вас стали посещать такие крамольные мысли?
Это их вы обыкновенно пытаетесь кормить откровенной горбухой под видом величайших откровений?
Это сугубо ваша прерогатива - натягивать сову на глобус, раздувать из мухи слона, не видеть очевидного и т.п. Даже сейчас непонятно, а что вы пытаетесь собственно доказать? Или вам просто "поговорить" от нечего делать?
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

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

Сообщение dosikus »

a5021 , не пора ли назад в свой серпентарий ? Пока своим же ядом не захлебнулся...
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

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

Сообщение a5021 »

Reflector писал(а):Ага, еще добавить сюда инициализацию остальных 4-х GPIO регистров для двух портов и будет почти то же самое, что у меня, только на два экрана вместо двух строк :)
Компактность и наглядность здесь антагонисты. Если минимум печатных знаков являются приоритетной целью, то волшебные цифры -- наше все.
dosikus писал(а):a5021 , не пора ли назад в свой серпентарий ? Пока своим же ядом не захлебнулся...
Да без вас с вашим другом-инсектом я это решу как-нибудь. Не напрягайтесь без нужды.
Аватара пользователя
scorpi_0n
Вымогатель припоя
Сообщения: 616
Зарегистрирован: Вс ноя 01, 2015 13:13:49

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

Сообщение scorpi_0n »

a5021 писал(а):я это решу как-нибудь. Не напрягайтесь без нужды.
Решите что? Вы понимаете, что у вас уже пошёл спор ради спора. Вы потеряли суть и цель ради чего всё это.
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

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

Сообщение a5021 »

Ваше-то какое дело?
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

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

Сообщение Reflector »

a5021 писал(а): Компактность и наглядность здесь антагонисты. Если минимум печатных знаков являются приоритетной целью, то волшебные цифры -- наше все.
Да ты хорошенько присмотрись :)

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

GpioD<0xC8B3>::altFunc(12);
или

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

GpioD<0b1100'1000'1011'0011>::altFunc(12);
или

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

const uint32_t mask = ...;	// FSMC D2 D3 NOE NWE NE1 A16 D0 D1
GpioD<mask>::altFunc(12);
и твое

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

#define ASSIGN_AF(PIN, AF) (AF << (4 * (PIN & 7)))

GPIOD->AFR[0] = (GPIOD->AFR[0] & ~0xF0FF00FF) | (
  ASSIGN_AF(0, 12)    |   // PD0: AF12 -- FSMC_D2
  ASSIGN_AF(1, 12)    |   // PD1: AF12 -- FSMC_D3
  ASSIGN_AF(4, 12)    |   // PD4: AF12 -- FSMC_NOE
  ASSIGN_AF(5, 12)    |   // PD5: AF12 -- FSMC_NWE
  ASSIGN_AF(7, 12)        // PD7: AF12 -- FSMC_NE1
);

GPIOD->AFR[1] = (GPIOD->AFR[1] & ~0xFF00F000) | (
  ASSIGN_AF(11, 12)   |   // PD11: AF12 -- FSMC_A16
  ASSIGN_AF(14, 12)   |   // PD14: AF12 -- FSMC_D0
  ASSIGN_AF(15, 12)       // PD15: AF12 -- FSMC_D1
);
a5021
Друг Кота
Сообщения: 6452
Зарегистрирован: Пт сен 13, 2013 13:11:31

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

Сообщение a5021 »

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

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

Сообщение Reflector »

a5021 писал(а):Разница, по большому счету, только в направлении развертывания текста. У вас горизонтальное, у меня вертикальное. Горизонтальное занимает меньше строк, вертикальное более наглядно с точки зрения одна строка -- действие и комментарий все вместе.
У меня всего две константы в которых теоретически можно ошибиться, у тебя уже есть 4 "магических числа" (0xF0FF00FF и т.д.) только для AFR. Это четверная маска, также понадобится две одиночных, для OTYPER, и две двойных, для трех остальных регистров. Конечно никто не заставляет их высчитывать в уме, можно все это культурно сформировать из всяких GPIO_MODER_MODERxx, но т.к. ног у нас целых 12, то компактной такую запись будет назвать очень трудно и все равно вероятность вписать не ту цифру будет в десятки раз больше, чем для кода из двух строк.
Ответить

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