Кто любит RISC в жизни, заходим, не стесняемся.
Ответить

Re: Флоаты в STM32F303

Пн фев 14, 2022 18:23:27

Но было бы достаточно посмотреть в стеке данные после вот этой пары команд[code] 0xED94 0x0B02 VLDR D0,[R4, #+8]
В стеке данные нормальные. Я это сразу проверил (поэтому там присутствует m[8] и memset()). Кроме того - если параметр один (типа double), то он вообще через регистры передаётся, а не через стек. В примере два сделал для того, чтобы поверить оба вида передачи.

Я вот стек руками не двигаю от слов совсем никогда.
Я тоже не двигаю. Но если размер стека для задачи указать (случайно) не кратный 8, то дальше он везде пойдёт невыровненный.

Eddy_Em писал(а):Даже с оптимизацией -O3 он пишет именно так вместо bic.w r2, r2, 0xc3c00000
Затем, что иначе ему пришлось бы добавлять команду LDR. А это дороже и по размеру и по тактам.
Компилятор знает систему команд CPU. В отличие от вас. :dont_know:

Re: Флоаты в STM32F303

Пн фев 14, 2022 18:47:51

Что-то gcc дурью мается.
Ох и на скользкую дорожку ты встал. С твоей категоричностью смотреть листинги компиляторов вредно для здоровья :) Возможно, тебе IAR больше подойдёт, он обычно более прямолинеен.
Код:
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE15_Msk | GPIO_MODER_MODE11_Msk | GPIO_MODER_MODE12_Msk));
       
        MOV      R1,#+1207959552  ; GPIOA.MODER
        LDR.N    R0,??DataTable0  ; 0x3C3F'FFFF
        LDR      R2,[R1, #+0]   
        ANDS     R2,R0,R2       
        STR      R2,[R1, #+0]

??DataTable0:
        DC32     0x3c3fffff

Re: Флоаты в STM32F303

Пн фев 14, 2022 19:21:52

Да черт с ним. Просто мне непонятно, зачем gcc разбивает то, что можно в один присест сделать, на две операции!
Зато вот это:
Код:
TRUE_INLINE uint32_t AFRf(uint8_t afr, uint8_t pin){
    if(pin > 7) pin -= 8;
    return (afr << (pin * 4));
}

Оптимизирует до константы. Жаль, нельзя как в С++ проверку диапазона сделать на стадии препроцессора. Хотя, для F303 особо и не проверишь: и AFR, и пины с номерами от 0 до 15…

Re: Флоаты в STM32F303

Пн фев 14, 2022 19:29:59

Загружать длинные константы в регистры дорого. Я же тебе показывал вчера на разрешении домтупа к FPU.

Re: Флоаты в STM32F303

Пн фев 14, 2022 19:52:35

Просто мне непонятно, зачем gcc разбивает то, что можно в один присест сделать, на две операции!

Сейчас у тебя две 4-х байтных инструкции с встроенными константами, выполняемые за 2 такта суммарно. Можно использовать AND с парой регистров, но сначала во второй придется загрузить 32-х битную константу, это можно сделать загружая половинки регистра при помощи тех же двух 4-х байтных инструкций, или читая в регистр из флеша, а это 2-х байтная LDR плюс 4 байта где-то во флеше, чтение из которого не такое и быстрое.

Re: Флоаты в STM32F303

Пн фев 14, 2022 19:59:48

Загружать длинные константы в регистры дорого.

Ну так ладно бы разбили на 2 16-битные операции. Но нет, там ведь 32-битные!!! Так чего ж здесь дорогого?

Re: Флоаты в STM32F303

Пн фев 14, 2022 20:22:47

Можно я его укушу? :) Считай
GCC
Код:
0x200007c2 4F F0 90 45          mov.w r5, #1207959552   ; 0x48000000
0x200007c6 2B 68                ldr r3, [r5, #0]
0x200007c8 23 F0 43 43          bic.w r3, r3, #3271557120   ; 0xc3000000
0x200007cc 23 F4 40 03          bic.w r3, r3, #12582912   ; 0xc00000
0x200007d0 2B 60                str r3, [r5, #0]

IAR
Код:
  0x2000'1466: 0xf04f 0x4490  MOV.W     R4, #1207959552         ; 0x4800'0000
  0x2000'146a: 0x4827         LDR.N     R0, ??DataTable3        ; 0x3c3f'ffff
  0x2000'146c: 0x6821         LDR       R1, [R4]
  0x2000'146e: 0x4001         ANDS      R1, R1, R0
  0x2000'1470: 0x6021         STR       R1, [R4]

??DataTable3:
  0x2000'1508: 0x3c3f'ffff    DC32      0x3c3f'ffff

Keil
Код:
0x20001FA2 F04F4090  MOV           r0,#0x48000000
0x20001FA6 6801      LDR           r1,[r0,#0x00]
0x20001FA8 F64F72FF  MOVW          r2,#0xFFFF
0x20001FAC F6C3423F  MOVT          r2,#0x3C3F
0x20001FB0 4011      ANDS          r1,r1,r2
0x20001FB2 6001      STR           r1,[r0,#0x00]

Re: Флоаты в STM32F303

Пн фев 14, 2022 22:39:57

VladislavS, еще раз: какого хрена gcc сразу не делает bic.w r3, r3, 0xc3c00000 ???
Или ты считаешь, что это - нормально? Какая ему, нафиг, разница: забульбенить константу 0xc3000000, а потом 0xc00000, или же сразу готовую?

Ну маразм же!!!!!1111

Re: Флоаты в STM32F303

Пн фев 14, 2022 23:04:49

Syntax of Operand2 as a constant

Re: Флоаты в STM32F303

Пн фев 14, 2022 23:29:19

Ух, епта! ОК, спасибо. Теперь понятно. Я-то думал, что пофиг, какая константа - абы 32 бита… А тут, оказывается, нужно, чтобы только 8 бит разными были…

Re: Флоаты в STM32F303

Ср фев 21, 2024 10:50:18

Вот такой код, выполняется за 5.11mS с вроде бы как включенными FPU. т.к только начинаю изучать stm32 не знаю как оценить результат. Прошу подсказать по использованию FPU и настроек.
Библиотека <math.h>,
--specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -Wl,--end-group
в int main() вызываю вначале и только потом инициализация пртов, ацп дма таймеров цап ит.п.:
Код:
 void SystemInit(void)
{
/* FPU settings ----------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
  SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
#endif
}

прочитал всю эту тему не понял где находится reset_handler и где по этому поводу инфы найти.
Сам код:
Код:
         GPIOC->BSRR = GPIO_BSRR_BS_14;
         for (uint16_t i = 0; i < ADC_BUFFER_SIZE; i++) //#define ADC_BUFFER_SIZE 512U
         {   uint16_t j = i / 2;
            float step = (float)j / SAMPLES_NO; // SAMPLES_NO (ADC_BUFFER_SIZE/2)   
            if (i % 2 == 0) //четность массива
            {
               BufInArray[j] = Buffer_ADC[i];
               Re += (float)BufInArray[j] * cosf(TWOPI_F * step);
               Im += (float)BufInArray[j] * sinf(TWOPI_F * step);
            }
            else
            {
               BufInArray_2[j] = Buffer_ADC[i];
               Re_2 += (float)BufInArray_2[j] * cosf(TWOPI_F * step);
               Im_2 += (float)BufInArray_2[j] * sinf(TWOPI_F * step);
            }
         }
         
         Angle = atan2f(Im, Re);
         Angle = Angle * RAD; // RAD=(180/ПИ)
         Angle_2 = atan2f(Im_2, Re_2);
         Angle_2 = Angle_2 * RAD;
         Re = 0; Re_2 = 0; Im = 0; Im_2 = 0;
         GPIOC->BSRR = GPIO_BSRR_BR_14;

Re: Флоаты в STM32F303

Ср фев 21, 2024 13:48:42

kote52, первым делом надо научиться смотреть листинг, либо в режиме отладки пошагово смотреть.

reset_handler в стартапе.

Re: Флоаты в STM32F303

Ср фев 21, 2024 15:27:08

kote52, reset_handler в стартапе.

Это предположу что найду в папке Startup>startup_stm32f303cctx.s

Re: Флоаты в STM32F303

Чт фев 22, 2024 17:03:07

Вот такой код, выполняется за 5.11mS с вроде бы как включенными FPU. т.к только начинаю изучать stm32 не знаю как оценить результат. Прошу подсказать по использованию FPU и настроек.
Наличие использования FPU в коде определяется одним взглядом в файлы листингов. Включение генерации листингов (при компиляции) - ищите где включается в вашем компиляторе.

Код:
         for (uint16_t i = 0; i < ADC_BUFFER_SIZE; i++) //#define ADC_BUFFER_SIZE 512U
         {   uint16_t j = i / 2;
...
Совет: Рабочие целочисленные переменные внутри функций следует делать типа int или unsigned int (т.е. - равными основной разрядности процессора). Не менее. Чтобы понять "почему", опять-же - изучайте листинги.

Добавлено after 7 minutes 8 seconds:
...
{
BufInArray[j] = Buffer_ADC[i];
Re += (float)BufInArray[j] * cosf(TWOPI_F * step);
Im += (float)BufInArray[j] * sinf(TWOPI_F * step);
}
else
{
BufInArray_2[j] = Buffer_ADC[i];
Re_2 += (float)BufInArray_2[j] * cosf(TWOPI_F * step);
Im_2 += (float)BufInArray_2[j] * sinf(TWOPI_F * step);
}
}
...[/code]
Зачем дважды одно и то же вычисляете?
Вам за размер исходника платят? 8)

Re: Флоаты в STM32F303

Чт фев 22, 2024 21:47:12

Наличие использования FPU в коде определяется одним взглядом в файлы листингов. Включение генерации листингов (при компиляции) - ищите где включается в вашем компиляторе.

VisualStudio+VisualGDB.Направление правильно понял - дисассемблер
Добавлено after 7 minutes 8 seconds:
...
{
BufInArray[j] = Buffer_ADC[i];
Re += (float)BufInArray[j] * cosf(TWOPI_F * step);
Im += (float)BufInArray[j] * sinf(TWOPI_F * step);
}
else
{
BufInArray_2[j] = Buffer_ADC[i];
Re_2 += (float)BufInArray_2[j] * cosf(TWOPI_F * step);
Im_2 += (float)BufInArray_2[j] * sinf(TWOPI_F * step);
}
}
...[/code]
Зачем дважды одно и то же вычисляете?
Вам за размер исходника платят? 8)

ну у меня по таймеру3 ацп1 и ацп2 в режиме Dual mode работают, ДМА настроено на полное слово, поэтому я данные в прерывании ДМА из буфера забираю в Buffer_ADC[] по половине и полной передаче, и потом сортирую в этом цикле четные это ацп1 BufInArray[], нечетные ацп2 BufInArray_2[]. Тут нет двойной работы. НЕ конечно можно не перекидывать в два разных буфера четное и не четное - минус два массива, а сразу вычислять - пока просто так играюсь.
Совет: Рабочие целочисленные переменные внутри функций следует делать типа int или unsigned int (т.е. - равными основной разрядности процессора). Не менее. Чтобы понять "почему", опять-же - изучайте листинги.

Вы об этом. для 8-битных микроконтроллеров char — 8бит, int 16бит, long 32бита. Для 32-х битных char — 8бит, short 16бит, int 32бита, long 64 бита.

Re: Флоаты в STM32F303

Пт фев 23, 2024 01:32:27

Тут нет двойной работы.
Есть дважды написанные одни и те же вычисления - вычисление синуса и косинуса (и вычисления вокруг них).
Вот так будет без двойной работы (если я правильно угадал разрядность BufInArray[] и BufInArray_2[]):
Код:
uint i;
u16 *p = &BufInArray[j];
if (i % 2) p = &BufInArray_2[j]; //нечётность массива
*p = i = Buffer_ADC[i];
float x0 = i * cosf(TWOPI_F * step);
float x1 = i * sinf(TWOPI_F * step);
if (i % 2) {
  Re_2 += x0;
  Im_2 += x1;
} else {
  Re += x0;
  Im += x1;
}
Можно и ещё лаконичнее написать, если вместо двух массивов BufInArray[] и BufInArray_2[] завести один двумерный BufInArray[2][] (или BufInArray[][2]) и вместо Re/Im и Re_2/Im_2 завести также массив из двух экземпляров:
Код:
struct {
  float Re, Im;
} x[2];


Вы об этом. для 8-битных микроконтроллеров char — 8бит, int 16бит, long 32бита. Для 32-х битных char — 8бит, short 16бит, int 32бита, long 64 бита.
Тогда зачем у вас рабочие переменные (счётчики) - 16-разрядные? У вас же ARM. Их лучше делать типа uint.

Re: Флоаты в STM32F303

Пт фев 23, 2024 09:45:43

Есть дважды написанные одни и те же вычисления - вычисление синуса и косинуса (и вычисления вокруг них).
Вот так будет без двойной работы (если я правильно угадал разрядность BufInArray[] и BufInArray_2[]):
Код:
uint i;
u16 *p = &BufInArray[j];
if (i % 2) p = &BufInArray_2[j]; //нечётность массива
*p = i = Buffer_ADC[i];
float x0 = i * cosf(TWOPI_F * step);
float x1 = i * sinf(TWOPI_F * step);
if (i % 2) {
  Re_2 += x0;
  Im_2 += x1;
} else {
  Re += x0;
  Im += x1;
}

Можно и ещё лаконичнее написать, если вместо двух массивов BufInArray[] и BufInArray_2[] завести один двумерный BufInArray[2][] (или BufInArray[][2]) и вместо Re/Im и Re_2/Im_2 завести также массив из двух экземпляров

Ну я ж написал что вообще можно обойтись без массивов BufInArray[] и BufInArray_2[], и работать только Buffer_ADC[i], хватило бы скорости вычислений, можно еще (TWOPI_F * step) считать один раз, а не два.
Еще раз спрошу, а точно двойная? Что вы, что я - посчитали sin и cos ровно 512, у меня после сортировки четность/нечетность был расчет, у вас до и потом раскидали. В чем фокус?
Тогда зачем у вас рабочие переменные (счётчики) - 16-разрядные? У вас же ARM. Их лучше делать типа uint.

для 8-битных микроконтроллеров char — 8бит, int 16бит, long 32бита, такое случается с новичками постоянно :dont_know:

Re: Флоаты в STM32F303

Пт фев 23, 2024 10:48:46

посчитали sin и cos ровно 512

Я так понимаю, что вы пытаетесь написать ДПФ.
Внезапно вопрос. А вы понимаете уровень боковых лепестков у прямоугольного окна?
Внезапно второй вопрос. Много ли бинов вы собираетесь считать в одном цикле накопления массивов?
ЗЫ. У меня тоже один кадр накопления содержит 512 отсчетов. Но вычисление скалярной амплитуды (фаза мне не нужна) ШЕСТИ каналов в каждом по 512 отсчетов занимает примерно 700 мкс. Причем окно не прямоугольное, а Хемминга (можно любое другое - это не принципиально). И делаю я это не во флоатах, а в целых числах. Ибо АЦП 12 разрядов для FIR не требует флоатов от слова совсем. Флоаты для такой разрядности если и нужны (а скорее просто удобны) - это для IIR фильтрации.

Re: Флоаты в STM32F303

Пт фев 23, 2024 10:56:49

КРАМ, не пытайтесь тему утянуть в нужную для вас сторону, её название ДРУГОЕ и тематика ДРУГАЯ! Выше все вопросы озвучены, хотите помочь? пожалуйста!

Re: Флоаты в STM32F303

Пт фев 23, 2024 11:04:45

Тема та же самая. Я пытаюсь понять зачем вы СЧИТАЕТЕ синус и косинус. Обычно их забивают таблицей. Причем сразу умножают на оконную функцию. Вы интересуетесь с чего вдруг 5 с лишним миллисекунд, а сами 1024 раза считаете ПЕРИОДИЧЕСКУЮ функцию в МК, где нет CORDIC-а... В чем сакральный смысл этого мазохизма?
Впрочем, все обсуждение свелось не к тому, как включить FPU, а к обсуждению самого кода. Так что все вопросы по содержанию - это не ко мне.
Ответить