Salamander
Участник*-
Постов
637 -
Зарегистрирован
-
Посещение
Весь контент Salamander
-
Вроде все нормально. Но немного глючит DMA2D. У меня последовательно осуществляется несколько посылок информации через DMA2D, то есть есть несколько вот таких конструкций (с отличиями), идущих друг за другом hdma2d.Init.Mode = DMA2D_R2M; hdma2d.Init.ColorMode = DMA2D_OUTPUT_ARGB8888; hdma2d.Init.OutputOffset =0; HAL_DMA2D_Init(&hdma2d); if(HAL_DMA2D_Start(&hdma2d, 0xFFFFFFFF, 0xD0400000, 1024, 600) == HAL_OK) { HAL_DMA2D_PollForTransfer(&hdma2d, 10); } Вот текст функции HAL_DMA2D_PollForTransfer Это выше моих сил.... Скажите - эта функция дожидается окончания передачи? Программа идет дальше после окончания передачи или сразу же после запуска копирования? HAL_StatusTypeDef HAL_DMA2D_PollForTransfer(DMA2D_HandleTypeDef *hdma2d, uint32_t Timeout) { uint32_t tickstart; uint32_t layer_start; __IO uint32_t isrflags = 0x0U; /* Polling for DMA2D transfer */ if((hdma2d->Instance->CR & DMA2D_CR_START) != 0U) { /* Get tick */ tickstart = HAL_GetTick(); while(__HAL_DMA2D_GET_FLAG(hdma2d, DMA2D_FLAG_TC) == 0U) { isrflags = READ_REG(hdma2d->Instance->ISR); if ((isrflags & (DMA2D_FLAG_CE|DMA2D_FLAG_TE)) != 0U) { if ((isrflags & DMA2D_FLAG_CE) != 0U) { hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CE; } if ((isrflags & DMA2D_FLAG_TE) != 0U) { hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TE; } /* Clear the transfer and configuration error flags */ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CE | DMA2D_FLAG_TE); /* Change DMA2D state */ hdma2d->State = HAL_DMA2D_STATE_ERROR; /* Process unlocked */ __HAL_UNLOCK(hdma2d); return HAL_ERROR; } /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U)) { /* Update error code */ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT; /* Change the DMA2D state */ hdma2d->State = HAL_DMA2D_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hdma2d); return HAL_TIMEOUT; } } } } /* Polling for CLUT loading (foreground or background) */ layer_start = hdma2d->Instance->FGPFCCR & DMA2D_FGPFCCR_START; layer_start |= hdma2d->Instance->BGPFCCR & DMA2D_BGPFCCR_START; if (layer_start != 0U) { /* Get tick */ tickstart = HAL_GetTick(); while(__HAL_DMA2D_GET_FLAG(hdma2d, DMA2D_FLAG_CTC) == 0U) { isrflags = READ_REG(hdma2d->Instance->ISR); if ((isrflags & (DMA2D_FLAG_CAE|DMA2D_FLAG_CE|DMA2D_FLAG_TE)) != 0U) { if ((isrflags & DMA2D_FLAG_CAE) != 0U) { hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CAE; } if ((isrflags & DMA2D_FLAG_CE) != 0U) { hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CE; } if ((isrflags & DMA2D_FLAG_TE) != 0U) { hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TE; } /* Clear the CLUT Access Error, Configuration Error and Transfer Error flags */ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CAE | DMA2D_FLAG_CE | DMA2D_FLAG_TE); /* Change DMA2D state */ hdma2d->State= HAL_DMA2D_STATE_ERROR; /* Process unlocked */ __HAL_UNLOCK(hdma2d); return HAL_ERROR; } /* Check for the Timeout */ if(Timeout != HAL_MAX_DELAY) { if(((HAL_GetTick() - tickstart ) > Timeout)||(Timeout == 0U)) { /* Update error code */ hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT; /* Change the DMA2D state */ hdma2d->State= HAL_DMA2D_STATE_TIMEOUT; /* Process unlocked */ __HAL_UNLOCK(hdma2d); return HAL_TIMEOUT; } } } } /* Clear the transfer complete and CLUT loading flags */ __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TC|DMA2D_FLAG_CTC); /* Change DMA2D state */ hdma2d->State = HAL_DMA2D_STATE_READY; /* Process unlocked */ __HAL_UNLOCK(hdma2d); return HAL_OK; } По тексту функции вроде бы должна дожидаться. ПО факту: HAL_DMA2D_Init(&hdma2d); if(HAL_DMA2D_Start(&hdma2d, 0xFFFFFFFF, 0xD0400000, 1024, 600) == HAL_OK) { HAL_DMA2D_PollForTransfer(&hdma2d, 10); } ЗДЕСЬ БРЕЙКПОИНТ HAL_DMA2D_Init(&hdma2d); if(HAL_DMA2D_Start(&hdma2d, 0xFFFFFFFF, 0xD0400000, 1024, 600) == HAL_OK) { HAL_DMA2D_PollForTransfer(&hdma2d, 10); } ЗДЕСЬ БРЕЙКПОИНТ HAL_DMA2D_Init(&hdma2d); if(HAL_DMA2D_Start(&hdma2d, 0xFFFFFFFF, 0xD0400000, 1024, 600) == HAL_OK) { HAL_DMA2D_PollForTransfer(&hdma2d, 10); } ЗДЕСЬ БРЕЙКПОИНТ если наставить брейкпоинтов и спокойно шагать, никаких артефактов не наблюдается. Если работать в обычном режиме - артефакты.
-
Поборол таки и Z-буфер и нормали.... Непонятным пока остается то что запись через DMA2D идет нормально, а вот через *(__IO uint32_t*)(adr + (x + y * 1024)*3)=color- с артефактами.... Пытаюсь теперь интегрировать этот код не в основную программу, а внутрь функций toochGFX - странные проблемы.....Тут уже вопросы к знатокам KEIL файл dsp3d.c - добавлен в проект #include <dsp3d.h> - добавлено в main.c Все работает. Беру другой файл, сгенерированный системой touchgfx - mainscreenview.cpp добавляю в него #include <dsp3d.h> вызываю в тексте dsp3D_renderGouraud(dsp3dModel2) (просто одна из функций файла dsp3d.c) Проект компилируется, но не линкуется Error: L6218E: Undefined symbol dsp3D_renderGouraud(float*) (referred from mainscreenview.o). Как так? Функция видна в одном месте проекта, но не видна в другом, хотя в обоих местах библиотека подключена одинаково....
-
Есть специалисты в области 3D? На видео кубик, в коде я включил использование при визуализации Z-буфера. Первые кадры визуализируются нормально, потом же кубик постепенно "растворяется". Скажу сразу - нормали у меня от балды (не понял пока, как расчитывать их), это заметно по тому, как по разному освещаются полигоны одной грани, но мне пока терпимо. Так вот, а могут ли неправильные нормали давать такой эффект? Или это только проблемы Z-буфера? Или еще чего-то? https://cloud.mail.ru/public/DGUX/TZoRw7stw Пардон, правильное видео тут https://cloud.mail.ru/public/4h2M/DeoFPhWme
-
Я полагаю, что в этом случае восприятие результата библиотекой и учет особенностей float остается на совести самой библиотеки. Меня волнует лишь - избранный мной способ записи в буфер - он обеспечивает корректную передачу и извлечение данных, скажем так в битовом выражении? Вы, похоже, невнимательно прочли - у меня ускорение в 1,5-2 раза получилось.
-
Так... следующий вопрос Он, возможно, потребует еще и знаний 3d, но все же.... Вот функции чтения и записи в Z-буфер void dsp3D_LL_writeToDepthBuffer(uint32_t pos, float32_t value) { // YOUR IMPLEMENTATION *(__IO float32_t*)(0xD0200000 + pos*sizeof(float32_t))=value; } float32_t dsp3D_LL_readFromDepthBuffer(uint32_t pos) { //return 0; // YOUR IMPLEMENTATION return *(__IO float_t*)(0xD0200000 + pos*sizeof(float32_t)); } прописал я их - ан нет, отображаются все грани, даже видимые. Я подозреваю несколько причин - часть из них исследую сам, а вот про одну хотел спросить вас. Проверил я, как на практике работают эти функции - принудительно записал в них 3.14. При чтении каждый раз получаю что-то вроде 3.1400001 1. С точки зрения программирования - почему так и как с этим бороться? 2. С точки зрения 3D программирования - повлияет ли это на работу с Z-буфером?
-
Вот оно че!!!! Заменил z = dsp3D_interpolate(z1, z2, (float32_t)(x - sx) * divider_multiplier); на z= z1 + (z2 - z1) * MAX(0.0f, MIN((float32_t)(x - sx) * divider_multiplier, 1.0f)); ну это к вопросу об инлайнах - с ними не получилось, я просто действие, заложенное в функции, подставил в формулу. FPS был 9 стабильно, стал колебаться от 16 до 22. Вот что оптимизация животворящая делает)))
-
Математически? Так это не тождественно термину "кибернетически" К примеру, 2-4 - математически это минус два, а для типа uint8t - это 253. Что-то не учли значит.... А то что математически не должно меняться, я согласен.
-
Ни на такт меньше не стало, а вот результат другой - кубик стал кривой))) Но это мелочь, 21 такт всего и вызываается нечасто.
-
у этого макаронника и емайл указан и скайп - молчит
-
А вот тут сам Фабио (автор библиотеки) сдулся и сделал себе самому пометку // OPTIMIZE IT! void dsp3D_transformVertex(float32_t *v, float32_t *m, float32_t *tv) { float32_t w; tv[0] = v[0]*m[0] + v[1]*m[4] + v[2]*m[8] + m[12]; tv[1] = v[0]*m[1] + v[1]*m[5] + v[2]*m[9] + m[13]; tv[2] = v[0]*m[2] + v[1]*m[6] + v[2]*m[10] + m[14]; w = 1.0f / (v[0]*m[3] + v[1]*m[7] + v[2]*m[11] + m[15]); tv[0] *= w; tv[1] *= w; tv[2] *= w; } А по-моему, тут ничего не оптимизировать..... Я не прав? А вот тут наверное можно, что скажете? m[0] = coordinates[0] * (float32_t)SCREEN_WIDTH + (float32_t)SCREEN_WIDTH / 2.0f;
-
Я не так инлайню? inline float32_t dsp3D_interpolate(float32_t min, float32_t max, float32_t gradient) { return (min + (max - min) * dsp3D_clamp(gradient)); } есть у меня сравнивалка файлов. Погляжу.
-
Упаси бог меня требовать от вас делать что-то для меня в ущерб своей работе. Так я так и делаю, не совсем я "бум-бум" )) Наверное я содержимое того, что инлайнится, перенесу внутрь целиком, посмотрю, что выйдет.
-
вот что он выдумывает sx = dsp3D_interpolate(pa[0], pb[0], gradient1); 0000a8 ed991a00 VLDR s2,[r9,#0] 0000ac eef00a41 VMOV.F32 s1,s2 0000b0 ed951a00 VLDR s2,[r5,#0] 0000b4 eeb00a41 VMOV.F32 s0,s2 0000b8 eeb01a49 VMOV.F32 s2,s18 0000bc f7fffffe BL dsp3D_interpolate 0000c0 eefd8ac0 VCVT.S32.F32 s17,s0 а вот без и инлайна ;;;550 sx = dsp3D_interpolate(pa[0], pb[0], gradient1); 0000ba ed951a00 VLDR s2,[r5,#0] 0000be eef00a41 VMOV.F32 s1,s2 0000c2 ed911a00 VLDR s2,[r1,#0] 0000c6 eeb00a41 VMOV.F32 s0,s2 0000ca eeb01a44 VMOV.F32 s2,s8 0000ce f7fffffe BL dsp3D_interpolate 0000d2 eefd3ac0 VCVT.S32.F32 s7,s0 разницы нет, но что добавилось, я не знаю, но адреса, если вы обратите внимание, сместились, значит что-то добавилось.
-
то есть, нужно приводить к int, а именно это и делается в вашем объявлении переменной? Иными словами, это нельзя оптимизировать?
-
Проверю. А пока вопрос.... Хочу заменить конструкцию #define ASSEMBLE_ARGB(A,R,G,B) (A << 24 | R << 16 | G << 8 | B) const uint32_t rt = r * ndl; // нет смысла преобразовывать цвет в uint8_t, это лишние операции для процессора const uint32_t gt = g * ndl; // также нет смысла приводить цвет к float, его тип будет расширен автоматически, а текста будет меньше const uint32_t bt = b * ndl; *(__IO uint32_t*)(0xD0000000 + 3*(y * SCREEN_WIDTH + x))=ASSEMBLE_ARGB(a, r, g, b); на прямое присваивание. *(__IO uint32_t*)(0xD0000000 + 3*(y * SCREEN_WIDTH + x))=(a << 24) | ((r * ndl) << 16) | ((r * ndl) << 8) | (r * ndl); но компилятор негодует ..\Middlewares\Third_Party\dsp3D\src\dsp3D.c(515): error: #1460: expression must have integral or fixed-point type const uint32_t col =(a << 24) | ((r * ndl) << 16) | ((r * ndl) << 8) | (r * ndl); Во первых, мне непонятно, почему он не хочет сдвигать влево заключенное в скобках произведение, а во вторых - в теории, должно ли это сократить число тактов?
-
Ух... это точно... в упор не увидел обновление r,g,b. До этого не застревал и, в общем-то работу провел большую. Один кубик в режиме flat дает 11 FPS на 1024х600. В режиме Gouraud - 6 FPS. И то - у меня пока не отсекается Z-буфер, по непонятным причинам в него идут кривые данные. А теперь результаты каждого из шагов: const float32_t divider_multiplier = 1.0f / (ex - sx); gradient = (float32_t)(x - sx) * divider_multiplier; было 31, стало 12 шагов const uint32_t rt = r * ndl; // нет смысла преобразовывать цвет в uint8_t, это лишние операции для процессора const uint32_t gt = g * ndl; // также нет смысла приводить цвет к float, его тип будет расширен автоматически, а текста будет меньше const uint32_t bt = b * ndl; было 48, стало 31 А вот "заинлайнивание" inline float32_t dsp3D_clamp(float32_t value) { return MAX(0.0f, MIN(value, 1.0f)); } inline float32_t dsp3D_interpolate(float32_t min, float32_t max, float32_t gradient) { return (min + (max - min) * dsp3D_clamp(gradient)); } наоборот добавило тормозов В одном месте было 216, стало 270 В другом было 70 стало 84. Листинг не смотрел, мне пора убегать. Но так, для информации.
-
Почистил. Софтового FPU не стало. Но все равно ужасно медленно. Очень много времени (до 30 000 тактов) занимает вот этот фрагмент, выводящий одну линию. for (x = sx; x < ex; x++) { gradient = (float32_t)(x - sx) / (float32_t)(ex - sx); z = dsp3D_interpolate(z1, z2, gradient); ndl = dsp3D_interpolate(snl, enl, gradient); a = (color >> 24); r = (color >> 16); g = (color >> 8); b = (color); r = (uint8_t)((float32_t)r * ndl); g = (uint8_t)((float32_t)g * ndl); b = (uint8_t)((float32_t)b * ndl); dsp3D_drawPointDepthBuffer(x, y, z, ASSEMBLE_ARGB(a, r, g, b)); } НИЖЕ ТАК, ДЛЯ СПРАВКИ СОДЕРЖАНИЕ ИСПОЛЬЗУЕМЫХ ФУНКЦИЙ float32_t dsp3D_clamp(float32_t value) { return MAX(0.0f, MIN(value, 1.0f)); } float32_t dsp3D_interpolate(float32_t min, float32_t max, float32_t gradient) { return (min + (max - min) * dsp3D_clamp(gradient)); } Есть мысли по оптимизации? А вот дальше - может быть я туплю... смотрите, еще раз приведу фрагмент: for (x = sx; x < ex; x++) { gradient = (float32_t)(x - sx) / (float32_t)(ex - sx); z = dsp3D_interpolate(z1, z2, gradient); ndl = dsp3D_interpolate(snl, enl, gradient); a = (color >> 24); // значения a,r,g,b r = (color >> 16);// в этой части цикла всегда одни и те же g = (color >> 8);// логично же вынести эти 4 строки до начала цикла for? и пользоваться единожды вычисленными значениями... b = (color);// но если я это делаю - отрисовка меняется r = (uint8_t)((float32_t)r * ndl); g = (uint8_t)((float32_t)g * ndl); b = (uint8_t)((float32_t)b * ndl); dsp3D_drawPointDepthBuffer(x, y, z, ASSEMBLE_ARGB(a, r, g, b)); } Скажите, почему меняется работа функции, если я указанные 4 строки переношу до начала цикла? Ведь вычисление a,r,g,b из неменяющегося color дает одни и те же значения, так почему бы их не вычислить заранее и потом просто использовать? Чего я в упор не вижу?
-
Что случилось с поставками STM32H7?
Salamander ответил MementoMori тема в Компоненты
Ужо продают. Но... В компании База Электроники мне выставили 5000 за одну микросхему. Зато 36 штук могут продать по 1100. Я расстроился и даже не поинтересовался о сроках поставки. -
Вернемся теперь к выходу за границы Тут самое интересное. Выход за границы вызывается макросом ASSEMBLE_ARGB - #define ASSEMBLE_ARGB(A,R,G,B) (A << 24 | R << 16 | G << 8 | B) Если написать к примеру так dsp3D_drawFaceGouraud(vertex_transform_a, vertex_transform_b, vertex_transform_c, 0xFFFFFFFF); // замена ASSEMBLE_ARGB на 0xFFFFFF То ошибка исчезает. Почему же? А вот почему - в нее подставляется RGBr, RGBg, RGBb. А они берутся из массива float32_t dsp3dModel[122] = {8,12, ...................} Задумка автора такова, что в однородном массиве запакованы и цвета и координаты и нормали. Поскольку нормали могут быть float32_t, то и все остальные данные - float32_t. Это не есть гуд? У меня так #define ARM_MATH_CM7 #if defined(ARM_MATH_CM7) #include "core_cm7.h" #define ARM_MATH_DSP #elif defined (ARM_MATH_CM4) #include "core_cm4.h" #define ARM_MATH_DSP #elif defined (ARM_MATH_CM3) #include "core_cm3.h" #elif defined (ARM_MATH_CM0) #include "core_cm0.h" #define ARM_MATH_CM0_FAMILY Да вот что странно - вроде бы расчеты там, где деление меняли на умножение сократили с 200 до 14, а функция отрисовки одной точки все так же длится около 340 попугаев.... Может в измерениях напутал, но тормоза на экране говорят об обратном. Буду искать, что грузит сильнее всего....
-
Быстрее конечно стало, но в целом еще дофига где тормозов.... хотя везде, где значения указаны как 1.0, 3.0 и пр., я сделал замены. Вот тут никаких фортелей типа замены деления на умножение не надо сделать? yScale = 1.0f / tan(fov * 0.5f); Смущает еще вот такая шляпа в листинге ;;;187 arm_sub_f32(lightPosition, vertex, lightDirection, 3); 00000e 2303 MOVS r3,#3 000010 aa07 ADD r2,sp,#0x1c 000012 4621 MOV r1,r4 000014 4630 MOV r0,r6 000016 f7fffffe BL arm_sub_f32 В конце вызывается функция, которая в библиотеке arm_math... Вот ее текст? void arm_sub_f32( float32_t * pSrcA, float32_t * pSrcB, float32_t * pDst, uint32_t blockSize) { uint32_t blkCnt; /* loop counter */ #if defined (ARM_MATH_DSP) /* Run the below code for Cortex-M4 and Cortex-M3 */ float32_t inA1, inA2, inA3, inA4; /* temporary variables */ float32_t inB1, inB2, inB3, inB4; /* temporary variables */ /*loop Unrolling */ blkCnt = blockSize >> 2U; /* First part of the processing with loop unrolling. Compute 4 outputs at a time. ** a second loop below computes the remaining 1 to 3 samples. */ while (blkCnt > 0U) { /* C = A - B */ /* Subtract and then store the results in the destination buffer. */ /* Read 4 input samples from sourceA and sourceB */ inA1 = *pSrcA; inB1 = *pSrcB; inA2 = *(pSrcA + 1); inB2 = *(pSrcB + 1); inA3 = *(pSrcA + 2); inB3 = *(pSrcB + 2); inA4 = *(pSrcA + 3); inB4 = *(pSrcB + 3); /* dst = srcA - srcB */ /* subtract and store the result */ *pDst = inA1 - inB1; *(pDst + 1) = inA2 - inB2; *(pDst + 2) = inA3 - inB3; *(pDst + 3) = inA4 - inB4; /* Update pointers to process next sampels */ pSrcA += 4U; pSrcB += 4U; pDst += 4U; /* Decrement the loop counter */ blkCnt--; } /* If the blockSize is not a multiple of 4, compute any remaining output samples here. ** No loop unrolling is used. */ blkCnt = blockSize % 0x4U; #else /* Run the below code for Cortex-M0 */ /* Initialize blkCnt with number of samples */ blkCnt = blockSize; #endif /* #if defined (ARM_MATH_DSP) */ while (blkCnt > 0U) { /* C = A - B */ /* Subtract and then store the results in the destination buffer. */ *pDst++ = (*pSrcA++) - (*pSrcB++); /* Decrement the loop counter */ blkCnt--; } } Это явно "софтовая тягомотина". Она имеет аналог в аппаратном исполнении? Это ошибка автора библиотеки - использовать эту функцию вместо аппаратной или это вынужденная мера?
-
Получилось 14-14-19 тиков.
-
Ну что я хочу сказать, вот число тиков DWT; vnFace[0] = (v1[6] + v2[6] + v3[6]) / 3.0; - от 160 до 190 vnFace[1] = (v1[7] + v2[7] + v3[7]) / 3.0; - от 110 до 280 vnFace[2] = (v1[8] + v2[8] + v3[8]) / 3.0; - от 85 до 205 А если аппаратно vnFace[0] = (v1[6] + v2[6] + v3[6]) / 3.0f; - 32 vnFace[1] = (v1[7] + v2[7] + v3[7]) / 3.0f; -35 vnFace[2] = (v1[8] + v2[8] + v3[8]) / 3.0f; -30 Не в 10 раз, но все же в разы быстрее. Все понял, буду чистить библиотеку...
-
Вот что я сделал h[0] = (a[0] + b[0] + c[0]) / 3.0; h[1] = (a[1] + b[1] + c[1]) / 3.0f; То есть, в одном месте поставил f, в другом оставил как есть. И вот листинг ;;;698 h[0] = (a[0] + b[0] + c[0]) / 3.0; 000016 ed950a00 VLDR s0,[r5,#0] 00001a edd60a00 VLDR s1,[r6,#0] 00001e ee300a20 VADD.F32 s0,s0,s1 000022 edd70a00 VLDR s1,[r7,#0] 000026 ee300a20 VADD.F32 s0,s0,s1 00002a ee101a10 VMOV r1,s0 00002e 4608 MOV r0,r1 000030 f7fffffe BL __aeabi_f2d 000034 ec410b19 VMOV d9,r0,r1 000038 ed9f0b37 VLDR d0,|L1.280| 00003c ec532b10 VMOV r2,r3,d0 000040 f7fffffe BL __aeabi_ddiv 000044 ec410b18 VMOV d8,r0,r1 000048 f7fffffe BL __aeabi_d2f 00004c 9003 STR r0,[sp,#0xc] ;;;699 h[1] = (a[1] + b[1] + c[1]) / 3.0f; 00004e ed950a01 VLDR s0,[r5,#4] 000052 edd60a01 VLDR s1,[r6,#4] 000056 ee300a20 VADD.F32 s0,s0,s1 00005a edd70a01 VLDR s1,[r7,#4] 00005e ee300a20 VADD.F32 s0,s0,s1 000062 eef00a08 VMOV.F32 s1,#3.00000000 000066 ee801a20 VDIV.F32 s2,s0,s1 00006a ed8d1a04 VSTR s2,[sp,#0x10] с "f" определенно короче. А судя по командам - FPU работает. И, как я понял, "BL __aeabi_f2d" - это не просто одна команда, а отсыл к жуткой софтовой тягомотине? Не серчайте на мое упрямство. Я не знал некоторых тонкостей и, думал, что это вы меня не понимаете. Спасибо за то, что терпеливо разъяснили.
-
Это об этом мне компилятор говорит? ..\Middlewares\Third_Party\dsp3D\src\dsp3D.c(233): warning: #1035-D: single-precision operand implicitly converted to double-precision
-
То есть, если я подправлю математическую операцию, как мне советовали (в частности, поставлю символ f), должно уменьшить я количество тактов счётчика DWT, затрачиваемое на эту операцию, правильно? Я почему спрашиваю - операций этих уйма, хочется не гадать, все ли я отредактировал, а отслеживать эффективность каждого шага...