From 5d26fdc64d86cdbf16d6796c3c51cef3ef05a8dc Mon Sep 17 00:00:00 2001 From: Attila BODY Date: Wed, 4 Dec 2019 15:57:18 +0100 Subject: [PATCH] packetusart unit tests --- consolehandler.c | 2 +- crcscheduler.c | 50 ++++++++++---- crcscheduler.h | 37 ++++++---- dmahelper.c | 2 +- memcpydma.c | 10 ++- memcpydma.h | 8 ++- packetusart.c | 176 ++++++++++++++++++++++++++++++----------------- packetusart.h | 85 ++++++++--------------- 8 files changed, 219 insertions(+), 151 deletions(-) diff --git a/consolehandler.c b/consolehandler.c index 97f5f20..fff308f 100644 --- a/consolehandler.c +++ b/consolehandler.c @@ -62,5 +62,5 @@ void Con_PrintStats(char *buffer, uint8_t id, struct usart_stats *stats, USART_ ADDINFO(buffer, " pmp: ", stats->premature_payload); buffer += strcpy_ex(buffer, "\r\n"); - Pku_SetupTransmit(usart, dmaInfo->dma, dmaInfo->stream, bs, buffer - bs + 1); + Pu_SetupTransmit(usart, dmaInfo->dma, dmaInfo->stream, bs, buffer - bs + 1); } diff --git a/crcscheduler.c b/crcscheduler.c index c6745d1..403f3ec 100644 --- a/crcscheduler.c +++ b/crcscheduler.c @@ -27,13 +27,14 @@ # define DIAG_INTERRUPT_OUT() #endif -#ifdef UNITTEST -#define STATIC_MOCKME -#else -#define STATIC_MOCKME static +#ifndef MOCKABLE +#define MOCKABLE(x) x #endif -void Crc_InitStatus(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_TypeDef *dma, uint32_t stream) +void Crc_StartNextTask(struct crcstatus_t *status); + + +void MOCKABLE(Crc_InitStatus)(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_TypeDef *dma, uint32_t stream) { st->crcUnit = crcUnit; Dma_Init(&st->dmaInfo, dma, stream); @@ -44,7 +45,8 @@ void Crc_InitStatus(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_TypeDef *d st->firstSlot = NULL; } -void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount) + +void MOCKABLE(Crc_AttachTask)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount) { slot->count = taskCount; slot->tasks = tasks; @@ -57,7 +59,8 @@ void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, __set_PRIMASK(prim); } -uint8_t Crc_GetActiveTask(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status) + +uint8_t MOCKABLE(Crc_GetActiveTask)(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status) { uint8_t ret; @@ -72,8 +75,24 @@ uint8_t Crc_GetActiveTask(struct crcslotlistitem_t **slot_out, struct crcstatus_ } -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) +uint8_t MOCKABLE(Crc_IsSlotQueued)(struct crcslotlistitem_t *slot, uint8_t task) { + return ((struct crcslottask_t volatile)slot->tasks[task]).address != NULL; +} + + +uint8_t MOCKABLE(Crc_IsSlotBusy)(struct crcslotlistitem_t *slot, uint8_t task) { + struct crcslottask_t volatile *taskPtr = &slot->tasks[task]; + return taskPtr->callback != NULL || taskPtr->callbackParam != NULL; +} + + +void MOCKABLE(Crc_WaitResults)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task) { + while(Crc_IsSlotBusy(slot, task)); +} + + +uint8_t MOCKABLE(Crc_Enqueue)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, + void *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam) { uint32_t prim = __get_PRIMASK(); uint16_t need_start; @@ -93,6 +112,7 @@ uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, __set_PRIMASK(prim); if(need_start) { + DIAG_CRC_CALC_START(); status->crcUnit->CR = 1; LL_DMA_SetM2MSrcAddress(status->dmaInfo.dma, status->dmaInfo.stream, (uint32_t)address); LL_DMA_SetDataLength(status->dmaInfo.dma, status->dmaInfo.stream, (len+3)/4); @@ -102,7 +122,8 @@ uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, return need_start; } -uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t *address, uint16_t len) + +uint32_t MOCKABLE(Crc_Compute)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, void *address, uint16_t len) { uint32_t result; Crc_Enqueue(status, slot, task, address, len, NULL, &result); @@ -110,8 +131,9 @@ uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, return result; } + // only called from ISR context -STATIC_MOCKME void Crc_StartNextTask(struct crcstatus_t *status) +void MOCKABLE(Crc_StartNextTask)(struct crcstatus_t *status) { char moreTasks; uint8_t index = 0; @@ -122,6 +144,7 @@ STATIC_MOCKME void Crc_StartNextTask(struct crcstatus_t *status) while(slot) { if(index < slot->count) { if(slot->tasks[index].address) { + DIAG_CRC_CALC_START(); status->activeSlot = slot; status->activeTask = index; status->crcUnit->CR = 1; @@ -141,8 +164,9 @@ STATIC_MOCKME void Crc_StartNextTask(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) + +// !!!PORTABILITY WARNING!!! using registers and bits directly. should be reviewed extremely when porting to a different MCU +void MOCKABLE(Crc_HandleDmaIrq)(struct crcstatus_t *status) { uint8_t success = 1; diff --git a/crcscheduler.h b/crcscheduler.h index 81d027b..ce1a4dc 100644 --- a/crcscheduler.h +++ b/crcscheduler.h @@ -46,29 +46,36 @@ void Crc_InitStatus(struct crcstatus_t *status, CRC_TypeDef *crcUnit, DMA_TypeDe uint8_t Crc_GetActiveTask(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status); -static inline uint8_t Crc_IsSlotQueued(struct crcslotlistitem_t *slot, uint8_t task) { - return ((struct crcslottask_t volatile)slot->tasks[task]).address != NULL; -} +uint8_t Crc_IsSlotQueued(struct crcslotlistitem_t *slot, uint8_t task); -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; -} +uint8_t Crc_IsSlotBusy(struct crcslotlistitem_t *slot, uint8_t task); -static inline void Crc_WaitResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task) { - while(Crc_IsSlotBusy(slot, task)); -} +void Crc_WaitResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t 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); -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, - void (*callback)(void*, uint32_t, uint8_t), void* callbackParam); + void *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam); +uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, void *address, uint16_t len); void Crc_HandleDmaIrq(struct crcstatus_t *status); +// !!!PRIVATE!!! exposed only to make mocking possible +void Crc_StartNextTask(struct crcstatus_t *status); + + +#ifdef UNITTEST +DECLARE_MOCK(Crc_InitStatus); +DECLARE_MOCK(Crc_GetActiveTask); +DECLARE_MOCK(Crc_IsSlotQueued); +DECLARE_MOCK(Crc_IsSlotBusy); +DECLARE_MOCK(Crc_WaitResults); +DECLARE_MOCK(Crc_AttachTask); +DECLARE_MOCK(Crc_Enqueue); +DECLARE_MOCK(Crc_Compute); +DECLARE_MOCK(Crc_HandleDmaIrq); +DECLARE_MOCK(Crc_StartNextTask); +#endif // UNITTEST + #ifdef __cplusplus } #endif diff --git a/dmahelper.c b/dmahelper.c index 525f729..961d496 100644 --- a/dmahelper.c +++ b/dmahelper.c @@ -6,7 +6,7 @@ */ #include #ifndef MOCKABLE -#define MOCKABLE(x) +#define MOCKABLE(x) x #endif volatile uint32_t* MOCKABLE(Dma_GetIsReg)(DMA_TypeDef *dma, uint32_t stream) diff --git a/memcpydma.c b/memcpydma.c index 17938cd..a6f5285 100644 --- a/memcpydma.c +++ b/memcpydma.c @@ -15,17 +15,21 @@ # define DIAG_INTERRUPT_OUT() #endif +#ifndef MOCKABLE +#define MOCKABLE(x) x +#endif // MOCKABLE + volatile uint8_t g_memcpyDmaBusy = 0; static struct dmainfo_t g_memcpyDmaInfo; -void Mcd_Init(DMA_TypeDef *dma, uint32_t stream) +void MOCKABLE(Mcd_Init)(DMA_TypeDef *dma, uint32_t stream) { Dma_Init(&g_memcpyDmaInfo, dma, stream); LL_DMA_EnableIT_TC(dma, stream); } -void * Mcd_Copy(void *dst, void const *src, size_t length) +void * MOCKABLE(Mcd_Copy)(void *dst, void const *src, size_t length) { LL_DMA_SetM2MSrcAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)src); LL_DMA_SetM2MDstAddress(g_memcpyDmaInfo.dma, g_memcpyDmaInfo.stream, (uint32_t)dst); @@ -36,7 +40,7 @@ void * Mcd_Copy(void *dst, void const *src, size_t length) return dst; } -void Mcd_HandleDmaIrq() +void MOCKABLE(Mcd_HandleDmaIrq)(void) { DIAG_INTERRUPT_IN(); if(*g_memcpyDmaInfo.isReg & g_memcpyDmaInfo.tcMask) { // DMA transfer complete diff --git a/memcpydma.h b/memcpydma.h index 8859d63..fb39134 100644 --- a/memcpydma.h +++ b/memcpydma.h @@ -17,7 +17,13 @@ extern "C" { void Mcd_Init(DMA_TypeDef *dma, uint32_t stream); void * Mcd_Copy(void *dst, void const *src, size_t length); -void Mcd_HandleDmaIrq(); +void Mcd_HandleDmaIrq(void); + +#ifdef UNITTEST +DECLARE_MOCK(Mcd_Init); +DECLARE_MOCK(Mcd_Copy); +DECLARE_MOCK(Mcd_HandleDmaIrq); +#endif // UNITTEST #ifdef __cplusplus } diff --git a/packetusart.c b/packetusart.c index 6adc252..4aca014 100644 --- a/packetusart.c +++ b/packetusart.c @@ -15,6 +15,10 @@ #include "f4ll_c/dmahelper.h" #include "f4ll_c/crcscheduler.h" +#ifndef MOCKABLE +#define MOCKABLE(x) x +#endif + #ifndef DIAG_RX_BUFFER_SWITCH # define DIAG_RX_BUFFER_SWITCH(x) #endif @@ -32,7 +36,51 @@ static inline uint32_t RoundUpTo4(uint32_t inp) return (inp + 3) & 0xfffc; } -void Pku_Init( +#ifndef USART_STATS_DISABLED +static inline void StatsIncOverrun(struct usart_stats *s) { + ++s->overrun; +} +static inline void StatsIncHdrError(struct usart_stats *s, uint32_t hdr) { + ++s->hdrError; + s->lastErrHdr = hdr; +} +static inline void StatsIncPayloadError(struct usart_stats *s, uint32_t pep1, uint32_t pep2) { + ++s->payloadErrror; + s->pep1 = pep1; + s->pep2 = pep2; +} +static inline void StatsIncDmaError(struct usart_stats *s) { + ++s->dmaError; +} +static inline void StatsIncRcvd(struct usart_stats *s) { + ++s->rcvd; +} +static inline void StatsIncPremature_hdr(struct usart_stats *s) { + ++s->premature_hdr; +} +static inline void StatsIncPremature_payload(struct usart_stats *s) { + ++s->premature_payload; +} +static inline void StatsIncSent(struct usart_stats *s) { + ++s->sent; +} +static inline void StatsAddSkiped(struct usart_stats *s, uint8_t cnt) { + s->skiped += s->rcvd > 2 ? cnt : 0; +} + +#else // USART_STATS_DISABLED +#define StatsIncOverrun(x) +#define StatsIncHdrError(x,y) +#define StatsIncPayloadError(x,y,z) +#define StatsIncDmaError(x) +#define StatsIncRcvd(x) +#define StatsIncPremature_hdr(x) +#define StatsIncPremature_payload(x) +#define StatsIncSent(x) +#define StatsAddSkiped(x) +#endif // USART_STATS_DISABLED + +void MOCKABLE(Pu_Init)( struct usartstatus_t *st, USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx, struct crcstatus_t *crcStatus, @@ -49,17 +97,17 @@ void Pku_Init( st->txBuffer.busy = 0; st->txBuffer.error = 0; st->txBuffer.requestedLength = 0; + st->txBuffer.usartStatus = st; st->rxBuffers[0].busy = 0; st->rxBuffers[1].busy = 0; st->rxBuffers[0].error = 0; st->rxBuffers[1].error = 0; st->rxBuffers[0].requestedLength = 0; st->rxBuffers[1].requestedLength = 0; - st->txBuffer.usartStatus = st; st->rxBuffers[0].usartStatus = st; st->rxBuffers[1].usartStatus = st; st->packetReceivedCallback = packetReceivedCallback; - st->packetReceivedCallbacParam = packetReceivedCallbackParam; + st->packetReceivedCallbackParam = packetReceivedCallbackParam; st->rxSerial = -1; st->txSerial = 0; st->activeRxBuf = 0; @@ -82,52 +130,46 @@ void Pku_Init( } -uint8_t* Pku_GetTxBuffer(struct usartstatus_t *status) +uint8_t* MOCKABLE(Pu_GetTxBuffer)(struct usartstatus_t *status) { return status->txBuffer.packet.payload; } -static inline void BuildHeader(struct usart_buffer_t *buffer, uint8_t serial, uint8_t length) -{ - uint8_t hash = STARTMARKER; - buffer->packet.header.startByte = STARTMARKER; - buffer->packet.header.serial = serial; - hash ^= serial; - buffer->packet.header.payloadLength = length - 1; - hash ^= length - 1; - buffer->packet.header.hash = hash; -} - -static inline uint8_t CheckHeader(struct usartpacket_t *packet) +uint8_t MOCKABLE(Pu_CheckHeader)(struct usartpacket_t *packet) { return packet->header.startByte == STARTMARKER && (packet->header.startByte ^ packet->header.serial ^ packet->header.payloadLength) == packet->header.hash; } -uint8_t Pku_Post(struct usartstatus_t *status, uint8_t const *payload, uint16_t length, struct crcstatus_t *crcStatus, uint8_t waitForCrcQueue) +uint8_t MOCKABLE(Pu_Post)(struct usartstatus_t *status, uint8_t const *payload, uint8_t length, struct crcstatus_t *crcStatus, uint8_t waitForCrcQueue) { - if(length > 256) - return 1; + struct usart_buffer_t *buffer = &status->txBuffer; + uint8_t hash = STARTMARKER; + buffer->packet.header.startByte = STARTMARKER; + buffer->packet.header.serial = status->txSerial; + hash ^= status->txSerial++; + buffer->packet.header.payloadLength = length; + hash ^= length; + buffer->packet.header.hash = hash; - BuildHeader(&status->txBuffer, status->txSerial++, length); uint16_t payloadLength = RoundUpTo4(length); if(payload) memcpy(status->txBuffer.packet.payload, payload, length); status->txBuffer.requestedLength = sizeof(struct usartpacketheader_t) + payloadLength + sizeof(uint32_t); // +4 for the hash status->txBuffer.busy = 1; status->txBuffer.error = 0; - Crc_Enqueue(status->crcStatus, &status->crcSlot, 0, status->txBuffer.packet.payload, length, + Crc_Enqueue(status->crcStatus, &status->crcSlot, 0, &status->txBuffer.packet, sizeof(status->txBuffer.packet.header) + payloadLength, NULL, (uint32_t*)(status->txBuffer.packet.payload + payloadLength)); while(waitForCrcQueue && Crc_IsSlotQueued(&status->crcSlot, 0)); - Pku_SetupTransmit(status->usart, status->txDmaInfo.dma, status->txDmaInfo.stream, &status->txBuffer.packet, status->txBuffer.requestedLength); + Pu_SetupTransmit(status->usart, status->txDmaInfo.dma, status->txDmaInfo.stream, &status->txBuffer.packet, status->txBuffer.requestedLength); StatsIncSent(&status->stats); return 0; } -void Pku_SetupReceive(struct usartstatus_t *status) +void MOCKABLE(Pu_SetupReceive)(struct usartstatus_t *status) { uint8_t packetIndex = status->activeRxBuf; @@ -141,12 +183,21 @@ void Pku_SetupReceive(struct usartstatus_t *status) } -void Pku_ConsumePacket(struct usartstatus_t *status, uint8_t packetIndex) +void MOCKABLE(Pu_SetupTransmit)(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length) +{ + LL_DMA_ConfigAddresses(dma, stream, (uint32_t)buffer, LL_USART_DMA_GetRegAddr(usart), LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + LL_DMA_SetDataLength(dma, stream, length); + LL_USART_EnableDMAReq_TX(usart); + LL_DMA_EnableStream(dma, stream); +} + + +void MOCKABLE(Pu_ConsumePacket)(struct usartstatus_t *status, uint8_t packetIndex) { struct usart_buffer_t *buffer = &status->rxBuffers[packetIndex]; if(buffer->busy) { if(buffer->error) - StatsIncPayloadError(&status->stats, buffer->errorInfo, *(uint32_t*) (buffer->packet.payload + RoundUpTo4(buffer->packet.header.payloadLength + 1))); + StatsIncPayloadError(&status->stats, buffer->errorInfo, *(uint32_t*) (buffer->packet.payload + RoundUpTo4(buffer->packet.header.payloadLength))); else { uint8_t diff = buffer->packet.header.serial - status->rxSerial; if(diff > 1) @@ -159,45 +210,24 @@ void Pku_ConsumePacket(struct usartstatus_t *status, uint8_t packetIndex) } -void Pku_SetupTransmit(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length) -{ - LL_DMA_ConfigAddresses(dma, stream, (uint32_t)buffer, LL_USART_DMA_GetRegAddr(usart), LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetDataLength(dma, stream, length); - LL_USART_EnableDMAReq_TX(usart); - LL_DMA_EnableStream(dma, stream); -} - -void RxCrcComputedCallback(void *callbackParm, uint32_t calculatedCrc, uint8_t success) -{ - struct usart_buffer_t *ub = (struct usart_buffer_t*) callbackParm; - if(!success) - ub->error = 1; - else if(*(uint32_t*) (ub->packet.payload + RoundUpTo4(ub->packet.header.payloadLength + 1)) == calculatedCrc) - ub->busy = 1; - else { - ub->error = ub->busy = 1; - ub->errorInfo = calculatedCrc; - } - if(ub->usartStatus->packetReceivedCallback) - ub->usartStatus->packetReceivedCallback(ub->usartStatus->packetReceivedCallbacParam, ub); -} - -void Pku_HandleRxDmaIrq(struct usartstatus_t *status) +void MOCKABLE(Pu_HandleRxDmaIrq)(struct usartstatus_t *status) { DIAG_INTERRUPT_IN(); StatsIncRcvd(&status->stats); if(*status->rxDmaInfo.isReg & status->rxDmaInfo.tcMask) { *status->rxDmaInfo.ifcReg = status->rxDmaInfo.tcMask; - if(CheckHeader(&status->rxBuffers[status->activeRxBuf].packet)) + if(Pu_CheckHeader(&status->rxBuffers[status->activeRxBuf].packet)) { Crc_Enqueue(status->crcStatus, &status->crcSlot, 1, - status->rxBuffers[status->activeRxBuf].packet.payload, - status->rxBuffers[status->activeRxBuf].packet.header.payloadLength +1, - RxCrcComputedCallback, &status->rxBuffers[status->activeRxBuf]); - else { + &status->rxBuffers[status->activeRxBuf].packet, + RoundUpTo4(status->rxBuffers[status->activeRxBuf].packet.header.payloadLength) + sizeof(struct usartpacketheader_t), + Pu_RxCrcComputedCallback, &status->rxBuffers[status->activeRxBuf]); + } else { StatsIncHdrError(&status->stats, *(uint32_t*)&status->rxBuffers[status->activeRxBuf].packet.header); status->rxBuffers[status->activeRxBuf].error = 1; } - } else if(*status->rxDmaInfo.isReg & status->rxDmaInfo.teMask) { + } + + if(*status->rxDmaInfo.isReg & status->rxDmaInfo.teMask) { *status->rxDmaInfo.ifcReg = status->rxDmaInfo.teMask; status->rxBuffers[status->activeRxBuf].error = 1; } @@ -207,11 +237,28 @@ void Pku_HandleRxDmaIrq(struct usartstatus_t *status) DIAG_RX_BUFFER_SWITCH(status->activeRxBuf); if(status->rxBuffers[status->activeRxBuf].busy) StatsIncOverrun(&status->stats); - Pku_SetupReceive(status); + Pu_SetupReceive(status); DIAG_INTERRUPT_OUT(); } -void Pku_HandleTxDmaIrq(struct usartstatus_t *status) + +void MOCKABLE(Pu_RxCrcComputedCallback)(void *callbackParm, uint32_t calculatedCrc, uint8_t success) +{ + struct usart_buffer_t *ub = (struct usart_buffer_t*) callbackParm; + if(!success) + ub->error = 1; + else if(*(uint32_t*) (ub->packet.payload + RoundUpTo4(ub->packet.header.payloadLength)) == calculatedCrc) + ub->busy = 1; + else { + ub->error = ub->busy = 1; + ub->errorInfo = calculatedCrc; + } + if(ub->usartStatus->packetReceivedCallback) + ub->usartStatus->packetReceivedCallback(ub->usartStatus->packetReceivedCallbackParam, ub); +} + + +void MOCKABLE(Pu_HandleTxDmaIrq)(struct usartstatus_t *status) { DIAG_INTERRUPT_IN(); if(*status->txDmaInfo.isReg & status->txDmaInfo.tcMask) { // DMA transfer complete @@ -219,9 +266,11 @@ void Pku_HandleTxDmaIrq(struct usartstatus_t *status) LL_USART_EnableIT_TC(status->usart); LL_DMA_DisableStream(status->txDmaInfo.dma, status->txDmaInfo.stream); } - else if(*status->txDmaInfo.isReg & status->txDmaInfo.teMask) { + if(*status->txDmaInfo.isReg & status->txDmaInfo.teMask) { *status->txDmaInfo.ifcReg = status->txDmaInfo.teMask; status->txBuffer.error = 1; + LL_USART_EnableIT_TC(status->usart); + LL_DMA_DisableStream(status->txDmaInfo.dma, status->txDmaInfo.stream); StatsIncDmaError(&status->stats); } if(*status->txDmaInfo.isReg & status->txDmaInfo.feMask) @@ -233,26 +282,29 @@ void Pku_HandleTxDmaIrq(struct usartstatus_t *status) DIAG_INTERRUPT_OUT(); } -void Pku_HandleUsartIrq(struct usartstatus_t *status) + +void MOCKABLE(Pu_HandleUsartIrq)(struct usartstatus_t *status) { DIAG_INTERRUPT_IN(); if(LL_USART_IsActiveFlag_IDLE(status->usart) && LL_USART_IsEnabledIT_IDLE(status->usart)) { // receiver idle LL_USART_ClearFlag_IDLE(status->usart); uint16_t rcvdLen = status->rxBuffers[status->activeRxBuf].requestedLength - LL_DMA_GetDataLength(status->rxDmaInfo.dma, status->rxDmaInfo.stream); if(rcvdLen >= sizeof(struct usartpacketheader_t)) { - if(CheckHeader(&status->rxBuffers[status->activeRxBuf].packet)) { - if(rcvdLen >= sizeof(struct usartpacketheader_t) + RoundUpTo4(status->rxBuffers[status->activeRxBuf].packet.header.payloadLength + 1) + sizeof(uint32_t)) + if(Pu_CheckHeader(&status->rxBuffers[status->activeRxBuf].packet)) { + if(rcvdLen >= sizeof(struct usartpacketheader_t) + RoundUpTo4(status->rxBuffers[status->activeRxBuf].packet.header.payloadLength) + sizeof(uint32_t)) LL_DMA_DisableStream(status->rxDmaInfo.dma, status->rxDmaInfo.stream); else StatsIncPremature_payload(&status->stats); } else { status->rxBuffers[status->activeRxBuf].error = 1; + status->rxBuffers[status->activeRxBuf].busy = 1; LL_DMA_DisableStream(status->rxDmaInfo.dma, status->rxDmaInfo.stream); } } else StatsIncPremature_hdr(&status->stats); } - else if(LL_USART_IsActiveFlag_TC(status->usart) && LL_USART_IsEnabledIT_TC(status->usart)) { // transmission complete + + if(LL_USART_IsActiveFlag_TC(status->usart) && LL_USART_IsEnabledIT_TC(status->usart)) { // transmission complete LL_USART_DisableIT_TC(status->usart); LL_USART_DisableDirectionTx(status->usart); // enforcing an idle frame LL_USART_EnableDirectionTx(status->usart); diff --git a/packetusart.h b/packetusart.h index fc168ea..c198865 100644 --- a/packetusart.h +++ b/packetusart.h @@ -7,10 +7,10 @@ #ifndef USART_HANDLER_H_ #define USART_HANDLER_H_ -#include #include - +#include #include "f4ll_c/dmahelper.h" +#include #ifdef __cplusplus extern "C" { @@ -18,25 +18,43 @@ extern "C" { struct usart_buffer_t; struct usartstatus_t; +struct usartpacket_t; typedef void (*pku_packetreceivedcallback_t)(void *userParam, struct usart_buffer_t *buffer); -void Pku_Init( +void Pu_Init( struct usartstatus_t *st, USART_TypeDef *usart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx, struct crcstatus_t *crcStatus, pku_packetreceivedcallback_t packetReceivedCallback, void * packetReceivedCallbackParam); -uint8_t* Pku_GetTxBuffer(struct usartstatus_t *status); +uint8_t* Pu_GetTxBuffer(struct usartstatus_t *status); -uint8_t Pku_Post(struct usartstatus_t *status, uint8_t const *payload, uint16_t length, struct crcstatus_t *crcStatus, uint8_t waitForCrcQueue); -void Pku_SetupReceive(struct usartstatus_t *status); -void Pku_SetupTransmit(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length); -void Pku_ConsumePacket(struct usartstatus_t *status, uint8_t packetIndex); +uint8_t Pu_Post(struct usartstatus_t *status, uint8_t const *payload, uint8_t length, struct crcstatus_t *crcStatus, uint8_t waitForCrcQueue); +void Pu_SetupReceive(struct usartstatus_t *status); +void Pu_SetupTransmit(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length); +void Pu_ConsumePacket(struct usartstatus_t *status, uint8_t packetIndex); -void Pku_HandleRxDmaIrq(struct usartstatus_t *status); -void Pku_HandleTxDmaIrq(struct usartstatus_t *status); -void Pku_HandleUsartIrq(struct usartstatus_t *status); +void Pu_HandleRxDmaIrq(struct usartstatus_t *status); +void Pu_HandleTxDmaIrq(struct usartstatus_t *status); +void Pu_HandleUsartIrq(struct usartstatus_t *status); + +// !!!Private!!! exposed only to make unit testing possible +void Pu_RxCrcComputedCallback(void *callbackParm, uint32_t calculatedCrc, uint8_t success); +uint8_t Pu_CheckHeader(struct usartpacket_t *packet); + +DECLARE_MOCK(Pu_Init); +DECLARE_MOCK(Pu_GetTxBuffer); +DECLARE_MOCK(Pu_Post); +DECLARE_MOCK(Pu_SetupReceive); +DECLARE_MOCK(Pu_SetupTransmit); +DECLARE_MOCK(Pu_ConsumePacket); +DECLARE_MOCK(Pu_ConsumePacket); +DECLARE_MOCK(Pu_HandleRxDmaIrq); +DECLARE_MOCK(Pu_HandleTxDmaIrq); +DECLARE_MOCK(Pu_HandleUsartIrq); +DECLARE_MOCK(Pu_RxCrcComputedCallback); +DECLARE_MOCK(Pu_CheckHeader); /****************************************************************************************** * @@ -94,54 +112,11 @@ struct usartstatus_t { struct usart_stats stats; uint8_t activeRxBuf; pku_packetreceivedcallback_t packetReceivedCallback; - void *packetReceivedCallbacParam; + void *packetReceivedCallbackParam; struct usart_buffer_t txBuffer; struct usart_buffer_t rxBuffers[2]; }; -#ifndef USART_STATS_DISABLED -static inline void StatsIncOverrun(struct usart_stats *s) { - ++s->overrun; -} -static inline void StatsIncHdrError(struct usart_stats *s, uint32_t hdr) { - ++s->hdrError; - s->lastErrHdr = hdr; -} -static inline void StatsIncPayloadError(struct usart_stats *s, uint32_t pep1, uint32_t pep2) { - ++s->payloadErrror; - s->pep1 = pep1; - s->pep2 = pep2; -} -static inline void StatsIncDmaError(struct usart_stats *s) { - ++s->dmaError; -} -static inline void StatsIncRcvd(struct usart_stats *s) { - ++s->rcvd; -} -static inline void StatsIncPremature_hdr(struct usart_stats *s) { - ++s->premature_hdr; -} -static inline void StatsIncPremature_payload(struct usart_stats *s) { - ++s->premature_payload; -} -static inline void StatsIncSent(struct usart_stats *s) { - ++s->sent; -} -static inline void StatsAddSkiped(struct usart_stats *s, uint8_t cnt) { - s->skiped += s->rcvd > 2 ? cnt : 0; -} - -#else // USART_STATS_DISABLED -#define StatsIncOverrun(x) -#define StatsIncHdrError(x,y) -#define StatsIncPayloadError(x,y,z) -#define StatsIncDmaError(x) -#define StatsIncRcvd(x) -#define StatsIncPremature_hdr(x) -#define StatsIncPremature_payload(x) -#define StatsIncSent(x) -#define StatsAddSkiped(x) -#endif // USART_STATS_DISABLED #ifdef __cplusplus }