| Форум РадиоКот https://radiokot.ru/forum/ |
|
| Ассемблерные вставки https://radiokot.ru/forum/viewtopic.php?f=59&t=98028 |
Страница 1 из 1 |
| Автор: | FPGAlover [ Чт дек 12, 2013 19:57:54 ] |
| Заголовок сообщения: | Ассемблерные вставки |
И еще раз здравствуйте! Вот и добрался я до своего любимого ассемблера Интересует технический вопрос: Как это делается ? можно ли непосредственно в сишный код вставлять? если можно то как? если нельзя то как это оформить? В конце концов, посодействуйте авторитетной ссылочкой |
|
| Автор: | coredumped [ Чт дек 12, 2013 20:43:41 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
Код: void _delay_loop_1(uint8_t __count) { __asm__ volatile ( "1: dec %0" "\n\t" "brne 1b" : "=r" (__count) : "0" (__count) ); } Упс, не ту сцылку прицепил, но смысл такой же. Вот для ARM: http://www.ethernut.de/en/documents/arm-inline-asm.html |
|
| Автор: | dosikus [ Чт дек 12, 2013 21:00:18 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
FPGAlover писал(а): И еще раз здравствуйте! Вот и добрался я до своего любимого ассемблера Так вот откуда ноги растут ... |
|
| Автор: | balmer [ Чт дек 12, 2013 21:55:36 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
Использую GCC, и там собственно говоря никаких особенностей нет и ничем не отличается кроме команд от AVR и x86. Набираешь в поисковике "gcc arm assembly" или "gcc STM32 assembly" и радуешься. Только ASM редко нужен. Память, как на дешевых AVR смысла нет экономить. Time Critical места встречаются очень редко. Да и для большинства Time Critical есть своя периферия. |
|
| Автор: | FPGAlover [ Чт дек 12, 2013 23:10:29 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
coredumped, спасибо! с первого взгляда возникла мысль: "что это за ахинея?? как то это рвет шаблон...", но пройдя по ссылке все приобрело смысл balmer писал(а): Память, как на дешевых AVR смысла нет экономить ну это понятно. Больше быстродействие интересует. глянул, какой код генерит компилятор и присел на 120мгц опрос внешнего ацп с занесением в буфер работает с частотой 3 Мгц. То есть 40тактов на цикл... и это хваленый риск Код: for (j=0;j<256;j++) { GPIOB->BSRRL |= 1<<12; for (i=0;i<1;i++){}; buff[j] = GPIOB->ODR; GPIOB->BSRRH |= 1<<12; } дизасмом посмотрел что творит компилятор.. не сказать что офигел, но был немного разочарован... Кстати, вопрос в продолжение: я, конечно, слабо себе представляю архитектуру АРМа. Но догадываюсь что шина не позволяет за такт произвести операцию чтения и записи в память (например инкремент ячейки памяти). Я прав? |
|
| Автор: | balmer [ Пт дек 13, 2013 00:53:17 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
Ну операция | тут совсем лишняя. А вот такой код Код: for (int j=0;j<256;j++) { GPIOB->BSRR = 1<<12; for (int i=0;i<1;i++){}; buff[j] = GPIOB->ODR; GPIOB->BRR = 1<<12; } компилируется в Код: 79 0020 4FF48051 mov r1, #4096 80 0024 074A ldr r2, .L9 82 0026 0848 ldr r0, .L9+4 85 0028 30B5 push {r4, r5, lr} 92 002a 0023 movs r3, #0 95 002c 0D46 mov r5, r1 97 .L7: 98 002e 9561 str r5, [r2, #24] 101 0030 948A ldrh r4, [r2, #20] 102 0032 E4B2 uxtb r4, r4 103 0034 C454 strb r4, [r0, r3] 105 0036 0133 adds r3, r3, #1 107 0038 B3F5807F cmp r3, #256 109 003c 1185 strh r1, [r2, #40] @ movhi 111 003e F6D1 bne .L7 По мне так вполне прилично. Естественно for (int i=0;i<1;i++){}; выкинуто полностью, ибо оптимизатор видит что цикл нафиг не нужен. Хотя да, ногодрыг - это одно из мест, где имело бы смысл на ASM точную задержку выставить. Правда мне такой подход не нравится. Меняешь частоту процессора - будь добр переписать код, неее я уж какнить DMA с Таймерами настрою на этот случай, будет надежнее. |
|
| Автор: | coredumped [ Пт дек 13, 2013 08:57:42 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
Скажем, DMA с внешним "параллельным" АЦП связать не просто - единственный вариант FSMC (поправьте меня, если я не прав). Да и смысла особого нет, при передаче 1 слова за итерацию. Тут бы проектик целиком увидеть. Таймер - да, нужная вещь, но с прерываниями надо быть внимательным - посмотрите какой код генерирует компилятор при входе - выходе из ISR. Если период таймера небольшой, то использование таймера может стать неэффективным, если нужно выжать из процессора все ресурсы. Что касается вставки ассемблерного кода и кода, генерируемого компилятором. Нужно было мне забирать данные с FPGA, порядка 10 Мбайт в секунду, блоками по 1К, обрабатывать и отправлять в эзернет. FSMC применить не получалось, ввиду не совсем удачного распределения GPIO. В общем - ногодрыг, задержки __nop() итп. Думал написать процедуру на ассемблере, чтоб выжать из процессора все, а когда посмотрел листинг компиллятора, понял, что лучшше я не сделаю пожалуй. Я это к тому, что компиляторы С довольно умные стали, главное код правильно написать. А методов оптимизации море - раскручивание циклов, работа с указателями с учетом архитектуры итп. Лучший оптимизатор - моск |
|
| Автор: | dosikus [ Пт дек 13, 2013 09:06:39 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
coredumped писал(а): Скажем, DMA с внешним "параллельным" АЦП связать не просто - единственный вариант FSMC (поправьте меня, если я не прав). Конечно не прав. GPIO та же периферия . Конечно при работе с DMA много не выжмешь , зато будет аппаратно... А вот почему буфер читается с ODR а не с IDR так же не понятно Код: buff[j] = GPIOB->ODR;
|
|
| Автор: | FPGAlover [ Пт дек 13, 2013 10:06:48 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
dosikus писал(а): А вот почему буфер читается с ODR а не с IDR так же не понятно Предельно понятно С ДМА я практически не разбирался(особенно с генерацией запросов) Поэтому не представляю, каким образом это на ДМА вообще можно сделать? 2 канала запускать? : 1 на клок (тут можно еще и управление усилителем запихать Так возможно? В идеале, конечно, надо плис подпаивать и хоть 200 МГц цифруй по четырем каналам параллельно |
|
| Автор: | coredumped [ Пт дек 13, 2013 10:10:30 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
dosikus писал(а): Конечно не прав. GPIO та же периферия . Конечно при работе с DMA много не выжмешь , зато будет аппаратно... Ну да, ну да... А строб данных как сформировать (шина данных 16-битная)? Варианты? 2 FPGAlover: В Вашем случае с DMA выигрыш не получить - передача 1 байта(слова). В моем - да, было бы хорошо, если бы можно было сформировать клок на FPGA + еще несколько сигналов. Использовать втрой канал ПДП - не вариант при пакетной передаче с подтверждением. FSMC - да, но платы уже готовы, а в 100-ногом корпусе расположение пинов таково(+ еще Ethernet, I2C), что нет вариантов замапить. Одеяльце коротковато В связке с ПЛИС можно поиграться с FIFO на ПЛИС + FSMC на ARM. Тут DMA очень даже выручит. Перекладываете работу с АЦП на стейтмашину, данные в FIFO, а дальше уж - куда Вам их надо |
|
| Автор: | FPGAlover [ Пт дек 13, 2013 10:55:08 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
поигрался с оптимизацией, получил достаточно приемлемый (6.5 мгц) с точки зрения компилятора результат. Выигрыш идет за счет того, что ссылки на регистры периферии сидят в регистрах процессора. Однако такой подход опасен... вот добавятся еще переменные - регистров на все не хватит, а компилятор втихоря в памяти значение хранить начнет и временная диаграмма поплывет ... Код: uint16_t buff[256]; uint32_t i = 0; uint32_t* SetReg ; uint32_t* ResetReg ; uint32_t* DataReg ; SetReg = (uint32_t*)&GPIOB->BSRRL; ResetReg = (uint32_t*)&GPIOB->BSRRH; DataReg = (uint32_t*)&GPIOB->IDR; while(1){ uint32_t j=0; do { *SetReg = 1<<12; //set bit i=0; //пауза.. АЦП быстродействующее, вполне хватает buff[j++] = *DataReg; *ResetReg = 1<<12; //set bit } while (j<256); 2 coredumped: На самом деле, в моем случае отношение времени сбора и обработки информации весьма мало. т.е. Мне важно с хорошей частотой собрать в буфер, а потом хоть по усарту выкачивать
|
|
| Автор: | coredumped [ Пт дек 13, 2013 11:03:50 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
Попробуй такой вариант: Код: uint16_t buff[256];
uint32_t i = 0; uint32_t* SetReg ; uint32_t* ResetReg ; uint32_t* DataReg ; uint16_t *bp; bp = buff; SetReg = (uint32_t*)&GPIOB->BSRRL; ResetReg = (uint32_t*)&GPIOB->BSRRH; DataReg = (uint32_t*)&GPIOB->ODR; while(1){ uint32_t j=256; *SetReg = 1<<12; //set bit do { *(bp++) = *DataReg; *ResetReg = 1<<12; //set bit *SetReg = 1<<12; //set bit } while (j--); |
|
| Автор: | dosikus [ Пт дек 13, 2013 11:04:28 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
coredumped писал(а): Ну да, ну да... А строб данных как сформировать (шина данных 16-битная)? Варианты? Тем же DMA , посмотри на казусе мою реализацию с LED дисплеем . С таймера пинать 2 канала DMA, один на строб второй на захват с IDR . |
|
| Автор: | FPGAlover [ Пт дек 13, 2013 11:25:55 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
coredumped писал(а): Попробуй такой вариант: почему то в хардфаулт уходит... Сейчас выясним. Выяснил : bp = buff; перед главным циклом стоит Выигрыша в скорости на глаз не видно. и кстати, я в си не силен, но... компиляторы отродясь такое понимали? bp = buff; это выглядил логичнее, но компилятор не понимает: bp = &buff; а с этим все в порядке... bp = &buff[0]; и еще непонятны предпосылки к генерации кода на while(j--): Код: MOVS R6,R5 SUBS R5,R6,1 CMP R6,#0 BNE.N ??Main_1 в системе команд отсутствует декремент регистра и флаг "зеро"? |
|
| Автор: | coredumped [ Пт дек 13, 2013 13:02:45 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
А компайлер какой? Вариант bp = buff; и bp = &buff[0]; одно и то же. Команды декремента нет, есть SUBS - который должен влиять на флаг Z (Z флаг имеется), не понятно зачем компилятор всунул CMP Я Кейлом пользуюсь, у меня все норм. Мой вариант должен работать чуть быстрее, хотя очень сильно зависит от компилятора. Посмотри ассемблерные листинги и сравни. |
|
| Автор: | FPGAlover [ Пт дек 13, 2013 15:01:27 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
coredumped писал(а): А компайлер какой? пользую IAR 6.5 листинги не сходятся ну вообще... У меня цикл с I стоически генерит код, несмотря на полную оптимизацию. а если честно, как то ваш листинг, в моем нубском мозгу(смысл половины команд пока непонятен), слабо коррелируется с исходником... Какие то непонятные L9 и push. а где же pop?. кстати, давно интересовал вопрос: "4FF48051 mov r1, #4096" откуда берется константа 4096? в "4FF48051" ее ни слухом ни духом |
|
| Автор: | balmer [ Пт дек 13, 2013 15:25:27 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
FPGAlover писал(а): "4FF48051 mov r1, #4096" откуда берется константа 4096? СпойлерFlexible second operandMany general data processing instructions have a flexible second operand. This is shown as operand2 in the descriptions of the syntax of each instruction. Operand2 can be a: ● Constant ● Register with optional shift Constant You specify an operand2 constant in the form #constant, where constant can be: ● Any constant that can be produced by shifting an 8-bit value left by any number of bits within a 32-bit word. ● Any constant of the form 0x00XY00XY ● Any constant of the form 0xXY00XY00 ● Any constant of the form 0xXYXYXYXY In the constants shown above, X and Y are hexadecimal digits. Это случай by shifting an 8-bit value left by any number of bits within a 32-bit word. |
|
| Автор: | FPGAlover [ Сб дек 14, 2013 18:29:33 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
Ну ничего себе! архиватор ну уровне расшифровки команд |
|
| Автор: | coredumped [ Вс дек 15, 2013 01:19:38 ] |
| Заголовок сообщения: | Re: Ассемблерные вставки |
Это еще 16-битный набор команд thumb - слегка "урезанный". Посмотрите что можно в режиме ARM (32-битном) http://www.gaw.ru/html.cgi/txt/doc/micr ... g_data.htm Правда в Cortex-M (к которым пренадлежит семейство stm32) набор ARM отсутствует, только THUMB |
|
| Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|


