From 7079f939d05478171d0271f35b2f6d35107cd0bf Mon Sep 17 00:00:00 2001 From: Attila BODY Date: Thu, 28 Nov 2019 11:34:41 +0100 Subject: [PATCH] crcscheduler: avoid static function for unit tests unifying execution paths of DMA interrupt handler (error/success) --- crcscheduler.c | 57 ++++++++++++++++++++------------------------------ crcscheduler.h | 16 ++++++++------ 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/crcscheduler.c b/crcscheduler.c index 6271890..c6745d1 100644 --- a/crcscheduler.c +++ b/crcscheduler.c @@ -27,6 +27,12 @@ # define DIAG_INTERRUPT_OUT() #endif +#ifdef UNITTEST +#define STATIC_MOCKME +#else +#define STATIC_MOCKME static +#endif + void Crc_InitStatus(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_TypeDef *dma, uint32_t stream) { st->crcUnit = crcUnit; @@ -35,7 +41,7 @@ void Crc_InitStatus(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_TypeDef *d LL_DMA_EnableIT_TE(dma, stream); LL_DMA_SetM2MDstAddress(dma, stream, (uint32_t)&crcUnit->DR); st->activeSlot = NULL; - st->first = NULL; + st->firstSlot = NULL; } void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount) @@ -46,8 +52,8 @@ void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint32_t prim = __get_PRIMASK(); __disable_irq(); - slot->next = status->first; - status->first = slot; + slot->next = status->firstSlot; + status->firstSlot = slot; __set_PRIMASK(prim); } @@ -73,7 +79,7 @@ uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint16_t need_start; struct crcstatus_t volatile *st = status; - while(st->activeSlot == slot && st->activeTask == task); + while(Crc_IsSlotBusy(slot, task)); __disable_irq(); need_start = (st->activeSlot == NULL); slot->tasks[task].address = need_start ? NULL : address; @@ -96,15 +102,6 @@ uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, return need_start; } -void Crc_WaitResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task) -{ - struct crcslotlistitem_t *slotQueued; - - while(Crc_IsSlotQueued(slot, task)); - while(Crc_GetActiveTask(&slotQueued, status) == task && slotQueued == slot); -} - - uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t *address, uint16_t len) { uint32_t result; @@ -114,13 +111,13 @@ uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, } // only called from ISR context -static void StartNextCrcTask(struct crcstatus_t *status) +STATIC_MOCKME void Crc_StartNextTask(struct crcstatus_t *status) { char moreTasks; uint8_t index = 0; do { - struct crcslotlistitem_t *slot = status->first; + struct crcslotlistitem_t *slot = status->firstSlot; moreTasks = 0; while(slot) { if(index < slot->count) { @@ -144,35 +141,27 @@ static void StartNextCrcTask(struct crcstatus_t *status) status->activeSlot = NULL; } +// !!!PORTABILITY WARNING!!! using registers and bits directly. should be reviewed extremely t void Crc_HandleDmaIrq(struct crcstatus_t *status) { + uint8_t success = 1; + DIAG_INTERRUPT_IN(); - if(*status->dmaInfo.isReg & status->dmaInfo.tcMask) { // DMA transfer complete - *status->dmaInfo.ifcReg = status->dmaInfo.tcMask; + if((*status->dmaInfo.isReg & status->dmaInfo.tcMask) || + (*status->dmaInfo.isReg & status->dmaInfo.teMask)) { + if(*status->dmaInfo.isReg & status->dmaInfo.teMask) + success = 0; + *status->dmaInfo.ifcReg = *status->dmaInfo.isReg & (status->dmaInfo.tcMask | status->dmaInfo.teMask); LL_DMA_DisableStream(status->dmaInfo.dma, status->dmaInfo.stream); if(status->activeSlot) { struct crcslottask_t *tsk = &status->activeSlot->tasks[status->activeTask]; if(tsk->callback) - tsk->callback(tsk->callbackParam, status->crcUnit->DR, 1); + tsk->callback(tsk->callbackParam, status->crcUnit->DR, success); else if(tsk->callbackParam) - *(uint32_t*)tsk->callbackParam = status->crcUnit->DR; + *(uint32_t*)tsk->callbackParam = success ? status->crcUnit->DR : 0xffffffff; tsk->callback = tsk->callbackParam = NULL; // marking as inactive DIAG_CRC_CALC_END(); - StartNextCrcTask(status); - } - } - else if(*status->dmaInfo.isReg & status->dmaInfo.teMask) { - *status->dmaInfo.ifcReg = status->dmaInfo.teMask; - LL_DMA_DisableStream(status->dmaInfo.dma, status->dmaInfo.stream); - if(status->activeSlot) { - struct crcslottask_t *tsk = &status->activeSlot->tasks[status->activeTask]; - if(tsk->callback) - tsk->callback(tsk->callbackParam, status->crcUnit->DR, 0); - else if(tsk->callbackParam) - *(uint32_t*)tsk->callbackParam = 0xffffffff; - tsk->callback = tsk->callbackParam = NULL; // marking as inactive - DIAG_CRC_CALC_END(); - StartNextCrcTask(status); + Crc_StartNextTask(status); } } DIAG_INTERRUPT_OUT(); diff --git a/crcscheduler.h b/crcscheduler.h index 3b117da..81d027b 100644 --- a/crcscheduler.h +++ b/crcscheduler.h @@ -39,26 +39,30 @@ struct crcstatus_t { struct dmainfo_t dmaInfo; struct crcslotlistitem_t *activeSlot; uint8_t activeTask; - struct crcslotlistitem_t *first; + struct crcslotlistitem_t *firstSlot; }; void Crc_InitStatus(struct crcstatus_t *status, CRC_TypeDef *crcUnit, DMA_TypeDef *dma, uint32_t stream); uint8_t Crc_GetActiveTask(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status); -static inline uint8_t Crc_IsSlotQueued(struct crcslotlistitem_t volatile *slot, uint8_t task) { - return slot->tasks[task].address != NULL; +static inline uint8_t Crc_IsSlotQueued(struct crcslotlistitem_t *slot, uint8_t task) { + return ((struct crcslottask_t volatile)slot->tasks[task]).address != NULL; } -static inline uint8_t Crc_IsSlotActive(struct crcslotlistitem_t volatile *slot, uint8_t task) { - return slot->tasks[task].callback != NULL || slot->tasks[task].callbackParam != NULL; +static inline uint8_t Crc_IsSlotBusy(struct crcslotlistitem_t *slot, uint8_t task) { + struct crcslottask_t volatile *taskPtr = &slot->tasks[task]; + return taskPtr->callback != NULL || taskPtr->callbackParam != NULL; +} + +static inline void Crc_WaitResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task) { + while(Crc_IsSlotBusy(slot, task)); } void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount); uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam); -void Crc_WaitResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task); uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t *address, uint16_t len); void Crc_ComputeAsync(struct crcstatus_t *status, uint8_t slot, uint8_t *address, uint16_t len,