Upload files to "/"
This commit is contained in:
285
test_handler.cpp
Normal file
285
test_handler.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
// test_handler.cpp - Hardware Test Handler Implementation
|
||||
|
||||
#include "test_handler.h"
|
||||
#include "can_handler.h"
|
||||
#include "task_config.h"
|
||||
#include "psram_buffer.h"
|
||||
|
||||
TestConfig testConfig;
|
||||
TestResult testResult;
|
||||
static uint32_t expectedSequence = 0;
|
||||
static uint32_t receivedSequence = 0;
|
||||
static TaskHandle_t testTaskHandle = NULL;
|
||||
|
||||
void initTestHandler() {
|
||||
testConfig.mode = TEST_MODE_IDLE;
|
||||
testConfig.frameCount = 1000;
|
||||
testConfig.intervalUs = 1000;
|
||||
testConfig.canId = 0x100;
|
||||
testConfig.dataLen = 8;
|
||||
testConfig.useFD = true;
|
||||
testConfig.running = false;
|
||||
|
||||
memset(&testResult, 0, sizeof(TestResult));
|
||||
}
|
||||
|
||||
uint32_t generateTestFrame(uint32_t sequence, CanFrame& frame) {
|
||||
frame.timestamp = micros();
|
||||
frame.id = testConfig.canId;
|
||||
frame.len = testConfig.useFD ? (testConfig.dataLen > 8 ? testConfig.dataLen : 8) : 8;
|
||||
frame.flags = testConfig.useFD ? 0x01 : 0x00;
|
||||
|
||||
frame.data[0] = (sequence >> 24) & 0xFF;
|
||||
frame.data[1] = (sequence >> 16) & 0xFF;
|
||||
frame.data[2] = (sequence >> 8) & 0xFF;
|
||||
frame.data[3] = sequence & 0xFF;
|
||||
frame.data[4] = 0xDE;
|
||||
frame.data[5] = 0xAD;
|
||||
frame.data[6] = 0xBE;
|
||||
frame.data[7] = 0xEF;
|
||||
|
||||
for (int i = 8; i < frame.len && i < 64; i++) {
|
||||
frame.data[i] = (uint8_t)(sequence + i);
|
||||
}
|
||||
|
||||
return sequence;
|
||||
}
|
||||
|
||||
bool validateTestFrame(const CanFrame& frame, uint32_t& expectedSeq) {
|
||||
if (frame.id != testConfig.canId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t receivedSeq = ((uint32_t)frame.data[0] << 24) |
|
||||
((uint32_t)frame.data[1] << 16) |
|
||||
((uint32_t)frame.data[2] << 8) |
|
||||
((uint32_t)frame.data[3]);
|
||||
|
||||
if (receivedSeq != expectedSeq) {
|
||||
uint32_t lost = receivedSeq - expectedSeq;
|
||||
testResult.framesLost += lost;
|
||||
expectedSeq = receivedSeq + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
expectedSeq++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void testTxTask(void *pvParameters) {
|
||||
Serial.println("Test TX Task started");
|
||||
|
||||
uint32_t sequence = 0;
|
||||
testResult.startTime = millis();
|
||||
testResult.framesSent = 0;
|
||||
testResult.framesReceived = 0;
|
||||
testResult.framesLost = 0;
|
||||
testResult.errors = 0;
|
||||
|
||||
uint8_t originalMode = getCANMode();
|
||||
setCANMode(2);
|
||||
delay(100);
|
||||
|
||||
expectedSequence = 0;
|
||||
|
||||
while (testConfig.running && sequence < testConfig.frameCount) {
|
||||
CanFrame frame;
|
||||
generateTestFrame(sequence, frame);
|
||||
|
||||
if (sendCANFrame(frame.id, frame.data, frame.len, testConfig.useFD)) {
|
||||
testResult.framesSent++;
|
||||
sequence++;
|
||||
} else {
|
||||
testResult.errors++;
|
||||
}
|
||||
|
||||
if (testConfig.intervalUs > 0) {
|
||||
delayMicroseconds(testConfig.intervalUs);
|
||||
}
|
||||
|
||||
while (canController.available()) {
|
||||
CANFDMessage rxMsg;
|
||||
if (canController.receive(rxMsg)) {
|
||||
CanFrame rxFrame;
|
||||
rxFrame.id = rxMsg.id;
|
||||
rxFrame.len = rxMsg.len;
|
||||
memcpy(rxFrame.data, rxMsg.data, rxMsg.len);
|
||||
|
||||
if (rxFrame.id == testConfig.canId) {
|
||||
if (validateTestFrame(rxFrame, expectedSequence)) {
|
||||
testResult.framesReceived++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delay(100);
|
||||
|
||||
while (canController.available()) {
|
||||
CANFDMessage rxMsg;
|
||||
if (canController.receive(rxMsg)) {
|
||||
CanFrame rxFrame;
|
||||
rxFrame.id = rxMsg.id;
|
||||
rxFrame.len = rxMsg.len;
|
||||
memcpy(rxFrame.data, rxMsg.data, rxMsg.len);
|
||||
|
||||
if (rxFrame.id == testConfig.canId) {
|
||||
if (validateTestFrame(rxFrame, expectedSequence)) {
|
||||
testResult.framesReceived++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testResult.endTime = millis();
|
||||
testResult.durationMs = testResult.endTime - testResult.startTime;
|
||||
|
||||
if (testResult.durationMs > 0) {
|
||||
testResult.frameRate = (float)testResult.framesSent / ((float)testResult.durationMs / 1000.0f);
|
||||
}
|
||||
|
||||
if (testResult.framesSent > 0) {
|
||||
testResult.lossRate = (float)testResult.framesLost / (float)testResult.framesSent * 100.0f;
|
||||
}
|
||||
|
||||
testResult.passed = (testResult.framesLost == 0 && testResult.framesSent == testResult.framesReceived);
|
||||
|
||||
setCANMode(originalMode);
|
||||
testConfig.running = false;
|
||||
testConfig.mode = TEST_MODE_IDLE;
|
||||
|
||||
Serial.printf("Test completed: Sent=%d, Received=%d, Lost=%d, Rate=%.1f fps, Loss=%.2f%%\n",
|
||||
testResult.framesSent, testResult.framesReceived, testResult.framesLost,
|
||||
testResult.frameRate, testResult.lossRate);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
testTaskHandle = NULL;
|
||||
}
|
||||
|
||||
bool startLoopbackTest(uint32_t frameCount, uint32_t intervalUs) {
|
||||
if (testConfig.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
testConfig.mode = TEST_MODE_LOOPBACK;
|
||||
testConfig.frameCount = frameCount;
|
||||
testConfig.intervalUs = intervalUs;
|
||||
testConfig.canId = 0x100;
|
||||
testConfig.dataLen = 8;
|
||||
testConfig.useFD = false;
|
||||
testConfig.running = true;
|
||||
|
||||
Serial.printf("Starting loopback test: %d frames, %d us interval\n", frameCount, intervalUs);
|
||||
|
||||
xTaskCreatePinnedToCore(
|
||||
testTxTask,
|
||||
"TEST_TX",
|
||||
4096,
|
||||
NULL,
|
||||
6,
|
||||
&testTaskHandle,
|
||||
0
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool startStressTest(uint32_t frameCount, uint8_t dataLen, bool useFD) {
|
||||
if (testConfig.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
testConfig.mode = TEST_MODE_STRESS;
|
||||
testConfig.frameCount = frameCount;
|
||||
testConfig.intervalUs = 0;
|
||||
testConfig.canId = 0x200;
|
||||
testConfig.dataLen = dataLen;
|
||||
testConfig.useFD = useFD;
|
||||
testConfig.running = true;
|
||||
|
||||
Serial.printf("Starting stress test: %d frames, %d bytes, FD=%s\n",
|
||||
frameCount, dataLen, useFD ? "true" : "false");
|
||||
|
||||
xTaskCreatePinnedToCore(
|
||||
testTxTask,
|
||||
"TEST_TX",
|
||||
4096,
|
||||
NULL,
|
||||
6,
|
||||
&testTaskHandle,
|
||||
0
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool startSequenceTest(uint32_t frameCount, uint32_t canId) {
|
||||
if (testConfig.running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
testConfig.mode = TEST_MODE_SEQUENCE;
|
||||
testConfig.frameCount = frameCount;
|
||||
testConfig.intervalUs = 1000;
|
||||
testConfig.canId = canId;
|
||||
testConfig.dataLen = 64;
|
||||
testConfig.useFD = true;
|
||||
testConfig.running = true;
|
||||
|
||||
Serial.printf("Starting sequence test: %d frames, ID=0x%X\n", frameCount, canId);
|
||||
|
||||
xTaskCreatePinnedToCore(
|
||||
testTxTask,
|
||||
"TEST_TX",
|
||||
4096,
|
||||
NULL,
|
||||
6,
|
||||
&testTaskHandle,
|
||||
0
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void stopTest() {
|
||||
if (testConfig.running) {
|
||||
testConfig.running = false;
|
||||
if (testTaskHandle != NULL) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateTest() {
|
||||
}
|
||||
|
||||
bool isTestRunning() {
|
||||
return testConfig.running;
|
||||
}
|
||||
|
||||
TestMode getTestMode() {
|
||||
return testConfig.mode;
|
||||
}
|
||||
|
||||
TestResult getTestResult() {
|
||||
return testResult;
|
||||
}
|
||||
|
||||
void getTestResultJSON(char* buffer, size_t bufferSize) {
|
||||
snprintf(buffer, bufferSize,
|
||||
"{\"running\":%s,\"mode\":%d,\"result\":{"
|
||||
"\"framesSent\":%d,\"framesReceived\":%d,\"framesLost\":%d,"
|
||||
"\"errors\":%d,\"durationMs\":%d,\"frameRate\":%.1f,"
|
||||
"\"lossRate\":%.2f,\"passed\":%s}}",
|
||||
testConfig.running ? "true" : "false",
|
||||
testConfig.mode,
|
||||
testResult.framesSent,
|
||||
testResult.framesReceived,
|
||||
testResult.framesLost,
|
||||
testResult.errors,
|
||||
testResult.durationMs,
|
||||
testResult.frameRate,
|
||||
testResult.lossRate,
|
||||
testResult.passed ? "true" : "false");
|
||||
}
|
||||
Reference in New Issue
Block a user