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

 
 
5 страниц V  < 1 2 3 4 > »   
Reply to this topicStart new topic
> Прошу помощи с STM32F051, Периодическое сваливание в HardFault
nanorobot
сообщение Aug 9 2014, 19:21
Сообщение #16


Местный
***

Группа: Участник
Сообщений: 244
Регистрация: 29-02-08
Пользователь №: 35 503



Цитата(jcxz @ Aug 10 2014, 00:50) *
Тогда эта модификация стека произошла в вашем обработчике HardFault.
Вы же вроде пытаетесь привести результат стекинга на входе в HardFault?
Вот как раз такого результата быть не может, как я вам выше уже показал.
Скорей всего Вы неправильно определили положение верхушки стека прерванной программы.


Осознавая недостаток собственной компетенции обработчик взял из Definitive Guide

CODE
// Hard Fault handler in C, with stack frame location and LR value
// extracted from the assembly wrapper as input parameters
void HardFault_Handler(unsigned int * hardfault_args, unsigned lr_value)
{
static volatile unsigned int stacked_r0;
static volatile unsigned int stacked_r1;
static volatile unsigned int stacked_r2;
static volatile unsigned int stacked_r3;
static volatile unsigned int stacked_r12;
static volatile unsigned int stacked_lr;
static volatile unsigned int stacked_pc;
static volatile unsigned int stacked_psr;
stacked_r0 = ((unsigned long) hardfault_args[0]);
stacked_r1 = ((unsigned long) hardfault_args[1]);
stacked_r2 = ((unsigned long) hardfault_args[2]);
stacked_r3 = ((unsigned long) hardfault_args[3]);
stacked_r12 = ((unsigned long) hardfault_args[4]);
stacked_lr = ((unsigned long) hardfault_args[5]);
stacked_pc = ((unsigned long) hardfault_args[6]);
stacked_psr = ((unsigned long) hardfault_args[7]);
printf ("[Hard fault handler]\n");
printf ("R0 = %x\n", stacked_r0);
printf ("R1 = %x\n", stacked_r1);
printf ("R2 = %x\n", stacked_r2);
printf ("R3 = %x\n", stacked_r3);
printf ("R12 = %x\n", stacked_r12);
printf ("Stacked LR = %x\n", stacked_lr);
printf ("Stacked PC = %x\n", stacked_pc);
printf ("Stacked PSR = %x\n", stacked_psr);
printf ("Current LR = %x\n", lr_value);
while(1); // endless loop
Go to the top of the page
 
+Quote Post
nanorobot
сообщение Aug 9 2014, 20:47
Сообщение #17


Местный
***

Группа: Участник
Сообщений: 244
Регистрация: 29-02-08
Пользователь №: 35 503



Со стеком разобрался. Нашел точку в которой происходит HardFault.
Точка - chSemSignal(&semAdc) - использование сервиса RTOS Nil(ChibiOs) от Jiovanni di Sirio.
В чем там косяк - только предстоит выяснить.

Всем спасибо за помощь.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Aug 9 2014, 20:50
Сообщение #18


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(nanorobot @ Aug 9 2014, 22:21) *
Осознавая недостаток собственной компетенции обработчик взял из Definitive Guide

Вы упустили выбор MSP / PSP, посмотрите в книге перед тем обработчиком, который показали.
О, так у вас ОС есть. А с ней оба регистра указателя стека используются.
Go to the top of the page
 
+Quote Post
nanorobot
сообщение Aug 9 2014, 21:03
Сообщение #19


Местный
***

Группа: Участник
Сообщений: 244
Регистрация: 29-02-08
Пользователь №: 35 503



Thank. День прожит не зря. ))
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Aug 10 2014, 12:21
Сообщение #20


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(nanorobot @ Aug 9 2014, 22:47) *
Точка - chSemSignal(&semAdc) - использование сервиса RTOS Nil(ChibiOs) от Jiovanni di Sirio.

Гляньте, выровнена ли переменная/структура (и ее поля) semAdc: для M0 это критично. Если M3 скушает структуру типа:
__packed {
U8 a;
void *p;
},
и не подавится (то есть, когда указатель p явно по нечетному адресу), то в M0 попытка обратиться через *p вызывает hard fault. На это я наткнулся, когда переносил библиотеку с M3 на M0. Т.к. структура у меня должна была оставаться __packed, пришлось перетасовать поля, чтобы указатели были по четным адресам.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 10 2014, 14:57
Сообщение #21


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(KnightIgor @ Aug 10 2014, 15:21) *
Т.к. структура у меня должна была оставаться __packed, пришлось перетасовать поля, чтобы указатели были по четным адресам.
Если структура __packed, то выравнивание полей значения не имеет - компилятор собирает каждое поле побайтово.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
nanorobot
сообщение Aug 10 2014, 15:14
Сообщение #22


Местный
***

Группа: Участник
Сообщений: 244
Регистрация: 29-02-08
Пользователь №: 35 503



Цитата(KnightIgor @ Aug 10 2014, 18:21) *
Гляньте, выровнена ли переменная/структура (и ее поля) semAdc: для M0 это критично. Если M3 скушает структуру типа:
__packed {
U8 a;
void *p;
},
и не подавится (то есть, когда указатель p явно по нечетному адресу), то в M0 попытка обратиться через *p вызывает hard fault. На это я наткнулся, когда переносил библиотеку с M3 на M0. Т.к. структура у меня должна была оставаться __packed, пришлось перетасовать поля, чтобы указатели были по четным адресам.



данная инструкция выполняется сотни раз в секунду а HF случается раз в часы. т.е. дело видимо не в не в выравнивании, а в стечении неких обстоятельств. Проблему решил, правда, не "в лоб" а обходным маневром - отказался от использования семафора, и вот уже более полусуток проблема не проявляет себя. Хотя желание разобраться в сути проблемы до конца есть.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Aug 10 2014, 16:49
Сообщение #23


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Сергей Борщ @ Aug 10 2014, 16:57) *
Если структура __packed, то выравнивание полей значения не имеет - компилятор собирает каждое поле побайтово.

У меня указатель был расположен после U8. В то время как вся структура была размещена с выравниванием 4, поле указателя имело адрес 4*n+1. Инструкция LDR R0, [Rx,#5] вешала систему. Фактически структура была что-то типа:
void *
U8
void *
..
Я сделал
void *
void *
U8
..
после чего все заработало.

P.S. KEIL 5.x

Сообщение отредактировал KnightIgor - Aug 10 2014, 16:50
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 11 2014, 08:43
Сообщение #24


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(KnightIgor @ Aug 10 2014, 19:49) *
У меня указатель был расположен после U8. В то время как вся структура была размещена с выравниванием 4, поле указателя имело адрес 4*n+1. Инструкция LDR R0, [Rx,#5] вешала систему.
Полагаю, вы чего-то недоговариваете. Если структура была обявлена без квалификатора packed, то компиляор был обязан выровнять указатель на его размер, т.е. на 4 байта, пропустив перед ним необходимое количество байтов. Если структура объявлена с packed, то компилятор пропускать байты не будет, но если процессор не умеет невыровненный доступ (как в случае с Cortex-M0) - компилятор обязан каждое многобайтовое поле считать побайтно и собрать целиком уже в регистрах. То есть он не имел права использовать в этом месте LDR R0, [Rx,#5]. Значит это либо ошибка компилятора (что маловероятно), либо вы использовали явное приведение типа, приведя (void *) к чему-то другому, но забыв packed в приводимом типе.

Попробуйте воспроизвести ситуацию еще раз, попытаемся докопаться до причины.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 11 2014, 09:11
Сообщение #25


Гуру
******

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



Цитата(Сергей Борщ @ Aug 11 2014, 14:43) *
либо вы использовали явное приведение типа, приведя (void *) к чему-то другому, но забыв packed в приводимом типе.

Скорее всего именно так и было (приведение указателя на невыровненные данные к указателю на непакованный тип и разыменование его) rolleyes.gif
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Aug 11 2014, 09:59
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



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

я вот только такой пример знаю

Код
char Array[8];
int *P = (int *)&Array[2];
*p = 10;


в некоторых процах такой маневр приводил к замене не 2, 3, 4, 5 байтов, а все равно к замене 0, 1, 2, 3. Допускаю что такой же ход в кортексе М0 должен взывать падение, я прав?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Aug 11 2014, 10:11
Сообщение #27


Гуру
******

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



Не правы.
Здесь совсем о другом разговор. Почитайте топик внимательнее. Здесь разговор о доступе к пакованным данным.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Aug 12 2014, 10:08
Сообщение #28


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Сергей Борщ @ Aug 11 2014, 10:43) *
Полагаю, вы чего-то недоговариваете.
Попробуйте воспроизвести ситуацию еще раз, попытаемся докопаться до причины.

Я попытался откатить код. Слетает. Конечно, не в момент заполнения структуры как таковой: в некую процедуру передается указатель на поле структуры типа (void *), а внутри есть инструкция:
LDR R0, [R0, #0], при этом R0 = 0x20000035, т.к. R0 это и есть входной параметр процедуры и указывает на поле типа (void *), которая размещена после поля U8, почему и такой нечетный адрес. Эта инструкция загрузки с нечетного адреса и вызывает исключение в -M0, в то время как -M3 все кушает без проблем.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 12 2014, 11:39
Сообщение #29


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(KnightIgor @ Aug 12 2014, 13:08) *
в некую процедуру передается указатель на поле структуры типа (void *)
Так вот это оно и есть. Против лома компилятор бессилен. Попробуйте передавать указатель типа (void * __packed), если компилятор такое позволяет.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Aug 12 2014, 12:33
Сообщение #30


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Сергей Борщ @ Aug 12 2014, 13:39) *
Так вот это оно и есть. Против лома компилятор бессилен. Попробуйте передавать указатель типа (void * __packed), если компилятор такое позволяет.

Я переразместил поля структуры, чтобы было выровнено. Была такая возможность.
Конечно, у компилятора против лома нет приема, но и передать в процедуру в качестве параметра поле структуры тоже легитимно. Надеюсь, что для топикстартера описаное мной поведение может помочь найти подобные навороты.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 19th July 2025 - 20:06
Рейтинг@Mail.ru


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