Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

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