From: Leandro Lucarella Date: Tue, 13 Dec 2005 21:10:03 +0000 (+0000) Subject: Se implementa un sistema primitivo de 'locking' para los leds. Cada vez que se X-Git-Tag: 0.2-elp~2 X-Git-Url: https://git.llucax.com/z.facultad/66.09/etherled.git/commitdiff_plain/db76f3270c5bee0eb1b5ee71fa1946e8d5132d43?ds=inline Se implementa un sistema primitivo de 'locking' para los leds. Cada vez que se lee o se escribe un registro de la placa de red, se deja de atender las interrupciones del timer de los leds para evitar una condición de carrera del puerto 2. También se hacen otros cambios pequeños: * Se hace un cheque sobre el tamaño de la matriz que viene de la red. * Se cambia el intervalo del timer de los leds (cuanto más grande menos interrupciones se saltea). Hay algo más de trabajo por hacer en este área. * Se corrige un bug en leds.asm, en algún momento se borró el .ds 1 que reservaba memoria para curr_col, que estaba tomando 'prestado' el 1er byte de la matriz (o peor, tomando un byte de vaya uno a saber dónde). --- diff --git a/src/dp8390.c b/src/dp8390.c index 5c472a5..76d0c6d 100644 --- a/src/dp8390.c +++ b/src/dp8390.c @@ -40,6 +40,7 @@ recv_state; static void write_reg(unsigned char reg, unsigned char wr_data) { + leds_lock(); // Select register address. ADDR_PORT &= ~ADDR_PORT_MASK; ADDR_PORT |= reg; @@ -56,11 +57,13 @@ static void write_reg(unsigned char reg, unsigned char wr_data) // Set register data port as input again. DATA_PORT = DATA_PORT_MASK; + leds_unlock(); } static unsigned char read_reg(unsigned char reg) { + leds_lock(); // Select register address. ADDR_PORT &= ~ADDR_PORT_MASK; ADDR_PORT |= reg; @@ -76,6 +79,7 @@ static unsigned char read_reg(unsigned char reg) IOR = 1; NICE = 1; + leds_unlock(); return reg; } diff --git a/src/elp.c b/src/elp.c index 6a2a654..69e3490 100644 --- a/src/elp.c +++ b/src/elp.c @@ -18,8 +18,6 @@ byte elp_read_process_command() *((byte*) &elp_command) = udp_read_byte(); netdev_read_end(); - printb(*((byte*) &elp_command), 0x01); - // Si es un SET lo proceso switch (elp_command.var) { @@ -45,7 +43,7 @@ byte elp_read_process_command() i = udp_read_byte(); netdev_read_end(); // Verifico cantidad de columnas - if ((LEDS_MIN_COLS < i) || (i < LEDS_MAX_COLS)) + if ((i < LEDS_MIN_COLS) || (i > LEDS_MAX_COLS)) return 0; leds_matrix_len = i; netdev_read_start(leds_matrix_len * 2); // matriz @@ -64,12 +62,11 @@ byte elp_read_process_command() return len + 1 /* booleano de 1 byte */; // Si es SET procesamos netdev_read_start(1); // booleano de 1 byte - //XXX if (udp_read_byte() == 0x00) // si viene 0 reanuda - //XXX TR2 = 1; - //XXX else - if (udp_read_byte() != 0x00) + if (udp_read_byte() == 0x00) // si viene 0 reanuda + ET2 = 1; + else { - TR2 = 0; + ET2 = 0; leds_write(0x0000); // Si pausa apaga leds } netdev_read_end(); @@ -119,7 +116,7 @@ void elp_write_response() case ELP_VAR_PAUSE: netdev_write_start(1 /* booleano de 1 byte */); - udp_write_byte(!TR2); + udp_write_byte(!ET2); netdev_write_end(); break; diff --git a/src/leds.asm b/src/leds.asm index db579cd..558f13f 100644 --- a/src/leds.asm +++ b/src/leds.asm @@ -19,15 +19,16 @@ LEDS_MAX_COLS = 32 ; Cantidad máxima de columnas .globl _leds_write_low ; void leds_write_low(unsigned char); .globl _leds_write_high ; void leds_write_high(unsigned char); .globl _leds_delay_update ; void leds_delay_update(); +.globl _leds_lock ; void leds_lock(); +.globl _leds_unlock ; void leds_unlock(); .globl _leds_timer2_isr ; void leds_timer2_isr() interrupt 5; ; Constantes -; UN CICLO DE MAQUINA SON 1.6666 useg (clock 8MHz) -INTERVAL = 65000 ; 0.05ms (por el clock de 8MHz) +INTERVAL = 666 ; 0.1ms (por el clock de 8MHz) LEDS_LOW = 0x0080 LEDS_HIGH = 0x00c0 -DELAY_BASE = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20 +DELAY_BASE = 11 ; 16 columnas anda bien con 28 - (len / 2) == 20 ; Área de bancos de registros .area REG_BANK_0 (REL,OVR,DATA) @@ -44,19 +45,25 @@ DELAY_BASE = 28 ; 16 columnas anda bien con 28 - (len / 2) == 20 ; Variables es memoria RAM común .area DSEG (DATA) -_leds_matrix_len:: +_leds_matrix_len:: ; Cantidad de columnas de la matriz .ds 1 -_leds_delay:: +_leds_delay:: ; Retardo de dibujado configurado .ds 1 -delay: +delay: ; Contador del retardo actual + .ds 1 +curr_col: ; Columna que se está dibujando actualmente .ds 1 -curr_col: ; Variables en memoria RAM extendida indirecta (8052) .area ISEG (DATA) -_leds_matrix:: +_leds_matrix:: ; Matriz a dibujar .ds LEDS_MAX_COLS * 2 ; 2 bytes por columna +; Variables de bit +.area BSEG (BIT) +lock: ; Variable utilizada para el 'locking', indica si el timer + .ds 1 ; estaba andando al momento de lockear para que el unlock + ; pueda reactivarlo de ser necesario ; Configuramos el vector de interrupciones para atender el timer2 ;.area INTV (ABS, CODE) @@ -110,7 +117,7 @@ proximo$: mov rcap2h, #>(-INTERVAL) ; high byte del intervalo mov t2con, #0x00; setup del timer2 (auto-reload), no lo arrancamos - setb et2 ; habilito interrupcion timer2 (IE.5) + setb tr2 ; largo a correr el timer2 mov curr_col, #0 ; inicializo el contador de columna en 0 @@ -215,6 +222,30 @@ _leds_delay_update:: subb a, dpl mov _leds_delay, a ret + + +; Bloquea el timer de los leds cuando se accede a una zona crítica (P0 y/o P2). +; Primitiva de C: +; void leds_lock(); +; +; C se encarga de hacer push y pop del dptr, a y psw si lo necesita. +_leds_lock:: + mov c, et2 ; En lock me queda si está el timer andando o no. + mov lock, c + clr et2 ; Sea como sea, lo paro. + ret + + +; Desbloquea el timer de los leds. +; Primitiva de C: +; void leds_unlock(); +; +; C se encarga de hacer push y pop del dptr, a y psw si lo necesita. +_leds_unlock:: + jnb lock, 1$ ; Si no estába andando, no hago nada + setb et2 ; Si estaba andando lo prendo +1$: + ret ; Manejador de la interrupción del timer2 para el uso de los leds. @@ -222,6 +253,8 @@ _leds_delay_update:: ; void leds_timer2_isr() interrupt 5; ; _leds_timer2_isr:: + ; limpiamos flag del timer2 + clr tf2 ; vemos si todavía hay que seguir esperando o si ya tenemos que leer djnz delay, 255$ diff --git a/src/leds.h b/src/leds.h index b24a6d6..c69a956 100644 --- a/src/leds.h +++ b/src/leds.h @@ -42,6 +42,14 @@ void leds_write_high(unsigned char); /** Actualiza el delay al recomendado según el tamaño de la matriz */ void leds_delay_update(); +/** Bloquea timer de leds cuando se accede a una zona crítica (P0 y/o P2). */ +void leds_lock(); + +/** Desbloquea el timer de los leds. + * @precond Se llamó a leds_lock(); + */ +void leds_unlock(); + /** Atiende interrupción del timer2 para 'dibujar' la matriz */ void leds_timer2_isr() interrupt 5; diff --git a/src/main.c b/src/main.c index 69e0a54..9714789 100644 --- a/src/main.c +++ b/src/main.c @@ -27,7 +27,7 @@ void main(void) // Comienza a 'dibujar' EA = 1; // Habilita interrupciones globalmente - //XXX TR2 = 1; // Pone a correr el 'dibujado' + ET2 = 1; // Pone a correr el 'dibujado' // Inicializo IP ip_addr_local[0] = 10; @@ -76,42 +76,37 @@ void main(void) // Procesamos comando ELP y obtenemos tamaño de la // respuesta len = elp_read_process_command(); - printb(len, 0x02); + //printb(len, 0x02); // Si el tamaño es 0, hubo error o no está soportado if (!len) goto drop; - print(0x0004); + //print(0x0004); // FIXME por ahora no tenemos forma de 'abortar' el // comando si el checksum es incorrecto, lo verificamos // por deporte. if (!udp_checksum_ok()) goto drop; - print(0x0008); + //print(0x0008); // Terminamos recepción netdev_recv_end(); - print(0x0010); + //print(0x0010); // Respuesta netdev_send_start(); eth_write_frame_header(); ip_packet_len = UDP_HEADER_SIZE + len; - printb(ip_packet_len, 0x20); + //printb(ip_packet_len, 0x20); ip_write_packet_header(); udp_dgram_len = len; - printb(udp_dgram_len, 0x40); + //printb(udp_dgram_len, 0x40); udp_write_dgram_header(); elp_write_response(); udp_write_checksum(ETH_HEADER_SIZE + IP_HEADER_SIZE); netdev_send_end(ETH_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE + len); - printb(ETH_HEADER_SIZE + IP_HEADER_SIZE - + UDP_HEADER_SIZE + len, 0x80); - //XXX - if (elp_command.set && (elp_command.var == ELP_VAR_PAUSE)) - TR2 = 1; } } continue; diff --git a/src/reg51keil.h b/src/reg51keil.h index a40d8ab..426783b 100644 --- a/src/reg51keil.h +++ b/src/reg51keil.h @@ -62,6 +62,7 @@ sbit CP_RL2C = 0xC8; /* IE */ sbit EA = 0xAF; +sbit ET2 = 0xAD; sbit ES = 0xAC; sbit ET1 = 0xAB; sbit EX1 = 0xAA; diff --git a/src/reg51sdcc.h b/src/reg51sdcc.h index 1710d8e..29f7d07 100644 --- a/src/reg51sdcc.h +++ b/src/reg51sdcc.h @@ -62,6 +62,7 @@ sbit at 0xC8 CP_RL2C; /* IE */ sbit at 0xAF EA; +sbit at 0xAD ET2; sbit at 0xAC ES; sbit at 0xAB ET1; sbit at 0xAA EX1;