Перейти к содержанию
    

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

Для доступа к байту выравнивать не нужно, для полуслова адрес должен быть кратен 2, для слова 4 байтам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

51 minutes ago, MasterElectric said:

Для доступа к байту выравнивать не нужно, для полуслова адрес должен быть кратен 2, для слова 4 байтам.

Это же указатель на массив из байт. Я вот и не могу понять, нужно ли массиву указывать это слово.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

packed необходим для того чтобы соответствующим образом разложить поля в структуре, ключевое слово __packed разлаживает поля "плотничком", но упакованная структура может лежать по не выровненному адресу!

для того чтобы положить данные по кратному адресу, в IAR например, используется конструкция #pragma data_alignment =4

#pragma data_alignment = 4 

uint8_t ptr1[128]; 
uint8_t ptr2[128]; 

memcpy( ptr1, ptr2, 128);

Но, Вы используете new, и он судя по всему он отдает вам адрес не кратный 4. К сожалению не могу сказать как заставить new сделать это, нужно смотреть в документацию на ваши инструменты разработки

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, haker_fox сказал:

Я так понимаю, это невыровненный доступ.

Нет конечно. Причём тут невыровненный доступ, если аргументы-указатели функции (memcpy()) могут быть произвольными (байтовыми)?

Скорее похоже на то, что Ваш memcpy() лезет в несуществующую память (нарушение границ). Смотрите код в точке fault-а и значение регистров в этой точке.

Как вариант: один из ваших new не может выделить память и возвращает NULL, который Вы затем передаёте в memcpy(). Отсюда и доступ в несуществующую память. Почему после new не проверяете возвращаемое ею значение? Это грубая ошибка.

Вообще эта ошибка находится за 5 минут, после взгляда в окна дизасма и состояния регистров отладчика.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 minutes ago, jcxz said:

Нет конечно. Причём тут невыровненный доступ, если аргументы-указатели функции (memcpy()) могут быть произвольными (байтовыми)?

Скорее похоже на то, что Ваш memcpy() лезет в несуществующую память (нарушение границ). Смотрите код в точке fault-а и значение регистров в этой точке.

Как вариант: один из ваших new не может выделить память и возвращает NULL, который Вы затем передаёте в memcpy(). Отсюда и доступ в несуществующую память. Почему после new не проверяете возвращаемое ею значение? Это грубая ошибка.

Вообще эта ошибка находится за 5 минут, после взгляда в окна дизасма и состояния регистров отладчика.

Соглашусь, проблема скорее не в выравнивании, на Cortex-M4F такое сложно сделать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

17 minutes ago, jcxz said:

Почему после new не проверяете возвращаемое ею значение? Это грубая ошибка.

Простите, это я код некорректно привёл. Указатель на null проверяется. Там всё ок.

А на счёт выравнивания меня эта статья смутила. Там написано, что __aeabi_memcpy4 ожидает выровненных указателей.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, haker_fox said:

А на счёт выравнивания меня эта статья смутила.

В данном примере, вероятно, ключевой момент был в (void *)packed_ptr, после этого компилятор будет использовать байтовый __aeabi_memcpy

#include <string.h>

unsigned int * const dest;

void example (unsigned int * const unaligned_ptr)
{
  __packed unsigned int * packed_ptr = unaligned_ptr;
  char * temp_ptr = (char *)unaligned_ptr;
  memcpy(dest, unaligned_ptr, 32);         /* Unsafe */
  memcpy(dest, (void *)packed_ptr, 32);    /* Safe   */
  memcpy(dest, temp_ptr, 32);              /* Safe   */
}

Не совсем понятно какую цель они преследовали добавив туда __packed, возможно что-бы явно показать что packed_ptr может быть не выровнен, о чем можно прочитать здесь

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, Integro said:

Не совсем понятно какую цель они преследовали добавив туда __packed, возможно что-бы явно показать что packed_ptr может быть не выровнен, о чем можно прочитать здесь

Там же написано:

You need to either explicitly tell the compiler when you are using unaligned pointers by using the __packed keyword (described in the compiler guide), or create a temporary char* pointer to access the address.

Что здесь непонятно?

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 minutes ago, scifi said:

По феншую нужно исправлять тип указателя, чтобы соответствовал.

Cмысл исправлять на __packed если они потом приводят к типу (void*) ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

25 minutes ago, Integro said:

Cмысл исправлять на __packed если они потом приводят к типу (void*) ?

Явное приведение к void*, очевидно, нужно лишь для того, чтобы подавить предупреждение компилятора. Всё равно оно неявно приведётся к тому же void* перед вызовом функции (см. объявление memcpy).

Кстати, стандарт говорит, что неопределённое поведение возникает в момент, когда указателю присваивают значение без нужного выравнивания. В примере, который приводит Арм, это происходит до вызова функции example(). В этом смысле пример плохой, так как исправляет последствия косяка и как бы поощряет неокрепшие умы забить на первопричину.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, jcxz said:

Вообще эта ошибка находится за 5 минут, после взгляда в окна дизасма и состояния регистров отладчика

Я так понимаю вприглядку на стандарт AEABI? Чтобы понять, в каких регистрах какие аргументы расположены...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

29 минут назад, haker_fox сказал:

Я так понимаю вприглядку на стандарт AEABI? Чтобы понять, в каких регистрах какие аргументы расположены...

Зачем? Точку фаулта (PC) знаете? Смотрите в окно дизасма на команды в этом месте и в окно регистров на их значения, и определяете причину.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, jcxz said:

Зачем? Точку фаулта (PC) знаете?

Кстати, насколько мне известно, она не всегда же валидна. Об этом на сайте arm.com написано. Насколько помню там нужно анализировать HFSR  или подобный регистр.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, haker_fox сказал:

Кстати, насколько мне известно, она не всегда же валидна. Об этом на сайте arm.com написано. Насколько помню там нужно анализировать HFSR  или подобный регистр.

Так вроде Вы написали, что анализируете:

8 часов назад, haker_fox сказал:

В отладчике HF у меня есть анализ регистров, и причина указан "A data bus error has occurred".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...