|
- #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_TIMER_CC1_BIT (0x0002U)
- #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
- };
-
- #ifndef PLSR_HOST_TEST
- static const uint8_t PlsrHwPulsePinIndex[PLSR_HW_AXIS_COUNT] =
- {
- 6U, 8U, 7U, 9U
- };
-
- /* 重定相期间由 GPIO 直接保持物理输出低电平。AFR 配置保持不变,
- * 只切换 MODER,因此恢复定时器复用功能只需一次寄存器写入。 */
- static void PlsrHwHoldPulsePinLow(uint8_t axis)
- {
- GPIO_TypeDef *port = PlsrHwAxisMap[axis].gpioPort;
- uint32_t shift = (uint32_t)PlsrHwPulsePinIndex[axis] * 2UL;
- uint32_t moder;
-
- port->BSRR = (uint32_t)PlsrHwAxisMap[axis].gpioPin << 16U;
- moder = port->MODER;
- moder &= ~(3UL << shift);
- moder |= 1UL << shift;
- port->MODER = moder;
- __DMB();
- }
-
- static void PlsrHwReleasePulsePin(uint8_t axis)
- {
- GPIO_TypeDef *port = PlsrHwAxisMap[axis].gpioPort;
- uint32_t shift = (uint32_t)PlsrHwPulsePinIndex[axis] * 2UL;
- uint32_t moder = port->MODER;
-
- moder &= ~(3UL << shift);
- moder |= 2UL << shift;
- port->MODER = moder;
- __DMB();
- }
- #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 cnt;
- 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;
- uint8_t abCountAxis;
- uint8_t abStartupPriming;
- uint8_t abOutputPrimed;
- uint16_t abActiveBasePsc;
- uint16_t abActivePairPsc;
- uint16_t abActiveArr;
- uint16_t abPendingBasePsc;
- uint16_t abPendingPairPsc;
- uint16_t abPendingArr;
- uint8_t abFrequencyPending;
- } PLSR_HW_AXIS_STATE;
-
- static PLSR_HW_AXIS_STATE PlsrHwAxes[PLSR_HW_AXIS_COUNT];
-
- /* 调试快照:当前上板自测只记录 Q0 的 160 ms,避免四轴
- * PlsrHwTick 互相混入,同时控制临时 RAM 占用。reason=0 表示段启动,
- * reason=3 表示 1 ms HAL tick,reason=4 表示 AB 在 00 边界换频重定相。 */
- #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 PlsrHwTimerSetCnt(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].cnt = value;
- /* F407 实测语义:CNT 写到活动 CCR1 比较值会置 CC1IF。 */
- if (value == PlsrHwTimers[axis].ccr1)
- {
- PlsrHwTimers[axis].sr |= PLSR_HW_TIMER_CC1_BIT;
- }
- #else
- PlsrHwAxisMap[axis].timer->CNT = 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
- }
-
- /* AB 启动和重定相时先把 OC1REF 钳到低电平,再切到 frozen 保持 00。
- * 两路 CNT 就位后从 frozen 切到 PWM1,硬件会按当前 CNT/CCR 重新计算输出,
- * 避免 UG 后残留的 OC1REF 高电平经 CC1E 暴露为窄脉冲。 */
- static void PlsrHwTimerSetForcedInactive(uint8_t axis)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].ccmr1 = 0x0048UL;
- #else
- PlsrHwAxisMap[axis].timer->CCMR1 = TIM_CCMR1_OC1M_2
- | TIM_CCMR1_OC1PE;
- #endif
- }
-
- static void PlsrHwTimerSetFrozen(uint8_t axis)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].ccmr1 = 0x0008UL;
- #else
- PlsrHwAxisMap[axis].timer->CCMR1 = 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 PlsrHwTimerSetCc1ie(uint8_t axis, uint32_t value)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].dier =
- (PlsrHwTimers[axis].dier & ~PLSR_HW_TIMER_CC1_BIT)
- | ((value != 0UL) ? PLSR_HW_TIMER_CC1_BIT : 0UL);
- if ((value != 0UL)
- && ((PlsrHwTimers[axis].sr & PLSR_HW_TIMER_CC1_BIT) != 0UL))
- {
- PlsrHwOnTimerUpdate(axis);
- }
- #else
- if (value != 0UL)
- {
- PlsrHwAxisMap[axis].timer->DIER |= TIM_DIER_CC1IE;
- }
- else
- {
- PlsrHwAxisMap[axis].timer->DIER &= ~TIM_DIER_CC1IE;
- }
- #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
- }
-
- static void PlsrHwTimerClearCc1if(uint8_t axis)
- {
- #ifdef PLSR_HOST_TEST
- PlsrHwTimers[axis].sr &= ~PLSR_HW_TIMER_CC1_BIT;
- #else
- PlsrHwAxisMap[axis].timer->SR &= ~TIM_SR_CC1IF;
- #endif
- }
-
- static uint8_t PlsrHwTimerHasCc1if(uint8_t axis)
- {
- #ifdef PLSR_HOST_TEST
- return ((PlsrHwTimers[axis].sr & PLSR_HW_TIMER_CC1_BIT) != 0UL)
- ? 1U
- : 0U;
- #else
- return ((PlsrHwAxisMap[axis].timer->SR & TIM_SR_CC1IF) != 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);
- PlsrHwTimerClearCc1if(axis);
- PlsrHwDbgCapture(axis, 0U);
- PlsrHwTimerSetCc1ie(axis, 0UL);
- PlsrHwTimerSetUie(axis, 1UL);
- PlsrHwTimerSetCc1e(axis, 1UL);
- PlsrHwTimerSetCen(axis, 1UL);
- }
-
- static void PlsrHwStopPwmTimer(uint8_t axis)
- {
- PlsrHwTimerSetCc1e(axis, 0UL);
- PlsrHwTimerSetUie(axis, 0UL);
- PlsrHwTimerSetCc1ie(axis, 0UL);
- PlsrHwTimerSetCen(axis, 0UL);
- PlsrHwTimerClearUif(axis);
- PlsrHwTimerClearCc1if(axis);
- }
-
- static uint8_t PlsrHwIsAbBaseAxis(uint8_t axis)
- {
- return ((axis == 0U) || (axis == 2U)) ? 1U : 0U;
- }
-
- static uint8_t PlsrHwGetPairedAxis(uint8_t axis)
- {
- return (uint8_t)(axis + 1U);
- }
-
- /* 为 168MHz/84MHz 配对定时器选择相同 ARR,并让前者的 PSC 分频
- * 始终是后者的 2 倍。两路获得完全相同的计数时钟与周期,避免
- * 独立取整造成 AB 相位随运行时间漂移。 */
- static uint8_t PlsrHwCalculateAbDividers(uint8_t axis,
- uint32_t frequencyHz,
- uint16_t *basePsc,
- uint16_t *pairPsc,
- uint16_t *arr)
- {
- uint8_t pairAxis = PlsrHwGetPairedAxis(axis);
- uint64_t baseClock = PlsrHwAxisMap[axis].timerClockHz;
- uint64_t pairClock = PlsrHwAxisMap[pairAxis].timerClockHz;
- uint64_t ratio;
- uint64_t pairDivider;
- uint64_t baseDivider;
- uint64_t periodTicks;
-
- if ((frequencyHz == 0UL) || (basePsc == NULL) || (pairPsc == NULL)
- || (arr == NULL) || (pairClock == 0UL)
- || ((baseClock % pairClock) != 0UL))
- {
- return 0U;
- }
- ratio = baseClock / pairClock;
- if (ratio == 0UL)
- {
- return 0U;
- }
- pairDivider = (pairClock
- + (uint64_t)frequencyHz * UINT64_C(65536) - 1UL)
- / ((uint64_t)frequencyHz * UINT64_C(65536));
- if (pairDivider == 0UL)
- {
- pairDivider = 1UL;
- }
- baseDivider = pairDivider * ratio;
- if ((pairDivider > UINT64_C(65536))
- || (baseDivider > UINT64_C(65536)))
- {
- return 0U;
- }
- periodTicks = (pairClock
- + ((uint64_t)frequencyHz * pairDivider) / 2UL)
- / ((uint64_t)frequencyHz * pairDivider);
- if ((periodTicks < 4UL) || (periodTicks > UINT64_C(65536)))
- {
- return 0U;
- }
- *basePsc = (uint16_t)(baseDivider - 1UL);
- *pairPsc = (uint16_t)(pairDivider - 1UL);
- *arr = (uint16_t)(periodTicks - 1UL);
- return 1U;
- }
-
- static void PlsrHwLoadAbPwm(uint8_t axis,
- uint16_t basePsc,
- uint16_t pairPsc,
- uint16_t arr)
- {
- uint8_t pairAxis = PlsrHwGetPairedAxis(axis);
- uint32_t compare;
-
- compare = ((uint32_t)arr + 1UL) / 2UL;
- PlsrHwTimerSetPsc(axis, basePsc);
- PlsrHwTimerSetPsc(pairAxis, pairPsc);
- PlsrHwTimerSetArr(axis, arr);
- PlsrHwTimerSetArr(pairAxis, arr);
- PlsrHwTimerSetCcr(axis, compare);
- PlsrHwTimerSetCcr(pairAxis, compare);
- PlsrHwTimerSetPwmMode1(axis);
- PlsrHwTimerSetPwmMode1(pairAxis);
- PlsrHwTimerSetArpe(axis, 1UL);
- PlsrHwTimerSetArpe(pairAxis, 1UL);
- PlsrHwAxes[axis].abActiveBasePsc = basePsc;
- PlsrHwAxes[axis].abActivePairPsc = pairPsc;
- PlsrHwAxes[axis].abActiveArr = arr;
- }
-
- static uint8_t PlsrHwConfigureAbPwm(uint8_t axis, uint32_t frequencyHz)
- {
- uint16_t basePsc;
- uint16_t pairPsc;
- uint16_t arr;
-
- if (PlsrHwCalculateAbDividers(axis,
- frequencyHz,
- &basePsc,
- &pairPsc,
- &arr) == 0U)
- {
- return 0U;
- }
- PlsrHwLoadAbPwm(axis, basePsc, pairPsc, arr);
- return 1U;
- }
-
- /* 运行中的 AB 调频不能直接写两路 ARR 预装载:两路定时器相差 1/4 周期,
- * 各自的 update 时刻也相差 1/4 周期,会短暂使用不同周期并永久积累相位误差。
- * 任务上下文只计算并发布最新参数,真正装载由 00 周期边界中断完成。 */
- static uint8_t PlsrHwQueueAbFrequency(uint8_t axis, uint32_t frequencyHz)
- {
- PLSR_HW_AXIS_STATE *state = &PlsrHwAxes[axis];
- uint16_t basePsc;
- uint16_t pairPsc;
- uint16_t arr;
- #ifndef PLSR_HOST_TEST
- uint32_t interruptState;
- #endif
-
- if (PlsrHwCalculateAbDividers(axis,
- frequencyHz,
- &basePsc,
- &pairPsc,
- &arr) == 0U)
- {
- return 0U;
- }
- #ifndef PLSR_HOST_TEST
- interruptState = __get_PRIMASK();
- __disable_irq();
- __DMB();
- #endif
- if ((basePsc == state->abActiveBasePsc)
- && (pairPsc == state->abActivePairPsc)
- && (arr == state->abActiveArr))
- {
- /* 量化后的分频参数未变化时取消旧请求,避免匀速段每 1ms 重定相。 */
- state->abFrequencyPending = 0U;
- }
- else
- {
- state->abPendingBasePsc = basePsc;
- state->abPendingPairPsc = pairPsc;
- state->abPendingArr = arr;
- state->abFrequencyPending = 1U;
- }
- #ifndef PLSR_HOST_TEST
- __DMB();
- if (interruptState == 0UL)
- {
- __enable_irq();
- }
- #endif
- return 1U;
- }
-
- static void PlsrHwBeginAbOutput(uint8_t axis, uint8_t debugReason)
- {
- PLSR_HW_AXIS_STATE *state = &PlsrHwAxes[axis];
- uint8_t pairAxis = PlsrHwGetPairedAxis(axis);
- uint8_t leadAxis = (state->directionPositive != 0U) ? axis : pairAxis;
- uint8_t lagAxis = (state->directionPositive != 0U) ? pairAxis : axis;
- uint32_t periodTicks;
- uint32_t leadStart;
- uint32_t lagStart;
- #ifndef PLSR_HOST_TEST
- uint32_t interruptState;
- #else
- (void)debugReason;
- #endif
-
- #ifdef PLSR_HOST_TEST
- periodTicks = PlsrHwTimers[axis].arr + 1UL;
- #else
- periodTicks = PlsrHwAxisMap[axis].timer->ARR + 1UL;
- #endif
- leadStart = (periodTicks * 3UL) / 4UL;
- /* 落后相从 CCR 精确起步;切回 PWM 后清 CC1IF,最后才开 CC1IE。 */
- lagStart = periodTicks / 2UL;
- state->abCountAxis = lagAxis;
- state->abQuarter = 0U;
- state->abStartupPriming = (state->abOutputPrimed == 0U) ? 1U : 0U;
-
- #ifndef PLSR_HOST_TEST
- interruptState = __get_PRIMASK();
- __disable_irq();
- __DMB();
- PlsrHwHoldPulsePinLow(axis);
- PlsrHwHoldPulsePinLow(pairAxis);
- #endif
- PlsrHwTimerSetCen(axis, 0UL);
- PlsrHwTimerSetCen(pairAxis, 0UL);
- PlsrHwTimerSetCc1e(axis, 0UL);
- PlsrHwTimerSetCc1e(pairAxis, 0UL);
- PlsrHwTimerSetUie(axis, 0UL);
- PlsrHwTimerSetUie(pairAxis, 0UL);
- PlsrHwTimerSetCc1ie(axis, 0UL);
- PlsrHwTimerSetCc1ie(pairAxis, 0UL);
- PlsrHwTimerSetForcedInactive(axis);
- PlsrHwTimerSetForcedInactive(pairAxis);
- PlsrHwTimerSetFrozen(axis);
- PlsrHwTimerSetFrozen(pairAxis);
- PlsrHwTimerSetUg(axis);
- PlsrHwTimerSetUg(pairAxis);
- PlsrHwTimerClearUif(axis);
- PlsrHwTimerClearUif(pairAxis);
- PlsrHwTimerClearCc1if(axis);
- PlsrHwTimerClearCc1if(pairAxis);
- PlsrHwTimerSetCnt(leadAxis, leadStart);
- PlsrHwTimerSetCnt(lagAxis, lagStart);
- #ifdef PLSR_HOST_TEST
- PlsrHwTimerSetCc1e(axis, 1UL);
- PlsrHwTimerSetCc1e(pairAxis, 1UL);
- PlsrHwTimerSetPwmMode1(axis);
- PlsrHwTimerSetPwmMode1(pairAxis);
- PlsrHwTimerClearCc1if(axis);
- PlsrHwTimerClearCc1if(pairAxis);
- PlsrHwTimerSetCen(axis, 1UL);
- PlsrHwTimerSetCen(pairAxis, 1UL);
- PlsrHwTimerClearCc1if(axis);
- PlsrHwTimerClearCc1if(pairAxis);
- PlsrHwTimerSetCc1ie(lagAxis, 1UL);
- #else
- PlsrHwTimerSetCc1e(axis, 1UL);
- PlsrHwTimerSetCc1e(pairAxis, 1UL);
- PlsrHwTimerSetPwmMode1(axis);
- PlsrHwTimerSetPwmMode1(pairAxis);
- PlsrHwTimerClearCc1if(axis);
- PlsrHwTimerClearCc1if(pairAxis);
- if (state->abStartupPriming == 0U)
- {
- /* 完成过首次预热后,段间/调频重定相均从已验证的 00 边界
- * 直接交还 AF,不额外吞掉用户周期。 */
- PlsrHwReleasePulsePin(axis);
- PlsrHwReleasePulsePin(pairAxis);
- }
- PlsrHwTimerSetCen(axis, 1UL);
- PlsrHwTimerSetCen(pairAxis, 1UL);
- PlsrHwTimerClearCc1if(axis);
- PlsrHwTimerClearCc1if(pairAxis);
- PlsrHwTimerSetCc1ie(lagAxis, 1UL);
- __DMB();
- if (interruptState == 0UL)
- {
- __enable_irq();
- }
- #endif
- PlsrHwDbgCapture(axis, debugReason);
- }
-
- static void PlsrHwConfigureActiveOutput(uint8_t axis,
- PLSR_OUTPUT_MODE outputMode,
- uint32_t frequencyHz)
- {
- if (outputMode == PLSR_OUTPUT_AB)
- {
- (void)PlsrHwConfigureAbPwm(axis, frequencyHz);
- }
- else
- {
- PlsrHwConfigurePwm(axis, frequencyHz);
- }
- }
-
- static void PlsrHwBeginActiveOutput(uint8_t axis,
- PLSR_OUTPUT_MODE outputMode)
- {
- if (outputMode == PLSR_OUTPUT_AB)
- {
- PlsrHwBeginAbOutput(axis, 0U);
- }
- else
- {
- PlsrHwPwmBegin(axis);
- }
- }
-
- static void PlsrHwStopActiveOutput(uint8_t axis,
- PLSR_OUTPUT_MODE outputMode)
- {
- if ((outputMode == PLSR_OUTPUT_AB) && (PlsrHwIsAbBaseAxis(axis) != 0U))
- {
- uint8_t pairAxis = PlsrHwGetPairedAxis(axis);
- #ifndef PLSR_HOST_TEST
- uint32_t interruptState = __get_PRIMASK();
-
- __disable_irq();
- __DMB();
- /* DONE/STOP 后继续由 GPIO 保持 00,禁止已关闭 timer 泄漏残余边沿。 */
- PlsrHwHoldPulsePinLow(axis);
- PlsrHwHoldPulsePinLow(pairAxis);
- #endif
- PlsrHwStopPwmTimer(axis);
- PlsrHwStopPwmTimer(pairAxis);
- PlsrHwAxes[axis].abStartupPriming = 0U;
- #ifndef PLSR_HOST_TEST
- __DMB();
- if (interruptState == 0UL)
- {
- __enable_irq();
- }
- #endif
- }
- else
- {
- PlsrHwStopPwmTimer(axis);
- }
- }
-
- 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);
- PlsrHwTimerSetCc1ie(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;
- }
- 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;
- state->abFrequencyPending = 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)
- {
- if (state->outputMode == PLSR_OUTPUT_AB)
- {
- if (PlsrHwQueueAbFrequency(axis, frequencyHz) == 0U)
- {
- return PLSR_RESULT_DIVIDER_UNREPRESENTABLE;
- }
- }
- else
- {
- /* PULSE/DIR 仍由单定时器在自身 update 边界加载预装值。 */
- 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);
- /* 必须先发布 RUNNING,避免启用 timer IRQ 后观察到 PWM_PENDING。 */
- state->state = PLSR_HW_STATE_RUNNING;
- PlsrHwBeginActiveOutput(axis, state->outputMode);
- }
- 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->abFrequencyPending = 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;
- }
-
- uint32_t PlsrHwGetCurrentFrequencyHz(uint8_t axis)
- {
- if ((axis >= PLSR_HW_AXIS_COUNT)
- || (PlsrHwAxes[axis].state != PLSR_HW_STATE_RUNNING))
- {
- return 0UL;
- }
- return PlsrHwAxes[axis].currentFrequencyHz;
- }
-
- /* 硬件已发出的脉冲数(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;
- }
-
- uint8_t PlsrHwIsAbStartupPriming(uint8_t axis)
- {
- if ((axis >= PLSR_HW_AXIS_COUNT) || (PlsrHwIsAbBaseAxis(axis) == 0U))
- {
- return 0U;
- }
- return PlsrHwAxes[axis].abStartupPriming;
- }
-
- 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);
- state->state = PLSR_HW_STATE_RUNNING;
- PlsrHwBeginActiveOutput(axis, state->outputMode);
- }
- break;
-
- default:
- break;
- }
- }
-
- /* 输出定时器中断入口:PULSE/DIR 在 update 计数;AB 在落后相
- * CC1 下降沿(四状态回到 00)计一个完整正交周期。 */
- void PlsrHwOnTimerUpdate(uint8_t axis)
- {
- PLSR_HW_AXIS_STATE *state;
- uint8_t ownerAxis;
- uint8_t hasCc1;
-
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return;
- }
-
- /* CC1IF 无论当前状态如何都必须先清除;否则启动窗口中的杂散
- * compare 标志会让共享 IRQ 持续重入,主线程无法完成 CEN 配置。 */
- hasCc1 = PlsrHwTimerHasCc1if(axis);
- if (hasCc1 != 0U)
- {
- PlsrHwTimerClearCc1if(axis);
- }
- ownerAxis = (uint8_t)(axis & 0xFEU);
- state = &PlsrHwAxes[ownerAxis];
- if ((state->state == PLSR_HW_STATE_RUNNING)
- && (state->outputMode == PLSR_OUTPUT_AB))
- {
- if (PlsrHwTimerHasUif(axis) != 0U)
- {
- PlsrHwTimerClearUif(axis);
- }
- if ((hasCc1 == 0U) || (axis != state->abCountAxis))
- {
- return;
- }
- if (state->abStartupPriming != 0U)
- {
- /* F407 首次切换 OC 模式时 OC1REF 初态不可直接作为物理AB相。
- * GPIO 保持 00 隐藏首个内部周期;落后相下降沿是真实 00
- * 边界,此时再交还 AF,且该隐藏周期绝不能计入 emitted。 */
- state->abStartupPriming = 0U;
- state->abOutputPrimed = 1U;
- #ifndef PLSR_HOST_TEST
- PlsrHwReleasePulsePin(ownerAxis);
- PlsrHwReleasePulsePin(PlsrHwGetPairedAxis(ownerAxis));
- #endif
- return;
- }
- state->emittedPulses++;
- if (state->emittedPulses >= state->targetPulses)
- {
- PlsrHwStopActiveOutput(ownerAxis, state->outputMode);
- state->abQuarter = 0U;
- state->abFrequencyPending = 0U;
- state->state = PLSR_HW_STATE_DONE;
- (void)PlsrPostEvent(ownerAxis, PLSR_EVENT_SEGMENT_COMPLETE);
- }
- else if (state->abFrequencyPending != 0U)
- {
- uint16_t basePsc = state->abPendingBasePsc;
- uint16_t pairPsc = state->abPendingPairPsc;
- uint16_t arr = state->abPendingArr;
-
- state->abFrequencyPending = 0U;
- PlsrHwLoadAbPwm(ownerAxis, basePsc, pairPsc, arr);
- /* 落后相刚下降,AB=00;两路从同一个完整周期边界重定相。 */
- PlsrHwBeginAbOutput(ownerAxis, 4U);
- }
- return;
- }
-
- if (hasCc1 != 0U)
- {
- /* 非运行态/非 AB 模式的 CC1 仅作为杂散标志消费。 */
- 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)
- {
- 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 PlsrHwTestGetCnt(uint8_t axis)
- {
- return PlsrHwTimers[axis].cnt;
- }
-
- 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)
- {
- /* 模拟目标板落后相 CC1 下降沿中断,复用生产计数路径。 */
- PlsrHwTimers[state->abCountAxis].sr |= PLSR_HW_TIMER_CC1_BIT;
- PlsrHwOnTimerUpdate(state->abCountAxis);
- }
- }
-
- 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
|