Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: запрягаем хлопцы кони...
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
klen
Здравствуйте коллеги. Итак сбылась мечта идиота - в микроконтроллерах появился 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


Вобщем бодро и жизнеутверждающе...
осталось дописать кватернионы и выложить на всеобщее обозрение.
если кому нужно плавучку вычислять - велком! подтянивайтесь...
Сергей Борщ
Немного не в тему: а откуда частота 250МГц? Разгон?
SasaVitebsk
Прошу прощения, не совсем в теме... Вроде st выкладывало свою либу... Что там совсем плохо?
И ещё один вопрос. Мне в новом проекте придётся вовсю пользоваться плавучкой ... Правда там мелочи - всякие умножения/ деления, корни, возведения в степени (в том числе дробные) ну и логарифмы. Хотелось бы получить совместимый код с процом не имеющим плавучки. Я думаю, что всё без проблем должно работать и на 207, хотя на старте заложил 407. Тем не менее было бы любопытно посмотреть (раз уж есть такая возможность) разницу в производительности этих кристаллов на моей задаче. Поэтому хотелось бы написать максимально унифицированный исходник, при этом хотелось бы, чтобы 407 задействовал бы аппаратную плавучку. Пишу под IAR и, до этого я думал, что достаточно будет установить галочку "использовать плавучку". rolleyes.gif Ну или, накройняк, подключать, по выбору, разные библиотеки и, соответственно, использовать разные вызовы ... rolleyes.gif
Я в корне заблуждаюсь?
Да, забыл, ещё фильтрацию придётся делать. Попробую на плавучке. Доложу. rolleyes.gif Хотя и не скоро ... Финиш ближе к лету ...
klen
2 _ Сергей Борщ
250 - это конечно разгон, квар 12мгц множители PLL_M =(12000000/ 1000000 ) PLL_N=500 PLL_P= 2 паралельно смотрел когдаж он глючить начнет, походу не начнет - при случае упирается наверно в шину флеша на чтение команд и константных данных, она проц наверно держит пока не выдаст то что поросили. но что характерно - рост линейный от частоы..... есть о чем подумать. не греется ... я думаю что на 250 может не вся переферия заработать. но уарт, таймеры, gpio работают без сбоев. есьть ощущение что еслиб не флеш то он бы и на 600мгц завелся бы, жрал бы наврно много.

2_SasaVitebsk
Вы все правильно понимаете.- с разными ключами один и тотже код скомпилится с разным набором инстукций, в случае 207 будут вызваны програмные реализации из libm.a
но чтото я не помню библиотек которые поиближались к потенциальной эффективности - все приходится напильником и зубиом рихтовать. в моем случае вызовов никаких не будет - все заинлайнено чтоб ихбавится потерь времени на работе со стеком и и на переходах.

по поводу ST мовской библиотке - там поддержка целочисленых вычисленй, как Вы наверно знаеете кроме FPU в ядро расширено SIMD инструкциями - вот про них в данном случае и песня.

можно будет просто сравнить скорость кода в результате - луший критерий, ну например калмановича и рикатичем пустить и посмотреть у кого такт системы быстрее будет.
я все это ковыряю к тому что БИНС хочу построить - тут нужно много и обильно вращать вектора и интегрировать матричные уравнения - самое то чтоб нагрузить FPU, хотя честно говоря практика показала что и stm32f103 хватает - полоса пропускания реальной ситемы (самолет беспилотник автомобиль дерижбобель) ну на крайняк десятки герц, если они не в кого не впиливаются. стогерцового такта хватает для оценки состояния и управления. тут резервы скорости позволят применить в контуре более детальные модели управляймрго объекта.
MrAlex
Чтото далековато до оптимальности.
У нас Калман 4x4 крутился на MSP430 8Мгц 25 раз в секунду и еще на фоне работал автопилот и GPS поток парсился.
klen
Цитата(MrAlex @ Nov 9 2012, 12:08) *
Чтото далековато до оптимальности.
У нас Калман 4x4 крутился на MSP430 8Мгц 25 раз в секунду и еще на фоне работал автопилот и GPS поток парсился.

что далеко от оптимальности? что с чем сравнивается? причем тут msp430? калман какой? модель линейная или линеризуется на каждом шаге? уравнение рикатти интегрируется?
Serg_D
Цитата(klen @ Nov 8 2012, 23:51) *
//---------------------------------------------------------------------------------------------------------
m.solve(v) 0.619uS(168MHz) 0.416(MHz)

очень любопытно будет посмотреть!
а каким методом система решается?
Xenia
Как-то тягостно мне оценить скорость работы плавучки по макро-задачам типа инвертирования матрицы...

Нельзя сообщить для несведующих, за сколько тактов выполняется там операция умножения (можно по даташиту)? А еще лучше - замерить, как быстро вычисляется скалярное произведение длинного вектора с самим собой. Скажем, вектор берем длиной в 1000 элементов, а вычисление повторяем сотни раз, чтобы в общем зачете заняло минуту-две. Тогда время реальной производительности на операциях умножения с накоплением будет определена с достаточной точностью.

Вся же остальная линейная алгебра, как бы она ни была привлекательна и практически полезна, в конечном итоге, зависит именно от этой операции умножения с накоплением. А потому реальные примеры из нее совершенно не нужны, а только запутывают.

P.S. А float-числа у него какой длины? Приведенные выше расчеты на 32-битных или 64-битных флоатах проводились?
_Pasha
Цитата(Xenia @ Nov 9 2012, 20:40) *

Здесь всё, что интересует.

Ага, еще
Цитата(Xenia @ Nov 9 2012, 20:40) *
Вся же остальная линейная алгебра, как бы она ни была привлекательна и практически полезна, в конечном итоге, зависит именно от этой операции умножения с накоплением.


Благодаря команде vcvt можно выползать на fixed point, использовать mac-инструкции и вползать обратно в плавучку.
Ну, и vmla - чистый float-mac, 3 такта...
Xenia
Цитата(_Pasha @ Nov 9 2012, 21:08) *
Здесь всё, что интересует.


Я поняла там написанное так, что double float (64-битные) числа он умножать не умеет. Тогда действительно ему только с матрицами 3х3 работать...
eisufu
вы тестировали те 64k памяти дополнительные?
-flto вообще работает для Cortex-M4F?
Также интересует -fgraphite и принципиальная возможность использования -fprofile-generate/-fprofile-use.
libgomp.a можно для FreeRTOS заточить?
MrAlex
Расширенный фильтр Калмана. Модель не линейная. Линеаризуется на каждом шаге. Интегрирование в самой простой форме использовали. Размерность матриц 4x4.
klen
serg_D
>а каким методом система решается?
самым тупым - для матрицы 3x3 расписана покомпонентно обратная матрица, потом умножение на вектор правых частей


Xenia
>за сколько тактов..
*, *-, *+ три такта, / и квадратый корень 14 тактов , остальное за 1 такт

написать тест оказалось очень сложно, поскольку компиллер жеско все перекручивает и оптимизирует, на выходе не совсем то что ожидается, тут скорее всего реальный алгоритм нада проверять на разных машинках

>float-числа у него какой длины?
IEEE 754-1985 тоесть стандартный 32 флоат.

>Я поняла там написанное так, что double float (64-битные) числа он умножать не умеет. Тогда действительно ему только с матрицами 3х3 работать...
смотря для чего матрицы и как заполнять ее элементы. учитывая ошибки входных сигналов(датчики, шумы) обычно даже для относительно больших матриц можно так вычмсления провести чтоб матрицы были хорошо обусловлены. например базис поменять или масштаб. тут просто нужна ловкость рук и никакого мошенства. некоторые товарисщии на даблах применя их в тупую получают ошибки больше чем джедаи на флотах.

2_eisufu
>вы тестировали те 64k памяти дополнительные?
те 64k это какие ? в том что у меня запаяно ее 128К+64К
если 64 - это дополнительный блок то нет, но могу. самому интересно. мне кажется разницы не будет. но проверим.

> -flto вообще работает для Cortex-M4F?
а якжо! тока он для всего работает независимо от ядра, тут много особенностей, он часто падает с диагностикой о внутренней ошибке но я выявил некоторые правила благодаря которым проект собирается с LTO, собсно представленные выше результаты были по коду с LTO
>Также интересует -fgraphite
чисто в принципе должно работать но нада проверять тестами какой асм вылазит, у меня графит всегда по умолчанию включен для проекта, а че оно дает или не дает я еще не исследовал. давайте вместе это выясним. тесты с "с неправильными цыклами" нужны.
>принципиальная возможность использования -fprofile-generate/-fprofile-use
к сожаления тут я ничео не могу сказать.... я пока даже механихма в ообщем инстументирования не вкуриваю, нада ковырять.
> libgomp.a можно для FreeRTOS заточить?
думаю что можно каминибудь костылями прикрученными к FreeRTOS и исходникам GCC и может быть даже не трудно, но!.... зачем, всеравно то одно вычислительное ядро имеется - смысла паралелние вычисления раскидывать по OMP задачкам на одном процессоре нет. если выродит арм микроконтроллеры с двумя и более ядрами то тогда наверно все зачешутся как код подятнуть под это. для linux+Cortex-A9/15 это стопудово работает, можно проверить.

2_MrAlex
>Расширенный фильтр Калмана. Модель не линейная. Линеаризуется на каждом шаге. Интегрирование в самой простой форме использовали. Размерность матриц 4x4.
гуд. тут то не в том как хорошо организовать вычисления на проце без FPU(Ваш случай с MSP) а в том что на Cortex-M4F получится это деать много раз быстрее при прочих условиях на равных тактовых.


доделал кватерниончики - вращают вектора хорошо.. позтиф!
цель достигнута - для высисление пространственных преобразований имеется полный набор операндов - vector3 matrix3 quat4, для экземпляров переопределены операторы теперь формулы можно из книжки брать и тупо писать в операторной форме:
решение системы
Код
float  z;
vector b(1,2,3), x;
matrix A(1,2,3,4,5,6,7,8,9);


x = !A*b;  // решение системы
z = b^a; // скалярное произведение
b = a*b; // векторное произведение
b = a*f + f*b - b/f; // мастабирование/ ссумирование векотров

quat  Q;
b.x=2;
b.y=54;
b.z-5.002;
Q.set_axis( b , 0.5* M_PI  );  // установка кватерниона на поаорот вокруг орта b на угол 90 градусов
b = Q^b; //  вычисление повернутого вектора

vector x,u,z;
matrix I,F,B,H,K,P,Q,R;

while(1)
{
z = .... // измерение

x = F*x+B*u; // экстраполяция состояня
P = F*P*(~F)+Q; // экстаоляция ошибок
K=P*(~H) * !(H*P*(~H)+R); // вычислене коэф усиления
x += K*(z-H*x); // корреция
P = (I-K*H)*P;  
}

цикл срасчетом фильта 3x3 выполняется за 5.05uS





kan35
Цитата(klen @ Nov 9 2012, 02:29) *
по поводу ST мовской библиотке - там поддержка целочисленых вычисленй, как Вы наверно знаеете кроме FPU в ядро расширено SIMD инструкциями - вот про них в данном случае и песня.

Библиотека ST, а точнее ее часть - CMSIS DSP библиотека содержит функции для работы как с SIMD расширениями так и с FPU. Или мы говорим про разные библиотеки?
Цитата
The library installer contains prebuilt versions of the libraries in the Lib folder.

arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4)
arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4)
arm_cortexM4l_math.lib (Little endian on Cortex-M4)
arm_cortexM4b_math.lib (Big endian on Cortex-M4)
arm_cortexM3l_math.lib (Little endian on Cortex-M3)
arm_cortexM3b_math.lib (Big endian on Cortex-M3)
arm_cortexM0l_math.lib (Little endian on Cortex-M0)
arm_cortexM0b_math.lib (Big endian on Cortex-M3)
Xenia
Цитата(klen @ Nov 10 2012, 13:32) *
vector b(1,2,3), x;
matrix A(1,2,3,4,5,6,7,8,9);

x = !A*b; // решение системы
z = b^a; // скалярное произведение
b = a*b; // векторное произведение
b = a*f + f*b - b/f; // масштабирование/ суммирование векторов

Скажите пожалуйста, как это вы так хитрО определили vector и matrix (полагаю, что это классы), что над ними стали возможны матричные операции в алгебраической записи? Очень уж мне любопытно, хотя этот вопрос напрямую к теме не относится.
Например, в записи
y = A*b
где: y и b - вектора, A - матрица
вы получаете промежуточный вектор результата произведения, и лишь только потом копируете его в y? Или все-таки исхитрились класть сразу на нужное место, обходя векторно-матричное копирование при выполнении операции присваивания? Этот мой вопрос продиктован беспокойством по поводу "лишних" операций аллокирования объекта для хранения промежуточного результата, его копирования при присвоении, и последующей деаллокации после использования. В обычной (не матричной) алгебре проблем с промежуточным результатом не возникает, т.к. для его хранения достаточно регистра или элемента стека. Но когда это вектор, а тем паче матрица, то с этим проблема немалая. Например, в операциях векторно-матричного сложения дополнительная операция копирования (чтение и запись в память на каждый элемент) занимает точти столько же времени, сколько само сложение.

К сожалению, я не знаю достататочно элегантного способа узнать адрес y при выполнении операции умножения y = A*b, реализуемой определением оператора умножения в классе matrix. А неэлегантный способ сводится к выполнению операции умножения в операторе присваивания, но тогда оператор умножения должен выдавать ему "задание" с адресами (а то и вместе с типами) сомножителей. Короче говоря, как это у вас реализовано?

P.S. Если такой отход от темы вы считаете недопустимым, то с благодарностью ознакомилась бы с вашим мнением в любой другой теме или личной переписке.
klen
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" ); нужны для того чтоб компиллер не смержил целочисленные инструкци спеерди и сзади идущие с собственно нас инрересуймыми. видимо компиллер чтото такое знает о кортексе чего я незнаю и пытается перемежать по возможности инструкции так чтоб шины и модули ЦПУ работали с пинимальными задержками. пибороми я не фексировал но возможно эта гипоза имеет основание быть.

зы. к компиллеру нада относится также как и к железу - как матчасти! а что клачики говорили - учи матчасть.

kan35
Все вектора и матрицы передаются в функции указателями, так что не соглашусь по поводу запихивания многих параметров в стек. Я согласен на 100% в том, что заточенное под задачу наверняка оптимальнее универсального.
И нужно поставить точки над i - все эти функции написаны программистами ARM как собственно вся CMSIS библиотека (а то вы постоянно упоминаете ST - это не корректно). Что касается SIMD, то если посмотрите - они все реализованы как интринсики, и оптимизировать в них по сути нечего - остается только применять.
klen
Цитата(kan35 @ Nov 10 2012, 21:15) *
Что касается SIMD, то если посмотрите - они все реализованы как интринсики, и оптимизировать в них по сути нечего - остается только применять.

ну всетаки как интринсики! тоесть нада вызывать функции. я пытаюсь сказать что когда мы флотовые операции делаем мы операторы используем а не функции из библиотеки вызываем.

предлагаю не уходить от темы - какие библиотеки и тд лучше ли хуже, вопрос который я пытаюсь тут поднять - какой хороший FPU когда он есть в наличии. библиотеки или их отсутствие пусть быдерет каждый сам, а вот с выбором использовать програмную плавучку(естественно случай с float) или FPU я думаю голосовать не прийдется sm.gif

складывается впечатление что разделить радость от наличия FPU и его применения мне нескем, так сказать позитиф неочивиден.... но я всеравно рад!


по ходу дела буду делать решалку систем нелинейных уравненй, оно же нелинейный оптимизатор. ктонить использует сложные модели управляймой системы чтоб такое требовалось?
_Pasha
Цитата(klen @ Nov 10 2012, 21:30) *
складывается впечатление что разделить радость от наличия FPU и его применения мне нескем, так сказать позитиф неочивиден.... но я всеравно рад!

Почему же. Вон, видео с дискретным косинус-преобразованием как попускает! Ето уже не жлобский фиксед поинт.
eisufu
Цитата(klen @ Nov 10 2012, 23:30) *
по ходу дела буду делать решалку систем нелинейных уравненй, оно же нелинейный оптимизатор. ктонить использует сложные модели управляймой системы чтоб такое требовалось?

вот например (GMCD) в реальном времени
http://www.referun.com/n/algoritm-vyyavlen...schih-agregatov
kan35
Цитата(klen @ Nov 10 2012, 21:30) *
ну всетаки как интринсики! тоесть нада вызывать функции. я пытаюсь сказать что когда мы флотовые операции делаем мы операторы используем а не функции из библиотеки вызываем.

предлагаю не уходить от темы - какие библиотеки и тд лучше ли хуже, вопрос который я пытаюсь тут поднять - какой хороший FPU когда он есть в наличии. библиотеки или их отсутствие пусть быдерет каждый сам, а вот с выбором использовать програмную плавучку(естественно случай с float) или FPU я думаю голосовать не прийдется sm.gif

складывается впечатление что разделить радость от наличия FPU и его применения мне нескем, так сказать позитиф неочивиден.... но я всеравно рад!


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

Hy интринсики по сути есть ассемблерные вставки как я считаю, может быть я и не прав, но в таком случае смысла в них нет.
По поводу радости от наличия FPU я могу с вами вместе ее разделить конечно, но все же если трезво рассуждать, то вряд ли он будет использоваться даже в каждом 10 проекте на STM32F4. Я считаю все эти FPU не более чем маркетингом, так как всем, кому он интересен как правило все равно не хватает мощности CortexM4F, а тем кому он нужен мало - и программным обойдутся в случае чего. Извините за отступление от вашей темы.
RabidRabbit
Цитата(kan35 @ Nov 11 2012, 13:34) *
Я считаю все эти FPU не более чем маркетингом, так как всем, кому он интересен как правило все равно не хватает мощности CortexM4F, а тем кому он нужен мало - и программным обойдутся в случае чего.

Мысля таким образом, "маркетингом" можно считать и умножение с делением - зачем они в железе, если и софтовой реализацией обойтись можно... sm.gif
SasaVitebsk
Цитата(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 даст существенный выигрыш в качестве. Ну и цена практически одинаковая ... Конечно, сейчас уже перерабатывать не станут - всех всё устраивает, денег на это выделятся не будет, но всё же ...
_Pasha
Столкнулся с трудностью.
Как разделить юзание FPU в прерывании и основном потоке с минимальным свопингом. По идее, надо плавучие регистры явно разделять. Что, снова ассемблер?
AHTOXA
Вот специальная статья от ARM про это .
_Pasha
Цитата(AHTOXA @ Nov 12 2012, 16:39) *

Это уж точно их маркетинговый ход sm.gif
Я пытаюсь понять, можно ли как-то вмешаться в GCC FPU register sheduling?
AHTOXA
Цитата(_Pasha @ Nov 12 2012, 19:52) *
Это уж точно их маркетинговый ход sm.gif

Почему? Имхо, очень неплохо придумано. Для осей так вообще очень удобно.
Цитата(_Pasha @ Nov 12 2012, 19:52) *
Я пытаюсь понять, можно ли как-то вмешаться в GCC FPU register sheduling?

Сильно сомневаюсь. Может быть проще отказаться от плавучки в прерываниях, и пользовать её только в одном процессе? Тогда ничего не надо сохранять, сохраняется только контекст M3. Я так пробовал - отлично работает.
_Pasha
Цитата(AHTOXA @ Nov 12 2012, 18:50) *
Сильно сомневаюсь. Может быть проще отказаться от плавучки в прерываниях, и пользовать её только в одном процессе? Тогда ничего не надо сохранять, сохраняется только контекст M3. Я так пробовал - отлично работает.

Понятно, что в прерываниях ничего особо делать низзя. Но надо...
Было бы неплохо
Код
register volatile float resw asm("S0");
VslavX
Цитата(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" все равно сомнительно.
Allregia
Извините что встряваю в вашу высоконаучную беседу, но последние сообщения меня несколько взволновали.
У меня в программе на STM32F405 в одном из прерываний используется float.
Флажек "Use FPU" разумеется стоит, без него (специально пробовал) все считается раз в 5 медленее.
Програма без ОС, в основной программе тоже кое-где есть float, хотя и довольно редко.
Нужно ли предпринимать какие-то шаги, для сохранения контекста FPU в прерываниях, или Keil с этим самостоятельно разберется и можно не переживать?
VslavX
Цитата(Allregia @ Nov 13 2012, 00:10) *
Програма без ОС, в основной программе тоже кое-где есть float, хотя и довольно редко.
Нужно ли предпринимать какие-то шаги, для сохранения контекста FPU в прерываниях, или Keil с этим самостоятельно разберется и можно не переживать?

Если без ОС, то должно нормально работать - для совместного использования FPU в обработчиках прерываний особых телодвижений от компилятора вроде не требуется.
AHTOXA
Цитата(VslavX @ Nov 13 2012, 01:28) *
А тут - при переключении контекста задачи RTOS старшие регистры s16-s31 нужно сохранить ручками в любом случае, даже если задача последний раз пользовалась FPU полчаса назад и может больше и не собирается дальше пользоваться.

Я ещё глубоко не вникал, но во-первых, не в любом случае, а только если задача использовала FPU, а во-вторых наверное можно CONTROL.FPCA сбросить вручную, если уж известно, что не собирается дальше пользоватьсяsm.gif
То, что ручками - это может быть и достоинством, ибо добавляет гибкости.
Цитата(VslavX @ Nov 13 2012, 01:28) *
ИМХО, на сегодняшний день такое решение для смены контекста FPU немного диковато, и не видится способа как эту "Lazy stacking feature" красиво встроить в переключатель контекста в RTOS.

Можно глянуть во FreeRtos. Хотя там ничего особенного нет, всё тривиально. Но по крайней мере, процессы, не использующие FPU, не сохраняют плавучий контекст.
ЗЫ. Вот соберусь наконец портировать scmRTOS под M4F - тогда возможно смогу рассказать что-то более конкретное.
VslavX
Цитата(AHTOXA @ Nov 13 2012, 09:46) *
а во-вторых наверное можно CONTROL.FPCA сбросить вручную, если уж известно, что не собирается дальше пользоватьсяsm.gif

Общесистемному переключателю контекста намерения задачи известны быть не могут. Это только сама задача знает, и нормальных средств запустить переключатель по требованию (как в x86 по исключению использования FPU с неактуальным контекстом) нету. Приходится гонять регистры s0-s31 всегда, при каждом переключении контекста.

Цитата(AHTOXA @ Nov 13 2012, 09:46) *
Можно глянуть во FreeRtos.

Глянул, все печально, как я и предполагал. Если процесс использовал FPU то при вытеснении s16-s31 сохраняются "ручками", вызывая неявное "ленивое" сохранение s0-s15. Если новый процесс использует FPU - то ему вгружают явно s16-s31 и неявно s0-s15 при выходе из исключения PendSV. Работать-то будет, но некрасиво и затратно.
AHTOXA
Цитата(VslavX @ Nov 13 2012, 14:17) *
Общесистемному переключателю контекста намерения задачи известны быть не могут. Это только сама задача знает

Ну да, я об этом и говорю. Пусть задача сбрасывает CONTROL.FPCA, если надобность в FPU отпала.
Цитата(VslavX @ Nov 13 2012, 14:17) *
и нормальных средств запустить переключатель по требованию (как в x86 по исключению использования FPU с неактуальным контекстом) нету.

Я всё равно не понял, как работает описанный вами механизм. Вот скажем, задачи 1 и 10 используют FPU, а задачи 2-9 - нет. После переключения с 1й на вторую задачу плавучий контекст не сохраняется, так? Потом при переключении со 2й на 3-ю, 3-4...4-9 - тоже не сохраняется. А при переключении с 9й на десятую надо сохранить. Как переключатель узнает, куда надо сохранять этот контекст?
VslavX
Цитата(AHTOXA @ Nov 13 2012, 11:24) *
Пусть задача сбрасывает CONTROL.FPCA, если надобность в FPU отпала

Ну да, бит можно сбросить, вариант.
Цитата(AHTOXA @ Nov 13 2012, 11:24) *
Я всё равно не понял, как работает описанный вами механизм. Вот скажем, задачи 1 и 10 используют FPU, а задачи 2-9 - нет. После переключения с 1й на вторую задачу плавучий контекст не сохраняется, так? Потом при переключении со 2й на 3-ю, 3-4...4-9 - тоже не сохраняется. А при переключении с 9й на десятую надо сохранить. Как переключатель узнает, куда надо сохранять этот контекст?

Заводится одна общесистемная переменная типа ptcb_fpu_context, которая указывает на TCB задачи, конекст FPU которой в данный момент загружен в физические регистры FPU. Когда эта задача вытесняется, то сохраняются только РОНы, и FPU запрещается, например битами в CPACR. Для новой вбрасываемой задачи загружаются только ее РОНы, FPU не трогается. Если новая задача не трогает FPU и потом возвращается к старой задаче - отлично, надо только разрешить снова FPU, а содержимое его регистров там и осталось нужное. А если эта новая задача (или еще более новая N-ая, которая ее вытеснит) начнет использовать FPU, то возникнет исключение UsageFault, обработчик посмотрит что ptask_fpu_context не соответствует tcb_current_task, сохранит регистры FPU согласно ptask_fpu_context, загрузит новый контекст из tcb_current_task, назначит новое значение ptask_fpu_context (задача-владелец FPU ведь поменялась), разрешит FPU в CPACR и продолжит исполнение с корректным контекстом FPU. Таким образом, фактически FPU-контекст переключается только при его совместном одновременном использовании несколькими задачами, и только тогда когда это реально нужно, а не тупо при каждом переключении задачи. Такой механизм реализован в x86 и в PowerPC, например. А для Cortex-M4F нужно вот CPACR руками рулить.
AHTOXA
Цитата(VslavX @ Nov 13 2012, 15:45) *
..

Теперь всё ясно, спасибо.
Мне кажется, что этот механизм может получиться достаточно тяжеловесным. Не уверен, что дополнительные исключения + всякие проверки не будут дольше, чем простое безусловное сохранение регистров у процессов, использующих FPU. Да, возможно потребуется более внимательное планирование процессов, чтобы FPU не использовался в процессах, которым это без надобности.
Хм, аж прямо руки зачесались попробовать и сравнить эти вариантыsm.gif
klen
Цитата(AHTOXA @ Nov 13 2012, 14:30) *
Теперь всё ясно, спасибо.
Мне кажется, что этот механизм может получиться достаточно тяжеловесным. Не уверен, что дополнительные исключения + всякие проверки не будут дольше, чем простое безусловное сохранение регистров у процессов, использующих FPU. Да, возможно потребуется более внимательное планирование процессов, чтобы FPU не использовался в процессах, которым это без надобности.
Хм, аж прямо руки зачесались попробовать и сравнить эти вариантыsm.gif

мдя.. тема интересная поднялась.
будет время переделаю переключатель контекстов и TCB FreeRTOS, в проект добавлю обработчик UsageFault по FPU, все под дефайнами влючит новый механизм или оставить прежний - это совсем просто , выложу - тогда вместе проверим как быстрее на круг из смеси задач разносортных, если Вы ранье меня это не сделаете sm.gif
.. как говорят игроки в ala Diablo - еще одна возможность повысить скилл мага... sm.gif а мож у фпу есть какаюнибудь скрытая секретная шинка по которой сохраняется .... не нупые же в ARM инженеры сидят, экономить тут не начем было...
VslavX
Цитата(klen @ Nov 15 2012, 10:48) *
а мож у фпу есть какаюнибудь скрытая секретная шинка по которой сохраняется ...

Маловероятно - FPU в ядре сидит, а внешние шины ядра документированы. Даже если оно теоретически ходит одновременно по S-bus и D-bus или даже "секретной шине", то это лишено смысла - замыкается-то оно все равно на один и тот же блок RAM (в котором стек сидит), будет арбитраж, выиграша никакого.

Цитата(klen @ Nov 15 2012, 10:48) *
не нупые же в ARM инженеры сидят, экономить тут не начем было..

Ну как бы не тупые, для однопоточного приложения и совместного использования FPU в обработчиках прерываний вроде бы неплохо оно все заточено. И совместимость с кодом для М3 отличная, наверное это за главный критерий приняли. Но вот с вытесняющей RTOS не все так гладко, что и удивляет - использование RTOS для чипов подобного класса на сегодня мейнстрим, имхо.
_Pasha
Лирика. Вспоминается ВсякоРазное, не совсем плавучее, но полезное.
SasaVitebsk
Уважаемые VslavX, klen и другие, кто в теме. Проясните мне пожалуйста такой вопрос. В текущей теме использую плавучку. Очень много. У меня FreeRTOS. Она контекст задачи сохраняет с учётом плавучки или нет? В прерываниях я плавучку не использую.
Заранее благодарю за ответ.
klen
Цитата(SasaVitebsk @ Nov 22 2012, 23:33) *
Уважаемые VslavX, klen и другие, кто в теме. Проясните мне пожалуйста такой вопрос. В текущей теме использую плавучку. Очень много. У меня FreeRTOS. Она контекст задачи сохраняет с учётом плавучки или нет? В прерываниях я плавучку не использую.
Заранее благодарю за ответ.


да, свитчер контекста провепяет использовала задача фпу или нет - от этого и пляшет
... рас уж пошла такая пьянка то давайте смотрет в пациента:

void xPortPendSVHandler( void )
{
/* This is a naked function. */

__asm volatile
(
" mrs r0, psp \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n"
" vstmdbeq r0!, {s16-s31} \n"

" \n"
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */
" \n"
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n"
" \n"
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n"
" \n"
" ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n"
" vldmiaeq r0!, {s16-s31} \n"

" \n"
" msr psp, r0 \n"
" bx r14 \n"
" \n"
" .align 2 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
}
SasaVitebsk
Спасибо.
klen
отпортировал библиотеку GSL для юзания на FPU
в раздел открытого софта запостил тему http://electronix.ru/forum/index.php?showtopic=108275
былобы неплохо если комунибудь пригодилось и заодно потестилось.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.