Но было бы достаточно посмотреть в стеке данные после вот этой пары команд[code] 0xED94 0x0B02 VLDR D0,[R4, #+8]
В стеке данные нормальные. Я это сразу проверил (поэтому там присутствует m[8] и memset()). Кроме того - если параметр один (типа double), то он вообще через регистры передаётся, а не через стек. В примере два сделал для того, чтобы поверить оба вида передачи.
Ох и на скользкую дорожку ты встал. С твоей категоричностью смотреть листинги компиляторов вредно для здоровья Возможно, тебе IAR больше подойдёт, он обычно более прямолинеен.
Оптимизирует до константы. Жаль, нельзя как в С++ проверку диапазона сделать на стадии препроцессора. Хотя, для F303 особо и не проверишь: и AFR, и пины с номерами от 0 до 15…
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Просто мне непонятно, зачем gcc разбивает то, что можно в один присест сделать, на две операции!
Сейчас у тебя две 4-х байтных инструкции с встроенными константами, выполняемые за 2 такта суммарно. Можно использовать AND с парой регистров, но сначала во второй придется загрузить 32-х битную константу, это можно сделать загружая половинки регистра при помощи тех же двух 4-х байтных инструкций, или читая в регистр из флеша, а это 2-х байтная LDR плюс 4 байта где-то во флеше, чтение из которого не такое и быстрое.
Ну так ладно бы разбили на 2 16-битные операции. Но нет, там ведь 32-битные!!! Так чего ж здесь дорогого?
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
VladislavS, еще раз: какого хрена gcc сразу не делает bic.w r3, r3, 0xc3c00000 ??? Или ты считаешь, что это - нормально? Какая ему, нафиг, разница: забульбенить константу 0xc3000000, а потом 0xc00000, или же сразу готовую?
Ну маразм же!!!!!1111
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Ух, епта! ОК, спасибо. Теперь понятно. Я-то думал, что пофиг, какая константа - абы 32 бита… А тут, оказывается, нужно, чтобы только 8 бит разными были…
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Зарегистрирован: Пт мар 19, 2021 08:58:45 Сообщений: 120
Рейтинг сообщения:0
Вот такой код, выполняется за 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() вызываю вначале и только потом инициализация пртов, ацп дма таймеров цап ит.п.:
Вот такой код, выполняется за 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 (т.е. - равными основной разрядности процессора). Не менее. Чтобы понять "почему", опять-же - изучайте листинги.
Наличие использования FPU в коде определяется одним взглядом в файлы листингов. Включение генерации листингов (при компиляции) - ищите где включается в вашем компиляторе.
Зачем дважды одно и то же вычисляете? Вам за размер исходника платят?
ну у меня по таймеру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 бита.
Есть дважды написанные одни и те же вычисления - вычисление синуса и косинуса (и вычисления вокруг них). Вот так будет без двойной работы (если я правильно угадал разрядность 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[]):
Код:
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, у меня после сортировки четность/нечетность был расчет, у вас до и потом раскидали. В чем фокус?
Я так понимаю, что вы пытаетесь написать ДПФ. Внезапно вопрос. А вы понимаете уровень боковых лепестков у прямоугольного окна? Внезапно второй вопрос. Много ли бинов вы собираетесь считать в одном цикле накопления массивов? ЗЫ. У меня тоже один кадр накопления содержит 512 отсчетов. Но вычисление скалярной амплитуды (фаза мне не нужна) ШЕСТИ каналов в каждом по 512 отсчетов занимает примерно 700 мкс. Причем окно не прямоугольное, а Хемминга (можно любое другое - это не принципиально). И делаю я это не во флоатах, а в целых числах. Ибо АЦП 12 разрядов для FIR не требует флоатов от слова совсем. Флоаты для такой разрядности если и нужны (а скорее просто удобны) - это для IIR фильтрации.
Тема та же самая. Я пытаюсь понять зачем вы СЧИТАЕТЕ синус и косинус. Обычно их забивают таблицей. Причем сразу умножают на оконную функцию. Вы интересуетесь с чего вдруг 5 с лишним миллисекунд, а сами 1024 раза считаете ПЕРИОДИЧЕСКУЮ функцию в МК, где нет CORDIC-а... В чем сакральный смысл этого мазохизма? Впрочем, все обсуждение свелось не к тому, как включить FPU, а к обсуждению самого кода. Так что все вопросы по содержанию - это не ко мне.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 25
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения