Waking up a task waiting on some random object is a bad idea. Fix
the waiters to look for suitable signalling.
Signed-off-by: Keith Packard <keithp@keithp.com>
void
ao_wakeup(__xdata void *wchan);
void
ao_wakeup(__xdata void *wchan);
-/* Wake up a specific task */
-void
-ao_wake_task(__xdata struct ao_task *task);
-
/* 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);
* then poke the master to send all queued data
*/
if (ao_packet_tx_used && ao_packet_master_sleeping)
* then poke the master to send all queued data
*/
if (ao_packet_tx_used && ao_packet_master_sleeping)
- ao_wake_task(&ao_packet_task);
+ ao_wakeup(&ao_packet_master_sleeping);
}
#endif /* PACKET_HAS_MASTER */
}
#endif /* PACKET_HAS_MASTER */
ao_packet_getchar(void) __critical
{
char c;
ao_packet_getchar(void) __critical
{
char c;
- while ((c = ao_packet_pollchar()) == AO_READ_AGAIN)
- {
+ while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) {
if (!ao_packet_enable)
break;
if (ao_packet_master_sleeping)
if (!ao_packet_enable)
break;
if (ao_packet_master_sleeping)
- ao_wake_task(&ao_packet_task);
+ ao_wakeup(&ao_packet_master_sleeping);
ao_usb_flush();
ao_sleep(&ao_stdin_ready);
ao_usb_flush();
ao_sleep(&ao_stdin_ready);
- if (!ao_packet_enable)
- break;
uint8_t c;
while (ao_packet_enable) {
c = ao_packet_getchar();
uint8_t c;
while (ao_packet_enable) {
c = ao_packet_getchar();
+ if (c != AO_READ_AGAIN)
ao_usb_putchar(c);
}
ao_exit();
ao_usb_putchar(c);
}
ao_exit();
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_delay(ao_packet_master_delay);
+ ao_alarm(ao_packet_master_delay);
+ ao_sleep(&ao_packet_master_sleeping);
ao_packet_master_sleeping = 0;
}
}
ao_packet_master_sleeping = 0;
}
}
ao_delay(AO_MS_TO_TICKS(100));
ao_packet_enable = 0;
while (ao_packet_echo_task.wchan || ao_packet_task.wchan) {
ao_delay(AO_MS_TO_TICKS(100));
ao_packet_enable = 0;
while (ao_packet_echo_task.wchan || ao_packet_task.wchan) {
- if (ao_packet_echo_task.wchan)
- ao_wake_task(&ao_packet_echo_task);
+ ao_radio_recv_abort();
+ ao_wakeup(&ao_stdin_ready);
ao_delay(AO_MS_TO_TICKS(10));
}
}
ao_delay(AO_MS_TO_TICKS(10));
}
}
{
if (ao_packet_enable) {
ao_packet_enable = 0;
{
if (ao_packet_enable) {
ao_packet_enable = 0;
while (ao_packet_task.wchan) {
while (ao_packet_task.wchan) {
- ao_wake_task(&ao_packet_task);
- ao_yield();
+ ao_radio_recv_abort();
+ ao_delay(AO_MS_TO_TICKS(10));
ao_radio_set_telemetry();
ao_radio_set_telemetry();
DMA_CFG1_PRIORITY_HIGH);
ao_dma_start(ao_radio_dma);
RFST = RFST_SRX;
DMA_CFG1_PRIORITY_HIGH);
ao_dma_start(ao_radio_dma);
RFST = RFST_SRX;
+
+ /* Wait for DMA to be done, for the radio receive process to
+ * get aborted or for a receive timeout to fire
+ */
__critical while (!ao_radio_dma_done && !ao_radio_abort)
__critical while (!ao_radio_dma_done && !ao_radio_abort)
- ao_sleep(&ao_radio_dma_done);
+ if (ao_sleep(&ao_radio_dma_done))
+ break;
/* 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
ao_cur_task->wchan = wchan;
}
ao_yield();
ao_cur_task->wchan = wchan;
}
ao_yield();
+ ao_cur_task->alarm = 0;
if (ao_cur_task->wchan) {
ao_cur_task->wchan = NULL;
if (ao_cur_task->wchan) {
ao_cur_task->wchan = NULL;
- ao_cur_task->alarm = 0;
- ao_cur_task->alarm = 0;
ao_cur_task->alarm = 1;
}
ao_cur_task->alarm = 1;
}
-void
-ao_wake_task(__xdata struct ao_task *task)
-{
- task->wchan = NULL;
-}
-
void
ao_exit(void) __critical
{
void
ao_exit(void) __critical
{