Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

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