Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Запись int по указателю на произвольный адрес и выравнивание
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
0x435641
Доброго времени суток.

начну с кода:

char arr[16];

int *pi1 = (int*)arr[0];
int *pi2 = (int*)arr[1];
int *pi3 = (int*)arr[2];
int *pi4 = (int*)arr[3];

*pi1 = 0x11223344;
*pi2 = 0x11223344;
*pi3 = 0x11223344;
*pi4 = 0x11223344;


среда IAR 6.30.1

в результате запись происходит по адресам со сдвигом влево до границы кратной размеру адресуемого типа. это смотрел через J-Link
в листинге каждая запись производится инструкцией STR R0, [Rx]... при чем в Rx лежат правильные значения с шагом в 1 байт.

тот же результат в uVision 4

если же запустить отладку в симуляторе, то при каждой записи по не кратному адресу вылетает сообщение
"STR instruction at addr: 0x40006835 made an illegal unaligned access to 0x40006835"

информации о том, что адрес должен быть выровнен для STR/LDR по 4 байтам для STRH/LDRH по 2 байта я не нашел.
пусть даже должен быть выровнен. почему компилятор не преобразует команду записи по указателю в набор инструкций с побайтовой записью, учитывая специфику адресации?
demiurg_spb
применяйте атрибут __packed к указателю
http://www.keil.com/support/man/docs/armcc...ef_CJAFJHJD.htm
0x435641
я работаю в IAR. кейл только для проверки использовал.

__packed int *pi1 = (int*)&arr[0];
__packed int *pi2 = (int*)&arr[1];
__packed int *pi3 = (int*)&arr[2];
__packed int *pi4 = (int*)&arr[3];

*pi1 = 0x11223344;
*pi2 = 0x11223344;
*pi3 = 0x11223344;
*pi4 = 0x11223344;


в симуляторе с теми же сообщениями, но память заполнилась правильно. через J-Link опять все легло поверх в одно место
кстати в ASM листинге без изменений - те же инструкции
demiurg_spb
В IAR тоже должны быть аналогичные средства. Ищите в справке по слову pack или packed.

Цитата(0x435641 @ Jul 26 2012, 09:29) *
опять все легло поверх в одно место
да вроде так и должно быть (с перекрытием инты должны были ложиться):

44 44 44 44 33 22 11 NA NA NA NA NA NA NA NA NA
scifi
Цитата(0x435641 @ Jul 26 2012, 09:19) *
если же запустить отладку в симуляторе, то при каждой записи по не кратному адресу вылетает сообщение
"STR instruction at addr: 0x40006835 made an illegal unaligned access to 0x40006835"

Значит симулятор неточно симулирует ядро Cortex-M3 (речь ведь о нём?).

Цитата(0x435641 @ Jul 26 2012, 09:19) *
пусть даже должен быть выровнен. почему компилятор не преобразует команду записи по указателю в набор инструкций с побайтовой записью, учитывая специфику адресации?

Компилятор не пытается отслеживать кратность указателя. Если кратность нарушается, то это ответственность автора кода: в Cortex-M3 поддерживается доступ по неровному адресу. Для побайтового доступа есть packed, как уже говорили.
0x435641
Цитата(demiurg_spb @ Jul 26 2012, 12:33) *
В IAR тоже должны быть аналогичные средства. Ищите в справке по слову pack или packed.


int __packed * p; A pointer to a packed integer.
int * __packed p; A packed pointer to an integer.
__packed int * p; A packed pointer to an integer.

спасибо за наводку. оказывается есть разница где атрибут ставить...

Цитата(demiurg_spb @ Jul 26 2012, 12:38) *
В IAR тоже должны быть аналогичные средства. Ищите в справке по слову pack или packed.

да вроде так и должно быть (с перекрытием инты должны были ложиться):

44 44 44 44 33 22 11 NA NA NA NA NA NA NA NA NA



в том то и дело что ложится в одно место так: 44 33 22 11 NA NA NA NA NA NA NA NA NA

СПАСИБО! тема закрыта, __packed в правильном месте помог )
PoReX
Цитата(0x435641 @ Jul 26 2012, 09:19) *
начну с кода:

char arr[16];

int *pi1 = (int*)arr[0];
int *pi2 = (int*)arr[1];
int *pi3 = (int*)arr[2];
int *pi4 = (int*)arr[3];

*pi1 = 0x11223344;
*pi2 = 0x11223344;
*pi3 = 0x11223344;
*pi4 = 0x11223344;


среда IAR 6.30.1

Вообще-то код изначально не правильный. После инициализации массива он может содержать мусор и этот мусор вы преобразуете в указатель. Например:
Код
char arr[8]={0,1,2,3,4,5,6,7};

тогда
Код
pi1 == 0x00000000;
pi2 == 0x00000001;
pi3 == 0x00000002;
pi4 == 0x00000003;

А если
Код
char arr[8]={0,0,0,0,0,0,0,0};

то и получится
Цитата
44 33 22 11 NA NA NA NA

правда в реальном контроллере это вызовет HardFault
А чтобы получить необходимый результат
Цитата
44 44 44 44 33 22 11 NA

нужно немного изменить код:
Код
int *pi1 = (int*)&arr[0];
    int *pi2 = (int*)&arr[1];
    int *pi3 = (int*)&arr[2];
    int *pi4 = (int*)&arr[3];

и никакой __packed не нужен. Проверено в Keil'e через j-tag на stm32f103.
demiurg_spb
Я то и не заметил отсутствие взятия адреса у вопрошающего...
А насчёт того что packed не нужен - я бы не был так категоричен. Иногда он очень даже нужен.
PoReX
Цитата(demiurg_spb @ Jul 26 2012, 11:27) *
А насчёт того что packed не нужен - я бы не был так категоричен. Иногда он очень даже нужен.

Имелось ввиду в данном случае не нужен. Кстати __packed это фишка Keil'a/IAR или он есть в стандарте Cи?
scifi
Цитата(PoReX @ Jul 26 2012, 11:32) *
Имелось ввиду в данном случае не нужен. Кстати __packed это фишка Keil'a/IAR или он есть в стандарте Cи?

Нет его в стандарте. Стандартными средствами можно склеивать по байтам (сдвигами или через указатель на char).
PoReX
Цитата(scifi @ Jul 26 2012, 11:51) *
Нет его в стандарте.

Жаль, а то думал заменить им #pragma pack для структур.
scifi
Цитата(PoReX @ Jul 26 2012, 12:05) *
Жаль, а то думал заменить им #pragma pack для структур.

#pragma pack тоже нет в стандарте, так что какая разница? :-)
В то же время #pragma pack поддерживается достаточно широко, то есть почти стандарт де факто.
jcxz
Почти да не почти - в CCS не поддерживается.
PoReX
Цитата(scifi @ Jul 26 2012, 12:38) *
#pragma pack тоже нет в стандарте, так что какая разница? :-)

Хм...думал есть в стандарте. Ну и фиг с ним, главное, что он широко поддерживается и на различных компиляторах работает одинаково. Часто бывает необходимым использовать один и тот же заголовочник в Keil и Qt:)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.