logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[STM32][C/uVision4] Częstotliwość przerwania SysTick

persy 16 Sie 2010 23:45 14480 33
Najlepsze odpowiedzi LABEL_AI_GENERATED

Dlaczego przerwanie SysTick na STM32F103 działa za szybko i jak poprawnie ustawić źródło zegara oraz wartość reload?

SysTick_Config nadpisuje ustawienie źródła zegara i ustawia CLKSOURCE na zegar procesora, więc wcześniejsze ustawienie HCLK/8 nie daje oczekiwanego wyniku [#8406001][#8406946] Jeśli chcesz używać zewnętrznego zegara SysTick (HCLK/8), bit 2 w STK_CTRL ma być wyczyszczony, więc po konfiguracji rejestr powinien mieć 0x03, a nie 0x07 [#8406375] Przy faktycznie użytym zegarze procesora 72 MHz wpisanie 9 000 000 do LOAD daje 8 przerwań na sekundę, więc przy przełączaniu stanu LED w każdym przerwaniu widać 4 pełne mignięcia na sekundę [#8406001][#8407137] Rozwiązanie z wątku polegało na usunięciu ponownego ustawiania źródła zegara po SysTick_Config albo na ręcznej konfiguracji SysTick tak, by CLKSOURCE odpowiadał wybranemu źródłu [#8406946][#8406375]
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA
  • #1 8405867
    persy
    Poziom 2  
    Posty: 4
    Ocena: 3
    Witam

    Niedawno zacząłem "zabawę" z zestawem Kamami ZL27ARM z procesorem STM32F103VB.
    Mam problem z przerwaniem od timera SysTick. Jest ono generowane 4 razy za często - miało być 1 raz na sekundę, a jest 4.
    Kwarc 8MHz, SYSCLK = 72MHz, SysTick_CLK= 72/8=9MHz czyli załądowanie do licznika wartości 9'000'000 powinno dać zgłoszenie przerwania co 1s, więc dioda powinna przez sekundę się świecić, i przez nastepną sekundę być zgaszona. Tymczasem dioda zmienia stan co 1/4s.
    Program pisany w Keil uVsion 4. W symulatorze czas jest OK (z właczoną opcją "Limit Speed to Real-Time") i przerwanie generowane jest co 1s, ale po załadowaniu do procesora wszystko działa 4 szybciej. Dotyczy to także pętli opoźniających zapalających diody na pinach 8 i 9. Na procesorze zmieniają się mniej więcj co 0.5s, a w symulatorze co 2s.

    Sprawdzalem, co jest w rejestrach SystTicka:
    Pod adresem 0E000E010 jest wartosc 07 00 00 00 (po skonfigurowaniu) i 07 00 01 00 (po odliczeniu czasu) - czyli OK
    Pod adresem 0E000E014 jest wartosc 3F 54 89 00 (czyli 9mln-1, tez OK)

    Uzywam standardowego (bez modyfikacji) pliku startup z bibliotek \STM32F10x_StdPeriph_Lib_V3.3.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm\startup_stm32f10x_md.s

    Próbowałem też z niższymi częstotliwościami taktowania rdzenia i objawy są takie same.

    Poniżej kod programu:
    
    #include "stm32f10x.h"
    
    void GPIO_Configuration(void)
    {
      //konfigurowanie portow GPIO
      GPIO_InitTypeDef  GPIO_InitStructure; 
    
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
      GPIO_Init(GPIOB, &GPIO_InitStructure);
    }
    
    
    void RCC_Configuration(void)
    {
      //konfigurowanie sygnalow taktujacych
      ErrorStatus HSEStartUpStatus;
    
      RCC_DeInit();                                                             //Reset ustawien RCC
      RCC_HSEConfig(RCC_HSE_ON);                                      //Wlaczenie HSE
      HSEStartUpStatus = RCC_WaitForHSEStartUp();               //Odczekaj az HSE bedzie gotowy
      if(HSEStartUpStatus == SUCCESS)
      {
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//
        FLASH_SetLatency(FLASH_Latency_2);                        //ustaw zwloke dla pamieci Flash; zaleznie od taktowania rdzenia
    	                                                                   //0:<24MHz; 1:24~48MHz; 2:>48MHz
        RCC_HCLKConfig(RCC_SYSCLK_Div1);                          //ustaw HCLK=SYSCLK
        RCC_PCLK2Config(RCC_HCLK_Div1);                            //ustaw PCLK2=HCLK
        RCC_PCLK1Config(RCC_HCLK_Div2);                            //ustaw PCLK1=HCLK/2
        //RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_9); //ustaw PLLCLK = HSI/2*9 czyli 8MHz/2*9 = 36 MHz
        //RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_9); //ustaw PLLCLK = HSE/2*9 czyli 8MHz/2*9 = 36 MHz
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //ustaw PLLCLK = HSE*9 czyli 8MHz*9 = 72 MHz
        RCC_PLLCmd(ENABLE);                                               //wlacz PLL
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);//odczekaj na poprawne uruchomienie PLL
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);           //ustaw PLL jako zrodlo sygnalu zegarowego
        while(RCC_GetSYSCLKSource() != 0x08);                      //odczekaj az PLL bedzie sygnalem zegarowym systemu
    
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//wlacz taktowanie portow GPIO A, B i C
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
      }
      else
      {
      } 
    }
    
    void NVIC_Conf(void)
    {
    //Konfigurowanie kontrolera przerwan NVIC
    #ifdef  VECT_TAB_RAM  
      // Jezeli tablica wektorow w RAM, to ustaw jej adres na 0x20000000
      NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
    #else  // VECT_TAB_FLASH
      // W przeciwnym wypadku ustaw na 0x08000000
      NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
    #endif
    }
    
    
    int main(void)
    {
      volatile unsigned long int i;
    		
      RCC_Configuration();
      NVIC_Conf();
      GPIO_Configuration();
    
      GPIO_ResetBits(GPIOB, GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);		 
      
      // SysTick bedzie taktowany z f = 72MHz/8 = 9MHz
      SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
    
      // Przerwanie ma byc co 1s, f = 9MHz / 1, czyli powinno byc 9'000'000 cykli 
      if (SysTick_Config(9000000ul))
      {
        while(1);		// W razie bledu petla nieskonczona
      }					
    
    
      do{								 
         GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_SET);
         for(i = 0; i < 0x5B8D80ul; i++);			   //okolo 0.5s przy 72MHz, na plytce
         GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET);
         GPIO_WriteBit(GPIOB, GPIO_Pin_9, Bit_SET);
         for(i = 0; i < 0x5B8D80ul; i++);
         GPIO_WriteBit(GPIOB, GPIO_Pin_9, Bit_RESET);
      } while(1);
      return 0;
    }
    
    
    


    i jeszcze kod obsługi przerwania z pliku stm32f10x_it.c
    
    void SysTick_Handler(void)
    {
       GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_10)));
    
    }
    


    Może ktoś ma pomysł o co chodzi? Czy czegoś brakuje?
  • REKLAMA
  • Pomocny post
    #2 8406001
    tymon_x
    Poziom 30  
    Posty: 1021
    Pomógł: 171
    Ocena: 15
    Tak to jest jak się z tej ogłupiającej biblioteki korzysta. Zajrzałem do core_cm3.h, tam funkcja SysTick_Config(ticks) przyjmuje postać:

    static __INLINE uint32_t SysTick_Config(uint32_t ticks)
    { 
      if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                                   
      SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
      NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
      SysTick->VAL   = 0;                                          /* Load the SysTick Counter Value */
      SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                       SysTick_CTRL_TICKINT_Msk   | 
                       SysTick_CTRL_ENABLE_Msk;                    /* Enable SysTick IRQ and SysTick Timer */
      return (0);                                                  /* Function successful */
    }


    Tam wartość SysTick_CTRL_CLKSOURCE_Msk jest zdefiniowana jako 1<<2, czyli mimo że dzielisz ten sygnał przez 8, to ta funkcja przywraca poprzednie ustawienie AHB=SYSCLK według noty: PM0056 Programming manual (gorąco zachęcam do korzystanie z niej). W sumie teraz powinno wychodzić tak: 72MHz/(9M)=8Hz, czyli 8 przerwań na sekundę, 4 razy świeci/gaśnie na przemian, czyli znowu coś tu nie gra? Na razie nie mam czasu, idę spać (;
  • Pomocny post
    #3 8406375
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    persy napisał:

    Sprawdzalem, co jest w rejestrach SystTicka:
    Pod adresem 0E000E010 jest wartosc 07 00 00 00 (po skonfigurowaniu) i 07 00 01 00 (po odliczeniu czasu) - czyli OK

    Może ktoś ma pomysł o co chodzi? Czy czegoś brakuje?


    Nie jest OK!
    Zamiast 07 powinno być 03!

    Cytat:

    SysTick control and status register (STK_CTRL)

    Bits 31:17 Reserved, must be kept cleared.
    Bit 16 COUNTFLAG:
    Returns 1 if timer counted to 0 since last time this was read.
    Bits 15:3 Reserved, must be kept cleared.
    Bit 2 CLKSOURCE: Clock source selection
    Selects the clock source.
    0: AHB/8
    1: Processor clock (AHB)
    Bit 1 TICKINT: SysTick exception request enable
    0: Counting down to zero does not assert the SysTick exception request
    1: Counting down to zero to asserts the SysTick exception request.
    Note: Software can use COUNTFLAG to determine if SysTick has ever
    counted to zero.
    Bit 0 ENABLE: Counter enable
    Enables the counter. When ENABLE is set to 1, the counter loads the
    RELOAD value from the LOAD register and then counts down.
    On reaching 0, it sets the COUNTFLAG to 1 and optionally asserts the
    SysTick depending on the value of TICKINT. It then loads the RELOAD
    value again, and begins counting.
    0: Counter disabled
    1: Counter enabled
  • #4 8406946
    persy
    Poziom 2  
    Posty: 4
    Ocena: 3
    Wielkie dzięki za naprowadzenie! Faktycznie - SysTick_Config "odkonfigurowywał" mi źródło zegara. Wyrzuciłem to ponowne ustawianie źródła i teraz działa dobrze.

    Dokumentację czytałem, funkcję przechodziłem wiele razy krok po kroku... ale widocznie ze zmęczenia i frustracji ciągle przegapiałem ten jeden bit :).

    Co do 4x za szybkiego migania - jednak było 8 razy szybciej. Skoro dioda migała 4 razy to znaczy, ze zmiana (przerwanie) było 8 razy w sekundzie.
  • #5 8406993
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Cytat:
    Tymczasem dioda zmienia stan co 1/4s.


    Na pewno zmieniała stan co 1/4s czy zapalała się 4 razy na sekundę?
  • #6 8407137
    persy
    Poziom 2  
    Posty: 4
    Ocena: 3
    Jednak zmieniała stan 8 razy a nie 4. Miałem nagrany filmik - jak puściłem klatka po klatce i porządnie rano policzyłem to w ciagu sekundy było: 01010101 czyli 4 zapalenia, czyli 8 zmian stanu.
  • #7 8407638
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    Jesli w ciągu sekundy naliczyłeś zbocze 8 razy, to twoja częstotliwość
    to 4Hz. Czyli w ciągu sekundy "świeci" 4 razy...
    Więc jeśli "co systick" generujesz zbocze, to systick tłucze z częstotliwością 8Hz.

    Cytat:
    Faktycznie - SysTick_Config "odkonfigurowywał" mi źródło zegara.

    I to kolejny dowód na to, że trzeba czytać manuale a nie korzystać
    z durnych bibliotek...
  • #8 8409921
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    Cytat:
    Faktycznie - SysTick_Config "odkonfigurowywał" mi źródło zegara.
    I to kolejny dowód na to, że trzeba czytać manuale a nie korzystać
    z durnych bibliotek...


    Pewnie, najlepiej klepać wszystko od zera, bo po co korzystać z bibliotek, w końcu "prawdziwy programista" uwielbia przekopywać się przez setki stron manuali, datasheetów i utrudniać sobie życię.
    Biblioteki od STMa może nie idealne, ale są nienajgorsze i stworzone po to by ułatwiały/przyśpieszały programowanie. To że zdarzją się błedy to już inna kwestia..nikt nie jest nieomylny.
  • REKLAMA
  • #9 8409978
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    A jak coś nie działa, to i tak trzeba kopać przez te setki stron manuali.
    Biblioteki do czegokolwiek operujące na tak niskim poziomie dostępu
    jeszcze nigdy nic nie usprawniły. Przeważnie nie działają tak jak powinny.

    adamusx napisał:
    [...]To że zdarzją się błedy[...]

    To nie jest kwestia błędów. Wykorzystanie bibliotek wymusza pewną
    kolejność wywoływania ichnich dziwnych funkcji, zeby wszystko
    raczyło działać zgodnie z założeniami. Ale nigdzie w dokumentacjach
    nie jest napisane
    jaka to kolejność. Fakt, że po zaznajomieniu
    się z źródłami bibliotek
    łatwo wywnioskować, jaką kolejność przyjąć,
    ale to już wtedy wymaga wyższego stopnia zaawansowania. A
    niby bilblioteki są po to, żeby ułatwić życie...

    Poza tym - tak jak napisałem już w innym topicu - po co deklarować
    struktury, zmieniać w nich milion niepotrzebnych zmiennych i
    wywoływać dziwne funkcje
    , skoro identyczny efekt daje w 99% przypadków zapis typu: USART2->CR1=0x206C;

    I zgadza się, może Kolega nie uważa mnie za programistę :), ale lubię,
    chcę i widzę konieczność
    w zapoznaniu się z dokumentacją. Wtedy i
    tylko wtedy ma się stuprocentową kontrolę nad procesorem, z którym
    się pracuje. Zauważmy, że ludzie nie korzystający z bibliotek nie mają
    z nimi problemów...
    Oczywiste...:D
  • #10 8410597
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    adamusx napisał:

    Pewnie, najlepiej klepać wszystko od zera, bo po co korzystać z bibliotek, w końcu "prawdziwy programista" uwielbia przekopywać się przez setki stron manuali, datasheetów i utrudniać sobie życię.

    Nie przesadzaj, jak napisał kolega wyżej, sam plik stm32f10x.h wystarcza, nie musisz wklepywać przecież dziesięciu tysięcy adresów rejestrów od nowa. A zapis USART1->GTPR |= 0xfcd2 jest 500 razy bardziej czytelny niż wywoływanie stu miliardów procedur.

    Cytat:

    Biblioteki od STMa może nie idealne, ale są nienajgorsze i stworzone po to by ułatwiały/przyśpieszały programowanie. To że zdarzją się błedy to już inna kwestia..nikt nie jest nieomylny.


    Czy ja wiem... Programowanie zwalniają o tyle, że trzeba się przekopywać nie tylko o datasheet, ale też przez te biblioteki, żeby zobaczyć co tam się dzieje i po co. Datasheet nie jest do nich przystosowany, więc pomocy można szukać tylko po forach, w przykładach i książkach. Jak się jej nie używa, to w 90% przypadków sam datasheet wystarczy, zakładając, że programista jest osobą dość ogarniętą
  • #11 8410688
    tymon_x
    Poziom 30  
    Posty: 1021
    Pomógł: 171
    Ocena: 15
    Polać im wina. Też się z tym zgadzam, sam stm32f10x.h w zupełności wystarczy plus podstawowe manuale i datasheet od mikrokontrolera.

    Ale jeśli kogoś korci korzystać z tej głupawej biblioteki, tu ma wersję jej opisu w starym poczciwym pe-de-efie zanim przeszła na chaotyczny plik pomocy.
    Załączniki:
    • STM32-LIB_manual.7z (1.51 MB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #12 8410971
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    Korzystanie z tej biblioteki poza tym mają również inne wady:

    1) Struktury inicjalizacyjne marnują pamięć. Te struktury są spakowane,
    więc dostęp do bitów w tej strukturze jest utrudniony. Co modyfikacja
    bitfielda kompilator musi uzywac instrukcji BFI,AND,ORR,BIC.
    Marnuje to sporo czasu, zamiast DWOCH instrukcji LDR,STR.
    Odczyt zawartości struktury jest też utrudniony, wykorzytując przesunięcia,
    BFX i operacje logiczne.
    kosmiczna strata czasu...

    2) Dostęp do rejestrów konfiguracyjnych odbywa się przez funkcje, która
    na chama wpisuje w rejestry zawartość struktur. Jeśli mamy dobry
    powód (np. rekonfiguracja DMA w przerwaniu) żeby machać jednym
    bitem
    , to zamiast machać nim w SFRrze, grzebiemy w strukturze
    i wywołujemy funkcje, która zmieniając interesujący nas bit wykona
    ileś zupełnie niepotrzebnych zapisów.

    3) Z powyższego wynika, że przy próbie zmiany konkretnej
    rzeczy w konkretnym SFRrze, głupia funkcja zapisze wszystko.
    Co jeśli to "wszystko" to są flagi przerwań lub Interrupt Enable, które
    zmienia się np. w przerwaniu i nie wolno sobie tego ot tak zmienić?

    4) Skoki do nie inline-owanych funkcji. Po raz kolejny marnowanie
    mocy obliczeniowej. Ze funkcja przyjmuje wskaznik, musi dokonywać
    jego dereferencji i dodatkowo zużywa na to czas. Popatrzcie w listing
    disasemblacji. Nawet przed samym skokiem procesor przygotowuje się
    do jego wykonania. Musi postawić wskaznik na strukturę w Rn, pobrać
    adres skoku itp.

    Niech zwolennicy bibliotek pokonają powyższe argumenty :) powodzenia!
  • #13 8411022
    tymon_x
    Poziom 30  
    Posty: 1021
    Pomógł: 171
    Ocena: 15
    Ja bym dodał jeszcze o bardzo przydatnym narzędziu zwanym bitband. Jak funkcja z tej biblioteki zwraca jakąś wartość (powiedzmy status flagi), to robi odczyt, maskowanie i zwrot. Nie powiem już o zmianie pojedynczego bitu w rejestrze. Czytelniej i mniej linijek zajmie zdefiniowanie sobie dostępu do określonych bitów: Bit-banding on Cortex-M3.
  • REKLAMA
  • #14 8411851
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    nsvinc napisał:
    ..Poza tym - tak jak napisałem już w innym topicu - po co deklarować struktury, zmieniać w nich milion niepotrzebnych zmiennych i
    wywoływać dziwne funkcje
    , skoro identyczny efekt daje w 99% przypadków zapis typu: USART2->CR1=0x206C;


    Pewnie, a po 3 miesiacach każdy będzie pamiętał co oznaczała wartość 0x206C... Nie mówiąc już o osobie, która potem miałaby taki kod po kimś rozczytywać.

    Chociaż co do rozbydowanych struktur to się zgadzam, gdy chcemy zmienic jedną wartość latwiej zapisać konkretną zmienną do konkretnego rejestru z pominięciem struktur.
  • #15 8412048
    Tantalos
    Poziom 18  
    Posty: 142
    Pomógł: 39
    Ocena: 3
    adamusx napisał:
    nsvinc napisał:
    ..Poza tym - tak jak napisałem już w innym topicu - po co deklarować struktury, zmieniać w nich milion niepotrzebnych zmiennych i
    wywoływać dziwne funkcje
    , skoro identyczny efekt daje w 99% przypadków zapis typu: USART2->CR1=0x206C;


    Pewnie, a po 3 miesiacach każdy będzie pamiętał co oznaczała wartość 0x206C... Nie mówiąc już o osobie, która potem miałaby taki kod po kimś rozczytywać.

    Chociaż co do rozbydowanych struktur to się zgadzam, gdy chcemy zmienic jedną wartość latwiej zapisać konkretną zmienną do konkretnego rejestru z pominięciem struktur.

    Przecież można w komentarzu napisać co 0x206C oznacza i po problemie.
  • REKLAMA
  • #16 8412974
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Ale piszecie herezje... kosmosy typu 0x33D9 są najgorsze ze wszystkiego... Jest tylko JEDNO dobre rozwiązanie, które jest już zaimplementowane w pliku nagłówkowym stm32f10x.h

    przykład:

    USART1->CR1=USART_CR1_UE|USART_CR1_TE|USART_CR1_RE|USART_CR1_RXNEIE;
    RCC->CFGR|=RCC_CFGR_PLLMULL6|RCC_CFGR_PLLSRC|RCC_CFGR_PPRE1_DIV2|RCC_CFGR_MCO_HSE;


    I od razu wiadomo o co chodzi - zakładając, że ktoś zna dany układ peryferyjny, ale jak nie to w żadnym przypadku by nie zrozumiał co się dzieje.

    Ja osobiście najwięcej stosuję bitbandów (jeśli mowa o Cortex-M3):

    RCC_CR_HSEON_bb=1;						// enable HSE clock
    while (!RCC_CR_HSERDY_bb);				// wait for stable clock
    ADC1_CR2_JSWSTART_bb = 1;
    I2C1_CR1_START_bb = 1;					// request a start
    while (I2C1_SR1_SB_bb == 0);			// wait for start to finish


    Żadnej biblioteki nie potrzeba, jest szybko, wydajnie, zrozumiale, przejrzyście - czego chcieć więcej?

    4\/3!!
  • #17 8413093
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    -> Freddie Chopin
    Akutat z Tobą kłócić się nie będę. Jak już ktoś rozumie zbyteczność
    i problematyke korzystania z bibliotek, to już jest wszystko jedno, czy
    stosujesz 0xblablabla czy coś co stoi pod #define. Każdy pisze jak mu
    wygodniej.
    Mi jest wygodniej pisać 0xblabla, bo jak właśnie piszę, to wiem co piszę
    bo na drugim monitorze mam datasheet lub manual. I zawsze piszę
    komentarze. Jestem już na tyle wjatemniczony, że nie pomylę w liczbie
    pozycji bitu, więc podczas wpisywania liczby w SFR istnieje ryzyko pomyłki
    rzędu 5ppm. :)
    Nikt nie krytykuje tego, czy zamiast podać liczbę hexem zorujesz kilka/kilkanaście define-ów. Liczba finalnie zapisana do SRFa będzie ta sama.

    Ja mogę powiedzieć, że dla mnie Twój kod jest nieczytelny - i równocześnie
    w kilku przykładach zupełnie niepraktyczny....
  • #18 8413424
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Freddie Chopin napisał:

    Ja osobiście najwięcej stosuję bitbandów (jeśli mowa o Cortex-M3):

    RCC_CR_HSEON_bb=1;						// enable HSE clock
    while (!RCC_CR_HSERDY_bb);				// wait for stable clock
    ADC1_CR2_JSWSTART_bb = 1;
    I2C1_CR1_START_bb = 1;					// request a start
    while (I2C1_SR1_SB_bb == 0);			// wait for start to finish



    Te bitbandy sam zdefiniowałeś czy jest to już gdzieś dostępne???
  • #19 8413528
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Sam sobie je definiuje - mam już sporą kolekcję plików nagłówkowych do wielu peryferiów z takimi właśnie definicjami... Musze to kiedyś wrzucić na stronę.

    4\/3!!
  • #20 8413602
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Freddie Chopin napisał:
    Sam sobie je definiuje - mam już sporą kolekcję plików nagłówkowych do wielu peryferiów z takimi właśnie definicjami... Musze to kiedyś wrzucić na stronę.

    4\/3!!

    A sprawdzałeś jak CS-GCC sobie radzi z nimi, bo w pierwszych wersjach obsługujących CM3 nie bardzo mu to wychodziło?
  • #21 8413682
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    radzi sobie perfekcyjnie (;

     800019a:	2201      	movs	r2, #1
    [...]
    	ADC1_CR2_JSWSTART_bb = 1;				// start Injected Group
     800019e:	4b0d      	ldr	r3, [pc, #52]	; (80001d4 <adc_get_internals+0x50>)
     80001a0:	601a      	str	r2, [r3, #0]
    	while (ADC1_SR_JEOC_bb == 0);			// wait for conversions to end
     80001a2:	4a0d      	ldr	r2, [pc, #52]	; (80001d8 <adc_get_internals+0x54>)
     80001a4:	6813      	ldr	r3, [r2, #0]
     80001a6:	2b00      	cmp	r3, #0
     80001a8:	d0fb      	beq.n	80001a2 <adc_get_internals+0x1e>
    	ADC1_SR_JEOC_bb = 0;					// reset "end of conversion" flag
     80001aa:	2300      	movs	r3, #0
     80001ac:	6013      	str	r3, [r2, #0]
    [...]
     80001d4:	42248154 	.word	0x42248154
     80001d8:	42248008 	.word	0x42248008


    4\/3!!
  • #22 8413752
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Rzeczywiście! Nic dodać nic ująć. :hop: :hop: :hop: :))
    Chyba poświęcę trochę czasu i na LM3s potworze te definicje.
  • #24 8414348
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    Przerobiłem ten przykład na taki, bez bitbandu i zajmuje około 944 bajty...
    bitbandowy oryginał to około 640 bajtów :P
  • #26 8414747
    gaskoin
    Poziom 38  
    Posty: 4159
    Pomógł: 436
    Ocena: 102
    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4203.html do utworzenia bitbandu, dla w sumie wszystkiego, wystarczy ta strona. Zamiast szukać po bibliotekach adresów peryferiów, wystarczy chyba po prostu &DAC->DHR8R2, z resztą z tego co widzę, w przykładzie mignięcia diodą też to tak jest zrobione.


    Nie wiem tylko, czy ten adres jest wtedy zawsze przy użyciu pobierany ? Czy już na poziomie kompilacji jest to robione?
  • #27 8414758
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    W moich przykładach właśnie tak jest to zrobione

    #define RCC_CR_PLLRDY_bb					bitband_t m_BITBAND_PERIPH(&RCC->CR, RCC_CR_PLLRDY_bit)


    Adresy jeśli są stałe (a tutaj są), obliczane są na etapie kompilacji/linkowania, a nie w programie.

    4\/3!!
  • #28 12319904
    kiclaw
    Poziom 16  
    Posty: 252
    Pomógł: 4
    Ocena: 5
    Odkopuje stary temat bo nie ma sensu żebym zakładał nowy, a pytanie mam bardzo podobne.

    Gdzie w datasheet STM32F407VGT6 znajduje się opis rejestru SysTicka? Wczoraj przekopałem cały i nie mogę nic znaleźć nic prócz "SysTick calibration value register" który i tak i tak nie jest opisany. Doszedłem do tego samego momentu autor tematu, czyli chciałbym mieć przerwanie co sekundę, a mam o wiele częściej, chciałbym operwać bezpośrednio na rejestrach bo w tym przypadku jak widać biblioteka nie jest zbyt dobrym pomysłem, no ale nie wiem gdzie znajdę opis tego rejestru.
  • #29 12319973
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Szukaj w dokumentacji rdzenia, bo systick jest jego częścią
    Link
  • #30 12320327
    kiclaw
    Poziom 16  
    Posty: 252
    Pomógł: 4
    Ocena: 5
    Aaaa no widzisz, nie wiedziałem że są dwie dokumentacje, jedna do rdzenia a druga do konkretnego mikroprocka. Dzieki!

    No to korzystając z bibliotek, po inicjalizacji włączyłem takie coś:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    No i teraz działa co sekundę. No ale chciałbym żeby to było zrobione całkowicie na rejestrach a nie przez biblioteki więc w dokumentacji jest napisane coś takiego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Więc napisałem taki kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    No i generalnie działa co sekundę. Ale tutaj moje pytanko bo dopiero zaczynam przygodę z ARM. Czy tutaj nie ma żadnego babola, tzn czy ten kod nadaje się do projektów czy trzeba coś tu jeszcze dodać?

    Druga sprawa to to, skąd wiadomo że wybranie zewnętrznego oscylatora domyślnie dzieli sygnał przez 8? W dokumentacji o tym nic nie jest napisane, a dowiedziałem się o tym dopiero z forum.

    Pozdrawiam

Podsumowanie tematu

LABEL_AI_GENERATED
W dyskusji poruszono problem z częstotliwością przerwania SysTick w mikrokontrolerze STM32F103VB, który generował przerwania cztery razy za często, zamiast raz na sekundę. Użytkownik skonfigurował SysTick z kwarcem 8MHz i SYSCLK 72MHz, co powinno skutkować przerwaniem co 1s. Po analizie okazało się, że problem wynikał z nieprawidłowej konfiguracji źródła zegara w funkcji SysTick_Config. Po usunięciu tej konfiguracji przerwania zaczęły działać poprawnie. W dyskusji podkreślono również znaczenie korzystania z dokumentacji oraz wyzwań związanych z używaniem bibliotek, które mogą wprowadzać dodatkowe komplikacje w programowaniu.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA