#include "plc_device.h" #include "plsr_core.h" #include "plsr_job.h" #include "plsr_persistence.h" #include #include #define TEST_WORD_CAPACITY (3000U) #define TEST_BIT_CAPACITY (128U) typedef struct { uint16_t words[3][TEST_WORD_CAPACITY]; uint8_t bits[3][TEST_BIT_CAPACITY]; } TEST_MEMORY; static int TestFailures; static int TestChecks; #define CHECK(condition) \ do \ { \ TestChecks++; \ if (!(condition)) \ { \ TestFailures++; \ (void)printf("FAIL line %d: %s\n", __LINE__, #condition); \ } \ } while (0) static uint8_t TestValidateWords(void *context, PLSR_DEVICE_TYPE device, uint32_t firstAddress, uint32_t wordCount) { (void)context; if ((device > PLSR_DEVICE_FD) || (wordCount == 0UL)) { return 0U; } return (((uint64_t)firstAddress + wordCount) <= TEST_WORD_CAPACITY) ? 1U : 0U; } static uint8_t TestReadWord(void *context, PLSR_DEVICE_TYPE device, uint32_t address, uint16_t *value) { TEST_MEMORY *memory = (TEST_MEMORY *)context; if ((memory == NULL) || (value == NULL) || (device > PLSR_DEVICE_FD) || (address >= TEST_WORD_CAPACITY)) { return 0U; } *value = memory->words[device][address]; return 1U; } static uint8_t TestReadBit(void *context, PLSR_DEVICE_TYPE device, uint32_t address, uint8_t *value) { TEST_MEMORY *memory = (TEST_MEMORY *)context; uint8_t index; if ((memory == NULL) || (value == NULL) || (device < PLSR_DEVICE_X) || (device > PLSR_DEVICE_HM) || (address >= TEST_BIT_CAPACITY)) { return 0U; } index = (uint8_t)(device - PLSR_DEVICE_X); *value = memory->bits[index][address]; return 1U; } static void TestWriteDword(TEST_MEMORY *memory, PLSR_DEVICE_TYPE device, uint32_t address, int32_t value) { uint32_t raw = (uint32_t)value; memory->words[device][address] = (uint16_t)(raw & 0xFFFFUL); memory->words[device][address + 1UL] = (uint16_t)(raw >> 16U); } static void TestWriteSfdDword(uint16_t address, uint32_t value) { CHECK(PlcDeviceWriteSfd(address, (int32_t)(value & 0xFFFFUL)) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd((uint16_t)(address + 1U), (int32_t)(value >> 16U)) == PLC_DEVICE_OK); } static void TestConfigureAxis0K1(void) { CHECK(PlcDeviceWriteSfd(900U, 0) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(907U, 10) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(908U, 17) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(909U, 23) == PLC_DEVICE_OK); TestWriteSfdDword(950U, 1000UL); CHECK(PlcDeviceWriteSfd(952U, 100) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(953U, 120) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(954U, 10) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(955U, 0) == PLC_DEVICE_OK); TestWriteSfdDword(956U, 100000UL); TestWriteSfdDword(958U, 120000UL); TestWriteSfdDword(960U, 500UL); CHECK(PlcDeviceWriteSfd(962U, 50) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(963U, 20) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(964U, 0) == PLC_DEVICE_OK); TestWriteSfdDword(966U, 2000UL); TestWriteSfdDword(968U, 200UL); } static void TestBuildValidBlocks(TEST_MEMORY *memory) { (void)memset(memory, 0, sizeof(*memory)); TestWriteDword(memory, PLSR_DEVICE_D, 100U, 2); TestWriteDword(memory, PLSR_DEVICE_D, 110U, 150000); TestWriteDword(memory, PLSR_DEVICE_D, 112U, 100); memory->words[PLSR_DEVICE_D][114U] = 0U; TestWriteDword(memory, PLSR_DEVICE_D, 115U, 0); memory->words[PLSR_DEVICE_D][117U] = 0U; TestWriteDword(memory, PLSR_DEVICE_D, 118U, 0); TestWriteDword(memory, PLSR_DEVICE_D, 120U, 0); TestWriteDword(memory, PLSR_DEVICE_D, 122U, -50); memory->words[PLSR_DEVICE_D][124U] = 0x0100U; TestWriteDword(memory, PLSR_DEVICE_D, 125U, 0); memory->words[PLSR_DEVICE_D][127U] = 0U; TestWriteDword(memory, PLSR_DEVICE_D, 128U, 2); TestWriteDword(memory, PLSR_DEVICE_D, 200U, 0); TestWriteDword(memory, PLSR_DEVICE_D, 202U, 0); TestWriteDword(memory, PLSR_DEVICE_HD, 10U, 1); } static PLSR_CALL TestMakeCall(TEST_MEMORY *memory) { PLSR_CALL call; (void)memset(&call, 0, sizeof(call)); call.sequence = 77UL; call.source.context = memory; call.source.validateWords = TestValidateWords; call.source.readWord = TestReadWord; call.source.readBit = TestReadBit; call.s0.device = PLSR_DEVICE_D; call.s0.address = 100UL; call.s1.device = PLSR_DEVICE_D; call.s1.address = 200UL; call.s2.type = PLSR_OPERAND_CONSTANT; call.s2.constant = 1; call.dAxis = 0U; call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD; return call; } static void TestValidSnapshotAndLiveFrequency(void) { TEST_MEMORY memory; PLSR_CALL call; PLSR_PARSE_CONTEXT context; PLSR_JOB_SNAPSHOT snapshot; PLSR_PARSE_DETAIL detail; uint32_t frequency; uint8_t clamped; TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); context.logicalPosition = 0; context.positionValid = 0U; CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_OK); CHECK(detail.result == PLSR_RESULT_OK); CHECK(snapshot.segmentCount == 2U); CHECK(snapshot.startSegment == 1U); CHECK(snapshot.s2Set == 1U); CHECK(snapshot.outputMode == PLSR_OUTPUT_PULSE_DIR); CHECK(snapshot.directionPoint == 4U); CHECK(snapshot.directionNegativeLogic == 0U); CHECK(snapshot.positiveBacklashPulses == 17U); CHECK(snapshot.negativeBacklashPulses == 23U); CHECK(snapshot.s2.defaultSpeed == 1000UL); CHECK(snapshot.s2.maximumSpeed == 100000UL); CHECK(snapshot.s2.startSpeed == 100000UL); CHECK(snapshot.speedClamped == 1U); CHECK(snapshot.segments[0].targetFrequency == 100000UL); CHECK((snapshot.segments[0].flags & PLSR_SEGMENT_FLAG_SPEED_CLAMPED) != 0U); CHECK(snapshot.segments[1].targetFrequency == 1000UL); CHECK((snapshot.segments[1].flags & PLSR_SEGMENT_FLAG_DEFAULT_SPEED) != 0U); CHECK((snapshot.segments[1].flags & PLSR_SEGMENT_FLAG_SELF_LOOP) != 0U); CHECK(snapshot.hasSelfLoop == 1U); CHECK(snapshot.initialDirectionPositive == 1U); CHECK(PlcDeviceWriteSfd(900U, (1U << 1U)) == PLC_DEVICE_OK); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_OK); CHECK(snapshot.directionNegativeLogic == 1U); CHECK(snapshot.initialDirectionPositive == 1U); CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK); TestWriteDword(&memory, PLSR_DEVICE_D, 112U, 9999); CHECK(snapshot.segments[0].pulseOrTarget == 100); TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 2500); CHECK(PlsrResolveLiveFrequency(&snapshot, 1U, &frequency, &clamped) == PLSR_RESULT_OK); CHECK(frequency == 2500UL); CHECK(clamped == 0U); TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 200000); CHECK(PlsrResolveLiveFrequency(&snapshot, 1U, &frequency, &clamped) == PLSR_RESULT_OK); CHECK(frequency == 100000UL); CHECK(clamped == 1U); call.s2.type = PLSR_OPERAND_DATA; call.s2.data.device = PLSR_DEVICE_HD; call.s2.data.address = 10UL; CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_OK); CHECK(snapshot.s2Set == 1U); } static void TestValidationFailures(void) { TEST_MEMORY memory; PLSR_CALL call; PLSR_PARSE_CONTEXT context = {0, 0U}; PLSR_JOB_SNAPSHOT snapshot; PLSR_PARSE_DETAIL detail; TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); call.s1.address = 120UL; CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_BLOCK_OVERLAP); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); memory.words[PLSR_DEVICE_D][103U] = 1U; CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_RESERVED_NOT_ZERO); CHECK(detail.address == 103UL); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); TestWriteDword(&memory, PLSR_DEVICE_D, 100U, 101); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_SEGMENT_OVERFLOW); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); TestWriteDword(&memory, PLSR_DEVICE_D, 110U, -1); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_INVALID_FREQUENCY); CHECK(detail.segment == 1U); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); memory.words[PLSR_DEVICE_D][124U] = 0x0405U; CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_INVALID_WAIT); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 3); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_INVALID_JUMP); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); TestWriteDword(&memory, PLSR_DEVICE_D, 118U, 2); TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 1); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_PATH_CYCLE); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); TestWriteDword(&memory, PLSR_DEVICE_D, 200U, 1); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_POSITION_INVALID); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); call.s0.address = UINT32_MAX - 5UL; CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_ADDRESS_OVERFLOW); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); call.s2.constant = 5; CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_INVALID_S2); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); CHECK(PlcDeviceWriteSfd(962U, 356) == PLC_DEVICE_OK); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_INVALID_S2); CHECK(PlcDeviceWriteSfd(962U, 50) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(964U, 1) == PLC_DEVICE_OK); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_INVALID_S2); CHECK(PlcDeviceWriteSfd(964U, 0) == PLC_DEVICE_OK); } static void TestDynamicReferences(void) { TEST_MEMORY memory; PLSR_CALL call; PLSR_PARSE_CONTEXT context = {0, 0U}; PLSR_JOB_SNAPSHOT snapshot; PLSR_PARSE_DETAIL detail; TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); memory.words[PLSR_DEVICE_D][124U] = 0x0101U; TestWriteDword(&memory, PLSR_DEVICE_D, 125U, 300); TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 25); memory.words[PLSR_DEVICE_D][127U] = 1U; TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 302); TestWriteDword(&memory, PLSR_DEVICE_D, 302U, 2); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_OK); CHECK(snapshot.segments[1].waitSource == PLSR_VALUE_D); CHECK(snapshot.segments[1].waitValueOrAddress == 300); CHECK(snapshot.segments[1].jumpSource == PLSR_VALUE_D); CHECK(snapshot.segments[1].jumpValueOrAddress == 302); memory.words[PLSR_DEVICE_D][124U] = 0x0404U; TestWriteDword(&memory, PLSR_DEVICE_D, 125U, 7); memory.bits[0][7U] = 1U; memory.words[PLSR_DEVICE_D][127U] = 0U; TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 2); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_OK); } static void TestOutputAndDivider(void) { TEST_MEMORY memory; PLSR_CALL call; PLSR_PARSE_CONTEXT context = {0, 0U}; PLSR_JOB_SNAPSHOT snapshot; PLSR_PARSE_DETAIL detail; uint16_t psc; uint16_t arr; TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); CHECK(PlcDeviceWriteSfd(900U, (1U << 13U)) == PLC_DEVICE_OK); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_OK); CHECK(snapshot.outputMode == PLSR_OUTPUT_AB); CHECK(snapshot.pairedTimerClockHz == 84000000UL); CHECK(PlsrCalculateTimerDivider(168000000UL, 1UL, &psc, &arr) == PLSR_RESULT_OK); CHECK(PlsrCalculateTimerDivider(84000000UL, 100000UL, &psc, &arr) == PLSR_RESULT_OK); CHECK(PlsrCalculateTimerDivider(84000000UL, 0UL, &psc, &arr) == PLSR_RESULT_INVALID_ARGUMENT); CHECK(PlsrCalculateTimerDivider(1UL, 100000UL, &psc, &arr) == PLSR_RESULT_DIVIDER_UNREPRESENTABLE); CHECK(PlcDeviceWriteSfd(900U, 0) == PLC_DEVICE_OK); } static void TestEquivalentSnapshot(void) { TEST_MEMORY memory; PLSR_CALL call; PLSR_PARSE_CONTEXT context = {0, 1U}; PLSR_JOB_SNAPSHOT snapshot; PLSR_PARSE_DETAIL detail; uint32_t liveFrequency; uint8_t clamped; TestBuildValidBlocks(&memory); TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 40000); call = TestMakeCall(&memory); CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK); TestWriteSfdDword(902U, 3UL); TestWriteSfdDword(904U, 2UL); TestWriteSfdDword(956U, 60000UL); TestWriteSfdDword(958U, 0UL); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_OK); CHECK(snapshot.equivalent.unitCode == 1U); CHECK(snapshot.equivalent.pulsesPerRevolution == 3UL); CHECK(snapshot.equivalent.movementPerRevolution == 2UL); CHECK(snapshot.inputDefaultSpeed == 1000UL); CHECK(snapshot.inputMaximumSpeed == 60000UL); CHECK(snapshot.s2.defaultSpeed == 1500UL); CHECK(snapshot.s2.maximumSpeed == 90000UL); CHECK(snapshot.segments[0].targetFrequency == 60000UL); CHECK(snapshot.segments[1].targetFrequency == 1500UL); TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 20000); CHECK(PlsrResolveLiveFrequency(&snapshot, 1U, &liveFrequency, &clamped) == PLSR_RESULT_OK); CHECK(liveFrequency == 30000UL); CHECK(clamped == 0U); TestWriteSfdDword(902U, 0UL); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_INVALID_S2); CHECK(detail.address == 902U); TestConfigureAxis0K1(); } static void TestLimitSnapshot(void) { TEST_MEMORY memory; PLSR_CALL call; PLSR_PARSE_CONTEXT context = {0, 1U}; PLSR_JOB_SNAPSHOT snapshot; PLSR_PARSE_DETAIL detail; TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(912U, (1U << 2U) | (1U << 3U)) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(915U, 0x0703U) == PLC_DEVICE_OK); TestWriteSfdDword(930U, 100UL); TestWriteSfdDword(932U, (uint32_t)(int32_t)-100); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_OK); CHECK(snapshot.limits.softLimitEnabled == 1U); CHECK(snapshot.limits.positiveSoftLimitPulses == 100); CHECK(snapshot.limits.negativeSoftLimitPulses == -100); CHECK(snapshot.limits.positiveInputPoint == 3U); CHECK(snapshot.limits.negativeInputPoint == 7U); CHECK(snapshot.limits.positiveInputActiveLow == 1U); CHECK(snapshot.limits.negativeInputActiveLow == 1U); TestWriteSfdDword(930U, (uint32_t)(int32_t)-100); TestWriteSfdDword(932U, 100UL); CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail) == PLSR_RESULT_INVALID_S2); CHECK(detail.address == 930U); TestConfigureAxis0K1(); CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(915U, 0xFFFFU) == PLC_DEVICE_OK); TestWriteSfdDword(930U, 0UL); TestWriteSfdDword(932U, 0UL); } static void TestCompatibleParseErrors(void) { TEST_MEMORY memory; PLSR_CALL call; int32_t code; int32_t block; PlsrPersistenceTestResetStorage(); CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TestConfigureAxis0K1(); CHECK(PlsrInit() == PLSR_RESULT_OK); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); TestWriteDword(&memory, PLSR_DEVICE_D, 110U, -1); call.sequence = 700UL; CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK); CHECK(PlcDeviceReadSd(1011U, &block) == PLC_DEVICE_OK); CHECK(code == 1); CHECK(block == 1); TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 1000); call.s2.constant = 5; call.sequence = 701UL; CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK); CHECK(code == 3); call.s2.constant = 1; CHECK(PlcDeviceWriteSfd(962U, 0U) == PLC_DEVICE_OK); call.sequence = 702UL; CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK); CHECK(code == 15); CHECK(PlcDeviceWriteSfd(962U, 50U) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(963U, 101U) == PLC_DEVICE_OK); call.sequence = 703UL; CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK); CHECK(code == 16); CHECK(PlcDeviceWriteSfd(963U, 0U) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK); TestWriteSfdDword(930U, 0UL); TestWriteSfdDword(932U, 0UL); call.sequence = 704UL; CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK); CHECK(code == 4); CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK); CHECK(PlcDeviceWriteSfd(906U, 0xFFU) == PLC_DEVICE_OK); call.sequence = 705UL; CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlcDeviceReadSd(1010U, &code) == PLC_DEVICE_OK); CHECK(code == 26); TestConfigureAxis0K1(); } static void TestCoreSubmission(void) { TEST_MEMORY memory; PLSR_CALL call; PLSR_STATUS status; PLSR_PARSE_DETAIL detail; TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); call.sequence = 500UL; CHECK(PlsrInit() == PLSR_RESULT_OK); CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK); CHECK(status.lastCommandResult == PLSR_RESULT_OK); CHECK(status.state == PLSR_STATE_ACCEL); CHECK(status.jobValid == 1U); CHECK(status.segmentCount == 2U); CHECK(status.startSegment == 1U); CHECK(status.s2Set == 1U); CHECK(status.speedClamped == 1U); CHECK(PlsrGetLastParseDetail(0U, &detail) == PLSR_RESULT_OK); CHECK(detail.result == PLSR_RESULT_OK); } static void TestDefaultSfdStartable(void) { TEST_MEMORY memory; PLSR_CALL call; PLSR_STATUS status; /* 全新 Flash:默认 S2 参数(FOLLOW=50、最大速度=100000 等)应可直接启动。 */ PlsrPersistenceTestResetStorage(); CHECK(PlcDeviceInit() == PLC_DEVICE_OK); CHECK(PlcDeviceGetLastSfdLoadResult() == PLSR_PERSISTENCE_DEFAULTED); TestBuildValidBlocks(&memory); call = TestMakeCall(&memory); call.sequence = 600UL; /* 方向端子是接线参数,未配置(0xFF)时 PULSE/DIR 应报资源错误。 */ CHECK(PlsrInit() == PLSR_RESULT_OK); CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK); CHECK(status.lastCommandResult == PLSR_RESULT_INVALID_RESOURCE); CHECK(status.state == PLSR_STATE_IDLE); /* 用户配置方向端子后,其余出厂默认参数应能直接启动。 */ CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK); call.sequence = 601UL; CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK); CHECK(status.lastCommandResult == PLSR_RESULT_OK); CHECK(status.state == PLSR_STATE_ACCEL); CHECK(status.jobValid == 1U); CHECK(status.s2Set == 1U); CHECK(status.speedClamped == 1U); CHECK(status.directionPoint == 4U); /* 回到 IDLE,避免资源泄漏影响后续。 */ CHECK(PlsrPostCommand(&(PLSR_COMMAND){602U, 0U, PLSR_CMD_STOP_IMMEDIATE, 0}) == PLSR_RESULT_QUEUED); PlsrProcess(); CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE) == PLSR_RESULT_OK); PlsrProcess(); CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK); CHECK(status.state == PLSR_STATE_STOPPED); } int main(void) { PlsrPersistenceTestResetStorage(); CHECK(PlcDeviceInit() == PLC_DEVICE_OK); TestConfigureAxis0K1(); TestValidSnapshotAndLiveFrequency(); TestValidationFailures(); TestDynamicReferences(); TestOutputAndDivider(); TestEquivalentSnapshot(); TestLimitSnapshot(); TestCompatibleParseErrors(); TestDefaultSfdStartable(); TestCoreSubmission(); if (TestFailures != 0) { (void)printf("FAIL: %d of %d PLSR job checks failed\n", TestFailures, TestChecks); return 1; } (void)printf("PASS: %d PLSR job checks\n", TestChecks); return 0; }