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

744 řádky
24 KiB

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