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

683 rivejä
22 KiB

  1. #include "plc_device.h"
  2. #include "plsr_core.h"
  3. #include "plsr_job.h"
  4. #include "plsr_path.h"
  5. #include "plsr_persistence.h"
  6. #include <stdio.h>
  7. #include <string.h>
  8. #define TEST_WORD_CAPACITY (3000U)
  9. #define TEST_BIT_CAPACITY (128U)
  10. #define TEST_S0_BASE (100U)
  11. #define TEST_S1_BASE (200U)
  12. #define TEST_SEGMENT_STRIDE (10U)
  13. /* 等待条件编码(信捷):高8位条件、低8位来源。 */
  14. #define TEST_WAIT_CODE(condition, source) \
  15. ((uint16_t)(((uint16_t)(condition) << 8U) | (uint16_t)(source)))
  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. if ((device > PLSR_DEVICE_FD) || (wordCount == 0UL))
  40. {
  41. return 0U;
  42. }
  43. return (((uint64_t)firstAddress + wordCount) <= TEST_WORD_CAPACITY)
  44. ? 1U
  45. : 0U;
  46. }
  47. static uint8_t TestReadWord(void *context,
  48. PLSR_DEVICE_TYPE device,
  49. uint32_t address,
  50. uint16_t *value)
  51. {
  52. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  53. if ((memory == NULL) || (value == NULL) || (device > PLSR_DEVICE_FD)
  54. || (address >= TEST_WORD_CAPACITY))
  55. {
  56. return 0U;
  57. }
  58. *value = memory->words[device][address];
  59. return 1U;
  60. }
  61. static uint8_t TestReadBit(void *context,
  62. PLSR_DEVICE_TYPE device,
  63. uint32_t address,
  64. uint8_t *value)
  65. {
  66. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  67. uint8_t index;
  68. if ((memory == NULL) || (value == NULL) || (device < PLSR_DEVICE_X)
  69. || (device > PLSR_DEVICE_HM) || (address >= TEST_BIT_CAPACITY))
  70. {
  71. return 0U;
  72. }
  73. index = (uint8_t)(device - PLSR_DEVICE_X);
  74. *value = memory->bits[index][address];
  75. return 1U;
  76. }
  77. static void TestWriteDword(TEST_MEMORY *memory,
  78. PLSR_DEVICE_TYPE device,
  79. uint32_t address,
  80. int32_t value)
  81. {
  82. uint32_t raw = (uint32_t)value;
  83. memory->words[device][address] = (uint16_t)(raw & 0xFFFFUL);
  84. memory->words[device][address + 1UL] = (uint16_t)(raw >> 16U);
  85. }
  86. /* 写入一个段的数据块(S0 布局,每段 10 字)。 */
  87. static void TestSetSegment(TEST_MEMORY *memory,
  88. uint16_t number,
  89. uint32_t frequency,
  90. int32_t pulses,
  91. uint16_t waitCode,
  92. int32_t waitValue,
  93. uint16_t jumpSource,
  94. int32_t jumpValue)
  95. {
  96. uint32_t base = TEST_S0_BASE + (uint32_t)number * TEST_SEGMENT_STRIDE;
  97. TestWriteDword(memory, PLSR_DEVICE_D, base, (int32_t)frequency);
  98. TestWriteDword(memory, PLSR_DEVICE_D, base + 2UL, pulses);
  99. memory->words[PLSR_DEVICE_D][base + 4UL] = waitCode;
  100. TestWriteDword(memory, PLSR_DEVICE_D, base + 5UL, waitValue);
  101. memory->words[PLSR_DEVICE_D][base + 7UL] = (uint16_t)jumpSource;
  102. TestWriteDword(memory, PLSR_DEVICE_D, base + 8UL, jumpValue);
  103. }
  104. static void TestResetEnvironment(void)
  105. {
  106. PlsrPersistenceTestResetStorage();
  107. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  108. /* 默认 SFD + 配置方向端子(接线参数,测试用 Y4)。 */
  109. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  110. CHECK(PlsrInit() == PLSR_RESULT_OK);
  111. }
  112. static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
  113. {
  114. PLSR_CALL call;
  115. (void)memset(&call, 0, sizeof(call));
  116. call.sequence = 10UL;
  117. call.source.context = memory;
  118. call.source.validateWords = TestValidateWords;
  119. call.source.readWord = TestReadWord;
  120. call.source.readBit = TestReadBit;
  121. call.s0.device = PLSR_DEVICE_D;
  122. call.s0.address = TEST_S0_BASE;
  123. call.s1.device = PLSR_DEVICE_D;
  124. call.s1.address = TEST_S1_BASE;
  125. call.s2.type = PLSR_OPERAND_CONSTANT;
  126. call.s2.constant = 1;
  127. call.dAxis = 0U;
  128. call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
  129. return call;
  130. }
  131. static PLSR_STATUS TestGetStatus(void)
  132. {
  133. PLSR_STATUS status;
  134. (void)memset(&status, 0, sizeof(status));
  135. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  136. return status;
  137. }
  138. /* 当前段加速完成进入 RUN。 */
  139. static void TestAccelToRun(void)
  140. {
  141. CHECK(PlsrPostEvent(0U, PLSR_EVENT_ACCEL_COMPLETE) == PLSR_RESULT_OK);
  142. PlsrProcess();
  143. CHECK(TestGetStatus().state == PLSR_STATE_RUN);
  144. }
  145. /* 启动一个 N 段任务(全部 H00 完成条件、顺序跳转)。 */
  146. static void TestStartSequentialJob(TEST_MEMORY *memory,
  147. uint16_t segmentCount,
  148. uint32_t sequence)
  149. {
  150. uint16_t segment;
  151. (void)memset(memory, 0, sizeof(*memory));
  152. TestWriteDword(memory, PLSR_DEVICE_D, TEST_S0_BASE, segmentCount);
  153. for (segment = 1U; segment <= segmentCount; segment++)
  154. {
  155. TestSetSegment(memory,
  156. segment,
  157. 1000U + (uint32_t)segment * 1000U,
  158. (int32_t)(segment * 100),
  159. TEST_WAIT_CODE(0U, 0U),
  160. 0,
  161. 0U,
  162. 0);
  163. }
  164. {
  165. PLSR_CALL call = TestMakeCall(memory);
  166. call.sequence = sequence;
  167. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  168. }
  169. PlsrProcess();
  170. CHECK(TestGetStatus().lastCommandResult == PLSR_RESULT_OK);
  171. }
  172. static void TestSequentialSegments(void)
  173. {
  174. TEST_MEMORY memory;
  175. TestResetEnvironment();
  176. TestStartSequentialJob(&memory, 3U, 10UL);
  177. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  178. CHECK(TestGetStatus().currentSegment == 1U);
  179. TestAccelToRun();
  180. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  181. PlsrProcess();
  182. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  183. CHECK(TestGetStatus().currentSegment == 2U);
  184. TestAccelToRun();
  185. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  186. PlsrProcess();
  187. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  188. CHECK(TestGetStatus().currentSegment == 3U);
  189. TestAccelToRun();
  190. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  191. PlsrProcess();
  192. CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
  193. CHECK(TestGetStatus().done != 0U);
  194. }
  195. static void TestJumpToSpecifiedSegment(void)
  196. {
  197. TEST_MEMORY memory;
  198. TestResetEnvironment();
  199. (void)memset(&memory, 0, sizeof(memory));
  200. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 3);
  201. TestSetSegment(&memory, 1U, 1000U, 100, TEST_WAIT_CODE(0U, 0U), 0, 0U, 3);
  202. TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  203. TestSetSegment(&memory, 3U, 3000U, 300, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  204. {
  205. PLSR_CALL call = TestMakeCall(&memory);
  206. call.sequence = 20UL;
  207. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  208. }
  209. PlsrProcess();
  210. CHECK(TestGetStatus().currentSegment == 1U);
  211. /* 段1 完成 → 跳到段3(跳过段2)。 */
  212. TestAccelToRun();
  213. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  214. PlsrProcess();
  215. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  216. CHECK(TestGetStatus().currentSegment == 3U);
  217. /* 段3 完成 → 顺序下一段超出 → 任务结束。 */
  218. TestAccelToRun();
  219. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  220. PlsrProcess();
  221. CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
  222. }
  223. static void TestWaitTime(void)
  224. {
  225. TEST_MEMORY memory;
  226. int ticks;
  227. TestResetEnvironment();
  228. (void)memset(&memory, 0, sizeof(memory));
  229. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  230. TestSetSegment(&memory, 1U, 1000U, 100,
  231. TEST_WAIT_CODE(1U, 0U), 200, 0U, 0);
  232. TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  233. {
  234. PLSR_CALL call = TestMakeCall(&memory);
  235. call.sequence = 30UL;
  236. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  237. }
  238. PlsrProcess();
  239. TestAccelToRun();
  240. /* 段1 完成 → 进入 WAIT(等 200ms)。 */
  241. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  242. PlsrProcess();
  243. CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
  244. /* 事件处理同轮已递减 1ms:198 个 tick 后仍在等待。 */
  245. for (ticks = 0; ticks < 198; ticks++)
  246. {
  247. PlsrProcess();
  248. }
  249. CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
  250. CHECK(TestGetStatus().currentSegment == 1U);
  251. /* 第 200 个 tick:计时到,跳到段2。 */
  252. PlsrProcess();
  253. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  254. CHECK(TestGetStatus().currentSegment == 2U);
  255. }
  256. static void TestWaitSignal(void)
  257. {
  258. TEST_MEMORY memory;
  259. TestResetEnvironment();
  260. (void)memset(&memory, 0, sizeof(memory));
  261. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  262. TestSetSegment(&memory, 1U, 1000U, 100,
  263. TEST_WAIT_CODE(2U, 5U), 10, 0U, 0);
  264. TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  265. {
  266. PLSR_CALL call = TestMakeCall(&memory);
  267. call.sequence = 40UL;
  268. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  269. }
  270. PlsrProcess();
  271. TestAccelToRun();
  272. /* 段1 完成 → 等 M10(当前 OFF)。 */
  273. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  274. PlsrProcess();
  275. CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
  276. /* 信号仍 OFF:不跳转。 */
  277. PlsrProcess();
  278. PlsrProcess();
  279. CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
  280. /* 信号置 ON:tick 轮询到后跳段。 */
  281. memory.bits[1U][10U] = 1U; /* M10 */
  282. PlsrProcess();
  283. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  284. CHECK(TestGetStatus().currentSegment == 2U);
  285. }
  286. static void TestActTruncatesSegment(void)
  287. {
  288. TEST_MEMORY memory;
  289. int ticks;
  290. TestResetEnvironment();
  291. (void)memset(&memory, 0, sizeof(memory));
  292. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  293. TestSetSegment(&memory, 1U, 1000U, 100,
  294. TEST_WAIT_CODE(3U, 0U), 200, 0U, 0);
  295. TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  296. {
  297. PLSR_CALL call = TestMakeCall(&memory);
  298. call.sequence = 50UL;
  299. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  300. }
  301. PlsrProcess();
  302. TestAccelToRun();
  303. /* 不注入 SEGMENT_COMPLETE:ACT 200ms 到时截断当前段。 */
  304. for (ticks = 0; ticks < 200; ticks++)
  305. {
  306. PlsrProcess();
  307. }
  308. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  309. CHECK(TestGetStatus().currentSegment == 2U);
  310. }
  311. static void TestActPendingAfterSegmentDone(void)
  312. {
  313. TEST_MEMORY memory;
  314. int ticks;
  315. TestResetEnvironment();
  316. (void)memset(&memory, 0, sizeof(memory));
  317. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  318. TestSetSegment(&memory, 1U, 1000U, 100,
  319. TEST_WAIT_CODE(3U, 0U), 200, 0U, 0);
  320. TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  321. {
  322. PLSR_CALL call = TestMakeCall(&memory);
  323. call.sequence = 60UL;
  324. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  325. }
  326. PlsrProcess();
  327. TestAccelToRun();
  328. /* 段脉冲先完成(ACT 还剩 199ms)→ 停在 ACT_PENDING(WAIT 状态)。 */
  329. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  330. PlsrProcess();
  331. CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
  332. /* ACT 到时 → 跳段2。 */
  333. for (ticks = 0; ticks < 199; ticks++)
  334. {
  335. PlsrProcess();
  336. }
  337. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  338. CHECK(TestGetStatus().currentSegment == 2U);
  339. }
  340. static void TestExtEdgeTruncates(void)
  341. {
  342. TEST_MEMORY memory;
  343. int ticks;
  344. TestResetEnvironment();
  345. (void)memset(&memory, 0, sizeof(memory));
  346. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  347. TestSetSegment(&memory, 1U, 1000U, 100,
  348. TEST_WAIT_CODE(4U, 4U), 0, 0U, 0);
  349. TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  350. /* X0 在任务开始前就有效:进入段时记录为已有电平,不算新边沿。 */
  351. memory.bits[0U][0U] = 1U;
  352. {
  353. PLSR_CALL call = TestMakeCall(&memory);
  354. call.sequence = 70UL;
  355. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  356. }
  357. PlsrProcess();
  358. TestAccelToRun();
  359. /* X0 持续 ON:没有新边沿,不应触发。 */
  360. for (ticks = 0; ticks < 5; ticks++)
  361. {
  362. PlsrProcess();
  363. }
  364. CHECK(TestGetStatus().state == PLSR_STATE_RUN);
  365. CHECK(TestGetStatus().currentSegment == 1U);
  366. /* 先拉低再拉高:新上升沿,截断当前段。 */
  367. memory.bits[0U][0U] = 0U;
  368. PlsrProcess();
  369. memory.bits[0U][0U] = 1U;
  370. PlsrProcess();
  371. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  372. CHECK(TestGetStatus().currentSegment == 2U);
  373. }
  374. static void TestExtOrComplete(void)
  375. {
  376. TEST_MEMORY memory;
  377. TestResetEnvironment();
  378. (void)memset(&memory, 0, sizeof(memory));
  379. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  380. TestSetSegment(&memory, 1U, 1000U, 100,
  381. TEST_WAIT_CODE(5U, 4U), 0, 0U, 0);
  382. TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  383. {
  384. PLSR_CALL call = TestMakeCall(&memory);
  385. call.sequence = 80UL;
  386. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  387. }
  388. PlsrProcess();
  389. TestAccelToRun();
  390. /* 段脉冲先完成 → 正常跳段(EXT 或完成)。 */
  391. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  392. PlsrProcess();
  393. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  394. CHECK(TestGetStatus().currentSegment == 2U);
  395. }
  396. static void TestDynamicJump(void)
  397. {
  398. TEST_MEMORY memory;
  399. TestResetEnvironment();
  400. (void)memset(&memory, 0, sizeof(memory));
  401. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 3);
  402. TestSetSegment(&memory, 1U, 1000U, 100,
  403. TEST_WAIT_CODE(0U, 0U), 0, 0U, 3);
  404. TestSetSegment(&memory, 2U, 2000U, 200, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  405. /* 段3 跳转也来自 D300(初始 3 = 自跳转,运行期改非法值验证越界)。 */
  406. TestSetSegment(&memory, 3U, 3000U, 300,
  407. TEST_WAIT_CODE(0U, 0U), 0, 1U, 300);
  408. TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 3);
  409. {
  410. PLSR_CALL call = TestMakeCall(&memory);
  411. call.sequence = 90UL;
  412. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  413. }
  414. PlsrProcess();
  415. TestAccelToRun();
  416. /* 段1 完成:跳到段3。 */
  417. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  418. PlsrProcess();
  419. CHECK(TestGetStatus().currentSegment == 3U);
  420. /* 段3 完成前把 D300 改成非法值 → 运行期错误 → ERROR。 */
  421. TestAccelToRun();
  422. TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 99);
  423. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  424. PlsrProcess();
  425. CHECK(TestGetStatus().state == PLSR_STATE_ERROR);
  426. }
  427. static void TestAbsoluteZeroDisplacement(void)
  428. {
  429. TEST_MEMORY memory;
  430. PLSR_COMMAND command;
  431. TestResetEnvironment();
  432. (void)memset(&memory, 0, sizeof(memory));
  433. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  434. /* S1+0 = 1:绝对模式。 */
  435. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 1);
  436. /* 段1 目标 0(=当前位置 0,零位移);段2 目标 5000。 */
  437. TestSetSegment(&memory, 1U, 1000U, 0,
  438. TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  439. TestSetSegment(&memory, 2U, 2000U, 5000,
  440. TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  441. /* 绝对定位需要 positionValid:先 SET_POSITION(0)。 */
  442. command.sequence = 91UL;
  443. command.axis = 0U;
  444. command.opcode = PLSR_CMD_SET_POSITION;
  445. command.argument = 0;
  446. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  447. PlsrProcess();
  448. {
  449. PLSR_CALL call = TestMakeCall(&memory);
  450. call.sequence = 92UL;
  451. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  452. }
  453. PlsrProcess();
  454. /* 起点段1 零位移:直接跳过,从段2 开始发脉冲。 */
  455. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  456. CHECK(TestGetStatus().currentSegment == 2U);
  457. }
  458. static void TestZeroJumpBudgetYields(void)
  459. {
  460. TEST_MEMORY memory;
  461. int rounds;
  462. TestResetEnvironment();
  463. (void)memset(&memory, 0, sizeof(memory));
  464. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 3);
  465. /* 段1:零脉冲,跳到段2;段2:零脉冲,动态跳转(初始自跳转);段3:正常段。 */
  466. TestSetSegment(&memory, 1U, 1000U, 0,
  467. TEST_WAIT_CODE(0U, 0U), 0, 0U, 2);
  468. TestSetSegment(&memory, 2U, 1000U, 0,
  469. TEST_WAIT_CODE(0U, 0U), 0, 1U, 300);
  470. TestSetSegment(&memory, 3U, 1000U, 100,
  471. TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  472. TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 2);
  473. {
  474. PLSR_CALL call = TestMakeCall(&memory);
  475. call.sequence = 100UL;
  476. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  477. }
  478. PlsrProcess();
  479. /* 每轮 100 次预算:零脉冲自循环链停在段2 并让出,任务不结束。 */
  480. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  481. CHECK(TestGetStatus().currentSegment == 2U);
  482. CHECK(TestGetStatus().done == 0U);
  483. for (rounds = 0; rounds < 3; rounds++)
  484. {
  485. PlsrProcess();
  486. }
  487. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  488. CHECK(TestGetStatus().currentSegment == 2U);
  489. CHECK(TestGetStatus().done == 0U);
  490. /* 运行中改动态跳转目标 → 链走向段3(有脉冲)→ 正常执行并完成。 */
  491. TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 3);
  492. PlsrProcess();
  493. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  494. CHECK(TestGetStatus().currentSegment == 3U);
  495. TestAccelToRun();
  496. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  497. PlsrProcess();
  498. CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
  499. }
  500. static void TestSelfLoopInterruptedByStop(void)
  501. {
  502. TEST_MEMORY memory;
  503. PLSR_COMMAND command;
  504. TestResetEnvironment();
  505. (void)memset(&memory, 0, sizeof(memory));
  506. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  507. TestSetSegment(&memory, 1U, 1000U, 100,
  508. TEST_WAIT_CODE(0U, 0U), 0, 0U, 1);
  509. {
  510. PLSR_CALL call = TestMakeCall(&memory);
  511. call.sequence = 110UL;
  512. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  513. }
  514. PlsrProcess();
  515. TestAccelToRun();
  516. /* 段1 完成 → 自跳转回段1。 */
  517. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  518. PlsrProcess();
  519. CHECK(TestGetStatus().state == PLSR_STATE_ACCEL);
  520. CHECK(TestGetStatus().currentSegment == 1U);
  521. /* STOP 可打断自循环。 */
  522. command.sequence = 111UL;
  523. command.axis = 0U;
  524. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  525. command.argument = 0;
  526. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  527. PlsrProcess();
  528. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  529. == PLSR_RESULT_OK);
  530. PlsrProcess();
  531. CHECK(TestGetStatus().state == PLSR_STATE_STOPPED);
  532. CHECK(TestGetStatus().done == 0U);
  533. }
  534. static void TestLastSegmentWaitTime(void)
  535. {
  536. TEST_MEMORY memory;
  537. int ticks;
  538. TestResetEnvironment();
  539. (void)memset(&memory, 0, sizeof(memory));
  540. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  541. TestSetSegment(&memory, 1U, 1000U, 100, TEST_WAIT_CODE(0U, 0U), 0, 0U, 0);
  542. /* 最后一段用 WAIT 时间(信捷警告场景:验证不会卡死)。 */
  543. TestSetSegment(&memory, 2U, 2000U, 200,
  544. TEST_WAIT_CODE(1U, 0U), 100, 0U, 0);
  545. {
  546. PLSR_CALL call = TestMakeCall(&memory);
  547. call.sequence = 120UL;
  548. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  549. }
  550. PlsrProcess();
  551. TestAccelToRun();
  552. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  553. PlsrProcess();
  554. TestAccelToRun();
  555. /* 段2(最后一段)完成 → 等待 100ms。 */
  556. CHECK(PlsrPostEvent(0U, PLSR_EVENT_SEGMENT_COMPLETE) == PLSR_RESULT_OK);
  557. PlsrProcess();
  558. CHECK(TestGetStatus().state == PLSR_STATE_WAIT);
  559. /* 计时到 → 任务正常结束。 */
  560. for (ticks = 0; ticks < 100; ticks++)
  561. {
  562. PlsrProcess();
  563. }
  564. CHECK(TestGetStatus().state == PLSR_STATE_COMPLETED);
  565. CHECK(TestGetStatus().done != 0U);
  566. }
  567. int main(void)
  568. {
  569. TestSequentialSegments();
  570. TestJumpToSpecifiedSegment();
  571. TestWaitTime();
  572. TestWaitSignal();
  573. TestActTruncatesSegment();
  574. TestActPendingAfterSegmentDone();
  575. TestExtEdgeTruncates();
  576. TestExtOrComplete();
  577. TestDynamicJump();
  578. TestAbsoluteZeroDisplacement();
  579. TestZeroJumpBudgetYields();
  580. TestSelfLoopInterruptedByStop();
  581. TestLastSegmentWaitTime();
  582. if (TestFailures != 0)
  583. {
  584. (void)printf("FAIL: %d of %d PLSR path checks failed\n",
  585. TestFailures,
  586. TestChecks);
  587. return 1;
  588. }
  589. (void)printf("PASS: %d PLSR path checks\n", TestChecks);
  590. return 0;
  591. }