|
- #include "plsr_core.h"
- #include "plc_device.h"
- #include "plsr_address_map.h"
- #include "plsr_hal_f407.h"
- #include "plsr_path.h"
- #include "plsr_profile.h"
- #include "plsr_resource.h"
- #include <string.h>
-
- #define PLSR_CORE_SFD_AXIS_STRIDE (130U)
-
- #ifndef PLSR_HOST_TEST
- #include "stm32f4xx.h"
- #include "ucos_ii.h"
- #endif
-
- typedef struct
- {
- PLSR_STATE state;
- PLSR_OUTPUT_MODE outputMode;
- PLSR_ERROR error;
- uint16_t compatibleErrorCode;
- uint16_t compatibleErrorBlock;
- PLSR_STOP_REASON stopReason;
- PLSR_STATE pendingTerminal;
- PLSR_RESOURCE_LEASE lease;
- PLSR_JOB_SNAPSHOT job;
- PLSR_PARSE_DETAIL parseDetail;
- volatile uint32_t pendingEvents;
- uint32_t lastCommandSequence;
- PLSR_RESULT lastCommandResult;
- uint32_t illegalTransitionCount;
- int64_t logicalPosition;
- int64_t taskPulses;
- int64_t totalPulses;
- int64_t segmentAccountedPulses;
- int64_t equivalentCommandRemainder;
- PLSR_EQUIVALENT_CONFIG equivalent;
- PLSR_PATH_CONTEXT path;
- PLSR_PROFILE_STATE profile;
- uint8_t profileActive;
- uint8_t profileWasAccel;
- uint8_t hasLastCommand;
- uint8_t done;
- uint8_t directionPositive;
- uint8_t immediateStopPending;
- uint8_t positionValid;
- uint8_t jobValid;
- uint8_t positionOverflow;
- uint8_t segmentAccountingActive;
- uint8_t positiveLimitActive;
- uint8_t negativeLimitActive;
- uint8_t emergencyLatched;
- uint8_t segmentEventPublished;
- } PLSR_AXIS;
-
- typedef struct
- {
- PLSR_COMMAND command;
- PLSR_START_REQUEST start;
- PLSR_CALL call;
- uint32_t ticket;
- uint8_t hasStart;
- uint8_t hasCall;
- uint8_t occupied;
- } PLSR_COMMAND_SLOT;
-
- static PLSR_AXIS PlsrAxes[PLSR_AXIS_COUNT];
- static PLSR_COMMAND_SLOT PlsrCommandQueue[PLSR_COMMAND_QUEUE_DEPTH];
- static uint32_t PlsrNextTicket;
- static uint8_t PlsrInitialized;
- static PLSR_JOB_SNAPSHOT PlsrJobScratch;
-
- static void PlsrStopSegmentHardware(uint8_t axis, PLSR_AXIS *axisObject);
- static PLSR_RESULT PlsrStartSegmentHardware(uint8_t axis,
- PLSR_AXIS *axisObject);
- static void PlsrAccountHardwarePulses(uint8_t axis,
- PLSR_AXIS *axisObject);
- static void PlsrPublishSegmentEvent(uint8_t axis,
- PLSR_AXIS *axisObject,
- PLSR_STOP_REASON reason);
-
- static uint32_t PlsrCoreEnterCritical(void)
- {
- #ifdef PLSR_HOST_TEST
- return 0UL;
- #else
- uint32_t interruptState = __get_PRIMASK();
- __disable_irq();
- __DMB();
- return interruptState;
- #endif
- }
-
- static void PlsrCoreExitCritical(uint32_t interruptState)
- {
- #ifdef PLSR_HOST_TEST
- (void)interruptState;
- #else
- __DMB();
- if (interruptState == 0UL)
- {
- __enable_irq();
- }
- #endif
- }
-
- static uint8_t PlsrStateIsBusy(PLSR_STATE state)
- {
- return ((state == PLSR_STATE_ACCEL) || (state == PLSR_STATE_RUN)
- || (state == PLSR_STATE_DECEL) || (state == PLSR_STATE_WAIT)
- || (state == PLSR_STATE_PAUSED))
- ? 1U
- : 0U;
- }
-
- static uint8_t PlsrStateIsPulseActive(PLSR_STATE state)
- {
- return ((state == PLSR_STATE_ACCEL) || (state == PLSR_STATE_RUN)
- || (state == PLSR_STATE_DECEL))
- ? 1U
- : 0U;
- }
-
- static void PlsrLoadAxisEquivalentConfig(uint8_t axis,
- PLSR_EQUIVALENT_CONFIG *config)
- {
- uint16_t base = (uint16_t)(PLSR_SFD_CONFIG_START
- + (uint16_t)axis
- * PLSR_CORE_SFD_AXIS_STRIDE);
- uint16_t word;
- uint16_t lowWord;
- uint16_t highWord;
-
- config->unitCode = 0U;
- config->pulsesPerRevolution = 1UL;
- config->movementPerRevolution = 1UL;
- if (PlcDeviceReadSfd(base, &word) != PLC_DEVICE_OK)
- {
- return;
- }
- config->unitCode = (uint8_t)((word >> 8U) & 0x07U);
- if ((PlcDeviceReadSfd((uint16_t)(base + 2U), &lowWord)
- != PLC_DEVICE_OK)
- || (PlcDeviceReadSfd((uint16_t)(base + 3U), &highWord)
- != PLC_DEVICE_OK))
- {
- config->unitCode = 0U;
- return;
- }
- config->pulsesPerRevolution = (uint32_t)lowWord
- | ((uint32_t)highWord << 16U);
- if ((PlcDeviceReadSfd((uint16_t)(base + 4U), &lowWord)
- != PLC_DEVICE_OK)
- || (PlcDeviceReadSfd((uint16_t)(base + 5U), &highWord)
- != PLC_DEVICE_OK))
- {
- config->unitCode = 0U;
- return;
- }
- config->movementPerRevolution = (uint32_t)lowWord
- | ((uint32_t)highWord << 16U);
- if (PlsrPositionValidateEquivalent(config) != PLSR_RESULT_OK)
- {
- config->unitCode = 0U;
- config->pulsesPerRevolution = 1UL;
- config->movementPerRevolution = 1UL;
- }
- }
-
- static void PlsrPublishSdDword(uint8_t axis,
- uint8_t lowItem,
- int32_t value)
- {
- (void)PlcDevicePublishSdDword(axis, lowItem, value);
- }
-
- static int32_t PlsrGetCompatibleSegmentPulses(const PLSR_AXIS *axisObject)
- {
- int64_t signedPulses = (axisObject->directionPositive != 0U)
- ? axisObject->segmentAccountedPulses
- : -axisObject->segmentAccountedPulses;
-
- if (signedPulses > INT32_MAX)
- {
- return INT32_MAX;
- }
- if (signedPulses < INT32_MIN)
- {
- return INT32_MIN;
- }
- return (int32_t)signedPulses;
- }
-
- static int32_t PlsrClampCompatibleInt32(int64_t value)
- {
- if (value > INT32_MAX) return INT32_MAX;
- if (value < INT32_MIN) return INT32_MIN;
- return (int32_t)value;
- }
-
- static void PlsrPublishSegmentEvent(uint8_t axis,
- PLSR_AXIS *axisObject,
- PLSR_STOP_REASON reason)
- {
- uint16_t segment;
-
- if ((axisObject->jobValid == 0U)
- || (axisObject->segmentEventPublished != 0U))
- {
- return;
- }
- segment = PlsrPathGetCurrentSegment(&axisObject->path);
- if ((segment == 0U) || (segment > PLSR_MAX_SEGMENTS))
- {
- return;
- }
- if (PlcDevicePublishEvent(axis, segment, (uint16_t)reason)
- == PLC_DEVICE_OK)
- {
- axisObject->segmentEventPublished = 1U;
- }
- }
-
- static void PlsrPublishRuntime(uint8_t axis)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
- uint16_t currentSegment = (axisObject->jobValid != 0U)
- ? PlsrPathGetCurrentSegment(
- &axisObject->path)
- : 0U;
- int32_t segmentPulses = PlsrGetCompatibleSegmentPulses(axisObject);
- int32_t frequencyHz = (int32_t)PlsrHwGetCurrentFrequencyHz(axis);
- int64_t segmentEquivalent64 = segmentPulses;
- uint32_t speed = (uint32_t)frequencyHz;
- uint16_t publishedError;
- uint16_t publishedBlock;
-
- if (PlsrPositionPulsesToUnits(&axisObject->equivalent,
- segmentPulses,
- &segmentEquivalent64) != PLSR_RESULT_OK)
- {
- axisObject->positionOverflow = 1U;
- segmentEquivalent64 = (segmentPulses < 0) ? INT32_MIN : INT32_MAX;
- }
- if (PlsrPositionPulseFrequencyToSpeed(&axisObject->equivalent,
- (uint32_t)frequencyHz,
- &speed) != PLSR_RESULT_OK)
- {
- speed = UINT32_MAX;
- }
-
- PlsrPublishSdDword(axis,
- PLSR_SD_ITEM_SEGMENT,
- (int32_t)currentSegment);
- PlsrPublishSdDword(axis,
- PLSR_SD_ITEM_SEGMENT_PULSES,
- segmentPulses);
- PlsrPublishSdDword(axis,
- PLSR_SD_ITEM_SEGMENT_EQUIV,
- PlsrClampCompatibleInt32(segmentEquivalent64));
- PlsrPublishSdDword(axis, PLSR_SD_ITEM_FREQUENCY, frequencyHz);
- PlsrPublishSdDword(axis,
- PLSR_SD_ITEM_SPEED,
- (speed > (uint32_t)INT32_MAX) ? INT32_MAX
- : (int32_t)speed);
- /* SD(B+10/+11)只发布信捷兼容码;项目内部符号错误保留在状态API,
- * 不得用枚举数值占用信捷固定错误码。 */
- publishedError = axisObject->compatibleErrorCode;
- publishedBlock = (publishedError != 0U)
- ? axisObject->compatibleErrorBlock
- : 0U;
- (void)PlcDevicePublishSd(axis,
- PLSR_SD_ITEM_ERROR_CODE,
- (int32_t)publishedError);
- (void)PlcDevicePublishSd(axis,
- PLSR_SD_ITEM_ERROR_BLOCK,
- (int32_t)publishedBlock);
- }
-
- static void PlsrSetCompatibleParseError(uint8_t axis,
- PLSR_AXIS *axisObject)
- {
- uint16_t commonBase = (uint16_t)(PLSR_SFD_CONFIG_START
- + (uint16_t)axis
- * PLSR_CORE_SFD_AXIS_STRIDE);
- uint16_t dynamicBase = (uint16_t)(PLSR_HSD_CONFIG_START
- + (uint16_t)axis * 20U);
- uint16_t set;
-
- axisObject->compatibleErrorCode = 0U;
- axisObject->compatibleErrorBlock = 0U;
- if ((axisObject->parseDetail.result == PLSR_RESULT_RESOURCE_CONFLICT)
- || (axisObject->parseDetail.result == PLSR_RESULT_INVALID_RESOURCE))
- {
- axisObject->compatibleErrorCode = 26U;
- return;
- }
- if ((axisObject->parseDetail.block == PLSR_PARSE_BLOCK_S0)
- && (axisObject->parseDetail.segment != 0U))
- {
- axisObject->compatibleErrorCode = 1U;
- axisObject->compatibleErrorBlock = axisObject->parseDetail.segment;
- return;
- }
- if ((axisObject->parseDetail.address == (uint32_t)(commonBase + 2U))
- || (axisObject->parseDetail.address
- == (uint32_t)(commonBase + 4U)))
- {
- axisObject->compatibleErrorCode = 2U;
- return;
- }
- if ((axisObject->parseDetail.address == (uint32_t)(dynamicBase + 12U))
- || (axisObject->parseDetail.address
- == (uint32_t)(dynamicBase + 13U)))
- {
- axisObject->compatibleErrorCode =
- (axisObject->parseDetail.address
- == (uint32_t)(dynamicBase + 12U)) ? 15U : 16U;
- return;
- }
- for (set = 0U; set < 4U; set++)
- {
- uint32_t setBase = (uint32_t)commonBase + 50UL
- + (uint32_t)set * 20UL;
-
- if (axisObject->parseDetail.address == setBase + 12UL)
- {
- axisObject->compatibleErrorCode = 15U;
- return;
- }
- if (axisObject->parseDetail.address == setBase + 13UL)
- {
- axisObject->compatibleErrorCode = 16U;
- return;
- }
- }
- if ((axisObject->parseDetail.address == (uint32_t)(commonBase + 30U))
- || (axisObject->parseDetail.address
- == (uint32_t)(commonBase + 32U))
- || (axisObject->parseDetail.result == PLSR_RESULT_SEGMENT_OVERFLOW)
- || (axisObject->parseDetail.result == PLSR_RESULT_BLOCK_OVERLAP)
- || (axisObject->parseDetail.result == PLSR_RESULT_ADDRESS_OVERFLOW))
- {
- axisObject->compatibleErrorCode = 4U;
- return;
- }
- if (axisObject->parseDetail.block == PLSR_PARSE_BLOCK_S2)
- {
- axisObject->compatibleErrorCode = 3U;
- }
- }
-
- static void PlsrPublishAxis(uint8_t axis)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
- uint8_t compatibleRun;
-
- compatibleRun = (uint8_t)((PlsrStateIsPulseActive(axisObject->state) != 0U)
- || (axisObject->state == PLSR_STATE_WAIT));
- (void)PlcDevicePublishSm(axis,
- compatibleRun,
- axisObject->directionPositive);
- PlsrPublishRuntime(axis);
- }
-
- static void PlsrSetStopReason(PLSR_AXIS *axis,
- PLSR_STOP_REASON stopReason)
- {
- if (stopReason > axis->stopReason)
- {
- axis->stopReason = stopReason;
- }
- }
-
- /* 将 64 位逻辑位置发布为 HSD 的 32 位兼容值。
- * 超出范围时保持最近一次合法值,只锁存诊断,禁止回绕或静默截断。 */
- static void PlsrPublishPosition(uint8_t axis, PLSR_AXIS *axisObject)
- {
- int32_t compatValue;
- int64_t equivalentPosition;
- uint16_t base = (uint16_t)((uint16_t)axis
- * PLSR_HSD_RUNTIME_AXIS_COUNT);
-
- if ((axisObject->logicalPosition > INT32_MAX)
- || (axisObject->logicalPosition < INT32_MIN))
- {
- axisObject->positionOverflow = 1U;
- return;
- }
- compatValue = (int32_t)axisObject->logicalPosition;
- (void)PlcDevicePublishHsdDword(base, compatValue);
- if ((PlsrPositionPulsesToUnits(&axisObject->equivalent,
- axisObject->logicalPosition,
- &equivalentPosition) != PLSR_RESULT_OK)
- || (equivalentPosition > INT32_MAX)
- || (equivalentPosition < INT32_MIN))
- {
- axisObject->positionOverflow = 1U;
- return;
- }
- (void)PlcDevicePublishHsdDword((uint16_t)(base + 2U),
- (int32_t)equivalentPosition);
- }
-
- static uint8_t PlsrAddInt64Checked(int64_t left,
- int64_t right,
- int64_t *result)
- {
- if ((result == NULL)
- || ((right > 0) && (left > INT64_MAX - right))
- || ((right < 0) && (left < INT64_MIN - right)))
- {
- return 0U;
- }
- *result = left + right;
- return 1U;
- }
-
- static PLSR_RESULT PlsrReadLimitInput(const PLSR_JOB_SNAPSHOT *job,
- uint8_t point,
- uint8_t activeLow,
- uint8_t *active)
- {
- uint8_t rawLevel;
-
- if ((job == NULL) || (active == NULL))
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if (point == 0xFFU)
- {
- *active = 0U;
- return PLSR_RESULT_OK;
- }
- if ((job->source.readBit == NULL)
- || (job->source.readBit(job->source.context,
- PLSR_DEVICE_X,
- point,
- &rawLevel) == 0U))
- {
- return PLSR_RESULT_DATA_ACCESS;
- }
- *active = (activeLow != 0U)
- ? ((rawLevel == 0U) ? 1U : 0U)
- : ((rawLevel != 0U) ? 1U : 0U);
- return PLSR_RESULT_OK;
- }
-
- static int64_t PlsrGetBrakingDistance(const PLSR_AXIS *axisObject)
- {
- uint64_t frequencyHz;
- uint64_t denominator;
- uint64_t numerator;
-
- if ((axisObject->profileActive == 0U)
- || (axisObject->profile.decelSlopeHzPerMs == 0UL))
- {
- return 0;
- }
- frequencyHz = axisObject->profile.frequencyQ32 >> 32U;
- numerator = frequencyHz * frequencyHz;
- denominator = UINT64_C(2000)
- * axisObject->profile.decelSlopeHzPerMs;
- return (int64_t)((numerator + denominator - 1UL) / denominator);
- }
-
- static PLSR_RESULT PlsrUpdateLimitState(PLSR_AXIS *axisObject,
- const PLSR_JOB_SNAPSHOT *job,
- uint8_t includeBrakingDistance)
- {
- int64_t brakingDistance = 0;
- uint8_t positiveHard;
- uint8_t negativeHard;
- uint8_t positiveSoft = 0U;
- uint8_t negativeSoft = 0U;
- PLSR_RESULT result;
-
- result = PlsrReadLimitInput(job,
- job->limits.positiveInputPoint,
- job->limits.positiveInputActiveLow,
- &positiveHard);
- if (result != PLSR_RESULT_OK) return result;
- result = PlsrReadLimitInput(job,
- job->limits.negativeInputPoint,
- job->limits.negativeInputActiveLow,
- &negativeHard);
- if (result != PLSR_RESULT_OK) return result;
-
- if ((job->limits.softLimitEnabled != 0U)
- && (axisObject->positionValid != 0U))
- {
- if (includeBrakingDistance != 0U)
- {
- brakingDistance = PlsrGetBrakingDistance(axisObject);
- }
- if (axisObject->logicalPosition
- >= job->limits.positiveSoftLimitPulses)
- {
- positiveSoft = 1U;
- }
- else if ((axisObject->directionPositive != 0U)
- && (brakingDistance > 0)
- && ((axisObject->logicalPosition
- > INT64_MAX - brakingDistance)
- || (axisObject->logicalPosition + brakingDistance
- >= job->limits.positiveSoftLimitPulses)))
- {
- positiveSoft = 1U;
- }
- if (axisObject->logicalPosition
- <= job->limits.negativeSoftLimitPulses)
- {
- negativeSoft = 1U;
- }
- else if ((axisObject->directionPositive == 0U)
- && (brakingDistance > 0)
- && ((axisObject->logicalPosition
- < INT64_MIN + brakingDistance)
- || (axisObject->logicalPosition - brakingDistance
- <= job->limits.negativeSoftLimitPulses)))
- {
- negativeSoft = 1U;
- }
- }
- axisObject->positiveLimitActive =
- ((positiveHard != 0U) || (positiveSoft != 0U)) ? 1U : 0U;
- axisObject->negativeLimitActive =
- ((negativeHard != 0U) || (negativeSoft != 0U)) ? 1U : 0U;
- return PLSR_RESULT_OK;
- }
-
- static PLSR_RESULT PlsrCheckStartProtection(PLSR_AXIS *axisObject,
- const PLSR_JOB_SNAPSHOT *job)
- {
- PLSR_RESULT result;
-
- if (axisObject->emergencyLatched != 0U)
- {
- return PLSR_RESULT_EMERGENCY_LATCHED;
- }
- if ((job->limits.softLimitEnabled != 0U)
- && (axisObject->positionValid == 0U))
- {
- return PLSR_RESULT_POSITION_INVALID;
- }
- result = PlsrUpdateLimitState(axisObject, job, 0U);
- if (result != PLSR_RESULT_OK)
- {
- return result;
- }
- if ((job->initialDirectionPositive != 0U)
- && (axisObject->positiveLimitActive != 0U))
- {
- return PLSR_RESULT_LIMIT_POSITIVE;
- }
- if ((job->initialDirectionPositive == 0U)
- && (axisObject->negativeLimitActive != 0U))
- {
- return PLSR_RESULT_LIMIT_NEGATIVE;
- }
- return PLSR_RESULT_OK;
- }
-
- /* 将 HAL 实际完成的完整脉冲/AB周期合并到64位位置。
- * emittedPulses 每段从0开始,因此用 segmentAccountedPulses 做差量去重。 */
- static void PlsrAccountHardwarePulses(uint8_t axis,
- PLSR_AXIS *axisObject)
- {
- int64_t emittedPulses;
- int64_t delta;
- int64_t signedDelta;
- int64_t newLogicalPosition;
- int64_t newTaskPulses;
- int64_t newTotalPulses;
-
- if (axisObject->segmentAccountingActive == 0U)
- {
- return;
- }
- emittedPulses = PlsrHwGetEmittedPulses(axis);
- if ((emittedPulses < 0)
- || (emittedPulses < axisObject->segmentAccountedPulses))
- {
- axisObject->positionOverflow = 1U;
- (void)PlsrPostEvent(axis, PLSR_EVENT_COUNTER_FAULT);
- return;
- }
- delta = emittedPulses - axisObject->segmentAccountedPulses;
- if (delta == 0)
- {
- return;
- }
- signedDelta = (axisObject->directionPositive != 0U) ? delta : -delta;
- if ((PlsrAddInt64Checked(axisObject->logicalPosition,
- signedDelta,
- &newLogicalPosition) == 0U)
- || (PlsrAddInt64Checked(axisObject->taskPulses,
- signedDelta,
- &newTaskPulses) == 0U)
- || (PlsrAddInt64Checked(axisObject->totalPulses,
- delta,
- &newTotalPulses) == 0U))
- {
- axisObject->positionOverflow = 1U;
- axisObject->segmentAccountedPulses = emittedPulses;
- (void)PlsrPostEvent(axis, PLSR_EVENT_COUNTER_FAULT);
- return;
- }
-
- axisObject->logicalPosition = newLogicalPosition;
- axisObject->taskPulses = newTaskPulses;
- axisObject->totalPulses = newTotalPulses;
- axisObject->segmentAccountedPulses = emittedPulses;
- PlsrPublishPosition(axis, axisObject);
- PlsrPublishRuntime(axis);
- }
-
- static uint8_t PlsrTransitionIsAllowed(PLSR_STATE current,
- PLSR_STATE target)
- {
- if (current == target)
- {
- return 1U;
- }
- if (target == PLSR_STATE_ERROR)
- {
- return 1U;
- }
-
- switch (current)
- {
- case PLSR_STATE_UNINITIALIZED:
- return (target == PLSR_STATE_IDLE) ? 1U : 0U;
-
- case PLSR_STATE_IDLE:
- case PLSR_STATE_COMPLETED:
- case PLSR_STATE_STOPPED:
- return ((target == PLSR_STATE_IDLE)
- || (target == PLSR_STATE_ACCEL)
- || (target == PLSR_STATE_WAIT)
- || (target == PLSR_STATE_COMPLETED))
- ? 1U
- : 0U;
-
- case PLSR_STATE_ACCEL:
- case PLSR_STATE_RUN:
- return ((target == PLSR_STATE_ACCEL)
- || (target == PLSR_STATE_RUN)
- || (target == PLSR_STATE_DECEL)
- || (target == PLSR_STATE_WAIT)
- || (target == PLSR_STATE_COMPLETED)
- || (target == PLSR_STATE_STOPPED))
- ? 1U
- : 0U;
-
- case PLSR_STATE_DECEL:
- return ((target == PLSR_STATE_ACCEL)
- || (target == PLSR_STATE_RUN)
- || (target == PLSR_STATE_WAIT)
- || (target == PLSR_STATE_PAUSED)
- || (target == PLSR_STATE_COMPLETED)
- || (target == PLSR_STATE_STOPPED))
- ? 1U
- : 0U;
-
- case PLSR_STATE_WAIT:
- return ((target == PLSR_STATE_ACCEL)
- || (target == PLSR_STATE_RUN)
- || (target == PLSR_STATE_PAUSED)
- || (target == PLSR_STATE_COMPLETED)
- || (target == PLSR_STATE_STOPPED))
- ? 1U
- : 0U;
-
- case PLSR_STATE_PAUSED:
- return ((target == PLSR_STATE_ACCEL)
- || (target == PLSR_STATE_RUN)
- || (target == PLSR_STATE_STOPPED))
- ? 1U
- : 0U;
-
- case PLSR_STATE_ERROR:
- return (target == PLSR_STATE_IDLE) ? 1U : 0U;
-
- default:
- return 0U;
- }
- }
-
- PLSR_RESULT PlsrStateTransition(uint8_t axis,
- PLSR_STATE target,
- PLSR_TRANSITION_REASON reason)
- {
- PLSR_AXIS *axisObject;
-
- (void)reason;
- if (axis >= PLSR_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_AXIS;
- }
- if ((uint32_t)target > (uint32_t)PLSR_STATE_ERROR)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
-
- axisObject = &PlsrAxes[axis];
- if (PlsrTransitionIsAllowed(axisObject->state, target) == 0U)
- {
- axisObject->illegalTransitionCount++;
- axisObject->error = PLSR_ERROR_ILLEGAL_TRANSITION;
- axisObject->stopReason = PLSR_STOP_REASON_FAULT;
- axisObject->done = 0U;
- axisObject->state = PLSR_STATE_ERROR;
- axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
- axisObject->immediateStopPending = 0U;
- PlsrStopSegmentHardware(axis, axisObject);
- PlsrResourceRelease(&axisObject->lease);
- PlsrPublishAxis(axis);
- return PLSR_RESULT_INVALID_STATE;
- }
-
- axisObject->state = target;
- if (target == PLSR_STATE_COMPLETED)
- {
- axisObject->done = 1U;
- }
- if ((target == PLSR_STATE_COMPLETED) || (target == PLSR_STATE_STOPPED)
- || (target == PLSR_STATE_ERROR))
- {
- axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
- axisObject->immediateStopPending = 0U;
- PlsrPathTerminate(&axisObject->path);
- PlsrStopSegmentHardware(axis, axisObject);
- PlsrResourceRelease(&axisObject->lease);
- /* 运动已结束:记录 lastBusy=0,保证掉电后恢复时位置仍可信。 */
- (void)PlcDeviceSetHsdCheckpointMeta(axisObject->positionValid, 0U);
- (void)PlcDeviceCheckpointHsd();
- }
- PlsrPublishAxis(axis);
- return PLSR_RESULT_OK;
- }
-
- static uint8_t PlsrCommandPriority(PLSR_COMMAND_OPCODE opcode)
- {
- switch (opcode)
- {
- case PLSR_CMD_STOP_IMMEDIATE:
- return 0U;
- case PLSR_CMD_STOP_DECEL:
- return 1U;
- case PLSR_CMD_PAUSE:
- return 2U;
- case PLSR_CMD_RESUME:
- return 3U;
- default:
- return 4U;
- }
- }
-
- static PLSR_RESULT PlsrQueueCommand(const PLSR_COMMAND *command,
- const PLSR_START_REQUEST *start,
- const PLSR_CALL *call)
- {
- uint32_t interruptState;
- uint8_t freeSlot = PLSR_COMMAND_QUEUE_DEPTH;
- uint8_t index;
-
- interruptState = PlsrCoreEnterCritical();
- if ((PlsrAxes[command->axis].hasLastCommand != 0U)
- && (PlsrAxes[command->axis].lastCommandSequence == command->sequence))
- {
- PLSR_RESULT result = PlsrAxes[command->axis].lastCommandResult;
- PlsrCoreExitCritical(interruptState);
- return result;
- }
-
- for (index = 0U; index < PLSR_COMMAND_QUEUE_DEPTH; index++)
- {
- if (PlsrCommandQueue[index].occupied != 0U)
- {
- if ((PlsrCommandQueue[index].command.axis == command->axis)
- && (PlsrCommandQueue[index].command.sequence
- == command->sequence))
- {
- PlsrCoreExitCritical(interruptState);
- return PLSR_RESULT_QUEUED;
- }
- }
- else if (freeSlot == PLSR_COMMAND_QUEUE_DEPTH)
- {
- freeSlot = index;
- }
- }
-
- if (freeSlot == PLSR_COMMAND_QUEUE_DEPTH)
- {
- PlsrCoreExitCritical(interruptState);
- return PLSR_RESULT_QUEUE_FULL;
- }
-
- PlsrCommandQueue[freeSlot].command = *command;
- if (start != NULL)
- {
- PlsrCommandQueue[freeSlot].start = *start;
- PlsrCommandQueue[freeSlot].hasStart = 1U;
- }
- else
- {
- (void)memset(&PlsrCommandQueue[freeSlot].start,
- 0,
- sizeof(PlsrCommandQueue[freeSlot].start));
- PlsrCommandQueue[freeSlot].hasStart = 0U;
- }
- if (call != NULL)
- {
- PlsrCommandQueue[freeSlot].call = *call;
- PlsrCommandQueue[freeSlot].hasCall = 1U;
- }
- else
- {
- (void)memset(&PlsrCommandQueue[freeSlot].call,
- 0,
- sizeof(PlsrCommandQueue[freeSlot].call));
- PlsrCommandQueue[freeSlot].hasCall = 0U;
- }
- PlsrCommandQueue[freeSlot].ticket = PlsrNextTicket++;
- PlsrCommandQueue[freeSlot].occupied = 1U;
- PlsrCoreExitCritical(interruptState);
- return PLSR_RESULT_QUEUED;
- }
-
- static uint8_t PlsrPopHighestPriorityCommand(PLSR_COMMAND_SLOT *slot)
- {
- uint32_t interruptState;
- uint32_t selectedTicket = 0UL;
- uint8_t selectedPriority = 0xFFU;
- uint8_t selected = PLSR_COMMAND_QUEUE_DEPTH;
- uint8_t index;
- uint8_t priority;
-
- interruptState = PlsrCoreEnterCritical();
- for (index = 0U; index < PLSR_COMMAND_QUEUE_DEPTH; index++)
- {
- if (PlsrCommandQueue[index].occupied == 0U)
- {
- continue;
- }
- priority = PlsrCommandPriority(PlsrCommandQueue[index].command.opcode);
- if ((selected == PLSR_COMMAND_QUEUE_DEPTH)
- || (priority < selectedPriority)
- || ((priority == selectedPriority)
- && ((int32_t)(PlsrCommandQueue[index].ticket
- - selectedTicket)
- < 0)))
- {
- selected = index;
- selectedPriority = priority;
- selectedTicket = PlsrCommandQueue[index].ticket;
- }
- }
-
- if (selected == PLSR_COMMAND_QUEUE_DEPTH)
- {
- PlsrCoreExitCritical(interruptState);
- return 0U;
- }
-
- *slot = PlsrCommandQueue[selected];
- PlsrCommandQueue[selected].occupied = 0U;
- PlsrCoreExitCritical(interruptState);
- return 1U;
- }
-
- #ifdef PLSR_HOST_TEST
- PLSR_RESULT PlsrPostStart(const PLSR_START_REQUEST *request)
- {
- PLSR_COMMAND command;
-
- if (request == NULL)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if (request->axis >= PLSR_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_AXIS;
- }
- if (PlsrInitialized == 0U)
- {
- return PLSR_RESULT_INVALID_STATE;
- }
-
- command.sequence = request->sequence;
- command.axis = request->axis;
- command.opcode = PLSR_CMD_START;
- command.argument = 0;
- return PlsrQueueCommand(&command, request, NULL);
- }
- #endif /* PLSR_HOST_TEST */
-
- PLSR_RESULT PlsrPostCall(const PLSR_CALL *call)
- {
- PLSR_COMMAND command;
-
- if (call == NULL)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if (call->dAxis >= PLSR_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_AXIS;
- }
- if (PlsrInitialized == 0U)
- {
- return PLSR_RESULT_INVALID_STATE;
- }
- command.sequence = call->sequence;
- command.axis = call->dAxis;
- command.opcode = PLSR_CMD_START;
- command.argument = 0;
- return PlsrQueueCommand(&command, NULL, call);
- }
-
- PLSR_RESULT PlsrPostCommand(const PLSR_COMMAND *command)
- {
- if (command == NULL)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if (command->axis >= PLSR_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_AXIS;
- }
- if (((uint32_t)command->opcode > (uint32_t)PLSR_CMD_SELF_TEST)
- || (command->opcode == PLSR_CMD_START))
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if (PlsrInitialized == 0U)
- {
- return PLSR_RESULT_INVALID_STATE;
- }
- return PlsrQueueCommand(command, NULL, NULL);
- }
-
- PLSR_RESULT PlsrPostEvent(uint8_t axis, uint32_t eventMask)
- {
- uint32_t interruptState;
-
- if (axis >= PLSR_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_AXIS;
- }
- if ((eventMask == 0UL) || ((eventMask & ~PLSR_EVENT_ALL_MASK) != 0UL))
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
-
- interruptState = PlsrCoreEnterCritical();
- PlsrAxes[axis].pendingEvents |= eventMask;
- PlsrCoreExitCritical(interruptState);
- return PLSR_RESULT_OK;
- }
-
- static uint32_t PlsrTakeEvents(uint8_t axis, uint32_t mask)
- {
- uint32_t interruptState;
- uint32_t events;
-
- interruptState = PlsrCoreEnterCritical();
- events = PlsrAxes[axis].pendingEvents & mask;
- PlsrAxes[axis].pendingEvents &= ~events;
- PlsrCoreExitCritical(interruptState);
- return events;
- }
-
- static uint8_t PlsrAnyAxisBusy(void)
- {
- uint8_t axis;
-
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- if (PlsrStateIsBusy(PlsrAxes[axis].state) != 0U)
- {
- return 1U;
- }
- }
- return 0U;
- }
-
- static PLSR_RESULT PlsrStartAxis(PLSR_AXIS *axisObject,
- const PLSR_START_REQUEST *start)
- {
- PLSR_RESOURCE_REQUEST resourceRequest;
- PLSR_RESULT result;
-
- if ((axisObject->state != PLSR_STATE_IDLE)
- && (axisObject->state != PLSR_STATE_COMPLETED)
- && (axisObject->state != PLSR_STATE_STOPPED))
- {
- return PLSR_RESULT_INVALID_STATE;
- }
-
- resourceRequest.ownerAxis = start->axis;
- resourceRequest.outputMode = start->outputMode;
- resourceRequest.dAxis = start->axis;
- resourceRequest.directionPoint = start->directionPoint;
- result = PlsrResourceReserve(&resourceRequest, &axisObject->lease);
- if (result != PLSR_RESULT_OK)
- {
- axisObject->error = (result == PLSR_RESULT_RESOURCE_CONFLICT)
- ? PLSR_ERROR_RESOURCE_CONFLICT
- : PLSR_ERROR_INVALID_RESOURCE;
- return result;
- }
-
- axisObject->outputMode = start->outputMode;
- axisObject->directionPositive = (start->directionPositive != 0U) ? 1U : 0U;
- axisObject->error = PLSR_ERROR_NONE;
- axisObject->compatibleErrorCode = 0U;
- axisObject->compatibleErrorBlock = 0U;
- axisObject->stopReason = PLSR_STOP_REASON_NONE;
- axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
- axisObject->immediateStopPending = 0U;
- axisObject->done = 0U;
- axisObject->jobValid = 0U;
- axisObject->taskPulses = 0;
- axisObject->segmentAccountedPulses = 0;
- axisObject->segmentAccountingActive = 0U;
- result = PlsrStateTransition(start->axis,
- PLSR_STATE_ACCEL,
- PLSR_TRANSITION_START);
- if (result != PLSR_RESULT_OK)
- {
- PlsrResourceRelease(&axisObject->lease);
- }
- else
- {
- /* 运动开始:掉电恢复时据此判定"断电时在运动中"。 */
- (void)PlcDeviceSetHsdCheckpointMeta(axisObject->positionValid, 1U);
- (void)PlcDeviceCheckpointHsd();
- }
- return result;
- }
-
- static PLSR_RESULT PlsrStartCall(PLSR_AXIS *axisObject,
- const PLSR_CALL *call)
- {
- PLSR_RESOURCE_REQUEST resourceRequest;
- PLSR_PARSE_CONTEXT parseContext;
- PLSR_RESULT result;
-
- if ((axisObject->state != PLSR_STATE_IDLE)
- && (axisObject->state != PLSR_STATE_COMPLETED)
- && (axisObject->state != PLSR_STATE_STOPPED))
- {
- return PLSR_RESULT_INVALID_STATE;
- }
- if (axisObject->emergencyLatched != 0U)
- {
- return PLSR_RESULT_EMERGENCY_LATCHED;
- }
-
- axisObject->compatibleErrorCode = 0U;
- axisObject->compatibleErrorBlock = 0U;
-
- parseContext.logicalPosition = axisObject->logicalPosition;
- parseContext.positionValid = axisObject->positionValid;
- result = PlsrBuildJobSnapshot(call,
- &parseContext,
- &PlsrJobScratch,
- &axisObject->parseDetail);
- if (result != PLSR_RESULT_OK)
- {
- PlsrSetCompatibleParseError(call->dAxis, axisObject);
- return result;
- }
- result = PlsrCheckStartProtection(axisObject, &PlsrJobScratch);
- if (result != PLSR_RESULT_OK)
- {
- if (result == PLSR_RESULT_LIMIT_POSITIVE)
- {
- axisObject->error = PLSR_ERROR_LIMIT_POSITIVE;
- axisObject->compatibleErrorCode = 5U;
- axisObject->stopReason = PLSR_STOP_REASON_LIMIT_POSITIVE;
- }
- else if (result == PLSR_RESULT_LIMIT_NEGATIVE)
- {
- axisObject->error = PLSR_ERROR_LIMIT_NEGATIVE;
- axisObject->compatibleErrorCode = 6U;
- axisObject->stopReason = PLSR_STOP_REASON_LIMIT_NEGATIVE;
- }
- else if (result == PLSR_RESULT_EMERGENCY_LATCHED)
- {
- axisObject->error = PLSR_ERROR_EMERGENCY;
- axisObject->stopReason = PLSR_STOP_REASON_SOFTWARE_EMERGENCY;
- }
- else if (result == PLSR_RESULT_DATA_ACCESS)
- {
- axisObject->error = PLSR_ERROR_INTERNAL;
- axisObject->compatibleErrorCode = 26U;
- axisObject->stopReason = PLSR_STOP_REASON_FAULT;
- }
- return result;
- }
-
- resourceRequest.ownerAxis = call->dAxis;
- resourceRequest.outputMode =
- (PLSR_OUTPUT_MODE)PlsrJobScratch.outputMode;
- resourceRequest.dAxis = call->dAxis;
- resourceRequest.directionPoint = PlsrJobScratch.directionPoint;
- result = PlsrResourceReserve(&resourceRequest, &axisObject->lease);
- if (result != PLSR_RESULT_OK)
- {
- axisObject->error = (result == PLSR_RESULT_RESOURCE_CONFLICT)
- ? PLSR_ERROR_RESOURCE_CONFLICT
- : PLSR_ERROR_INVALID_RESOURCE;
- axisObject->parseDetail.result = result;
- axisObject->parseDetail.block = PLSR_PARSE_BLOCK_OUTPUT;
- axisObject->compatibleErrorCode = 26U;
- axisObject->compatibleErrorBlock = 0U;
- return result;
- }
-
- axisObject->job = PlsrJobScratch;
- axisObject->jobValid = 1U;
- if ((axisObject->equivalent.unitCode
- != axisObject->job.equivalent.unitCode)
- || (axisObject->equivalent.pulsesPerRevolution
- != axisObject->job.equivalent.pulsesPerRevolution)
- || (axisObject->equivalent.movementPerRevolution
- != axisObject->job.equivalent.movementPerRevolution))
- {
- axisObject->equivalentCommandRemainder = 0;
- }
- axisObject->equivalent = axisObject->job.equivalent;
- axisObject->outputMode = (PLSR_OUTPUT_MODE)axisObject->job.outputMode;
- axisObject->directionPositive = axisObject->job.initialDirectionPositive;
- axisObject->error = PLSR_ERROR_NONE;
- axisObject->compatibleErrorCode = 0U;
- axisObject->compatibleErrorBlock = 0U;
- axisObject->stopReason = PLSR_STOP_REASON_NONE;
- axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
- axisObject->immediateStopPending = 0U;
- axisObject->done = 0U;
- axisObject->taskPulses = 0;
- axisObject->segmentAccountedPulses = 0;
- axisObject->segmentAccountingActive = 0U;
- axisObject->segmentEventPublished = 0U;
- PlsrPathBegin(&axisObject->path,
- &axisObject->job,
- axisObject->logicalPosition);
- if (axisObject->path.jobEnded != 0U)
- {
- /* 起点就是零脉冲且跳转链已结束(任务无实际脉冲)。 */
- axisObject->stopReason = PLSR_STOP_REASON_NORMAL_COMPLETE;
- (void)PlsrStateTransition(call->dAxis,
- PLSR_STATE_COMPLETED,
- PLSR_TRANSITION_JOB_COMPLETE);
- axisObject->jobValid = 0U;
- return PLSR_RESULT_OK;
- }
- result = PlsrStateTransition(call->dAxis,
- PLSR_STATE_ACCEL,
- PLSR_TRANSITION_START);
- if (result != PLSR_RESULT_OK)
- {
- axisObject->jobValid = 0U;
- PlsrResourceRelease(&axisObject->lease);
- }
- else
- {
- /* 启动当前段硬件输出与速度曲线。 */
- /* 零脉冲跳转链耗尽本轮预算时没有实际运动段,等待下一次
- * PlsrPathTick 找到非零段后再启动硬件。 */
- if (axisObject->path.jumpChainPending == 0U)
- {
- result = PlsrStartSegmentHardware(call->dAxis, axisObject);
- }
- if (result != PLSR_RESULT_OK)
- {
- if ((result == PLSR_RESULT_LIMIT_POSITIVE)
- || (result == PLSR_RESULT_LIMIT_NEGATIVE))
- {
- axisObject->error =
- (result == PLSR_RESULT_LIMIT_POSITIVE)
- ? PLSR_ERROR_LIMIT_POSITIVE
- : PLSR_ERROR_LIMIT_NEGATIVE;
- axisObject->compatibleErrorCode =
- (result == PLSR_RESULT_LIMIT_POSITIVE) ? 5U : 6U;
- PlsrSetStopReason(
- axisObject,
- (result == PLSR_RESULT_LIMIT_POSITIVE)
- ? PLSR_STOP_REASON_LIMIT_POSITIVE
- : PLSR_STOP_REASON_LIMIT_NEGATIVE);
- (void)PlsrStateTransition(call->dAxis,
- PLSR_STATE_STOPPED,
- PLSR_TRANSITION_STOP);
- }
- else
- {
- axisObject->error = PLSR_ERROR_TIMER_FAULT;
- PlsrSetStopReason(axisObject, PLSR_STOP_REASON_FAULT);
- axisObject->done = 0U;
- (void)PlsrStateTransition(call->dAxis,
- PLSR_STATE_ERROR,
- PLSR_TRANSITION_FAULT);
- }
- return result;
- }
- /* 运动开始:掉电恢复时据此判定"断电时在运动中"。 */
- (void)PlcDeviceSetHsdCheckpointMeta(axisObject->positionValid, 1U);
- (void)PlcDeviceCheckpointHsd();
- }
- return result;
- }
-
- static PLSR_RESULT PlsrStopImmediate(uint8_t axis)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
-
- if ((axisObject->state == PLSR_STATE_IDLE)
- || (axisObject->state == PLSR_STATE_COMPLETED)
- || (axisObject->state == PLSR_STATE_STOPPED))
- {
- return PLSR_RESULT_OK;
- }
- if (axisObject->state == PLSR_STATE_ERROR)
- {
- return PLSR_RESULT_INVALID_STATE;
- }
- if (axisObject->immediateStopPending != 0U)
- {
- return PLSR_RESULT_OK;
- }
-
- PlsrSetStopReason(axisObject, PLSR_STOP_REASON_STOP_IMMEDIATE);
- axisObject->pendingTerminal = PLSR_STATE_STOPPED;
- PlsrPublishSegmentEvent(axis,
- axisObject,
- PLSR_STOP_REASON_STOP_IMMEDIATE);
- PlsrPathTerminate(&axisObject->path);
- PlsrStopSegmentHardware(axis, axisObject);
- return PlsrStateTransition(axis,
- PLSR_STATE_STOPPED,
- PLSR_TRANSITION_STOP);
- }
-
- static PLSR_RESULT PlsrRequestControlledStop(uint8_t axis,
- PLSR_STATE terminal,
- PLSR_STOP_REASON reason)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
- PLSR_RESULT result;
-
- PlsrSetStopReason(axisObject, reason);
- axisObject->pendingTerminal = terminal;
- PlsrPublishSegmentEvent(axis, axisObject, reason);
- PlsrPathTerminate(&axisObject->path);
-
- if ((axisObject->state == PLSR_STATE_WAIT)
- || (axisObject->state == PLSR_STATE_PAUSED))
- {
- PlsrStopSegmentHardware(axis, axisObject);
- return PlsrStateTransition(axis,
- terminal,
- PLSR_TRANSITION_DECEL_COMPLETE);
- }
- if (axisObject->profileActive == 0U)
- {
- return (axisObject->state == PLSR_STATE_DECEL)
- ? PLSR_RESULT_OK
- : PlsrStateTransition(axis,
- PLSR_STATE_DECEL,
- PLSR_TRANSITION_DECEL_REQUEST);
- }
- result = PlsrProfileRequestStop(&axisObject->profile);
- if (result != PLSR_RESULT_OK)
- {
- return result;
- }
- if (axisObject->state == PLSR_STATE_DECEL)
- {
- return PLSR_RESULT_OK;
- }
- return PlsrStateTransition(axis,
- PLSR_STATE_DECEL,
- PLSR_TRANSITION_DECEL_REQUEST);
- }
-
- static PLSR_RESULT PlsrStopDecel(uint8_t axis)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
-
- if ((axisObject->state == PLSR_STATE_IDLE)
- || (axisObject->state == PLSR_STATE_COMPLETED)
- || (axisObject->state == PLSR_STATE_STOPPED))
- {
- return PLSR_RESULT_OK;
- }
- if (axisObject->state == PLSR_STATE_ERROR)
- {
- return PLSR_RESULT_INVALID_STATE;
- }
- if (axisObject->stopReason >= PLSR_STOP_REASON_STOP_IMMEDIATE)
- {
- return PLSR_RESULT_OK;
- }
-
- return PlsrRequestControlledStop(axis,
- PLSR_STATE_STOPPED,
- PLSR_STOP_REASON_STOP_DECEL);
- }
-
- static PLSR_RESULT PlsrPause(uint8_t axis)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
-
- if (axisObject->state == PLSR_STATE_PAUSED)
- {
- return PLSR_RESULT_OK;
- }
- if (axisObject->stopReason >= PLSR_STOP_REASON_STOP_DECEL)
- {
- return PLSR_RESULT_BUSY;
- }
- if (axisObject->state == PLSR_STATE_WAIT)
- {
- return PlsrRequestControlledStop(axis,
- PLSR_STATE_PAUSED,
- PLSR_STOP_REASON_PAUSE);
- }
- if ((axisObject->state != PLSR_STATE_ACCEL)
- && (axisObject->state != PLSR_STATE_RUN)
- && (axisObject->state != PLSR_STATE_DECEL))
- {
- return PLSR_RESULT_INVALID_STATE;
- }
-
- return PlsrRequestControlledStop(axis,
- PLSR_STATE_PAUSED,
- PLSR_STOP_REASON_PAUSE);
- }
-
- static PLSR_RESULT PlsrExecuteCommand(const PLSR_COMMAND_SLOT *slot)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[slot->command.axis];
- PLC_DEVICE_RESULT deviceResult;
- PLSR_RESULT result;
-
- switch (slot->command.opcode)
- {
- case PLSR_CMD_START:
- if (slot->hasCall != 0U)
- {
- result = PlsrStartCall(axisObject, &slot->call);
- }
- else
- {
- result = (slot->hasStart != 0U)
- ? PlsrStartAxis(axisObject, &slot->start)
- : PLSR_RESULT_INVALID_ARGUMENT;
- }
- break;
-
- case PLSR_CMD_STOP_DECEL:
- result = PlsrStopDecel(slot->command.axis);
- break;
-
- case PLSR_CMD_STOP_IMMEDIATE:
- result = PlsrStopImmediate(slot->command.axis);
- break;
-
- case PLSR_CMD_PAUSE:
- result = PlsrPause(slot->command.axis);
- break;
-
- case PLSR_CMD_RESUME:
- if (axisObject->state != PLSR_STATE_PAUSED)
- {
- result = PLSR_RESULT_INVALID_STATE;
- }
- else
- {
- axisObject->stopReason = PLSR_STOP_REASON_NONE;
- axisObject->pendingTerminal = PLSR_STATE_UNINITIALIZED;
- result = PlsrStateTransition(slot->command.axis,
- PLSR_STATE_ACCEL,
- PLSR_TRANSITION_WAIT_COMPLETE);
- }
- break;
-
- case PLSR_CMD_SET_POSITION:
- if (PlsrStateIsBusy(axisObject->state) != 0U)
- {
- result = PLSR_RESULT_BUSY;
- }
- else
- {
- axisObject->logicalPosition = slot->command.argument;
- axisObject->positionValid = 1U;
- axisObject->positionOverflow = 0U;
- PlsrPublishPosition(slot->command.axis, axisObject);
- (void)PlcDeviceSetHsdCheckpointMeta(1U, 0U);
- (void)PlcDeviceCheckpointHsd();
- result = PLSR_RESULT_OK;
- }
- break;
-
- case PLSR_CMD_CLEAR_POSITION:
- if (PlsrStateIsBusy(axisObject->state) != 0U)
- {
- result = PLSR_RESULT_BUSY;
- }
- else
- {
- axisObject->logicalPosition = 0;
- axisObject->positionValid = 1U;
- axisObject->positionOverflow = 0U;
- PlsrPublishPosition(slot->command.axis, axisObject);
- (void)PlcDeviceSetHsdCheckpointMeta(1U, 0U);
- (void)PlcDeviceCheckpointHsd();
- result = PLSR_RESULT_OK;
- }
- break;
-
- case PLSR_CMD_CLEAR_TOTAL:
- if (PlsrStateIsBusy(axisObject->state) != 0U)
- {
- result = PLSR_RESULT_BUSY;
- }
- else
- {
- axisObject->totalPulses = 0;
- (void)PlcDeviceSetHsdCheckpointMeta(
- axisObject->positionValid,
- 0U);
- (void)PlcDeviceCheckpointHsd();
- result = PLSR_RESULT_OK;
- }
- break;
-
- case PLSR_CMD_SAVE_CONFIG:
- if (PlsrAnyAxisBusy() != 0U)
- {
- result = PLSR_RESULT_BUSY;
- }
- else
- {
- deviceResult = PlcDeviceSaveSfd();
- result = (deviceResult == PLC_DEVICE_OK)
- ? PLSR_RESULT_OK
- : PLSR_RESULT_PERSISTENCE_ERROR;
- }
- break;
-
- case PLSR_CMD_LOAD_CONFIG:
- if (PlsrAnyAxisBusy() != 0U)
- {
- result = PLSR_RESULT_BUSY;
- }
- else
- {
- deviceResult = PlcDeviceLoadSfd();
- result = (deviceResult == PLC_DEVICE_OK)
- ? PLSR_RESULT_OK
- : PLSR_RESULT_PERSISTENCE_ERROR;
- }
- break;
-
- case PLSR_CMD_RESET_ERROR:
- if (PlsrStateIsBusy(axisObject->state) != 0U)
- {
- result = PLSR_RESULT_BUSY;
- }
- else if ((axisObject->state != PLSR_STATE_ERROR)
- && (axisObject->error == PLSR_ERROR_NONE)
- && (axisObject->emergencyLatched == 0U)
- && (axisObject->compatibleErrorCode == 0U))
- {
- result = PLSR_RESULT_INVALID_STATE;
- }
- else
- {
- axisObject->error = PLSR_ERROR_NONE;
- axisObject->compatibleErrorCode = 0U;
- axisObject->compatibleErrorBlock = 0U;
- axisObject->emergencyLatched = 0U;
- axisObject->stopReason = PLSR_STOP_REASON_NONE;
- axisObject->done = 0U;
- result = (axisObject->state == PLSR_STATE_IDLE)
- ? PLSR_RESULT_OK
- : PlsrStateTransition(
- slot->command.axis,
- PLSR_STATE_IDLE,
- PLSR_TRANSITION_RESET_ERROR);
- }
- break;
-
- case PLSR_CMD_SELF_TEST:
- result = ((PlsrAnyAxisBusy() == 0U)
- && (PlsrResourceCheckInvariant() != 0U))
- ? PLSR_RESULT_OK
- : PLSR_RESULT_BUSY;
- break;
-
- default:
- result = PLSR_RESULT_INVALID_ARGUMENT;
- break;
- }
-
- axisObject->lastCommandSequence = slot->command.sequence;
- axisObject->lastCommandResult = result;
- axisObject->hasLastCommand = 1U;
- PlsrPublishAxis(slot->command.axis);
- return result;
- }
-
- static void PlsrProcessCriticalEvents(uint8_t axis, uint32_t events)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
-
- if ((events & PLSR_EVENT_SOFTWARE_EMERGENCY) != 0UL)
- {
- axisObject->emergencyLatched = 1U;
- axisObject->error = PLSR_ERROR_EMERGENCY;
- PlsrSetStopReason(axisObject,
- PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
- axisObject->done = 0U;
- if (PlsrStateIsBusy(axisObject->state) != 0U)
- {
- PlsrPublishSegmentEvent(
- axis,
- axisObject,
- PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
- PlsrPathTerminate(&axisObject->path);
- PlsrStopSegmentHardware(axis, axisObject);
- (void)PlsrStateTransition(axis,
- PLSR_STATE_STOPPED,
- PLSR_TRANSITION_STOP);
- }
- else
- {
- PlsrPublishAxis(axis);
- }
- return;
- }
-
- if ((events & PLSR_EVENT_LIMIT_POSITIVE) != 0UL)
- {
- axisObject->positiveLimitActive = 1U;
- if ((axisObject->directionPositive != 0U)
- && (PlsrStateIsBusy(axisObject->state) != 0U))
- {
- axisObject->error = PLSR_ERROR_LIMIT_POSITIVE;
- axisObject->compatibleErrorCode = 5U;
- axisObject->compatibleErrorBlock = 0U;
- (void)PlsrRequestControlledStop(
- axis,
- PLSR_STATE_STOPPED,
- PLSR_STOP_REASON_LIMIT_POSITIVE);
- return;
- }
- }
-
- if ((events & PLSR_EVENT_LIMIT_NEGATIVE) != 0UL)
- {
- axisObject->negativeLimitActive = 1U;
- if ((axisObject->directionPositive == 0U)
- && (PlsrStateIsBusy(axisObject->state) != 0U))
- {
- axisObject->error = PLSR_ERROR_LIMIT_NEGATIVE;
- axisObject->compatibleErrorCode = 6U;
- axisObject->compatibleErrorBlock = 0U;
- (void)PlsrRequestControlledStop(
- axis,
- PLSR_STATE_STOPPED,
- PLSR_STOP_REASON_LIMIT_NEGATIVE);
- return;
- }
- }
-
- if ((events & (PLSR_EVENT_TIMER_FAULT | PLSR_EVENT_COUNTER_FAULT)) != 0UL)
- {
- axisObject->error = ((events & PLSR_EVENT_TIMER_FAULT) != 0UL)
- ? PLSR_ERROR_TIMER_FAULT
- : PLSR_ERROR_COUNTER_FAULT;
- PlsrSetStopReason(axisObject, PLSR_STOP_REASON_FAULT);
- axisObject->done = 0U;
- PlsrPathTerminate(&axisObject->path);
- PlsrStopSegmentHardware(axis, axisObject);
- (void)PlsrStateTransition(axis,
- PLSR_STATE_ERROR,
- PLSR_TRANSITION_FAULT);
- }
- }
-
- static void PlsrMonitorAxisProtection(uint8_t axis)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
- PLSR_RESULT result;
-
- if ((axisObject->jobValid == 0U)
- || (PlsrStateIsBusy(axisObject->state) == 0U))
- {
- return;
- }
- result = PlsrUpdateLimitState(axisObject, &axisObject->job, 1U);
- if (result != PLSR_RESULT_OK)
- {
- axisObject->error = PLSR_ERROR_INTERNAL;
- axisObject->compatibleErrorCode = 26U;
- axisObject->compatibleErrorBlock = 0U;
- PlsrSetStopReason(axisObject, PLSR_STOP_REASON_FAULT);
- axisObject->done = 0U;
- PlsrPublishSegmentEvent(axis,
- axisObject,
- PLSR_STOP_REASON_FAULT);
- PlsrPathTerminate(&axisObject->path);
- PlsrStopSegmentHardware(axis, axisObject);
- (void)PlsrStateTransition(axis,
- PLSR_STATE_ERROR,
- PLSR_TRANSITION_FAULT);
- return;
- }
- if ((axisObject->directionPositive != 0U)
- && (axisObject->positiveLimitActive != 0U)
- && !((axisObject->pendingTerminal == PLSR_STATE_STOPPED)
- && (axisObject->stopReason
- == PLSR_STOP_REASON_LIMIT_POSITIVE)))
- {
- (void)PlsrPostEvent(axis, PLSR_EVENT_LIMIT_POSITIVE);
- }
- else if ((axisObject->directionPositive == 0U)
- && (axisObject->negativeLimitActive != 0U)
- && !((axisObject->pendingTerminal == PLSR_STATE_STOPPED)
- && (axisObject->stopReason
- == PLSR_STOP_REASON_LIMIT_NEGATIVE)))
- {
- (void)PlsrPostEvent(axis, PLSR_EVENT_LIMIT_NEGATIVE);
- }
- }
-
- /* 启动当前段的硬件输出与速度曲线(P3a:单轴 PULSE/DIR)。
- * 由段进入 ACCEL 时调用(任务启动 + 段间推进)。 */
- static PLSR_RESULT PlsrStartSegmentHardware(uint8_t axis,
- PLSR_AXIS *axisObject)
- {
- const PLSR_JOB_SNAPSHOT *job = &axisObject->job;
- const PLSR_SEGMENT_SNAPSHOT *segment =
- &job->segments[axisObject->path.currentSegment - 1U];
- PLSR_PROFILE_REQUEST profileRequest;
- PLSR_HW_START_PARAMS params;
- PLSR_RESULT result;
- int64_t pulses;
- int64_t signedPulses;
- int64_t targetPosition;
- int64_t nextEquivalentRemainder =
- axisObject->equivalentCommandRemainder;
- uint8_t positive;
-
- if (job->positioningMode == 0U)
- {
- result = PlsrPositionUnitsToPulses(
- &axisObject->equivalent,
- segment->pulseOrTarget,
- axisObject->equivalentCommandRemainder,
- &signedPulses,
- &nextEquivalentRemainder);
- if (result != PLSR_RESULT_OK)
- {
- return result;
- }
- if (signedPulses == INT64_MIN)
- {
- return PLSR_RESULT_POSITION_OVERFLOW;
- }
- pulses = (signedPulses < 0) ? -signedPulses : signedPulses;
- positive = (signedPulses >= 0) ? 1U : 0U;
- }
- else
- {
- /* 绝对模式使用实际硬件脉冲闭环更新后的逻辑位置计算位移。 */
- int64_t delta;
-
- result = PlsrPositionAbsoluteUnitsToPulses(
- &axisObject->equivalent,
- segment->pulseOrTarget,
- &targetPosition);
- if (result != PLSR_RESULT_OK)
- {
- return result;
- }
- if (((axisObject->logicalPosition > 0)
- && (targetPosition
- < INT64_MIN + axisObject->logicalPosition))
- || ((axisObject->logicalPosition < 0)
- && (targetPosition
- > INT64_MAX + axisObject->logicalPosition)))
- {
- return PLSR_RESULT_POSITION_OVERFLOW;
- }
- delta = targetPosition - axisObject->logicalPosition;
- if (delta == INT64_MIN)
- {
- return PLSR_RESULT_POSITION_OVERFLOW;
- }
-
- pulses = (delta < 0) ? -delta : delta;
- positive = (delta >= 0) ? 1U : 0U;
- }
-
- result = PlsrUpdateLimitState(axisObject, job, 0U);
- if (result != PLSR_RESULT_OK)
- {
- return result;
- }
- if ((positive != 0U) && (axisObject->positiveLimitActive != 0U))
- {
- return PLSR_RESULT_LIMIT_POSITIVE;
- }
- if ((positive == 0U) && (axisObject->negativeLimitActive != 0U))
- {
- return PLSR_RESULT_LIMIT_NEGATIVE;
- }
- axisObject->segmentEventPublished = 0U;
-
- if (pulses == 0)
- {
- /* 当量小于一个物理脉冲时保存余数并按零脉冲段推进;不启动PWM。 */
- axisObject->equivalentCommandRemainder = nextEquivalentRemainder;
- axisObject->directionPositive = positive;
- axisObject->segmentAccountedPulses = 0;
- axisObject->segmentAccountingActive = 0U;
- PlsrPublishAxis(axis);
- (void)PlsrPostEvent(axis, PLSR_EVENT_SEGMENT_COMPLETE);
- return PLSR_RESULT_OK;
- }
-
- (void)memset(&profileRequest, 0, sizeof(profileRequest));
- profileRequest.targetFrequencyHz = segment->targetFrequency;
- profileRequest.startFrequencyHz = job->s2.startSpeed;
- profileRequest.stopFrequencyHz = job->s2.stopSpeed;
- profileRequest.maxFrequencyHz = job->s2.maximumSpeed;
- profileRequest.accelSlopeHzPerMs =
- (job->s2.accelerationMs != 0U)
- ? job->s2.defaultSpeed / job->s2.accelerationMs
- : 0UL;
- profileRequest.decelSlopeHzPerMs =
- (job->s2.decelerationMs != 0U)
- ? job->s2.defaultSpeed / job->s2.decelerationMs
- : 0UL;
- profileRequest.curveMode = job->s2.curveMode;
-
- result = PlsrProfileStart(&axisObject->profile,
- &profileRequest,
- pulses,
- 1000U);
- if (result != PLSR_RESULT_OK)
- {
- return result;
- }
-
- params.frequencyHz = job->s2.startSpeed;
- params.targetPulses = pulses;
- params.outputMode = (PLSR_OUTPUT_MODE)job->outputMode;
- params.directionPoint = job->directionPoint;
- params.directionPositive = positive;
- params.directionDelayMs = job->s2.directionDelayMs;
- result = PlsrHwStartPulse(axis, ¶ms);
- if (result != PLSR_RESULT_OK)
- {
- axisObject->profileActive = 0U;
- axisObject->profileWasAccel = 0U;
- return result;
- }
- axisObject->equivalentCommandRemainder = nextEquivalentRemainder;
- axisObject->directionPositive = positive;
- axisObject->segmentAccountedPulses = 0;
- axisObject->segmentAccountingActive = 1U;
- axisObject->profileActive = 1U;
- axisObject->profileWasAccel =
- (axisObject->profile.phase == PLSR_PROFILE_PHASE_ACCEL) ? 1U : 0U;
- PlsrPublishAxis(axis);
- return PLSR_RESULT_OK;
- }
-
- /* 停止当前段的硬件输出与速度曲线。 */
- static void PlsrStopSegmentHardware(uint8_t axis, PLSR_AXIS *axisObject)
- {
- PlsrAccountHardwarePulses(axis, axisObject);
- axisObject->profileActive = 0U;
- axisObject->profileWasAccel = 0U;
- (void)PlsrHwStopPulse(axis);
- PlsrAccountHardwarePulses(axis, axisObject);
- axisObject->segmentAccountingActive = 0U;
- PlsrPublishRuntime(axis);
- }
-
- /* 应用路径执行器的动作:段间推进、进入等待、结束、让出、错误。 */
- static void PlsrApplyPathAction(uint8_t axis, PLSR_PATH_ACTION action)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
-
- switch (action)
- {
- case PLSR_PATH_ACTION_NEXT_SEGMENT:
- /* SEGMENT_COMPLETE 表示上一段输出边界已经结束。统一收口旧段
- * profile/HAL 后再启动新段;真实 IRQ 与测试注入事件均一致。 */
- PlsrStopSegmentHardware(axis, axisObject);
- if (axisObject->state == PLSR_STATE_WAIT)
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_ACCEL,
- PLSR_TRANSITION_WAIT_COMPLETE);
- }
- else if ((axisObject->state == PLSR_STATE_ACCEL)
- || (axisObject->state == PLSR_STATE_RUN)
- || (axisObject->state == PLSR_STATE_DECEL))
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_ACCEL,
- PLSR_TRANSITION_START);
- }
- /* 进入新段:重新启动硬件输出与速度曲线。 */
- if (axisObject->state == PLSR_STATE_ACCEL)
- {
- PLSR_RESULT startResult =
- PlsrStartSegmentHardware(axis, axisObject);
-
- if ((startResult == PLSR_RESULT_LIMIT_POSITIVE)
- || (startResult == PLSR_RESULT_LIMIT_NEGATIVE))
- {
- axisObject->error =
- (startResult == PLSR_RESULT_LIMIT_POSITIVE)
- ? PLSR_ERROR_LIMIT_POSITIVE
- : PLSR_ERROR_LIMIT_NEGATIVE;
- axisObject->compatibleErrorCode =
- (startResult == PLSR_RESULT_LIMIT_POSITIVE) ? 5U : 6U;
- PlsrSetStopReason(
- axisObject,
- (startResult == PLSR_RESULT_LIMIT_POSITIVE)
- ? PLSR_STOP_REASON_LIMIT_POSITIVE
- : PLSR_STOP_REASON_LIMIT_NEGATIVE);
- (void)PlsrStateTransition(axis,
- PLSR_STATE_STOPPED,
- PLSR_TRANSITION_STOP);
- }
- else if (startResult != PLSR_RESULT_OK)
- {
- axisObject->error = PLSR_ERROR_TIMER_FAULT;
- PlsrSetStopReason(axisObject, PLSR_STOP_REASON_FAULT);
- axisObject->done = 0U;
- (void)PlsrStateTransition(axis,
- PLSR_STATE_ERROR,
- PLSR_TRANSITION_FAULT);
- }
- }
- break;
-
- case PLSR_PATH_ACTION_ENTER_WAIT:
- if ((axisObject->state == PLSR_STATE_ACCEL)
- || (axisObject->state == PLSR_STATE_RUN))
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_WAIT,
- PLSR_TRANSITION_WAIT_BEGIN);
- }
- break;
-
- case PLSR_PATH_ACTION_JOB_COMPLETE:
- if (PlsrStateIsBusy(axisObject->state) != 0U)
- {
- axisObject->stopReason = PLSR_STOP_REASON_NORMAL_COMPLETE;
- (void)PlsrStateTransition(axis,
- PLSR_STATE_COMPLETED,
- PLSR_TRANSITION_JOB_COMPLETE);
- }
- break;
-
- case PLSR_PATH_ACTION_YIELD:
- /* 预算耗尽:本轮不再推进,下个 tick 由 PlsrPathTick 恢复。 */
- break;
-
- case PLSR_PATH_ACTION_ERROR:
- axisObject->error = PLSR_ERROR_INTERNAL;
- PlsrSetStopReason(axisObject, PLSR_STOP_REASON_FAULT);
- axisObject->done = 0U;
- (void)PlsrStateTransition(axis,
- PLSR_STATE_ERROR,
- PLSR_TRANSITION_FAULT);
- break;
-
- default:
- break;
- }
- }
-
- static void PlsrProcessNormalEvents(uint8_t axis, uint32_t events)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
-
- if (((events & PLSR_EVENT_STOP_IMMEDIATE_DONE) != 0UL)
- && (axisObject->immediateStopPending != 0U))
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_STOPPED,
- PLSR_TRANSITION_STOP);
- return;
- }
-
- if (((events & PLSR_EVENT_ACCEL_COMPLETE) != 0UL)
- && (axisObject->state == PLSR_STATE_ACCEL)
- && (axisObject->immediateStopPending == 0U))
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_RUN,
- PLSR_TRANSITION_ACCEL_COMPLETE);
- }
-
- if (((events & PLSR_EVENT_DECEL_COMPLETE) != 0UL)
- && (axisObject->state == PLSR_STATE_DECEL))
- {
- if (axisObject->pendingTerminal == PLSR_STATE_PAUSED)
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_PAUSED,
- PLSR_TRANSITION_DECEL_COMPLETE);
- }
- else if (axisObject->pendingTerminal == PLSR_STATE_STOPPED)
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_STOPPED,
- PLSR_TRANSITION_DECEL_COMPLETE);
- }
- else
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_RUN,
- PLSR_TRANSITION_DECEL_COMPLETE);
- }
- }
-
- if (((events & PLSR_EVENT_WAIT_BEGIN) != 0UL)
- && ((axisObject->state == PLSR_STATE_ACCEL)
- || (axisObject->state == PLSR_STATE_RUN)))
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_WAIT,
- PLSR_TRANSITION_WAIT_BEGIN);
- }
-
- if (((events & PLSR_EVENT_WAIT_COMPLETE) != 0UL)
- && (axisObject->state == PLSR_STATE_WAIT))
- {
- (void)PlsrStateTransition(axis,
- PLSR_STATE_ACCEL,
- PLSR_TRANSITION_WAIT_COMPLETE);
- }
-
- if (((events & PLSR_EVENT_SEGMENT_COMPLETE) != 0UL)
- && ((axisObject->state == PLSR_STATE_ACCEL)
- || (axisObject->state == PLSR_STATE_RUN)
- || (axisObject->state == PLSR_STATE_DECEL))
- && (axisObject->pendingTerminal == PLSR_STATE_UNINITIALIZED)
- && (axisObject->immediateStopPending == 0U))
- {
- PLSR_PATH_ACTION action;
-
- PlsrPublishSegmentEvent(axis,
- axisObject,
- PLSR_STOP_REASON_NORMAL_COMPLETE);
- action = PlsrPathOnSegmentDone(&axisObject->path,
- &axisObject->job,
- axisObject->logicalPosition);
- PlsrApplyPathAction(axis, action);
- }
-
- if (((events & PLSR_EVENT_JOB_COMPLETE) != 0UL)
- && (PlsrStateIsBusy(axisObject->state) != 0U)
- && (axisObject->pendingTerminal == PLSR_STATE_UNINITIALIZED)
- && (axisObject->immediateStopPending == 0U))
- {
- axisObject->stopReason = PLSR_STOP_REASON_NORMAL_COMPLETE;
- (void)PlsrStateTransition(axis,
- PLSR_STATE_COMPLETED,
- PLSR_TRANSITION_JOB_COMPLETE);
- }
- }
-
- PLSR_RESULT PlsrInit(void)
- {
- int32_t restoredPosition;
- uint8_t restoredPositionValid;
- uint8_t restoredLastBusy;
- uint8_t axis;
-
- (void)memset(PlsrAxes, 0, sizeof(PlsrAxes));
- (void)memset(PlsrCommandQueue, 0, sizeof(PlsrCommandQueue));
- PlsrNextTicket = 0UL;
- PlsrResourceInit();
- (void)PlsrHwInit();
- PlsrInitialized = 1U;
-
- restoredPositionValid = PlcDeviceGetRestoredHsdPositionValid();
- restoredLastBusy = PlcDeviceGetRestoredHsdLastBusy();
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- PlsrAxes[axis].state = PLSR_STATE_UNINITIALIZED;
- PlsrAxes[axis].pendingTerminal = PLSR_STATE_UNINITIALIZED;
- PlsrAxes[axis].lease.directionPoint = PLSR_DIRECTION_POINT_NONE;
- PlsrLoadAxisEquivalentConfig(axis, &PlsrAxes[axis].equivalent);
- if (PlcDeviceReadHsdDword(
- (uint16_t)(axis * PLSR_HSD_RUNTIME_AXIS_COUNT),
- &restoredPosition) == PLC_DEVICE_OK)
- {
- PlsrAxes[axis].logicalPosition = restoredPosition;
- }
- /* 只有上次正常停机且保存了位置有效标志,才允许绝对定位;
- * 运动中掉电(lastBusy=1)时位置不可信。 */
- if ((restoredPositionValid != 0U) && (restoredLastBusy == 0U))
- {
- PlsrAxes[axis].positionValid = 1U;
- }
- if (PlsrStateTransition(axis,
- PLSR_STATE_IDLE,
- PLSR_TRANSITION_INITIALIZED)
- != PLSR_RESULT_OK)
- {
- return PLSR_RESULT_INTERNAL_ERROR;
- }
- }
- return PLSR_RESULT_OK;
- }
-
- void PlsrProcess(void)
- {
- PLSR_COMMAND_SLOT slot;
- uint32_t events;
- uint8_t processedCommands = 0U;
- uint8_t criticalAxes = 0U;
- uint8_t axis;
-
- if (PlsrInitialized == 0U)
- {
- return;
- }
-
- /* 先合并 ISR 已完成的实际脉冲,确保段完成、STOP或新命令不会在
- * HAL 计数清零前丢失最后一批位置增量。 */
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- PlsrAccountHardwarePulses(axis, &PlsrAxes[axis]);
- PlsrMonitorAxisProtection(axis);
- }
-
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- events = PlsrTakeEvents(axis, PLSR_EVENT_CRITICAL_MASK);
- if (events != 0UL)
- {
- criticalAxes |= (uint8_t)(1U << axis);
- PlsrProcessCriticalEvents(axis, events);
- }
- }
-
- while ((processedCommands < PLSR_COMMAND_QUEUE_DEPTH)
- && (PlsrPopHighestPriorityCommand(&slot) != 0U))
- {
- if ((slot.command.opcode == PLSR_CMD_RESET_ERROR)
- && ((criticalAxes & (uint8_t)(1U << slot.command.axis)) != 0U))
- {
- PLSR_AXIS *axisObject = &PlsrAxes[slot.command.axis];
-
- axisObject->lastCommandSequence = slot.command.sequence;
- axisObject->lastCommandResult = PLSR_RESULT_BUSY;
- axisObject->hasLastCommand = 1U;
- PlsrPublishAxis(slot.command.axis);
- }
- else
- {
- (void)PlsrExecuteCommand(&slot);
- }
- processedCommands++;
- }
-
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- events = PlsrTakeEvents(axis,
- PLSR_EVENT_ALL_MASK
- & ~PLSR_EVENT_CRITICAL_MASK);
- if (events != 0UL)
- {
- PlsrProcessNormalEvents(axis, events);
- }
- }
-
- /* 1ms tick:路径执行器推进(WAIT/ACT 计时、信号/EXT 轮询、跳转链)
- * + 速度曲线推进(P2) + HAL 状态机(DIR 延时)。 */
- for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
- {
- PLSR_AXIS *axisObject = &PlsrAxes[axis];
- PLSR_PATH_ACTION action;
- uint32_t frequencyHz;
- uint32_t outputFrequencyHz;
- uint64_t hardwarePulses;
- uint64_t remainingPulses;
- uint8_t profileDone;
- uint8_t wasAccel;
-
- PlsrHwTick(axis);
- PlsrAccountHardwarePulses(axis, axisObject);
- /* 首次 AB 内部预热周期不属于用户运动,速度曲线也必须冻结;
- * 否则低速起步时会在隐藏周期内提前爬升十余个刷新步。 */
- if (PlsrHwIsAbStartupPriming(axis) != 0U)
- {
- continue;
- }
- if (PlsrStateIsBusy(axisObject->state) == 0U)
- {
- continue;
- }
- action = PlsrPathTick(&axisObject->path,
- &axisObject->job,
- axisObject->logicalPosition);
- if (action != PLSR_PATH_ACTION_NONE)
- {
- PlsrApplyPathAction(axis, action);
- }
-
- if ((axisObject->profileActive != 0U)
- && (PlsrHwGetState(axis) != PLSR_HW_STATE_DIR_SETTLING))
- {
- /* 虚拟计数校准到硬件实际计数:ARPE 预装载滞后的偏差不累积,
- * 保证 profile DONE 与硬件计数同步(消除段尾冻结频率收尾)。 */
- hardwarePulses = (uint64_t)PlsrHwGetEmittedPulses(axis);
- PlsrProfileSyncPulses(&axisObject->profile, hardwarePulses);
- wasAccel = axisObject->profileWasAccel;
- (void)PlsrProfileStep(&axisObject->profile,
- &frequencyHz,
- &profileDone);
- outputFrequencyHz = frequencyHz;
- if ((PlsrHwGetState(axis) == PLSR_HW_STATE_RUNNING)
- && (wasAccel == 0U)
- && (axisObject->pendingTerminal
- == PLSR_STATE_UNINITIALIZED)
- && ((uint64_t)axisObject->profile.totalPulses
- > hardwarePulses + 1UL))
- {
- /* ARR 预装载在当前脉冲结束后生效,因此计算的是
- * “当前脉冲之后”剩余的脉冲。用位置反推减速频率,
- * 避免 1 ms 时间曲线与预装载滞后造成段尾突停。 */
- remainingPulses =
- (uint64_t)axisObject->profile.totalPulses
- - hardwarePulses - 1UL;
- outputFrequencyHz =
- PlsrProfileGetBrakingOutputFrequency(
- &axisObject->profile,
- remainingPulses);
- }
- if ((PlsrHwGetState(axis) == PLSR_HW_STATE_PWM_PENDING)
- && (axisObject->profile.phase
- == PLSR_PROFILE_PHASE_ACCEL))
- {
- outputFrequencyHz =
- PlsrProfileGetInitialOutputFrequency(
- &axisObject->profile);
- }
- if ((profileDone == 0U) || (outputFrequencyHz != 0UL))
- {
- (void)PlsrHwSetFrequency(axis, outputFrequencyHz);
- }
- if ((profileDone != 0U)
- && (axisObject->pendingTerminal
- != PLSR_STATE_UNINITIALIZED))
- {
- (void)PlsrHwSetFrequency(axis, 0UL);
- axisObject->profileActive = 0U;
- (void)PlsrPostEvent(axis, PLSR_EVENT_DECEL_COMPLETE);
- }
- axisObject->profileWasAccel =
- (axisObject->profile.phase == PLSR_PROFILE_PHASE_ACCEL)
- ? 1U
- : 0U;
- if ((wasAccel != 0U)
- && (axisObject->profileWasAccel == 0U)
- && (axisObject->state == PLSR_STATE_ACCEL))
- {
- /* 加速完成(曲线进入匀速/减速)→ 状态机推进到 RUN。 */
- (void)PlsrPostEvent(axis, PLSR_EVENT_ACCEL_COMPLETE);
- }
- }
- }
- }
-
- void PlsrTask(void *argument)
- {
- (void)argument;
- #ifdef PLSR_HOST_TEST
- PlsrProcess();
- #else
- while (1)
- {
- PlsrProcess();
- OSTimeDly(1U);
- }
- #endif
- }
-
- PLSR_RESULT PlsrGetStatus(uint8_t axis, PLSR_STATUS *status)
- {
- PLSR_AXIS *axisObject;
- uint32_t interruptState;
-
- if (axis >= PLSR_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_AXIS;
- }
- if (status == NULL)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
-
- interruptState = PlsrCoreEnterCritical();
- axisObject = &PlsrAxes[axis];
- status->state = axisObject->state;
- status->outputMode = axisObject->outputMode;
- status->error = axisObject->error;
- status->stopReason = axisObject->stopReason;
- status->lastCommandResult = axisObject->lastCommandResult;
- status->lastCommandSequence = axisObject->lastCommandSequence;
- status->illegalTransitionCount = axisObject->illegalTransitionCount;
- status->pendingEvents = axisObject->pendingEvents;
- status->logicalPosition = axisObject->logicalPosition;
- status->taskPulses = axisObject->taskPulses;
- status->totalPulses = axisObject->totalPulses;
- status->busy = PlsrStateIsBusy(axisObject->state);
- status->pulseActive = PlsrStateIsPulseActive(axisObject->state);
- status->done = axisObject->done;
- status->wait = (axisObject->state == PLSR_STATE_WAIT) ? 1U : 0U;
- status->directionPositive = axisObject->directionPositive;
- status->highResourceMask = axisObject->lease.highMask;
- status->directionPoint = (axisObject->lease.valid != 0U)
- ? axisObject->lease.directionPoint
- : PLSR_DIRECTION_POINT_NONE;
- status->positionValid = axisObject->positionValid;
- status->jobValid = axisObject->jobValid;
- status->positionOverflow = axisObject->positionOverflow;
- status->positiveLimitActive = axisObject->positiveLimitActive;
- status->negativeLimitActive = axisObject->negativeLimitActive;
- status->emergencyLatched = axisObject->emergencyLatched;
- status->s2Set = (axisObject->jobValid != 0U) ? axisObject->job.s2Set : 0U;
- status->speedClamped = (axisObject->jobValid != 0U)
- ? axisObject->job.speedClamped
- : 0U;
- status->segmentCount = (axisObject->jobValid != 0U)
- ? axisObject->job.segmentCount
- : 0U;
- status->startSegment = (axisObject->jobValid != 0U)
- ? axisObject->job.startSegment
- : 0U;
- status->currentSegment = (axisObject->jobValid != 0U)
- ? PlsrPathGetCurrentSegment(
- &axisObject->path)
- : 0U;
- PlsrCoreExitCritical(interruptState);
- return PLSR_RESULT_OK;
- }
-
- PLSR_RESULT PlsrGetLastParseDetail(uint8_t axis,
- PLSR_PARSE_DETAIL *detail)
- {
- uint32_t interruptState;
-
- if (axis >= PLSR_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_AXIS;
- }
- if (detail == NULL)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- interruptState = PlsrCoreEnterCritical();
- *detail = PlsrAxes[axis].parseDetail;
- PlsrCoreExitCritical(interruptState);
- return PLSR_RESULT_OK;
- }
|