You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

738 lines
25 KiB

  1. #include "plc_device.h"
  2. #include "plsr_core.h"
  3. #include "plsr_hal_f407.h"
  4. #include "plsr_job.h"
  5. #include "plsr_persistence.h"
  6. #include "plsr_self_test.h"
  7. #include <stdio.h>
  8. #include <string.h>
  9. #define TEST_WORD_CAPACITY (3000U)
  10. #define TEST_S0_BASE (100U)
  11. #define TEST_S1_BASE (200U)
  12. typedef struct
  13. {
  14. uint16_t words[3][TEST_WORD_CAPACITY];
  15. } TEST_MEMORY;
  16. static int TestFailures;
  17. static int TestChecks;
  18. #define CHECK(condition) \
  19. do \
  20. { \
  21. TestChecks++; \
  22. if (!(condition)) \
  23. { \
  24. TestFailures++; \
  25. (void)printf("FAIL line %d: %s\n", __LINE__, #condition); \
  26. } \
  27. } while (0)
  28. static uint8_t TestValidateWords(void *context,
  29. PLSR_DEVICE_TYPE device,
  30. uint32_t firstAddress,
  31. uint32_t wordCount)
  32. {
  33. (void)context;
  34. (void)device;
  35. return (((uint64_t)firstAddress + wordCount) <= TEST_WORD_CAPACITY)
  36. ? 1U
  37. : 0U;
  38. }
  39. static uint8_t TestReadWord(void *context,
  40. PLSR_DEVICE_TYPE device,
  41. uint32_t address,
  42. uint16_t *value)
  43. {
  44. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  45. if ((memory == NULL) || (value == NULL) || (device > PLSR_DEVICE_FD)
  46. || (address >= TEST_WORD_CAPACITY))
  47. {
  48. return 0U;
  49. }
  50. *value = memory->words[device][address];
  51. return 1U;
  52. }
  53. static uint8_t TestReadBit(void *context,
  54. PLSR_DEVICE_TYPE device,
  55. uint32_t address,
  56. uint8_t *value)
  57. {
  58. (void)context;
  59. (void)device;
  60. (void)address;
  61. *value = 0U;
  62. return 1U;
  63. }
  64. static void TestWriteDword(TEST_MEMORY *memory,
  65. PLSR_DEVICE_TYPE device,
  66. uint32_t address,
  67. int32_t value)
  68. {
  69. uint32_t raw = (uint32_t)value;
  70. memory->words[device][address] = (uint16_t)(raw & 0xFFFFUL);
  71. memory->words[device][address + 1UL] = (uint16_t)(raw >> 16U);
  72. }
  73. static void TestSetSegment(TEST_MEMORY *memory,
  74. uint16_t number,
  75. uint32_t frequency,
  76. int32_t pulses)
  77. {
  78. uint32_t base = TEST_S0_BASE + (uint32_t)number * 10UL;
  79. TestWriteDword(memory, PLSR_DEVICE_D, base, (int32_t)frequency);
  80. TestWriteDword(memory, PLSR_DEVICE_D, base + 2UL, pulses);
  81. memory->words[PLSR_DEVICE_D][base + 4UL] = 0U;
  82. TestWriteDword(memory, PLSR_DEVICE_D, base + 5UL, 0);
  83. memory->words[PLSR_DEVICE_D][base + 7UL] = 0U;
  84. TestWriteDword(memory, PLSR_DEVICE_D, base + 8UL, 0);
  85. }
  86. static void TestResetEnvironment(void)
  87. {
  88. PlsrPersistenceTestResetStorage();
  89. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  90. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  91. CHECK(PlsrInit() == PLSR_RESULT_OK);
  92. }
  93. static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
  94. {
  95. PLSR_CALL call;
  96. (void)memset(&call, 0, sizeof(call));
  97. call.sequence = 10UL;
  98. call.source.context = memory;
  99. call.source.validateWords = TestValidateWords;
  100. call.source.readWord = TestReadWord;
  101. call.source.readBit = TestReadBit;
  102. call.s0.device = PLSR_DEVICE_D;
  103. call.s0.address = TEST_S0_BASE;
  104. call.s1.device = PLSR_DEVICE_D;
  105. call.s1.address = TEST_S1_BASE;
  106. call.s2.type = PLSR_OPERAND_CONSTANT;
  107. call.s2.constant = 1;
  108. call.dAxis = 0U;
  109. call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
  110. return call;
  111. }
  112. static PLSR_STATUS TestGetStatus(void)
  113. {
  114. PLSR_STATUS status;
  115. (void)memset(&status, 0, sizeof(status));
  116. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  117. return status;
  118. }
  119. /* ---- HAL 单测 ---- */
  120. static void TestMapping(void)
  121. {
  122. (void)PlsrHwInit();
  123. CHECK(PlsrHwGetTimerClockHz(0U) == 168000000UL);
  124. CHECK(PlsrHwGetTimerClockHz(1U) == 84000000UL);
  125. CHECK(PlsrHwGetTimerClockHz(2U) == 168000000UL);
  126. CHECK(PlsrHwGetTimerClockHz(3U) == 84000000UL);
  127. CHECK(PlsrHwGetTimerClockHz(4U) == 0UL);
  128. CHECK(PlsrHwResolveDirectionPoint(4U) != 0U);
  129. CHECK(PlsrHwResolveDirectionPoint(8U) == 0U);
  130. CHECK(PlsrHwResolveDirectionPoint(20U) != 0U);
  131. CHECK(PlsrHwResolveDirectionPoint(21U) == 0U);
  132. }
  133. static void TestDirDelaySequence(void)
  134. {
  135. (void)PlsrHwInit();
  136. PLSR_HW_START_PARAMS params;
  137. uint16_t psc;
  138. uint16_t arr;
  139. int ticks;
  140. (void)memset(&params, 0, sizeof(params));
  141. params.frequencyHz = 1000UL;
  142. params.targetPulses = 100;
  143. params.directionPoint = 4U;
  144. params.directionPositive = 1U;
  145. params.directionDelayMs = 10U;
  146. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  147. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  148. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  149. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  150. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  151. for (ticks = 0; ticks < 9; ticks++)
  152. {
  153. PlsrHwTick(0U);
  154. }
  155. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  156. PlsrHwTick(0U);
  157. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  158. /* 首个非零频率启动 PWM,ARR/CCR 与分频计算一致。 */
  159. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  160. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  161. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  162. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  163. CHECK(PlsrCalculateTimerDivider(168000000UL, 1000UL, &psc, &arr)
  164. == PLSR_RESULT_OK);
  165. CHECK(PlsrHwTestGetArr(0U) == arr);
  166. CHECK(PlsrHwTestGetPsc(0U) == psc);
  167. CHECK(PlsrHwTestGetCcr(0U) == arr / 2UL);
  168. /* PWM 模式 1(OC1M=110):复位后 CCMR1=0 冻结,无此配置输出恒定电平。 */
  169. CHECK((PlsrHwTestGetCcmr1(0U) & 0x70UL) == 0x60UL);
  170. /* ARR/CCR 预装载(ARPE=CR1 bit7,OC1PE=CCMR1 bit3):
  171. * 运行中调频不产生提前回绕,否则加速段多出 ~ln(f1/f0) 个假脉冲。 */
  172. CHECK((PlsrHwTestGetCr1(0U) & 0x80UL) == 0x80UL);
  173. CHECK((PlsrHwTestGetCcmr1(0U) & 0x08UL) == 0x08UL);
  174. /* 段间同向衔接:方向不变时跳过方向延时,直接进入 PWM 待启动。 */
  175. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  176. params.targetPulses = 50;
  177. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  178. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  179. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  180. /* 反向时方向延时仍生效。 */
  181. params.directionPositive = 0U;
  182. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  183. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  184. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  185. }
  186. static void TestZeroFrequencyWaits(void)
  187. {
  188. (void)PlsrHwInit();
  189. PLSR_HW_START_PARAMS params;
  190. (void)memset(&params, 0, sizeof(params));
  191. params.frequencyHz = 0UL;
  192. params.targetPulses = 50;
  193. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  194. params.directionPositive = 1U;
  195. params.directionDelayMs = 0U;
  196. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  197. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  198. PlsrHwTick(0U);
  199. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  200. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  201. /* 起始速度为 0:profile 升频后首个非零频率才启动 PWM。 */
  202. CHECK(PlsrHwSetFrequency(0U, 10UL) == PLSR_RESULT_OK);
  203. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  204. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  205. }
  206. static void TestPulseCounting(void)
  207. {
  208. (void)PlsrHwInit();
  209. PLSR_HW_START_PARAMS params;
  210. int pulse;
  211. (void)memset(&params, 0, sizeof(params));
  212. params.frequencyHz = 1000UL;
  213. params.targetPulses = 5;
  214. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  215. params.directionPositive = 1U;
  216. params.directionDelayMs = 0U;
  217. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  218. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  219. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  220. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  221. /* EGR.UG 只加载预装载寄存器,不能被当作物理脉冲。
  222. * 共享 IRQ 入口在对应定时器没有 UIF 时也必须无动作。 */
  223. PlsrHwOnTimerUpdate(0U);
  224. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  225. for (pulse = 0; pulse < 4; pulse++)
  226. {
  227. PlsrHwTestTriggerUpdate(0U);
  228. CHECK(PlsrHwGetEmittedPulses(0U) == pulse + 1);
  229. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  230. }
  231. /* 第 5 个脉冲:到目标,停止 + 段完成事件。 */
  232. PlsrHwTestTriggerUpdate(0U);
  233. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  234. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  235. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  236. /* 停止后再触发更新中断无动作。 */
  237. PlsrHwTestTriggerUpdate(0U);
  238. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  239. }
  240. static void TestAbPhaseAndCounting(void)
  241. {
  242. PLSR_HW_START_PARAMS params;
  243. static const uint8_t positiveA[4] = {1U, 1U, 0U, 0U};
  244. static const uint8_t positiveB[4] = {0U, 1U, 1U, 0U};
  245. static const uint8_t negativeA[4] = {0U, 1U, 1U, 0U};
  246. static const uint8_t negativeB[4] = {1U, 1U, 0U, 0U};
  247. uint32_t oldArr;
  248. uint32_t oldBasePsc;
  249. uint32_t oldPairPsc;
  250. uint32_t newPeriod;
  251. int quarter;
  252. (void)PlsrHwInit();
  253. (void)memset(&params, 0, sizeof(params));
  254. params.frequencyHz = 1000UL;
  255. params.targetPulses = 4;
  256. params.outputMode = PLSR_OUTPUT_AB;
  257. params.directionPoint = 4U; /* AB 模式必须忽略独立 DIR 点。 */
  258. params.directionPositive = 1U;
  259. params.directionDelayMs = 10U; /* AB 模式不得执行方向延时。 */
  260. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  261. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  262. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  263. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  264. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  265. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  266. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  267. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  268. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  269. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  270. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  271. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  272. CHECK(PlsrHwTestGetCcr(0U) == PlsrHwTestGetCcr(1U));
  273. CHECK(PlsrHwTestGetCcr(0U)
  274. == (PlsrHwTestGetArr(0U) + 1UL) / 2UL);
  275. /* 两相从精确 00 边界起步;CC1IF 会在开中断前再次清除。 */
  276. CHECK(PlsrHwTestGetCnt(0U)
  277. == ((PlsrHwTestGetArr(0U) + 1UL) * 3UL) / 4UL);
  278. CHECK(PlsrHwTestGetCnt(1U) == PlsrHwTestGetCcr(1U));
  279. /* 任一物理 timer update 不能直接计作完整 AB 周期。 */
  280. PlsrHwTestTriggerUpdate(0U);
  281. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  282. /* 正向:00→10→11→01→00;四次相位跳变只计一个脉冲。 */
  283. for (quarter = 0; quarter < 4; quarter++)
  284. {
  285. PlsrHwTestAdvanceAbQuarter(0U);
  286. CHECK(PlsrHwTestGetAbPhaseA(0U) == positiveA[quarter]);
  287. CHECK(PlsrHwTestGetAbPhaseB(0U) == positiveB[quarter]);
  288. }
  289. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  290. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  291. /* 运行中调频先排队,不能让相差 1/4 周期的两路各自加载 ARR。 */
  292. oldArr = PlsrHwTestGetArr(0U);
  293. oldBasePsc = PlsrHwTestGetPsc(0U);
  294. oldPairPsc = PlsrHwTestGetPsc(1U);
  295. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  296. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  297. for (quarter = 0; quarter < 4; quarter++)
  298. {
  299. PlsrHwTestAdvanceAbQuarter(0U);
  300. }
  301. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  302. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  303. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  304. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  305. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  306. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  307. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  308. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  309. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  310. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  311. for (quarter = 0; quarter < 3; quarter++)
  312. {
  313. PlsrHwTestAdvanceAbQuarter(0U);
  314. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  315. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  316. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  317. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  318. }
  319. /* 回到 00 后,两路同时装载新频率并从精确 90° 位置重启。 */
  320. PlsrHwTestAdvanceAbQuarter(0U);
  321. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  322. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  323. CHECK((PlsrHwTestGetArr(0U) != oldArr)
  324. || (PlsrHwTestGetPsc(0U) != oldBasePsc));
  325. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  326. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  327. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  328. newPeriod = PlsrHwTestGetArr(0U) + 1UL;
  329. CHECK(PlsrHwTestGetCnt(0U) == (newPeriod * 3UL) / 4UL);
  330. CHECK(PlsrHwTestGetCnt(1U) == newPeriod / 2UL);
  331. for (quarter = 0; quarter < 4; quarter++)
  332. {
  333. PlsrHwTestAdvanceAbQuarter(0U);
  334. }
  335. CHECK(PlsrHwGetEmittedPulses(0U) == 4);
  336. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  337. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  338. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  339. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  340. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  341. /* 反向:00→01→11→10→00。 */
  342. params.targetPulses = 1;
  343. params.directionPositive = 0U;
  344. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  345. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  346. for (quarter = 0; quarter < 4; quarter++)
  347. {
  348. PlsrHwTestAdvanceAbQuarter(0U);
  349. CHECK(PlsrHwTestGetAbPhaseA(0U) == negativeA[quarter]);
  350. CHECK(PlsrHwTestGetAbPhaseB(0U) == negativeB[quarter]);
  351. }
  352. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  353. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  354. /* 紧急停止即使发生在周期中间,也必须回到安全 00。 */
  355. params.targetPulses = 10;
  356. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  357. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  358. PlsrHwTestAdvanceAbQuarter(0U);
  359. CHECK(PlsrHwTestGetAbQuarter(0U) == 1U);
  360. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  361. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  362. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  363. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  364. }
  365. static void TestTwoAbAxesIndependent(void)
  366. {
  367. PLSR_HW_START_PARAMS params;
  368. int quarter;
  369. (void)PlsrHwInit();
  370. (void)memset(&params, 0, sizeof(params));
  371. params.frequencyHz = 1000UL;
  372. params.targetPulses = 1;
  373. params.outputMode = PLSR_OUTPUT_AB;
  374. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  375. params.directionPositive = 1U;
  376. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  377. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  378. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  379. CHECK(PlsrHwSetFrequency(2U, 2000UL) == PLSR_RESULT_OK);
  380. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  381. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  382. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  383. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  384. for (quarter = 0; quarter < 4; quarter++)
  385. {
  386. PlsrHwTestAdvanceAbQuarter(0U);
  387. }
  388. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  389. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
  390. CHECK(PlsrHwGetEmittedPulses(2U) == 0);
  391. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  392. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  393. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  394. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  395. for (quarter = 0; quarter < 4; quarter++)
  396. {
  397. PlsrHwTestAdvanceAbQuarter(2U);
  398. }
  399. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
  400. CHECK(PlsrHwGetEmittedPulses(2U) == 1);
  401. }
  402. static void TestAbFrequencyLimits(void)
  403. {
  404. PLSR_HW_START_PARAMS params;
  405. int quarter;
  406. (void)PlsrHwInit();
  407. (void)memset(&params, 0, sizeof(params));
  408. params.frequencyHz = 1UL;
  409. params.targetPulses = 100;
  410. params.outputMode = PLSR_OUTPUT_AB;
  411. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  412. params.directionPositive = 1U;
  413. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  414. CHECK(PlsrHwSetFrequency(0U, 1UL) == PLSR_RESULT_OK);
  415. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  416. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  417. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  418. CHECK(PlsrHwTestGetArr(0U) <= 65535UL);
  419. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  420. for (quarter = 0; quarter < 4; quarter++)
  421. {
  422. PlsrHwTestAdvanceAbQuarter(0U);
  423. }
  424. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  425. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  426. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  427. CHECK(PlsrHwTestGetArr(0U) >= 3UL);
  428. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  429. }
  430. static void TestStopAndInvalidArgs(void)
  431. {
  432. (void)PlsrHwInit();
  433. PLSR_HW_START_PARAMS params;
  434. (void)memset(&params, 0, sizeof(params));
  435. params.frequencyHz = 1000UL;
  436. params.targetPulses = 100;
  437. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  438. params.directionPositive = 1U;
  439. params.directionDelayMs = 0U;
  440. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  441. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  442. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  443. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  444. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  445. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  446. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  447. CHECK(PlsrHwStartPulse(4U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  448. CHECK(PlsrHwStartPulse(0U, NULL) == PLSR_RESULT_INVALID_ARGUMENT);
  449. params.targetPulses = 0;
  450. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  451. params.targetPulses = 1;
  452. params.outputMode = PLSR_OUTPUT_CW_CCW;
  453. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_NOT_SUPPORTED);
  454. params.outputMode = (PLSR_OUTPUT_MODE)99;
  455. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  456. CHECK(PlsrHwSetFrequency(4U, 1000UL) == PLSR_RESULT_INVALID_ARGUMENT);
  457. CHECK(PlsrHwStopPulse(4U) == PLSR_RESULT_INVALID_ARGUMENT);
  458. }
  459. /* ---- 端到端集成:START → 硬件 → 计数 → 事件 → 段间 → 完成 ---- */
  460. static void TestEndToEndTwoSegments(void)
  461. {
  462. TEST_MEMORY memory;
  463. PLSR_CALL call;
  464. PLSR_STATUS status;
  465. uint16_t initialPsc;
  466. uint16_t initialArr;
  467. int ticks;
  468. int pulse;
  469. TestResetEnvironment();
  470. (void)memset(&memory, 0, sizeof(memory));
  471. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  472. TestSetSegment(&memory, 1U, 1000U, 100);
  473. TestSetSegment(&memory, 2U, 2000U, 200);
  474. call = TestMakeCall(&memory);
  475. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  476. PlsrProcess();
  477. status = TestGetStatus();
  478. CHECK(status.state == PLSR_STATE_ACCEL);
  479. CHECK(status.currentSegment == 1U);
  480. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  481. /* DIR 延时 10ms → PWM 启动(段1 起始速度 0,profile 升频后启动)。 */
  482. for (ticks = 0; ticks < 9; ticks++)
  483. {
  484. PlsrProcess();
  485. }
  486. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  487. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  488. CHECK(PlsrCalculateTimerDivider(168000000UL, 75UL,
  489. &initialPsc, &initialArr)
  490. == PLSR_RESULT_OK);
  491. CHECK(PlsrHwTestGetPsc(0U) == initialPsc);
  492. CHECK(PlsrHwTestGetArr(0U) == initialArr);
  493. /* 加速完成 → 状态机进入 RUN。 */
  494. for (ticks = 0; ticks < 500; ticks++)
  495. {
  496. PlsrProcess();
  497. if (TestGetStatus().state == PLSR_STATE_RUN)
  498. {
  499. break;
  500. }
  501. }
  502. status = TestGetStatus();
  503. CHECK(status.state == PLSR_STATE_RUN);
  504. CHECK(status.currentSegment == 1U);
  505. /* 段1 脉冲完成:100 次更新中断 → SEGMENT_COMPLETE → 段2 启动。 */
  506. for (pulse = 0; pulse < 100; pulse++)
  507. {
  508. PlsrHwTestTriggerUpdate(0U);
  509. }
  510. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  511. PlsrProcess();
  512. status = TestGetStatus();
  513. CHECK(status.state == PLSR_STATE_ACCEL);
  514. CHECK(status.currentSegment == 2U);
  515. /* 段2:DIR 延时 → PWM → 加速 → RUN。 */
  516. for (ticks = 0; ticks < 600; ticks++)
  517. {
  518. PlsrProcess();
  519. if (TestGetStatus().state == PLSR_STATE_RUN)
  520. {
  521. break;
  522. }
  523. }
  524. status = TestGetStatus();
  525. CHECK(status.state == PLSR_STATE_RUN);
  526. CHECK(status.currentSegment == 2U);
  527. /* 段2 脉冲完成 → 任务结束。 */
  528. for (pulse = 0; pulse < 200; pulse++)
  529. {
  530. PlsrHwTestTriggerUpdate(0U);
  531. }
  532. PlsrProcess();
  533. status = TestGetStatus();
  534. CHECK(status.state == PLSR_STATE_COMPLETED);
  535. CHECK(status.done != 0U);
  536. /* 终态转换后 HAL 回 IDLE(允许重新启动),脉冲已停止。 */
  537. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  538. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  539. }
  540. static void TestEndToEndAbSegment(void)
  541. {
  542. TEST_MEMORY memory;
  543. PLSR_CALL call;
  544. PLSR_STATUS status;
  545. int quarter;
  546. TestResetEnvironment();
  547. (void)memset(&memory, 0, sizeof(memory));
  548. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  549. TestSetSegment(&memory, 1U, 1000U, -2);
  550. call = TestMakeCall(&memory);
  551. call.sequence = 15UL;
  552. call.outputModeOverride = PLSR_OUTPUT_AB;
  553. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  554. PlsrProcess();
  555. status = TestGetStatus();
  556. CHECK(status.state == PLSR_STATE_ACCEL);
  557. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  558. CHECK(status.directionPoint == PLSR_DIRECTION_POINT_NONE);
  559. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  560. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  561. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  562. /* 负脉冲选择反向相序,完整两个周期后由同一事件链结束任务。 */
  563. PlsrHwTestAdvanceAbQuarter(0U);
  564. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  565. CHECK(PlsrHwTestGetAbPhaseB(0U) == 1U);
  566. for (quarter = 1; quarter < 8; quarter++)
  567. {
  568. PlsrHwTestAdvanceAbQuarter(0U);
  569. }
  570. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  571. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  572. PlsrProcess();
  573. status = TestGetStatus();
  574. CHECK(status.state == PLSR_STATE_COMPLETED);
  575. CHECK(status.done != 0U);
  576. CHECK(status.highResourceMask == 0U);
  577. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  578. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  579. }
  580. static void TestProductionSelfTestStartsAb(void)
  581. {
  582. PLSR_STATUS status;
  583. TestResetEnvironment();
  584. CHECK(PlsrSelfTestQueue() == PLSR_RESULT_QUEUED);
  585. PlsrProcess();
  586. status = TestGetStatus();
  587. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  588. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  589. CHECK(status.currentSegment == 1U);
  590. CHECK(status.state == PLSR_STATE_ACCEL);
  591. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  592. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  593. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  594. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  595. }
  596. static void TestStopStopsHardware(void)
  597. {
  598. TEST_MEMORY memory;
  599. PLSR_CALL call;
  600. PLSR_COMMAND command;
  601. PLSR_STATUS status;
  602. int ticks;
  603. TestResetEnvironment();
  604. (void)memset(&memory, 0, sizeof(memory));
  605. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  606. TestSetSegment(&memory, 1U, 1000U, 10000);
  607. call = TestMakeCall(&memory);
  608. call.sequence = 20UL;
  609. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  610. PlsrProcess();
  611. for (ticks = 0; ticks < 10; ticks++)
  612. {
  613. PlsrProcess();
  614. }
  615. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  616. /* STOP_IMMEDIATE:硬件立即停止。 */
  617. command.sequence = 21UL;
  618. command.axis = 0U;
  619. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  620. command.argument = 0;
  621. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  622. PlsrProcess();
  623. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  624. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  625. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  626. == PLSR_RESULT_OK);
  627. PlsrProcess();
  628. status = TestGetStatus();
  629. CHECK(status.state == PLSR_STATE_STOPPED);
  630. }
  631. int main(void)
  632. {
  633. TestMapping();
  634. TestDirDelaySequence();
  635. TestZeroFrequencyWaits();
  636. TestPulseCounting();
  637. TestAbPhaseAndCounting();
  638. TestTwoAbAxesIndependent();
  639. TestAbFrequencyLimits();
  640. TestStopAndInvalidArgs();
  641. TestEndToEndTwoSegments();
  642. TestEndToEndAbSegment();
  643. TestProductionSelfTestStartsAb();
  644. TestStopStopsHardware();
  645. if (TestFailures != 0)
  646. {
  647. (void)printf("FAIL: %d of %d PLSR HAL checks failed\n",
  648. TestFailures,
  649. TestChecks);
  650. return 1;
  651. }
  652. (void)printf("PASS: %d PLSR HAL checks\n", TestChecks);
  653. return 0;
  654. }