From fc932977374f417e087b9c1af39e111d8033db6d Mon Sep 17 00:00:00 2001 From: Attila BODY Date: Tue, 10 Dec 2019 15:06:33 +0100 Subject: [PATCH] git subrepo pull components/f4ll_c subrepo: subdir: "components/f4ll_c" merged: "3f84137" upstream: origin: "git@git.pcmuhely.hu:compi/f4ll_c.git" branch: "master" commit: "3f84137" git-subrepo: version: "0.4.0" origin: "https://github.com/ingydotnet/git-subrepo" commit: "5d6aba9" --- components/f4ll_c/.gitrepo | 4 +- .../f4ll_c/test/crcscheduler_unittests.cpp | 412 ++++++++++ .../f4ll_c/test/packetusart_unittest.cpp | 710 ++++++++++++++++++ 3 files changed, 1124 insertions(+), 2 deletions(-) create mode 100644 components/f4ll_c/test/crcscheduler_unittests.cpp create mode 100644 components/f4ll_c/test/packetusart_unittest.cpp diff --git a/components/f4ll_c/.gitrepo b/components/f4ll_c/.gitrepo index 83763ff..91b34b1 100644 --- a/components/f4ll_c/.gitrepo +++ b/components/f4ll_c/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = git@git.pcmuhely.hu:compi/f4ll_c.git branch = master - commit = 5d26fdc64d86cdbf16d6796c3c51cef3ef05a8dc - parent = 357b30b34479b3f45b97b60068d7d0fcaa4d98eb + commit = 3f841370ef21911ef034d622fd98a53463d94b10 + parent = f62880b4fa42f6c72823cb0b247caae481df7077 method = merge cmdver = 0.4.0 diff --git a/components/f4ll_c/test/crcscheduler_unittests.cpp b/components/f4ll_c/test/crcscheduler_unittests.cpp new file mode 100644 index 0000000..4999008 --- /dev/null +++ b/components/f4ll_c/test/crcscheduler_unittests.cpp @@ -0,0 +1,412 @@ +/* + ============================================================================ + Name : unittest.c + Author : + Version : + Copyright : Your copyright notice + Description : Hello World in C, Ansi-style + ============================================================================ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" void Crc_StartNextTask(struct crcstatus_t *status); + +DMA_TypeDef * DMA1 __attribute__((weak)); +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 CRC_TypeDef fakeCrc; + +static DMA_TypeDef *expectedDma; +static uint32_t expectedStream; +static uint32_t expectedSrcAddress; +static uint32_t expectedDstAddress; +static uint32_t expectedLength; +static void *expectedCustomPtr; +static uint8_t expectedSuccess; +static uint32_t expectedCrc; + +////////////////////////////////////////////////////////////////////////////// +DEFINE_MOCK_RET(uint32_t, __get_PRIMASK, mock) { + RETURN_MOCK_PREDEF(__get_PRIMASK, mock); +} + +DEFINE_MOCK_VAR(uint32_t, __set_PRIMASK, mock, lastprimask); +DEFINE_MOCK(__set_PRIMASK, mock, uint32_t primask) { + MOCK_STORE(__set_PRIMASK, mock, lastprimask, primask); + LEAVE_MOCK; +} + +DEFINE_MOCK_VAR(crcslotlistitem_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)); + } + LEAVE_MOCK; +} + +DEFINE_MOCK(LL_DMA_EnableIT_TC, mock, DMA_TypeDef *dma, uint32_t stream) { + EXPECT_EQ(expectedDma, dma); + EXPECT_EQ(expectedStream, stream); + LEAVE_MOCK; +} + +DEFINE_MOCK(LL_DMA_EnableIT_TE, mock, DMA_TypeDef *dma, uint32_t stream) { + EXPECT_EQ(expectedDma, dma); + EXPECT_EQ(expectedStream, stream); + LEAVE_MOCK; +} + +DEFINE_MOCK(LL_DMA_SetM2MDstAddress, mock, DMA_TypeDef *dma, uint32_t stream, uint32_t address) { + EXPECT_EQ(expectedDma, dma); + EXPECT_EQ(expectedStream, stream); + EXPECT_EQ(expectedDstAddress, address); + LEAVE_MOCK; +} + +DEFINE_MOCK(LL_DMA_SetM2MSrcAddress, mock, DMA_TypeDef *dma, uint32_t stream, uint32_t address) { + EXPECT_EQ(expectedDma, dma); + EXPECT_EQ(expectedStream, stream); + EXPECT_EQ(expectedSrcAddress, address); + LEAVE_MOCK; +} + +DEFINE_MOCK(LL_DMA_SetDataLength, mock, DMA_TypeDef *dma, uint32_t stream, uint32_t length) { + EXPECT_EQ(expectedDma, dma); + EXPECT_EQ(expectedStream, stream); + EXPECT_EQ(expectedLength, length); + LEAVE_MOCK; +} + +DEFINE_MOCK(LL_DMA_EnableStream, mock, DMA_TypeDef *dma, uint32_t stream) +{ + EXPECT_EQ(expectedDma, dma); + EXPECT_EQ(expectedStream, stream); + LEAVE_MOCK; +} + +DEFINE_MOCK(LL_DMA_DisableStream, mock, DMA_TypeDef *dma, uint32_t stream) +{ + EXPECT_EQ(expectedDma, dma); + EXPECT_EQ(expectedStream, stream); + LEAVE_MOCK; +} + +DEFINE_MOCK(Crc_StartNextTask, mock, struct crcstatus_t *status) +{ + EXPECT_EQ(status, &crcStatus); + LEAVE_MOCK +} + +void FakeCallback_1(void*, uint32_t, uint8_t) {} +void FakeCallback_2(void*, uint32_t, uint8_t) {} +void FakeCallback_3(void*, uint32_t, uint8_t) {} + +void FakeCallbackCheck(void* ptr, uint32_t crc, uint8_t success) +{ + EXPECT_EQ(ptr, expectedCustomPtr); + EXPECT_EQ(crc, expectedCrc); + EXPECT_EQ(success, expectedSuccess); +} + +DEFINE_MOCK(Dma_Init, mock, struct dmainfo_t * info, DMA_TypeDef *dma, uint32_t stream) +{ + LEAVE_MOCK; +} + +////////////////////////////////////////////////////////////////////////////// +TEST(CrcScheduler, InitStatus) +{ + expectedDma = DMA2; + expectedStream = LL_DMA_STREAM_4; + expectedDstAddress = (uint32_t)&fakeCrc; + memset(&crcStatus, 0xff, sizeof(crcStatus)); + + ACTIVATE_MOCK(LL_DMA_EnableIT_TC, mock); + ACTIVATE_MOCK(LL_DMA_EnableIT_TE, mock); + ACTIVATE_MOCK(LL_DMA_SetM2MDstAddress, mock); + ACTIVATE_MOCK(Dma_Init, mock); + + Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); + EXPECT_EQ(crcStatus.crcUnit, &fakeCrc); + EXPECT_EQ(crcStatus.activeSlot, nullptr); + EXPECT_EQ(crcStatus.firstSlot, nullptr); + EXPECT_EQ(MOCK_VAR(Dma_Init, mock, callcount), 1); +} + + +TEST(CrcScheduler, AttachTask_single) +{ + ACTIVATE_MOCK_RV(__get_PRIMASK, mock, 1); + ACTIVATE_MOCK(__set_PRIMASK, mock); + ACTIVATE_MOCK(__disable_irq, mock); + MOCK_STORE(__disable_irq, mock, compare, nullptr); + DMA1 = &dma1; + DMA2 = &dma2; + Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); + + Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + + EXPECT_EQ(MOCK_VAR(__get_PRIMASK, mock, callcount), 1); + EXPECT_EQ(MOCK_VAR(__set_PRIMASK, mock, callcount), 1); + EXPECT_EQ(MOCK_VAR(__disable_irq, mock, callcount), 1); + EXPECT_EQ(crcStatus.firstSlot, &slot1); + EXPECT_EQ(slot1.next, nullptr); + EXPECT_EQ(slot1.count, 2); + EXPECT_EQ(crcStatus.activeSlot, nullptr); +} + +TEST(CrcScheduler, AttachTask_multiple) +{ + ACTIVATE_MOCK_RV(__get_PRIMASK, mock, 1); + ACTIVATE_MOCK(__set_PRIMASK, mock); + ACTIVATE_MOCK(__disable_irq, mock); + MOCK_STORE(__disable_irq, mock, compare, nullptr); + DMA1 = &dma1; + DMA2 = &dma2; + Crc_InitStatus(&crcStatus, NULL, DMA2, LL_DMA_STREAM_4); + + Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + MOCK_STORE(__disable_irq, mock, compare, &slot1); + Crc_AttachTask(&crcStatus, &slot2, tasks2, 2); + + EXPECT_EQ(__get_PRIMASK_mock_callcount, 2); + EXPECT_EQ(__set_PRIMASK_mock_callcount, 2); + EXPECT_EQ(__disable_irq_mock_callcount, 2); + EXPECT_EQ(crcStatus.firstSlot, &slot2); + EXPECT_EQ(slot2.next, &slot1); + EXPECT_EQ(slot1.next, nullptr); + EXPECT_EQ(slot2.count, 2); + EXPECT_EQ(crcStatus.activeSlot, nullptr); +} + +TEST(CrcScheduler, Enqueue_nowait) +{ + uint32_t fakeCrcResult; + uint8_t testData[] = "qwerty"; + expectedDma = DMA2; + expectedStream = LL_DMA_STREAM_4; + expectedSrcAddress = (uint32_t)testData; + + memset(tasks1, 0, sizeof(tasks1)); + memset(&fakeCrc, 0, sizeof(fakeCrc)); + + Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); + Crc_AttachTask(&crcStatus, &slot1, tasks1, 2); + expectedLength = 2; + + ACTIVATE_MOCK(LL_DMA_SetM2MSrcAddress, mock); + ACTIVATE_MOCK(LL_DMA_SetDataLength, mock); + ACTIVATE_MOCK(LL_DMA_EnableStream, mock); + + EXPECT_TRUE(Crc_Enqueue(&crcStatus, &slot1, 0, testData, sizeof(testData), FakeCallback_1, &fakeCrcResult)); + + //first task should be picked up before return; + EXPECT_EQ(slot1.tasks[0].address, nullptr); + EXPECT_EQ((uintptr_t)slot1.tasks[0].callback, (uintptr_t)FakeCallback_1); + EXPECT_EQ(MOCK_VAR(LL_DMA_SetM2MSrcAddress, mock, callcount), 1); + EXPECT_EQ(MOCK_VAR(LL_DMA_SetDataLength, mock, callcount), 1); + EXPECT_EQ(MOCK_VAR(LL_DMA_EnableStream, mock, callcount), 1); + + EXPECT_FALSE(Crc_Enqueue(&crcStatus, &slot1, 1, testData, 4, FakeCallback_1, &fakeCrcResult)); + + // second task should be queued + EXPECT_EQ(slot1.tasks[1].address, testData); + EXPECT_EQ((uintptr_t)slot1.tasks[1].callback, (uintptr_t)FakeCallback_1); + EXPECT_EQ(slot1.tasks[1].wordCount, 1); + + // should be no new calls to hardware handling functions + EXPECT_EQ(MOCK_VAR(LL_DMA_SetM2MSrcAddress, mock, callcount), 1); + EXPECT_EQ(MOCK_VAR(LL_DMA_SetDataLength, mock, callcount), 1); + EXPECT_EQ(MOCK_VAR(LL_DMA_EnableStream, mock, callcount), 1); +} + +TEST(CrcScheduler, Enqueue_shouldblockthencontinue) +{ + uint8_t testData[] = "qwerty"; + uint32_t fakeCrcResult; + + memset(tasks1, 0, sizeof(tasks1)); + memset(&fakeCrc, 0, sizeof(fakeCrc)); + + Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); + Crc_AttachTask(&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) + std::promise promisedFinished; + auto futureResult = promisedFinished.get_future(); + pthread_t th; + std::thread t([&testData](std::promise& finished) { + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); + Crc_Enqueue(&crcStatus, &slot1, 0, testData, sizeof(testData), FakeCallback_1, nullptr); + finished.set_value(true); + }, std::ref(promisedFinished)); + th = t.native_handle(); + t.detach(); + EXPECT_EQ(futureResult.wait_for(std::chrono::milliseconds(100)), std::future_status::timeout); + tasks1[0].callback = nullptr; + tasks1[0].callbackParam = nullptr; + 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); +} + +TEST(CrcScheduler, Crc_StartNextTask) +{ + uint8_t testData[] = "qwerty"; + uint32_t fakeCrcResult1, fakeCrcResult2, fakeCrcResult3; + + memset(tasks1, 0, sizeof(tasks1)); + memset(tasks2, 0, sizeof(tasks2)); + 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_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); + + EXPECT_EQ(crcStatus.activeSlot, &slot1); + EXPECT_EQ(crcStatus.activeTask, 0); + crcStatus.activeSlot->tasks[crcStatus.activeTask].callback = nullptr; + crcStatus.activeSlot->tasks[crcStatus.activeTask].callbackParam = nullptr; + + ACTIVATE_MOCK(LL_DMA_SetM2MSrcAddress, mock); + ACTIVATE_MOCK(LL_DMA_SetDataLength, mock); + ACTIVATE_MOCK(LL_DMA_EnableStream, mock); + + expectedDma = DMA2; + expectedStream = LL_DMA_STREAM_4; + expectedSrcAddress = (uint32_t)testData; + expectedLength = (sizeof(testData) + 3) / 4; + + Crc_StartNextTask(&crcStatus); + + EXPECT_EQ(crcStatus.activeSlot, &slot2); + EXPECT_EQ(crcStatus.activeTask, 0); + EXPECT_EQ(LL_DMA_SetM2MSrcAddress_mock_callcount, 1); + EXPECT_EQ(LL_DMA_SetDataLength_mock_callcount, 1); + EXPECT_EQ(LL_DMA_EnableStream_mock_callcount, 1); + crcStatus.activeSlot->tasks[crcStatus.activeTask].callback = nullptr; + crcStatus.activeSlot->tasks[crcStatus.activeTask].callbackParam = nullptr; + + Crc_StartNextTask(&crcStatus); + + EXPECT_EQ(crcStatus.activeSlot, &slot1); + EXPECT_EQ(crcStatus.activeTask, 1); + EXPECT_EQ(LL_DMA_SetM2MSrcAddress_mock_callcount, 2); + EXPECT_EQ(LL_DMA_SetDataLength_mock_callcount, 2); + EXPECT_EQ(LL_DMA_EnableStream_mock_callcount, 2); +} + +TEST(CrcScheduler, HandleDmaIrq_callback) +{ + uint8_t testData[] = "qwerty"; + uint32_t FakeCustomData1, FakeCustomData2; + + + memset(tasks1, 0, sizeof(tasks1)); + memset(tasks2, 0, sizeof(tasks2)); + memset(&fakeCrc, 0, sizeof(fakeCrc)); + + 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_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); + + ACTIVATE_MOCK(LL_DMA_DisableStream, mock); + ACTIVATE_MOCK(LL_DMA_SetM2MSrcAddress, mock); + ACTIVATE_MOCK(LL_DMA_SetDataLength, mock); + ACTIVATE_MOCK(LL_DMA_EnableStream, mock); + ACTIVATE_MOCK(Crc_StartNextTask, mock); + + expectedDma = DMA2; + expectedStream = LL_DMA_STREAM_4; + + expectedCustomPtr = &FakeCustomData1; + expectedCrc = fakeCrc.DR; + expectedSuccess = 1; + + DMA2->HISR |= DMA_HISR_TCIF4; + DMA2->HIFCR = 0; + + Crc_HandleDmaIrq(&crcStatus); + + EXPECT_EQ(LL_DMA_DisableStream_mock_callcount, 1); + + EXPECT_EQ(DMA2->HIFCR & DMA_HIFCR_CTCIF4, DMA_HIFCR_CTCIF4); + + expectedCustomPtr = &FakeCustomData2; + DMA2->HISR |= DMA_HISR_TCIF4 | DMA_HISR_TEIF4; + DMA2->HIFCR = 0; + crcStatus.activeSlot->tasks[crcStatus.activeTask].callback = nullptr; + crcStatus.activeSlot->tasks[crcStatus.activeTask].callbackParam = nullptr; + + Crc_HandleDmaIrq(&crcStatus); + + EXPECT_EQ(DMA2->HIFCR & (DMA_HIFCR_CTCIF4 | DMA_HIFCR_CTEIF4), DMA_HIFCR_CTCIF4 | DMA_HIFCR_CTEIF4); + EXPECT_EQ(LL_DMA_DisableStream_mock_callcount, 2); +} + +TEST(CrcScheduler, IsSlotQueued) +{ + uint8_t testData[] = "qwerty"; + uint32_t FakeCustomData1; + + Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); + Crc_AttachTask(&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); + + Crc_StartNextTask(&crcStatus); + + EXPECT_EQ(Crc_IsSlotQueued(&slot1, 1), 0); +} + +TEST(CrcScheduler, IsSlotBusy) +{ + uint8_t testData[] = "qwerty"; + uint32_t FakeCustomData1; + + Crc_InitStatus(&crcStatus, &fakeCrc, DMA2, LL_DMA_STREAM_4); + Crc_AttachTask(&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); + + DMA2->HISR |= DMA_HISR_TCIF4; + Crc_HandleDmaIrq(&crcStatus); + + EXPECT_EQ(Crc_IsSlotBusy(&slot1, 0), 0); + EXPECT_NE(Crc_IsSlotBusy(&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); +} diff --git a/components/f4ll_c/test/packetusart_unittest.cpp b/components/f4ll_c/test/packetusart_unittest.cpp new file mode 100644 index 0000000..3d1e76e --- /dev/null +++ b/components/f4ll_c/test/packetusart_unittest.cpp @@ -0,0 +1,710 @@ +/* + * packetusart_unittest.cpp + * + * Created on: Dec 2, 2019 + * Author: abody + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static inline uint32_t RoundUpTo4(uint32_t inp) +{ + return (inp + 3) & 0xfffc; +} + +DMA_TypeDef* DMA1 __attribute__((weak)); +DMA_TypeDef* DMA2 __attribute__((weak)); + +static DMA_TypeDef fakeDma1, fakeDma2; +static CRC_TypeDef fakeCrc; +static USART_TypeDef fakeUsart; + +static struct usartstatus_t usartStatus; +static struct crcstatus_t crcStatus; + +uint8_t testData[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + +//static uint32_t expected_stream; +//static uint32_t expected_srcaddress; +//static uint32_t expected_dstaddress; +//static uint32_t expected_length; +//static void *expected_customptr; +//static uint8_t expected_success; +//static struct usartstatus_t * expectedUsartStatus; +static uint32_t expectedStreams[2] = { 0,7 }; +struct crcstatus_t *expectedCrcStatus; +struct crcslotlistitem_t *expectedCrcSlotListItem; +struct crcslottask_t *expectedTasks; +uint8_t expectedTaskCount; +uint32_t expectedCrcLength; +uint32_t expectedLength; +void* expectedCrcEnqueueAddress; +void *expectedTransmitBuffer; + +static uint32_t expectedStream; +uint32_t expectedSrcAddress; +uint32_t expectedDstAddress; +uint32_t expectedDirection; + +uint32_t fakePacketReceivedCallbackParam; + + +DEFINE_MOCK(FakePacketReceivedCallback, mock, void* userParam, struct usart_buffer_t *buffer) +{ + EXPECT_EQ((void*)&fakePacketReceivedCallbackParam, userParam); + LEAVE_MOCK +} + +DEFINE_MOCK(Dma_Init, mock, struct dmainfo_t* dmaInfo, DMA_TypeDef *dma, uint32_t stream) +{ + Dma_Init__(dmaInfo, dma, stream); + LEAVE_MOCK +} + +DEFINE_MOCK(Crc_AttachTask, mock, struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_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); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_DMA_EnableIT_TC, init, DMA_TypeDef *dma, uint32_t stream) +{ + EXPECT_EQ(dma, &fakeDma1); + EXPECT_EQ(stream, expectedStreams[MOCK_VAR(LL_DMA_EnableIT_TC, init, callcount)-1]); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_DMA_EnableIT_TE, init, DMA_TypeDef *dma, uint32_t stream) +{ + EXPECT_EQ(dma, &fakeDma1); + EXPECT_EQ(stream, expectedStreams[MOCK_VAR(LL_DMA_EnableIT_TE, init, callcount)-1]); + LEAVE_MOCK +} + +DEFINE_MOCK_RET(uint32_t, LL_USART_DMA_GetRegAddr, mock, USART_TypeDef *usart) +{ + RETURN_MOCK_PREDEF(LL_USART_DMA_GetRegAddr, mock) +} + +DEFINE_MOCK(LL_DMA_ConfigAddresses, mock, DMA_TypeDef* dma, uint32_t stream, uint32_t srcAddress, uint32_t dstAddress, uint32_t direction) +{ + EXPECT_EQ(dma, &fakeDma1); + EXPECT_EQ(stream, expectedStream); + EXPECT_EQ(srcAddress, expectedSrcAddress); + EXPECT_EQ(dstAddress, expectedDstAddress); + EXPECT_EQ(direction, expectedDirection); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_DMA_SetDataLength, mock, DMA_TypeDef* dma, uint32_t stream, uint32_t length) +{ + EXPECT_EQ(dma, &fakeDma1); + EXPECT_EQ(stream, expectedStream); + EXPECT_EQ(length, expectedLength); + LEAVE_MOCK +} + +DEFINE_MOCK_RET(uint32_t, LL_DMA_GetDataLength, mock, DMA_TypeDef* dma, uint32_t stream) +{ + EXPECT_EQ(dma, &fakeDma1); + EXPECT_EQ(stream, expectedStream); + RETURN_MOCK_PREDEF(LL_DMA_GetDataLength, mock) +} + +DEFINE_MOCK(LL_DMA_EnableStream, mock, DMA_TypeDef* dma, uint32_t stream) +{ + EXPECT_EQ(dma, &fakeDma1); + EXPECT_EQ(stream, expectedStream); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_DMA_DisableStream, mock, DMA_TypeDef* dma, uint32_t stream) +{ + EXPECT_EQ(dma, &fakeDma1); + EXPECT_EQ(stream, expectedStream); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_USART_EnableDMAReq_TX, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_USART_EnableDMAReq_RX, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_USART_EnableIT_IDLE, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_USART_EnableIT_TC, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_USART_DisableIT_TC, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK +} + +DEFINE_MOCK_RET(uint32_t, LL_USART_IsActiveFlag_IDLE, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + RETURN_MOCK_PREDEF(LL_USART_IsActiveFlag_IDLE, mock) +} + +DEFINE_MOCK_RET(uint32_t, LL_USART_IsActiveFlag_TC, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + RETURN_MOCK_PREDEF(LL_USART_IsActiveFlag_TC, mock) +} + +DEFINE_MOCK(LL_USART_ClearFlag_IDLE, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK; +} + +DEFINE_MOCK_RET(uint32_t, LL_USART_IsEnabledIT_IDLE, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + RETURN_MOCK_PREDEF(LL_USART_IsEnabledIT_IDLE, mock) +} + +DEFINE_MOCK_RET(uint32_t, LL_USART_IsEnabledIT_TC, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + RETURN_MOCK_PREDEF(LL_USART_IsEnabledIT_TC, mock) +} + +DEFINE_MOCK(LL_USART_EnableDirectionTx, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_USART_DisableDirectionTx, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK +} + +DEFINE_MOCK(LL_USART_ClearFlag_ORE, mock, USART_TypeDef *usart) +{ + EXPECT_EQ(usart, &fakeUsart); + LEAVE_MOCK +} + +DEFINE_MOCK_RET(uint8_t, Crc_Enqueue, mock, 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) +{ + EXPECT_EQ(expectedCrcLength, len); + EXPECT_EQ(expectedCrcEnqueueAddress, address); + RETURN_MOCK_PREDEF(Crc_Enqueue, mock); +} + +DEFINE_MOCK_RET(uint8_t, Crc_IsSlotQueued, mock, struct crcslotlistitem_t *slot, uint8_t task) +{ + RETURN_MOCK_PREDEF(Crc_IsSlotQueued, mock); +} + +DEFINE_MOCK(Pu_SetupTransmit, mock, USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length) +{ + EXPECT_EQ(buffer, expectedTransmitBuffer); + EXPECT_EQ(length, expectedLength); + LEAVE_MOCK +} + +DEFINE_MOCK_RET(uint8_t, Pu_CheckHeader, proxy, struct usartpacket_t *packet) +{ + RETURN_MOCK(Pu_CheckHeader, proxy, Pu_CheckHeader__(packet)); +} + +DEFINE_MOCK(Pu_SetupReceive, mock, struct usartstatus_t *status) +{ + LEAVE_MOCK +} + +struct PacketUsart : public ::testing::Test { + void SetUp() + { + DMA1 = &fakeDma1; + DMA2 = &fakeDma2; + + memset(&usartStatus, 0x5a, sizeof(usartStatus)); + Crc_InitStatus(&crcStatus, &fakeCrc, &fakeDma2, 4); + + expectedCrcStatus = &crcStatus; + expectedCrcSlotListItem = &usartStatus.crcSlot; + expectedTasks = usartStatus.crcTasks; + expectedTaskCount = 2; + } +}; + +////////////////////////////////////////////////////////////////////////////// +TEST_F(PacketUsart, Init) +{ + ACTIVATE_MOCK(Dma_Init, mock); + ACTIVATE_MOCK(Crc_AttachTask, mock); + ACTIVATE_MOCK(LL_DMA_EnableIT_TC, init); + ACTIVATE_MOCK(LL_DMA_EnableIT_TE, init); + ACTIVATE_MOCK(LL_USART_EnableIT_IDLE, mock); + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + + EXPECT_EQ(fakeDma1.LIFCR, DMA_LISR_TCIF0 | DMA_LISR_HTIF0 | DMA_LISR_TEIF0 | DMA_LISR_FEIF0 | DMA_LISR_DMEIF0); + EXPECT_EQ(fakeDma1.HIFCR, DMA_HISR_TCIF7 | DMA_HISR_HTIF7 | DMA_HISR_TEIF7 | DMA_HISR_FEIF7 | DMA_HISR_DMEIF7); + EXPECT_EQ(MOCK_CALLCOUNT(Dma_Init, mock), 2); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_EnableIT_TC, init), 2); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_EnableIT_TE, init), 2); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableIT_IDLE, mock), 1); + EXPECT_EQ(usartStatus.usart, &fakeUsart); + EXPECT_EQ(usartStatus.txBuffer.usartStatus, &usartStatus); + EXPECT_EQ(usartStatus.txBuffer.busy, 0); + EXPECT_EQ(usartStatus.txBuffer.error, 0); + EXPECT_EQ(usartStatus.txBuffer.requestedLength, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].requestedLength, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].usartStatus, &usartStatus ); + EXPECT_EQ(usartStatus.rxBuffers[1].busy, 0); + EXPECT_EQ(usartStatus.rxBuffers[1].error, 0); + EXPECT_EQ(usartStatus.rxBuffers[1].requestedLength, 0); + EXPECT_EQ(usartStatus.rxBuffers[1].usartStatus, &usartStatus ); + EXPECT_TRUE(usartStatus.packetReceivedCallback == FakePacketReceivedCallback_mock); + EXPECT_EQ(usartStatus.packetReceivedCallbackParam, &fakePacketReceivedCallbackParam); + EXPECT_EQ(usartStatus.rxSerial, (uint8_t)-1); + EXPECT_EQ(usartStatus.txSerial, 0); + EXPECT_EQ(usartStatus.activeRxBuf, 0); + EXPECT_EQ(usartStatus.crcStatus, &crcStatus); +} + +TEST_F(PacketUsart, GetTxBuffer) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + EXPECT_EQ(Pu_GetTxBuffer(&usartStatus), (unsigned char*)&usartStatus.txBuffer.packet.payload); +} + +TEST_F(PacketUsart, SetupTransmit) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + expectedStream = 7; + expectedSrcAddress = (uint32_t)testData; + expectedDstAddress = (uint32_t)&fakeUsart.DR; + expectedDirection = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; + expectedLength = sizeof(testData); + + ACTIVATE_MOCK(LL_DMA_ConfigAddresses, mock); + ACTIVATE_MOCK(LL_DMA_SetDataLength , mock); + ACTIVATE_MOCK(LL_DMA_EnableStream , mock); + ACTIVATE_MOCK(LL_USART_EnableDMAReq_TX, mock); + ACTIVATE_MOCK_RV(LL_USART_DMA_GetRegAddr, mock, expectedDstAddress); + + Pu_SetupTransmit(&fakeUsart, &fakeDma1, 7, testData, sizeof(testData)); +} + +TEST_F(PacketUsart, Post_copy_nowait) +{ + struct usartpacketheader_t expectedHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; + expectedCrcLength = sizeof(usartStatus.txBuffer.packet.header) + 12; + expectedCrcEnqueueAddress = &usartStatus.txBuffer.packet; + expectedLength = sizeof(usartStatus.txBuffer.packet.header) + 12 + sizeof(uint32_t); + expectedTransmitBuffer = &usartStatus.txBuffer.packet; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + + ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); + ACTIVATE_MOCK(Pu_SetupTransmit, mock); + ACTIVATE_MOCK_RV(Crc_IsSlotQueued, mock, 1); + + Pu_Post(&usartStatus, testData, sizeof(testData), &crcStatus, false); + + EXPECT_EQ(usartStatus.txBuffer.busy, 1); + EXPECT_EQ(usartStatus.txBuffer.requestedLength, expectedLength); + 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); +} + +TEST_F(PacketUsart, Post_copy_wait_nodelay) +{ + expectedCrcLength = sizeof(usartStatus.txBuffer.packet.header) + 12; + expectedCrcEnqueueAddress = &usartStatus.txBuffer.packet; + expectedLength = sizeof(usartStatus.txBuffer.packet.header) + 12 + sizeof(uint32_t); + expectedTransmitBuffer = &usartStatus.txBuffer.packet; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + + ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); + ACTIVATE_MOCK(Pu_SetupTransmit, mock); + ACTIVATE_MOCK_RV(Crc_IsSlotQueued, mock, 0); + + Pu_Post(&usartStatus, testData, sizeof(testData), &crcStatus, true); + + EXPECT_EQ(MOCK_CALLCOUNT(Crc_IsSlotQueued, mock), 1); +} + +TEST_F(PacketUsart, Post_copy_wait_delay) +{ + expectedCrcLength = sizeof(usartStatus.txBuffer.packet.header) + 12; + expectedCrcEnqueueAddress = &usartStatus.txBuffer.packet; + expectedLength = sizeof(usartStatus.txBuffer.packet.header) + 12 + sizeof(uint32_t); + expectedTransmitBuffer = &usartStatus.txBuffer.packet; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + + ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 1); + ACTIVATE_MOCK(Pu_SetupTransmit, mock); + ACTIVATE_MOCK_RV(Crc_IsSlotQueued, mock, 1); + + // black magic to test if the function blocks (at least for 100ms) + std::promise promiseFinished; + auto futureResult = promiseFinished.get_future(); + pthread_t th; + std::thread t([](std::promise& finished) { + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL); + Pu_Post(&usartStatus, testData, sizeof(testData), &crcStatus, true);; + finished.set_value(true); + }, std::ref(promiseFinished)); + th = t.native_handle(); + t.detach(); + EXPECT_EQ(futureResult.wait_for(std::chrono::milliseconds(100)), std::future_status::timeout); + Crc_IsSlotQueued_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); +} + +TEST_F(PacketUsart, HandleTxDmaIrq_tc) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_Post(&usartStatus, testData, sizeof(testData), &crcStatus, true); + + memset(&fakeDma1, 0, sizeof(fakeDma1)); + fakeDma1.HISR = DMA_HISR_TCIF7; + expectedStream = 7; + + ACTIVATE_MOCK(LL_USART_EnableIT_TC, mock); + ACTIVATE_MOCK(LL_DMA_DisableStream, mock); + + Pu_HandleTxDmaIrq(&usartStatus); + + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableIT_TC, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 1); + EXPECT_EQ(fakeDma1.HIFCR, DMA_HIFCR_CTCIF7); +} + +TEST_F(PacketUsart, HandleTxDmaIrq_te) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_Post(&usartStatus, testData, sizeof(testData), &crcStatus, true); + + memset(&fakeDma1, 0, sizeof(fakeDma1)); + fakeDma1.HISR = DMA_HISR_TEIF7; + expectedStream = 7; + + Pu_HandleTxDmaIrq(&usartStatus); + + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableIT_TC, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 1); + EXPECT_EQ(fakeDma1.HIFCR, DMA_HIFCR_CTEIF7); + EXPECT_EQ(usartStatus.txBuffer.error, 1); +} + +TEST_F(PacketUsart, HandleUsartIrq_tc) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_Post(&usartStatus, testData, sizeof(testData), &crcStatus, true); + + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 0); + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); + ACTIVATE_MOCK(LL_USART_DisableIT_TC, mock); + ACTIVATE_MOCK(LL_USART_EnableDirectionTx, mock); + ACTIVATE_MOCK(LL_USART_DisableDirectionTx, mock); + + Pu_HandleUsartIrq(&usartStatus); + + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DisableIT_TC, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DisableDirectionTx, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_EnableDirectionTx, mock), 1); + EXPECT_EQ(usartStatus.txBuffer.busy, 0); +} + +TEST_F(PacketUsart, setupReceive) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + expectedStream = 0; + expectedDstAddress = (uint32_t)&usartStatus.rxBuffers[usartStatus.activeRxBuf].packet; + expectedSrcAddress = (uint32_t)&fakeUsart.DR; + expectedDirection = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; + expectedLength = sizeof(struct usartpacket_t); + + ACTIVATE_MOCK(LL_DMA_ConfigAddresses, mock); + ACTIVATE_MOCK(LL_DMA_SetDataLength , mock); + ACTIVATE_MOCK(LL_DMA_EnableStream , mock); + ACTIVATE_MOCK(LL_USART_EnableDMAReq_RX, mock); + ACTIVATE_MOCK(LL_USART_ClearFlag_ORE, mock); + + ACTIVATE_MOCK_RV(LL_USART_DMA_GetRegAddr, mock, expectedSrcAddress); + + Pu_SetupReceive(&usartStatus); + + 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_RX, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_ORE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_DMA_GetRegAddr, mock), 1); +} + +TEST_F(PacketUsart, HandleUsartIrq_idle_fullpacket_hdr_ok) +{ + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + expectedStream = 0; + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 0); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); + ACTIVATE_MOCK(LL_USART_ClearFlag_IDLE, mock); + ACTIVATE_MOCK_RV(LL_DMA_GetDataLength, mock, sizeof(struct usartpacket_t) - sizeof(struct usartpacketheader_t) - RoundUpTo4(sizeof(testData)) - sizeof(uint32_t)); + ACTIVATE_MOCK_RV(Pu_CheckHeader, proxy, 1); + ACTIVATE_MOCK(LL_DMA_DisableStream, mock); + + Pu_HandleUsartIrq(&usartStatus); + + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsActiveFlag_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsEnabledIT_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_GetDataLength, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 1); + EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); +} + +TEST_F(PacketUsart, HandleUsartIrq_idle_fullpacket_hdr_bad) +{ + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + expectedStream = 0; + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 0); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); + ACTIVATE_MOCK(LL_USART_ClearFlag_IDLE, mock); + ACTIVATE_MOCK_RV(LL_DMA_GetDataLength, mock, sizeof(struct usartpacket_t) - sizeof(struct usartpacketheader_t) - RoundUpTo4(sizeof(testData)) - sizeof(uint32_t)); + ACTIVATE_MOCK_RV(Pu_CheckHeader, proxy, 1); + ACTIVATE_MOCK(LL_DMA_DisableStream, mock); + + Pu_HandleUsartIrq(&usartStatus); + + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsActiveFlag_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsEnabledIT_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_GetDataLength, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 1); + EXPECT_NE(usartStatus.rxBuffers[0].error, 0); + EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); +} + +TEST_F(PacketUsart, HandleUsartIrq_idle_tooshort) +{ + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + expectedStream = 0; + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 0); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); + ACTIVATE_MOCK(LL_USART_ClearFlag_IDLE, mock); + ACTIVATE_MOCK_RV(LL_DMA_GetDataLength, mock, sizeof(struct usartpacket_t) - sizeof(struct usartpacketheader_t) - RoundUpTo4(sizeof(testData)) - sizeof(uint32_t) + 1); + ACTIVATE_MOCK_RV(Pu_CheckHeader, proxy, 1); + ACTIVATE_MOCK(LL_DMA_DisableStream, mock); + + Pu_HandleUsartIrq(&usartStatus); + + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsActiveFlag_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsEnabledIT_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_GetDataLength, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 0); + EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); +} + +TEST_F(PacketUsart, HandleUsartIrq_idle_tooshortforheadercheck) +{ + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + expectedStream = 0; + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsActiveFlag_TC, mock, 0); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_IDLE, mock, 1); + ACTIVATE_MOCK_RV(LL_USART_IsEnabledIT_TC, mock, 1); + ACTIVATE_MOCK(LL_USART_ClearFlag_IDLE, mock); + ACTIVATE_MOCK_RV(LL_DMA_GetDataLength, mock, sizeof(struct usartpacket_t) - 3); + ACTIVATE_MOCK_RV(Pu_CheckHeader, proxy, 1); + ACTIVATE_MOCK(LL_DMA_DisableStream, mock); + + Pu_HandleUsartIrq(&usartStatus); + + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsActiveFlag_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_IsEnabledIT_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_USART_ClearFlag_IDLE, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_GetDataLength, mock), 1); + EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 0); + EXPECT_EQ(MOCK_CALLCOUNT(LL_DMA_DisableStream, mock), 0); + EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); +} + +TEST_F(PacketUsart, HandleRxDmaIrq_tc_hdrok) +{ + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0x95 ^ 0 ^ sizeof(testData) }; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + memset(&fakeDma1, 0, sizeof(fakeDma1)); + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + expectedStream = 0; + expectedCrcEnqueueAddress = &usartStatus.rxBuffers[0].packet; + expectedCrcLength = RoundUpTo4(usartStatus.rxBuffers[0].packet.header.payloadLength) + sizeof(struct usartpacketheader_t); + fakeDma1.LISR = DMA_LISR_TCIF0; + + ACTIVATE_MOCK(Pu_CheckHeader, proxy); + ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 0); + ACTIVATE_MOCK(Pu_SetupReceive, mock); + + Pu_HandleRxDmaIrq(&usartStatus); + + EXPECT_EQ(fakeDma1.LIFCR, DMA_LIFCR_CTCIF0); + EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); +} + +TEST_F(PacketUsart, HandleRxDmaIrq_tc_hdrfail) +{ + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; + + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + memset(&fakeDma1, 0, sizeof(fakeDma1)); + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + expectedStream = 0; + expectedCrcEnqueueAddress = &usartStatus.rxBuffers[0].packet; + expectedCrcLength = RoundUpTo4(usartStatus.rxBuffers[0].packet.header.payloadLength) + sizeof(struct usartpacketheader_t); + fakeDma1.LISR = DMA_LISR_TCIF0; + + ACTIVATE_MOCK(Pu_CheckHeader, proxy); + ACTIVATE_MOCK_RV(Crc_Enqueue, mock, 0); + ACTIVATE_MOCK(Pu_SetupReceive, mock); + + Pu_HandleRxDmaIrq(&usartStatus); + + EXPECT_EQ(MOCK_CALLCOUNT(Pu_CheckHeader, proxy), 1); + EXPECT_EQ(MOCK_CALLCOUNT(Crc_Enqueue, mock), 0); + EXPECT_EQ(fakeDma1.LIFCR, DMA_LIFCR_CTCIF0); + EXPECT_EQ(usartStatus.rxBuffers[0].error, 1); + EXPECT_EQ(usartStatus.rxBuffers[0].busy, 0); +} + +TEST_F(PacketUsart, HandleRxCrcComputedCallback_success_match) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + memcpy(usartStatus.rxBuffers[0].packet.payload, &testData, sizeof(testData)); + *(uint32_t*)(usartStatus.rxBuffers[0].packet.payload + RoundUpTo4(sizeof(testData))) = 0xa55a; + MOCK_CALLCOUNT(FakePacketReceivedCallback, mock) = 0; + + Pu_RxCrcComputedCallback(&usartStatus.rxBuffers[0], 0xa55a, 1); + + EXPECT_EQ(MOCK_CALLCOUNT(FakePacketReceivedCallback, mock), 1); + EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); + EXPECT_EQ(usartStatus.rxBuffers[0].error, 0); +} + +TEST_F(PacketUsart, HandleRxCrcComputedCallback_success_mismatch) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + memcpy(usartStatus.rxBuffers[0].packet.payload, &testData, sizeof(testData)); + *(uint32_t*)(usartStatus.rxBuffers[0].packet.payload + RoundUpTo4(sizeof(testData))) = 0xa5a5; + MOCK_CALLCOUNT(FakePacketReceivedCallback, mock) = 0; + + Pu_RxCrcComputedCallback(&usartStatus.rxBuffers[0], 0xa55a, 1); + + EXPECT_EQ(MOCK_CALLCOUNT(FakePacketReceivedCallback, mock), 1); + EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); + EXPECT_NE(usartStatus.rxBuffers[0].error, 0); +} + +TEST_F(PacketUsart, HandleRxCrcComputedCallback_failure) +{ + Pu_Init(&usartStatus, &fakeUsart, DMA1, 0, 7, &crcStatus, FakePacketReceivedCallback_mock, &fakePacketReceivedCallbackParam); + Pu_SetupReceive(&usartStatus); + + struct usartpacketheader_t fakeHeader = { 0x95, 0, sizeof(testData), 0xff ^ 0 ^ sizeof(testData) }; + memcpy(&usartStatus.rxBuffers[0].packet.header, &fakeHeader, sizeof(fakeHeader)); + memcpy(usartStatus.rxBuffers[0].packet.payload, &testData, sizeof(testData)); + *(uint32_t*)(usartStatus.rxBuffers[0].packet.payload + RoundUpTo4(sizeof(testData))) = 0xa5a5; + MOCK_CALLCOUNT(FakePacketReceivedCallback, mock) = 0; + + Pu_RxCrcComputedCallback(&usartStatus.rxBuffers[0], 0xa55a, 1); + + EXPECT_EQ(MOCK_CALLCOUNT(FakePacketReceivedCallback, mock), 1); + EXPECT_NE(usartStatus.rxBuffers[0].busy, 0); + EXPECT_NE(usartStatus.rxBuffers[0].error, 0); +}