|
- #include "plc_device.h"
- #include "plsr_core.h"
- #include "plsr_hal_f407.h"
- #include "plsr_job.h"
- #include "plsr_path.h"
- #include "plsr_persistence.h"
- #include <stdio.h>
- #include <string.h>
-
- #define TEST_WORD_CAPACITY (3000U)
- #define TEST_BIT_CAPACITY (128U)
-
- #define TEST_S0_BASE (100U)
- #define TEST_S1_BASE (200U)
- #define TEST_SEGMENT_STRIDE (10U)
-
- /* 等待条件编码(信捷):高8位条件、低8位来源。 */
- #define TEST_WAIT_CODE(condition, source) \
- ((uint16_t)(((uint16_t)(condition) << 8U) | (uint16_t)(source)))
-
- 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);
- }
-
- /* 写入一个段的数据块(S0 布局,每段 10 字)。 */
- static void TestSetSegment(TEST_MEMORY *memory,
- uint16_t number,
- uint32_t frequency,
- int32_t pulses,
- uint16_t waitCode,
- int32_t waitValue,
- uint16_t jumpSource,
- int32_t jumpValue)
- {
- uint32_t base = TEST_S0_BASE + (uint32_t)number * TEST_SEGMENT_STRIDE;
-
- TestWriteDword(memory, PLSR_DEVICE_D, base, (int32_t)frequency);
- TestWriteDword(memory, PLSR_DEVICE_D, base + 2UL, pulses);
- memory->words[PLSR_DEVICE_D][base + 4UL] = waitCode;
- TestWriteDword(memory, PLSR_DEVICE_D, base + 5UL, waitValue);
- memory->words[PLSR_DEVICE_D][base + 7UL] = (uint16_t)jumpSource;
- TestWriteDword(memory, PLSR_DEVICE_D, base + 8UL, jumpValue);
- }
-
- static void TestResetEnvironment(void)
- {
- PlsrPersistenceTestResetStorage();
- CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
- /* 默认 SFD + 配置方向端子(接线参数,测试用 Y4)。 */
- CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
- CHECK(PlsrInit() == PLSR_RESULT_OK);
- }
-
- static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
- {
- PLSR_CALL call;
-
- (void)memset(&call, 0, sizeof(call));
- call.sequence = 10UL;
- 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 = TEST_S0_BASE;
- call.s1.device = PLSR_DEVICE_D;
- call.s1.address = TEST_S1_BASE;
- call.s2.type = PLSR_OPERAND_CONSTANT;
- call.s2.constant = 1;
- call.dAxis = 0U;
- call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
- return call;
- }
-
- static PLSR_STATUS TestGetStatus(void)
- {
- PLSR_STATUS status;
-
- (void)memset(&status, 0, sizeof(status));
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- return status;
- }
-
- /* 当前段加速完成进入 RUN。 */
- static void TestAccelToRun(void)
- {
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_ACCEL_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_RUN);
- }
-
- static void TestWaitHardwareRunning(void)
- {
- int ticks;
-
- for (ticks = 0; ticks < 20; ticks++)
- {
- if (PlsrHwIsPulseActive(0U) != 0U)
- {
- break;
- }
- PlsrProcess();
- }
- CHECK(PlsrHwIsPulseActive(0U) != 0U);
- }
-
- /* 启动一个 N 段任务(全部 H00 完成条件、顺序跳转)。 */
- static void TestStartSequentialJob(TEST_MEMORY *memory,
- uint16_t segmentCount,
- uint32_t sequence)
- {
- uint16_t segment;
-
- (void)memset(memory, 0, sizeof(*memory));
- TestWriteDword(memory, PLSR_DEVICE_D, TEST_S0_BASE, segmentCount);
- for (segment = 1U; segment <= segmentCount; segment++)
- {
- TestSetSegment(memory,
- segment,
- 1000U + (uint32_t)segment * 1000U,
- (int32_t)(segment * 100),
- TEST_WAIT_CODE(0U, 0U),
- 0,
- 0U,
- 0);
- }
- {
- PLSR_CALL call = TestMakeCall(memory);
-
- call.sequence = sequence;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- CHECK(TestGetStatus().lastCommandResult == PLSR_RESULT_OK);
- }
-
- static void TestSequentialSegments(void)
- {
- TEST_MEMORY memory;
-
- TestResetEnvironment();
- TestStartSequentialJob(&memory, 3U, 10UL);
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 1U);
-
- TestAccelToRun();
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
-
- TestAccelToRun();
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 3U);
-
- TestAccelToRun();
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
- CHECK(TestGetStatus().done != 0U);
- }
-
- static void TestJumpToSpecifiedSegment(void)
- {
- TEST_MEMORY memory;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 3);
- TestSetSegment(&memory, 1U, 1000U, 100, TEST_WAIT_CODE(0U, 0U), 0, 0U, 3);
- TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- TestSetSegment(&memory, 3U, 3000U, 300, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 20UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- CHECK(TestGetStatus().currentSegment == 1U);
-
- /* 段1 完成 → 跳到段3(跳过段2)。 */
- TestAccelToRun();
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 3U);
-
- /* 段3 完成 → 顺序下一段超出 → 任务结束。 */
- TestAccelToRun();
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
- }
-
- static void TestWaitTime(void)
- {
- TEST_MEMORY memory;
- int ticks;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- TestSetSegment(&memory, 1U, 1000U, 100,
- TEST_WAIT_CODE(1U, 0U), 200, 0U, 0);
- TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 30UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
-
- /* 段1 完成 → 进入 WAIT(等 200ms)。 */
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
-
- /* 事件处理同轮已递减 1ms:198 个 tick 后仍在等待。 */
- for (ticks = 0; ticks < 198; ticks++)
- {
- PlsrProcess();
- }
- CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
- CHECK(TestGetStatus().currentSegment == 1U);
-
- /* 第 200 个 tick:计时到,跳到段2。 */
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- }
-
- static void TestWaitSignal(void)
- {
- TEST_MEMORY memory;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- TestSetSegment(&memory, 1U, 1000U, 100,
- TEST_WAIT_CODE(2U, 5U), 10, 0U, 0);
- TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 40UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
-
- /* 段1 完成 → 等 M10(当前 OFF)。 */
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
-
- /* 信号仍 OFF:不跳转。 */
- PlsrProcess();
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
-
- /* 信号置 ON:tick 轮询到后跳段。 */
- memory.bits[1U][10U] = 1U; /* M10 */
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- }
-
- static void TestActTruncatesSegment(void)
- {
- TEST_MEMORY memory;
- int ticks;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- TestSetSegment(&memory, 1U, 1000U, 100,
- TEST_WAIT_CODE(3U, 0U), 200, 0U, 0);
- TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 50UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
-
- /* 不注入 SEGMENT_COMPLETE:ACT 200ms 到时截断当前段。 */
- for (ticks = 0; ticks < 200; ticks++)
- {
- PlsrProcess();
- }
- CHECK(TestGetStatus().state == PLSR_STATE_RUN);
- CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
- PlsrHwTestTriggerUpdate(0U);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- }
-
- static void TestActPendingAfterSegmentDone(void)
- {
- TEST_MEMORY memory;
- int ticks;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- TestSetSegment(&memory, 1U, 1000U, 100,
- TEST_WAIT_CODE(3U, 0U), 200, 0U, 0);
- TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 60UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
-
- /* 段脉冲先完成(ACT 还剩 199ms)→ 停在 ACT_PENDING(WAIT 状态)。 */
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
-
- /* ACT 到时 → 跳段2。 */
- for (ticks = 0; ticks < 199; ticks++)
- {
- PlsrProcess();
- }
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- }
-
- static void TestExtEdgeTruncates(void)
- {
- TEST_MEMORY memory;
- int ticks;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- TestSetSegment(&memory, 1U, 1000U, 100,
- TEST_WAIT_CODE(4U, 4U), 0, 0U, 0);
- TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- /* X0 在任务开始前就有效:进入段时记录为已有电平,不算新边沿。 */
- memory.bits[0U][0U] = 1U;
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 70UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
-
- /* X0 持续 ON:没有新边沿,不应触发。 */
- for (ticks = 0; ticks < 5; ticks++)
- {
- PlsrProcess();
- }
- CHECK(TestGetStatus().state == PLSR_STATE_RUN);
- CHECK(TestGetStatus().currentSegment == 1U);
- TestWaitHardwareRunning();
-
- /* 先拉低再拉高:新上升沿,截断当前段。 */
- memory.bits[0U][0U] = 0U;
- PlsrProcess();
- memory.bits[0U][0U] = 1U;
- PlsrProcess();
- /* EXT freezes the profile but preserves the in-flight physical high/low
- * period. The job must not start segment 2 until the natural update
- * boundary has stopped the old PWM and posted completion. */
- CHECK(TestGetStatus().state == PLSR_STATE_RUN);
- CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
- PlsrHwTestTriggerUpdate(0U);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- }
-
- static void TestExtOrComplete(void)
- {
- TEST_MEMORY memory;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- TestSetSegment(&memory, 1U, 1000U, 100,
- TEST_WAIT_CODE(5U, 4U), 0, 0U, 0);
- TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 80UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
-
- /* 段脉冲先完成 → 正常跳段(EXT 或完成)。 */
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- }
-
- static void TestExtLastSegmentWaitsForPhysicalBoundary(void)
- {
- TEST_MEMORY memory;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 2000U, 50000,
- TEST_WAIT_CODE(4U, 4U), 0, 0U, 0);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 81UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
- TestWaitHardwareRunning();
-
- memory.bits[0U][0U] = 1U;
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_RUN);
- CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
-
- PlsrHwTestTriggerUpdate(0U);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
- CHECK(TestGetStatus().done != 0U);
- }
-
- static void TestDynamicJump(void)
- {
- TEST_MEMORY memory;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 3);
- TestSetSegment(&memory, 1U, 1000U, 100,
- TEST_WAIT_CODE(0U, 0U), 0, 0U, 3);
- TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- /* 段3 跳转也来自 D300(初始 3 = 自跳转,运行期改非法值验证越界)。 */
- TestSetSegment(&memory, 3U, 3000U, 300,
- TEST_WAIT_CODE(0U, 0U), 0, 1U, 300);
- TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 3);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 90UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
-
- /* 段1 完成:跳到段3。 */
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().currentSegment == 3U);
-
- /* 段3 完成前把 D300 改成非法值 → 运行期错误 → ERROR。 */
- TestAccelToRun();
- TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 99);
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ERROR);
- }
-
- static void TestAbsoluteZeroDisplacement(void)
- {
- TEST_MEMORY memory;
- PLSR_COMMAND command;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- /* S1+0 = 1:绝对模式。 */
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 1);
- /* 段1 目标 0(=当前位置 0,零位移);段2 目标 5000。 */
- TestSetSegment(&memory, 1U, 1000U, 0,
- TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- TestSetSegment(&memory, 2U, 2000U, 5000,
- TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
-
- /* 绝对定位需要 positionValid:先 SET_POSITION(0)。 */
- command.sequence = 91UL;
- command.axis = 0U;
- command.opcode = PLSR_CMD_SET_POSITION;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
-
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 92UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- /* 起点段1 零位移:直接跳过,从段2 开始发脉冲。 */
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- }
-
- static void TestZeroJumpBudgetYields(void)
- {
- TEST_MEMORY memory;
- int rounds;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 3);
- /* 段1:零脉冲,跳到段2;段2:零脉冲,动态跳转(初始自跳转);段3:正常段。 */
- TestSetSegment(&memory, 1U, 1000U, 0,
- TEST_WAIT_CODE(0U, 0U), 0, 0U, 2);
- TestSetSegment(&memory, 2U, 1000U, 0,
- TEST_WAIT_CODE(0U, 0U), 0, 1U, 300);
- TestSetSegment(&memory, 3U, 1000U, 100,
- TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 2);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 100UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
-
- /* 每轮 100 次预算:零脉冲自循环链停在段2 并让出,任务不结束。 */
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- CHECK(TestGetStatus().done == 0U);
- for (rounds = 0; rounds < 3; rounds++)
- {
- PlsrProcess();
- }
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 2U);
- CHECK(TestGetStatus().done == 0U);
-
- /* 运行中改动态跳转目标 → 链走向段3(有脉冲)→ 正常执行并完成。 */
- TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 3);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 3U);
- TestAccelToRun();
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
- }
-
- static void TestSelfLoopInterruptedByStop(void)
- {
- TEST_MEMORY memory;
- PLSR_COMMAND command;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 100,
- TEST_WAIT_CODE(0U, 0U), 0, 0U, 1);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 110UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
-
- /* 段1 完成 → 自跳转回段1。 */
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
- CHECK(TestGetStatus().currentSegment == 1U);
-
- /* STOP 可打断自循环。 */
- command.sequence = 111UL;
- command.axis = 0U;
- command.opcode = PLSR_CMD_STOP_IMMEDIATE;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
- == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_STOPPED);
- CHECK(TestGetStatus().done == 0U);
- }
-
- static void TestLastSegmentWaitTime(void)
- {
- TEST_MEMORY memory;
- int ticks;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- TestSetSegment(&memory, 1U, 1000U, 100, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
- /* 最后一段用 WAIT 时间(信捷警告场景:验证不会卡死)。 */
- TestSetSegment(&memory, 2U, 2000U, 200,
- TEST_WAIT_CODE(1U, 0U), 100, 0U, 0);
- {
- PLSR_CALL call = TestMakeCall(&memory);
-
- call.sequence = 120UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- }
- PlsrProcess();
- TestAccelToRun();
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- TestAccelToRun();
-
- /* 段2(最后一段)完成 → 等待 100ms。 */
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
- PlsrProcess();
- CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
-
- /* 计时到 → 任务正常结束。 */
- for (ticks = 0; ticks < 100; ticks++)
- {
- PlsrProcess();
- }
- CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
- CHECK(TestGetStatus().done != 0U);
- }
-
- int main(void)
- {
- TestSequentialSegments();
- TestJumpToSpecifiedSegment();
- TestWaitTime();
- TestWaitSignal();
- TestActTruncatesSegment();
- TestActPendingAfterSegmentDone();
- TestExtEdgeTruncates();
- TestExtOrComplete();
- TestExtLastSegmentWaitsForPhysicalBoundary();
- TestDynamicJump();
- TestAbsoluteZeroDisplacement();
- TestZeroJumpBudgetYields();
- TestSelfLoopInterruptedByStop();
- TestLastSegmentWaitTime();
-
- if (TestFailures != 0)
- {
- (void)printf("FAIL: %d of %d PLSR path checks failed\n",
- TestFailures,
- TestChecks);
- return 1;
- }
- (void)printf("PASS: %d PLSR path checks\n", TestChecks);
- return 0;
- }
|