rendered paste body/* ----------------------------------------------------------
@ led_blink_irq.s: Utilisation des interruptions AIC, d'un
@ des trois timers et du PIO
---------------------------------------------------------- */
.include "carte.inc"
.global _start @ Pour éviter le warning de arm-elf-ld
_start:
main: @ Pour le point d'arrêt automatique
@mov r13,#0x20000 @ pile en 0x20000
adr r9, tableau
ldr r8, =ft
bl INIT_PIO_AIC
bl INIT_USART
@affichage initial
bl AFFICH_CADRE
@On attend que la procédure de départ soit finie pour commencer la partie
att_depart:
cmp r9, r8
bne att_depart
exit:
@ Retour â Angel par exception (appel systême)
mov r0, #0x18
ldr r1, =0x20026
swi 0x123456
@ ===============================================================
@ Fin du programme principal
@ ===============================================================
@=====Affiche le cadre du plateau de jeu=========================
AFFICH_CADRE:
@----------------Dimensions du cadre ~ 80 / 22-------------------
stmfd r13!, {r0, r1, r14}
mov r1, #1 @r1 est le compteur pour savoir combien de caractère on a affiché
@affichage de la 1e ligne
@Passage en mode graphique pour pouvoir afficher le cadre
mov r0, #0xe
bl PUTCHAR
@angle en haut à gauche
mov r0, #0x6c
bl PUTCHAR
@ligne horizontale
mov r0, #0x71
tq_affich_ligne_plateau:
cmp r1, #50
beq ftq_affich_ligne_plateau
bl PUTCHAR
add r1, r1, #1
b tq_affich_ligne_plateau
ftq_affich_ligne_plateau:
@angle au milieu à gauche
mov r0, #0x77
bl PUTCHAR
add r1, r1, #1 @pour avoir une longueur de 80
@ligne horizontale
mov r0, #0x71
tq_affich_ligne_score:
cmp r1, #79 @le 80e caractère est un angle
beq ftq_affich_ligne_score
bl PUTCHAR
add r1, r1, #1
b tq_affich_ligne_score
ftq_affich_ligne_score:
@angle au milieu à droite
mov r0, #0x6b
bl PUTCHAR
@barre verticale
mov r1, #2 @on commence à la 2e ligne
mov r0, #0x78
tq_affich_barre:
cmp r1, #20 @le plateau fait 20 lignes de hauteur
beq ftq_affich_barre
@positionnement du caractère
bl ITOA
mov r4, #'0'
mov r5, #'0'
stmfd r13!, {r2, r3, r4, r5}
bl POS
sub r13, r13, #16
@affichage du caractère
bl PUTCHAR
mov r4, #'5'
mov r5, #'0'
stmfd r13!, {r2, r3, r4, r5}
bl POS
sub r13, r13, #16
@affichage du caractère
bl PUTCHAR
add r1, r1, #1
b tq_affich_barre
ftq_affich_barre:
@Sortie du mode graphique
mov r0, #0x1b
bl PUTCHAR
mov r0, #'n'
bl PUTCHAR
ldmfd r13!, {r0, r1, r15}
@===================Integer TO Ascii, entier placé par registre r1, renvoie les caractères par registres r2, r3=============================
ITOA:
mov r3, r1
mov r2, #0
tq_itoa:
cmp r3, #10
blo ftq_itoa
add r2, r2, #1
sub r3, r3, #10
b ftq_itoa
ftq_itoa:
@on convertit chaque chiffre en caractère
add r2, r2, #48
add r3, r3, #48
mov r15, r14
@=====Position du curseur (4 paramètres placés par pile)=========
POS:
stmfd r13!, {r0, r14}
mov r0, #0x1B
bl PUTCHAR
mov r0, #'['
bl PUTCHAR
ldr r0, [r13, #8]
bl PUTCHAR
ldr r0, [r13, #12]
bl PUTCHAR
mov r0, #';'
bl PUTCHAR
ldr r0, [r13, #16]
bl PUTCHAR
ldr r0, [r13, #20]
bl PUTCHAR
mov r0, #'H'
bl PUTCHAR
ldmfd r13!, {r0, r15}
@=============Initiallisation PIO / AIC===========================
INIT_PIO_AIC:
@ initialisation des leds
@ -----------------------
ldr r12,=PIO_BASE
ldr r0,=(LED8|LED7|LED6|LED5|LED4|LED2|LED3|LED1)
str r0,[r12, #PIO_PER] @ Autoriser les ports
str r0,[r12, #PIO_OER] @ P6 et P16 en sortie
@str r0,[r1, #PIO_CODR]@ eteindre les leds 8 et 1
@ initialisation du timer1
@ -----------------------
ldr r10,=TC1_BASE
mov r0,#0b10
str r0,[r10, #TC_CCR] @ interdire l'horloge du compteur
mvn r0,#0x0
str r0,[r10, #TC_IDR] @ interdire la génération d'interruption
ldr r0,[r10, #TC_SR] @ lire le SR de TC1
ldr r0,=0x4004
str r0,[r10, #TC_CMR] @ TC1 utilise MCK/1024 et redémarrage auto
mov r0,#1
str r0,[r10, #TC_CCR] @ Autoriser l'horloge
mov r0,#0x10
str r0,[r10, #TC_IER] @ Valider l'interruption de comparaison avec RC
@ Initialisation AIC
@ -----------------------
ldr r11,=AIC_BASE
mov r0,#0b100000
str r0,[r11, #AIC_IDCR] @ Interdire l'interruption du Timer1 dans l'AIC
adr r0, DRIVER_TIMER @ Mettre l'adresse de la routine d'interruption
str r0,[r11, #AIC_SVR5] @ dans AIC_SVR5 (vecteur relatif à TC1_IRQ)
mov r0,#0x04 @ Priorité 4 pour l'interruption TC1
str r0,[r11, #AIC_SMR5]
mov r0,#0b100000
str r0,[r11, #AIC_ICCR] @ RAZ de l'interruption TC1
str r0,[r11, #AIC_IECR] @ Autorise l'interruption TC1
@ paramètres de timing du timer1
@ -----------------------
ldr r0,=64453 @ 64453 * MCK/1024 -> une seconde
str r0,[r10, #TC_RC] @ Placer le délai dans le registre C
mov r0,#0b100 @ Mise à 1 bu bit 2 de CCR
str r0,[r10, #TC_CCR] @ -> RAZ compteur et démarrage
mov r15, r14
@ ===============================================================
@ Gestionnaire de l'interruption du timer 1
@ ===============================================================
DRIVER_TIMER:
@ ------------------------
@- Ajuster et sauvegarder le registre de retour du mode IRQ dans la pile IRQ
sub r14, r14, #4 @ r14 pointe une instruction trop loin
stmfd sp!, {r14} @ sauvegarder l'adresse de retour dans la pile IRQ
@ Sauvegarder SPSR et R0 dans la pile IRQ
mrs r14, spsr
stmfd sp!, {r0, r14}
@ passer en mode systême
mrs r14, cpsr
orr r14, r14, #0b11111 @ (mode systême)
msr cpsr, r14
@ Sauvegarde de registres dans la pile systême
stmfd sp!, { r1, r2, r14}
@ autoriser les interruptions
mrs r14, cpsr
bic r14, r14, #0x80 @ CPSR[I] <- 0
msr cpsr, r14
@ -----------------------
@ ldr r1,=TC1_BASE
ldr r0,[r10, #TC_SR] @ Lecture SR pour le remettre à 0
@ (pour signifier qu'on traite l'IT)
@ ldr r1,=PIO_BASE
ldr r0, =LED1|LED2|LED3|LED4
ldrb r2, [r9], #1
mov r3, r2, lsl #16
and r0, r0, r3
str r0, [r12, #PIO_CODR]
mvn r0, r0
str r0, [r12, #PIO_SODR]
@ Fin interruption
fin_irq:
@- Interdire les interruptions
mrs r0, cpsr
orr r0, r0, #0b10000000 @ CPSR[I] <- 1
msr cpsr, r0
@ Restaurer les registres depuis la pile systême
ldmfd sp!, { r1, r2, r14}
@- repasser en mode IRQ
mrs r0, cpsr
bic r0, r0, #0x1F @ CPSR[MO..M4] <- 0b00000
orr r0, r0, #0b10010 @ CPSR[MO..M4] <- 0b10010
msr cpsr, r0
@ Indiquer la prise en compte de l'interruption à l'AIC
@ = écriture de n'importe quoi dans AIC_EOICR
@ ldr r0, =AIC_BASE
str r11, [r11, #AIC_EOICR]
@ Restaurer SPSR_irq et r0 à partir de la pile IRQ
ldmfd sp!, {r0, r14}
msr spsr, r14
@ Restaurer LR_irq depuis la pile IRQ et le mettre directement dans le PC
ldmfd sp!, {pc}^
@ Fin du sous_programme d'interruption
@==================================================================@
@ Sous-programme initialisation USART @
@ ----------------------------------- @
@ Paramètres : néant @
@ Valeur de retour : néant @
@==================================================================@
INIT_USART:
stmfd r13!,{r0,r1,r14}
@ Au cas ou, on desactive les ports du PIO
@ pour USART1
@ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ldr r0,=PIO_BASE
ldr r1,=0x700000
str r1,[r0,#PIO_PDR]
str r1,[r0,#PIO_IDR]
@ On initialise l'USART pour recevoir et transmettre des caractères
@ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ldr r0,=USART1_BASE
@ On fait un reset de l'émetteur et du récepteur
@-----------------------------------------------
ldr r1,=(US_RSTRX|US_RSTTX|US_RSTSTA)
str r1,[r0,#US_CR]
@ On active l'émetteur et le récepteur
@-------------------------------------
ldr r1,=(US_RXEN|US_TXEN)
str r1,[r0,#US_CR]
@ Configuration des modes
@------------------------
@ - Clock Selection = MCK (US_CLKS_MCK)
@ - Taille de caractère = 8 (US_CHRL_8)
@ - Mode Asynchrone (SYNC=0)
@ - Pas de parité (US_PAR_NO)
@ - 1 stop bit (US_NBSTOP_1)
@ - Normal Channel Mode (US_CHMODE_NORMAL)
ldr r1,=(US_CLKS_MCK8|US_CHRL_8|US_PAR_NO|US_NBSTOP_1|US_CHMODE_NORMAL)
str r1,[r0,#US_MR]
@Initialisation du baud rate generator register (CD)
@---------------------------------------------------
@ Cette valeur est calculée à partir de
@ - MCK = 66.6 MHz
@ - débit du terminal = 57600
@ - mode asynchrone (débit = MCK/(CD*16))
mov r1,#9
str r1,[r0,#US_BRGR]
@Initialisation du temps de garde
@--------------------------------
mov r1,#0xa
str r1,[r0,#US_TTGR]
@ Désactivation des interruptions de tout genre
@----------------------------------------------
mov r1,#0x3F
str r1,[r0,#US_IDR]
ldmfd r13!,{r0,r1,r15}
@==================================================================@
@ Sous-programme envoi d'un caractère sur gtkterm @
@ ----------------------------------------------- @
@ Paramètres : code ASCII passé dans r0 @
@ Valeur de retour : néant @
@==================================================================@
PUTCHAR:
stmfd r13!,{r1,r2,r14}
ldr r1,=USART1_BASE
put_wait:
ldr r2,[r1,#US_CSR]
ands r2,r2,#US_TXRDY
beq put_wait
@ On place le caractère dans le registre
@ Transmitter Holding Register ( US_THR)
strb r0,[r1,#US_THR]
ldmfd r13!,{r1,r2,r15}
@==================================================================@
@ Sous-programme saisie d'un caractère au clavier @
@ ----------------------------------------------- @
@ Paramètres : néant @
@ Valeur de retour : code ASCII passé dans r0 @
@==================================================================@
GETCHAR:
stmfd r13!,{r1,r2,r14}
ldr r1,=USART1_BASE
@ Attente active de l'arrivée d'un caractère
@ tapé au clavier
get_wait:
ldr r2,[r1,#US_CSR]
ands r2,r2,#US_RXRDY
beq get_wait
@ Une fois le caractère saisi, on le place dans r0
ldrb r0,[r1,#US_RHR]
ldmfd r13!,{r1,r2,r15}
tableau: .byte 1, 3, 7, 15, 0, 15, 0, 15, 0
ft: