Hello all,
I have started working again on a little project of mine involving an ATmega8. It's halfway done and using printf() and its brothers had already brought the flash usage to around 6500 bytes, so I decided that I can go with my own functions to print to USART. I wrote these:
void myputchar(char c) { if (c == '\n') myputchar('\r'); while ((UCSRA & (1 << UDRE)) == 0) {}; //loop_until_bit_is_set(UCSRA, UDRE); UDR = c; } /******************/ void myprint(char *s) { char *t; t = s; while (*t) { myputchar(*t); t++; } }
They seem to work fine, as I can do things such as:
myprint("Configuring Two-Wire Interface (I2C)...\n");
and even:
char s[8]; atoi(myint, s, 10); myprint(s); myputchar('\n');
and everything works (of course, it's not as flexible or elegant as printf(), but it's not a problem).
The issue I'm facing is probably not even linked to it, but since I did this, a global variable called "state" is not being properly initialized. It is declared like this in my main.c, *outside* the main() function:
uint8_t state = STATE_BOOTING;
(STATE_BOOTING, STATE_NORMAL and STATE_CONSOLE are #define'd as 0, 1 and 2 respectively)
This "state" variable is used at start-up, as I have a 3000 ms delay to allow the user to send ESC down the USART to switch to "console mode". The problem is that "state" is not initialized to 0, but rather to a random value usually around 26000, but right now it's *exactly* 8192.
Printing it out inside the ISR for the USART_RXC vector, I get this if I press ESC during the delay:
Key pressed. Current state: 8192, key code: 27
Of course, as the "state" variable is not the same as STATE_BOOTING, it is not considered and after a few seconds (*not* 3 seconds as expected) it goes to "normal mode" (do_normal()), printing this:
Starting normal operation.
configuration
Reading thermometer configuration
which is weird, because the code generating it is:
void do_normal(void) { uint8_t i = 0; uint8_t conf; int8_t temperature; myprint("Writing thermometer configuration\n"); thermo_writeconf(0x0b); myprint("Reading thermometer configuration\n"); conf = thermo_readconf(); /* ... */ }
The funny thing is that if I press any key at this point, "state" is actually incremented by 1, as if the "state = STATE_NORMAL" statement which is carried out right before calling do_normal() worked... albeit the zero is not really zero, but is the original value of "state":
Key pressed. Current state: 8193, key code: 97
I even tried moving the original assignment of state to main(), as in "state = 0", but it doesn't seem to be considered at all. I attempted to run avr-objdump with -d -S to get inline source code, and even though I'm completely ignorant when it comes to avr assembly, it seems to me that it's completely dismissed:
int main(void) { 8e: 10 92 62 04 sts 0x0462, r1 state = 0; USART_init(); 92: 4c d0 rcall .+152 ; 0x12c//stdout = &mystdout; myprint("\x1b[2J"); // clear screen 94: 81 ec ldi r24, 0xC1 ; 193 96: 90 e0 ldi r25, 0x00 ; 0 98: 5c d0 rcall .+184 ; 0x152 myprint("\x1b[0;0H"); // go home 9a: 86 ec ldi r24, 0xC6 ; 198 9c: 90 e0 ldi r25, 0x00 ; 0 9e: 59 d0 rcall .+178 ; 0x152
I am extremely confused. Could someone please help shed some light on the matter? :)
Thank you in advance