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

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

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

Сообщение Reflector »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3943052#p3943052"]Так что сократить не получится, только усложнить.[/uquote]
Потестил немного на 32-х пиновом списке. Стандартная версия быстрее твоей в 11 раз, а если пины более-менее упорядочить, то получим еще значительное ускорение. Моя медленная реализация, с BSRR и одним байтом на пин, быстрее в 1.6 раза.
Реклама
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

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

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

Сообщение Dimon456 »

Reflector, за-то без всяких там классов и 3-4 страниц не известно какого кода.
Но пока сравнить не с чем, вашего кода, а особенно кода VladislavS я не видел.

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

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

Сообщение VladislavS »

Вам же открытым текстом написали КАК.
[uquote="VladislavS",url="/forum/viewtopic.php?p=3942425#p3942425"]Хоть бы через BSRR сделали.[/uquote]
[uquote="VladislavS",url="/forum/viewtopic.php?p=3942962#p3942962"]Вот этот ваш код

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

if (data & s)
  *p->port |= p->or;
else
  *p->port &= ~(p->or);
можно сократить в три раза.[/uquote]
[uquote="VladislavS",url="/forum/viewtopic.php?p=3943070#p3943070"]В ветке про асм стыдно не знать, что доступ к BSRR и BRR можно через один указатель получить.[/uquote]
[uquote="VladislavS",url="/forum/viewtopic.php?p=3943097#p3943097"]как-то неспортивно - соревноваться с пишущими в BSRR через |=.[/uquote]

Дай голодному рыбу и он насытится на день. Научи его ловить рыбу и он будет сыт всю жизнь.

Скомпилируйте свой код, посмотрите листинг, найдите в нём слабое место, исправьте. Вот тогда будет польза.
Реклама
Эиком - электронные компоненты и радиодетали
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

VladislavS, я не знал что в этот регистр можно просто писать, все равно это ни чего не меняет, чуть-чуть не считается.

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

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

Сообщение VladislavS »

В три раза это не чуть-чуть. Хотя, если это вам не надо, то мне и подавно.
Реклама
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

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

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

Сообщение VladislavS »

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

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

Сообщение Reflector »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3943190#p3943190"]VladislavS, я не знал что в этот регистр можно просто писать[/uquote]
В теме "STM32 новичку..." VladislavS приводил пример класса TSimplePort специально для тебя, с комментариями, а в классе была фактически одна функция преимущественно пишущая в BRR/BSRR:

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

  static inline void toggle()
  {
    if constexpr (PM == 0xFFFF)
      base()->ODR = ~base()->ODR;
    else
      if constexpr (countSetBits(PM)==1)
        if(base()->ODR & PM) base()->BRR = PM; else base()->BSRR = PM;
      else 
        base()->BSRR = (PM << 16) | (~base()->ODR & PM);
  }
Это помимо обсуждения BSRR в той-же теме...
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Посмотрел во что же этот ужас от Dimon456 выливается. Листинг того что было
Спойлер

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

//  210 void port_write (const port_pin *p, uint8_t a, k_bit data)
//  211 {   k_bit s=1;
_Z10port_writePK8port_pinhy:
        PUSH     {R4-R9,LR}
        MOV      R12,R0
        MOV      R4,R1
        MOV      R0,R2
        MOV      R1,R3
        MOVS     R6,#+1
        MOVS     R7,#+0
//  212       for(uint8_t i=0; i<a; i++, s<<=1){
        MOVS     R2,#+0
        MOV      R3,R4
        B.N      ??port_write_0
//  213       if (data & s)
??port_write_1:
        LDR      LR,[R12, #+0]
        LDR      R9,[R12, #+4]
        LDR      R8,[LR, #+0]
        AND      R4,R0,R6
        ANDS     R5,R1,R7
        ITTE     EQ 
        CMPEQ    R4,#+0
        BICEQ    R4,R8,R9
        ORRNE    R4,R9,R8
//  214          *p->port|= p->_or;
//  215          else
//  216             *p->port &= ~(p->_or);
//  217       p++;
//  218    }
        LSLS     R7,R7,#+1
        ORR      R7,R7,R6, LSR #+31
        STR      R4,[LR, #+0]
        ADD      R12,R12,#+8
        ADDS     R2,R2,#+1
        LSLS     R6,R6,#+1
??port_write_0:
        UXTB     R4,R2
        CMP      R4,R3
        BCC.N    ??port_write_1
//  219 }
        POP      {R4-R9,PC}       ;; return
Не долго думая переписал без 64-битной арифметики.

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

typedef struct{
   uint32_t *bsrr;
   uint32_t mask;
} port_pin;

void port_write64 (const port_pin *p, int a, uint64_t data)
{  
  do 
  { 
    uint32_t const count = a>32 ? 32 : a ;
    for(uint8_t i=0; i<count; i++) 
    {
      if ((uint32_t)data & (1<<i))
        *p->bsrr = p->_or;
       else
         *(p->bsrr+4) = p->_or;
         // Для контроллеров у которых нет BSRR
         //*(volatile uint16_t *)((uint16_t *)p->bsrr+1) = p->_or; 
      p++;       
    }
    data >>= 32; 
    a-=32;
  } 
  while(a>0);
}
Листинг. Основной цикл похудел. Должно прибавить в скорости значительно.
Спойлер

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

//void port_write64 (const port_pin *p, int a, uint64_t data)
//{  
_Z12port_write64PK8port_piniy:
        PUSH     {R4-R7,LR}
//  do 
//  { 
//    uint32_t const count = a>32 ? 32 :a ;
??port_write64_0:
        CMP      R1,#+33
        ITE      GE 
        MOVGE    R4,#+32
        MOVLT    R4,R1
//    for(uint8_t i=0; i<count; i++) 
        MOVS     R5,#+0
        B.N      ??port_write64_1
//    {
??port_write64_2:
//      if ((uint32_t)data & (1<<i))
        LDR      R7,[R0, #+4]
        LDR      R6,[R0, #+0]
        LSR      R12,R2,R5
        LSLS     LR,R12,#+31
//        *p->bsrr = p->_or;
//      else
//        *(p->bsrr+4) = p->_or;        
        ITE      PL 
        STRPL    R7,[R6, #+16]
        STRMI    R7,[R6, #+0]
//      p++;       
        ADDS     R0,R0,#+8
//    }
        ADDS     R5,R5,#+1
??port_write64_1:
        UXTB     R6,R5
        CMP      R6,R4
        BCC.N    ??port_write64_2
//    data >>= 32; 
        MOV      R2,R3
        MOVS     R3,#+0
//    a-=32;
        SUBS     R1,R1,#+32
//  } 
//  while(a>0);
        CMP      R1,#+1
        BGE.N    ??port_write64_0
//}
        POP      {R4-R7,PC}       ;; return
За неимением constexpr для коротких списков руками вот такую вызывать

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

void port_write32 (const port_pin *p, uint32_t a, uint32_t data)
{    
  for(uint8_t i=0; i<a; i++)
  {
    if (data & (1<<i))
      *p->bsrr = p->_or;
     else
       *(p->bsrr+4) = p->mask;
       // Для контроллеров у которых нет BRR
       //*(volatile uint16_t *)((uint16_t *)p->bsrr+1) = p->mask; 
    p++;
  }  
}   
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

VladislavS, вы только листинг смотрите или еще что?
Такая конструкция
Спойлер

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

*(p->port+4) = p->or;
*(volatile uint16_t *)((uint16_t *)p->port+4) = p->or;
уводит МК в hard fault
Я не знаю как у вас, ide - компилятор - С++, таблица находится во флеш, соответственно должен быть вызов не const port_pin *p а volatile const port_pin *p, хотя может быть у вас это и позволяет.
Тем не менее сделал сравнительные тесты, исправив кое-что что бы работало
Спойлер

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

Program Size:	port_write 89us
      text	   data	    bss	    dec	    hex	filename
      1216	      0	   1024	   2240	    8c0	port_103.elf
	  
Program Size:	port_write64 108us
      text	   data	    bss	    dec	    hex	filename
      1288	      0	   1024	   2312	    908	port_103.elf
	  
Program Size:  port_write32 104us 
      text	   data	    bss	    dec	    hex	filename
      1224	      0	   1024	   2248	    8c8	port_103.elf
port_write моя функция, остальные две ваши, us - время в микро секундах измеренное в протеусе + проверка на реальном МК.
Что вы пытаетесь с этой функции выжить, мне не понятно.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3943325#p3943325"]VladislavS, вы только листинг смотрите или еще что?[/uquote]Моего опыта хватает, чтобы по листингу сказать как это будет работать.

[uquote="Dimon456",url="/forum/viewtopic.php?p=3943325#p3943325"]Такая конструкция

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

*(p->port+4) = p->or;
*(volatile uint16_t *)((uint16_t *)p->port+4) = p->or;
уводит МК в hard fault[/uquote]OMG!!! Во-первых, даже скопировать не можете правильно. У меня не такой код. Во-вторых, нужна либо первая, либо вторая строка. Зачем их вместе то? Вы вообще не понимаете что код делает? В-третьих, и самое главное, у вас F103 - у него есть BRR и нет пословного доступа к BSRR!!! Снимать комментарий с этой строки было в высшей степени глупо.

[uquote="Dimon456",url="/forum/viewtopic.php?p=3943325#p3943325"]Я не знаю как у вас, ide - компилятор - С++, таблица находится во флеш, соответственно должен быть вызов не const port_pin *p а volatile const port_pin *p, хотя может быть у вас это и позволяет.[/uquote]volatile нужен только в одном месте - при доступе к регистру BSRR. Во всех остальных местах его надо резать не дожидаясь перитонита! Нечего ему делать ни во флеше, ни в параметре функции.

[uquote="Dimon456",url="/forum/viewtopic.php?p=3943325#p3943325"]Что вы пытаетесь с этой функции выжить, мне не понятно.[/uquote]Скорость. Ещё страницу назад вы утверждали, что эту функцию нельзя оптимизировать в принципе. Называли меня болтуном. А потом, оказалось, в 4!!! раза оптимизируется. Где извинения?
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

VladislavS, ну извините высокоинтеллектуальный программист,
не соблаговолит ли ВАША светлость проверить, что будет в переменной temp после выполнения этого кода

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

uint32_t temp;
volatile const port_pin *p;

	p = pins;
	
	temp = p->bsrr+4;
а потом вот эту строку, плиз

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

temp = (volatile uint16_t *)((uint16_t *)p->bsrr+1);
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Зашибись. Это мне в ответ на хамство ещё и ошибки в вашем коде искать?
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

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

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

Сообщение VladislavS »

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

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

Сообщение Dimon456 »

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

Ну да ладно, как вам, уважаемый, такой вариант?
Спойлер

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

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)
         ((GPIO_TypeDef *) p->port)->BSRR = p->or;
         else
         ((GPIO_TypeDef *) p->port)->BSRR = p->and;
      p++;
   }
}
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Плохо. Я для кого тут распинался?
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

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

Сообщение Dimon456 »

VladislavS писал(а):Плохо. Я для кого тут распинался?
Видимо для себя
Спойлер

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

Program Size:   port_write 89us
      text      data       bss       dec       hex   filename
      1216         0      1024      2240       8c0   port_103.elf
    
Program Size:   port_write64 108us
      text      data       bss       dec       hex   filename
      1288         0      1024      2312       908   port_103.elf
    
Program Size:  port_write32 104us
      text      data       bss       dec       hex   filename
      1224         0      1024      2248       8c8   port_103.elf
не только больше по объему, один на 72 другой на 8 байт, но и по времени выполнения, 89/108/104 us
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

[uquote="Dimon456",url="/forum/viewtopic.php?p=3943901#p3943901"]не только больше по объему, один на 72 другой на 8 байт, но и по времени выполнения, 89/108/104 us.[/uquote]Во-первых, вы не показали что компилировали. Судя по усердной борьбе с HardFault - сравнивали вы между собой какую-то хрень, а не мой пример.

Во-вторых, я свои примеры скомпилировал и там даже по листингу видно, что они быстрее. Из главного цикла "вынута" 64-битная арифметика. А цикл там аж 36 раз выполняется.

В-третьих, что вы там измеряли вообще непонятно. Возьмём те же 104 мкс на установку 36 бит. У f103 частота 72 МГц. Я должен поверить, что на установку одного бита уходит 104/36*72 = 208 тактов процессора? Даже если вы его на 8 МГц измеряли с пьяну, то это 23 такта на бит - овердофига для листинга из моего сообщения. Так что, без кода и листинга это всё бла-бла.

В-четвёртых, скорость и размер кода вообще сложносвязанные величины. Оптимизация по скорости очень часто идёт за счёт увеличения размера кода. Например, IAR при определённых настройках в этой функции частично разворачивает цикл - делает 8х4 итераций. Размер кода растёт в несколько раз, скорость лишь незначительно. Поэтому, при "выжимании" скорости/размера открываем листинг и смотрим что там получается. Я больше чем уверен, что вы ни разу этого не сделали.

А потом приходит Reflector и показывает алгоритм, работающий в 10 раз быстрее :)))

[uquote="Dimon456",url="/forum/viewtopic.php?p=3943901#p3943901"]Видимо для себя[/uquote]У меня тоже такое ощущение складывается. Открытым текстом вам рассказываешь что и как надо делать, а вы в упор не слышите. Как будто мы на разных языках разговариваем. Да ещё и хамство в ответ. :(
Ответить

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