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

Эффективно и быстро управлять линией порта STM32F407

Мне необходимо быстро менять состояние линии порта (програмно, без таймеров и прочего аппаратного). Пишу кусочек кода для проверки скорости функций управления линией порта portC.13.

 while (1)
{

HAL_GPIO_TogglePin(GPIOC, 1 << 13);

}

Получаю меандр с частотой порядка 2.4MHz.

Это очень медленно. Посмотрел как работает функция и переписал код так:

  while (1)
{

      GPIOC->ODR ^= 1 << 13;
}

Получил меандр 8.4 MHz

Уже лучше, но все равно очень медленно. Учитывая что ядро летает на скорости 168 MHz.

Подскажите пожалуйста как сделать управление эффестивнее и быстрее.

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне необходимо быстро менять состояние линии порта (програмно, без таймеров и прочего аппаратного).

Подскажите пожалуйста как сделать управление эффестивнее и быстрее.

"Без аппаратного" и "эффективнее и быстрее" два противоречащих понятия.

Можете задачу описать подробнее?

 

while(1)
{
  GPIOC->BSRR = (1 << 13) << 0;
  GPIOC->BSRR = (1 << 13) << 16;
}

 

Даст Вам максимальную частоту. Включите опримизацию по скорости. Покажите листинг.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

скорость ножки задали? Надо задать максимальную частоту переключения ноги, а то будет наружу будет лезть не пойми че!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если хочется максимально быстро и именно процессором, то без ассемблера не получится.

 

скорость ножки задали? Надо задать максимальную частоту переключения ноги, а то будет наружу будет лезть не пойми че!

Неправда. Максимум завалятся фронты, если у осциллографа ёмкость щупа неприлично большая. Частота не изменится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

while(1)
{
  GPIOC->BSRR = (1 << 13) << 0;
  GPIOC->BSRR = (1 << 13) << 16;
}

Вариант 2 (какой лучше?):

while(1)
{
  GPIOC->BSRR = (1 << 13);
  GPIOC->BRR = (1 << 13);
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если хочется максимально быстро и именно процессором, то без ассемблера не получится.
Всё прекрасно получается и без ассемблера.

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);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно просто быстро. Порт сконфигурирован на 100 MHz.

Попробовал предложенный способ:

  while (1)
{
        GPIOC->BSRRH = (1 << 13);
      GPIOC->BSRRL = (1 << 13);
}

Этот вариант работает быстрее получил частоту 14 MHz

Думаю этого будет вполне достаточно.

Посмотрел код дизассемблером, выглядит прилично думаю врядли смогу его сильно оптимизировать.

Спасибо всем за советы и adnega за его вариант решения.

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всё прекрасно получается и без ассемблера.

Bitband для GPIO есть не у всех процессоров STM32, так что лучше не подсаживать)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Этот вариант работает быстрее получил частоту 14 MHz

Думаю этого будет вполне достаточно.

Посмотрел код дизассемблером, выглядит прилично думаю врядли смогу его сильно оптимизировать.

12 тактов на весь цикл? Многовато. А листинг покажите.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Bitband для GPIO есть не у всех процессоров STM32, так что лучше не подсаживать)
Ну да.

Но когда есть, то почему бы не пользоваться...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну да.

Но когда есть, то почему бы не пользоваться...

Потому что в данном случае вы не выиграете ничего.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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>

 

Как-то так

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Потому что в данном случае вы не выиграете ничего.
Ну давайте померяемся...

Напишите макрос, инвертирующий состояние линии 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МГц.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну давайте померяемся...

Напишите макрос, инвертирующий состояние линии GPIO без BB и посмотрите, что получится...

На STM32F103 разница очевидна.

Давайте по-другому. :rolleyes: Будем не инвертировать предыдущее состояние, а конкретно задавать то 0, то 1. Мой "макрос" уже выдан чуть выше.

Отдельно обращу внимание, что в обычном варианте можно одновременно изменить состояние не одного бита, а целой группы. Причем, некоторые можно установить, а некоторые сбросить.

 

Как-то так

А оптимизация не задана?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как-то так

Плохенький листинг. Четыре инструкции просятся, чтобы их вынесли за цикл. Оптимизация по скорости не была включена, видимо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...