реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Выравнивание в gcc, Обращение по нечётным адресам
xelax
сообщение Sep 7 2007, 06:21
Сообщение #1


Местный
***

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



Есть задача перенести код с avr на arm (компилятор gcc). Люди, которые писали программу на avr активно использовали атрибут packed для структур, затем передавали данные структуры по сериальному интерфейсу.

При переходе на arm вот с чем столкнулся. Компилятор с дериктивой packed честно пакует данные без выравнивания, а далее при попытки записать и прочитать 16, 32 - разрядные переменные, запакованные по нечётным адресам вызывает переходя ядра arm в abort mode.

Есть ли какая возможность обойти данную особенность архитектуры с помощью компилятора. Например деректива какая-нибудь. Что бы он например при обращении по нечётным адресам, делал вычитывание побайтно, а затем собирал из них short или long.

Вообще кто-нибудь сталкивался с такой проблемой? И как решал её? help.gif
Go to the top of the page
 
+Quote Post
Puzan
сообщение Sep 7 2007, 06:36
Сообщение #2


Участник
*

Группа: Новичок
Сообщений: 30
Регистрация: 16-12-05
Пользователь №: 12 295



Директивами не исправить.
Попробуй сделать битовыми полями.

Сообщение отредактировал Puzan - Sep 7 2007, 06:38
Go to the top of the page
 
+Quote Post
xelax
сообщение Sep 7 2007, 07:13
Сообщение #3


Местный
***

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



Цитата(Puzan @ Sep 7 2007, 10:36) *
Директивами не исправить.
Попробуй сделать битовыми полями.


около ста файлов в проекте, очень не хочется отыскивать структуры и править их руками.

Вот нашёл в старых разделах форума
Цитата
1. Все memory allocator'ы выделяют "выровненные" блоки памяти. Можешь у себя это проверить выделив два блока памяти размером в байт и посмотреть на адреса соответствующих pointer'ов.
2. Если уж очень надо читать с невыровненного адреса существует специальный модификатор (по крайней мере в EVC++) - __unaligned, например - WORD __unaligned *pwD. Он нормально (только медленнее) читает с любого адреса.

Насчет Keil и прочих - не в курсе, но наверное есть что-то похожее


но такой или похожей фичи для gnu-gcc на их сайте найти не могу в упор.
Go to the top of the page
 
+Quote Post
amw
сообщение Sep 7 2007, 07:44
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847



Цитата(xelax @ Sep 7 2007, 09:21) *
Есть задача перенести код с avr на arm (компилятор gcc). Люди, которые писали программу на avr активно использовали атрибут packed для структур, затем передавали данные структуры по сериальному интерфейсу.

При переходе на arm вот с чем столкнулся. Компилятор с дериктивой packed честно пакует данные без выравнивания, а далее при попытки записать и прочитать 16, 32 - разрядные переменные, запакованные по нечётным адресам вызывает переходя ядра arm в abort mode.

Есть ли какая возможность обойти данную особенность архитектуры с помощью компилятора. Например деректива какая-нибудь. Что бы он например при обращении по нечётным адресам, делал вычитывание побайтно, а затем собирал из них short или long.

Вообще кто-нибудь сталкивался с такой проблемой? И как решал её? help.gif

Код
typedef struct _ustr {
char c;
int i;
} __attribute__ ((packed)) ustr_t;

int x;
ustr_t str;
str.i = 5;
x = str.i;

GCC 3.4.5 AT91SAM7S256 - все работает.


В догонку дизассемблируем прведенный выше код
Код
    str.i = 5;
    8180:    e59f2060     ldr    r2, [pc, #96]; 81e8 <.text+0x1cc>
    8184:    e3a03000     mov    r3, #0; 0x0
    8188:    e3833005     orr    r3, r3, #5; 0x5
    818c:    e5c23001     strb    r3, [r2, #1]
    8190:    e3a03000     mov    r3, #0; 0x0
    8194:    e5c23002     strb    r3, [r2, #2]
    8198:    e3a03000     mov    r3, #0; 0x0
    819c:    e5c23003     strb    r3, [r2, #3]
    81a0:    e3a03000     mov    r3, #0; 0x0
    81a4:    e5c23004     strb    r3, [r2, #4]
    x = str.i;
    81a8:    e59f003c     ldr    r0, [pc, #60]; 81ec <.text+0x1d0>
    81ac:    e59f2034     ldr    r2, [pc, #52]; 81e8 <.text+0x1cc>
    81b0:    e5d21001     ldrb    r1, [r2, #1]
    81b4:    e5d23002     ldrb    r3, [r2, #2]
    81b8:    e1a03403     mov    r3, r3, lsl #8
    81bc:    e1831001     orr    r1, r3, r1
    81c0:    e5d23003     ldrb    r3, [r2, #3]
    81c4:    e1a03803     mov    r3, r3, lsl #16
    81c8:    e1831001     orr    r1, r3, r1
    81cc:    e5d23004     ldrb    r3, [r2, #4]
    81d0:    e1a03c03     mov    r3, r3, lsl #24
    81d4:    e1833001     orr    r3, r3, r1
    81d8:    e5803000     str    r3, [r0]

Как видим - доступ побайтный и OR со сдвигом.
Все в порядке.


--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть.
© Lewis Carroll. Alice's adventures in wonderland.
Go to the top of the page
 
+Quote Post
xelax
сообщение Sep 7 2007, 07:53
Сообщение #5


Местный
***

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



Код
#define PACK __attribute__ ((__packed__))

typedef struct
{
  uint8_t  a;
  uint16_t b;
  uint32_t d;
  uint8_t  c;
} PACK my_packed_struct;      

void test(void)
{
  my_packed_struct  str;
  my_packed_struct* pstr;
  uint8_t*  pa;
  uint16_t*  pb;
  uint32_t*  pd;
  uint8_t*  pc;    
  uint16_t q = 1;
  
  pstr = &str;
  pa = &(pstr->a);
  pb = &(pstr->b);
  pd = &(pstr->d);
  pc = &(pstr->c);  
  *pb = q;
}


Пухнет и дохнет. uint32_t и uint16_t. Расположенны по нечётным адресам. Смотрел дебагером.

А ваш пример действительно работает, так как он начало структуры кладёт по нечётному адресу.

GCC-4.1.1 sam7x256

З.Ы.

Только что проверил такой код
Код
pstr = &str;
  pa = &(pstr->a);
  pstr->b = q;
  pb = &(pstr->b);
  pd = &(pstr->d);
  pc = &(pstr->c);  
  *pb = q;


pstr->b = q; ---- работает, хотя pb после присваивания указывает на нечётный адрес.
вот дизасм кода.
Код
pstr->b = q;
  100d80:    e51b0024     ldr    r0, [fp, #-36]
  100d84:    e55b100e     ldrb    r1, [fp, #-14]
  100d88:    e3a03000     mov    r3, #0; 0x0
  100d8c:    e1a02003     mov    r2, r3
  100d90:    e1a03001     mov    r3, r1
  100d94:    e1823003     orr    r3, r2, r3
  100d98:    e5c03001     strb    r3, [r0, #1]
  100d9c:    e55b100d     ldrb    r1, [fp, #-13]
  100da0:    e3a03000     mov    r3, #0; 0x0
  100da4:    e1a02003     mov    r2, r3
  100da8:    e1a03001     mov    r3, r1
  100dac:    e1823003     orr    r3, r2, r3
  100db0:    e5c03002     strb    r3, [r0, #2]


Отрадно конечно, но всё равно половина присваиваний в коде идёт через разыменование указателей.
crying.gif

Сообщение отредактировал xelax - Sep 7 2007, 08:21
Go to the top of the page
 
+Quote Post
abcdefg
сообщение Sep 7 2007, 08:16
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 201
Регистрация: 23-01-06
Из: Msk
Пользователь №: 13 490



Цитата(Puzan @ Sep 7 2007, 10:36) *
Директивами не исправить.
Попробуй сделать битовыми полями.


Наверно имелось ввиду байтовые?!

имел похожу проблему в keil'е, пришлось менять на массивы байтов...
Go to the top of the page
 
+Quote Post
amw
сообщение Sep 7 2007, 08:18
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847



Цитата
А ваш пример действительно работает, так как он начало структуры кладёт по нечётному адресу.


Нет. Структура расположена расположена по адресу 0x000083f4. А int поле - по нечетному соответственно. Смотри вложение.
Сейчас посмотрю Ваш вариант.

Сообщение отредактировал amw - Sep 7 2007, 08:19
Прикрепленные файлы
Прикрепленный файл  alignment.zip ( 22.88 килобайт ) Кол-во скачиваний: 51
 


--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть.
© Lewis Carroll. Alice's adventures in wonderland.
Go to the top of the page
 
+Quote Post
xelax
сообщение Sep 7 2007, 08:24
Сообщение #8


Местный
***

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



Цитата(amw @ Sep 7 2007, 12:18) *
Нет. Структура расположена расположена по адресу 0x000083f4. А int поле - по нечетному соответственно. Смотри вложение.
Сейчас посмотрю Ваш вариант.

видимо зависит от проектной реализации. У меня наоборот начало структуры по нечётному было, а переменная по чётному.
Go to the top of the page
 
+Quote Post
amw
сообщение Sep 7 2007, 08:32
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847



Цитата(xelax @ Sep 7 2007, 11:24) *
видимо зависит от проектной реализации. У меня наоборот начало структуры по нечётному было, а переменная по чётному.

Не понял.

Код
    *pb = q;
    81c0:    e51b2020     ldr    r2, [fp, #-32]
    81c4:    e15b32ba     ldrh    r3, [fp, #-42]
    81c8:    e1c230b0     strh    r3, [r2]
    pstr->b = q;
    81cc:    e51b0018     ldr    r0, [fp, #-24]
    81d0:    e55b102a     ldrb    r1, [fp, #-42]
    81d4:    e3a03000     mov    r3, #0; 0x0
    81d8:    e1a02003     mov    r2, r3
    81dc:    e1a03001     mov    r3, r1
    81e0:    e1823003     orr    r3, r2, r3
    81e4:    e5c03001     strb    r3, [r0, #1]
    81e8:    e55b1029     ldrb    r1, [fp, #-41]
    81ec:    e3a03000     mov    r3, #0; 0x0
    81f0:    e1a02003     mov    r2, r3
    81f4:    e1a03001     mov    r3, r1
    81f8:    e1823003     orr    r3, r2, r3
    81fc:    e5c03002     strb    r3, [r0, #2]

Да, с разименованием работает, а через указатель - нет.
Потому как typedef unsigned short uint16_t - требует расположения по четному адресу.


--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть.
© Lewis Carroll. Alice's adventures in wonderland.
Go to the top of the page
 
+Quote Post
Puzan
сообщение Sep 7 2007, 08:42
Сообщение #10


Участник
*

Группа: Новичок
Сообщений: 30
Регистрация: 16-12-05
Пользователь №: 12 295



С указателями на поля по-любому не получится. С указателем на структуру и разыменованием работает.
Go to the top of the page
 
+Quote Post
scifi
сообщение Sep 7 2007, 08:47
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Если при попытке сделать чтение или запись по неровному адресу процессор генерирует исключение, то можно в обработчике исключения реализовать чтение и запись по неровному адресу. К примеру, Linux так и делает, см. linux/arch/arm/mm/alignement.c.
Go to the top of the page
 
+Quote Post
xelax
сообщение Sep 7 2007, 09:08
Сообщение #12


Местный
***

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



Цитата(scifi @ Sep 7 2007, 12:47) *
Если при попытке сделать чтение или запись по неровному адресу процессор генерирует исключение, то можно в обработчике исключения реализовать чтение и запись по неровному адресу. К примеру, Linux так и делает, см. linux/arch/arm/mm/alignement.c.


07.gif Это где такой файл???

Если не тяжело приаттачте сюда плизз.

Цитата
(xelax @ Sep 7 2007, 11:24) *

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

Не понял.


имеется в виду я Ваш код не отдельно компилил, а в свой проект вставил.
Go to the top of the page
 
+Quote Post
scifi
сообщение Sep 7 2007, 09:19
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(xelax @ Sep 7 2007, 13:08) *
07.gif Это где такой файл???

Если не тяжело приаттачте сюда плизз.
имеется в виду я Ваш код не отдельно компилил, а в свой проект вставил.

http://www.google.com/search?hl=en&q=l.../mm/alignment.c
Go to the top of the page
 
+Quote Post
xelax
сообщение Sep 10 2007, 07:09
Сообщение #14


Местный
***

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



Цитата(scifi @ Sep 7 2007, 12:47) *
Если при попытке сделать чтение или запись по неровному адресу процессор генерирует исключение, то можно в обработчике исключения реализовать чтение и запись по неровному адресу. К примеру, Linux так и делает, см. linux/arch/arm/mm/alignement.c.


Посмотрел я исходник линукса... wacko.gif Видимо я ещё не осознал суть матрицы, так как конвертация thumb инструкций на лету из arm инструкций не поддалась моему разуму. В джедаи не годен smile.gif

А если серьёзно, то такой вопрос возник: в регистрах контроллера памяти я могу посмотреть адрес памяти при доступе к которому возникла ошибка, разрядность и тип этого доступа. Для того чтобы самому завершить запись или чтение в побайтном режиме не хватает для полноты информации адреса куда записать считываемые данные (при ошибки чтения) или адреса откуда записывались данные (при ошибки записи).

Где взять недостающие данные? Есть ли простое решение этой задачки?

Сообщение отредактировал xelax - Sep 10 2007, 07:10
Go to the top of the page
 
+Quote Post
Alex03
сообщение Sep 10 2007, 07:34
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



Цитата(xelax @ Sep 10 2007, 13:09) *
А если серьёзно, то такой вопрос возник: в регистрах контроллера памяти я могу посмотреть адрес памяти при доступе к которому возникла ошибка, разрядность и тип этого доступа.

Эт кто такие данные предоставляет?
Цитата
Для того чтобы самому завершить запись или чтение в побайтном режиме не хватает для полноты информации адреса куда записать считываемые данные (при ошибки чтения) или адреса откуда записывались данные (при ошибки записи).

А это видимо в любом случае регистр. Какой? Кроме как из кода операции видимо никак не узнать.
Цитата
Где взять недостающие данные? Есть ли простое решение этой задачки?

ИМХО простого решения тут видимо нет. Если есть возможность, т.е. не устаканен этот бинарный протокол связи с внешним миром, то можно попереупорядочивать элементы в структурах. Но в ряде случаев это не возможно...


А вообще когдато был топик примерно на эту тему, точно не помню, но по моему вывод был такой:
Ядро ARM - это одно, а контроллер памяти это другое. Простой контроллер памяти генерит исключение, более продвинутый разбивает одно обращение к памяти на несколько.
Вплоть до того что один и тотже пример на чипах разных производителей на ARM7 ядре давал разные результаты.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 21:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.01542 секунд с 7
ELECTRONIX ©2004-2016