*add unit test.
This commit is contained in:
@@ -0,0 +1,366 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
../../unit_test_framework.h
|
||||
Reference in New Issue
Block a user