Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 
 

517 rindas
12 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. return PLSR_RESULT_OK;
  265. }
  266. PLSR_RESULT PlsrHwStartPulse(uint8_t axis, const PLSR_HW_START_PARAMS *params)
  267. {
  268. PLSR_HW_AXIS_STATE *state;
  269. if ((axis >= PLSR_HW_AXIS_COUNT) || (params == NULL))
  270. {
  271. return PLSR_RESULT_INVALID_ARGUMENT;
  272. }
  273. if (params->targetPulses <= 0)
  274. {
  275. return PLSR_RESULT_INVALID_ARGUMENT;
  276. }
  277. state = &PlsrHwAxes[axis];
  278. if (state->state == PLSR_HW_STATE_RUNNING)
  279. {
  280. return PLSR_RESULT_BUSY;
  281. }
  282. state->targetPulses = params->targetPulses;
  283. state->emittedPulses = 0;
  284. state->currentFrequencyHz = params->frequencyHz;
  285. state->directionPoint = params->directionPoint;
  286. state->directionDelayRemainingMs = params->directionDelayMs;
  287. PlsrHwSetDirLevel(axis, params->directionPositive);
  288. state->state = (params->directionDelayMs > 0U)
  289. ? PLSR_HW_STATE_DIR_SETTLING
  290. : PLSR_HW_STATE_PWM_PENDING;
  291. return PLSR_RESULT_OK;
  292. }
  293. PLSR_RESULT PlsrHwSetFrequency(uint8_t axis, uint32_t frequencyHz)
  294. {
  295. PLSR_HW_AXIS_STATE *state;
  296. if (axis >= PLSR_HW_AXIS_COUNT)
  297. {
  298. return PLSR_RESULT_INVALID_ARGUMENT;
  299. }
  300. state = &PlsrHwAxes[axis];
  301. state->currentFrequencyHz = frequencyHz;
  302. if (state->state == PLSR_HW_STATE_RUNNING)
  303. {
  304. if (frequencyHz > 0UL)
  305. {
  306. PlsrHwStartPwmTimer(axis, frequencyHz);
  307. }
  308. else
  309. {
  310. PlsrHwStopPwmTimer(axis);
  311. }
  312. }
  313. else if ((state->state == PLSR_HW_STATE_PWM_PENDING)
  314. && (frequencyHz > 0UL))
  315. {
  316. PlsrHwStartPwmTimer(axis, frequencyHz);
  317. state->state = PLSR_HW_STATE_RUNNING;
  318. }
  319. return PLSR_RESULT_OK;
  320. }
  321. PLSR_RESULT PlsrHwStopPulse(uint8_t axis)
  322. {
  323. PLSR_HW_AXIS_STATE *state;
  324. if (axis >= PLSR_HW_AXIS_COUNT)
  325. {
  326. return PLSR_RESULT_INVALID_ARGUMENT;
  327. }
  328. state = &PlsrHwAxes[axis];
  329. if (state->state != PLSR_HW_STATE_IDLE)
  330. {
  331. PlsrHwStopPwmTimer(axis);
  332. state->state = PLSR_HW_STATE_IDLE;
  333. }
  334. return PLSR_RESULT_OK;
  335. }
  336. uint8_t PlsrHwIsPulseActive(uint8_t axis)
  337. {
  338. if (axis >= PLSR_HW_AXIS_COUNT)
  339. {
  340. return 0U;
  341. }
  342. return (PlsrHwAxes[axis].state == PLSR_HW_STATE_RUNNING) ? 1U : 0U;
  343. }
  344. PLSR_HW_STATE PlsrHwGetState(uint8_t axis)
  345. {
  346. if (axis >= PLSR_HW_AXIS_COUNT)
  347. {
  348. return PLSR_HW_STATE_IDLE;
  349. }
  350. return PlsrHwAxes[axis].state;
  351. }
  352. uint32_t PlsrHwGetTimerClockHz(uint8_t axis)
  353. {
  354. if (axis >= PLSR_HW_AXIS_COUNT)
  355. {
  356. return 0UL;
  357. }
  358. return PlsrHwAxisMap[axis].timerClockHz;
  359. }
  360. void PlsrHwTick(uint8_t axis)
  361. {
  362. PLSR_HW_AXIS_STATE *state;
  363. if (axis >= PLSR_HW_AXIS_COUNT)
  364. {
  365. return;
  366. }
  367. state = &PlsrHwAxes[axis];
  368. switch (state->state)
  369. {
  370. case PLSR_HW_STATE_DIR_SETTLING:
  371. if (state->directionDelayRemainingMs > 0U)
  372. {
  373. state->directionDelayRemainingMs--;
  374. }
  375. if (state->directionDelayRemainingMs == 0U)
  376. {
  377. state->state = PLSR_HW_STATE_PWM_PENDING;
  378. }
  379. break;
  380. case PLSR_HW_STATE_PWM_PENDING:
  381. if (state->currentFrequencyHz > 0UL)
  382. {
  383. PlsrHwStartPwmTimer(axis, state->currentFrequencyHz);
  384. state->state = PLSR_HW_STATE_RUNNING;
  385. }
  386. break;
  387. default:
  388. break;
  389. }
  390. }
  391. /* 输出定时器更新中断:每周期末触发一次(=1 个脉冲)。 */
  392. void PlsrHwOnTimerUpdate(uint8_t axis)
  393. {
  394. PLSR_HW_AXIS_STATE *state;
  395. if (axis >= PLSR_HW_AXIS_COUNT)
  396. {
  397. return;
  398. }
  399. state = &PlsrHwAxes[axis];
  400. PlsrHwTimerClearUif(axis);
  401. if (state->state != PLSR_HW_STATE_RUNNING)
  402. {
  403. return;
  404. }
  405. state->emittedPulses++;
  406. if (state->emittedPulses >= state->targetPulses)
  407. {
  408. /* 更新时刻 = 周期结束:关通道即完整下降沿后停止,无额外脉冲。 */
  409. PlsrHwStopPwmTimer(axis);
  410. state->state = PLSR_HW_STATE_DONE;
  411. (void)PlsrPostEvent(axis, PLSR_EVENT_SEGMENT_COMPLETE);
  412. }
  413. }
  414. #ifdef PLSR_HOST_TEST
  415. uint32_t PlsrHwTestGetArr(uint8_t axis)
  416. {
  417. return PlsrHwTimers[axis].arr;
  418. }
  419. uint32_t PlsrHwTestGetCcr(uint8_t axis)
  420. {
  421. return PlsrHwTimers[axis].ccr1;
  422. }
  423. uint32_t PlsrHwTestGetPsc(uint8_t axis)
  424. {
  425. return PlsrHwTimers[axis].psc;
  426. }
  427. uint8_t PlsrHwTestGetPwmEnabled(uint8_t axis)
  428. {
  429. return ((PlsrHwTimers[axis].ccer & PLSR_HW_TIMER_CHANNEL1_BIT) != 0UL)
  430. ? 1U
  431. : 0U;
  432. }
  433. uint8_t PlsrHwTestGetDirLevel(uint8_t axis)
  434. {
  435. return PlsrHwTimers[axis].dirLevel;
  436. }
  437. void PlsrHwTestTriggerUpdate(uint8_t axis)
  438. {
  439. PlsrHwOnTimerUpdate(axis);
  440. }
  441. #endif
  442. #ifndef PLSR_HOST_TEST
  443. void TIM1_UP_TIM10_IRQHandler(void)
  444. {
  445. PlsrHwOnTimerUpdate(0U);
  446. }
  447. void TIM8_UP_TIM13_IRQHandler(void)
  448. {
  449. PlsrHwOnTimerUpdate(1U);
  450. }
  451. void TIM1_TRG_COM_TIM11_IRQHandler(void)
  452. {
  453. PlsrHwOnTimerUpdate(2U);
  454. }
  455. void TIM8_TRG_COM_TIM14_IRQHandler(void)
  456. {
  457. PlsrHwOnTimerUpdate(3U);
  458. }
  459. #endif