Sida 8 av 11

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 19:46:08
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".

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 20:28:38
av blueint
Att cache för de addresser som är deklarerade på detta sätt inaktiveras elller gås förbi.

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 20:29:59
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)

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 20:44:46
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.

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 23:30:59
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.

Re: Enkla men fatala buggar

Postat: 2 juni 2014, 02:36:16
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.

Re: Enkla men fatala buggar

Postat: 2 juni 2014, 03:43:46
av blueint
Vad menas med "page tabeller" på ARM? det är ju rätt många som inte har någon MMU.

Re: Enkla men fatala buggar

Postat: 2 juni 2014, 16:38:16
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.

Re: Enkla men fatala buggar

Postat: 4 juni 2014, 10:28:15
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.

Re: Enkla men fatala buggar

Postat: 27 juni 2014, 20:34:35
av Birger1234

Re: Enkla men fatala buggar

Postat: 28 juni 2014, 00:13:29
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

Re: Enkla men fatala buggar

Postat: 28 juni 2014, 04:04:52
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 .. ;)

Re: Enkla men fatala buggar

Postat: 28 juni 2014, 09:25:42
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.

Re: Enkla men fatala buggar

Postat: 15 augusti 2014, 22:11:10
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"

Re: Enkla men fatala buggar

Postat: 16 augusti 2014, 00:22:20
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