Keresd a hibát

Avagy az ilyenekért szeretek labort tartani:


volatile int * ptr_ps2 = 0x40000000;
char read_key() {
        char status;
        char key;
        while (1) {
                status = *(ptr_ps2);
                while ((status & 0x1) == 1) {
                        status = *(ptr_ps2);
                }

                key = *(ptr_ps2 + 1);
                if (key == 0xF0) {
                        status = *(ptr_ps2);
                        while ((status & 0x1) == 1) {
                                status = *(ptr_ps2);
                        }
                        key = *(ptr_ps2 + 1);
                        clear_display(0);
                        return key;
                }
        }
}

Mit kell tudni: ptr_ps2 egy ps2 periféria státuszregiszterére mutat. Alsó bitje 1, ha a fogadó FIFO üres. *(ptr_ps2+1)-ból olvasva pedig kiveszed a FIFO-ból az aktuális karaktert (ha empty, akkor szemetet).
A PS/2 periféria működése: billentyű nyomvatartásakor a karakter ASCII kódját (átfordítja SCAN kódból) teszi a FIFO-ba, utána felengedéskor egy 0xf0 értéket, utána megint a karakter ASCII kódját.
Tünet: sosem lép ki a függvény, hiába nyomja az ember a billentyűket.

UI: van spoiler-tag a HUP-on? Leírnám a megoldást is :-)

Hozzászólások

A státusz kiolvasás egyben az adatot is kiolvassa? (mert pl a char szélesebb az adott környezetben, mint 8 bit?)

Üdv,
Marci

Barkochba ér? Az az érzésem, hogy a (key == 0xF0) sose lesz igaz valamiért, pedig eljut odáig. Rosszfelé járok?

Üdv,
Marci

Mert a 0xF0 akkor kerül a key-be, amikor az if belsejében olvassuk ki a következő karaktert, amit viszont sose nézünk nem-e 0xF0?

Szerk: Ez egy marhaság pls ignore (de mekkora! :D - látszik, hogy okostelefonon nem látszik egyben minden - tán akkor nem írok ekkora hülyeséget)

Üdv,
Marci

A 0xF0 az +240 (integer konstans, legalább 16 bit előjeles konstans, platformfüggő, hogy pont hány).

Ha ezt beleteszem egy előjeles char-ba, aztán visszaalakja a program implicite (signed)int-té az összehasonlításhoz, az már -16, tehát nem egyenlők.

Ez amúgy nem is teljesen C specifikus, hasonló szívásokat Java-ban is el lehet követni.

:D
Ezt szerettem én is a tanításban. Meg a jó kérdéseket, amik annyira relevánsak az adott helyen, mintha csak megbeszéltük volna a táncrendet. :)
Amúgy sejtettem, hogy a C típuskezelése körül lesz a megoldás, de a tudás hiánya megakadályozott, hogy megtaláljam :)

Üdv,
Marci

...vagy az ismeretlen tartalmú clear_display() sose tér vissza valamiért.

Üdv,
Marci

C-től borsódzik a hátam, de:
int pointer-t derefel és tárolja el egy char-ba (gondolom a fordító azért minimum warningolt rá... remélem).

A másik tipp, hogy a PS/2 vezérlő nem várja meg a 0xF0 ellenőrzés előtti kiolvasást, hanem addigra visszaírta a karakter kódját, úgyhogy visszalép a ciklusba.

BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)

Csak egy tipp: Az if elojeles es nem elojeles valtozokra maskepp mukodik a fordító miatt.

Nah egy kis update egy kis peldaval:


#include <stdio.h>

int main(){
unsigned char key;
char elojeles_key;
key = 0xF0;
elojeles_key = 0xF0;

    if (key == 0xF0)
    {
        printf("Key jol mukodik\n");
    }
    else
    {
        printf("Key nem jol mukodik\n");
    }

    if (elojeles_key == 0xF0)
    {
        printf("Elojeles key jol mukodik\n");
    }
    else
    {
        printf("Elojeles key nem jol mukodik\n");
    }
}

Ami lefordítva és futtatva a következőt adja:


~$ gcc elojeles.c -o elojeles
~$ ./elojeles 
Key jol mukodik
Elojeles key nem jol mukodik
~$ 

Ha szétvesszük a forrást két részre külön-külön lefordítjuk, hogy lássuk mit is csinál a fordító, akkor a fordítás után ezt kapjuk az előjelnélküli változó használata esetén::


        .file   "nem_elojeles.c"
        .section        .rodata
.LC0:
        .string "Key jol mukodik"
.LC1:
        .string "Key nem jol mukodik"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushl   %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        andl    $-16, %esp
        subl    $32, %esp
        movb    $-16, 31(%esp)
        cmpb    $-16, 31(%esp)
        jne     .L2
        movl    $.LC0, (%esp)
        call    puts
        jmp     .L4
.L2:
        movl    $.LC1, (%esp)
        call    puts
.L4:
        leave
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Debian 4.7.2-5) 4.7.2"
        .section        .note.GNU-stack,"",@progbits

Ez nagyjából úgy néz ki, mint amit egy ember is írna. A feltétel teljesülésének vizsgálatát a cmpb végzi és jne ugrással megy az else ágra.
Előjeles változó definiálása esetén másképp néz ki a dolog:


       .file   "elojeles.c"
        .section        .rodata
.LC0:
        .string "Elojeles key nem jol mukodik"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushl   %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        andl    $-16, %esp
        subl    $32, %esp
        movb    $-16, 31(%esp)
        movl    $.LC0, (%esp)
        call    puts
        leave
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Debian 4.7.2-5) 4.7.2"
        .section        .note.GNU-stack,"",@progbits

Ami elsőre feltűnik, hogy az "Elojeles key jol mukodik" hianyzik,ez pedig azt jelenti, hogy bizony itt valami okossággal van dolgunk. Ahogy hiányzik a cmpb is, helyette csak egy call hívás van a printf-hez. Bizony, a fordítónk kioptimalizálta a kódunkat.

De ez csak okoskodás, mert nem vagyok programozó, és C-hez sem értek.
--
"Maradt még 2 kB-om. Teszek bele egy TCP-IP stacket és egy bootlogót. "

Én hülye vagyok a C-hez, de én azt a "while (1)" részt írnám át.

[ Falu.me ]