WinAVR: Názvy proměnných, použití static u globálních prom.

Zdravím.
To neni poprvý, co sem narazil na to, že C kompiler v AVR studiu (doinstalované WinAVR) je nehorázná srágora.
Promiňte mi to vyjadřování, ale po 6 hodináchm, co sem se nehnul zmísta, díky výše zmíněnému kompilátoru, to už je fakt vrchol. Já se snad vrátím k ASM. Tam mě všecko poslocuhalo a fungovalo jak má, jen s tím, že některé věci se psaly obtížněji, a byly složitější na přemýšlení.
Ale k věci… Začal jsem psát program, který má dělat cosi, c oje hooodně složité na vysvětlení, a nyní to je nepodstatné. Podstatné je to, co vám nyní ukážu.
Tato část programu způsobí blikání LED diod na I/O pinech po dobu 3 sekund:

ControlLED(0b0110, 0b0100); _delay_ms(3000); ControlLED(0, 0);

Ovšem problém, se kterým se s prominutím seru už několik hodin je ten, že to bliká jen tehdy, pokud zakomentuju tu část programu co je za tím v té nekonečné smyčce while. Tak sakra, kdo my vysvětlí, jeslti já jsem debil, nebo jestli debil programoval ten C kompilátor.
Pokud někdo vidíte někde, jakou tam mám chybu, že část programu, která ani ještě neproběhla mi ovlivňuje programovou část právě běžící… tak tohle opravdu nechápu.
Disassembler jsme nezkoumal, ale sei se tam vzteky podívám, co to tam vymýšlí za ptákoviny.

[code]#include <avr/io.h>
#define F_CPU 4000000U
#include <util/delay.h>
#include <avr/interrupt.h>

volatile char position;
volatile char realpos;
volatile int counter;
volatile char LEDf;
volatile char div;
volatile char btns; //b0 - DOWN, b1 - UP, b2 - DNblock, b3 - UPblock

void ControlLED(char state, char flash)
{
LEDf = flash;
PORTB = (PORTB & 0xF0) | (state & 0x0F);
}

//****************************** IRQ ***************************

ISR(TIMER0_OVF_vect)
{
div++;
if (div==15)
{
div = 0;
PORTB = (PORTB & 0xF0) | ((PORTB ^ LEDf) & 0x0F);
}

if (!(btns & 0b00000100) && !(PINB & 0b01000000)) btns |= 0b00000101;
if ((btns & 0b00000100) && (PINB & 0b01000000)) btns &=~0b00000101;

if (!(btns & 0b00001000) && !(PINB & 0b10000000)) btns |= 0b00001010;
if ((btns & 0b00001000) && (PINB & 0b10000000)) btns &=~0b00001010;
}

ISR(INT0_vect)
{
if (PIND & 0b00001000) counter++; else counter–;
}

//****************************** MAIN **************************

int main(void)
{

PORTB = 0b11000000;
DDRB = 0b00111111;

PORTD = 0b01001100;
DDRD = 0b00000000;

TCCR0A = 0;
TCCR0B = (1<<CS02);
TIMSK = (1<<TOIE0);

GIMSK = (1<<INT0);
MCUCR = (1<<ISC01);

sei();

div = 0;
LEDf = 0b0000;
btns = 0;
counter = 0;
position = 0;
realpos = 0;

ControlLED(0b0110, 0b0100);
_delay_ms(3000);
ControlLED(0, 0);

while (1)
{
if (btns & 0x01) //DOWN
{
btns &=~0x01;
if (position > 0)
{
position–;
ControlLED((1<<position), (1<<position));
//Pozadavek na presun
}
}

if (btns & 0x02)  //UP
{
  btns &=~0x02;
  if (position < 3)
  {
    position++;
	ControlLED((1<<position), (1<<position));
	//Pozadavek na presun
  }
}


_delay_ms(10);

}

while (1) ;
}
[/code]

Promiňte mi mé podrážděné chování, ale koho by tohle po n hodinách nenasralo.

EDIT: Jen tak ze srandy jsem ke všem proměnným přidal slovčko “static” a ono to najednou začalo fungovat. PROČ?!

:arrow_right: administrator: přejmenováno z "AVR Studio C kompiler - kdo je tu blbej?"

Použití static u globálních proměnných má vliv pouze na viditelnost mezi více soubory s kódem. Zdroják v 1 souboru by to nemělo ovlivnit.

Jesli se neplteu, tak v úvodním makru chybí na konci “L”: “#define F_CPU 4000000UL”

Detaily, které by na problém neměly mít vliv: proměnné “position” a “realpos” by se měly bez volatile obejít (nepracuje se s nimy v přerušení), mohly by být lokální v main. Main by měl mít návratovou hodnotu void nebo doplnit return.

Edit: přejmenuj proměnnou “div” třeba na “divi” a snad to pojede. Důvod mi není jasnej, ale na tiny2313 měla proměnná adresu přes 200H, což je samozřejmě nesmysl (mimo ram, jedině flash, ale tam nemá co dělat). Po přejmenování je umístěná správně.
V gcc je funkce div(), tak to asi dělá problémy (ikdyž je v headeru, kterej přímo neimportuješ, může ho importovat jinej soubor).

No, já vím (treda aspoň tuším) co dělá static, ale nechápu, proč to vyřešilo ten problém.

div jsem pojmenoval od slova “divider”, pač je to softwarová dělící proměnná. No co, GCC kompiler je debílek, a nerozliší proměnnou od funkce.
Díky za upozornění, zkusím si s tím pohrát.

u toho makra F_CPU na konci L být nemusí, protože to kompiler (doufám) sám od sebe nadefinuje jako long integer. (stejně tak i to U je tam zbytečné, taky to běhá bez něj, ale radši tam unsigned píšu).

Tak jsem to přejmenoval, a zdá se, že to začalo i fungovat bez těch static.
Každopádně díky piityy za upozornění na ten název proměnné.

Static asi kompiler nějak nakoplo takže si uvědomil, že jde o proměnncou. V čistém C totiž nejsou statické funkce, tudíž mu to asi doteklo.
Podezřelým názvům funkcí/proměnných (jako asm instrukce nebo zkratky mat. operací viz. zde) se radši vyhýbej.

V simulátoru však bylo vidět poměrně dobře, že je tam cosi shnilého. Ona proměnná se neinkrementovala a její adresa byla jak pěst na oko (včetně nápisu “FLASH” za adresou). Po přejmenování si můžeš také všimnout, že se zmenšil výsledný kód, ta funkce tam již očividně není :wink:.

Mimochodem ta proměnná by měla být statická v přerušení (nikde jinde se nepoužívá). A jelikož se nevyužívá mimo přerušení, není nutné volatile, protože z pohledu přerušení se k ní nepřistupuje asynchronně.

Na to, že kompiler něco nadefinuje sám bych radši moc nespoléhal (třeba 1000*1000 nadefinuje špatně jako int nebo uint). V některé příští verzi to nebude chodit a budeš na to koukat jak puk :slight_smile:.