From f3dc025a764ca6a2c44fb514ccaf22e6210f769d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 Mar 2013 15:00:20 -0700 Subject: altos: Do not release interrupts from any pollchar function getchar relies on interrupts being blocked across the pollchar calls and into the sleep call or it may go to sleep with data pending. This prefixes all pollchar functions with _ to indicate that they are to be called with interrupts blocked and eliminates all interrupt manipulation calls from within the pollchar functions. Signed-off-by: Keith Packard --- src/avr/ao_serial_avr.c | 43 +++++++++++++++++++++---------------------- src/avr/ao_usb_avr.c | 42 +++++++++++++++++------------------------- 2 files changed, 38 insertions(+), 47 deletions(-) (limited to 'src/avr') diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c index dcee246c..e0f813d5 100644 --- a/src/avr/ao_serial_avr.c +++ b/src/avr/ao_serial_avr.c @@ -59,52 +59,51 @@ ISR(USART1_UDRE_vect) ao_wakeup(&ao_serial1_tx_fifo); } -char -ao_serial1_getchar(void) __critical -{ - char c; - cli(); - while (ao_fifo_empty(ao_serial1_rx_fifo)) - ao_sleep(&ao_serial1_rx_fifo); - ao_fifo_remove(ao_serial1_rx_fifo, c); - sei(); - return c; -} - #if USE_SERIAL_1_STDIN -char -ao_serial1_pollchar(void) __critical +int +_ao_serial1_pollchar(void) { char c; - cli(); if (ao_fifo_empty(ao_serial1_rx_fifo)) { sei(); return AO_READ_AGAIN; } ao_fifo_remove(ao_serial1_rx_fifo,c); - sei(); return c; } #endif +char +ao_serial1_getchar(void) __critical +{ + char c; + + ao_arch_block_interrupts(); + while (ao_fifo_empty(ao_serial1_rx_fifo)) + ao_sleep(&ao_serial1_rx_fifo); + ao_fifo_remove(ao_serial1_rx_fifo, c); + ao_arch_release_interrupts(); + return c; +} + void -ao_serial1_putchar(char c) __critical +ao_serial1_putchar(char c) { - cli(); + ao_arch_block_interrupts(); while (ao_fifo_full(ao_serial1_tx_fifo)) ao_sleep(&ao_serial1_tx_fifo); ao_fifo_insert(ao_serial1_tx_fifo, c); ao_serial_tx1_start(); - sei(); + ao_arch_release_interrupts(); } void ao_serial1_drain(void) __critical { - cli(); + ao_arch_block_interrupts(); while (!ao_fifo_empty(ao_serial1_tx_fifo)) ao_sleep(&ao_serial1_tx_fifo); - sei(); + ao_arch_release_interrupts(); } static const struct { @@ -155,7 +154,7 @@ ao_serial_init(void) (1 << RXCIE1) | /* Enable receive interrupts */ (1 << UDRIE1)); /* Enable transmit empty interrupts */ #if USE_SERIAL_1_STDIN - ao_add_stdio(ao_serial1_pollchar, + ao_add_stdio(_ao_serial1_pollchar, ao_serial1_putchar, NULL); #endif diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 2ef546c9..bd75b17d 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -411,7 +411,7 @@ ao_usb_ep0(void) /* Wait for a free IN buffer */ static void -ao_usb_in_wait(void) +_ao_usb_in_wait(void) { for (;;) { /* Check if the current buffer is writable */ @@ -419,7 +419,6 @@ ao_usb_in_wait(void) if (UEINTX & (1 << RWAL)) break; - cli(); /* Wait for an IN buffer to be ready */ for (;;) { UENUM = AO_USB_IN_EP; @@ -430,24 +429,24 @@ ao_usb_in_wait(void) } /* Ack the interrupt */ UEINTX &= ~(1 << TXINI); - sei(); } } /* Queue the current IN buffer for transmission */ static void -ao_usb_in_send(void) +_ao_usb_in_send(void) { UENUM = AO_USB_IN_EP; UEINTX &= ~(1 << FIFOCON); } void -ao_usb_flush(void) __critical +ao_usb_flush(void) { if (!ao_usb_running) return; + ao_arch_block_interrupts(); /* Anytime we've sent a character since * the last time we flushed, we'll need * to send a packet -- the only other time @@ -457,18 +456,20 @@ ao_usb_flush(void) __critical */ if (!ao_usb_in_flushed) { ao_usb_in_flushed = 1; - ao_usb_in_wait(); - ao_usb_in_send(); + _ao_usb_in_wait(); + _ao_usb_in_send(); } + ao_arch_release_interrupts(); } void -ao_usb_putchar(char c) __critical __reentrant +ao_usb_putchar(char c) { if (!ao_usb_running) return; - ao_usb_in_wait(); + ao_arch_block_interrupts(); + _ao_usb_in_wait(); /* Queue a byte */ UENUM = AO_USB_IN_EP; @@ -476,11 +477,12 @@ ao_usb_putchar(char c) __critical __reentrant /* Send the packet when full */ if ((UEINTX & (1 << RWAL)) == 0) - ao_usb_in_send(); + _ao_usb_in_send(); ao_usb_in_flushed = 0; + ao_arch_release_interrupts(); } -static int +int _ao_usb_pollchar(void) { uint8_t c; @@ -517,25 +519,15 @@ _ao_usb_pollchar(void) return c; } -int -ao_usb_pollchar(void) -{ - int c; - cli(); - c = _ao_usb_pollchar(); - sei(); - return c; -} - char -ao_usb_getchar(void) __critical +ao_usb_getchar(void) { int c; - cli(); + ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) ao_sleep(&ao_stdin_ready); - sei(); + ao_arch_release_interrupts(); return c; } @@ -668,5 +660,5 @@ ao_usb_init(void) #if USB_DEBUG ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif - ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); + ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); } -- cgit v1.2.3