Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

459 строки
16 KiB

  1. #include "plc_device.h"
  2. #include "plsr_core.h"
  3. #include "plsr_job.h"
  4. #include "plsr_persistence.h"
  5. #include <stdio.h>
  6. #include <string.h>
  7. #define TEST_WORD_CAPACITY (3000U)
  8. #define TEST_BIT_CAPACITY (128U)
  9. typedef struct
  10. {
  11. uint16_t words[3][TEST_WORD_CAPACITY];
  12. uint8_t bits[3][TEST_BIT_CAPACITY];
  13. } TEST_MEMORY;
  14. static int TestFailures;
  15. static int TestChecks;
  16. #define CHECK(condition) \
  17. do \
  18. { \
  19. TestChecks++; \
  20. if (!(condition)) \
  21. { \
  22. TestFailures++; \
  23. (void)printf("FAIL line %d: %s\n", __LINE__, #condition); \
  24. } \
  25. } while (0)
  26. static uint8_t TestValidateWords(void *context,
  27. PLSR_DEVICE_TYPE device,
  28. uint32_t firstAddress,
  29. uint32_t wordCount)
  30. {
  31. (void)context;
  32. if ((device > PLSR_DEVICE_FD) || (wordCount == 0UL))
  33. {
  34. return 0U;
  35. }
  36. return (((uint64_t)firstAddress + wordCount) <= TEST_WORD_CAPACITY)
  37. ? 1U
  38. : 0U;
  39. }
  40. static uint8_t TestReadWord(void *context,
  41. PLSR_DEVICE_TYPE device,
  42. uint32_t address,
  43. uint16_t *value)
  44. {
  45. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  46. if ((memory == NULL) || (value == NULL) || (device > PLSR_DEVICE_FD)
  47. || (address >= TEST_WORD_CAPACITY))
  48. {
  49. return 0U;
  50. }
  51. *value = memory->words[device][address];
  52. return 1U;
  53. }
  54. static uint8_t TestReadBit(void *context,
  55. PLSR_DEVICE_TYPE device,
  56. uint32_t address,
  57. uint8_t *value)
  58. {
  59. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  60. uint8_t index;
  61. if ((memory == NULL) || (value == NULL) || (device < PLSR_DEVICE_X)
  62. || (device > PLSR_DEVICE_HM) || (address >= TEST_BIT_CAPACITY))
  63. {
  64. return 0U;
  65. }
  66. index = (uint8_t)(device - PLSR_DEVICE_X);
  67. *value = memory->bits[index][address];
  68. return 1U;
  69. }
  70. static void TestWriteDword(TEST_MEMORY *memory,
  71. PLSR_DEVICE_TYPE device,
  72. uint32_t address,
  73. int32_t value)
  74. {
  75. uint32_t raw = (uint32_t)value;
  76. memory->words[device][address] = (uint16_t)(raw & 0xFFFFUL);
  77. memory->words[device][address + 1UL] = (uint16_t)(raw >> 16U);
  78. }
  79. static void TestWriteSfdDword(uint16_t address, uint32_t value)
  80. {
  81. CHECK(PlcDeviceWriteSfd(address, (int32_t)(value & 0xFFFFUL))
  82. == PLC_DEVICE_OK);
  83. CHECK(PlcDeviceWriteSfd((uint16_t)(address + 1U),
  84. (int32_t)(value >> 16U))
  85. == PLC_DEVICE_OK);
  86. }
  87. static void TestConfigureAxis0K1(void)
  88. {
  89. CHECK(PlcDeviceWriteSfd(900U, 0) == PLC_DEVICE_OK);
  90. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  91. CHECK(PlcDeviceWriteSfd(907U, 10) == PLC_DEVICE_OK);
  92. TestWriteSfdDword(950U, 1000UL);
  93. CHECK(PlcDeviceWriteSfd(952U, 100) == PLC_DEVICE_OK);
  94. CHECK(PlcDeviceWriteSfd(953U, 120) == PLC_DEVICE_OK);
  95. CHECK(PlcDeviceWriteSfd(954U, 10) == PLC_DEVICE_OK);
  96. CHECK(PlcDeviceWriteSfd(955U, 0) == PLC_DEVICE_OK);
  97. TestWriteSfdDword(956U, 100000UL);
  98. TestWriteSfdDword(958U, 120000UL);
  99. TestWriteSfdDword(960U, 500UL);
  100. CHECK(PlcDeviceWriteSfd(962U, 50) == PLC_DEVICE_OK);
  101. CHECK(PlcDeviceWriteSfd(963U, 20) == PLC_DEVICE_OK);
  102. CHECK(PlcDeviceWriteSfd(964U, 0) == PLC_DEVICE_OK);
  103. TestWriteSfdDword(966U, 2000UL);
  104. TestWriteSfdDword(968U, 200UL);
  105. }
  106. static void TestBuildValidBlocks(TEST_MEMORY *memory)
  107. {
  108. (void)memset(memory, 0, sizeof(*memory));
  109. TestWriteDword(memory, PLSR_DEVICE_D, 100U, 2);
  110. TestWriteDword(memory, PLSR_DEVICE_D, 110U, 150000);
  111. TestWriteDword(memory, PLSR_DEVICE_D, 112U, 100);
  112. memory->words[PLSR_DEVICE_D][114U] = 0U;
  113. TestWriteDword(memory, PLSR_DEVICE_D, 115U, 0);
  114. memory->words[PLSR_DEVICE_D][117U] = 0U;
  115. TestWriteDword(memory, PLSR_DEVICE_D, 118U, 0);
  116. TestWriteDword(memory, PLSR_DEVICE_D, 120U, 0);
  117. TestWriteDword(memory, PLSR_DEVICE_D, 122U, -50);
  118. memory->words[PLSR_DEVICE_D][124U] = 0x0100U;
  119. TestWriteDword(memory, PLSR_DEVICE_D, 125U, 0);
  120. memory->words[PLSR_DEVICE_D][127U] = 0U;
  121. TestWriteDword(memory, PLSR_DEVICE_D, 128U, 2);
  122. TestWriteDword(memory, PLSR_DEVICE_D, 200U, 0);
  123. TestWriteDword(memory, PLSR_DEVICE_D, 202U, 0);
  124. TestWriteDword(memory, PLSR_DEVICE_HD, 10U, 1);
  125. }
  126. static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
  127. {
  128. PLSR_CALL call;
  129. (void)memset(&call, 0, sizeof(call));
  130. call.sequence = 77UL;
  131. call.source.context = memory;
  132. call.source.validateWords = TestValidateWords;
  133. call.source.readWord = TestReadWord;
  134. call.source.readBit = TestReadBit;
  135. call.s0.device = PLSR_DEVICE_D;
  136. call.s0.address = 100UL;
  137. call.s1.device = PLSR_DEVICE_D;
  138. call.s1.address = 200UL;
  139. call.s2.type = PLSR_OPERAND_CONSTANT;
  140. call.s2.constant = 1;
  141. call.dAxis = 0U;
  142. call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
  143. return call;
  144. }
  145. static void TestValidSnapshotAndLiveFrequency(void)
  146. {
  147. TEST_MEMORY memory;
  148. PLSR_CALL call;
  149. PLSR_PARSE_CONTEXT context;
  150. PLSR_JOB_SNAPSHOT snapshot;
  151. PLSR_PARSE_DETAIL detail;
  152. uint32_t frequency;
  153. uint8_t clamped;
  154. TestBuildValidBlocks(&memory);
  155. call = TestMakeCall(&memory);
  156. context.logicalPosition = 0;
  157. context.positionValid = 0U;
  158. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  159. == PLSR_RESULT_OK);
  160. CHECK(detail.result == PLSR_RESULT_OK);
  161. CHECK(snapshot.segmentCount == 2U);
  162. CHECK(snapshot.startSegment == 1U);
  163. CHECK(snapshot.s2Set == 1U);
  164. CHECK(snapshot.outputMode == PLSR_OUTPUT_PULSE_DIR);
  165. CHECK(snapshot.directionPoint == 4U);
  166. CHECK(snapshot.s2.defaultSpeed == 1000UL);
  167. CHECK(snapshot.s2.maximumSpeed == 100000UL);
  168. CHECK(snapshot.s2.startSpeed == 100000UL);
  169. CHECK(snapshot.speedClamped == 1U);
  170. CHECK(snapshot.segments[0].targetFrequency == 100000UL);
  171. CHECK((snapshot.segments[0].flags & PLSR_SEGMENT_FLAG_SPEED_CLAMPED)
  172. != 0U);
  173. CHECK(snapshot.segments[1].targetFrequency == 1000UL);
  174. CHECK((snapshot.segments[1].flags & PLSR_SEGMENT_FLAG_DEFAULT_SPEED)
  175. != 0U);
  176. CHECK((snapshot.segments[1].flags & PLSR_SEGMENT_FLAG_SELF_LOOP) != 0U);
  177. CHECK(snapshot.hasSelfLoop == 1U);
  178. CHECK(snapshot.initialDirectionPositive == 1U);
  179. TestWriteDword(&memory, PLSR_DEVICE_D, 112U, 9999);
  180. CHECK(snapshot.segments[0].pulseOrTarget == 100);
  181. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 2500);
  182. CHECK(PlsrResolveLiveFrequency(&snapshot, 1U, &frequency, &clamped)
  183. == PLSR_RESULT_OK);
  184. CHECK(frequency == 2500UL);
  185. CHECK(clamped == 0U);
  186. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, 200000);
  187. CHECK(PlsrResolveLiveFrequency(&snapshot, 1U, &frequency, &clamped)
  188. == PLSR_RESULT_OK);
  189. CHECK(frequency == 100000UL);
  190. CHECK(clamped == 1U);
  191. call.s2.type = PLSR_OPERAND_DATA;
  192. call.s2.data.device = PLSR_DEVICE_HD;
  193. call.s2.data.address = 10UL;
  194. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  195. == PLSR_RESULT_OK);
  196. CHECK(snapshot.s2Set == 1U);
  197. }
  198. static void TestValidationFailures(void)
  199. {
  200. TEST_MEMORY memory;
  201. PLSR_CALL call;
  202. PLSR_PARSE_CONTEXT context = {0, 0U};
  203. PLSR_JOB_SNAPSHOT snapshot;
  204. PLSR_PARSE_DETAIL detail;
  205. TestBuildValidBlocks(&memory);
  206. call = TestMakeCall(&memory);
  207. call.s1.address = 120UL;
  208. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  209. == PLSR_RESULT_BLOCK_OVERLAP);
  210. TestBuildValidBlocks(&memory);
  211. call = TestMakeCall(&memory);
  212. memory.words[PLSR_DEVICE_D][103U] = 1U;
  213. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  214. == PLSR_RESULT_RESERVED_NOT_ZERO);
  215. CHECK(detail.address == 103UL);
  216. TestBuildValidBlocks(&memory);
  217. call = TestMakeCall(&memory);
  218. TestWriteDword(&memory, PLSR_DEVICE_D, 100U, 101);
  219. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  220. == PLSR_RESULT_SEGMENT_OVERFLOW);
  221. TestBuildValidBlocks(&memory);
  222. call = TestMakeCall(&memory);
  223. TestWriteDword(&memory, PLSR_DEVICE_D, 110U, -1);
  224. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  225. == PLSR_RESULT_INVALID_FREQUENCY);
  226. CHECK(detail.segment == 1U);
  227. TestBuildValidBlocks(&memory);
  228. call = TestMakeCall(&memory);
  229. memory.words[PLSR_DEVICE_D][124U] = 0x0405U;
  230. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  231. == PLSR_RESULT_INVALID_WAIT);
  232. TestBuildValidBlocks(&memory);
  233. call = TestMakeCall(&memory);
  234. TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 3);
  235. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  236. == PLSR_RESULT_INVALID_JUMP);
  237. TestBuildValidBlocks(&memory);
  238. call = TestMakeCall(&memory);
  239. TestWriteDword(&memory, PLSR_DEVICE_D, 118U, 2);
  240. TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 1);
  241. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  242. == PLSR_RESULT_PATH_CYCLE);
  243. TestBuildValidBlocks(&memory);
  244. call = TestMakeCall(&memory);
  245. TestWriteDword(&memory, PLSR_DEVICE_D, 200U, 1);
  246. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  247. == PLSR_RESULT_POSITION_INVALID);
  248. TestBuildValidBlocks(&memory);
  249. call = TestMakeCall(&memory);
  250. call.s0.address = UINT32_MAX - 5UL;
  251. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  252. == PLSR_RESULT_ADDRESS_OVERFLOW);
  253. TestBuildValidBlocks(&memory);
  254. call = TestMakeCall(&memory);
  255. call.s2.constant = 5;
  256. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  257. == PLSR_RESULT_INVALID_S2);
  258. TestBuildValidBlocks(&memory);
  259. call = TestMakeCall(&memory);
  260. CHECK(PlcDeviceWriteSfd(962U, 356) == PLC_DEVICE_OK);
  261. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  262. == PLSR_RESULT_INVALID_S2);
  263. CHECK(PlcDeviceWriteSfd(962U, 50) == PLC_DEVICE_OK);
  264. CHECK(PlcDeviceWriteSfd(964U, 1) == PLC_DEVICE_OK);
  265. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  266. == PLSR_RESULT_INVALID_S2);
  267. CHECK(PlcDeviceWriteSfd(964U, 0) == PLC_DEVICE_OK);
  268. }
  269. static void TestDynamicReferences(void)
  270. {
  271. TEST_MEMORY memory;
  272. PLSR_CALL call;
  273. PLSR_PARSE_CONTEXT context = {0, 0U};
  274. PLSR_JOB_SNAPSHOT snapshot;
  275. PLSR_PARSE_DETAIL detail;
  276. TestBuildValidBlocks(&memory);
  277. call = TestMakeCall(&memory);
  278. memory.words[PLSR_DEVICE_D][124U] = 0x0101U;
  279. TestWriteDword(&memory, PLSR_DEVICE_D, 125U, 300);
  280. TestWriteDword(&memory, PLSR_DEVICE_D, 300U, 25);
  281. memory.words[PLSR_DEVICE_D][127U] = 1U;
  282. TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 302);
  283. TestWriteDword(&memory, PLSR_DEVICE_D, 302U, 2);
  284. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  285. == PLSR_RESULT_OK);
  286. CHECK(snapshot.segments[1].waitSource == PLSR_VALUE_D);
  287. CHECK(snapshot.segments[1].waitValueOrAddress == 300);
  288. CHECK(snapshot.segments[1].jumpSource == PLSR_VALUE_D);
  289. CHECK(snapshot.segments[1].jumpValueOrAddress == 302);
  290. memory.words[PLSR_DEVICE_D][124U] = 0x0404U;
  291. TestWriteDword(&memory, PLSR_DEVICE_D, 125U, 7);
  292. memory.bits[0][7U] = 1U;
  293. memory.words[PLSR_DEVICE_D][127U] = 0U;
  294. TestWriteDword(&memory, PLSR_DEVICE_D, 128U, 2);
  295. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  296. == PLSR_RESULT_OK);
  297. }
  298. static void TestOutputAndDivider(void)
  299. {
  300. TEST_MEMORY memory;
  301. PLSR_CALL call;
  302. PLSR_PARSE_CONTEXT context = {0, 0U};
  303. PLSR_JOB_SNAPSHOT snapshot;
  304. PLSR_PARSE_DETAIL detail;
  305. uint16_t psc;
  306. uint16_t arr;
  307. TestBuildValidBlocks(&memory);
  308. call = TestMakeCall(&memory);
  309. CHECK(PlcDeviceWriteSfd(900U, (1U << 13U)) == PLC_DEVICE_OK);
  310. CHECK(PlsrBuildJobSnapshot(&call, &context, &snapshot, &detail)
  311. == PLSR_RESULT_OK);
  312. CHECK(snapshot.outputMode == PLSR_OUTPUT_AB);
  313. CHECK(snapshot.pairedTimerClockHz == 84000000UL);
  314. CHECK(PlsrCalculateTimerDivider(168000000UL, 1UL, &psc, &arr)
  315. == PLSR_RESULT_OK);
  316. CHECK(PlsrCalculateTimerDivider(84000000UL, 100000UL, &psc, &arr)
  317. == PLSR_RESULT_OK);
  318. CHECK(PlsrCalculateTimerDivider(84000000UL, 0UL, &psc, &arr)
  319. == PLSR_RESULT_INVALID_ARGUMENT);
  320. CHECK(PlsrCalculateTimerDivider(1UL, 100000UL, &psc, &arr)
  321. == PLSR_RESULT_DIVIDER_UNREPRESENTABLE);
  322. CHECK(PlcDeviceWriteSfd(900U, 0) == PLC_DEVICE_OK);
  323. }
  324. static void TestCoreSubmission(void)
  325. {
  326. TEST_MEMORY memory;
  327. PLSR_CALL call;
  328. PLSR_STATUS status;
  329. PLSR_PARSE_DETAIL detail;
  330. TestBuildValidBlocks(&memory);
  331. call = TestMakeCall(&memory);
  332. call.sequence = 500UL;
  333. CHECK(PlsrInit() == PLSR_RESULT_OK);
  334. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  335. PlsrProcess();
  336. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  337. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  338. CHECK(status.state == PLSR_STATE_ACCEL);
  339. CHECK(status.jobValid == 1U);
  340. CHECK(status.segmentCount == 2U);
  341. CHECK(status.startSegment == 1U);
  342. CHECK(status.s2Set == 1U);
  343. CHECK(status.speedClamped == 1U);
  344. CHECK(PlsrGetLastParseDetail(0U, &detail) == PLSR_RESULT_OK);
  345. CHECK(detail.result == PLSR_RESULT_OK);
  346. }
  347. static void TestDefaultSfdStartable(void)
  348. {
  349. TEST_MEMORY memory;
  350. PLSR_CALL call;
  351. PLSR_STATUS status;
  352. /* 全新 Flash:默认 S2 参数(FOLLOW=50、最大速度=100000 等)应可直接启动。 */
  353. PlsrPersistenceTestResetStorage();
  354. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  355. CHECK(PlcDeviceGetLastSfdLoadResult() == PLSR_PERSISTENCE_DEFAULTED);
  356. TestBuildValidBlocks(&memory);
  357. call = TestMakeCall(&memory);
  358. call.sequence = 600UL;
  359. /* 方向端子是接线参数,未配置(0xFF)时 PULSE/DIR 应报资源错误。 */
  360. CHECK(PlsrInit() == PLSR_RESULT_OK);
  361. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  362. PlsrProcess();
  363. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  364. CHECK(status.lastCommandResult == PLSR_RESULT_INVALID_RESOURCE);
  365. CHECK(status.state == PLSR_STATE_IDLE);
  366. /* 用户配置方向端子后,其余出厂默认参数应能直接启动。 */
  367. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  368. call.sequence = 601UL;
  369. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  370. PlsrProcess();
  371. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  372. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  373. CHECK(status.state == PLSR_STATE_ACCEL);
  374. CHECK(status.jobValid == 1U);
  375. CHECK(status.s2Set == 1U);
  376. CHECK(status.speedClamped == 1U);
  377. CHECK(status.directionPoint == 4U);
  378. /* 回到 IDLE,避免资源泄漏影响后续。 */
  379. CHECK(PlsrPostCommand(&(PLSR_COMMAND){602U, 0U, PLSR_CMD_STOP_IMMEDIATE, 0})
  380. == PLSR_RESULT_QUEUED);
  381. PlsrProcess();
  382. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  383. == PLSR_RESULT_OK);
  384. PlsrProcess();
  385. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  386. CHECK(status.state == PLSR_STATE_STOPPED);
  387. }
  388. int main(void)
  389. {
  390. PlsrPersistenceTestResetStorage();
  391. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  392. TestConfigureAxis0K1();
  393. TestValidSnapshotAndLiveFrequency();
  394. TestValidationFailures();
  395. TestDynamicReferences();
  396. TestOutputAndDivider();
  397. TestDefaultSfdStartable();
  398. TestCoreSubmission();
  399. if (TestFailures != 0)
  400. {
  401. (void)printf("FAIL: %d of %d PLSR job checks failed\n",
  402. TestFailures,
  403. TestChecks);
  404. return 1;
  405. }
  406. (void)printf("PASS: %d PLSR job checks\n", TestChecks);
  407. return 0;
  408. }