|
|
  |
Odd address trap и LPC23xx, А что, LPC не генерит unaligned access exeption? |
|
|
|
Jan 18 2009, 13:30
|

embarrassed systems engineer
    
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038

|
Мне правда интересно. На ARM-е можно любой невыравненный USHORT (16-битное целое) загрузить за 3 инструкции Код ldrb R1, [R0, #0] ldrb R2, [R0, #1] orr R1, R1, R2, shl #8 Как можно грузить быстрее - ума не приложу  . Если даже воспользоваться изращенным способом загрузки от NXP - то все равно нужна проверка, что 16-битное не пересекает границу 32-битного слова. Вот я такой тестик запустил: Код { BYTE a[8]; DWORD i; for(i=0; i<sizeof(a); i++) a[i] = (BYTE)(i+1); dprintf("\r\n%08X %08X %08X %08X", *((PDWORD)&a[0]), *((PDWORD)&a[1]), *((PDWORD)&a[2]), *((PDWORD)&a[3])); } Результат: 04030201 01040302 02010403 03020104 То есть, действительно имеет место циклический сдвиг - так еще (дополнительно к проверке вмещения в одно слово) и старшие биты чистить надо. Не понимаю, где тут можно выиграть
|
|
|
|
|
Jan 18 2009, 14:29
|

embarrassed systems engineer
    
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038

|
Цитата(zltigo @ Jan 18 2009, 15:53)  У меня память под буфера внешняя и замена одного из двух ldrb из внешней памяти банальным tst регистр,#0x3 мне и понравилась, хотя и те-же "три инструкции", как понравилось и использование (кусочек на ASM) только одного регистра вместо 2 ( у Вас даже 3x ). Ну, допустим, доступ к внешней памяти медленный. Но ведь если, например, младшие два бита адреса равны 0x03, то все равно надо читать два раза из памяти - два последовательных DWORD/WORD-a. И дополнительная проверка на равенство этих битов адреса на 0x03 с последующим ветвлением/пропуском тоже нужна. Где собак зарыт? P.S. Переписал свой тестик на использование 16-битных невыравненных слов - там еще результаты мрачней. Ну никак за одно обращение два слова (16 или 32-битных) не читается. P.P.S. "Листинг, сестра, листинг"
|
|
|
|
|
Jan 18 2009, 15:32
|

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

|
Цитата(VslavX @ Jan 18 2009, 16:29)  Ну, допустим, доступ к внешней памяти медленный. Но ведь если, например, младшие два бита адреса равны 0x03, то все равно надо читать два раза из памяти - два последовательных DWORD/WORD-a. В этом моем случае - нет - все двухбайтовое. 0x3 я просто так использовал. Ну а в случае реального смещения на байт речь уже идет о той-же двухкратно разнице - 2 или 4 обращения. Цитата И дополнительная проверка на равенство этих битов адреса на 0x03 Одна команда Цитата с последующим ветвлением/пропуском тоже нужна. Где собак зарыт? Для ARM без ветвления  Цитата P.P.S. "Листинг, сестра, листинг"  Код tst R0,#0x3 ldrh R0,[R0, #+0] lsrne R0,R0,#+8 вместо Код ldrb R1,[R0, #+0] ldrb R0,[R0, #+1] orr R0,R1,R0, lsl #+8
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 18 2009, 15:43
|

Йа моск ;)
     
Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610

|
Цитата tst R0,#0x3 ldrh R0,[R0, #+0] lsrne R0,R0,#+8 Простите, а разве это работает? По меньшей мере tst #1 для полуслов нужен. Позже... чето я вообще не пойму, что тут и как...
--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
|
|
|
|
|
Jan 18 2009, 15:47
|

embarrassed systems engineer
    
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038

|
Код tst R0,#0x3 ldrh R0,[R0, #+0] lsrne R0,R0,#+8 А это правильно работает? Проверяли? У меня такой тест: Код { BYTE a[8]; DWORD i;
for(i=0; i<sizeof(a); i++) a[i] = (BYTE)(i+1); dprintf("\r\n%08X %08X %08X %08X", *((PDWORD)&a[0]), *((PDWORD)&a[1]), *((PDWORD)&a[2]), *((PDWORD)&a[3])); dprintf("\r\n%08X %08X %08X %08X %08X %08X %08X %08X", *((PWORD)&a[0]), *((PWORD)&a[1]), *((PWORD)&a[2]), *((PWORD)&a[3]), *((PWORD)&a[4]), *((PWORD)&a[5]), *((PWORD)&a[6]), *((PWORD)&a[7])); } Дает такой результат: 04030201 01040302 02010403 03020104 00000201 01000002 00000403 03000004 00000605 05000006 00000807 07000008 То есть, если читаем ldrh по смещению +1 - вместо 0x0302 получаем коктейль из 1 и 2. Если читать по +3, то вместо ожидаемых 0x0504 получаем опять смесь 3 и 4. Это для внутренней памяти на LPC23. Фрагмент листинга такой (чтобы было видно ldr и ldrh) Код \ 000001B8 03009DE5 LDR R0,[SP, #+3] \ 000001BC 01002DE9 PUSH {R0} \ 000001C0 06309DE5 LDR R3,[SP, #+6] \ 000001C4 05209DE5 LDR R2,[SP, #+5] \ 000001C8 04109DE5 LDR R1,[SP, #+4] \ 000001CC E80E84E2 ADD R0,R4,#+3712 \ 000001D0 ........ _BLF tn_debug_printf,??tn_debug_printf??rA \ 000001D4 BB00DDE1 LDRH R0,[SP, #+11] \ 000001D8 01002DE9 PUSH {R0} \ 000001DC BE00DDE1 LDRH R0,[SP, #+14] \ 000001E0 01002DE9 PUSH {R0} \ 000001E4 B101DDE1 LDRH R0,[SP, #+17] \ 000001E8 01002DE9 PUSH {R0} \ 000001EC B401DDE1 LDRH R0,[SP, #+20] \ 000001F0 01002DE9 PUSH {R0} \ 000001F4 B701DDE1 LDRH R0,[SP, #+23] \ 000001F8 01002DE9 PUSH {R0} \ 000001FC BA31DDE1 LDRH R3,[SP, #+26] \ 00000200 B921DDE1 LDRH R2,[SP, #+25] \ 00000204 B811DDE1 LDRH R1,[SP, #+24] \ 00000208 9800A0E3 MOV R0,#+152 \ 0000020C E00E80E3 ORR R0,R0,#0xE00 \ 00000210 040080E0 ADD R0,R0,R4 \ 00000214 ........ _BLF tn_debug_printf,??tn_debug_printf??rA \ 00000218 18D08DE2 ADD SP,SP,#+24 ;; stack cleaning "И чего люди не придумают - лишь бы "на картошку" не ехать"  BTW, мне не нравится как компилятор стеком распрядился - на 4 слова можно и меньше было бы.
|
|
|
|
|
Jan 18 2009, 16:05
|

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

|
Цитата(Rst7 @ Jan 18 2009, 17:43)  Простите, а разве это работает? В железе не проверял, но проблем не вижу. Сейчас поищу дома какую-нибудь железку.... Цитата По меньшей мере tst #1 для полуслов нужен. В моем случае неважно 3 или 1 - есть гарантированное выравнивание на 2. Цитата(VslavX @ Jan 18 2009, 17:47)  То есть, если читаем ldrh по смещению +1 - вместо 0x0302 получаем коктейль из 1 и 2. Если читать по +3, то вместо ожидаемых 0x0504 получаем опять смесь 3 и 4. Это для внутренней памяти на LPC23. Я НЕ читаю по +1 и +3 - только +0 и +2 - ну писал-же уже не раз - в этом случае у меня двухбайтовые элементы в буфере.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 18 2009, 16:28
|

embarrassed systems engineer
    
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038

|
Цитата(zltigo @ Jan 18 2009, 18:05)  Я НЕ читаю по +1 и +3 - только +0 и +2 - ну писал-же уже не раз - в этом случае у меня двухбайтовые элементы в буфере. Я не имел ввиду смещения от начала буфера данных. Я имел ввиду смещение от границы физического 32-битного слова. В моем тесте буфер выравнен на 32-битную границу (проверено), поэтому эти значения совпадают и отсюда, видимо, путаница. Если у Вас 16-битный буфер не выравнен, то каждое второе 16-битное слово будет пересекать границу выравненного физического (нативного для AHB) 32-битного слова. То есть младший байт 16-битного у Вас будет в одном физическом 32-битном слове, старший - в другом, не в том же где и младший, физическом 32-битном слове. Чтобы ядро могло получить это разломанное 16-битное - ему все равно надо выполнить ДВЕ транзакции. Для ARM7TDMI это означает ДВE инструкции ldr - не умеет оно иначе. Как я понял, в CortexM3 добавили AHB-AP - прослоечка между ARM-ядром и AHB - вот он это умеет. Если NXP эту приблуду не выкинет, да еще и флажок реализуют - тогда я, пожалуй, перестану NXP пинать ногами. А пока - суксь и масдай
|
|
|
|
|
Jan 18 2009, 17:27
|

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

|
Цитата(GetSmart @ Jan 18 2009, 18:28)  Это что за команда? IAR ругается. Может это movne ...,lsr #8 ? С чего-бы это вдруг? обычный сдвиг при условии. вот аж листинг из сишного исходника Код 108 int test_b( BYTE *buff ) 109 { 110 if( (ulong)buff & 0x3 ) \ test_b: \ 00000000 030010E3 TST R0,#0x3 \ 00000004 B000D0E1 LDRH R0,[R0, #+0] 111 return( *(ushort *)buff>>8 ); \ 00000008 2004A011 LSRNE R0,R0,#+8 112 else 113 return( *(ushort *)buff ); \ 0000000C 0EF0A0E1 MOV PC,LR ;; return 114 } Другое дело, что все это бред - что-то переклинило  . В моем примере это просто ldrh вне зависимости от смещения. Код BYTE tbuff[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
int test( BYTE *buff ) { return( *(ushort *)buff ); }
void test_short(void) { xprintf( "%04X %04X %04X %04X\r", test(tbuff), test(tbuff+2), test(tbuff+4), test(tbuff+6) ); } Результат: 0201 0403 0605 0807 Листинг суперфункции: Код 114 int test( BYTE *buff ) 115 { 116 return( *(ushort *)buff ); \ test: \ 00000000 B000D0E1 LDRH R0,[R0, #+0] \ 00000004 0EF0A0E1 MOV PC,LR ;; return 117 }
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 18 2009, 19:32
|

embarrassed systems engineer
    
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038

|
Код BYTE tbuff[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
int test( BYTE *buff ) { return( *(ushort *)buff ); }
void test_short(void) { xprintf( "%04X %04X %04X %04X\r", test(tbuff), test(tbuff+2), test(tbuff+4), test(tbuff+6) ); } А чего Вы хотели, если у Вас буфер выравнен (как стековая переменная) на 32-битную границу? (сорри, пропустил, это у меня стековая, а у Вас - глобальная. Но, на 99% уверен, что буфер таки выравнен - надо для 100% гарантии еще &tbuff[0] посмотреть бы). Так что, это - не фокус, попробуйте написать так: Код BYTE tbuff[9] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 };
int test( BYTE *buff ) { return( *(ushort *)buff ); }
void test_short(void) { xprintf( "%04X %04X %04X %04X\r", test(tbuff+1), test(tbuff+3), test(tbuff+5), test(tbuff+7) ); } Думаю, результат будет: 1000002 3000004 5000006 7000008 А должен бы быть: 0302 0504 0706 0908.
|
|
|
|
|
Jan 18 2009, 20:06
|

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

|
Цитата(VslavX @ Jan 18 2009, 21:32)  А чего Вы хотели, если у Вас буфер выравнен (как стековая переменная) на 32-битную границу? Писал об этом несметное число раз. Цитата(VslavX @ Jan 18 2009, 21:32)  Думаю, результат будет: 1000002 3000004 5000006 7000008 Я где-то для этих условий утверждал обратное?
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 18 2009, 20:37
|

embarrassed systems engineer
    
Группа: Свой
Сообщений: 1 083
Регистрация: 24-10-05
Из: Осокорки
Пользователь №: 10 038

|
Цитата(zltigo @ Jan 18 2009, 22:06)  Писал об этом несметное число раз. Хм, а как насчет этого: Цитата(zltigo @ Jan 18 2009, 22:06)  "буфер само-собой выровненный, а слова лежащие в нем, естественно, уже нет. Буфера обслуживают 16bit SPI, протокол старинный и тоже 16bit" Я так понял, что с аппаратуры принимаете 16-битные слова, складываете в буфер - массив из 16-битных слов, начало буфера "само-собой" выравнено (на 16 или 32). А уже там - "внутри пакета/структуры" - есть инкапсулированные 16-битные данные. И вот для этих инкапсулированных - бывает что адрес нечетный. А как это еще можно понять - "невыравненные слова в само-собой выравненном буфере"? (с)?  Предполагается же что это профессионал сказал. И обсуждается, в первую очередь, доступ к этим "невыравненным словам". А тривиальный случай доступа к элементам выравненного буфера - это упражнение для новичков. OK, ясность есть - чудес не бывает. Резюмирую - отсутствие OAT/DABT в LPC - "это - залет, воин" ©. И, к сожалению, для меня это весьма весомый недостаток  . Тут у меня в столе парочка SAM9XE лежит - надеюсь, до него скоро руки дойдут.
|
|
|
|
|
Jan 18 2009, 20:55
|

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

|
Цитата(VslavX @ Jan 18 2009, 22:37)  Я так понял, что с аппаратуры принимаете 16-битные слова, складываете в буфер - массив из 16-битных слов, начало буфера "само-собой" выравнено (на 16 или 32). А уже там - "внутри пакета/структуры" - есть инкапсулированные 16-битные данные. И только 16 бит и никаких других. Цитата Резюмирую - отсутствие OAT/DABT в LPC - "это - залет, воин" ©. И, к сожалению, для меня это весьма весомый недостаток  . А для меня оказалось  - нет, причем это проверено практикой портирования. Из имеющего место быть эффекта (трюк, но вдруг) при случае можно извлечь пользу.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|