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.
 
 
 
 
 
 

1319 wiersze
44 KiB

  1. #include "plc_device.h"
  2. #include "plsr_core.h"
  3. #include "plsr_hal_f407.h"
  4. #include "plsr_job.h"
  5. #include "plsr_persistence.h"
  6. #include "plsr_self_test.h"
  7. #include <stdio.h>
  8. #include <string.h>
  9. #define TEST_WORD_CAPACITY (3000U)
  10. #define TEST_BIT_CAPACITY (128U)
  11. #define TEST_S0_BASE (100U)
  12. #define TEST_S1_BASE (200U)
  13. typedef struct
  14. {
  15. uint16_t words[3][TEST_WORD_CAPACITY];
  16. uint8_t bits[3][TEST_BIT_CAPACITY];
  17. } TEST_MEMORY;
  18. static int TestFailures;
  19. static int TestChecks;
  20. #define CHECK(condition) \
  21. do \
  22. { \
  23. TestChecks++; \
  24. if (!(condition)) \
  25. { \
  26. TestFailures++; \
  27. (void)printf("FAIL line %d: %s\n", __LINE__, #condition); \
  28. } \
  29. } while (0)
  30. static uint8_t TestValidateWords(void *context,
  31. PLSR_DEVICE_TYPE device,
  32. uint32_t firstAddress,
  33. uint32_t wordCount)
  34. {
  35. (void)context;
  36. (void)device;
  37. return (((uint64_t)firstAddress + wordCount) <= TEST_WORD_CAPACITY)
  38. ? 1U
  39. : 0U;
  40. }
  41. static uint8_t TestReadWord(void *context,
  42. PLSR_DEVICE_TYPE device,
  43. uint32_t address,
  44. uint16_t *value)
  45. {
  46. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  47. if ((memory == NULL) || (value == NULL) || (device > PLSR_DEVICE_FD)
  48. || (address >= TEST_WORD_CAPACITY))
  49. {
  50. return 0U;
  51. }
  52. *value = memory->words[device][address];
  53. return 1U;
  54. }
  55. static uint8_t TestReadBit(void *context,
  56. PLSR_DEVICE_TYPE device,
  57. uint32_t address,
  58. uint8_t *value)
  59. {
  60. TEST_MEMORY *memory = (TEST_MEMORY *)context;
  61. uint8_t index;
  62. if ((memory == NULL) || (value == NULL) || (device < PLSR_DEVICE_X)
  63. || (device > PLSR_DEVICE_HM) || (address >= TEST_BIT_CAPACITY))
  64. {
  65. return 0U;
  66. }
  67. index = (uint8_t)(device - PLSR_DEVICE_X);
  68. *value = memory->bits[index][address];
  69. return 1U;
  70. }
  71. static void TestWriteDword(TEST_MEMORY *memory,
  72. PLSR_DEVICE_TYPE device,
  73. uint32_t address,
  74. int32_t value)
  75. {
  76. uint32_t raw = (uint32_t)value;
  77. memory->words[device][address] = (uint16_t)(raw & 0xFFFFUL);
  78. memory->words[device][address + 1UL] = (uint16_t)(raw >> 16U);
  79. }
  80. static void TestWriteSfdDword(uint16_t address, uint32_t value)
  81. {
  82. CHECK(PlcDeviceWriteSfd(address, (uint16_t)(value & 0xFFFFUL))
  83. == PLC_DEVICE_OK);
  84. CHECK(PlcDeviceWriteSfd((uint16_t)(address + 1U),
  85. (uint16_t)(value >> 16U)) == PLC_DEVICE_OK);
  86. }
  87. static void TestSetSegment(TEST_MEMORY *memory,
  88. uint16_t number,
  89. uint32_t frequency,
  90. int32_t pulses)
  91. {
  92. uint32_t base = TEST_S0_BASE + (uint32_t)number * 10UL;
  93. TestWriteDword(memory, PLSR_DEVICE_D, base, (int32_t)frequency);
  94. TestWriteDword(memory, PLSR_DEVICE_D, base + 2UL, pulses);
  95. memory->words[PLSR_DEVICE_D][base + 4UL] = 0U;
  96. TestWriteDword(memory, PLSR_DEVICE_D, base + 5UL, 0);
  97. memory->words[PLSR_DEVICE_D][base + 7UL] = 0U;
  98. TestWriteDword(memory, PLSR_DEVICE_D, base + 8UL, 0);
  99. }
  100. static void TestResetEnvironment(void)
  101. {
  102. PlsrPersistenceTestResetStorage();
  103. CHECK(PlcDeviceInit() == PLC_DEVICE_OK);
  104. CHECK(PlcDeviceWriteSfd(906U, 4) == PLC_DEVICE_OK);
  105. CHECK(PlsrInit() == PLSR_RESULT_OK);
  106. }
  107. static void TestCompleteFirstAbPrime(uint8_t axis)
  108. {
  109. int quarter;
  110. CHECK(PlsrHwIsAbStartupPriming(axis) != 0U);
  111. for (quarter = 0; quarter < 4; quarter++)
  112. {
  113. PlsrHwTestAdvanceAbQuarter(axis);
  114. }
  115. CHECK(PlsrHwIsAbStartupPriming(axis) == 0U);
  116. CHECK(PlsrHwGetEmittedPulses(axis) == 0);
  117. CHECK(PlsrHwTestGetAbQuarter(axis) == 0U);
  118. }
  119. static PLSR_CALL TestMakeCall(TEST_MEMORY *memory)
  120. {
  121. PLSR_CALL call;
  122. (void)memset(&call, 0, sizeof(call));
  123. call.sequence = 10UL;
  124. call.source.context = memory;
  125. call.source.validateWords = TestValidateWords;
  126. call.source.readWord = TestReadWord;
  127. call.source.readBit = TestReadBit;
  128. call.s0.device = PLSR_DEVICE_D;
  129. call.s0.address = TEST_S0_BASE;
  130. call.s1.device = PLSR_DEVICE_D;
  131. call.s1.address = TEST_S1_BASE;
  132. call.s2.type = PLSR_OPERAND_CONSTANT;
  133. call.s2.constant = 1;
  134. call.dAxis = 0U;
  135. call.outputModeOverride = PLSR_OUTPUT_MODE_FROM_SFD;
  136. return call;
  137. }
  138. static PLSR_STATUS TestGetStatus(void)
  139. {
  140. PLSR_STATUS status;
  141. (void)memset(&status, 0, sizeof(status));
  142. CHECK(PlsrGetStatus(0U, &status) == PLSR_RESULT_OK);
  143. return status;
  144. }
  145. static int32_t TestReadSdDword(uint16_t lowAddress)
  146. {
  147. int32_t lowWord = 0;
  148. int32_t highWord = 0;
  149. uint32_t rawValue;
  150. CHECK(PlcDeviceReadSd(lowAddress, &lowWord) == PLC_DEVICE_OK);
  151. CHECK(PlcDeviceReadSd((uint16_t)(lowAddress + 1U), &highWord)
  152. == PLC_DEVICE_OK);
  153. rawValue = ((uint32_t)lowWord & 0xFFFFUL)
  154. | (((uint32_t)highWord & 0xFFFFUL) << 16U);
  155. return (int32_t)rawValue;
  156. }
  157. /* ---- HAL 单测 ---- */
  158. static void TestMapping(void)
  159. {
  160. (void)PlsrHwInit();
  161. CHECK(PlsrHwGetTimerClockHz(0U) == 168000000UL);
  162. CHECK(PlsrHwGetTimerClockHz(1U) == 84000000UL);
  163. CHECK(PlsrHwGetTimerClockHz(2U) == 168000000UL);
  164. CHECK(PlsrHwGetTimerClockHz(3U) == 84000000UL);
  165. CHECK(PlsrHwGetTimerClockHz(4U) == 0UL);
  166. CHECK(PlsrHwResolveDirectionPoint(4U) != 0U);
  167. CHECK(PlsrHwResolveDirectionPoint(8U) == 0U);
  168. CHECK(PlsrHwResolveDirectionPoint(20U) != 0U);
  169. CHECK(PlsrHwResolveDirectionPoint(21U) == 0U);
  170. }
  171. static void TestDirDelaySequence(void)
  172. {
  173. (void)PlsrHwInit();
  174. PLSR_HW_START_PARAMS params;
  175. uint16_t psc;
  176. uint16_t arr;
  177. int ticks;
  178. (void)memset(&params, 0, sizeof(params));
  179. params.frequencyHz = 1000UL;
  180. params.targetPulses = 100;
  181. params.directionPoint = 4U;
  182. params.directionPositive = 1U;
  183. params.directionDelayMs = 10U;
  184. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  185. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  186. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  187. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  188. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  189. for (ticks = 0; ticks < 9; ticks++)
  190. {
  191. PlsrHwTick(0U);
  192. }
  193. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  194. PlsrHwTick(0U);
  195. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  196. /* 首个非零频率启动 PWM,ARR/CCR 与分频计算一致。 */
  197. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  198. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  199. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  200. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  201. CHECK(PlsrCalculateTimerDivider(168000000UL, 1000UL, &psc, &arr)
  202. == PLSR_RESULT_OK);
  203. CHECK(PlsrHwTestGetArr(0U) == arr);
  204. CHECK(PlsrHwTestGetPsc(0U) == psc);
  205. CHECK(PlsrHwTestGetCcr(0U) == arr / 2UL);
  206. /* PWM 模式 1(OC1M=110):复位后 CCMR1=0 冻结,无此配置输出恒定电平。 */
  207. CHECK((PlsrHwTestGetCcmr1(0U) & 0x70UL) == 0x60UL);
  208. /* ARR/CCR 预装载(ARPE=CR1 bit7,OC1PE=CCMR1 bit3):
  209. * 运行中调频不产生提前回绕,否则加速段多出 ~ln(f1/f0) 个假脉冲。 */
  210. CHECK((PlsrHwTestGetCr1(0U) & 0x80UL) == 0x80UL);
  211. CHECK((PlsrHwTestGetCcmr1(0U) & 0x08UL) == 0x08UL);
  212. /* 段间同向衔接:方向不变时跳过方向延时,直接进入 PWM 待启动。 */
  213. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  214. params.targetPulses = 50;
  215. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  216. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  217. CHECK(PlsrHwTestGetDirLevel(0U) == 1U);
  218. /* 反向时方向延时仍生效。 */
  219. params.directionPositive = 0U;
  220. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  221. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  222. CHECK(PlsrHwTestGetDirLevel(0U) == 0U);
  223. }
  224. static void TestZeroFrequencyWaits(void)
  225. {
  226. (void)PlsrHwInit();
  227. PLSR_HW_START_PARAMS params;
  228. (void)memset(&params, 0, sizeof(params));
  229. params.frequencyHz = 0UL;
  230. params.targetPulses = 50;
  231. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  232. params.directionPositive = 1U;
  233. params.directionDelayMs = 0U;
  234. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  235. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  236. PlsrHwTick(0U);
  237. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  238. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  239. /* 起始速度为 0:profile 升频后首个非零频率才启动 PWM。 */
  240. CHECK(PlsrHwSetFrequency(0U, 10UL) == PLSR_RESULT_OK);
  241. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  242. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  243. }
  244. static void TestPulseCounting(void)
  245. {
  246. (void)PlsrHwInit();
  247. PLSR_HW_START_PARAMS params;
  248. int pulse;
  249. (void)memset(&params, 0, sizeof(params));
  250. params.frequencyHz = 1000UL;
  251. params.targetPulses = 5;
  252. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  253. params.directionPositive = 1U;
  254. params.directionDelayMs = 0U;
  255. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  256. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  257. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  258. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  259. /* EGR.UG 只加载预装载寄存器,不能被当作物理脉冲。
  260. * 共享 IRQ 入口在对应定时器没有 UIF 时也必须无动作。 */
  261. PlsrHwOnTimerUpdate(0U);
  262. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  263. for (pulse = 0; pulse < 4; pulse++)
  264. {
  265. PlsrHwTestTriggerUpdate(0U);
  266. CHECK(PlsrHwGetEmittedPulses(0U) == pulse + 1);
  267. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  268. }
  269. /* 第 5 个脉冲:到目标,停止 + 段完成事件。 */
  270. PlsrHwTestTriggerUpdate(0U);
  271. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  272. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  273. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  274. /* 停止后再触发更新中断无动作。 */
  275. PlsrHwTestTriggerUpdate(0U);
  276. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  277. }
  278. static void TestAbPhaseAndCounting(void)
  279. {
  280. PLSR_HW_START_PARAMS params;
  281. static const uint8_t positiveA[4] = {1U, 1U, 0U, 0U};
  282. static const uint8_t positiveB[4] = {0U, 1U, 1U, 0U};
  283. static const uint8_t negativeA[4] = {0U, 1U, 1U, 0U};
  284. static const uint8_t negativeB[4] = {1U, 1U, 0U, 0U};
  285. uint32_t oldArr;
  286. uint32_t oldBasePsc;
  287. uint32_t oldPairPsc;
  288. uint32_t newPeriod;
  289. int quarter;
  290. (void)PlsrHwInit();
  291. (void)memset(&params, 0, sizeof(params));
  292. params.frequencyHz = 1000UL;
  293. params.targetPulses = 4;
  294. params.outputMode = PLSR_OUTPUT_AB;
  295. params.directionPoint = 4U; /* AB 模式必须忽略独立 DIR 点。 */
  296. params.directionPositive = 1U;
  297. params.directionDelayMs = 10U; /* AB 模式不得执行方向延时。 */
  298. CHECK(PlsrHwStartPulse(1U, &params) == PLSR_RESULT_INVALID_AXIS);
  299. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  300. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_PWM_PENDING);
  301. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  302. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  303. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  304. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  305. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  306. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  307. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  308. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  309. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  310. CHECK(PlsrHwTestGetCcr(0U) == PlsrHwTestGetCcr(1U));
  311. CHECK(PlsrHwTestGetCcr(0U)
  312. == (PlsrHwTestGetArr(0U) + 1UL) / 2UL);
  313. /* 两相从精确 00 边界起步;CC1IF 会在开中断前再次清除。 */
  314. CHECK(PlsrHwTestGetCnt(0U)
  315. == ((PlsrHwTestGetArr(0U) + 1UL) * 3UL) / 4UL);
  316. CHECK(PlsrHwTestGetCnt(1U) == PlsrHwTestGetCcr(1U));
  317. TestCompleteFirstAbPrime(0U);
  318. /* 任一物理 timer update 不能直接计作完整 AB 周期。 */
  319. PlsrHwTestTriggerUpdate(0U);
  320. CHECK(PlsrHwGetEmittedPulses(0U) == 0);
  321. /* 正向:00→10→11→01→00;四次相位跳变只计一个脉冲。 */
  322. for (quarter = 0; quarter < 4; quarter++)
  323. {
  324. PlsrHwTestAdvanceAbQuarter(0U);
  325. CHECK(PlsrHwTestGetAbPhaseA(0U) == positiveA[quarter]);
  326. CHECK(PlsrHwTestGetAbPhaseB(0U) == positiveB[quarter]);
  327. }
  328. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  329. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  330. /* 运行中调频先排队,不能让相差 1/4 周期的两路各自加载 ARR。 */
  331. oldArr = PlsrHwTestGetArr(0U);
  332. oldBasePsc = PlsrHwTestGetPsc(0U);
  333. oldPairPsc = PlsrHwTestGetPsc(1U);
  334. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  335. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  336. for (quarter = 0; quarter < 4; quarter++)
  337. {
  338. PlsrHwTestAdvanceAbQuarter(0U);
  339. }
  340. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  341. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  342. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  343. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  344. CHECK(PlsrHwSetFrequency(0U, 2000UL) == PLSR_RESULT_OK);
  345. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  346. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  347. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  348. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  349. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  350. for (quarter = 0; quarter < 3; quarter++)
  351. {
  352. PlsrHwTestAdvanceAbQuarter(0U);
  353. CHECK(PlsrHwTestGetArr(0U) == oldArr);
  354. CHECK(PlsrHwTestGetArr(1U) == oldArr);
  355. CHECK(PlsrHwTestGetPsc(0U) == oldBasePsc);
  356. CHECK(PlsrHwTestGetPsc(1U) == oldPairPsc);
  357. }
  358. /* 回到 00 后,两路同时装载新频率并从精确 90° 位置重启。 */
  359. PlsrHwTestAdvanceAbQuarter(0U);
  360. CHECK(PlsrHwGetEmittedPulses(0U) == 3);
  361. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  362. CHECK((PlsrHwTestGetArr(0U) != oldArr)
  363. || (PlsrHwTestGetPsc(0U) != oldBasePsc));
  364. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  365. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  366. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  367. newPeriod = PlsrHwTestGetArr(0U) + 1UL;
  368. CHECK(PlsrHwTestGetCnt(0U) == (newPeriod * 3UL) / 4UL);
  369. CHECK(PlsrHwTestGetCnt(1U) == newPeriod / 2UL);
  370. for (quarter = 0; quarter < 4; quarter++)
  371. {
  372. PlsrHwTestAdvanceAbQuarter(0U);
  373. }
  374. CHECK(PlsrHwGetEmittedPulses(0U) == 4);
  375. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  376. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  377. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  378. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  379. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  380. /* 反向:00→01→11→10→00。 */
  381. params.targetPulses = 1;
  382. params.directionPositive = 0U;
  383. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  384. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  385. for (quarter = 0; quarter < 4; quarter++)
  386. {
  387. PlsrHwTestAdvanceAbQuarter(0U);
  388. CHECK(PlsrHwTestGetAbPhaseA(0U) == negativeA[quarter]);
  389. CHECK(PlsrHwTestGetAbPhaseB(0U) == negativeB[quarter]);
  390. }
  391. CHECK(PlsrHwGetEmittedPulses(0U) == 1);
  392. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  393. /* 紧急停止即使发生在周期中间,也必须回到安全 00。 */
  394. params.targetPulses = 10;
  395. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  396. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  397. PlsrHwTestAdvanceAbQuarter(0U);
  398. CHECK(PlsrHwTestGetAbQuarter(0U) == 1U);
  399. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  400. CHECK(PlsrHwTestGetAbQuarter(0U) == 0U);
  401. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  402. CHECK(PlsrHwTestGetAbPhaseB(0U) == 0U);
  403. }
  404. static void TestTwoAbAxesIndependent(void)
  405. {
  406. PLSR_HW_START_PARAMS params;
  407. int quarter;
  408. (void)PlsrHwInit();
  409. (void)memset(&params, 0, sizeof(params));
  410. params.frequencyHz = 1000UL;
  411. params.targetPulses = 1;
  412. params.outputMode = PLSR_OUTPUT_AB;
  413. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  414. params.directionPositive = 1U;
  415. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  416. CHECK(PlsrHwStartPulse(2U, &params) == PLSR_RESULT_OK);
  417. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  418. CHECK(PlsrHwSetFrequency(2U, 2000UL) == PLSR_RESULT_OK);
  419. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  420. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  421. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  422. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  423. TestCompleteFirstAbPrime(0U);
  424. TestCompleteFirstAbPrime(2U);
  425. for (quarter = 0; quarter < 4; quarter++)
  426. {
  427. PlsrHwTestAdvanceAbQuarter(0U);
  428. }
  429. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  430. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_RUNNING);
  431. CHECK(PlsrHwGetEmittedPulses(2U) == 0);
  432. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  433. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  434. CHECK(PlsrHwTestGetPwmEnabled(2U) != 0U);
  435. CHECK(PlsrHwTestGetPwmEnabled(3U) != 0U);
  436. for (quarter = 0; quarter < 4; quarter++)
  437. {
  438. PlsrHwTestAdvanceAbQuarter(2U);
  439. }
  440. CHECK(PlsrHwGetState(2U) == PLSR_HW_STATE_DONE);
  441. CHECK(PlsrHwGetEmittedPulses(2U) == 1);
  442. }
  443. static void TestAbFrequencyLimits(void)
  444. {
  445. PLSR_HW_START_PARAMS params;
  446. int quarter;
  447. (void)PlsrHwInit();
  448. (void)memset(&params, 0, sizeof(params));
  449. params.frequencyHz = 1UL;
  450. params.targetPulses = 100;
  451. params.outputMode = PLSR_OUTPUT_AB;
  452. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  453. params.directionPositive = 1U;
  454. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  455. CHECK(PlsrHwSetFrequency(0U, 1UL) == PLSR_RESULT_OK);
  456. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  457. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  458. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  459. CHECK(PlsrHwTestGetArr(0U) <= 65535UL);
  460. TestCompleteFirstAbPrime(0U);
  461. CHECK(PlsrHwSetFrequency(0U, 100000UL) == PLSR_RESULT_OK);
  462. for (quarter = 0; quarter < 4; quarter++)
  463. {
  464. PlsrHwTestAdvanceAbQuarter(0U);
  465. }
  466. CHECK(PlsrHwTestGetArr(0U) == PlsrHwTestGetArr(1U));
  467. CHECK((PlsrHwTestGetPsc(0U) + 1UL)
  468. == 2UL * (PlsrHwTestGetPsc(1U) + 1UL));
  469. CHECK(PlsrHwTestGetArr(0U) >= 3UL);
  470. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  471. }
  472. static void TestStopAndInvalidArgs(void)
  473. {
  474. (void)PlsrHwInit();
  475. PLSR_HW_START_PARAMS params;
  476. (void)memset(&params, 0, sizeof(params));
  477. params.frequencyHz = 1000UL;
  478. params.targetPulses = 100;
  479. params.directionPoint = PLSR_HW_DIR_POINT_NONE;
  480. params.directionPositive = 1U;
  481. params.directionDelayMs = 0U;
  482. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_OK);
  483. CHECK(PlsrHwSetFrequency(0U, 1000UL) == PLSR_RESULT_OK);
  484. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  485. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  486. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  487. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  488. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  489. CHECK(PlsrHwStartPulse(4U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  490. CHECK(PlsrHwStartPulse(0U, NULL) == PLSR_RESULT_INVALID_ARGUMENT);
  491. params.targetPulses = 0;
  492. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  493. params.targetPulses = 1;
  494. params.outputMode = PLSR_OUTPUT_CW_CCW;
  495. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_NOT_SUPPORTED);
  496. params.outputMode = (PLSR_OUTPUT_MODE)99;
  497. CHECK(PlsrHwStartPulse(0U, &params) == PLSR_RESULT_INVALID_ARGUMENT);
  498. CHECK(PlsrHwSetFrequency(4U, 1000UL) == PLSR_RESULT_INVALID_ARGUMENT);
  499. CHECK(PlsrHwStopPulse(4U) == PLSR_RESULT_INVALID_ARGUMENT);
  500. }
  501. /* ---- 端到端集成:START → 硬件 → 计数 → 事件 → 段间 → 完成 ---- */
  502. static void TestEndToEndTwoSegments(void)
  503. {
  504. TEST_MEMORY memory;
  505. PLSR_CALL call;
  506. PLSR_STATUS status;
  507. uint16_t initialPsc;
  508. uint16_t initialArr;
  509. int ticks;
  510. int pulse;
  511. TestResetEnvironment();
  512. (void)memset(&memory, 0, sizeof(memory));
  513. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 2);
  514. TestSetSegment(&memory, 1U, 1000U, 100);
  515. TestSetSegment(&memory, 2U, 2000U, 200);
  516. call = TestMakeCall(&memory);
  517. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  518. PlsrProcess();
  519. status = TestGetStatus();
  520. CHECK(status.state == PLSR_STATE_ACCEL);
  521. CHECK(status.currentSegment == 1U);
  522. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DIR_SETTLING);
  523. /* DIR 延时 10ms → PWM 启动(段1 起始速度 0,profile 升频后启动)。 */
  524. for (ticks = 0; ticks < 9; ticks++)
  525. {
  526. PlsrProcess();
  527. }
  528. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  529. CHECK(PlsrHwTestGetPwmEnabled(0U) == 1U);
  530. CHECK(PlsrCalculateTimerDivider(168000000UL, 75UL,
  531. &initialPsc, &initialArr)
  532. == PLSR_RESULT_OK);
  533. CHECK(PlsrHwTestGetPsc(0U) == initialPsc);
  534. CHECK(PlsrHwTestGetArr(0U) == initialArr);
  535. /* 加速完成 → 状态机进入 RUN。 */
  536. for (ticks = 0; ticks < 500; ticks++)
  537. {
  538. PlsrProcess();
  539. if (TestGetStatus().state == PLSR_STATE_RUN)
  540. {
  541. break;
  542. }
  543. }
  544. status = TestGetStatus();
  545. CHECK(status.state == PLSR_STATE_RUN);
  546. CHECK(status.currentSegment == 1U);
  547. /* 段1 脉冲完成:100 次更新中断 → SEGMENT_COMPLETE → 段2 启动。 */
  548. for (pulse = 0; pulse < 100; pulse++)
  549. {
  550. PlsrHwTestTriggerUpdate(0U);
  551. }
  552. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  553. PlsrProcess();
  554. status = TestGetStatus();
  555. CHECK(status.state == PLSR_STATE_ACCEL);
  556. CHECK(status.currentSegment == 2U);
  557. CHECK(status.logicalPosition == 100);
  558. CHECK(status.taskPulses == 100);
  559. CHECK(status.totalPulses == 100);
  560. CHECK(TestReadSdDword(1000U) == 2);
  561. CHECK(TestReadSdDword(1002U) == 0);
  562. /* 段2:DIR 延时 → PWM → 加速 → RUN。 */
  563. for (ticks = 0; ticks < 600; ticks++)
  564. {
  565. PlsrProcess();
  566. if (TestGetStatus().state == PLSR_STATE_RUN)
  567. {
  568. break;
  569. }
  570. }
  571. status = TestGetStatus();
  572. CHECK(status.state == PLSR_STATE_RUN);
  573. CHECK(status.currentSegment == 2U);
  574. /* 段2 脉冲完成 → 任务结束。 */
  575. for (pulse = 0; pulse < 200; pulse++)
  576. {
  577. PlsrHwTestTriggerUpdate(0U);
  578. }
  579. PlsrProcess();
  580. status = TestGetStatus();
  581. CHECK(status.state == PLSR_STATE_COMPLETED);
  582. CHECK(status.done != 0U);
  583. CHECK(status.logicalPosition == 300);
  584. CHECK(status.taskPulses == 300);
  585. CHECK(status.totalPulses == 300);
  586. CHECK(TestReadSdDword(1000U) == 2);
  587. CHECK(TestReadSdDword(1002U) == 200);
  588. CHECK(TestReadSdDword(1004U) == 200);
  589. CHECK(TestReadSdDword(1006U) == 0);
  590. {
  591. int32_t hsdPulses;
  592. int32_t hsdEquivalent;
  593. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  594. CHECK(hsdPulses == 300);
  595. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent)
  596. == PLC_DEVICE_OK);
  597. CHECK(hsdEquivalent == 300);
  598. }
  599. /* 终态转换后 HAL 回 IDLE(允许重新启动),脉冲已停止。 */
  600. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  601. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  602. }
  603. static void TestEndToEndAbSegment(void)
  604. {
  605. TEST_MEMORY memory;
  606. PLSR_CALL call;
  607. PLSR_STATUS status;
  608. int quarter;
  609. TestResetEnvironment();
  610. (void)memset(&memory, 0, sizeof(memory));
  611. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  612. TestSetSegment(&memory, 1U, 1000U, -2);
  613. call = TestMakeCall(&memory);
  614. call.sequence = 15UL;
  615. call.outputModeOverride = PLSR_OUTPUT_AB;
  616. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  617. PlsrProcess();
  618. status = TestGetStatus();
  619. CHECK(status.state == PLSR_STATE_ACCEL);
  620. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  621. CHECK(status.directionPoint == PLSR_DIRECTION_POINT_NONE);
  622. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  623. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  624. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  625. TestCompleteFirstAbPrime(0U);
  626. /* 负脉冲选择反向相序,完整两个周期后由同一事件链结束任务。 */
  627. PlsrHwTestAdvanceAbQuarter(0U);
  628. CHECK(PlsrHwTestGetAbPhaseA(0U) == 0U);
  629. CHECK(PlsrHwTestGetAbPhaseB(0U) == 1U);
  630. for (quarter = 1; quarter < 8; quarter++)
  631. {
  632. PlsrHwTestAdvanceAbQuarter(0U);
  633. }
  634. CHECK(PlsrHwGetEmittedPulses(0U) == 2);
  635. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_DONE);
  636. PlsrProcess();
  637. status = TestGetStatus();
  638. CHECK(status.state == PLSR_STATE_COMPLETED);
  639. CHECK(status.done != 0U);
  640. CHECK(status.directionPositive == 0U);
  641. CHECK(status.logicalPosition == -2);
  642. CHECK(status.taskPulses == -2);
  643. CHECK(status.totalPulses == 2);
  644. CHECK(TestReadSdDword(1002U) == -2);
  645. CHECK(TestReadSdDword(1004U) == -2);
  646. CHECK(status.highResourceMask == 0U);
  647. CHECK(PlsrHwTestGetPwmEnabled(0U) == 0U);
  648. CHECK(PlsrHwTestGetPwmEnabled(1U) == 0U);
  649. }
  650. static void TestPositionOnImmediateStop(void)
  651. {
  652. TEST_MEMORY memory;
  653. PLSR_CALL call;
  654. PLSR_COMMAND command;
  655. PLSR_STATUS status;
  656. int pulse;
  657. int tick;
  658. TestResetEnvironment();
  659. (void)memset(&memory, 0, sizeof(memory));
  660. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  661. TestSetSegment(&memory, 1U, 1000U, 100);
  662. call = TestMakeCall(&memory);
  663. call.sequence = 30UL;
  664. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  665. PlsrProcess();
  666. for (tick = 0; tick < 10; tick++)
  667. {
  668. PlsrProcess();
  669. }
  670. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  671. for (pulse = 0; pulse < 37; pulse++)
  672. {
  673. PlsrHwTestTriggerUpdate(0U);
  674. }
  675. PlsrProcess();
  676. status = TestGetStatus();
  677. CHECK(status.logicalPosition == 37);
  678. CHECK(status.taskPulses == 37);
  679. CHECK(status.totalPulses == 37);
  680. command.sequence = 31UL;
  681. command.axis = 0U;
  682. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  683. command.argument = 0;
  684. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  685. PlsrProcess();
  686. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  687. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  688. == PLSR_RESULT_OK);
  689. PlsrProcess();
  690. status = TestGetStatus();
  691. CHECK(status.state == PLSR_STATE_STOPPED);
  692. CHECK(status.logicalPosition == 37);
  693. CHECK(status.taskPulses == 37);
  694. CHECK(status.totalPulses == 37);
  695. CHECK(TestReadSdDword(1002U) == 37);
  696. command.sequence = 32UL;
  697. command.opcode = PLSR_CMD_CLEAR_TOTAL;
  698. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  699. PlsrProcess();
  700. status = TestGetStatus();
  701. CHECK(status.logicalPosition == 37);
  702. CHECK(status.totalPulses == 0);
  703. }
  704. static void TestAbsolutePositionAccounting(void)
  705. {
  706. TEST_MEMORY memory;
  707. PLSR_CALL call;
  708. PLSR_COMMAND command;
  709. PLSR_STATUS status;
  710. int32_t hsdPosition;
  711. int pulse;
  712. int tick;
  713. TestResetEnvironment();
  714. command.sequence = 40UL;
  715. command.axis = 0U;
  716. command.opcode = PLSR_CMD_SET_POSITION;
  717. command.argument = 100;
  718. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  719. PlsrProcess();
  720. (void)memset(&memory, 0, sizeof(memory));
  721. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  722. TestSetSegment(&memory, 1U, 1000U, 130);
  723. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S1_BASE, 1);
  724. call = TestMakeCall(&memory);
  725. call.sequence = 41UL;
  726. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  727. PlsrProcess();
  728. for (tick = 0; tick < 10; tick++)
  729. {
  730. PlsrProcess();
  731. }
  732. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  733. for (pulse = 0; pulse < 30; pulse++)
  734. {
  735. PlsrHwTestTriggerUpdate(0U);
  736. }
  737. PlsrProcess();
  738. status = TestGetStatus();
  739. CHECK(status.state == PLSR_STATE_COMPLETED);
  740. CHECK(status.logicalPosition == 130);
  741. CHECK(status.taskPulses == 30);
  742. CHECK(status.totalPulses == 30);
  743. CHECK(status.positionValid != 0U);
  744. CHECK(PlcDeviceReadHsdDword(0U, &hsdPosition) == PLC_DEVICE_OK);
  745. CHECK(hsdPosition == 130);
  746. }
  747. static void TestEquivalentRemainderAccounting(void)
  748. {
  749. TEST_MEMORY memory;
  750. PLSR_CALL call;
  751. PLSR_STATUS status;
  752. int32_t hsdPulses;
  753. int32_t hsdEquivalent;
  754. TestResetEnvironment();
  755. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  756. TestWriteSfdDword(902U, 3UL);
  757. TestWriteSfdDword(904U, 2UL);
  758. TestWriteSfdDword(956U, 60000UL);
  759. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  760. (void)memset(&memory, 0, sizeof(memory));
  761. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  762. TestSetSegment(&memory, 1U, 1000U, 1);
  763. call = TestMakeCall(&memory);
  764. call.sequence = 30UL;
  765. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  766. /* 3脉冲/2单位:第一次1单位只输出1脉冲并保存1/2余数。 */
  767. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  768. PlsrProcess();
  769. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  770. PlsrHwTestTriggerUpdate(0U);
  771. PlsrProcess();
  772. status = TestGetStatus();
  773. CHECK(status.state == PLSR_STATE_COMPLETED);
  774. CHECK(status.logicalPosition == 1);
  775. CHECK(status.taskPulses == 1);
  776. CHECK(status.totalPulses == 1);
  777. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  778. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  779. CHECK(hsdPulses == 1);
  780. CHECK(hsdEquivalent == 0);
  781. /* 第二次1单位合并余数后输出2脉冲;两次合计精确为3脉冲/2单位。 */
  782. call.sequence = 31UL;
  783. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  784. PlsrProcess();
  785. PlsrHwTestTriggerUpdate(0U);
  786. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  787. PlsrHwTestTriggerUpdate(0U);
  788. PlsrProcess();
  789. status = TestGetStatus();
  790. CHECK(status.state == PLSR_STATE_COMPLETED);
  791. CHECK(status.logicalPosition == 3);
  792. CHECK(status.taskPulses == 2);
  793. CHECK(status.totalPulses == 3);
  794. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  795. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  796. CHECK(hsdPulses == 3);
  797. CHECK(hsdEquivalent == 2);
  798. CHECK(TestReadSdDword(1002U) == 2);
  799. CHECK(TestReadSdDword(1004U) == 1);
  800. }
  801. static void TestEquivalentCompatibleError(void)
  802. {
  803. TEST_MEMORY memory;
  804. PLSR_CALL call;
  805. PLSR_STATUS status;
  806. int32_t errorCode = -1;
  807. int32_t errorBlock = -1;
  808. TestResetEnvironment();
  809. CHECK(PlcDeviceWriteSfd(900U, (1U << 8U)) == PLC_DEVICE_OK);
  810. TestWriteSfdDword(902U, 0UL);
  811. TestWriteSfdDword(904U, 2UL);
  812. TestWriteSfdDword(956U, 60000UL);
  813. (void)memset(&memory, 0, sizeof(memory));
  814. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  815. TestSetSegment(&memory, 1U, 1000U, 1);
  816. call = TestMakeCall(&memory);
  817. call.sequence = 32UL;
  818. call.outputModeOverride = PLSR_OUTPUT_PULSE_DIR;
  819. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  820. PlsrProcess();
  821. status = TestGetStatus();
  822. CHECK(status.lastCommandResult == PLSR_RESULT_INVALID_S2);
  823. CHECK(status.state == PLSR_STATE_IDLE);
  824. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  825. CHECK(PlcDeviceReadSd(1011U, &errorBlock) == PLC_DEVICE_OK);
  826. CHECK(errorCode == 2);
  827. CHECK(errorBlock == 0);
  828. /* A valid retry clears the compatible parameter error. */
  829. TestWriteSfdDword(902U, 3UL);
  830. call.sequence = 33UL;
  831. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  832. PlsrProcess();
  833. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  834. CHECK(errorCode == 0);
  835. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  836. }
  837. static void TestSoftLimitAndSegmentEvent(void)
  838. {
  839. TEST_MEMORY memory;
  840. PLSR_CALL call;
  841. PLSR_COMMAND command;
  842. PLSR_STATUS status;
  843. PLC_DEVICE_EVENT_RECORD eventRecord;
  844. int32_t errorCode;
  845. int pulse;
  846. int tick;
  847. TestResetEnvironment();
  848. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  849. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  850. CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
  851. CHECK(PlcDeviceWriteSfd(915U, 0xFFFFU) == PLC_DEVICE_OK);
  852. TestWriteSfdDword(930U, 100UL);
  853. TestWriteSfdDword(932U, (uint32_t)(int32_t)-100);
  854. command.sequence = 40UL;
  855. command.axis = 0U;
  856. command.opcode = PLSR_CMD_SET_POSITION;
  857. command.argument = 100;
  858. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  859. PlsrProcess();
  860. (void)memset(&memory, 0, sizeof(memory));
  861. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  862. TestSetSegment(&memory, 1U, 1000U, 10);
  863. call = TestMakeCall(&memory);
  864. call.sequence = 41UL;
  865. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  866. PlsrProcess();
  867. status = TestGetStatus();
  868. CHECK(status.lastCommandResult == PLSR_RESULT_LIMIT_POSITIVE);
  869. CHECK(status.state == PLSR_STATE_IDLE);
  870. CHECK(status.positiveLimitActive != 0U);
  871. CHECK(status.error == PLSR_ERROR_LIMIT_POSITIVE);
  872. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  873. CHECK(errorCode == 5);
  874. /* 正限位上只禁止正向,反向离开仍可正常完成。 */
  875. TestSetSegment(&memory, 1U, 1000U, -10);
  876. call.sequence = 42UL;
  877. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  878. PlsrProcess();
  879. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  880. for (pulse = 0; pulse < 10; pulse++)
  881. {
  882. PlsrHwTestTriggerUpdate(0U);
  883. }
  884. PlsrProcess();
  885. status = TestGetStatus();
  886. CHECK(status.state == PLSR_STATE_COMPLETED);
  887. CHECK(status.logicalPosition == 90);
  888. CHECK(status.error == PLSR_ERROR_NONE);
  889. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  890. CHECK(eventRecord.count == 1UL);
  891. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_NORMAL_COMPLETE);
  892. CHECK(eventRecord.pending != 0U);
  893. /* 运行中按预计制动距离触发软限位,PWM保持运行并按曲线缓停。 */
  894. TestResetEnvironment();
  895. CHECK(PlcDeviceWriteSfd(900U, (1U << 2U)) == PLC_DEVICE_OK);
  896. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  897. TestWriteSfdDword(930U, 50UL);
  898. TestWriteSfdDword(932U, (uint32_t)(int32_t)-50);
  899. command.sequence = 43UL;
  900. command.opcode = PLSR_CMD_SET_POSITION;
  901. command.argument = 0;
  902. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  903. PlsrProcess();
  904. (void)memset(&memory, 0, sizeof(memory));
  905. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  906. TestSetSegment(&memory, 1U, 1000U, 10000);
  907. call = TestMakeCall(&memory);
  908. call.sequence = 44UL;
  909. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  910. PlsrProcess();
  911. for (pulse = 0; pulse < 49; pulse++)
  912. {
  913. PlsrHwTestTriggerUpdate(0U);
  914. }
  915. PlsrProcess();
  916. status = TestGetStatus();
  917. CHECK(status.state == PLSR_STATE_DECEL);
  918. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  919. CHECK(status.positiveLimitActive != 0U);
  920. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  921. CHECK(PlcDeviceReadSd(1010U, &errorCode) == PLC_DEVICE_OK);
  922. CHECK(errorCode == 5);
  923. for (tick = 0; tick < 20; tick++)
  924. {
  925. PlsrProcess();
  926. }
  927. status = TestGetStatus();
  928. CHECK(status.state == PLSR_STATE_STOPPED);
  929. CHECK(status.logicalPosition == 49);
  930. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  931. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  932. CHECK(eventRecord.count == 1UL);
  933. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  934. }
  935. static void TestHardLimitAndEmergencyLatch(void)
  936. {
  937. TEST_MEMORY memory;
  938. PLSR_CALL call;
  939. PLSR_COMMAND command;
  940. PLSR_STATUS status;
  941. PLC_DEVICE_EVENT_RECORD eventRecord;
  942. TestResetEnvironment();
  943. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  944. CHECK(PlcDeviceWriteSfd(912U, 0U) == PLC_DEVICE_OK);
  945. CHECK(PlcDeviceWriteSfd(915U, 0xFF03U) == PLC_DEVICE_OK);
  946. (void)memset(&memory, 0, sizeof(memory));
  947. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  948. TestSetSegment(&memory, 1U, 1000U, 10000);
  949. call = TestMakeCall(&memory);
  950. call.sequence = 50UL;
  951. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  952. PlsrProcess();
  953. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  954. memory.bits[0][3U] = 1U;
  955. PlsrProcess();
  956. status = TestGetStatus();
  957. CHECK(status.state == PLSR_STATE_DECEL);
  958. CHECK(status.positiveLimitActive != 0U);
  959. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  960. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  961. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  962. TestResetEnvironment();
  963. CHECK(PlcDeviceWriteSfd(907U, 0U) == PLC_DEVICE_OK);
  964. (void)memset(&memory, 0, sizeof(memory));
  965. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  966. TestSetSegment(&memory, 1U, 1000U, 10000);
  967. call = TestMakeCall(&memory);
  968. call.sequence = 51UL;
  969. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  970. PlsrProcess();
  971. command.sequence = 52UL;
  972. command.axis = 0U;
  973. command.opcode = PLSR_CMD_RESET_ERROR;
  974. command.argument = 0;
  975. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  976. CHECK(PlsrPostEvent(0U,
  977. PLSR_EVENT_LIMIT_POSITIVE
  978. | PLSR_EVENT_SOFTWARE_EMERGENCY)
  979. == PLSR_RESULT_OK);
  980. PlsrProcess();
  981. status = TestGetStatus();
  982. CHECK(status.state == PLSR_STATE_STOPPED);
  983. CHECK(status.stopReason == PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
  984. CHECK(status.error == PLSR_ERROR_EMERGENCY);
  985. CHECK(status.emergencyLatched != 0U);
  986. CHECK(status.lastCommandSequence == 52UL);
  987. CHECK(status.lastCommandResult == PLSR_RESULT_BUSY);
  988. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  989. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  990. CHECK(eventRecord.count == 1UL);
  991. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_SOFTWARE_EMERGENCY);
  992. call.sequence = 53UL;
  993. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  994. PlsrProcess();
  995. status = TestGetStatus();
  996. CHECK(status.lastCommandResult == PLSR_RESULT_EMERGENCY_LATCHED);
  997. CHECK(status.state == PLSR_STATE_STOPPED);
  998. command.sequence = 54UL;
  999. command.axis = 0U;
  1000. command.opcode = PLSR_CMD_RESET_ERROR;
  1001. command.argument = 0;
  1002. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1003. PlsrProcess();
  1004. status = TestGetStatus();
  1005. CHECK(status.state == PLSR_STATE_IDLE);
  1006. CHECK(status.error == PLSR_ERROR_NONE);
  1007. CHECK(status.emergencyLatched == 0U);
  1008. }
  1009. static void TestProductionSelfTestStartsAb(void)
  1010. {
  1011. PLSR_STATUS status;
  1012. TestResetEnvironment();
  1013. CHECK(PlsrSelfTestQueue() == PLSR_RESULT_QUEUED);
  1014. PlsrProcess();
  1015. status = TestGetStatus();
  1016. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  1017. CHECK(status.outputMode == PLSR_OUTPUT_AB);
  1018. CHECK(status.currentSegment == 1U);
  1019. CHECK(status.state == PLSR_STATE_ACCEL);
  1020. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1021. CHECK(PlsrHwTestGetPwmEnabled(0U) != 0U);
  1022. CHECK(PlsrHwTestGetPwmEnabled(1U) != 0U);
  1023. CHECK(PlsrHwStopPulse(0U) == PLSR_RESULT_OK);
  1024. }
  1025. static void TestEquivalentSelfTest(void)
  1026. {
  1027. PLSR_STATUS status;
  1028. int32_t hsdPulses;
  1029. int32_t hsdEquivalent;
  1030. int ticks;
  1031. TestResetEnvironment();
  1032. CHECK(PlsrEquivalentSelfTestQueue() == PLSR_RESULT_QUEUED);
  1033. PlsrProcess();
  1034. /* SFD907=10ms. Advance the simulated hardware delay before segment 1. */
  1035. for (ticks = 0; ticks < 10; ticks++)
  1036. {
  1037. PlsrProcess();
  1038. }
  1039. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1040. /* 3 pulses / 2 units: 1001 units emit 1501 pulses and keep 1/2 remainder. */
  1041. for (ticks = 0; ticks < 1501; ticks++)
  1042. {
  1043. PlsrHwTestTriggerUpdate(0U);
  1044. }
  1045. PlsrProcess();
  1046. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1047. /* Segment 2 consumes the remainder and therefore emits 1502 pulses. */
  1048. for (ticks = 0; ticks < 1502; ticks++)
  1049. {
  1050. PlsrHwTestTriggerUpdate(0U);
  1051. }
  1052. PlsrProcess();
  1053. status = TestGetStatus();
  1054. CHECK(status.lastCommandResult == PLSR_RESULT_OK);
  1055. CHECK(status.outputMode == PLSR_OUTPUT_PULSE_DIR);
  1056. CHECK(status.state == PLSR_STATE_COMPLETED);
  1057. CHECK(status.currentSegment == 2U);
  1058. CHECK(status.logicalPosition == 3003);
  1059. CHECK(status.taskPulses == 3003);
  1060. CHECK(status.totalPulses == 3003);
  1061. CHECK(PlcDeviceReadHsdDword(0U, &hsdPulses) == PLC_DEVICE_OK);
  1062. CHECK(PlcDeviceReadHsdDword(2U, &hsdEquivalent) == PLC_DEVICE_OK);
  1063. CHECK(hsdPulses == 3003);
  1064. CHECK(hsdEquivalent == 2002);
  1065. CHECK(TestReadSdDword(1002U) == 1502);
  1066. CHECK(TestReadSdDword(1004U) == 1001);
  1067. }
  1068. static void TestProtectionSelfTest(void)
  1069. {
  1070. PLC_DEVICE_EVENT_RECORD eventRecord;
  1071. PLSR_STATUS status;
  1072. uint32_t pulseAccumulator = 0UL;
  1073. int32_t value;
  1074. int ticks;
  1075. TestResetEnvironment();
  1076. CHECK(PlsrProtectionSelfTestQueue() == PLSR_RESULT_QUEUED);
  1077. PlsrProcess();
  1078. /* Complete the 10ms direction-settle interval. */
  1079. for (ticks = 0; ticks < 10; ticks++)
  1080. {
  1081. PlsrProcess();
  1082. }
  1083. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_RUNNING);
  1084. /* Convert the current frequency into simulated hardware updates over
  1085. * each 1ms process tick. This also models the falling pulse density
  1086. * during the controlled stop. */
  1087. status = TestGetStatus();
  1088. for (ticks = 0; ticks < 600; ticks++)
  1089. {
  1090. pulseAccumulator += PlsrHwGetCurrentFrequencyHz(0U);
  1091. while ((pulseAccumulator >= 1000UL)
  1092. && (PlsrHwIsPulseActive(0U) != 0U))
  1093. {
  1094. PlsrHwTestTriggerUpdate(0U);
  1095. pulseAccumulator -= 1000UL;
  1096. }
  1097. PlsrProcess();
  1098. status = TestGetStatus();
  1099. if (status.state == PLSR_STATE_STOPPED)
  1100. {
  1101. break;
  1102. }
  1103. }
  1104. status = TestGetStatus();
  1105. CHECK(status.state == PLSR_STATE_STOPPED);
  1106. CHECK(status.stopReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1107. CHECK(status.error == PLSR_ERROR_LIMIT_POSITIVE);
  1108. CHECK(status.emergencyLatched == 0U);
  1109. CHECK(status.logicalPosition >= 499);
  1110. CHECK(status.logicalPosition <= 501);
  1111. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1112. CHECK(PlcDeviceReadSd(1010U, &value) == PLC_DEVICE_OK);
  1113. CHECK(value == 5U);
  1114. CHECK(PlcDeviceReadEvent(6000U, &eventRecord) == PLC_DEVICE_OK);
  1115. CHECK(eventRecord.count == 1UL);
  1116. CHECK(eventRecord.pending != 0U);
  1117. CHECK(eventRecord.lastReason == PLSR_STOP_REASON_LIMIT_POSITIVE);
  1118. }
  1119. static void TestStopStopsHardware(void)
  1120. {
  1121. TEST_MEMORY memory;
  1122. PLSR_CALL call;
  1123. PLSR_COMMAND command;
  1124. PLSR_STATUS status;
  1125. int ticks;
  1126. TestResetEnvironment();
  1127. (void)memset(&memory, 0, sizeof(memory));
  1128. TestWriteDword(&memory, PLSR_DEVICE_D, TEST_S0_BASE, 1);
  1129. TestSetSegment(&memory, 1U, 1000U, 10000);
  1130. call = TestMakeCall(&memory);
  1131. call.sequence = 20UL;
  1132. CHECK(PlsrPostCall(&call) == PLSR_RESULT_QUEUED);
  1133. PlsrProcess();
  1134. for (ticks = 0; ticks < 10; ticks++)
  1135. {
  1136. PlsrProcess();
  1137. }
  1138. CHECK(PlsrHwIsPulseActive(0U) == 1U);
  1139. /* STOP_IMMEDIATE:硬件立即停止。 */
  1140. command.sequence = 21UL;
  1141. command.axis = 0U;
  1142. command.opcode = PLSR_CMD_STOP_IMMEDIATE;
  1143. command.argument = 0;
  1144. CHECK(PlsrPostCommand(&command) == PLSR_RESULT_QUEUED);
  1145. PlsrProcess();
  1146. CHECK(PlsrHwIsPulseActive(0U) == 0U);
  1147. CHECK(PlsrHwGetState(0U) == PLSR_HW_STATE_IDLE);
  1148. CHECK(PlsrPostEvent(0U, PLSR_EVENT_STOP_IMMEDIATE_DONE)
  1149. == PLSR_RESULT_OK);
  1150. PlsrProcess();
  1151. status = TestGetStatus();
  1152. CHECK(status.state == PLSR_STATE_STOPPED);
  1153. }
  1154. int main(void)
  1155. {
  1156. TestMapping();
  1157. TestDirDelaySequence();
  1158. TestZeroFrequencyWaits();
  1159. TestPulseCounting();
  1160. TestAbPhaseAndCounting();
  1161. TestTwoAbAxesIndependent();
  1162. TestAbFrequencyLimits();
  1163. TestStopAndInvalidArgs();
  1164. TestEndToEndTwoSegments();
  1165. TestEndToEndAbSegment();
  1166. TestPositionOnImmediateStop();
  1167. TestAbsolutePositionAccounting();
  1168. TestEquivalentRemainderAccounting();
  1169. TestEquivalentCompatibleError();
  1170. TestSoftLimitAndSegmentEvent();
  1171. TestHardLimitAndEmergencyLatch();
  1172. TestProductionSelfTestStartsAb();
  1173. TestEquivalentSelfTest();
  1174. TestProtectionSelfTest();
  1175. TestStopStopsHardware();
  1176. if (TestFailures != 0)
  1177. {
  1178. (void)printf("FAIL: %d of %d PLSR HAL checks failed\n",
  1179. TestFailures,
  1180. TestChecks);
  1181. return 1;
  1182. }
  1183. (void)printf("PASS: %d PLSR HAL checks\n", TestChecks);
  1184. return 0;
  1185. }