derun 0 21 мая, 2014 Опубликовано 21 мая, 2014 (изменено) · Жалоба Мне необходимо быстро менять состояние линии порта (програмно, без таймеров и прочего аппаратного). Пишу кусочек кода для проверки скорости функций управления линией порта portC.13. while (1) { HAL_GPIO_TogglePin(GPIOC, 1 << 13); } Получаю меандр с частотой порядка 2.4MHz. Это очень медленно. Посмотрел как работает функция и переписал код так: while (1) { GPIOC->ODR ^= 1 << 13; } Получил меандр 8.4 MHz Уже лучше, но все равно очень медленно. Учитывая что ядро летает на скорости 168 MHz. Подскажите пожалуйста как сделать управление эффестивнее и быстрее. Изменено 21 мая, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Мне необходимо быстро менять состояние линии порта (програмно, без таймеров и прочего аппаратного). Подскажите пожалуйста как сделать управление эффестивнее и быстрее. "Без аппаратного" и "эффективнее и быстрее" два противоречащих понятия. Можете задачу описать подробнее? while(1) { GPIOC->BSRR = (1 << 13) << 0; GPIOC->BSRR = (1 << 13) << 16; } Даст Вам максимальную частоту. Включите опримизацию по скорости. Покажите листинг. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба скорость ножки задали? Надо задать максимальную частоту переключения ноги, а то будет наружу будет лезть не пойми че! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Если хочется максимально быстро и именно процессором, то без ассемблера не получится. скорость ножки задали? Надо задать максимальную частоту переключения ноги, а то будет наружу будет лезть не пойми че! Неправда. Максимум завалятся фронты, если у осциллографа ёмкость щупа неприлично большая. Частота не изменится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба while(1) { GPIOC->BSRR = (1 << 13) << 0; GPIOC->BSRR = (1 << 13) << 16; } Вариант 2 (какой лучше?): while(1) { GPIOC->BSRR = (1 << 13); GPIOC->BRR = (1 << 13); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Если хочется максимально быстро и именно процессором, то без ассемблера не получится.Всё прекрасно получается и без ассемблера. static __inline volatile uint32_t* bb_bit_address(volatile uint32_t* p, uint_fast8_t bit) { return ( (volatile uint32_t*) ( (((uint32_t)p & 0xf0000000UL) | 0x02000000UL) + ((((uint32_t)p & 0x000fffffUL)<<5) | (bit<<2)) ) ); } #define _PIN_BITBAND_RD_PTR(XPORT, XPIN, ...) bb_bit_address(&GPIO##XPORT->IDR, XPIN) #define _PIN_BITBAND_WR_PTR(XPORT, XPIN, ...) bb_bit_address(&GPIO##XPORT->ODR, XPIN) #define _PIN_TOGGLE(XPORT, XPIN, ...) do {*_PIN_BITBAND_WR_PTR(XPORT, XPIN) = ~*_PIN_BITBAND_RD_PTR(XPORT, XPIN);} while (0) #define pin_toggle(PIN) _PIN_TOGGLE(PIN) И далее в программе: #define PIN_LED_RED B,9,H,OUTPUT_PUSH_PULL,SPEED_10MHZ // можно и 50MHZ, но не особо нужно... pin_init(PIN_LED_RED); for(;;) pin_toggle(PIN_LED_RED); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
derun 0 21 мая, 2014 Опубликовано 21 мая, 2014 (изменено) · Жалоба Нужно просто быстро. Порт сконфигурирован на 100 MHz. Попробовал предложенный способ: while (1) { GPIOC->BSRRH = (1 << 13); GPIOC->BSRRL = (1 << 13); } Этот вариант работает быстрее получил частоту 14 MHz Думаю этого будет вполне достаточно. Посмотрел код дизассемблером, выглядит прилично думаю врядли смогу его сильно оптимизировать. Спасибо всем за советы и adnega за его вариант решения. Изменено 21 мая, 2014 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Всё прекрасно получается и без ассемблера. Bitband для GPIO есть не у всех процессоров STM32, так что лучше не подсаживать) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Этот вариант работает быстрее получил частоту 14 MHz Думаю этого будет вполне достаточно. Посмотрел код дизассемблером, выглядит прилично думаю врядли смогу его сильно оптимизировать. 12 тактов на весь цикл? Многовато. А листинг покажите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Bitband для GPIO есть не у всех процессоров STM32, так что лучше не подсаживать)Ну да. Но когда есть, то почему бы не пользоваться... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Ну да. Но когда есть, то почему бы не пользоваться... Потому что в данном случае вы не выиграете ничего. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
derun 0 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба 12 тактов на весь цикл? Многовато. А листинг покажите. GPIOC->BSRRL = (1 << 13); 080002d8: ldr r3, [pc, #16] ; (0x80002ec <main+116>) 080002da: mov.w r2, #8192 ; 0x2000 080002de: strh r2, [r3, #24] 117 GPIOC->BSRRH = (1 << 13); 080002e0: ldr r3, [pc, #8] ; (0x80002ec <main+116>) 080002e2: mov.w r2, #8192 ; 0x2000 080002e6: strh r2, [r3, #26] 120 } 080002e8: b.n 0x80002d8 <main+96> Как-то так Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Потому что в данном случае вы не выиграете ничего.Ну давайте померяемся... Напишите макрос, инвертирующий состояние линии GPIO без BB и посмотрите, что получится... На STM32F103 разница очевидна. 8000bb2: 6823 ldr r3, [r4, #0] 8000bb4: ea6f 0203 mvn.w r2, r3 8000bb8: 602a str r2, [r5, #0] 8000bba: e7fa b.n 8000bb2 <Reset_Handler+0xc2> Итого по предварительной оценке 18МГц при тактовой 72МГц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Ну давайте померяемся... Напишите макрос, инвертирующий состояние линии GPIO без BB и посмотрите, что получится... На STM32F103 разница очевидна. Давайте по-другому. :rolleyes: Будем не инвертировать предыдущее состояние, а конкретно задавать то 0, то 1. Мой "макрос" уже выдан чуть выше. Отдельно обращу внимание, что в обычном варианте можно одновременно изменить состояние не одного бита, а целой группы. Причем, некоторые можно установить, а некоторые сбросить. Как-то так А оптимизация не задана? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 21 мая, 2014 Опубликовано 21 мая, 2014 · Жалоба Как-то так Плохенький листинг. Четыре инструкции просятся, чтобы их вынесли за цикл. Оптимизация по скорости не была включена, видимо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться