Walczę teraz z pewną dziwną zagadką, która teoretycznie nie powinna mieć miejsca. Chodzi o jeden z moich projektów retro na 6502, ale teoretycznie nie powinno mieć to nic wspólnego z procesorem.
Oprogramowanie napisane w C i skompilowane kompilatorem CC65. Kod źródłowy jest dostępny tutaj:
Dość długo szukałem błędu w kodzie, ale nie mogłem go znaleźć. Upewniłem się, że winy nie ponosi uszkodzony RAM albo procesor. Aż w końcu zacząłem eksperymentować ze zmiennymi - zmniejszyłem rozmiar niektórych buforów, część zmiennych zmieniłem z globalnych na lokalne. Pomogło! Samoczynne resety ustały, fałszywe wciśnięcia przycisków występują, ale bardzo rzadko.
Sprawa jest jednak bardzo dziwna, bo wygląda to tak, jakbym teraz był na skraju maksymalnego wykorzystani RAM-u. A tak nie powinno być. Układ ma
8kB pamięci RAM, więc naprawdę dużo jak na taki "kontroler". W pamięci nie ma za dużo zmiennych globalnych. Są tylko dwa większe bufory (po 256 bajtów każdy), poza tym parę mniejszych buforów, trochę stosunkowo niewielkich struktur i umiarkowna ilość zmiennych. Nie ma szansy, żeby to nagle zajęło zdecydowaną większość RAM-u. Nie widzę też niczego, co mogłoby pożerać stos - nie używam nigdzie rekurencji ani nie stosuję większych zmiennych globalnych, zbyt zagnieżdżonych wywołań funkcji też nie ma.Gdyby ktoś wpadł na pomysł, że to wina niewielkiego sprzętowego stosu
6502 (zaledwie 256 bajtów w pierwszej stronie pamięci) to tłumaczę, że CC65 korzysta z programowego stosu, który działa tak, jak we współczesnych MCU, zapisując dane od końca pamięci w dół.Fragment pliku .map wygenerowanego podczas linkowania projektu potwierdza, że zmienne globalne zajmują bardzo małą część pamięci:
Segment list:
------------- Name Start End Size Align
---------------------------------------------------- ZEROPAGE 000000 000019 00001A 00001 DATA 000200 00024A 00004B 00001 BSS 00024B 0004FF 0002B5 00001 STARTUP 00804B 008066 00001C 00001 ONCE 008067 008072 00000C 00001 CODE 008073 00A022 001FB0 00001 RODATA 00A023 00A1D6 0001B4 00001 VECTORS 00FFFA 00FFFF 000006 00001
Plik cfg wygląda następująco:
MEMORY { ZP: start = $0, size = $100, type = rw, define = yes; RAM: start = $200, size = $1E00, define = yes; ROM: start = $8000, size = $8000, file = %O; }
SEGMENTS { ZEROPAGE: load = ZP, type = zp, define = yes; DATA: load = ROM, type = rw, define = yes, run = RAM; BSS: load = RAM, type = bss, define = yes; HEAP: load = RAM, type = bss, optional = yes; STARTUP: load = ROM, type = ro; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro; RODATA: load = ROM, type = ro; VECTORS: load = ROM, type = ro, start = $FFFA; }
FEATURES { CONDES: segment = STARTUP, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__; CONDES: segment = STARTUP, type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__; }
SYMBOLS { # Define the stack size for the application
__STACKSIZE__: value = $0200, type = weak; }
Ktoś ma jakiś pomysł co do tego, gdzie można szukać przyczyny? Na chwilę obecną urządzenie działa w miarę stabilnie, jednak chciałem dodać jeszcze kilka funkcji, które będą wymagały trochę RAM-u, więc przedtem muszę rozwiązać ten problem.