Перейти к содержанию
    

ViKo

Модератор
  • Постов

    12 216
  • Зарегистрирован

Весь контент ViKo


  1. Если ПЛИСы нападают на процессоры, то почему бы и процессорам не нанести ответный удар?!
  2. На пальцах до 200? У меня столько пальцев нет :) Я лучше на бумаге :) и калькуляторе. А SDIV r0,r0,r3 выполняется за 11 тактов... upd. Не всегда! - обнаружил и 10 тактов, и 9 тактов, похоже, от чисел зависит. О! чем меньше делимое, тем меньше тактов. Видел 4 такта. ... а MLS r2,r3,r0,r2 всего за 2. Так что на пальцах, извините, никак не посчитать. Максимальное количество тактов для SDIV заметил 12. Где про такты написано? 2 zltigo Ну если упорно не хотите нормальное сравнение сделать... :)
  3. Хочу знать, насколько замедлят. MOV r2,#0x20202020 выполняется за 1 такт.
  4. Давайте проверим. Число -2147483647 (т.е. -(2^31 - 1), максимально допустимое для функции) Keil преобразовал за 207 тактов (сравнивал счетчик тактов перед вызовом itoad и после нее). Сколько у IAR?
  5. Похоже, у вас именно тот случай, когда вопрос нужно задавать в специальном разделе форума, посвященном DSP.
  6. По-моему, для самого SPI никаких пауз между байтами не требуется. Каждому такту соответствует свой бит данных. Другое дело, что дальше с ними происходит, в данном случае, в ПЛИС.
  7. Грабли можно избежать, если определить строку в виде объединения байтов и 4-байтовых слов. 2 all: Как сделать в Keil то же, что и в IAR? Только в таблице у него 8 байтов, а у Keil-а 4. Итого, с учетом таблицы, 60 байтов против 62 байтов. P.S. А тема-то, действительно, начинает соответствовать своему названию - "Вопрос C" :)
  8. Вы имеете в виду сравнение кода, или операции сравнения внутри кода? Почему не хочу? Еще как! Листинг я же выдал, там, в файлике keil_temp.txt (он и создается Keil-ом именно в таком виде, с расширением txt). Вот еще раз, после замены типа переменной sign (думал, может в ней дело). С недоумением разглядываю ваш и свой листинги, ничего путного на ум не приходит. itoad PROC ;;;27 *************************************************************************** ****/ ;;;28 void itoad(int number, uint8_t *string) 000000 b510 PUSH {r4,lr} ;;;29 { ;;;30 #define TETRASPACE ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24 ;;;31 #define TETRATAIL ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24 ;;;32 // uint8_t sign; ;;;33 int sign; ;;;34 *(uint32_t *)(string) = TETRASPACE; 000002 f04f3220 MOV r2,#0x20202020 ;;;35 *(uint32_t *)(string + 4) = TETRASPACE; 000006 600a STR r2,[r1,#0] ;;;36 *(uint32_t *)(string + 8) = TETRATAIL; 000008 604a STR r2,[r1,#4] 00000a 4a62 LDR r2,|L1.404| ;;;37 string += 10; 00000c 608a STR r2,[r1,#8] 00000e 310a ADDS r1,r1,#0xa ;;;38 if (!number) return; 000010 2800 CMP r0,#0 000012 d011 BEQ |L1.56| ;;;39 if (number > 0) sign = '+'; 000014 dd02 BLE |L1.28| 000016 f04f042b MOV r4,#0x2b 00001a e001 B |L1.32| |L1.28| ;;;40 else { ;;;41 number = -number; 00001c 4240 RSBS r0,r0,#0 ;;;42 sign = '-'; 00001e 242d MOVS r4,#0x2d |L1.32| ;;;43 } ;;;44 do { ;;;45 *string-- = number % 10 + '0'; 000020 230a MOVS r3,#0xa |L1.34| 000022 4602 MOV r2,r0 000024 fb90f0f3 SDIV r0,r0,r3 000028 fb032210 MLS r2,r3,r0,r2 00002c 3230 ADDS r2,r2,#0x30 00002e f8012901 STRB r2,[r1],#-1 ;;;46 } while (number /= 10); 000032 2800 CMP r0,#0 000034 d1f5 BNE |L1.34| ;;;47 *string = sign; 000036 700c STRB r4,[r1,#0] |L1.56| ;;;48 } 000038 bd10 POP {r4,pc} ;;;49 ENDP У вас метка itoad играет какую-то роль? Почему-то у меня запоминается в стеке LR, а у вас нет. У вас в строке 63 должно быть число 0x20202020 или, как написано? Сравнение number производится по-разному, но я не вижу в исходниках разницы. И это LDR.N - там действительно будет по 2 байта? Где-то рядом таблица? Забавно, что байты в машинных кодах в IAR и Keil написаны по-разному. Где младший, где старший? Еще один прикол - у меня '+' заносится в регистр 4-байтовой командой (потому что не имеет повторяющейся последовательности?), а '-' 2-байтовой. У вас все 2-байтовые. Неужели IAR настолько лучше Keil?
  9. Я понял. Сложнее поставить знак в нужное место, и для гашения лидирующих нулей нужна переменная. Зато вместо деления - умножение. В-общем, все наоборот. Идея интересная - поделить число на 10000 и умножить на 2^28 (для других размерностей можно использовать другие числа, например, для 8-битов - использовать форму 4.12, умножив на 41).
  10. Напоследок - проверил вариант с преобразованием в 4.28, для int16, с той же формой выдачи результата. Получилось 100 байтов, 150 циклов, не лучший способ. В-общем, вариант itoa для Cortex для себя я уже выбрал :).
  11. В 51-й микроЭВМ была. А в Cortex заменяется двумя командами (upd. Вернее, тремя. Исправил код). Дважды не делается. 000022 4602 MOV r2,r0 000024 fb90f0f3 SDIV r0,r0,r3 000028 fb032210 MLS r2,r3,r0,r2
  12. 16-битовая версия (на основе 32-битовой) void i16toad(int16_t number, uint8_t *string) { #define TETRASPACE ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24 #define TETRATAIL ' ' | '0' << 8 | '\0'<< 16 | '\0'<< 24 uint8_t sign; int32_t num = (int32_t)number; *(uint32_t *)string = TETRASPACE; *(uint32_t *)(string + 4) = TETRATAIL; string += 5; if (!num) return; else if (num > 0) sign = '+'; else { sign = '-'; num = -num; } do { *string-- = num % 10 + '0'; } while (num /= 10); *string = sign; } Те же 58 байтов, но нет константы 4-байтовой. 105 тактов для -32767.
  13. "Шеф, все пропало!..." По команде *(uint32_t *)(string + 8) = (uint32_t)" 0"; заносится адрес строки, а не сама строка! На всякий случай, если кто-то заинтересуется, выдаю работающий код. void itoad(int number, uint8_t *string) { #define TETRASPACE ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24 #define TETRATAIL ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24 uint8_t sign; *(uint32_t *)(string) = TETRASPACE; *(uint32_t *)(string + 4) = TETRASPACE; *(uint32_t *)(string + 8) = TETRATAIL; string += 10; if (!number) return; if (number > 0) sign = '+'; else { number = -number; sign = '-'; } do { *string-- = number % 10 + '0'; } while (number /= 10); *string = sign; } Часть листинга, обратите внимание, стоит команда LDR, а не ADR, как раньше ;;;31 *(uint32_t *)(string) = TETRASPACE; 000002 f04f3220 MOV r2,#0x20202020 ;;;32 *(uint32_t *)(string + 4) = TETRASPACE; 000006 600a STR r2,[r1,#0] ;;;33 *(uint32_t *)(string + 8) = TETRATAIL; 000008 604a STR r2,[r1,#4] 00000a 4a3a LDR r2,|L1.244| ;;;34 string += 10; 00000c 608a STR r2,[r1,#8] 00000e 310a ADDS r1,r1,#0xa
  14. Выкладываю ваш вариант. Последнее, что вы написали, тоже делал. Пара вопросов, возникших в процессе... - 1. Можно ли "заинлайнить" библиотечную функцию, ту же div, например? 2. Есть ли способ задать массив, выровненный по 4-байтовой границе? upd. Вах, получилось! void itoad(int number, uint8_t *string) { #define FOUR_SPACES ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24 uint8_t sign; *(uint32_t *)(string) = FOUR_SPACES; *(uint32_t *)(string + 4) = FOUR_SPACES; *(uint32_t *)(string + 8) = (uint32_t)" 0"; string += 10; // *(uint32_t *)(string += sizeof(int32_t)) = ' '; // *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )" 0"; // string += 2; if (!number) return; if (number > 0) sign = '+'; else { number = -number; sign = '-'; } do { *string-- = number % 10 + '0'; } while (number /= 10); *string = sign; } 58 байтов ;;;31 *(uint32_t *)(string) = FOUR_SPACES; 000002 f04f3220 MOV r2,#0x20202020 ;;;32 *(uint32_t *)(string + 4) = FOUR_SPACES; 000006 600a STR r2,[r1,#0] ;;;33 *(uint32_t *)(string + 8) = (uint32_t)" 0"; 000008 604a STR r2,[r1,#4] 00000a a23a ADR r2,|L1.244| ;;;34 string += 10; 00000c 608a STR r2,[r1,#8] 00000e 310a ADDS r1,r1,#0xa Вроде уже делал так. keil_temp.txt
  15. Во всех (!) перечисленнных вариантах делается одно и то же: +8 +2 ;;;34 *(uint32_t *)(string += sizeof(int32_t)) = ' '; 000006 600a STR r2,[r1,#0] ;;;35 *(uint32_t *)(string += sizeof(int32_t)) = (uint32_t )" 0"; 000008 604a STR r2,[r1,#4] 00000a a23b ADR r2,|L1.248| 00000c f8412f08 STR r2,[r1,#8]! ;;;36 string += 2; 000010 1c89 ADDS r1,r1,#2 ;;;37
  16. В смысле, прилепить string +=2 сразу к предыдущему выражению, использующему указатель? А, заменить +8 +2 на +4 +4 +2? upd. Попробовал и так, и сяк, и +10, лучше не становится. 16-битовую хочу попробовать с применением формата 4.28, как у aaarrr. А с тем, что сделал для 32 битов, и не знаю, куда уж дальше "копать" для 16 битов. Я, собственно, с 16-битовой и возился, пока не увидел, что 32-битовая из нее получается практически "даром":)
  17. Полгода назад были :) Актуальности не потеряли. http://electronix.ru/forum/index.php?showt...st&p=675132
  18. Так - нельзя, пропускается два байта. С кавычками - понял, но варнинги... как бы удовлетворить требованиям компилятора? #define FOUR_SPACES 0x20202020 *(uint32_t *) string = FOUR_SPACES; Нормально?
  19. Кавычки не двойные? Из этой 16-битов автоматически получается, если малое число использовать и буфер соответствующий.
  20. А для Cortex-M3? А как надо по вашему мнению?
  21. void itoad(int number, uint8_t *string) { uint8_t sign; *(int32_t *) string = ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24; *(int32_t *)(string + 4) = ' ' | ' ' << 8 | ' ' << 16 | ' ' << 24; *(int32_t *)(string += 8) = ' ' | ' ' << 8 | '0' << 16 | '\0'<< 24; if (!number) return; if (number > 0) sign = '+'; else { number = -number; sign = '-'; } string += 2; do { *string-- = number % 10 + '0'; } while (number /= 10); *string = sign; } Работает с 32-битовыми числами со знаком. string должна быть 12 байтов для 32-битового числа. 60 байтов (+ 4 байта хранят константу "_ _ 0"). ~207 тактов.
  22. 2 zltigo Непременно. :) Выставил две "галки" - Use Cross-Module Optimization и Use MicroLIB. Общий размер кода сократился до 212 и 324 байтов для первой и второй программ. Причем, такой размер получается со второго раза компиляции. "Все чудесатее и чудесатее." Что эти параметры делают? А на конкретный размер и состав кода пока не смотрел.
  23. Перед "0" я символ + или - не ставлю (считаю, так "красивее" и "правильнее"), потому и обработка такая в начале программ. Итого _ _ _ _ _ 0 \0. По поводу размеров и тактов - могу выдать весь проект в заархивированном виде. В настройках есть какие-то "галочки", которых не трогал. Может, что-то и упустил... Keil_Temp.zip
  24. Прежде, чем писать новое, изучил в отладчике работу обеих моих программ - начальной si16toad и измененной itoa, в которой операции % и / были заменены вызовом библиотечной функции div. Напомню: Keil uVision - RealView MDK-ARM 4.10, STM32F103. Результаты оказались интересными. После компиляции в окне Build Ouitput для обеих программ выдаются одинаковые размеры для кода - 548 байтов при оптимизации O0 и 536 байтов при оптимизации O3. Почему они одинаковые, не понимаю (см. ниже)?! Размеры данных всех типов тоже одинаковые вообще всегда, но это, как раз, не удивляет. Посчитал размер обеих функций по листингу C компилятора (есть галочка в настройках генерировать листинг). При O0 для si16toad насчитал 84 байта, для itoa 98 байтов (не считая 14 байтов в самой функции div, это уже в отладчике увидел). При O3 - 80 байтов и 94 байта, соответственно. Причем, при оптимизации O0 в si16toad команда деления использовалась дважды, а при O3 только один раз. В-общем, мой первый вариант оказался компактнее. Посчитал в отладчике количество тактов. Счетчик тактов виден в окне регистров, засекал значение перед вызовом своей функции и после нее. При O0 si16toad выполнялась за 171 такт, itoa за 232 такта. При O3 - 121 такт и 210 тактов, соответственно. Мой первый вариант оказался еще и быстрее. Увидел лишние знаковые и беззнаковые расширения для переменных меньше 32 байтов. Вот здесь буду совершенствовать программу. Массив или указатель - тоже проверю. Заносить пробелы сразу - их, к сожалению, максимум 5 (не 4). Над этим и др. пока думаю.
×
×
  • Создать...