scifi 1 15 февраля, 2016 Опубликовано 15 февраля, 2016 · Жалоба К чему в очередной раз поминание древней глупости - "преждевременная оптимизация" ? http://electronix.ru/forum/index.php?showt...t&p=1348755 Нет времени отвечать на ваши глупости. Кто имеет уши - тот услышит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 15 февраля, 2016 Опубликовано 15 февраля, 2016 · Жалоба Нет времени... Не сомневался :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 15 февраля, 2016 Опубликовано 15 февраля, 2016 · Жалоба И это тоже. Прогресс в компиляторостроении привёл к тому, что вот эти стенания "а как же эти лишние две инструкции?" - зачастую устаревшая выдумка Типичный аргумент кодера-форточника, создающего шедевры, способные показом обычного диалога загрузить intel-i7 на 100% на минуту. Но даже не так, пара лишних тактов и байтов вредит крайне редко. Короче, "преждевременная оптимизация", если говорить без матюков, но иметь в виду именно их :smile3009: Предположим: нужна функция, инкрементирующая пакованный int. С __packed на Cortex-M это будет: LDR R1, [R0] ADDS R1, R1, #1 STR R1, [R0] BX LR В случае с memcpy будет: создание стекового фрейма, копирование, инкремент, опять копирование, удаление стекового фрейма - итого: не на пару байт, а во много раз (!!!) дольше + занимает доп.регистры + доп.стек. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Предположим: нужна функция, инкрементирующая пакованный int. С __packed на Cortex-M это будет: LDR R1, [R0] ADDS R1, R1, #1 STR R1, [R0] BX LR Попробовал на своём Cortex-M0. Не работает :crying: В случае с memcpy будет: создание стекового фрейма, копирование, инкремент, опять копирование, удаление стекового фрейма - итого: не на пару байт, а во много раз (!!!) дольше + занимает доп.регистры + доп.стек. Глупость какая. Только что попробовал на Cortex-M3: как и положено, вместо memcpy подставляет LDR/STR. А по мне так наоборот - если происходит действие "обращение по указателю" - то логично было бы использовать предусмотренные для этого в языке средства разыменования указателя, а не захламлять исходник вызовами memcpy(). То, что этот указатель учитывает какие-то аппаратные особенности (невыровненный доступ), логично было бы как-то указать один раз при объявлении указателя (тот же __packed), а не распылять по исходнику в виде memcpy() и надеяться, что программист не забудет именно этот указатель использовать через memcpy(). В gcc можно обернуть искомые данные в упакованную структуру и обращаться по указателю на эту структуру. Наверное, всё дело в том, что мне не доводилось писать код с невыровненным доступом, потому и удивляюсь. А ради одного-двух случаев в коде я точно не стал бы городить packed, а сделал бы memcpy. Хотя могу представить себе такой код - lwip, к примеру. Там нужно постоянно обращаться к полям пакетов, и там повсеместно используются упакованные структуры. Альтернатива - сделать функции доступа к полям через указание смещений, но это точно будет выглядеть коряво на фоне упакованных структур, так что принято. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Наверное, всё дело в том, что мне не доводилось писать код с невыровненным доступом, потому и удивляюсь. Практически абсолютно любой протокол обмена требует обращения ко всяким разным полям (в том числе и битовым )во фрейме, то что они не выровнееные это практически наверняка и если не писать разбоку и формирование в стиле "третий бит в пятом байте слева" (за что вообще-то надо сразу чего нибудь оторвать, что болтается), то сразу становятся необходимыми структуры и обьединения. Причем, если платформа не восьмибитовая, то сразу возникают понятия раковки стуктур и на многих платформах невыровненный доступ. Но проблема доступа в таком случае сразу скрывает компилятор. Но в общем структуры организуются СОВЕРШЕННО не для того, что-бы бороться с выравниваним и заявление: А ради одного-двух случаев в коде я точно не стал бы городить packed более чем.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба А использование что-то вроде такого: #if defined(__GNUC__) (( unaligned_uint16 *)EP0Buf)->value = (USB_EndPointHalt & m) ? 1 : 0;; #else *((__packed uint16_t *)EP0Buf) = (USB_EndPointHalt & m) ? 1 : 0; #endif Интересно, зачем так? Ведь гнусишный вариант вполне может работать и с RealView. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kabdim 0 16 февраля, 2016 Опубликовано 16 февраля, 2016 (изменено) · Жалоба Интересно, зачем так? Ведь гнусишный вариант вполне может работать и с RealView. Там были глупостей и ошибки похлеще, но работало. Подозреваю что вначале написали на Кейле, а потом другой человек отпортировали на gcc не слишком задумываясь, лишь бы работало. Изменено 16 февраля, 2016 пользователем Kabdim Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба В случае с memcpy будет: создание стекового фрейма...Такого ужаса уже давно нет. По крайней мере, в gcc практически все библиотечные функции за'builtin'ены, и компилятор встраивает и разворачивает их максимально гибко, вплоть до того, что sin(const) и иже с ним считается чуть-ли не на этапе препроцессинга и может использоваться даже для инициализации констант. typedef struct { uint16_t value __attribute__(( packed ));}unaligned_uint16_t; (( unaligned_uint16_t *)EP0Buf)->value = 1; С выкрутасом решение, но читаемость хромает. Если запрятать это в макрос, то читаемость поднимется в разы... Спасибо! Может когда-нибудь пригодится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 241 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Такого ужаса уже давно нет. По крайней мере, в gcc практически все библиотечные функции за'builtin'ены, и компилятор встраивает и разворачивает их максимально гибко, вплоть до того, что sin(const) и иже с ним считается чуть-ли не на этапе препроцессинга и может использоваться даже для инициализации констант. Часто приходится компилить без оптимизации, для отладки и т.п. С отключенной оптимизацией разве развернёт? Один фиг - писать все эти memcpy() для доступа к одной пакованной переменной - это как раз глупо и слишком громоздко (снижает читаемость исходника). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Часто приходится компилить без оптимизации, для отладки и т.п. С отключенной оптимизацией разве развернёт?Не знаю, т.к. меня этот вопрос вообще не заботит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Задача такая - есть массив 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? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 78 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Один фиг - писать все эти memcpy() для доступа к одной пакованной переменной - это как раз глупо и слишком громоздко (снижает читаемость исходника). ради одной пакованной переменной писать кучу #if при объявлении, с различными прагмами/атрибутами для разных компиляторов не менее глупо. лучше уж макрос или инлайн функция которая возвращает нормальный int из невыровненного адреса. в единственном случае где могут понадобится упакованные структуры и где без этого вполне можно обойтись - в случае с протоколами обмена, там всё равно все доступы к структуре будут обёрнуты в hton / ntoh. ну будет еще одна обёртка для выравнивания, тоже мне проблема. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 2 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба ради одной пакованной переменной писать кучу #if при объявлении, с различными прагмами/атрибутами для разных компиляторов не менее глупо. лучше уж макрос или инлайн функция которая возвращает нормальный int из невыровненного адреса. Городить какую-то функцию, которая будет разбитаться как именно невыровнен адрес а может и выровнен.... тода уж memcpy() - эта занимается тем-же самым, но понятно, что делает. И все это ради того, что-бы отвергать великолепный механизм паковки и доступа к структурам. Дурдом. Но понятный после этого заявления: в единственном случае где могут понадобится упакованные структуры и где без этого вполне можно обойтись - в случае с протоколами обмена становится понятным, что задачи обмена данными бесконечно далеки от Вас и "контроллеров светодиодов". , там всё равно все доступы к структуре будут обёрнуты в hton / ntoh. C какого бодуна, если это зависит от протокола и контрорлера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 78 16 февраля, 2016 Опубликовано 16 февраля, 2016 · Жалоба Городить какую-то функцию, которая будет разбитаться как именно невыровнен адрес а может и выровнен.... тода уж memcpy() - эта занимается тем-же самым, но понятно, что делает. И все это ради того, что-бы отвергать великолепный механизм паковки и доступа к структурам. Дурдом. Этот великолепный механизм - костыли которые в каждом компиляторе сделаны (и хорошо если в каждом) по своему. Вон у TI, TCP стэк для msp430, как-то обошлись без великолепных механизмов. И раз уж Вы так близки к задачам обмена данными, не приведёте код объявления упакованной структуры который любой С компилятор поймёт? C какого бодуна, если это зависит от протокола и контрорлера. endiannes у всех всех контроллеров вдруг стала одинаковая и так получиться так что она будет отличаться от заданной в протоколе никак не может? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться