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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> STM32L0 HardFault: заморочки с выравниванием
k000858
сообщение Jan 31 2017, 12:19
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Есть какие то ограничения в ядре, приводящие к HardFault?

Пришлось в одной функции привести указатель типа uint8_t* к типу uint32_t* изза чего получил HardFault.

В STM32F4 камне тот же самый код работает нормально.
Почему же M0+ вылетает в HardFault?

Сообщение отредактировал k000858 - Feb 1 2017, 03:59
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 31 2017, 12:21
Сообщение #2


Гуру
******

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



QUOTE (k000858 @ Jan 31 2017, 14:19) *
Почему же M0+ вылетает в HardFault?
Потому что не поддерживает невыровненный доступ.


--------------------
На любой вопрос даю любой ответ
"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
k000858
сообщение Jan 31 2017, 12:27
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Сергей Борщ @ Jan 31 2017, 15:21) *
Потому что не поддерживает невыровненный доступ.

можно поподробнее?
пока все проблемы выравнивая обходил стороной, проектов на M0+ минимум
Go to the top of the page
 
+Quote Post
adnega
сообщение Jan 31 2017, 12:35
Сообщение #4


Гуру
******

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



Нужно гарантировать, что uint32_t* указывает на переменную, расположенную по адресу, кратному 4.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 31 2017, 13:11
Сообщение #5


Гуру
******

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



QUOTE (k000858 @ Jan 31 2017, 14:27) *
можно поподробнее?
PM0223: STM32L0 Series Cortex®-M0+ programming manual, искать словосочетание "unaligned access"


--------------------
На любой вопрос даю любой ответ
"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
k000858
сообщение Feb 1 2017, 04:04
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(adnega @ Jan 31 2017, 15:35) *
Нужно гарантировать, что uint32_t* указывает на переменную, расположенную по адресу, кратному 4.

а, вот оно что. теперь более менее понимаю.


буфер в котором содержится нужное мне 32-битное значение uint8_t buf[100];
указатель на место, в котором содержится значением uint8_t* ptr = &buf[5];

на Cortex-M4 не заморачивался и делал вот так printf("val = %lu\n", *(uint32_t*)ptr);
на Cortex-M0+ такая запись приводит к HardFault'у. Причину теперь понимаю хорошо, и как не получать такой эффект тоже.

Пока сделал вот так:
Код
uint8_t value[4];
value[0]    = *ptr;
value[1]    = *(ptr + 1);
value[2]    = *(ptr + 2);
value[3]    = *(ptr+ 3);
uint32_t val    = (value[0]) | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
printf("val = %lu\n", val);


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

Сообщение отредактировал k000858 - Feb 1 2017, 04:05
Go to the top of the page
 
+Quote Post
Alechek
сообщение Feb 1 2017, 05:06
Сообщение #7


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Код
#pragma pack(push, 1)
struct _input {
uint32_t Value;
};
#pragma pack(pop)

struct _input * I = (struct _input *) ptr;
printf("val = %lu\n", I->Value);



Go to the top of the page
 
+Quote Post
k000858
сообщение Feb 1 2017, 05:52
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Alechek @ Feb 1 2017, 08:06) *
Код
#pragma pack(push, 1)
struct _input {
uint32_t Value;
};
#pragma pack(pop)

struct _input * I = (struct _input *) ptr;
printf("val = %lu\n", I->Value);

да, спасибо, такой способ вполне подойдет.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 1 2017, 06:54
Сообщение #9


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

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



Цитата(k000858 @ Feb 1 2017, 08:52) *
да, спасибо, такой способ вполне подойдет.

Отпишитесь о результате.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Feb 1 2017, 07:08
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



... или более каноничный через memcpy.
Код
uint32_t value;
memcpy(&value, ptr, sizeof(value));
printf("val = %lu\n", value);

Он вам кстати еще много где пригодится.
Go to the top of the page
 
+Quote Post
k000858
сообщение Feb 1 2017, 07:31
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 319
Регистрация: 31-01-12
Пользователь №: 69 978



Цитата(Kabdim @ Feb 1 2017, 10:08) *
... или более каноничный через memcpy.
Код
uint32_t value;
memcpy(&value, ptr, sizeof(value));
printf("val = %lu\n", value);

Он вам кстати еще много где пригодится.

заработали оба способа
второй способ понравился даже больше. еще раз спасибо, теперь мне тема выравнивания еще более понятна.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Feb 1 2017, 07:44
Сообщение #12


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

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



Допустим, memcpy умеет правильно обращаться по невыровненному адресу. Или тупо байтами копирует. Но как помогает приведение указателя к указателю на выровненную структуру? От этого положение данных не меняется же.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Feb 1 2017, 07:58
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Почему ж она выровненная? Там прагма спереди и в конце стоит.
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 1 2017, 09:25
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Kabdim @ Feb 1 2017, 10:08) *
... или более каноничный через memcpy.
Код
uint32_t value;
memcpy(&value, ptr, sizeof(value));
printf("val = %lu\n", value);

Он вам кстати еще много где пригодится.

Если уж мы тут образованием занимаемся, то более кошерно формат указывать вот так:
Код
uint32_t value;
memcpy(&value, ptr, sizeof(value));
printf("val = %" PRIu32 "\n", value);

Go to the top of the page
 
+Quote Post
jcxz
сообщение Feb 1 2017, 09:26
Сообщение #15


Гуру
******

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



Цитата(k000858 @ Feb 1 2017, 06:04) *
но чувствую, можно сделать это поизящнее. Подскажите красивый способ получения доступа к 32-битному значению

Если компилятор поддерживает соответствующий префикс, создать пакованные типы:
Код
typedef __packed u16 u16p8;
typedef __packed s16 s16p8;
typedef __packed u32 u32p8;
typedef __packed s32 s32p8;
typedef __packed u64 u64p8;
typedef __packed s64 s64p8;
либо, если в компиляторе нет соответствующего префикса, создать соотв. классы и перегрузить в них операторы присваивания и приведения типа:
Код
struct u32p8 {
  u8 bytes[4];
  operator u32() const { return u32load(&bytes); }
  u32p8 & operator =(u32 val) { u32save(&bytes, val); return *this; }
};

где: u32load() и u32save() - макросы, которые на процессоре поддерживающем невыровненный доступ определены просто как чтение или запись значения по этому адресу, а на процессоре не поддерживающем невыровненный доступ - они осуществляют побайтное чтение/запись слова.
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 Текстовая версия Сейчас: 13th August 2025 - 14:22
Рейтинг@Mail.ru


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