реклама на сайте
подробности

 
 
> Обработка математических ошибок в ARM
cyrax0
сообщение Jan 14 2015, 14:36
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 9-12-14
Пользователь №: 84 046



Здравствуйте!
Я использую IAR EWARM 6.40 и STM32F407 (с FPU). Нужно останавливать контроллер при возникновении математических ошибок, например, при log(-1). В этом случае я получаю NaN в качестве результата, но по умолчанию никакого вызова функции или exception не происходит. Нету ли для ARM функции, аналогичной стандартной _matherr (math.h)? На других архитектурах она вызывается при следующих ошибках:

Код
    DOMAIN = 1,    /* argument domain error -- log (-1)        */
    SING,          /* argument singularity  -- pow (0,-2))     */
    OVERFLOW,      /* overflow range error  -- exp (1000)      */
    UNDERFLOW,     /* underflow range error -- exp (-1000)     */
    TLOSS,         /* total loss of significance -- sin(10e70) */
    PLOSS,         /* partial loss of signif. -- not used      */
    STACKFAULT     /* floating point unit stack overflow       */

Через FPU все эти ошибки, как я понял, тоже нельзя определить, например, регистр FPSCR Cortex-M4 среди битов исключений domain error не имеет:

Bit 7 IDC: Input denormal cumulative exception bit. Cumulative exception bit for floating-point
exception.
1: Indicates that the corresponding exception occurred since 0 was last written to it.
Bit 6:5 Reserved
Bit 4 IXC: Inexact cumulative exception bit. Cumulative exception bit for floating-point exception.
1: Indicates that the corresponding exception occurred since 0 was last written to it.
Bit 3 UFC: Underflow cumulative exception bit. Cumulative exception bit for floating-point exception.
1: Indicates that the corresponding exception occurred since 0 was last written to it.
Bit 2 OFC: Overflow cumulative exception bit. Cumulative exception bit for floating-point exception.
1: Indicates that the corresponding exception occurred since 0 was last written to it.
Bit 1 DZC: Division by zero cumulative exception bit. Cumulative exception bit for floating-point
exception. 1: Indicates that the corresponding exception occurred since 0 was last written to it.
Bit 0 IOC: Invalid operation cumulative exception bit. Cumulative exception bit for floating-point
exception. 1: Indicates that the corresponding exception occurred since 0 was last written to it.


Мне даже переполнение при результате операции 0.Infinite не удалось зафиксировать в этих флагах. Может, что-то не так сделал, но вроде бы в любом случае ситуацию log(-1) ни один из этих флагов не должен определять?
Заранее спасибо.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
cyrax0
сообщение Jan 15 2015, 09:25
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 9-12-14
Пользователь №: 84 046



Цитата
А если привлечь Си++, то можно и операторы переопределить.

В итоге так, скорее всего, и придется сделать. Минус в том, что вместо math.h нужно будет подключать условный safemath.h, что с учетом сотрудников-вредителей не факт, что будет выполняться. Не проверять же мне потом все их программы.

Цитата
Вроде бы линкеры позволяют размещать данные в том числе по имени объектного файла. Нужно только вычислить, в каком файле определяется errno.

Ну похоже, что файл я определил - это errno.c. Если его объектный файл действительно можно разместить в какой-то секции средствами icf или еще какими, было бы круто.
Go to the top of the page
 
+Quote Post
klen
сообщение Jan 16 2015, 07:25
Сообщение #3


бессмертным стать можно тремя способами
*****

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



здравствуйте.
вставлю свои 5 копеек.
1. FPU вычислительный блок который, как справедливо заметила Xenia, над данными типа флоат умеет делать арифмитические операци + немного необходимых ништяков. FPU за то то эти арифметические операции он сделал правильно с предсказуемым результатом.
2. в силу того сто косинусы логарифмы и тд это функции с аргументом типа флоат не раелизованы аппаратно в соответствующих библиотеках они реализованы как подпрограмки. стандарно это делается в виде быстросходящегося ряда. поэтому FPU понятия не имеет что за результат он получил в результате вычисленй и не может интепретировать результат логарифма - эта сущность выше по уровню. В частности результат NAN или INF это хороший правильный резульат - какие данные воткнули он вам для них выдал то что описывает стандарт IEEE764 .... он свое дело сделал и может честно отдыхать.
3. Вывод - в данной случае если вызывающая сторона не может контролировать входные данные то анализ резульата подпрограммы должна делать она сама - это забота libm (math.h) что и предполагается по стандарту на POSIX Standard C Library (https://ru.wikipedia.org/wiki/Errno.h). Код либы гарантирует что он в переменную errno запишет сотояние результата .... он свое дело сделал и может честно отдыхать. А его анализ ложится на вызывающую сторону. Если ты вызвал логарифм с кривыми входными данными - о чем ты можен по многим причина не знать и не ПРОВЕРИЛ СОСТОЯНИЕ РЕЗУЛЬТАТА то ты сам ДУРАК. одним словом FPU + libc/libm дает иструмент позволяющий выплыть из нештатной ситуации.
пример - возьмем реализацию из библиотеки NewLib в части libm : log

Код
#include "fdlibm.h"
#include <errno.h>

#ifdef __STDC__
    float logf(float x)        /* wrapper logf */
#else
    float logf(x)            /* wrapper logf */
    float x;
#endif
{
#ifdef _IEEE_LIBM
    return __ieee754_logf(x);
#else
    float z;
    struct exception exc;
    z = __ieee754_logf(x);
    if(_LIB_VERSION == _IEEE_ || isnan(x) || x > (float)0.0) return z;
#ifndef HUGE_VAL
#define HUGE_VAL inf
    double inf = 0.0;

    SET_HIGH_WORD(inf,0x7ff00000);    /* set inf to infinite */
#endif
    exc.name = "logf";
    exc.err = 0;
    exc.arg1 = exc.arg2 = (double)x;
    if (_LIB_VERSION == _SVID_)
           exc.retval = -HUGE;
    else
       exc.retval = -HUGE_VAL;
    if(x==(float)0.0) {
        /* logf(0) */
        exc.type = SING;
        if (_LIB_VERSION == _POSIX_)
           errno = ERANGE;
        else if (!matherr(&exc)) {
           errno = ERANGE;
        }
    } else {
        /* logf(x<0) */
        exc.type = DOMAIN;
        if (_LIB_VERSION == _POSIX_)
           errno = EDOM;
        else if (!matherr(&exc)) {
           errno = EDOM;
        }
            exc.retval = nan("");
        }
    if (exc.err != 0)
           errno = exc.err;
        return (float)exc.retval;
#endif
}


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

4. это было введение о том как есть, а теперь мое предложение о том как сделать решение как хочется автору поста (естественно это приминительно для CORTEX-M4F или прочий ибо автор про его FPU затеял тему).
если нада дествительно эксепшен так что хачу-нимагу!! , ну например подчиненные программисты лесом посылают errno и лепят горбатого в своем коде то можно поступить следующим образом.
берем исходнички libm и во всех местах где errno присваиваются кода крывых состояний вызывать svc - бутет порожден эксепшен который приведет к исполненению обработчика прерывания - вот тут уже бойцы не смогут перепрыгнуть через окоп для танков и им прийдется прореагировать на ситуацию что чтото пошло не так.

5. а вообще, я считаю, нада всех кто не хочет стандарты изучать и применять в жизни, тек кто изобретает велосипЭд и прочих водителей луноходов пороть ремнем три раза в день и оставлять без ужина sm.gif
надесь чем то помог.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- cyrax0   Обработка математических ошибок в ARM   Jan 14 2015, 14:36
- - scifi   Цитата(cyrax0 @ Jan 14 2015, 17:36) Я исп...   Jan 14 2015, 14:55
- - cyrax0   А можно поподробнее, что за errno? Отмечу еще раз,...   Jan 14 2015, 17:02
|- - scifi   Цитата(cyrax0 @ Jan 14 2015, 20:02) А мож...   Jan 14 2015, 19:17
- - _Pasha   Насколько я помню, Вам нужно переопределить хандле...   Jan 14 2015, 19:15
|- - cyrax0   ЦитатаНасколько я помню, Вам нужно переопределить ...   Jan 14 2015, 19:43
|- - jcxz   Цитата(cyrax0 @ Jan 15 2015, 01:43) Если ...   Jan 15 2015, 05:26
|- - scifi   Цитата(jcxz @ Jan 15 2015, 08:26) Через M...   Jan 15 2015, 06:57
- - Xenia   Цитата(cyrax0 @ Jan 14 2015, 20:02) А мож...   Jan 14 2015, 22:42
|- - cyrax0   Цитата(Xenia @ Jan 15 2015, 02:42) А чем ...   Jan 15 2015, 07:59
|- - jcxz   Цитата(cyrax0 @ Jan 15 2015, 13:59) Прико...   Jan 15 2015, 08:20
- - _Pasha   Собственно можно пойти далеко в обход: написать ну...   Jan 15 2015, 04:32
- - cyrax0   Не очень понимаю, с какой стати errno может быть в...   Jan 15 2015, 08:35
|- - jcxz   Цитата(cyrax0 @ Jan 15 2015, 14:35) Не оч...   Jan 15 2015, 10:14
- - scifi   Цитата(cyrax0 @ Jan 15 2015, 10:59) У нас...   Jan 15 2015, 09:08
|- - jcxz   Цитата(scifi @ Jan 15 2015, 15:08) Не фак...   Jan 15 2015, 10:27
|- - scifi   Цитата(cyrax0 @ Jan 15 2015, 12:25) В ито...   Jan 15 2015, 10:22
- - Xenia   Господа! Вы что, с ума сошли? Переменную errn...   Jan 15 2015, 12:28
|- - scifi   Цитата(Xenia @ Jan 15 2015, 15:28) Одного...   Jan 15 2015, 13:01
||- - Xenia   Цитата(scifi @ Jan 15 2015, 16:01) Конечн...   Jan 15 2015, 13:29
||- - scifi   Цитата(Xenia @ Jan 15 2015, 16:29) Тогда ...   Jan 15 2015, 13:47
||- - cyrax0   Цитата(scifi @ Jan 15 2015, 17:47) Подозр...   Jan 15 2015, 13:53
||- - scifi   Цитата(cyrax0 @ Jan 15 2015, 16:53) Делен...   Jan 15 2015, 14:51
|- - jcxz   Цитата(Xenia @ Jan 15 2015, 18:28) Господ...   Jan 15 2015, 17:08
- - cyrax0   Цитата(scifi @ Jan 15 2015, 14:22) Там ес...   Jan 15 2015, 13:46
- - cyrax0   Цитата(jcxz @ Jan 15 2015, 21:08) Так пом...   Jan 16 2015, 06:09
|- - jcxz   Цитата(cyrax0 @ Jan 16 2015, 12:09) Я поп...   Jan 16 2015, 17:55
- - WitFed   Ещё 1 коп: обычно можно переопределить "систе...   Jan 16 2015, 09:19


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 12:55
Рейтинг@Mail.ru


Страница сгенерированна за 0.01403 секунд с 7
ELECTRONIX ©2004-2016