[STM32] STM32F103 - Jak wygląda szybkość operacji na pinach.

Pytania dotyczące problemów ze zrozumieniem kart katalogowych, not aplikacyjnych dla mkrokontrolerów ARM firmy STMicroelectronics, rozwiązania układowe z zastosowaniem STM.
Awatar użytkownika
ZbeeGin
User
User
Posty: 492
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

[STM32] STM32F103 - Jak wygląda szybkość operacji na pinach.

Postautor: ZbeeGin » niedziela 15 kwie 2018, 14:06

W zasadzie wątek nie jest o problemie, ale o zależnościach czasowych, które wynikły z napisanego kodu. Weźmy na przykład taki kod - zaczerpnięty z jednego z wcześniejszych tematów, gdzie walczyliśmy z problemem blokowania pinu.

Kod: Zaznacz cały

#include "stm32f10x.h"

int main(void)
{
   RCC->APB2ENR = RCC_APB2ENR_IOPBEN;

   RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
   AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE;

   GPIOB->CRL |= GPIO_CRL_MODE3;
   GPIOB->CRL &= ~GPIO_CRL_CNF3_0;

   GPIOB->CRL |= GPIO_CRL_MODE4;
   GPIOB->CRL &= ~GPIO_CRL_CNF4_1;

   GPIOB->CRL |= GPIO_CRL_MODE5;
   GPIOB->CRL &= ~GPIO_CRL_CNF5_0;

   while(1)
   {
     GPIOB->ODR |= GPIO_ODR_ODR3;
     GPIOB->ODR |= GPIO_ODR_ODR4;
     GPIOB->ODR |= GPIO_ODR_ODR5;

     GPIOB->ODR &= ~GPIO_ODR_ODR3;
     GPIOB->ODR &= ~GPIO_ODR_ODR4;
     GPIOB->ODR &= ~GPIO_ODR_ODR5;
   }
}


Kod nie robi nic szczególnego. Ot, macha pinami PB3, PB4, PB5, całkowicie bez opóźnień. Ustawienia zegara dla całego systemu są domyślne jak dla gołej płytki Nucleo.

Taka postać kodu da nam następujący przebieg. Kanał 1, czerwony to PB3, a kanał 2, żółty to PB4.
20130828_910433.png

Jak widać oscyloskop zmierzył częstotliwość ~655kHz, co jest dość małą wartością jak na szybkie przecież procesory z rdzeniem ARM. Widać też, że sygnały są przesunięte względem siebie, bo modyfikujemy je kolejno. Zmieńmy zatem nieco kod by wyeliminować przesunięcia i zobaczymy jak taka zmiana wpłynie na przebiegi.

Kod: Zaznacz cały

    GPIOB->ODR |= (GPIO_ODR_ODR3 | GPIO_ODR_ODR4 | GPIO_ODR_ODR5);
    GPIOB->ODR &= ~(GPIO_ODR_ODR3 | GPIO_ODR_ODR4 | GPIO_ODR_ODR5);


Sterując piny w tym samym czasie pozbyliśmy się przesunięcia, a i uzyskana częstotliwość uległa znacznemu zwiększeniu.
20130828_910556.png

Teraz oscyloskop zmierzył już ~1,67MHz. To więcej niż 2 krotny przyrost. Czy można z takiego programu wycisnąć więcej? Skorzystajmy z innego podejścia do zmianach w porcie. Dalej będzie to programowa zmiana, ale tym razem wykorzystamy szybkie zerowanie i ustawianie bitów za pomocą rejestru BSRR.

Kod: Zaznacz cały

    GPIOB->BSRR |= (GPIO_BSRR_BS3 | GPIO_BSRR_BS4 | GPIO_BSRR_BS5);
    GPIOB->BSRR |= (GPIO_BSRR_BR3 | GPIO_BSRR_BR4 | GPIO_BSRR_BR5);


Pomiar nie wykazuje kolejnego przyśpieszenia operacji. Coś jest nie tak...
20130828_910720.png

No tak! Popełniliśmy niezłą gafę. Przecież przy rejestrze BSRR nie musimy wykonywać operacji read-modify-write jaką wymusi operacja OR na rejestrze. Od tego jest ten rejestr by dostęp do niego był szybki, a zmiany za jego pomocą były realizowane równie szybko. Zmieńmy zatem to migiem na bardziej poprawną wersję.

Kod: Zaznacz cały

    GPIOB->BSRR = (GPIO_BSRR_BS3 | GPIO_BSRR_BS4 | GPIO_BSRR_BS5);
    GPIOB->BSRR = (GPIO_BSRR_BR3 | GPIO_BSRR_BR4 | GPIO_BSRR_BR5);


Teraz uzyskaliśmy już wynik ~2,88MHz. Jest to ponad 4 razy szybciej niż w kodzie pierwszym.
20130828_910804.png


EDIT:
Okazuje się, że kod z wykorzystaniem jeszcze jednego rejestru "specjalnej troski", ale tylko do zerowania pozwala nam na uzyskanie dodatkowych kilkunastu kHz więcej.

Kod: Zaznacz cały

    GPIOB->BSRR = (GPIO_BSRR_BS3 | GPIO_BSRR_BS4 | GPIO_BSRR_BS5);
    GPIOB->BRR = (GPIO_BRR_BR3 | GPIO_BRR_BR4 | GPIO_BRR_BR5);


Wszystkie kody kompilowane z brakiem optymalizacji i jako Release. Znalazłem współpracujący Pendrive więc nowe kompilacje i nowe zrzuty.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Ostatnio zmieniony poniedziałek 16 kwie 2018, 16:01 przez ZbeeGin, łącznie zmieniany 5 razy.

Awatar użytkownika
dambo
Expert
Expert
Posty: 645
Rejestracja: czwartek 17 mar 2016, 17:12

Re: [STM32] STM32F103 a szybkość operacji na pinach.

Postautor: dambo » niedziela 15 kwie 2018, 14:45

Jeśli masz dalej ustawiony setup możesz sprawdzić jeszcze jedną rzecz - bitbanding - można ustawić/zgasić zadany bit w rejestrze jedną komendą.
Bo BSRR ma atomowy dostęp do portów, ale zapis do BSRR z punktu widzenia rdzenia to dalej RMW. Wada - ustawiamy jeden bit na komende.
Taktujesz teraz procka wewnętrznym RC 8MHz, jeszcze kolejną sztuczką, która może trochę wpłynąć to włączenie mechanizmu prefetch.

A co do screenów/fotek - wydaje mi się, że przy jakości zdjęć z telefonów są one o wiele wygodniejsze + połączenie z drive i mamy je zarchiwizowane itp.

Update:
Źle napisałem z tą jedną komendą - można zrozumieć, ze chodzi o komendę w assemblerze. Chodzi o to, ze zamiast zapisywać do całego rejestru 32 bitowego robimy sobie "wskaźnik" na pojedynczy bit w pamięci i do niego zapisujemy 0/1.
Przy GPIO względem zapisu do BSRR nie powinno być więc różnicy.
No ale inne rejestry nie mają takiego mechanizmu, więc tam można wykorzystać Bit-Banding w takiej formie.
Ostatnio zmieniony niedziela 15 kwie 2018, 15:26 przez dambo, łącznie zmieniany 1 raz.
Nowy blog o tematyce embedded -> https://www.embedownik.pl/

Awatar użytkownika
ZbeeGin
User
User
Posty: 492
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

Re: [STM32] STM32F103 a szybkość operacji na pinach.

Postautor: ZbeeGin » niedziela 15 kwie 2018, 14:51

Jako dodatkową informację dodaje jeszcze jeden zrzut. Zamiast bezpośredniego dostępu do portów użyjemy poleceń z biblioteki SPL GPIO_SetBits(), GPIO_ResetBits(). Biblioteka ta jest uważana za strasznie rozdmuchaną i "wolną".
20130828_911007.png

I tak rzeczywiście jest.

dambo pisze:Jeśli masz dalej ustawiony setup możesz sprawdzić jeszcze jedną rzecz - bitbanding - można ustawić/zgasić zadany bit w rejestrze jedną komendą.

Pamiętasz adresy? :mrgreen:
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Ostatnio zmieniony niedziela 15 kwie 2018, 18:24 przez ZbeeGin, łącznie zmieniany 2 razy.

Awatar użytkownika
dambo
Expert
Expert
Posty: 645
Rejestracja: czwartek 17 mar 2016, 17:12

Re: [STM32] STM32F103 a szybkość operacji na pinach.

Postautor: dambo » niedziela 15 kwie 2018, 15:09

http://mightydevices.com/?p=144

tutaj można znaleźć makra do tego i mały opis. Na elektrodzie w poradniku do STM32 autorstwa "szczywronka" tez można o tym poczytać.
Nowy blog o tematyce embedded -> https://www.embedownik.pl/

Awatar użytkownika
ZbeeGin
User
User
Posty: 492
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

Re: [STM32] STM32F103 a szybkość operacji na pinach.

Postautor: ZbeeGin » niedziela 15 kwie 2018, 15:42

Skorzystałem z takiego kodu:

Kod: Zaznacz cały

#include "stm32f10x.h"

#define BITBAND_ADDRESS(_item,_bitNumber)\
    (uint32_t*) ((((uint32_t)(&(_item))) & 0x60000000)\
    + 0x2000000\
    + ((((uint32_t)&(_item)) & 0x1FFFFFFF)*32)\
    + ((_bitNumber)*4))

#define BITBAND_ACCESS(_item,_bitNumber)\
    *BITBAND_ADDRESS(_item,_bitNumber)

int main(void)
{
   RCC->APB2ENR = RCC_APB2ENR_IOPBEN;

   RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
   AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE;

   GPIOB->CRL |= GPIO_CRL_MODE3;
   GPIOB->CRL &= ~GPIO_CRL_CNF3_0;

   GPIOB->CRL |= GPIO_CRL_MODE4;
   GPIOB->CRL &= ~GPIO_CRL_CNF4_1;

   GPIOB->CRL |= GPIO_CRL_MODE5;
   GPIOB->CRL &= ~GPIO_CRL_CNF5_0;

   //volatile uint64_t delay;

   while(1)
   {
    BITBAND_ACCESS(GPIOB->ODR, 3) = 1;
    BITBAND_ACCESS(GPIOB->ODR, 3) = 0;
   }
}


I... W zasadzie nie widzę przyśpieszenia operacji na portach. Ok. 3MHz w tej konfiguracji jest do osiągnięcia.
20130828_910852.png
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Ostatnio zmieniony niedziela 15 kwie 2018, 18:29 przez ZbeeGin, łącznie zmieniany 1 raz.

Awatar użytkownika
dambo
Expert
Expert
Posty: 645
Rejestracja: czwartek 17 mar 2016, 17:12

Re: [STM32] STM32F103 a szybkość operacji na pinach.

Postautor: dambo » niedziela 15 kwie 2018, 17:02

ok - czyli mamy ładnie pokazane, że dla machania GPIO możemy używać tak samo dobrze BB jak i BSRR. Z tym, ze BSRR pozwoli zapisać kilka bitów jednocześnie, a BB tylko pojedyncze.
Nowy blog o tematyce embedded -> https://www.embedownik.pl/

Awatar użytkownika
ZbeeGin
User
User
Posty: 492
Rejestracja: sobota 08 lip 2017, 17:16
Lokalizacja: Śląsko-Zagłębiowska Metropolia
Kontaktowanie:

Re: [STM32] STM32F103 - Jak wygląda szybkość operacji na pinach.

Postautor: ZbeeGin » niedziela 15 kwie 2018, 20:26

To jeszcze jedna próbka szybkości. Tym razem przełączyłem się na płytkę Nucleo z STM32F072. SystemCoreClock domyślnie wskazuje na taktowanie 48MHz. Co będzie jak napiszemy podobny kod i uruchomimy jego najszybszą wersję...

Kod: Zaznacz cały

#include "stm32f0xx.h"
         
int main(void)
{
   RCC->AHBENR = RCC_AHBENR_GPIOBEN;

   GPIOB->MODER |= GPIO_MODER_MODER3_0;
   GPIOB->OTYPER &= ~GPIO_OTYPER_OT_3;
   GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR3;

   GPIOB->MODER |= GPIO_MODER_MODER4_0;
   GPIOB->OTYPER &= ~GPIO_OTYPER_OT_4;
   GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR4;

   GPIOB->MODER |= GPIO_MODER_MODER5_0;
   GPIOB->OTYPER &= ~GPIO_OTYPER_OT_5;
   GPIOB->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR5;

   while(1)
   {
      GPIOB->BSRR = (GPIO_BSRR_BS_3 | GPIO_BSRR_BS_4 | GPIO_BSRR_BS_5);
      GPIOB->BSRR = (GPIO_BSRR_BR_3 | GPIO_BSRR_BR_4 | GPIO_BSRR_BR_5);
   }
}


20130828_932449.png


---EDIT---

Na koniec (?) mały test porównawczy. Weźmy ATmega8-16PU, zasilana 5V i taktowana 8MHz z Int.RC. Przy podobnie prostym programie do machania pinami

Kod: Zaznacz cały

#include <avr/io.h>

int main(void)
{
   DDRB |= 0xff;
   
   while (1)
    {
      PORTB = 0x00;
      PORTB = 0xff;
    }
}


Uzyskujemy 1,97MHz. Czyli podobnie jak w przypadku wyżej taktowanego ARM-a F103 z operacjami na rejestrze ODR!

avrm8_8.png


No robi się ciekawie... Czy rzeczywiście operacje na GPIO w układach ARM są jednak mimo wszystko dosyć wolne? Czy taktując ARM-a i AVR-a np. 16MHz okazałoby się, że AVR byłby w tym wypadku szybszy?
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.


Wróć do „STM - problemy układowe”

Kto jest online

Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 2 gości