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

 
 
> STM32 Обработка hard fault exception, Как правильно с ним работать
Serj78
сообщение Dec 28 2010, 02:19
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 966
Регистрация: 27-05-06
Из: СПб
Пользователь №: 17 499



Читаю документацию на ARM ( DDI0337e - Cortex™-M3 Revision: r1p1 Technical Reference Manual)

Хочется более полного понимания, от тех кто работал с системой исключений.

Из того что я понял- это как будто "верхний" уровень "прерываний" происходящий по критическим событиям в процессоре.

Из структуры стартап-файла (использую Keil 4.12) видно, что по каждому исключению может быть вызвано прерывание.

Очень вероятно, что назначением прерываний ведает Configurable Fault handler, упомянутый в вышеуказанном документе (DDI0337e).

Но как его включить (где описана структура управляющего регистра) ?

Как вообще используют систему исключений? У меня она нигде никак в явном виде не инициализируется , как узнать что исключение произошло?
Периодически читать статус регистр исключения? И если оно произошло, какие могут быть последствия?
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 14)
Harvester
сообщение Dec 28 2010, 03:36
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 338
Регистрация: 1-02-06
Из: Королев, М.О.
Пользователь №: 13 846



Исключение Hard Fault, также как сброс и NMI, является системным исключением с фиксированным приоритетом и разрешено всегда.
Данное исключение генерируется при появлении исключений Bus Fault, MemManage Fault, Usage Fault, если соответствующие исключения запрещены. Также Hard Fault может генерироваться при отказе шины во время выборки вектора из таблицы. Причина исключения Hard Fault - см. регистр HFSR (0xE000ED2C).
Примечание: Если очень нужно запретить HArd Fault, то можно установить регистр FAULTMASK - при этом разрешенным останется только NMI

Сообщение отредактировал IgorKossak - Dec 28 2010, 11:06
Причина редактирования: Бездумное цитирование


--------------------
-Да как так-то?/-Да как-то так/-Ну так-то да
Go to the top of the page
 
+Quote Post
zltigo
сообщение Dec 28 2010, 05:03
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (Serj78 @ Dec 28 2010, 08:19) *
Но как его включить (где описана структура управляющего регистра) ?

Так в помянутом документе все есть, остальное уже в документации на конкретный чип.
QUOTE
Как вообще используют систему исключений?

Обработчики висят.
QUOTE
У меня она нигде никак в явном виде не инициализируется , как узнать что исключение произошло?

Узнаете сразу, не сомневайтесь sm.gif - вылетев из программы.
Минимальные заглушки обработчиков для начала:
CODE
//-----------------------------------------------------------------------------
// This is the code that gets called when the processor receives a NMI
//-----------------------------------------------------------------------------
void nmi_isr(void)
{
ulong link = __get_LR();

    xprintf( "\r\tNMI Exception\r"
             "LR:%8X SP:%8X\r", link, __get_SP() );
    print_all();

    for(;; );
}

//-----------------------------------------------------------------------------
// This is the code that gets called when the processor receives a Fault
// interrupt.
//-----------------------------------------------------------------------------
void hard_fault_isr(void)
{
ulong link = __get_LR();

    xprintf( "\r\tHard Fault\r"
             "LR:%8X SP:%8X St:%8X\r", link, __get_SP(), NVIC_HARDFAULT );
    print_all();

    for(;; );
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void bus_fault_isr(void)
{
ulong link = __get_LR();

    xprintf( "\r\tBUS Fault\r"                
            "LR:%8X SP:%8X St:%2X ", link, __get_SP(), (ulong)NVIC_BUSFAULT );
    if( NVIC_BUSFAULT & BUSFAULT_STAT_ARV )
        xprintf( "Adr:%8X\r", NVIC_BUSFAULTADR );
    else
        println( "Adr:None" );

    print_all();

    for(;; );
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void usage_fault_isr(void)
{
ulong link = __get_LR();

    xprintf( "\r\tUsage Fault\r"
             "LR:%8X SP:%8X St:%4X\r", link, __get_SP(),
                                        (ulong)NVIC_USAGEFAULT );
    print_all();

    for(;; );
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void mpu_fault_isr(void)
{
ulong link = __get_LR();

    xprintf( "\r\tMPU Fault\r"                
            "LR:%8X SP:%8X St:%2X ", link, __get_SP(), (ulong)NVIC_MEMFAULT );
    if( NVIC_MEMFAULT & MEMFAULT_STAT_ARV )
        xprintf( "Adr:%8X\r", NVIC_MEMFAULTADR );
    else
        println( "Adr:None" );

    print_all();                                                                      

    for(;; );
}


//-----------------------------------------------------------------------------
// This is the code that gets called when the processor receives an Unexpected
// Interrupt.
//-----------------------------------------------------------------------------
void default_isr(void)
{
ulong link = __get_LR();

    xprintf( "\r\tDefault/Unknown Interrupt\r"
             "LR:%8X SP:%8X\r", link, __get_SP() );
    print_all();

    for(;; );
}

//-----------------------------------------------------------------------------
// This is the code that gets called when the processor receives an Unexpected
// Interrupt.
//-----------------------------------------------------------------------------
void debug_isr(void)
{
ulong link = __get_LR();

    xprintf( "\r\tDebug Fault\r"
             "LR:%8X SP:%8X St:%2X Data:%8X\r", link, __get_SP(),
                                             NVIC_DEBUGFAULT & 0xFF, NVIC_DBG_DATA );
    print_all();

    for(;; );
}


Дальше думайте, что и как Вам надо.



--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Serj78
сообщение Dec 28 2010, 12:14
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 966
Регистрация: 27-05-06
Из: СПб
Пользователь №: 17 499



Цитата(Harvester @ Dec 28 2010, 09:36) *
Также Hard Fault может генерироваться при отказе шины во время выборки вектора из таблицы. Причина исключения Hard Fault - см. регистр HFSR (0xE000ED2C).
Примечание: Если очень нужно запретить HArd Fault, то можно установить регистр FAULTMASK - при этом разрешенным останется только NMI


Спасибо за ответы, но мне не понятно главное- суть системы исключений.

Слово "отказ" я воспринимаю как некую неисправность, возникающую по причине несоответствия конструкции (в данном случае контроллера) условиям работы.
Это некие "затычки" против системных отказов? Как вообще может возникнуть "отказ шины" (имеется в виду, очевидно, внутренняя шина данных контроллера? )

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

Недавно перешел с более простой архитектуры ( AVR) там, такого понятия нет, вот и спрашиваю....
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Dec 28 2010, 12:46
Сообщение #5


Профессионал
*****

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



Например, Вы можете попытаться обратиться или выполнить код из области памяти, которой не существует.


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 28 2010, 13:59
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Serj78 @ Dec 28 2010, 20:14) *
Больше всего интересует, что я могу в программе написать такое, чтобы возникло это исключение?

Например вот так:
Код
void make_hard_fault()
{
    __asm volatile
    (
        "MOVS r0, #1       \n"
        "LDM r0,{r1-r2}    \n"
        "BX LR                \n"
    );
}

Это попытка чтения по невыровненному адресу. Будет исключение.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Serj78
сообщение Dec 28 2010, 15:48
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 966
Регистрация: 27-05-06
Из: СПб
Пользователь №: 17 499



Спасибо за примеры!
Но это если я, образно говоря- сам дурак и [ кидаю лом в унитаз поезда на полном ходу sm.gif ]

По идее, компилятор должен не допускать подобных вещей при генерации ассемблерного кода, или, по крайней мере, сообщать о них?

Как часто на практике приходится сталкиваться с подобными вещами (проявлением исключений)?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 28 2010, 16:56
Сообщение #8


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Serj78 @ Dec 28 2010, 23:48) *
По идее, компилятор должен не допускать подобных вещей при генерации ассемблерного кода, или, по крайней мере, сообщать о них?

Нет, компилятор никак не может отследить такое. Для него это вполне допустимые инструкции. Проблема возникает уже при выполнеинии этих инструкций, в периферии. Например, чтение из несуществующего участка памяти. AVR молча проглатывал такое, возвращая какое-то значение. И это было трудно отследить. А тут для облегчения труда программистов придумали исключения. Очень удобно - накосячил -- вывалился в HardFault, сразу ясно, что что-то не так sm.gif
Цитата
Как часто на практике приходится сталкиваться с подобными вещами (проявлением исключений)?

Если писать аккуратно, то редко. Но не надо бояться исключений, это полезная штука.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sonycman
сообщение Dec 28 2010, 23:50
Сообщение #9


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(AHTOXA @ Dec 28 2010, 23:56) *
Нет, компилятор никак не может отследить такое. Для него это вполне допустимые инструкции.

Почему же не может? Разве много труда компилятору стоит, чтобы проверить, выровнен ли адрес для LDM?
Это если такая конструкция генерируется с языка Си, а не написана изначально на асме, конечно.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 29 2010, 00:29
Сообщение #10


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



А если адрес получается извне? Например, читается из порта?
А чтение несуществующего адреса?
Или вы имеете в виду, что компилятор должен перед каждым чтением вставлять проверку адреса на выравнивание? Я думаю, что такой компилятор не будет пользоваться популярностью sm.gif


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sonycman
сообщение Dec 29 2010, 02:53
Сообщение #11


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(AHTOXA @ Dec 29 2010, 08:29) *
А если адрес получается извне? Например, читается из порта?

А вы уверены, что в случае с неопределённым по выравниванию указателем компилятором будет сгенерирован код с использованием LDM?
Цитата
Или вы имеете в виду, что компилятор должен перед каждым чтением вставлять проверку адреса на выравнивание?

Весьма эффективные функции memcpy() именно так и делают.
Не вижу тут никакого криминала sm.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 29 2010, 03:40
Сообщение #12


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sonycman @ Dec 29 2010, 10:53) *
А вы уверены, что в случае с неопределённым по выравниванию указателем компилятором будет сгенерирован код с использованием LDM?

Без понятияsm.gif

Цитата
Весьма эффективные функции memcpy() именно так и делают.
Не вижу тут никакого криминала sm.gif

Так то функции, а не компилятор. Компилятор же своевольничать не должен.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sonycman
сообщение Dec 29 2010, 06:40
Сообщение #13


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



У меня была как то проблема с таким вылетом - в исходниках FatFs от Чена есть такая функция - mem_cpy().
Весьма вредная, оказывается, так как при установленном флаге WORD_ACCESS она будет производить копирование 32-ух битными словами, а не байтами, безо всякого внимания к выравниванию.
Естественно, это быстро приводит к исключению.

Дело в том, что большая часть команд Cortex-M3 допускает работу с невыровненными по границе слова данными.
Но только не LDM и несколько других.

А именно они генерируются при компиляции Ченовской mem_cpy с флагом WORD_ACCESS.

Не знаю, почему он вставил эту свою писульку, вместо стандартных библиотечных функций. sad.gif
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Dec 29 2010, 09:31
Сообщение #14


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(sonycman @ Dec 29 2010, 14:40) *
Не знаю, почему он вставил эту свою писульку, вместо стандартных библиотечных функций. sad.gif


Я видел кучу самодельных реализаций memcpy(). Раз люди пишут, значит есть причины. Думаю, что основных претензий к библиотечной memcpy() две: она очень большая, и она медленная на маленьких кусках данных. Оба недостатка - следствие огромной кучи начальных проверок в стремлении копировать максимальными блоками. Не всегда это всё нужно. Например, я копирую блоки максимум 20 байт. В этом случае тупое побайтовое(!) копирование может быть быстрее memcpy(). Или наоборот, блоки большие, но я, как программист, гарантирую, что они будут выровнены. Зачем мне тогда начальные проверки memcpy()?
(А теперь представьте, что всё, что делает memcpy(), делает сам компилятор, принудительно?! sm.gif )


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sonycman
сообщение Dec 29 2010, 11:58
Сообщение #15


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



Цитата(AHTOXA @ Dec 29 2010, 17:31) *
Я видел кучу самодельных реализаций memcpy(). Раз люди пишут, значит есть причины. Думаю, что основных претензий к библиотечной memcpy() две: она очень большая, и она медленная на маленьких кусках данных.

Хм, ну ради некоторой экономии места смысл есть, это да. Да и то только на "маленьких" контроллерах, и в случае, когда больше нигде в программе эта функция не используется.

А насчёт "огромной" преогромной кучи проверок не соглашусь. Несколько битовых проверок с регистрами много времени не займут.
В отличии от примитивного побайтового цикла с обращением к памяти.
wink.gif
Go to the top of the page
 
+Quote Post

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

 


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


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