Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

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