Enkla men fatala buggar

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Enkla men fatala buggar

Inlägg av sodjan »

Ja, det går ju inte att "cacha" t.ex "PORTA", det kan ju ändra sig
hur det vill på porten utan att cachen har en susning.

Och visst, en massa optimeringar kopplas ifrån, men det är ju
just det som man vill uppnå, så det är inget "problem".
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Att cache för de addresser som är deklarerade på detta sätt inaktiveras elller gås förbi.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45168
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Enkla men fatala buggar

Inlägg av TomasL »

Cachen fungerar inte på det sättet, i alla fall inte i de flesta uProllar.

Det handlar helt enkelt om att förhindra kompilatorn från att optimera bort kod, som den tror är onödig.

Ponera att du har deklarerat en variabel,

Kod: Markera allt

unsigned char a;
sedan väntar du på att variabeln skall få ett visst värde:

Kod: Markera allt

while (a!=100);
Kompilatorn kan i vissa lägen få för sig att "a" aldrig kommer att få värdet 100, eftersom "a" inte används någon annan stans i programmet, följaktligen tar kompilatorn bort alla referenser för "a" och ersätter det hela med
while(1)
Vilket inte är meningen, eftersom i detta fallet kan "a" få ett värde från något annat, a kan vara en port, till exempel, eller också kan man ha en DMA-överföring som startas någon annanstans och ger "a" ett värde.

I dessa lägen behöver man använda "volitile"

(enkel och kort förklaring)
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Enkla men fatala buggar

Inlägg av sodjan »

Jag tror inte heller att cachen någonsin är inblandad vid läsning
från hårdvaruportar. Men det viktiga är, som sagt, att kompilatorn
inte ska försöka vara smart och göra gissningar kring variablen.

> Det handlar helt enkelt om att förhindra kompilatorn från att optimera bort kod,

Eller att *flytta* på kod, t.ex flytta ut "myvar = PORTA;" från en loop och lägga
det en gång *innan* loopen eftersom PORTA (ju) inte ändras i loopen. En vanlig
C optimering.
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: Enkla men fatala buggar

Inlägg av superx »

kimmen skrev:Sådan aliasing är ju inte heller tillåten enligt C-standarden, så det är med all rätt GCC gör sådana antaganden.
Det stämmer! Men det finns ju kod som fungerar så länge inte kompilatorn utnyttjar dessa delar av standarden bokstavligt så att säga, vilket kan vara svårfelsökt. Moderna gcc-versioner har dock bra varningar för detta har jag för mig.
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Re: Enkla men fatala buggar

Inlägg av arte »

blueint skrev:Att cache för de addresser som är deklarerade på detta sätt inaktiveras elller gås förbi.
Inte på ARMv7, där cachas volatile. Det ända som avgör ifall någoting fastnar i Cache är hur man har satt upp sina page tabeller.
Så t.ex PORTA skall vara volatile OCH den pagen skall markeras som device.
På ARM är volatile är bara till för kompilatorn, CPUn bryr sig inte ett dugg. Den kollar bara på page tabeller.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Vad menas med "page tabeller" på ARM? det är ju rätt många som inte har någon MMU.
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Re: Enkla men fatala buggar

Inlägg av arte »

blueint skrev:Vad menas med "page tabeller" på ARM? det är ju rätt många som inte har någon MMU.
Bra poäng, tror endast det gäller ARMv7-AR arkitekturen. Altså Cortex A processorerna och kanske också Cortex R serien.
Vet inte hur ARMv7-M fungerar, kanske är mer som de andra uC?

Tror att Cortex-M har fördefinerade adressspann där IO skall ligga men att man kan komma runt det med en MPU.
Sedan så tror jag inte Cortex-M har någon inbyggd cache utan det är upp till tillverkaren (t.ex TI) att implementera en sådan.
gkar
Inlägg: 1453
Blev medlem: 31 oktober 2011, 15:28:29
Ort: Linköping

Re: Enkla men fatala buggar

Inlägg av gkar »

blueint skrev:Vad menas med "page tabeller" på ARM? det är ju rätt många som inte har någon MMU.
Samma som på andra processorer. https://en.wikipedia.org/wiki/Page_table
Volatile har inget med minnescachning att göra, det är ett kompilatordirektiv.

ARM finns i olika versioner, med eller utan cache, ARM7TDMI tex har inte cache, det är bara en kärna. ARM720T har cahe och MMU. Samma med ARM9.

En del processesorer har en MPU istället för MMU.
Birger1234
Inlägg: 466
Blev medlem: 20 februari 2011, 23:32:40
Ort: Gävle

Re: Enkla men fatala buggar

Inlägg av Birger1234 »

Användarvisningsbild
adent
Inlägg: 4094
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Enkla men fatala buggar

Inlägg av adent »

volatile används även med fördel på globala variabler som delas mellan main() och interrupt-rutiner. Brukar funka bra ändå om man inte optimerar, men slår man på optimering kan det gå åt skogen.

För övrigt skrev en jobbarkompis något liknande följande kod och fattade inte varför det inte funkade :)

if(!strcmp("foo->bar->string", "MinFinaJämförelseSträng")) ...

bit96 skrev väldigt utförliga kommentarer till det där att plocka ut high och low nibble. Det tycker jag verkar lite väl mycket.
Det är bra med kommentarer, men man får inte kluttra ner koden med för mycket kommentarer heller. Förekommer sådana bitshiftningar
ofta i ens kod så räcker det med en kort kommentar före varje om ens det imho då.

Kommentarer ska främst vara där det inte alls är uppenbart vad koden gör.

Dåligt:

Kod: Markera allt

printf("Value %d\n");  // Skriver ut "Value" följt av värdet och enterslag
if(lcd_on) ...   // Om LCD:n är på
Kanske motiverat:

Kod: Markera allt

if(lcd_on && power_good) ...  // Om LCD:n är på och spänningen är över 4.5V
Fast där agerar 4.5V mest som en påminnelse om vad power_good är bra för och det bör man ju rimligtvis ha koll
på, lätt att kolla upp. Dessutom kan ju definitionen lätt ändras och man missar att uppdatera kommentaren, lurigt.

Motiverat:

Kod: Markera allt

if(power_down)
{
  power_on();  // Kretsen kan vara av och måste initieras ordentligt för att kunna stängas av korrekt.
  power_off();
}
MVH: Mikael
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

För den där "if(!strcmp("foo->bar->string", "MinFinaJämförelseSträng")) ..." så måste man också kontrollera att foo är en giltig pekare, och att bar också är det samt till sist string. Annars kan man få mycket intressanta resultat .. ;)
Användarvisningsbild
bit96
Inlägg: 2492
Blev medlem: 3 september 2007, 10:04:29
Ort: Säffle

Re: Enkla men fatala buggar

Inlägg av bit96 »

adent skrev: if(!strcmp("foo->bar->string", "MinFinaJämförelseSträng")) ...
Jag antar att citationstecken skall bort på första parametern annans kommer if-villkoret aldrig uppfyllas.

Vad de gäller kommentarer så är det naturligtvis individuellt.
Men jag menar att de skall uttrycka vad som händer i ett större sammanhang.
Det skall nästan vara som att läsa en berättelse.
Man förstår vad som händer även om man inte läser koden.

Kod: Markera allt

printf("Value %d\n");  // Skriver ut "Value" följt av värdet och enterslag
if(lcd_on) ...   // Om LCD:n är på
Här kan jag hålla med om att kommentarerna är onödig, eller egentligen dåligt skrivna.
Att tala om att printf() skriver ut är meningslöst, det ser man ändå. Kommentaren blir bara en upprepning av koden.

Istället bör man tala om varför och vad som är syftet, t.ex. /* Skriv ut PID-inställningens P-värde */
(Det saknas för övrigt en parameter i printf()-exemplet)

"// Om LCD:n är på" är meningslös information.
Möjligen skulle man kunna skriva syftet med if-testen.
if(lcd_on) ... /* Om LCD:n är på så rensa skärmen eller nåt... */

Alltså, kommentaren kan handla om vad som är syftet med koden, inte vara en text-upprepning av vad koden gör.
Men ibland är koden komplicerad och då bör kommentaren istället beskriva med ord vad som händer.
Det är en avvägningssak som inte är helt lätt.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45168
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Enkla men fatala buggar

Inlägg av TomasL »

Interruptköer kan skapa problem.
Vi har haft en bug som plågat oss ett tag.
Problemet är att den bara inträffat typ en gång varannan vecka, helt slumpmässigt.

Det visade sig att det var uppköing av interrupt som orsakade problemet, och det inträffar bara när vissa saker händer inom ett intervall om runt 200 ns eller så.
Vi har ett UART tx interrupt, vilket ger interrupt när det finns plats i TX-bufferten.
När interruptet inträffarer, stänger vi av RX-interruptet (för att inte störa TX)
Samt nollställer TX-Int-flaggan, därefter fyller vi på Bufferten.
När Bufferten är påfylld sista gången, stänger vi av TX-interruptet och slår på RX-interruptet.
Mellan det vi slår av flaggan och slår på RX är det runt 200-300ns instruktioner, dock har det visat sig att vid vissa tillfällen, typ varannan vecka eller så, så hinner vi tömma TX-bufferten innan vi hinner slå av TX-interruptet, vilket då innebär att det blir uppköat, och återgenereras, trots att vi inte har något att sända, vilket i sin tur innebar att RX aldrig blev påslaget.

Lösning, rensa INT-flaggan det sista innan man hoppar ur rutinen (elementärt egentligen), dock har aldrig problemet visat sig "Inhouse"
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: Enkla men fatala buggar

Inlägg av johano »

Alltså, kommentarer ska inte förklara *vad* koden gör utan *varför* den gör det.
Om man behöver kommentarer för att förklara vad koden utför så har man skrivit dålig kod.

Edit: alltså precis som Bit96 skrev ovan...

/johan
Skriv svar