Having arbitrary alarms firing in the middle of complicated device
logic makes no sense at all. Therefore only correct use of ao_alarm
and ao_clear_alarm was around a specific ao_sleep call, with correct
recovery in case the alarm fires.
This patch replaces all uses of ao_alarm/ao_sleep/ao_clear_alarm with
ao_sleep_for, a new function which takes the alarm timeout directly.
A few cases which weren't simply calling ao_sleep have been reworked
to pass the timeout value down to the place where sleep *is* being
called, and having that code deal with the return correctly.
Signed-off-by: Keith Packard <keithp@keithp.com>
23 files changed:
ao_button_init(void);
char
ao_button_init(void);
char
-ao_button_get(void) __critical;
+ao_button_get(uint16_t timeout) __critical;
void
ao_button_clear(void) __critical;
void
ao_button_clear(void) __critical;
-ao_button_get(void) __critical
+ao_button_get(uint16_t timeout) __critical
{
char b;
while (ao_fifo_empty(ao_button_fifo))
{
char b;
while (ao_fifo_empty(ao_button_fifo))
- if (ao_sleep(&ao_button_fifo))
+ if (ao_sleep_for(&ao_button_fifo, timeout))
return 0;
ao_fifo_remove(ao_button_fifo, b);
return b;
return 0;
ao_fifo_remove(ao_button_fifo, b);
return b;
/* Wait for DMA to be done, for the radio receive process to
* get aborted or for a receive timeout to fire
*/
/* Wait for DMA to be done, for the radio receive process to
* get aborted or for a receive timeout to fire
*/
- if (timeout)
- ao_alarm(timeout);
__critical while (!ao_radio_dma_done && !ao_radio_abort)
__critical while (!ao_radio_dma_done && !ao_radio_abort)
- if (ao_sleep(&ao_radio_dma_done))
+ if (ao_sleep_for(&ao_radio_dma_done, timeout))
- if (timeout)
- ao_clear_alarm();
/* If recv was aborted, clean up by stopping the DMA engine
* and idling the radio
/* If recv was aborted, clean up by stopping the DMA engine
* and idling the radio
#ifndef ao_serial_btm_getchar
#define ao_serial_btm_putchar ao_serial1_putchar
#define _ao_serial_btm_pollchar _ao_serial1_pollchar
#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_sleep() ao_sleep((void *) &ao_serial1_rx_fifo)
+#define _ao_serial_btm_sleep_for(timeout) ao_sleep_for((void *) &ao_serial1_rx_fifo, timeout)
#define ao_serial_btm_set_speed ao_serial1_set_speed
#define ao_serial_btm_drain ao_serial1_drain
#endif
#define ao_serial_btm_set_speed ao_serial1_set_speed
#define ao_serial_btm_drain ao_serial1_drain
#endif
while (ao_btm_enable) {
ao_arch_block_interrupts();
while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN && ao_btm_enable)
while (ao_btm_enable) {
ao_arch_block_interrupts();
while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN && ao_btm_enable)
- _ao_serial_btm_sleep();
+ _ao_serial_btm_sleep_for(0);
ao_arch_release_interrupts();
if (c != AO_READ_AGAIN) {
putchar(c);
ao_arch_release_interrupts();
if (c != AO_READ_AGAIN) {
putchar(c);
ao_arch_block_interrupts();
while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) {
ao_arch_block_interrupts();
while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) {
- ao_alarm(AO_MS_TO_TICKS(10));
- c = _ao_serial_btm_sleep();
- ao_clear_alarm();
+ c = _ao_serial_btm_sleep_for(AO_MS_TO_TICKS(10));
if (c) {
c = AO_READ_AGAIN;
break;
if (c) {
c = AO_READ_AGAIN;
break;
static void
ao_radio_wait_isr(uint16_t timeout)
{
static void
ao_radio_wait_isr(uint16_t timeout)
{
- if (timeout)
- ao_alarm(timeout);
ao_arch_block_interrupts();
while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
ao_arch_block_interrupts();
while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort)
- if (ao_sleep(&ao_radio_wake))
+ if (ao_sleep_for(&ao_radio_wake, timeout))
ao_radio_abort = 1;
ao_arch_release_interrupts();
ao_radio_abort = 1;
ao_arch_release_interrupts();
- if (timeout)
- ao_clear_alarm();
if (ao_radio_mcu_wake)
ao_radio_check_marc_status();
}
if (ao_radio_mcu_wake)
ao_radio_check_marc_status();
}
static uint16_t
ao_radio_rx_wait(void)
{
static uint16_t
ao_radio_rx_wait(void)
{
- ao_alarm(AO_MS_TO_TICKS(100));
ao_arch_block_interrupts();
rx_waiting = 1;
while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
!ao_radio_abort &&
!ao_radio_mcu_wake)
{
ao_arch_block_interrupts();
rx_waiting = 1;
while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
!ao_radio_abort &&
!ao_radio_mcu_wake)
{
- if (ao_sleep(&ao_radio_wake))
+ if (ao_sleep_for(&ao_radio_wake, AO_MS_TO_TICKS(100)))
ao_radio_abort = 1;
}
rx_waiting = 0;
ao_arch_release_interrupts();
ao_radio_abort = 1;
}
rx_waiting = 0;
ao_arch_release_interrupts();
if (ao_radio_abort || ao_radio_mcu_wake)
return 0;
rx_data_consumed += AO_FEC_DECODE_BLOCK;
if (ao_radio_abort || ao_radio_mcu_wake)
return 0;
rx_data_consumed += AO_FEC_DECODE_BLOCK;
ao_radio_strobe(CC1120_SRX);
ao_radio_strobe(CC1120_SRX);
- if (timeout)
- ao_alarm(timeout);
ao_arch_block_interrupts();
while (rx_starting && !ao_radio_abort) {
ao_arch_block_interrupts();
while (rx_starting && !ao_radio_abort) {
- if (ao_sleep(&ao_radio_wake))
+ if (ao_sleep_for(&ao_radio_wake, timeout))
ao_radio_abort = 1;
}
uint8_t rx_task_id_save = rx_task_id;
rx_task_id = 0;
rx_starting = 0;
ao_arch_release_interrupts();
ao_radio_abort = 1;
}
uint8_t rx_task_id_save = rx_task_id;
rx_task_id = 0;
rx_starting = 0;
ao_arch_release_interrupts();
- if (timeout)
- ao_clear_alarm();
if (ao_radio_abort) {
if (rx_task_id_save == 0)
if (ao_radio_abort) {
if (rx_task_id_save == 0)
static void
ao_radio_wait_isr(uint16_t timeout)
{
static void
ao_radio_wait_isr(uint16_t timeout)
{
- if (timeout)
- ao_alarm(timeout);
-
ao_arch_block_interrupts();
while (!ao_radio_wake && !ao_radio_abort)
ao_arch_block_interrupts();
while (!ao_radio_wake && !ao_radio_abort)
- if (ao_sleep(&ao_radio_wake))
+ if (ao_sleep_for(&ao_radio_wake, timeout))
ao_radio_abort = 1;
ao_arch_release_interrupts();
ao_radio_abort = 1;
ao_arch_release_interrupts();
-
- if (timeout)
- ao_clear_alarm();
break;
}
while (ao_companion_running) {
break;
}
while (ao_companion_running) {
- ao_alarm(ao_companion_setup.update_period);
- if (ao_sleep(DATA_TO_XDATA(&ao_flight_state)))
+ if (ao_sleep_for(DATA_TO_XDATA(&ao_flight_state), ao_companion_setup.update_period))
ao_companion_get_data();
else
ao_companion_notify();
ao_companion_get_data();
else
ao_companion_notify();
ao_exti_enable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN);
ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE);
ao_exti_enable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN);
ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE);
- ao_alarm(AO_MS_TO_TICKS(10));
ao_arch_block_interrupts();
while (!ao_hmc5883_done)
ao_arch_block_interrupts();
while (!ao_hmc5883_done)
- if (ao_sleep(&ao_hmc5883_done))
+ if (ao_sleep_for(&ao_hmc5883_done, AO_MS_TO_TICKS(10)))
++ao_hmc5883_missed_irq;
ao_arch_release_interrupts();
++ao_hmc5883_missed_irq;
ao_arch_release_interrupts();
ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample));
#if __BYTE_ORDER == __LITTLE_ENDIAN
ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample));
#if __BYTE_ORDER == __LITTLE_ENDIAN
+ao_packet_recv(uint16_t timeout)
{
uint8_t dma_done;
#ifdef AO_LED_GREEN
ao_led_on(AO_LED_GREEN);
#endif
{
uint8_t dma_done;
#ifdef AO_LED_GREEN
ao_led_on(AO_LED_GREEN);
#endif
- dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv), 0);
+ dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv), timeout);
#ifdef AO_LED_GREEN
ao_led_off(AO_LED_GREEN);
#endif
#ifdef AO_LED_GREEN
ao_led_off(AO_LED_GREEN);
#endif
if (ao_tx_packet.len)
ao_packet_master_busy();
ao_packet_master_check_busy();
if (ao_tx_packet.len)
ao_packet_master_busy();
ao_packet_master_check_busy();
- ao_alarm(AO_PACKET_MASTER_RECV_DELAY);
- r = ao_packet_recv();
- ao_clear_alarm();
+ r = ao_packet_recv(AO_PACKET_MASTER_RECV_DELAY);
if (r) {
/* if we can transmit data, do so */
if (ao_packet_tx_used && ao_tx_packet.len == 0)
if (r) {
/* if we can transmit data, do so */
if (ao_packet_tx_used && ao_tx_packet.len == 0)
if (ao_rx_packet.packet.len)
ao_packet_master_busy();
ao_packet_master_sleeping = 1;
if (ao_rx_packet.packet.len)
ao_packet_master_busy();
ao_packet_master_sleeping = 1;
- ao_alarm(ao_packet_master_delay);
- ao_sleep(&ao_packet_master_sleeping);
- ao_clear_alarm();
+ ao_sleep_for(&ao_packet_master_sleeping, ao_packet_master_delay);
ao_packet_master_sleeping = 0;
}
}
ao_packet_master_sleeping = 0;
}
}
ao_tx_packet.len = AO_PACKET_SYN;
ao_packet_restart = 1;
while (ao_packet_enable) {
ao_tx_packet.len = AO_PACKET_SYN;
ao_packet_restart = 1;
while (ao_packet_enable) {
- if (ao_packet_recv()) {
+ if (ao_packet_recv(0)) {
ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);
#if HAS_FLIGHT
ao_flight_force_idle = TRUE;
ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN);
#if HAS_FLIGHT
ao_flight_force_idle = TRUE;
ao_packet_send(void);
uint8_t
ao_packet_send(void);
uint8_t
+ao_packet_recv(uint16_t timeout);
void
ao_packet_flush(void);
void
ao_packet_flush(void);
ao_sleep(&ao_flight_state);
for (;;) {
ao_sleep(&ao_flight_state);
for (;;) {
- ao_alarm(AO_MS_TO_TICKS(100));
- ao_sleep(&ao_pyro_wakeup);
- ao_clear_alarm();
+ ao_sleep_for(&ao_pyro_wakeup, AO_MS_TO_TICKS(100));
if (ao_flight_state >= ao_flight_landed)
break;
any_waiting = ao_pyro_check();
if (ao_flight_state >= ao_flight_landed)
break;
any_waiting = ao_pyro_check();
_ao_serial0_pollchar(void);
uint8_t
_ao_serial0_pollchar(void);
uint8_t
-_ao_serial0_sleep(void);
+_ao_serial0_sleep_for(uint16_t timeout);
void
ao_serial0_putchar(char c);
void
ao_serial0_putchar(char c);
_ao_serial1_pollchar(void);
uint8_t
_ao_serial1_pollchar(void);
uint8_t
-_ao_serial1_sleep(void);
+_ao_serial1_sleep_for(uint16_t timeout);
void
ao_serial1_putchar(char c);
void
ao_serial1_putchar(char c);
_ao_serial2_pollchar(void);
uint8_t
_ao_serial2_pollchar(void);
uint8_t
-_ao_serial2_sleep(void);
+_ao_serial2_sleep_for(uint16_t timeout);
void
ao_serial2_putchar(char c);
void
ao_serial2_putchar(char c);
_ao_serial3_pollchar(void);
uint8_t
_ao_serial3_pollchar(void);
uint8_t
-_ao_serial3_sleep(void);
+_ao_serial3_sleep_for(uint16_t timeout);
void
ao_serial3_putchar(char c);
void
ao_serial3_putchar(char c);
ao_alarm(uint16_t delay)
{
#if HAS_TASK_QUEUE
ao_alarm(uint16_t delay)
{
#if HAS_TASK_QUEUE
ao_clear_alarm(void)
{
#if HAS_TASK_QUEUE
ao_clear_alarm(void)
{
#if HAS_TASK_QUEUE
+uint8_t
+ao_sleep_for(__xdata void *wchan, uint16_t timeout)
+{
+ uint8_t ret;
+ if (timeout)
+ ao_alarm(timeout);
+ ret = ao_sleep(wchan);
+ if (timeout)
+ ao_clear_alarm();
+ return ret;
+}
+
static __xdata uint8_t ao_forever;
void
ao_delay(uint16_t ticks)
{
static __xdata uint8_t ao_forever;
void
ao_delay(uint16_t ticks)
{
- ao_alarm(ticks);
- ao_sleep(&ao_forever);
- ao_clear_alarm();
+ ao_sleep_for(&ao_forever, ticks);
uint8_t
ao_sleep(__xdata void *wchan);
uint8_t
ao_sleep(__xdata void *wchan);
+/* Suspend the current task until wchan is awoken or the timeout
+ * expires. returns:
+ * 0 on normal wake
+ * 1 on alarm
+ */
+uint8_t
+ao_sleep_for(__xdata void *wchan, uint16_t timeout);
+
/* Wake all tasks sleeping on wchan */
void
ao_wakeup(__xdata void *wchan) __reentrant;
/* Wake all tasks sleeping on wchan */
void
ao_wakeup(__xdata void *wchan) __reentrant;
/* set an alarm to go off in 'delay' ticks */
void
ao_alarm(uint16_t delay);
/* set an alarm to go off in 'delay' ticks */
void
ao_alarm(uint16_t delay);
/* Clear any pending alarm */
void
ao_clear_alarm(void);
/* Clear any pending alarm */
void
ao_clear_alarm(void);
/* Yield the processor to another task */
void
/* Yield the processor to another task */
void
#endif /* HAS_APRS */
delay = time - ao_time();
if (delay > 0) {
#endif /* HAS_APRS */
delay = time - ao_time();
if (delay > 0) {
- ao_alarm(delay);
- ao_sleep(&telemetry);
- ao_clear_alarm();
+ ao_sleep_for(&telemetry, delay);
else
ao_terraui_page[ao_current_page]();
else
ao_terraui_page[ao_current_page]();
- ao_alarm(AO_SEC_TO_TICKS(1));
- b = ao_button_get();
- ao_clear_alarm();
+ b = ao_button_get(AO_SEC_TO_TICKS(1));
if (b > 0) {
ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(10));
if (b > 0) {
ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(10));
if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START)))
break;
}
if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START)))
break;
}
- ao_alarm(AO_MS_TO_TICKS(250));
ao_arch_block_interrupts();
stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
ao_i2c_ev_isr(index);
while (ao_i2c_state[index] == I2C_IDLE)
ao_arch_block_interrupts();
stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
ao_i2c_ev_isr(index);
while (ao_i2c_state[index] == I2C_IDLE)
- if (ao_sleep(&ao_i2c_state[index]))
+ if (ao_sleep_for(&ao_i2c_state[index], AO_MS_TO_TICKS(250)))
break;
ao_arch_release_interrupts();
break;
ao_arch_release_interrupts();
return ao_i2c_state[index] == I2C_RUNNING;
}
return ao_i2c_state[index] == I2C_RUNNING;
}
(STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
ao_dma_start(tx_dma_index);
(STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR));
ao_dma_start(tx_dma_index);
ao_arch_block_interrupts();
while (!ao_dma_done[tx_dma_index])
ao_arch_block_interrupts();
while (!ao_dma_done[tx_dma_index])
- if (ao_sleep(&ao_dma_done[tx_dma_index]))
+ if (ao_sleep_for(&ao_dma_done[tx_dma_index], 1 + len))
ao_dma_done_transfer(tx_dma_index);
stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0)
ao_dma_done_transfer(tx_dma_index);
stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN);
while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0)
- if (ao_sleep(&ao_i2c_state[index]))
+ if (ao_sleep_for(&ao_i2c_state[index], 1 + len))
break;
stm_i2c->cr2 = AO_STM_I2C_CR2;
ao_arch_release_interrupts();
break;
stm_i2c->cr2 = AO_STM_I2C_CR2;
ao_arch_release_interrupts();
if (stop)
stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
if (stop)
stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
ao_arch_block_interrupts();
while (ao_i2c_recv_len[index])
ao_arch_block_interrupts();
while (ao_i2c_recv_len[index])
- if (ao_sleep(&ao_i2c_recv_len[index]))
+ if (ao_sleep_for(&ao_i2c_recv_len[index], 1))
break;
ao_arch_release_interrupts();
ret = ao_i2c_recv_len[index] == 0;
break;
ao_arch_release_interrupts();
ret = ao_i2c_recv_len[index] == 0;
} else {
uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;
ao_dma_set_transfer(rx_dma_index,
} else {
uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index;
ao_dma_set_transfer(rx_dma_index,
ao_i2c_wait_addr(index);
ao_dma_start(rx_dma_index);
ao_i2c_wait_addr(index);
ao_dma_start(rx_dma_index);
ao_arch_block_interrupts();
while (!ao_dma_done[rx_dma_index])
ao_arch_block_interrupts();
while (!ao_dma_done[rx_dma_index])
- if (ao_sleep(&ao_dma_done[rx_dma_index]))
+ if (ao_sleep_for(&ao_dma_done[rx_dma_index], len))
break;
ao_arch_release_interrupts();
break;
ao_arch_release_interrupts();
ret = ao_dma_done[rx_dma_index];
ao_dma_done_transfer(rx_dma_index);
stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
ret = ao_dma_done[rx_dma_index];
ao_dma_done_transfer(rx_dma_index);
stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP);
-_ao_usart_sleep(struct ao_stm_usart *usart)
+_ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout)
- return ao_sleep(&usart->rx_fifo);
+ return ao_sleep_for(&usart->rx_fifo, timeout);
+_ao_serial1_sleep_for(uint16_t timeout)
- return _ao_usart_sleep(&ao_stm_usart1);
+ return _ao_usart_sleep_for(&ao_stm_usart1, timeout);
+_ao_serial2_sleep_for(uint16_t timeout)
- return _ao_usart_sleep(&ao_stm_usart2);
+ return _ao_usart_sleep_for(&ao_stm_usart2, timeout);
+_ao_serial3_sleep_for(uint16_t timeout)
- return _ao_usart_sleep(&ao_stm_usart3);
+ return _ao_usart_sleep_for(&ao_stm_usart3, timeout);
#define ao_serial_btm_getchar ao_serial2_getchar
#define ao_serial_btm_putchar ao_serial2_putchar
#define _ao_serial_btm_pollchar _ao_serial2_pollchar
#define ao_serial_btm_getchar ao_serial2_getchar
#define ao_serial_btm_putchar ao_serial2_putchar
#define _ao_serial_btm_pollchar _ao_serial2_pollchar
-#define _ao_serial_btm_sleep _ao_serial2_sleep
+#define _ao_serial_btm_sleep_for _ao_serial2_sleep_for
#define ao_serial_btm_set_speed ao_serial2_set_speed
#define ao_serial_btm_drain ao_serial2_drain
#define ao_serial_btm_rx_fifo (ao_stm_usart2.rx_fifo)
#define ao_serial_btm_set_speed ao_serial2_set_speed
#define ao_serial_btm_drain ao_serial2_drain
#define ao_serial_btm_rx_fifo (ao_stm_usart2.rx_fifo)
uint16_t delay;
for (;;) {
uint16_t delay;
for (;;) {
if (!ao_lco_valid) {
ao_led_on(AO_LED_RED);
ao_led_off(AO_LED_GREEN);
if (!ao_lco_valid) {
ao_led_on(AO_LED_RED);
ao_led_off(AO_LED_GREEN);
delay = AO_MS_TO_TICKS(100);
else
delay = AO_SEC_TO_TICKS(1);
delay = AO_MS_TO_TICKS(100);
else
delay = AO_SEC_TO_TICKS(1);
- ao_alarm(delay);
- ao_sleep(&ao_lco_armed);
- ao_clear_alarm();
+ ao_sleep_for(&ao_lco_armed, delay);
delay = AO_MS_TO_TICKS(100);
else
delay = AO_SEC_TO_TICKS(1);
delay = AO_MS_TO_TICKS(100);
else
delay = AO_SEC_TO_TICKS(1);
- ao_alarm(delay);
- ao_sleep(&ao_lco_armed);
- ao_clear_alarm();
+ ao_sleep_for(&ao_lco_armed, delay);