Jump to content

    
Sign in to follow this  
k000858

STM32L0 HardFault: заморочки с выравниванием

Recommended Posts

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

 

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

 

В STM32F4 камне тот же самый код работает нормально.

Почему же M0+ вылетает в HardFault?

Edited by k000858

Share this post


Link to post
Share on other sites
Потому что не поддерживает невыровненный доступ.

можно поподробнее?

пока все проблемы выравнивая обходил стороной, проектов на M0+ минимум

Share this post


Link to post
Share on other sites
Нужно гарантировать, что 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-битному значению

Edited by k000858

Share this post


Link to post
Share on other sites
... или более каноничный через memcpy.

uint32_t value;
memcpy(&value, ptr, sizeof(value));
printf("val = %lu\n", value);

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

заработали оба способа

второй способ понравился даже больше. еще раз спасибо, теперь мне тема выравнивания еще более понятна.

Share this post


Link to post
Share on other sites

Допустим, memcpy умеет правильно обращаться по невыровненному адресу. Или тупо байтами копирует. Но как помогает приведение указателя к указателю на выровненную структуру? От этого положение данных не меняется же.

Share this post


Link to post
Share on other sites
... или более каноничный через 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);

 

Share this post


Link to post
Share on other sites
но чувствую, можно сделать это поизящнее. Подскажите красивый способ получения доступа к 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() - макросы, которые на процессоре поддерживающем невыровненный доступ определены просто как чтение или запись значения по этому адресу, а на процессоре не поддерживающем невыровненный доступ - они осуществляют побайтное чтение/запись слова.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this