|
- #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)
-
- 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},
- {168000000UL, 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},
- {168000000UL, PLSR_HW_DIR_POINT_NONE, TIM14, GPIOF, GPIO_PIN_9, 9U, TIM8_TRG_COM_TIM14_IRQn}
- #else
- {168000000UL, PLSR_HW_DIR_POINT_NONE},
- {168000000UL, PLSR_HW_DIR_POINT_NONE},
- {168000000UL, PLSR_HW_DIR_POINT_NONE},
- {168000000UL, 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 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;
- uint32_t currentFrequencyHz;
- int64_t targetPulses;
- int64_t emittedPulses;
- uint16_t directionDelayRemainingMs;
- uint8_t directionPoint;
- uint8_t directionPositive;
- } PLSR_HW_AXIS_STATE;
-
- static PLSR_HW_AXIS_STATE PlsrHwAxes[PLSR_HW_AXIS_COUNT];
-
- /* ---- 定时器寄存器访问抽象(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
- }
-
- 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
- }
-
- /* ---- DIR 输出 ---- */
-
- 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];
-
- if (pin->port != NULL)
- {
- HAL_GPIO_WritePin(pin->port, pin->pin,
- (positive != 0U) ? GPIO_PIN_SET : GPIO_PIN_RESET);
- }
- }
- #endif
- }
-
- /* ---- PWM 启停 ---- */
-
- static void PlsrHwStartPwmTimer(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% 占空比 */
- PlsrHwTimerSetUie(axis, 1UL);
- PlsrHwTimerSetCc1e(axis, 1UL);
- PlsrHwTimerSetCen(axis, 1UL);
- }
-
- static void PlsrHwStopPwmTimer(uint8_t axis)
- {
- PlsrHwTimerSetCc1e(axis, 0UL);
- PlsrHwTimerSetUie(axis, 0UL);
- PlsrHwTimerSetCen(axis, 0UL);
- }
-
- 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
- }
- return PLSR_RESULT_OK;
- }
-
- PLSR_RESULT PlsrHwStartPulse(uint8_t axis, const PLSR_HW_START_PARAMS *params)
- {
- PLSR_HW_AXIS_STATE *state;
-
- if ((axis >= PLSR_HW_AXIS_COUNT) || (params == NULL))
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- if (params->targetPulses <= 0)
- {
- return PLSR_RESULT_INVALID_ARGUMENT;
- }
- state = &PlsrHwAxes[axis];
- if (state->state == PLSR_HW_STATE_RUNNING)
- {
- return PLSR_RESULT_BUSY;
- }
-
- state->targetPulses = params->targetPulses;
- state->emittedPulses = 0;
- state->currentFrequencyHz = params->frequencyHz;
- state->directionPoint = params->directionPoint;
- state->directionDelayRemainingMs = params->directionDelayMs;
- PlsrHwSetDirLevel(axis, params->directionPositive);
- state->state = (params->directionDelayMs > 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)
- {
- PlsrHwStartPwmTimer(axis, frequencyHz);
- }
- else
- {
- PlsrHwStopPwmTimer(axis);
- }
- }
- else if ((state->state == PLSR_HW_STATE_PWM_PENDING)
- && (frequencyHz > 0UL))
- {
- PlsrHwStartPwmTimer(axis, frequencyHz);
- 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)
- {
- PlsrHwStopPwmTimer(axis);
- 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;
- }
-
- void PlsrHwTick(uint8_t axis)
- {
- PLSR_HW_AXIS_STATE *state;
-
- if (axis >= PLSR_HW_AXIS_COUNT)
- {
- return;
- }
- state = &PlsrHwAxes[axis];
- 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)
- {
- PlsrHwStartPwmTimer(axis, state->currentFrequencyHz);
- 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];
- PlsrHwTimerClearUif(axis);
- if (state->state != PLSR_HW_STATE_RUNNING)
- {
- return;
- }
-
- state->emittedPulses++;
- if (state->emittedPulses >= state->targetPulses)
- {
- /* 更新时刻 = 周期结束:关通道即完整下降沿后停止,无额外脉冲。 */
- PlsrHwStopPwmTimer(axis);
- 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 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;
- }
-
- void PlsrHwTestTriggerUpdate(uint8_t axis)
- {
- 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
|