|
- #include "plc_device.h"
- #include "modbus_data_store.h"
- #include "plsr_core.h"
- #include "plsr_hal_f407.h"
- #include "plsr_job.h"
- #include "plsr_modbus_control.h"
- #include "plsr_persistence.h"
- #include "plsr_resource.h"
- #include "plsr_self_test.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)
-
- 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;
- (void)device;
- 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, (uint16_t)(value & 0xFFFFUL))
- == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd((uint16_t)(address + 1U),
- (uint16_t)(value >> 16U)) == PLC_DEVICE_OK);
- }
-
- static void TestSetSegment(TEST_MEMORY *memory,
- uint16_t number,
- uint32_t frequency,
- int32_t pulses)
- {
- uint32_t base = TEST_S0_BASE + (uint32_t)number * 10UL;
-
- TestWriteDword(memory, PLSR_DEVICE_D, base, (int32_t)frequency);
- TestWriteDword(memory, PLSR_DEVICE_D, base + 2UL, pulses);
- memory->words[PLSR_DEVICE_D][base + 4UL] = 0U;
- TestWriteDword(memory, PLSR_DEVICE_D, base + 5UL, 0);
- memory->words[PLSR_DEVICE_D][base + 7UL] = 0U;
- TestWriteDword(memory, PLSR_DEVICE_D, base + 8UL, 0);
- }
-
- static void TestResetEnvironment(void)
- {
- PlsrPersistenceTestResetStorage();
- CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
- 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;
- }
-
- static int32_t TestReadSdDword(uint16_t lowAddress)
- {
- int32_t lowWord = 0;
- int32_t highWord = 0;
- uint32_t rawValue;
-
- CHECK(PlcDeviceReadSd(lowAddress, &lowWord) == PLC_DEVICE_OK);
- CHECK(PlcDeviceReadSd((uint16_t)(lowAddress + 1U), &highWord)
- == PLC_DEVICE_OK);
- rawValue = ((uint32_t)lowWord & 0xFFFFUL)
- | (((uint32_t)highWord & 0xFFFFUL) << 16U);
- return (int32_t)rawValue;
- }
-
- /* ---- HAL 单测 ---- */
-
- static void TestMapping(void)
- {
- (void)PlsrHwInit();
- CHECK(PlsrHwGetTimerClockHz(0U) == 168000000UL);
- CHECK(PlsrHwGetTimerClockHz(1U) == 84000000UL);
- CHECK(PlsrHwGetTimerClockHz(2U) == 168000000UL);
- CHECK(PlsrHwGetTimerClockHz(3U) == 84000000UL);
- CHECK(PlsrHwGetTimerClockHz(4U) == 0UL);
- CHECK(PlsrHwResolveDirectionPoint(4U) != 0U);
- CHECK(PlsrHwResolveDirectionPoint(8U) == 0U);
- CHECK(PlsrHwResolveDirectionPoint(20U) != 0U);
- CHECK(PlsrHwResolveDirectionPoint(21U) == 0U);
- }
-
- static void TestDirDelaySequence(void)
- {
- (void)PlsrHwInit();
- PLSR_HW_START_PARAMS params;
- uint16_t psc;
- uint16_t arr;
- int ticks;
-
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 1000UL;
- params.targetPulses = 100;
- params.directionPoint = 4U;
- params.directionPositive = 1U;
- params.directionDelayMs = 10U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
- CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwIsPulseActive(0U) == 0U);
-
- for (ticks = 0; ticks < 9; ticks++)
- {
- PlsrHwTick(0U);
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
-
- PlsrHwTick(0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
-
- /* 首个非零频率启动 PWM,ARR/CCR 与分频计算一致。 */
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
- CHECK(PlsrHwIsPulseActive(0U) == 1U);
- CHECK(PlsrCalculateTimerDivider(168000000UL, 1000UL, &psc, &arr)
- == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetArr(0U) == arr);
- CHECK(PlsrHwTestGetPsc(0U) == psc);
- CHECK(PlsrHwTestGetCcr(0U) == arr / 2UL);
- /* PWM 模式 1(OC1M=110):复位后 CCMR1=0 冻结,无此配置输出恒定电平。 */
- CHECK((PlsrHwTestGetCcmr1(0U) & 0x70UL) == 0x60UL);
- /* ARR/CCR 预装载(ARPE=CR1 bit7,OC1PE=CCMR1 bit3):
- * 运行中调频不产生提前回绕,否则加速段多出 ~ln(f1/f0) 个假脉冲。 */
- CHECK((PlsrHwTestGetCr1(0U) & 0x80UL) == 0x80UL);
- CHECK((PlsrHwTestGetCcmr1(0U) & 0x08UL) == 0x08UL);
-
- /* 段间同向衔接:方向不变时跳过方向延时,直接进入 PWM 待启动。 */
- CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
- params.targetPulses = 50;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
- CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
-
- /* 反向时方向延时仍生效。 */
- params.directionPositive = 0U;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
- CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
-
- /* Bit1 negative logic reverses only the electrical DIR terminal. */
- params.directionNegativeLogic = 1U;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
- CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
- params.directionPositive = 1U;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
- }
-
- static void TestDirectionBatch(void)
- {
- PLSR_HW_START_PARAMS params;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 0UL;
- params.targetPulses = 10;
- params.outputMode = PLSR_OUTPUT_PULSE_DIR;
- params.directionPoint = 4U;
- params.directionPositive = 1U;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- params.directionPoint = 3U;
- params.directionNegativeLogic = 1U;
- CHECK(PlsrHwStartPulse(1U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
- CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
-
- PlsrHwBeginDirectionBatch();
- params.directionPoint = 4U;
- params.directionPositive = 0U;
- params.directionNegativeLogic = 0U;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- params.directionPoint = 3U;
- params.directionNegativeLogic = 1U;
- CHECK(PlsrHwStartPulse(1U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
- CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
- PlsrHwEndDirectionBatch();
- CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
- CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
- }
-
- static void TestHardwareCounterLeases(void)
- {
- PLSR_HW_START_PARAMS params;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 100000UL;
- params.targetPulses = 10;
- params.outputMode = PLSR_OUTPUT_PULSE_DIR;
- params.directionPoint = 4U;
- params.directionPositive = 1U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
- /* Replacing a prepared segment must release and reacquire the same lease
- * instead of orphaning TIM9 under the old preparation. */
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
- CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
- /* A hardware-counted PWM starts in the inactive half-cycle. TIM9/TIM12
- * must see a low ITR level when external-clock mode is armed, otherwise
- * the startup OCREF level is counted before a terminal pulse exists. */
- CHECK(PlsrHwTestGetCnt(0U) == PlsrHwTestGetCcr(0U));
- params.directionPoint = 5U;
- CHECK(PlsrHwStartPulse(2U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
- CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
- /* PWM compare and update flags coexist at the period boundary. A
- * software fallback axis must consume both in one ISR and count once. */
- PlsrHwTestTriggerUpdateAndCompare(2U);
- CHECK(PlsrHwGetEmittedPulses(2U) == 1);
- PlsrHwTestTriggerCompare(2U);
- CHECK(PlsrHwGetEmittedPulses(2U) == 1);
-
- CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
- CHECK(PlsrHwStopPulse(2U) == PLSR_RESULT_OK);
- CHECK(PlsrHwUsesHardwareCounter(0U) == 0U);
- params.directionPoint = 5U;
- CHECK(PlsrHwStartPulse(2U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 1U);
- CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
- while (PlsrHwGetState(2U) != PLSR_HW_STATE_DONE)
- {
- PlsrHwTestTriggerUpdate(2U);
- }
- CHECK(PlsrHwGetEmittedPulses(2U) == 10);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
- }
-
- static void TestPulseDirTargetUpdateBoundaryStop(void)
- {
- PLSR_HW_START_PARAMS params;
- uint32_t activeArr;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 100000UL;
- params.targetPulses = 3;
- params.outputMode = PLSR_OUTPUT_PULSE_DIR;
- params.directionPoint = 5U;
- params.directionPositive = 1U;
-
- CHECK(PlsrHwStartPulse(2U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
- activeArr = PlsrHwTestGetArr(2U);
- PlsrHwTestTriggerUpdate(2U);
- CHECK(PlsrHwGetEmittedPulses(2U) == 1);
- CHECK(PlsrHwTestGetArr(2U) == activeArr);
-
- /* target-1 pre-arms a long low tail but must not stop yet. */
- PlsrHwTestTriggerUpdate(2U);
- CHECK(PlsrHwGetEmittedPulses(2U) == 2);
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetArr(2U) == 0xFFFFUL);
- CHECK(PlsrHwTestGetCcr(2U) == 0xFFFFUL);
-
- /* The target update is the completed physical pulse boundary. */
- PlsrHwTestTriggerUpdate(2U);
- CHECK(PlsrHwGetEmittedPulses(2U) == 3);
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwTestGetPwmEnabled(2U) == 0U);
- }
-
- static void TestSoftwareCounterPeerDrain(void)
- {
- PLSR_HW_START_PARAMS params;
- uint8_t axis;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 100000UL;
- params.targetPulses = 10;
- params.outputMode = PLSR_OUTPUT_PULSE_DIR;
- params.directionPositive = 1U;
-
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- params.directionPoint = (uint8_t)(4U + axis);
- CHECK(PlsrHwStartPulse(axis, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(axis, 100000UL) == PLSR_RESULT_OK);
- }
- CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
- CHECK(PlsrHwUsesHardwareCounter(1U) == 1U);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
- CHECK(PlsrHwUsesHardwareCounter(3U) == 0U);
-
- PlsrHwTestSetUpdatePending(3U);
- PlsrHwTestTriggerUpdate(2U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 0);
- CHECK(PlsrHwGetEmittedPulses(1U) == 0);
- CHECK(PlsrHwGetEmittedPulses(2U) == 1);
- CHECK(PlsrHwGetEmittedPulses(3U) == 1);
- }
-
- static void TestCwCcwSequence(void)
- {
- PLSR_HW_START_PARAMS params;
- uint16_t psc;
- uint16_t arr;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 2000UL;
- params.targetPulses = 3;
- params.outputMode = PLSR_OUTPUT_CW_CCW;
- params.directionPoint = PLSR_HW_DIR_POINT_NONE;
- params.directionPositive = 1U;
- params.directionDelayMs = 10U;
-
- CHECK(PlsrHwStartPulse(1U, ¶ms) == PLSR_RESULT_INVALID_AXIS);
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
- CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
- PlsrHwTestTriggerCompare(1U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 0);
- PlsrHwTestTriggerCompare(0U);
- PlsrHwTestTriggerCompare(0U);
- PlsrHwTestTriggerCompare(0U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 3);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
- CHECK(PlsrHwTestGetCc1PolarityInverted(0U) == 0U);
- PlsrHwTestTriggerUpdate(0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
-
- params.frequencyHz = 1000UL;
- params.targetPulses = 2;
- params.directionPositive = 0U;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
- CHECK(PlsrCalculateTimerDivider(84000000UL, 1000UL, &psc, &arr)
- == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetPsc(1U) == psc);
- CHECK(PlsrHwTestGetArr(1U) == arr);
- PlsrHwTestTriggerCompare(1U);
- PlsrHwTestTriggerCompare(1U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 2);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
- PlsrHwTestTriggerUpdate(1U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
- }
-
- static void TestFastRefreshControlTick(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_STATUS status;
- int tick;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(902U, 1UL);
- TestWriteSfdDword(904U, 1UL);
- CHECK(PlcDeviceWriteSfd(906U, 4U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(950U, 1000UL);
- CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(954U, 0U) == PLC_DEVICE_OK);
- /* Linear curve: 10Hz/ms becomes exactly 1Hz per 0.1ms tick. */
- CHECK(PlcDeviceWriteSfd(955U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(956U, 100000UL);
- TestWriteSfdDword(958U, 0UL);
- TestWriteSfdDword(960U, 0UL);
- CHECK(PlcDeviceWriteSfd(962U, 50U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(963U, 0U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(964U, 2U) == PLC_DEVICE_OK);
- TestWriteSfdDword(966U, 2000UL);
- TestWriteSfdDword(968U, 200UL);
-
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 10000);
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 0);
- call = TestMakeCall(&memory);
- call.sequence = 0xB000UL;
- call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_ACCEL);
- CHECK(status.jobValid != 0U);
- CHECK(PlsrTestGetJobRefreshCode(0U) == 2U);
- CHECK(PlsrTestGetProfileRefreshHz(0U) == 10000UL);
- CHECK(PlsrTestGetProfileActive(0U) != 0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
- CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 0UL);
-
- /* A normal 1ms process pass must not advance a 0.1ms profile. */
- PlsrProcess();
- CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 0UL);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
- CHECK(PlsrTestGetJobRefreshCode(0U) == 2U);
- CHECK(PlsrTestGetProfileActive(0U) != 0U);
- PlsrControlTick100us();
- CHECK(PlsrTestGetProfileFrequencyHz(0U) == 1UL);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwGetCurrentFrequencyHz(0U) > 0UL);
- for (tick = 1; tick < 10; tick++)
- {
- PlsrControlTick100us();
- }
- CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 10UL);
- PlsrProcess();
- CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 10UL);
- for (tick = 0; tick < 10; tick++)
- {
- PlsrControlTick100us();
- }
- CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 20UL);
- }
-
- static void TestDynamicFrequencyRetarget(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_STATUS status;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(902U, 1UL);
- TestWriteSfdDword(904U, 1UL);
- CHECK(PlcDeviceWriteSfd(906U, 4U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(950U, 1000UL);
- CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(954U, 0U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(955U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(956U, 5000UL);
- TestWriteSfdDword(958U, 1000UL);
- TestWriteSfdDword(960U, 0UL);
- CHECK(PlcDeviceWriteSfd(962U, 50U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(963U, 0U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(964U, 2U) == PLC_DEVICE_OK);
- TestWriteSfdDword(966U, 2000UL);
- TestWriteSfdDword(968U, 200UL);
-
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 100000);
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 0);
- call = TestMakeCall(&memory);
- call.sequence = 0xB100UL;
- call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.currentFrequencyHz == 1000UL);
- CHECK(status.targetFrequencyHz == 1000UL);
-
- /* Only the 100us control tick may observe/apply a refreshCode=2 edit. */
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 4000);
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.targetFrequencyHz == 1000UL);
- CHECK(status.currentFrequencyHz == 1000UL);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.targetFrequencyHz == 4000UL);
- CHECK(status.currentFrequencyHz == 1001UL);
- PlsrControlTick100us();
- CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 1002UL);
-
- /* Down-retarget follows the configured slope instead of jumping. */
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 500);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.targetFrequencyHz == 500UL);
- CHECK(status.currentFrequencyHz == 1001UL);
-
- /* Raw zero means the immutable S2 default speed. */
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 0);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.targetFrequencyHz == 1000UL);
- CHECK(status.currentFrequencyHz == 1000UL);
-
- /* Above-maximum values clamp; invalid negatives retain the last safe
- * target and produce one sticky rejection for that observed value. */
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 8000);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.targetFrequencyHz == 5000UL);
- CHECK(status.currentFrequencyHz == 1001UL);
- CHECK(status.speedClamped != 0U);
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, -1);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.targetFrequencyHz == 5000UL);
- CHECK(status.currentFrequencyHz == 1002UL);
- CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_INVALID_FREQUENCY);
- CHECK(status.liveFrequencyRejectCount == 1UL);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.liveFrequencyRejectCount == 1UL);
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 2000);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.targetFrequencyHz == 2000UL);
- CHECK(status.currentFrequencyHz == 1004UL);
- CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_OK);
- }
-
- static void TestZeroFrequencyWaits(void)
- {
- (void)PlsrHwInit();
- PLSR_HW_START_PARAMS params;
-
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 0UL;
- params.targetPulses = 50;
- params.directionPoint = PLSR_HW_DIR_POINT_NONE;
- params.directionPositive = 1U;
- params.directionDelayMs = 0U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
- PlsrHwTick(0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
-
- /* 起始速度为 0:profile 升频后首个非零频率才启动 PWM。 */
- CHECK(PlsrHwSetFrequency(0U, 10UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
- }
-
- static void TestPulseCounting(void)
- {
- (void)PlsrHwInit();
- PLSR_HW_START_PARAMS params;
- int pulse;
-
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 1000UL;
- params.targetPulses = 5;
- params.directionPoint = PLSR_HW_DIR_POINT_NONE;
- params.directionPositive = 1U;
- params.directionDelayMs = 0U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwGetEmittedPulses(0U) == 0);
-
- /* EGR.UG 只加载预装载寄存器,不能被当作物理脉冲。
- * 共享 IRQ 入口在对应定时器没有 UIF 时也必须无动作。 */
- PlsrHwOnTimerUpdate(0U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 0);
-
- for (pulse = 0; pulse < 4; pulse++)
- {
- PlsrHwTestTriggerUpdate(0U);
- CHECK(PlsrHwGetEmittedPulses(0U) == pulse + 1);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- }
- /* 第 5 个脉冲:到目标,停止 + 段完成事件。 */
- PlsrHwTestTriggerUpdate(0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwIsPulseActive(0U) == 0U);
-
- /* 停止后再触发更新中断无动作。 */
- PlsrHwTestTriggerUpdate(0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- }
-
- static void TestAbPhaseAndCounting(void)
- {
- PLSR_HW_START_PARAMS params;
- static const uint8_t positiveA[4] = {1U, 1U, 0U, 0U};
- static const uint8_t positiveB[4] = {0U, 1U, 1U, 0U};
- static const uint8_t negativeA[4] = {0U, 1U, 1U, 0U};
- static const uint8_t negativeB[4] = {1U, 1U, 0U, 0U};
- uint32_t oldArr;
- uint32_t oldBasePsc;
- uint32_t oldPairPsc;
- uint32_t newPeriod;
- int quarter;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 1000UL;
- params.targetPulses = 4;
- params.outputMode = PLSR_OUTPUT_AB;
- params.directionPoint = 4U; /* AB 模式必须忽略独立 DIR 点。 */
- params.directionPositive = 1U;
- params.directionDelayMs = 10U; /* AB 模式不得执行方向延时。 */
-
- CHECK(PlsrHwStartPulse(1U, ¶ms) == PLSR_RESULT_INVALID_AXIS);
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
- CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
- CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
- CHECK((PlsrHwTestGetPsc(0U) + 1UL)
- == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
- CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
- CHECK(PlsrHwTestGetCcr(0U) == PlsrHwTestGetCcr(1U));
- CHECK(PlsrHwTestGetCcr(0U)
- == (PlsrHwTestGetArr(0U) + 1UL) / 2UL);
- /* 两相从精确 00 边界起步;CC1IF 会在开中断前再次清除。 */
- CHECK(PlsrHwTestGetCnt(0U)
- == ((PlsrHwTestGetArr(0U) + 1UL) * 3UL) / 4UL + 1UL);
- CHECK(PlsrHwTestGetCnt(1U) == PlsrHwTestGetCcr(1U) + 1UL);
- CHECK(PlsrHwIsAbStartupPriming(0U) == 0U);
-
- /* 任一物理 timer update 不能直接计作完整 AB 周期。 */
- PlsrHwTestTriggerUpdate(0U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 0);
-
- /* 正向:00→10→11→01→00;四次相位跳变只计一个脉冲。 */
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- CHECK(PlsrHwTestGetAbPhaseA(0U) == positiveA[quarter]);
- CHECK(PlsrHwTestGetAbPhaseB(0U) == positiveB[quarter]);
- }
- CHECK(PlsrHwGetEmittedPulses(0U) == 1);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
-
- /* 运行中调频先排队,不能让相差 1/4 周期的两路各自加载 ARR。 */
- oldArr = PlsrHwTestGetArr(0U);
- oldBasePsc = PlsrHwTestGetPsc(0U);
- oldPairPsc = PlsrHwTestGetPsc(1U);
- CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- CHECK(PlsrHwGetEmittedPulses(0U) == 2);
- CHECK(PlsrHwTestGetArr(0U) == oldArr);
- CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
- CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
-
- CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
- CHECK(PlsrHwTestGetArr(0U) == oldArr);
- CHECK(PlsrHwTestGetArr(1U) == oldArr);
- CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
- CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
-
- for (quarter = 0; quarter < 3; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- CHECK(PlsrHwTestGetArr(0U) == oldArr);
- CHECK(PlsrHwTestGetArr(1U) == oldArr);
- CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
- CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
- }
- /* 回到 00 后,两路同时装载新频率并从精确 90° 位置重启。 */
- PlsrHwTestAdvanceAbQuarter(0U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 3);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK((PlsrHwTestGetArr(0U) != oldArr)
- || (PlsrHwTestGetPsc(0U) != oldBasePsc));
- CHECK((PlsrHwTestGetPsc(0U) + 1UL)
- == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
- CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
- newPeriod = PlsrHwTestGetArr(0U) + 1UL;
- CHECK(PlsrHwTestGetCnt(0U) == (newPeriod * 3UL) / 4UL + 1UL);
- CHECK(PlsrHwTestGetCnt(1U) == newPeriod / 2UL + 1UL);
-
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- CHECK(PlsrHwGetEmittedPulses(0U) == 4);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- PlsrHwTick(0U);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
- CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
- CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
-
- /* 反向:00→01→11→10→00。 */
- params.targetPulses = 1;
- params.directionPositive = 0U;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- CHECK(PlsrHwTestGetAbPhaseA(0U) == negativeA[quarter]);
- CHECK(PlsrHwTestGetAbPhaseB(0U) == negativeB[quarter]);
- }
- CHECK(PlsrHwGetEmittedPulses(0U) == 1);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- PlsrHwTick(0U);
-
- /* 紧急停止即使发生在周期中间,也必须回到安全 00。 */
- params.targetPulses = 10;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- PlsrHwTestAdvanceAbQuarter(0U);
- CHECK(PlsrHwTestGetAbQuarter(0U) == 1U);
- CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
- CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
- CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
- }
-
- static void TestTwoAbAxesIndependent(void)
- {
- PLSR_HW_START_PARAMS params;
- int quarter;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 1000UL;
- params.targetPulses = 1;
- params.outputMode = PLSR_OUTPUT_AB;
- params.directionPoint = PLSR_HW_DIR_POINT_NONE;
- params.directionPositive = 1U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwStartPulse(2U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(2U, 2000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
- CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
- CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
-
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- PlsrHwTick(0U);
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwGetEmittedPulses(2U) == 0);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
- CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
-
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(2U);
- }
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwGetEmittedPulses(2U) == 1);
- PlsrHwTick(2U);
- }
-
- static void TestDualAbHardwareCountersAndResume(void)
- {
- PLSR_HW_START_PARAMS params;
- int quarter;
- int cycle;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 100000UL;
- params.targetPulses = 6;
- params.outputMode = PLSR_OUTPUT_AB;
- params.directionPoint = PLSR_HW_DIR_POINT_NONE;
- params.directionPositive = 1U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwStartPulse(2U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 1U);
- CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
-
- for (cycle = 0; cycle < 2; cycle++)
- {
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- }
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(2U);
- }
- CHECK(PlsrHwGetEmittedPulses(0U) == 2);
- CHECK(PlsrHwGetEmittedPulses(2U) == 1);
-
- /* The source timer can cross its edge just before the ITR slave observes
- * it. The phase-corrected public count must not regress from 2 to 1 in
- * that synchronization window, otherwise core PAUSE raises COUNTER_FAULT. */
- PlsrHwTestSetAbQuarterWithoutCounter(0U, 1U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 2);
- PlsrHwTestSetAbQuarterWithoutCounter(0U, 0U);
-
- /* Request PAUSE after the source edge but before the following 00. The
- * pair must finish this already-started cycle instead of forcing GPIO 00
- * and re-emitting its source edge after RESUME. */
- PlsrHwTestAdvanceAbQuarter(0U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 2);
- CHECK(PlsrHwSetFrequency(0U, 0UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetAbQuarter(0U) == 1U);
- CHECK((PlsrHwTestGetCr1(0U) & 1UL) != 0UL);
- CHECK((PlsrHwTestGetCr1(1U) & 1UL) != 0UL);
- for (quarter = 1; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- CHECK(PlsrHwGetEmittedPulses(0U) == 3);
- CHECK((PlsrHwTestGetCr1(0U) & 1UL) == 0UL);
- CHECK((PlsrHwTestGetCr1(1U) & 1UL) == 0UL);
- CHECK(PlsrHwResumePulse(0U) == PLSR_RESULT_INVALID_STATE);
- PlsrHwTick(0U);
- CHECK(PlsrHwGetEmittedPulses(0U) == 3);
- CHECK(PlsrHwResumePulse(0U) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
-
- for (cycle = 0; cycle < 3; cycle++)
- {
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwGetEmittedPulses(0U) == 6);
- PlsrHwTick(0U);
- CHECK(PlsrHwUsesHardwareCounter(0U) == 0U);
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
-
- for (cycle = 1; cycle < 6; cycle++)
- {
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(2U);
- }
- }
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwGetEmittedPulses(2U) == 6);
- PlsrHwTick(2U);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
- }
-
- static void TestDualAbSimultaneousFastGate(void)
- {
- PLSR_HW_START_PARAMS params;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 100000UL;
- params.targetPulses = 200000;
- params.outputMode = PLSR_OUTPUT_AB;
- params.directionPoint = PLSR_HW_DIR_POINT_NONE;
- params.directionPositive = 1U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- params.directionPositive = 0U;
- CHECK(PlsrHwStartPulse(2U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 1U);
-
- /* Both lag flags become pending before the first equal-priority handler.
- * Its entry scan must freeze all four timers before publishing axis 0. */
- PlsrHwTestSignalDualAbFinalBoundary(0U);
- CHECK(PlsrHwTestGetAbFullGateCount() == 1UL);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwGetEmittedPulses(0U) == 200000);
- CHECK((PlsrHwTestGetCr1(2U) & 1UL) == 0UL);
- CHECK((PlsrHwTestGetCr1(3U) & 1UL) == 0UL);
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
-
- /* The lag axis for negative Q2/Q3 is Q2. */
- PlsrHwTestTriggerCompare(2U);
- CHECK(PlsrHwTestGetAbFullGateCount() == 2UL);
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwGetEmittedPulses(2U) == 200000);
- PlsrHwTick(0U);
- PlsrHwTick(2U);
- CHECK(PlsrHwUsesHardwareCounter(0U) == 0U);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
-
- /* Repeat with pair 2's flag injected after the first entry scan. The
- * second scan must gate it before pair 0 performs deferred GPIO/counter
- * cleanup, and both pairs must still be frozen at a real 00 boundary. */
- (void)PlsrHwInit();
- params.directionPositive = 1U;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- params.directionPositive = 0U;
- CHECK(PlsrHwStartPulse(2U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
-
- PlsrHwTestSignalDualAbStaggeredFinalBoundary(0U);
- CHECK(PlsrHwTestGetAbFullGateCount() == 1UL);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwGetEmittedPulses(0U) == 200000);
- CHECK((PlsrHwTestGetCr1(2U) & 1UL) == 0UL);
- CHECK((PlsrHwTestGetCr1(3U) & 1UL) == 0UL);
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
- PlsrHwTestTriggerCompare(2U);
- CHECK(PlsrHwTestGetAbFullGateCount() == 2UL);
- CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
- CHECK(PlsrHwGetEmittedPulses(2U) == 200000);
- PlsrHwTick(0U);
- PlsrHwTick(2U);
- CHECK(PlsrHwUsesHardwareCounter(0U) == 0U);
- CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
- }
-
- static void TestAbFrequencyLimits(void)
- {
- PLSR_HW_START_PARAMS params;
- uint32_t oldArr;
- int quarter;
-
- (void)PlsrHwInit();
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 1UL;
- params.targetPulses = 100;
- params.outputMode = PLSR_OUTPUT_AB;
- params.directionPoint = PLSR_HW_DIR_POINT_NONE;
- params.directionPositive = 1U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 1UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
- CHECK((PlsrHwTestGetPsc(0U) + 1UL)
- == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
- CHECK(PlsrHwTestGetArr(0U) <= 65535UL);
-
- oldArr = PlsrHwTestGetArr(0U);
- CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetArr(0U) == oldArr);
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- /* This request is 99 cycles away from target-1: it must be applied by
- * the frequency one-shot CCIE, not accidentally by the final guard. */
- CHECK(PlsrHwTestGetArr(0U) != oldArr);
- CHECK(PlsrHwTestGetArr(0U) == 839UL);
- CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
- CHECK((PlsrHwTestGetPsc(0U) + 1UL)
- == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
- CHECK(PlsrHwTestGetArr(0U) >= 3UL);
- CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
- }
-
- static void TestStopAndInvalidArgs(void)
- {
- (void)PlsrHwInit();
- PLSR_HW_START_PARAMS params;
-
- (void)memset(¶ms, 0, sizeof(params));
- params.frequencyHz = 1000UL;
- params.targetPulses = 100;
- params.directionPoint = PLSR_HW_DIR_POINT_NONE;
- params.directionPositive = 1U;
- params.directionDelayMs = 0U;
-
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_OK);
- CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
- CHECK(PlsrHwIsPulseActive(0U) == 1U);
- CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
- CHECK(PlsrHwIsPulseActive(0U) == 0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
-
- CHECK(PlsrHwStartPulse(4U, ¶ms) == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrHwStartPulse(0U, NULL) == PLSR_RESULT_INVALID_ARGUMENT);
- params.targetPulses = 0;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_INVALID_ARGUMENT);
- params.targetPulses = 1;
- params.outputMode = PLSR_OUTPUT_CW_CCW;
- CHECK(PlsrHwStartPulse(1U, ¶ms) == PLSR_RESULT_INVALID_AXIS);
- params.outputMode = (PLSR_OUTPUT_MODE)99;
- CHECK(PlsrHwStartPulse(0U, ¶ms) == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrHwSetFrequency(4U, 1000UL) == PLSR_RESULT_INVALID_ARGUMENT);
- CHECK(PlsrHwStopPulse(4U) == PLSR_RESULT_INVALID_ARGUMENT);
- }
-
- /* ---- 端到端集成:START → 硬件 → 计数 → 事件 → 段间 → 完成 ---- */
-
- static void TestEndToEndTwoSegments(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_STATUS status;
- uint16_t initialPsc;
- uint16_t initialArr;
- int ticks;
- int pulse;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
- TestSetSegment(&memory, 1U, 1000U, 100);
- TestSetSegment(&memory, 2U, 2000U, 200);
-
- call = TestMakeCall(&memory);
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_ACCEL);
- CHECK(status.currentSegment == 1U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
-
- /* DIR 延时 10ms → PWM 启动(段1 起始速度 0,profile 升频后启动)。 */
- for (ticks = 0; ticks < 9; ticks++)
- {
- PlsrProcess();
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
- CHECK(PlsrCalculateTimerDivider(168000000UL, 75UL,
- &initialPsc, &initialArr)
- == PLSR_RESULT_OK);
- CHECK(PlsrHwTestGetPsc(0U) == initialPsc);
- CHECK(PlsrHwTestGetArr(0U) == initialArr);
-
- /* 加速完成 → 状态机进入 RUN。 */
- for (ticks = 0; ticks < 500; ticks++)
- {
- PlsrProcess();
- if (TestGetStatus().state == PLSR_STATE_RUN)
- {
- break;
- }
- }
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_RUN);
- CHECK(status.currentSegment == 1U);
-
- /* 段1 脉冲完成:100 次更新中断 → SEGMENT_COMPLETE → 段2 启动。 */
- for (pulse = 0; pulse < 100; pulse++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_ACCEL);
- CHECK(status.currentSegment == 2U);
- CHECK(status.logicalPosition == 100);
- CHECK(status.taskPulses == 100);
- CHECK(status.totalPulses == 100);
- CHECK(TestReadSdDword(1000U) == 2);
- CHECK(TestReadSdDword(1002U) == 0);
-
- /* 段2:DIR 延时 → PWM → 加速 → RUN。 */
- for (ticks = 0; ticks < 600; ticks++)
- {
- PlsrProcess();
- if (TestGetStatus().state == PLSR_STATE_RUN)
- {
- break;
- }
- }
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_RUN);
- CHECK(status.currentSegment == 2U);
-
- /* 段2 脉冲完成 → 任务结束。 */
- for (pulse = 0; pulse < 200; pulse++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.done != 0U);
- CHECK(status.logicalPosition == 300);
- CHECK(status.taskPulses == 300);
- CHECK(status.totalPulses == 300);
- CHECK(TestReadSdDword(1000U) == 2);
- CHECK(TestReadSdDword(1002U) == 200);
- CHECK(TestReadSdDword(1004U) == 200);
- CHECK(TestReadSdDword(1006U) == 0);
- {
- int32_t hsdPulses;
- int32_t hsdEquivalent;
-
- CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
- CHECK(hsdPulses == 300);
- CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent)
- == PLC_DEVICE_OK);
- CHECK(hsdEquivalent == 300);
- }
- /* 终态转换后 HAL 回 IDLE(允许重新启动),脉冲已停止。 */
- CHECK(PlsrHwIsPulseActive(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- }
-
- static void TestEndToEndAbSegment(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_STATUS status;
- int quarter;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, -2);
-
- call = TestMakeCall(&memory);
- call.sequence = 15UL;
- call.outputModeOverride = PLSR_OUTPUT_AB;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_ACCEL);
- CHECK(status.outputMode == PLSR_OUTPUT_AB);
- CHECK(status.directionPoint == PLSR_DIRECTION_POINT_NONE);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
- CHECK(PlsrHwTestGetCc1PolarityInverted(0U) != 0U);
- CHECK(PlsrHwTestGetCc1PolarityInverted(1U) != 0U);
-
- /* 负脉冲选择反向相序,完整两个周期后由同一事件链结束任务。 */
- PlsrHwTestAdvanceAbQuarter(0U);
- CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
- CHECK(PlsrHwTestGetAbPhaseB(0U) == 1U);
- for (quarter = 1; quarter < 8; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- CHECK(PlsrHwGetEmittedPulses(0U) == 2);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- PlsrProcess();
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.done != 0U);
- CHECK(status.directionPositive == 0U);
- CHECK(status.logicalPosition == -2);
- CHECK(status.taskPulses == -2);
- CHECK(status.totalPulses == 2);
- CHECK(TestReadSdDword(1002U) == -2);
- CHECK(TestReadSdDword(1004U) == -2);
- CHECK(status.highResourceMask == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
- }
-
- static void TestPositionOnImmediateStop(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_COMMAND command;
- PLSR_STATUS status;
- int pulse;
- int tick;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 100);
- call = TestMakeCall(&memory);
- call.sequence = 30UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (tick = 0; tick < 10; tick++)
- {
- PlsrProcess();
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
-
- for (pulse = 0; pulse < 37; pulse++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.logicalPosition == 37);
- CHECK(status.taskPulses == 37);
- CHECK(status.totalPulses == 37);
-
- command.sequence = 31UL;
- command.axis = 0U;
- command.opcode = PLSR_CMD_STOP_IMMEDIATE;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
- == PLSR_RESULT_OK);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_STOPPED);
- CHECK(status.logicalPosition == 37);
- CHECK(status.taskPulses == 37);
- CHECK(status.totalPulses == 37);
- CHECK(TestReadSdDword(1002U) == 37);
-
- command.sequence = 32UL;
- command.opcode = PLSR_CMD_CLEAR_TOTAL;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.logicalPosition == 37);
- CHECK(status.totalPulses == 0);
- }
-
- static void TestAbsolutePositionAccounting(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_COMMAND command;
- PLSR_STATUS status;
- int32_t hsdPosition;
- int pulse;
- int tick;
-
- TestResetEnvironment();
- command.sequence = 40UL;
- command.axis = 0U;
- command.opcode = PLSR_CMD_SET_POSITION;
- command.argument = 100;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
-
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 130);
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 1);
- call = TestMakeCall(&memory);
- call.sequence = 41UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (tick = 0; tick < 10; tick++)
- {
- PlsrProcess();
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- for (pulse = 0; pulse < 30; pulse++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.logicalPosition == 130);
- CHECK(status.taskPulses == 30);
- CHECK(status.totalPulses == 30);
- CHECK(status.positionValid != 0U);
- CHECK(PlcDeviceReadHsdDword(0U, &hsdPosition) == PLC_DEVICE_OK);
- CHECK(hsdPosition == 130);
- }
-
- static void TestEquivalentRemainderAccounting(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_STATUS status;
- int32_t hsdPulses;
- int32_t hsdEquivalent;
-
- TestResetEnvironment();
- CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
- TestWriteSfdDword(902U, 3UL);
- TestWriteSfdDword(904U, 2UL);
- TestWriteSfdDword(956U, 60000UL);
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
-
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 1);
- call = TestMakeCall(&memory);
- call.sequence = 30UL;
- call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
-
- /* 3脉冲/2单位:第一次1单位只输出1脉冲并保存1/2余数。 */
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- PlsrHwTestTriggerUpdate(0U);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.logicalPosition == 1);
- CHECK(status.taskPulses == 1);
- CHECK(status.totalPulses == 1);
- CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
- CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
- CHECK(hsdPulses == 1);
- CHECK(hsdEquivalent == 0);
-
- /* 第二次1单位合并余数后输出2脉冲;两次合计精确为3脉冲/2单位。 */
- call.sequence = 31UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- PlsrHwTestTriggerUpdate(0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- PlsrHwTestTriggerUpdate(0U);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.logicalPosition == 3);
- CHECK(status.taskPulses == 2);
- CHECK(status.totalPulses == 3);
- CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
- CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
- CHECK(hsdPulses == 3);
- CHECK(hsdEquivalent == 2);
- CHECK(TestReadSdDword(1002U) == 2);
- CHECK(TestReadSdDword(1004U) == 1);
- }
-
- static void TestEquivalentCompatibleError(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_STATUS status;
- int32_t errorCode = -1;
- int32_t errorBlock = -1;
-
- TestResetEnvironment();
- CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
- TestWriteSfdDword(902U, 0UL);
- TestWriteSfdDword(904U, 2UL);
- TestWriteSfdDword(956U, 60000UL);
-
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 1);
- call = TestMakeCall(&memory);
- call.sequence = 32UL;
- call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
-
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.lastCommandResult == PLSR_RESULT_INVALID_S2);
- CHECK(status.state == PLSR_STATE_IDLE);
- CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
- CHECK(PlcDeviceReadSd(1011U, &errorBlock) == PLC_DEVICE_OK);
- CHECK(errorCode == 2);
- CHECK(errorBlock == 0);
-
- /* A valid retry clears the compatible parameter error. */
- TestWriteSfdDword(902U, 3UL);
- call.sequence = 33UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
- CHECK(errorCode == 0);
- CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
- }
-
- static void TestSoftLimitAndSegmentEvent(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_COMMAND command;
- PLSR_STATUS status;
- PLC_DEVICE_EVENT_RECORD eventRecord;
- int32_t errorCode;
- int pulse;
- int tick;
- uint32_t pulsePhase = 0UL;
-
- TestResetEnvironment();
- CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(915U, 0xFFFFU) == PLC_DEVICE_OK);
- TestWriteSfdDword(930U, 100UL);
- TestWriteSfdDword(932U, (uint32_t)(int32_t)-100);
-
- command.sequence = 40UL;
- command.axis = 0U;
- command.opcode = PLSR_CMD_SET_POSITION;
- command.argument = 100;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
-
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 10);
- call = TestMakeCall(&memory);
- call.sequence = 41UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.lastCommandResult == PLSR_RESULT_LIMIT_POSITIVE);
- CHECK(status.state == PLSR_STATE_IDLE);
- CHECK(status.positiveLimitActive != 0U);
- CHECK(status.error == PLSR_ERROR_LIMIT_POSITIVE);
- CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
- CHECK(errorCode == 5);
-
- /* 正限位上只禁止正向,反向离开仍可正常完成。 */
- TestSetSegment(&memory, 1U, 1000U, -10);
- call.sequence = 42UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- for (pulse = 0; pulse < 10; pulse++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.logicalPosition == 90);
- CHECK(status.error == PLSR_ERROR_NONE);
- CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
- CHECK(eventRecord.pending != 0U);
-
- /* 运行中按预计制动距离触发软限位,PWM保持运行并按曲线缓停。 */
- TestResetEnvironment();
- CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(930U, 50UL);
- TestWriteSfdDword(932U, (uint32_t)(int32_t)-50);
- command.sequence = 43UL;
- command.opcode = PLSR_CMD_SET_POSITION;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 10000);
- call = TestMakeCall(&memory);
- call.sequence = 44UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (pulse = 0; pulse < 49; pulse++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_DECEL);
- CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
- CHECK(status.positiveLimitActive != 0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
- CHECK(errorCode == 5);
- for (tick = 0; tick < 20; tick++)
- {
- PlsrProcess();
- }
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_STOPPED);
- CHECK(status.logicalPosition == 49);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
- CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
-
- /* Board-equivalent time simulation for the +500 precision case. Each
- * loop represents 1 ms and emits complete hardware periods according to
- * the frequency that was active during that interval. */
- TestResetEnvironment();
- CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(930U, 500UL);
- TestWriteSfdDword(932U, (uint32_t)(int32_t)-500);
- TestWriteSfdDword(950U, 1000UL);
- CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
- TestWriteSfdDword(958U, 1000UL);
- TestWriteSfdDword(960U, 0UL);
- command.sequence = 45UL;
- command.opcode = PLSR_CMD_SET_POSITION;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 10000);
- call = TestMakeCall(&memory);
- call.sequence = 46UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (tick = 0; tick < 1000; tick++)
- {
- pulsePhase += PlsrHwGetCurrentFrequencyHz(0U);
- while ((pulsePhase >= 1000UL)
- && (PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING))
- {
- pulsePhase -= 1000UL;
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- if (status.state == PLSR_STATE_STOPPED)
- {
- break;
- }
- }
- CHECK(status.state == PLSR_STATE_STOPPED);
- CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
- CHECK(status.logicalPosition >= 499);
- CHECK(status.logicalPosition <= 501);
-
- /* Negative/high-speed companion case for the P15 board matrix. */
- TestResetEnvironment();
- pulsePhase = 0UL;
- CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
- TestWriteSfdDword(930U, 1000UL);
- TestWriteSfdDword(932U, (uint32_t)(int32_t)-1000);
- TestWriteSfdDword(950U, 2000UL);
- CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
- TestWriteSfdDword(958U, 2000UL);
- TestWriteSfdDword(960U, 0UL);
- command.sequence = 47UL;
- command.opcode = PLSR_CMD_SET_POSITION;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 2000U, -10000);
- call = TestMakeCall(&memory);
- call.sequence = 48UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (tick = 0; tick < 1000; tick++)
- {
- pulsePhase += PlsrHwGetCurrentFrequencyHz(0U);
- while ((pulsePhase >= 1000UL)
- && (PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING))
- {
- pulsePhase -= 1000UL;
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- if (status.state == PLSR_STATE_STOPPED)
- {
- break;
- }
- }
- CHECK(status.state == PLSR_STATE_STOPPED);
- CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_NEGATIVE);
- CHECK(status.logicalPosition >= -1001);
- CHECK(status.logicalPosition <= -999);
- }
-
- static void TestHardLimitAndEmergencyLatch(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_COMMAND command;
- PLSR_STATUS status;
- PLC_DEVICE_EVENT_RECORD eventRecord;
-
- TestResetEnvironment();
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
- CHECK(PlcDeviceWriteSfd(915U, 0xFF03U) == PLC_DEVICE_OK);
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 10000);
- call = TestMakeCall(&memory);
- call.sequence = 50UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- memory.bits[0][3U] = 1U;
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_DECEL);
- CHECK(status.positiveLimitActive != 0U);
- CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
- CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
-
- TestResetEnvironment();
- CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 10000);
- call = TestMakeCall(&memory);
- call.sequence = 51UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- command.sequence = 52UL;
- command.axis = 0U;
- command.opcode = PLSR_CMD_RESET_ERROR;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- CHECK(PlsrPostEvent(0U,
- PLSR_EVENT_LIMIT_POSITIVE
- | PLSR_EVENT_SOFTWARE_EMERGENCY)
- == PLSR_RESULT_OK);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_STOPPED);
- CHECK(status.stopReason == PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
- CHECK(status.error == PLSR_ERROR_EMERGENCY);
- CHECK(status.emergencyLatched != 0U);
- CHECK(status.lastCommandSequence == 52UL);
- CHECK(status.lastCommandResult == PLSR_RESULT_BUSY);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
- CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(eventRecord.lastReason == PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
-
- call.sequence = 53UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.lastCommandResult == PLSR_RESULT_EMERGENCY_LATCHED);
- CHECK(status.state == PLSR_STATE_STOPPED);
-
- command.sequence = 54UL;
- command.axis = 0U;
- command.opcode = PLSR_CMD_RESET_ERROR;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_IDLE);
- CHECK(status.error == PLSR_ERROR_NONE);
- CHECK(status.emergencyLatched == 0U);
- }
-
- static void TestProductionSelfTestStartsAb(void)
- {
- PLSR_STATUS status;
-
- TestResetEnvironment();
- CHECK(PlsrSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.lastCommandResult == PLSR_RESULT_OK);
- CHECK(status.outputMode == PLSR_OUTPUT_AB);
- CHECK(status.currentSegment == 1U);
- CHECK(status.state == PLSR_STATE_ACCEL);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
- CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
- }
-
- static void TestEquivalentSelfTest(void)
- {
- PLSR_STATUS status;
- int32_t hsdPulses;
- int32_t hsdEquivalent;
- int ticks;
-
- TestResetEnvironment();
- CHECK(PlsrEquivalentSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
-
- /* SFD907=10ms. Advance the simulated hardware delay before segment 1. */
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
-
- /* 3 pulses / 2 units: 1001 units emit 1501 pulses and keep 1/2 remainder. */
- for (ticks = 0; ticks < 1501; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
-
- /* Segment 2 consumes the remainder and therefore emits 1502 pulses. */
- for (ticks = 0; ticks < 1502; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
-
- status = TestGetStatus();
- CHECK(status.lastCommandResult == PLSR_RESULT_OK);
- CHECK(status.outputMode == PLSR_OUTPUT_PULSE_DIR);
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.currentSegment == 2U);
- CHECK(status.logicalPosition == 3003);
- CHECK(status.taskPulses == 3003);
- CHECK(status.totalPulses == 3003);
- CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
- CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
- CHECK(hsdPulses == 3003);
- CHECK(hsdEquivalent == 2002);
- CHECK(TestReadSdDword(1002U) == 1502);
- CHECK(TestReadSdDword(1004U) == 1001);
- }
-
- static void TestProtectionSelfTest(void)
- {
- PLC_DEVICE_EVENT_RECORD eventRecord;
- PLSR_STATUS status;
- uint32_t pulseAccumulator = 0UL;
- int32_t value;
- int ticks;
-
- TestResetEnvironment();
- CHECK(PlsrProtectionSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
-
- /* Complete the 10ms direction-settle interval. */
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
-
- /* Convert the current frequency into simulated hardware updates over
- * each 1ms process tick. This also models the falling pulse density
- * during the controlled stop. */
- status = TestGetStatus();
- for (ticks = 0; ticks < 600; ticks++)
- {
- pulseAccumulator += PlsrHwGetCurrentFrequencyHz(0U);
- while ((pulseAccumulator >= 1000UL)
- && (PlsrHwIsPulseActive(0U) != 0U))
- {
- PlsrHwTestTriggerUpdate(0U);
- pulseAccumulator -= 1000UL;
- }
- PlsrProcess();
- status = TestGetStatus();
- if (status.state == PLSR_STATE_STOPPED)
- {
- break;
- }
- }
-
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_STOPPED);
- CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
- CHECK(status.error == PLSR_ERROR_LIMIT_POSITIVE);
- CHECK(status.emergencyLatched == 0U);
- CHECK(status.logicalPosition >= 499);
- CHECK(status.logicalPosition <= 501);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
- CHECK(PlcDeviceReadSd(1010U, &value) == PLC_DEVICE_OK);
- CHECK(value == 5U);
- CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(eventRecord.pending != 0U);
- CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
- }
-
- static void TestFourAxisSelfTest(void)
- {
- static const uint32_t expectedFrequency[PLSR_AXIS_COUNT] =
- {
- 1000UL, 2000UL, 3000UL, 4000UL
- };
- static const int32_t expectedPulses[PLSR_AXIS_COUNT] =
- {
- 1000, 2000, 3000, 4000
- };
- PLC_DEVICE_EVENT_RECORD eventRecord;
- PLSR_RESOURCE_STATUS resources;
- PLSR_STATUS status;
- int32_t hsdPulses;
- int subTick;
- int ticks;
- uint8_t axis;
-
- TestResetEnvironment();
- CHECK(PlsrFourAxisSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
-
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_RUN);
- CHECK(status.outputMode == PLSR_OUTPUT_PULSE_DIR);
- CHECK(status.directionPoint == (uint8_t)(4U + axis));
- CHECK(status.directionPositive != 0U);
- CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_RUNNING);
- CHECK(PlsrHwGetCurrentFrequencyHz(axis)
- == expectedFrequency[axis]);
- CHECK(status.hardwareCounter == ((axis < 2U) ? 1U : 0U));
- }
-
- /* A 0.25ms base slot produces 1/2/3/4kHz update ratios while all four
- * hardware channels are active concurrently for one simulated second. */
- for (subTick = 0; subTick < 4000; subTick++)
- {
- if ((subTick & 3) == 0)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- if ((subTick & 1) == 0)
- {
- PlsrHwTestTriggerUpdate(1U);
- }
- if ((subTick & 3) != 3)
- {
- PlsrHwTestTriggerUpdate(2U);
- }
- PlsrHwTestTriggerUpdate(3U);
-
- if ((subTick & 3) == 3)
- {
- PlsrProcess();
- }
- }
-
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.stopReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
- CHECK(status.done != 0U);
- CHECK(status.logicalPosition == expectedPulses[axis]);
- CHECK(status.taskPulses == expectedPulses[axis]);
- CHECK(status.totalPulses == expectedPulses[axis]);
- CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_IDLE);
- CHECK(PlcDeviceReadHsdDword((uint16_t)(axis * 4U),
- &hsdPulses) == PLC_DEVICE_OK);
- CHECK(hsdPulses == expectedPulses[axis]);
- CHECK(PlcDeviceReadEvent((uint16_t)(6000U
- + (uint16_t)axis * 100U),
- &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(eventRecord.pending != 0U);
- CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
- }
- PlsrResourceGetStatus(&resources);
- CHECK(resources.outputMask == 0UL);
- CHECK(resources.highMask == 0U);
- CHECK(PlsrResourceCheckInvariant() != 0U);
- }
-
- static void TestBacklashSelfTest(void)
- {
- PLC_DEVICE_EVENT_RECORD eventRecord;
- PLSR_STATUS status;
- int32_t hsdPosition;
- int ticks;
-
- TestResetEnvironment();
- CHECK(PlsrBacklashSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
-
- /* Segment 1: +200 user pulses, with no compensation on first motion. */
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- for (ticks = 0; ticks < 200; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.currentSegment == 2U);
- CHECK(status.backlashActive != 0U);
- CHECK(status.directionPositive == 0U);
- CHECK(status.logicalPosition == 200);
- CHECK(status.taskPulses == 200);
- CHECK(status.totalPulses == 200);
- CHECK(status.physicalPulses == 200UL);
- CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 0UL);
-
- /* Direction change to negative: 20 physical compensation pulses first. */
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
- for (ticks = 0; ticks < 20; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.backlashActive == 0U);
- CHECK(status.currentSegment == 2U);
- CHECK(status.logicalPosition == 200);
- CHECK(status.taskPulses == 200);
- CHECK(status.totalPulses == 200);
- CHECK(status.physicalPulses == 220UL);
- CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 0UL);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
-
- /* The real segment 2 contributes -200 to user position/counting. */
- for (ticks = 0; ticks < 200; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.currentSegment == 3U);
- CHECK(status.backlashActive != 0U);
- CHECK(status.directionPositive != 0U);
- CHECK(status.logicalPosition == 0);
- CHECK(status.taskPulses == 0);
- CHECK(status.totalPulses == 400);
- CHECK(status.physicalPulses == 420UL);
- CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 0UL);
-
- /* Direction change back to positive: 10 compensation, then +100 user. */
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.backlashActive == 0U);
- CHECK(status.logicalPosition == 0);
- CHECK(status.totalPulses == 400);
- CHECK(status.physicalPulses == 430UL);
- CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 0UL);
-
- for (ticks = 0; ticks < 100; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.done != 0U);
- CHECK(status.logicalPosition == 100);
- CHECK(status.taskPulses == 100);
- CHECK(status.totalPulses == 500);
- CHECK(status.physicalPulses == 530UL);
- CHECK(PlcDeviceReadHsdDword(0U, &hsdPosition) == PLC_DEVICE_OK);
- CHECK(hsdPosition == 100);
- CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
- }
-
- static void TestDirectionLogicSelfTest(void)
- {
- static const uint8_t expectedDirectionPoint[2] = {4U, 3U};
- PLC_DEVICE_EVENT_RECORD eventRecord;
- PLSR_STATUS status;
- uint8_t smDirection;
- uint8_t axis;
- int ticks;
-
- TestResetEnvironment();
- CHECK(PlsrDirectionLogicSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
-
- /* Both axes move logically positive. Electrical DIR terminals are
- * complementary because axis 1 has SFD1030 Bit1 set. */
- CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
- CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
- for (axis = 0U; axis < 2U; axis++)
- {
- CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_RUN);
- CHECK(status.directionPoint == expectedDirectionPoint[axis]);
- CHECK(status.directionPositive != 0U);
- CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_RUNNING);
- }
-
- for (ticks = 0; ticks < 200; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- PlsrHwTestTriggerUpdate(1U);
- }
- PlsrProcess();
-
- /* Both reverse logically; only the physical terminal mapping differs. */
- CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
- CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
- for (axis = 0U; axis < 2U; axis++)
- {
- CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
- CHECK(status.currentSegment == 2U);
- CHECK(status.directionPositive == 0U);
- CHECK(status.logicalPosition == 200);
- CHECK(status.totalPulses == 200);
- CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_DIR_SETTLING);
- }
-
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
- for (ticks = 0; ticks < 200; ticks++)
- {
- PlsrHwTestTriggerUpdate(0U);
- PlsrHwTestTriggerUpdate(1U);
- }
- PlsrProcess();
-
- for (axis = 0U; axis < 2U; axis++)
- {
- CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.done != 0U);
- CHECK(status.directionPositive == 0U);
- CHECK(status.logicalPosition == 0);
- CHECK(status.taskPulses == 0);
- CHECK(status.totalPulses == 400);
- CHECK(status.physicalPulses == 400UL);
- CHECK(PlcDeviceReadSm((uint16_t)(1001U
- + (uint16_t)axis * 20U),
- &smDirection) == PLC_DEVICE_OK);
- CHECK(smDirection == 0U);
- CHECK(PlcDeviceReadEvent((uint16_t)(6000U
- + (uint16_t)axis * 100U),
- &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(PlcDeviceReadEvent((uint16_t)(6001U
- + (uint16_t)axis * 100U),
- &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- }
- CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
- CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
- }
-
- static void TestCwCcwSelfTest(void)
- {
- PLC_DEVICE_EVENT_RECORD eventRecord;
- PLSR_STATUS status;
- int pulse;
-
- TestResetEnvironment();
- CHECK(PlsrCwCcwSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_RUN);
- CHECK(status.outputMode == PLSR_OUTPUT_CW_CCW);
- CHECK(status.directionPositive != 0U);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
-
- for (pulse = 0; pulse < 300; pulse++)
- {
- PlsrHwTestTriggerCompare(0U);
- }
- PlsrHwTestTriggerUpdate(0U);
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.currentSegment == 2U);
- CHECK(status.directionPositive == 0U);
- CHECK(status.logicalPosition == 300);
- CHECK(status.totalPulses == 300);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
-
- for (pulse = 0; pulse < 200; pulse++)
- {
- PlsrHwTestTriggerCompare(1U);
- }
- PlsrHwTestTriggerUpdate(1U);
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_COMPLETED);
- CHECK(status.done != 0U);
- CHECK(status.logicalPosition == 100);
- CHECK(status.taskPulses == 100);
- CHECK(status.totalPulses == 500);
- CHECK(status.physicalPulses == 500UL);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
- CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
- CHECK(eventRecord.count == 1UL);
- }
-
- static void TestFastRefreshSelfTest(void)
- {
- PLSR_STATUS status;
- uint32_t beforeFastHz;
- uint16_t refreshCode;
- int tick;
-
- TestResetEnvironment();
- CHECK(PlsrFastRefreshSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (tick = 0; tick < 10; tick++)
- {
- PlsrProcess();
- }
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_ACCEL);
- CHECK(status.directionPoint == 4U);
- CHECK(PlsrHwGetCurrentFrequencyHz(0U) > 0UL);
- CHECK(PlsrGetStatus(1U, &status) == PLSR_RESULT_OK);
- CHECK(status.state == PLSR_STATE_ACCEL);
- CHECK(status.directionPoint == 3U);
- CHECK(PlsrTestGetJobRefreshCode(1U) == 2U);
- CHECK(PlsrTestGetProfileRefreshHz(1U) == 10000UL);
- beforeFastHz = PlsrTestGetProfileFrequencyHz(1U);
- PlsrControlTick100us();
- CHECK(PlsrTestGetProfileFrequencyHz(1U) > beforeFastHz);
- CHECK(PlcDeviceReadSfd(964U, &refreshCode) == PLC_DEVICE_OK);
- CHECK(refreshCode == 0U);
- CHECK(PlcDeviceReadSfd(1094U, &refreshCode) == PLC_DEVICE_OK);
- CHECK(refreshCode == 2U);
- }
-
- static void TestDynamicFrequencySelfTest(void)
- {
- PLSR_STATUS status;
- int tick;
-
- TestResetEnvironment();
- CHECK(PlsrDynamicFrequencySelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (tick = 0; tick < 10; tick++)
- {
- PlsrProcess();
- }
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.currentFrequencyHz == 1000UL);
- CHECK(status.targetFrequencyHz == 1000UL);
-
- PlsrSelfTestLiveFrequencyHz = 4000;
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.currentFrequencyHz == 1001UL);
- CHECK(status.targetFrequencyHz == 4000UL);
-
- PlsrSelfTestLiveFrequencyHz = 500;
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.currentFrequencyHz == 1000UL);
- CHECK(status.targetFrequencyHz == 500UL);
- CHECK(status.liveFrequencyRejectCount == 0UL);
- }
-
- static void TestDynamicFrequencySchedule(void)
- {
- int tick;
-
- TestResetEnvironment();
- CHECK(PlsrDynamicFrequencySelfTestQueue() == PLSR_RESULT_QUEUED);
- CHECK(PlsrSelfTestLiveFrequencyHz == 1000);
- CHECK(PlsrSelfTestDynamicPhase == 0U);
- for (tick = 0; tick < 9999; tick++)
- {
- PlsrSelfTestControlTick100us();
- }
- CHECK(PlsrSelfTestLiveFrequencyHz == 1000);
- PlsrSelfTestControlTick100us();
- CHECK(PlsrSelfTestLiveFrequencyHz == 4000);
- CHECK(PlsrSelfTestDynamicPhase == 1U);
- for (tick = 0; tick < 5000; tick++)
- {
- PlsrSelfTestControlTick100us();
- }
- CHECK(PlsrSelfTestLiveFrequencyHz == 500);
- CHECK(PlsrSelfTestDynamicPhase == 2U);
- for (tick = 0; tick < 5000; tick++)
- {
- PlsrSelfTestControlTick100us();
- }
- CHECK(PlsrSelfTestLiveFrequencyHz == 0);
- CHECK(PlsrSelfTestDynamicPhase == 3U);
- for (tick = 0; tick < 2000; tick++)
- {
- PlsrSelfTestControlTick100us();
- }
- CHECK(PlsrSelfTestLiveFrequencyHz == 8000);
- CHECK(PlsrSelfTestDynamicPhase == 4U);
- for (tick = 0; tick < 5000; tick++)
- {
- PlsrSelfTestControlTick100us();
- }
- CHECK(PlsrSelfTestLiveFrequencyHz == -1);
- CHECK(PlsrSelfTestDynamicPhase == 5U);
- for (tick = 0; tick < 2000; tick++)
- {
- PlsrSelfTestControlTick100us();
- }
- CHECK(PlsrSelfTestLiveFrequencyHz == 2000);
- CHECK(PlsrSelfTestDynamicPhase == 6U);
- CHECK(PlsrSelfTestDynamicTick100us == 29000UL);
- PlsrSelfTestControlTick100us();
- CHECK(PlsrSelfTestDynamicTick100us == 29000UL);
- }
-
- static void TestModbusDataSelfTest(void)
- {
- PLSR_STATUS status;
- uint16_t frequencyWords[2];
- uint16_t word;
- int tick;
-
- TestResetEnvironment();
- CHECK(PlsrModbusDataSelfTestQueue() == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (tick = 0; tick < 10; tick++)
- {
- PlsrProcess();
- }
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D, 1000UL, &word) == 1U);
- CHECK(word == 1U);
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK((status.state == PLSR_STATE_ACCEL) || (status.state == PLSR_STATE_RUN));
- CHECK(PlsrHwIsPulseActive(0U) == 1U);
- CHECK(status.currentFrequencyHz == 1000UL);
- CHECK(status.targetFrequencyHz == 1000UL);
-
- frequencyWords[0] = 4000U;
- frequencyWords[1] = 0U;
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- 1010UL,
- frequencyWords,
- 2UL) == 1U);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.currentFrequencyHz == 1001UL);
- CHECK(status.targetFrequencyHz == 4000UL);
- CHECK(status.liveFrequencyRejectCount == 0UL);
-
- frequencyWords[0] = 0xFFFFU;
- frequencyWords[1] = 0xFFFFU;
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- 1010UL,
- frequencyWords,
- 2UL) == 1U);
- PlsrControlTick100us();
- CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
- CHECK(status.targetFrequencyHz == 4000UL);
- CHECK(status.liveFrequencyRejectCount == 1UL);
- CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_INVALID_FREQUENCY);
- }
-
- static void TestModbusControlProtocol(void)
- {
- const uint32_t controlBase = 1200UL;
- const uint32_t s0Base = 1600UL;
- const uint32_t s1Base = 1700UL;
- uint16_t s0Words[20] = {0U};
- uint16_t s1Words[4] = {0U};
- uint16_t callRequest[16] = {0U};
- uint16_t callResponse[12];
- uint16_t commandRequest[8] = {0U};
- uint16_t commandResponse[8];
- uint16_t controlHeader[8];
- uint16_t performanceWords[8];
- uint16_t stagePerformanceWords[PLSR_MODBUS_STAGE_PERFORMANCE_WORDS];
- uint16_t usbDiagnosticsWords[PLSR_MODBUS_USB_DIAGNOSTICS_WORDS];
- uint16_t axisStatus[48];
- uint16_t pulseWords[2];
- uint32_t generationBegin;
- uint32_t generationEnd;
- PLSR_STATUS coreStatus;
- int64_t pausedPulses;
- int tick;
-
- TestResetEnvironment();
- CHECK(PlsrModbusControlSelfTestPrepare() == PLSR_RESULT_OK);
- CHECK(PlsrModbusControlInit((uint16_t)controlBase) == PLSR_RESULT_OK);
- CHECK(PlsrModbusControlIsEnabled() == 1U);
- CHECK(PlsrModbusControlGetBaseAddress() == controlBase);
- for (tick = 0; tick < 8; tick++)
- {
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
- controlBase + (uint32_t)tick,
- &controlHeader[tick]) == 1U);
- CHECK(ModbusDataReadWord(
- MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_PERFORMANCE_OFFSET
- + (uint32_t)tick,
- &performanceWords[tick]) == 1U);
- }
- CHECK(controlHeader[5] == (uint16_t)(168000000UL & 0xFFFFUL));
- CHECK(controlHeader[6] == (uint16_t)(168000000UL >> 16U));
- CHECK(controlHeader[7] == PLSR_MODBUS_PERFORMANCE_VERSION);
- CHECK(controlHeader[3] == (uint16_t)PLSR_MODBUS_WINDOW_WORDS);
- for (tick = 0; tick < 8; tick++)
- {
- CHECK(performanceWords[tick] == 0U);
- }
- for (tick = 0; tick < (int)PLSR_MODBUS_STAGE_PERFORMANCE_WORDS; tick++)
- {
- CHECK(ModbusDataReadWord(
- MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_STAGE_PERFORMANCE_OFFSET
- + (uint32_t)tick,
- &stagePerformanceWords[tick]) == 1U);
- CHECK(stagePerformanceWords[tick] == 0U);
- }
- for (tick = 0; tick < (int)PLSR_MODBUS_USB_DIAGNOSTICS_WORDS; tick++)
- {
- CHECK(ModbusDataReadWord(
- MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_USB_DIAGNOSTICS_OFFSET
- + (uint32_t)tick,
- &usbDiagnosticsWords[tick]) == 1U);
- }
- generationBegin = (uint32_t)usbDiagnosticsWords[0]
- | ((uint32_t)usbDiagnosticsWords[1] << 16U);
- generationEnd = (uint32_t)usbDiagnosticsWords[20]
- | ((uint32_t)usbDiagnosticsWords[21] << 16U);
- CHECK(generationBegin == generationEnd);
- CHECK((generationBegin & 1UL) == 0UL);
- CHECK(usbDiagnosticsWords[2] ==
- PLSR_MODBUS_USB_DIAGNOSTICS_VERSION);
- for (tick = 3; tick < 20; tick++)
- {
- CHECK(usbDiagnosticsWords[tick] == 0U);
- }
-
- s0Words[0] = 1U;
- s0Words[10] = 2000U;
- s0Words[12] = (uint16_t)(50000UL & 0xFFFFUL);
- s0Words[13] = (uint16_t)(50000UL >> 16U);
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- s0Base,
- s0Words,
- 20UL) == 1U);
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- s1Base,
- s1Words,
- 4UL) == 1U);
-
- callRequest[0] = 1U;
- callRequest[2] = PLSR_DEVICE_D;
- callRequest[3] = (uint16_t)s0Base;
- callRequest[5] = PLSR_DEVICE_D;
- callRequest[6] = (uint16_t)s1Base;
- callRequest[8] = PLSR_OPERAND_CONSTANT;
- callRequest[10] = 1U;
- callRequest[12] = 0U;
- callRequest[13] = PLSR_OUTPUT_PULSE_DIR;
- callRequest[14] = PLSR_MODBUS_CALL_COMMIT;
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
- callRequest,
- 16UL) == 1U);
- PlsrModbusControlPoll();
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET,
- &callResponse[0]) == 1U);
- for (tick = 1; tick < 12; tick++)
- {
- CHECK(ModbusDataReadWord(
- MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
- + (uint32_t)tick,
- &callResponse[tick]) == 1U);
- }
- CHECK(callResponse[0] == 1U);
- CHECK(callResponse[2] == PLSR_MODBUS_CALL_COMMIT);
- CHECK(callResponse[3] == PLSR_RESULT_OK);
- CHECK(callResponse[11] == 1U);
-
- /* Any S0 edit after COMMIT invalidates START until a new COMMIT. */
- pulseWords[0] = (uint16_t)(50001UL & 0xFFFFUL);
- pulseWords[1] = (uint16_t)(50001UL >> 16U);
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- s0Base + 12UL,
- pulseWords,
- 2UL) == 1U);
- callRequest[0] = 2U;
- callRequest[14] = PLSR_MODBUS_CALL_START;
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
- callRequest,
- 16UL) == 1U);
- PlsrModbusControlPoll();
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
- + 3UL,
- &callResponse[3]) == 1U);
- CHECK(callResponse[3] == PLSR_RESULT_BUSY);
-
- pulseWords[0] = (uint16_t)(50000UL & 0xFFFFUL);
- pulseWords[1] = (uint16_t)(50000UL >> 16U);
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- s0Base + 12UL,
- pulseWords,
- 2UL) == 1U);
- callRequest[0] = 3U;
- callRequest[14] = PLSR_MODBUS_CALL_COMMIT;
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
- callRequest,
- 16UL) == 1U);
- PlsrModbusControlPoll();
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
- + 3UL,
- &callResponse[3]) == 1U);
- CHECK(callResponse[3] == PLSR_RESULT_OK);
-
- callRequest[0] = 4U;
- callRequest[14] = PLSR_MODBUS_CALL_START;
- CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
- callRequest,
- 16UL) == 1U);
- PlsrModbusControlPoll();
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
- + 3UL,
- &callResponse[3]) == 1U);
- CHECK(callResponse[3] == PLSR_RESULT_QUEUED);
- for (tick = 0; tick < 10; tick++)
- {
- PlsrProcess();
- }
- PlsrModbusControlPoll();
- for (tick = 0; tick < 48; tick++)
- {
- CHECK(ModbusDataReadWord(
- MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET
- + (uint32_t)tick,
- &axisStatus[tick]) == 1U);
- }
- generationBegin = (uint32_t)axisStatus[0]
- | ((uint32_t)axisStatus[1] << 16U);
- generationEnd = (uint32_t)axisStatus[46]
- | ((uint32_t)axisStatus[47] << 16U);
- CHECK(generationBegin == generationEnd);
- CHECK((generationBegin & 1UL) == 0UL);
- CHECK((axisStatus[2] == PLSR_STATE_ACCEL)
- || (axisStatus[2] == PLSR_STATE_RUN));
- CHECK(axisStatus[10] == 4U);
- CHECK(axisStatus[11] == 0U);
- CHECK(axisStatus[8] == PLSR_RESULT_OK);
- CHECK(axisStatus[37] == 1U);
-
- commandRequest[0] = 10U;
- commandRequest[2] = PLSR_CMD_PAUSE;
- commandRequest[3] = 0U;
- CHECK(ModbusDataWriteWords(
- MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
- commandRequest,
- 8UL) == 1U);
- PlsrModbusControlPoll();
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_COMMAND_RESPONSE_OFFSET
- + 4UL,
- &commandResponse[4]) == 1U);
- CHECK(commandResponse[4] == PLSR_RESULT_QUEUED);
- for (tick = 0; tick < 400; tick++)
- {
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
- if (coreStatus.state == PLSR_STATE_PAUSED)
- {
- break;
- }
- }
- CHECK(coreStatus.state == PLSR_STATE_PAUSED);
- CHECK(coreStatus.currentFrequencyHz == 0UL);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
- pausedPulses = coreStatus.taskPulses;
- PlsrModbusControlPoll();
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET + 2UL,
- &axisStatus[2]) == 1U);
- CHECK(axisStatus[2] == PLSR_STATE_PAUSED);
-
- /* Polling an unchanged request sequence must not execute PAUSE twice. */
- PlsrModbusControlPoll();
- commandRequest[0] = 11U;
- commandRequest[2] = PLSR_CMD_RESUME;
- CHECK(ModbusDataWriteWords(
- MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
- commandRequest,
- 8UL) == 1U);
- PlsrModbusControlPoll();
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
- CHECK(coreStatus.currentFrequencyHz > 0UL);
- CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
- for (tick = 0; tick < 10; tick++)
- {
- PlsrHwTestTriggerUpdate(0U);
- }
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
- CHECK(coreStatus.taskPulses == pausedPulses + 10);
- PlsrModbusControlPoll();
- CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET + 2UL,
- &axisStatus[2]) == 1U);
- CHECK((axisStatus[2] == PLSR_STATE_ACCEL)
- || (axisStatus[2] == PLSR_STATE_RUN));
-
- commandRequest[0] = 12U;
- commandRequest[2] = PLSR_CMD_STOP_DECEL;
- CHECK(ModbusDataWriteWords(
- MODBUS_DATA_DEVICE_D,
- controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
- commandRequest,
- 8UL) == 1U);
- PlsrModbusControlPoll();
- for (tick = 0; tick < 400; tick++)
- {
- PlsrProcess();
- CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
- if (coreStatus.state == PLSR_STATE_STOPPED)
- {
- break;
- }
- }
- CHECK(coreStatus.state == PLSR_STATE_STOPPED);
- CHECK(coreStatus.currentFrequencyHz == 0UL);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
- }
-
- static void TestStopStopsHardware(void)
- {
- TEST_MEMORY memory;
- PLSR_CALL call;
- PLSR_COMMAND command;
- PLSR_STATUS status;
- int ticks;
-
- TestResetEnvironment();
- (void)memset(&memory, 0, sizeof(memory));
- TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
- TestSetSegment(&memory, 1U, 1000U, 10000);
-
- call = TestMakeCall(&memory);
- call.sequence = 20UL;
- CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- for (ticks = 0; ticks < 10; ticks++)
- {
- PlsrProcess();
- }
- CHECK(PlsrHwIsPulseActive(0U) == 1U);
-
- /* STOP_IMMEDIATE:硬件立即停止。 */
- command.sequence = 21UL;
- command.axis = 0U;
- command.opcode = PLSR_CMD_STOP_IMMEDIATE;
- command.argument = 0;
- CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
- PlsrProcess();
- CHECK(PlsrHwIsPulseActive(0U) == 0U);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
-
- CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
- == PLSR_RESULT_OK);
- PlsrProcess();
- status = TestGetStatus();
- CHECK(status.state == PLSR_STATE_STOPPED);
- }
-
- int main(void)
- {
- TestMapping();
- TestDirDelaySequence();
- TestDirectionBatch();
- TestHardwareCounterLeases();
- TestPulseDirTargetUpdateBoundaryStop();
- TestSoftwareCounterPeerDrain();
- TestCwCcwSequence();
- TestFastRefreshControlTick();
- TestDynamicFrequencyRetarget();
- TestZeroFrequencyWaits();
- TestPulseCounting();
- TestAbPhaseAndCounting();
- TestTwoAbAxesIndependent();
- TestDualAbHardwareCountersAndResume();
- TestDualAbSimultaneousFastGate();
- TestAbFrequencyLimits();
- TestStopAndInvalidArgs();
- TestEndToEndTwoSegments();
- TestEndToEndAbSegment();
- TestPositionOnImmediateStop();
- TestAbsolutePositionAccounting();
- TestEquivalentRemainderAccounting();
- TestEquivalentCompatibleError();
- TestSoftLimitAndSegmentEvent();
- TestHardLimitAndEmergencyLatch();
- TestProductionSelfTestStartsAb();
- TestEquivalentSelfTest();
- TestProtectionSelfTest();
- TestFourAxisSelfTest();
- TestBacklashSelfTest();
- TestDirectionLogicSelfTest();
- TestCwCcwSelfTest();
- TestFastRefreshSelfTest();
- TestDynamicFrequencySelfTest();
- TestDynamicFrequencySchedule();
- TestModbusDataSelfTest();
- TestModbusControlProtocol();
- TestStopStopsHardware();
-
- if (TestFailures != 0)
- {
- (void)printf("FAIL: %d of %d PLSR HAL checks failed\n",
- TestFailures,
- TestChecks);
- return 1;
- }
- (void)printf("PASS: %d PLSR HAL checks\n", TestChecks);
- return 0;
- }
|