From c4c6ac8bb36a31593e1fba0d4fed84345fe6112b Mon Sep 17 00:00:00 2001 From: Attila BODY Date: Mon, 13 Jan 2020 09:47:52 +0100 Subject: [PATCH] Changes requested during the initial review --- .cproject | 64 +++++++++++++++++-- components/f4ll_c/inc/f4ll_c/crcscheduler.h | 32 +++++----- components/f4ll_c/inc/f4ll_c/packetusart.h | 4 +- components/f4ll_c/src/crcscheduler.c | 30 ++++----- components/f4ll_c/src/packetusart.c | 4 +- .../f4ll_c/test/crcscheduler_unittests.cpp | 63 ++++++++++-------- .../f4ll_c/test/packetusart_unittest.cpp | 62 +++++++++++++----- tests.mk | 16 ++--- 8 files changed, 186 insertions(+), 89 deletions(-) diff --git a/.cproject b/.cproject index 5e0434a..cacde4e 100644 --- a/.cproject +++ b/.cproject @@ -46,10 +46,11 @@ - - + + + @@ -77,13 +78,39 @@ + + + + - + @@ -135,8 +162,9 @@ - + + @@ -164,13 +192,39 @@ + + + + - + diff --git a/components/f4ll_c/inc/f4ll_c/crcscheduler.h b/components/f4ll_c/inc/f4ll_c/crcscheduler.h index ce1a4dc..b8a7359 100644 --- a/components/f4ll_c/inc/f4ll_c/crcscheduler.h +++ b/components/f4ll_c/inc/f4ll_c/crcscheduler.h @@ -21,42 +21,42 @@ extern "C" { #endif -struct crcslottask_t { +struct crctask_t { void * volatile address; uint16_t wordCount; void (*callback)(void*, uint32_t, uint8_t); void *callbackParam; }; -struct crcslotlistitem_t { +struct crcslot_t { uint16_t count; - struct crcslotlistitem_t *next; - struct crcslottask_t *tasks; + struct crcslot_t *next; + struct crctask_t *tasks; }; struct crcstatus_t { CRC_TypeDef *crcUnit; struct dmainfo_t dmaInfo; - struct crcslotlistitem_t *activeSlot; + struct crcslot_t *activeSlot; uint8_t activeTask; - struct crcslotlistitem_t *firstSlot; + struct crcslot_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); +uint8_t Crc_GetActiveTask(struct crcslot_t **slot_out, struct crcstatus_t volatile *status); -uint8_t Crc_IsSlotQueued(struct crcslotlistitem_t *slot, uint8_t task); +uint8_t Crc_IsTaskQueued(struct crcslot_t *slot, uint8_t task); -uint8_t Crc_IsSlotBusy(struct crcslotlistitem_t *slot, uint8_t task); +uint8_t Crc_IsTaskBusy(struct crcslot_t *slot, uint8_t task); -void Crc_WaitResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task); +void Crc_WaitResults(struct crcstatus_t *status, struct crcslot_t *slot, uint8_t task); -void Crc_AttachTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount); +void Crc_AttachTasks(struct crcstatus_t *status, struct crcslot_t *slot, struct crctask_t *tasks, uint8_t taskCount); -uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, +uint8_t Crc_Enqueue(struct crcstatus_t *status, struct crcslot_t *slot, uint8_t task, 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); +uint32_t Crc_Compute(struct crcstatus_t *status, struct crcslot_t *slot, uint8_t task, void *address, uint16_t len); void Crc_HandleDmaIrq(struct crcstatus_t *status); // !!!PRIVATE!!! exposed only to make mocking possible @@ -66,10 +66,10 @@ 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_IsTaskQueued); +DECLARE_MOCK(Crc_IsTaskBusy); DECLARE_MOCK(Crc_WaitResults); -DECLARE_MOCK(Crc_AttachTask); +DECLARE_MOCK(Crc_AttachTasks); DECLARE_MOCK(Crc_Enqueue); DECLARE_MOCK(Crc_Compute); DECLARE_MOCK(Crc_HandleDmaIrq); diff --git a/components/f4ll_c/inc/f4ll_c/packetusart.h b/components/f4ll_c/inc/f4ll_c/packetusart.h index c198865..b6a4038 100644 --- a/components/f4ll_c/inc/f4ll_c/packetusart.h +++ b/components/f4ll_c/inc/f4ll_c/packetusart.h @@ -104,8 +104,8 @@ struct usartstatus_t { struct dmainfo_t rxDmaInfo; struct dmainfo_t txDmaInfo; struct crcstatus_t *crcStatus; - struct crcslotlistitem_t crcSlot; - struct crcslottask_t crcTasks[2]; + struct crcslot_t crcSlot; + struct crctask_t crcTasks[2]; uint8_t rxSerial; uint8_t txSerial; diff --git a/components/f4ll_c/src/crcscheduler.c b/components/f4ll_c/src/crcscheduler.c index 403f3ec..1ae6be7 100644 --- a/components/f4ll_c/src/crcscheduler.c +++ b/components/f4ll_c/src/crcscheduler.c @@ -46,7 +46,7 @@ void MOCKABLE(Crc_InitStatus)(struct crcstatus_t *st, CRC_TypeDef *crcUnit, DMA_ } -void MOCKABLE(Crc_AttachTask)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount) +void MOCKABLE(Crc_AttachTasks)(struct crcstatus_t *status, struct crcslot_t *slot, struct crctask_t *tasks, uint8_t taskCount) { slot->count = taskCount; slot->tasks = tasks; @@ -60,7 +60,7 @@ void MOCKABLE(Crc_AttachTask)(struct crcstatus_t *status, struct crcslotlistitem } -uint8_t MOCKABLE(Crc_GetActiveTask)(struct crcslotlistitem_t **slot_out, struct crcstatus_t volatile *status) +uint8_t MOCKABLE(Crc_GetActiveTask)(struct crcslot_t **slot_out, struct crcstatus_t volatile *status) { uint8_t ret; @@ -69,36 +69,36 @@ uint8_t MOCKABLE(Crc_GetActiveTask)(struct crcslotlistitem_t **slot_out, struct __disable_irq(); ret = status->activeTask; if(slot_out) - *slot_out = (struct crcslotlistitem_t *) status->activeSlot; + *slot_out = (struct crcslot_t *) status->activeSlot; __set_PRIMASK(prim); return ret; } -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_IsTaskQueued)(struct crcslot_t *slot, uint8_t task) { + return ((struct crctask_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]; +uint8_t MOCKABLE(Crc_IsTaskBusy)(struct crcslot_t *slot, uint8_t task) { + struct crctask_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)); +void MOCKABLE(Crc_WaitResults)(struct crcstatus_t *status, struct crcslot_t *slot, uint8_t task) { + while(Crc_IsTaskBusy(slot, task)); } -uint8_t MOCKABLE(Crc_Enqueue)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, +uint8_t MOCKABLE(Crc_Enqueue)(struct crcstatus_t *status, struct crcslot_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; struct crcstatus_t volatile *st = status; - while(Crc_IsSlotBusy(slot, task)); + while(Crc_IsTaskBusy(slot, task)); __disable_irq(); need_start = (st->activeSlot == NULL); slot->tasks[task].address = need_start ? NULL : address; @@ -123,11 +123,11 @@ uint8_t MOCKABLE(Crc_Enqueue)(struct crcstatus_t *status, struct crcslotlistitem } -uint32_t MOCKABLE(Crc_Compute)(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, void *address, uint16_t len) +uint32_t MOCKABLE(Crc_Compute)(struct crcstatus_t *status, struct crcslot_t *slot, uint8_t task, void *address, uint16_t len) { uint32_t result; Crc_Enqueue(status, slot, task, address, len, NULL, &result); - while((struct crcslotlistitem_t volatile *)slot->tasks[task].callbackParam); + while((struct crcslot_t volatile *)slot->tasks[task].callbackParam); return result; } @@ -139,7 +139,7 @@ void MOCKABLE(Crc_StartNextTask)(struct crcstatus_t *status) uint8_t index = 0; do { - struct crcslotlistitem_t *slot = status->firstSlot; + struct crcslot_t *slot = status->firstSlot; moreTasks = 0; while(slot) { if(index < slot->count) { @@ -178,7 +178,7 @@ void MOCKABLE(Crc_HandleDmaIrq)(struct crcstatus_t *status) *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]; + struct crctask_t *tsk = &status->activeSlot->tasks[status->activeTask]; if(tsk->callback) tsk->callback(tsk->callbackParam, status->crcUnit->DR, success); else if(tsk->callbackParam) diff --git a/components/f4ll_c/src/packetusart.c b/components/f4ll_c/src/packetusart.c index 4aca014..764b670 100644 --- a/components/f4ll_c/src/packetusart.c +++ b/components/f4ll_c/src/packetusart.c @@ -112,7 +112,7 @@ void MOCKABLE(Pu_Init)( st->txSerial = 0; st->activeRxBuf = 0; st->crcStatus = crcStatus; - Crc_AttachTask(crcStatus, &st->crcSlot, st->crcTasks, 2); + Crc_AttachTasks(crcStatus, &st->crcSlot, st->crcTasks, 2); memset(&st->stats, 0, sizeof(st->stats)); *Dma_GetIfcReg(dma, stream_rx) = @@ -161,7 +161,7 @@ uint8_t MOCKABLE(Pu_Post)(struct usartstatus_t *status, uint8_t const *payload, status->txBuffer.error = 0; 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)); + while(waitForCrcQueue && Crc_IsTaskQueued(&status->crcSlot, 0)); Pu_SetupTransmit(status->usart, status->txDmaInfo.dma, status->txDmaInfo.stream, &status->txBuffer.packet, status->txBuffer.requestedLength); StatsIncSent(&status->stats); diff --git a/components/f4ll_c/test/crcscheduler_unittests.cpp b/components/f4ll_c/test/crcscheduler_unittests.cpp index 4999008..a4cf497 100644 --- a/components/f4ll_c/test/crcscheduler_unittests.cpp +++ b/components/f4ll_c/test/crcscheduler_unittests.cpp @@ -25,8 +25,8 @@ DMA_TypeDef * DMA2 __attribute__((weak)); static DMA_TypeDef dma1, dma2; static crcstatus_t crcStatus; -static crcslotlistitem_t slot1, slot2; -static crcslottask_t tasks1[2], tasks2[2]; +static crcslot_t slot1, slot2; +static crctask_t tasks1[2], tasks2[2]; static CRC_TypeDef fakeCrc; static DMA_TypeDef *expectedDma; @@ -49,7 +49,7 @@ DEFINE_MOCK(__set_PRIMASK, mock, uint32_t primask) { LEAVE_MOCK; } -DEFINE_MOCK_VAR(crcslotlistitem_t *, __disable_irq, mock, compare); +DEFINE_MOCK_VAR(crcslot_t *, __disable_irq, mock, compare); DEFINE_MOCK(__disable_irq, mock) { if(!MOCK_VAR(__disable_irq, mock, callcount)) { EXPECT_EQ(crcStatus.firstSlot, MOCK_VAR(__disable_irq, mock, compare)); @@ -157,7 +157,7 @@ TEST(CrcScheduler, AttachTask_single) DMA2 = &dma2; Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); - Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + Crc_AttachTasks(&crcStatus, &slot1, tasks1, 2); EXPECT_EQ(MOCK_VAR(__get_PRIMASK, mock, callcount), 1); EXPECT_EQ(MOCK_VAR(__set_PRIMASK, mock, callcount), 1); @@ -168,6 +168,7 @@ TEST(CrcScheduler, AttachTask_single) EXPECT_EQ(crcStatus.activeSlot, nullptr); } +// Are tasks attached in the expected order internally TEST(CrcScheduler, AttachTask_multiple) { ACTIVATE_MOCK_RV(__get_PRIMASK, mock, 1); @@ -178,9 +179,9 @@ TEST(CrcScheduler, AttachTask_multiple) DMA2 = &dma2; Crc_InitStatus(&crcStatus, NULL, DMA2, LL_DMA_STREAM_4); - Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + Crc_AttachTasks(&crcStatus, &slot1, tasks1, 2); MOCK_STORE(__disable_irq, mock, compare, &slot1); - Crc_AttachTask(&crcStatus, &slot2, tasks2, 2); + Crc_AttachTasks(&crcStatus, &slot2, tasks2, 2); EXPECT_EQ(__get_PRIMASK_mock_callcount, 2); EXPECT_EQ(__set_PRIMASK_mock_callcount, 2); @@ -192,6 +193,7 @@ TEST(CrcScheduler, AttachTask_multiple) EXPECT_EQ(crcStatus.activeSlot, nullptr); } +// No blocking should occur if the the task is not busy TEST(CrcScheduler, Enqueue_nowait) { uint32_t fakeCrcResult; @@ -204,7 +206,7 @@ TEST(CrcScheduler, Enqueue_nowait) memset(&fakeCrc, 0, sizeof(fakeCrc)); Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); - Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + Crc_AttachTasks(&crcStatus, &slot1, tasks1, 2); expectedLength = 2; ACTIVATE_MOCK(LL_DMA_SetM2MSrcAddress, mock); @@ -233,6 +235,9 @@ TEST(CrcScheduler, Enqueue_nowait) EXPECT_EQ(MOCK_VAR(LL_DMA_EnableStream, mock, callcount), 1); } +// When trying to enqueue for a busy task it should blok firs +// then when the previously blocked task finishes it should +// enqueue the new one TEST(CrcScheduler, Enqueue_shouldblockthencontinue) { uint8_t testData[] = "qwerty"; @@ -242,7 +247,7 @@ TEST(CrcScheduler, Enqueue_shouldblockthencontinue) memset(&fakeCrc, 0, sizeof(fakeCrc)); Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); - Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + Crc_AttachTasks(&crcStatus, &slot1, tasks1, 2); Crc_Enqueue(&crcStatus, &slot1, 0, testData, sizeof(testData), FakeCallback_1, &fakeCrcResult); // black magic to test if the function blocks (at least for 100ms) @@ -265,6 +270,7 @@ TEST(CrcScheduler, Enqueue_shouldblockthencontinue) pthread_cancel(th); } +// StartNextTask should start the scheduled tasks in predefined order TEST(CrcScheduler, Crc_StartNextTask) { uint8_t testData[] = "qwerty"; @@ -275,8 +281,8 @@ TEST(CrcScheduler, Crc_StartNextTask) memset(&fakeCrc, 0, sizeof(fakeCrc)); Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); - Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); - Crc_AttachTask(&crcStatus, &slot2, tasks2, 2); + Crc_AttachTasks(&crcStatus, &slot1, tasks1, 2); + Crc_AttachTasks(&crcStatus, &slot2, tasks2, 2); Crc_Enqueue(&crcStatus, &slot1, 0, testData, sizeof(testData), FakeCallback_1, &fakeCrcResult1); Crc_Enqueue(&crcStatus, &slot1, 1, testData, sizeof(testData), FakeCallback_2, &fakeCrcResult2); Crc_Enqueue(&crcStatus, &slot2, 0, testData, sizeof(testData), FakeCallback_3, &fakeCrcResult3); @@ -314,6 +320,8 @@ TEST(CrcScheduler, Crc_StartNextTask) EXPECT_EQ(LL_DMA_EnableStream_mock_callcount, 2); } +// HandleDmaIrq should start the next scheduled task or +// disable the CRC DMA engine if there is no other task scheduled. TEST(CrcScheduler, HandleDmaIrq_callback) { uint8_t testData[] = "qwerty"; @@ -327,8 +335,8 @@ TEST(CrcScheduler, HandleDmaIrq_callback) fakeCrc.DR = 0xa5a55a5a; Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); - Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); - Crc_AttachTask(&crcStatus, &slot2, tasks2, 2); + Crc_AttachTasks(&crcStatus, &slot1, tasks1, 2); + Crc_AttachTasks(&crcStatus, &slot2, tasks2, 2); Crc_Enqueue(&crcStatus, &slot1, 1, testData, sizeof(testData), FakeCallbackCheck, &FakeCustomData1); // we need to set this up here to check if HandleDmaIrq calls Crc_StartNextTask or not; Crc_Enqueue(&crcStatus, &slot2, 0, testData, sizeof(testData), FakeCallbackCheck, &FakeCustomData2); @@ -367,46 +375,51 @@ TEST(CrcScheduler, HandleDmaIrq_callback) EXPECT_EQ(LL_DMA_DisableStream_mock_callcount, 2); } -TEST(CrcScheduler, IsSlotQueued) +// Crc_StartNextTask starts executing the next task and removes it from the queue +// Test if IsTaskQueued reflects this behaviour correctly +TEST(CrcScheduler, IsTaskQueued) { uint8_t testData[] = "qwerty"; uint32_t FakeCustomData1; Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); - Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + Crc_AttachTasks(&crcStatus, &slot1, tasks1, 2); Crc_Enqueue(&crcStatus, &slot1, 0, testData, sizeof(testData), FakeCallback_1, &FakeCustomData1); Crc_Enqueue(&crcStatus, &slot1, 1, testData, sizeof(testData), FakeCallback_1, &FakeCustomData1); - EXPECT_EQ(Crc_IsSlotQueued(&slot1, 0), 0); - EXPECT_NE(Crc_IsSlotQueued(&slot1, 1), 0); + EXPECT_EQ(Crc_IsTaskQueued(&slot1, 0), 0); + EXPECT_NE(Crc_IsTaskQueued(&slot1, 1), 0); Crc_StartNextTask(&crcStatus); - EXPECT_EQ(Crc_IsSlotQueued(&slot1, 1), 0); + EXPECT_EQ(Crc_IsTaskQueued(&slot1, 1), 0); } -TEST(CrcScheduler, IsSlotBusy) +// Crc_HandleDmaIrq completes the active task and start executing the next (by calling StartNextTask) +// Crc_IsTaskBusy should reflect these changes +TEST(CrcScheduler, IsTaskBusy) { uint8_t testData[] = "qwerty"; uint32_t FakeCustomData1; Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); - Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + Crc_AttachTasks(&crcStatus, &slot1, tasks1, 2); Crc_Enqueue(&crcStatus, &slot1, 0, testData, sizeof(testData), FakeCallback_1, &FakeCustomData1); Crc_Enqueue(&crcStatus, &slot1, 1, testData, sizeof(testData), FakeCallback_1, &FakeCustomData1); - EXPECT_NE(Crc_IsSlotBusy(&slot1, 0), 0); - EXPECT_NE(Crc_IsSlotBusy(&slot1, 1), 0); + EXPECT_NE(Crc_IsTaskBusy(&slot1, 0), 0); + EXPECT_NE(Crc_IsTaskBusy(&slot1, 1), 0); DMA2->HISR |= DMA_HISR_TCIF4; Crc_HandleDmaIrq(&crcStatus); - EXPECT_EQ(Crc_IsSlotBusy(&slot1, 0), 0); - EXPECT_NE(Crc_IsSlotBusy(&slot1, 1), 0); + EXPECT_EQ(Crc_IsTaskBusy(&slot1, 0), 0); + EXPECT_NE(Crc_IsTaskBusy(&slot1, 1), 0); DMA2->HISR |= DMA_HISR_TCIF4; Crc_HandleDmaIrq(&crcStatus); - EXPECT_EQ(Crc_IsSlotBusy(&slot1, 0), 0); - EXPECT_EQ(Crc_IsSlotBusy(&slot1, 1), 0); + EXPECT_EQ(Crc_IsTaskBusy(&slot1, 0), 0); + EXPECT_EQ(Crc_IsTaskBusy(&slot1, 1), 0); } + diff --git a/components/f4ll_c/test/packetusart_unittest.cpp b/components/f4ll_c/test/packetusart_unittest.cpp index 3d1e76e..0a13bc9 100644 --- a/components/f4ll_c/test/packetusart_unittest.cpp +++ b/components/f4ll_c/test/packetusart_unittest.cpp @@ -39,8 +39,8 @@ uint8_t testData[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //static struct usartstatus_t * expectedUsartStatus; static uint32_t expectedStreams[2] = { 0,7 }; struct crcstatus_t *expectedCrcStatus; -struct crcslotlistitem_t *expectedCrcSlotListItem; -struct crcslottask_t *expectedTasks; +struct crcslot_t *expectedCrcSlotListItem; +struct crctask_t *expectedTasks; uint8_t expectedTaskCount; uint32_t expectedCrcLength; uint32_t expectedLength; @@ -55,6 +55,8 @@ uint32_t expectedDirection; uint32_t fakePacketReceivedCallbackParam; +// this isn't a real mov but we use the mockinginfrastructure +// to automate administration (call count, etc) DEFINE_MOCK(FakePacketReceivedCallback, mock, void* userParam, struct usart_buffer_t *buffer) { EXPECT_EQ((void*)&fakePacketReceivedCallbackParam, userParam); @@ -67,13 +69,13 @@ DEFINE_MOCK(Dma_Init, mock, struct dmainfo_t* dmaInfo, DMA_TypeDef *dma, uint32_ LEAVE_MOCK } -DEFINE_MOCK(Crc_AttachTask, mock, struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount) +DEFINE_MOCK(Crc_AttachTasks, mock, struct crcstatus_t *status, struct crcslot_t *slot, struct crctask_t *tasks, uint8_t taskCount) { EXPECT_EQ(status, expectedCrcStatus); EXPECT_EQ(slot, expectedCrcSlotListItem); EXPECT_EQ(tasks, expectedTasks); EXPECT_EQ(taskCount, expectedTaskCount); - Crc_AttachTask__(status, slot, tasks, taskCount); + Crc_AttachTasks__(status, slot, tasks, taskCount); LEAVE_MOCK } @@ -213,7 +215,7 @@ DEFINE_MOCK(LL_USART_ClearFlag_ORE, mock, USART_TypeDef *usart) LEAVE_MOCK } -DEFINE_MOCK_RET(uint8_t, Crc_Enqueue, mock, struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, +DEFINE_MOCK_RET(uint8_t, Crc_Enqueue, mock, struct crcstatus_t *status, struct crcslot_t *slot, uint8_t task, void *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam) { EXPECT_EQ(expectedCrcLength, len); @@ -221,9 +223,9 @@ DEFINE_MOCK_RET(uint8_t, Crc_Enqueue, mock, struct crcstatus_t *status, struct c RETURN_MOCK_PREDEF(Crc_Enqueue, mock); } -DEFINE_MOCK_RET(uint8_t, Crc_IsSlotQueued, mock, struct crcslotlistitem_t *slot, uint8_t task) +DEFINE_MOCK_RET(uint8_t, Crc_IsTaskQueued, mock, struct crcslot_t *slot, uint8_t task) { - RETURN_MOCK_PREDEF(Crc_IsSlotQueued, mock); + RETURN_MOCK_PREDEF(Crc_IsTaskQueued, mock); } DEFINE_MOCK(Pu_SetupTransmit, mock, USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length) @@ -263,7 +265,7 @@ struct PacketUsart : public ::testing::Test { TEST_F(PacketUsart, Init) { ACTIVATE_MOCK(Dma_Init, mock); - ACTIVATE_MOCK(Crc_AttachTask, mock); + ACTIVATE_MOCK(Crc_AttachTasks, mock); ACTIVATE_MOCK(LL_DMA_EnableIT_TC, init); ACTIVATE_MOCK(LL_DMA_EnableIT_TE, init); ACTIVATE_MOCK(LL_USART_EnableIT_IDLE, mock); @@ -303,6 +305,7 @@ TEST_F(PacketUsart, GetTxBuffer) EXPECT_EQ(Pu_GetTxBuffer(&usartStatus), (unsigned char*)&usartStatus.txBuffer.packet.payload); } +// SetupTransmit should set all engines (DMA, USART) up properly for starting the transmission TEST_F(PacketUsart, SetupTransmit) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); @@ -319,8 +322,15 @@ TEST_F(PacketUsart, SetupTransmit) ACTIVATE_MOCK_RV(LL_USART_DMA_GetRegAddr, mock, expectedDstAddress); Pu_SetupTransmit(&fakeUsart, &fakeDma1, 7, testData, sizeof(testData)); + + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_ConfigAddresses, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_SetDataLength, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_EnableStream, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableDMAReq_TX, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DMA_GetRegAddr, mock), 1); } +// Testing Pu_Post, not waiting for the crc scheduler to start processing our block TEST_F(PacketUsart, Post_copy_nowait) { struct usartpacketheader_t expectedHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; @@ -333,7 +343,7 @@ TEST_F(PacketUsart, Post_copy_nowait) ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); ACTIVATE_MOCK(Pu_SetupTransmit, mock); - ACTIVATE_MOCK_RV(Crc_IsSlotQueued, mock, 1); + ACTIVATE_MOCK_RV(Crc_IsTaskQueued, mock, 1); Pu_Post(&usartStatus, testData, sizeof(testData), &crcStatus, false); @@ -342,9 +352,10 @@ TEST_F(PacketUsart, Post_copy_nowait) EXPECT_EQ(memcmp(&usartStatus.txBuffer.packet.header, &expectedHeader, sizeof(expectedHeader)), 0); EXPECT_EQ(MOCK_CALLCOUNT(Crc_Enqueue, mock), 1); EXPECT_EQ(MOCK_CALLCOUNT(Pu_SetupTransmit, mock), 1); - EXPECT_EQ(MOCK_CALLCOUNT(Crc_IsSlotQueued, mock), 0); + EXPECT_EQ(MOCK_CALLCOUNT(Crc_IsTaskQueued, mock), 0); } +// Posting with free CRC engine (will execute our block immediately) TEST_F(PacketUsart, Post_copy_wait_nodelay) { expectedCrcLength = sizeof(usartStatus.txBuffer.packet.header) + 12; @@ -356,13 +367,14 @@ TEST_F(PacketUsart, Post_copy_wait_nodelay) ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); ACTIVATE_MOCK(Pu_SetupTransmit, mock); - ACTIVATE_MOCK_RV(Crc_IsSlotQueued, mock, 0); + ACTIVATE_MOCK_RV(Crc_IsTaskQueued, mock, 0); Pu_Post(&usartStatus, testData, sizeof(testData), &crcStatus, true); - EXPECT_EQ(MOCK_CALLCOUNT(Crc_IsSlotQueued, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(Crc_IsTaskQueued, mock), 1); } +// Posting with with busy CRC engine should block our call TEST_F(PacketUsart, Post_copy_wait_delay) { expectedCrcLength = sizeof(usartStatus.txBuffer.packet.header) + 12; @@ -374,7 +386,7 @@ TEST_F(PacketUsart, Post_copy_wait_delay) ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); ACTIVATE_MOCK(Pu_SetupTransmit, mock); - ACTIVATE_MOCK_RV(Crc_IsSlotQueued, mock, 1); + ACTIVATE_MOCK_RV(Crc_IsTaskQueued, mock, 1); // black magic to test if the function blocks (at least for 100ms) std::promise promiseFinished; @@ -388,13 +400,14 @@ TEST_F(PacketUsart, Post_copy_wait_delay) th = t.native_handle(); t.detach(); EXPECT_EQ(futureResult.wait_for(std::chrono::milliseconds(100)), std::future_status::timeout); - Crc_IsSlotQueued_mock_retval = 0; + Crc_IsTaskQueued_mock_retval = 0; auto waitResult(futureResult.wait_for(std::chrono::milliseconds(100))); EXPECT_NE(waitResult, std::future_status::timeout); if(waitResult == std::future_status::timeout) pthread_cancel(th); } +// HandleTxDmaIrq_tc should enable USART TC interrupt and disable DMA stream TEST_F(PacketUsart, HandleTxDmaIrq_tc) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); @@ -414,6 +427,7 @@ TEST_F(PacketUsart, HandleTxDmaIrq_tc) EXPECT_EQ(fakeDma1.HIFCR, DMA_HIFCR_CTCIF7); } +// HandleTxDmaIrq_te should enable USART TC interrupt disable DMA stream and set the error flag TEST_F(PacketUsart, HandleTxDmaIrq_te) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); @@ -431,6 +445,8 @@ TEST_F(PacketUsart, HandleTxDmaIrq_te) EXPECT_EQ(usartStatus.txBuffer.error, 1); } +// HandleUsartIrq_tc should disable USART TC interrupt, pulse TX direction enabled to enforce an idle frame +// and mark the tx buffer as free TEST_F(PacketUsart, HandleUsartIrq_tc) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); @@ -452,7 +468,8 @@ TEST_F(PacketUsart, HandleUsartIrq_tc) EXPECT_EQ(usartStatus.txBuffer.busy, 0); } -TEST_F(PacketUsart, setupReceive) +// SetupReceive must set USART and DMA engine up for reception +TEST_F(PacketUsart, SetupReceive) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); expectedStream = 0; @@ -479,6 +496,7 @@ TEST_F(PacketUsart, setupReceive) EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DMA_GetRegAddr, mock), 1); } +// Test HandleUsartIrq with a received packet having a correct header checksum TEST_F(PacketUsart, HandleUsartIrq_idle_fullpacket_hdr_ok) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; @@ -510,6 +528,7 @@ TEST_F(PacketUsart, HandleUsartIrq_idle_fullpacket_hdr_ok) EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); } +// Test HandleUsartIrq with a received packet having a incorrect header checksum TEST_F(PacketUsart, HandleUsartIrq_idle_fullpacket_hdr_bad) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; @@ -541,6 +560,7 @@ TEST_F(PacketUsart, HandleUsartIrq_idle_fullpacket_hdr_bad) EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); } +// Packet reception should continue if the packet is not fully received yet TEST_F(PacketUsart, HandleUsartIrq_idle_tooshort) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; @@ -572,6 +592,7 @@ TEST_F(PacketUsart, HandleUsartIrq_idle_tooshort) EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); } +// Packet reception should continue if the packet is shorter than the packet header TEST_F(PacketUsart, HandleUsartIrq_idle_tooshortforheadercheck) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; @@ -603,6 +624,8 @@ TEST_F(PacketUsart, HandleUsartIrq_idle_tooshortforheadercheck) EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); } +// Reception DMA engine transfer complete interrupt is the real verification point of the packet +// verify that the packet is really checked TEST_F(PacketUsart, HandleRxDmaIrq_tc_hdrok) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; @@ -623,11 +646,15 @@ TEST_F(PacketUsart, HandleRxDmaIrq_tc_hdrok) Pu_HandleRxDmaIrq(&usartStatus); + EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); + EXPECT_EQ(MOCK_CALLCOUNT(Crc_Enqueue, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(Pu_SetupReceive, mock), 1); EXPECT_EQ(fakeDma1.LIFCR, DMA_LIFCR_CTCIF0); EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); } +// In case of the header fails on the end of packet reception error flag should be set TEST_F(PacketUsart, HandleRxDmaIrq_tc_hdrfail) { struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; @@ -655,6 +682,7 @@ TEST_F(PacketUsart, HandleRxDmaIrq_tc_hdrfail) EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); } +// successfull CRC32 check, CRC32 match, callback should be called, busy flag should be set TEST_F(PacketUsart, HandleRxCrcComputedCallback_success_match) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); @@ -673,6 +701,8 @@ TEST_F(PacketUsart, HandleRxCrcComputedCallback_success_match) EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); } +// successfull CRC32 check, CRC32 mismatch, callback should be called, +// both busy and error flag should be set TEST_F(PacketUsart, HandleRxCrcComputedCallback_success_mismatch) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); @@ -691,6 +721,8 @@ TEST_F(PacketUsart, HandleRxCrcComputedCallback_success_mismatch) EXPECT_NE(usartStatus.rxBuffers[0].error, 0); } +//failed CRC32 check, callback should be called, +// both busy and error flag should be set TEST_F(PacketUsart, HandleRxCrcComputedCallback_failure) { Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); diff --git a/tests.mk b/tests.mk index a5d8244..a50c0e0 100644 --- a/tests.mk +++ b/tests.mk @@ -1,15 +1,7 @@ ########################################################################################################################## -# File automatically-generated by tool: [projectgenerator] version: [3.5.2] date: [Tue Dec 10 15:21:03 CET 2019] +# Main makefile for unit tests ########################################################################################################################## -# ------------------------------------------------ -# Generic Makefile (based on gcc) -# -# ChangeLog : -# 2017-02-10 - Several enhancements + project update mode -# 2015-07-22 - first version -# ------------------------------------------------ - ###################################### # target ###################################### @@ -21,6 +13,8 @@ COMPONENT_DEPS = ###################################### # debug build? DEBUG = 1 +# save preprocessor output +SAVETEMPS = 0 # optimization OPT = -Og # c++ standard @@ -128,6 +122,10 @@ CFLAGS += -g3 CXXFLAGS += -g3 endif +ifeq ($(SAVETEMPS), 1) +CFLAGS += -save-temps +CXXFLAGS += -save-temps +endif # Generate dependency information CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)"