|
запрягаем хлопцы кони..., немного результатов по юзанию FPU Cortex-M4F |
|
|
|
Nov 8 2012, 19:51
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
Здравствуйте коллеги. Итак сбылась мечта идиота - в микроконтроллерах появился FPU. прежде чем его эффективно использовать я решил потестить его и заодно потренироватся писать для него хороший код. была поставлена задача по быстрому нависать либу на C/C++ которая компилялась бы моей сборкой GCC в гожий код, цель - максимальная скорость. таким образом была сделана либа линейной алгебы векторов 3x1 матриц 3x3 и быстрые синусы и косинусы. линейная алгебра реализована на в виде класов чтоб можно былоюы использовать человеческие записис типа Код matrix m; vector vv(1,2,3), v; m.m00=1.2f; v.v0 = 0.3f .... v = !m*vv - v синусы на табличках во флеше. код написан так чтобы компиллер заинлайнил все что только возможно заинлайнить gcc версия 4.8.0 20121106 (experimental) (Klen's GNU package (KGP) for ARM/elf platform) ключи с чем все было собрано -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Os -fomit-frame-pointer -finline-functions -ffunction-sections -fdata-sections -fgraphite -funroll-loops -flto запускалось на самодельной платке с STM32F405RGT6 мерялось таймером и измерения верифицировались осциллографом. проект состоит из FreeRTOS 7.3.0 запущены 4 задачки - одна тестовая с вычислениями вторая моргание светодиодом для контроля что не улетело в кору, третья - консоль, четвертая фоновая. прикручено TLSF. размеры мяса: section info: sec name size increase[%] .text 100208 0 (0.000000%) .data 40 0 (0.000000%) .bss 99664 0 (0.000000%) utilization: ram : 76.0681% 0 (0.000000%) flash: 9.56039% 0 (0.000000%) из них 86К флеша - это таблица синуса, флеша немеряно девать некуда..... док мы его теряем.. не сцать!! их у нас еще много!!! далее результаты - тип операции, время выполнения на двух частотах системного клока, исходный код на С/С++ и асм - то что вылезло из под компиллера. CODE
//----------------------------------------------------------------- m.inv() 0.500uS(168MHz) 0.336uS(250MHz)
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; m.inv(); asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
080020c2: mov r5, r5 080020c4: mov.w r6, #1073741824 ; 0x40000000 080020c8: bl 0x8001244 <vPortEnterCritical()> 080020cc: ldr r1, [r6, #36] ; 0x24 080020ce: mov r5, r5 080020d0: vnmul.f32 s0, s23, s22 080020d4: vnmul.f32 s1, s23, s18 080020d8: vfma.f32 s0, s24, s17 080020dc: vfma.f32 s1, s16, s17 080020e0: vnmul.f32 s14, s16, s22 080020e4: vnmul.f32 s2, s0, s20 080020e8: vfma.f32 s14, s24, s18 080020ec: vfma.f32 s2, s21, s1 080020f0: vnmul.f32 s3, s19, s18 080020f4: vfma.f32 s2, s19, s14 080020f8: vnmul.f32 s4, s19, s22 080020fc: vdiv.f32 s15, s27, s2 08002100: vnmul.f32 s11, s20, s22 08002104: vfma.f32 s4, s21, s17 08002108: vfma.f32 s11, s21, s18 0800210c: vfma.f32 s3, s20, s17 08002110: vnmul.f32 s18, s19, s16 08002114: vnmul.f32 s22, s19, s24 08002118: vnmul.f32 s17, s20, s24 0800211c: vfma.f32 s18, s20, s23 08002120: vfma.f32 s22, s21, s23 08002124: vfma.f32 s17, s21, s16 08002128: vmul.f32 s19, s18, s15 0800212c: vnmul.f32 s23, s22, s15 08002130: vmul.f32 s21, s1, s15 08002134: vnmul.f32 s20, s3, s15 08002138: vnmul.f32 s24, s0, s15 0800213c: vmul.f32 s16, s4, s15 08002140: vmul.f32 s22, s14, s15 08002144: vnmul.f32 s18, s11, s15 08002148: vmul.f32 s17, s17, s15 0800214c: mov r5, r5 0800214e: ldr r7, [r6, #36] ; 0x24 08002150: ldr r2, [pc, #124] ; (0x80021d0 <TFPUTask::Code()+1676>) 08002152: subs r3, r7, r1 08002154: rsb r6, r8, r3 08002158: str r6, [r2, #0] 0800215a: bl 0x8001220 <vPortExitCritical()> 0800215e: mov r5, r5 //--------------------------------------------------------------------------------------------------------- m.det() 0.119uS(168MHz) 0.080uS(250MHz)
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; s0 = m.det(); asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
0800284c: mov r5, r5 0800284e: bl 0x8001244 <vPortEnterCritical()> 08002852: mov.w r3, #1073741824 ; 0x40000000 08002856: ldr r0, [r3, #36] ; 0x24 08002858: mov r5, r5 0800285a: vneg.f32 s7, s16 0800285e: vmov.f32 s9, s24 08002862: vsub.f32 s1, s7, s23 08002866: vfma.f32 s9, s7, s17 0800286a: vneg.f32 s0, s1 0800286e: vsub.f32 s20, s0, s22 08002872: vfma.f32 s20, s9, s18 08002876: mov r5, r5 08002878: ldr r1, [r3, #36] ; 0x24 0800287a: ldr r4, [pc, #140] ; (0x8002908 <TFPUTask::Code()+1592>) 0800287c: subs r2, r1, r0 0800287e: rsb r5, r8, r2 08002882: str r5, [r4, #0] 08002884: bl 0x8001220 <vPortExitCritical()> 08002888: mov r5, r5 //--------------------------------------------------------------------------------------------------------- m /= z 0.190uS(168MHz) 0.128uS(250MHz)
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; m /= z ; asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
0800285a: mov r5, r5 0800285c: mov.w r6, #1073741824 ; 0x40000000 08002860: bl 0x8001244 <vPortEnterCritical()> 08002864: ldr r2, [r6, #36] ; 0x24 08002866: mov r5, r5 08002868: vdiv.f32 s16, s22, s16 0800286c: vmul.f32 s18, s18, s16 08002870: vmul.f32 s21, s21, s16 08002874: vmul.f32 s28, s28, s16 08002878: vmul.f32 s17, s17, s16 0800287c: vmul.f32 s19, s19, s16 08002880: vmul.f32 s20, s20, s16 08002884: mov r5, r5 08002886: ldr r3, [r6, #36] ; 0x24 08002888: ldr r1, [pc, #204] ; (0x8002958 <TFPUTask::Code()+1672>) 0800288a: subs r0, r3, r2 0800288c: rsb r6, r8, r0 08002890: str r6, [r1, #0] 08002892: bl 0x8001220 <vPortExitCritical()> 08002896: mov r5, r5
//--------------------------------------------------------------------------------------------------------- m.solve(v) 0.619uS(168MHz) 0.416(MHz)
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; vv = m.solve(v); asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ; det = rt_counter_us(hrt_count) ;
mov r5, r5 08002858: mov.w r7, #1073741824 ; 0x40000000 0800285c: bl 0x8001244 <vPortEnterCritical()> 08002860: ldr r2, [r7, #36] ; 0x24 08002862: ldr r3, [pc, #268] ; (0x8002970 <TFPUTask::Code()+1696>) 08002864: str r2, [r3, #0] 08002866: mov r5, r5 08002868: vneg.f32 s7, s16 0800286c: vsub.f32 s9, s7, s20 08002870: vmov.f32 s1, s21 08002874: vfma.f32 s1, s7, s26 08002878: vneg.f32 s0, s9 0800287c: vsub.f32 s2, s0, s25 08002880: vmov.f32 s14, #168 ; 0xa8 08002884: vfma.f32 s2, s1, s22 08002888: vmov.f32 s10, s23 0800288c: vdiv.f32 s4, s24, s2 08002890: vfma.f32 s10, s7, s22 08002894: vmul.f32 s15, s9, s4 08002898: vmul.f32 s8, s4, s14 0800289c: vmul.f32 s1, s1, s4 080028a0: vmul.f32 s5, s15, s19 080028a4: vmul.f32 s3, s8, s19 080028a8: vmul.f32 s2, s1, s19 080028ac: vmov.f32 s7, #172 ; 0xac 080028b0: vfma.f32 s5, s4, s17 080028b4: vldr s12, [pc, #188] ; 0x8002974 <TFPUTask::Code()+1700> 080028b8: vfma.f32 s3, s4, s7 080028bc: vsub.f32 s9, s21, s16 080028c0: vfma.f32 s2, s4, s20 080028c4: vmul.f32 s11, s10, s4 080028c8: vmul.f32 s6, s4, s12 080028cc: vmul.f32 s0, s9, s4 080028d0: vfma.f32 s5, s11, s17 080028d4: vfma.f32 s3, s6, s17 080028d8: vfma.f32 s2, s0, s17 080028dc: vstr s5, [r11] 080028e0: vstr s3, [r11, #4] 080028e4: vstr s2, [r11, #8] 080028e8: mov r5, r5 080028ea: ldr r0, [r7, #36] ; 0x24 080028ec: subs r1, r0, r2 080028ee: rsb r6, r8, r1 080028f2: str r6, [r3, #0] 080028f4: bl 0x8001220 <vPortExitCritical()> 080028f8: mov r5, r5 //--------------------------------------------------------------------------------------------------------- vsincos(a,sin,cos) 0.357uS(168MHz) 0.272uS(250MHz) arg=8.599 cos=-0.678717434 sin=0.734399676
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; vsincos ( arg , s0,s1) ; asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
08002ed8: mov r5, r5 08002eda: mov.w r4, #1073741824 ; 0x40000000 08002ede: bl 0x80024b8 <vPortEnterCritical> 08002ee2: ldr r1, [r4, #36] ; 0x24 08002ee4: mov r5, r5 08002ee6: vmul.f32 s3, s16, s17 08002eea: vmov.f32 s9, s16 08002eee: vcvt.u32.f32 s4, s3 08002ef2: ldr r5, [pc, #188] ; (0x8002fb0 <TFPUTask::Code()+1156>) 08002ef4: vcvt.f32.u32 s7, s4 08002ef8: vfms.f32 s9, s7, s23 08002efc: vmul.f32 s13, s9, s22 08002f00: vmul.f32 s14, s13, s17 08002f04: vcvt.u32.f32 s15, s14 08002f08: vcvt.f32.u32 s12, s15 08002f0c: vmov r3, s15 08002f10: vfms.f32 s9, s12, s21 08002f14: add.w r0, r5, r3, lsl #3 08002f18: vldr s0, [r0] 08002f1c: vldr s6, [r0, #4] 08002f20: vmov.f32 s19, s0 08002f24: vmov.f32 s20, s6 08002f28: vfma.f32 s19, s6, s9 08002f2c: vfms.f32 s20, s0, s9 08002f30: mov r5, r5 08002f32: ldr r2, [r4, #36] ; 0x24 08002f34: subs r4, r2, r1 08002f36: ldr r1, [pc, #124] ; (0x8002fb4 <TFPUTask::Code()+1160>) 08002f38: subs r5, r4, r7 08002f3a: str r5, [r1, #0] 08002f3c: bl 0x8002494 <vPortExitCritical> 08002f40: mov r5, r5
//------------------------------------------------------------------------------- vcos(a) 0.177uS 0224us(250MHz) arg=8.599 cos=-0.519285738
asm volatile ( "mov r5,r5" ) ; rt_counter_start(hrt_count); asm volatile ( "mov r5,r5" ) ; s0 = vsin ( arg ) ; asm volatile ( "mov r5,r5" ) ; rt_counter_stop(hrt_count); asm volatile ( "mov r5,r5" ) ;
08002ee8: mov r5, r5 08002eea: mov.w r5, #1073741824 ; 0x40000000 08002eee: bl 0x80024b8 <vPortEnterCritical> 08002ef2: ldr r1, [r5, #36] ; 0x24 08002ef4: mov r5, r5 08002ef6: vmul.f32 s4, s16, s18 08002efa: vmov.f32 s12, s16 08002efe: vcvt.u32.f32 s7, s4 08002f02: ldr r2, [pc, #184] ; (0x8002fbc <TFPUTask::Code()+1168>) 08002f04: vcvt.f32.u32 s9, s7 08002f08: vfms.f32 s12, s9, s22 08002f0c: vmul.f32 s14, s12, s21 08002f10: vmov.f32 s15, s12 08002f14: vmul.f32 s0, s14, s18 08002f18: vcvt.u32.f32 s6, s0 08002f1c: vcvt.f32.u32 s5, s6 08002f20: vmov r3, s6 08002f24: vfms.f32 s15, s5, s20 08002f28: add.w r0, r2, r3, lsl #3 08002f2c: vldr s8, [r0, #4] 08002f30: vldr s17, [r0] 08002f34: vfma.f32 s17, s8, s15 08002f38: mov r5, r5 08002f3a: ldr r4, [r5, #36] ; 0x24 08002f3c: subs r5, r4, r1 08002f3e: ldr r1, [pc, #128] ; (0x8002fc0 <TFPUTask::Code()+1172>) 08002f40: rsb r4, r8, r5 08002f44: str r4, [r1, #0] 08002f46: bl 0x8002494 <vPortExitCritical> 08002f4a: mov r5, r5
Вобщем бодро и жизнеутверждающе... осталось дописать кватернионы и выложить на всеобщее обозрение. если кому нужно плавучку вычислять - велком! подтянивайтесь...
|
|
|
|
|
 |
Ответов
(15 - 29)
|
Nov 10 2012, 16:22
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
2_kan35 в конкретно моем случае библиотка в контексте матричных вычислений не подходит: 1. ST либа иметт С интрфейс, поэтому писать придется вызывая функции из нее. это с одной сторны приведет к плохо читайемому коду, с другой - потери скорости на стековых операциях - Вы посмотрите сколько параметров они пихают в функции, некотороые полетят в стек. это плохо. В моем случае все инлайнится в длинную портянку без пеерходов, конвеер опятьже не сбрасывается. 2. ST либа имеет ограниченный набор функционала с матрицами 3. ST либа предлагает матрицы произвольной размерности, при малых размерностях будут потери на циклах и тд, прэтому 3x3 расписанные по компонентно быстрее будут работать. 4. Интерес представляет в ST либе табличные синусы и косинусы но их еще на соответствие стандарту нада проверить. если мне потребуется матрицы большого размера то я опять же возьму шаблоны и также буду в операторном виде писать код. если по ТЗ код должен быть на С написан (глупости манагеров) то тогда ST либа может стать хорошим подспорьем. но в любом случае вещи то примитивные и скорее всего для конкретной задачи руками написаный функционал будет быстрее и короче. все вышенаписанное не относится к функциям с фиксированной запятой и SIMD- поскольку для них компиллер не может автоматом ничего генерить о тут однозначно использовать либу от ST либо смотреть на нее и делать лучне и быстрее. 2_Xenia >Скажите пожалуйста.... разумеется все сделано на классах, больше никак. > Этот мой вопрос продиктован беспокойством по поводу "лишних" операций... Ваше беспокойство совершенно понятно, еслибы Вы не беспокоилить бы такими вопросами то наверно не быть вам эмбеддером... посуществу - да действительно, для перемножения матрицы на матрицу с присвоением ( A*=B ) нужен временный объект чтоб хранить промежуточные суммы и не портить элементы матрицы, с другой стороны не хочется создавать временный обхект и возюкатся с лишними копированиями . C++ в таких случаях задача решается передачей не по укателю или экземпляру объекта а по ссылке что снимает проблему копирования при передачи в функцию. если функция инлайн типа вообще нет никаой передачи параметров. Про аллокацию, все временые объекты создаются на стеке статически, это означает что размещение объекта это всеволишь суммирование указателя стека с числом равным размер объекта и вызов конструктора, а один конструктор мы оставляем пустым - он формально должен быть вызван по стандарту С++ но так как он пустой то и вызывать фактичеси ничего не надо что компиллер и делат! это подходящий случай какраз временых объектов. таким образом no priblem. приходя к размышлениям о подобных вещах нада учитывать два факта - современный компиллер зело хитрожопый суслик, а если вы начнете ковырятся в оптимизаторах дерева кода промежуточного предствленя кода RTL то и восе поймете что в 99 процентах вас обманет и выдас код лучше (правдо это зависит от таргет платформы). второй факт - 99 процентов програмистов С++ не умеют им пользоватся. к сожалению для эффективного использования нада глубоко изучать рализацию заложенных методик а не то как писать классы и тд - а с этим проблема, мало кто этим занимается. например вопрос - где GCC кладет таблицу виртуальных функций? какова реализация вызова виртуальных методов. знание подобных вещей позволят безнаказанно юзать вещи на микроконтроллера с объемом ОЗУ несколько килобайт и плевать с большой башни на многочисленные стада верующих во сякие мифы про С++. чуваки делающие стандарт для С++ не такие тупые и очень отчетливо понимают что код возможно прийдется компилять для чайника или градусника. довольно болтавни, давайте сравним код умножения матицы на вектор 3x3: код: Код asm volatile( "mov r5,r5" ); asm volatile( "mov r5,r5" ); x = A*x; asm volatile( "mov r5,r5" ); asm volatile( "mov r5,r5" ); asm: Код 08000e18: mov r5, r5 08000e1a: mov r5, r5 08000e1c: vmul.f32 s14, s3, s19 08000e20: vmov.f32 s16, s4 08000e24: vmov.f32 s18, s3 08000e28: vfnms.f32 s16, s3, s23 08000e2c: vfma.f32 s18, s4, s21 08000e30: vfma.f32 s14, s4, s20 08000e34: vfma.f32 s16, s17, s22 08000e38: vfma.f32 s18, s17, s19 08000e3c: vsub.f32 s17, s14, s17 08000e40: mov r5, r5 08000e42: mov r5, r5 прикол в том что в данном случае даже на стеке ничего не размещается - хватает регистров FPU... затычки из asm volatile( "mov r5,r5" ); нужны для того чтоб компиллер не смержил целочисленные инструкци спеерди и сзади идущие с собственно нас инрересуймыми. видимо компиллер чтото такое знает о кортексе чего я незнаю и пытается перемежать по возможности инструкции так чтоб шины и модули ЦПУ работали с пинимальными задержками. пибороми я не фексировал но возможно эта гипоза имеет основание быть. зы. к компиллеру нада относится также как и к железу - как матчасти! а что клачики говорили - учи матчасть.
|
|
|
|
|
Nov 10 2012, 17:30
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
Цитата(kan35 @ Nov 10 2012, 21:15)  Что касается SIMD, то если посмотрите - они все реализованы как интринсики, и оптимизировать в них по сути нечего - остается только применять. ну всетаки как интринсики! тоесть нада вызывать функции. я пытаюсь сказать что когда мы флотовые операции делаем мы операторы используем а не функции из библиотеки вызываем. предлагаю не уходить от темы - какие библиотеки и тд лучше ли хуже, вопрос который я пытаюсь тут поднять - какой хороший FPU когда он есть в наличии. библиотеки или их отсутствие пусть быдерет каждый сам, а вот с выбором использовать програмную плавучку(естественно случай с float) или FPU я думаю голосовать не прийдется  складывается впечатление что разделить радость от наличия FPU и его применения мне нескем, так сказать позитиф неочивиден.... но я всеравно рад! по ходу дела буду делать решалку систем нелинейных уравненй, оно же нелинейный оптимизатор. ктонить использует сложные модели управляймой системы чтоб такое требовалось?
|
|
|
|
|
Nov 10 2012, 20:47
|
Участник

Группа: Участник
Сообщений: 33
Регистрация: 29-06-10
Пользователь №: 58 196

|
Цитата(klen @ Nov 10 2012, 23:30)  по ходу дела буду делать решалку систем нелинейных уравненй, оно же нелинейный оптимизатор. ктонить использует сложные модели управляймой системы чтоб такое требовалось? вот например (GMCD) в реальном времени http://www.referun.com/n/algoritm-vyyavlen...schih-agregatov
|
|
|
|
|
Nov 11 2012, 09:34
|
Знающий
   
Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594

|
Цитата(klen @ Nov 10 2012, 21:30)  ну всетаки как интринсики! тоесть нада вызывать функции. я пытаюсь сказать что когда мы флотовые операции делаем мы операторы используем а не функции из библиотеки вызываем. предлагаю не уходить от темы - какие библиотеки и тд лучше ли хуже, вопрос который я пытаюсь тут поднять - какой хороший FPU когда он есть в наличии. библиотеки или их отсутствие пусть быдерет каждый сам, а вот с выбором использовать програмную плавучку(естественно случай с float) или FPU я думаю голосовать не прийдется  складывается впечатление что разделить радость от наличия FPU и его применения мне нескем, так сказать позитиф неочивиден.... но я всеравно рад! по ходу дела буду делать решалку систем нелинейных уравненй, оно же нелинейный оптимизатор. ктонить использует сложные модели управляймой системы чтоб такое требовалось? Hy интринсики по сути есть ассемблерные вставки как я считаю, может быть я и не прав, но в таком случае смысла в них нет. По поводу радости от наличия FPU я могу с вами вместе ее разделить конечно, но все же если трезво рассуждать, то вряд ли он будет использоваться даже в каждом 10 проекте на STM32F4. Я считаю все эти FPU не более чем маркетингом, так как всем, кому он интересен как правило все равно не хватает мощности CortexM4F, а тем кому он нужен мало - и программным обойдутся в случае чего. Извините за отступление от вашей темы.
|
|
|
|
|
Nov 12 2012, 12:44
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(kan35 @ Nov 11 2012, 12:34)  Я считаю все эти FPU не более чем маркетингом, так как всем, кому он интересен как правило все равно не хватает мощности CortexM4F, а тем кому он нужен мало - и программным обойдутся в случае чего. Извините за отступление от вашей темы. Может быть и можно было бы согласится, но есть ещё вопрос цены. Простой запрос на efind даёт цену для 207 от 216 рублей и в среднем 260, а на 407 от 221 и в среднем 320 рублей. И это не сравнивая данные по объёмам флэши, ногам и прочее. Учитывая, что как правило, серийность изделий разрабатываемых на просторах бывшего союза далека от массовости, а также, учитывая, что стоимость законченного изделия, как правило, не определятся стоимостью МК и комплектующих в частности, то вполне допустимо потратить лишних 2$ на такую фичу как FPU + доп флэш + 10-15% скорости. Особенно учитывая тенденции ... Приведу пример из другой немного области, но сопоставимый. Разрабатывал девайс. Нужен был UART+DAC+ADC+мало ног. Поставил atmega88, цап сделал шимом, цифровой фильтр на целых числах долго просчитывал на разных моделях, несколько раз пересчитывал - добился приемлемого качества работы. Выпускается. Сейчас смотрю на stm32f100 - как хорошо на эту задачу ложится. ЦАП есть - не надо мутить, оперировать можно 32 битами, фильтр получится красивее, АЦП 12 бит. Думаю в целом устройство будет работать значительно устойчивее. Можно и частоту семплирования поднять. Несмотря на то, что качество АЦП у меги не лучшее, тем не менее при оцифровке 10 битами девайс работает устойчивее при помехах. Поэтому можно предположить, что перевод изделия на stm даст существенный выигрыш в качестве. Ну и цена практически одинаковая ... Конечно, сейчас уже перерабатывать не станут - всех всё устраивает, денег на это выделятся не будет, но всё же ...
|
|
|
|
|
Nov 12 2012, 18:25
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(AHTOXA @ Nov 12 2012, 18:50)  Сильно сомневаюсь. Может быть проще отказаться от плавучки в прерываниях, и пользовать её только в одном процессе? Тогда ничего не надо сохранять, сохраняется только контекст M3. Я так пробовал - отлично работает. Понятно, что в прерываниях ничего особо делать низзя. Но надо... Было бы неплохо Код register volatile float resw asm("S0");
|
|
|
|
|
Nov 12 2012, 19:28
|

embarrassed systems engineer
    
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038

|
Цитата(AHTOXA @ Nov 12 2012, 15:39)  Разочарование сплошное. Проблема давно изящно решена, например, в i80386-ом - при переключении контекста меняется содержимое только РОН-ов, FPU не трогается и взводится специальный флажок. Если в новом контексте начинает использоваться FPU и этот спецфлажок установлен, то генерируется исключение, обработчик которого выполнит отложенную смену контекста FPU - сохранит старый и загрузит новый. А тут - при переключении контекста задачи RTOS старшие регистры s16-s31 нужно сохранить ручками в любом случае, даже если задача последний раз пользовалась FPU полчаса назад и может больше и не собирается дальше пользоваться. И новый контекст не грузится автоматически при попытке использования - значит изволь для новой задачи его также ручками загрузить. Флажки-то в Cortex-M4F есть, но аппаратный способ смены контекста FPU "не доделан", а программного "по требованию", я так понял нету. ИМХО, на сегодняшний день такое решение для смены контекста FPU немного диковато, и не видится способа как эту "Lazy stacking feature" красиво встроить в переключатель контекста в RTOS. Или чего-то не так понял? Upd: ну слегка корявый способ нашелся - при переключении контекста запрещать использование FPU через биты 11/10 в CPACR. Тогда при попытке использования FPU в новом контексте вылезет исключение UsageFault и можно будет ситуацию разрулить. Но при этом использование "Lazy stacking feature" все равно сомнительно.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|