355 | | Pour ce TME, vous n'aurez qu'une seule étape |
356 | | == Ajout de l'ISR timer |
357 | | |
358 | | |
359 | | |
360 | | |
361 | | == Game Over |
362 | | |
363 | | Dans le premier TME, vous avez réalisé un petit jeu dans lequel vous deviez deviner un nombre tiré au hasard. Ce jeu avait été mis dans kinit parce qu'a ce moment, il n'y avait pas encore d'application utilisateur. Nous vous proposons de mettre le jeu dans l'application user et de limiter le temps pendant lequel vous pouvez jouer. |
364 | | |
365 | | Modifier l'ISR du timer pour afficher "Game Over" |
366 | | |
367 | | |
368 | | |
369 | | [...] |
370 | | |
371 | | |
| 355 | Dans le premier TME, vous avez réalisé un petit jeu dans lequel vous deviez deviner un nombre tiré au hasard. Ce jeu avait été mis dans kinit parce qu'a ce moment, il n'y avait pas encore d'application utilisateur. Nous vous proposons de mettre le jeu dans l'application user et de limiter le temps pendant lequel vous pouvez jouer. Nous allons vous quider pas-à-pas. |
| 356 | |
| 357 | Récuperez l'[htdocs:files/tp3.tgz archive du code du tp3], placez-là dans le répertoire `kO6` et décompressez-là. Les commandes ci-dessous suppose que vous avez mis l'archive dans le répertoire `k06` |
| 358 | {{{#!bash |
| 359 | cd ~/k06 |
| 360 | tar xvzf tp3.tgz |
| 361 | cd tp3/1_gameover |
| 362 | }}} |
| 363 | |
| 364 | Le code de l'application est le suivant (dans uapp/main.c) |
| 365 | |
| 366 | {{{#!c |
| 367 | #include <libc.h> |
| 368 | int main (void) |
| 369 | { |
| 370 | int guess; |
| 371 | int random; |
| 372 | char buf[8]; |
| 373 | char name[16]; |
| 374 | |
| 375 | fprintf(0,"Tapez votre nom : "); |
| 376 | fgets(name, sizeof(name), 0); |
| 377 | if (name[strlen(name)] == '\n') |
| 378 | name[strlen(name)] = 0; |
| 379 | srand(clock()); // start the random generator with a "random" seed. |
| 380 | |
| 381 | random = 1 + rand() % 99; |
| 382 | fprintf(0,"Donnez un nombre entre 1 et 99: "); |
| 383 | do { |
| 384 | fgets(buf, sizeof(buf), 0); |
| 385 | guess = atoi (buf); |
| 386 | if (guess < random) |
| 387 | fprintf(0,"%d est trop petit: ", guess); |
| 388 | else if (guess > random) |
| 389 | fprintf(0,"%d est trop grand: ", guess); |
| 390 | } while (random != guess); |
| 391 | |
| 392 | fprintf(0,"\nGagné\n"); |
| 393 | return 0; |
| 394 | } |
| 395 | }}} |
| 396 | |
| 397 | 1. Essayez le jeu (dans le répertoire `tp3/1_gameover`) : tapez `make exec`\\ |
| 398 | comme vous pouvez le constater, vous avez le temps de jouer. |
| 399 | 2. Ouvrez le fichier `kernel/kinit.c`. Dans cette fonction, on appelle `archi_init()` avec en paramètre un nombre qui va servir de période d'horloge. Le simulateur de la plateforme sur les machines de la PPTI va environ à 3.5MHz. Combien de secondes demande-t-on dans ce code ? |
| 400 | {{{#!protected ------------------------------------------------------------------------------------ |
| 401 | '' |
| 402 | arch_init (30*3500000); // about 30 secondes with this simulator (3.5MHz) |
| 403 | '' |
| 404 | }}} |
| 405 | 3. Ouvrez le fichier `kernel/harch.c` et vous allez devoir remplir 3 fonctions pour configurer le timer: `arch_inti()`, `timer_init()` et `timer_isr()` (pour trouver ces fonctions cherchez le mot `TODO`) |
| 406 | {{{#!c |
| 407 | void arch_init (int tick) |
| 408 | { |
| 409 | // TODO A remplir avec 4 lignes : |
| 410 | // 1) appel de la fonction timer_init(pour le timer 0 avec tick comme période |
| 411 | // 2) mise à 1 du bit 0 du registre ICU_MASK en utilisant la fonction icu_set_mask() |
| 412 | // 3) initialisation de la table irq_vector_isr[] vecteur d'interruption avec timer_isr() |
| 413 | // 4) initialisation de la table irq_vector_dev[] vecteur d'interruption avec 0 |
| 414 | } |
| 415 | static void timer_init (int timer, int tick) |
| 416 | { |
| 417 | // TODO A remplir avec 2 lignes : |
| 418 | // 1) initialiser le registre period du timer n°timer avec la période tick (reçus en argument) |
| 419 | // 2) initialiser le registre mode du timer n°timer avec 3 (démarre le timer avec IRQ demandée) |
| 420 | } |
| 421 | static void timer_isr (int timer) |
| 422 | { |
| 423 | // TODO A remplir avec 3 lignes : |
| 424 | // 1) Acquiter l'interruption du timer en écrivant n'importe quoi dans le registre resetirq |
| 425 | // 2) afficher un message "Game Over" avec kprintf() |
| 426 | // 3) appeler la fonction kernel exit() (c'est une sortie définitive ici) |
| 427 | } |
| 428 | }}} |
| 429 | {{{#!protected |
| 430 | {{{#!c |
| 431 | void arch_init (int tick) |
| 432 | { |
| 433 | timer_init (0, tick); // sets period of timer n'0 (thus for CPU n'0) and starts it |
| 434 | icu_set_mask (0, 0); // [CPU n'0].IRQ <-- ICU.PIN[0] <- Interrupt signal timer n'0 |
| 435 | irq_vector_isr [0] = timer_isr; // tell the kernel which isr to exec for ICU.PIN n'0 |
| 436 | irq_vector_dev [0] = 0; // device instance attached to ICU.PIN n'0 |
| 437 | } |
| 438 | static void timer_init (int timer, int tick) |
| 439 | { |
| 440 | __timer_regs_map[timer].period = tick; // next period |
| 441 | __timer_regs_map[timer].mode = (tick)?3:0; // timer ON with IRQ only if (tick != 0) |
| 442 | } |
| 443 | static void timer_isr (int timer) |
| 444 | { |
| 445 | __timer_regs_map[timer].resetirq = 1; // IRQ acknoledgement to lower the interrupt signal |
| 446 | kprintf ("Game Over\n"); |
| 447 | exit(1); |
| 448 | } |
| 449 | }}}}}} |
| 450 | |
| 451 | |