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

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

Разве не достаточно создать union для обращения к переменной по байтам и словом?

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


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

Если уж мы тут образованием занимаемся, то более кошерно формат указывать вот так:

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

Всё хорошо в меру, те эмбедед библиотеки с которыми я работал такой формат не понимают. Можно конечно определить самому, но тогда насколько я помню у меня были проблемы с постоянными варнингами на size_t/ptrdiff_t.

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


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

Разве не достаточно создать union для обращения к переменной по байтам и словом?

Достаточно. О чём я выше и написал. Но ТС хочет красиво. А красиво это - или перегрузить в этом union-e/struct-е операторы присваивания/приведения типа или воспользоваться соответствующим префиксом компилятора если таковой есть (как в IAR).

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


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

Красиво - это когда просто. :) Перегрузка операторов - это не красиво. Вообще не знаю, зачем это придумали. Какая-то "феня" высоких интеллектуалов.

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


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

Красиво - это когда просто. :) Перегрузка операторов - это не красиво. Вообще не знаю, зачем это придумали. Какая-то "феня" высоких интеллектуалов.

Чем именно не красиво???

Вам это нравится:

int x;

x = y;

а это нет:

u32p8 x;

x = y;

почему?

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


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

Чем именно не красиво???

u32p8 x;

x = y;

почему?

Покажите полное решение вопроса, с макросами или функциями. Вот чтобы скопипастить в исходник, и оно работало. :biggrin: Тогда оценим красоту. А пока вижу только идею.

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


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

Покажите полное решение вопроса, с макросами или функциями. Вот чтобы скопипастить в исходник, и оно работало. :biggrin: Тогда оценим красоту. А пока вижу только идею.

Идею я обрисовал, а чтобы работало - это может проверить только тот, у кого M0 или ARM7. У меня сейчас такого МК нет под рукой.

Вот для типов u16p8 и s16p8 (пакованный до байт беззнаковый и знаковый u16/s16):

#ifdef ADDR_ALIGN
#define u16load(p) (*(u8 *)(p) | (u16)((u8 *)(p))[1] << 8)
#define s16load(p) (*(u8 *)(p) | (s16)((s8 *)(p))[1] << 8)
#define u16save(p, x) { *(u8 *)(p) = (u8)(x); ((u8 *)(p))[1] = (x) >> 8; }
#else //ADDR_ALIGN
#define u16load(p) (*(u16 *)(p))
#define s16load(p) (*(s16 *)(p))
#define u16save(p, x) { *(u16 *)(p) = (x); }
#endif

#ifdef ADDR_ALIGN

struct u16p8 {
 u8 bytes[2];
 operator u16() const { return u16load(&bytes); }
 u16p8 & operator =(u32 val) { u16save(&bytes, val); return *this; }
};
struct s16p8 {
 u8 bytes[2];
 operator s16() const { return s16load(&bytes); }
 s16p8 & operator =(s32 val) { u16save(&bytes, val); return *this; }
};

#else  //ADDR_ALIGN

typedef __packed u16 u16p8;
typedef __packed s16 s16p8;

#endif //ADDR_ALIGN

Реализация остальные типов - на домашнее задание ;)

ADDR_ALIGN должен быть определён для случая если:

a) процессор не поддерживает выравнивание;

...И...

б) компилятор не понимает префикса __packed.

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


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

И все это ради того, чтобы не дать указание компилятору-линкеру разместить переменную в правильном месте. :laughing:

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


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

И все это ради того, чтобы не дать указание компилятору-линкеру разместить переменную в правильном месте. :laughing:

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

 

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


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

И все это ради того, чтобы не дать указание компилятору-линкеру разместить переменную в правильном месте. :laughing:

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

Такой вариант никто не предлагал:

uint32_t __packed* p = &buff[33];
uint32_t x = *p;

Около года назад в gcc эта шляпа не сработала, а в кейле работала.

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


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

Около года назад в gcc эта шляпа не сработала, а в кейле работала.

__packed не все компиляторы поддерживают. IAR поддерживает. И Keil значит - тоже.

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


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

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

Для M0 здесь нет решения, кроме как читать по байтам.

Такой вариант никто не предлагал:

uint32_t __packed* p = &buff[33];
uint32_t x = *p;

Около года назад в gcc эта шляпа не сработала, а в кейле работала.

Поясните. Выше интересовался таким же вопросом. Указатель на упакованную структуру - как это помогает обратиться к слову по не выровненному адресу?

Ясно. Читает по байтам.

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


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

__packed не все компиляторы поддерживают. IAR поддерживает. И Keil значит - тоже.
__packed и gcc поддерживаете, но не полностью - он не отрабатывает указатели с квалификатором __packed...

 

У меня так сделано:

#if defined(__MINGW32__)
#    define __packed       __attribute__((__gcc_struct__, __packed__, __aligned__(1)))
#else
#    define __packed       __attribute__((__packed__, __aligned__(1)))
#endif

Поясните. Выше интересовался таким же вопросом. Указатель на упакованную структуру - как это помогает обратиться к слову по не выровненному адресу?
Очень просто. Компилятор, видя такой указатель, сам генерирует правильные инструкции для доступа по невыровненному адресу.

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


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

Для M0 здесь нет решения, кроме как читать по байтам.

...

Ясно. Читает по байтам.

А Вы что хотели - некую чудесную инструкцию процессора? :biggrin:

M0 физически не умеет невыровненный доступ - нет таких инструкций у него!

Так что такой доступ можно только эмулировать. Либо встроенными возможностями компилятора (__packed) либо реализовав это самостоятельно (свой класс с перегрузками, например).

 

PS: Более того - даже для ядра M4 (и прочих) если переменная находится (или может находиться) по невыровненному адресу, для неё надо указывать спецификатор __packed.

А то, что у ТС "В STM32F4 камне тот же самый код работает нормально" - о говорит только о кривости написания этого кода, который сейчас работает, завтра перекомпилят его на другом компиляторе (или новой версии того же компилятора) - он будет падать в тот же HF на том же самом ядре M4. Так как никто не мешает компилятору для обращения к этим данным использовать не инструкции LDR/STR, а например LDRD/STRD или LDM/STM, которые не умеют невыровненный доступ. И компилятор имеет право это сделать, например при оптимизации.

Так что надо взять за правило: на любом процессоре, если переменная невыровнена, она должна быть объявлена как невыровненная.

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


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

А Вы что хотели - некую чудесную инструкцию процессора?

 

Так что надо взять за правило: на любом процессоре, если переменная невыровнена, она должна быть объявлена как невыровненная.

Я руками (головой) размещаю переменные в структуре так, чтобы стояли ровно. :biggrin: Если есть дыры, забиваю их uint8_t RESERVED_n. А саму структуру линкер знает, куда разместить. Без указаний.

И компиляторы не пугают, ни прошлые, ни будущие.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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