Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 Обработка hard fault exception
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Serj78
Читаю документацию на ARM ( DDI0337e - Cortex™-M3 Revision: r1p1 Technical Reference Manual)

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

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

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

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

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

Как вообще используют систему исключений? У меня она нигде никак в явном виде не инициализируется , как узнать что исключение произошло?
Периодически читать статус регистр исключения? И если оно произошло, какие могут быть последствия?
Harvester
Исключение Hard Fault, также как сброс и NMI, является системным исключением с фиксированным приоритетом и разрешено всегда.
Данное исключение генерируется при появлении исключений Bus Fault, MemManage Fault, Usage Fault, если соответствующие исключения запрещены. Также Hard Fault может генерироваться при отказе шины во время выборки вектора из таблицы. Причина исключения Hard Fault - см. регистр HFSR (0xE000ED2C).
Примечание: Если очень нужно запретить HArd Fault, то можно установить регистр FAULTMASK - при этом разрешенным останется только NMI
zltigo
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(;; );
}


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

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


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

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

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

Недавно перешел с более простой архитектуры ( AVR) там, такого понятия нет, вот и спрашиваю....
Dron_Gus
Например, Вы можете попытаться обратиться или выполнить код из области памяти, которой не существует.
AHTOXA
Цитата(Serj78 @ Dec 28 2010, 20:14) *
Больше всего интересует, что я могу в программе написать такое, чтобы возникло это исключение?

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

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

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

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

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

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

Почему же не может? Разве много труда компилятору стоит, чтобы проверить, выровнен ли адрес для LDM?
Это если такая конструкция генерируется с языка Си, а не написана изначально на асме, конечно.
AHTOXA
А если адрес получается извне? Например, читается из порта?
А чтение несуществующего адреса?
Или вы имеете в виду, что компилятор должен перед каждым чтением вставлять проверку адреса на выравнивание? Я думаю, что такой компилятор не будет пользоваться популярностью sm.gif
sonycman
Цитата(AHTOXA @ Dec 29 2010, 08:29) *
А если адрес получается извне? Например, читается из порта?

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

Весьма эффективные функции memcpy() именно так и делают.
Не вижу тут никакого криминала sm.gif
AHTOXA
Цитата(sonycman @ Dec 29 2010, 10:53) *
А вы уверены, что в случае с неопределённым по выравниванию указателем компилятором будет сгенерирован код с использованием LDM?

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

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

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

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

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

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


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

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

А насчёт "огромной" преогромной кучи проверок не соглашусь. Несколько битовых проверок с регистрами много времени не займут.
В отличии от примитивного побайтового цикла с обращением к памяти.
wink.gif
AHTOXA
Цитата(sonycman @ Dec 29 2010, 19:58) *
А насчёт "огромной" преогромной кучи проверок не соглашусь. Несколько битовых проверок с регистрами много времени не займут.
В отличии от примитивного побайтового цикла с обращением к памяти.
wink.gif

Ха! Вот вам примерчик "нескольких регистровых проверок":
CODE
void * memcpy(void * __restrict__ dest, const void * __restrict__ src, size_t n)
{
int adjust, delta;
unsigned int soffset1, doffset1, doffset2;
vec_uchar16 *vSrc, *vDst;
vec_uchar16 sdata1, sdata2, sdata, ddata, shuffle;
vec_uchar16 mask, mask1, mask2, mask3;

vSrc = (vec_uchar16 *)(src);
vDst = (vec_uchar16 *)(dest);

/* Handle any leading destination partial quadwords as
* well a very short copy (ie, such that the n characters
* all reside in a single (destination) quadword.
*/
soffset1 = (unsigned int)(src) & 15;
doffset1 = (unsigned int)(dest) & 15;
doffset2 = ((unsigned int)(dest) + n) & 15;

/* Compute a shuffle pattern used to align the source string
* with the alignment of the destination string.
*/

adjust = (int)spu_extract(spu_cmpgt(spu_promote(doffset1, 0), spu_promote(soffset1, 0)), 0);
delta = (int)soffset1 - (int)doffset1;
delta += adjust & 16;

shuffle = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char)delta),
VEC_LITERAL(vec_uint4, 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F));

vSrc += adjust;

sdata1 = *vSrc++;
sdata2 = *vSrc++;

ddata = *vDst;
sdata = spu_shuffle(sdata1, sdata2, shuffle);

/* Construct a series of masks used to data insert. The masks
* contain 0 when the destination word is unchanged, 1 when it
* must be replaced by source bytes.
*
* mask1 = mask for leading unchanged bytes
* mask2 = mask for trailing unchange bytes
* mask3 = mask indicating the more than one qword is being changed.
*/
mask = spu_splats((unsigned char)-1);
mask1 = spu_rlmaskqwbyte(mask, -doffset1);
mask2 = spu_slqwbyte(mask, 16-doffset2);
mask3 = (vec_uchar16)spu_cmpgt(spu_splats((unsigned int)(doffset1 + n)), 15);

*vDst++ = spu_sel(ddata, sdata, spu_and(mask1, spu_or(mask2, mask3)));

n += doffset1;

/* Handle complete destination quadwords
*/
while (n > 31) {
sdata1 = sdata2;
sdata2 = *vSrc++;
*vDst++ = spu_shuffle(sdata1, sdata2, shuffle);
n -= 16;
}

/* Handle any trailing partial (destination) quadwords
*/
mask = spu_and((vec_uchar16)spu_cmpgt(spu_splats((unsigned int)n), 16), mask2);
*vDst = spu_sel(*vDst, spu_shuffle(sdata2, *vSrc, shuffle), mask);

return (dest);
}


sm.gif
sonycman
Цитата(AHTOXA @ Dec 29 2010, 21:11) *
Ха! Вот вам примерчик "нескольких регистровых проверок":

И откуда вы эту непотребность вытащили?
Поди, гнусь?
biggrin.gif
Вот эта строчка
Код
    memcpy((void*)ptr, (const void*)(ptr+20), 20);

сгенерилась вот в такой код под IAR:
CODE
__aeabi_memcpy(_D, _S, _N);
0x327a: 0x2214 MOVS r2, #20 ; 0x14
0x327c: 0xf100 0x0114 ADD.W r1, r0, #20 ; 0x14
0x3280: 0xf003 0xf924 BL __aeabi_memcpy ; 0x64cc
........
__aeabi_memcpy:
0x64cc: 0xb34a CBZ r2, 0x6522
0x64ce: 0x078b LSLS r3, r1, #30
0x64d0: 0xd007 BEQ.N 0x64e2
0x64d2: 0xf811 0x3b01 LDRB.W r3, [r1], #0x1
0x64d6: 0xf800 0x3b01 STRB.W r3, [r0], #0x1
0x64da: 0x1e52 SUBS r2, r2, #1
0x64dc: 0xd021 BEQ.N 0x6522
0x64de: 0x078b LSLS r3, r1, #30
0x64e0: 0xd1f7 BNE.N 0x64d2
0x64e2: 0x0783 LSLS r3, r0, #30
0x64e4: 0xd11e BNE.N 0x6524
__aeabi_memcpy4:
__aeabi_memcpy8:
0x64e6: 0x3a10 SUBS r2, r2, #16 ; 0x10
0x64e8: 0xd307 BCC.N 0x64fa
0x64ea: 0xb430 PUSH {r4, r5}
0x64ec: 0xe8b1 0x1038 LDM r1!, {r3-r5, r12}
0x64f0: 0x3a10 SUBS r2, r2, #16 ; 0x10
0x64f2: 0xe8a0 0x1038 STM r0!, {r3-r5, r12}
0x64f6: 0xd2f9 BCS.N 0x64ec
0x64f8: 0xbc30 POP {r4, r5}
0x64fa: 0x0753 LSLS r3, r2, #29
0x64fc: 0xbf24 ITT CS
0x64fe: 0xe8b1 0x1008 LDMCS r1!, {r3, r12}
0x6502: 0xe8a0 0x1008 STMCS r0!, {r3, r12}
0x6506: 0xbf44 ITT MI
0x6508: 0xf851 0x3b04 LDRMI.W r3, [r1], #0x4
0x650c: 0xf840 0x3b04 STRMI.W r3, [r0], #0x4
0x6510: 0x07d2 LSLS r2, r2, #31
0x6512: 0xbf24 ITT CS
0x6514: 0xf831 0x2b02 LDRHCS.W r2, [r1], #0x2
0x6518: 0xf820 0x2b02 STRHCS.W r2, [r0], #0x2
0x651c: 0xbf44 ITT MI
0x651e: 0x780b LDRBMI r3, [r1]
0x6520: 0x7003 STRBMI r3, [r0]
0x6522: 0x4770 BX lr
0x6524: 0x3a08 SUBS r2, r2, #8
0x6526: 0xd307 BCC.N 0x6538
0x6528: 0xe8b1 0x1008 LDM r1!, {r3, r12}
0x652c: 0x3a08 SUBS r2, r2, #8
0x652e: 0xf840 0x3b04 STR.W r3, [r0], #0x4
0x6532: 0xf840 0xcb04 STR.W r12, [r0], #0x4
0x6536: 0xd2f7 BCS.N 0x6528
0x6538: 0x0753 LSLS r3, r2, #29
0x653a: 0xe7e4 B.N 0x6506

Оверхед, конечно, есть, но не бог весть какой значительный, в уплату универсальности.
ЗЫ: какой смысл смотреть исходник, когда подобные библиотечные функции жёстко "затачиваются" на ассемблере?
laughing.gif
pan_oleg
День добрый.
Нужна помощ.
Код для STM32F101BT6 написаный на Си под IAR через определеное время работы по непонятным причинам вылетает в HardFaultException(void). Из флагов выставелся FORCED в HFSR регистре, и IBUSERR в регистре CFSR. Все что в доке нашел, что проблема с шиной. Но какая? Подскажите, как найти где в коде я накосячил. Какие регистры смотреть, что анализировать?
Атмег
Цитата(pan_oleg @ Jan 5 2011, 14:31) *
День добрый.
Нужна помощ.
Код для STM32F101BT6 написаный на Си под IAR через определеное время работы по непонятным причинам вылетает в HardFaultException(void). Из флагов выставелся FORCED в HFSR регистре, и IBUSERR в регистре CFSR. Все что в доке нашел, что проблема с шиной. Но какая? Подскажите, как найти где в коде я накосячил. Какие регистры смотреть, что анализировать?


Я использую прерывание по таймеру и HSMCI, периодически вылетаю по HardFault, выставлен FORCED, в LR лежит 0xFFFFFFF9. При изменениях в программе то все работает нормально, то вылетает, такое впечатление, что изменение числа инструкций смещает по времени прерывания, и, если они накладываются, возникает исключение.
Правильно я понимаю, что вылет происходит при выходе из прерывания?
KnightIgor
Цитата(Атмег @ Apr 5 2011, 18:48) *
При изменениях в программе то все работает нормально, то вылетает, такое впечатление, что изменение числа инструкций смещает по времени прерывания, и, если они накладываются, возникает исключение.
Правильно я понимаю, что вылет происходит при выходе из прерывания?


Это типичное поведение, когда забывают проинициализировать какие-либо переменные (указатели или счетчики). Может быть у Вас выключена в компиляторе начальная прочистка/инициализация памяти для переменных?
Атмег
Цитата(KnightIgor @ Apr 6 2011, 15:32) *
Это типичное поведение, когда забывают проинициализировать какие-либо переменные (указатели или счетчики). Может быть у Вас выключена в компиляторе начальная прочистка/инициализация памяти для переменных?


я все переменные инициализирую при объявлении, привычка такая. на счет библиотек - не знаю, я пользовался атмеловским драйвером HSMCI. с ним изначально проблемы были, потом работал нормально, я его больше не трогал.

может есть какие то особенности работы с прерываниями у кортексов? до них писал под арм9, там все работало нормально.
Атмег
Кажется, причины ясны, проблема не в моем коде. У меня чип ATSAM3S4C ревизии ES.
Подсунули Engineering Samples, не предупредили даже, а я не заметил...
igorsk
Цитата(sonycman @ Dec 29 2010, 16:37) *
И откуда вы эту непотребность вытащили?

Это цветочки. Вот как выглядит memcpy у айфона (ARMv7).

(код тут).
aaarrr
Цитата(Атмег @ Apr 7 2011, 21:45) *
Кажется, причины ясны, проблема не в моем коде. У меня чип ATSAM3S4C ревизии ES.
Подсунули Engineering Samples, не предупредили даже, а я не заметил...

Можно подумать, что ES какие-то совсем недоделанные. На них есть своя еррата, ничего страшного не содержащая.
А описанные вами проблемы могут возникать в нескольких случаях:
- если неправильно настроена PLL (например, значение входной частоты ниже минимальной)
- если регистр EEFC_FMR записывается при выполнении программы из флеш
- таки да, из-за ошибки в коде
Атмег
Цитата(aaarrr @ Apr 8 2011, 01:11) *
Можно подумать, что ES какие-то совсем недоделанные. На них есть своя еррата, ничего страшного не содержащая.
А описанные вами проблемы могут возникать в нескольких случаях:
- если неправильно настроена PLL (например, значение входной частоты ниже минимальной)
- если регистр EEFC_FMR записывается при выполнении программы из флеш
- таки да, из-за ошибки в коде


Я не склонен валить все косяки на производителя, честно ковырялся в своем коде, но увиденное вчера меня добило окончательно: еще до разрешения прерываний просто шагаю по коду, вхожу в одну функцию, выхожу, все норм, вхожу в следующую - исключение с флагом IMPRECISERR (ошибка на шине, но адрес не определен?). При том что данный кусок кода (библиотечный) вполне успешно работал и работает при изменениях в любом другом месте программы. Т.е. от перегруппировки памяти периодически возникает какой то неработоспособный код.

Правда тут более странный момент заметил, один и тот же код на одной плате может вызвать HardFault, а на другой нет. Внешнюю шину не использую. PLL настроена правильно. Были мысли насчет нестабильности частоты, но причины, недомытая плата? Тогда почему только при определенном коде?

Не настаиваю, что причина в ES, буду рад услышать другое объяснение!
aaarrr
Цитата(Атмег @ Apr 8 2011, 11:53) *
PLL настроена правильно.

А FMR?

Цитата(Атмег @ Apr 8 2011, 11:53) *
Не настаиваю, что причина в ES, буду рад услышать другое объяснение!

Бывает и совсем наоборот.
Атмег
Цитата(aaarrr @ Apr 8 2011, 11:49) *
А FMR?


в EEFC_FMR у меня 2 цикла на обращение, но MCK на порядок больше, чем 5 MHz, указанные в еррате.
код из флеши исполняется, но к EEFC_FMR обращение единственный раз в стартапе.
aaarrr
Цитата(Атмег @ Apr 8 2011, 13:48) *
код из флеши исполняется, но к EEFC_FMR обращение единственный раз в стартапе.

Как показывает практика, этого достаточно для появления сбоя совсем в другом месте.
Атмег
Это я взял как есть из примера. Как будет очередной сбой - проверю, это ли явилось причиной.
Запись в регистр str r2,[r1] Мне казалось, проблем здесь не возникает, я же не пишу/читаю из флеши в момент записи?
aaarrr
Цитата(Атмег @ Apr 8 2011, 14:23) *
Запись в регистр str r2,[r1] Мне казалось, проблем здесь не возникает, я же не пишу/читаю из флеши в момент записи?

В том-то и дело, что читает не ядро непосредственно, а контроллер флеш в свои внутренние буферы. И узнать, чем он занимается в данный момент, не представляется возможным.
Атмег
Цитата(aaarrr @ Apr 8 2011, 14:28) *
В том-то и дело, что читает не ядро непосредственно, а контроллер флеш в свои внутренние буферы. И узнать, чем он занимается в данный момент, не представляется возможным.


Ну да, верно. Строка-то, по сути, бессмысленная. Код исполняется из флеши, значит EEFC уже инициализирован загрузчиком.
aaarrr
Если программа стартует из флеш, то загрузчик не задействуется.
Атмег
Цитата(aaarrr @ Apr 8 2011, 15:06) *
Если программа стартует из флеш, то загрузчик не задействуется.


Имел в виду rom boot. А что инициализирует этот регистр? При загрузке из флеши он проинициализирован.
aaarrr
Цитата(Атмег @ Apr 8 2011, 19:39) *
Имел в виду rom boot.

Процессор всегда стартует с нулевого адреса. Там может быть отмаплена флеш, если GNPVM 1 установлен, или ROM, если сброшен. В первом случае никакого лишнего кода не выполняется.

Цитата(Атмег @ Apr 8 2011, 19:39) *
А что инициализирует этот регистр? При загрузке из флеши он проинициализирован.

В документации прописано значение по сбросу - 0x0. У вас оно отличается? Если да, то как смотрите?
Атмег
Цитата(aaarrr @ Apr 8 2011, 20:13) *
Процессор всегда стартует с нулевого адреса. Там может быть отмаплена флеш, если GNPVM 1 установлен, или ROM, если сброшен. В первом случае никакого лишнего кода не выполняется.


В документации прописано значение по сбросу - 0x0. У вас оно отличается? Если да, то как смотрите?


Да, правда, загрузчик то непричем.

Отличается, смотрю отладчиком, хотите сказать, он и инициализирует?
aaarrr
Цитата(Атмег @ Apr 8 2011, 21:28) *
Отличается, смотрю отладчиком, хотите сказать, он и инициализирует?

Скорее всего так и есть, посмотрите его скрипты. Я, конечно, не смотрел дефолтное значение, но оснований не доверять даташиту нет.
Атмег
Да, вы были правы, действительно дело оказалось EEFC_FMR, но не в самом факте записи в регистр*, а в том что писалось туда 2 цикла, а при заданной частоте должно быть 3. Вроде пока сбоев не наблюдаю, видимо, в этом и было дело. Но Атмел реабилитирован лишь частично, это все из их стартапа пошло, второй раз уже с этим сталкиваюсь именно у Атмела (в прошлый раз была ошибка примере инициализации SDRAM).
Именно так было в стартапе, частота выставлена 48 МГц, а в EEFC_FMR - 0х1, то есть два цикла.

*Изначально в регистре 0х0, то есть 1 цикл на чтение.
aaarrr
Цитата(Атмег @ Apr 13 2011, 02:02) *
Но Атмел реабилитирован лишь частично, это все из их стартапа пошло, второй раз уже с этим сталкиваюсь именно у Атмела (в прошлый раз была ошибка примере инициализации SDRAM).

Я их код перестал смотреть со времен M40800, ибо просто мусор. Поэтому и претензий не имею sm.gif
Haamu
Цитата(pan_oleg @ Jan 5 2011, 15:31) *
Код для STM32F101BT6 написаный на Си под IAR через определеное время работы по непонятным причинам вылетает в HardFaultException(void). Из флагов выставелся FORCED в HFSR регистре, и IBUSERR в регистре CFSR. Все что в доке нашел, что проблема с шиной. Но какая? Подскажите, как найти где в коде я накосячил. Какие регистры смотреть, что анализировать?

Аналогичная ситуация, разве что контроллер STM32F407. Подскажите, в чем проблемма?
Сергей Борщ
Цитата(Haamu @ Apr 11 2014, 04:30) *
Подскажите, в чем проблемма?
Поднимите глаза и перечитайте сообщение 37. У Атмег проблема была в недостаточном количестве тактов ожидания в контроллере флеша. Ваш же код на отладочной плате работает, значит 100% проблема в вашей аппаратной части - разводке и схеме.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.