Страница 10 из 15

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

Добавлено: Вс дек 13, 2020 03:44:07
VladislavS
[uquote="AVI-crak",url="/forum/viewtopic.php?p=3940800#p3940800"]Это там https://github.com/AVI-crak/gpio_one
Материалы для создания таблиц не включены в проект, не хватало чтобы меня ещё и за них пинали.[/uquote]Глянул краем глаза. Попинаю.
1. Вот это вот совсем плохо.

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

zap_GPIO_TypeDef* GPIOx = (void*)0x40020000 + init.port;
Это магическое число запросто может быть 0x50000000 у некоторых контроллеров. Она же определена в заголовочном файле контроллера, надо пользоваться. Ну и с приведение типов надо что-то делать.

2. Состояние пина в PushPull режиме это тоже часть конфигурации. Почему на него забито? Должно быть три опции: 0, 1 и "не трогать".

3. RM говорит, что lock() это

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

GPIOx->LCKR = (1 << 16) | (1 << init.pin);
GPIOx->LCKR = 1 << init.pin;
GPIOx->LCKR = (1 << 16) | (1 << init.pin); 
GPIOx->LCKR;
ЗЫ: А с народным f103 что будем делать?

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

Добавлено: Вс дек 13, 2020 13:55:53
AVI-crak
Reflector писал(а):Вот это вот совсем плохо.
Это плохо споткнулось на stm32l552xx - там вообще всё переделано. Ну даа, нужно подключать внешнее, чтобы работало везде и всегда (кроме F1). Но на данный момент до этого далеко.

Народный f103 оптимизировать нет смысла: это намного сложнее - и практически с нуля, накопилась критическая масса публикаций в инете - которую невозможно пробить. Даже победив дракона - героя никто не заметит, а может даже затопают в суматохе.
Reflector писал(а):Состояние пина в PushPull

Ну дык к это относится к работе выхлопа на верхнем и нижнем транзисторе, но в любом случае это выхлоп. А вот не выхлоп - обозначен для выбора.

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

Добавлено: Вс дек 13, 2020 15:56:54
VladislavS
Ну не знаю, раз уж взялись за пин, то лучше полностью состояние задать, чем лочить его. И какая может быть трудность у F1 с его 4 битами конфигурации на пин в одном регистре?

Залочить, кстати, если есть список пинов, это одна команда.
Спойлер

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

using PINS = PinList<PB4, PB3, PA1, PA4, PA7, PB1, PB8, PB15>;
PINS::lock();
        LDR.N    R1,??main_0      ;; 0x4800001c
        LDR.N    R0,??main_0+0x4  ;; 0x10092
        STR      R0,[R1, #+0]
        MOVS     R2,#+146
        STR      R2,[R1, #+0]
        STR      R0,[R1, #+0]
        MOVW     R2,#+33050
        LDR      R0,[R1, #+0]
        LDR.N    R0,??main_0+0x8  ;; 0x1811a
        STR      R0,[R1, #+1024]
        STR      R2,[R1, #+1024]
        STR      R0,[R1, #+1024]
        LDR      R0,[R1, #+1024]
Или вот так, сразу три порта лочим, легко и непринуждённо.
Спойлер

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

PinList<GpioA<>,GpioB<>,GpioC<>>::lock();
        LDR.N    R1,??main_0      ;; 0x4800001c
        LDR.N    R0,??main_0+0x4  ;; 0x1ffff
        STR      R0,[R1, #+0]
        MOVW     R2,#+65535
        STR      R2,[R1, #+0]
        STR      R0,[R1, #+0]
        LDR      R3,[R1, #+0]
        STR      R0,[R1, #+1024]
        STR      R2,[R1, #+1024]
        STR      R0,[R1, #+1024]
        LDR      R3,[R1, #+1024]
        STR      R0,[R1, #+2048]
        STR      R2,[R1, #+2048]
        STR      R0,[R1, #+2048]
        LDR      R0,[R1, #+2048]
Вот тут цикл просится в оптимизацию :)

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

Добавлено: Пн дек 14, 2020 10:31:01
AVI-crak
Трудность с F1 в том что кубик не даёт полноценный рапорт, а вводить всё это дело руками - рехнуться можно. (это я про своё решение)
Лок нужен по другим причинам, не связанных с безопасностью. Точнее это даже почти правило, всё сто статично - должно лочится.

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

Добавлено: Пн дек 14, 2020 22:21:20
Dimon456
VladislavS, еще вопрос.
И так ваш метод:

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

PinList<PC7, PC6, PC5, PC4, PC3, PA0, PA1, PA5> pins1;
PinList<PB1, PB2, PB3, PB4, PB5, PD5> pins2;
Теперь, плиз, в цикле, будем записывать, ни знаю как у вас правильно, но

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

a = 0;
b = 0;
while (1)
      {
		pins1 = a++;
		pins2 = b++;
      }
При объявлении pins1 и pins2 у вас создается таблица, массив, соответственно будет два массива.
На текущий момент нет способа узнать длину массива, соответственно будет две функции записи.

Покажите получившийся ассемблер?

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

Добавлено: Пн дек 14, 2020 22:49:00
Reflector
[uquote="Dimon456",url="/forum/viewtopic.php?p=3941691#p3941691"]При объявлении pins1 и pins2 у вас создается таблица, массив, соответственно будет два массива.[/uquote]
Нет там никаких массивов, они есть у меня, но только для инициализации и как один из вариантов, потому что иногда скорость важнее размера. Для присваивания скорость важнее гораздо чаще, потому обходимся без массивов, хотя добавить можно, даже с автоматической подстановкой более компактного варианта.

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

Добавлено: Пн дек 14, 2020 23:03:50
VladislavS
[uquote="Dimon456",url="/forum/viewtopic.php?p=3941691#p3941691"]Теперь, плиз, в цикле,[/uquote]Зачем тут две переменных-счётчика?
[uquote="Dimon456",url="/forum/viewtopic.php?p=3941691#p3941691"]При объявлении pins1 и pins2 у вас создается таблица, массив, соответственно будет два массива.[/uquote]Ничего не создастся. Вообще. Совсем. Только код записи в порты.
[uquote="Dimon456",url="/forum/viewtopic.php?p=3941691#p3941691"]На текущий момент нет способа узнать длину массива, соответственно будет две функции записи.[/uquote]Какого массива? О чём вы?
[uquote="Dimon456",url="/forum/viewtopic.php?p=3941691#p3941691"]Покажите получившийся ассемблер?[/uquote]Завтра, компьютер на работе оставил.

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

Добавлено: Вт дек 15, 2020 00:12:34
Reflector
[uquote="VladislavS",url="/forum/viewtopic.php?p=3941705#p3941705"]Завтра, компьютер на работе оставил.[/uquote]
Покажу пока как это может быть с массивами и циклами, набросал буквально за 20 мин:

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

ldr r5, [pc, #168]
add.w r6, r5, #12 
mov r1, r4 
mov r0, r5 
bl 0x24000214
mov r1, r4 
mov r0, r6 
adds r4, #1 
bl 0x24000214
b.n 0x240015f6 
Два массива выглядят так:

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

05 01 00 23 24 25 26 27 FF
35 15 14 13 12 11 FF
Ну и сама функция существующая в единственном экземпляре которая получает на вход такой массив и записываемое значение:
Спойлер

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

push {r4, r5, lr} 
subs r0, #1 
mov.w r4, #65536
ldrb.w r3, [r0, #1]! 
cmp r3, #255
beq.n 0x24000242
and.w r5, r3, #15 
lsrs r3, r3, #4 
and.w r2, r1, #1 
lsrs r1, r1, #1 
lsls r3, r3, #10 
orrs r2, r4 
add.w r3, r3, #1476395008
lsls r2, r5 
add.w r3, r3, #131072
str r2, [r3, #24] 
b.n 0x2400021c
pop {r4, r5, pc}

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

Добавлено: Вт дек 15, 2020 08:58:36
VladislavS
Для F3 оптимизация по скорости
Спойлер

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

PinList<PC7, PC6, PC5, PC4, PC3, PA0, PA1, PA5> pins1;
PinList<PB1, PB2, PB3, PB4, PB5, PD5> pins2;
for(auto i=0;;i++)
        MOVS     R0,#+0
        LDR.N    R1,??DataTable1_4  ;; 0x48000018
{
//  pins1=i;
??main_0:
        AND      R2,R0,#0xF8
        ORR      R2,R2,#0xF80000
        STR      R2,[R1, #+2048]
        AND      R3,R0,#0x2
        LSLS     R2,R0,#+5
        AND      R2,R2,#0x20
        ORRS     R3,R3,R2
        UBFX     R4,R0,#+2,#+1
        ORRS     R3,R4,R3
        ORR      R3,R3,#0x230000
        STR      R3,[R1, #+0]
//  pins2=i;
        ORR      R2,R2,#0x200000
        AND      R3,R0,#0x3E
        RBIT     R3,R3
        LSRS     R3,R3,#+25
        AND      R3,R3,#0x3E
        ORR      R3,R3,#0x3E0000
        STR      R3,[R1, #+1024]
        STR      R2,[R1, #+3072]
//}
        ADDS     R0,R0,#+1
        B.N      ??main_0

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

Добавлено: Вт дек 15, 2020 09:03:45
Dimon456
VladislavS писал(а):Зачем тут две переменных-счётчика?
Я считаю что если одна переменная, то будет оптимизация.
Еще раз, плиз, две переменные в цикле while.

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

Добавлено: Вт дек 15, 2020 10:37:49
VladislavS
[uquote="Dimon456",url="/forum/viewtopic.php?p=3941792#p3941792"]Я считаю что если одна переменная, то будет оптимизация.[/uquote]Не будет никакой разницы, кроме глупого расхода одного РОН.
[uquote="Dimon456",url="/forum/viewtopic.php?p=3941792#p3941792"]Еще раз, плиз, две переменные в цикле while.[/uquote]
Спойлер

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

//auto a=0;
        MOVS     R0,#+0
//auto b=0;
        MOVS     R1,#+0
        LDR.N    R2,??DataTable1_4  ;; 0x48000018
//while(1)
//{
//  pins1=a++;
??main_0:
        MOV      R3,R0
        AND      R4,R3,#0xF8
        ORR      R4,R4,#0xF80000
        STR      R4,[R2, #+2048]
        LSLS     R5,R3,#+5
        AND      R5,R5,#0x20
        AND      R4,R3,#0x2
        ORRS     R5,R4,R5
        UBFX     R3,R3,#+2,#+1
        ORRS     R5,R3,R5
        ORR      R5,R5,#0x230000
        STR      R5,[R2, #+0]
//  pins2=b++;
        MOV      R3,R1
        AND      R4,R3,#0x3E
        RBIT     R4,R4
        LSRS     R4,R4,#+25
        AND      R4,R4,#0x3E
        LSLS     R3,R3,#+5
        ORR      R4,R4,#0x3E0000
        AND      R3,R3,#0x20
        STR      R4,[R2, #+1024]
        ORR      R3,R3,#0x200000
        ADDS     R0,R0,#+1
        ADDS     R1,R1,#+1
        STR      R3,[R2, #+3072]
//}
        B.N      ??main_0
Компилятор тут тупанул - не объединил переменные. Но вина, скорее, программиста.
GCC, кстати, допёр, что надо объединить переменные
Спойлер

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

20000410:	4d14      	ldr	r5, [pc, #80]	; (20000464 <main+0x58>)
20000412:	4c15      	ldr	r4, [pc, #84]	; (20000468 <main+0x5c>)
20000414:	f8df e054 	ldr.w	lr, [pc, #84]	; 2000046c <main+0x60>
20000418:	2100      	movs	r1, #0
2000041a:	f04f 4c90 	mov.w	ip, #1207959552	; 0x48000000
2000041e:	0148      	lsls	r0, r1, #5
20000420:	f000 0020 	and.w	r0, r0, #32
20000424:	f3c1 0280 	ubfx	r2, r1, #2, #1
20000428:	f001 0702 	and.w	r7, r1, #2
2000042c:	f001 033e 	and.w	r3, r1, #62	; 0x3e
20000430:	4302      	orrs	r2, r0
20000432:	fa93 f3a3 	rbit	r3, r3
20000436:	0e5b      	lsrs	r3, r3, #25
20000438:	f001 06f8 	and.w	r6, r1, #248	; 0xf8
2000043c:	433a      	orrs	r2, r7
2000043e:	f003 033e 	and.w	r3, r3, #62	; 0x3e
20000442:	f446 0678 	orr.w	r6, r6, #16252928	; 0xf80000
20000446:	f442 120c 	orr.w	r2, r2, #2293760	; 0x230000
2000044a:	f443 1378 	orr.w	r3, r3, #4063232	; 0x3e0000
2000044e:	f440 1000 	orr.w	r0, r0, #2097152	; 0x200000
20000452:	61ae      	str	r6, [r5, #24]
20000454:	3101      	adds	r1, #1
20000456:	f8cc 2018 	str.w	r2, [ip, #24]
2000045a:	61a3      	str	r3, [r4, #24]
2000045c:	f8ce 0018 	str.w	r0, [lr, #24]
20000460:	e7dd      	b.n	2000041e <main+0x12>
20000462:	bf00      	nop
20000464:	48000800 	.word	0x48000800
20000468:	48000400 	.word	0x48000400
2000046c:	48000c00 	.word	0x48000c00
ARMClang
Спойлер

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

0x08000790 4912      LDR           r1,[pc,#72]  ; @0x080007DC
0x08000792 2000      MOVS          r0,#0x00
0x08000794 2200      MOVS          r2,#0x00
0x08000798 F00203F8  AND           r3,r2,#0xF8
0x0800079C F0020402  AND           r4,r2,#0x02
0x080007A0 F5030378  ADD           r3,r3,#0xF80000
0x080007A4 F8C13800  STR           r3,[r1,#0x800]
0x080007A8 F3C20380  UBFX          r3,r2,#2,#1
0x080007AC 4423      ADD           r3,r3,r4
0x080007AE F0000420  AND           r4,r0,#0x20
0x080007B2 3020      ADDS          r0,r0,#0x20
0x080007B4 4423      ADD           r3,r3,r4
0x080007B6 F503130C  ADD           r3,r3,#0x230000
0x080007BA 600B      STR           r3,[r1,#0x00]
0x080007BC F002033E  AND           r3,r2,#0x3E
0x080007C0 3201      ADDS          r2,r2,#0x01
0x080007C2 FA93F3A3  RBIT          r3,r3
0x080007C6 0E5B      LSRS          r3,r3,#25
0x080007C8 F5031378  ADD           r3,r3,#0x3E0000
0x080007CC F8C13400  STR           r3,[r1,#0x400]
0x080007D0 F5041300  ADD           r3,r4,#0x200000
0x080007D4 F8C13C00  STR           r3,[r1,#0xC00]
0x080007D8 E7DE      B             0x08000798
0x080007DA BF00      NOP           
0x080007DC 0018      DCW           0x0018
0x080007DE 4800      DCW           0x4800

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

Добавлено: Вт дек 15, 2020 17:26:47
Dimon456
VladislavS писал(а):Компилятор тут тупанул - не объединил переменные. Но вина, скорее, программиста.
Нет, не тупанул, правильно сделал.
К примеру на pins1 весит индикатор какой-то лсд не важно, а на pins2 светодиоды.
Как их можно объединить и для чего?
А что это за строка?

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

LDR.N    R2,??DataTable1_4  ;; 0x48000018

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

Добавлено: Вт дек 15, 2020 18:11:36
VladislavS
[uquote="Dimon456",url="/forum/viewtopic.php?p=3941999#p3941999"]Нет, не тупанул, правильно сделал.[/uquote]Тупанул ещё как. В pins1 и pins2 всегда записывается одинаковое значение. GCC это смог просчитать и выкинул одну переменную. У GCC, правда, какое-то хроническое неумение объединять доступ со смещением от разных базовых адресов.

[uquote="Dimon456",url="/forum/viewtopic.php?p=3941999#p3941999"]Как их можно объединить и для чего?[/uquote]Ну так же как я в С-коде объединил. Так же как GCC это сделал в результате компиляции. Для оптимизации. Я бы ещё на его месте предупреждение "user fool" выдавал.

[uquote="Dimon456",url="/forum/viewtopic.php?p=3941999#p3941999"]А что это за строка?

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

LDR.N    R2,??DataTable1_4  ;; 0x48000018
[/uquote]Загрузка константы из памяти по адресу ??DataTable1_4. В комментарии компилятор показал что это константа 0x48000018 (скорее всего &GPIOA->BSRR).

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

Добавлено: Вт дек 15, 2020 18:51:30
Dimon456
VladislavS писал(а):Тупанул ещё как. В pins1 и pins2 всегда записывается одно и то же значение.
Нет, не тупанул.
Цикл while говорит компилятору что pins1 и pins2 будет использоваться многократно, значит нельзя оптимизировать.
А то что записывается одно и то же значение - это чисто случай, надо было а=10 а в=0, были бы разные значения.
А в С-коде тот же GCC используется, а ну да в иаре другой, свой какой-то.

Ну да ладно, что я хотел, то я получил.

С++ конечно красиво, но все создается на этапе компиляции и как выяснилось, плохая возможность отладки.
Что бы, найти ошибку, что то исправить, надо колупать целый класс, и что там в классе написано, да еще и связано с другими.
Увы, примеров и там и тут навалом.

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

Добавлено: Вт дек 15, 2020 19:10:06
VladislavS
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942042#p3942042"]надо было а=10 а в=0, были бы разные значения.[/uquote]Что значит "были бы"? Если бы у бабушки был хрен... Компилировался конкретный код, в котором вы сами написали a=0 и b=0. Компилятор это не увидел, а значит тупанул.
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942042#p3942042"]С++ конечно красиво, но все создается на этапе компиляции[/uquote]Ну надо же, превратить в недостаток бесспорное достоинство. И, по секрету, чтобы что-то просчитывалось на этапе компиляции надо приложить немалые усилия.
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942042#p3942042"]и как выяснилось, плохая возможность отладки.[/uquote]Кем выяснилось? Когда выяснилось? Много вы С++ кода отладили?
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942042#p3942042"]Что бы, найти ошибку, что то исправить, надо колупать целый класс, и что там в классе написано, да еще и связано с другими.[/uquote]Зачем? Воспринимайте класс как библиотечную функцию. Один раз написал, оттестировал и пользуйся как чёрным ящиком. Чего в него лазить? Вот вы написали код с pins1 и pins2 не зная что внутри и всё правильно сработало. А глупость с а=0 и b=0 без всяких классов сморозили.

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

Добавлено: Вт дек 15, 2020 19:26:09
Reflector
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942042#p3942042"]С++ конечно красиво, но все создается на этапе компиляции и как выяснилось, плохая возможность отладки.[/uquote]
Показывай реализацию для своих двух списков на С, желательно с инициализацией портов, она ведь тоже нужна, а мы оценим как там обстоят дела с отладкой. Потом поменяй пины на другие и продемонстрируй насколько легко получившийся код использовать повторно :)

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

Добавлено: Вт дек 15, 2020 19:48:40
Dimon456
VladislavS, Reflector, уважаемые, мне 51 год, скоро 52 будет, на кой х мне это сдалось? Я уже "там" место себе забронировал.
Мне всего раз потребовалось 40 входов и 40 выходов, и то это на 80С31 лет так 30 назад.
Идите учите молодых, ах да забыл, молодые же в ардуино играют.
Если и начинать изучать С++ это надо начинать с буквы А и года 4 зубрить.

А мне уже лень, я в лучше в танки поиграю.

PS: Reflector, вот вам на С реализация, правда для AVR контроллеров
Спойлер

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

typedef struct{
   volatile uint8_t * port;
   uint8_t            or;
} port_pin;

#define FLASH __flash

#define pn(p,b) {&PORT ## p, _BV(b)}

const FLASH port_pin pins[] = {
  pn(A,3),
  pn(C,5),
  pn(B,4),
  pn(C,6)
};

const FLASH port_pin pin_ns[] = {
  pn(D,1)
};

void port_write (volatile const FLASH port_pin *p, uint8_t a, uint8_t data) 
{	uint8_t s=1;
	   for(uint8_t i=0; i<a; i++, s<<=1){
	   if (data & s)
		   *p->port |= p->or;
		   else
	   	   *p->port &= ~(p->or);
      p++; 
   }
}


port_write (pins, sizeof(pins)/sizeof(port_pin), 0b00001101);
port_write (pins, sizeof(pins)/sizeof(port_pin), 0b00000101);
port_write (pins, sizeof(pins)/sizeof(port_pin), 0);

port_write (pin_ns, sizeof(pin_ns)/sizeof(port_pin), 1);
port_write (pin_ns, sizeof(pin_ns)/sizeof(port_pin), 0);

Как хотите так и трясите, я трясти не буду.

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

Добавлено: Вт дек 15, 2020 23:55:15
VladislavS
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942080#p3942080"]Идите учите молодых[/uquote]А мы этим и занимаемся. Почему мы должны куда-то уходить? Вам не нужно - проходите мимо.
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942080#p3942080"]вот вам на С реализация,[/uquote]C есть С. Что-то вроде того что Reflector по приколу с массивами показал. Только у него массивы упакованы лучше и их руками не надо делать. Единственный вопрос вызывает вот это место

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

*p->port |= p->or;
Сможет ли компилятор тут sbi поставить или будет неэффективная команда записи в память? Я думаю второе.
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942080#p3942080"]

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

port_write (pins, sizeof(pins)/sizeof(port_pin), 0b00001101);
[/uquote]С PinList это бы скомпилировплось в последовательность из пяти команд sbi и сbi. Представляете разницу в скорости для и так небыстрой AVR-ки?

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

Добавлено: Ср дек 16, 2020 03:11:00
Reflector
[uquote="VladislavS",url="/forum/viewtopic.php?p=3942098#p3942098"]C есть С. Что-то вроде того что Reflector по приколу с массивами показал. Только у него массивы упакованы лучше и их руками не надо делать.[/uquote]
Вчера показал, сегодня уже этот код удалил как не выдерживающий конкуренции, а сам он был простейший и отладка будет соответствующая :) Зато аналогичный подход для инициализации наоборот развил, теперь нет функции проверки дубликатов, эта задача легла на функцию инициализации которая и так в цикле читает данные пинов из массива. В сборке без проверок 7-й бит режима отвечает за лок, а для отладочной сборки лочить пины незачем, там этот бит отвечает за проверку дубликатов, плюс FF в конце тоже нет, все массивы стали короче на два байта:

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

PinList<PA1, PA6, PA5, PD14, PB9> pins;
pins.init<PinMode::AF_PushPull, AF5>();
PA5::init<PinMode::PullUp>();
GpioB<0xFF00>::init<PinMode::OpenDrain_MediumSpeed_PullUp>();
pins.mode<PinMode::PushPull, PinMode::PullDown, 3, PinMode::Floating>();
pins.modeInline<PinMode::AF_PushPull, AF5>();
Init() - это тот же mode(), но с проверкой дубликатов, если она включена, а modeInline() вместо массива работает напрямую c регистрами. Для этого кода получаем:

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

ldr r0, [pc, #704]
bl 0x24000c2c
ldr r0, [pc, #704]
bl 0x24000c2c
ldr r0, [pc, #700]
bl 0x24000c2c
ldr r0, [pc, #700]
bl 0x24000c2c

ldr r1, [pc, #696] ; modeInline() инитит 12 регистров, с учетом RMW - это ~50 инструкций
movw r0, #10248
movw r2, #15372
......
strh r2, [r3, #36]
Также получим два сообщения об ошибках:

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

Error: PA5 is Reused!
Error: PB9 is Reused!
Добавлено after 2 hours 57 minutes 46 seconds:
[uquote="Dimon456",url="/forum/viewtopic.php?p=3942080#p3942080"]Если и начинать изучать С++ это надо начинать с буквы А и года 4 зубрить.[/uquote]
Удалил в сишной реализации бесполезный typedef для структуры, заменил все

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

sizeof(pins)/sizeof(port_pin)
на

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

std::size(pins)
И уже пишешь на C++, для сравнения начать изучать STM32 после AVR так просто не получится :)

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

Добавлено: Ср дек 16, 2020 15:28:10
Dimon456
VladislavS писал(а):или будет неэффективная команда записи в память? Я думаю второе.
Правильно думаете
СпойлерНа 64 бита, с возможностью выбора 8-16-32-64, в любой последовательности пинов.
Не знаю поддерживает ли GCC uint128_t?

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

#define k_bit	uint64_t//64бита uint32_t-32бита uint16_t-16бита uint8_t-8бита

typedef struct{
   volatile uint32_t * port;
   k_bit            or;
} port_pin;


#define PORTA (GPIOA->ODR)
#define PORTB (GPIOB->ODR)
#define PORTC (GPIOC->ODR)


#define pn(p,b) {&PORT ## p, (1<<b)}

const port_pin pins[] = {
  pn(A,3),
  pn(A,5),
  pn(A,4),
  pn(A,1),
  pn(A,2),
  pn(A,0),
  pn(A,7),
  pn(A,8),
  pn(A,12),
  pn(A,13),
  pn(A,14),
  pn(A,15),
  pn(C,4),
  pn(C,6),
  pn(C,3),
  pn(C,5),
  pn(C,2),
  pn(C,7),
  pn(C,8),
  pn(C,12),
  pn(C,13),
  pn(C,14),
  pn(B,3),
  pn(B,5),
  pn(B,4),
  pn(B,6),
  pn(B,1),
  pn(B,2),
  pn(B,7),
  pn(B,0),
  pn(B,8),
  pn(B,9),
  pn(B,12),
  pn(B,13),
  pn(B,14)
};

const port_pin pin_ns[] = {
  pn(C,1)
};

void port_write (volatile const port_pin *p, uint8_t a, k_bit data)
{   k_bit s=1;
      for(uint8_t i=0; i<a; i++, s<<=1){
      if (data & s)
         *p->port |= p->or;
         else
            *p->port &= ~(p->or);
      p++;
   }
}

int main(void)
{

	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN;

	GPIOA->CRL &= ~GPIO_CRL_CNF;
	GPIOA->CRL |= GPIO_CRL_MODE;

	GPIOA->CRH &= ~GPIO_CRH_CNF;
	GPIOA->CRH |= GPIO_CRH_MODE;

	GPIOB->CRL &= ~GPIO_CRL_CNF;
	GPIOB->CRL |= GPIO_CRL_MODE;

	GPIOB->CRH &= ~GPIO_CRH_CNF;
	GPIOB->CRH |= GPIO_CRH_MODE;

	GPIOC->CRL &= ~GPIO_CRL_CNF;
	GPIOC->CRL |= GPIO_CRL_MODE;

	GPIOC->CRH &= ~GPIO_CRH_CNF;
	GPIOC->CRH |= GPIO_CRH_MODE;

	port_write (pins, sizeof(pins)/sizeof(port_pin), 0b00100001001001000001000010000100100);
	port_write (pins, sizeof(pins)/sizeof(port_pin), 0b00100101101001001000001010010100100);
	port_write (pins, sizeof(pins)/sizeof(port_pin), 0);

	port_write (pin_ns, sizeof(pin_ns)/sizeof(port_pin), 1);
	port_write (pin_ns, sizeof(pin_ns)/sizeof(port_pin), 0);

    while(1)
    {
    }
}
да же еще без ошибок собирается.
Честно говоря, до последнего не думал что будет работать.
Пусть это и далеко не эффективный код, но он работает, и прекрасно работает.

На F103

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

Program Size:
      text	   data	    bss	    dec	    hex	filename
      1456	      0	   1024	   2480	    9b0	port_103.elf
Есть еще один метод, но он посложнее будет.