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ů.
 
 
 
 
 
 

1069 řádky
35 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 TestWriteSfdDword(uint16_t address, uint32_t value)
  74. {
  75. CHECK(PlcDeviceWriteSfd(address, (uint16_t)(value & 0xFFFFUL))
  76. == PLC_DEVICE_OK);
  77. CHECK(PlcDeviceWriteSfd((uint16_t)(address + 1U),
  78. (uint16_t)(value >> 16U)) == PLC_DEVICE_OK);
  79. }
  80. static void TestSetSegment(TEST_MEMORY *memory,
  81. uint16_t number,
  82. uint32_t frequency,
  83. int32_t pulses)
  84. {
  85. uint32_t base = TEST_S0_BASE + (uint32_t)number * 10UL;
  86. TestWriteDword(memory, PLSR_DEVICE_D, base, (int32_t)frequency);
  87. TestWriteDword(memory, PLSR_DEVICE_D, base + 2UL, pulses);
  88. memory->words[PLSR_DEVICE_D][base + 4UL] = 0U;
  89. TestWriteDword(memory, PLSR_DEVICE_D, base + 5UL, 0);
  90. memory->words[PLSR_DEVICE_D][base + 7UL] = 0U;
  91. TestWriteDword(memory, PLSR_DEVICE_D, base + 8UL, 0);
  92. }
  93. static void TestResetEnvironment(void)
  94. {
  95. PlsrPersistenceTestResetStorage();
  96. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  97. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  98. CHECK(PlsrInit() == PLSR_RESULT_OK);
  99. }
  100. static void TestCompleteFirstAbPrime(uint8_t axis)
  101. {
  102. int quarter;
  103. CHECK(PlsrHwIsAbStartupPriming(axis) != 0U);
  104. for (quarter = 0; quarter < 4; quarter++)
  105. {
  106. PlsrHwTestAdvanceAbQuarter(axis);
  107. }
  108. CHECK(PlsrHwIsAbStartupPriming(axis) == 0U);
  109. CHECK(PlsrHwGetEmittedPulses(axis) == 0);
  110. CHECK(PlsrHwTestGetAbQuarter(axis) == 0U);
  111. }
  112. static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
  113. {
  114. PLSR_CALL call;
  115. (void)memset(&call, 0, sizeof(call));
  116. call.sequence = 10UL;
  117. call.source.context = memory;
  118. call.source.validateWords = TestValidateWords;
  119. call.source.readWord = TestReadWord;
  120. call.source.readBit = TestReadBit;
  121. call.s0.device = PLSR_DEVICE_D;
  122. call.s0.address = TEST_S0_BASE;
  123. call.s1.device = PLSR_DEVICE_D;
  124. call.s1.address = TEST_S1_BASE;
  125. call.s2.type = PLSR_OPERAND_CONSTANT;
  126. call.s2.constant = 1;
  127. call.dAxis = 0U;
  128. call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
  129. return call;
  130. }
  131. static PLSR_STATUS TestGetStatus(void)
  132. {
  133. PLSR_STATUS status;
  134. (void)memset(&status, 0, sizeof(status));
  135. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  136. return status;
  137. }
  138. static int32_t TestReadSdDword(uint16_t lowAddress)
  139. {
  140. int32_t lowWord = 0;
  141. int32_t highWord = 0;
  142. uint32_t rawValue;
  143. CHECK(PlcDeviceReadSd(lowAddress, &lowWord) == PLC_DEVICE_OK);
  144. CHECK(PlcDeviceReadSd((uint16_t)(lowAddress + 1U), &highWord)
  145. == PLC_DEVICE_OK);
  146. rawValue = ((uint32_t)lowWord & 0xFFFFUL)
  147. | (((uint32_t)highWord & 0xFFFFUL) << 16U);
  148. return (int32_t)rawValue;
  149. }
  150. /* ---- HAL 单测 ---- */
  151. static void TestMapping(void)
  152. {
  153. (void)PlsrHwInit();
  154. CHECK(PlsrHwGetTimerClockHz(0U) == 168000000UL);
  155. CHECK(PlsrHwGetTimerClockHz(1U) == 84000000UL);
  156. CHECK(PlsrHwGetTimerClockHz(2U) == 168000000UL);
  157. CHECK(PlsrHwGetTimerClockHz(3U) == 84000000UL);
  158. CHECK(PlsrHwGetTimerClockHz(4U) == 0UL);
  159. CHECK(PlsrHwResolveDirectionPoint(4U) != 0U);
  160. CHECK(PlsrHwResolveDirectionPoint(8U) == 0U);
  161. CHECK(PlsrHwResolveDirectionPoint(20U) != 0U);
  162. CHECK(PlsrHwResolveDirectionPoint(21U) == 0U);
  163. }
  164. static void TestDirDelaySequence(void)
  165. {
  166. (void)PlsrHwInit();
  167. PLSR_HW_START_PARAMS params;
  168. uint16_t psc;
  169. uint16_t arr;
  170. int ticks;
  171. (void)memset(&params, 0, sizeof(params));
  172. params.frequencyHz = 1000UL;
  173. params.targetPulses = 100;
  174. params.directionPoint = 4U;
  175. params.directionPositive = 1U;
  176. params.directionDelayMs = 10U;
  177. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  178. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  179. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  180. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  181. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  182. for (ticks = 0; ticks < 9; ticks++)
  183. {
  184. PlsrHwTick(0U);
  185. }
  186. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  187. PlsrHwTick(0U);
  188. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  189. /* 首个非零频率启动 PWM,ARR/CCR 与分频计算一致。 */
  190. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  191. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  192. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  193. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  194. CHECK(PlsrCalculateTimerDivider(168000000UL, 1000UL, &psc, &arr)
  195. == PLSR_RESULT_OK);
  196. CHECK(PlsrHwTestGetArr(0U) == arr);
  197. CHECK(PlsrHwTestGetPsc(0U) == psc);
  198. CHECK(PlsrHwTestGetCcr(0U) == arr / 2UL);
  199. /* PWM 模式 1(OC1M=110):复位后 CCMR1=0 冻结,无此配置输出恒定电平。 */
  200. CHECK((PlsrHwTestGetCcmr1(0U) & 0x70UL) == 0x60UL);
  201. /* ARR/CCR 预装载(ARPE=CR1 bit7,OC1PE=CCMR1 bit3):
  202. * 运行中调频不产生提前回绕,否则加速段多出 ~ln(f1/f0) 个假脉冲。 */
  203. CHECK((PlsrHwTestGetCr1(0U) & 0x80UL) == 0x80UL);
  204. CHECK((PlsrHwTestGetCcmr1(0U) & 0x08UL) == 0x08UL);
  205. /* 段间同向衔接:方向不变时跳过方向延时,直接进入 PWM 待启动。 */
  206. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  207. params.targetPulses = 50;
  208. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  209. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  210. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  211. /* 反向时方向延时仍生效。 */
  212. params.directionPositive = 0U;
  213. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  214. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  215. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  216. }
  217. static void TestZeroFrequencyWaits(void)
  218. {
  219. (void)PlsrHwInit();
  220. PLSR_HW_START_PARAMS params;
  221. (void)memset(&params, 0, sizeof(params));
  222. params.frequencyHz = 0UL;
  223. params.targetPulses = 50;
  224. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  225. params.directionPositive = 1U;
  226. params.directionDelayMs = 0U;
  227. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  228. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  229. PlsrHwTick(0U);
  230. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  231. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  232. /* 起始速度为 0:profile 升频后首个非零频率才启动 PWM。 */
  233. CHECK(PlsrHwSetFrequency(0U, 10UL) == PLSR_RESULT_OK);
  234. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  235. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  236. }
  237. static void TestPulseCounting(void)
  238. {
  239. (void)PlsrHwInit();
  240. PLSR_HW_START_PARAMS params;
  241. int pulse;
  242. (void)memset(&params, 0, sizeof(params));
  243. params.frequencyHz = 1000UL;
  244. params.targetPulses = 5;
  245. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  246. params.directionPositive = 1U;
  247. params.directionDelayMs = 0U;
  248. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  249. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  250. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  251. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  252. /* EGR.UG 只加载预装载寄存器,不能被当作物理脉冲。
  253. * 共享 IRQ 入口在对应定时器没有 UIF 时也必须无动作。 */
  254. PlsrHwOnTimerUpdate(0U);
  255. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  256. for (pulse = 0; pulse < 4; pulse++)
  257. {
  258. PlsrHwTestTriggerUpdate(0U);
  259. CHECK(PlsrHwGetEmittedPulses(0U) == pulse + 1);
  260. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  261. }
  262. /* 第 5 个脉冲:到目标,停止 + 段完成事件。 */
  263. PlsrHwTestTriggerUpdate(0U);
  264. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  265. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  266. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  267. /* 停止后再触发更新中断无动作。 */
  268. PlsrHwTestTriggerUpdate(0U);
  269. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  270. }
  271. static void TestAbPhaseAndCounting(void)
  272. {
  273. PLSR_HW_START_PARAMS params;
  274. static const uint8_t positiveA[4] = {1U, 1U, 0U, 0U};
  275. static const uint8_t positiveB[4] = {0U, 1U, 1U, 0U};
  276. static const uint8_t negativeA[4] = {0U, 1U, 1U, 0U};
  277. static const uint8_t negativeB[4] = {1U, 1U, 0U, 0U};
  278. uint32_t oldArr;
  279. uint32_t oldBasePsc;
  280. uint32_t oldPairPsc;
  281. uint32_t newPeriod;
  282. int quarter;
  283. (void)PlsrHwInit();
  284. (void)memset(&params, 0, sizeof(params));
  285. params.frequencyHz = 1000UL;
  286. params.targetPulses = 4;
  287. params.outputMode = PLSR_OUTPUT_AB;
  288. params.directionPoint = 4U; /* AB 模式必须忽略独立 DIR 点。 */
  289. params.directionPositive = 1U;
  290. params.directionDelayMs = 10U; /* AB 模式不得执行方向延时。 */
  291. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  292. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  293. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  294. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  295. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  296. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  297. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  298. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  299. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  300. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  301. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  302. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  303. CHECK(PlsrHwTestGetCcr(0U) == PlsrHwTestGetCcr(1U));
  304. CHECK(PlsrHwTestGetCcr(0U)
  305. == (PlsrHwTestGetArr(0U) + 1UL) / 2UL);
  306. /* 两相从精确 00 边界起步;CC1IF 会在开中断前再次清除。 */
  307. CHECK(PlsrHwTestGetCnt(0U)
  308. == ((PlsrHwTestGetArr(0U) + 1UL) * 3UL) / 4UL);
  309. CHECK(PlsrHwTestGetCnt(1U) == PlsrHwTestGetCcr(1U));
  310. TestCompleteFirstAbPrime(0U);
  311. /* 任一物理 timer update 不能直接计作完整 AB 周期。 */
  312. PlsrHwTestTriggerUpdate(0U);
  313. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  314. /* 正向:00→10→11→01→00;四次相位跳变只计一个脉冲。 */
  315. for (quarter = 0; quarter < 4; quarter++)
  316. {
  317. PlsrHwTestAdvanceAbQuarter(0U);
  318. CHECK(PlsrHwTestGetAbPhaseA(0U) == positiveA[quarter]);
  319. CHECK(PlsrHwTestGetAbPhaseB(0U) == positiveB[quarter]);
  320. }
  321. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  322. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  323. /* 运行中调频先排队,不能让相差 1/4 周期的两路各自加载 ARR。 */
  324. oldArr = PlsrHwTestGetArr(0U);
  325. oldBasePsc = PlsrHwTestGetPsc(0U);
  326. oldPairPsc = PlsrHwTestGetPsc(1U);
  327. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  328. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  329. for (quarter = 0; quarter < 4; quarter++)
  330. {
  331. PlsrHwTestAdvanceAbQuarter(0U);
  332. }
  333. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  334. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  335. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  336. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  337. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  338. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  339. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  340. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  341. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  342. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  343. for (quarter = 0; quarter < 3; quarter++)
  344. {
  345. PlsrHwTestAdvanceAbQuarter(0U);
  346. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  347. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  348. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  349. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  350. }
  351. /* 回到 00 后,两路同时装载新频率并从精确 90° 位置重启。 */
  352. PlsrHwTestAdvanceAbQuarter(0U);
  353. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  354. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  355. CHECK((PlsrHwTestGetArr(0U) != oldArr)
  356. || (PlsrHwTestGetPsc(0U) != oldBasePsc));
  357. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  358. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  359. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  360. newPeriod = PlsrHwTestGetArr(0U) + 1UL;
  361. CHECK(PlsrHwTestGetCnt(0U) == (newPeriod * 3UL) / 4UL);
  362. CHECK(PlsrHwTestGetCnt(1U) == newPeriod / 2UL);
  363. for (quarter = 0; quarter < 4; quarter++)
  364. {
  365. PlsrHwTestAdvanceAbQuarter(0U);
  366. }
  367. CHECK(PlsrHwGetEmittedPulses(0U) == 4);
  368. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  369. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  370. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  371. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  372. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  373. /* 反向:00→01→11→10→00。 */
  374. params.targetPulses = 1;
  375. params.directionPositive = 0U;
  376. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  377. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  378. for (quarter = 0; quarter < 4; quarter++)
  379. {
  380. PlsrHwTestAdvanceAbQuarter(0U);
  381. CHECK(PlsrHwTestGetAbPhaseA(0U) == negativeA[quarter]);
  382. CHECK(PlsrHwTestGetAbPhaseB(0U) == negativeB[quarter]);
  383. }
  384. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  385. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  386. /* 紧急停止即使发生在周期中间,也必须回到安全 00。 */
  387. params.targetPulses = 10;
  388. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  389. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  390. PlsrHwTestAdvanceAbQuarter(0U);
  391. CHECK(PlsrHwTestGetAbQuarter(0U) == 1U);
  392. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  393. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  394. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  395. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  396. }
  397. static void TestTwoAbAxesIndependent(void)
  398. {
  399. PLSR_HW_START_PARAMS params;
  400. int quarter;
  401. (void)PlsrHwInit();
  402. (void)memset(&params, 0, sizeof(params));
  403. params.frequencyHz = 1000UL;
  404. params.targetPulses = 1;
  405. params.outputMode = PLSR_OUTPUT_AB;
  406. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  407. params.directionPositive = 1U;
  408. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  409. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  410. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  411. CHECK(PlsrHwSetFrequency(2U, 2000UL) == PLSR_RESULT_OK);
  412. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  413. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  414. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  415. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  416. TestCompleteFirstAbPrime(0U);
  417. TestCompleteFirstAbPrime(2U);
  418. for (quarter = 0; quarter < 4; quarter++)
  419. {
  420. PlsrHwTestAdvanceAbQuarter(0U);
  421. }
  422. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  423. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
  424. CHECK(PlsrHwGetEmittedPulses(2U) == 0);
  425. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  426. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  427. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  428. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  429. for (quarter = 0; quarter < 4; quarter++)
  430. {
  431. PlsrHwTestAdvanceAbQuarter(2U);
  432. }
  433. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
  434. CHECK(PlsrHwGetEmittedPulses(2U) == 1);
  435. }
  436. static void TestAbFrequencyLimits(void)
  437. {
  438. PLSR_HW_START_PARAMS params;
  439. int quarter;
  440. (void)PlsrHwInit();
  441. (void)memset(&params, 0, sizeof(params));
  442. params.frequencyHz = 1UL;
  443. params.targetPulses = 100;
  444. params.outputMode = PLSR_OUTPUT_AB;
  445. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  446. params.directionPositive = 1U;
  447. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  448. CHECK(PlsrHwSetFrequency(0U, 1UL) == PLSR_RESULT_OK);
  449. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  450. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  451. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  452. CHECK(PlsrHwTestGetArr(0U) <= 65535UL);
  453. TestCompleteFirstAbPrime(0U);
  454. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  455. for (quarter = 0; quarter < 4; quarter++)
  456. {
  457. PlsrHwTestAdvanceAbQuarter(0U);
  458. }
  459. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  460. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  461. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  462. CHECK(PlsrHwTestGetArr(0U) >= 3UL);
  463. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  464. }
  465. static void TestStopAndInvalidArgs(void)
  466. {
  467. (void)PlsrHwInit();
  468. PLSR_HW_START_PARAMS params;
  469. (void)memset(&params, 0, sizeof(params));
  470. params.frequencyHz = 1000UL;
  471. params.targetPulses = 100;
  472. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  473. params.directionPositive = 1U;
  474. params.directionDelayMs = 0U;
  475. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  476. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  477. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  478. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  479. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  480. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  481. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  482. CHECK(PlsrHwStartPulse(4U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  483. CHECK(PlsrHwStartPulse(0U, NULL) == PLSR_RESULT_INVALID_ARGUMENT);
  484. params.targetPulses = 0;
  485. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  486. params.targetPulses = 1;
  487. params.outputMode = PLSR_OUTPUT_CW_CCW;
  488. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_NOT_SUPPORTED);
  489. params.outputMode = (PLSR_OUTPUT_MODE)99;
  490. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  491. CHECK(PlsrHwSetFrequency(4U, 1000UL) == PLSR_RESULT_INVALID_ARGUMENT);
  492. CHECK(PlsrHwStopPulse(4U) == PLSR_RESULT_INVALID_ARGUMENT);
  493. }
  494. /* ---- 端到端集成:START → 硬件 → 计数 → 事件 → 段间 → 完成 ---- */
  495. static void TestEndToEndTwoSegments(void)
  496. {
  497. TEST_MEMORY memory;
  498. PLSR_CALL call;
  499. PLSR_STATUS status;
  500. uint16_t initialPsc;
  501. uint16_t initialArr;
  502. int ticks;
  503. int pulse;
  504. TestResetEnvironment();
  505. (void)memset(&memory, 0, sizeof(memory));
  506. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  507. TestSetSegment(&memory, 1U, 1000U, 100);
  508. TestSetSegment(&memory, 2U, 2000U, 200);
  509. call = TestMakeCall(&memory);
  510. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  511. PlsrProcess();
  512. status = TestGetStatus();
  513. CHECK(status.state == PLSR_STATE_ACCEL);
  514. CHECK(status.currentSegment == 1U);
  515. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  516. /* DIR 延时 10ms → PWM 启动(段1 起始速度 0,profile 升频后启动)。 */
  517. for (ticks = 0; ticks < 9; ticks++)
  518. {
  519. PlsrProcess();
  520. }
  521. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  522. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  523. CHECK(PlsrCalculateTimerDivider(168000000UL, 75UL,
  524. &initialPsc, &initialArr)
  525. == PLSR_RESULT_OK);
  526. CHECK(PlsrHwTestGetPsc(0U) == initialPsc);
  527. CHECK(PlsrHwTestGetArr(0U) == initialArr);
  528. /* 加速完成 → 状态机进入 RUN。 */
  529. for (ticks = 0; ticks < 500; ticks++)
  530. {
  531. PlsrProcess();
  532. if (TestGetStatus().state == PLSR_STATE_RUN)
  533. {
  534. break;
  535. }
  536. }
  537. status = TestGetStatus();
  538. CHECK(status.state == PLSR_STATE_RUN);
  539. CHECK(status.currentSegment == 1U);
  540. /* 段1 脉冲完成:100 次更新中断 → SEGMENT_COMPLETE → 段2 启动。 */
  541. for (pulse = 0; pulse < 100; pulse++)
  542. {
  543. PlsrHwTestTriggerUpdate(0U);
  544. }
  545. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  546. PlsrProcess();
  547. status = TestGetStatus();
  548. CHECK(status.state == PLSR_STATE_ACCEL);
  549. CHECK(status.currentSegment == 2U);
  550. CHECK(status.logicalPosition == 100);
  551. CHECK(status.taskPulses == 100);
  552. CHECK(status.totalPulses == 100);
  553. CHECK(TestReadSdDword(1000U) == 2);
  554. CHECK(TestReadSdDword(1002U) == 0);
  555. /* 段2:DIR 延时 → PWM → 加速 → RUN。 */
  556. for (ticks = 0; ticks < 600; ticks++)
  557. {
  558. PlsrProcess();
  559. if (TestGetStatus().state == PLSR_STATE_RUN)
  560. {
  561. break;
  562. }
  563. }
  564. status = TestGetStatus();
  565. CHECK(status.state == PLSR_STATE_RUN);
  566. CHECK(status.currentSegment == 2U);
  567. /* 段2 脉冲完成 → 任务结束。 */
  568. for (pulse = 0; pulse < 200; pulse++)
  569. {
  570. PlsrHwTestTriggerUpdate(0U);
  571. }
  572. PlsrProcess();
  573. status = TestGetStatus();
  574. CHECK(status.state == PLSR_STATE_COMPLETED);
  575. CHECK(status.done != 0U);
  576. CHECK(status.logicalPosition == 300);
  577. CHECK(status.taskPulses == 300);
  578. CHECK(status.totalPulses == 300);
  579. CHECK(TestReadSdDword(1000U) == 2);
  580. CHECK(TestReadSdDword(1002U) == 200);
  581. CHECK(TestReadSdDword(1004U) == 200);
  582. CHECK(TestReadSdDword(1006U) == 0);
  583. {
  584. int32_t hsdPulses;
  585. int32_t hsdEquivalent;
  586. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  587. CHECK(hsdPulses == 300);
  588. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent)
  589. == PLC_DEVICE_OK);
  590. CHECK(hsdEquivalent == 300);
  591. }
  592. /* 终态转换后 HAL 回 IDLE(允许重新启动),脉冲已停止。 */
  593. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  594. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  595. }
  596. static void TestEndToEndAbSegment(void)
  597. {
  598. TEST_MEMORY memory;
  599. PLSR_CALL call;
  600. PLSR_STATUS status;
  601. int quarter;
  602. TestResetEnvironment();
  603. (void)memset(&memory, 0, sizeof(memory));
  604. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  605. TestSetSegment(&memory, 1U, 1000U, -2);
  606. call = TestMakeCall(&memory);
  607. call.sequence = 15UL;
  608. call.outputModeOverride = PLSR_OUTPUT_AB;
  609. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  610. PlsrProcess();
  611. status = TestGetStatus();
  612. CHECK(status.state == PLSR_STATE_ACCEL);
  613. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  614. CHECK(status.directionPoint == PLSR_DIRECTION_POINT_NONE);
  615. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  616. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  617. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  618. TestCompleteFirstAbPrime(0U);
  619. /* 负脉冲选择反向相序,完整两个周期后由同一事件链结束任务。 */
  620. PlsrHwTestAdvanceAbQuarter(0U);
  621. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  622. CHECK(PlsrHwTestGetAbPhaseB(0U) == 1U);
  623. for (quarter = 1; quarter < 8; quarter++)
  624. {
  625. PlsrHwTestAdvanceAbQuarter(0U);
  626. }
  627. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  628. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  629. PlsrProcess();
  630. status = TestGetStatus();
  631. CHECK(status.state == PLSR_STATE_COMPLETED);
  632. CHECK(status.done != 0U);
  633. CHECK(status.directionPositive == 0U);
  634. CHECK(status.logicalPosition == -2);
  635. CHECK(status.taskPulses == -2);
  636. CHECK(status.totalPulses == 2);
  637. CHECK(TestReadSdDword(1002U) == -2);
  638. CHECK(TestReadSdDword(1004U) == -2);
  639. CHECK(status.highResourceMask == 0U);
  640. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  641. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  642. }
  643. static void TestPositionOnImmediateStop(void)
  644. {
  645. TEST_MEMORY memory;
  646. PLSR_CALL call;
  647. PLSR_COMMAND command;
  648. PLSR_STATUS status;
  649. int pulse;
  650. int tick;
  651. TestResetEnvironment();
  652. (void)memset(&memory, 0, sizeof(memory));
  653. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  654. TestSetSegment(&memory, 1U, 1000U, 100);
  655. call = TestMakeCall(&memory);
  656. call.sequence = 30UL;
  657. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  658. PlsrProcess();
  659. for (tick = 0; tick < 10; tick++)
  660. {
  661. PlsrProcess();
  662. }
  663. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  664. for (pulse = 0; pulse < 37; pulse++)
  665. {
  666. PlsrHwTestTriggerUpdate(0U);
  667. }
  668. PlsrProcess();
  669. status = TestGetStatus();
  670. CHECK(status.logicalPosition == 37);
  671. CHECK(status.taskPulses == 37);
  672. CHECK(status.totalPulses == 37);
  673. command.sequence = 31UL;
  674. command.axis = 0U;
  675. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  676. command.argument = 0;
  677. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  678. PlsrProcess();
  679. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  680. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  681. == PLSR_RESULT_OK);
  682. PlsrProcess();
  683. status = TestGetStatus();
  684. CHECK(status.state == PLSR_STATE_STOPPED);
  685. CHECK(status.logicalPosition == 37);
  686. CHECK(status.taskPulses == 37);
  687. CHECK(status.totalPulses == 37);
  688. CHECK(TestReadSdDword(1002U) == 37);
  689. command.sequence = 32UL;
  690. command.opcode = PLSR_CMD_CLEAR_TOTAL;
  691. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  692. PlsrProcess();
  693. status = TestGetStatus();
  694. CHECK(status.logicalPosition == 37);
  695. CHECK(status.totalPulses == 0);
  696. }
  697. static void TestAbsolutePositionAccounting(void)
  698. {
  699. TEST_MEMORY memory;
  700. PLSR_CALL call;
  701. PLSR_COMMAND command;
  702. PLSR_STATUS status;
  703. int32_t hsdPosition;
  704. int pulse;
  705. int tick;
  706. TestResetEnvironment();
  707. command.sequence = 40UL;
  708. command.axis = 0U;
  709. command.opcode = PLSR_CMD_SET_POSITION;
  710. command.argument = 100;
  711. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  712. PlsrProcess();
  713. (void)memset(&memory, 0, sizeof(memory));
  714. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  715. TestSetSegment(&memory, 1U, 1000U, 130);
  716. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 1);
  717. call = TestMakeCall(&memory);
  718. call.sequence = 41UL;
  719. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  720. PlsrProcess();
  721. for (tick = 0; tick < 10; tick++)
  722. {
  723. PlsrProcess();
  724. }
  725. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  726. for (pulse = 0; pulse < 30; pulse++)
  727. {
  728. PlsrHwTestTriggerUpdate(0U);
  729. }
  730. PlsrProcess();
  731. status = TestGetStatus();
  732. CHECK(status.state == PLSR_STATE_COMPLETED);
  733. CHECK(status.logicalPosition == 130);
  734. CHECK(status.taskPulses == 30);
  735. CHECK(status.totalPulses == 30);
  736. CHECK(status.positionValid != 0U);
  737. CHECK(PlcDeviceReadHsdDword(0U, &hsdPosition) == PLC_DEVICE_OK);
  738. CHECK(hsdPosition == 130);
  739. }
  740. static void TestEquivalentRemainderAccounting(void)
  741. {
  742. TEST_MEMORY memory;
  743. PLSR_CALL call;
  744. PLSR_STATUS status;
  745. int32_t hsdPulses;
  746. int32_t hsdEquivalent;
  747. TestResetEnvironment();
  748. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  749. TestWriteSfdDword(902U, 3UL);
  750. TestWriteSfdDword(904U, 2UL);
  751. TestWriteSfdDword(956U, 60000UL);
  752. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  753. (void)memset(&memory, 0, sizeof(memory));
  754. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  755. TestSetSegment(&memory, 1U, 1000U, 1);
  756. call = TestMakeCall(&memory);
  757. call.sequence = 30UL;
  758. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  759. /* 3脉冲/2单位:第一次1单位只输出1脉冲并保存1/2余数。 */
  760. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  761. PlsrProcess();
  762. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  763. PlsrHwTestTriggerUpdate(0U);
  764. PlsrProcess();
  765. status = TestGetStatus();
  766. CHECK(status.state == PLSR_STATE_COMPLETED);
  767. CHECK(status.logicalPosition == 1);
  768. CHECK(status.taskPulses == 1);
  769. CHECK(status.totalPulses == 1);
  770. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  771. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  772. CHECK(hsdPulses == 1);
  773. CHECK(hsdEquivalent == 0);
  774. /* 第二次1单位合并余数后输出2脉冲;两次合计精确为3脉冲/2单位。 */
  775. call.sequence = 31UL;
  776. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  777. PlsrProcess();
  778. PlsrHwTestTriggerUpdate(0U);
  779. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  780. PlsrHwTestTriggerUpdate(0U);
  781. PlsrProcess();
  782. status = TestGetStatus();
  783. CHECK(status.state == PLSR_STATE_COMPLETED);
  784. CHECK(status.logicalPosition == 3);
  785. CHECK(status.taskPulses == 2);
  786. CHECK(status.totalPulses == 3);
  787. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  788. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  789. CHECK(hsdPulses == 3);
  790. CHECK(hsdEquivalent == 2);
  791. CHECK(TestReadSdDword(1002U) == 2);
  792. CHECK(TestReadSdDword(1004U) == 1);
  793. }
  794. static void TestEquivalentCompatibleError(void)
  795. {
  796. TEST_MEMORY memory;
  797. PLSR_CALL call;
  798. PLSR_STATUS status;
  799. int32_t errorCode = -1;
  800. int32_t errorBlock = -1;
  801. TestResetEnvironment();
  802. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  803. TestWriteSfdDword(902U, 0UL);
  804. TestWriteSfdDword(904U, 2UL);
  805. TestWriteSfdDword(956U, 60000UL);
  806. (void)memset(&memory, 0, sizeof(memory));
  807. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  808. TestSetSegment(&memory, 1U, 1000U, 1);
  809. call = TestMakeCall(&memory);
  810. call.sequence = 32UL;
  811. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  812. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  813. PlsrProcess();
  814. status = TestGetStatus();
  815. CHECK(status.lastCommandResult == PLSR_RESULT_INVALID_S2);
  816. CHECK(status.state == PLSR_STATE_IDLE);
  817. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  818. CHECK(PlcDeviceReadSd(1011U, &errorBlock) == PLC_DEVICE_OK);
  819. CHECK(errorCode == 2);
  820. CHECK(errorBlock == 0);
  821. /* A valid retry clears the compatible parameter error. */
  822. TestWriteSfdDword(902U, 3UL);
  823. call.sequence = 33UL;
  824. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  825. PlsrProcess();
  826. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  827. CHECK(errorCode == 0);
  828. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  829. }
  830. static void TestProductionSelfTestStartsAb(void)
  831. {
  832. PLSR_STATUS status;
  833. TestResetEnvironment();
  834. CHECK(PlsrSelfTestQueue() == PLSR_RESULT_QUEUED);
  835. PlsrProcess();
  836. status = TestGetStatus();
  837. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  838. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  839. CHECK(status.currentSegment == 1U);
  840. CHECK(status.state == PLSR_STATE_ACCEL);
  841. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  842. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  843. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  844. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  845. }
  846. static void TestEquivalentSelfTest(void)
  847. {
  848. PLSR_STATUS status;
  849. int32_t hsdPulses;
  850. int32_t hsdEquivalent;
  851. int ticks;
  852. TestResetEnvironment();
  853. CHECK(PlsrEquivalentSelfTestQueue() == PLSR_RESULT_QUEUED);
  854. PlsrProcess();
  855. /* SFD907=10ms. Advance the simulated hardware delay before segment 1. */
  856. for (ticks = 0; ticks < 10; ticks++)
  857. {
  858. PlsrProcess();
  859. }
  860. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  861. /* 3 pulses / 2 units: 1001 units emit 1501 pulses and keep 1/2 remainder. */
  862. for (ticks = 0; ticks < 1501; ticks++)
  863. {
  864. PlsrHwTestTriggerUpdate(0U);
  865. }
  866. PlsrProcess();
  867. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  868. /* Segment 2 consumes the remainder and therefore emits 1502 pulses. */
  869. for (ticks = 0; ticks < 1502; ticks++)
  870. {
  871. PlsrHwTestTriggerUpdate(0U);
  872. }
  873. PlsrProcess();
  874. status = TestGetStatus();
  875. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  876. CHECK(status.outputMode == PLSR_OUTPUT_PULSE_DIR);
  877. CHECK(status.state == PLSR_STATE_COMPLETED);
  878. CHECK(status.currentSegment == 2U);
  879. CHECK(status.logicalPosition == 3003);
  880. CHECK(status.taskPulses == 3003);
  881. CHECK(status.totalPulses == 3003);
  882. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  883. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  884. CHECK(hsdPulses == 3003);
  885. CHECK(hsdEquivalent == 2002);
  886. CHECK(TestReadSdDword(1002U) == 1502);
  887. CHECK(TestReadSdDword(1004U) == 1001);
  888. }
  889. static void TestStopStopsHardware(void)
  890. {
  891. TEST_MEMORY memory;
  892. PLSR_CALL call;
  893. PLSR_COMMAND command;
  894. PLSR_STATUS status;
  895. int ticks;
  896. TestResetEnvironment();
  897. (void)memset(&memory, 0, sizeof(memory));
  898. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  899. TestSetSegment(&memory, 1U, 1000U, 10000);
  900. call = TestMakeCall(&memory);
  901. call.sequence = 20UL;
  902. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  903. PlsrProcess();
  904. for (ticks = 0; ticks < 10; ticks++)
  905. {
  906. PlsrProcess();
  907. }
  908. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  909. /* STOP_IMMEDIATE:硬件立即停止。 */
  910. command.sequence = 21UL;
  911. command.axis = 0U;
  912. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  913. command.argument = 0;
  914. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  915. PlsrProcess();
  916. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  917. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  918. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  919. == PLSR_RESULT_OK);
  920. PlsrProcess();
  921. status = TestGetStatus();
  922. CHECK(status.state == PLSR_STATE_STOPPED);
  923. }
  924. int main(void)
  925. {
  926. TestMapping();
  927. TestDirDelaySequence();
  928. TestZeroFrequencyWaits();
  929. TestPulseCounting();
  930. TestAbPhaseAndCounting();
  931. TestTwoAbAxesIndependent();
  932. TestAbFrequencyLimits();
  933. TestStopAndInvalidArgs();
  934. TestEndToEndTwoSegments();
  935. TestEndToEndAbSegment();
  936. TestPositionOnImmediateStop();
  937. TestAbsolutePositionAccounting();
  938. TestEquivalentRemainderAccounting();
  939. TestEquivalentCompatibleError();
  940. TestProductionSelfTestStartsAb();
  941. TestEquivalentSelfTest();
  942. TestStopStopsHardware();
  943. if (TestFailures != 0)
  944. {
  945. (void)printf("FAIL: %d of %d PLSR HAL checks failed\n",
  946. TestFailures,
  947. TestChecks);
  948. return 1;
  949. }
  950. (void)printf("PASS: %d PLSR HAL checks\n", TestChecks);
  951. return 0;
  952. }