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

 
 
5 страниц V  < 1 2 3 4 5 >  
Reply to this topicStart new topic
> Прошу помощи с STM32F051, Периодическое сваливание в HardFault
Сергей Борщ
сообщение Aug 12 2014, 17:39
Сообщение #31


Гуру
******

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



Цитата(KnightIgor @ Aug 12 2014, 15:33) *
но и передать в процедуру в качестве параметра поле структуры тоже легитимно.
Передавать содержимое поля - легитимно. Передавать указатель на поле (указатель на __packed 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
MiklPolikov
сообщение Aug 17 2014, 11:18
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Очень интересная тема !
Подскажите, нет ли в интернете какой-нибудь статьи, где разжёваны все отладочные возможности, которые есть после попадания в Hardfault ?

И ещё вопрос .
Вот тут, что именно произойдёт неправильно?
Цитата(KnightIgor @ Aug 10 2014, 16:21) *
__packed {
U8 a;
void *p;
},
, то в M0 попытка обратиться через *p вызывает hard fault.

Я верно понимаю, что не получится прочитать из памяти 32х битную переменную, не выровненную в памяти на 32 бита ?
То есть, ядре М0 вот в этом случае значение b будет всё время некорректным ?
__packed {
U8 a;
U32 b;
},


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 17 2014, 11:45
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(MiklPolikov @ Aug 17 2014, 15:18) *
Я верно понимаю, что не получится прочитать из памяти 32х битную переменную, не выровненную в памяти на 32 бита ?

Почему же. Можно, только компилятор должен превратить обращение к невыровненным данным к нескольким обращениям к выровненным.
CM-3 могло делать это налету - HF не случался, но возникали тормоза.
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Aug 17 2014, 11:54
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(adnega @ Aug 17 2014, 15:45) *
Почему же. Можно, только компилятор должен превратить обращение к невыровненным данным к нескольким обращениям к выровненным.
CM-3 могло делать это налету - HF не случался, но возникали тормоза.

А почему компилятор не сможет это сделать, если невыровненное поле это указатель void *p; , как в примере выше ?


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 17 2014, 13:46
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(MiklPolikov @ Aug 17 2014, 15:54) *
А почему компилятор не сможет это сделать, если невыровненное поле это указатель void *p; , как в примере выше ?

void *p он обработает без ошибок и HF. Но если p будет указывать на невыровненные данные и будет обращение к этим данным, то в этот момент возникнет HF.
Как заставить обработать эту ситуацию? Не знаю, я забочусь, чтоб p всегда указывал на выровненные данные.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Aug 17 2014, 14:07
Сообщение #36


Гуру
******

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



ну типа

Код
char Array[10];
int *p = (int *)&Array[2];
*p = 10; //пипец %)


но при этом к полям пакованной структуры компилятор будет обращаться правильно, понимая что они могут быть не выровнены. Но передав это поле в функцию просто указателем будет опять обломс....
Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 17 2014, 14:36
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Golikov A. @ Aug 17 2014, 18:07) *
ну типа

Код
char Array[10];
int *p = (int *)&Array[2];
*p = 10; //пипец %)


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

Вы же согласитесь, что выстрел в ногу произошел во второй строчке кода?
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Aug 17 2014, 17:11
Сообщение #38


Гуру
******

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



это же условно...

может же быть входной байтовый буфер через который идет структура, который при декодировании вот так сделает. Ну или прям стандарт, протокол вида:
преамбула - байт, код команды - байт, данные - 32 бита, как раз приводит к таким строчкам...
Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 17 2014, 20:45
Сообщение #39


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Golikov A. @ Aug 17 2014, 21:11) *
это же условно...

может же быть входной байтовый буфер через который идет структура, который при декодировании вот так сделает. Ну или прям стандарт, протокол вида:
преамбула - байт, код команды - байт, данные - 32 бита, как раз приводит к таким строчкам...

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

CODE
typedef struct s_test
{
DWORD dw1;
BYTE b1;
BYTE b2;
DWORD dw2;
} __attribute((packed)) s_test;

BYTE b_test[10];

void f_test(void)
{
s_test *p;
p = (s_test *)b_test;
p->dw1 = p->dw2;
}

Листинг

void f_test(void)
{
8000f18: b510 push {r4, lr}
s_test *p;
p = (s_test *)b_test;
p->dw1 = p->dw2;
8000f1a: 4c0a ldr r4, [pc, #40] ; (8000f44 <f_test+0x2c>)
8000f1c: 79e2 ldrb r2, [r4, #7]
8000f1e: 79a0 ldrb r0, [r4, #6]
8000f20: 7a23 ldrb r3, [r4, #8]
8000f22: 0212 lsls r2, r2, #8
8000f24: 4302 orrs r2, r0
8000f26: 041b lsls r3, r3, #16
8000f28: 4313 orrs r3, r2
8000f2a: 1c1a adds r2, r3, #0
8000f2c: 7a63 ldrb r3, [r4, #9]
8000f2e: 061b lsls r3, r3, #24
8000f30: 4313 orrs r3, r2
8000f32: 0a1a lsrs r2, r3, #8
8000f34: 7023 strb r3, [r4, #0]
8000f36: 7062 strb r2, [r4, #1]
8000f38: 0c1a lsrs r2, r3, #16
8000f3a: 0e1b lsrs r3, r3, #24
8000f3c: 70a2 strb r2, [r4, #2]
8000f3e: 70e3 strb r3, [r4, #3]
}
8000f40: bd10 pop {r4, pc}
8000f42: 46c0 nop ; (mov r8, r8) ; прикольно. это выравнивание?))
8000f44: 2000063c .word 0x2000063c - адрес буфера



Не стреляет))
Даже осторожничает с dw1
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 17 2014, 22:22
Сообщение #40


Гуру
******

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



Цитата(Golikov A. @ Aug 17 2014, 17:07) *
Но передав это поле в функцию просто указателем будет опять обломс....
Вот тут вы и стреляете себе в ногу - пытясь передать указатель на упакованное поле как обычный указатель. Передавайте его честно, как указатель на упакованные данные - и обломса не будет.


--------------------
На любой вопрос даю любой ответ
"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
Golikov A.
сообщение Aug 18 2014, 07:00
Сообщение #41


Гуру
******

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



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

Вот у меня есть проект под 3 кортекс(кажется). Функция разбора входящего сообщения принимает указатель на данные сообщения - это 3 байт буфера. Перенос этой штуки на кортекс м0 - уронит его с первым же сообщением, где в данных идет число.

И я вот не знаю, если честно, поможет ли мне добавить в объявление функции __packed перед указателем на данные. И второй вопрос не замедлит ли это текущий ход программы ненужными действиями. А городить ветвление дефайнами тоже не хочется. Вот...

Go to the top of the page
 
+Quote Post
adnega
сообщение Aug 18 2014, 07:38
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Golikov A. @ Aug 18 2014, 11:00) *
Перенос этой штуки на кортекс м0 - уронит его с первым же сообщением, где в данных идет число.

А вот у меня не получилось завалить. Если p присваивать адрес указателя на байтовый буфер, то все операции далее идут как с невыровненными данными.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Aug 18 2014, 07:50
Сообщение #43


Знающий
****

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



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

Как правильно заметил Golikov A., обломс наступает при переносе библиотек.
У меня есть обработчик SVC, код которого базируется на широко цитируемых в сети примерах от ARM. Там, чтобы получить номер SVC из кода инструкции, есть выражение LDRB R0,[R0, #-2], где в R0 загружен сохраненный PC, который, очевидно, указывает на следующую за SVC инструкцию. Так вот, M0 НЕ ДОПУСКАЕТ отрицательные смещения. Хорошо, что ругня идет еще на этапе трансляции... Чтобы код был универсальным, пришлось сделать

SUBS R0, R0, #2
LDRB R0,[R0]

Сообщение отредактировал KnightIgor - Aug 18 2014, 07:51
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 18 2014, 09:56
Сообщение #44


Гуру
******

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



Цитата(KnightIgor @ Aug 18 2014, 10:50) *
Как правильно заметил Golikov A., обломс наступает при переносе библиотек.
Почему вы упорно валите с больной головы на здоровую? Если библиотека написана правильно, то указатель на упакованные данные будет описан именно как указатель на упакованные данные, без всяких допущений - умеет процессор сам работать с неупакованными данными или нет. Это работа компилятора - он знает целевой процессор лучше нас с вами и если досуп к упакованным данным на целевом процессоре возможен одной командой - он так и сделает. Но если такой доступ невозможен - он сгенерит честный побайтовый доступ. Если же автор библиотеки попытался обмануть компилятор и вместо указателя на упакованные данные подсунул обычный указатель, то виноват в этом писатель библиотеки и более никто. Эта попытка обмануть компилятор и есть выстрел в ногу.

Цитата(KnightIgor @ Aug 18 2014, 10:50) *
У меня есть обработчик SVC, код которого базируется на широко цитируемых в сети примерах от ARM.
То есть вас удивляет, что ассемблерный код для одного ядра не ассемблируется для другого??? А почему вас тогда не удивляет, что код для Пентиума не ассемблируется под 8086? Простите, но это напоминает анекдот:

- У меня на телефоне фотографии нечеткими получаются.
- Да ладно? Прикинь, а у меня с фотоаппарата вообще звонить нельзя!


--------------------
На любой вопрос даю любой ответ
"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
Golikov A.
сообщение Aug 18 2014, 11:39
Сообщение #45


Гуру
******

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



Цитата
Почему вы упорно валите с больной головы на здоровую?

да я вроде без претензий. Это для меня не столько "ё мое ну нафига так сделали?", сколько объяснение почему бездумное копирование и использование в нормальной работе халявных примеров ведет к неприятным последствиям.

в качестве легбеза:
получается лучше все указатели что void* передавать как указатели на пакованный тип? А лучше вообще все так передавать?
Потому что сейчас выравнивание 32 бита, а завтра будет 64 и проблема старых библиотек и реюз кода вылезет заново?

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

Go to the top of the page
 
+Quote Post

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

 


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


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