From 8272a36aee33d75c69b97d03cc4f730fc42b0b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Mon, 15 Jan 2018 15:04:09 +0100 Subject: [PATCH] Implemented unit timed tick and uart rx timeout --- framework/unit.h | 10 ++++++++++ framework/unit_registry.c | 18 ++++++++++++++++++ framework/unit_registry.h | 5 +++++ gex_hooks.c | 2 ++ platform/irq_dispatcher.c | 1 + units/usart/_init.c | 8 +++++--- units/usart/_internal.h | 9 +++++++++ units/usart/unit_usart.c | 19 +++++++++++++++++++ 8 files changed, 69 insertions(+), 3 deletions(-) diff --git a/framework/unit.h b/framework/unit.h index 3b530b1..961eb2e 100644 --- a/framework/unit.h +++ b/framework/unit.h @@ -45,6 +45,9 @@ struct unit { /** Bit-map of held resources */ ResourceMap resources; + + uint16_t tick_interval; + uint16_t _tick_cnt; }; /** @@ -111,6 +114,13 @@ struct unit_driver { * Handle an incoming request. Return true if command was OK. */ error_t (*handleRequest)(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp); + + /** + * Periodic update call. + * This is run from the SysTick interrupt handler, + * any communication should be deferred via the job queue. + */ + void (*updateTick)(Unit *unit); }; /** diff --git a/framework/unit_registry.c b/framework/unit_registry.c index 21ffb49..d6524ea 100644 --- a/framework/unit_registry.c +++ b/framework/unit_registry.c @@ -583,3 +583,21 @@ void ureg_print_unit_resources(IniWriter *iw) } iw_newline(iw); } + +void ureg_tick_units(void) +{ + UlistEntry *li = ulist_head; + while (li != NULL) { + Unit *const pUnit = &li->unit; + if (pUnit->status == E_SUCCESS && pUnit->tick_interval > 0) { + if (pUnit->_tick_cnt == 0) { + if (pUnit->driver->updateTick) { + pUnit->driver->updateTick(pUnit); + } + pUnit->_tick_cnt = pUnit->tick_interval; + } + pUnit->_tick_cnt--; + } + li = li->next; + } +} diff --git a/framework/unit_registry.h b/framework/unit_registry.h index d42f76a..23ab198 100644 --- a/framework/unit_registry.h +++ b/framework/unit_registry.h @@ -142,4 +142,9 @@ Unit *ureg_get_rsc_owner(Resource resource); */ void ureg_print_unit_resources(IniWriter *iw); +/** + * 1ms tick for all units that want it + */ +void ureg_tick_units(void); + #endif //GEX_UNIT_REGISTRY_H diff --git a/gex_hooks.c b/gex_hooks.c index 8712475..e60f4bb 100644 --- a/gex_hooks.c +++ b/gex_hooks.c @@ -9,6 +9,7 @@ #include "platform/status_led.h" #include "platform/debug_uart.h" #include "gex_hooks.h" +#include "unit_registry.h" /** * This is a systick callback for GEX application logic @@ -17,6 +18,7 @@ void GEX_MsTick(void) { TF_Tick(comm); Indicator_Tick(); + ureg_tick_units(); } /** diff --git a/platform/irq_dispatcher.c b/platform/irq_dispatcher.c index cb9921e..40715a1 100644 --- a/platform/irq_dispatcher.c +++ b/platform/irq_dispatcher.c @@ -143,6 +143,7 @@ static struct cbslot *get_slot_for_periph(void *periph) void irqd_attach(void *periph, IrqCallback callback, void *arg) { struct cbslot *slot = get_slot_for_periph(periph); + assert_param(slot->callback == NULL); slot->callback = callback; slot->arg = arg; } diff --git a/units/usart/_init.c b/units/usart/_init.c index 2679b19..a4068f5 100644 --- a/units/usart/_init.c +++ b/units/usart/_init.c @@ -1,6 +1,7 @@ // // Created by MightyPork on 2018/01/14. // +#include #include "platform.h" #include "unit_base.h" @@ -43,9 +44,6 @@ error_t UUSART_preInit(Unit *unit) priv->de_assert_time = 8; priv->de_clear_time = 8; - priv->rx_buffer = NULL; - priv->tx_buffer = NULL; - return E_SUCCESS; } @@ -315,6 +313,10 @@ error_t UUSART_init(Unit *unit) // modifies some usart registers that can't be modified when enabled TRY(UUSART_SetupDMAs(unit)); + // timeout based on the baudrate + unit->tick_interval = (uint16_t) ((50 * 1000) / priv->baudrate); // receive timeout (ms) + if (unit->tick_interval < 5) unit->tick_interval = 5; + return E_SUCCESS; } diff --git a/units/usart/_internal.h b/units/usart/_internal.h index 21e1e9d..3aeb0d2 100644 --- a/units/usart/_internal.h +++ b/units/usart/_internal.h @@ -57,6 +57,8 @@ struct priv { volatile uint16_t tx_buf_nw; volatile uint16_t tx_buf_chunk; volatile bool tx_dma_busy; + + volatile uint16_t rx_last_dmapos; }; /** Allocate data structure and set defaults */ @@ -95,6 +97,13 @@ void UUSART_DMA_HandleRxFromIRQ(Unit *unit, uint16_t endpos); */ uint16_t UUSART_DMA_TxQueue(struct priv *priv, const uint8_t *buffer, uint16_t len); +/** + * Handle rx timeout, grab what is received and send it immediately. + * + * @param unit + */ +void UUSART_DMA_HandleRxTimeout(Unit *unit); + // ------------------------------------------------------------------------ diff --git a/units/usart/unit_usart.c b/units/usart/unit_usart.c index e4684f6..6ff862b 100644 --- a/units/usart/unit_usart.c +++ b/units/usart/unit_usart.c @@ -2,6 +2,7 @@ // Created by MightyPork on 2018/01/02. // +#include #include "platform.h" #include "comm/messages.h" #include "unit_base.h" @@ -68,6 +69,23 @@ void UUSART_DMA_HandleRxFromIRQ(Unit *unit, uint16_t endpos) priv->rx_buf_readpos = endpos; } +void UUSART_Tick(Unit *unit) +{ + assert_param(unit); + struct priv *priv = unit->data; + assert_param(priv); + + if (priv->rx_last_dmapos == priv->dma_rx->CNDTR) { + uint16_t endpos = (uint16_t) (UUSART_RXBUF_LEN - priv->rx_last_dmapos); + if (endpos != priv->rx_buf_readpos) { + dbg("DMA timeout"); + UUSART_DMA_HandleRxFromIRQ(unit, endpos); + } + } else { + priv->rx_last_dmapos = (uint16_t) priv->dma_rx->CNDTR; + } +} + error_t UU_USART_Write(Unit *unit, const uint8_t *buffer, uint32_t len) { @@ -155,5 +173,6 @@ const UnitDriver UNIT_USART = { .init = UUSART_init, .deInit = UUSART_deInit, // Function + .updateTick = UUSART_Tick, .handleRequest = UUSART_handleRequest, };