Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: проблемы с выравниванием ARM7
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
dimka76
Есть такой код для процессора ARM7
Код
char     data[256];

void foo(void)
{
   int parametr = 0xAA55BBCC;
   char*   ptr = data;

   //если сделать так
  *((int*)(ptr+1)) = paramtr;
  // то прцессор вылетет в DataAbort

  // можно сделать конечно так
  memcpy(ptr+1, &parametr, sizeof(parametr));

}


Последний вариант конечно работоспособный, но может быть есть какие-то более изящные решения?
zltigo
Цитата(dimka76 @ Jun 25 2009, 08:59) *
Последний вариант конечно работоспособный, но может быть есть какие-то более изящные решения?

Или "правильно" писать программы c "правильными" структурами данных. Или не сбивать с толку компилятор и дать ему инфрмацию об объекте с которым он работает. Либо действительно пользоваться memcpy(), котрая разберется с проблемой в online.
dimka76
Цитата(zltigo @ Jun 25 2009, 10:19) *
Или "правильно" писать программы c "правильными" структурами данных. Или не сбивать с толку компилятор и дать ему инфрмацию об объекте с которым он работает. Либо действительно пользоваться memcpy(), котрая разберется с проблемой в online.


С "правильной" структурой данных не получается. Т.к. тип передаваемых данных в data[] в разных местах программы может быть разным. data[] это массив для передачи донных из процессора по запросу внешнего устройства. А внешнее устройство в одном случае может запросить данные типа time_t, а в другом данные типа char.
Axel
Это не "проблема", это - факт "наличия присутствия" выравнивания. Общая техника в этих случаях - обращаться к переменным по адресам, кратным их (переменных) формату. А если не получается - перегонять байты (напрямую или memcpy()) и формировать типы ручками.
dimka76
Всем спасибо за ответы. smile.gif
Тему можно считать закрытой
zltigo
Цитата(dimka76 @ Jun 25 2009, 09:34) *
С "правильной" структурой данных не получается. Т.к. тип передаваемых данных в data[] в разных местах программы может быть разным.

Значит и структуры данных должны быть описаны для разных случаев и объединены в union. Что по любому полезно, ибо общение в стиле второй бит слева в 33 байте справа в массиве data по любому путь у никуда.
Сергей Борщ
Цитата(Axel @ Jun 25 2009, 09:41) *
перегонять байты (напрямую или memcpy()) и формировать типы ручками.
Зачем же? Существует такое понятие, как упаковка структур:
Код
#include  <stdint.h>
uint8_t Buffer[256];


typedef struct
__attribute__((packed))
{
   uint8_t   Data1;
   uint32_t  Data2;
} answer_t;

void foo(void)
{

    int parametr = 0xAA55BBCC;
    answer_t * pAnswer = (answer_t *)Buffer;

    pAnswer->Data2 = paramtr;
    pAnswer->Data1 = 0x12;

}
Пример для GCC, для других компиляторов с высокой долей вероятности будет #pragma pack(1)
xelax
Цитата(zltigo @ Jun 25 2009, 10:19) *
Либо действительно пользоваться memcpy(), котрая разберется с проблемой в online.


Очень редко у меня возникали случаи когда внутри memcpy появлялся аборт. Так что memcpy не панацея.
Либо не пудрить мозг компилятору, либо писать свою функцию memcpy, которая 100% не допустит аборта.
dimka76
Цитата(Сергей Борщ @ Jun 25 2009, 11:29) *
Зачем же? Существует такое понятие, как упаковка структур:


Спасибо !!! Так работает.
Выглядит читабельно, но копирование происходит побайтно ( смотрел листинг в IAR).
Но от этого никуда не денешься в данной ситуации.
VslavX
Цитата(Сергей Борщ @ Jun 25 2009, 10:29) *
Пример для GCC, для других компиляторов с высокой долей вероятности будет #pragma pack(1)

GCC 4.x тоже уже поддерживает "#pragma pack" - не так давно был сам приятно удивлен
Сергей Борщ
Цитата(dimka76 @ Jun 25 2009, 11:42) *
но копирование происходит побайтно ( смотрел листинг в IAR).
А как вы хотели, если только побайтно можно обратиться к любому адресу? Не, ну если заранее знать, что 4-байтовое число расположено со сдвигом на 1 байт, то можно скопировать первый байт, потом полуслово и потом последний байт, но такое - только ручками.
zltigo
Цитата(xelax @ Jun 25 2009, 10:41) *
Очень редко у меня возникали случаи когда внутри memcpy появлялся аборт. Так что memcpy не панацея.

Не говорите глупости. Охотно верю, что Вы копируете неаонятно куда и непонятно откуда и получаете Abort, только выравнивание здесь совсем ни причем - это чисто Ваши ошибки.


Цитата(Сергей Борщ @ Jun 25 2009, 12:41) *
но такое - только ручками.

Такое, и даже большее (при копировании больших массивов) делает хоть сколько нибудь приличное библиотечное memcpy().
Сергей Борщ
Цитата(zltigo @ Jun 25 2009, 13:08) *
Такое, и даже большее (при копировании больших массивов) делает хоть сколько нибудь приличное библиотечное memcpy().
Потратив время на разбор - к какому из заготовленных сценариев отнести конкретный случай. Что для случая 4-байтовой или 2-байтовой переменной даст проигрыш во времени по сравнению с побайтовым копированием по месту. На больших структурах, да, эффект будет.
SasaVitebsk
А я выравниваю при получении. В месте получения всё равно ведь вы каким-то образом уже тип структуры получаете. Так вот я определяю тип и выравниваю, если нужно. А в проге работаю уже с выровненными данными. Правда у меня таких мест немного и потери памяти несущественны.
xelax
Цитата(zltigo @ Jun 25 2009, 14:08) *
Не говорите глупости. Охотно верю, что Вы копируете неаонятно куда и непонятно откуда и получаете Abort, только выравнивание здесь совсем ни причем - это чисто Ваши ошибки.


Жаль, что не сохранил дизасм для неверующих. Замена memcpy на цикл с побайтным присваиванием непонятно куда из непонятно откуда чудесным образом всё починило.

P.S. Моя первая реакция на такое чудо была такая же как у Вас на мой пост в теме.
aaarrr
Цитата(xelax @ Jun 25 2009, 14:39) *
Жаль, что не сохранил дизасм для неверующих. Замена memcpy на цикл с побайтным присваиванием непонятно куда из непонятно откуда чудесным образом всё починило. biggrin.gif

Что ровным счетом ничего не доказывает. Конкретную причину abort'а нашли?
zltigo
Цитата(xelax @ Jun 25 2009, 13:39) *
непонятно куда из непонятно откуда чудесным образом всё починило.

Вот и разбирались-бы с непонятками, а memcpy() это, так сказать, святое smile.gif и при этом достаточно простое, дабы уже лет 30 не содержать ошибок ни в одной из реализаций.
xelax
Цитата(zltigo @ Jun 25 2009, 14:51) *
Вот и разбирались-бы с непонятками, а memcpy() это, так сказать, святое smile.gif и при этом достаточно простое, дабы уже лет 30 не содержать ошибок ни в одной из реализаций.


Согласен, что простое... Я и не утверждаю что в memcpy есть ошибка, уверен что такие вещи сто раз отладили. Я вот что пытаюсь донести. Есть пердположение, что компилятор лепит в проект несколько реализаций данной функции, в зависимости от разрядности копируемых данных(байтное, 2байтное и 4байтное)? И стоит ему потерять (в результате действий программиста) атрибут packed для какой-нибудь структуры и он запросто применит пословное копирование вместо побайтного(имеет полное право на оптимизацию). И тут то и случится abort именно внутри memcpy.

Моё ИМХО, что в общем случае от абортов нельзя защищаться memcpy. Это всего лишь уменьшит вероятность ошибки, но не устранит причину.
aaarrr
Цитата(xelax @ Jun 25 2009, 18:54) *
Есть пердположение, что компилятор лепит в проект несколько реализаций данной функции, в зависимости от разрядности копируемых данных(байтное, 2байтное и 4байтное)?

Реализация одна. Да и какой смысл делать несколько, если использовать их можно будет только когда оба адреса константны?
defunct
Цитата(xelax @ Jun 25 2009, 17:54) *
Моё ИМХО, что в общем случае от абортов нельзя защищаться memcpy. Это всего лишь уменьшит вероятность ошибки, но не устранит причину.

Странный вывод. Вопрос на самом деле шире - дилемма между скоростью и надежностью:

1. *(U32*) xxxx = zz; - это быстро но чревато абортом.
2. memcpy - медленно и надежно, от Align Exception'а - это самая лучшая защита, если скорость не жмет.

Сказки про глючный memcpy травить не нужно, т.к. ничто не мешает послать библиотечку куда подальше и написать свой "безглючный" вариант memcpy.
aaarrr
Цитата(xelax @ Jun 25 2009, 18:54) *
Моё ИМХО, что в общем случае от абортов нельзя защищаться memcpy. Это всего лишь уменьшит вероятность ошибки, но не устранит причину.

От абортов вообще нельзя защищаться. Их просто не должно быть.
xelax
Цитата(defunct @ Jun 25 2009, 19:06) *
Сказки про глючный memcpy травить не нужно, т.к. ничто не мешает послать библиотечку куда подальше и написать свой "безглючный" вариант memcpy.


Ткните пальцем где я написал, о том что memcpy глючит??? maniac.gif Читать мой пост до полного осознания того, что я написал, прежде чем лицом об асфальт возить.
defunct
Цитата(xelax @ Jun 25 2009, 18:10) *
Ткните пальцем где я написал, о том что memcpy глючит??? maniac.gif

вот здесь
Цитата
Замена memcpy на цикл с побайтным присваиванием непонятно куда из непонятно откуда чудесным образом всё починило.
xelax
Цитата(defunct @ Jun 25 2009, 19:13) *
Цитата(xelax @ Jun 25 2009, 18:10) *

Замена memcpy на цикл с побайтным присваиванием непонятно куда из непонятно откуда чудесным образом всё починило.

вот здесь


В упор не вижу своих слов... memcpy глючит. Ненадо за меня додумывать.

сделал дизасм проекта с memcpy, с несколькими экземплярами memcpy я оказался неправ, но всё равно основное то копирование идёт пословно.
aaarrr
Цитата(xelax @ Jun 25 2009, 19:45) *
сделал дизасм проекта с memcpy, с несколькими экземплярами memcpy я оказался неправ, но всё равно основное то копирование идёт пословно.

Ну дык слова-то выровнены. И "сковырнуть" memcpy невыровненными адресами никак нельзя.
meister
Цитата(aaarrr @ Jun 25 2009, 19:49) *
Ну дык слова-то выровнены. И "сковырнуть" memcpy невыровненными адресами никак нельзя.


Код
void zuzu(int * to, int const * from)
{
    memcpy(to, from, sizeof(int));
}


нужна оптимизация с интрисик.
aaarrr
Цитата(meister @ Jun 25 2009, 20:09) *
нужна оптимизация с интрисик.

Поясните мысль.
meister
Цитата(aaarrr @ Jun 25 2009, 20:12) *
Поясните мысль.


Тут у меня не на чем сделать листинг, но при оптимизации по скорости с интрисик код получится такой же как от *to = *from, если нужно скопировать 3 int, то код будет такой же как от

Код
to[0] = from[0]; to[1] = from[1]; to[2] = from[2];
aaarrr
Понятно. Ну, это уже дела и проблемы оптимизатора - memcpy ведь как таковой нет.
zltigo
Цитата(xelax @ Jun 25 2009, 17:54) *
в зависимости от разрядности копируемых данных(байтное, 2байтное и 4байтное)?

5, 6, 7, 8, 9...... а еще начинающиеся с 0,1,2,.... а еще заканчивающиеся на 0,1,2,3.... smile.gif smile.gif
Вот, кода реализация в IAR была какая-то тормозная пользовал вместо библиотечной такое
Код
//---------------------------------------------------------------------------
// void *(memcpy)(void *p1, const void *p2, size_t n)
// Copy char p2[n] to p1[n]
//---------------------------------------------------------------------------
memcpy:
        teq      r2,#0                  // Is p1 == 0 ?
        bxeq     lr                     // If p1 == 0, return

        stmdb    sp!,{lr}               // Push return address
        mov      r12,r0                 // Copy pointer p1
        cmp      r2,#8                  // Is buffer long or short?
        ble      byteserial             // Jump if n <= 8

        sub      r3,r0,r1               // Compare pointers p1, p2
        tst      r3,#3                  // Strings aligned same?
        bne      byteserial             // Jump if buffers not aligned


// Both strings are similarly aligned WRT word boundaries.
// At least a portion of the data can be copied an entire
// word at a time, which is faster than copying bytes.
wordserial:
        ands     r3,r0,#3               // Check byte alignment
        beq      wordaligned            // Jump if p1, p2 word-aligned

        rsb      r3,r3,#4               // m = no. of odd initial bytes
        sub      r2,r2,r3               // n = n - m


// If the two buffers do not begin on word boundaries, begin
// by copying the odd bytes that precede the first full word.
preloop:
        ldrb     lr,[r1],#1             // Read byte from source
        subs     r3,r3,#1               // --m (decrement loop count)
        strb     lr,[r12],#1            // Write byte to destination
        bne      preloop                // Loop if more bytes to move


wordaligned:
#if WORDS8_TRANSFER == 1
        movs     r3,r2,asr #5           // Any chunks of 8 words?
        beq      octsdone               // Jump if no 8-word chunks

        and      r2,r2,#0x1F            // Subtract chunks from n
        stmdb    sp!,{r4-r10}           // Save registers on stack


// The strings are long enough that we can transfer at least
// some portion of the data in 8-word chunks.
octloop:
        ldmia    r1!,{r4-r10,lr}        // Load 8 words from source
        subs     r3,r3,#1               // More 8-word chunks to move?
        stmia    r12!,{r4-r10,lr}       // Write 8 words to destination
        bne      octloop                // Loop if more chunks

        ldmia    sp!,{r4-r10}           // Restore registers from stack

octsdone:
#endif
        movs     r3,r2,asr #2           // Any more whole words to move?
        beq      wordsdone              // Jump if no more whole words


// Copy as much of the remaining data as possible one word at
// a time.
wordloop2:
        ldr      lr,[r1],#4             // Read next word from source
        subs     r3,r3,#1               // Decrement word count
        str      lr,[r12],#4            // Write next word to destination
        bne      wordloop2              // Loop while more words to move

wordsdone:
        ands     r2,r2,#3               // Any last bytes to transfer?
        beq      theend                 // Return if already done


// The two strings do not end on word boundaries.
// Copy the remaining data one byte at a time.
byteserial:
        ldrb     lr,[r1],#1             // Read byte from source
        subs     r2,r2,#1               // --n (decrement loop count)
        strb     lr,[r12],#1            // Write byte to destination
        bne      byteserial             // Loop if more bytes to move

theend:
        ldmia    sp!,{lr}               // Return
        bx       lr


Цитата(xelax @ Jun 25 2009, 18:45) *
но всё равно основное то копирование идёт пословно.

Зависит от реализации, пример, когда не только пословно, выше (под ключем WORDS8_TRANSFER)
defunct
Цитата(xelax @ Jun 25 2009, 18:45) *
В упор не вижу своих слов... memcpy глючит. Ненадо за меня додумывать.

Мы же тут не в политику играем и не в лингвистике упражняемся.

я не люблю недомолвок, каких-то закрученных фраз и пр., а стараюсь называть вещи своими именами.
То что вы пытались сказать: когда memcpy приводит в abort'у, а цикл с побайтовым копированием тех же самых данных к abort'у не приводит - иными словами кроме как memcpy глючит - более точно и прямо назвать нельзя.

Хотите чтобы за вас "не додумывали" - попробуйте выражайться всегда точно и прямо.
dimka76
Тут на форуме промелькивала фраза, что Cortex-M3 не требует выравнивания (сам я документацию на него не читал ).
Так, получается, что у него вообще DataAbort не существует?
xelax
Цитата(zltigo @ Jun 25 2009, 20:56) *
5, 6, 7, 8, 9...... а еще начинающиеся с 0,1,2,.... а еще заканчивающиеся на 0,1,2,3.... smile.gif smile.gif


С каждым новом постом у меня всё более нелепо отвечать получается.
Доводы у всех высказывающихся весомые, в отличие от моего "а я видел" smile3046.gif

Могу только добавить, что если вдруг моя "галюцинация" с data abort внутри memcpy повторится, обязательно сделаю скриншот дебагера и приатачу сюда. rolleyes.gif
aaarrr
Цитата(dimka76 @ Jun 26 2009, 09:13) *
Тут на форуме промелькивала фраза, что Cortex-M3 не требует выравнивания (сам я документацию на него не читал ).

В некоторых случаях - LDM/STM/LDRD/STRD - требует. Кроме того, можно принудительно включить проверку выравнивания для любых операций.

Цитата(xelax @ Jun 26 2009, 10:30) *
Могу только добавить, что если вдруг моя "галюцинация" с data abort внутри memcpy повторится, обязательно сделаю скриншот дебагера и приатачу сюда. rolleyes.gif

Это не пройдет. Нужен отчет с причиной возникновения abort'а внутри memcpy, причем нужен в первую очередь Вам.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.