NorthStar-Endurance-TestBench/EnduranceTestBench/nehemis/test.c

299 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file batch_endurance_testbench.c
*
* @brief Batch mode test bench:
* 1. Write to all nodes (at 100ms intervals)
* 2. Read all nodes
* 3. Verify positions (retry mismatch up to 2 times)
* 4. Cycle complete reset for next iteration
*
* @copyright
*/
#include "enduranceTestBench.h"
#include "stdlib.h"
/* CANopen includes */
#include <gen_define.h>
#include <co_canopen.h>
#include "../nms_hal/hal_system.h"
/******************************************************************************
* Macro constant declarations
******************************************************************************/
#define ENDURANCE_TEST_BENCH_MAX_RETRY_CNT 3u
#define ENDURANCE_TEST_BENCH_TIMEOUT 1000u
#define ENDURANCE_TEST_BENCH_LSS_NODE_COUNT 20u
#define ENDURANCE_TEST_BENCH_POSITION_SETPOINT_INDEX 0x6002
#define ENDURANCE_TEST_BENCH_POSITION_SETPOINT_SUB_INDEX 0x0
#define ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_INDEX 0x6004
#define ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_SUB_INDEX 0x0
/* Batch delay between node operations (in ms) */
#define NODE_OP_DELAY_MS 100u
/******************************************************************************
* Type Declarations
******************************************************************************/
typedef enum
{
TEST_BENCH_BATCH_WRITE, /* Write to nodes in batch */
TEST_BENCH_BATCH_WRITE_WAIT, /* Wait between writes */
TEST_BENCH_BATCH_READ, /* Read all nodes */
TEST_BENCH_BATCH_READ_WAIT, /* Wait between reads */
TEST_BENCH_BATCH_VERIFY, /* Verify all nodes */
TEST_BENCH_CYCLE_COMPLETE, /* End of cycle, reset for next iteration */
TEST_BENCH_IDLE /* Idle state (optional) */
} SdlTestBenchState_en;
typedef enum
{
TEST_BENCH_DATA_VERIF_DEFAULT,
TEST_BENCH_DATA_VERIF_SUCCESS,
TEST_BENCH_DATA_VERIF_FAILURE,
TEST_BENCH_DATA_VERIF_SKIPPED,
} TestBenchStatus_en;
typedef struct
{
uint8 targetPositions_gau8[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT];
uint8 readPosition_gau8[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT];
TestBenchStatus_en status_en[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT];
} TestBenchData_en;
/******************************************************************************
* Global variable declarations
******************************************************************************/
static TestBenchData_en testBenchData_en;
static uint8 currentNode_gu8 = 0u;
static SdlTestBenchState_en testBenchState_en = TEST_BENCH_IDLE;
static uint32 readPosition_gu32;
static uint8 storedTargetPos = 0u; /* Flag: target written to current node */
static uint8 readMismatchRetries_u8 = 0u; /* Retry count for verify mismatches */
static uint64 writeTime_u64 = 0uLL;
static uint64 readExecutedTime_u64 = 0uLL;
static uint64 cycleStartTime_u64 = 0uLL;
static uint8 retries_u8 = 0u; /* General retry counter for SDO communication */
/******************************************************************************
* Public Function Definitions
******************************************************************************/
void TestRun(void)
{
uint64 currentTime_u64;
HalSystemGetRunTimeMs(&currentTime_u64);
/* Initialization: start new cycle if in idle or cycle complete state */
if (testBenchState_en == TEST_BENCH_IDLE || testBenchState_en == TEST_BENCH_CYCLE_COMPLETE)
{
/* Prepare new cycle: reset all node statuses and choose new target positions */
for (uint8 i = 0u; i < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT; i++)
{
testBenchData_en.targetPositions_gau8[i] = (uint8)(rand() % 256);
testBenchData_en.readPosition_gau8[i] = 0u;
testBenchData_en.status_en[i] = TEST_BENCH_DATA_VERIF_DEFAULT;
}
currentNode_gu8 = 0u;
storedTargetPos = 0u;
retries_u8 = 0u;
readMismatchRetries_u8 = 0u;
cycleStartTime_u64 = currentTime_u64;
testBenchState_en = TEST_BENCH_BATCH_WRITE;
}
switch (testBenchState_en)
{
/* -------------------- Batch Write -------------------- */
case TEST_BENCH_BATCH_WRITE:
{
if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT)
{
if (storedTargetPos == 0)
{
/* Use the pre-assigned target value for this node */
uint8 value_u8 = testBenchData_en.targetPositions_gau8[currentNode_gu8];
RET_T retVal_en = coSdoWrite(
(currentNode_gu8 + 1),
ENDURANCE_TEST_BENCH_POSITION_SETPOINT_INDEX,
ENDURANCE_TEST_BENCH_POSITION_SETPOINT_SUB_INDEX,
&value_u8,
sizeof(uint8),
CO_FALSE,
ENDURANCE_TEST_BENCH_TIMEOUT
);
if (retVal_en == RET_OK)
{
storedTargetPos = 1; /* Mark that target is written for this node */
HalSystemGetRunTimeMs(&writeTime_u64);
retries_u8 = 0u;
testBenchState_en = TEST_BENCH_BATCH_WRITE_WAIT;
}
else
{
retries_u8++;
if (retries_u8 >= ENDURANCE_TEST_BENCH_MAX_RETRY_CNT)
{
testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SKIPPED;
/* Mark node as skipped and move on */
currentNode_gu8++;
retries_u8 = 0u;
storedTargetPos = 0u;
testBenchState_en = TEST_BENCH_BATCH_WRITE;
}
}
}
}
else
{
/* Finished writing to all nodes */
currentNode_gu8 = 0u; /* Reset index for read phase */
testBenchState_en = TEST_BENCH_BATCH_READ;
}
break;
}
case TEST_BENCH_BATCH_WRITE_WAIT:
{
/* Wait 100ms between writes */
if ((currentTime_u64 - writeTime_u64) >= 500)
{
/* Move to next node write */
currentNode_gu8++;
storedTargetPos = 0u; /* Reset for next node */
testBenchState_en = TEST_BENCH_BATCH_WRITE;
}
break;
}
/* -------------------- Batch Read -------------------- */
case TEST_BENCH_BATCH_READ:
{
if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT)
{
RET_T retVal_en = coSdoRead(
(currentNode_gu8 + 1),
ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_INDEX,
ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_SUB_INDEX,
(uint8*)&readPosition_gu32,
sizeof(uint32),
CO_FALSE,
ENDURANCE_TEST_BENCH_TIMEOUT
);
if (retVal_en == RET_OK)
{
retries_u8 = 0u;
/* The read indication callback is assumed to update
* testBenchData_en.readPosition_gau8[currentNode_gu8] and
* then we simply continue to next node after a small delay.
*/
HalSystemGetRunTimeMs(&readExecutedTime_u64);
testBenchData_en.readPosition_gau8[currentNode_gu8] = (uint8)readPosition_gu32;
testBenchState_en = TEST_BENCH_BATCH_READ_WAIT;
}
else if (retVal_en == RET_SERVICE_BUSY && retries_u8 < ENDURANCE_TEST_BENCH_MAX_RETRY_CNT)
{
retries_u8++;
}
else
{
/* If read fails, mark as skipped and move on */
testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SKIPPED;
currentNode_gu8++;
retries_u8 = 0u;
}
}
else
{
/* Finished reading all nodes */
currentNode_gu8 = 0u; /* Reset for verification phase */
testBenchState_en = TEST_BENCH_BATCH_VERIFY;
}
break;
}
case TEST_BENCH_BATCH_READ_WAIT:
{
/* Wait 100ms between node reads */
if ((currentTime_u64 - readExecutedTime_u64) >= 10)
{
currentNode_gu8++;
testBenchState_en = TEST_BENCH_BATCH_READ;
}
break;
}
/* -------------------- Batch Verify -------------------- */
case TEST_BENCH_BATCH_VERIFY:
{
if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT)
{
/* Process only if the node was not already skipped */
if (testBenchData_en.status_en[currentNode_gu8] != TEST_BENCH_DATA_VERIF_SKIPPED)
{
uint8 diff = abs(testBenchData_en.targetPositions_gau8[currentNode_gu8] -
testBenchData_en.readPosition_gau8[currentNode_gu8]);
if (diff <= 1)
{
testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SUCCESS;
}
else
{
testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_FAILURE;
}
}
/* Move to the next node in any case */
currentNode_gu8++;
testBenchState_en = TEST_BENCH_BATCH_VERIFY;
}
else
{
/* All nodes verified; complete cycle */
testBenchState_en = TEST_BENCH_CYCLE_COMPLETE;
}
break;
}
/* -------------------- Cycle Complete -------------------- */
case TEST_BENCH_CYCLE_COMPLETE:
{
/* Optionally, you can log or process the batch results here */
/* Reset all node data for the next cycle */
for (uint8 i = 0u; i < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT; i++)
{
testBenchData_en.targetPositions_gau8[i] = 0u;
testBenchData_en.readPosition_gau8[i] = 0u;
testBenchData_en.status_en[i] = TEST_BENCH_DATA_VERIF_DEFAULT;
}
currentNode_gu8 = 0u;
storedTargetPos = 0u;
retries_u8 = 0u;
readMismatchRetries_u8 = 0u;
/* Start next cycle */
testBenchState_en = TEST_BENCH_IDLE;
break;
}
default:
break;
}
}
/******************************************************************************
* Callback Functions
******************************************************************************/
void TestReadInd(uint8 sdoNr_u8, uint16 index_u16, uint8 subIndex_u8, uint32 errorVal_u32)
{
HalSystemGetRunTimeMs(&writeTime_u64);
}
void TestWriteInd(uint8 sdoNr_u8, uint16 index_u16, uint8 subIndex_u8, uint32 size, uint32 errorVal_u32)
{
HalSystemGetRunTimeMs(&readExecutedTime_u64);
//testBenchData_en.readPosition_gau8[currentNode_gu8] = (uint8)readPosition_gu32;
}