From 8bfff9431a78829c1169f08713a107ddc8bbe4b3 Mon Sep 17 00:00:00 2001 From: Gatsby Van Date: Wed, 24 Jan 2024 11:42:57 +0800 Subject: [PATCH] *add unit test. --- .../unit_test/linklayer_emulate_unit_test.c | 366 ++++++++++++++++++ .../unit_test/unit_test_framework.h | 1 + 2 files changed, 367 insertions(+) create mode 100644 df_datalink_sp/unit_test/linklayer_emulate_unit_test.c create mode 120000 df_datalink_sp/unit_test/unit_test_framework.h diff --git a/df_datalink_sp/unit_test/linklayer_emulate_unit_test.c b/df_datalink_sp/unit_test/linklayer_emulate_unit_test.c new file mode 100644 index 0000000..65406f1 --- /dev/null +++ b/df_datalink_sp/unit_test/linklayer_emulate_unit_test.c @@ -0,0 +1,366 @@ +#include +#include +#include +#include "error.h" +#include "unit_test_framework.h" +#include "time_ctrl/time_ctrl.h" +#include "networking/phy_layer/phy_layer.h" +#include "networking/link_layer/link_layer.h" +#include "networking/link_layer/link_layer_types.h" +#include "networking/link_layer/msg_def.h" + +#define TIME_INT_REG (0x00000008 >> 2) +#define TIME_FRAC_REG (0x0000000C >> 2) +#define TIME_ADJ_INT (0x0000001C >> 2) +#define TIME_ADJ_FRAC (0x00000020 >> 2) +#define TIME_ADJ_TRIG (0x00000024 >> 2) +#define CNTSTEP_OPT (0x00000028 >> 2) + +#define SIM_STEP (TIME_FRAC_MAX/100) + +TMC_INST *tmcInstPtr = NULL; +PHY_INST *phyInstPtr = NULL; +L2_INST *linkInstPtr = NULL; + +uint32_t tmcReg[32] = {0}; +uint32_t phycReg[512] = {0}; + +L2_CONFIG l2Config = +{ + .myType = L2_NODE_HEAD, + .isInterHead = false, + .myId = 1, + .clustId = 1, + .headId = 1, + .bkpHeadId = 1, + .netScale = 2, + .phyInstPtr = NULL, + .tmcInstPtr = NULL +}; + +PHY_CONFIG l1Config = +{ + .devId = 0, + .txBramId = 0, + .rxBramId = 0, + .antBramId = 0, + .hwXadcId = 0, + .baseAddr = (uintptr_t)phycReg +}; + +TMC_CONFIG tmcConfig = +{ + .baseAddr = (uintptr_t)tmcReg, + .reset = 10 +}; + +int32_t rand_range(int32_t a, int32_t b); +inline int32_t rand_range(int32_t a, int32_t b) +{ + ASSERT(b > a); + return (rand() % (b + 1 - a) + a); +} + +void linklayer_setup(void) +{ + int32_t Status; + Status = SysMonitor_Init(); + ASSERT_EQUAL(SUCCESS, Status); + Status = TimeCtrl_Init(&tmcInstPtr, &tmcConfig); + ASSERT_EQUAL(SUCCESS, Status); + Status = Phy_InstInit(&phyInstPtr, &l1Config); + ASSERT_EQUAL(SUCCESS, Status); + + // Update l2 config + l2Config.phyInstPtr = phyInstPtr; + l2Config.tmcInstPtr = tmcInstPtr; + + Status = Linklayer_Init(&linkInstPtr, &l2Config); + ASSERT_EQUAL(SUCCESS, Status); +} + +void linklayer_teardown(void) +{ + Linklayer_Destroy(linkInstPtr); + Phy_Destroy(phyInstPtr); + TimeCtrl_Destroy(tmcInstPtr); + SysMonitor_Destroy(); +} + +void forge_adv_frame(uint8_t *buff, uint8_t srcId, uint8_t destId, + uint32_t frameNum, uint32_t slotNum, uint32_t netStartTime) +{ + uint8_t type = L2_ADV_FRAME; + L2_FrameInsertChunk(buff, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &type); + L2_FrameInsertChunk(buff, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &frameNum); + L2_FrameInsertChunk(buff, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &slotNum); + L2_FrameInsertChunk(buff, L2_MSG_SRC_ID, L2_MSG_SRC_ID_LEN, &srcId); + L2_FrameInsertChunk(buff, L2_MSG_DST_ID, L2_MSG_DST_ID_LEN, &destId); + + + float testData = 3.14; + L2_FrameInsertChunk(buff, L2_MSG_ADV_SRC_POSX, L2_MSG_ADV_SRC_POSX_LEN, &testData); + L2_FrameInsertChunk(buff, L2_MSG_ADV_SRC_POSY, L2_MSG_ADV_SRC_POSY_LEN, &testData); + L2_FrameInsertChunk(buff, L2_MSG_ADV_SRC_POSZ, L2_MSG_ADV_SRC_POSZ_LEN, &testData); + + // Insert net start time + L2_FrameInsertChunk(buff, L2_MSG_ADV_SRC_NETSTART_TIME, L2_MSG_ADV_SRC_NETSTART_TIME_LEN, &netStartTime); + + // Append CRC + if (L2_CrcAppend(buff, L2_ADV_PACK_LEN - L2_MSG_ADV_SVC_CRC_LEN, L2_MSG_ADV_SVC_CRC, L2_CRC16_1021) != SUCCESS) + { + DBG_ERROR("Fail to append CRC.\n"); + ASSERT(false); + } + +} + +void forge_cfm_frame(uint8_t *buff, uint16_t srcId, uint16_t destId, + uint32_t frameNum, uint32_t slotNum) +{ + uint8_t type = L2_CFM_FRAME; + L2_FrameInsertChunk(buff, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &type); + L2_FrameInsertChunk(buff, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &frameNum); + L2_FrameInsertChunk(buff, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &slotNum); + L2_FrameInsertChunk(buff, L2_MSG_SRC_ID, L2_MSG_SRC_ID_LEN, &srcId); + L2_FrameInsertChunk(buff, L2_MSG_DST_ID, L2_MSG_DST_ID_LEN, &destId); + + float testData = 3.14; + L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_POSX, L2_MSG_CFM_SRC_POSX_LEN, &testData); + L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_POSY, L2_MSG_CFM_SRC_POSY_LEN, &testData); + L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_POSZ, L2_MSG_CFM_SRC_POSZ_LEN, &testData); + L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_SPEEDX, L2_MSG_CFM_SRC_SPEEDX_LEN, &testData); + L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_SPEEDY, L2_MSG_CFM_SRC_SPEEDY_LEN, &testData); + L2_FrameInsertChunk(buff, L2_MSG_CFM_SRC_SPEEDZ, L2_MSG_CFM_SRC_SPEEDZ_LEN, &testData); + + if (L2_CrcAppend(buff, L2_CMF_PACK_LEN - L2_MSG_CFM_CRC_LEN, L2_MSG_CFM_CRC, L2_CRC16_1021) != SUCCESS) + { + DBG_ERROR("Fail to append CRC.\n"); + ASSERT(false); + } +} + +void forge_svc_frame(uint8_t *buff, uint16_t srcId, uint16_t destId, + uint32_t frameNum, uint32_t slotNum) +{ + uint8_t type = L2_SVC_FRAME; + L2_FrameInsertChunk(buff, L2_MSG_TYPE, L2_MSG_TYPE_LEN, &type); + L2_FrameInsertChunk(buff, L2_MSG_FRAME_NUM, L2_MSG_FRAME_NUM_LEN, &frameNum); + L2_FrameInsertChunk(buff, L2_MSG_SLOT_NUM, L2_MSG_SLOT_NUM_LEN, &slotNum); + L2_FrameInsertChunk(buff, L2_MSG_SRC_ID, L2_MSG_SRC_ID_LEN, &srcId); + L2_FrameInsertChunk(buff, L2_MSG_DST_ID, L2_MSG_DST_ID_LEN, &destId); +} + +TEST(linklayer_reconfig) +{ + int32_t Status; + Status = Linklayer_Reconfig(linkInstPtr, &l2Config); + ASSERT_EQUAL(SUCCESS, Status); + ASSERT_EQUAL(false, linkInstPtr->isEnable); + ASSERT_EQUAL(false, linkInstPtr->isEnable); + ASSERT_EQUAL(0, linkInstPtr->nodeList->len); + ASSERT_EQUAL(0, linkInstPtr->schdEventPool->envCnt); +} + +TEST(linklayer_master_routine) +{ + int32_t Status; + l2Config.myType = L2_NODE_HEAD; + l2Config.myId = 1; + Status = Linklayer_Reconfig(linkInstPtr, &l2Config); + ASSERT_EQUAL(SUCCESS, Status); + Linklayer_Start(linkInstPtr); + // 6 seconds + for (int i = 0; i < 6 * L2_SLOTS_PER_FRAME; i++) + { + tmcReg[TIME_INT_REG]++; + uint32_t slotNum = tmcReg[TIME_INT_REG]%L2_SLOTS_PER_FRAME; + + if (L2_GetCurrentTor(linkInstPtr) == L2_TOR_RX) + { + if (L2_GetCurrentFrameType(linkInstPtr) == L2_ADV_FRAME && slotNum % 4 == 1) + { + forge_adv_frame((uint8_t *)phyInstPtr->recvDataAddr, 1, 2, 0, 0, 0); + PhyWrite(phyInstPtr, TXRX_STATE, 0x01010101); + PhyWrite(phyInstPtr, RECVDATA_STATE, L2_ADV_PACK_LEN); + PhyWrite(phyInstPtr, COASE_FREQEST, COASE_TYPE_10KBPS_20MS); + } + + if (L2_GetCurrentFrameType(linkInstPtr) == L2_CFM_FRAME && slotNum % 4 == 1) + { + forge_cfm_frame((uint8_t *)phyInstPtr->recvDataAddr, 2, 1, + L2_GetCurrentFrameNum(linkInstPtr), L2_GetCurrentSlotNum(linkInstPtr) - 4); + PhyWrite(phyInstPtr, TXRX_STATE, 0x01010101); + PhyWrite(phyInstPtr, RECVDATA_STATE, L2_CMF_PACK_LEN); + PhyWrite(phyInstPtr, COASE_FREQEST, COASE_TYPE_40KBPS_20MS); + } + + if (L2_GetCurrentFrameType(linkInstPtr) == L2_SVC_FRAME && slotNum % 4 == 1) + { + forge_svc_frame((uint8_t *)phyInstPtr->recvDataAddr, 2, 1, + L2_GetCurrentFrameNum(linkInstPtr), L2_GetCurrentSlotNum(linkInstPtr) - 4); + PhyWrite(phyInstPtr, TXRX_STATE, 0x01010101); + PhyWrite(phyInstPtr, RECVDATA_STATE, L2_SVC_PACK_LEN); + PhyWrite(phyInstPtr, COASE_FREQEST, COASE_TYPE_40KBPS_20MS); + } + } + else + { + PhyWrite(phyInstPtr, TXRX_STATE, 0x02020202); + } + + if (PhyRead(phyInstPtr, TXRX_STATE) != 0x02020202) + { + Phy_UpdateState(phyInstPtr); + PhyWrite(phyInstPtr, TXRX_STATE, 0x02020202); + } + + Status = Linklayer_Proc(linkInstPtr); + + if ((tmcReg[TIME_INT_REG] + 1) / 200 < linkInstPtr->netStartTime) + { + ASSERT_EQUAL(EIGNORE, Status); + } + else + { + ASSERT_EQUAL(SUCCESS, Status); + } + + if (L2_isDataAvail(linkInstPtr)) + { + if (L2_GetLastOptFrameType(linkInstPtr) == L2_CFM_FRAME) + { + ASSERT_EQUAL(1, L2_GetNodeListLen(linkInstPtr->nodeList)); + ASSERT_TRUE(L2_isNodeInList(linkInstPtr->nodeList, 2)); + } + } + } +} + +TEST(linklayer_slave_netsetup) +{ + int32_t Status; + TIME_WORD advTime; + uint32_t netStart; + uint32_t frameSyncSlot; + // 30 seconds + l2Config.myType = L2_NODE_MEMBER; + l2Config.myId = 2; + Status = Linklayer_Reconfig(linkInstPtr, &l2Config); + tmcReg[TIME_FRAC_REG] = rand_range(0, TIME_FRAC_MAX)/SIM_STEP*SIM_STEP; + tmcReg[TIME_INT_REG] = rand_range(0, 60 * L2_SLOTS_PER_FRAME); // 0~60s + advTime.frac_part = rand_range(0, TIME_FRAC_MAX)/SIM_STEP*SIM_STEP; + advTime.int_part = rand_range(tmcReg[TIME_INT_REG], tmcReg[TIME_INT_REG] + 5 * L2_SLOTS_PER_FRAME); + + // 74 is the index of bm frame in routine table. + netStart = advTime.int_part / L2_SLOTS_PER_FRAME + rand_range(-4, 0); + + Linklayer_Start(linkInstPtr); + for (int i = 0; i < 12 * L2_SLOTS_PER_FRAME * TIME_FRAC_MAX; i += SIM_STEP) + { + tmcReg[TIME_FRAC_REG] += SIM_STEP; + if (tmcReg[TIME_FRAC_REG] >= TIME_FRAC_MAX) + { + tmcReg[TIME_FRAC_REG] = 0; + tmcReg[TIME_INT_REG]++; + } + + uint32_t slotNum = (tmcReg[TIME_INT_REG] - advTime.int_part%L2_SLOTS_PER_FRAME) % L2_SLOTS_PER_FRAME; + + if (L2_GetNextTor(linkInstPtr) == L2_TOR_TX) + { + // TODO: + } + if (L2_GetCurrentTor(linkInstPtr) == L2_TOR_RX) + { + if (tmcReg[TIME_FRAC_REG] == advTime.frac_part && tmcReg[TIME_INT_REG] == advTime.int_part + 4) + { + frameSyncSlot = advTime.int_part; + forge_adv_frame((uint8_t *)phyInstPtr->recvDataAddr, 1, 2, netStart, 74, netStart); + PhyWrite(phyInstPtr, TXRX_STATE, 0x01010101); + PhyWrite(phyInstPtr, RECVDATA_STATE, L2_ADV_PACK_LEN); + PhyWrite(phyInstPtr, COASE_FREQEST, COASE_TYPE_10KBPS_20MS); + PhyWrite(phyInstPtr, FSTIME_H, frameSyncSlot); + PhyWrite(phyInstPtr, FSTIME_L, Phy_GetTimeComp(L1_10KBPS_20MS_FRAME)); + } + + if (L2_GetCurrentFrameType(linkInstPtr) == L2_CFM_FRAME && slotNum % 4 == 1) + { + frameSyncSlot = L2_GetCurrentFrameNum(linkInstPtr) * L2_SLOTS_PER_FRAME + + L2_GetCurrentSlotNum(linkInstPtr) - 4; + + forge_cfm_frame((uint8_t *)phyInstPtr->recvDataAddr, 1, 2, + frameSyncSlot/L2_SLOTS_PER_FRAME, frameSyncSlot%L2_SLOTS_PER_FRAME); + + PhyWrite(phyInstPtr, TXRX_STATE, 0x01010101); + PhyWrite(phyInstPtr, RECVDATA_STATE, L2_CMF_PACK_LEN); + PhyWrite(phyInstPtr, COASE_FREQEST, COASE_TYPE_40KBPS_20MS); + PhyWrite(phyInstPtr, FSTIME_H, frameSyncSlot); + PhyWrite(phyInstPtr, FSTIME_L, Phy_GetTimeComp(L1_10KBPS_20MS_FRAME)); + } + + if (L2_GetCurrentFrameType(linkInstPtr) == L2_SVC_FRAME && slotNum % 4 == 1) + { + frameSyncSlot = L2_GetCurrentFrameNum(linkInstPtr) * L2_SLOTS_PER_FRAME + + L2_GetCurrentSlotNum(linkInstPtr) - 4; + + forge_svc_frame((uint8_t *)phyInstPtr->recvDataAddr, 1, 2, + frameSyncSlot/L2_SLOTS_PER_FRAME, frameSyncSlot%L2_SLOTS_PER_FRAME); + + PhyWrite(phyInstPtr, TXRX_STATE, 0x01010101); + PhyWrite(phyInstPtr, RECVDATA_STATE, L2_SVC_PACK_LEN); + PhyWrite(phyInstPtr, COASE_FREQEST, COASE_TYPE_40KBPS_20MS); + PhyWrite(phyInstPtr, FSTIME_H, frameSyncSlot); + PhyWrite(phyInstPtr, FSTIME_L, Phy_GetTimeComp(L1_10KBPS_20MS_FRAME)); + } + } + else + { + PhyWrite(phyInstPtr, TXRX_STATE, 0x02020202); + } + + if (PhyRead(phyInstPtr, TXRX_STATE) != 0x02020202) + { + Phy_UpdateState(phyInstPtr); + PhyWrite(phyInstPtr, TXRX_STATE, 0x02020202); + } + + // 2ms interrupt + if (tmcReg[TIME_FRAC_REG] == 200000) + { + Status = Linklayer_Proc(linkInstPtr); + if ((tmcReg[TIME_INT_REG] + 1) / 200 < linkInstPtr->netStartTime) + { + ASSERT_EQUAL(EIGNORE, Status); + } + else + { + ASSERT_EQUAL(SUCCESS, Status); + } + + if (L2_isDataAvail(linkInstPtr)) + { + if (L2_GetLastFrameType(linkInstPtr) == L2_CFM_FRAME) + { + ASSERT_EQUAL(1, L2_GetNodeListLen(linkInstPtr->nodeList)); + ASSERT_TRUE(L2_isNodeInList(linkInstPtr->nodeList, 1)); + } + } + } + } +} + +TEST_SUITE(linklayer_unit_test) +{ + TEST_SUITE_CONFIGURE(linklayer_setup, linklayer_teardown); + RUN_TEST(linklayer_reconfig); + RUN_TEST(linklayer_master_routine); + RUN_TEST(linklayer_slave_netsetup); +} + +int main(void) +{ + RUN_TEST_SUITE(linklayer_unit_test); + TEST_REPORT(); + return TEST_EXIT_CODE; +} diff --git a/df_datalink_sp/unit_test/unit_test_framework.h b/df_datalink_sp/unit_test/unit_test_framework.h new file mode 120000 index 0000000..f5fd5de --- /dev/null +++ b/df_datalink_sp/unit_test/unit_test_framework.h @@ -0,0 +1 @@ +../../unit_test_framework.h \ No newline at end of file