Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

760 Zeilen
20 KiB

  1. #include "plc_device.h"
  2. #include <string.h>
  3. #ifndef PLSR_HOST_TEST
  4. #include "stm32f4xx.h"
  5. #endif
  6. #define PLC_SM_PULSE_ACTIVE_MASK (0x01U)
  7. #define PLC_SM_DIRECTION_MASK (0x02U)
  8. const PLSR_AXIS_ADDRESS_MAP PlsrAxisAddressMap[PLSR_AXIS_COUNT] =
  9. {
  10. {0U, 1000U, 1001U, 1000U, 6000U},
  11. {4U, 1020U, 1021U, 1020U, 6100U},
  12. {8U, 1040U, 1041U, 1040U, 6200U},
  13. {12U, 1060U, 1061U, 1060U, 6300U}
  14. };
  15. static PLSR_HSD_DATA PlcHsdData;
  16. static PLSR_SFD_DATA PlcSfdData;
  17. static int32_t PlcSdRuntime[PLSR_AXIS_COUNT][PLSR_SD_AXIS_ITEM_COUNT];
  18. static uint8_t PlcSmFlags[PLSR_AXIS_COUNT];
  19. static PLC_DEVICE_EVENT_RECORD
  20. PlcEventRecords[PLSR_AXIS_COUNT][PLSR_EVENT_AXIS_ITEM_COUNT];
  21. static uint8_t PlcHsdDirty;
  22. static uint8_t PlcSfdDirty;
  23. static uint8_t PlcSfdOperationActive;
  24. static uint32_t PlcHsdChangeCounter;
  25. static PLSR_PERSISTENCE_RESULT PlcLastHsdLoadResult;
  26. static PLSR_PERSISTENCE_RESULT PlcLastSfdLoadResult;
  27. static uint8_t PlcRestoredHsdPositionValid;
  28. static uint8_t PlcRestoredHsdLastBusy;
  29. static uint32_t PlcDeviceEnterCritical(void)
  30. {
  31. #ifdef PLSR_HOST_TEST
  32. return 0UL;
  33. #else
  34. uint32_t interruptState = __get_PRIMASK();
  35. __disable_irq();
  36. __DMB();
  37. return interruptState;
  38. #endif
  39. }
  40. static void PlcDeviceExitCritical(uint32_t interruptState)
  41. {
  42. #ifdef PLSR_HOST_TEST
  43. (void)interruptState;
  44. #else
  45. __DMB();
  46. if (interruptState == 0UL)
  47. {
  48. __enable_irq();
  49. }
  50. #endif
  51. }
  52. static uint8_t PlcDeviceBeginSfdOperation(void)
  53. {
  54. uint8_t axis;
  55. uint8_t busy;
  56. uint32_t interruptState;
  57. #ifndef PLSR_HOST_TEST
  58. if (__get_IPSR() != 0UL)
  59. {
  60. return 0U;
  61. }
  62. #endif
  63. interruptState = PlcDeviceEnterCritical();
  64. busy = PlcSfdOperationActive;
  65. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  66. {
  67. if ((PlcSmFlags[axis] & PLC_SM_PULSE_ACTIVE_MASK) != 0U)
  68. {
  69. busy = 1U;
  70. }
  71. }
  72. if (busy == 0U)
  73. {
  74. PlcSfdOperationActive = 1U;
  75. }
  76. PlcDeviceExitCritical(interruptState);
  77. return (busy == 0U) ? 1U : 0U;
  78. }
  79. static void PlcDeviceEndSfdOperation(void)
  80. {
  81. uint32_t interruptState = PlcDeviceEnterCritical();
  82. PlcSfdOperationActive = 0U;
  83. PlcDeviceExitCritical(interruptState);
  84. }
  85. static uint16_t *PlcDeviceResolveHsd(uint16_t address)
  86. {
  87. if (address < PLSR_HSD_RUNTIME_START + PLSR_HSD_RUNTIME_COUNT)
  88. {
  89. return &PlcHsdData.runtime[address - PLSR_HSD_RUNTIME_START];
  90. }
  91. if ((address >= PLSR_HSD_CONFIG_START)
  92. && (address < PLSR_HSD_CONFIG_START + PLSR_HSD_CONFIG_COUNT))
  93. {
  94. return &PlcHsdData.config[address - PLSR_HSD_CONFIG_START];
  95. }
  96. return NULL;
  97. }
  98. static int32_t *PlcDeviceResolveSd(uint16_t address,
  99. uint8_t *axis,
  100. uint8_t *item)
  101. {
  102. uint8_t axisIndex;
  103. uint16_t base;
  104. for (axisIndex = 0U; axisIndex < PLSR_AXIS_COUNT; axisIndex++)
  105. {
  106. base = PlsrAxisAddressMap[axisIndex].sdRuntimeBase;
  107. if ((address >= base)
  108. && (address < base + PLSR_SD_AXIS_ITEM_COUNT))
  109. {
  110. if (axis != NULL)
  111. {
  112. *axis = axisIndex;
  113. }
  114. if (item != NULL)
  115. {
  116. *item = (uint8_t)(address - base);
  117. }
  118. return &PlcSdRuntime[axisIndex][address - base];
  119. }
  120. }
  121. return NULL;
  122. }
  123. static PLC_DEVICE_RESULT PlcDeviceResolveSm(uint16_t address,
  124. uint8_t *axis,
  125. uint8_t *mask)
  126. {
  127. uint8_t axisIndex;
  128. if ((axis == NULL) || (mask == NULL))
  129. {
  130. return PLC_DEVICE_NULL_POINTER;
  131. }
  132. for (axisIndex = 0U; axisIndex < PLSR_AXIS_COUNT; axisIndex++)
  133. {
  134. if (address == PlsrAxisAddressMap[axisIndex].smPulseActiveAddress)
  135. {
  136. *axis = axisIndex;
  137. *mask = PLC_SM_PULSE_ACTIVE_MASK;
  138. return PLC_DEVICE_OK;
  139. }
  140. if (address == PlsrAxisAddressMap[axisIndex].smDirectionAddress)
  141. {
  142. *axis = axisIndex;
  143. *mask = PLC_SM_DIRECTION_MASK;
  144. return PLC_DEVICE_OK;
  145. }
  146. }
  147. return PLC_DEVICE_INVALID_ADDRESS;
  148. }
  149. static PLC_DEVICE_EVENT_RECORD *PlcDeviceResolveEvent(uint16_t address)
  150. {
  151. uint8_t axis;
  152. uint16_t base;
  153. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  154. {
  155. base = PlsrAxisAddressMap[axis].eventBase;
  156. if ((address >= base)
  157. && (address < base + PLSR_EVENT_AXIS_ITEM_COUNT))
  158. {
  159. return &PlcEventRecords[axis][address - base];
  160. }
  161. }
  162. return NULL;
  163. }
  164. PLC_DEVICE_RESULT PlcDeviceInit(void)
  165. {
  166. (void)memset(&PlcHsdData, 0, sizeof(PlcHsdData));
  167. (void)memset(&PlcSfdData, 0, sizeof(PlcSfdData));
  168. (void)memset(PlcSdRuntime, 0, sizeof(PlcSdRuntime));
  169. (void)memset(PlcSmFlags, 0, sizeof(PlcSmFlags));
  170. (void)memset(PlcEventRecords, 0, sizeof(PlcEventRecords));
  171. PlcSfdOperationActive = 0U;
  172. PlcHsdChangeCounter = 0UL;
  173. PlcRestoredHsdPositionValid = 0U;
  174. PlcRestoredHsdLastBusy = 0U;
  175. PlcLastHsdLoadResult = PlsrPersistenceLoadHsd(&PlcHsdData);
  176. PlcHsdDirty = (PlcLastHsdLoadResult == PLSR_PERSISTENCE_DEFAULTED)
  177. ? 1U
  178. : 0U;
  179. if ((PlcLastHsdLoadResult != PLSR_PERSISTENCE_OK)
  180. && (PlcLastHsdLoadResult != PLSR_PERSISTENCE_DEFAULTED))
  181. {
  182. return PLC_DEVICE_PERSISTENCE_ERROR;
  183. }
  184. PlcRestoredHsdPositionValid =
  185. ((PlcHsdData.metadata & PLSR_HSD_META_POSITION_VALID) != 0UL)
  186. ? 1U
  187. : 0U;
  188. PlcRestoredHsdLastBusy =
  189. ((PlcHsdData.metadata & PLSR_HSD_META_LAST_BUSY) != 0UL) ? 1U : 0U;
  190. PlcLastSfdLoadResult = PlsrPersistenceLoadSfd(&PlcSfdData);
  191. PlcSfdDirty = (PlcLastSfdLoadResult == PLSR_PERSISTENCE_OK) ? 0U : 1U;
  192. if ((PlcLastSfdLoadResult != PLSR_PERSISTENCE_OK)
  193. && (PlcLastSfdLoadResult != PLSR_PERSISTENCE_DEFAULTED))
  194. {
  195. return PLC_DEVICE_PERSISTENCE_ERROR;
  196. }
  197. return PLC_DEVICE_OK;
  198. }
  199. PLC_DEVICE_RESULT PlcDeviceReadHsd(uint16_t address, uint16_t *value)
  200. {
  201. uint16_t *source;
  202. if (value == NULL)
  203. {
  204. return PLC_DEVICE_NULL_POINTER;
  205. }
  206. source = PlcDeviceResolveHsd(address);
  207. if (source == NULL)
  208. {
  209. return PLC_DEVICE_INVALID_ADDRESS;
  210. }
  211. *value = *source;
  212. return PLC_DEVICE_OK;
  213. }
  214. PLC_DEVICE_RESULT PlcDeviceWriteHsdConfig(uint16_t address, uint16_t value)
  215. {
  216. if ((address < PLSR_HSD_CONFIG_START)
  217. || (address >= PLSR_HSD_CONFIG_START + PLSR_HSD_CONFIG_COUNT))
  218. {
  219. return (address < PLSR_HSD_RUNTIME_START
  220. + PLSR_HSD_RUNTIME_COUNT)
  221. ? PLC_DEVICE_READ_ONLY
  222. : PLC_DEVICE_INVALID_ADDRESS;
  223. }
  224. PlcHsdData.config[address - PLSR_HSD_CONFIG_START] = value;
  225. PlcHsdChangeCounter++;
  226. PlcHsdDirty = 1U;
  227. return PLC_DEVICE_OK;
  228. }
  229. PLC_DEVICE_RESULT PlcDevicePublishHsdRuntime(uint16_t address, uint16_t value)
  230. {
  231. if (address >= PLSR_HSD_RUNTIME_START + PLSR_HSD_RUNTIME_COUNT)
  232. {
  233. return PLC_DEVICE_INVALID_ADDRESS;
  234. }
  235. PlcHsdData.runtime[address - PLSR_HSD_RUNTIME_START] = value;
  236. PlcHsdChangeCounter++;
  237. PlcHsdDirty = 1U;
  238. return PLC_DEVICE_OK;
  239. }
  240. /* 两个相邻 WORD 组成一个 32 位值:低地址=低16位,高地址=高16位(信捷兼容布局)。 */
  241. PLC_DEVICE_RESULT PlcDeviceReadHsdDword(uint16_t lowAddress, int32_t *value)
  242. {
  243. uint32_t combined;
  244. uint32_t interruptState;
  245. uint16_t offset;
  246. if (value == NULL)
  247. {
  248. return PLC_DEVICE_NULL_POINTER;
  249. }
  250. if ((lowAddress >= PLSR_HSD_RUNTIME_COUNT)
  251. || ((lowAddress & 1U) != 0U)
  252. || ((uint16_t)(lowAddress + 1U) >= PLSR_HSD_RUNTIME_COUNT))
  253. {
  254. return PLC_DEVICE_INVALID_ADDRESS;
  255. }
  256. offset = (uint16_t)(lowAddress - PLSR_HSD_RUNTIME_START);
  257. interruptState = PlcDeviceEnterCritical();
  258. combined = (uint32_t)PlcHsdData.runtime[offset];
  259. combined |= ((uint32_t)PlcHsdData.runtime[offset + 1U]) << 16U;
  260. PlcDeviceExitCritical(interruptState);
  261. *value = (int32_t)combined;
  262. return PLC_DEVICE_OK;
  263. }
  264. PLC_DEVICE_RESULT PlcDevicePublishHsdDword(uint16_t lowAddress, int32_t value)
  265. {
  266. uint32_t rawValue;
  267. uint32_t interruptState;
  268. uint16_t offset;
  269. if ((lowAddress >= PLSR_HSD_RUNTIME_COUNT)
  270. || ((lowAddress & 1U) != 0U)
  271. || ((uint16_t)(lowAddress + 1U) >= PLSR_HSD_RUNTIME_COUNT))
  272. {
  273. return PLC_DEVICE_INVALID_ADDRESS;
  274. }
  275. rawValue = (uint32_t)value;
  276. offset = (uint16_t)(lowAddress - PLSR_HSD_RUNTIME_START);
  277. interruptState = PlcDeviceEnterCritical();
  278. PlcHsdData.runtime[offset] = (uint16_t)(rawValue & 0xFFFFUL);
  279. PlcHsdData.runtime[offset + 1U] = (uint16_t)(rawValue >> 16U);
  280. PlcHsdChangeCounter++;
  281. PlcHsdDirty = 1U;
  282. PlcDeviceExitCritical(interruptState);
  283. return PLC_DEVICE_OK;
  284. }
  285. PLC_DEVICE_RESULT PlcDeviceSetHsdCheckpointMeta(uint8_t positionValid,
  286. uint8_t lastBusy)
  287. {
  288. uint32_t interruptState = PlcDeviceEnterCritical();
  289. PlcHsdData.metadata &= ~(PLSR_HSD_META_POSITION_VALID
  290. | PLSR_HSD_META_LAST_BUSY);
  291. if (positionValid != 0U)
  292. {
  293. PlcHsdData.metadata |= PLSR_HSD_META_POSITION_VALID;
  294. }
  295. if (lastBusy != 0U)
  296. {
  297. PlcHsdData.metadata |= PLSR_HSD_META_LAST_BUSY;
  298. }
  299. PlcHsdChangeCounter++;
  300. PlcHsdDirty = 1U;
  301. PlcDeviceExitCritical(interruptState);
  302. return PLC_DEVICE_OK;
  303. }
  304. uint8_t PlcDeviceGetRestoredHsdPositionValid(void)
  305. {
  306. return PlcRestoredHsdPositionValid;
  307. }
  308. uint8_t PlcDeviceGetRestoredHsdLastBusy(void)
  309. {
  310. return PlcRestoredHsdLastBusy;
  311. }
  312. PLC_DEVICE_RESULT PlcDeviceCheckpointHsd(void)
  313. {
  314. PLSR_HSD_DATA snapshot;
  315. PLSR_PERSISTENCE_RESULT result;
  316. uint32_t snapshotCounter;
  317. uint32_t interruptState;
  318. if (PlcHsdDirty == 0U)
  319. {
  320. return PLC_DEVICE_OK;
  321. }
  322. interruptState = PlcDeviceEnterCritical();
  323. snapshot = PlcHsdData;
  324. snapshotCounter = PlcHsdChangeCounter;
  325. PlcDeviceExitCritical(interruptState);
  326. result = PlsrPersistenceSaveHsd(&snapshot);
  327. if (result != PLSR_PERSISTENCE_OK)
  328. {
  329. return PLC_DEVICE_PERSISTENCE_ERROR;
  330. }
  331. interruptState = PlcDeviceEnterCritical();
  332. if (PlcHsdChangeCounter == snapshotCounter)
  333. {
  334. PlcHsdDirty = 0U;
  335. }
  336. PlcDeviceExitCritical(interruptState);
  337. return PLC_DEVICE_OK;
  338. }
  339. PLC_DEVICE_RESULT PlcDeviceReadSfd(uint16_t address, uint16_t *value)
  340. {
  341. uint32_t interruptState;
  342. if (value == NULL)
  343. {
  344. return PLC_DEVICE_NULL_POINTER;
  345. }
  346. if ((address < PLSR_SFD_CONFIG_START)
  347. || (address >= PLSR_SFD_CONFIG_START + PLSR_SFD_CONFIG_COUNT))
  348. {
  349. return PLC_DEVICE_INVALID_ADDRESS;
  350. }
  351. interruptState = PlcDeviceEnterCritical();
  352. if (PlcSfdOperationActive != 0U)
  353. {
  354. PlcDeviceExitCritical(interruptState);
  355. return PLC_DEVICE_BUSY;
  356. }
  357. *value = PlcSfdData.config[address - PLSR_SFD_CONFIG_START];
  358. PlcDeviceExitCritical(interruptState);
  359. return PLC_DEVICE_OK;
  360. }
  361. PLC_DEVICE_RESULT PlcDeviceWriteSfd(uint16_t address, uint16_t value)
  362. {
  363. uint32_t interruptState;
  364. if ((address < PLSR_SFD_CONFIG_START)
  365. || (address >= PLSR_SFD_CONFIG_START + PLSR_SFD_CONFIG_COUNT))
  366. {
  367. return PLC_DEVICE_INVALID_ADDRESS;
  368. }
  369. interruptState = PlcDeviceEnterCritical();
  370. if (PlcSfdOperationActive != 0U)
  371. {
  372. PlcDeviceExitCritical(interruptState);
  373. return PLC_DEVICE_BUSY;
  374. }
  375. PlcSfdData.config[address - PLSR_SFD_CONFIG_START] = value;
  376. PlcSfdDirty = 1U;
  377. PlcDeviceExitCritical(interruptState);
  378. return PLC_DEVICE_OK;
  379. }
  380. PLC_DEVICE_RESULT PlcDeviceLoadSfd(void)
  381. {
  382. if (PlcDeviceBeginSfdOperation() == 0U)
  383. {
  384. return PLC_DEVICE_BUSY;
  385. }
  386. PlcLastSfdLoadResult = PlsrPersistenceLoadSfd(&PlcSfdData);
  387. if ((PlcLastSfdLoadResult != PLSR_PERSISTENCE_OK)
  388. && (PlcLastSfdLoadResult != PLSR_PERSISTENCE_DEFAULTED))
  389. {
  390. PlcDeviceEndSfdOperation();
  391. return PLC_DEVICE_PERSISTENCE_ERROR;
  392. }
  393. PlcSfdDirty = (PlcLastSfdLoadResult == PLSR_PERSISTENCE_OK) ? 0U : 1U;
  394. PlcDeviceEndSfdOperation();
  395. return PLC_DEVICE_OK;
  396. }
  397. PLC_DEVICE_RESULT PlcDeviceSaveSfd(void)
  398. {
  399. PLSR_PERSISTENCE_RESULT result;
  400. if (PlcDeviceBeginSfdOperation() == 0U)
  401. {
  402. return PLC_DEVICE_BUSY;
  403. }
  404. if (PlcSfdDirty == 0U)
  405. {
  406. PlcDeviceEndSfdOperation();
  407. return PLC_DEVICE_OK;
  408. }
  409. result = PlsrPersistenceSaveSfd(&PlcSfdData);
  410. if (result != PLSR_PERSISTENCE_OK)
  411. {
  412. PlcDeviceEndSfdOperation();
  413. return PLC_DEVICE_PERSISTENCE_ERROR;
  414. }
  415. PlcSfdDirty = 0U;
  416. PlcDeviceEndSfdOperation();
  417. return PLC_DEVICE_OK;
  418. }
  419. PLC_DEVICE_RESULT PlcDeviceResetSfdDefaults(void)
  420. {
  421. PLSR_PERSISTENCE_RESULT result;
  422. if (PlcDeviceBeginSfdOperation() == 0U)
  423. {
  424. return PLC_DEVICE_BUSY;
  425. }
  426. result = PlsrPersistenceEraseSfd();
  427. if (result != PLSR_PERSISTENCE_OK)
  428. {
  429. PlcDeviceEndSfdOperation();
  430. return PLC_DEVICE_PERSISTENCE_ERROR;
  431. }
  432. PlcLastSfdLoadResult = PlsrPersistenceLoadSfd(&PlcSfdData);
  433. if (PlcLastSfdLoadResult != PLSR_PERSISTENCE_DEFAULTED)
  434. {
  435. PlcDeviceEndSfdOperation();
  436. return PLC_DEVICE_PERSISTENCE_ERROR;
  437. }
  438. PlcSfdDirty = 1U;
  439. PlcDeviceEndSfdOperation();
  440. return PLC_DEVICE_OK;
  441. }
  442. PLC_DEVICE_RESULT PlcDeviceReadSm(uint16_t address, uint8_t *state)
  443. {
  444. uint8_t axis;
  445. uint8_t mask;
  446. PLC_DEVICE_RESULT result;
  447. if (state == NULL)
  448. {
  449. return PLC_DEVICE_NULL_POINTER;
  450. }
  451. result = PlcDeviceResolveSm(address, &axis, &mask);
  452. if (result != PLC_DEVICE_OK)
  453. {
  454. return result;
  455. }
  456. *state = ((PlcSmFlags[axis] & mask) != 0U) ? 1U : 0U;
  457. return PLC_DEVICE_OK;
  458. }
  459. PLC_DEVICE_RESULT PlcDeviceWriteSm(uint16_t address, uint8_t state)
  460. {
  461. uint8_t axis;
  462. uint8_t mask;
  463. PLC_DEVICE_RESULT result;
  464. (void)state;
  465. result = PlcDeviceResolveSm(address, &axis, &mask);
  466. return (result == PLC_DEVICE_OK) ? PLC_DEVICE_READ_ONLY : result;
  467. }
  468. PLC_DEVICE_RESULT PlcDevicePublishSm(uint8_t axis,
  469. uint8_t pulseActive,
  470. uint8_t direction)
  471. {
  472. uint8_t flags = 0U;
  473. uint32_t interruptState;
  474. if (axis >= PLSR_AXIS_COUNT)
  475. {
  476. return PLC_DEVICE_INVALID_ARGUMENT;
  477. }
  478. if (pulseActive != 0U)
  479. {
  480. flags |= PLC_SM_PULSE_ACTIVE_MASK;
  481. }
  482. if (direction != 0U)
  483. {
  484. flags |= PLC_SM_DIRECTION_MASK;
  485. }
  486. interruptState = PlcDeviceEnterCritical();
  487. if ((pulseActive != 0U) && (PlcSfdOperationActive != 0U))
  488. {
  489. PlcDeviceExitCritical(interruptState);
  490. return PLC_DEVICE_BUSY;
  491. }
  492. PlcSmFlags[axis] = flags;
  493. PlcDeviceExitCritical(interruptState);
  494. return PLC_DEVICE_OK;
  495. }
  496. PLC_DEVICE_RESULT PlcDeviceReadSd(uint16_t address, int32_t *value)
  497. {
  498. int32_t *source;
  499. uint32_t interruptState;
  500. if (value == NULL)
  501. {
  502. return PLC_DEVICE_NULL_POINTER;
  503. }
  504. source = PlcDeviceResolveSd(address, NULL, NULL);
  505. if (source == NULL)
  506. {
  507. return PLC_DEVICE_INVALID_ADDRESS;
  508. }
  509. interruptState = PlcDeviceEnterCritical();
  510. *value = *source;
  511. PlcDeviceExitCritical(interruptState);
  512. return PLC_DEVICE_OK;
  513. }
  514. PLC_DEVICE_RESULT PlcDeviceWriteSd(uint16_t address, int32_t value)
  515. {
  516. (void)value;
  517. return (PlcDeviceResolveSd(address, NULL, NULL) != NULL)
  518. ? PLC_DEVICE_READ_ONLY
  519. : PLC_DEVICE_INVALID_ADDRESS;
  520. }
  521. PLC_DEVICE_RESULT PlcDevicePublishSd(uint8_t axis,
  522. uint8_t item,
  523. int32_t value)
  524. {
  525. uint32_t interruptState;
  526. if ((axis >= PLSR_AXIS_COUNT) || (item >= PLSR_SD_AXIS_ITEM_COUNT))
  527. {
  528. return PLC_DEVICE_INVALID_ARGUMENT;
  529. }
  530. interruptState = PlcDeviceEnterCritical();
  531. PlcSdRuntime[axis][item] = value;
  532. PlcDeviceExitCritical(interruptState);
  533. return PLC_DEVICE_OK;
  534. }
  535. PLC_DEVICE_RESULT PlcDeviceReadSdDword(uint16_t lowAddress, int32_t *value)
  536. {
  537. int32_t *source;
  538. uint32_t rawValue;
  539. uint32_t interruptState;
  540. uint8_t axis;
  541. uint8_t item;
  542. if (value == NULL)
  543. {
  544. return PLC_DEVICE_NULL_POINTER;
  545. }
  546. source = PlcDeviceResolveSd(lowAddress, &axis, &item);
  547. if ((source == NULL) || ((item & 1U) != 0U)
  548. || (item > PLSR_SD_ITEM_SPEED))
  549. {
  550. return PLC_DEVICE_INVALID_ADDRESS;
  551. }
  552. interruptState = PlcDeviceEnterCritical();
  553. rawValue = (uint32_t)PlcSdRuntime[axis][item] & 0xFFFFUL;
  554. rawValue |= ((uint32_t)PlcSdRuntime[axis][item + 1U] & 0xFFFFUL)
  555. << 16U;
  556. PlcDeviceExitCritical(interruptState);
  557. *value = (int32_t)rawValue;
  558. return PLC_DEVICE_OK;
  559. }
  560. PLC_DEVICE_RESULT PlcDevicePublishSdDword(uint8_t axis,
  561. uint8_t lowItem,
  562. int32_t value)
  563. {
  564. uint32_t rawValue;
  565. uint32_t interruptState;
  566. if ((axis >= PLSR_AXIS_COUNT) || ((lowItem & 1U) != 0U)
  567. || (lowItem > PLSR_SD_ITEM_SPEED))
  568. {
  569. return PLC_DEVICE_INVALID_ARGUMENT;
  570. }
  571. rawValue = (uint32_t)value;
  572. interruptState = PlcDeviceEnterCritical();
  573. PlcSdRuntime[axis][lowItem] = (int32_t)(rawValue & 0xFFFFUL);
  574. PlcSdRuntime[axis][lowItem + 1U] = (int32_t)(rawValue >> 16U);
  575. PlcDeviceExitCritical(interruptState);
  576. return PLC_DEVICE_OK;
  577. }
  578. PLC_DEVICE_RESULT PlcDeviceGetEventAddress(uint8_t axis,
  579. uint16_t segmentNumber,
  580. uint16_t *eventAddress)
  581. {
  582. if (eventAddress == NULL)
  583. {
  584. return PLC_DEVICE_NULL_POINTER;
  585. }
  586. if ((axis >= PLSR_AXIS_COUNT) || (segmentNumber == 0U)
  587. || (segmentNumber > PLSR_EVENT_AXIS_ITEM_COUNT))
  588. {
  589. return PLC_DEVICE_INVALID_ARGUMENT;
  590. }
  591. *eventAddress = (uint16_t)(PlsrAxisAddressMap[axis].eventBase
  592. + segmentNumber - 1U);
  593. return PLC_DEVICE_OK;
  594. }
  595. PLC_DEVICE_RESULT PlcDevicePublishEvent(uint8_t axis,
  596. uint16_t segmentNumber,
  597. uint16_t reason)
  598. {
  599. PLC_DEVICE_EVENT_RECORD *record;
  600. uint32_t interruptState;
  601. if ((axis >= PLSR_AXIS_COUNT) || (segmentNumber == 0U)
  602. || (segmentNumber > PLSR_EVENT_AXIS_ITEM_COUNT))
  603. {
  604. return PLC_DEVICE_INVALID_ARGUMENT;
  605. }
  606. record = &PlcEventRecords[axis][segmentNumber - 1U];
  607. interruptState = PlcDeviceEnterCritical();
  608. if (record->count != UINT32_MAX)
  609. {
  610. record->count++;
  611. }
  612. record->lastReason = reason;
  613. record->pending = 1U;
  614. PlcDeviceExitCritical(interruptState);
  615. return PLC_DEVICE_OK;
  616. }
  617. PLC_DEVICE_RESULT PlcDeviceReadEvent(uint16_t eventAddress,
  618. PLC_DEVICE_EVENT_RECORD *record)
  619. {
  620. PLC_DEVICE_EVENT_RECORD *source;
  621. uint32_t interruptState;
  622. if (record == NULL)
  623. {
  624. return PLC_DEVICE_NULL_POINTER;
  625. }
  626. source = PlcDeviceResolveEvent(eventAddress);
  627. if (source == NULL)
  628. {
  629. return PLC_DEVICE_INVALID_ADDRESS;
  630. }
  631. interruptState = PlcDeviceEnterCritical();
  632. *record = *source;
  633. PlcDeviceExitCritical(interruptState);
  634. return PLC_DEVICE_OK;
  635. }
  636. PLC_DEVICE_RESULT PlcDeviceAcknowledgeEvent(uint16_t eventAddress)
  637. {
  638. PLC_DEVICE_EVENT_RECORD *record = PlcDeviceResolveEvent(eventAddress);
  639. uint32_t interruptState;
  640. if (record == NULL)
  641. {
  642. return PLC_DEVICE_INVALID_ADDRESS;
  643. }
  644. interruptState = PlcDeviceEnterCritical();
  645. record->pending = 0U;
  646. PlcDeviceExitCritical(interruptState);
  647. return PLC_DEVICE_OK;
  648. }
  649. uint8_t PlcDeviceIsHsdDirty(void)
  650. {
  651. return PlcHsdDirty;
  652. }
  653. uint8_t PlcDeviceIsSfdDirty(void)
  654. {
  655. return PlcSfdDirty;
  656. }
  657. PLSR_PERSISTENCE_RESULT PlcDeviceGetLastHsdLoadResult(void)
  658. {
  659. return PlcLastHsdLoadResult;
  660. }
  661. PLSR_PERSISTENCE_RESULT PlcDeviceGetLastSfdLoadResult(void)
  662. {
  663. return PlcLastSfdLoadResult;
  664. }