您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

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