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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Обработка математических ошибок в 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
scifi
сообщение Jan 14 2015, 14:55
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(cyrax0 @ Jan 14 2015, 17:36) *
Я использую IAR EWARM 6.40 и STM32F407 (с FPU). Нужно останавливать контроллер при возникновении математических ошибок, например, при log(-1).

Мне казалось, что FPU внутри STM32F407 умеет только single precision. Тогда вам не log() нужен, а logf(), если надеетесь на какое-то аппаратное ускорение.
А для проверок на ошибки есть такая штука, как errno.
Go to the top of the page
 
+Quote Post
cyrax0
сообщение Jan 14 2015, 17:02
Сообщение #3


Участник
*

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



А можно поподробнее, что за errno? Отмечу еще раз, что мне нужна не просто проверка на ошибки (не делать же ее после каждой операции), а что-то вроде исключения, если результат математической операции = NaN, Inf, etc.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 14 2015, 19:15
Сообщение #4


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Насколько я помню, Вам нужно переопределить хандлер matherr() который должен отвечать за обработку ошибки.
Только я этим никогда не пользовался, подробностей не скажу.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 14 2015, 19:17
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(cyrax0 @ Jan 14 2015, 20:02) *
А можно поподробнее, что за errno?

Это стандарт языка Си. Читайте учебники.

Цитата(cyrax0 @ Jan 14 2015, 20:02) *
Отмечу еще раз, что мне нужна не просто проверка на ошибки (не делать же ее после каждой операции), а что-то вроде исключения, если результат математической операции = NaN, Inf, etc.

Хотеть не вредно. Я не в курсе, но не удивлюсь, если в яре для STM32F4 этого нет. Так что да, делайте проверку после и/или перед каждой операцией. На самом деле это совсем не сложно.
Go to the top of the page
 
+Quote Post
cyrax0
сообщение Jan 14 2015, 19:43
Сообщение #6


Участник
*

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



Цитата
Насколько я помню, Вам нужно переопределить хандлер matherr() который должен отвечать за обработку ошибки.

Хотелось бы, только в моей среде в math.h эта функция не описана, как и ее аргумент exception, поэтому переопределять нечего sad.gif.

Цитата
Так что да, делайте проверку после и/или перед каждой операцией. На самом деле это совсем не сложно.

Если бы этот вариант подходил, я бы здесь не писал.

Сообщение отредактировал cyrax0 - Jan 14 2015, 19:45
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jan 14 2015, 22:42
Сообщение #7


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(cyrax0 @ Jan 14 2015, 20:02) *
А можно поподробнее, что за errno? Отмечу еще раз, что мне нужна не просто проверка на ошибки (не делать же ее после каждой операции), а что-то вроде исключения, если результат математической операции = NaN, Inf, etc.


А чем плоха проверка результата? Неприятие к этой процедуре можно было еще объяснить, если бы STM32F вычислял логарифмы аппаратно, но ведь этого-то нет! Он способен лишь на то, чтобы выполнять с плавающей точкой 4 арифметрических действия. Ну, еще два числа умеет сравнивать. Но ведь функций-то вычислять аппаратно он не умеет! А, стало быть, все эти логарифмы, экспоненты и тригонометрия - галимая эмуляция sm.gif. А раз так, то вы крайне незначительно замедлите вычисление логарифма, если решитесь на проверку результата. Опять же всегда можно создать свою функцию типа my_log(), которая вызывает нативную функцию log(), проверяя после нее результат.

Учитывая эти обстоятельства, предлагаю вам просто заглянуть в исходники и поглядеть, как там реализована функция log(). Я сама заглядывала (только у меня EWARM не 6.40, а 7.30), но нашла там лишь присвоение кода ошибки глобальной переменной errno. Хотя в хидере xmath.h есть что-то похожее на возможность установки собственного хэндлера для реакции на математические ошибки. Глубже не разбиралась.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 15 2015, 04:32
Сообщение #8


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Собственно можно пойти далеко в обход: написать нужный функционал на плюсах, но при этом переопределить оператор =
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 15 2015, 05:26
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(cyrax0 @ Jan 15 2015, 01:43) *
Если бы этот вариант подходил, я бы здесь не писал.

Ну Вам же уже подсказали, что при ошибках, состояние ошибки сохраняется в errno (я сам не уверен что для всех желаемых Вами случаев).
Если Вам нужно именно прерывание, в чем проблема? В Вашем STM32F407 отсутствует MPU?
Через MPU защищаете некую область памяти от записи, линкуете туда errno и получаете прерывание MPU каждый раз при попытке записи в errno.
Фсё.

В особо извращённом случае, можно errno смаппировать на регистр данных какой-нить неиспользуемой периферии, например - буфер передаваемых данных SPI и разрешить прерывание на
завершение передачи от этой периферии. cheers.gif

Цитата(_Pasha @ Jan 15 2015, 10:32) *
Собственно можно пойти далеко в обход: написать нужный функционал на плюсах, но при этом переопределить оператор =

Ну да, и как прикажете быть например с: a = log(-1) + 1 ?

Если идти в обход плюсами, то нужно описать errno как класс, перегрузить оператор присвоения ему и внутрь этого перегруженного оператора вставить вызов обработчика ошибки.
Но это возможно только если не используется предкомпилённых математических библиотек, а все они компилятся в исходниках с проектом.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 15 2015, 06:57
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(jcxz @ Jan 15 2015, 08:26) *
Через MPU защищаете некую область памяти от записи, линкуете туда errno и получаете прерывание MPU каждый раз при попытке записи в errno.
Фсё.

Ловко :-)
Go to the top of the page
 
+Quote Post
cyrax0
сообщение Jan 15 2015, 07:59
Сообщение #11


Участник
*

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



Цитата(Xenia @ Jan 15 2015, 02:42) *
А чем плоха проверка результата? Неприятие к этой процедуре можно было еще объяснить, если бы STM32F вычислял логарифмы аппаратно, но ведь этого-то нет!

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

Цитата
Хотя в хидере xmath.h есть что-то похожее на возможность установки собственного хэндлера для реакции на математические ошибки. Глубже не разбиралась.

Хорошая мысль, но похоже эта _Feraise не вызывается автоматически, по крайней мере брекпоинт на нее не ставится. Либо у меня не подключена DLib, не знаю, как это делается.

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

Прикольная идея, спасибо. Под линковкой понимается приделать к errno:
Код
@ какой-то_адрес

и как это сделать, модифицировать стандартный код?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 15 2015, 08:20
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(cyrax0 @ Jan 15 2015, 13:59) *
Прикольная идея, спасибо. Под линковкой понимается приделать к errno:
Код
@ какой-то_адрес

и как это сделать, модифицировать стандартный код?

Если errno не вынесен в отдельную секцию, которую можно отдельно линковать, то придётся править исходники - вынести его в отдельную секцию.
Если вынесен (или в секции, где он находится, остальные переменные используются как read-only) - то библиотеку править не надо, только свой icf-файл.
Посмотрите свой map-файл - в какой секции находится errno.
Go to the top of the page
 
+Quote Post
cyrax0
сообщение Jan 15 2015, 08:35
Сообщение #13


Участник
*

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



Не очень понимаю, с какой стати errno может быть вынесен в отдельную секцию. У меня стандартные секции ROM, RAM, CMMRAM. В map-файле errno, скорее всего, вот он:
__iar_Errno 0x20008bdc 0x4 Data Gb errno.o [3]
Находится в стандартной секции RAM.

Если править библиотеки, то проще уж наверное в math.h добавить проверку аргументов, чтобы не заморачиваться с MPU? С ним я еще не работал.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 15 2015, 09:08
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(cyrax0 @ Jan 15 2015, 10:59) *
У нас математические алгоритмы пишут разные сотрудники, и кто-то может забыть проверить результат. Поэтому нужно проверять такие ошибки на системном уровне.

Уровни разные бывают. Совсем не сложно обернуть код сотрудников-вредителей макросами, тогда функции будут с проверками на ошибки и вообще с чем угодно. А если привлечь Си++, то можно и операторы переопределить.

Цитата(jcxz @ Jan 15 2015, 11:20) *
Если errno не вынесен в отдельную секцию, которую можно отдельно линковать, то придётся править исходники - вынести его в отдельную секцию.

Не факт. Вроде бы линкеры позволяют размещать данные в том числе по имени объектного файла. Нужно только вычислить, в каком файле определяется errno.
Кроме того, можно обработать файл библиотеки ELF-тулзами и подменить название секции.
Go to the top of the page
 
+Quote Post
cyrax0
сообщение Jan 15 2015, 09:25
Сообщение #15


Участник
*

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



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

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

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

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


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(cyrax0 @ Jan 15 2015, 14:35) *
Не очень понимаю, с какой стати errno может быть вынесен в отдельную секцию. У меня стандартные секции ROM, RAM, CMMRAM. В map-файле errno, скорее всего, вот он:
__iar_Errno 0x20008bdc 0x4 Data Gb errno.o [3]
Находится в стандартной секции RAM.

RAM - это не секция, это одна из целевых областей линковки.
Я говорил о выходных секциях компилятора (для IAR это: .text, .bss и т.п.).
Часто бывает что в библиотеках определяют собственные имена секций, для возможности более оптимально размещать их в памяти.
Посмотрел у себя в map-файле:
Код
.bss                zero     0x40006ef8      0x8  errno.o [3]
__iar_Errno 0x40006efc 0x4 Data Gb errno.o [3]
__iar_Tls_setup___iar_Errno 0x40006ef8 0x4 Data Gb errno.o [3]

Как видно - в .bss-секцию из файла errno.o слинкованы 8 байт (две переменных: __iar_Errno и __iar_Tls_setup___iar_Errno).
Вот этот кусочек и можно перенести в отдельный регион MPU_RO_mem, который потом закрыть по записи MPU. В icf-файле:
place in MPU_RO_mem {section .bss object errno.o};
Правда косяк, что прерывание будет происходить и при модификации __iar_Tls_setup___iar_Errno если она будет случаться. Это нужно будет учесть в ISR.

Минус такого способа конечно в том, что гранулярность защиты памяти в MPU довольно большая (дискретность границ вроде около 1 кБ).
Так что потеряете на этом размер ОЗУ равный гранулярности.
Можно конечно смаппировать MPU_RO_mem на адреса, где нет ОЗУ. Но тогда (если нужно значение errno) надо будет в ISR разбирать код команды вызвавшей сбой защиты
и определять регистр-источник записываемого значения.

Цитата(cyrax0 @ Jan 15 2015, 14:35) *
Если править библиотеки, то проще уж наверное в math.h добавить проверку аргументов, чтобы не заморачиваться с MPU? С ним я еще не работал.

Зато будет польза что разобрались с ним rolleyes.gif
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 15 2015, 10:22
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(cyrax0 @ Jan 15 2015, 12:25) *
В итоге так, скорее всего, и придется сделать. Минус в том, что вместо math.h нужно будет подключать условный safemath.h, что с учетом сотрудников-вредителей не факт, что будет выполняться. Не проверять же мне потом все их программы.

Не нужно это, достаточно написать свой файл math.h и указать компилятору директорию с этим файлом для поиска заголовков. Яр ищет заголовки в папке стандартной библиотеки в последнюю очередь, то есть свой файл подцепится первым. Правда, как оттуда подцепить настоящий math.h, не совсем ясно :-) Можно по абсолютному пути, но это не очень комильфо.

Update:
Там есть забавная прагма include_alias.

Файл preinclude.h (заставить включать его ключом компилятора --preinclude):
Код
#pragma include_alias (<math.h> , "safemath.h")

Файл safemath.h:
Код
#pragma include_alias (<math.h> , <math.h>)
#include <math.h>

...
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 15 2015, 10:27
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(scifi @ Jan 15 2015, 15:08) *
Не факт. Вроде бы линкеры позволяют размещать данные в том числе по имени объектного файла. Нужно только вычислить, в каком файле определяется errno.
Кроме того, можно обработать файл библиотеки ELF-тулзами и подменить название секции.

Позволяют, но только не отдельные переменные, а выходные секции компилятора.
Если для переменной не задана явно секция, то она будет компилятором объединена в секцию .bss общую для всех переменных данного файла.
И разделить эту .bss потом, на этапе линковки, невозможно.
Тут надо или в исходниках для errno явно указать секцию отличную от .bss.
Или вроде есть опция компилятора, которая позволяет каждую переменную выделять в отдельную секцию. Не помню только это в IAR или где я видел.
Но это увеличивает размер кода, так как если ранее компилятор для группы соседних переменных мог в .text создавать одну ссылку (указатель на начало секции),
то теперь ему нужно будет отдельно адресовать каждую переменную. Так что эту опцию нужно применить только к файлу errno.c.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jan 15 2015, 12:28
Сообщение #19


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Господа! Вы что, с ума сошли? sm.gif Переменную errno в отдельную секцию выносить??? Все это можно сделать много проще, а не такими драконовскими мерами.

Заметим, что ни в одной функции, и log() в том числе, значение errno не присваивается явно, а только через вызов дефайнов:
Код
#define _FERAISE_INVALID()    { errno = EDOM;   }
#define _FERAISE_DIVBYZERO()  { errno = ERANGE; }
#define _FERAISE_OVERFLOW()   { errno = ERANGE; }
#define _FERAISE_UNDERFLOW()  { errno = ERANGE; }
#define _FERAISE_INEXACT()

Так что, если вы взялись за дело настолько серьезно, что решили перекомпилировать библиотеку, то было бы куда проще переопределить эти 5 дефиниций на свои функции.

Однако я полагаю, что и в этом нет большой нужды, т.к. эти дефиниции определены в хидере xmath.h не жестко, а условно:
Код
#if defined(math_errhandling) && math_errhandling == MATH_ERRNO

  /* Optimization of the _Feraise function when the IAR default is used. */
  #define _FERAISE_INVALID()    { errno = EDOM;   }
  #define _FERAISE_DIVBYZERO()  { errno = ERANGE; }
  #define _FERAISE_OVERFLOW()   { errno = ERANGE; }
  #define _FERAISE_UNDERFLOW()  { errno = ERANGE; }
  #define _FERAISE_INEXACT()

#else
... // здесь определена функция _Feraise()

#define _FERAISE_INVALID()    _Feraise(FE_INVALID)
#define _FERAISE_DIVBYZERO()  _Feraise(FE_DIVBYZERO)
#define _FERAISE_OVERFLOW()   _Feraise(FE_OVERFLOW)
#define _FERAISE_UNDERFLOW()  _Feraise(FE_UNDERFLOW)
#define _FERAISE_INEXACT()    _Feraise(FE_INEXACT)

#endif

Т.е. достаточно определить "math_errhandling" иначе, чем MATH_ERRNO, чтобы определение этих дефиниций изменилось на альтернативное, с явным вызовом функции _Feraise(), получающей код ошибки в качестве параметра.

Саму функцию _Feraise() при желании можно легко заменить на свою (т.к. самодельный вариант линкуется раньше библиотечного), а можно оставить той, что написана авторами компилятора - она там errno присваивает, а потом исключение вызывает.

Одного только я уверенно сказать не могу, нужно ли для этого перекомпилировать библиотеку или достататочно будет определить math_errhandling перед включением хидера xmath.h.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 15 2015, 13:01
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Xenia @ Jan 15 2015, 15:28) *
Одного только я уверенно сказать не могу, нужно ли для этого перекомпилировать библиотеку или достататочно будет определить math_errhandling перед включением хидера xmath.h.

Конечно перекомпилировать.
Но перекомпиляция библиотеки сопряжена с неудобствами. К примеру, чтобы подготовить новый компьютер к сборке программ, нужно помимо установки яра колдовать с библиотекой. В общем, надо взвешивать плюсы и минусы.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Jan 15 2015, 13:29
Сообщение #21


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(scifi @ Jan 15 2015, 16:01) *
Конечно перекомпилировать.
Но перекомпиляция библиотеки сопряжена с неудобствами. К примеру, чтобы подготовить новый компьютер к сборке программ, нужно помимо установки яра колдовать с библиотекой. В общем, надо взвешивать плюсы и минусы.


Тогда уж гораздо проще перекомпилировать один единственный модуль, в котором функция log() находится sm.gif, а потом добавить этот объектник в проект. Жалко библиотеку курочить.
Go to the top of the page
 
+Quote Post
cyrax0
сообщение Jan 15 2015, 13:46
Сообщение #22


Участник
*

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



Цитата(scifi @ Jan 15 2015, 14:22) *
Там есть забавная прагма include_alias.

Спасибо, этот вариант подходит! Только код пришлось написать немного по-другому:
Код
#pragma include_alias("math.h", "safemath.h")
#pragma include_alias(<math.h>, <safemath.h>)


Цитата(jcxz @ Jan 15 2015, 14:14) *
RAM - это не секция, это одна из целевых областей линковки.
Я говорил о выходных секциях компилятора (для IAR это: .text, .bss и т.п.).
Часто бывает что в библиотеках определяют собственные имена секций, для возможности более оптимально размещать их в памяти.

Хорошо, но bss - это тоже стандартная секция.

Цитата
В icf-файле:
place in MPU_RO_mem {section .bss object errno.o};

Попробовал так:
define region MPU_region = mem:[from 0x20000000 to __ICFEDIT_region_RAM_start__ - 1];
place in MPU_region {section .bss object errno.o};
// Place in RAM_region .data, .bss, and .noinit
place in RAM_region { readwrite };


Возможно place in RAM_region перекрывает директиву place in MPU_region - __iar_Errno у меня остался на прежнем месте в RAM.

Цитата
Минус такого способа конечно в том, что гранулярность защиты памяти в MPU довольно большая (дискретность границ вроде около 1 кБ).

Вроде бы нет. Регистр MPU_RASR в Cortex-M4:
Bits 5:1 SIZE: Size of the MPU protection region.
The minimum permitted value is 3 (b00010), see SIZE field values for more information.
Bit 0 ENABLE: Region enable bit.
SIZE field values
The SIZE field defines the size of the MPU memory region specified by the MPU_RNR
regsiter as follows:
(Region size in bytes) = 2(SIZE+1)
The smallest permitted region size is 32B, corresponding to a SIZE value of 4.


Цитата
Правда косяк, что прерывание будет происходить и при модификации __iar_Tls_setup___iar_Errno если она будет случаться. Это нужно будет учесть в ISR.

А в ISR MPU можно получить, скажем, адрес функции, которая вызвала прерывание?

Цитата
Зато будет польза что разобрались с ним rolleyes.gif

Честно говоря, сейчас скорее всего не будет на это времени. Но разобраться все равно хотел бы sm.gif.

Xenia
Вариант интересный, спасибо. Хотя у нас подключается math.h, но через алиас можно и xmath.h подключить. Перекомпиляция нужна, если меняется один из дефайнов, используемых в библиотеке? Я этим никогда не занимался, не представляю как это делается, хотя сейчас наверно и не понадобится.

Еще раз всем спасибо за ответы! Вопрос в принципе решен sm.gif.

Сообщение отредактировал cyrax0 - Jan 15 2015, 13:48
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 15 2015, 13:47
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Xenia @ Jan 15 2015, 16:29) *
Тогда уж гораздо проще перекомпилировать один единственный модуль, в котором функция log() находится sm.gif, а потом добавить этот объектник в проект. Жалко библиотеку курочить.

Подозреваю, что топикстартера не только логарифм интересует. А если он ещё захочет ловить деление на ноль, то ему точно от Си++ и перегрузки операторов не отвертеться.
Go to the top of the page
 
+Quote Post
cyrax0
сообщение Jan 15 2015, 13:53
Сообщение #24


Участник
*

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



Цитата(scifi @ Jan 15 2015, 17:47) *
Подозреваю, что топикстартера не только логарифм интересует. А если он ещё захочет ловить деление на ноль, то ему точно от Си++ и перегрузки операторов не отвертеться.

Деление на ноль как раз ловится элементарно:
SCB->CCR |= 0x10;
Без этого (по умолчанию) деление на ноль дает ноль.
С этим - HardFault.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 15 2015, 14:51
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(cyrax0 @ Jan 15 2015, 16:53) *
Деление на ноль как раз ловится элементарно:
SCB->CCR |= 0x10;

И с плавучкой это будет работать?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 15 2015, 17:08
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Xenia @ Jan 15 2015, 18:28) *
Господа! Вы что, с ума сошли? sm.gif Переменную errno в отдельную секцию выносить??? Все это можно сделать много проще, а не такими драконовскими мерами.

Переменная errno в IAR уже практически в отдельной секции. Я же написал выше.
И способ с MPU хорош тем, что не надо ничего перекомпилировать и вмешиваться в библиотеку.

Цитата(cyrax0 @ Jan 15 2015, 19:46) *
Попробовал так:
define region MPU_region = mem:[from 0x20000000 to __ICFEDIT_region_RAM_start__ - 1];
place in MPU_region {section .bss object errno.o};
// Place in RAM_region .data, .bss, and .noinit
place in RAM_region { readwrite };

Возможно place in RAM_region перекрывает директиву place in MPU_region - __iar_Errno у меня остался на прежнем месте в RAM.

Так поменяйте их местами. Линкер считывает команды по порядку и последующая перекрывает действие предыдущих.

Цитата(cyrax0 @ Jan 15 2015, 19:46) *
А в ISR MPU можно получить, скажем, адрес функции, которая вызвала прерывание?

Вы же уже открыли даташит на странице MPU? Так и прочитайте laughing.gif
Я не использовал на практике MPU на Cortex, только на других CPU.
Если адрес команды записи в errno нельзя получить из регистров MPU, то очевидно его можно получить из сохранённого контекста на входе в прерывание.
Только не забудьте отключить write-back для защищаемого региона.
Go to the top of the page
 
+Quote Post
cyrax0
сообщение Jan 16 2015, 06:09
Сообщение #27


Участник
*

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



Цитата(jcxz @ Jan 15 2015, 21:08) *
Так поменяйте их местами. Линкер считывает команды по порядку и последующая перекрывает действие предыдущих.

Я попробовал и так, и так.

Цитата(scifi @ Jan 15 2015, 18:51) *
И с плавучкой это будет работать?

Бинго! С плавучкой не работает. Спасибо за подсказку!
Go to the top of the page
 
+Quote Post
klen
сообщение Jan 16 2015, 07:25
Сообщение #28


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

Группа: Свой
Сообщений: 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
WitFed
сообщение Jan 16 2015, 09:19
Сообщение #29


Местный
***

Группа: Свой
Сообщений: 271
Регистрация: 6-12-11
Из: Taganrog
Пользователь №: 68 701



Ещё 1 коп: обычно можно переопределить "системную" функцию своею с тем же именем, и линкер возьмёт последнюю, там можно больше всего проверить до/после. Системные либы не трогаются.
Но как из своей функции-обёртки вызвать оригинальную -- не знаю, не пробовал.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jan 16 2015, 17:55
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(cyrax0 @ Jan 16 2015, 12:09) *
Я попробовал и так, и так.

Что-то у вас странное происходит...
Вот выдержка из icf из одного моего текущего проекта:
Код
place in RAM_regionA {ro, first block IMAGE_HEAD, last section .codetail};
place in RAM_regionBB {
  section .text object timeout.o,
  section .text object str.o,
  ...
};

Всё, что посылается в RAM_regionBB там и оказывается.
Go to the top of the page
 
+Quote Post

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

 


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


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