25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

2675 satır
94 KiB

  1. #include "plc_device.h"
  2. #include "modbus_data_store.h"
  3. #include "plsr_core.h"
  4. #include "plsr_hal_f407.h"
  5. #include "plsr_job.h"
  6. #include "plsr_modbus_control.h"
  7. #include "plsr_persistence.h"
  8. #include "plsr_resource.h"
  9. #include "plsr_self_test.h"
  10. #include <stdio.h>
  11. #include <string.h>
  12. #define TEST_WORD_CAPACITY (3000U)
  13. #define TEST_BIT_CAPACITY (128U)
  14. #define TEST_S0_BASE (100U)
  15. #define TEST_S1_BASE (200U)
  16. typedef struct
  17. {
  18. uint16_t words[3][TEST_WORD_CAPACITY];
  19. uint8_t bits[3][TEST_BIT_CAPACITY];
  20. } TEST_MEMORY;
  21. static int TestFailures;
  22. static int TestChecks;
  23. #define CHECK(condition) \
  24. do \
  25. { \
  26. TestChecks++; \
  27. if (!(condition)) \
  28. { \
  29. TestFailures++; \
  30. (void)printf("FAIL line %d: %s\n", __LINE__, #condition); \
  31. } \
  32. } while (0)
  33. static uint8_t TestValidateWords(void *context,
  34. PLSR_DEVICE_TYPE device,
  35. uint32_t firstAddress,
  36. uint32_t wordCount)
  37. {
  38. (void)context;
  39. (void)device;
  40. return (((uint64_t)firstAddress + wordCount) <= TEST_WORD_CAPACITY)
  41. ? 1U
  42. : 0U;
  43. }
  44. static uint8_t TestReadWord(void *context,
  45. PLSR_DEVICE_TYPE device,
  46. uint32_t address,
  47. uint16_t *value)
  48. {
  49. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  50. if ((memory == NULL) || (value == NULL) || (device > PLSR_DEVICE_FD)
  51. || (address >= TEST_WORD_CAPACITY))
  52. {
  53. return 0U;
  54. }
  55. *value = memory->words[device][address];
  56. return 1U;
  57. }
  58. static uint8_t TestReadBit(void *context,
  59. PLSR_DEVICE_TYPE device,
  60. uint32_t address,
  61. uint8_t *value)
  62. {
  63. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  64. uint8_t index;
  65. if ((memory == NULL) || (value == NULL) || (device < PLSR_DEVICE_X)
  66. || (device > PLSR_DEVICE_HM) || (address >= TEST_BIT_CAPACITY))
  67. {
  68. return 0U;
  69. }
  70. index = (uint8_t)(device - PLSR_DEVICE_X);
  71. *value = memory->bits[index][address];
  72. return 1U;
  73. }
  74. static void TestWriteDword(TEST_MEMORY *memory,
  75. PLSR_DEVICE_TYPE device,
  76. uint32_t address,
  77. int32_t value)
  78. {
  79. uint32_t raw = (uint32_t)value;
  80. memory->words[device][address] = (uint16_t)(raw & 0xFFFFUL);
  81. memory->words[device][address + 1UL] = (uint16_t)(raw >> 16U);
  82. }
  83. static void TestWriteSfdDword(uint16_t address, uint32_t value)
  84. {
  85. CHECK(PlcDeviceWriteSfd(address, (uint16_t)(value & 0xFFFFUL))
  86. == PLC_DEVICE_OK);
  87. CHECK(PlcDeviceWriteSfd((uint16_t)(address + 1U),
  88. (uint16_t)(value >> 16U)) == PLC_DEVICE_OK);
  89. }
  90. static void TestSetSegment(TEST_MEMORY *memory,
  91. uint16_t number,
  92. uint32_t frequency,
  93. int32_t pulses)
  94. {
  95. uint32_t base = TEST_S0_BASE + (uint32_t)number * 10UL;
  96. TestWriteDword(memory, PLSR_DEVICE_D, base, (int32_t)frequency);
  97. TestWriteDword(memory, PLSR_DEVICE_D, base + 2UL, pulses);
  98. memory->words[PLSR_DEVICE_D][base + 4UL] = 0U;
  99. TestWriteDword(memory, PLSR_DEVICE_D, base + 5UL, 0);
  100. memory->words[PLSR_DEVICE_D][base + 7UL] = 0U;
  101. TestWriteDword(memory, PLSR_DEVICE_D, base + 8UL, 0);
  102. }
  103. static void TestResetEnvironment(void)
  104. {
  105. PlsrPersistenceTestResetStorage();
  106. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  107. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  108. CHECK(PlsrInit() == PLSR_RESULT_OK);
  109. }
  110. static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
  111. {
  112. PLSR_CALL call;
  113. (void)memset(&call, 0, sizeof(call));
  114. call.sequence = 10UL;
  115. call.source.context = memory;
  116. call.source.validateWords = TestValidateWords;
  117. call.source.readWord = TestReadWord;
  118. call.source.readBit = TestReadBit;
  119. call.s0.device = PLSR_DEVICE_D;
  120. call.s0.address = TEST_S0_BASE;
  121. call.s1.device = PLSR_DEVICE_D;
  122. call.s1.address = TEST_S1_BASE;
  123. call.s2.type = PLSR_OPERAND_CONSTANT;
  124. call.s2.constant = 1;
  125. call.dAxis = 0U;
  126. call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
  127. return call;
  128. }
  129. static PLSR_STATUS TestGetStatus(void)
  130. {
  131. PLSR_STATUS status;
  132. (void)memset(&status, 0, sizeof(status));
  133. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  134. return status;
  135. }
  136. static int32_t TestReadSdDword(uint16_t lowAddress)
  137. {
  138. int32_t lowWord = 0;
  139. int32_t highWord = 0;
  140. uint32_t rawValue;
  141. CHECK(PlcDeviceReadSd(lowAddress, &lowWord) == PLC_DEVICE_OK);
  142. CHECK(PlcDeviceReadSd((uint16_t)(lowAddress + 1U), &highWord)
  143. == PLC_DEVICE_OK);
  144. rawValue = ((uint32_t)lowWord & 0xFFFFUL)
  145. | (((uint32_t)highWord & 0xFFFFUL) << 16U);
  146. return (int32_t)rawValue;
  147. }
  148. /* ---- HAL 单测 ---- */
  149. static void TestMapping(void)
  150. {
  151. (void)PlsrHwInit();
  152. CHECK(PlsrHwGetTimerClockHz(0U) == 168000000UL);
  153. CHECK(PlsrHwGetTimerClockHz(1U) == 84000000UL);
  154. CHECK(PlsrHwGetTimerClockHz(2U) == 168000000UL);
  155. CHECK(PlsrHwGetTimerClockHz(3U) == 84000000UL);
  156. CHECK(PlsrHwGetTimerClockHz(4U) == 0UL);
  157. CHECK(PlsrHwResolveDirectionPoint(4U) != 0U);
  158. CHECK(PlsrHwResolveDirectionPoint(8U) == 0U);
  159. CHECK(PlsrHwResolveDirectionPoint(20U) != 0U);
  160. CHECK(PlsrHwResolveDirectionPoint(21U) == 0U);
  161. }
  162. static void TestDirDelaySequence(void)
  163. {
  164. (void)PlsrHwInit();
  165. PLSR_HW_START_PARAMS params;
  166. uint16_t psc;
  167. uint16_t arr;
  168. int ticks;
  169. (void)memset(&params, 0, sizeof(params));
  170. params.frequencyHz = 1000UL;
  171. params.targetPulses = 100;
  172. params.directionPoint = 4U;
  173. params.directionPositive = 1U;
  174. params.directionDelayMs = 10U;
  175. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  176. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  177. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  178. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  179. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  180. for (ticks = 0; ticks < 9; ticks++)
  181. {
  182. PlsrHwTick(0U);
  183. }
  184. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  185. PlsrHwTick(0U);
  186. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  187. /* 首个非零频率启动 PWM,ARR/CCR 与分频计算一致。 */
  188. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  189. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  190. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  191. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  192. CHECK(PlsrCalculateTimerDivider(168000000UL, 1000UL, &psc, &arr)
  193. == PLSR_RESULT_OK);
  194. CHECK(PlsrHwTestGetArr(0U) == arr);
  195. CHECK(PlsrHwTestGetPsc(0U) == psc);
  196. CHECK(PlsrHwTestGetCcr(0U) == arr / 2UL);
  197. /* PWM 模式 1(OC1M=110):复位后 CCMR1=0 冻结,无此配置输出恒定电平。 */
  198. CHECK((PlsrHwTestGetCcmr1(0U) & 0x70UL) == 0x60UL);
  199. /* ARR/CCR 预装载(ARPE=CR1 bit7,OC1PE=CCMR1 bit3):
  200. * 运行中调频不产生提前回绕,否则加速段多出 ~ln(f1/f0) 个假脉冲。 */
  201. CHECK((PlsrHwTestGetCr1(0U) & 0x80UL) == 0x80UL);
  202. CHECK((PlsrHwTestGetCcmr1(0U) & 0x08UL) == 0x08UL);
  203. /* 段间同向衔接:方向不变时跳过方向延时,直接进入 PWM 待启动。 */
  204. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  205. params.targetPulses = 50;
  206. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  207. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  208. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  209. /* 反向时方向延时仍生效。 */
  210. params.directionPositive = 0U;
  211. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  212. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  213. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  214. /* Bit1 negative logic reverses only the electrical DIR terminal. */
  215. params.directionNegativeLogic = 1U;
  216. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  217. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  218. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  219. params.directionPositive = 1U;
  220. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  221. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  222. }
  223. static void TestDirectionBatch(void)
  224. {
  225. PLSR_HW_START_PARAMS params;
  226. (void)PlsrHwInit();
  227. (void)memset(&params, 0, sizeof(params));
  228. params.frequencyHz = 0UL;
  229. params.targetPulses = 10;
  230. params.outputMode = PLSR_OUTPUT_PULSE_DIR;
  231. params.directionPoint = 4U;
  232. params.directionPositive = 1U;
  233. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  234. params.directionPoint = 3U;
  235. params.directionNegativeLogic = 1U;
  236. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_OK);
  237. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  238. CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
  239. PlsrHwBeginDirectionBatch();
  240. params.directionPoint = 4U;
  241. params.directionPositive = 0U;
  242. params.directionNegativeLogic = 0U;
  243. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  244. params.directionPoint = 3U;
  245. params.directionNegativeLogic = 1U;
  246. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_OK);
  247. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  248. CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
  249. PlsrHwEndDirectionBatch();
  250. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  251. CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
  252. }
  253. static void TestHardwareCounterLeases(void)
  254. {
  255. PLSR_HW_START_PARAMS params;
  256. (void)PlsrHwInit();
  257. (void)memset(&params, 0, sizeof(params));
  258. params.frequencyHz = 100000UL;
  259. params.targetPulses = 10;
  260. params.outputMode = PLSR_OUTPUT_PULSE_DIR;
  261. params.directionPoint = 4U;
  262. params.directionPositive = 1U;
  263. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  264. CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
  265. /* Replacing a prepared segment must release and reacquire the same lease
  266. * instead of orphaning TIM9 under the old preparation. */
  267. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  268. CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
  269. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  270. /* A hardware-counted PWM starts in the inactive half-cycle. TIM9/TIM12
  271. * must see a low ITR level when external-clock mode is armed, otherwise
  272. * the startup OCREF level is counted before a terminal pulse exists. */
  273. CHECK(PlsrHwTestGetCnt(0U) == PlsrHwTestGetCcr(0U));
  274. params.directionPoint = 5U;
  275. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  276. CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
  277. CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
  278. /* PWM compare and update flags coexist at the period boundary. A
  279. * software fallback axis must consume both in one ISR and count once. */
  280. PlsrHwTestTriggerUpdateAndCompare(2U);
  281. CHECK(PlsrHwGetEmittedPulses(2U) == 1);
  282. PlsrHwTestTriggerCompare(2U);
  283. CHECK(PlsrHwGetEmittedPulses(2U) == 1);
  284. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  285. CHECK(PlsrHwStopPulse(2U) == PLSR_RESULT_OK);
  286. CHECK(PlsrHwUsesHardwareCounter(0U) == 0U);
  287. params.directionPoint = 5U;
  288. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  289. CHECK(PlsrHwUsesHardwareCounter(2U) == 1U);
  290. CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
  291. while (PlsrHwGetState(2U) != PLSR_HW_STATE_DONE)
  292. {
  293. PlsrHwTestTriggerUpdate(2U);
  294. }
  295. CHECK(PlsrHwGetEmittedPulses(2U) == 10);
  296. CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
  297. }
  298. static void TestCwCcwSequence(void)
  299. {
  300. PLSR_HW_START_PARAMS params;
  301. uint16_t psc;
  302. uint16_t arr;
  303. (void)PlsrHwInit();
  304. (void)memset(&params, 0, sizeof(params));
  305. params.frequencyHz = 2000UL;
  306. params.targetPulses = 3;
  307. params.outputMode = PLSR_OUTPUT_CW_CCW;
  308. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  309. params.directionPositive = 1U;
  310. params.directionDelayMs = 10U;
  311. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  312. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  313. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  314. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  315. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  316. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  317. PlsrHwTestTriggerCompare(1U);
  318. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  319. PlsrHwTestTriggerCompare(0U);
  320. PlsrHwTestTriggerCompare(0U);
  321. PlsrHwTestTriggerCompare(0U);
  322. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  323. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  324. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  325. CHECK(PlsrHwTestGetCc1PolarityInverted(0U) == 0U);
  326. PlsrHwTestTriggerUpdate(0U);
  327. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  328. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  329. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  330. params.frequencyHz = 1000UL;
  331. params.targetPulses = 2;
  332. params.directionPositive = 0U;
  333. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  334. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  335. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  336. CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
  337. CHECK(PlsrCalculateTimerDivider(84000000UL, 1000UL, &psc, &arr)
  338. == PLSR_RESULT_OK);
  339. CHECK(PlsrHwTestGetPsc(1U) == psc);
  340. CHECK(PlsrHwTestGetArr(1U) == arr);
  341. PlsrHwTestTriggerCompare(1U);
  342. PlsrHwTestTriggerCompare(1U);
  343. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  344. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  345. CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
  346. PlsrHwTestTriggerUpdate(1U);
  347. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  348. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  349. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  350. }
  351. static void TestFastRefreshControlTick(void)
  352. {
  353. TEST_MEMORY memory;
  354. PLSR_CALL call;
  355. PLSR_STATUS status;
  356. int tick;
  357. TestResetEnvironment();
  358. (void)memset(&memory, 0, sizeof(memory));
  359. CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK);
  360. TestWriteSfdDword(902U, 1UL);
  361. TestWriteSfdDword(904U, 1UL);
  362. CHECK(PlcDeviceWriteSfd(906U, 4U) == PLC_DEVICE_OK);
  363. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  364. TestWriteSfdDword(950U, 1000UL);
  365. CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
  366. CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
  367. CHECK(PlcDeviceWriteSfd(954U, 0U) == PLC_DEVICE_OK);
  368. /* Linear curve: 10Hz/ms becomes exactly 1Hz per 0.1ms tick. */
  369. CHECK(PlcDeviceWriteSfd(955U, 0U) == PLC_DEVICE_OK);
  370. TestWriteSfdDword(956U, 100000UL);
  371. TestWriteSfdDword(958U, 0UL);
  372. TestWriteSfdDword(960U, 0UL);
  373. CHECK(PlcDeviceWriteSfd(962U, 50U) == PLC_DEVICE_OK);
  374. CHECK(PlcDeviceWriteSfd(963U, 0U) == PLC_DEVICE_OK);
  375. CHECK(PlcDeviceWriteSfd(964U, 2U) == PLC_DEVICE_OK);
  376. TestWriteSfdDword(966U, 2000UL);
  377. TestWriteSfdDword(968U, 200UL);
  378. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  379. TestSetSegment(&memory, 1U, 1000U, 10000);
  380. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 0);
  381. call = TestMakeCall(&memory);
  382. call.sequence = 0xB000UL;
  383. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  384. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  385. PlsrProcess();
  386. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  387. CHECK(status.state == PLSR_STATE_ACCEL);
  388. CHECK(status.jobValid != 0U);
  389. CHECK(PlsrTestGetJobRefreshCode(0U) == 2U);
  390. CHECK(PlsrTestGetProfileRefreshHz(0U) == 10000UL);
  391. CHECK(PlsrTestGetProfileActive(0U) != 0U);
  392. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  393. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 0UL);
  394. /* A normal 1ms process pass must not advance a 0.1ms profile. */
  395. PlsrProcess();
  396. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 0UL);
  397. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  398. CHECK(PlsrTestGetJobRefreshCode(0U) == 2U);
  399. CHECK(PlsrTestGetProfileActive(0U) != 0U);
  400. PlsrControlTick100us();
  401. CHECK(PlsrTestGetProfileFrequencyHz(0U) == 1UL);
  402. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  403. CHECK(PlsrHwGetCurrentFrequencyHz(0U) > 0UL);
  404. for (tick = 1; tick < 10; tick++)
  405. {
  406. PlsrControlTick100us();
  407. }
  408. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 10UL);
  409. PlsrProcess();
  410. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 10UL);
  411. for (tick = 0; tick < 10; tick++)
  412. {
  413. PlsrControlTick100us();
  414. }
  415. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 20UL);
  416. }
  417. static void TestDynamicFrequencyRetarget(void)
  418. {
  419. TEST_MEMORY memory;
  420. PLSR_CALL call;
  421. PLSR_STATUS status;
  422. TestResetEnvironment();
  423. (void)memset(&memory, 0, sizeof(memory));
  424. CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK);
  425. TestWriteSfdDword(902U, 1UL);
  426. TestWriteSfdDword(904U, 1UL);
  427. CHECK(PlcDeviceWriteSfd(906U, 4U) == PLC_DEVICE_OK);
  428. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  429. TestWriteSfdDword(950U, 1000UL);
  430. CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
  431. CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
  432. CHECK(PlcDeviceWriteSfd(954U, 0U) == PLC_DEVICE_OK);
  433. CHECK(PlcDeviceWriteSfd(955U, 0U) == PLC_DEVICE_OK);
  434. TestWriteSfdDword(956U, 5000UL);
  435. TestWriteSfdDword(958U, 1000UL);
  436. TestWriteSfdDword(960U, 0UL);
  437. CHECK(PlcDeviceWriteSfd(962U, 50U) == PLC_DEVICE_OK);
  438. CHECK(PlcDeviceWriteSfd(963U, 0U) == PLC_DEVICE_OK);
  439. CHECK(PlcDeviceWriteSfd(964U, 2U) == PLC_DEVICE_OK);
  440. TestWriteSfdDword(966U, 2000UL);
  441. TestWriteSfdDword(968U, 200UL);
  442. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  443. TestSetSegment(&memory, 1U, 1000U, 100000);
  444. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 0);
  445. call = TestMakeCall(&memory);
  446. call.sequence = 0xB100UL;
  447. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  448. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  449. PlsrProcess();
  450. PlsrControlTick100us();
  451. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  452. CHECK(status.currentFrequencyHz == 1000UL);
  453. CHECK(status.targetFrequencyHz == 1000UL);
  454. /* Only the 100us control tick may observe/apply a refreshCode=2 edit. */
  455. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 4000);
  456. PlsrProcess();
  457. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  458. CHECK(status.targetFrequencyHz == 1000UL);
  459. CHECK(status.currentFrequencyHz == 1000UL);
  460. PlsrControlTick100us();
  461. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  462. CHECK(status.targetFrequencyHz == 4000UL);
  463. CHECK(status.currentFrequencyHz == 1001UL);
  464. PlsrControlTick100us();
  465. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 1002UL);
  466. /* Down-retarget follows the configured slope instead of jumping. */
  467. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 500);
  468. PlsrControlTick100us();
  469. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  470. CHECK(status.targetFrequencyHz == 500UL);
  471. CHECK(status.currentFrequencyHz == 1001UL);
  472. /* Raw zero means the immutable S2 default speed. */
  473. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 0);
  474. PlsrControlTick100us();
  475. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  476. CHECK(status.targetFrequencyHz == 1000UL);
  477. CHECK(status.currentFrequencyHz == 1000UL);
  478. /* Above-maximum values clamp; invalid negatives retain the last safe
  479. * target and produce one sticky rejection for that observed value. */
  480. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 8000);
  481. PlsrControlTick100us();
  482. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  483. CHECK(status.targetFrequencyHz == 5000UL);
  484. CHECK(status.currentFrequencyHz == 1001UL);
  485. CHECK(status.speedClamped != 0U);
  486. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, -1);
  487. PlsrControlTick100us();
  488. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  489. CHECK(status.targetFrequencyHz == 5000UL);
  490. CHECK(status.currentFrequencyHz == 1002UL);
  491. CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_INVALID_FREQUENCY);
  492. CHECK(status.liveFrequencyRejectCount == 1UL);
  493. PlsrControlTick100us();
  494. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  495. CHECK(status.liveFrequencyRejectCount == 1UL);
  496. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 2000);
  497. PlsrControlTick100us();
  498. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  499. CHECK(status.targetFrequencyHz == 2000UL);
  500. CHECK(status.currentFrequencyHz == 1004UL);
  501. CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_OK);
  502. }
  503. static void TestZeroFrequencyWaits(void)
  504. {
  505. (void)PlsrHwInit();
  506. PLSR_HW_START_PARAMS params;
  507. (void)memset(&params, 0, sizeof(params));
  508. params.frequencyHz = 0UL;
  509. params.targetPulses = 50;
  510. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  511. params.directionPositive = 1U;
  512. params.directionDelayMs = 0U;
  513. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  514. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  515. PlsrHwTick(0U);
  516. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  517. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  518. /* 起始速度为 0:profile 升频后首个非零频率才启动 PWM。 */
  519. CHECK(PlsrHwSetFrequency(0U, 10UL) == PLSR_RESULT_OK);
  520. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  521. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  522. }
  523. static void TestPulseCounting(void)
  524. {
  525. (void)PlsrHwInit();
  526. PLSR_HW_START_PARAMS params;
  527. int pulse;
  528. (void)memset(&params, 0, sizeof(params));
  529. params.frequencyHz = 1000UL;
  530. params.targetPulses = 5;
  531. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  532. params.directionPositive = 1U;
  533. params.directionDelayMs = 0U;
  534. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  535. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  536. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  537. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  538. /* EGR.UG 只加载预装载寄存器,不能被当作物理脉冲。
  539. * 共享 IRQ 入口在对应定时器没有 UIF 时也必须无动作。 */
  540. PlsrHwOnTimerUpdate(0U);
  541. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  542. for (pulse = 0; pulse < 4; pulse++)
  543. {
  544. PlsrHwTestTriggerUpdate(0U);
  545. CHECK(PlsrHwGetEmittedPulses(0U) == pulse + 1);
  546. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  547. }
  548. /* 第 5 个脉冲:到目标,停止 + 段完成事件。 */
  549. PlsrHwTestTriggerUpdate(0U);
  550. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  551. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  552. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  553. /* 停止后再触发更新中断无动作。 */
  554. PlsrHwTestTriggerUpdate(0U);
  555. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  556. }
  557. static void TestAbPhaseAndCounting(void)
  558. {
  559. PLSR_HW_START_PARAMS params;
  560. static const uint8_t positiveA[4] = {1U, 1U, 0U, 0U};
  561. static const uint8_t positiveB[4] = {0U, 1U, 1U, 0U};
  562. static const uint8_t negativeA[4] = {0U, 1U, 1U, 0U};
  563. static const uint8_t negativeB[4] = {1U, 1U, 0U, 0U};
  564. uint32_t oldArr;
  565. uint32_t oldBasePsc;
  566. uint32_t oldPairPsc;
  567. uint32_t newPeriod;
  568. int quarter;
  569. (void)PlsrHwInit();
  570. (void)memset(&params, 0, sizeof(params));
  571. params.frequencyHz = 1000UL;
  572. params.targetPulses = 4;
  573. params.outputMode = PLSR_OUTPUT_AB;
  574. params.directionPoint = 4U; /* AB 模式必须忽略独立 DIR 点。 */
  575. params.directionPositive = 1U;
  576. params.directionDelayMs = 10U; /* AB 模式不得执行方向延时。 */
  577. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  578. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  579. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  580. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  581. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  582. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  583. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  584. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  585. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  586. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  587. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  588. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  589. CHECK(PlsrHwTestGetCcr(0U) == PlsrHwTestGetCcr(1U));
  590. CHECK(PlsrHwTestGetCcr(0U)
  591. == (PlsrHwTestGetArr(0U) + 1UL) / 2UL);
  592. /* 两相从精确 00 边界起步;CC1IF 会在开中断前再次清除。 */
  593. CHECK(PlsrHwTestGetCnt(0U)
  594. == ((PlsrHwTestGetArr(0U) + 1UL) * 3UL) / 4UL + 1UL);
  595. CHECK(PlsrHwTestGetCnt(1U) == PlsrHwTestGetCcr(1U) + 1UL);
  596. CHECK(PlsrHwIsAbStartupPriming(0U) == 0U);
  597. /* 任一物理 timer update 不能直接计作完整 AB 周期。 */
  598. PlsrHwTestTriggerUpdate(0U);
  599. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  600. /* 正向:00→10→11→01→00;四次相位跳变只计一个脉冲。 */
  601. for (quarter = 0; quarter < 4; quarter++)
  602. {
  603. PlsrHwTestAdvanceAbQuarter(0U);
  604. CHECK(PlsrHwTestGetAbPhaseA(0U) == positiveA[quarter]);
  605. CHECK(PlsrHwTestGetAbPhaseB(0U) == positiveB[quarter]);
  606. }
  607. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  608. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  609. /* 运行中调频先排队,不能让相差 1/4 周期的两路各自加载 ARR。 */
  610. oldArr = PlsrHwTestGetArr(0U);
  611. oldBasePsc = PlsrHwTestGetPsc(0U);
  612. oldPairPsc = PlsrHwTestGetPsc(1U);
  613. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  614. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  615. for (quarter = 0; quarter < 4; quarter++)
  616. {
  617. PlsrHwTestAdvanceAbQuarter(0U);
  618. }
  619. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  620. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  621. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  622. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  623. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  624. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  625. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  626. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  627. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  628. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  629. for (quarter = 0; quarter < 3; quarter++)
  630. {
  631. PlsrHwTestAdvanceAbQuarter(0U);
  632. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  633. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  634. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  635. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  636. }
  637. /* 回到 00 后,两路同时装载新频率并从精确 90° 位置重启。 */
  638. PlsrHwTestAdvanceAbQuarter(0U);
  639. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  640. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  641. CHECK((PlsrHwTestGetArr(0U) != oldArr)
  642. || (PlsrHwTestGetPsc(0U) != oldBasePsc));
  643. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  644. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  645. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  646. newPeriod = PlsrHwTestGetArr(0U) + 1UL;
  647. CHECK(PlsrHwTestGetCnt(0U) == (newPeriod * 3UL) / 4UL + 1UL);
  648. CHECK(PlsrHwTestGetCnt(1U) == newPeriod / 2UL + 1UL);
  649. for (quarter = 0; quarter < 4; quarter++)
  650. {
  651. PlsrHwTestAdvanceAbQuarter(0U);
  652. }
  653. CHECK(PlsrHwGetEmittedPulses(0U) == 4);
  654. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  655. PlsrHwTick(0U);
  656. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  657. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  658. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  659. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  660. /* 反向:00→01→11→10→00。 */
  661. params.targetPulses = 1;
  662. params.directionPositive = 0U;
  663. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  664. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  665. for (quarter = 0; quarter < 4; quarter++)
  666. {
  667. PlsrHwTestAdvanceAbQuarter(0U);
  668. CHECK(PlsrHwTestGetAbPhaseA(0U) == negativeA[quarter]);
  669. CHECK(PlsrHwTestGetAbPhaseB(0U) == negativeB[quarter]);
  670. }
  671. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  672. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  673. PlsrHwTick(0U);
  674. /* 紧急停止即使发生在周期中间,也必须回到安全 00。 */
  675. params.targetPulses = 10;
  676. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  677. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  678. PlsrHwTestAdvanceAbQuarter(0U);
  679. CHECK(PlsrHwTestGetAbQuarter(0U) == 1U);
  680. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  681. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  682. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  683. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  684. }
  685. static void TestTwoAbAxesIndependent(void)
  686. {
  687. PLSR_HW_START_PARAMS params;
  688. int quarter;
  689. (void)PlsrHwInit();
  690. (void)memset(&params, 0, sizeof(params));
  691. params.frequencyHz = 1000UL;
  692. params.targetPulses = 1;
  693. params.outputMode = PLSR_OUTPUT_AB;
  694. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  695. params.directionPositive = 1U;
  696. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  697. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  698. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  699. CHECK(PlsrHwSetFrequency(2U, 2000UL) == PLSR_RESULT_OK);
  700. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  701. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  702. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  703. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  704. for (quarter = 0; quarter < 4; quarter++)
  705. {
  706. PlsrHwTestAdvanceAbQuarter(0U);
  707. }
  708. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  709. PlsrHwTick(0U);
  710. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
  711. CHECK(PlsrHwGetEmittedPulses(2U) == 0);
  712. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  713. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  714. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  715. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  716. for (quarter = 0; quarter < 4; quarter++)
  717. {
  718. PlsrHwTestAdvanceAbQuarter(2U);
  719. }
  720. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
  721. CHECK(PlsrHwGetEmittedPulses(2U) == 1);
  722. PlsrHwTick(2U);
  723. }
  724. static void TestDualAbHardwareCountersAndResume(void)
  725. {
  726. PLSR_HW_START_PARAMS params;
  727. int quarter;
  728. int cycle;
  729. (void)PlsrHwInit();
  730. (void)memset(&params, 0, sizeof(params));
  731. params.frequencyHz = 100000UL;
  732. params.targetPulses = 6;
  733. params.outputMode = PLSR_OUTPUT_AB;
  734. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  735. params.directionPositive = 1U;
  736. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  737. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  738. CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
  739. CHECK(PlsrHwUsesHardwareCounter(2U) == 1U);
  740. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  741. CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
  742. for (cycle = 0; cycle < 2; cycle++)
  743. {
  744. for (quarter = 0; quarter < 4; quarter++)
  745. {
  746. PlsrHwTestAdvanceAbQuarter(0U);
  747. }
  748. }
  749. for (quarter = 0; quarter < 4; quarter++)
  750. {
  751. PlsrHwTestAdvanceAbQuarter(2U);
  752. }
  753. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  754. CHECK(PlsrHwGetEmittedPulses(2U) == 1);
  755. /* The source timer can cross its edge just before the ITR slave observes
  756. * it. The phase-corrected public count must not regress from 2 to 1 in
  757. * that synchronization window, otherwise core PAUSE raises COUNTER_FAULT. */
  758. PlsrHwTestSetAbQuarterWithoutCounter(0U, 1U);
  759. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  760. PlsrHwTestSetAbQuarterWithoutCounter(0U, 0U);
  761. /* Request PAUSE after the source edge but before the following 00. The
  762. * pair must finish this already-started cycle instead of forcing GPIO 00
  763. * and re-emitting its source edge after RESUME. */
  764. PlsrHwTestAdvanceAbQuarter(0U);
  765. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  766. CHECK(PlsrHwSetFrequency(0U, 0UL) == PLSR_RESULT_OK);
  767. CHECK(PlsrHwTestGetAbQuarter(0U) == 1U);
  768. CHECK((PlsrHwTestGetCr1(0U) & 1UL) != 0UL);
  769. CHECK((PlsrHwTestGetCr1(1U) & 1UL) != 0UL);
  770. for (quarter = 1; quarter < 4; quarter++)
  771. {
  772. PlsrHwTestAdvanceAbQuarter(0U);
  773. }
  774. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  775. CHECK((PlsrHwTestGetCr1(0U) & 1UL) == 0UL);
  776. CHECK((PlsrHwTestGetCr1(1U) & 1UL) == 0UL);
  777. CHECK(PlsrHwResumePulse(0U) == PLSR_RESULT_INVALID_STATE);
  778. PlsrHwTick(0U);
  779. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  780. CHECK(PlsrHwResumePulse(0U) == PLSR_RESULT_OK);
  781. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  782. for (cycle = 0; cycle < 3; cycle++)
  783. {
  784. for (quarter = 0; quarter < 4; quarter++)
  785. {
  786. PlsrHwTestAdvanceAbQuarter(0U);
  787. }
  788. }
  789. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  790. CHECK(PlsrHwGetEmittedPulses(0U) == 6);
  791. PlsrHwTick(0U);
  792. CHECK(PlsrHwUsesHardwareCounter(0U) == 0U);
  793. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
  794. for (cycle = 1; cycle < 6; cycle++)
  795. {
  796. for (quarter = 0; quarter < 4; quarter++)
  797. {
  798. PlsrHwTestAdvanceAbQuarter(2U);
  799. }
  800. }
  801. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
  802. CHECK(PlsrHwGetEmittedPulses(2U) == 6);
  803. PlsrHwTick(2U);
  804. CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
  805. }
  806. static void TestDualAbSimultaneousFastGate(void)
  807. {
  808. PLSR_HW_START_PARAMS params;
  809. (void)PlsrHwInit();
  810. (void)memset(&params, 0, sizeof(params));
  811. params.frequencyHz = 100000UL;
  812. params.targetPulses = 200000;
  813. params.outputMode = PLSR_OUTPUT_AB;
  814. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  815. params.directionPositive = 1U;
  816. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  817. params.directionPositive = 0U;
  818. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  819. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  820. CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
  821. CHECK(PlsrHwUsesHardwareCounter(0U) == 1U);
  822. CHECK(PlsrHwUsesHardwareCounter(2U) == 1U);
  823. /* Both lag flags become pending before the first equal-priority handler.
  824. * Its entry scan must freeze all four timers before publishing axis 0. */
  825. PlsrHwTestSignalDualAbFinalBoundary(0U);
  826. CHECK(PlsrHwTestGetAbFullGateCount() == 1UL);
  827. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  828. CHECK(PlsrHwGetEmittedPulses(0U) == 200000);
  829. CHECK((PlsrHwTestGetCr1(2U) & 1UL) == 0UL);
  830. CHECK((PlsrHwTestGetCr1(3U) & 1UL) == 0UL);
  831. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
  832. /* The lag axis for negative Q2/Q3 is Q2. */
  833. PlsrHwTestTriggerCompare(2U);
  834. CHECK(PlsrHwTestGetAbFullGateCount() == 2UL);
  835. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
  836. CHECK(PlsrHwGetEmittedPulses(2U) == 200000);
  837. PlsrHwTick(0U);
  838. PlsrHwTick(2U);
  839. CHECK(PlsrHwUsesHardwareCounter(0U) == 0U);
  840. CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
  841. /* Repeat with pair 2's flag injected after the first entry scan. The
  842. * second scan must gate it before pair 0 performs deferred GPIO/counter
  843. * cleanup, and both pairs must still be frozen at a real 00 boundary. */
  844. (void)PlsrHwInit();
  845. params.directionPositive = 1U;
  846. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  847. params.directionPositive = 0U;
  848. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  849. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  850. CHECK(PlsrHwSetFrequency(2U, 100000UL) == PLSR_RESULT_OK);
  851. PlsrHwTestSignalDualAbStaggeredFinalBoundary(0U);
  852. CHECK(PlsrHwTestGetAbFullGateCount() == 1UL);
  853. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  854. CHECK(PlsrHwGetEmittedPulses(0U) == 200000);
  855. CHECK((PlsrHwTestGetCr1(2U) & 1UL) == 0UL);
  856. CHECK((PlsrHwTestGetCr1(3U) & 1UL) == 0UL);
  857. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
  858. PlsrHwTestTriggerCompare(2U);
  859. CHECK(PlsrHwTestGetAbFullGateCount() == 2UL);
  860. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
  861. CHECK(PlsrHwGetEmittedPulses(2U) == 200000);
  862. PlsrHwTick(0U);
  863. PlsrHwTick(2U);
  864. CHECK(PlsrHwUsesHardwareCounter(0U) == 0U);
  865. CHECK(PlsrHwUsesHardwareCounter(2U) == 0U);
  866. }
  867. static void TestAbFrequencyLimits(void)
  868. {
  869. PLSR_HW_START_PARAMS params;
  870. uint32_t oldArr;
  871. int quarter;
  872. (void)PlsrHwInit();
  873. (void)memset(&params, 0, sizeof(params));
  874. params.frequencyHz = 1UL;
  875. params.targetPulses = 100;
  876. params.outputMode = PLSR_OUTPUT_AB;
  877. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  878. params.directionPositive = 1U;
  879. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  880. CHECK(PlsrHwSetFrequency(0U, 1UL) == PLSR_RESULT_OK);
  881. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  882. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  883. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  884. CHECK(PlsrHwTestGetArr(0U) <= 65535UL);
  885. oldArr = PlsrHwTestGetArr(0U);
  886. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  887. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  888. for (quarter = 0; quarter < 4; quarter++)
  889. {
  890. PlsrHwTestAdvanceAbQuarter(0U);
  891. }
  892. /* This request is 99 cycles away from target-1: it must be applied by
  893. * the frequency one-shot CCIE, not accidentally by the final guard. */
  894. CHECK(PlsrHwTestGetArr(0U) != oldArr);
  895. CHECK(PlsrHwTestGetArr(0U) == 839UL);
  896. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  897. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  898. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  899. CHECK(PlsrHwTestGetArr(0U) >= 3UL);
  900. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  901. }
  902. static void TestStopAndInvalidArgs(void)
  903. {
  904. (void)PlsrHwInit();
  905. PLSR_HW_START_PARAMS params;
  906. (void)memset(&params, 0, sizeof(params));
  907. params.frequencyHz = 1000UL;
  908. params.targetPulses = 100;
  909. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  910. params.directionPositive = 1U;
  911. params.directionDelayMs = 0U;
  912. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  913. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  914. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  915. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  916. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  917. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  918. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  919. CHECK(PlsrHwStartPulse(4U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  920. CHECK(PlsrHwStartPulse(0U, NULL) == PLSR_RESULT_INVALID_ARGUMENT);
  921. params.targetPulses = 0;
  922. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  923. params.targetPulses = 1;
  924. params.outputMode = PLSR_OUTPUT_CW_CCW;
  925. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  926. params.outputMode = (PLSR_OUTPUT_MODE)99;
  927. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  928. CHECK(PlsrHwSetFrequency(4U, 1000UL) == PLSR_RESULT_INVALID_ARGUMENT);
  929. CHECK(PlsrHwStopPulse(4U) == PLSR_RESULT_INVALID_ARGUMENT);
  930. }
  931. /* ---- 端到端集成:START → 硬件 → 计数 → 事件 → 段间 → 完成 ---- */
  932. static void TestEndToEndTwoSegments(void)
  933. {
  934. TEST_MEMORY memory;
  935. PLSR_CALL call;
  936. PLSR_STATUS status;
  937. uint16_t initialPsc;
  938. uint16_t initialArr;
  939. int ticks;
  940. int pulse;
  941. TestResetEnvironment();
  942. (void)memset(&memory, 0, sizeof(memory));
  943. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  944. TestSetSegment(&memory, 1U, 1000U, 100);
  945. TestSetSegment(&memory, 2U, 2000U, 200);
  946. call = TestMakeCall(&memory);
  947. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  948. PlsrProcess();
  949. status = TestGetStatus();
  950. CHECK(status.state == PLSR_STATE_ACCEL);
  951. CHECK(status.currentSegment == 1U);
  952. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  953. /* DIR 延时 10ms → PWM 启动(段1 起始速度 0,profile 升频后启动)。 */
  954. for (ticks = 0; ticks < 9; ticks++)
  955. {
  956. PlsrProcess();
  957. }
  958. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  959. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  960. CHECK(PlsrCalculateTimerDivider(168000000UL, 75UL,
  961. &initialPsc, &initialArr)
  962. == PLSR_RESULT_OK);
  963. CHECK(PlsrHwTestGetPsc(0U) == initialPsc);
  964. CHECK(PlsrHwTestGetArr(0U) == initialArr);
  965. /* 加速完成 → 状态机进入 RUN。 */
  966. for (ticks = 0; ticks < 500; ticks++)
  967. {
  968. PlsrProcess();
  969. if (TestGetStatus().state == PLSR_STATE_RUN)
  970. {
  971. break;
  972. }
  973. }
  974. status = TestGetStatus();
  975. CHECK(status.state == PLSR_STATE_RUN);
  976. CHECK(status.currentSegment == 1U);
  977. /* 段1 脉冲完成:100 次更新中断 → SEGMENT_COMPLETE → 段2 启动。 */
  978. for (pulse = 0; pulse < 100; pulse++)
  979. {
  980. PlsrHwTestTriggerUpdate(0U);
  981. }
  982. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  983. PlsrProcess();
  984. status = TestGetStatus();
  985. CHECK(status.state == PLSR_STATE_ACCEL);
  986. CHECK(status.currentSegment == 2U);
  987. CHECK(status.logicalPosition == 100);
  988. CHECK(status.taskPulses == 100);
  989. CHECK(status.totalPulses == 100);
  990. CHECK(TestReadSdDword(1000U) == 2);
  991. CHECK(TestReadSdDword(1002U) == 0);
  992. /* 段2:DIR 延时 → PWM → 加速 → RUN。 */
  993. for (ticks = 0; ticks < 600; ticks++)
  994. {
  995. PlsrProcess();
  996. if (TestGetStatus().state == PLSR_STATE_RUN)
  997. {
  998. break;
  999. }
  1000. }
  1001. status = TestGetStatus();
  1002. CHECK(status.state == PLSR_STATE_RUN);
  1003. CHECK(status.currentSegment == 2U);
  1004. /* 段2 脉冲完成 → 任务结束。 */
  1005. for (pulse = 0; pulse < 200; pulse++)
  1006. {
  1007. PlsrHwTestTriggerUpdate(0U);
  1008. }
  1009. PlsrProcess();
  1010. status = TestGetStatus();
  1011. CHECK(status.state == PLSR_STATE_COMPLETED);
  1012. CHECK(status.done != 0U);
  1013. CHECK(status.logicalPosition == 300);
  1014. CHECK(status.taskPulses == 300);
  1015. CHECK(status.totalPulses == 300);
  1016. CHECK(TestReadSdDword(1000U) == 2);
  1017. CHECK(TestReadSdDword(1002U) == 200);
  1018. CHECK(TestReadSdDword(1004U) == 200);
  1019. CHECK(TestReadSdDword(1006U) == 0);
  1020. {
  1021. int32_t hsdPulses;
  1022. int32_t hsdEquivalent;
  1023. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  1024. CHECK(hsdPulses == 300);
  1025. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent)
  1026. == PLC_DEVICE_OK);
  1027. CHECK(hsdEquivalent == 300);
  1028. }
  1029. /* 终态转换后 HAL 回 IDLE(允许重新启动),脉冲已停止。 */
  1030. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  1031. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  1032. }
  1033. static void TestEndToEndAbSegment(void)
  1034. {
  1035. TEST_MEMORY memory;
  1036. PLSR_CALL call;
  1037. PLSR_STATUS status;
  1038. int quarter;
  1039. TestResetEnvironment();
  1040. (void)memset(&memory, 0, sizeof(memory));
  1041. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1042. TestSetSegment(&memory, 1U, 1000U, -2);
  1043. call = TestMakeCall(&memory);
  1044. call.sequence = 15UL;
  1045. call.outputModeOverride = PLSR_OUTPUT_AB;
  1046. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1047. PlsrProcess();
  1048. status = TestGetStatus();
  1049. CHECK(status.state == PLSR_STATE_ACCEL);
  1050. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  1051. CHECK(status.directionPoint == PLSR_DIRECTION_POINT_NONE);
  1052. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1053. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  1054. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  1055. CHECK(PlsrHwTestGetCc1PolarityInverted(0U) != 0U);
  1056. CHECK(PlsrHwTestGetCc1PolarityInverted(1U) != 0U);
  1057. /* 负脉冲选择反向相序,完整两个周期后由同一事件链结束任务。 */
  1058. PlsrHwTestAdvanceAbQuarter(0U);
  1059. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  1060. CHECK(PlsrHwTestGetAbPhaseB(0U) == 1U);
  1061. for (quarter = 1; quarter < 8; quarter++)
  1062. {
  1063. PlsrHwTestAdvanceAbQuarter(0U);
  1064. }
  1065. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  1066. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  1067. PlsrProcess();
  1068. PlsrProcess();
  1069. status = TestGetStatus();
  1070. CHECK(status.state == PLSR_STATE_COMPLETED);
  1071. CHECK(status.done != 0U);
  1072. CHECK(status.directionPositive == 0U);
  1073. CHECK(status.logicalPosition == -2);
  1074. CHECK(status.taskPulses == -2);
  1075. CHECK(status.totalPulses == 2);
  1076. CHECK(TestReadSdDword(1002U) == -2);
  1077. CHECK(TestReadSdDword(1004U) == -2);
  1078. CHECK(status.highResourceMask == 0U);
  1079. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  1080. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  1081. }
  1082. static void TestPositionOnImmediateStop(void)
  1083. {
  1084. TEST_MEMORY memory;
  1085. PLSR_CALL call;
  1086. PLSR_COMMAND command;
  1087. PLSR_STATUS status;
  1088. int pulse;
  1089. int tick;
  1090. TestResetEnvironment();
  1091. (void)memset(&memory, 0, sizeof(memory));
  1092. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1093. TestSetSegment(&memory, 1U, 1000U, 100);
  1094. call = TestMakeCall(&memory);
  1095. call.sequence = 30UL;
  1096. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1097. PlsrProcess();
  1098. for (tick = 0; tick < 10; tick++)
  1099. {
  1100. PlsrProcess();
  1101. }
  1102. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1103. for (pulse = 0; pulse < 37; pulse++)
  1104. {
  1105. PlsrHwTestTriggerUpdate(0U);
  1106. }
  1107. PlsrProcess();
  1108. status = TestGetStatus();
  1109. CHECK(status.logicalPosition == 37);
  1110. CHECK(status.taskPulses == 37);
  1111. CHECK(status.totalPulses == 37);
  1112. command.sequence = 31UL;
  1113. command.axis = 0U;
  1114. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  1115. command.argument = 0;
  1116. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1117. PlsrProcess();
  1118. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1119. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  1120. == PLSR_RESULT_OK);
  1121. PlsrProcess();
  1122. status = TestGetStatus();
  1123. CHECK(status.state == PLSR_STATE_STOPPED);
  1124. CHECK(status.logicalPosition == 37);
  1125. CHECK(status.taskPulses == 37);
  1126. CHECK(status.totalPulses == 37);
  1127. CHECK(TestReadSdDword(1002U) == 37);
  1128. command.sequence = 32UL;
  1129. command.opcode = PLSR_CMD_CLEAR_TOTAL;
  1130. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1131. PlsrProcess();
  1132. status = TestGetStatus();
  1133. CHECK(status.logicalPosition == 37);
  1134. CHECK(status.totalPulses == 0);
  1135. }
  1136. static void TestAbsolutePositionAccounting(void)
  1137. {
  1138. TEST_MEMORY memory;
  1139. PLSR_CALL call;
  1140. PLSR_COMMAND command;
  1141. PLSR_STATUS status;
  1142. int32_t hsdPosition;
  1143. int pulse;
  1144. int tick;
  1145. TestResetEnvironment();
  1146. command.sequence = 40UL;
  1147. command.axis = 0U;
  1148. command.opcode = PLSR_CMD_SET_POSITION;
  1149. command.argument = 100;
  1150. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1151. PlsrProcess();
  1152. (void)memset(&memory, 0, sizeof(memory));
  1153. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1154. TestSetSegment(&memory, 1U, 1000U, 130);
  1155. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 1);
  1156. call = TestMakeCall(&memory);
  1157. call.sequence = 41UL;
  1158. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1159. PlsrProcess();
  1160. for (tick = 0; tick < 10; tick++)
  1161. {
  1162. PlsrProcess();
  1163. }
  1164. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1165. for (pulse = 0; pulse < 30; pulse++)
  1166. {
  1167. PlsrHwTestTriggerUpdate(0U);
  1168. }
  1169. PlsrProcess();
  1170. status = TestGetStatus();
  1171. CHECK(status.state == PLSR_STATE_COMPLETED);
  1172. CHECK(status.logicalPosition == 130);
  1173. CHECK(status.taskPulses == 30);
  1174. CHECK(status.totalPulses == 30);
  1175. CHECK(status.positionValid != 0U);
  1176. CHECK(PlcDeviceReadHsdDword(0U, &hsdPosition) == PLC_DEVICE_OK);
  1177. CHECK(hsdPosition == 130);
  1178. }
  1179. static void TestEquivalentRemainderAccounting(void)
  1180. {
  1181. TEST_MEMORY memory;
  1182. PLSR_CALL call;
  1183. PLSR_STATUS status;
  1184. int32_t hsdPulses;
  1185. int32_t hsdEquivalent;
  1186. TestResetEnvironment();
  1187. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  1188. TestWriteSfdDword(902U, 3UL);
  1189. TestWriteSfdDword(904U, 2UL);
  1190. TestWriteSfdDword(956U, 60000UL);
  1191. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1192. (void)memset(&memory, 0, sizeof(memory));
  1193. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1194. TestSetSegment(&memory, 1U, 1000U, 1);
  1195. call = TestMakeCall(&memory);
  1196. call.sequence = 30UL;
  1197. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  1198. /* 3脉冲/2单位:第一次1单位只输出1脉冲并保存1/2余数。 */
  1199. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1200. PlsrProcess();
  1201. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1202. PlsrHwTestTriggerUpdate(0U);
  1203. PlsrProcess();
  1204. status = TestGetStatus();
  1205. CHECK(status.state == PLSR_STATE_COMPLETED);
  1206. CHECK(status.logicalPosition == 1);
  1207. CHECK(status.taskPulses == 1);
  1208. CHECK(status.totalPulses == 1);
  1209. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  1210. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  1211. CHECK(hsdPulses == 1);
  1212. CHECK(hsdEquivalent == 0);
  1213. /* 第二次1单位合并余数后输出2脉冲;两次合计精确为3脉冲/2单位。 */
  1214. call.sequence = 31UL;
  1215. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1216. PlsrProcess();
  1217. PlsrHwTestTriggerUpdate(0U);
  1218. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1219. PlsrHwTestTriggerUpdate(0U);
  1220. PlsrProcess();
  1221. status = TestGetStatus();
  1222. CHECK(status.state == PLSR_STATE_COMPLETED);
  1223. CHECK(status.logicalPosition == 3);
  1224. CHECK(status.taskPulses == 2);
  1225. CHECK(status.totalPulses == 3);
  1226. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  1227. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  1228. CHECK(hsdPulses == 3);
  1229. CHECK(hsdEquivalent == 2);
  1230. CHECK(TestReadSdDword(1002U) == 2);
  1231. CHECK(TestReadSdDword(1004U) == 1);
  1232. }
  1233. static void TestEquivalentCompatibleError(void)
  1234. {
  1235. TEST_MEMORY memory;
  1236. PLSR_CALL call;
  1237. PLSR_STATUS status;
  1238. int32_t errorCode = -1;
  1239. int32_t errorBlock = -1;
  1240. TestResetEnvironment();
  1241. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  1242. TestWriteSfdDword(902U, 0UL);
  1243. TestWriteSfdDword(904U, 2UL);
  1244. TestWriteSfdDword(956U, 60000UL);
  1245. (void)memset(&memory, 0, sizeof(memory));
  1246. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1247. TestSetSegment(&memory, 1U, 1000U, 1);
  1248. call = TestMakeCall(&memory);
  1249. call.sequence = 32UL;
  1250. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  1251. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1252. PlsrProcess();
  1253. status = TestGetStatus();
  1254. CHECK(status.lastCommandResult == PLSR_RESULT_INVALID_S2);
  1255. CHECK(status.state == PLSR_STATE_IDLE);
  1256. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  1257. CHECK(PlcDeviceReadSd(1011U, &errorBlock) == PLC_DEVICE_OK);
  1258. CHECK(errorCode == 2);
  1259. CHECK(errorBlock == 0);
  1260. /* A valid retry clears the compatible parameter error. */
  1261. TestWriteSfdDword(902U, 3UL);
  1262. call.sequence = 33UL;
  1263. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1264. PlsrProcess();
  1265. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  1266. CHECK(errorCode == 0);
  1267. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  1268. }
  1269. static void TestSoftLimitAndSegmentEvent(void)
  1270. {
  1271. TEST_MEMORY memory;
  1272. PLSR_CALL call;
  1273. PLSR_COMMAND command;
  1274. PLSR_STATUS status;
  1275. PLC_DEVICE_EVENT_RECORD eventRecord;
  1276. int32_t errorCode;
  1277. int pulse;
  1278. int tick;
  1279. uint32_t pulsePhase = 0UL;
  1280. TestResetEnvironment();
  1281. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  1282. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1283. CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
  1284. CHECK(PlcDeviceWriteSfd(915U, 0xFFFFU) == PLC_DEVICE_OK);
  1285. TestWriteSfdDword(930U, 100UL);
  1286. TestWriteSfdDword(932U, (uint32_t)(int32_t)-100);
  1287. command.sequence = 40UL;
  1288. command.axis = 0U;
  1289. command.opcode = PLSR_CMD_SET_POSITION;
  1290. command.argument = 100;
  1291. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1292. PlsrProcess();
  1293. (void)memset(&memory, 0, sizeof(memory));
  1294. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1295. TestSetSegment(&memory, 1U, 1000U, 10);
  1296. call = TestMakeCall(&memory);
  1297. call.sequence = 41UL;
  1298. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1299. PlsrProcess();
  1300. status = TestGetStatus();
  1301. CHECK(status.lastCommandResult == PLSR_RESULT_LIMIT_POSITIVE);
  1302. CHECK(status.state == PLSR_STATE_IDLE);
  1303. CHECK(status.positiveLimitActive != 0U);
  1304. CHECK(status.error == PLSR_ERROR_LIMIT_POSITIVE);
  1305. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  1306. CHECK(errorCode == 5);
  1307. /* 正限位上只禁止正向,反向离开仍可正常完成。 */
  1308. TestSetSegment(&memory, 1U, 1000U, -10);
  1309. call.sequence = 42UL;
  1310. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1311. PlsrProcess();
  1312. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1313. for (pulse = 0; pulse < 10; pulse++)
  1314. {
  1315. PlsrHwTestTriggerUpdate(0U);
  1316. }
  1317. PlsrProcess();
  1318. status = TestGetStatus();
  1319. CHECK(status.state == PLSR_STATE_COMPLETED);
  1320. CHECK(status.logicalPosition == 90);
  1321. CHECK(status.error == PLSR_ERROR_NONE);
  1322. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1323. CHECK(eventRecord.count == 1UL);
  1324. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  1325. CHECK(eventRecord.pending != 0U);
  1326. /* 运行中按预计制动距离触发软限位,PWM保持运行并按曲线缓停。 */
  1327. TestResetEnvironment();
  1328. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  1329. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1330. TestWriteSfdDword(930U, 50UL);
  1331. TestWriteSfdDword(932U, (uint32_t)(int32_t)-50);
  1332. command.sequence = 43UL;
  1333. command.opcode = PLSR_CMD_SET_POSITION;
  1334. command.argument = 0;
  1335. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1336. PlsrProcess();
  1337. (void)memset(&memory, 0, sizeof(memory));
  1338. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1339. TestSetSegment(&memory, 1U, 1000U, 10000);
  1340. call = TestMakeCall(&memory);
  1341. call.sequence = 44UL;
  1342. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1343. PlsrProcess();
  1344. for (pulse = 0; pulse < 49; pulse++)
  1345. {
  1346. PlsrHwTestTriggerUpdate(0U);
  1347. }
  1348. PlsrProcess();
  1349. status = TestGetStatus();
  1350. CHECK(status.state == PLSR_STATE_DECEL);
  1351. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1352. CHECK(status.positiveLimitActive != 0U);
  1353. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1354. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  1355. CHECK(errorCode == 5);
  1356. for (tick = 0; tick < 20; tick++)
  1357. {
  1358. PlsrProcess();
  1359. }
  1360. status = TestGetStatus();
  1361. CHECK(status.state == PLSR_STATE_STOPPED);
  1362. CHECK(status.logicalPosition == 49);
  1363. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1364. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1365. CHECK(eventRecord.count == 1UL);
  1366. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1367. /* Board-equivalent time simulation for the +500 precision case. Each
  1368. * loop represents 1 ms and emits complete hardware periods according to
  1369. * the frequency that was active during that interval. */
  1370. TestResetEnvironment();
  1371. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  1372. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1373. TestWriteSfdDword(930U, 500UL);
  1374. TestWriteSfdDword(932U, (uint32_t)(int32_t)-500);
  1375. TestWriteSfdDword(950U, 1000UL);
  1376. CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
  1377. CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
  1378. TestWriteSfdDword(958U, 1000UL);
  1379. TestWriteSfdDword(960U, 0UL);
  1380. command.sequence = 45UL;
  1381. command.opcode = PLSR_CMD_SET_POSITION;
  1382. command.argument = 0;
  1383. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1384. PlsrProcess();
  1385. (void)memset(&memory, 0, sizeof(memory));
  1386. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1387. TestSetSegment(&memory, 1U, 1000U, 10000);
  1388. call = TestMakeCall(&memory);
  1389. call.sequence = 46UL;
  1390. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1391. PlsrProcess();
  1392. for (tick = 0; tick < 1000; tick++)
  1393. {
  1394. pulsePhase += PlsrHwGetCurrentFrequencyHz(0U);
  1395. while ((pulsePhase >= 1000UL)
  1396. && (PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING))
  1397. {
  1398. pulsePhase -= 1000UL;
  1399. PlsrHwTestTriggerUpdate(0U);
  1400. }
  1401. PlsrProcess();
  1402. status = TestGetStatus();
  1403. if (status.state == PLSR_STATE_STOPPED)
  1404. {
  1405. break;
  1406. }
  1407. }
  1408. CHECK(status.state == PLSR_STATE_STOPPED);
  1409. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1410. CHECK(status.logicalPosition >= 499);
  1411. CHECK(status.logicalPosition <= 501);
  1412. /* Negative/high-speed companion case for the P15 board matrix. */
  1413. TestResetEnvironment();
  1414. pulsePhase = 0UL;
  1415. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  1416. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1417. TestWriteSfdDword(930U, 1000UL);
  1418. TestWriteSfdDword(932U, (uint32_t)(int32_t)-1000);
  1419. TestWriteSfdDword(950U, 2000UL);
  1420. CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
  1421. CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
  1422. TestWriteSfdDword(958U, 2000UL);
  1423. TestWriteSfdDword(960U, 0UL);
  1424. command.sequence = 47UL;
  1425. command.opcode = PLSR_CMD_SET_POSITION;
  1426. command.argument = 0;
  1427. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1428. PlsrProcess();
  1429. (void)memset(&memory, 0, sizeof(memory));
  1430. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1431. TestSetSegment(&memory, 1U, 2000U, -10000);
  1432. call = TestMakeCall(&memory);
  1433. call.sequence = 48UL;
  1434. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1435. PlsrProcess();
  1436. for (tick = 0; tick < 1000; tick++)
  1437. {
  1438. pulsePhase += PlsrHwGetCurrentFrequencyHz(0U);
  1439. while ((pulsePhase >= 1000UL)
  1440. && (PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING))
  1441. {
  1442. pulsePhase -= 1000UL;
  1443. PlsrHwTestTriggerUpdate(0U);
  1444. }
  1445. PlsrProcess();
  1446. status = TestGetStatus();
  1447. if (status.state == PLSR_STATE_STOPPED)
  1448. {
  1449. break;
  1450. }
  1451. }
  1452. CHECK(status.state == PLSR_STATE_STOPPED);
  1453. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_NEGATIVE);
  1454. CHECK(status.logicalPosition >= -1001);
  1455. CHECK(status.logicalPosition <= -999);
  1456. }
  1457. static void TestHardLimitAndEmergencyLatch(void)
  1458. {
  1459. TEST_MEMORY memory;
  1460. PLSR_CALL call;
  1461. PLSR_COMMAND command;
  1462. PLSR_STATUS status;
  1463. PLC_DEVICE_EVENT_RECORD eventRecord;
  1464. TestResetEnvironment();
  1465. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1466. CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
  1467. CHECK(PlcDeviceWriteSfd(915U, 0xFF03U) == PLC_DEVICE_OK);
  1468. (void)memset(&memory, 0, sizeof(memory));
  1469. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1470. TestSetSegment(&memory, 1U, 1000U, 10000);
  1471. call = TestMakeCall(&memory);
  1472. call.sequence = 50UL;
  1473. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1474. PlsrProcess();
  1475. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1476. memory.bits[0][3U] = 1U;
  1477. PlsrProcess();
  1478. status = TestGetStatus();
  1479. CHECK(status.state == PLSR_STATE_DECEL);
  1480. CHECK(status.positiveLimitActive != 0U);
  1481. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1482. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1483. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1484. TestResetEnvironment();
  1485. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1486. (void)memset(&memory, 0, sizeof(memory));
  1487. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1488. TestSetSegment(&memory, 1U, 1000U, 10000);
  1489. call = TestMakeCall(&memory);
  1490. call.sequence = 51UL;
  1491. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1492. PlsrProcess();
  1493. command.sequence = 52UL;
  1494. command.axis = 0U;
  1495. command.opcode = PLSR_CMD_RESET_ERROR;
  1496. command.argument = 0;
  1497. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1498. CHECK(PlsrPostEvent(0U,
  1499. PLSR_EVENT_LIMIT_POSITIVE
  1500. | PLSR_EVENT_SOFTWARE_EMERGENCY)
  1501. == PLSR_RESULT_OK);
  1502. PlsrProcess();
  1503. status = TestGetStatus();
  1504. CHECK(status.state == PLSR_STATE_STOPPED);
  1505. CHECK(status.stopReason == PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
  1506. CHECK(status.error == PLSR_ERROR_EMERGENCY);
  1507. CHECK(status.emergencyLatched != 0U);
  1508. CHECK(status.lastCommandSequence == 52UL);
  1509. CHECK(status.lastCommandResult == PLSR_RESULT_BUSY);
  1510. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1511. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1512. CHECK(eventRecord.count == 1UL);
  1513. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
  1514. call.sequence = 53UL;
  1515. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1516. PlsrProcess();
  1517. status = TestGetStatus();
  1518. CHECK(status.lastCommandResult == PLSR_RESULT_EMERGENCY_LATCHED);
  1519. CHECK(status.state == PLSR_STATE_STOPPED);
  1520. command.sequence = 54UL;
  1521. command.axis = 0U;
  1522. command.opcode = PLSR_CMD_RESET_ERROR;
  1523. command.argument = 0;
  1524. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1525. PlsrProcess();
  1526. status = TestGetStatus();
  1527. CHECK(status.state == PLSR_STATE_IDLE);
  1528. CHECK(status.error == PLSR_ERROR_NONE);
  1529. CHECK(status.emergencyLatched == 0U);
  1530. }
  1531. static void TestProductionSelfTestStartsAb(void)
  1532. {
  1533. PLSR_STATUS status;
  1534. TestResetEnvironment();
  1535. CHECK(PlsrSelfTestQueue() == PLSR_RESULT_QUEUED);
  1536. PlsrProcess();
  1537. status = TestGetStatus();
  1538. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  1539. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  1540. CHECK(status.currentSegment == 1U);
  1541. CHECK(status.state == PLSR_STATE_ACCEL);
  1542. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1543. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  1544. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  1545. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  1546. }
  1547. static void TestEquivalentSelfTest(void)
  1548. {
  1549. PLSR_STATUS status;
  1550. int32_t hsdPulses;
  1551. int32_t hsdEquivalent;
  1552. int ticks;
  1553. TestResetEnvironment();
  1554. CHECK(PlsrEquivalentSelfTestQueue() == PLSR_RESULT_QUEUED);
  1555. PlsrProcess();
  1556. /* SFD907=10ms. Advance the simulated hardware delay before segment 1. */
  1557. for (ticks = 0; ticks < 10; ticks++)
  1558. {
  1559. PlsrProcess();
  1560. }
  1561. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1562. /* 3 pulses / 2 units: 1001 units emit 1501 pulses and keep 1/2 remainder. */
  1563. for (ticks = 0; ticks < 1501; ticks++)
  1564. {
  1565. PlsrHwTestTriggerUpdate(0U);
  1566. }
  1567. PlsrProcess();
  1568. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1569. /* Segment 2 consumes the remainder and therefore emits 1502 pulses. */
  1570. for (ticks = 0; ticks < 1502; ticks++)
  1571. {
  1572. PlsrHwTestTriggerUpdate(0U);
  1573. }
  1574. PlsrProcess();
  1575. status = TestGetStatus();
  1576. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  1577. CHECK(status.outputMode == PLSR_OUTPUT_PULSE_DIR);
  1578. CHECK(status.state == PLSR_STATE_COMPLETED);
  1579. CHECK(status.currentSegment == 2U);
  1580. CHECK(status.logicalPosition == 3003);
  1581. CHECK(status.taskPulses == 3003);
  1582. CHECK(status.totalPulses == 3003);
  1583. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  1584. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  1585. CHECK(hsdPulses == 3003);
  1586. CHECK(hsdEquivalent == 2002);
  1587. CHECK(TestReadSdDword(1002U) == 1502);
  1588. CHECK(TestReadSdDword(1004U) == 1001);
  1589. }
  1590. static void TestProtectionSelfTest(void)
  1591. {
  1592. PLC_DEVICE_EVENT_RECORD eventRecord;
  1593. PLSR_STATUS status;
  1594. uint32_t pulseAccumulator = 0UL;
  1595. int32_t value;
  1596. int ticks;
  1597. TestResetEnvironment();
  1598. CHECK(PlsrProtectionSelfTestQueue() == PLSR_RESULT_QUEUED);
  1599. PlsrProcess();
  1600. /* Complete the 10ms direction-settle interval. */
  1601. for (ticks = 0; ticks < 10; ticks++)
  1602. {
  1603. PlsrProcess();
  1604. }
  1605. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1606. /* Convert the current frequency into simulated hardware updates over
  1607. * each 1ms process tick. This also models the falling pulse density
  1608. * during the controlled stop. */
  1609. status = TestGetStatus();
  1610. for (ticks = 0; ticks < 600; ticks++)
  1611. {
  1612. pulseAccumulator += PlsrHwGetCurrentFrequencyHz(0U);
  1613. while ((pulseAccumulator >= 1000UL)
  1614. && (PlsrHwIsPulseActive(0U) != 0U))
  1615. {
  1616. PlsrHwTestTriggerUpdate(0U);
  1617. pulseAccumulator -= 1000UL;
  1618. }
  1619. PlsrProcess();
  1620. status = TestGetStatus();
  1621. if (status.state == PLSR_STATE_STOPPED)
  1622. {
  1623. break;
  1624. }
  1625. }
  1626. status = TestGetStatus();
  1627. CHECK(status.state == PLSR_STATE_STOPPED);
  1628. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1629. CHECK(status.error == PLSR_ERROR_LIMIT_POSITIVE);
  1630. CHECK(status.emergencyLatched == 0U);
  1631. CHECK(status.logicalPosition >= 499);
  1632. CHECK(status.logicalPosition <= 501);
  1633. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1634. CHECK(PlcDeviceReadSd(1010U, &value) == PLC_DEVICE_OK);
  1635. CHECK(value == 5U);
  1636. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1637. CHECK(eventRecord.count == 1UL);
  1638. CHECK(eventRecord.pending != 0U);
  1639. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1640. }
  1641. static void TestFourAxisSelfTest(void)
  1642. {
  1643. static const uint32_t expectedFrequency[PLSR_AXIS_COUNT] =
  1644. {
  1645. 1000UL, 2000UL, 3000UL, 4000UL
  1646. };
  1647. static const int32_t expectedPulses[PLSR_AXIS_COUNT] =
  1648. {
  1649. 1000, 2000, 3000, 4000
  1650. };
  1651. PLC_DEVICE_EVENT_RECORD eventRecord;
  1652. PLSR_RESOURCE_STATUS resources;
  1653. PLSR_STATUS status;
  1654. int32_t hsdPulses;
  1655. int subTick;
  1656. int ticks;
  1657. uint8_t axis;
  1658. TestResetEnvironment();
  1659. CHECK(PlsrFourAxisSelfTestQueue() == PLSR_RESULT_QUEUED);
  1660. PlsrProcess();
  1661. for (ticks = 0; ticks < 10; ticks++)
  1662. {
  1663. PlsrProcess();
  1664. }
  1665. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  1666. {
  1667. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1668. CHECK(status.state == PLSR_STATE_RUN);
  1669. CHECK(status.outputMode == PLSR_OUTPUT_PULSE_DIR);
  1670. CHECK(status.directionPoint == (uint8_t)(4U + axis));
  1671. CHECK(status.directionPositive != 0U);
  1672. CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_RUNNING);
  1673. CHECK(PlsrHwGetCurrentFrequencyHz(axis)
  1674. == expectedFrequency[axis]);
  1675. CHECK(status.hardwareCounter == ((axis < 2U) ? 1U : 0U));
  1676. }
  1677. /* A 0.25ms base slot produces 1/2/3/4kHz update ratios while all four
  1678. * hardware channels are active concurrently for one simulated second. */
  1679. for (subTick = 0; subTick < 4000; subTick++)
  1680. {
  1681. if ((subTick & 3) == 0)
  1682. {
  1683. PlsrHwTestTriggerUpdate(0U);
  1684. }
  1685. if ((subTick & 1) == 0)
  1686. {
  1687. PlsrHwTestTriggerUpdate(1U);
  1688. }
  1689. if ((subTick & 3) != 3)
  1690. {
  1691. PlsrHwTestTriggerUpdate(2U);
  1692. }
  1693. PlsrHwTestTriggerUpdate(3U);
  1694. if ((subTick & 3) == 3)
  1695. {
  1696. PlsrProcess();
  1697. }
  1698. }
  1699. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  1700. {
  1701. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1702. CHECK(status.state == PLSR_STATE_COMPLETED);
  1703. CHECK(status.stopReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  1704. CHECK(status.done != 0U);
  1705. CHECK(status.logicalPosition == expectedPulses[axis]);
  1706. CHECK(status.taskPulses == expectedPulses[axis]);
  1707. CHECK(status.totalPulses == expectedPulses[axis]);
  1708. CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_IDLE);
  1709. CHECK(PlcDeviceReadHsdDword((uint16_t)(axis * 4U),
  1710. &hsdPulses) == PLC_DEVICE_OK);
  1711. CHECK(hsdPulses == expectedPulses[axis]);
  1712. CHECK(PlcDeviceReadEvent((uint16_t)(6000U
  1713. + (uint16_t)axis * 100U),
  1714. &eventRecord) == PLC_DEVICE_OK);
  1715. CHECK(eventRecord.count == 1UL);
  1716. CHECK(eventRecord.pending != 0U);
  1717. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  1718. }
  1719. PlsrResourceGetStatus(&resources);
  1720. CHECK(resources.outputMask == 0UL);
  1721. CHECK(resources.highMask == 0U);
  1722. CHECK(PlsrResourceCheckInvariant() != 0U);
  1723. }
  1724. static void TestBacklashSelfTest(void)
  1725. {
  1726. PLC_DEVICE_EVENT_RECORD eventRecord;
  1727. PLSR_STATUS status;
  1728. int32_t hsdPosition;
  1729. int ticks;
  1730. TestResetEnvironment();
  1731. CHECK(PlsrBacklashSelfTestQueue() == PLSR_RESULT_QUEUED);
  1732. PlsrProcess();
  1733. for (ticks = 0; ticks < 10; ticks++)
  1734. {
  1735. PlsrProcess();
  1736. }
  1737. /* Segment 1: +200 user pulses, with no compensation on first motion. */
  1738. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1739. for (ticks = 0; ticks < 200; ticks++)
  1740. {
  1741. PlsrHwTestTriggerUpdate(0U);
  1742. }
  1743. PlsrProcess();
  1744. status = TestGetStatus();
  1745. CHECK(status.currentSegment == 2U);
  1746. CHECK(status.backlashActive != 0U);
  1747. CHECK(status.directionPositive == 0U);
  1748. CHECK(status.logicalPosition == 200);
  1749. CHECK(status.taskPulses == 200);
  1750. CHECK(status.totalPulses == 200);
  1751. CHECK(status.physicalPulses == 200UL);
  1752. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1753. CHECK(eventRecord.count == 1UL);
  1754. CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
  1755. CHECK(eventRecord.count == 0UL);
  1756. /* Direction change to negative: 20 physical compensation pulses first. */
  1757. for (ticks = 0; ticks < 10; ticks++)
  1758. {
  1759. PlsrProcess();
  1760. }
  1761. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1762. for (ticks = 0; ticks < 20; ticks++)
  1763. {
  1764. PlsrHwTestTriggerUpdate(0U);
  1765. }
  1766. PlsrProcess();
  1767. status = TestGetStatus();
  1768. CHECK(status.backlashActive == 0U);
  1769. CHECK(status.currentSegment == 2U);
  1770. CHECK(status.logicalPosition == 200);
  1771. CHECK(status.taskPulses == 200);
  1772. CHECK(status.totalPulses == 200);
  1773. CHECK(status.physicalPulses == 220UL);
  1774. CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
  1775. CHECK(eventRecord.count == 0UL);
  1776. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1777. /* The real segment 2 contributes -200 to user position/counting. */
  1778. for (ticks = 0; ticks < 200; ticks++)
  1779. {
  1780. PlsrHwTestTriggerUpdate(0U);
  1781. }
  1782. PlsrProcess();
  1783. status = TestGetStatus();
  1784. CHECK(status.currentSegment == 3U);
  1785. CHECK(status.backlashActive != 0U);
  1786. CHECK(status.directionPositive != 0U);
  1787. CHECK(status.logicalPosition == 0);
  1788. CHECK(status.taskPulses == 0);
  1789. CHECK(status.totalPulses == 400);
  1790. CHECK(status.physicalPulses == 420UL);
  1791. CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
  1792. CHECK(eventRecord.count == 1UL);
  1793. CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
  1794. CHECK(eventRecord.count == 0UL);
  1795. /* Direction change back to positive: 10 compensation, then +100 user. */
  1796. for (ticks = 0; ticks < 10; ticks++)
  1797. {
  1798. PlsrProcess();
  1799. }
  1800. for (ticks = 0; ticks < 10; ticks++)
  1801. {
  1802. PlsrHwTestTriggerUpdate(0U);
  1803. }
  1804. PlsrProcess();
  1805. status = TestGetStatus();
  1806. CHECK(status.backlashActive == 0U);
  1807. CHECK(status.logicalPosition == 0);
  1808. CHECK(status.totalPulses == 400);
  1809. CHECK(status.physicalPulses == 430UL);
  1810. CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
  1811. CHECK(eventRecord.count == 0UL);
  1812. for (ticks = 0; ticks < 100; ticks++)
  1813. {
  1814. PlsrHwTestTriggerUpdate(0U);
  1815. }
  1816. PlsrProcess();
  1817. status = TestGetStatus();
  1818. CHECK(status.state == PLSR_STATE_COMPLETED);
  1819. CHECK(status.done != 0U);
  1820. CHECK(status.logicalPosition == 100);
  1821. CHECK(status.taskPulses == 100);
  1822. CHECK(status.totalPulses == 500);
  1823. CHECK(status.physicalPulses == 530UL);
  1824. CHECK(PlcDeviceReadHsdDword(0U, &hsdPosition) == PLC_DEVICE_OK);
  1825. CHECK(hsdPosition == 100);
  1826. CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
  1827. CHECK(eventRecord.count == 1UL);
  1828. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  1829. }
  1830. static void TestDirectionLogicSelfTest(void)
  1831. {
  1832. static const uint8_t expectedDirectionPoint[2] = {4U, 3U};
  1833. PLC_DEVICE_EVENT_RECORD eventRecord;
  1834. PLSR_STATUS status;
  1835. uint8_t smDirection;
  1836. uint8_t axis;
  1837. int ticks;
  1838. TestResetEnvironment();
  1839. CHECK(PlsrDirectionLogicSelfTestQueue() == PLSR_RESULT_QUEUED);
  1840. PlsrProcess();
  1841. for (ticks = 0; ticks < 10; ticks++)
  1842. {
  1843. PlsrProcess();
  1844. }
  1845. /* Both axes move logically positive. Electrical DIR terminals are
  1846. * complementary because axis 1 has SFD1030 Bit1 set. */
  1847. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  1848. CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
  1849. for (axis = 0U; axis < 2U; axis++)
  1850. {
  1851. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1852. CHECK(status.state == PLSR_STATE_RUN);
  1853. CHECK(status.directionPoint == expectedDirectionPoint[axis]);
  1854. CHECK(status.directionPositive != 0U);
  1855. CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_RUNNING);
  1856. }
  1857. for (ticks = 0; ticks < 200; ticks++)
  1858. {
  1859. PlsrHwTestTriggerUpdate(0U);
  1860. PlsrHwTestTriggerUpdate(1U);
  1861. }
  1862. PlsrProcess();
  1863. /* Both reverse logically; only the physical terminal mapping differs. */
  1864. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  1865. CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
  1866. for (axis = 0U; axis < 2U; axis++)
  1867. {
  1868. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1869. CHECK(status.currentSegment == 2U);
  1870. CHECK(status.directionPositive == 0U);
  1871. CHECK(status.logicalPosition == 200);
  1872. CHECK(status.totalPulses == 200);
  1873. CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_DIR_SETTLING);
  1874. }
  1875. for (ticks = 0; ticks < 10; ticks++)
  1876. {
  1877. PlsrProcess();
  1878. }
  1879. for (ticks = 0; ticks < 200; ticks++)
  1880. {
  1881. PlsrHwTestTriggerUpdate(0U);
  1882. PlsrHwTestTriggerUpdate(1U);
  1883. }
  1884. PlsrProcess();
  1885. for (axis = 0U; axis < 2U; axis++)
  1886. {
  1887. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1888. CHECK(status.state == PLSR_STATE_COMPLETED);
  1889. CHECK(status.done != 0U);
  1890. CHECK(status.directionPositive == 0U);
  1891. CHECK(status.logicalPosition == 0);
  1892. CHECK(status.taskPulses == 0);
  1893. CHECK(status.totalPulses == 400);
  1894. CHECK(status.physicalPulses == 400UL);
  1895. CHECK(PlcDeviceReadSm((uint16_t)(1001U
  1896. + (uint16_t)axis * 20U),
  1897. &smDirection) == PLC_DEVICE_OK);
  1898. CHECK(smDirection == 0U);
  1899. CHECK(PlcDeviceReadEvent((uint16_t)(6000U
  1900. + (uint16_t)axis * 100U),
  1901. &eventRecord) == PLC_DEVICE_OK);
  1902. CHECK(eventRecord.count == 1UL);
  1903. CHECK(PlcDeviceReadEvent((uint16_t)(6001U
  1904. + (uint16_t)axis * 100U),
  1905. &eventRecord) == PLC_DEVICE_OK);
  1906. CHECK(eventRecord.count == 1UL);
  1907. }
  1908. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  1909. CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
  1910. }
  1911. static void TestCwCcwSelfTest(void)
  1912. {
  1913. PLC_DEVICE_EVENT_RECORD eventRecord;
  1914. PLSR_STATUS status;
  1915. int pulse;
  1916. TestResetEnvironment();
  1917. CHECK(PlsrCwCcwSelfTestQueue() == PLSR_RESULT_QUEUED);
  1918. PlsrProcess();
  1919. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1920. CHECK(status.state == PLSR_STATE_RUN);
  1921. CHECK(status.outputMode == PLSR_OUTPUT_CW_CCW);
  1922. CHECK(status.directionPositive != 0U);
  1923. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  1924. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  1925. for (pulse = 0; pulse < 300; pulse++)
  1926. {
  1927. PlsrHwTestTriggerCompare(0U);
  1928. }
  1929. PlsrHwTestTriggerUpdate(0U);
  1930. PlsrProcess();
  1931. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1932. CHECK(status.currentSegment == 2U);
  1933. CHECK(status.directionPositive == 0U);
  1934. CHECK(status.logicalPosition == 300);
  1935. CHECK(status.totalPulses == 300);
  1936. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  1937. CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
  1938. for (pulse = 0; pulse < 200; pulse++)
  1939. {
  1940. PlsrHwTestTriggerCompare(1U);
  1941. }
  1942. PlsrHwTestTriggerUpdate(1U);
  1943. PlsrProcess();
  1944. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1945. CHECK(status.state == PLSR_STATE_COMPLETED);
  1946. CHECK(status.done != 0U);
  1947. CHECK(status.logicalPosition == 100);
  1948. CHECK(status.taskPulses == 100);
  1949. CHECK(status.totalPulses == 500);
  1950. CHECK(status.physicalPulses == 500UL);
  1951. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  1952. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  1953. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1954. CHECK(eventRecord.count == 1UL);
  1955. CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
  1956. CHECK(eventRecord.count == 1UL);
  1957. }
  1958. static void TestFastRefreshSelfTest(void)
  1959. {
  1960. PLSR_STATUS status;
  1961. uint32_t beforeFastHz;
  1962. uint16_t refreshCode;
  1963. int tick;
  1964. TestResetEnvironment();
  1965. CHECK(PlsrFastRefreshSelfTestQueue() == PLSR_RESULT_QUEUED);
  1966. PlsrProcess();
  1967. for (tick = 0; tick < 10; tick++)
  1968. {
  1969. PlsrProcess();
  1970. }
  1971. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1972. CHECK(status.state == PLSR_STATE_ACCEL);
  1973. CHECK(status.directionPoint == 4U);
  1974. CHECK(PlsrHwGetCurrentFrequencyHz(0U) > 0UL);
  1975. CHECK(PlsrGetStatus(1U, &status) == PLSR_RESULT_OK);
  1976. CHECK(status.state == PLSR_STATE_ACCEL);
  1977. CHECK(status.directionPoint == 3U);
  1978. CHECK(PlsrTestGetJobRefreshCode(1U) == 2U);
  1979. CHECK(PlsrTestGetProfileRefreshHz(1U) == 10000UL);
  1980. beforeFastHz = PlsrTestGetProfileFrequencyHz(1U);
  1981. PlsrControlTick100us();
  1982. CHECK(PlsrTestGetProfileFrequencyHz(1U) > beforeFastHz);
  1983. CHECK(PlcDeviceReadSfd(964U, &refreshCode) == PLC_DEVICE_OK);
  1984. CHECK(refreshCode == 0U);
  1985. CHECK(PlcDeviceReadSfd(1094U, &refreshCode) == PLC_DEVICE_OK);
  1986. CHECK(refreshCode == 2U);
  1987. }
  1988. static void TestDynamicFrequencySelfTest(void)
  1989. {
  1990. PLSR_STATUS status;
  1991. int tick;
  1992. TestResetEnvironment();
  1993. CHECK(PlsrDynamicFrequencySelfTestQueue() == PLSR_RESULT_QUEUED);
  1994. PlsrProcess();
  1995. for (tick = 0; tick < 10; tick++)
  1996. {
  1997. PlsrProcess();
  1998. }
  1999. PlsrControlTick100us();
  2000. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  2001. CHECK(status.currentFrequencyHz == 1000UL);
  2002. CHECK(status.targetFrequencyHz == 1000UL);
  2003. PlsrSelfTestLiveFrequencyHz = 4000;
  2004. PlsrControlTick100us();
  2005. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  2006. CHECK(status.currentFrequencyHz == 1001UL);
  2007. CHECK(status.targetFrequencyHz == 4000UL);
  2008. PlsrSelfTestLiveFrequencyHz = 500;
  2009. PlsrControlTick100us();
  2010. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  2011. CHECK(status.currentFrequencyHz == 1000UL);
  2012. CHECK(status.targetFrequencyHz == 500UL);
  2013. CHECK(status.liveFrequencyRejectCount == 0UL);
  2014. }
  2015. static void TestDynamicFrequencySchedule(void)
  2016. {
  2017. int tick;
  2018. TestResetEnvironment();
  2019. CHECK(PlsrDynamicFrequencySelfTestQueue() == PLSR_RESULT_QUEUED);
  2020. CHECK(PlsrSelfTestLiveFrequencyHz == 1000);
  2021. CHECK(PlsrSelfTestDynamicPhase == 0U);
  2022. for (tick = 0; tick < 9999; tick++)
  2023. {
  2024. PlsrSelfTestControlTick100us();
  2025. }
  2026. CHECK(PlsrSelfTestLiveFrequencyHz == 1000);
  2027. PlsrSelfTestControlTick100us();
  2028. CHECK(PlsrSelfTestLiveFrequencyHz == 4000);
  2029. CHECK(PlsrSelfTestDynamicPhase == 1U);
  2030. for (tick = 0; tick < 5000; tick++)
  2031. {
  2032. PlsrSelfTestControlTick100us();
  2033. }
  2034. CHECK(PlsrSelfTestLiveFrequencyHz == 500);
  2035. CHECK(PlsrSelfTestDynamicPhase == 2U);
  2036. for (tick = 0; tick < 5000; tick++)
  2037. {
  2038. PlsrSelfTestControlTick100us();
  2039. }
  2040. CHECK(PlsrSelfTestLiveFrequencyHz == 0);
  2041. CHECK(PlsrSelfTestDynamicPhase == 3U);
  2042. for (tick = 0; tick < 2000; tick++)
  2043. {
  2044. PlsrSelfTestControlTick100us();
  2045. }
  2046. CHECK(PlsrSelfTestLiveFrequencyHz == 8000);
  2047. CHECK(PlsrSelfTestDynamicPhase == 4U);
  2048. for (tick = 0; tick < 5000; tick++)
  2049. {
  2050. PlsrSelfTestControlTick100us();
  2051. }
  2052. CHECK(PlsrSelfTestLiveFrequencyHz == -1);
  2053. CHECK(PlsrSelfTestDynamicPhase == 5U);
  2054. for (tick = 0; tick < 2000; tick++)
  2055. {
  2056. PlsrSelfTestControlTick100us();
  2057. }
  2058. CHECK(PlsrSelfTestLiveFrequencyHz == 2000);
  2059. CHECK(PlsrSelfTestDynamicPhase == 6U);
  2060. CHECK(PlsrSelfTestDynamicTick100us == 29000UL);
  2061. PlsrSelfTestControlTick100us();
  2062. CHECK(PlsrSelfTestDynamicTick100us == 29000UL);
  2063. }
  2064. static void TestModbusDataSelfTest(void)
  2065. {
  2066. PLSR_STATUS status;
  2067. uint16_t frequencyWords[2];
  2068. uint16_t word;
  2069. int tick;
  2070. TestResetEnvironment();
  2071. CHECK(PlsrModbusDataSelfTestQueue() == PLSR_RESULT_QUEUED);
  2072. PlsrProcess();
  2073. for (tick = 0; tick < 10; tick++)
  2074. {
  2075. PlsrProcess();
  2076. }
  2077. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D, 1000UL, &word) == 1U);
  2078. CHECK(word == 1U);
  2079. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  2080. CHECK((status.state == PLSR_STATE_ACCEL) || (status.state == PLSR_STATE_RUN));
  2081. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  2082. CHECK(status.currentFrequencyHz == 1000UL);
  2083. CHECK(status.targetFrequencyHz == 1000UL);
  2084. frequencyWords[0] = 4000U;
  2085. frequencyWords[1] = 0U;
  2086. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2087. 1010UL,
  2088. frequencyWords,
  2089. 2UL) == 1U);
  2090. PlsrControlTick100us();
  2091. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  2092. CHECK(status.currentFrequencyHz == 1001UL);
  2093. CHECK(status.targetFrequencyHz == 4000UL);
  2094. CHECK(status.liveFrequencyRejectCount == 0UL);
  2095. frequencyWords[0] = 0xFFFFU;
  2096. frequencyWords[1] = 0xFFFFU;
  2097. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2098. 1010UL,
  2099. frequencyWords,
  2100. 2UL) == 1U);
  2101. PlsrControlTick100us();
  2102. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  2103. CHECK(status.targetFrequencyHz == 4000UL);
  2104. CHECK(status.liveFrequencyRejectCount == 1UL);
  2105. CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_INVALID_FREQUENCY);
  2106. }
  2107. static void TestModbusControlProtocol(void)
  2108. {
  2109. const uint32_t controlBase = 1200UL;
  2110. const uint32_t s0Base = 1600UL;
  2111. const uint32_t s1Base = 1700UL;
  2112. uint16_t s0Words[20] = {0U};
  2113. uint16_t s1Words[4] = {0U};
  2114. uint16_t callRequest[16] = {0U};
  2115. uint16_t callResponse[12];
  2116. uint16_t commandRequest[8] = {0U};
  2117. uint16_t commandResponse[8];
  2118. uint16_t controlHeader[8];
  2119. uint16_t performanceWords[8];
  2120. uint16_t stagePerformanceWords[PLSR_MODBUS_STAGE_PERFORMANCE_WORDS];
  2121. uint16_t usbDiagnosticsWords[PLSR_MODBUS_USB_DIAGNOSTICS_WORDS];
  2122. uint16_t axisStatus[48];
  2123. uint16_t pulseWords[2];
  2124. uint32_t generationBegin;
  2125. uint32_t generationEnd;
  2126. PLSR_STATUS coreStatus;
  2127. int64_t pausedPulses;
  2128. int tick;
  2129. TestResetEnvironment();
  2130. CHECK(PlsrModbusControlSelfTestPrepare() == PLSR_RESULT_OK);
  2131. CHECK(PlsrModbusControlInit((uint16_t)controlBase) == PLSR_RESULT_OK);
  2132. CHECK(PlsrModbusControlIsEnabled() == 1U);
  2133. CHECK(PlsrModbusControlGetBaseAddress() == controlBase);
  2134. for (tick = 0; tick < 8; tick++)
  2135. {
  2136. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2137. controlBase + (uint32_t)tick,
  2138. &controlHeader[tick]) == 1U);
  2139. CHECK(ModbusDataReadWord(
  2140. MODBUS_DATA_DEVICE_D,
  2141. controlBase + PLSR_MODBUS_PERFORMANCE_OFFSET
  2142. + (uint32_t)tick,
  2143. &performanceWords[tick]) == 1U);
  2144. }
  2145. CHECK(controlHeader[5] == (uint16_t)(168000000UL & 0xFFFFUL));
  2146. CHECK(controlHeader[6] == (uint16_t)(168000000UL >> 16U));
  2147. CHECK(controlHeader[7] == PLSR_MODBUS_PERFORMANCE_VERSION);
  2148. CHECK(controlHeader[3] == (uint16_t)PLSR_MODBUS_WINDOW_WORDS);
  2149. for (tick = 0; tick < 8; tick++)
  2150. {
  2151. CHECK(performanceWords[tick] == 0U);
  2152. }
  2153. for (tick = 0; tick < (int)PLSR_MODBUS_STAGE_PERFORMANCE_WORDS; tick++)
  2154. {
  2155. CHECK(ModbusDataReadWord(
  2156. MODBUS_DATA_DEVICE_D,
  2157. controlBase + PLSR_MODBUS_STAGE_PERFORMANCE_OFFSET
  2158. + (uint32_t)tick,
  2159. &stagePerformanceWords[tick]) == 1U);
  2160. CHECK(stagePerformanceWords[tick] == 0U);
  2161. }
  2162. for (tick = 0; tick < (int)PLSR_MODBUS_USB_DIAGNOSTICS_WORDS; tick++)
  2163. {
  2164. CHECK(ModbusDataReadWord(
  2165. MODBUS_DATA_DEVICE_D,
  2166. controlBase + PLSR_MODBUS_USB_DIAGNOSTICS_OFFSET
  2167. + (uint32_t)tick,
  2168. &usbDiagnosticsWords[tick]) == 1U);
  2169. }
  2170. generationBegin = (uint32_t)usbDiagnosticsWords[0]
  2171. | ((uint32_t)usbDiagnosticsWords[1] << 16U);
  2172. generationEnd = (uint32_t)usbDiagnosticsWords[20]
  2173. | ((uint32_t)usbDiagnosticsWords[21] << 16U);
  2174. CHECK(generationBegin == generationEnd);
  2175. CHECK((generationBegin & 1UL) == 0UL);
  2176. CHECK(usbDiagnosticsWords[2] ==
  2177. PLSR_MODBUS_USB_DIAGNOSTICS_VERSION);
  2178. for (tick = 3; tick < 20; tick++)
  2179. {
  2180. CHECK(usbDiagnosticsWords[tick] == 0U);
  2181. }
  2182. s0Words[0] = 1U;
  2183. s0Words[10] = 2000U;
  2184. s0Words[12] = (uint16_t)(50000UL & 0xFFFFUL);
  2185. s0Words[13] = (uint16_t)(50000UL >> 16U);
  2186. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2187. s0Base,
  2188. s0Words,
  2189. 20UL) == 1U);
  2190. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2191. s1Base,
  2192. s1Words,
  2193. 4UL) == 1U);
  2194. callRequest[0] = 1U;
  2195. callRequest[2] = PLSR_DEVICE_D;
  2196. callRequest[3] = (uint16_t)s0Base;
  2197. callRequest[5] = PLSR_DEVICE_D;
  2198. callRequest[6] = (uint16_t)s1Base;
  2199. callRequest[8] = PLSR_OPERAND_CONSTANT;
  2200. callRequest[10] = 1U;
  2201. callRequest[12] = 0U;
  2202. callRequest[13] = PLSR_OUTPUT_PULSE_DIR;
  2203. callRequest[14] = PLSR_MODBUS_CALL_COMMIT;
  2204. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2205. controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
  2206. callRequest,
  2207. 16UL) == 1U);
  2208. PlsrModbusControlPoll();
  2209. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2210. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET,
  2211. &callResponse[0]) == 1U);
  2212. for (tick = 1; tick < 12; tick++)
  2213. {
  2214. CHECK(ModbusDataReadWord(
  2215. MODBUS_DATA_DEVICE_D,
  2216. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
  2217. + (uint32_t)tick,
  2218. &callResponse[tick]) == 1U);
  2219. }
  2220. CHECK(callResponse[0] == 1U);
  2221. CHECK(callResponse[2] == PLSR_MODBUS_CALL_COMMIT);
  2222. CHECK(callResponse[3] == PLSR_RESULT_OK);
  2223. CHECK(callResponse[11] == 1U);
  2224. /* Any S0 edit after COMMIT invalidates START until a new COMMIT. */
  2225. pulseWords[0] = (uint16_t)(50001UL & 0xFFFFUL);
  2226. pulseWords[1] = (uint16_t)(50001UL >> 16U);
  2227. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2228. s0Base + 12UL,
  2229. pulseWords,
  2230. 2UL) == 1U);
  2231. callRequest[0] = 2U;
  2232. callRequest[14] = PLSR_MODBUS_CALL_START;
  2233. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2234. controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
  2235. callRequest,
  2236. 16UL) == 1U);
  2237. PlsrModbusControlPoll();
  2238. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2239. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
  2240. + 3UL,
  2241. &callResponse[3]) == 1U);
  2242. CHECK(callResponse[3] == PLSR_RESULT_BUSY);
  2243. pulseWords[0] = (uint16_t)(50000UL & 0xFFFFUL);
  2244. pulseWords[1] = (uint16_t)(50000UL >> 16U);
  2245. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2246. s0Base + 12UL,
  2247. pulseWords,
  2248. 2UL) == 1U);
  2249. callRequest[0] = 3U;
  2250. callRequest[14] = PLSR_MODBUS_CALL_COMMIT;
  2251. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2252. controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
  2253. callRequest,
  2254. 16UL) == 1U);
  2255. PlsrModbusControlPoll();
  2256. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2257. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
  2258. + 3UL,
  2259. &callResponse[3]) == 1U);
  2260. CHECK(callResponse[3] == PLSR_RESULT_OK);
  2261. callRequest[0] = 4U;
  2262. callRequest[14] = PLSR_MODBUS_CALL_START;
  2263. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  2264. controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
  2265. callRequest,
  2266. 16UL) == 1U);
  2267. PlsrModbusControlPoll();
  2268. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2269. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
  2270. + 3UL,
  2271. &callResponse[3]) == 1U);
  2272. CHECK(callResponse[3] == PLSR_RESULT_QUEUED);
  2273. for (tick = 0; tick < 10; tick++)
  2274. {
  2275. PlsrProcess();
  2276. }
  2277. PlsrModbusControlPoll();
  2278. for (tick = 0; tick < 48; tick++)
  2279. {
  2280. CHECK(ModbusDataReadWord(
  2281. MODBUS_DATA_DEVICE_D,
  2282. controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET
  2283. + (uint32_t)tick,
  2284. &axisStatus[tick]) == 1U);
  2285. }
  2286. generationBegin = (uint32_t)axisStatus[0]
  2287. | ((uint32_t)axisStatus[1] << 16U);
  2288. generationEnd = (uint32_t)axisStatus[46]
  2289. | ((uint32_t)axisStatus[47] << 16U);
  2290. CHECK(generationBegin == generationEnd);
  2291. CHECK((generationBegin & 1UL) == 0UL);
  2292. CHECK((axisStatus[2] == PLSR_STATE_ACCEL)
  2293. || (axisStatus[2] == PLSR_STATE_RUN));
  2294. CHECK(axisStatus[10] == 4U);
  2295. CHECK(axisStatus[11] == 0U);
  2296. CHECK(axisStatus[8] == PLSR_RESULT_OK);
  2297. CHECK(axisStatus[37] == 1U);
  2298. commandRequest[0] = 10U;
  2299. commandRequest[2] = PLSR_CMD_PAUSE;
  2300. commandRequest[3] = 0U;
  2301. CHECK(ModbusDataWriteWords(
  2302. MODBUS_DATA_DEVICE_D,
  2303. controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
  2304. commandRequest,
  2305. 8UL) == 1U);
  2306. PlsrModbusControlPoll();
  2307. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2308. controlBase + PLSR_MODBUS_COMMAND_RESPONSE_OFFSET
  2309. + 4UL,
  2310. &commandResponse[4]) == 1U);
  2311. CHECK(commandResponse[4] == PLSR_RESULT_QUEUED);
  2312. for (tick = 0; tick < 400; tick++)
  2313. {
  2314. PlsrProcess();
  2315. CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
  2316. if (coreStatus.state == PLSR_STATE_PAUSED)
  2317. {
  2318. break;
  2319. }
  2320. }
  2321. CHECK(coreStatus.state == PLSR_STATE_PAUSED);
  2322. CHECK(coreStatus.currentFrequencyHz == 0UL);
  2323. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  2324. pausedPulses = coreStatus.taskPulses;
  2325. PlsrModbusControlPoll();
  2326. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2327. controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET + 2UL,
  2328. &axisStatus[2]) == 1U);
  2329. CHECK(axisStatus[2] == PLSR_STATE_PAUSED);
  2330. /* Polling an unchanged request sequence must not execute PAUSE twice. */
  2331. PlsrModbusControlPoll();
  2332. commandRequest[0] = 11U;
  2333. commandRequest[2] = PLSR_CMD_RESUME;
  2334. CHECK(ModbusDataWriteWords(
  2335. MODBUS_DATA_DEVICE_D,
  2336. controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
  2337. commandRequest,
  2338. 8UL) == 1U);
  2339. PlsrModbusControlPoll();
  2340. PlsrProcess();
  2341. CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
  2342. CHECK(coreStatus.currentFrequencyHz > 0UL);
  2343. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  2344. for (tick = 0; tick < 10; tick++)
  2345. {
  2346. PlsrHwTestTriggerUpdate(0U);
  2347. }
  2348. PlsrProcess();
  2349. CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
  2350. CHECK(coreStatus.taskPulses == pausedPulses + 10);
  2351. PlsrModbusControlPoll();
  2352. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2353. controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET + 2UL,
  2354. &axisStatus[2]) == 1U);
  2355. CHECK((axisStatus[2] == PLSR_STATE_ACCEL)
  2356. || (axisStatus[2] == PLSR_STATE_RUN));
  2357. commandRequest[0] = 12U;
  2358. commandRequest[2] = PLSR_CMD_STOP_DECEL;
  2359. CHECK(ModbusDataWriteWords(
  2360. MODBUS_DATA_DEVICE_D,
  2361. controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
  2362. commandRequest,
  2363. 8UL) == 1U);
  2364. PlsrModbusControlPoll();
  2365. for (tick = 0; tick < 400; tick++)
  2366. {
  2367. PlsrProcess();
  2368. CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
  2369. if (coreStatus.state == PLSR_STATE_STOPPED)
  2370. {
  2371. break;
  2372. }
  2373. }
  2374. CHECK(coreStatus.state == PLSR_STATE_STOPPED);
  2375. CHECK(coreStatus.currentFrequencyHz == 0UL);
  2376. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  2377. }
  2378. static void TestStopStopsHardware(void)
  2379. {
  2380. TEST_MEMORY memory;
  2381. PLSR_CALL call;
  2382. PLSR_COMMAND command;
  2383. PLSR_STATUS status;
  2384. int ticks;
  2385. TestResetEnvironment();
  2386. (void)memset(&memory, 0, sizeof(memory));
  2387. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  2388. TestSetSegment(&memory, 1U, 1000U, 10000);
  2389. call = TestMakeCall(&memory);
  2390. call.sequence = 20UL;
  2391. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  2392. PlsrProcess();
  2393. for (ticks = 0; ticks < 10; ticks++)
  2394. {
  2395. PlsrProcess();
  2396. }
  2397. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  2398. /* STOP_IMMEDIATE:硬件立即停止。 */
  2399. command.sequence = 21UL;
  2400. command.axis = 0U;
  2401. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  2402. command.argument = 0;
  2403. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  2404. PlsrProcess();
  2405. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  2406. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  2407. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  2408. == PLSR_RESULT_OK);
  2409. PlsrProcess();
  2410. status = TestGetStatus();
  2411. CHECK(status.state == PLSR_STATE_STOPPED);
  2412. }
  2413. int main(void)
  2414. {
  2415. TestMapping();
  2416. TestDirDelaySequence();
  2417. TestDirectionBatch();
  2418. TestHardwareCounterLeases();
  2419. TestCwCcwSequence();
  2420. TestFastRefreshControlTick();
  2421. TestDynamicFrequencyRetarget();
  2422. TestZeroFrequencyWaits();
  2423. TestPulseCounting();
  2424. TestAbPhaseAndCounting();
  2425. TestTwoAbAxesIndependent();
  2426. TestDualAbHardwareCountersAndResume();
  2427. TestDualAbSimultaneousFastGate();
  2428. TestAbFrequencyLimits();
  2429. TestStopAndInvalidArgs();
  2430. TestEndToEndTwoSegments();
  2431. TestEndToEndAbSegment();
  2432. TestPositionOnImmediateStop();
  2433. TestAbsolutePositionAccounting();
  2434. TestEquivalentRemainderAccounting();
  2435. TestEquivalentCompatibleError();
  2436. TestSoftLimitAndSegmentEvent();
  2437. TestHardLimitAndEmergencyLatch();
  2438. TestProductionSelfTestStartsAb();
  2439. TestEquivalentSelfTest();
  2440. TestProtectionSelfTest();
  2441. TestFourAxisSelfTest();
  2442. TestBacklashSelfTest();
  2443. TestDirectionLogicSelfTest();
  2444. TestCwCcwSelfTest();
  2445. TestFastRefreshSelfTest();
  2446. TestDynamicFrequencySelfTest();
  2447. TestDynamicFrequencySchedule();
  2448. TestModbusDataSelfTest();
  2449. TestModbusControlProtocol();
  2450. TestStopStopsHardware();
  2451. if (TestFailures != 0)
  2452. {
  2453. (void)printf("FAIL: %d of %d PLSR HAL checks failed\n",
  2454. TestFailures,
  2455. TestChecks);
  2456. return 1;
  2457. }
  2458. (void)printf("PASS: %d PLSR HAL checks\n", TestChecks);
  2459. return 0;
  2460. }