Articolul descrie procesul de proiectare a unui driver pentru transmisia datelor de mare viteză de tip SPI (Serial Peripheral Interface) între microcontroler și ADC. Următoarele secțiuni vor prezenta o scurtă descriere a diferitelor modalități de optimizare a driverului SPI și a configurației necesare pe ADC și microcontroler. După această scurtă prezentare, va fi oferită o descriere detaliată a exemplului de cod corespunzător transmisiei de date SPI și a accesului direct la memorie (DMA). La final, se va face o demonstrație a randamentului ADC-ului cu același driver existent într-un alt microcontroler (ADuCM4050, MAX32660).
Odată cu evoluția tehnologiei, este necesară transmiterea mai precisă a datelor în cadrul aplicațiilor IoT (Internetul lucrurilor) cu consum redus de putere și al celor de calcul edge/cloud. În figura 1, sistemul wireless de detecție este un sistem de achiziție de date de înaltă precizie cu un convertor analog-digital (ADC) pe 24-biți. În acest caz, problema noastră este dacă microcontrolerul își poate permite interfața serială de mare viteză a convertorului de date.
Prezentarea driverului SPI general
După cum sugerează și titlul, furnizorii de microcontrolere oferă un driver SPI general/API cu exemplu de cod pentru fiecare microcontroler. Driverul general SPI/API poate acoperi, de regulă, majoritatea aplicațiilor utilizatorilor care pot avea numeroase configurații sau instrucțiuni. În unele scenarii specifice, cum ar fi achiziția de date ADC, driverul SPI general nu poate satisface viteza maximă de procesare a datelor din ADC deoarece sunt implementate prea multe și diverse configurații în driverul general. Configurațiile care nu sunt utilizate în aplicație creează o supraîncărcare suplimentară și cauzează o întârziere de timp.
Idei și practică
Pentru a extrage datele de la ieșirea unui ADC prin SPI, ar trebui să alegem un microcontroler ca dispozitiv principal atât pentru consumul său redus de putere, cât și pentru performanțele sale de mare viteză. Cu toate acestea, atunci când o transmisie de date se bazează pe driverul SPI de la ADI, viteza se poate degrada din cauza comenzilor care nu sunt funcționale în aplicația ADC-to-MCU (microcontroler). Pentru a profita în totalitate de potențialul de viteză al ADC-ului, experimentăm cu ADuCM4050 și AD7768-1 și încercăm soluții posibile. În ciuda vitezei maxime a datelor de ieșire de 256 kHz (în condițiile filtrului implicit), ADuCM4050 este limitat, în prezent, la 8 kHz. Printre soluțiile potențiale pentru accelerarea ratei de ieșire se numără eliminarea comenzilor inutile și activarea controlerului DMA. Aceste idei sunt realizate în secțiunile următoare.
Microcontrolerul ca element principal
Microcontrolerul ADuCM4050 MCU este un dispozitiv cu un consum foarte redus de putere, cu o frecvență a ceasului de 26 MHz. Sistemul este activat de procesorul Arm® Cortex®-M4F. ADuCM4050 dispune de trei interfețe SPI, iar fiecare dintre acestea încorporează două canale DMA, de recepție și de transmisie, care se interfațează cu controlerul DMA. Controlerul DMA și canalele DMA oferă un mijloc de transfer de date între memorie și periferice. Aceasta este o modalitate eficientă de distribuire a datelor, permițând nucleului să se ocupe de alte sarcini.
ADC ca Nod
AD7768-1 este un ADC sigma-delta (Σ-Δ) pe 24-biți, cu consum redus de putere, de înaltă performanță. Rata datelor de ieșire ODR (Output Data Rate) și modul de disipare a puterii sunt reglabile pentru a satisface cerințele utilizatorilor. Factorul de decimare și modul de putere determină împreună ODR, după cum se arată în tabelul 1.
Mod de putere | Decimare | ODR |
Fast (MCLK/2) | ×32 | 256 kHz |
Fast (MCLK/2) | ×64 | 128 kHz |
Median (MCLK/4) | ×32 | 128 kHz |
Median (MCLK/4) | ×64 | 64 kHz |
Low Power (MCLK/16) | ×32 | 32 kHz |
Low Power (MCLK/16) | ×64 | 16 kHz |
Tabelul 1: Configurarea modului de alimentare (Power Mode Configuration) pentru rata datelor de ieșire
Modul de citire continuă al dispozitivului AD7768-1 este, de asemenea, o caracteristică semnificativă. Datele de ieșire ale ADC-ului sunt stocate în registrul 0x6C. În general, datele din registrul ADC necesită specificarea adresei înainte de fiecare operațiune de citire/scriere. Modul de citire continuă permite extragerea directă a datelor din registrul 0x6C după fiecare semnal privind disponibilitatea datelor. Datele de ieșire ale ADC-ului reprezintă un semnal digital pe 24-biți care se convertește în volți, după cum se arată în tabelul 2.
Descriere | Intrare analogică | Cod de ieșire digitală |
+Full Swing –1 LSB | +4.095999512 V | 0x7FFFFF |
Midscale +1 LSB | +488 nV | 0x000001 |
Midscale | 0 V | 0x000000 |
Midscale –1 LSB | –488 nV | 0xFFFFFF |
–Full Swing –1 LSB | –4.095999512 V | 0x800001 |
–Full Swing | +4.096 V | 0x800000 |
Tabelul 2: Codurile de ieșire și tensiunea de intrare ideală
Diagrama de conectare a fluxului de date
ADuCM4050 și AD7768-1 sunt utilizate ca modele de exemplu pentru tranzacția de date. Conexiunea pinilor este prezentată în figura 4.
Semnalul de resetare a acestora este trimis de la pinul GPIO28 al microcontrolerului la pinul RST_1 al ADC-ului, iar semnalul privind disponibilitatea datelor este trimis de la ADC DRDY_1 la pinul GPIO27 al microcontrolerului. Restul pinilor sunt conectați ca o configurație SPI generală, în care MCU (microcontrolerul) este principalul și ADC este nodul. SDI_1 primește comenzile de citire/scriere ale registrului ADC de la microcontroler, iar DOUT_1 trimite datele de ieșire către microcontroler.
Realizarea transmisiei de date
Întreruperea transmisiei de date
Pentru a realiza o transmisie de date continuă, folosim GPIO27 (conectat la DRDY) ca declanșator al întreruperii. Atunci când ADC-ul trimite un semnal către GPIO27 prin care se anunță că datele sunt disponibile, microcontrolerul rulează funcția de rechemare, în care sunt incluse comenzile de transmisie de date. După cum se arată în figura 5, achiziția de date trebuie să fie gestionată în intervalul dintre întreruperea A și întreruperea B.
Cu ajutorul driverului SPI ADI, putem realiza cu ușurință transferul de date între ADC și microcontroler. Cu toate acestea, ODR-ul ADC va fi limitat la 8 kHz din cauza comenzilor redundante din driver. Pentru a accelera procesul, ajustăm codurile pentru a fi cât mai mici. Introducem două metode pentru transmisiile de date DMA: transferul DMA în modul “Basic” și transferul DMA în modul “Ping-pong”.
Transfer DMA – Modul “Basic”
Înainte de fiecare tranzacție DMA, sunt necesare unele setări SPI și DMA (a se vedea exemplul de cod din figura 6). SPI_CTL este configurația SPI. SPI_ CTL=0x280f este derivată din valoarea setată pentru driverul SPI de la ADI. SPI_CNT este numărul de octeți de transfer. Deoarece fiecare tranzacție DMA poate transmite doar un număr fix de 16 biți, SPI_CNT trebuie să fie un multiplu de 2. În cazul nostru, SPI_CNT=4 este ales pentru a acoperi datele de ieșire pe 24-biți ale ADC-ului. SPI_DMA register este activarea SPI DMA. SPI_DMA=0x5 activează cererea DMA de recepție. pADI_DMA0->EN_SET=(1<<5) activează DMA, al cincilea canal DMA – SPI0 RX.
Nume | Descriere |
SRC_END_PTR | Source end pointer |
DST_END_PTR | Destination end pointer |
CHNL_CFG | Control data configuration |
Tabelul 3. Structură registru DMA
Fiecare canal DMA are câte un registru DMA prezentat în tabelul 3. Rețineți că sfârșitul adresei sursei de aici (adică SPI0 Rx) nu are nevoie de nicio incrementare pe parcursul întregii operațiuni, deoarece Rx FIFO împinge automat datele din registru. Pe de altă parte, sfârșitul adresei de destinație este calculat prin funcția (adresa de destinație + SPI_CNT -2) în conformitate cu driverul SPI de la ADI.
Adresa curentă este, aici, adresa unui buffer intern. Configurarea datelor de control DMA include setările pentru dimensiunea datelor sursă, incrementul adresei sursă, incrementul adresei de destinație, numărul de transferuri rămase și modul de control DMA. Valoarea 0x4D000011 setează configurația așa cum este descrisă în tabelul 4.
Registru | Descriere | Valoare |
DST_INC | Incrementare adresă de destinație | 2 octeți |
SRC_INC | Incrementare adresă sursă | 0 |
SRC_SIZE | Incrementare adresă sursă | 2 octeți |
N_minus_1 | Numărul total de transferuri în ciclul DMS curent – 1 | 1 (N = 2) |
Cycle_ctrl | Modul de operare al ciclului DMA | Mod “Basic” |
Tabelul 4. Configurația DMA pentru setarea datelor de control 0x4D00011
Cu comanda de citire fictivă SPI_SPI0 -> RX, începe sincronizarea SCLK, iar datele de ieșire sunt transmise de la ADC la microcontroler prin linia MISO. Există, totodată, unele transferuri de date neglijabile pe linia MOSI. Odată ce Rx FIFO este umplut, se generează cererea DMA, activând astfel controlerul DMA pentru a transfera datele de la sursa DMA (adică SPI0 Rx FIFO) la destinația DMA (adică bufferul intern). Este demn de remarcat că solicitarea Tc este generată la SPI_DMA=0x3.
La final, menținem adresa de destinație pentru următoarea transmisie de 4 octeți, adăugând 4 la adresa de destinație curentă.
De asemenea, vă rugăm să aveți în vedere că atât pADI_DMA0->DSTADDR_CLR, cât și pADI_DMA0->RMSK_CLR pentru canalul DMA SPI0 trebuie să fie setate ca funcții principale înainte de apariția primei întreruperi. Registrul anterior este DMA Channel Destination Address Decrement Decrement Enable Clear, care setează deplasarea adresei de destinație după fiecare transfer DMA în modul incremental (doar în modul incremental operează funcția pentru calculul adresei de destinație). Cel de-al doilea registru este DMA Channel Request Mask Clear, care șterge starea de solicitare DMA pentru canalul respectiv.
O diagramă de timp pentru transferul DMA în modul “Basic” este prezentată în figura 7a. Sloturile de timp reprezintă semnalul DRDY, setările SPI/DMA și, respectiv, transmisia de date DMA. Pentru a utiliza mai bine timpul de inactivitate al CPU, dorim să atribuim sarcini pentru CPU în timp ce controlerul DMA se ocupă de transferul de date.
Transfer DMA – Modul “Ping-Pong”
După implementarea comenzii fictive de citire, controlerul DMA începe transferul de date, lăsând procesorul microcontrolerului inactiv și fără sarcini. Dacă putem face ca CPU-ul și controlerul DMA să lucreze simultan, gestionarea sarcinilor nu mai este serială, ci paralelă. Prin urmare, putem efectua configurarea DMA (de către CPU) și transferul de date DMA (de către controlerul DMA) în același timp. Pentru a materializa această idee, este necesar așa-numitul mod “ping-pong” pentru controlerul DMA. Modul “ping-pong” încorporează două seturi de structuri DMA – primară și alternativă.
Controlerul DMA comută automat între cele două structuri la fiecare solicitare DMA. Inițial setată la 0, variabila p marchează care structură DMA este responsabilă: cea primară (p = 0) sau cea alternativă (p = 1). Dacă p = 0, tranzacția de date DMA primară începe la comanda de citire fictivă. În același timp, se atribuie valori pentru structura DMA alternativă, care va fi responsabilă în următorul ciclu de întrerupere. Dacă p = 1, structurile primară și alternativă își schimbă rolul. Modificarea structurii DMA în timpul unui transfer DMA poate eșua doar în cazul în care structura primară se află în modul DMA “Basic”. Utilizarea modului “ping-pong” permite procesorului să acceseze și să scrie structura DMA alternativă în timp ce cea primară este citită de controlerul DMA și invers. După cum se arată în figura 7b, tranzacția de date DMA poate fi efectuată imediat după ce semnalul DRDY a fost transmis de la ADC la microcontroler, deoarece configurarea structurii DMA se face în ultimul ciclu. CPU și DMA lucrează acum simultan, fără ca una să o aștepte pe cealaltă. Ne așteptăm ca acum să existe loc pentru optimizarea ODR a ADC-ului, deoarece timpul total de operare este semnificativ redus.
Optimizarea administratorului de întreruperi
Intervalul de timp între semnalele privind disponibilitatea datelor nu include numai timpul de execuție a comenzilor din funcția de rechemare, ci și pe cele din administratorul de întreruperi GPIO al ADI.
La activarea microcontrolerului, procesorul rulează fișierul start-up (și anume, startup.s). În acest fișier sunt definite toate evenimentele, inclusiv managerul de întreruperi GPIO. Odată ce întreruperea GPIO este declanșată, se execută funcția de gestionare a întreruperii (adică GPIO_A_INT_HANDLER și GPIO_B_INT_HANDLER în driverul GPIO ADI). În funcțiile generale de administrare a întreruperilor, unitatea centrală de procesare caută prin toți pinii GPIO pe cel care s-a declanșat, îi șterge starea de întrerupere și execută funcția de rechemare înregistrată. În aplicația ADC-MCU utilizată, DRDY este singurul semnal de întrerupere. Prin urmare, am dori să ajustăm funcția pentru a accelera procesul. Printre soluțiile posibile se numără (1) retargetarea în fișierul start-up și (2) modificarea managerului de întreruperi original. “Retargeting” înseamnă autodefinirea unui manager de întreruperi și înlocuirea celui original în fișierul de inițializare (start-up).
Modificarea, pe de altă parte, necesită un driver GPIO autodefinit. Alegem cea din urmă opțiune și modificăm funcția ca în figura 8, unde aceasta șterge doar starea de întrerupere a pinului conectat la DRDY și trece direct la funcția de apelare. Vă rugăm să rețineți că driverul GPIO original trebuie blocat prin debifarea căsuței de includere în “build target”.
Rezultat
Performanță de viteză
Să presupunem că utilizatorul citește acum cele 200 de date de ieșire ale ADC-ului pe 24-biți. Rata de biți SPI este setată la 13 MHz. Conectăm pinul cu semnalul DRDY și SCLK la osciloscop. Prin observarea intervalului de timp dintre semnalul DRDY și începutul transmisiei de date SPI (de asemenea, transmisia DMA), putem cuantifica îmbunătățirea vitezei în fiecare metodă introdusă în acest articol. Pentru comoditate, ne referim la intervalul de timp dintre semnalul DRDY și începutul semnalului SCLK ca ∆t. Pentru rata de biți SPI de 13 MHz, Δt măsurate sunt:
- (a) DMA în modul “Basic” Δt = 3,754 μs.
- (b) DMA în modul “Ping-pong” Δt = 2,8433 μs
- (c) DMA în modul “Ping-pong” cu administrator de întreruperi optimizat Δt = 1,694 μs
Metodele (a) și (b) pot suporta un ODR de 64 kHz, în timp ce metoda (c) poate suporta un ODR de 128 kHz. Acest lucru se datorează faptului că ∆t pentru metoda (c) este cel mai scurt, permițând ca SCLK să se încheie mai devreme. Dacă semnalul SCLK – adică transmisia de date – se face înainte de T/2 (T este perioada de date de ieșire curentă a ADC-ului), va fi disponibilă multiplicarea ODR. În comparație cu performanța vitezei ODR de 8 kHz a driverului SPI de la ADI, acest lucru poate fi considerat un progres extraordinar.
MAX32660 cu AD7768-1
Care este rezultatul atunci când se utilizează MAX32660, adică un microcontroler cu o frecvență de ceas de 96 MHz? În acest caz, am utilizat o întrerupere a transferului de date, cu administrator de întreruperi optimizat. Cu această setare de întrerupere, se poate obține o rată de date de ieșire de 256 kHz fără funcția DMA. Vedeți figura 10.
Concluzie
Cu ADC-ul selectat (AD7768-1) și unul dintre cele două microcontrolere (ADuCM4050 sau MAX32660), putem realiza un transfer de date de mare viteză prin SPI. Pentru a atinge obiectivul de optimizare a vitezei, realizăm transferul de date în conformitate cu driverul SPI de la ADI, dar reducem comenzile redundante. De asemenea, activarea controlerului DMA degrevează nucleul și accelerează transferul continuu de date. Datorită modului DMA “ping-pong”, cu un program adecvat se reduce timpul de configurare DMA. Pe lângă accelerarea prin DMA, administratorul de întreruperi poate fi, de asemenea, optimizat prin specificarea directă a pinului de întrerupere. Cea mai bună performanță ajunge la un ODR ADC de 128 kSPS la o rată de biți SPI de 13 MHz.
ADuCM4050 (MCU) | MAX32660 (MCU) | ||||
Data Transaction | Interrupt Without Optimization | Basic Mode DMA |
Ping-Pong Mode DMA |
Interrupt with Optimization |
Interrupt with Optimization |
Bus Type | SPI | SPI | SPI | SPI | SPI |
Main Clock Rate | 26 MHz | 26 MHz | 26 MHz | 26 MHz | 96 MHz |
SPI Clock Rate | 13 MHz | 13 MHz | 13 MHz | 13 MHz | 20 MHz |
Interval Between DRDY and SCLK | 6.34 µs | 3.754 µs | 2.834 µs | 1.694 µs | 1.464 µs |
Output Data Rate | 8 kSPS | 32 kSPS | 64 kSPS | 128 kSPS | 256 kSPS |
Tabelul 5: Conexiune SPI de mare viteză realizată cu ADuCM405 și MAX32660
Mulțumiri
De-a lungul scrierii acestei disertații am beneficiat de mult sprijin și asistență.
Dorim să-i mulțumim lui Charles Lee, a cărui expertiză a fost neprețuită în ceea ce privește experiența hardware, suportul software și chiar sfaturi de depanare.
De asemenea, am dori să-i mulțumim mentorului nostru, William Chen, pentru îndrumarea sa în ceea ce privește suportul tehnic.
În sfârșit, dorim să-i mulțumim lui Frank Chang, care ne-a împărtășit o mare parte din experiența tehnică din cariera sa.
Autori: Denny Wang, Applications Engineer and Sally Tseng, Applications Engineer
Despre autori
Denny Wang este inginer de aplicații care a petrecut un an și jumătate în cadrul programului NCG la Analog Devices Taiwan. Deține o diplomă de master în ingineria circuitelor integrate de la Universitatea din Peking. În timpul școlii postuniversitare, s-a implicat în domeniul procesării semiconductorilor, al controlului motoarelor BLDC/PMSM și al circuitelor analogice. S-a alăturat ADI în 2021, iar în prezent, se ocupă de soluții de sistem, securitate și autentificare a datelor și transmisie wireless MQTT.
Sally Tseng este inginer de aplicații stagiar la ADI Taiwan. Este studentă în ultimul an la National Taiwan University, specializându-se în inginerie electrică. Proiectele ei la NTU se referă, în principal, la cercetarea circuitelor analogice. De asemenea, în perioada stagiului de practică la ADI, se ocupă și de sisteme embedded.
Vizitați https://ez.analog.com