Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[STM32F4][C] Odbieranie danych z I2C poprzez DMA

KFplay4free 09 Apr 2017 15:45 2358 39
  • #1
    KFplay4free
    Level 5  
    Witam,
    Na początek zadam kluczowe pytanie: Czy w trybie master można tak skonfigurować DMA, by w trybie cyklicznym całkowicie odciążyć procek? Tzn. czy będzie konieczne "manualne" wysyłanie adresu, odbieranie ack'ów itp.?
    Z góry dzięki za odpowiedź :)
  • #2
    User removed account
    Level 1  
  • #3
    KFplay4free
    Level 5  
    Dzięki za odpowiedź. Jest to F446
  • #4
    User removed account
    Level 1  
  • #5
    KFplay4free
    Level 5  
    Rozumiem. Czy w takim razie wystarczy rozpocząć komunikację (wysłać START, adres i reg. adres), a DMA odbierze dane?
  • Helpful post
    #6
    User removed account
    Level 1  
  • #7
    KFplay4free
    Level 5  
    Jeszcze tylko jedno pytanie. Skąd DMA zna adres rejestru? Przecież w konfiguracji podaję tylko adres DRa...
  • #8
    Freddie Chopin
    MCUs specialist
    KFplay4free wrote:
    Skąd DMA zna adres rejestru?

    Nie ma czegoś takiego jak "adres rejestru" w standardzie I2C. To że akurat Twoje urządzenie pierwszy bajt danych interpretuje jakoś specjalnie (jako wewnętrzny adres), to już jest sprawa tego urządzenia. To jest po prostu pierwszy bajt wysłanych danych.
  • #9
    KFplay4free
    Level 5  
    No tak, ale ja chcę odbierać dane. W takim razie DMA najpierw wysyła, a potem odbiera?
  • #10
    User removed account
    Level 1  
  • #11
    KFplay4free
    Level 5  
    Te układy to L3GD20H, LSM303D i LPS25H. Jeśli chodzi o I2C to w dokumentacji każdego jest to opisane tak samo. Na razie prowadzę komunikację w przerwaniu, ale chcę odciążyć procek, więc sięgam po DMA w trybie cyklicznym.
  • #12
    User removed account
    User removed account  
  • #13
    KFplay4free
    Level 5  
    1. DMA cykliczne, pomyliłem się.
    2. Odbieram 6 bajtów.
    3. Napisałem obsługę I2C na przerwaniach samodzielnie, bez czytania RM F4. Czytałem RMy układów, z którymi się komunikuję. Natomiast rzeczywiście nie studiowałem DMA pod I2C. Z resztą, ciężko o dobre źródła z tego zakresu - często spotykam się ze stwierdzeniem, że na F4 nie warto w ogóle obsługiwać I2C przez DMA.
    Pozdrawiam
  • #14
    User removed account
    User removed account  
  • #15
    KFplay4free
    Level 5  
    Piotrus_999 wrote:
    Podziwiam - ja bez przeczytania dokumentacji uC nie umiałbym go programować.

    Używałem biblioteki I2C... ;)
  • #16
    User removed account
    User removed account  
  • #17
    KFplay4free
    Level 5  
    Piotrus_999 wrote:
    A jest przepracowany tymi kilkoma bajtami?

    No niestety jest, bo w 800Hz odbieram 6, a właściwie 12 bajtów i zajmuje mi to kilkadziesiąt procent procesora.
    Jeśli chodzi o bibliotekę, to używam jej, bo pisząc samodzielnie nie oszczędziłbym na prędkości transferu, ale rozumiem jak działa I2C. To nie jest tak, że biorę gotowca, odpalam i liczę, że będzie działał. Ale skoro chcę napisać obsługę DMA i manualnie wysyłać sekwencję START i adres układu, to czemu miałbym nie użyć niskopoziomowych funkcji z biblioteki? Moja niewiedza w zakresie tego problemu dotyczy głównie DMA pod magistralę I2C. Dodam jeszcze tylko, że rozumiem działanie samego DMA - napisałem samodzielnie obsługę, ale pod UART (co chyba jest trochę prostsze).
    Pozdrawiam
  • #18
    Freddie Chopin
    MCUs specialist
    KFplay4free wrote:
    No niestety jest, bo w 800Hz odbieram 6, a właściwie 12 bajtów i zajmuje mi to kilkadziesiąt procent procesora.

    To musi być jakiś niezły dramat ta biblioteka, ponieważ jakby tu nie liczyć, to powiedzmy że 12 bajtów to 12 przerwań, niech każde trwa (niech stracę) 1000 cykli zegara, to razem jest ledwo 12000 cykli. Skoro zajmuje Ci to "800Hz", to powiedzmy że przy zegarze 84MHz (niech stracę, załóżmy że to STM32F401) daje to tak czy siak ledwo 11%. Oczywiście liczby wziąłem z kapelusza (szczególnie to "1000"), w rzeczywistości pewnie byłoby to <1%, więc gdzie tu miejsce na "kilkadziesiąt procent"? No chyba że te przerwania ustawiają flagę, na którą czeka Twój program w pętli - wtedy tak naprawdę to jest polling, a nie żadne przerwania.
  • #19
    KFplay4free
    Level 5  
    Freddie Chopin wrote:
    12 bajtów to 12 przerwań

    W 800Hz wywoływane jest przez timer przerwanie. W funkcji obsługi przerwania wywoływane są dwie funkcje ( co 8 przerwań - 3 funkcje ), które wysyłają łącznie 2*(33 bity) i odbierają 2*(51 bitów) ( co 8 przerwań odpowiednio 3*33 + 3*51). Wychodzi 168 bitów. Częstotliwość na linii SCL to 400kHz. 400 000 Hz / 168 = ~2380 Hz. 800 Hz / 2380 Hz * 100% = ~33%
  • #20
    Freddie Chopin
    MCUs specialist
    Przecież te obliczenia są bezsensowne... Mikrokontroler nie jest "zajęty" wysyłaniem poszczególnych bitów czy bajtów przez cały czas. Wchodzi do przerwania, wpisuje coś do rejestru, wychodzi, nudzi się dalej... W rzeczywistości wysłanie jedneg bajtu przez I2C to powiedzmy kilkadziesiąt cykli zegara. Z wejściem/wyjściem z przerwania, powiedzmy że może 100-200. Przy 400kHz możesz wysłać - w przybliżeniu - max 50kB/s. Powiedzmy więc że przy 84MHz zegarze rdzenia Twoje "obciążenie" powinno wynosić (200 cykli * 50000 bajtów) / 84000000 cykli, co daje jakieś 12%. Wszystko przy grubo przesadzonych założeniach dotyczących implementacji.

    Twoje obliczenia pokazują co najwyżej "obciążenie I2C", czyli to ile "pasma" dostępnego na danej magistrali wykorzystałeś. Użycie DMA przecież nic tu nie zmieni, bo będziesz przesyłał dokładnie tyle samo danych z dokładnie tą samą "częstotliwością"...
  • Helpful post
    #21
    User removed account
    User removed account  
  • #22
    KFplay4free
    Level 5  
    Ale jak program może opuścić funkcję obsługi przerwania, będąc wewnątrz funkcji TM_I2C_ReadMulti?
    Code: c
    Log in, to see the code

    Code: c
    Log in, to see the code


    EDIT: OK, rozumiem, zrobiłem polling w przerwaniu...
  • #23
    User removed account
    User removed account  
  • #24
    KFplay4free
    Level 5  
    Napisałem obsługę I2C na przerwaniach. Niestety program wchodzi mi w UsageFault_Handler(). Prawdę mówiąc nie wiem, co to oznacza. Zamieszczę przy okazji kod, ale z tego co zaobserwowałem w debugu, program wywala się przy funkcji I2C_EV_init() :
    Code: c
    Log in, to see the code

    Tutaj jest stm32f4xx_it.c :
    Code: c
    Log in, to see the code

    Funkcja IT_I2C_Start() :
    Code: c
    Log in, to see the code

    Z góry dzięki za pomoc ;)
  • #25
    User removed account
    User removed account  
  • #26
    KFplay4free
    Level 5  
    1. Przepraszam, zapomniałem przesłać fragmentu kodu : SysTick_Config(SystemCoreClock / 800);
    2. Czy wystarczy ta jedna funkcja?
    3. Nie za bardzo wiem o co Ci chodzi, ale otrzymuję taki komunikat:
    Program received signal SIGINT, Interrupt.
    UsageFault_Handler () at ../startup/startup_stm32.s:96
    96 ../startup/startup_stm32.s: No such file or directory.
  • #27
    User removed account
    User removed account  
  • #28
    KFplay4free
    Level 5  
    Chyba o to chodzi:
    Code: c
    Log in, to see the code
  • #29
    User removed account
    User removed account  
  • #30
    KFplay4free
    Level 5  
    Ahh, czyli chodzi o to, że I2C1_EV_IRQHandler() nie jest przypisany, dobrze rozumiem?