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

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

|
У меня в тестовой прошивке есть такой небольшой чудный кусочек кода: Код { ungigned long *p; dprintf("\r\nNon aligned DWORD read.. "); dflush(); p = (unsigned long*)(0x209 + LPC_ISRAM); dprintf("%08X", *p); } Назначение этого кусочка - протестировать работу соответствующего обработчика исключения. Код прекрасно отработал на S3C44BOX, S3C2410, IXP42x, SAM7xx, PXA2xx/3xx и много лет все было чудесно. И вот, "понимаете, в машине в которой мы ехали, случайно, совершенно случайно, оказался цемент" ©. Я "совершенно случайно" запустил этот код на LPC2388, и... не увидел свой любимый "ODD ADDRESS TRAP". Смотрим документацию, "усер мануал" на LPC23xx вообще не содержит слова "unaligned". В-общем, красота - при невыравненном адресе - на LPC23xx читается/пишется переставленный мусор, и все это МОЛЧА. Такая низость в самом деле имеет место, или я чего-то недопонимаю?
|
|
|
|
|
 |
Ответов
(1 - 63)
|
Jan 16 2009, 07:35
|
Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 23-01-06
Из: Msk
Пользователь №: 13 490

|
Цитата(VslavX @ Jan 15 2009, 23:08)  P.S. Надо будет на их новые Кортексы глянуть - может там исключение добавили. в кортексах вообще нет проблемы обращения к невыравненным адресам
|
|
|
|
|
Jan 16 2009, 07:43
|
Знающий
   
Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847

|
Цитата(VslavX @ Jan 15 2009, 20:43)  У меня в тестовой прошивке есть такой небольшой чудный кусочек кода: Код { ungigned long *p; dprintf("\r\nNon aligned DWORD read.. "); dflush(); p = (unsigned long*)(0x209 + LPC_ISRAM); dprintf("%08X", *p); } Назначение этого кусочка - протестировать работу соответствующего обработчика исключения. Код прекрасно отработал на S3C44BOX, S3C2410, IXP42x, SAM7xx, PXA2xx/3xx и много лет все было чудесно. И вот, "понимаете, в машине в которой мы ехали, случайно, совершенно случайно, оказался цемент" ©. Я "совершенно случайно" запустил этот код на LPC2388, и... не увидел свой любимый "ODD ADDRESS TRAP". Смотрим документацию, "усер мануал" на LPC23xx вообще не содержит слова "unaligned". В-общем, красота - при невыравненном адресе - на LPC23xx читается/пишется переставленный мусор, и все это МОЛЧА. Такая низость в самом деле имеет место, или я чего-то недопонимаю? Да есть такая фигня при чтении. Посмотрите еще и запись.
--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть. © Lewis Carroll. Alice's adventures in wonderland.
|
|
|
|
|
Jan 16 2009, 08:33
|

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

|
Цитата(VslavX @ Jan 15 2009, 22:43)  В-общем, красота - при невыравненном адресе - на LPC23xx читается/пишется переставленный мусор, и все это МОЛЧА. Такая низость в самом деле имеет место, или я чего-то недопонимаю? У меня есть файл arm7tdmi_instruction_set_reference.pdf, там написано следующее: Код If the memory address is not word-aligned, the value read is rotated right by 8 times the value of bits [1:0] of the memory address. If R15 is specified as the destination, the value is loaded from memory and written to the PC, effecting a branch.
|
|
|
|
|
Jan 16 2009, 09:02
|

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

|
Код If the memory address is not word-aligned, the value read is rotated right by 8 times the value of bits [1:0] of the memory address. If R15 is specified as the destination, the value is loaded from memory and written to the PC, effecting a branch. Именно это я подразумевал под словом "переставленный". Для ARM7TDMI, который работает только в LE - будет такой вариант как Вы отцитировали. Для старших ARM-ов работающих в BE/LE вполне могут быть и отличия. В любом случае - в результате невыравненного доступа получаем отнюдь не тот результат какой ожидали, а поскольку исключения нет - то "дорогая не узнает, какой у парня был конец" ©. Очень весело отлавливать такие проблемы при портировании 200К строк С-шного кода с 8-битника, например. NXP - "низачот", первый раз такой облом вижу. В 70-ых на PDP такое счастье как OAT было, а вот в 21-ом веке - не судьба.
|
|
|
|
|
Jan 16 2009, 09:58
|

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

|
Цитата(VslavX @ Jan 16 2009, 12:02)  Очень весело отлавливать такие проблемы при портировании 200К строк С-шного кода с 8-битника, например. Вообще-то "это отлаживать" - Вам "низачет", ибо нужно не с последствиями бороться а банально этои 200К строк (кстати для 8bit это число строк кода СИЛЬНО СИЛЬНО надуманное - "урежте осетра" как минимум на порядок, тогда еще где-то в 64-128K бинарника поверю ) хоть мельком, но просмотреть. И вообще с этим хорошие компиляторы хорошо справляются - warning-ов хватает, если, конечно перворначальный код не совсем через заденпроходное отверстие писан, но незачем такое и портировать. Цитата NXP - "низачот", первый раз такой облом вижу. В 70-ых на PDP такое счастье как OAT было, а вот в 21-ом веке - не судьба. Тут странное дело - когда давно поверял работу своего обработчика exception на чем-то вроде LPC2114 - точно работало, а потом на свежих чипах как-то исчезло, хотя недавно переписывал слегка и некоторым удивлением обнаружил, что на одном из китов с LPC2148 тоже отработал!
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 16 2009, 10:20
|

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

|
Цитата(zltigo @ Jan 16 2009, 11:58)  (кстати для 8bit это число строк кода СИЛЬНО СИЛЬНО надуманное - "урежте осетра" как минимум на порядок, тогда еще где-то в 64-128K бинарника поверю ) Я прочитал как 200KB  200K строк действительно многовато. Цитата И вообще с этим хорошие компиляторы хорошо справляются - warning-ов хватает, если, конечно перворначальный код не совсем через заденпроходное отверстие писан, то незачем такое и портировать. Компиляторы не помогут когда адрес вычисляется диамически.  Например, сравнение IPшника приятого пакета с сетевой маской.
|
|
|
|
|
Jan 16 2009, 10:30
|

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

|
Цитата(defunct @ Jan 16 2009, 13:20)  Компиляторы не помогут когда адрес вычисляется диамически.  Например, сравнение IPшника приятого пакета с сетевой маской. Отнюдь. В реальности буфера под фреймы выделяются выровненые а нормальная разборка ведется по наложенной структуре. При работе с невыровнеными элемсентами структуры полусите предупреждение. Есть масса более ветвистых протоколов, то там в основном и разборка побайтовая. Если кто-то нагородил нечто непотребное в стиле "я пишу на любом языке, как в машинных кодах", то, простите, портировать такое просто не надо - проблемы будут по любому.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 16 2009, 11:03
|

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

|
Цитата(zltigo @ Jan 16 2009, 11:58)  Вообще-то "это отлаживать" - Вам "низачет", ибо нужно не с последствиями бороться а банально этои 200К строк (кстати для 8bit это число надуманное) Увы, не надуманное. "У меня линейка есть" - поэтому я абсолютно спокоен. Самый старый проект был начат в 1992-ом, пережил asm x86, BCC3.1, Watcom, IAR AVR 1.30, IAR MSP, Softune LX16, GCC ARM, GCC PPC, сотни две вариаций и моделей, десяток языков (рус, укр, англ, нем, ...), сотни флагов условной компиляции. Так что 200К - это весьма и весьма скромно, могу Вас заверить. Много лет это "утаптывали ногами" в 128К меги - ей просто не было даже близкой конкуренции по цене, и там _очень_ много финтов направленных на "лишь бы влезло" и "хто украл 10 байт RAMы" - хроника одного байта - во всей красе. На проектах на ARM-ах - еще веселее - 200K - " это только лицо" ©, т.е. приложение. Сейчас моя "зона ответственности" - системный софт - HAL + TN + TCP + FAT + USB-host за 100К грозит играючи перейти. Впрочем, сложность - понятие относительное, посмотрим на исходники Линукса - там никакой "линейки" хватит. Цитата(zltigo @ Jan 16 2009, 11:58)  хоть мельком, но просмотреть. И вообще с этим хорошие компиляторы хорошо справляются - warning-ов хватает, если, конечно перворначальный код не совсем через заденпроходное отверстие писан, но незачем такое и портировать. Да это все понятно, компилятором ловится 95% проблем, потом на других ARM-платформах отловили еще 3-4%. А вот вчера меня программеры ткнули носом в листинг - "ldrh R0, [R4, #0x209]" и спросили - "почему бнопня лезет?". И пришлось мне, "случайно, совершенно случайно", стряхнуть пыль с теста обработчика исключения. Профтыкал-с, признаю. И вот этот оставшийся 1% - самое трудное. В сумме несколько десятков человек тестировало пару месяцев изделие, а вот на баг только вчера попали  . Цитата(zltigo @ Jan 16 2009, 11:58)  Тут странное дело - когда давно поверял работу своего обработчика exception на чем-то вроде LPC2114 - точно работало, а потом на свежих чипах как-то исчезло, хотя недавно переписывал слегка и некоторым удивлением обнаружил, что на одном из китов с LPC2148 тоже отработал! Да, интересно. Само исключение есть, и работает - я ж обработчик таки при написании проверял. (как оказалось по черновым тестам - записью невыравненного слова во флеш - по адресу 1) . Но, судя по доке, возникает при обращении к несуществующей памяти и при записи во флэшку. Есть плата на свежем 2148revB и есть китовая от MT на 2148rev- - попробую на них. P.S. Таки купили Вы меня на "надуманное", ну и ладно, сделаю вид что провокации не было  Цитата(defunct @ Jan 16 2009, 12:20)  Компиляторы не помогут когда адрес вычисляется диамически.  Например, сравнение IPшника приятого пакета с сетевой маской. IP-шник - неудачный пример. И вообще протоколы для "внешних сношений". Если учитывать endianess, то разбор такой структуры все равно макросами надо делать, и в них aligment учесть. У меня, например, в TCP в итоге получилось 4 варианта макроса считывания поля IP - BE/LE + aligned/unaligned. А вот со своими внутренними структурами - там да, некоторый unaligned трабл у прикладников был. Вот еще беспокойство есть насчет оставшегося 1%  . Предполагался сценарий - "odd address trap" -> "bug report" -> e-mail -> база ошибок. Увы, мечты были грубо разрушены злобным NXP
|
|
|
|
|
Jan 16 2009, 12:07
|

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

|
Цитата(VslavX @ Jan 16 2009, 14:03)  Самый старый проект был начат в 1992-ом, пережил asm x86, BCC3.1, Watcom, IAR AVR 1.30, IAR MSP, Softune LX16, GCC ARM, GCC PPC, сотни две вариаций и моделей..... Все верно, у меня практически такие-же вещи по полной программе, НО все это не делалось единовременно вдруг с 8 на 32. При переходе ровным счетом ни одной проблемы в работе, именно с выравниванием не вызвало. Все отсеялось в процессе портирования при работе с исходниками. Цитата На проектах на ARM-ах - еще веселее - 200K - " это только лицо" ©, т.е. приложение. Посторяю - 200K чего? Кода или сишных строк??? Вот прям сейчас сижу в начале обычного проекта: ARM 94 файла 40767 текстовых строк из них всего 21943 стороки с кодом. Бинарник 134504 байта. Процентов 15% пришло с 8bit. Еще 20% вообще сразу живут на всех платформах. Будет развиваится и раздуваться еще несколько лет. Естественно есть и уже перевалившие за 300K бинарника. Говорите, что у Вас "200К строк С-шного кода" причем, как ранее говорили, для чего-либо врезультате влезающего в AVR128 и затем портированых? Так вот не верю. Цитата P.S. Таки купили Вы меня на "надуманное", ну и ладно, сделаю вид что провокации не было  Никаких провокаций - просто удивился. Полагаю обосновано.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 16 2009, 13:27
|

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

|
Цитата(zltigo @ Jan 16 2009, 12:30)  Отнюдь. В реальности буфера под фреймы выделяются выровненые а нормальная разборка ведется по наложенной структуре. Это все так, но давайте рассмотрим случай когда пакеты идут с разных интерфейсов. Eth и PPP-Link (у одного перед IP header'ом 14 байт eth заголовка, у второго длина ppp заголовка зависит от настроек канала и может быть от 1 байта и выше... И там и там "по-умолчанию" IP заголовок получается невыровненым относительно начала пакета. А мы хотим проверить по маске быстро (чтобы "одной" командой): Код *(U32 *)(packet + offset) & mask Вот тут недостача align exception'а может сыграть злую шутку Цитата Если кто-то нагородил нечто непотребное в стиле "я пишу на любом языке, как в машинных кодах", то, простите, портировать такое просто не надо - проблемы будут по любому. Я безотносительно, ни к чьему коду не привязываясь. Просто интересно получить ответы на следующие вопросы: Что у NXP есть по поводу misalign'a - как они предлагают обрабатывать такие ситуации в run-time (какие-нить их доки на этот счет)? Может быть есть сводка в каких NXP чипах align exception поддерживается, а в каких нет?
|
|
|
|
|
Jan 16 2009, 13:38
|

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

|
Цитата(defunct @ Jan 16 2009, 16:27)  Это все так, но давайте рассмотрим случай когда пакеты идут с разных интерфейсов. Можно многое, что искусственно придумать и еще больше "реализовать" по дурному - не вопрос  . В данном конкретном случае сразу могу спросить, а какого они идут в один и тот-же буфер? Давайте не будем развивать эту тему. Я ведь тоже все это не просто так сказал - в частности протоколы, например, входящие в стеки SS7, ISDN, V5.2, ... реализовывалитсь на разных платформах, портировались, инкапсулировались а в них разборки на порядки сложнее и ветвистее нежели IP, пусть даже он Ethernet+VLAN и т.д.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 16 2009, 13:43
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(defunct @ Jan 16 2009, 19:27)  Код *(U32 *)(packet + offset) & mask Вот тут недостача align exception'а может сыграть злую шутку Для таких случаев нужно создавать дополнительный U32 (например U32ua) внутри pragma pack (1). Это конечно не совместимость снизу вверх, но так можно написать универсальный код, правильно работающий на 8, 16 и 32 платформах.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 16 2009, 13:49
|

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

|
Цитата(zltigo @ Jan 16 2009, 15:38)  В данном конкретном случае сразу могу спросить, а какого они идут в один и тот-же буфер? Ну... потому что на IP уровне и те и те - IP. Да и чтоб расход памяти соптимизировать - пользовать один и тот же пул пакетов. Цитата Давайте не будем развивать эту тему. ОК Цитата(GetSmart @ Jan 16 2009, 15:43)  Для таких случаев нужно создавать дополнительный U32 (например U32ua) внутри pragma pack (1). Не, такое - не пойдет. Тормозить будет, т.к. будет LDRB вместо LDR. Мы ж скорости хотим.  - если скорость не нужна можно везде все упаковать и будет ARM как восьмибитник работать.
|
|
|
|
|
Jan 16 2009, 14:16
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(defunct @ Jan 16 2009, 19:49)  Не, такое - не пойдет. Тормозить будет, т.к. будет LDRB вместо LDR. Мы ж скорости хотим.  - если скорость не нужна можно везде все упаковать и будет ARM как восьмибитник работать. Ещё как пойдёт. Только использовать его надо именно в местах разбора буферов, в которых есть хоть малейшая вероятность невыровненности данных. Для работы с обычными переменными (статика, локальные) надо применять тип без прагмы.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 16 2009, 16:23
|

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

|
Цитата(zltigo @ Jan 16 2009, 14:07)  Все верно, у меня практически такие-же вещи по полной программе, НО все это не делалось единовременно вдруг с 8 на 32. При переходе ровным счетом ни одной проблемы в работе, именно с выравниванием не вызвало. Все отсеялось в процессе портирования при работе с исходниками. Да, понятно, что на любом проекте крупнее среднего будет практически то же самое. Но у нас некоторая разница в подходах - Вы пишете что " все отсеялось" (ну так уж и все?), а я пишу - " 1% остался". И вчера мне мои прикладники показали часть от этого "1%". Цитата(zltigo @ Jan 16 2009, 14:07)  Посторяю - 200K чего? Кода или сишных строк??? Вот прям сейчас сижу в начале обычного проекта: ARM 94 файла 40767 текстовых строк из них всего 21943 стороки с кодом. Бинарник 134504 байта. Процентов Дело было давно (в районе 2000-го) - из любопытства написал простой скриптик подсчета текстовых строк на Perl и прогнал на каталоге с исходниками для одной платформы (AVR, кажись). Тогда вышло около 150К - всех текстовых строк - с хидерами, C- кодом, комментариями, но без документации, makefiles и всяких вспомогательных скриптов (то отдельно все лежит). Сейчас не считал, по минимуму полагаю 200K. Эти все 200К написаны прикладниками - без платформозависимого и системного кода, который пишу я. ИМХО, по стилю там тяжеловато - с комментами напряг, и макросов засилье изрядное, так что текст - "плотненький", сколько строк именно с кодом - не скажу, но тоже не менее 50%. Цитата(zltigo @ Jan 16 2009, 14:07)  несколько лет. Естественно есть и уже перевалившие за 300K бинарника. Говорите, что у Вас "200К строк С-шного кода" причем, как ранее говорили, для чего-либо врезультате влезающего в AVR128 и затем портированых? Это где я говорил что все 200К строк исходников одновременно влезают в 128К? Я сказал, что в сумме есть 200К строк из которых получается сотня различных вариантов путем условной компиляции. Цитата(zltigo @ Jan 16 2009, 14:07)  Процентов 15% пришло с 8bit. Еще 20% вообще сразу живут на всех платформах В-о-о-о-т. А у нас 75-90% пришло с 8-битника и эти же 75-90% живут на всех 8/32-битных платформах. Из оставшихся 10-25% для 32-битников - 80% (ОС, стеки) тоже живут на всех 32-битных платформах. Итого - у меня "не живущая" и заново пишущаяся для платформы часть составляет 2-5% - против Ваших 65%. Отсюда и Ваш совет - "при портировании надо пересмотреть код". Когда пишешь заново - не вопрос - само собой так получается, а вот когда оно уже написано, отлажено и работает - хто ж в здравом уме туда полезет? Цитата(zltigo @ Jan 16 2009, 14:07)  Так вот не верю. Чему именно? Что бывают проекты где 75-90% процентов платформо-независимо и может жить на 8/16/32? Цитата(defunct @ Jan 16 2009, 15:49)  Не, такое - не пойдет. Тормозить будет, т.к. будет LDRB вместо LDR. Мы ж скорости хотим.  - если скорость не нужна можно везде все упаковать и будет ARM как восьмибитник работать. У меня эту проблему в общем случае решить не удалось. Для TCP/IP у меня такая реализация: Код LW_INLINE_FORCED DWORD lw_ipload( PLW_IP_ADDR ptr) { #if LW_ALIGNED_HDR // // Вариант перестановки для выравненного доступа // DWORD v, t1, t2;
v = *(PDWORD)ptr;
t1 = v ^ ((v << 16) | v >> 16); // t1 = 2143 ^ 4321 t2 = (v >> 8) | (v << 24); // t2 = 1432 t1 = t1 & 0xFF00FFFF; // t1 = 2043 ^ 4021 return t2 ^ (t1 >> 8); // 1432 ^ (0204 ^ 0402) #else // // Вариант перестановки для невыравненного доступа // return (DWORD)((PBYTE)ptr)[3] | ((DWORD)((PBYTE)ptr)[2] << 8) | ((DWORD)((PBYTE)ptr)[1] << 16) | ((DWORD)((PBYTE)ptr)[0] << 24); #endif } Для PowerPC в bigendian это выглядит так: Код LW_INLINE_FORCED DWORD lw_ipload( PLW_IP_ADDR ptr) { return *(PDWORD)ptr; } Если в проекте есть хоть один сетевой интерфейс для которого поле IP может быть невыравнено, то в кофигурации указан LW_ALIGNED_HDR нулевой. Но обычно есть только один ethernet, я стараюсь чтобы было выравнивание (гы, на SAM7X - получилось выровнять пакеты при приеме, на LPC - нет  ) и работает выравненный вариант. Пример работы с полем: Код { DWORD ip;
ip = lw_ipload(&iphdr->ipsrc); // // Делаем с IP чего надо // { Но тут как раз проблема ловли исключений не так остро стоит - этот код свой и писался изначально под разные платформы с разной endianess и alignment. Проблема острее стоит в портированном "старье".
|
|
|
|
|
Jan 16 2009, 16:38
|

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

|
Цитата(VslavX @ Jan 16 2009, 19:06)  Чему именно? Я более, чем четко сказал чему, что и подтвердилось. Если считать строки "по Вашему", то у меня их в одном из проектов и 500K, пожалуй наберется только это дутые строки. Из нуждающихся во внимательном портировании ни у Вас, ни у меня и десятка % не наберется. Тем более когда Вы ведете речь практически обо все совокупности наработанного из которого полагаю только 10-20% в конкретный проект ложатся. Порядка единиц процентов можно неспешно и глазками вычитать на предмет скользких мест. Цитата Что бывают проекты где 75-90% процентов платформо-независимо и может жить на 8/16/32? У меня сейчас, пожалуй, поболе 99,9% не зависят от 8/16/32, ибо я говорил откуда пришли исходники, а не то, какими они стали. Цитата из любопытства написал простой скриптик подсчета текстовых строк на Perl и прогнал Я в редактор скрипт встроил - всегда могу глянуть  Цитата(VslavX @ Jan 16 2009, 19:23)  У меня эту проблему в общем случае решить не удалось. Для общего случая эта проблема решается через memcpy(). Причем для прилично писанных на ASM библиотек все получается вполне эффективно.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 16 2009, 16:39
|

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

|
Цитата(zltigo @ Jan 16 2009, 18:24)  проект ложатся. Порядка единиц процентов можно неспешно и глазками вычитать на предмет скользких мест. Мое мнение - можно вычитать на 99%  , вчерашний случай это подтвердил А про неспешно - забудьте - еще в прошлом году уже все должно быть сделано. Цитата(zltigo @ Jan 16 2009, 18:24)  Я в редактор скрипт встроил - всегда могу глянуть  Зачем? Это же смешно - строками меряться  . Я вот давно объем оценил и забыл, сейчас вот брякнул - и пожалел  . Я обычно объем архива смотрю - и прогресс виден и понятно когда снапшоты бэкапить пора. Цитата(zltigo @ Jan 16 2009, 18:38)  Для обшего случая эта проблема решается через memcpy(). Причем для прилично писанных на ASM библиотек все получается вполне эффективно. А можно пример?
|
|
|
|
|
Jan 16 2009, 17:01
|

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

|
Цитата(VslavX @ Jan 16 2009, 19:39)  А можно пример? В смысле? Копируете Ваши байты по адресу переменной/структуры с произвольного адреса. memcpy() содержит разборки с адресами и обеспечивает побайтное копирование невыровненных адресов и пословное выровненных. Да, естественно, имея дополнительно информацию об обьектах можно в частом случае превзойти универсальный вариант. Вот прям сейчас под руками получение контрольной суммы прошивки располагающейся по совершенно произвольному адресу: memcpy( &crc, (BYTE *)crc_addr, 2 ); Естественно такое черевато: crc = *((ushort *)crc_addr ); А такое мудрено: crc = (((ushort)(*(((BYTE *)crc_addr)+1)))<<8) | (ushort)( *((BYTE *)crc_addr) ); Кстати, знаете почему я именно этот кусок привел  - Я НА ЭТО НАСТУПИЛ и запомнил. Наступил, сразу скажу, не при портировании, а при изучении ARM - первые шаги, загрузчик, контроль целостности... Наступил и запомнил  и теперь просто внимателен и осторожен. Цитата(VslavX @ Jan 16 2009, 19:39)  Зачем? Это же смешно - строками меряться  . Упаси бог - Чисто для себя делалось - так сказать интегральная оценка.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 16 2009, 18:01
|

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

|
Цитата(GetSmart @ Jan 16 2009, 16:16)  Ещё как пойдёт. Да не пойдет так! т.к. медленно. Конкретно в этом случае ожидается, что данные в буфере выровнены. Если нет - тогда это критическая ситуация и проц должен дать мне фатальный эксепшин. Цитата Только использовать его надо именно в местах разбора буферов, в которых есть хоть малейшая вероятность невыровненности данных. Для работы с обычными переменными (статика, локальные) надо применять тип без прагмы. Зачем замедлять работу программы лишними проверками и лишними побайтовыми операциями в критических для производительности местах? Из-за "малейшей" вероятности делать код вчетверо медленнее - увольте. Мне лучше эксепшн
|
|
|
|
|
Jan 16 2009, 18:06
|

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

|
Цитата(zltigo @ Jan 16 2009, 19:01)  memcpy( &crc, (BYTE *)crc_addr, 2 ); Естественно такое черевато: crc = *((ushort *)crc_addr ); А такое мудрено: crc = (((ushort)(*(((BYTE *)crc_addr)+1)))<<8) | (ushort)( *((BYTE *)crc_addr) ); Ну и - почему просто не написать: Код crc = lw_wload((ushort *)crc_addr); где lw_wload - это макрос, аналогичный приведенному мной в посте выше и вырождающийся в один из Ваших вариантов. Если адрес произвольный и неизвестно, выравнен ли он при runtime, на этот случай есть макрос lw_wload_na() (na - not aligned). Все эти макросы компилируются в нормальный компактный код, да еще и обеспечивают конверсию BE/LE при необходимости. А вызов функции - всегда оверхед, и очень заметный, особенно для копирования 2/4 байт. Хотя бы посмотрите в листинг - сколько при вызове для ARM-а регистров сохраняться будет. Не-е-е - это не мой путь, точно. ИМХО, скопировать структуру целиком - еще можно, но это если памяти завались и скорость не волнует. А у меня так не бывает  И все же: 1. Есть проект, состоит из двух частей - прикладной и системной 2. Системная часть - небольшой процент от проекта - легко заменяется при смене аппаратной части на том же процессоре 3. Прикладная часть - большой процент от проекта и - развивается долгий срок - долгое время живет на 8-битной платформе - долгое время компилируется одним и тем же компилятором - значительная многовариантность - значительная оптимизация по размеру кода и оперативной памяти, с учетом платформы и компилятора 4. Возникает необходимость смены платформы на 32-битную И теперь, как автор системной части, я обязан обеспечить своим коллегам-прикладникам максимально безболезненные условия для портирования и отладки прикладной части. А я не могу сделать это в полном объеме, потому как NXP не удосужилась сделать простейшую и стандартную вещь. И что, мое возмущение неоправдано?
|
|
|
|
|
Jan 16 2009, 18:52
|

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

|
Цитата(VslavX @ Jan 16 2009, 21:06)  Ну и - почему просто не написать: Когда это оправдано, естественно, используются разные способы и макросы однин из часто используемых. В данном случае Вы просили пример с memcpy() - я привел пример использования в загрузчике - совершенно не критичном по скорости месте. При копировании струкрур тоже весьма эффективно. Цитата но это если памяти завались и скорость не волнует. Ну насчет размера кода то возможны и даже очень возможны варианты  Цитата А у меня так не бывает  Посмею опять не поверить, основываясь на своих реалиях, что вcегда и везде дела обстят именно так  . Цитата И теперь, как автор системной части, я обязан обеспечить своим коллегам-прикладникам максимально безболезненные условия для портирования и отладки прикладной части. А я не могу сделать это в полном объеме, потому как NXP не удосужилась сделать простейшую и стандартную вещь. Смотря как подходить к делу, сваять обработчик exception и умыть руки, предоставив возможность поэкспериментировать с наступанием на грабли в паркетно-домашних условиях? Но что делать при таком эмпирическом подходе к делу в реально-непаркетных условиях эксплуатации? Сделать из заказчика естествоиспытателя? В рабочей системе есть система фиксации и выкарабкивания нештатных сттуаций? Тогда какая особо разница, между вылетом и фиксацией факта разборки, например, странного пакета в конкретной ветке? Цитата И что, мое возмущение неоправдано? Лучше, конечно, быть здоровым и богатым  .... А вообще, настаиваю, что лучше думать. Вы, например, настаиваете на необходимости максимально возможной производительности всегда и везде? Как тогда быть, напимер на 32bit x86, когда при "неправильном" доступе к памяти просто напросто молча получими торможение в разы  . Опять возмущаться  ?
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 16 2009, 20:28
|

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

|
Цитата(zltigo @ Jan 16 2009, 20:52)  Посмею опять не поверить, основываясь на своих реалиях, что вcегда и везде дела обстят именно так  . Гы, я обычно пишу системный код - то есть универсальные сервисы, которые будут использовать другие люди, иногда даже через несколько лет после написания. Поэтому вполне естественно заложить максимально возможное быстродействие и все доступные оптимизации. Вы гарантируете, что при использовании memcpy() у Вас не переполнится, к примеру стек? (а в многопоточке это будет естественно скопировать выравненную структуру в локальную переменную). Или прикладники не будут злоупотреблять частым вызовом функции? Хотя иногда так приятно себе сказать - "а вот таких гадских условий у нас в этой функции не будет никогда" и не писать какой-то противный кусок. В тех нечастых случаях, когда я себе такое позволяю, подстилается соответствующий ASSERT. А вообще - разочарован я Вашим примером использования memcpy(). Он, конечно, имеет право на жизнь, но я надеялся увидеть что-нить менее брутальное. Цитата(zltigo @ Jan 16 2009, 20:52)  Смотря как подходить к делу, сваять обработчик exception и умыть руки, предоставив возможность поэкспериментировать с Это уже мои проблемы и мои фантазии какой обработчик написать, понадобится - буду эмулировать корректный доступ, потребуют - запишу проблему в лог, разрешат - отправлю баг-репорт по и-мейлу. Но на LPC23xx у меня нет выбора. Цитата(zltigo @ Jan 16 2009, 20:52)  максимально возможной производительности всегда и везде? Как тогда быть, напимер на 32bit x86, когда при "неправильном" доступе к памяти просто напросто молча получими торможение в разы  . Опять возмущаться  ? Ну это уже, имхо, передергивание - априори программу пытаемся написать правильно, доступ предполагаем корректный и по необходимости оптимизированный (если уж хотим избежать "торможения в разы"). Речь идет об исключении - когда что-то пошло нештатно. А насчет возмущения - есть стандартная, привычная и много раз использованная при отладке вещь - OAT/DABT, а теперь вот ее нет, а она реально полезна. А думать - да, оно вредно обычно (а то опять не поверите  ) не бывает.
|
|
|
|
|
Jan 16 2009, 21:45
|

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

|
Цитата(VslavX @ Jan 16 2009, 22:28)  Гы, я обычно пишу системный код - то есть универсальные сервисы, которые будут использовать другие люди, иногда даже через несколько лет после написания. Поэтому вполне естественно заложить максимально возможное быстродействие и все доступные оптимизации. Абсолютно аналогично  Цитата А вообще - разочарован я Вашим примером использования memcpy(). Он, конечно, имеет право на жизнь, но я надеялся увидеть что-нить менее брутальное. Пример, как пример. Один из варианов наряду с разнообразными (к сожалению разнообразными) макросами, какими-нибудь узкозаточенными intrinsic функциями типа memcpy_word_from_unaligned( dst, src ) представляющими собой усеченные memcpy(), где только dst гарантированно "хороший" адрес и прочими совершенно, напомню, не отрицаемыми мною решениями. Причем (действительно зачастую брутальный) memcpy() можно легко и гарантировнно безошибочно обернуть в любые макросы и ими сразу и без проблем обозначать проблемные места. C последующим обдумыванием и созданием более узкоспециализированных решений.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 17 2009, 05:12
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(defunct @ Jan 17 2009, 00:01)  Да не пойдет так! т.к. медленно. Паранойя?! Вы ещё совсем недавно всё на AVR песали и не жаловались на быстродействие. LPC раз в 5 быстрее AVR, и если на нём побайтово из буфера собирать Long, то особых тормозов не будет заметно. Дальше спорить не буду. Я всё равно останусь при своём мнении. А вообще, тут все забыли одну вещь касательно Data Abort при невыровненных словах. Где-то читал, что в LPC он возникает только если проц работает в USER MODE. Во всех остальных MODE, в частности в SYSTEM MODE он специально заблокирован, так как все остальные режимы предназначены для системы. Так что, господа песатели, отлаживайте свои проги в USER MODE, а когда уже всё отладите можете переносить код в другие режимы
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 17 2009, 06:46
|

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

|
Цитата(GetSmart @ Jan 17 2009, 07:12)  А вообще, тут все забыли одну вещь касательно Data Abort при невыровненных словах. Где-то читал, что в LPC он возникает только если проц работает в USER MODE. Во всех остальных MODE, в частности в SYSTEM MODE он специально заблокирован, так как все остальные режимы предназначены для системы. Так что, господа песатели, отлаживайте свои проги в USER MODE, а когда уже всё отладите можете переносить код в другие режимы  Совет хороший, и стал бы еще лучше если бы Вы его ссылкой подтвердили. А то документация производителя и google как-то скромно умалчивают про приведенные Вами факты.
|
|
|
|
|
Jan 17 2009, 08:52
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Прямо скажу, я за 3 года об АРМах столько всего начитался, что уже не помню когда и где читал. Но скорее всего где-то в разделе об ограничениях USER MODE. Точно помню, что в этом режиме нельзя изменить младшие биты регистра флагов, отвечающих за текущий режим и за запрет прерываний. Мне сейчас лень искать всем желающим нужную им инфу. Подсказки я дал. Все желающие - на поиски!!! А не вылетание в аборт при невыровненном чтении имеет свои плюсы. Жаль, что IAR это делать не умеет, но эта фича даёт возможность прочитать 32 бита с любого нечётного адреса всего за две команды LDR. Например читая слово с адреса 1 в регистр прочитаются правильно сразу три байта. Старший байт нужно будет прочитать в другой регистр из адреса 5. Потом по маске их объеденить. Браво LPC!!!  Потестировал это дело на LPC2134/01 но не срабатывает исключение ни в SYSTEM, ни в USER. Абыдно  А может где-то флажок стоит, управляющий этой фичей.
Сообщение отредактировал GetSmart - Jan 17 2009, 08:58
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 17 2009, 17:00
|

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

|
Цитата(GetSmart @ Jan 17 2009, 07:12)  Паранойя?! Вы ещё совсем недавно всё на AVR песали и не жаловались на быстродействие. Я и до сих пор под AVR/C51 много чего пишу, и не жалуюсь на быстродействие. Но там у меня задачи нетребовательные к быстродействию. Не понимаю, Вы пытаетесь защитить/оправдать остуствие exception'a в LPC?! Цитата LPC раз в 5 быстрее AVR, и если на нём побайтово из буфера собирать Long, то особых тормозов не будет заметно. Дальше спорить не буду. Я всё равно останусь при своём мнении. В таком случае SAM7 "порвет" LPC по производительности (т.к. не нужно будет собирать Long побайтово). Цитата А вообще, тут все забыли одну вещь касательно Data Abort при невыровненных словах. Где-то читал, что в LPC он возникает только если проц работает в USER MODE. Во всех остальных MODE, в частности в SYSTEM MODE он специально заблокирован, так как все остальные режимы предназначены для системы. Если можно - более подробно на этот счет. Где читали? ;>
|
|
|
|
|
Jan 17 2009, 18:25
|

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

|
Цитата(zltigo @ Jan 17 2009, 19:13)  Вы, это, простите о чем??? О том что мне совесть не позволит в проц в котором нет exception'a вставить опасный код. Следовательно придется добавлять проверки, а они будут тормозить. на SAM'е мне ничто не мешает там где нужна скорость написать: *(U32 *)<произвольный адрес> = x; т.к. есть полная уверенность в том, что даже если произвольный адрес неправильный я это не пропущу. на LPC будет как минимум: Код if (<произвольный адрес> & 0x3) { slow implementation } else { fast }
|
|
|
|
|
Jan 17 2009, 18:47
|
Местный
  
Группа: Свой
Сообщений: 201
Регистрация: 23-01-06
Из: Msk
Пользователь №: 13 490

|
Цитата(defunct @ Jan 17 2009, 21:25)  О том что мне совесть не позволит в проц в котором нет exception'a вставить опасный код. на LPC будет как минимум: Код if (<произвольный адрес> & 0x3) { slow implementation } else { fast } Ну вообщем то так и делается  И не только для LPC Например, в WinCE'шных драйверах упомянутого выше самсунга...
|
|
|
|
|
Jan 17 2009, 19:46
|

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

|
Цитата(defunct @ Jan 17 2009, 20:25)  О том что мне совесть не позволит в проц в котором нет exception'a вставить опасный код. Ну и как это новое утверждение соотностится с Вашим предыдущим Цитата В таком случае SAM7 "порвет" LPC по производительности (т.к. не нужно будет собирать Long побайтово). , которое и вызвало моой вопрос. Повторяю вопрос - как наличие exception приводит к результату "не нужно будет собирать Long побайтово"
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 17 2009, 19:58
|

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

|
Цитата(defunct @ Jan 17 2009, 20:25)  на LPC будет как минимум: Код if (<произвольный адрес> & 0x3) { slow implementation } else { fast } ИМХО, при неработающем исключении лучше бы написать так: Код { ASSERT(((DWORD)adr & (sizeof(DWORD)-1)) == 0, "Ugly unaligned pointer"); fast implementation } ASSERT программно сгенерит недостающее исключение. Но беда в том, что я предпочитаю "традиционный вариант нормы" - то есть работающее исключение, и на такую подлянку никто не рассчитывал и, соответственно, этот ASSERT по коду не "раскидан".
|
|
|
|
|
Jan 18 2009, 00:44
|

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

|
Цитата(zltigo @ Jan 17 2009, 21:46)  Ну и как это новое утверждение соотностится с Вашим предыдущим ну.. так сказать "прямопропорционально". На SAM'е будет быстрый опасный код, на LPC - медленный и безопасный. Цитата Повторяю вопрос - как наличие exception приводит к результату "не нужно будет собирать Long побайтово" Чтобы ответить на этот вопрос, позвольте мне определить рамки в которых плаваем. Дано: 1. буферы, содержащие некие типизированные данные, например IP заголовок; 2. предполагается, что для любого буфера, IP заголовок может находиться с произвольным смещением от начала буфера; 3. предполагается, что начало IP заголовка всегда на границе 32 бит. (напр, программируем DMA так, чтобы он нам клал пакет не с начала буфера, а с некоторого смещения, так чтобы IP заголовок получался выровненным). (отступ от последнего условия - есть ситуация неординарная, возникающая возможно при фатальной ошибке программы). Теперь собсно ответ на вопрос: С наличием exception'a - я буду работать с полями IP заголовка как с U32 без проверок на выровненность. Без exception'a мне придется либо предусмотреть его программную генерацию, либо - побайтовую сборку/копирование полей с требуемым выравниванием. Оба варианта будут пагубно сказываться на быстродействии (лишний код и все-таки). Цитата ИМХО, при неработающем исключении лучше бы написать так: ... ASSERT(((DWORD)adr & (sizeof(DWORD)-1)) == 0, "Ugly unaligned pointer"); Согласен, однако это не сделает реализацию такой же быстрой как без assert'a  Проверка останется все равно.
|
|
|
|
|
Jan 18 2009, 06:15
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(defunct @ Jan 18 2009, 06:44)  Согласен, однако это не сделает реализацию такой же быстрой как без assert'a  Проверка останется все равно. С такой паранойей надо писать на ассемблере и ничего не бояться  Т.к. любители структурированного программирования на Си без забот выносят часть кода в отдельную процедуру, что сказывается на быстродействии ещё хуже чем сборка одного Long побайтово. А уж если программа написана на C++, то жаловаться на замедление просто смешно. Дам бесплатный совет. В режиме отладки ставьте ASSERT или любую проверку. В режиме Release уберите проверки и получите быстродействие ещё больше чем в SAM7, т.к. проц быстрее. Но даже если LPC будет собирать Long побайтово, то по скорости он всё равно (!) не уступит SAM7. Хочу подчеркнуть, что я предлагал собирать побайтово Long только для быстрой проверки какого-либо условия в буфере. Если же нужно выгребать множество слов из буфера, то как правильно писал zltigo, сперва нужно через memcpy скопировать буфер и выровнять его начало. Можно даже не тратить дополнительную память и скопировать внутри текущего буфера на 1, 2 или 3 байта назад. Или вперёд. Как там говорится: в чужом глазу соринку... в своём глазу бревно...
Сообщение отредактировал GetSmart - Jan 18 2009, 06:32
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 18 2009, 11:17
|

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

|
Цитата(GetSmart @ Jan 17 2009, 10:52)  А не вылетание в аборт при невыровненном чтении имеет свои плюсы. Жаль, что IAR это делать не умеет, но эта фича даёт возможность прочитать..... Сейчас попробовал переписать один относительно критичный кусочек работающий (никаих проблем не было - компилятор, естественно, сам разруливал) в кольцевом буфере с 16bit данными под описаный стиль "корреция результата после чтения по невыровненному адресу" результат мне понравился. Если до этого я в принципе пребывал на позициях - особо без разницы есть аборт или нет, то теперь чаша весов (если действительно требуется выжимать быстродействие) склоняется к безабортовому варианту.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
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
|
|
|
|
|
Jan 19 2009, 06:00
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Понятно, хочется переложить на процессор собственные баги. Причём хочется чтобы в процессе эксплуатации программа именно зависла, но нельзя допустить чтобы она исполнялась на 1% медленнее, но без багов Достаточно короткий вариант отлова ошибок: Код tst r0,#3 swine 100 ldr r1,[r0,#+0] И не говорите, что он будет тормозить проц. Два такта проверки в дополнение к 3 тактам чтения рамы это ничто. Не знаю, как эту проверку автоматизировать на Си, но на Асме это делается легко.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|