Enhet 3 / 9

Innebygde systemer og mikrokontrollerkode

Gevinster:

  • Evne til å definere register-, avbrudds- og tidskrav for mikrokontrolleren med en klar melding
  • Evne til å sjekke C/Arduino-koden produsert av AI når det gjelder registerinnstillinger, bufferoverflyt og sanntidsbegrensninger
  • Evne til å bruke vanen med å verifisere den genererte koden ved å måle den på maskinvare (oscilloskop, seriell port)

Innebygd systemutvikling er der programvare og maskinvare krysser hverandre: å sette en registerbit feil, holde et avbrudd for lenge eller overfylle en buffer vil forårsake merkelige, vanskelige å reprodusere feil i feltet, selv om koden "kompileres" og kjører. AI er virkelig en akselerator på dette området; Den kan produsere innledende skjeletter, maskinvareabstraksjonsfunksjoner, tilstandsmaskiner og kommunikasjonsrutiner. Men AI ser ikke databladet til kortet ditt, kjenner ikke klokkefrekvensen din og merker ikke sanntidsbegrensningene dine. I denne enheten vil vi dekke hvordan du tydelig definerer mikrokontrollerarbeid til AI, hvordan du sjekker den genererte C/Arduino-koden, og hvorfor du bør måle alt i maskinvare.

Definere kravet tydelig: Registrer, klipping, timing

Å fortelle AI å "tenne opp en LED" vil ikke fungere; Hvilket kort, hvilken pinne, hvilken klokkefrekvens, hvilken timing? Når du tilordner en innebygd oppgave til AI, bruk dette rammeverket: maskinvare (MCU-familie, klokke, pin), funksjon (hva vil skje), begrensning (timing, strøm, minne) og grensesnitt (register, HAL, Arduino-bibliotek).

Svak forespørsel / sterk forespørsel

SVAK: "Produser PWM med STM32." (Resultat: hvilken tidtaker, hvilken frekvens, hvilken pinne er uklart; generelt, sannsynligvis feil registernavnkode.) STERK: "Produser 20 kHz, 0-100% justerbar duty PWM på TIM3 CH1 (PA6) for STM32F103 (72 MHz systemklokke). Skriv på registernivå (ikke HAL HAL og kHRR-verdier viser 2 ALCHULATE-verdien og CALCH-kalkulering). i kommentarlinjen - Sett plikten med en funksjonsparameter mellom 0-100 - Kommenter hver registerbit du bruker.

Forskjellen er at den kraftige ledeteksten får modellen til å vise beregningen og avsløre klokkeforutsetningen. Så du kan sjekke prescaler/ARR-verdiene uavhengig:

For 20 kHz PWM (72 MHz klokke): Timer_clock = 72 MHz Hvis vi ønsker forhåndsskalering = 72-1 → tellerklokke = 1 MHzARR = (1 MHz / 20 kHz) - 1 = 50 - 1 = 49Verifikasjon: 1e6 / (49+1) = 20 000

Revisjon av AI-kode: Hva skal du se etter?

Bare fordi den genererte koden kompilerer betyr det ikke at den fungerer riktig. Følg denne sjekklisten:

kontrollområde

Hva du skal se etter

Register/bit-innstillinger

Nøyaktig kompatibel med dataark, riktig bitmaske

Avbryt (ISR)

Er den kort? Ingen blokkeringsforsinkelse? Brukes flyktig?

buffer/array

Er det grensekontroll? Fare for overløp?

timing

Med forsinkelse eller timer? Er den faktiske tidsbegrensningen oppfylt?

Type og bredde

8/16/32-biters overløp, signert/usignert forvirring

makt/vaktbikkje

Uendelig loop fôring vakthund?

Avbruddstjenesterutiner (ISR) er den vanligste feilkilden. AI legger noen ganger delay() eller lang loop inne i ISR. Dette fører til at andre avbrudd blir savnet og vakthund tilbakestilles. Regel: ISR skal være så kort som mulig; Hovedjobben bør være å sette opp et flagg og flytte det til hovedsløyfen.

// SVAK (AI produserer noen ganger dette): Blocker-funksjon i ISR ​​void TIM3_IRQHandler(void) { if (TIM3->SR & TIM_SR_UIF) { TIM3->SR &= ~TIM_SR_UIF; read_sensor(); // kan ta lang tid - BAD CASE_Delay(10); // forsinkelse i ISR ​​- VERY BAD }}// STERK: ISR kort; jobb flyttes til hovedsløyfevolatile uint8_t tick_flag = 0; // volatile CONDITIONvoid TIM3_IRQHandler(void) { if (TIM3->SR & TIM_SR_UIF) { TIM3->SR &= ~TIM_SR_UIF; tick_flag = 1; //sett bare flagg }}// i hovedsløyfe:if (tick_flag) { tick_flag = 0; read_sensor(); }

Forsiktig: Enhver variabel som deles mellom avbruddet og hovedsløyfen må være flyktig. Ellers kan kompilatoren bufre variabelen i registeret og gå glipp av oppdateringen. AI glemmer ofte dette nøkkelordet; Se etter det spesielt når du leser koden.

Bufferoverløp og typefeil

AI kan kopiere data fra den serielle porten til en matrise med fast størrelse uten grensekontroll. I et innebygd system betyr dette knusing av sammenhengende minne og uforklarlige krasj. Sørg for at grensen er kontrollert ved hver strcpy, array index og DMA buffer. På samme måte tilbakestilles en 8-bits teller etter 255; AI kan ignorere dette og stole på en overfylt konto.

Verifikasjon i maskinvare: "Fungerer" er målt, ikke antatt

I et innebygd system er det mest pålitelige beviset måleren, ikke kompilatoren. Bekreft den genererte koden på disse tre måtene:

  1. Oscilloskop/logikkanalysator: Mål PWM-frekvens, signaltiming og kommunikasjonsbølgeform. Hvis du ønsket 20 kHz, se 20 kHz på skjermen.
  2. Seriell port (UART)-logg: Skriv ut variabelverdier, tilstandsoverganger og feiltellere og sammenlign med forventet oppførsel.
  3. Bundet og stresstesting: Test om systemet holder seg under høyest belastning, raskeste data og dårligste timing.

Hvis den målte verdien ikke stemmer overens med beregningen, er klokkeforutsetningen, prescaler-verdien eller registerinnstillingen feil; jage.

Mini etui

Et team med studenter har AI-utskriften av en avstandsmålingskode med en HC-SR04 ultralydsensor. Koden kompilerer, men avstanden gir alltid latterlige verdier. Når de kobler det til oscilloskopet, ser de at ekkobenet beregner timingen i millisekunder i stedet for mikrosekunder; AI brukte millis() i stedet for micros(). Denne ettordsfeilen forvirret hele målingen med en faktor på 1000. Når de skriver ut den rå ekkotiden inn i serieloggen og sammenligner den med en ekte linjal, finner de feilen og fikser den. Leksjon: kompilert kode er ikke riktig kode; Måling i maskinvare avslører feilen umiddelbart.

Vanlige feil

  • Godta registernavn og bitmasker uten å sammenligne dem med dataarket.
  • Tillater blokkeringsforsinkelse eller lang behandling i ISR.
  • Glem flyktig på delte variabler.
  • Omgå buffer- og array-grensekontroll; ser ikke overløpet.
  • Stole på klokkefrekvens og tidsantakelser uten å verifisere dem.
  • Vurderer at koden "fungerer" uten å måle den med oscilloskop/serielogg.

Oppsummert

  • Definer tydelig den innebygde oppgaven når det gjelder maskinvare, funksjon, begrensninger og grensesnitt.
  • Få AI til å beregne tidsverdier som forskalering/ARR og verifisere dem uavhengig.
  • Hold ISR-er korte, bruk volatile på delte variabler.
  • Se spesielt etter register, buffergrense og typebreddefeil.
  • "Det fungerer" er bevist med et oscilloskop, logikkanalysator og seriell logg, ikke med kompilatoren.
  • Hvis den målte verdien ikke stemmer overens med beregningen, forfølge forutsetningene.

Søknadsoppgave

Med en mikrokontroller du har (Arduino, STM32, ESP32), be AI om PWM eller en periodisk oppgave med en viss frekvens. Før du laster inn koden: (1) kontroller frekvens-/tidspunktverdiene uavhengig av kontoen i kommentarfeltet, (2) sjekk for flyktige og blokkerende i ISR ​​og delte variabler. Etter opplasting, mål den faktiske frekvensen med et oscilloskop eller logikkanalysator og sammenlign den med målet. Hvis det er et avvik, finn kilden og korriger den, og noter hva som ble antatt feil.