Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

575 Zeilen
14 KiB

  1. #include "plsr_hal_f407.h"
  2. #include "plsr_address_map.h"
  3. #include "plsr_core.h"
  4. #include "plsr_job.h"
  5. #include <string.h>
  6. #ifndef PLSR_HOST_TEST
  7. #include "stm32f4xx.h"
  8. #include "stm32f4xx_hal.h"
  9. #endif
  10. #define PLSR_HW_TIMER_CHANNEL1_BIT (0x0001U)
  11. #define PLSR_HW_TIMER_UPDATE_BIT (0x0001U)
  12. #define PLSR_HW_OUTPUT_POINT_COUNT (21U)
  13. typedef struct
  14. {
  15. uint32_t timerClockHz;
  16. uint8_t directionPoint; /* 0xFF = 无 */
  17. #ifndef PLSR_HOST_TEST
  18. TIM_TypeDef *timer;
  19. GPIO_TypeDef *gpioPort;
  20. uint16_t gpioPin;
  21. uint8_t afMode;
  22. IRQn_Type irq;
  23. #endif
  24. } PLSR_HW_AXIS_MAP;
  25. #ifndef PLSR_HOST_TEST
  26. /* 输出点(Y 点号)→ GPIO 引脚:XDM-60T4-E 原理图。
  27. * 点号 8/9/18/19 不存在(资源层掩码 0x0013FCFF 已约束)。 */
  28. typedef struct
  29. {
  30. GPIO_TypeDef *port;
  31. uint16_t pin;
  32. } PLSR_HW_OUTPUT_PIN;
  33. static const PLSR_HW_OUTPUT_PIN PlsrHwOutputPins[PLSR_HW_OUTPUT_POINT_COUNT] =
  34. {
  35. {GPIOF, GPIO_PIN_6}, /* Y0 */
  36. {GPIOF, GPIO_PIN_8}, /* Y1 */
  37. {GPIOF, GPIO_PIN_7}, /* Y2 */
  38. {GPIOF, GPIO_PIN_9}, /* Y3 */
  39. {GPIOI, GPIO_PIN_8}, /* Y4 */
  40. {GPIOE, GPIO_PIN_6}, /* Y5 */
  41. {GPIOE, GPIO_PIN_5}, /* Y6 */
  42. {GPIOE, GPIO_PIN_4}, /* Y7 */
  43. {NULL, 0U}, /* Y8 */
  44. {NULL, 0U}, /* Y9 */
  45. {GPIOG, GPIO_PIN_7}, /* Y10 */
  46. {GPIOG, GPIO_PIN_6}, /* Y11 */
  47. {GPIOH, GPIO_PIN_9}, /* Y12 */
  48. {GPIOH, GPIO_PIN_8}, /* Y13 */
  49. {GPIOH, GPIO_PIN_7}, /* Y14 */
  50. {GPIOH, GPIO_PIN_6}, /* Y15 */
  51. {GPIOF, GPIO_PIN_11}, /* Y16 */
  52. {GPIOB, GPIO_PIN_0}, /* Y17 */
  53. {NULL, 0U}, /* Y18 */
  54. {NULL, 0U}, /* Y19 */
  55. {GPIOH, GPIO_PIN_5} /* Y20 */
  56. };
  57. #endif
  58. /* Q0~Q3 定时器:XDM-60T4-E。
  59. * PF6=TIM10_CH1(AF3)、PF7=TIM11_CH1(AF3)、PF8=TIM13_CH1(AF9)、PF9=TIM14_CH1(AF9)。
  60. * 定时器时钟由 RCC 实际配置计算(APB2 分频≠1 时定时器时钟×2)。 */
  61. static const PLSR_HW_AXIS_MAP PlsrHwAxisMap[PLSR_HW_AXIS_COUNT] =
  62. {
  63. #ifndef PLSR_HOST_TEST
  64. {168000000UL, PLSR_HW_DIR_POINT_NONE, TIM10, GPIOF, GPIO_PIN_6, 3U, TIM1_UP_TIM10_IRQn},
  65. {168000000UL, PLSR_HW_DIR_POINT_NONE, TIM13, GPIOF, GPIO_PIN_8, 9U, TIM8_UP_TIM13_IRQn},
  66. {168000000UL, PLSR_HW_DIR_POINT_NONE, TIM11, GPIOF, GPIO_PIN_7, 3U, TIM1_TRG_COM_TIM11_IRQn},
  67. {168000000UL, PLSR_HW_DIR_POINT_NONE, TIM14, GPIOF, GPIO_PIN_9, 9U, TIM8_TRG_COM_TIM14_IRQn}
  68. #else
  69. {168000000UL, PLSR_HW_DIR_POINT_NONE},
  70. {168000000UL, PLSR_HW_DIR_POINT_NONE},
  71. {168000000UL, PLSR_HW_DIR_POINT_NONE},
  72. {168000000UL, PLSR_HW_DIR_POINT_NONE}
  73. #endif
  74. };
  75. /* host 测试:模拟定时器寄存器。 */
  76. #ifdef PLSR_HOST_TEST
  77. typedef struct
  78. {
  79. uint32_t cr1;
  80. uint32_t dier;
  81. uint32_t sr;
  82. uint32_t psc;
  83. uint32_t arr;
  84. uint32_t ccr1;
  85. uint32_t ccer;
  86. uint8_t dirLevel;
  87. } PLSR_HW_TIMER_REGS;
  88. static PLSR_HW_TIMER_REGS PlsrHwTimers[PLSR_HW_AXIS_COUNT];
  89. #endif
  90. typedef struct
  91. {
  92. PLSR_HW_STATE state;
  93. uint32_t currentFrequencyHz;
  94. int64_t targetPulses;
  95. int64_t emittedPulses;
  96. uint16_t directionDelayRemainingMs;
  97. uint8_t directionPoint;
  98. uint8_t directionPositive;
  99. } PLSR_HW_AXIS_STATE;
  100. static PLSR_HW_AXIS_STATE PlsrHwAxes[PLSR_HW_AXIS_COUNT];
  101. /* ---- 定时器寄存器访问抽象(host 模拟 / 生产真实) ---- */
  102. static void PlsrHwTimerSetArr(uint8_t axis, uint32_t value)
  103. {
  104. #ifdef PLSR_HOST_TEST
  105. PlsrHwTimers[axis].arr = value;
  106. #else
  107. PlsrHwAxisMap[axis].timer->ARR = value;
  108. #endif
  109. }
  110. static void PlsrHwTimerSetPsc(uint8_t axis, uint32_t value)
  111. {
  112. #ifdef PLSR_HOST_TEST
  113. PlsrHwTimers[axis].psc = value;
  114. #else
  115. PlsrHwAxisMap[axis].timer->PSC = value;
  116. #endif
  117. }
  118. static void PlsrHwTimerSetCcr(uint8_t axis, uint32_t value)
  119. {
  120. #ifdef PLSR_HOST_TEST
  121. PlsrHwTimers[axis].ccr1 = value;
  122. #else
  123. PlsrHwAxisMap[axis].timer->CCR1 = value;
  124. #endif
  125. }
  126. static void PlsrHwTimerSetCen(uint8_t axis, uint32_t value)
  127. {
  128. #ifdef PLSR_HOST_TEST
  129. PlsrHwTimers[axis].cr1 = (PlsrHwTimers[axis].cr1 & ~0x0001UL) | value;
  130. #else
  131. if (value != 0UL)
  132. {
  133. PlsrHwAxisMap[axis].timer->CR1 |= TIM_CR1_CEN;
  134. }
  135. else
  136. {
  137. PlsrHwAxisMap[axis].timer->CR1 &= ~TIM_CR1_CEN;
  138. }
  139. #endif
  140. }
  141. static void PlsrHwTimerSetCc1e(uint8_t axis, uint32_t value)
  142. {
  143. #ifdef PLSR_HOST_TEST
  144. PlsrHwTimers[axis].ccer = (PlsrHwTimers[axis].ccer & ~0x0001UL) | value;
  145. #else
  146. if (value != 0UL)
  147. {
  148. PlsrHwAxisMap[axis].timer->CCER |= TIM_CCER_CC1E;
  149. }
  150. else
  151. {
  152. PlsrHwAxisMap[axis].timer->CCER &= ~TIM_CCER_CC1E;
  153. }
  154. #endif
  155. }
  156. static void PlsrHwTimerSetUie(uint8_t axis, uint32_t value)
  157. {
  158. #ifdef PLSR_HOST_TEST
  159. PlsrHwTimers[axis].dier = (PlsrHwTimers[axis].dier & ~0x0001UL) | value;
  160. #else
  161. if (value != 0UL)
  162. {
  163. PlsrHwAxisMap[axis].timer->DIER |= TIM_DIER_UIE;
  164. }
  165. else
  166. {
  167. PlsrHwAxisMap[axis].timer->DIER &= ~TIM_DIER_UIE;
  168. }
  169. #endif
  170. }
  171. static void PlsrHwTimerClearUif(uint8_t axis)
  172. {
  173. #ifdef PLSR_HOST_TEST
  174. PlsrHwTimers[axis].sr &= ~PLSR_HW_TIMER_UPDATE_BIT;
  175. #else
  176. PlsrHwAxisMap[axis].timer->SR &= ~TIM_SR_UIF;
  177. #endif
  178. }
  179. /* ---- DIR 输出 ---- */
  180. static void PlsrHwSetDirLevel(uint8_t axis, uint8_t positive)
  181. {
  182. PLSR_HW_AXIS_STATE *state = &PlsrHwAxes[axis];
  183. state->directionPositive = (positive != 0U) ? 1U : 0U;
  184. if (state->directionPoint == PLSR_HW_DIR_POINT_NONE)
  185. {
  186. return;
  187. }
  188. #ifdef PLSR_HOST_TEST
  189. PlsrHwTimers[axis].dirLevel = (positive != 0U) ? 1U : 0U;
  190. #else
  191. if (state->directionPoint < PLSR_HW_OUTPUT_POINT_COUNT)
  192. {
  193. const PLSR_HW_OUTPUT_PIN *pin =
  194. &PlsrHwOutputPins[state->directionPoint];
  195. if (pin->port != NULL)
  196. {
  197. HAL_GPIO_WritePin(pin->port, pin->pin,
  198. (positive != 0U) ? GPIO_PIN_SET : GPIO_PIN_RESET);
  199. }
  200. }
  201. #endif
  202. }
  203. /* ---- PWM 启停 ---- */
  204. static void PlsrHwStartPwmTimer(uint8_t axis, uint32_t frequencyHz)
  205. {
  206. uint16_t psc;
  207. uint16_t arr;
  208. if (PlsrCalculateTimerDivider(PlsrHwAxisMap[axis].timerClockHz,
  209. frequencyHz,
  210. &psc,
  211. &arr) != PLSR_RESULT_OK)
  212. {
  213. return;
  214. }
  215. PlsrHwTimerSetPsc(axis, psc);
  216. PlsrHwTimerSetArr(axis, arr);
  217. PlsrHwTimerSetCcr(axis, (uint32_t)arr / 2UL); /* 50% 占空比 */
  218. PlsrHwTimerSetUie(axis, 1UL);
  219. PlsrHwTimerSetCc1e(axis, 1UL);
  220. PlsrHwTimerSetCen(axis, 1UL);
  221. }
  222. static void PlsrHwStopPwmTimer(uint8_t axis)
  223. {
  224. PlsrHwTimerSetCc1e(axis, 0UL);
  225. PlsrHwTimerSetUie(axis, 0UL);
  226. PlsrHwTimerSetCen(axis, 0UL);
  227. }
  228. uint8_t PlsrHwResolveDirectionPoint(uint8_t pointNumber)
  229. {
  230. /* 与资源层一致的合法输出点掩码(Q0~Q7、Q10~Q17、Q20)。 */
  231. const uint32_t validOutputMask = 0x0013FCFFUL;
  232. if (pointNumber >= PLSR_HW_OUTPUT_POINT_COUNT)
  233. {
  234. return 0U;
  235. }
  236. if ((validOutputMask & (1UL << pointNumber)) == 0UL)
  237. {
  238. return 0U;
  239. }
  240. #ifndef PLSR_HOST_TEST
  241. if (PlsrHwOutputPins[pointNumber].port == NULL)
  242. {
  243. return 0U;
  244. }
  245. #endif
  246. return 1U;
  247. }
  248. PLSR_RESULT PlsrHwInit(void)
  249. {
  250. uint8_t axis;
  251. (void)memset(PlsrHwAxes, 0, sizeof(PlsrHwAxes));
  252. for (axis = 0U; axis < PLSR_HW_AXIS_COUNT; axis++)
  253. {
  254. PlsrHwAxes[axis].state = PLSR_HW_STATE_IDLE;
  255. PlsrHwAxes[axis].directionPoint = PLSR_HW_DIR_POINT_NONE;
  256. #ifdef PLSR_HOST_TEST
  257. (void)memset(&PlsrHwTimers[axis], 0, sizeof(PlsrHwTimers[axis]));
  258. #else
  259. PlsrHwTimerSetCc1e(axis, 0UL);
  260. PlsrHwTimerSetUie(axis, 0UL);
  261. PlsrHwTimerSetCen(axis, 0UL);
  262. #endif
  263. }
  264. #ifndef PLSR_HOST_TEST
  265. {
  266. GPIO_InitTypeDef gpio;
  267. uint8_t point;
  268. /* 1. 输出点 GPIO 时钟。 */
  269. __HAL_RCC_GPIOF_CLK_ENABLE();
  270. __HAL_RCC_GPIOI_CLK_ENABLE();
  271. __HAL_RCC_GPIOE_CLK_ENABLE();
  272. __HAL_RCC_GPIOG_CLK_ENABLE();
  273. __HAL_RCC_GPIOH_CLK_ENABLE();
  274. __HAL_RCC_GPIOB_CLK_ENABLE();
  275. /* 2. 全部输出点上电安全电平(推挽输出、低)。 */
  276. gpio.Mode = GPIO_MODE_OUTPUT_PP;
  277. gpio.Pull = GPIO_NOPULL;
  278. gpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  279. for (point = 0U; point < PLSR_HW_OUTPUT_POINT_COUNT; point++)
  280. {
  281. if (PlsrHwOutputPins[point].port != NULL)
  282. {
  283. gpio.Pin = PlsrHwOutputPins[point].pin;
  284. HAL_GPIO_WritePin(PlsrHwOutputPins[point].port,
  285. PlsrHwOutputPins[point].pin,
  286. GPIO_PIN_RESET);
  287. HAL_GPIO_Init(PlsrHwOutputPins[point].port,
  288. &gpio);
  289. }
  290. }
  291. /* 3. 定时器时钟。 */
  292. __HAL_RCC_TIM10_CLK_ENABLE();
  293. __HAL_RCC_TIM11_CLK_ENABLE();
  294. __HAL_RCC_TIM13_CLK_ENABLE();
  295. __HAL_RCC_TIM14_CLK_ENABLE();
  296. /* 4. 脉冲点切定时器复用(PF6/7=AF3、PF8/9=AF9)。
  297. * 定时器通道尚未使能(CC1E=0),输出为无效电平(低),无毛刺。 */
  298. gpio.Mode = GPIO_MODE_AF_PP;
  299. gpio.Pin = GPIO_PIN_6 | GPIO_PIN_7;
  300. gpio.Alternate = 3U;
  301. HAL_GPIO_Init(GPIOF, &gpio);
  302. gpio.Pin = GPIO_PIN_8 | GPIO_PIN_9;
  303. gpio.Alternate = 9U;
  304. HAL_GPIO_Init(GPIOF, &gpio);
  305. /* 5. 更新中断 NVIC:高速计数/尾脉冲层(P3b 统一规划优先级表)。 */
  306. HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 1U, 0U);
  307. HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
  308. HAL_NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 1U, 0U);
  309. HAL_NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn);
  310. HAL_NVIC_SetPriority(TIM1_TRG_COM_TIM11_IRQn, 1U, 0U);
  311. HAL_NVIC_EnableIRQ(TIM1_TRG_COM_TIM11_IRQn);
  312. HAL_NVIC_SetPriority(TIM8_TRG_COM_TIM14_IRQn, 1U, 0U);
  313. HAL_NVIC_EnableIRQ(TIM8_TRG_COM_TIM14_IRQn);
  314. }
  315. #endif
  316. return PLSR_RESULT_OK;
  317. }
  318. PLSR_RESULT PlsrHwStartPulse(uint8_t axis, const PLSR_HW_START_PARAMS *params)
  319. {
  320. PLSR_HW_AXIS_STATE *state;
  321. if ((axis >= PLSR_HW_AXIS_COUNT) || (params == NULL))
  322. {
  323. return PLSR_RESULT_INVALID_ARGUMENT;
  324. }
  325. if (params->targetPulses <= 0)
  326. {
  327. return PLSR_RESULT_INVALID_ARGUMENT;
  328. }
  329. state = &PlsrHwAxes[axis];
  330. if (state->state == PLSR_HW_STATE_RUNNING)
  331. {
  332. return PLSR_RESULT_BUSY;
  333. }
  334. state->targetPulses = params->targetPulses;
  335. state->emittedPulses = 0;
  336. state->currentFrequencyHz = params->frequencyHz;
  337. state->directionPoint = params->directionPoint;
  338. state->directionDelayRemainingMs = params->directionDelayMs;
  339. PlsrHwSetDirLevel(axis, params->directionPositive);
  340. state->state = (params->directionDelayMs > 0U)
  341. ? PLSR_HW_STATE_DIR_SETTLING
  342. : PLSR_HW_STATE_PWM_PENDING;
  343. return PLSR_RESULT_OK;
  344. }
  345. PLSR_RESULT PlsrHwSetFrequency(uint8_t axis, uint32_t frequencyHz)
  346. {
  347. PLSR_HW_AXIS_STATE *state;
  348. if (axis >= PLSR_HW_AXIS_COUNT)
  349. {
  350. return PLSR_RESULT_INVALID_ARGUMENT;
  351. }
  352. state = &PlsrHwAxes[axis];
  353. state->currentFrequencyHz = frequencyHz;
  354. if (state->state == PLSR_HW_STATE_RUNNING)
  355. {
  356. if (frequencyHz > 0UL)
  357. {
  358. PlsrHwStartPwmTimer(axis, frequencyHz);
  359. }
  360. else
  361. {
  362. PlsrHwStopPwmTimer(axis);
  363. }
  364. }
  365. else if ((state->state == PLSR_HW_STATE_PWM_PENDING)
  366. && (frequencyHz > 0UL))
  367. {
  368. PlsrHwStartPwmTimer(axis, frequencyHz);
  369. state->state = PLSR_HW_STATE_RUNNING;
  370. }
  371. return PLSR_RESULT_OK;
  372. }
  373. PLSR_RESULT PlsrHwStopPulse(uint8_t axis)
  374. {
  375. PLSR_HW_AXIS_STATE *state;
  376. if (axis >= PLSR_HW_AXIS_COUNT)
  377. {
  378. return PLSR_RESULT_INVALID_ARGUMENT;
  379. }
  380. state = &PlsrHwAxes[axis];
  381. if (state->state != PLSR_HW_STATE_IDLE)
  382. {
  383. PlsrHwStopPwmTimer(axis);
  384. state->state = PLSR_HW_STATE_IDLE;
  385. }
  386. return PLSR_RESULT_OK;
  387. }
  388. uint8_t PlsrHwIsPulseActive(uint8_t axis)
  389. {
  390. if (axis >= PLSR_HW_AXIS_COUNT)
  391. {
  392. return 0U;
  393. }
  394. return (PlsrHwAxes[axis].state == PLSR_HW_STATE_RUNNING) ? 1U : 0U;
  395. }
  396. PLSR_HW_STATE PlsrHwGetState(uint8_t axis)
  397. {
  398. if (axis >= PLSR_HW_AXIS_COUNT)
  399. {
  400. return PLSR_HW_STATE_IDLE;
  401. }
  402. return PlsrHwAxes[axis].state;
  403. }
  404. uint32_t PlsrHwGetTimerClockHz(uint8_t axis)
  405. {
  406. if (axis >= PLSR_HW_AXIS_COUNT)
  407. {
  408. return 0UL;
  409. }
  410. return PlsrHwAxisMap[axis].timerClockHz;
  411. }
  412. void PlsrHwTick(uint8_t axis)
  413. {
  414. PLSR_HW_AXIS_STATE *state;
  415. if (axis >= PLSR_HW_AXIS_COUNT)
  416. {
  417. return;
  418. }
  419. state = &PlsrHwAxes[axis];
  420. switch (state->state)
  421. {
  422. case PLSR_HW_STATE_DIR_SETTLING:
  423. if (state->directionDelayRemainingMs > 0U)
  424. {
  425. state->directionDelayRemainingMs--;
  426. }
  427. if (state->directionDelayRemainingMs == 0U)
  428. {
  429. state->state = PLSR_HW_STATE_PWM_PENDING;
  430. }
  431. break;
  432. case PLSR_HW_STATE_PWM_PENDING:
  433. if (state->currentFrequencyHz > 0UL)
  434. {
  435. PlsrHwStartPwmTimer(axis, state->currentFrequencyHz);
  436. state->state = PLSR_HW_STATE_RUNNING;
  437. }
  438. break;
  439. default:
  440. break;
  441. }
  442. }
  443. /* 输出定时器更新中断:每周期末触发一次(=1 个脉冲)。 */
  444. void PlsrHwOnTimerUpdate(uint8_t axis)
  445. {
  446. PLSR_HW_AXIS_STATE *state;
  447. if (axis >= PLSR_HW_AXIS_COUNT)
  448. {
  449. return;
  450. }
  451. state = &PlsrHwAxes[axis];
  452. PlsrHwTimerClearUif(axis);
  453. if (state->state != PLSR_HW_STATE_RUNNING)
  454. {
  455. return;
  456. }
  457. state->emittedPulses++;
  458. if (state->emittedPulses >= state->targetPulses)
  459. {
  460. /* 更新时刻 = 周期结束:关通道即完整下降沿后停止,无额外脉冲。 */
  461. PlsrHwStopPwmTimer(axis);
  462. state->state = PLSR_HW_STATE_DONE;
  463. (void)PlsrPostEvent(axis, PLSR_EVENT_SEGMENT_COMPLETE);
  464. }
  465. }
  466. #ifdef PLSR_HOST_TEST
  467. uint32_t PlsrHwTestGetArr(uint8_t axis)
  468. {
  469. return PlsrHwTimers[axis].arr;
  470. }
  471. uint32_t PlsrHwTestGetCcr(uint8_t axis)
  472. {
  473. return PlsrHwTimers[axis].ccr1;
  474. }
  475. uint32_t PlsrHwTestGetPsc(uint8_t axis)
  476. {
  477. return PlsrHwTimers[axis].psc;
  478. }
  479. uint8_t PlsrHwTestGetPwmEnabled(uint8_t axis)
  480. {
  481. return ((PlsrHwTimers[axis].ccer & PLSR_HW_TIMER_CHANNEL1_BIT) != 0UL)
  482. ? 1U
  483. : 0U;
  484. }
  485. uint8_t PlsrHwTestGetDirLevel(uint8_t axis)
  486. {
  487. return PlsrHwTimers[axis].dirLevel;
  488. }
  489. void PlsrHwTestTriggerUpdate(uint8_t axis)
  490. {
  491. PlsrHwOnTimerUpdate(axis);
  492. }
  493. #endif
  494. #ifndef PLSR_HOST_TEST
  495. void TIM1_UP_TIM10_IRQHandler(void)
  496. {
  497. PlsrHwOnTimerUpdate(0U);
  498. }
  499. void TIM8_UP_TIM13_IRQHandler(void)
  500. {
  501. PlsrHwOnTimerUpdate(1U);
  502. }
  503. void TIM1_TRG_COM_TIM11_IRQHandler(void)
  504. {
  505. PlsrHwOnTimerUpdate(2U);
  506. }
  507. void TIM8_TRG_COM_TIM14_IRQHandler(void)
  508. {
  509. PlsrHwOnTimerUpdate(3U);
  510. }
  511. #endif