|
- #include "plc_device.h"
- #include "plsr_core.h"
- #include "plsr_hal_f407.h"
- #include "plsr_job.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 void TestCompleteFirstAbPrime(uint8_t axis)
- {
- int quarter;
-
- CHECK(PlsrHwIsAbStartupPriming(axis) != 0U);
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(axis);
- }
- CHECK(PlsrHwIsAbStartupPriming(axis) == 0U);
- CHECK(PlsrHwGetEmittedPulses(axis) == 0);
- CHECK(PlsrHwTestGetAbQuarter(axis) == 0U);
- }
-
- 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);
- }
-
- 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);
- CHECK(PlsrHwTestGetCnt(1U) == PlsrHwTestGetCcr(1U));
- TestCompleteFirstAbPrime(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);
- CHECK(PlsrHwTestGetCnt(1U) == newPeriod / 2UL);
-
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- CHECK(PlsrHwGetEmittedPulses(0U) == 4);
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- 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);
-
- /* 紧急停止即使发生在周期中间,也必须回到安全 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);
-
- TestCompleteFirstAbPrime(0U);
- TestCompleteFirstAbPrime(2U);
-
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
- 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);
- }
-
- static void TestAbFrequencyLimits(void)
- {
- PLSR_HW_START_PARAMS params;
- 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);
-
- TestCompleteFirstAbPrime(0U);
-
- CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
- for (quarter = 0; quarter < 4; quarter++)
- {
- PlsrHwTestAdvanceAbQuarter(0U);
- }
- 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(0U, ¶ms) == PLSR_RESULT_NOT_SUPPORTED);
- 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);
-
- TestCompleteFirstAbPrime(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();
- 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;
-
- 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);
- }
-
- 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]);
- }
-
- /* 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 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();
- TestZeroFrequencyWaits();
- TestPulseCounting();
- TestAbPhaseAndCounting();
- TestTwoAbAxesIndependent();
- TestAbFrequencyLimits();
- TestStopAndInvalidArgs();
- TestEndToEndTwoSegments();
- TestEndToEndAbSegment();
- TestPositionOnImmediateStop();
- TestAbsolutePositionAccounting();
- TestEquivalentRemainderAccounting();
- TestEquivalentCompatibleError();
- TestSoftLimitAndSegmentEvent();
- TestHardLimitAndEmergencyLatch();
- TestProductionSelfTestStartsAb();
- TestEquivalentSelfTest();
- TestProtectionSelfTest();
- TestFourAxisSelfTest();
- 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;
- }
|