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

2325 řádky
80 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 void TestCompleteFirstAbPrime(uint8_t axis)
  111. {
  112. int quarter;
  113. CHECK(PlsrHwIsAbStartupPriming(axis) != 0U);
  114. for (quarter = 0; quarter < 4; quarter++)
  115. {
  116. PlsrHwTestAdvanceAbQuarter(axis);
  117. }
  118. CHECK(PlsrHwIsAbStartupPriming(axis) == 0U);
  119. CHECK(PlsrHwGetEmittedPulses(axis) == 0);
  120. CHECK(PlsrHwTestGetAbQuarter(axis) == 0U);
  121. }
  122. static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
  123. {
  124. PLSR_CALL call;
  125. (void)memset(&call, 0, sizeof(call));
  126. call.sequence = 10UL;
  127. call.source.context = memory;
  128. call.source.validateWords = TestValidateWords;
  129. call.source.readWord = TestReadWord;
  130. call.source.readBit = TestReadBit;
  131. call.s0.device = PLSR_DEVICE_D;
  132. call.s0.address = TEST_S0_BASE;
  133. call.s1.device = PLSR_DEVICE_D;
  134. call.s1.address = TEST_S1_BASE;
  135. call.s2.type = PLSR_OPERAND_CONSTANT;
  136. call.s2.constant = 1;
  137. call.dAxis = 0U;
  138. call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
  139. return call;
  140. }
  141. static PLSR_STATUS TestGetStatus(void)
  142. {
  143. PLSR_STATUS status;
  144. (void)memset(&status, 0, sizeof(status));
  145. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  146. return status;
  147. }
  148. static int32_t TestReadSdDword(uint16_t lowAddress)
  149. {
  150. int32_t lowWord = 0;
  151. int32_t highWord = 0;
  152. uint32_t rawValue;
  153. CHECK(PlcDeviceReadSd(lowAddress, &lowWord) == PLC_DEVICE_OK);
  154. CHECK(PlcDeviceReadSd((uint16_t)(lowAddress + 1U), &highWord)
  155. == PLC_DEVICE_OK);
  156. rawValue = ((uint32_t)lowWord & 0xFFFFUL)
  157. | (((uint32_t)highWord & 0xFFFFUL) << 16U);
  158. return (int32_t)rawValue;
  159. }
  160. /* ---- HAL 单测 ---- */
  161. static void TestMapping(void)
  162. {
  163. (void)PlsrHwInit();
  164. CHECK(PlsrHwGetTimerClockHz(0U) == 168000000UL);
  165. CHECK(PlsrHwGetTimerClockHz(1U) == 84000000UL);
  166. CHECK(PlsrHwGetTimerClockHz(2U) == 168000000UL);
  167. CHECK(PlsrHwGetTimerClockHz(3U) == 84000000UL);
  168. CHECK(PlsrHwGetTimerClockHz(4U) == 0UL);
  169. CHECK(PlsrHwResolveDirectionPoint(4U) != 0U);
  170. CHECK(PlsrHwResolveDirectionPoint(8U) == 0U);
  171. CHECK(PlsrHwResolveDirectionPoint(20U) != 0U);
  172. CHECK(PlsrHwResolveDirectionPoint(21U) == 0U);
  173. }
  174. static void TestDirDelaySequence(void)
  175. {
  176. (void)PlsrHwInit();
  177. PLSR_HW_START_PARAMS params;
  178. uint16_t psc;
  179. uint16_t arr;
  180. int ticks;
  181. (void)memset(&params, 0, sizeof(params));
  182. params.frequencyHz = 1000UL;
  183. params.targetPulses = 100;
  184. params.directionPoint = 4U;
  185. params.directionPositive = 1U;
  186. params.directionDelayMs = 10U;
  187. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  188. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  189. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  190. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  191. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  192. for (ticks = 0; ticks < 9; ticks++)
  193. {
  194. PlsrHwTick(0U);
  195. }
  196. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  197. PlsrHwTick(0U);
  198. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  199. /* 首个非零频率启动 PWM,ARR/CCR 与分频计算一致。 */
  200. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  201. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  202. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  203. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  204. CHECK(PlsrCalculateTimerDivider(168000000UL, 1000UL, &psc, &arr)
  205. == PLSR_RESULT_OK);
  206. CHECK(PlsrHwTestGetArr(0U) == arr);
  207. CHECK(PlsrHwTestGetPsc(0U) == psc);
  208. CHECK(PlsrHwTestGetCcr(0U) == arr / 2UL);
  209. /* PWM 模式 1(OC1M=110):复位后 CCMR1=0 冻结,无此配置输出恒定电平。 */
  210. CHECK((PlsrHwTestGetCcmr1(0U) & 0x70UL) == 0x60UL);
  211. /* ARR/CCR 预装载(ARPE=CR1 bit7,OC1PE=CCMR1 bit3):
  212. * 运行中调频不产生提前回绕,否则加速段多出 ~ln(f1/f0) 个假脉冲。 */
  213. CHECK((PlsrHwTestGetCr1(0U) & 0x80UL) == 0x80UL);
  214. CHECK((PlsrHwTestGetCcmr1(0U) & 0x08UL) == 0x08UL);
  215. /* 段间同向衔接:方向不变时跳过方向延时,直接进入 PWM 待启动。 */
  216. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  217. params.targetPulses = 50;
  218. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  219. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  220. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  221. /* 反向时方向延时仍生效。 */
  222. params.directionPositive = 0U;
  223. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  224. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  225. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  226. /* Bit1 negative logic reverses only the electrical DIR terminal. */
  227. params.directionNegativeLogic = 1U;
  228. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  229. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  230. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  231. params.directionPositive = 1U;
  232. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  233. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  234. }
  235. static void TestDirectionBatch(void)
  236. {
  237. PLSR_HW_START_PARAMS params;
  238. (void)PlsrHwInit();
  239. (void)memset(&params, 0, sizeof(params));
  240. params.frequencyHz = 0UL;
  241. params.targetPulses = 10;
  242. params.outputMode = PLSR_OUTPUT_PULSE_DIR;
  243. params.directionPoint = 4U;
  244. params.directionPositive = 1U;
  245. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  246. params.directionPoint = 3U;
  247. params.directionNegativeLogic = 1U;
  248. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_OK);
  249. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  250. CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
  251. PlsrHwBeginDirectionBatch();
  252. params.directionPoint = 4U;
  253. params.directionPositive = 0U;
  254. params.directionNegativeLogic = 0U;
  255. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  256. params.directionPoint = 3U;
  257. params.directionNegativeLogic = 1U;
  258. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_OK);
  259. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  260. CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
  261. PlsrHwEndDirectionBatch();
  262. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  263. CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
  264. }
  265. static void TestCwCcwSequence(void)
  266. {
  267. PLSR_HW_START_PARAMS params;
  268. uint16_t psc;
  269. uint16_t arr;
  270. (void)PlsrHwInit();
  271. (void)memset(&params, 0, sizeof(params));
  272. params.frequencyHz = 2000UL;
  273. params.targetPulses = 3;
  274. params.outputMode = PLSR_OUTPUT_CW_CCW;
  275. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  276. params.directionPositive = 1U;
  277. params.directionDelayMs = 10U;
  278. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  279. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  280. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  281. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  282. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  283. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  284. PlsrHwTestTriggerCompare(1U);
  285. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  286. PlsrHwTestTriggerCompare(0U);
  287. PlsrHwTestTriggerCompare(0U);
  288. PlsrHwTestTriggerCompare(0U);
  289. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  290. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  291. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  292. PlsrHwTestTriggerUpdate(0U);
  293. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  294. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  295. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  296. params.frequencyHz = 1000UL;
  297. params.targetPulses = 2;
  298. params.directionPositive = 0U;
  299. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  300. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  301. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  302. CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
  303. CHECK(PlsrCalculateTimerDivider(84000000UL, 1000UL, &psc, &arr)
  304. == PLSR_RESULT_OK);
  305. CHECK(PlsrHwTestGetPsc(1U) == psc);
  306. CHECK(PlsrHwTestGetArr(1U) == arr);
  307. PlsrHwTestTriggerCompare(1U);
  308. PlsrHwTestTriggerCompare(1U);
  309. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  310. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  311. CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
  312. PlsrHwTestTriggerUpdate(1U);
  313. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  314. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  315. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  316. }
  317. static void TestFastRefreshControlTick(void)
  318. {
  319. TEST_MEMORY memory;
  320. PLSR_CALL call;
  321. PLSR_STATUS status;
  322. int tick;
  323. TestResetEnvironment();
  324. (void)memset(&memory, 0, sizeof(memory));
  325. CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK);
  326. TestWriteSfdDword(902U, 1UL);
  327. TestWriteSfdDword(904U, 1UL);
  328. CHECK(PlcDeviceWriteSfd(906U, 4U) == PLC_DEVICE_OK);
  329. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  330. TestWriteSfdDword(950U, 1000UL);
  331. CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
  332. CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
  333. CHECK(PlcDeviceWriteSfd(954U, 0U) == PLC_DEVICE_OK);
  334. /* Linear curve: 10Hz/ms becomes exactly 1Hz per 0.1ms tick. */
  335. CHECK(PlcDeviceWriteSfd(955U, 0U) == PLC_DEVICE_OK);
  336. TestWriteSfdDword(956U, 100000UL);
  337. TestWriteSfdDword(958U, 0UL);
  338. TestWriteSfdDword(960U, 0UL);
  339. CHECK(PlcDeviceWriteSfd(962U, 50U) == PLC_DEVICE_OK);
  340. CHECK(PlcDeviceWriteSfd(963U, 0U) == PLC_DEVICE_OK);
  341. CHECK(PlcDeviceWriteSfd(964U, 2U) == PLC_DEVICE_OK);
  342. TestWriteSfdDword(966U, 2000UL);
  343. TestWriteSfdDword(968U, 200UL);
  344. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  345. TestSetSegment(&memory, 1U, 1000U, 10000);
  346. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 0);
  347. call = TestMakeCall(&memory);
  348. call.sequence = 0xB000UL;
  349. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  350. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  351. PlsrProcess();
  352. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  353. CHECK(status.state == PLSR_STATE_ACCEL);
  354. CHECK(status.jobValid != 0U);
  355. CHECK(PlsrTestGetJobRefreshCode(0U) == 2U);
  356. CHECK(PlsrTestGetProfileRefreshHz(0U) == 10000UL);
  357. CHECK(PlsrTestGetProfileActive(0U) != 0U);
  358. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  359. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 0UL);
  360. /* A normal 1ms process pass must not advance a 0.1ms profile. */
  361. PlsrProcess();
  362. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 0UL);
  363. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  364. CHECK(PlsrTestGetJobRefreshCode(0U) == 2U);
  365. CHECK(PlsrTestGetProfileActive(0U) != 0U);
  366. PlsrControlTick100us();
  367. CHECK(PlsrTestGetProfileFrequencyHz(0U) == 1UL);
  368. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  369. CHECK(PlsrHwGetCurrentFrequencyHz(0U) > 0UL);
  370. for (tick = 1; tick < 10; tick++)
  371. {
  372. PlsrControlTick100us();
  373. }
  374. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 10UL);
  375. PlsrProcess();
  376. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 10UL);
  377. for (tick = 0; tick < 10; tick++)
  378. {
  379. PlsrControlTick100us();
  380. }
  381. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 20UL);
  382. }
  383. static void TestDynamicFrequencyRetarget(void)
  384. {
  385. TEST_MEMORY memory;
  386. PLSR_CALL call;
  387. PLSR_STATUS status;
  388. TestResetEnvironment();
  389. (void)memset(&memory, 0, sizeof(memory));
  390. CHECK(PlcDeviceWriteSfd(900U, 0U) == PLC_DEVICE_OK);
  391. TestWriteSfdDword(902U, 1UL);
  392. TestWriteSfdDword(904U, 1UL);
  393. CHECK(PlcDeviceWriteSfd(906U, 4U) == PLC_DEVICE_OK);
  394. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  395. TestWriteSfdDword(950U, 1000UL);
  396. CHECK(PlcDeviceWriteSfd(952U, 100U) == PLC_DEVICE_OK);
  397. CHECK(PlcDeviceWriteSfd(953U, 100U) == PLC_DEVICE_OK);
  398. CHECK(PlcDeviceWriteSfd(954U, 0U) == PLC_DEVICE_OK);
  399. CHECK(PlcDeviceWriteSfd(955U, 0U) == PLC_DEVICE_OK);
  400. TestWriteSfdDword(956U, 5000UL);
  401. TestWriteSfdDword(958U, 1000UL);
  402. TestWriteSfdDword(960U, 0UL);
  403. CHECK(PlcDeviceWriteSfd(962U, 50U) == PLC_DEVICE_OK);
  404. CHECK(PlcDeviceWriteSfd(963U, 0U) == PLC_DEVICE_OK);
  405. CHECK(PlcDeviceWriteSfd(964U, 2U) == PLC_DEVICE_OK);
  406. TestWriteSfdDword(966U, 2000UL);
  407. TestWriteSfdDword(968U, 200UL);
  408. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  409. TestSetSegment(&memory, 1U, 1000U, 100000);
  410. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 0);
  411. call = TestMakeCall(&memory);
  412. call.sequence = 0xB100UL;
  413. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  414. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  415. PlsrProcess();
  416. PlsrControlTick100us();
  417. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  418. CHECK(status.currentFrequencyHz == 1000UL);
  419. CHECK(status.targetFrequencyHz == 1000UL);
  420. /* Only the 100us control tick may observe/apply a refreshCode=2 edit. */
  421. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 4000);
  422. PlsrProcess();
  423. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  424. CHECK(status.targetFrequencyHz == 1000UL);
  425. CHECK(status.currentFrequencyHz == 1000UL);
  426. PlsrControlTick100us();
  427. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  428. CHECK(status.targetFrequencyHz == 4000UL);
  429. CHECK(status.currentFrequencyHz == 1001UL);
  430. PlsrControlTick100us();
  431. CHECK(PlsrHwGetCurrentFrequencyHz(0U) == 1002UL);
  432. /* Down-retarget follows the configured slope instead of jumping. */
  433. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 500);
  434. PlsrControlTick100us();
  435. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  436. CHECK(status.targetFrequencyHz == 500UL);
  437. CHECK(status.currentFrequencyHz == 1001UL);
  438. /* Raw zero means the immutable S2 default speed. */
  439. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 0);
  440. PlsrControlTick100us();
  441. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  442. CHECK(status.targetFrequencyHz == 1000UL);
  443. CHECK(status.currentFrequencyHz == 1000UL);
  444. /* Above-maximum values clamp; invalid negatives retain the last safe
  445. * target and produce one sticky rejection for that observed value. */
  446. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 8000);
  447. PlsrControlTick100us();
  448. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  449. CHECK(status.targetFrequencyHz == 5000UL);
  450. CHECK(status.currentFrequencyHz == 1001UL);
  451. CHECK(status.speedClamped != 0U);
  452. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, -1);
  453. PlsrControlTick100us();
  454. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  455. CHECK(status.targetFrequencyHz == 5000UL);
  456. CHECK(status.currentFrequencyHz == 1002UL);
  457. CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_INVALID_FREQUENCY);
  458. CHECK(status.liveFrequencyRejectCount == 1UL);
  459. PlsrControlTick100us();
  460. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  461. CHECK(status.liveFrequencyRejectCount == 1UL);
  462. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE + 10U, 2000);
  463. PlsrControlTick100us();
  464. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  465. CHECK(status.targetFrequencyHz == 2000UL);
  466. CHECK(status.currentFrequencyHz == 1004UL);
  467. CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_OK);
  468. }
  469. static void TestZeroFrequencyWaits(void)
  470. {
  471. (void)PlsrHwInit();
  472. PLSR_HW_START_PARAMS params;
  473. (void)memset(&params, 0, sizeof(params));
  474. params.frequencyHz = 0UL;
  475. params.targetPulses = 50;
  476. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  477. params.directionPositive = 1U;
  478. params.directionDelayMs = 0U;
  479. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  480. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  481. PlsrHwTick(0U);
  482. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  483. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  484. /* 起始速度为 0:profile 升频后首个非零频率才启动 PWM。 */
  485. CHECK(PlsrHwSetFrequency(0U, 10UL) == PLSR_RESULT_OK);
  486. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  487. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  488. }
  489. static void TestPulseCounting(void)
  490. {
  491. (void)PlsrHwInit();
  492. PLSR_HW_START_PARAMS params;
  493. int pulse;
  494. (void)memset(&params, 0, sizeof(params));
  495. params.frequencyHz = 1000UL;
  496. params.targetPulses = 5;
  497. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  498. params.directionPositive = 1U;
  499. params.directionDelayMs = 0U;
  500. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  501. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  502. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  503. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  504. /* EGR.UG 只加载预装载寄存器,不能被当作物理脉冲。
  505. * 共享 IRQ 入口在对应定时器没有 UIF 时也必须无动作。 */
  506. PlsrHwOnTimerUpdate(0U);
  507. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  508. for (pulse = 0; pulse < 4; pulse++)
  509. {
  510. PlsrHwTestTriggerUpdate(0U);
  511. CHECK(PlsrHwGetEmittedPulses(0U) == pulse + 1);
  512. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  513. }
  514. /* 第 5 个脉冲:到目标,停止 + 段完成事件。 */
  515. PlsrHwTestTriggerUpdate(0U);
  516. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  517. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  518. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  519. /* 停止后再触发更新中断无动作。 */
  520. PlsrHwTestTriggerUpdate(0U);
  521. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  522. }
  523. static void TestAbPhaseAndCounting(void)
  524. {
  525. PLSR_HW_START_PARAMS params;
  526. static const uint8_t positiveA[4] = {1U, 1U, 0U, 0U};
  527. static const uint8_t positiveB[4] = {0U, 1U, 1U, 0U};
  528. static const uint8_t negativeA[4] = {0U, 1U, 1U, 0U};
  529. static const uint8_t negativeB[4] = {1U, 1U, 0U, 0U};
  530. uint32_t oldArr;
  531. uint32_t oldBasePsc;
  532. uint32_t oldPairPsc;
  533. uint32_t newPeriod;
  534. int quarter;
  535. (void)PlsrHwInit();
  536. (void)memset(&params, 0, sizeof(params));
  537. params.frequencyHz = 1000UL;
  538. params.targetPulses = 4;
  539. params.outputMode = PLSR_OUTPUT_AB;
  540. params.directionPoint = 4U; /* AB 模式必须忽略独立 DIR 点。 */
  541. params.directionPositive = 1U;
  542. params.directionDelayMs = 10U; /* AB 模式不得执行方向延时。 */
  543. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  544. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  545. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  546. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  547. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  548. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  549. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  550. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  551. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  552. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  553. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  554. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  555. CHECK(PlsrHwTestGetCcr(0U) == PlsrHwTestGetCcr(1U));
  556. CHECK(PlsrHwTestGetCcr(0U)
  557. == (PlsrHwTestGetArr(0U) + 1UL) / 2UL);
  558. /* 两相从精确 00 边界起步;CC1IF 会在开中断前再次清除。 */
  559. CHECK(PlsrHwTestGetCnt(0U)
  560. == ((PlsrHwTestGetArr(0U) + 1UL) * 3UL) / 4UL);
  561. CHECK(PlsrHwTestGetCnt(1U) == PlsrHwTestGetCcr(1U));
  562. TestCompleteFirstAbPrime(0U);
  563. /* 任一物理 timer update 不能直接计作完整 AB 周期。 */
  564. PlsrHwTestTriggerUpdate(0U);
  565. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  566. /* 正向:00→10→11→01→00;四次相位跳变只计一个脉冲。 */
  567. for (quarter = 0; quarter < 4; quarter++)
  568. {
  569. PlsrHwTestAdvanceAbQuarter(0U);
  570. CHECK(PlsrHwTestGetAbPhaseA(0U) == positiveA[quarter]);
  571. CHECK(PlsrHwTestGetAbPhaseB(0U) == positiveB[quarter]);
  572. }
  573. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  574. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  575. /* 运行中调频先排队,不能让相差 1/4 周期的两路各自加载 ARR。 */
  576. oldArr = PlsrHwTestGetArr(0U);
  577. oldBasePsc = PlsrHwTestGetPsc(0U);
  578. oldPairPsc = PlsrHwTestGetPsc(1U);
  579. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  580. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  581. for (quarter = 0; quarter < 4; quarter++)
  582. {
  583. PlsrHwTestAdvanceAbQuarter(0U);
  584. }
  585. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  586. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  587. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  588. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  589. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  590. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  591. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  592. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  593. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  594. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  595. for (quarter = 0; quarter < 3; quarter++)
  596. {
  597. PlsrHwTestAdvanceAbQuarter(0U);
  598. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  599. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  600. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  601. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  602. }
  603. /* 回到 00 后,两路同时装载新频率并从精确 90° 位置重启。 */
  604. PlsrHwTestAdvanceAbQuarter(0U);
  605. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  606. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  607. CHECK((PlsrHwTestGetArr(0U) != oldArr)
  608. || (PlsrHwTestGetPsc(0U) != oldBasePsc));
  609. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  610. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  611. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  612. newPeriod = PlsrHwTestGetArr(0U) + 1UL;
  613. CHECK(PlsrHwTestGetCnt(0U) == (newPeriod * 3UL) / 4UL);
  614. CHECK(PlsrHwTestGetCnt(1U) == newPeriod / 2UL);
  615. for (quarter = 0; quarter < 4; quarter++)
  616. {
  617. PlsrHwTestAdvanceAbQuarter(0U);
  618. }
  619. CHECK(PlsrHwGetEmittedPulses(0U) == 4);
  620. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  621. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  622. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  623. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  624. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  625. /* 反向:00→01→11→10→00。 */
  626. params.targetPulses = 1;
  627. params.directionPositive = 0U;
  628. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  629. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  630. for (quarter = 0; quarter < 4; quarter++)
  631. {
  632. PlsrHwTestAdvanceAbQuarter(0U);
  633. CHECK(PlsrHwTestGetAbPhaseA(0U) == negativeA[quarter]);
  634. CHECK(PlsrHwTestGetAbPhaseB(0U) == negativeB[quarter]);
  635. }
  636. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  637. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  638. /* 紧急停止即使发生在周期中间,也必须回到安全 00。 */
  639. params.targetPulses = 10;
  640. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  641. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  642. PlsrHwTestAdvanceAbQuarter(0U);
  643. CHECK(PlsrHwTestGetAbQuarter(0U) == 1U);
  644. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  645. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  646. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  647. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  648. }
  649. static void TestTwoAbAxesIndependent(void)
  650. {
  651. PLSR_HW_START_PARAMS params;
  652. int quarter;
  653. (void)PlsrHwInit();
  654. (void)memset(&params, 0, sizeof(params));
  655. params.frequencyHz = 1000UL;
  656. params.targetPulses = 1;
  657. params.outputMode = PLSR_OUTPUT_AB;
  658. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  659. params.directionPositive = 1U;
  660. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  661. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  662. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  663. CHECK(PlsrHwSetFrequency(2U, 2000UL) == PLSR_RESULT_OK);
  664. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  665. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  666. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  667. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  668. TestCompleteFirstAbPrime(0U);
  669. TestCompleteFirstAbPrime(2U);
  670. for (quarter = 0; quarter < 4; quarter++)
  671. {
  672. PlsrHwTestAdvanceAbQuarter(0U);
  673. }
  674. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  675. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
  676. CHECK(PlsrHwGetEmittedPulses(2U) == 0);
  677. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  678. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  679. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  680. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  681. for (quarter = 0; quarter < 4; quarter++)
  682. {
  683. PlsrHwTestAdvanceAbQuarter(2U);
  684. }
  685. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
  686. CHECK(PlsrHwGetEmittedPulses(2U) == 1);
  687. }
  688. static void TestAbFrequencyLimits(void)
  689. {
  690. PLSR_HW_START_PARAMS params;
  691. int quarter;
  692. (void)PlsrHwInit();
  693. (void)memset(&params, 0, sizeof(params));
  694. params.frequencyHz = 1UL;
  695. params.targetPulses = 100;
  696. params.outputMode = PLSR_OUTPUT_AB;
  697. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  698. params.directionPositive = 1U;
  699. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  700. CHECK(PlsrHwSetFrequency(0U, 1UL) == PLSR_RESULT_OK);
  701. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  702. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  703. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  704. CHECK(PlsrHwTestGetArr(0U) <= 65535UL);
  705. TestCompleteFirstAbPrime(0U);
  706. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  707. for (quarter = 0; quarter < 4; quarter++)
  708. {
  709. PlsrHwTestAdvanceAbQuarter(0U);
  710. }
  711. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  712. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  713. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  714. CHECK(PlsrHwTestGetArr(0U) >= 3UL);
  715. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  716. }
  717. static void TestStopAndInvalidArgs(void)
  718. {
  719. (void)PlsrHwInit();
  720. PLSR_HW_START_PARAMS params;
  721. (void)memset(&params, 0, sizeof(params));
  722. params.frequencyHz = 1000UL;
  723. params.targetPulses = 100;
  724. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  725. params.directionPositive = 1U;
  726. params.directionDelayMs = 0U;
  727. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  728. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  729. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  730. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  731. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  732. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  733. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  734. CHECK(PlsrHwStartPulse(4U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  735. CHECK(PlsrHwStartPulse(0U, NULL) == PLSR_RESULT_INVALID_ARGUMENT);
  736. params.targetPulses = 0;
  737. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  738. params.targetPulses = 1;
  739. params.outputMode = PLSR_OUTPUT_CW_CCW;
  740. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  741. params.outputMode = (PLSR_OUTPUT_MODE)99;
  742. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  743. CHECK(PlsrHwSetFrequency(4U, 1000UL) == PLSR_RESULT_INVALID_ARGUMENT);
  744. CHECK(PlsrHwStopPulse(4U) == PLSR_RESULT_INVALID_ARGUMENT);
  745. }
  746. /* ---- 端到端集成:START → 硬件 → 计数 → 事件 → 段间 → 完成 ---- */
  747. static void TestEndToEndTwoSegments(void)
  748. {
  749. TEST_MEMORY memory;
  750. PLSR_CALL call;
  751. PLSR_STATUS status;
  752. uint16_t initialPsc;
  753. uint16_t initialArr;
  754. int ticks;
  755. int pulse;
  756. TestResetEnvironment();
  757. (void)memset(&memory, 0, sizeof(memory));
  758. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  759. TestSetSegment(&memory, 1U, 1000U, 100);
  760. TestSetSegment(&memory, 2U, 2000U, 200);
  761. call = TestMakeCall(&memory);
  762. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  763. PlsrProcess();
  764. status = TestGetStatus();
  765. CHECK(status.state == PLSR_STATE_ACCEL);
  766. CHECK(status.currentSegment == 1U);
  767. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  768. /* DIR 延时 10ms → PWM 启动(段1 起始速度 0,profile 升频后启动)。 */
  769. for (ticks = 0; ticks < 9; ticks++)
  770. {
  771. PlsrProcess();
  772. }
  773. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  774. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  775. CHECK(PlsrCalculateTimerDivider(168000000UL, 75UL,
  776. &initialPsc, &initialArr)
  777. == PLSR_RESULT_OK);
  778. CHECK(PlsrHwTestGetPsc(0U) == initialPsc);
  779. CHECK(PlsrHwTestGetArr(0U) == initialArr);
  780. /* 加速完成 → 状态机进入 RUN。 */
  781. for (ticks = 0; ticks < 500; ticks++)
  782. {
  783. PlsrProcess();
  784. if (TestGetStatus().state == PLSR_STATE_RUN)
  785. {
  786. break;
  787. }
  788. }
  789. status = TestGetStatus();
  790. CHECK(status.state == PLSR_STATE_RUN);
  791. CHECK(status.currentSegment == 1U);
  792. /* 段1 脉冲完成:100 次更新中断 → SEGMENT_COMPLETE → 段2 启动。 */
  793. for (pulse = 0; pulse < 100; pulse++)
  794. {
  795. PlsrHwTestTriggerUpdate(0U);
  796. }
  797. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  798. PlsrProcess();
  799. status = TestGetStatus();
  800. CHECK(status.state == PLSR_STATE_ACCEL);
  801. CHECK(status.currentSegment == 2U);
  802. CHECK(status.logicalPosition == 100);
  803. CHECK(status.taskPulses == 100);
  804. CHECK(status.totalPulses == 100);
  805. CHECK(TestReadSdDword(1000U) == 2);
  806. CHECK(TestReadSdDword(1002U) == 0);
  807. /* 段2:DIR 延时 → PWM → 加速 → RUN。 */
  808. for (ticks = 0; ticks < 600; ticks++)
  809. {
  810. PlsrProcess();
  811. if (TestGetStatus().state == PLSR_STATE_RUN)
  812. {
  813. break;
  814. }
  815. }
  816. status = TestGetStatus();
  817. CHECK(status.state == PLSR_STATE_RUN);
  818. CHECK(status.currentSegment == 2U);
  819. /* 段2 脉冲完成 → 任务结束。 */
  820. for (pulse = 0; pulse < 200; pulse++)
  821. {
  822. PlsrHwTestTriggerUpdate(0U);
  823. }
  824. PlsrProcess();
  825. status = TestGetStatus();
  826. CHECK(status.state == PLSR_STATE_COMPLETED);
  827. CHECK(status.done != 0U);
  828. CHECK(status.logicalPosition == 300);
  829. CHECK(status.taskPulses == 300);
  830. CHECK(status.totalPulses == 300);
  831. CHECK(TestReadSdDword(1000U) == 2);
  832. CHECK(TestReadSdDword(1002U) == 200);
  833. CHECK(TestReadSdDword(1004U) == 200);
  834. CHECK(TestReadSdDword(1006U) == 0);
  835. {
  836. int32_t hsdPulses;
  837. int32_t hsdEquivalent;
  838. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  839. CHECK(hsdPulses == 300);
  840. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent)
  841. == PLC_DEVICE_OK);
  842. CHECK(hsdEquivalent == 300);
  843. }
  844. /* 终态转换后 HAL 回 IDLE(允许重新启动),脉冲已停止。 */
  845. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  846. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  847. }
  848. static void TestEndToEndAbSegment(void)
  849. {
  850. TEST_MEMORY memory;
  851. PLSR_CALL call;
  852. PLSR_STATUS status;
  853. int quarter;
  854. TestResetEnvironment();
  855. (void)memset(&memory, 0, sizeof(memory));
  856. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  857. TestSetSegment(&memory, 1U, 1000U, -2);
  858. call = TestMakeCall(&memory);
  859. call.sequence = 15UL;
  860. call.outputModeOverride = PLSR_OUTPUT_AB;
  861. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  862. PlsrProcess();
  863. status = TestGetStatus();
  864. CHECK(status.state == PLSR_STATE_ACCEL);
  865. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  866. CHECK(status.directionPoint == PLSR_DIRECTION_POINT_NONE);
  867. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  868. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  869. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  870. TestCompleteFirstAbPrime(0U);
  871. /* 负脉冲选择反向相序,完整两个周期后由同一事件链结束任务。 */
  872. PlsrHwTestAdvanceAbQuarter(0U);
  873. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  874. CHECK(PlsrHwTestGetAbPhaseB(0U) == 1U);
  875. for (quarter = 1; quarter < 8; quarter++)
  876. {
  877. PlsrHwTestAdvanceAbQuarter(0U);
  878. }
  879. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  880. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  881. PlsrProcess();
  882. status = TestGetStatus();
  883. CHECK(status.state == PLSR_STATE_COMPLETED);
  884. CHECK(status.done != 0U);
  885. CHECK(status.directionPositive == 0U);
  886. CHECK(status.logicalPosition == -2);
  887. CHECK(status.taskPulses == -2);
  888. CHECK(status.totalPulses == 2);
  889. CHECK(TestReadSdDword(1002U) == -2);
  890. CHECK(TestReadSdDword(1004U) == -2);
  891. CHECK(status.highResourceMask == 0U);
  892. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  893. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  894. }
  895. static void TestPositionOnImmediateStop(void)
  896. {
  897. TEST_MEMORY memory;
  898. PLSR_CALL call;
  899. PLSR_COMMAND command;
  900. PLSR_STATUS status;
  901. int pulse;
  902. int tick;
  903. TestResetEnvironment();
  904. (void)memset(&memory, 0, sizeof(memory));
  905. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  906. TestSetSegment(&memory, 1U, 1000U, 100);
  907. call = TestMakeCall(&memory);
  908. call.sequence = 30UL;
  909. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  910. PlsrProcess();
  911. for (tick = 0; tick < 10; tick++)
  912. {
  913. PlsrProcess();
  914. }
  915. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  916. for (pulse = 0; pulse < 37; pulse++)
  917. {
  918. PlsrHwTestTriggerUpdate(0U);
  919. }
  920. PlsrProcess();
  921. status = TestGetStatus();
  922. CHECK(status.logicalPosition == 37);
  923. CHECK(status.taskPulses == 37);
  924. CHECK(status.totalPulses == 37);
  925. command.sequence = 31UL;
  926. command.axis = 0U;
  927. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  928. command.argument = 0;
  929. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  930. PlsrProcess();
  931. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  932. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  933. == PLSR_RESULT_OK);
  934. PlsrProcess();
  935. status = TestGetStatus();
  936. CHECK(status.state == PLSR_STATE_STOPPED);
  937. CHECK(status.logicalPosition == 37);
  938. CHECK(status.taskPulses == 37);
  939. CHECK(status.totalPulses == 37);
  940. CHECK(TestReadSdDword(1002U) == 37);
  941. command.sequence = 32UL;
  942. command.opcode = PLSR_CMD_CLEAR_TOTAL;
  943. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  944. PlsrProcess();
  945. status = TestGetStatus();
  946. CHECK(status.logicalPosition == 37);
  947. CHECK(status.totalPulses == 0);
  948. }
  949. static void TestAbsolutePositionAccounting(void)
  950. {
  951. TEST_MEMORY memory;
  952. PLSR_CALL call;
  953. PLSR_COMMAND command;
  954. PLSR_STATUS status;
  955. int32_t hsdPosition;
  956. int pulse;
  957. int tick;
  958. TestResetEnvironment();
  959. command.sequence = 40UL;
  960. command.axis = 0U;
  961. command.opcode = PLSR_CMD_SET_POSITION;
  962. command.argument = 100;
  963. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  964. PlsrProcess();
  965. (void)memset(&memory, 0, sizeof(memory));
  966. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  967. TestSetSegment(&memory, 1U, 1000U, 130);
  968. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 1);
  969. call = TestMakeCall(&memory);
  970. call.sequence = 41UL;
  971. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  972. PlsrProcess();
  973. for (tick = 0; tick < 10; tick++)
  974. {
  975. PlsrProcess();
  976. }
  977. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  978. for (pulse = 0; pulse < 30; pulse++)
  979. {
  980. PlsrHwTestTriggerUpdate(0U);
  981. }
  982. PlsrProcess();
  983. status = TestGetStatus();
  984. CHECK(status.state == PLSR_STATE_COMPLETED);
  985. CHECK(status.logicalPosition == 130);
  986. CHECK(status.taskPulses == 30);
  987. CHECK(status.totalPulses == 30);
  988. CHECK(status.positionValid != 0U);
  989. CHECK(PlcDeviceReadHsdDword(0U, &hsdPosition) == PLC_DEVICE_OK);
  990. CHECK(hsdPosition == 130);
  991. }
  992. static void TestEquivalentRemainderAccounting(void)
  993. {
  994. TEST_MEMORY memory;
  995. PLSR_CALL call;
  996. PLSR_STATUS status;
  997. int32_t hsdPulses;
  998. int32_t hsdEquivalent;
  999. TestResetEnvironment();
  1000. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  1001. TestWriteSfdDword(902U, 3UL);
  1002. TestWriteSfdDword(904U, 2UL);
  1003. TestWriteSfdDword(956U, 60000UL);
  1004. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1005. (void)memset(&memory, 0, sizeof(memory));
  1006. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1007. TestSetSegment(&memory, 1U, 1000U, 1);
  1008. call = TestMakeCall(&memory);
  1009. call.sequence = 30UL;
  1010. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  1011. /* 3脉冲/2单位:第一次1单位只输出1脉冲并保存1/2余数。 */
  1012. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1013. PlsrProcess();
  1014. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1015. PlsrHwTestTriggerUpdate(0U);
  1016. PlsrProcess();
  1017. status = TestGetStatus();
  1018. CHECK(status.state == PLSR_STATE_COMPLETED);
  1019. CHECK(status.logicalPosition == 1);
  1020. CHECK(status.taskPulses == 1);
  1021. CHECK(status.totalPulses == 1);
  1022. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  1023. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  1024. CHECK(hsdPulses == 1);
  1025. CHECK(hsdEquivalent == 0);
  1026. /* 第二次1单位合并余数后输出2脉冲;两次合计精确为3脉冲/2单位。 */
  1027. call.sequence = 31UL;
  1028. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1029. PlsrProcess();
  1030. PlsrHwTestTriggerUpdate(0U);
  1031. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1032. PlsrHwTestTriggerUpdate(0U);
  1033. PlsrProcess();
  1034. status = TestGetStatus();
  1035. CHECK(status.state == PLSR_STATE_COMPLETED);
  1036. CHECK(status.logicalPosition == 3);
  1037. CHECK(status.taskPulses == 2);
  1038. CHECK(status.totalPulses == 3);
  1039. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  1040. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  1041. CHECK(hsdPulses == 3);
  1042. CHECK(hsdEquivalent == 2);
  1043. CHECK(TestReadSdDword(1002U) == 2);
  1044. CHECK(TestReadSdDword(1004U) == 1);
  1045. }
  1046. static void TestEquivalentCompatibleError(void)
  1047. {
  1048. TEST_MEMORY memory;
  1049. PLSR_CALL call;
  1050. PLSR_STATUS status;
  1051. int32_t errorCode = -1;
  1052. int32_t errorBlock = -1;
  1053. TestResetEnvironment();
  1054. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  1055. TestWriteSfdDword(902U, 0UL);
  1056. TestWriteSfdDword(904U, 2UL);
  1057. TestWriteSfdDword(956U, 60000UL);
  1058. (void)memset(&memory, 0, sizeof(memory));
  1059. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1060. TestSetSegment(&memory, 1U, 1000U, 1);
  1061. call = TestMakeCall(&memory);
  1062. call.sequence = 32UL;
  1063. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  1064. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1065. PlsrProcess();
  1066. status = TestGetStatus();
  1067. CHECK(status.lastCommandResult == PLSR_RESULT_INVALID_S2);
  1068. CHECK(status.state == PLSR_STATE_IDLE);
  1069. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  1070. CHECK(PlcDeviceReadSd(1011U, &errorBlock) == PLC_DEVICE_OK);
  1071. CHECK(errorCode == 2);
  1072. CHECK(errorBlock == 0);
  1073. /* A valid retry clears the compatible parameter error. */
  1074. TestWriteSfdDword(902U, 3UL);
  1075. call.sequence = 33UL;
  1076. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1077. PlsrProcess();
  1078. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  1079. CHECK(errorCode == 0);
  1080. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  1081. }
  1082. static void TestSoftLimitAndSegmentEvent(void)
  1083. {
  1084. TEST_MEMORY memory;
  1085. PLSR_CALL call;
  1086. PLSR_COMMAND command;
  1087. PLSR_STATUS status;
  1088. PLC_DEVICE_EVENT_RECORD eventRecord;
  1089. int32_t errorCode;
  1090. int pulse;
  1091. int tick;
  1092. TestResetEnvironment();
  1093. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  1094. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1095. CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
  1096. CHECK(PlcDeviceWriteSfd(915U, 0xFFFFU) == PLC_DEVICE_OK);
  1097. TestWriteSfdDword(930U, 100UL);
  1098. TestWriteSfdDword(932U, (uint32_t)(int32_t)-100);
  1099. command.sequence = 40UL;
  1100. command.axis = 0U;
  1101. command.opcode = PLSR_CMD_SET_POSITION;
  1102. command.argument = 100;
  1103. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1104. PlsrProcess();
  1105. (void)memset(&memory, 0, sizeof(memory));
  1106. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1107. TestSetSegment(&memory, 1U, 1000U, 10);
  1108. call = TestMakeCall(&memory);
  1109. call.sequence = 41UL;
  1110. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1111. PlsrProcess();
  1112. status = TestGetStatus();
  1113. CHECK(status.lastCommandResult == PLSR_RESULT_LIMIT_POSITIVE);
  1114. CHECK(status.state == PLSR_STATE_IDLE);
  1115. CHECK(status.positiveLimitActive != 0U);
  1116. CHECK(status.error == PLSR_ERROR_LIMIT_POSITIVE);
  1117. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  1118. CHECK(errorCode == 5);
  1119. /* 正限位上只禁止正向,反向离开仍可正常完成。 */
  1120. TestSetSegment(&memory, 1U, 1000U, -10);
  1121. call.sequence = 42UL;
  1122. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1123. PlsrProcess();
  1124. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1125. for (pulse = 0; pulse < 10; pulse++)
  1126. {
  1127. PlsrHwTestTriggerUpdate(0U);
  1128. }
  1129. PlsrProcess();
  1130. status = TestGetStatus();
  1131. CHECK(status.state == PLSR_STATE_COMPLETED);
  1132. CHECK(status.logicalPosition == 90);
  1133. CHECK(status.error == PLSR_ERROR_NONE);
  1134. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1135. CHECK(eventRecord.count == 1UL);
  1136. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  1137. CHECK(eventRecord.pending != 0U);
  1138. /* 运行中按预计制动距离触发软限位,PWM保持运行并按曲线缓停。 */
  1139. TestResetEnvironment();
  1140. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  1141. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1142. TestWriteSfdDword(930U, 50UL);
  1143. TestWriteSfdDword(932U, (uint32_t)(int32_t)-50);
  1144. command.sequence = 43UL;
  1145. command.opcode = PLSR_CMD_SET_POSITION;
  1146. command.argument = 0;
  1147. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1148. PlsrProcess();
  1149. (void)memset(&memory, 0, sizeof(memory));
  1150. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1151. TestSetSegment(&memory, 1U, 1000U, 10000);
  1152. call = TestMakeCall(&memory);
  1153. call.sequence = 44UL;
  1154. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1155. PlsrProcess();
  1156. for (pulse = 0; pulse < 49; pulse++)
  1157. {
  1158. PlsrHwTestTriggerUpdate(0U);
  1159. }
  1160. PlsrProcess();
  1161. status = TestGetStatus();
  1162. CHECK(status.state == PLSR_STATE_DECEL);
  1163. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1164. CHECK(status.positiveLimitActive != 0U);
  1165. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1166. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  1167. CHECK(errorCode == 5);
  1168. for (tick = 0; tick < 20; tick++)
  1169. {
  1170. PlsrProcess();
  1171. }
  1172. status = TestGetStatus();
  1173. CHECK(status.state == PLSR_STATE_STOPPED);
  1174. CHECK(status.logicalPosition == 49);
  1175. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1176. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1177. CHECK(eventRecord.count == 1UL);
  1178. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1179. }
  1180. static void TestHardLimitAndEmergencyLatch(void)
  1181. {
  1182. TEST_MEMORY memory;
  1183. PLSR_CALL call;
  1184. PLSR_COMMAND command;
  1185. PLSR_STATUS status;
  1186. PLC_DEVICE_EVENT_RECORD eventRecord;
  1187. TestResetEnvironment();
  1188. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1189. CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
  1190. CHECK(PlcDeviceWriteSfd(915U, 0xFF03U) == PLC_DEVICE_OK);
  1191. (void)memset(&memory, 0, sizeof(memory));
  1192. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1193. TestSetSegment(&memory, 1U, 1000U, 10000);
  1194. call = TestMakeCall(&memory);
  1195. call.sequence = 50UL;
  1196. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1197. PlsrProcess();
  1198. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1199. memory.bits[0][3U] = 1U;
  1200. PlsrProcess();
  1201. status = TestGetStatus();
  1202. CHECK(status.state == PLSR_STATE_DECEL);
  1203. CHECK(status.positiveLimitActive != 0U);
  1204. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1205. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1206. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1207. TestResetEnvironment();
  1208. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  1209. (void)memset(&memory, 0, sizeof(memory));
  1210. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1211. TestSetSegment(&memory, 1U, 1000U, 10000);
  1212. call = TestMakeCall(&memory);
  1213. call.sequence = 51UL;
  1214. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1215. PlsrProcess();
  1216. command.sequence = 52UL;
  1217. command.axis = 0U;
  1218. command.opcode = PLSR_CMD_RESET_ERROR;
  1219. command.argument = 0;
  1220. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1221. CHECK(PlsrPostEvent(0U,
  1222. PLSR_EVENT_LIMIT_POSITIVE
  1223. | PLSR_EVENT_SOFTWARE_EMERGENCY)
  1224. == PLSR_RESULT_OK);
  1225. PlsrProcess();
  1226. status = TestGetStatus();
  1227. CHECK(status.state == PLSR_STATE_STOPPED);
  1228. CHECK(status.stopReason == PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
  1229. CHECK(status.error == PLSR_ERROR_EMERGENCY);
  1230. CHECK(status.emergencyLatched != 0U);
  1231. CHECK(status.lastCommandSequence == 52UL);
  1232. CHECK(status.lastCommandResult == PLSR_RESULT_BUSY);
  1233. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1234. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1235. CHECK(eventRecord.count == 1UL);
  1236. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
  1237. call.sequence = 53UL;
  1238. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1239. PlsrProcess();
  1240. status = TestGetStatus();
  1241. CHECK(status.lastCommandResult == PLSR_RESULT_EMERGENCY_LATCHED);
  1242. CHECK(status.state == PLSR_STATE_STOPPED);
  1243. command.sequence = 54UL;
  1244. command.axis = 0U;
  1245. command.opcode = PLSR_CMD_RESET_ERROR;
  1246. command.argument = 0;
  1247. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1248. PlsrProcess();
  1249. status = TestGetStatus();
  1250. CHECK(status.state == PLSR_STATE_IDLE);
  1251. CHECK(status.error == PLSR_ERROR_NONE);
  1252. CHECK(status.emergencyLatched == 0U);
  1253. }
  1254. static void TestProductionSelfTestStartsAb(void)
  1255. {
  1256. PLSR_STATUS status;
  1257. TestResetEnvironment();
  1258. CHECK(PlsrSelfTestQueue() == PLSR_RESULT_QUEUED);
  1259. PlsrProcess();
  1260. status = TestGetStatus();
  1261. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  1262. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  1263. CHECK(status.currentSegment == 1U);
  1264. CHECK(status.state == PLSR_STATE_ACCEL);
  1265. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1266. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  1267. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  1268. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  1269. }
  1270. static void TestEquivalentSelfTest(void)
  1271. {
  1272. PLSR_STATUS status;
  1273. int32_t hsdPulses;
  1274. int32_t hsdEquivalent;
  1275. int ticks;
  1276. TestResetEnvironment();
  1277. CHECK(PlsrEquivalentSelfTestQueue() == PLSR_RESULT_QUEUED);
  1278. PlsrProcess();
  1279. /* SFD907=10ms. Advance the simulated hardware delay before segment 1. */
  1280. for (ticks = 0; ticks < 10; ticks++)
  1281. {
  1282. PlsrProcess();
  1283. }
  1284. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1285. /* 3 pulses / 2 units: 1001 units emit 1501 pulses and keep 1/2 remainder. */
  1286. for (ticks = 0; ticks < 1501; ticks++)
  1287. {
  1288. PlsrHwTestTriggerUpdate(0U);
  1289. }
  1290. PlsrProcess();
  1291. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1292. /* Segment 2 consumes the remainder and therefore emits 1502 pulses. */
  1293. for (ticks = 0; ticks < 1502; ticks++)
  1294. {
  1295. PlsrHwTestTriggerUpdate(0U);
  1296. }
  1297. PlsrProcess();
  1298. status = TestGetStatus();
  1299. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  1300. CHECK(status.outputMode == PLSR_OUTPUT_PULSE_DIR);
  1301. CHECK(status.state == PLSR_STATE_COMPLETED);
  1302. CHECK(status.currentSegment == 2U);
  1303. CHECK(status.logicalPosition == 3003);
  1304. CHECK(status.taskPulses == 3003);
  1305. CHECK(status.totalPulses == 3003);
  1306. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  1307. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  1308. CHECK(hsdPulses == 3003);
  1309. CHECK(hsdEquivalent == 2002);
  1310. CHECK(TestReadSdDword(1002U) == 1502);
  1311. CHECK(TestReadSdDword(1004U) == 1001);
  1312. }
  1313. static void TestProtectionSelfTest(void)
  1314. {
  1315. PLC_DEVICE_EVENT_RECORD eventRecord;
  1316. PLSR_STATUS status;
  1317. uint32_t pulseAccumulator = 0UL;
  1318. int32_t value;
  1319. int ticks;
  1320. TestResetEnvironment();
  1321. CHECK(PlsrProtectionSelfTestQueue() == PLSR_RESULT_QUEUED);
  1322. PlsrProcess();
  1323. /* Complete the 10ms direction-settle interval. */
  1324. for (ticks = 0; ticks < 10; ticks++)
  1325. {
  1326. PlsrProcess();
  1327. }
  1328. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1329. /* Convert the current frequency into simulated hardware updates over
  1330. * each 1ms process tick. This also models the falling pulse density
  1331. * during the controlled stop. */
  1332. status = TestGetStatus();
  1333. for (ticks = 0; ticks < 600; ticks++)
  1334. {
  1335. pulseAccumulator += PlsrHwGetCurrentFrequencyHz(0U);
  1336. while ((pulseAccumulator >= 1000UL)
  1337. && (PlsrHwIsPulseActive(0U) != 0U))
  1338. {
  1339. PlsrHwTestTriggerUpdate(0U);
  1340. pulseAccumulator -= 1000UL;
  1341. }
  1342. PlsrProcess();
  1343. status = TestGetStatus();
  1344. if (status.state == PLSR_STATE_STOPPED)
  1345. {
  1346. break;
  1347. }
  1348. }
  1349. status = TestGetStatus();
  1350. CHECK(status.state == PLSR_STATE_STOPPED);
  1351. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1352. CHECK(status.error == PLSR_ERROR_LIMIT_POSITIVE);
  1353. CHECK(status.emergencyLatched == 0U);
  1354. CHECK(status.logicalPosition >= 499);
  1355. CHECK(status.logicalPosition <= 501);
  1356. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1357. CHECK(PlcDeviceReadSd(1010U, &value) == PLC_DEVICE_OK);
  1358. CHECK(value == 5U);
  1359. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1360. CHECK(eventRecord.count == 1UL);
  1361. CHECK(eventRecord.pending != 0U);
  1362. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1363. }
  1364. static void TestFourAxisSelfTest(void)
  1365. {
  1366. static const uint32_t expectedFrequency[PLSR_AXIS_COUNT] =
  1367. {
  1368. 1000UL, 2000UL, 3000UL, 4000UL
  1369. };
  1370. static const int32_t expectedPulses[PLSR_AXIS_COUNT] =
  1371. {
  1372. 1000, 2000, 3000, 4000
  1373. };
  1374. PLC_DEVICE_EVENT_RECORD eventRecord;
  1375. PLSR_RESOURCE_STATUS resources;
  1376. PLSR_STATUS status;
  1377. int32_t hsdPulses;
  1378. int subTick;
  1379. int ticks;
  1380. uint8_t axis;
  1381. TestResetEnvironment();
  1382. CHECK(PlsrFourAxisSelfTestQueue() == PLSR_RESULT_QUEUED);
  1383. PlsrProcess();
  1384. for (ticks = 0; ticks < 10; ticks++)
  1385. {
  1386. PlsrProcess();
  1387. }
  1388. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  1389. {
  1390. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1391. CHECK(status.state == PLSR_STATE_RUN);
  1392. CHECK(status.outputMode == PLSR_OUTPUT_PULSE_DIR);
  1393. CHECK(status.directionPoint == (uint8_t)(4U + axis));
  1394. CHECK(status.directionPositive != 0U);
  1395. CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_RUNNING);
  1396. CHECK(PlsrHwGetCurrentFrequencyHz(axis)
  1397. == expectedFrequency[axis]);
  1398. }
  1399. /* A 0.25ms base slot produces 1/2/3/4kHz update ratios while all four
  1400. * hardware channels are active concurrently for one simulated second. */
  1401. for (subTick = 0; subTick < 4000; subTick++)
  1402. {
  1403. if ((subTick & 3) == 0)
  1404. {
  1405. PlsrHwTestTriggerUpdate(0U);
  1406. }
  1407. if ((subTick & 1) == 0)
  1408. {
  1409. PlsrHwTestTriggerUpdate(1U);
  1410. }
  1411. if ((subTick & 3) != 3)
  1412. {
  1413. PlsrHwTestTriggerUpdate(2U);
  1414. }
  1415. PlsrHwTestTriggerUpdate(3U);
  1416. if ((subTick & 3) == 3)
  1417. {
  1418. PlsrProcess();
  1419. }
  1420. }
  1421. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  1422. {
  1423. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1424. CHECK(status.state == PLSR_STATE_COMPLETED);
  1425. CHECK(status.stopReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  1426. CHECK(status.done != 0U);
  1427. CHECK(status.logicalPosition == expectedPulses[axis]);
  1428. CHECK(status.taskPulses == expectedPulses[axis]);
  1429. CHECK(status.totalPulses == expectedPulses[axis]);
  1430. CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_IDLE);
  1431. CHECK(PlcDeviceReadHsdDword((uint16_t)(axis * 4U),
  1432. &hsdPulses) == PLC_DEVICE_OK);
  1433. CHECK(hsdPulses == expectedPulses[axis]);
  1434. CHECK(PlcDeviceReadEvent((uint16_t)(6000U
  1435. + (uint16_t)axis * 100U),
  1436. &eventRecord) == PLC_DEVICE_OK);
  1437. CHECK(eventRecord.count == 1UL);
  1438. CHECK(eventRecord.pending != 0U);
  1439. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  1440. }
  1441. PlsrResourceGetStatus(&resources);
  1442. CHECK(resources.outputMask == 0UL);
  1443. CHECK(resources.highMask == 0U);
  1444. CHECK(PlsrResourceCheckInvariant() != 0U);
  1445. }
  1446. static void TestBacklashSelfTest(void)
  1447. {
  1448. PLC_DEVICE_EVENT_RECORD eventRecord;
  1449. PLSR_STATUS status;
  1450. int32_t hsdPosition;
  1451. int ticks;
  1452. TestResetEnvironment();
  1453. CHECK(PlsrBacklashSelfTestQueue() == PLSR_RESULT_QUEUED);
  1454. PlsrProcess();
  1455. for (ticks = 0; ticks < 10; ticks++)
  1456. {
  1457. PlsrProcess();
  1458. }
  1459. /* Segment 1: +200 user pulses, with no compensation on first motion. */
  1460. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1461. for (ticks = 0; ticks < 200; ticks++)
  1462. {
  1463. PlsrHwTestTriggerUpdate(0U);
  1464. }
  1465. PlsrProcess();
  1466. status = TestGetStatus();
  1467. CHECK(status.currentSegment == 2U);
  1468. CHECK(status.backlashActive != 0U);
  1469. CHECK(status.directionPositive == 0U);
  1470. CHECK(status.logicalPosition == 200);
  1471. CHECK(status.taskPulses == 200);
  1472. CHECK(status.totalPulses == 200);
  1473. CHECK(status.physicalPulses == 200UL);
  1474. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1475. CHECK(eventRecord.count == 1UL);
  1476. CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
  1477. CHECK(eventRecord.count == 0UL);
  1478. /* Direction change to negative: 20 physical compensation pulses first. */
  1479. for (ticks = 0; ticks < 10; ticks++)
  1480. {
  1481. PlsrProcess();
  1482. }
  1483. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1484. for (ticks = 0; ticks < 20; ticks++)
  1485. {
  1486. PlsrHwTestTriggerUpdate(0U);
  1487. }
  1488. PlsrProcess();
  1489. status = TestGetStatus();
  1490. CHECK(status.backlashActive == 0U);
  1491. CHECK(status.currentSegment == 2U);
  1492. CHECK(status.logicalPosition == 200);
  1493. CHECK(status.taskPulses == 200);
  1494. CHECK(status.totalPulses == 200);
  1495. CHECK(status.physicalPulses == 220UL);
  1496. CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
  1497. CHECK(eventRecord.count == 0UL);
  1498. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1499. /* The real segment 2 contributes -200 to user position/counting. */
  1500. for (ticks = 0; ticks < 200; ticks++)
  1501. {
  1502. PlsrHwTestTriggerUpdate(0U);
  1503. }
  1504. PlsrProcess();
  1505. status = TestGetStatus();
  1506. CHECK(status.currentSegment == 3U);
  1507. CHECK(status.backlashActive != 0U);
  1508. CHECK(status.directionPositive != 0U);
  1509. CHECK(status.logicalPosition == 0);
  1510. CHECK(status.taskPulses == 0);
  1511. CHECK(status.totalPulses == 400);
  1512. CHECK(status.physicalPulses == 420UL);
  1513. CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
  1514. CHECK(eventRecord.count == 1UL);
  1515. CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
  1516. CHECK(eventRecord.count == 0UL);
  1517. /* Direction change back to positive: 10 compensation, then +100 user. */
  1518. for (ticks = 0; ticks < 10; ticks++)
  1519. {
  1520. PlsrProcess();
  1521. }
  1522. for (ticks = 0; ticks < 10; ticks++)
  1523. {
  1524. PlsrHwTestTriggerUpdate(0U);
  1525. }
  1526. PlsrProcess();
  1527. status = TestGetStatus();
  1528. CHECK(status.backlashActive == 0U);
  1529. CHECK(status.logicalPosition == 0);
  1530. CHECK(status.totalPulses == 400);
  1531. CHECK(status.physicalPulses == 430UL);
  1532. CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
  1533. CHECK(eventRecord.count == 0UL);
  1534. for (ticks = 0; ticks < 100; ticks++)
  1535. {
  1536. PlsrHwTestTriggerUpdate(0U);
  1537. }
  1538. PlsrProcess();
  1539. status = TestGetStatus();
  1540. CHECK(status.state == PLSR_STATE_COMPLETED);
  1541. CHECK(status.done != 0U);
  1542. CHECK(status.logicalPosition == 100);
  1543. CHECK(status.taskPulses == 100);
  1544. CHECK(status.totalPulses == 500);
  1545. CHECK(status.physicalPulses == 530UL);
  1546. CHECK(PlcDeviceReadHsdDword(0U, &hsdPosition) == PLC_DEVICE_OK);
  1547. CHECK(hsdPosition == 100);
  1548. CHECK(PlcDeviceReadEvent(6002U, &eventRecord) == PLC_DEVICE_OK);
  1549. CHECK(eventRecord.count == 1UL);
  1550. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  1551. }
  1552. static void TestDirectionLogicSelfTest(void)
  1553. {
  1554. static const uint8_t expectedDirectionPoint[2] = {4U, 3U};
  1555. PLC_DEVICE_EVENT_RECORD eventRecord;
  1556. PLSR_STATUS status;
  1557. uint8_t smDirection;
  1558. uint8_t axis;
  1559. int ticks;
  1560. TestResetEnvironment();
  1561. CHECK(PlsrDirectionLogicSelfTestQueue() == PLSR_RESULT_QUEUED);
  1562. PlsrProcess();
  1563. for (ticks = 0; ticks < 10; ticks++)
  1564. {
  1565. PlsrProcess();
  1566. }
  1567. /* Both axes move logically positive. Electrical DIR terminals are
  1568. * complementary because axis 1 has SFD1030 Bit1 set. */
  1569. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  1570. CHECK(PlsrHwTestGetDirLevel(1U) == 0U);
  1571. for (axis = 0U; axis < 2U; axis++)
  1572. {
  1573. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1574. CHECK(status.state == PLSR_STATE_RUN);
  1575. CHECK(status.directionPoint == expectedDirectionPoint[axis]);
  1576. CHECK(status.directionPositive != 0U);
  1577. CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_RUNNING);
  1578. }
  1579. for (ticks = 0; ticks < 200; ticks++)
  1580. {
  1581. PlsrHwTestTriggerUpdate(0U);
  1582. PlsrHwTestTriggerUpdate(1U);
  1583. }
  1584. PlsrProcess();
  1585. /* Both reverse logically; only the physical terminal mapping differs. */
  1586. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  1587. CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
  1588. for (axis = 0U; axis < 2U; axis++)
  1589. {
  1590. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1591. CHECK(status.currentSegment == 2U);
  1592. CHECK(status.directionPositive == 0U);
  1593. CHECK(status.logicalPosition == 200);
  1594. CHECK(status.totalPulses == 200);
  1595. CHECK(PlsrHwGetState(axis) == PLSR_HW_STATE_DIR_SETTLING);
  1596. }
  1597. for (ticks = 0; ticks < 10; ticks++)
  1598. {
  1599. PlsrProcess();
  1600. }
  1601. for (ticks = 0; ticks < 200; ticks++)
  1602. {
  1603. PlsrHwTestTriggerUpdate(0U);
  1604. PlsrHwTestTriggerUpdate(1U);
  1605. }
  1606. PlsrProcess();
  1607. for (axis = 0U; axis < 2U; axis++)
  1608. {
  1609. CHECK(PlsrGetStatus(axis, &status) == PLSR_RESULT_OK);
  1610. CHECK(status.state == PLSR_STATE_COMPLETED);
  1611. CHECK(status.done != 0U);
  1612. CHECK(status.directionPositive == 0U);
  1613. CHECK(status.logicalPosition == 0);
  1614. CHECK(status.taskPulses == 0);
  1615. CHECK(status.totalPulses == 400);
  1616. CHECK(status.physicalPulses == 400UL);
  1617. CHECK(PlcDeviceReadSm((uint16_t)(1001U
  1618. + (uint16_t)axis * 20U),
  1619. &smDirection) == PLC_DEVICE_OK);
  1620. CHECK(smDirection == 0U);
  1621. CHECK(PlcDeviceReadEvent((uint16_t)(6000U
  1622. + (uint16_t)axis * 100U),
  1623. &eventRecord) == PLC_DEVICE_OK);
  1624. CHECK(eventRecord.count == 1UL);
  1625. CHECK(PlcDeviceReadEvent((uint16_t)(6001U
  1626. + (uint16_t)axis * 100U),
  1627. &eventRecord) == PLC_DEVICE_OK);
  1628. CHECK(eventRecord.count == 1UL);
  1629. }
  1630. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  1631. CHECK(PlsrHwTestGetDirLevel(1U) == 1U);
  1632. }
  1633. static void TestCwCcwSelfTest(void)
  1634. {
  1635. PLC_DEVICE_EVENT_RECORD eventRecord;
  1636. PLSR_STATUS status;
  1637. int pulse;
  1638. TestResetEnvironment();
  1639. CHECK(PlsrCwCcwSelfTestQueue() == PLSR_RESULT_QUEUED);
  1640. PlsrProcess();
  1641. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1642. CHECK(status.state == PLSR_STATE_RUN);
  1643. CHECK(status.outputMode == PLSR_OUTPUT_CW_CCW);
  1644. CHECK(status.directionPositive != 0U);
  1645. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  1646. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  1647. for (pulse = 0; pulse < 300; pulse++)
  1648. {
  1649. PlsrHwTestTriggerCompare(0U);
  1650. }
  1651. PlsrHwTestTriggerUpdate(0U);
  1652. PlsrProcess();
  1653. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1654. CHECK(status.currentSegment == 2U);
  1655. CHECK(status.directionPositive == 0U);
  1656. CHECK(status.logicalPosition == 300);
  1657. CHECK(status.totalPulses == 300);
  1658. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  1659. CHECK(PlsrHwTestGetPwmEnabled(1U) == 1U);
  1660. for (pulse = 0; pulse < 200; pulse++)
  1661. {
  1662. PlsrHwTestTriggerCompare(1U);
  1663. }
  1664. PlsrHwTestTriggerUpdate(1U);
  1665. PlsrProcess();
  1666. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1667. CHECK(status.state == PLSR_STATE_COMPLETED);
  1668. CHECK(status.done != 0U);
  1669. CHECK(status.logicalPosition == 100);
  1670. CHECK(status.taskPulses == 100);
  1671. CHECK(status.totalPulses == 500);
  1672. CHECK(status.physicalPulses == 500UL);
  1673. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  1674. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  1675. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1676. CHECK(eventRecord.count == 1UL);
  1677. CHECK(PlcDeviceReadEvent(6001U, &eventRecord) == PLC_DEVICE_OK);
  1678. CHECK(eventRecord.count == 1UL);
  1679. }
  1680. static void TestFastRefreshSelfTest(void)
  1681. {
  1682. PLSR_STATUS status;
  1683. uint32_t beforeFastHz;
  1684. uint16_t refreshCode;
  1685. int tick;
  1686. TestResetEnvironment();
  1687. CHECK(PlsrFastRefreshSelfTestQueue() == PLSR_RESULT_QUEUED);
  1688. PlsrProcess();
  1689. for (tick = 0; tick < 10; tick++)
  1690. {
  1691. PlsrProcess();
  1692. }
  1693. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1694. CHECK(status.state == PLSR_STATE_ACCEL);
  1695. CHECK(status.directionPoint == 4U);
  1696. CHECK(PlsrHwGetCurrentFrequencyHz(0U) > 0UL);
  1697. CHECK(PlsrGetStatus(1U, &status) == PLSR_RESULT_OK);
  1698. CHECK(status.state == PLSR_STATE_ACCEL);
  1699. CHECK(status.directionPoint == 3U);
  1700. CHECK(PlsrTestGetJobRefreshCode(1U) == 2U);
  1701. CHECK(PlsrTestGetProfileRefreshHz(1U) == 10000UL);
  1702. beforeFastHz = PlsrTestGetProfileFrequencyHz(1U);
  1703. PlsrControlTick100us();
  1704. CHECK(PlsrTestGetProfileFrequencyHz(1U) > beforeFastHz);
  1705. CHECK(PlcDeviceReadSfd(964U, &refreshCode) == PLC_DEVICE_OK);
  1706. CHECK(refreshCode == 0U);
  1707. CHECK(PlcDeviceReadSfd(1094U, &refreshCode) == PLC_DEVICE_OK);
  1708. CHECK(refreshCode == 2U);
  1709. }
  1710. static void TestDynamicFrequencySelfTest(void)
  1711. {
  1712. PLSR_STATUS status;
  1713. int tick;
  1714. TestResetEnvironment();
  1715. CHECK(PlsrDynamicFrequencySelfTestQueue() == PLSR_RESULT_QUEUED);
  1716. PlsrProcess();
  1717. for (tick = 0; tick < 10; tick++)
  1718. {
  1719. PlsrProcess();
  1720. }
  1721. PlsrControlTick100us();
  1722. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1723. CHECK(status.currentFrequencyHz == 1000UL);
  1724. CHECK(status.targetFrequencyHz == 1000UL);
  1725. PlsrSelfTestLiveFrequencyHz = 4000;
  1726. PlsrControlTick100us();
  1727. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1728. CHECK(status.currentFrequencyHz == 1001UL);
  1729. CHECK(status.targetFrequencyHz == 4000UL);
  1730. PlsrSelfTestLiveFrequencyHz = 500;
  1731. PlsrControlTick100us();
  1732. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1733. CHECK(status.currentFrequencyHz == 1000UL);
  1734. CHECK(status.targetFrequencyHz == 500UL);
  1735. CHECK(status.liveFrequencyRejectCount == 0UL);
  1736. }
  1737. static void TestDynamicFrequencySchedule(void)
  1738. {
  1739. int tick;
  1740. TestResetEnvironment();
  1741. CHECK(PlsrDynamicFrequencySelfTestQueue() == PLSR_RESULT_QUEUED);
  1742. CHECK(PlsrSelfTestLiveFrequencyHz == 1000);
  1743. CHECK(PlsrSelfTestDynamicPhase == 0U);
  1744. for (tick = 0; tick < 9999; tick++)
  1745. {
  1746. PlsrSelfTestControlTick100us();
  1747. }
  1748. CHECK(PlsrSelfTestLiveFrequencyHz == 1000);
  1749. PlsrSelfTestControlTick100us();
  1750. CHECK(PlsrSelfTestLiveFrequencyHz == 4000);
  1751. CHECK(PlsrSelfTestDynamicPhase == 1U);
  1752. for (tick = 0; tick < 5000; tick++)
  1753. {
  1754. PlsrSelfTestControlTick100us();
  1755. }
  1756. CHECK(PlsrSelfTestLiveFrequencyHz == 500);
  1757. CHECK(PlsrSelfTestDynamicPhase == 2U);
  1758. for (tick = 0; tick < 5000; tick++)
  1759. {
  1760. PlsrSelfTestControlTick100us();
  1761. }
  1762. CHECK(PlsrSelfTestLiveFrequencyHz == 0);
  1763. CHECK(PlsrSelfTestDynamicPhase == 3U);
  1764. for (tick = 0; tick < 2000; tick++)
  1765. {
  1766. PlsrSelfTestControlTick100us();
  1767. }
  1768. CHECK(PlsrSelfTestLiveFrequencyHz == 8000);
  1769. CHECK(PlsrSelfTestDynamicPhase == 4U);
  1770. for (tick = 0; tick < 5000; tick++)
  1771. {
  1772. PlsrSelfTestControlTick100us();
  1773. }
  1774. CHECK(PlsrSelfTestLiveFrequencyHz == -1);
  1775. CHECK(PlsrSelfTestDynamicPhase == 5U);
  1776. for (tick = 0; tick < 2000; tick++)
  1777. {
  1778. PlsrSelfTestControlTick100us();
  1779. }
  1780. CHECK(PlsrSelfTestLiveFrequencyHz == 2000);
  1781. CHECK(PlsrSelfTestDynamicPhase == 6U);
  1782. CHECK(PlsrSelfTestDynamicTick100us == 29000UL);
  1783. PlsrSelfTestControlTick100us();
  1784. CHECK(PlsrSelfTestDynamicTick100us == 29000UL);
  1785. }
  1786. static void TestModbusDataSelfTest(void)
  1787. {
  1788. PLSR_STATUS status;
  1789. uint16_t frequencyWords[2];
  1790. uint16_t word;
  1791. int tick;
  1792. TestResetEnvironment();
  1793. CHECK(PlsrModbusDataSelfTestQueue() == PLSR_RESULT_QUEUED);
  1794. PlsrProcess();
  1795. for (tick = 0; tick < 10; tick++)
  1796. {
  1797. PlsrProcess();
  1798. }
  1799. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D, 1000UL, &word) == 1U);
  1800. CHECK(word == 1U);
  1801. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1802. CHECK((status.state == PLSR_STATE_ACCEL) || (status.state == PLSR_STATE_RUN));
  1803. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  1804. CHECK(status.currentFrequencyHz == 1000UL);
  1805. CHECK(status.targetFrequencyHz == 1000UL);
  1806. frequencyWords[0] = 4000U;
  1807. frequencyWords[1] = 0U;
  1808. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1809. 1010UL,
  1810. frequencyWords,
  1811. 2UL) == 1U);
  1812. PlsrControlTick100us();
  1813. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1814. CHECK(status.currentFrequencyHz == 1001UL);
  1815. CHECK(status.targetFrequencyHz == 4000UL);
  1816. CHECK(status.liveFrequencyRejectCount == 0UL);
  1817. frequencyWords[0] = 0xFFFFU;
  1818. frequencyWords[1] = 0xFFFFU;
  1819. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1820. 1010UL,
  1821. frequencyWords,
  1822. 2UL) == 1U);
  1823. PlsrControlTick100us();
  1824. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  1825. CHECK(status.targetFrequencyHz == 4000UL);
  1826. CHECK(status.liveFrequencyRejectCount == 1UL);
  1827. CHECK(status.lastLiveFrequencyResult == PLSR_RESULT_INVALID_FREQUENCY);
  1828. }
  1829. static void TestModbusControlProtocol(void)
  1830. {
  1831. const uint32_t controlBase = 1200UL;
  1832. const uint32_t s0Base = 1600UL;
  1833. const uint32_t s1Base = 1700UL;
  1834. uint16_t s0Words[20] = {0U};
  1835. uint16_t s1Words[4] = {0U};
  1836. uint16_t callRequest[16] = {0U};
  1837. uint16_t callResponse[12];
  1838. uint16_t commandRequest[8] = {0U};
  1839. uint16_t commandResponse[8];
  1840. uint16_t axisStatus[48];
  1841. uint16_t pulseWords[2];
  1842. uint32_t generationBegin;
  1843. uint32_t generationEnd;
  1844. PLSR_STATUS coreStatus;
  1845. int64_t pausedPulses;
  1846. int tick;
  1847. TestResetEnvironment();
  1848. CHECK(PlsrModbusControlSelfTestPrepare() == PLSR_RESULT_OK);
  1849. CHECK(PlsrModbusControlInit((uint16_t)controlBase) == PLSR_RESULT_OK);
  1850. CHECK(PlsrModbusControlIsEnabled() == 1U);
  1851. CHECK(PlsrModbusControlGetBaseAddress() == controlBase);
  1852. s0Words[0] = 1U;
  1853. s0Words[10] = 2000U;
  1854. s0Words[12] = (uint16_t)(50000UL & 0xFFFFUL);
  1855. s0Words[13] = (uint16_t)(50000UL >> 16U);
  1856. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1857. s0Base,
  1858. s0Words,
  1859. 20UL) == 1U);
  1860. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1861. s1Base,
  1862. s1Words,
  1863. 4UL) == 1U);
  1864. callRequest[0] = 1U;
  1865. callRequest[2] = PLSR_DEVICE_D;
  1866. callRequest[3] = (uint16_t)s0Base;
  1867. callRequest[5] = PLSR_DEVICE_D;
  1868. callRequest[6] = (uint16_t)s1Base;
  1869. callRequest[8] = PLSR_OPERAND_CONSTANT;
  1870. callRequest[10] = 1U;
  1871. callRequest[12] = 0U;
  1872. callRequest[13] = PLSR_OUTPUT_PULSE_DIR;
  1873. callRequest[14] = PLSR_MODBUS_CALL_COMMIT;
  1874. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1875. controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
  1876. callRequest,
  1877. 16UL) == 1U);
  1878. PlsrModbusControlPoll();
  1879. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  1880. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET,
  1881. &callResponse[0]) == 1U);
  1882. for (tick = 1; tick < 12; tick++)
  1883. {
  1884. CHECK(ModbusDataReadWord(
  1885. MODBUS_DATA_DEVICE_D,
  1886. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
  1887. + (uint32_t)tick,
  1888. &callResponse[tick]) == 1U);
  1889. }
  1890. CHECK(callResponse[0] == 1U);
  1891. CHECK(callResponse[2] == PLSR_MODBUS_CALL_COMMIT);
  1892. CHECK(callResponse[3] == PLSR_RESULT_OK);
  1893. CHECK(callResponse[11] == 1U);
  1894. /* Any S0 edit after COMMIT invalidates START until a new COMMIT. */
  1895. pulseWords[0] = (uint16_t)(50001UL & 0xFFFFUL);
  1896. pulseWords[1] = (uint16_t)(50001UL >> 16U);
  1897. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1898. s0Base + 12UL,
  1899. pulseWords,
  1900. 2UL) == 1U);
  1901. callRequest[0] = 2U;
  1902. callRequest[14] = PLSR_MODBUS_CALL_START;
  1903. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1904. controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
  1905. callRequest,
  1906. 16UL) == 1U);
  1907. PlsrModbusControlPoll();
  1908. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  1909. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
  1910. + 3UL,
  1911. &callResponse[3]) == 1U);
  1912. CHECK(callResponse[3] == PLSR_RESULT_BUSY);
  1913. pulseWords[0] = (uint16_t)(50000UL & 0xFFFFUL);
  1914. pulseWords[1] = (uint16_t)(50000UL >> 16U);
  1915. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1916. s0Base + 12UL,
  1917. pulseWords,
  1918. 2UL) == 1U);
  1919. callRequest[0] = 3U;
  1920. callRequest[14] = PLSR_MODBUS_CALL_COMMIT;
  1921. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1922. controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
  1923. callRequest,
  1924. 16UL) == 1U);
  1925. PlsrModbusControlPoll();
  1926. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  1927. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
  1928. + 3UL,
  1929. &callResponse[3]) == 1U);
  1930. CHECK(callResponse[3] == PLSR_RESULT_OK);
  1931. callRequest[0] = 4U;
  1932. callRequest[14] = PLSR_MODBUS_CALL_START;
  1933. CHECK(ModbusDataWriteWords(MODBUS_DATA_DEVICE_D,
  1934. controlBase + PLSR_MODBUS_CALL_REQUEST_OFFSET,
  1935. callRequest,
  1936. 16UL) == 1U);
  1937. PlsrModbusControlPoll();
  1938. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  1939. controlBase + PLSR_MODBUS_CALL_RESPONSE_OFFSET
  1940. + 3UL,
  1941. &callResponse[3]) == 1U);
  1942. CHECK(callResponse[3] == PLSR_RESULT_QUEUED);
  1943. for (tick = 0; tick < 10; tick++)
  1944. {
  1945. PlsrProcess();
  1946. }
  1947. PlsrModbusControlPoll();
  1948. for (tick = 0; tick < 48; tick++)
  1949. {
  1950. CHECK(ModbusDataReadWord(
  1951. MODBUS_DATA_DEVICE_D,
  1952. controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET
  1953. + (uint32_t)tick,
  1954. &axisStatus[tick]) == 1U);
  1955. }
  1956. generationBegin = (uint32_t)axisStatus[0]
  1957. | ((uint32_t)axisStatus[1] << 16U);
  1958. generationEnd = (uint32_t)axisStatus[46]
  1959. | ((uint32_t)axisStatus[47] << 16U);
  1960. CHECK(generationBegin == generationEnd);
  1961. CHECK((generationBegin & 1UL) == 0UL);
  1962. CHECK((axisStatus[2] == PLSR_STATE_ACCEL)
  1963. || (axisStatus[2] == PLSR_STATE_RUN));
  1964. CHECK(axisStatus[10] == 4U);
  1965. CHECK(axisStatus[11] == 0U);
  1966. CHECK(axisStatus[8] == PLSR_RESULT_OK);
  1967. commandRequest[0] = 10U;
  1968. commandRequest[2] = PLSR_CMD_PAUSE;
  1969. commandRequest[3] = 0U;
  1970. CHECK(ModbusDataWriteWords(
  1971. MODBUS_DATA_DEVICE_D,
  1972. controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
  1973. commandRequest,
  1974. 8UL) == 1U);
  1975. PlsrModbusControlPoll();
  1976. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  1977. controlBase + PLSR_MODBUS_COMMAND_RESPONSE_OFFSET
  1978. + 4UL,
  1979. &commandResponse[4]) == 1U);
  1980. CHECK(commandResponse[4] == PLSR_RESULT_QUEUED);
  1981. for (tick = 0; tick < 400; tick++)
  1982. {
  1983. PlsrProcess();
  1984. CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
  1985. if (coreStatus.state == PLSR_STATE_PAUSED)
  1986. {
  1987. break;
  1988. }
  1989. }
  1990. CHECK(coreStatus.state == PLSR_STATE_PAUSED);
  1991. CHECK(coreStatus.currentFrequencyHz == 0UL);
  1992. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  1993. pausedPulses = coreStatus.taskPulses;
  1994. PlsrModbusControlPoll();
  1995. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  1996. controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET + 2UL,
  1997. &axisStatus[2]) == 1U);
  1998. CHECK(axisStatus[2] == PLSR_STATE_PAUSED);
  1999. /* Polling an unchanged request sequence must not execute PAUSE twice. */
  2000. PlsrModbusControlPoll();
  2001. commandRequest[0] = 11U;
  2002. commandRequest[2] = PLSR_CMD_RESUME;
  2003. CHECK(ModbusDataWriteWords(
  2004. MODBUS_DATA_DEVICE_D,
  2005. controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
  2006. commandRequest,
  2007. 8UL) == 1U);
  2008. PlsrModbusControlPoll();
  2009. PlsrProcess();
  2010. CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
  2011. CHECK(coreStatus.currentFrequencyHz > 0UL);
  2012. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  2013. for (tick = 0; tick < 10; tick++)
  2014. {
  2015. PlsrHwTestTriggerUpdate(0U);
  2016. }
  2017. PlsrProcess();
  2018. CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
  2019. CHECK(coreStatus.taskPulses == pausedPulses + 10);
  2020. PlsrModbusControlPoll();
  2021. CHECK(ModbusDataReadWord(MODBUS_DATA_DEVICE_D,
  2022. controlBase + PLSR_MODBUS_AXIS_STATUS_OFFSET + 2UL,
  2023. &axisStatus[2]) == 1U);
  2024. CHECK((axisStatus[2] == PLSR_STATE_ACCEL)
  2025. || (axisStatus[2] == PLSR_STATE_RUN));
  2026. commandRequest[0] = 12U;
  2027. commandRequest[2] = PLSR_CMD_STOP_DECEL;
  2028. CHECK(ModbusDataWriteWords(
  2029. MODBUS_DATA_DEVICE_D,
  2030. controlBase + PLSR_MODBUS_COMMAND_REQUEST_OFFSET,
  2031. commandRequest,
  2032. 8UL) == 1U);
  2033. PlsrModbusControlPoll();
  2034. for (tick = 0; tick < 400; tick++)
  2035. {
  2036. PlsrProcess();
  2037. CHECK(PlsrGetStatus(0U, &coreStatus) == PLSR_RESULT_OK);
  2038. if (coreStatus.state == PLSR_STATE_STOPPED)
  2039. {
  2040. break;
  2041. }
  2042. }
  2043. CHECK(coreStatus.state == PLSR_STATE_STOPPED);
  2044. CHECK(coreStatus.currentFrequencyHz == 0UL);
  2045. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  2046. }
  2047. static void TestStopStopsHardware(void)
  2048. {
  2049. TEST_MEMORY memory;
  2050. PLSR_CALL call;
  2051. PLSR_COMMAND command;
  2052. PLSR_STATUS status;
  2053. int ticks;
  2054. TestResetEnvironment();
  2055. (void)memset(&memory, 0, sizeof(memory));
  2056. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  2057. TestSetSegment(&memory, 1U, 1000U, 10000);
  2058. call = TestMakeCall(&memory);
  2059. call.sequence = 20UL;
  2060. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  2061. PlsrProcess();
  2062. for (ticks = 0; ticks < 10; ticks++)
  2063. {
  2064. PlsrProcess();
  2065. }
  2066. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  2067. /* STOP_IMMEDIATE:硬件立即停止。 */
  2068. command.sequence = 21UL;
  2069. command.axis = 0U;
  2070. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  2071. command.argument = 0;
  2072. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  2073. PlsrProcess();
  2074. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  2075. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  2076. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  2077. == PLSR_RESULT_OK);
  2078. PlsrProcess();
  2079. status = TestGetStatus();
  2080. CHECK(status.state == PLSR_STATE_STOPPED);
  2081. }
  2082. int main(void)
  2083. {
  2084. TestMapping();
  2085. TestDirDelaySequence();
  2086. TestDirectionBatch();
  2087. TestCwCcwSequence();
  2088. TestFastRefreshControlTick();
  2089. TestDynamicFrequencyRetarget();
  2090. TestZeroFrequencyWaits();
  2091. TestPulseCounting();
  2092. TestAbPhaseAndCounting();
  2093. TestTwoAbAxesIndependent();
  2094. TestAbFrequencyLimits();
  2095. TestStopAndInvalidArgs();
  2096. TestEndToEndTwoSegments();
  2097. TestEndToEndAbSegment();
  2098. TestPositionOnImmediateStop();
  2099. TestAbsolutePositionAccounting();
  2100. TestEquivalentRemainderAccounting();
  2101. TestEquivalentCompatibleError();
  2102. TestSoftLimitAndSegmentEvent();
  2103. TestHardLimitAndEmergencyLatch();
  2104. TestProductionSelfTestStartsAb();
  2105. TestEquivalentSelfTest();
  2106. TestProtectionSelfTest();
  2107. TestFourAxisSelfTest();
  2108. TestBacklashSelfTest();
  2109. TestDirectionLogicSelfTest();
  2110. TestCwCcwSelfTest();
  2111. TestFastRefreshSelfTest();
  2112. TestDynamicFrequencySelfTest();
  2113. TestDynamicFrequencySchedule();
  2114. TestModbusDataSelfTest();
  2115. TestModbusControlProtocol();
  2116. TestStopStopsHardware();
  2117. if (TestFailures != 0)
  2118. {
  2119. (void)printf("FAIL: %d of %d PLSR HAL checks failed\n",
  2120. TestFailures,
  2121. TestChecks);
  2122. return 1;
  2123. }
  2124. (void)printf("PASS: %d PLSR HAL checks\n", TestChecks);
  2125. return 0;
  2126. }