|
STM32 Обработка hard fault exception, Как правильно с ним работать |
|
|
|
 |
Ответов
(15 - 29)
|
Dec 29 2010, 13:11
|

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

|
Цитата(sonycman @ Dec 29 2010, 19:58)  А насчёт "огромной" преогромной кучи проверок не соглашусь. Несколько битовых проверок с регистрами много времени не займут. В отличии от примитивного побайтового цикла с обращением к памяти.  Ха! Вот вам примерчик "нескольких регистровых проверок": 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); }
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Dec 29 2010, 14:37
|

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

|
Цитата(AHTOXA @ Dec 29 2010, 21:11)  Ха! Вот вам примерчик "нескольких регистровых проверок": И откуда вы эту непотребность вытащили? Поди, гнусь? Вот эта строчка Код 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 Оверхед, конечно, есть, но не бог весть какой значительный, в уплату универсальности. ЗЫ: какой смысл смотреть исходник, когда подобные библиотечные функции жёстко "затачиваются" на ассемблере?
|
|
|
|
|
Apr 5 2011, 16:48
|
Частый гость
 
Группа: Участник
Сообщений: 149
Регистрация: 17-05-07
Пользователь №: 27 787

|
Цитата(pan_oleg @ Jan 5 2011, 14:31)  День добрый. Нужна помощ. Код для STM32F101BT6 написаный на Си под IAR через определеное время работы по непонятным причинам вылетает в HardFaultException(void). Из флагов выставелся FORCED в HFSR регистре, и IBUSERR в регистре CFSR. Все что в доке нашел, что проблема с шиной. Но какая? Подскажите, как найти где в коде я накосячил. Какие регистры смотреть, что анализировать? Я использую прерывание по таймеру и HSMCI, периодически вылетаю по HardFault, выставлен FORCED, в LR лежит 0xFFFFFFF9. При изменениях в программе то все работает нормально, то вылетает, такое впечатление, что изменение числа инструкций смещает по времени прерывания, и, если они накладываются, возникает исключение. Правильно я понимаю, что вылет происходит при выходе из прерывания?
|
|
|
|
|
Apr 6 2011, 12:32
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Атмег @ Apr 5 2011, 18:48)  При изменениях в программе то все работает нормально, то вылетает, такое впечатление, что изменение числа инструкций смещает по времени прерывания, и, если они накладываются, возникает исключение. Правильно я понимаю, что вылет происходит при выходе из прерывания? Это типичное поведение, когда забывают проинициализировать какие-либо переменные (указатели или счетчики). Может быть у Вас выключена в компиляторе начальная прочистка/инициализация памяти для переменных?
|
|
|
|
|
Apr 6 2011, 17:10
|
Частый гость
 
Группа: Участник
Сообщений: 149
Регистрация: 17-05-07
Пользователь №: 27 787

|
Цитата(KnightIgor @ Apr 6 2011, 15:32)  Это типичное поведение, когда забывают проинициализировать какие-либо переменные (указатели или счетчики). Может быть у Вас выключена в компиляторе начальная прочистка/инициализация памяти для переменных? я все переменные инициализирую при объявлении, привычка такая. на счет библиотек - не знаю, я пользовался атмеловским драйвером HSMCI. с ним изначально проблемы были, потом работал нормально, я его больше не трогал. может есть какие то особенности работы с прерываниями у кортексов? до них писал под арм9, там все работало нормально.
|
|
|
|
|
Apr 7 2011, 21:45
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 22-03-10
Пользователь №: 56 131

|
Цитата(sonycman @ Dec 29 2010, 16:37)  И откуда вы эту непотребность вытащили? Это цветочки. Вот как выглядит memcpy у айфона (ARMv7).  (код тут).
|
|
|
|
|
Apr 7 2011, 22:11
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Атмег @ Apr 7 2011, 21:45)  Кажется, причины ясны, проблема не в моем коде. У меня чип ATSAM3S4C ревизии ES. Подсунули Engineering Samples, не предупредили даже, а я не заметил... Можно подумать, что ES какие-то совсем недоделанные. На них есть своя еррата, ничего страшного не содержащая. А описанные вами проблемы могут возникать в нескольких случаях: - если неправильно настроена PLL (например, значение входной частоты ниже минимальной) - если регистр EEFC_FMR записывается при выполнении программы из флеш - таки да, из-за ошибки в коде
|
|
|
|
|
Apr 8 2011, 07:53
|
Частый гость
 
Группа: Участник
Сообщений: 149
Регистрация: 17-05-07
Пользователь №: 27 787

|
Цитата(aaarrr @ Apr 8 2011, 01:11)  Можно подумать, что ES какие-то совсем недоделанные. На них есть своя еррата, ничего страшного не содержащая. А описанные вами проблемы могут возникать в нескольких случаях: - если неправильно настроена PLL (например, значение входной частоты ниже минимальной) - если регистр EEFC_FMR записывается при выполнении программы из флеш - таки да, из-за ошибки в коде Я не склонен валить все косяки на производителя, честно ковырялся в своем коде, но увиденное вчера меня добило окончательно: еще до разрешения прерываний просто шагаю по коду, вхожу в одну функцию, выхожу, все норм, вхожу в следующую - исключение с флагом IMPRECISERR (ошибка на шине, но адрес не определен?). При том что данный кусок кода (библиотечный) вполне успешно работал и работает при изменениях в любом другом месте программы. Т.е. от перегруппировки памяти периодически возникает какой то неработоспособный код. Правда тут более странный момент заметил, один и тот же код на одной плате может вызвать HardFault, а на другой нет. Внешнюю шину не использую. PLL настроена правильно. Были мысли насчет нестабильности частоты, но причины, недомытая плата? Тогда почему только при определенном коде? Не настаиваю, что причина в ES, буду рад услышать другое объяснение!
|
|
|
|
|
Apr 8 2011, 08:49
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Атмег @ Apr 8 2011, 11:53)  PLL настроена правильно. А FMR? Цитата(Атмег @ Apr 8 2011, 11:53)  Не настаиваю, что причина в ES, буду рад услышать другое объяснение! Бывает и совсем наоборот.
|
|
|
|
|
Apr 8 2011, 09:48
|
Частый гость
 
Группа: Участник
Сообщений: 149
Регистрация: 17-05-07
Пользователь №: 27 787

|
Цитата(aaarrr @ Apr 8 2011, 11:49)  А FMR? в EEFC_FMR у меня 2 цикла на обращение, но MCK на порядок больше, чем 5 MHz, указанные в еррате. код из флеши исполняется, но к EEFC_FMR обращение единственный раз в стартапе.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|