summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2013-03-24 15:00:20 -0700
committerKeith Packard <keithp@keithp.com>2013-03-31 12:24:24 -0700
commit4f1f3e836393304434130d362771a39f6f8f859a (patch)
tree5655f7ae7aa252a96aa585e3aee47b1b57a8fc9a /src/drivers
parent7afcec1a1dce140dfa569469df4ef42ed407a742 (diff)
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 <keithp@keithp.com>
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/ao_btm.c52
-rw-r--r--src/drivers/ao_packet.c6
-rw-r--r--src/drivers/ao_packet_master.c7
-rw-r--r--src/drivers/ao_packet_slave.c2
4 files changed, 42 insertions, 25 deletions
diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c
index c862200a..de1f31a3 100644
--- a/src/drivers/ao_btm.c
+++ b/src/drivers/ao_btm.c
@@ -19,9 +19,10 @@
#ifndef ao_serial_btm_getchar
#define ao_serial_btm_putchar ao_serial1_putchar
-#define ao_serial_btm_pollchar ao_serial1_pollchar
+#define _ao_serial_btm_pollchar _ao_serial1_pollchar
#define ao_serial_btm_set_speed ao_serial1_set_speed
#define ao_serial_btm_drain ao_serial1_drain
+#define ao_serial_btm_rx_fifo ao_serial1_rx_fifo
#endif
int8_t ao_btm_stdio;
@@ -112,6 +113,30 @@ __code struct ao_cmds ao_btm_cmds[] = {
__xdata char ao_btm_reply[AO_BTM_MAX_REPLY];
/*
+ * Read one bluetooth character.
+ * Returns AO_READ_AGAIN if no character arrives within 10ms
+ */
+
+static int
+ao_btm_getchar(void)
+{
+ int c;
+
+ ao_arch_block_interrupts();
+ while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) {
+ ao_alarm(AO_MS_TO_TICKS(10));
+ c = ao_sleep(&ao_serial_btm_rx_fifo);
+ ao_clear_alarm();
+ if (c) {
+ c = AO_READ_AGAIN;
+ break;
+ }
+ }
+ ao_arch_release_interrupts();
+ return c;
+}
+
+/*
* Read a line of data from the serial port, truncating
* it after a few characters.
*/
@@ -122,24 +147,13 @@ ao_btm_get_line(void)
uint8_t ao_btm_reply_len = 0;
int c;
- for (;;) {
-
- while ((c = ao_serial_btm_pollchar()) != AO_READ_AGAIN) {
- ao_btm_log_in_char(c);
- if (ao_btm_reply_len < sizeof (ao_btm_reply))
- ao_btm_reply[ao_btm_reply_len++] = c;
- if (c == '\r' || c == '\n')
- goto done;
- }
- for (c = 0; c < 10; c++) {
- ao_delay(AO_MS_TO_TICKS(10));
- if (!ao_fifo_empty(ao_serial1_rx_fifo))
- break;
- }
- if (c == 10)
- goto done;
+ while ((c = ao_btm_getchar()) != AO_READ_AGAIN) {
+ ao_btm_log_in_char(c);
+ if (ao_btm_reply_len < sizeof (ao_btm_reply))
+ ao_btm_reply[ao_btm_reply_len++] = c;
+ if (c == '\r' || c == '\n')
+ break;
}
-done:
for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);)
ao_btm_reply[c++] = '\0';
return ao_btm_reply_len;
@@ -279,7 +293,7 @@ ao_btm(void)
/* Turn off status reporting */
ao_btm_cmd("ATQ1\r");
- ao_btm_stdio = ao_add_stdio(ao_serial_btm_pollchar,
+ ao_btm_stdio = ao_add_stdio(_ao_serial_btm_pollchar,
ao_serial_btm_putchar,
NULL);
ao_btm_echo(0);
diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c
index 91319923..5a507478 100644
--- a/src/drivers/ao_packet.c
+++ b/src/drivers/ao_packet.c
@@ -169,12 +169,10 @@ ao_packet_putchar(char c) __reentrant
tx_data[ao_packet_tx_used++] = c;
}
+/* May be called with interrupts blocked */
int
-ao_packet_pollchar(void)
+_ao_packet_pollchar(void)
{
- /* No need to block interrupts, all variables here
- * are only manipulated in task context
- */
if (!ao_packet_enable)
return AO_READ_AGAIN;
diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c
index 023c788b..4c0dc573 100644
--- a/src/drivers/ao_packet_master.c
+++ b/src/drivers/ao_packet_master.c
@@ -21,7 +21,12 @@ static char
ao_packet_getchar(void)
{
int c;
- while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) {
+
+ /* No need to block interrupts in this function as
+ * all packet variables are only modified from task
+ * context, not an interrupt handler
+ */
+ while ((c = _ao_packet_pollchar()) == AO_READ_AGAIN) {
if (!ao_packet_enable)
break;
if (ao_packet_master_sleeping)
diff --git a/src/drivers/ao_packet_slave.c b/src/drivers/ao_packet_slave.c
index e45775cb..e75df0d6 100644
--- a/src/drivers/ao_packet_slave.c
+++ b/src/drivers/ao_packet_slave.c
@@ -59,7 +59,7 @@ ao_packet_slave_stop(void)
void
ao_packet_slave_init(uint8_t enable)
{
- ao_add_stdio(ao_packet_pollchar,
+ ao_add_stdio(_ao_packet_pollchar,
ao_packet_putchar,
NULL);
if (enable)