zltigo 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Имхо, это уж совсем клиническая ситуация - "невыровненный кольцевой буфер 16-битных слов" - такого я еще не встречал. Ну маленько не так написал :( - буфер само-собой выровненный, а слова лежащие в нем, естественно, уже нет. Буфера обслуживают 16bit SPI, протокол старинный и тоже 16bit - пришел из 70x годов с машины которая про 8bit вобще не знала :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Мне правда интересно. На ARM-е можно любой невыравненный USHORT (16-битное целое) загрузить за 3 инструкции ldrb R1, [R0, #0] ldrb R2, [R0, #1] orr R1, R1, R2, shl #8 Как можно грузить быстрее - ума не приложу :laughing: . Если даже воспользоваться изращенным способом загрузки от 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 То есть, действительно имеет место циклический сдвиг - так еще (дополнительно к проверке вмещения в одно слово) и старшие биты чистить надо. Не понимаю, где тут можно выиграть :blink: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Не понимаю, где тут можно выиграть :blink: У меня память под буфера внешняя и замена одного из двух ldrb из внешней памяти банальным tst регистр,#0x3 мне и понравилась, хотя и те-же "три инструкции", как понравилось и использование (кусочек на ASM) только одного регистра вместо 2 ( у Вас даже 3x ). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба У меня память под буфера внешняя и замена одного из двух ldrb из внешней памяти банальным tst регистр,#0x3 мне и понравилась, хотя и те-же "три инструкции", как понравилось и использование (кусочек на ASM) только одного регистра вместо 2 ( у Вас даже 3x ). Ну, допустим, доступ к внешней памяти медленный. Но ведь если, например, младшие два бита адреса равны 0x03, то все равно надо читать два раза из памяти - два последовательных DWORD/WORD-a. И дополнительная проверка на равенство этих битов адреса на 0x03 с последующим ветвлением/пропуском тоже нужна. Где собак зарыт? P.S. Переписал свой тестик на использование 16-битных невыравненных слов - там еще результаты мрачней. Ну никак за одно обращение два слова (16 или 32-битных) не читается. P.P.S. "Листинг, сестра, листинг" :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Ну, допустим, доступ к внешней памяти медленный. Но ведь если, например, младшие два бита адреса равны 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rst7 5 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба tst R0,#0x3 ldrh R0,[R0, #+0] lsrne R0,R0,#+8 Простите, а разве это работает? По меньшей мере tst #1 для полуслов нужен. Позже... чето я вообще не пойму, что тут и как... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба 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 слова можно и меньше было бы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Простите, а разве это работает? В железе не проверял, но проблем не вижу. Сейчас поищу дома какую-нибудь железку.... По меньшей мере tst #1 для полуслов нужен. В моем случае неважно 3 или 1 - есть гарантированное выравнивание на 2. То есть, если читаем ldrh по смещению +1 - вместо 0x0302 получаем коктейль из 1 и 2. Если читать по +3, то вместо ожидаемых 0x0504 получаем опять смесь 3 и 4. Это для внутренней памяти на LPC23. Я НЕ читаю по +1 и +3 - только +0 и +2 - ну писал-же уже не раз - в этом случае у меня двухбайтовые элементы в буфере. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Я НЕ читаю по +1 и +3 - только +0 и +2 - ну писал-же уже не раз - в этом случае у меня двухбайтовые элементы в буфере. Я не имел ввиду смещения от начала буфера данных. Я имел ввиду смещение от границы физического 32-битного слова. В моем тесте буфер выравнен на 32-битную границу (проверено), поэтому эти значения совпадают и отсюда, видимо, путаница. Если у Вас 16-битный буфер не выравнен, то каждое второе 16-битное слово будет пересекать границу выравненного физического (нативного для AHB) 32-битного слова. То есть младший байт 16-битного у Вас будет в одном физическом 32-битном слове, старший - в другом, не в том же где и младший, физическом 32-битном слове. Чтобы ядро могло получить это разломанное 16-битное - ему все равно надо выполнить ДВЕ транзакции. Для ARM7TDMI это означает ДВE инструкции ldr - не умеет оно иначе. Как я понял, в CortexM3 добавили AHB-AP - прослоечка между ARM-ядром и AHB - вот он это умеет. Если NXP эту приблуду не выкинет, да еще и флажок реализуют - тогда я, пожалуй, перестану NXP пинать ногами. А пока - суксь и масдай :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба lsrne R0,R0,#+8 Это что за команда? IAR ругается. Может это movne ...,lsr #8 ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Это что за команда? 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 } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба А чего Вы хотели, если у Вас буфер выравнен (как стековая переменная) на 32-битную границу? Писал об этом несметное число раз. Думаю, результат будет: 1000002 3000004 5000006 7000008 Я где-то для этих условий утверждал обратное? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VslavX 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Писал об этом несметное число раз. Хм, а как насчет этого: "буфер само-собой выровненный, а слова лежащие в нем, естественно, уже нет. Буфера обслуживают 16bit SPI, протокол старинный и тоже 16bit" Я так понял, что с аппаратуры принимаете 16-битные слова, складываете в буфер - массив из 16-битных слов, начало буфера "само-собой" выравнено (на 16 или 32). А уже там - "внутри пакета/структуры" - есть инкапсулированные 16-битные данные. И вот для этих инкапсулированных - бывает что адрес нечетный. А как это еще можно понять - "невыравненные слова в само-собой выравненном буфере"? (с)? :) Предполагается же что это профессионал сказал. И обсуждается, в первую очередь, доступ к этим "невыравненным словам". А тривиальный случай доступа к элементам выравненного буфера - это упражнение для новичков. OK, ясность есть - чудес не бывает. Резюмирую - отсутствие OAT/DABT в LPC - "это - залет, воин" ©. И, к сожалению, для меня это весьма весомый недостаток :(. Тут у меня в столе парочка SAM9XE лежит - надеюсь, до него скоро руки дойдут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 18 января, 2009 Опубликовано 18 января, 2009 · Жалоба Я так понял, что с аппаратуры принимаете 16-битные слова, складываете в буфер - массив из 16-битных слов, начало буфера "само-собой" выравнено (на 16 или 32). А уже там - "внутри пакета/структуры" - есть инкапсулированные 16-битные данные. И только 16 бит и никаких других. Резюмирую - отсутствие OAT/DABT в LPC - "это - залет, воин" ©. И, к сожалению, для меня это весьма весомый недостаток :( . А для меня оказалось :) - нет, причем это проверено практикой портирования. Из имеющего место быть эффекта (трюк, но вдруг) при случае можно извлечь пользу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться