|
|
  |
Формирование int из массива char |
|
|
|
Feb 15 2016, 23:34
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(scifi @ Feb 16 2016, 00:02)  И это тоже. Прогресс в компиляторостроении привёл к тому, что вот эти стенания "а как же эти лишние две инструкции?" - зачастую устаревшая выдумка Типичный аргумент кодера-форточника, создающего шедевры, способные показом обычного диалога загрузить intel-i7 на 100% на минуту. Цитата(scifi @ Feb 16 2016, 00:02)  Но даже не так, пара лишних тактов и байтов вредит крайне редко. Короче, "преждевременная оптимизация", если говорить без матюков, но иметь в виду именно их  Предположим: нужна функция, инкрементирующая пакованный int. С __packed на Cortex-M это будет: Код LDR R1, [R0] ADDS R1, R1, #1 STR R1, [R0] BX LR В случае с memcpy будет: создание стекового фрейма, копирование, инкремент, опять копирование, удаление стекового фрейма - итого: не на пару байт, а во много раз (!!!) дольше + занимает доп.регистры + доп.стек.
|
|
|
|
|
Feb 16 2016, 08:36
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(jcxz @ Feb 16 2016, 02:34)  Предположим: нужна функция, инкрементирующая пакованный int. С __packed на Cortex-M это будет: Код LDR R1, [R0] ADDS R1, R1, #1 STR R1, [R0] BX LR Попробовал на своём Cortex-M0. Не работает  Цитата(jcxz @ Feb 16 2016, 02:34)  В случае с memcpy будет: создание стекового фрейма, копирование, инкремент, опять копирование, удаление стекового фрейма - итого: не на пару байт, а во много раз (!!!) дольше + занимает доп.регистры + доп.стек. Глупость какая. Только что попробовал на Cortex-M3: как и положено, вместо memcpy подставляет LDR/STR. Цитата(Сергей Борщ @ Feb 15 2016, 13:43)  А по мне так наоборот - если происходит действие "обращение по указателю" - то логично было бы использовать предусмотренные для этого в языке средства разыменования указателя, а не захламлять исходник вызовами memcpy(). То, что этот указатель учитывает какие-то аппаратные особенности (невыровненный доступ), логично было бы как-то указать один раз при объявлении указателя (тот же __packed), а не распылять по исходнику в виде memcpy() и надеяться, что программист не забудет именно этот указатель использовать через memcpy().
В gcc можно обернуть искомые данные в упакованную структуру и обращаться по указателю на эту структуру. Наверное, всё дело в том, что мне не доводилось писать код с невыровненным доступом, потому и удивляюсь. А ради одного-двух случаев в коде я точно не стал бы городить packed, а сделал бы memcpy. Хотя могу представить себе такой код - lwip, к примеру. Там нужно постоянно обращаться к полям пакетов, и там повсеместно используются упакованные структуры. Альтернатива - сделать функции доступа к полям через указание смещений, но это точно будет выглядеть коряво на фоне упакованных структур, так что принято.
|
|
|
|
|
Feb 16 2016, 10:52
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (scifi @ Feb 16 2016, 10:36)  Наверное, всё дело в том, что мне не доводилось писать код с невыровненным доступом, потому и удивляюсь. Практически абсолютно любой протокол обмена требует обращения ко всяким разным полям (в том числе и битовым )во фрейме, то что они не выровнееные это практически наверняка и если не писать разбоку и формирование в стиле "третий бит в пятом байте слева" (за что вообще-то надо сразу чего нибудь оторвать, что болтается), то сразу становятся необходимыми структуры и обьединения. Причем, если платформа не восьмибитовая, то сразу возникают понятия раковки стуктур и на многих платформах невыровненный доступ. Но проблема доступа в таком случае сразу скрывает компилятор. Но в общем структуры организуются СОВЕРШЕННО не для того, что-бы бороться с выравниваним и заявление: QUOTE А ради одного-двух случаев в коде я точно не стал бы городить packed более чем....
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 16 2016, 11:07
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Цитата(dimka76 @ Feb 15 2016, 14:19)  Код typedef volatile uint32_t REG32; #define pREG32 (REG32 *) #define USB_TXDATA (*(pREG32 (0x4002001C)))
uint8_t *pData;
USB_TXDATA = *((uint32_t __attribute__((packed)) *)pData); В тех примерах от NXP которые у меня: Код #if defined(__GNUC__) // Code Red tools
...
// The following two typedefs are required as GCC does // not directly support a method of hinting that a variable // (as opposed to a structure) should be accessed with // the assumption that it is unaligned, which can be done // in Keil using, for example, __packed uint32_t *p; typedef struct { uint32_t value __attribute__(( packed )); }unaligned_uint32;
typedef struct { uint16_t value __attribute__(( packed )); }unaligned_uint16;
... А использование что-то вроде такого: Код #if defined(__GNUC__) (( unaligned_uint16 *)EP0Buf)->value = (USB_EndPointHalt & m) ? 1 : 0;; #else *((__packed uint16_t *)EP0Buf) = (USB_EndPointHalt & m) ? 1 : 0; #endif
|
|
|
|
|
Feb 16 2016, 13:08
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(jcxz @ Feb 16 2016, 02:34)  В случае с memcpy будет: создание стекового фрейма... Такого ужаса уже давно нет. По крайней мере, в gcc практически все библиотечные функции за'builtin'ены, и компилятор встраивает и разворачивает их максимально гибко, вплоть до того, что sin(const) и иже с ним считается чуть-ли не на этапе препроцессинга и может использоваться даже для инициализации констант. Цитата(Kabdim @ Feb 16 2016, 14:07)  Код typedef struct { uint16_t value __attribute__(( packed ));}unaligned_uint16_t;
(( unaligned_uint16_t *)EP0Buf)->value = 1; С выкрутасом решение, но читаемость хромает. Если запрятать это в макрос, то читаемость поднимется в разы... Спасибо! Может когда-нибудь пригодится.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 16 2016, 14:31
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(AlexeyT @ Feb 12 2016, 18:05)  Задача такая - есть массив test_buff, из подряд идущих 4-х элементов которого нужно сформировать переменную unsigned int.
unsigned char test_buff[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; unsigned char *tst_point = &test_buff[0]; unsigned int *tst;
tst = (unsigned int *)(tst_point + 2*sizeof(unsigned char)); //должны получить 0x06050403 = 100992003
Т.е. в *tst пытаюсь записать unsigned int, состоящий из байтов массива с 3-го по 6-й.
При исполнении этого кода на ARM-процессоре (ядро Cortex-M1) происходит зависание ядра (когда обращаюсь к адресу, некратному 4 байтам). При исполнении этого же кода на ПК - все ок, *tst = 100992003, как и должно быть. Компилятор Keil.
Есть идеи, как решить задачу? А ваш процессор Big endian или little endian? Вроде в АРМ это переключить можно, хотя чаще всего он он little endian. Второй вопрос в вашем массиве данные Big endian или little endian?
|
|
|
|
|
Feb 16 2016, 19:16
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
QUOTE (_pv @ Feb 16 2016, 20:33)  ради одной пакованной переменной писать кучу #if при объявлении, с различными прагмами/атрибутами для разных компиляторов не менее глупо. лучше уж макрос или инлайн функция которая возвращает нормальный int из невыровненного адреса. Городить какую-то функцию, которая будет разбитаться как именно невыровнен адрес а может и выровнен.... тода уж memcpy() - эта занимается тем-же самым, но понятно, что делает. И все это ради того, что-бы отвергать великолепный механизм паковки и доступа к структурам. Дурдом. Но понятный после этого заявления: QUOTE в единственном случае где могут понадобится упакованные структуры и где без этого вполне можно обойтись - в случае с протоколами обмена становится понятным, что задачи обмена данными бесконечно далеки от Вас и "контроллеров светодиодов". QUOTE , там всё равно все доступы к структуре будут обёрнуты в hton / ntoh. C какого бодуна, если это зависит от протокола и контрорлера.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 16 2016, 20:16
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
Цитата(zltigo @ Feb 17 2016, 01:16)  Городить какую-то функцию, которая будет разбитаться как именно невыровнен адрес а может и выровнен.... тода уж memcpy() - эта занимается тем-же самым, но понятно, что делает. И все это ради того, что-бы отвергать великолепный механизм паковки и доступа к структурам. Дурдом. Этот великолепный механизм - костыли которые в каждом компиляторе сделаны (и хорошо если в каждом) по своему. Вон у TI, TCP стэк для msp430, как-то обошлись без великолепных механизмов. И раз уж Вы так близки к задачам обмена данными, не приведёте код объявления упакованной структуры который любой С компилятор поймёт? Цитата(zltigo @ Feb 17 2016, 01:16)  C какого бодуна, если это зависит от протокола и контрорлера. endiannes у всех всех контроллеров вдруг стала одинаковая и так получиться так что она будет отличаться от заданной в протоколе никак не может?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|