|
проблемы с выравниванием ARM7 |
|
|
|
Jun 25 2009, 05:59
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Есть такой код для процессора ARM7 Код char data[256];
void foo(void) { int parametr = 0xAA55BBCC; char* ptr = data;
//если сделать так *((int*)(ptr+1)) = paramtr; // то прцессор вылетет в DataAbort
// можно сделать конечно так memcpy(ptr+1, ¶metr, sizeof(parametr));
} Последний вариант конечно работоспособный, но может быть есть какие-то более изящные решения?
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 33)
|
Jun 25 2009, 07:29
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(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)
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 25 2009, 07:41
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(zltigo @ Jun 25 2009, 10:19)  Либо действительно пользоваться memcpy(), котрая разберется с проблемой в online. Очень редко у меня возникали случаи когда внутри memcpy появлялся аборт. Так что memcpy не панацея. Либо не пудрить мозг компилятору, либо писать свою функцию memcpy, которая 100% не допустит аборта.
|
|
|
|
|
Jun 25 2009, 08:42
|

developer
   
Группа: Свой
Сообщений: 902
Регистрация: 12-04-06
Из: Казань
Пользователь №: 16 032

|
Цитата(Сергей Борщ @ Jun 25 2009, 11:29)  Зачем же? Существует такое понятие, как упаковка структур: Спасибо !!! Так работает. Выглядит читабельно, но копирование происходит побайтно ( смотрел листинг в IAR). Но от этого никуда не денешься в данной ситуации.
--------------------
Все может быть и быть все может, и лишь того не может быть-чего уж точно быть не может, хотя..и это может быть.
|
|
|
|
|
Jun 25 2009, 09:41
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(dimka76 @ Jun 25 2009, 11:42)  но копирование происходит побайтно ( смотрел листинг в IAR). А как вы хотели, если только побайтно можно обратиться к любому адресу? Не, ну если заранее знать, что 4-байтовое число расположено со сдвигом на 1 байт, то можно скопировать первый байт, потом полуслово и потом последний байт, но такое - только ручками.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 25 2009, 10:08
|

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

|
Цитата(xelax @ Jun 25 2009, 10:41)  Очень редко у меня возникали случаи когда внутри memcpy появлялся аборт. Так что memcpy не панацея. Не говорите глупости. Охотно верю, что Вы копируете неаонятно куда и непонятно откуда и получаете Abort, только выравнивание здесь совсем ни причем - это чисто Ваши ошибки. Цитата(Сергей Борщ @ Jun 25 2009, 12:41)  но такое - только ручками. Такое, и даже большее (при копировании больших массивов) делает хоть сколько нибудь приличное библиотечное memcpy().
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 25 2009, 10:39
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(zltigo @ Jun 25 2009, 14:08)  Не говорите глупости. Охотно верю, что Вы копируете неаонятно куда и непонятно откуда и получаете Abort, только выравнивание здесь совсем ни причем - это чисто Ваши ошибки. Жаль, что не сохранил дизасм для неверующих. Замена memcpy на цикл с побайтным присваиванием непонятно куда из непонятно откуда чудесным образом всё починило. P.S. Моя первая реакция на такое чудо была такая же как у Вас на мой пост в теме.
|
|
|
|
|
Jun 25 2009, 14:54
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(zltigo @ Jun 25 2009, 14:51)  Вот и разбирались-бы с непонятками, а memcpy() это, так сказать, святое  и при этом достаточно простое, дабы уже лет 30 не содержать ошибок ни в одной из реализаций. Согласен, что простое... Я и не утверждаю что в memcpy есть ошибка, уверен что такие вещи сто раз отладили. Я вот что пытаюсь донести. Есть пердположение, что компилятор лепит в проект несколько реализаций данной функции, в зависимости от разрядности копируемых данных(байтное, 2байтное и 4байтное)? И стоит ему потерять (в результате действий программиста) атрибут packed для какой-нибудь структуры и он запросто применит пословное копирование вместо побайтного(имеет полное право на оптимизацию). И тут то и случится abort именно внутри memcpy. Моё ИМХО, что в общем случае от абортов нельзя защищаться memcpy. Это всего лишь уменьшит вероятность ошибки, но не устранит причину.
|
|
|
|
|
Jun 25 2009, 15:06
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(xelax @ Jun 25 2009, 17:54)  Моё ИМХО, что в общем случае от абортов нельзя защищаться memcpy. Это всего лишь уменьшит вероятность ошибки, но не устранит причину. Странный вывод. Вопрос на самом деле шире - дилемма между скоростью и надежностью: 1. *(U32*) xxxx = zz; - это быстро но чревато абортом. 2. memcpy - медленно и надежно, от Align Exception'а - это самая лучшая защита, если скорость не жмет. Сказки про глючный memcpy травить не нужно, т.к. ничто не мешает послать библиотечку куда подальше и написать свой "безглючный" вариант memcpy.
|
|
|
|
|
Jun 25 2009, 15:45
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(defunct @ Jun 25 2009, 19:13)  Цитата(xelax @ Jun 25 2009, 18:10)  Замена memcpy на цикл с побайтным присваиванием непонятно куда из непонятно откуда чудесным образом всё починило.
вот здесь В упор не вижу своих слов... memcpy глючит. Ненадо за меня додумывать. сделал дизасм проекта с memcpy, с несколькими экземплярами memcpy я оказался неправ, но всё равно основное то копирование идёт пословно.
|
|
|
|
|
Jun 25 2009, 16:09
|

Местный
  
Группа: Участник
Сообщений: 219
Регистрация: 20-11-07
Пользователь №: 32 484

|
Цитата(aaarrr @ Jun 25 2009, 19:49)  Ну дык слова-то выровнены. И "сковырнуть" memcpy невыровненными адресами никак нельзя. Код void zuzu(int * to, int const * from) { memcpy(to, from, sizeof(int)); } нужна оптимизация с интрисик.
|
|
|
|
|
Jun 25 2009, 16:30
|

Местный
  
Группа: Участник
Сообщений: 219
Регистрация: 20-11-07
Пользователь №: 32 484

|
Цитата(aaarrr @ Jun 25 2009, 20:12)  Поясните мысль. Тут у меня не на чем сделать листинг, но при оптимизации по скорости с интрисик код получится такой же как от *to = *from, если нужно скопировать 3 int, то код будет такой же как от Код to[0] = from[0]; to[1] = from[1]; to[2] = from[2];
|
|
|
|
|
Jun 25 2009, 16:56
|

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

|
Цитата(xelax @ Jun 25 2009, 17:54)  в зависимости от разрядности копируемых данных(байтное, 2байтное и 4байтное)? 5, 6, 7, 8, 9...... а еще начинающиеся с 0,1,2,.... а еще заканчивающиеся на 0,1,2,3....  Вот, кода реализация в 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)
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 25 2009, 17:04
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(xelax @ Jun 25 2009, 18:45)  В упор не вижу своих слов... memcpy глючит. Ненадо за меня додумывать. Мы же тут не в политику играем и не в лингвистике упражняемся. я не люблю недомолвок, каких-то закрученных фраз и пр., а стараюсь называть вещи своими именами. То что вы пытались сказать: когда memcpy приводит в abort'у, а цикл с побайтовым копированием тех же самых данных к abort'у не приводит - иными словами кроме как memcpy глючит - более точно и прямо назвать нельзя. Хотите чтобы за вас "не додумывали" - попробуйте выражайться всегда точно и прямо.
|
|
|
|
|
Jun 26 2009, 06:30
|

Местный
  
Группа: Свой
Сообщений: 370
Регистрация: 7-11-06
Пользователь №: 22 035

|
Цитата(zltigo @ Jun 25 2009, 20:56)  5, 6, 7, 8, 9...... а еще начинающиеся с 0,1,2,.... а еще заканчивающиеся на 0,1,2,3....  С каждым новом постом у меня всё более нелепо отвечать получается. Доводы у всех высказывающихся весомые, в отличие от моего "а я видел" Могу только добавить, что если вдруг моя "галюцинация" с data abort внутри memcpy повторится, обязательно сделаю скриншот дебагера и приатачу сюда.
|
|
|
|
|
Jun 26 2009, 07:37
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(dimka76 @ Jun 26 2009, 09:13)  Тут на форуме промелькивала фраза, что Cortex-M3 не требует выравнивания (сам я документацию на него не читал ). В некоторых случаях - LDM/STM/LDRD/STRD - требует. Кроме того, можно принудительно включить проверку выравнивания для любых операций. Цитата(xelax @ Jun 26 2009, 10:30)  Могу только добавить, что если вдруг моя "галюцинация" с data abort внутри memcpy повторится, обязательно сделаю скриншот дебагера и приатачу сюда.  Это не пройдет. Нужен отчет с причиной возникновения abort'а внутри memcpy, причем нужен в первую очередь Вам.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|