ViKo 1 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Разве не достаточно создать union для обращения к переменной по байтам и словом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Если уж мы тут образованием занимаемся, то более кошерно формат указывать вот так: uint32_t value; memcpy(&value, ptr, sizeof(value)); printf("val = %" PRIu32 "\n", value); Всё хорошо в меру, те эмбедед библиотеки с которыми я работал такой формат не понимают. Можно конечно определить самому, но тогда насколько я помню у меня были проблемы с постоянными варнингами на size_t/ptrdiff_t. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Разве не достаточно создать union для обращения к переменной по байтам и словом? Достаточно. О чём я выше и написал. Но ТС хочет красиво. А красиво это - или перегрузить в этом union-e/struct-е операторы присваивания/приведения типа или воспользоваться соответствующим префиксом компилятора если таковой есть (как в IAR). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Красиво - это когда просто. :) Перегрузка операторов - это не красиво. Вообще не знаю, зачем это придумали. Какая-то "феня" высоких интеллектуалов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Красиво - это когда просто. :) Перегрузка операторов - это не красиво. Вообще не знаю, зачем это придумали. Какая-то "феня" высоких интеллектуалов. Чем именно не красиво??? Вам это нравится: int x; x = y; а это нет: u32p8 x; x = y; почему? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Чем именно не красиво??? u32p8 x; x = y; почему? Покажите полное решение вопроса, с макросами или функциями. Вот чтобы скопипастить в исходник, и оно работало. Тогда оценим красоту. А пока вижу только идею. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Покажите полное решение вопроса, с макросами или функциями. Вот чтобы скопипастить в исходник, и оно работало. Тогда оценим красоту. А пока вижу только идею. Идею я обрисовал, а чтобы работало - это может проверить только тот, у кого 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба И все это ради того, чтобы не дать указание компилятору-линкеру разместить переменную в правильном месте. :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k000858 0 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба И все это ради того, чтобы не дать указание компилятору-линкеру разместить переменную в правильном месте. :laughing: лично для меня это нужно, что бы обратиться к переменной, не заморачиваясь, куда же ее разместил линкер-компилятор Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба И все это ради того, чтобы не дать указание компилятору-линкеру разместить переменную в правильном месте. :laughing: Нет. Это для того чтобы из принятого буфера прочесть переменную с произвольным смещением в этом буфере. Такой вариант никто не предлагал: uint32_t __packed* p = &buff[33]; uint32_t x = *p; Около года назад в gcc эта шляпа не сработала, а в кейле работала. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Около года назад в gcc эта шляпа не сработала, а в кейле работала. __packed не все компиляторы поддерживают. IAR поддерживает. И Keil значит - тоже. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Нет. Это для того чтобы из принятого буфера прочесть переменную с произвольным смещением в этом буфере. Для M0 здесь нет решения, кроме как читать по байтам. Такой вариант никто не предлагал: uint32_t __packed* p = &buff[33]; uint32_t x = *p; Около года назад в gcc эта шляпа не сработала, а в кейле работала. Поясните. Выше интересовался таким же вопросом. Указатель на упакованную структуру - как это помогает обратиться к слову по не выровненному адресу? Ясно. Читает по байтам. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба __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 Поясните. Выше интересовался таким же вопросом. Указатель на упакованную структуру - как это помогает обратиться к слову по не выровненному адресу?Очень просто. Компилятор, видя такой указатель, сам генерирует правильные инструкции для доступа по невыровненному адресу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба Для M0 здесь нет решения, кроме как читать по байтам. ... Ясно. Читает по байтам. А Вы что хотели - некую чудесную инструкцию процессора? M0 физически не умеет невыровненный доступ - нет таких инструкций у него! Так что такой доступ можно только эмулировать. Либо встроенными возможностями компилятора (__packed) либо реализовав это самостоятельно (свой класс с перегрузками, например). PS: Более того - даже для ядра M4 (и прочих) если переменная находится (или может находиться) по невыровненному адресу, для неё надо указывать спецификатор __packed. А то, что у ТС "В STM32F4 камне тот же самый код работает нормально" - о говорит только о кривости написания этого кода, который сейчас работает, завтра перекомпилят его на другом компиляторе (или новой версии того же компилятора) - он будет падать в тот же HF на том же самом ядре M4. Так как никто не мешает компилятору для обращения к этим данным использовать не инструкции LDR/STR, а например LDRD/STRD или LDM/STM, которые не умеют невыровненный доступ. И компилятор имеет право это сделать, например при оптимизации. Так что надо взять за правило: на любом процессоре, если переменная невыровнена, она должна быть объявлена как невыровненная. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 1 февраля, 2017 Опубликовано 1 февраля, 2017 · Жалоба А Вы что хотели - некую чудесную инструкцию процессора? Так что надо взять за правило: на любом процессоре, если переменная невыровнена, она должна быть объявлена как невыровненная. Я руками (головой) размещаю переменные в структуре так, чтобы стояли ровно. Если есть дыры, забиваю их uint8_t RESERVED_n. А саму структуру линкер знает, куда разместить. Без указаний. И компиляторы не пугают, ни прошлые, ни будущие. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться