|
- #include "plsr_hal_f407.h"
- #include "plsr_address_map.h"
- #include "plsr_core.h"
- #include "plsr_job.h"
- #include <string.h>
-
- #ifndef PLSR_HOST_TEST
- #include "stm32f4xx.h"
- #include "stm32f4xx_hal.h"
- #endif
-
- #define PLSR_HW_TIMER_CHANNEL1_BIT (0x0001U)
- #define PLSR_HW_TIMER_UPDATE_BIT (0x0001U)
- #define PLSR_HW_OUTPUT_POINT_COUNT (21U)
- #define PLSR_HW_DBG_SNAPSHOT_COUNT (160U)
- #define PLSR_HW_AB_QUARTER_COUNT (4U)
-
- typedef struct
- {
- uint32_t timerClockHz;
- uint8_t directionPoint; /* 0xFF = 无 */
- #ifndef PLSR_HOST_TEST
- TIM_TypeDef *timer;
- GPIO_TypeDef *gpioPort;
- uint16_t gpioPin;
- uint8_t afMode;
- IRQn_Type irq;
- #endif
- } PLSR_HW_AXIS_MAP;
-
- #ifndef PLSR_HOST_TEST
- /* 输出点(Y 点号)→ GPIO 引脚:XDM-60T4-E 原理图。
- * 点号 8/9/18/19 不存在(资源层掩码 0x0013FCFF 已约束)。 */
- typedef struct
- {
- GPIO_TypeDef *port;
- uint16_t pin;
- } PLSR_HW_OUTPUT_PIN;
-
- static const PLSR_HW_OUTPUT_PIN PlsrHwOutputPins[PLSR_HW_OUTPUT_POINT_COUNT] =
- {
- {GPIOF, GPIO_PIN_6}, /* Y0 */
- {GPIOF, GPIO_PIN_8}, /* Y1 */
- {GPIOF, GPIO_PIN_7}, /* Y2 */
- {GPIOF, GPIO_PIN_9}, /* Y3 */
- {GPIOI, GPIO_PIN_8}, /* Y4 */
- {GPIOE, GPIO_PIN_6}, /* Y5 */
- {GPIOE, GPIO_PIN_5}, /* Y6 */
- {GPIOE, GPIO_PIN_4}, /* Y7 */
- {NULL, 0U}, /* Y8 */
- {NULL, 0U}, /* Y9 */
- {GPIOG, GPIO_PIN_7}, /* Y10 */
- {GPIOG, GPIO_PIN_6}, /* Y11 */
- {GPIOH, GPIO_PIN_9}, /* Y12 */
- {GPIOH, GPIO_PIN_8}, /* Y13 */
- {GPIOH, GPIO_PIN_7}, /* Y14 */
- {GPIOH, GPIO_PIN_6}, /* Y15 */
- {GPIOF, GPIO_PIN_11}, /* Y16 */
- {GPIOB, GPIO_PIN_0}, /* Y17 */
- {NULL, 0U}, /* Y18 */
- {NULL, 0U}, /* Y19 */
- {GPIOH, GPIO_PIN_5} /* Y20 */
- };
- #endif
-
- /* Q0~Q3 定时器:XDM-60T4-E。
- * PF6=TIM10_CH1(AF3)、PF7=TIM11_CH1(AF3)、PF8=TIM13_CH1(AF9)、PF9=TIM14_CH1(AF9)。
- * 定时器时钟由 RCC 实际配置计算(APB2 分频≠1 时定时器时钟×2)。 */
- static const PLSR_HW_AXIS_MAP PlsrHwAxisMap[PLSR_HW_AXIS_COUNT] =
- {
- #ifndef PLSR_HOST_TEST
- {168000000UL, PLSR_HW_DIR_POINT_NONE, TIM10, GPIOF, GPIO_PIN_6, 3U, TIM1_UP_TIM10_IRQn},
- {84000000UL, PLSR_HW_DIR_POINT_NONE, TIM13, GPIOF, GPIO_PIN_8, 9U, TIM8_UP_TIM13_IRQn},
- {168000000UL, PLSR_HW_DIR_POINT_NONE, TIM11, GPIOF, GPIO_PIN_7, 3U, TIM1_TRG_COM_TIM11_IRQn},
- {84000000UL, PLSR_HW_DIR_POINT_NONE, TIM14, GPIOF, GPIO_PIN_9, 9U, TIM8_TRG_COM_TIM14_IRQn}
- #else
- {168000000UL, PLSR_HW_DIR_POINT_NONE},
- {84000000UL, PLSR_HW_DIR_POINT_NONE},
- {168000000UL, PLSR_HW_DIR_POINT_NONE},
- {84000000UL, PLSR_HW_DIR_POINT_NONE}
- #endif
- };
-
- /* host 测试:模拟定时器寄存器。 */
- #ifdef PLSR_HOST_TEST
- typedef struct
- {
- uint32_t cr1;
- uint32_t dier;
- uint32_t sr;
- uint32_t psc;
- uint32_t arr;
- uint32_t ccr1;
- uint32_t ccmr1;
- uint32_t ccer;
- uint8_t dirLevel;
- } PLSR_HW_TIMER_REGS;
-
- static PLSR_HW_TIMER_REGS PlsrHwTimers[PLSR_HW_AXIS_COUNT];
- #endif
-
- typedef struct
- {
- PLSR_HW_STATE state;
- PLSR_OUTPUT_MODE outputMode;
- uint32_t currentFrequencyHz;
- int64_t targetPulses;
- int64_t emittedPulses;
- uint16_t directionDelayRemainingMs;
- uint8_t directionPoint;
- uint8_t directionPositive;
- uint8_t abQuarter;
- } PLSR_HW_AXIS_STATE;
-
- static PLSR_HW_AXIS_STATE PlsrHwAxes[PLSR_HW_AXIS_COUNT];
-
- /* 调试快照:当前上板自测只记录 Q0 的 160 ms,避免四轴
- * PlsrHwTick 互相混入,同时控制临时 RAM 占用。reason=0 表示 PwmBegin,
- * reason=3 表示 1 ms HAL tick。 */
- #ifndef PLSR_HOST_TEST
- typedef struct
- {
- uint8_t reason; /* 0=PwmBegin(UG后) 3=PlsrHwTick(每1ms) */
- uint32_t psc;
- uint32_t arr;
- uint32_t ccr;
- uint32_t cnt;
- uint32_t frequencyHz;
- int64_t emittedPulses;
- } PLSR_HW_DBG_SNAP;
-
- static PLSR_HW_DBG_SNAP PlsrHwDbgSnap[PLSR_HW_DBG_SNAPSHOT_COUNT];
- static volatile uint16_t PlsrHwDbgCount;
-
- static void PlsrHwDbgCapture(uint8_t axis, uint8_t reason)
- {
- if (axis != 0U)
- {
- return;
- }
- if (reason == 0U)
- {
- PlsrHwDbgCount = 0U;
- }
- if (PlsrHwDbgCount < PLSR_HW_DBG_SNAPSHOT_COUNT)
- {
- PLSR_HW_DBG_SNAP *snap = &PlsrHwDbgSnap[PlsrHwDbgCount++];
- snap->reason = reason;
- snap->psc = PlsrHwAxisMap[axis].timer->PSC;
- snap->arr = PlsrHwAxisMap[axis].timer->ARR;
- snap->ccr = PlsrHwAxisMap[axis].timer->CCR1;
- snap->cnt = PlsrHwAxisMap[axis].timer->CNT;
- snap->frequencyHz = PlsrHwAxes[axis].currentFrequencyHz;
- snap->emittedPulses = PlsrHwAxes[axis].emittedPulses;
- }
- }
- #else
- #define PlsrHwDbgCapture(axis, reason) ((void)0)
- #endif
-
- /* ---- 定时器寄存器访问抽象(host 模拟 / 生产真实) ---- */
-
- static void PlsrHwTimerSetArr(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].arr = value;
- #else
- PlsrHwAxisMap[axis].timer->ARR = value;
- #endif
- }
-
- static void PlsrHwTimerSetPsc(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].psc = value;
- #else
- PlsrHwAxisMap[axis].timer->PSC = value;
- #endif
- }
-
- static void PlsrHwTimerSetCcr(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].ccr1 = value;
- #else
- PlsrHwAxisMap[axis].timer->CCR1 = value;
- #endif
- }
-
- static void PlsrHwTimerSetCen(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].cr1 = (PlsrHwTimers[axis].cr1 & ~0x0001UL) | value;
- #else
- if (value != 0UL)
- {
- PlsrHwAxisMap[axis].timer->CR1 |= TIM_CR1_CEN;
- }
- else
- {
- PlsrHwAxisMap[axis].timer->CR1 &= ~TIM_CR1_CEN;
- }
- #endif
- }
-
- static void PlsrHwTimerSetCc1e(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].ccer = (PlsrHwTimers[axis].ccer & ~0x0001UL) | value;
- #else
- if (value != 0UL)
- {
- PlsrHwAxisMap[axis].timer->CCER |= TIM_CCER_CC1E;
- }
- else
- {
- PlsrHwAxisMap[axis].timer->CCER &= ~TIM_CCER_CC1E;
- }
- #endif
- }
-
- /* 通道 1 输出模式 = PWM 模式 1(OC1M=110)+ CCR 预装载(OC1PE)。
- * 上电复位后 CCMR1=0(冻结),通道输出恒定电平、无方波,必须显式配置。 */
- static void PlsrHwTimerSetPwmMode1(uint8_t axis)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].ccmr1 = 0x0068UL;
- #else
- PlsrHwAxisMap[axis].timer->CCMR1 = (TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2)
- | TIM_CCMR1_OC1PE;
- #endif
- }
-
- static void PlsrHwTimerSetUie(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].dier = (PlsrHwTimers[axis].dier & ~0x0001UL) | value;
- #else
- if (value != 0UL)
- {
- PlsrHwAxisMap[axis].timer->DIER |= TIM_DIER_UIE;
- }
- else
- {
- PlsrHwAxisMap[axis].timer->DIER &= ~TIM_DIER_UIE;
- }
- #endif
- }
-
- static void PlsrHwTimerClearUif(uint8_t axis)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].sr &= ~PLSR_HW_TIMER_UPDATE_BIT;
- #else
- PlsrHwAxisMap[axis].timer->SR &= ~TIM_SR_UIF;
- #endif
- }
-
- static uint8_t PlsrHwTimerHasUif(uint8_t axis)
- {
- #ifdef PLSR_HOST_TEST
- return ((PlsrHwTimers[axis].sr & PLSR_HW_TIMER_UPDATE_BIT) != 0UL)
- ? 1U
- : 0U;
- #else
- return ((PlsrHwAxisMap[axis].timer->SR & TIM_SR_UIF) != 0UL) ? 1U : 0U;
- #endif
- }
-
- /* ---- DIR 输出 ----
- * XDM 为晶体管(NPN 漏型)输出:ON(导通)= 引脚低电平。
- * 信捷正逻辑:正向发脉冲时方向端子置 ON(低)。 */
-
- static void PlsrHwSetDirLevel(uint8_t axis, uint8_t positive)
- {
- PLSR_HW_AXIS_STATE *state = &PlsrHwAxes[axis];
-
- state->directionPositive = (positive != 0U) ? 1U : 0U;
- if (state->directionPoint == PLSR_HW_DIR_POINT_NONE)
- {
- return;
- }
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].dirLevel = (positive != 0U) ? 1U : 0U;
- #else
- if (state->directionPoint < PLSR_HW_OUTPUT_POINT_COUNT)
- {
- const PLSR_HW_OUTPUT_PIN *pin =
- &PlsrHwOutputPins[state->directionPoint];
- GPIO_InitTypeDef gpio;
-
- if (pin->port != NULL)
- {
- /* DIR 点按需配置为推挽输出(上电默认高阻=截止,安全)。 */
- gpio.Pin = pin->pin;
- gpio.Mode = GPIO_MODE_OUTPUT_PP;
- gpio.Pull = GPIO_NOPULL;
- gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- HAL_GPIO_Init(pin->port, &gpio);
- /* 漏型输出:ON(导通)= 低电平。 */
- HAL_GPIO_WritePin(pin->port,
- pin->pin,
- (positive != 0U) ? GPIO_PIN_RESET
- : GPIO_PIN_SET);
- }
- }
- #endif
- }
-
- /* ---- PWM 启停 ----
- * ARR/CCR 使用预装载(ARPE/OC1PE):运行中调频写入延迟到更新事件生效,
- * 避免 ARR 变小瞬间 CNT 超调提前回绕(每段加速会多出 ~ln(f1/f0) 个假脉冲)。
- * 首次启动用 EGR.UG 把预装载值加载到影子寄存器,杜绝首个周期用复位值。 */
-
- static void PlsrHwTimerSetArpe(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].cr1 = (PlsrHwTimers[axis].cr1 & ~0x0080UL)
- | ((value != 0UL) ? 0x0080UL : 0UL);
- #else
- if (value != 0UL)
- {
- PlsrHwAxisMap[axis].timer->CR1 |= TIM_CR1_ARPE;
- }
- else
- {
- PlsrHwAxisMap[axis].timer->CR1 &= ~TIM_CR1_ARPE;
- }
- #endif
- }
-
- /* 生成更新事件:立即加载 ARR/CCR/PSC 影子寄存器(启动时用)。 */
- static void PlsrHwTimerSetUg(uint8_t axis)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].sr |= PLSR_HW_TIMER_UPDATE_BIT;
- #else
- PlsrHwAxisMap[axis].timer->EGR = TIM_EGR_UG;
- #endif
- }
-
- /* 配置 PWM 定时器(预装载写入;启动/调频共用,不触碰使能位)。 */
- static void PlsrHwConfigurePwm(uint8_t axis, uint32_t frequencyHz)
- {
- uint16_t psc;
- uint16_t arr;
-
- if (PlsrCalculateTimerDivider(PlsrHwAxisMap[axis].timerClockHz,
- frequencyHz,
- &psc,
- &arr) != PLSR_RESULT_OK)
- {
- return;
- }
- PlsrHwTimerSetPsc(axis, psc);
- PlsrHwTimerSetArr(axis, arr);
- PlsrHwTimerSetCcr(axis, (uint32_t)arr / 2UL); /* 50% 占空比 */
- PlsrHwTimerSetPwmMode1(axis);
- PlsrHwTimerSetArpe(axis, 1UL);
- }
-
- /* 首次启动输出:加载影子寄存器后使能更新中断、通道与计数。 */
- static void PlsrHwPwmBegin(uint8_t axis)
- {
- PlsrHwTimerSetUg(axis);
- /* UG 只用于加载影子寄存器,不是物理脉冲,不得计数。 */
- PlsrHwTimerClearUif(axis);
- PlsrHwDbgCapture(axis, 0U);
- PlsrHwTimerSetUie(axis, 1UL);
- PlsrHwTimerSetCc1e(axis, 1UL);
- PlsrHwTimerSetCen(axis, 1UL);
- }
-
- static void PlsrHwStopPwmTimer(uint8_t axis)
- {
- PlsrHwTimerSetCc1e(axis, 0UL);
- PlsrHwTimerSetUie(axis, 0UL);
- PlsrHwTimerSetCen(axis, 0UL);
- }
-
- static uint8_t PlsrHwIsAbBaseAxis(uint8_t axis)
- {
- return ((axis == 0U) || (axis == 2U)) ? 1U : 0U;
- }
-
- #ifdef PLSR_HOST_TEST
- static uint8_t PlsrHwGetPairedAxis(uint8_t axis)
- {
- return (uint8_t)(axis + 1U);
- }
- #endif
-
- /* P3b-1:AB 正交相序先在 host 模型中闭环。真实 STM32 双定时器的
- * 同步启动、相位偏置和安全停止将在 P3b-2 接入。 */
- static void PlsrHwConfigureActiveOutput(uint8_t axis,
- PLSR_OUTPUT_MODE outputMode,
- uint32_t frequencyHz)
- {
- PlsrHwConfigurePwm(axis, frequencyHz);
- #ifdef PLSR_HOST_TEST
- if (outputMode == PLSR_OUTPUT_AB)
- {
- PlsrHwConfigurePwm(PlsrHwGetPairedAxis(axis), frequencyHz);
- }
- #else
- (void)outputMode;
- #endif
- }
-
- static void PlsrHwBeginActiveOutput(uint8_t axis,
- PLSR_OUTPUT_MODE outputMode)
- {
- PlsrHwPwmBegin(axis);
- #ifdef PLSR_HOST_TEST
- if (outputMode == PLSR_OUTPUT_AB)
- {
- PlsrHwPwmBegin(PlsrHwGetPairedAxis(axis));
- }
- #else
- (void)outputMode;
- #endif
- }
-
- static void PlsrHwStopActiveOutput(uint8_t axis,
- PLSR_OUTPUT_MODE outputMode)
- {
- PlsrHwStopPwmTimer(axis);
- #ifdef PLSR_HOST_TEST
- if ((outputMode == PLSR_OUTPUT_AB) && (PlsrHwIsAbBaseAxis(axis) != 0U))
- {
- PlsrHwStopPwmTimer(PlsrHwGetPairedAxis(axis));
- }
- #else
- (void)outputMode;
- #endif
- }
-
- uint8_t PlsrHwResolveDirectionPoint(uint8_t pointNumber)
- {
- /* 与资源层一致的合法输出点掩码(Q0~Q7、Q10~Q17、Q20)。 */
- const uint32_t validOutputMask = 0x0013FCFFUL;
-
- if (pointNumber >= PLSR_HW_OUTPUT_POINT_COUNT)
- {
- return 0U;
- }
- if ((validOutputMask & (1UL << pointNumber)) == 0UL)
- {
- return 0U;
- }
- #ifndef PLSR_HOST_TEST
- if (PlsrHwOutputPins[pointNumber].port == NULL)
- {
- return 0U;
- }
- #endif
- return 1U;
- }
-
- PLSR_RESULT PlsrHwInit(void)
- {
- uint8_t axis;
-
- (void)memset(PlsrHwAxes, 0, sizeof(PlsrHwAxes));
- for (axis = 0U; axis < PLSR_HW_AXIS_COUNT; axis++)
- {
- PlsrHwAxes[axis].state = PLSR_HW_STATE_IDLE;
- PlsrHwAxes[axis].directionPoint = PLSR_HW_DIR_POINT_NONE;
- #ifdef PLSR_HOST_TEST
- (void)memset(&PlsrHwTimers[axis], 0, sizeof(PlsrHwTimers[axis]));
- #else
- PlsrHwTimerSetCc1e(axis, 0UL);
- PlsrHwTimerSetUie(axis, 0UL);
- PlsrHwTimerSetCen(axis, 0UL);
- #endif
- }
-
- #ifndef PLSR_HOST_TEST
- {
- GPIO_InitTypeDef gpio;
-
- /* 1. 输出点 GPIO 时钟(DIR 点按需配置时使用)。 */
- __HAL_RCC_GPIOF_CLK_ENABLE();
- __HAL_RCC_GPIOI_CLK_ENABLE();
- __HAL_RCC_GPIOE_CLK_ENABLE();
- __HAL_RCC_GPIOG_CLK_ENABLE();
- __HAL_RCC_GPIOH_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
-
- /* 2. 上电安全:输出点保持复位默认高阻(漏型输出 = 截止 = OFF)。
- * 不驱动任何 Y 点,DIR 点仅在 PlsrHwSetDirLevel 时按需配置。 */
-
- /* 3. 定时器时钟。 */
- __HAL_RCC_TIM10_CLK_ENABLE();
- __HAL_RCC_TIM11_CLK_ENABLE();
- __HAL_RCC_TIM13_CLK_ENABLE();
- __HAL_RCC_TIM14_CLK_ENABLE();
-
- /* 4. 脉冲点切定时器复用(PF6/7=AF3、PF8/9=AF9)。
- * 定时器通道尚未使能(CC1E=0),输出级断开,无毛刺。 */
- gpio.Mode = GPIO_MODE_AF_PP;
- gpio.Pull = GPIO_NOPULL;
- gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
- gpio.Pin = GPIO_PIN_6 | GPIO_PIN_7;
- gpio.Alternate = 3U;
- HAL_GPIO_Init(GPIOF, &gpio);
- gpio.Pin = GPIO_PIN_8 | GPIO_PIN_9;
- gpio.Alternate = 9U;
- HAL_GPIO_Init(GPIOF, &gpio);
-
- /* 5. 更新中断 NVIC:高速计数/尾脉冲层(P3b 统一规划优先级表)。 */
- HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 1U, 0U);
- HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
- HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 1U, 0U);
- HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
- HAL_NVIC_SetPriority(TIM1_TRG_COM_TIM11_IRQn, 1U, 0U);
- HAL_NVIC_EnableIRQ(TIM1_TRG_COM_TIM11_IRQn);
- HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, 1U, 0U);
- HAL_NVIC_EnableIRQ(TIM8_TRG_COM_TIM14_IRQn);
- }
- #endif
- return PLSR_RESULT_OK;
- }
-
- PLSR_RESULT PlsrHwStartPulse(uint8_t axis, const PLSR_HW_START_PARAMS *params)
- {
- PLSR_HW_AXIS_STATE *state;
- uint8_t directionChanged = 0U;
-
- if ((axis >= PLSR_HW_AXIS_COUNT) || (params == NULL))
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if (params->targetPulses <= 0)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if ((uint32_t)params->outputMode > (uint32_t)PLSR_OUTPUT_CW_CCW)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if ((params->outputMode == PLSR_OUTPUT_AB)
- && (PlsrHwIsAbBaseAxis(axis) == 0U))
- {
- return PLSR_RESULT_INVALID_AXIS;
- }
- if (params->outputMode == PLSR_OUTPUT_CW_CCW)
- {
- return PLSR_RESULT_NOT_SUPPORTED;
- }
- #ifndef PLSR_HOST_TEST
- if (params->outputMode == PLSR_OUTPUT_AB)
- {
- /* P3b-1 只交付可验证的 host 相序模型;禁止目标板误输出成
- * 单路 PULSE/DIR。P3b-2 接入双定时器后移除此保护。 */
- return PLSR_RESULT_NOT_SUPPORTED;
- }
- #endif
- state = &PlsrHwAxes[axis];
- if (state->state == PLSR_HW_STATE_RUNNING)
- {
- return PLSR_RESULT_BUSY;
- }
-
- /* 方向延时只在方向发生变化时生效(首次启动/换向/换方向点):
- * 段间同向衔接不再等待 10ms,直接进入 PWM 待启动。 */
- if (params->outputMode == PLSR_OUTPUT_PULSE_DIR)
- {
- directionChanged =
- (state->directionPoint == PLSR_HW_DIR_POINT_NONE)
- || (state->directionPoint != params->directionPoint)
- || (state->directionPositive != params->directionPositive);
- }
-
- state->outputMode = params->outputMode;
- state->targetPulses = params->targetPulses;
- state->emittedPulses = 0;
- state->currentFrequencyHz = params->frequencyHz;
- state->directionPoint =
- (params->outputMode == PLSR_OUTPUT_PULSE_DIR)
- ? params->directionPoint
- : PLSR_HW_DIR_POINT_NONE;
- state->directionDelayRemainingMs =
- ((params->outputMode == PLSR_OUTPUT_PULSE_DIR)
- && (directionChanged != 0U))
- ? params->directionDelayMs
- : 0U;
- state->abQuarter = 0U;
- if (params->outputMode == PLSR_OUTPUT_PULSE_DIR)
- {
- PlsrHwSetDirLevel(axis, params->directionPositive);
- }
- else
- {
- state->directionPositive =
- (params->directionPositive != 0U) ? 1U : 0U;
- }
- state->state = (state->directionDelayRemainingMs > 0U)
- ? PLSR_HW_STATE_DIR_SETTLING
- : PLSR_HW_STATE_PWM_PENDING;
- return PLSR_RESULT_OK;
- }
-
- PLSR_RESULT PlsrHwSetFrequency(uint8_t axis, uint32_t frequencyHz)
- {
- PLSR_HW_AXIS_STATE *state;
-
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- state = &PlsrHwAxes[axis];
- state->currentFrequencyHz = frequencyHz;
- if (state->state == PLSR_HW_STATE_RUNNING)
- {
- if (frequencyHz > 0UL)
- {
- /* 运行中调频:预装载写入,更新事件时生效,不触碰使能位。 */
- PlsrHwConfigureActiveOutput(axis, state->outputMode, frequencyHz);
- }
- else
- {
- PlsrHwStopActiveOutput(axis, state->outputMode);
- }
- }
- else if ((state->state == PLSR_HW_STATE_PWM_PENDING)
- && (frequencyHz > 0UL))
- {
- PlsrHwConfigureActiveOutput(axis, state->outputMode, frequencyHz);
- PlsrHwBeginActiveOutput(axis, state->outputMode);
- state->state = PLSR_HW_STATE_RUNNING;
- }
- return PLSR_RESULT_OK;
- }
-
- PLSR_RESULT PlsrHwStopPulse(uint8_t axis)
- {
- PLSR_HW_AXIS_STATE *state;
-
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- state = &PlsrHwAxes[axis];
- if (state->state != PLSR_HW_STATE_IDLE)
- {
- PlsrHwStopActiveOutput(axis, state->outputMode);
- state->abQuarter = 0U;
- state->state = PLSR_HW_STATE_IDLE;
- }
- return PLSR_RESULT_OK;
- }
-
- uint8_t PlsrHwIsPulseActive(uint8_t axis)
- {
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return 0U;
- }
- return (PlsrHwAxes[axis].state == PLSR_HW_STATE_RUNNING) ? 1U : 0U;
- }
-
- PLSR_HW_STATE PlsrHwGetState(uint8_t axis)
- {
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return PLSR_HW_STATE_IDLE;
- }
- return PlsrHwAxes[axis].state;
- }
-
- uint32_t PlsrHwGetTimerClockHz(uint8_t axis)
- {
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return 0UL;
- }
- return PlsrHwAxisMap[axis].timerClockHz;
- }
-
- /* 硬件已发出的脉冲数(profile 虚拟计数校准用,中断内递增)。 */
- int64_t PlsrHwGetEmittedPulses(uint8_t axis)
- {
- int64_t emittedPulses;
-
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return 0;
- }
- #ifdef PLSR_HOST_TEST
- emittedPulses = PlsrHwAxes[axis].emittedPulses;
- #else
- {
- uint32_t interruptState = __get_PRIMASK();
-
- __disable_irq();
- __DMB();
- emittedPulses = PlsrHwAxes[axis].emittedPulses;
- __DMB();
- if (interruptState == 0UL)
- {
- __enable_irq();
- }
- }
- #endif
- return emittedPulses;
- }
-
- void PlsrHwTick(uint8_t axis)
- {
- PLSR_HW_AXIS_STATE *state;
-
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return;
- }
- state = &PlsrHwAxes[axis];
- /* 调试:每 tick 记录定时器实况(CNT 演化定位第一周期压缩)。 */
- PlsrHwDbgCapture(axis, 3U);
- switch (state->state)
- {
- case PLSR_HW_STATE_DIR_SETTLING:
- if (state->directionDelayRemainingMs > 0U)
- {
- state->directionDelayRemainingMs--;
- }
- if (state->directionDelayRemainingMs == 0U)
- {
- state->state = PLSR_HW_STATE_PWM_PENDING;
- }
- break;
-
- case PLSR_HW_STATE_PWM_PENDING:
- if (state->currentFrequencyHz > 0UL)
- {
- PlsrHwConfigureActiveOutput(axis,
- state->outputMode,
- state->currentFrequencyHz);
- PlsrHwBeginActiveOutput(axis, state->outputMode);
- state->state = PLSR_HW_STATE_RUNNING;
- }
- break;
-
- default:
- break;
- }
- }
-
- /* 输出定时器更新中断:每周期末触发一次(=1 个脉冲)。 */
- void PlsrHwOnTimerUpdate(uint8_t axis)
- {
- PLSR_HW_AXIS_STATE *state;
-
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return;
- }
- state = &PlsrHwAxes[axis];
- if (PlsrHwTimerHasUif(axis) == 0U)
- {
- return;
- }
- PlsrHwTimerClearUif(axis);
- if (state->state != PLSR_HW_STATE_RUNNING)
- {
- return;
- }
- if (state->outputMode != PLSR_OUTPUT_PULSE_DIR)
- {
- /* AB host 模型按四分之一周期推进,不能把任一物理定时器的
- * update 直接当成完整 AB 指令脉冲。 */
- return;
- }
-
- state->emittedPulses++;
- if (state->emittedPulses >= state->targetPulses)
- {
- /* 更新时刻 = 周期结束:关通道即完整下降沿后停止,无额外脉冲。 */
- PlsrHwStopActiveOutput(axis, state->outputMode);
- state->state = PLSR_HW_STATE_DONE;
- (void)PlsrPostEvent(axis, PLSR_EVENT_SEGMENT_COMPLETE);
- }
- }
-
- #ifdef PLSR_HOST_TEST
- uint32_t PlsrHwTestGetArr(uint8_t axis)
- {
- return PlsrHwTimers[axis].arr;
- }
-
- uint32_t PlsrHwTestGetCcr(uint8_t axis)
- {
- return PlsrHwTimers[axis].ccr1;
- }
-
- uint32_t PlsrHwTestGetCcmr1(uint8_t axis)
- {
- return PlsrHwTimers[axis].ccmr1;
- }
-
- uint32_t PlsrHwTestGetCr1(uint8_t axis)
- {
- return PlsrHwTimers[axis].cr1;
- }
-
- uint32_t PlsrHwTestGetPsc(uint8_t axis)
- {
- return PlsrHwTimers[axis].psc;
- }
-
- uint8_t PlsrHwTestGetPwmEnabled(uint8_t axis)
- {
- return ((PlsrHwTimers[axis].ccer & PLSR_HW_TIMER_CHANNEL1_BIT) != 0UL)
- ? 1U
- : 0U;
- }
-
- uint8_t PlsrHwTestGetDirLevel(uint8_t axis)
- {
- return PlsrHwTimers[axis].dirLevel;
- }
-
- uint8_t PlsrHwTestGetAbPhaseA(uint8_t axis)
- {
- const PLSR_HW_AXIS_STATE *state;
-
- if ((axis >= PLSR_HW_AXIS_COUNT) || (PlsrHwIsAbBaseAxis(axis) == 0U))
- {
- return 0U;
- }
- state = &PlsrHwAxes[axis];
- if (state->directionPositive != 0U)
- {
- return ((state->abQuarter == 1U) || (state->abQuarter == 2U))
- ? 1U
- : 0U;
- }
- return ((state->abQuarter == 2U) || (state->abQuarter == 3U))
- ? 1U
- : 0U;
- }
-
- uint8_t PlsrHwTestGetAbPhaseB(uint8_t axis)
- {
- const PLSR_HW_AXIS_STATE *state;
-
- if ((axis >= PLSR_HW_AXIS_COUNT) || (PlsrHwIsAbBaseAxis(axis) == 0U))
- {
- return 0U;
- }
- state = &PlsrHwAxes[axis];
- if (state->directionPositive != 0U)
- {
- return ((state->abQuarter == 2U) || (state->abQuarter == 3U))
- ? 1U
- : 0U;
- }
- return ((state->abQuarter == 1U) || (state->abQuarter == 2U))
- ? 1U
- : 0U;
- }
-
- uint8_t PlsrHwTestGetAbQuarter(uint8_t axis)
- {
- if ((axis >= PLSR_HW_AXIS_COUNT) || (PlsrHwIsAbBaseAxis(axis) == 0U))
- {
- return 0U;
- }
- return PlsrHwAxes[axis].abQuarter;
- }
-
- void PlsrHwTestAdvanceAbQuarter(uint8_t axis)
- {
- PLSR_HW_AXIS_STATE *state;
-
- if ((axis >= PLSR_HW_AXIS_COUNT) || (PlsrHwIsAbBaseAxis(axis) == 0U))
- {
- return;
- }
- state = &PlsrHwAxes[axis];
- if ((state->state != PLSR_HW_STATE_RUNNING)
- || (state->outputMode != PLSR_OUTPUT_AB))
- {
- return;
- }
-
- state->abQuarter = (uint8_t)((state->abQuarter + 1U)
- % PLSR_HW_AB_QUARTER_COUNT);
- if (state->abQuarter == 0U)
- {
- state->emittedPulses++;
- if (state->emittedPulses >= state->targetPulses)
- {
- /* 仅在完整 00 边界停机,禁止留下半个正交周期。 */
- PlsrHwStopActiveOutput(axis, state->outputMode);
- state->state = PLSR_HW_STATE_DONE;
- (void)PlsrPostEvent(axis, PLSR_EVENT_SEGMENT_COMPLETE);
- }
- }
- }
-
- void PlsrHwTestTriggerUpdate(uint8_t axis)
- {
- if (axis < PLSR_HW_AXIS_COUNT)
- {
- PlsrHwTimers[axis].sr |= PLSR_HW_TIMER_UPDATE_BIT;
- }
- PlsrHwOnTimerUpdate(axis);
- }
- #endif
-
- #ifndef PLSR_HOST_TEST
- void TIM1_UP_TIM10_IRQHandler(void)
- {
- PlsrHwOnTimerUpdate(0U);
- }
-
- void TIM8_UP_TIM13_IRQHandler(void)
- {
- PlsrHwOnTimerUpdate(1U);
- }
-
- void TIM1_TRG_COM_TIM11_IRQHandler(void)
- {
- PlsrHwOnTimerUpdate(2U);
- }
-
- void TIM8_TRG_COM_TIM14_IRQHandler(void)
- {
- PlsrHwOnTimerUpdate(3U);
- }
- #endif
|