25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 
 
 

584 satır
15 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 uint8_t PlcHsdDirty;
  20. static uint8_t PlcSfdDirty;
  21. static uint8_t PlcSfdOperationActive;
  22. static uint32_t PlcHsdChangeCounter;
  23. static PLSR_PERSISTENCE_RESULT PlcLastHsdLoadResult;
  24. static PLSR_PERSISTENCE_RESULT PlcLastSfdLoadResult;
  25. static uint32_t PlcDeviceEnterCritical(void)
  26. {
  27. #ifdef PLSR_HOST_TEST
  28. return 0UL;
  29. #else
  30. uint32_t interruptState = __get_PRIMASK();
  31. __disable_irq();
  32. __DMB();
  33. return interruptState;
  34. #endif
  35. }
  36. static void PlcDeviceExitCritical(uint32_t interruptState)
  37. {
  38. #ifdef PLSR_HOST_TEST
  39. (void)interruptState;
  40. #else
  41. __DMB();
  42. if (interruptState == 0UL)
  43. {
  44. __enable_irq();
  45. }
  46. #endif
  47. }
  48. static uint8_t PlcDeviceBeginSfdOperation(void)
  49. {
  50. uint8_t axis;
  51. uint8_t busy;
  52. uint32_t interruptState;
  53. #ifndef PLSR_HOST_TEST
  54. if (__get_IPSR() != 0UL)
  55. {
  56. return 0U;
  57. }
  58. #endif
  59. interruptState = PlcDeviceEnterCritical();
  60. busy = PlcSfdOperationActive;
  61. for (axis = 0U; axis < PLSR_AXIS_COUNT; axis++)
  62. {
  63. if ((PlcSmFlags[axis] & PLC_SM_PULSE_ACTIVE_MASK) != 0U)
  64. {
  65. busy = 1U;
  66. }
  67. }
  68. if (busy == 0U)
  69. {
  70. PlcSfdOperationActive = 1U;
  71. }
  72. PlcDeviceExitCritical(interruptState);
  73. return (busy == 0U) ? 1U : 0U;
  74. }
  75. static void PlcDeviceEndSfdOperation(void)
  76. {
  77. uint32_t interruptState = PlcDeviceEnterCritical();
  78. PlcSfdOperationActive = 0U;
  79. PlcDeviceExitCritical(interruptState);
  80. }
  81. static int32_t *PlcDeviceResolveHsd(uint16_t address)
  82. {
  83. if (address < PLSR_HSD_RUNTIME_START + PLSR_HSD_RUNTIME_COUNT)
  84. {
  85. return &PlcHsdData.runtime[address - PLSR_HSD_RUNTIME_START];
  86. }
  87. if ((address >= PLSR_HSD_CONFIG_START)
  88. && (address < PLSR_HSD_CONFIG_START + PLSR_HSD_CONFIG_COUNT))
  89. {
  90. return &PlcHsdData.config[address - PLSR_HSD_CONFIG_START];
  91. }
  92. return NULL;
  93. }
  94. static int32_t *PlcDeviceResolveSd(uint16_t address,
  95. uint8_t *axis,
  96. uint8_t *item)
  97. {
  98. uint8_t axisIndex;
  99. uint16_t base;
  100. for (axisIndex = 0U; axisIndex < PLSR_AXIS_COUNT; axisIndex++)
  101. {
  102. base = PlsrAxisAddressMap[axisIndex].sdRuntimeBase;
  103. if ((address >= base)
  104. && (address < base + PLSR_SD_AXIS_ITEM_COUNT))
  105. {
  106. if (axis != NULL)
  107. {
  108. *axis = axisIndex;
  109. }
  110. if (item != NULL)
  111. {
  112. *item = (uint8_t)(address - base);
  113. }
  114. return &PlcSdRuntime[axisIndex][address - base];
  115. }
  116. }
  117. return NULL;
  118. }
  119. static PLC_DEVICE_RESULT PlcDeviceResolveSm(uint16_t address,
  120. uint8_t *axis,
  121. uint8_t *mask)
  122. {
  123. uint8_t axisIndex;
  124. if ((axis == NULL) || (mask == NULL))
  125. {
  126. return PLC_DEVICE_NULL_POINTER;
  127. }
  128. for (axisIndex = 0U; axisIndex < PLSR_AXIS_COUNT; axisIndex++)
  129. {
  130. if (address == PlsrAxisAddressMap[axisIndex].smPulseActiveAddress)
  131. {
  132. *axis = axisIndex;
  133. *mask = PLC_SM_PULSE_ACTIVE_MASK;
  134. return PLC_DEVICE_OK;
  135. }
  136. if (address == PlsrAxisAddressMap[axisIndex].smDirectionAddress)
  137. {
  138. *axis = axisIndex;
  139. *mask = PLC_SM_DIRECTION_MASK;
  140. return PLC_DEVICE_OK;
  141. }
  142. }
  143. return PLC_DEVICE_INVALID_ADDRESS;
  144. }
  145. PLC_DEVICE_RESULT PlcDeviceInit(void)
  146. {
  147. (void)memset(&PlcHsdData, 0, sizeof(PlcHsdData));
  148. (void)memset(&PlcSfdData, 0, sizeof(PlcSfdData));
  149. (void)memset(PlcSdRuntime, 0, sizeof(PlcSdRuntime));
  150. (void)memset(PlcSmFlags, 0, sizeof(PlcSmFlags));
  151. PlcSfdOperationActive = 0U;
  152. PlcHsdChangeCounter = 0UL;
  153. PlcLastHsdLoadResult = PlsrPersistenceLoadHsd(&PlcHsdData);
  154. PlcHsdDirty = (PlcLastHsdLoadResult == PLSR_PERSISTENCE_DEFAULTED)
  155. ? 1U
  156. : 0U;
  157. if ((PlcLastHsdLoadResult != PLSR_PERSISTENCE_OK)
  158. && (PlcLastHsdLoadResult != PLSR_PERSISTENCE_DEFAULTED))
  159. {
  160. return PLC_DEVICE_PERSISTENCE_ERROR;
  161. }
  162. PlcLastSfdLoadResult = PlsrPersistenceLoadSfd(&PlcSfdData);
  163. PlcSfdDirty = (PlcLastSfdLoadResult == PLSR_PERSISTENCE_OK) ? 0U : 1U;
  164. if ((PlcLastSfdLoadResult != PLSR_PERSISTENCE_OK)
  165. && (PlcLastSfdLoadResult != PLSR_PERSISTENCE_DEFAULTED))
  166. {
  167. return PLC_DEVICE_PERSISTENCE_ERROR;
  168. }
  169. return PLC_DEVICE_OK;
  170. }
  171. PLC_DEVICE_RESULT PlcDeviceReadHsd(uint16_t address, int32_t *value)
  172. {
  173. int32_t *source;
  174. if (value == NULL)
  175. {
  176. return PLC_DEVICE_NULL_POINTER;
  177. }
  178. source = PlcDeviceResolveHsd(address);
  179. if (source == NULL)
  180. {
  181. return PLC_DEVICE_INVALID_ADDRESS;
  182. }
  183. *value = *source;
  184. return PLC_DEVICE_OK;
  185. }
  186. PLC_DEVICE_RESULT PlcDeviceWriteHsdConfig(uint16_t address, int32_t value)
  187. {
  188. if ((address < PLSR_HSD_CONFIG_START)
  189. || (address >= PLSR_HSD_CONFIG_START + PLSR_HSD_CONFIG_COUNT))
  190. {
  191. return (address < PLSR_HSD_RUNTIME_START
  192. + PLSR_HSD_RUNTIME_COUNT)
  193. ? PLC_DEVICE_READ_ONLY
  194. : PLC_DEVICE_INVALID_ADDRESS;
  195. }
  196. PlcHsdData.config[address - PLSR_HSD_CONFIG_START] = value;
  197. PlcHsdChangeCounter++;
  198. PlcHsdDirty = 1U;
  199. return PLC_DEVICE_OK;
  200. }
  201. PLC_DEVICE_RESULT PlcDevicePublishHsdRuntime(uint16_t address, int32_t value)
  202. {
  203. if (address >= PLSR_HSD_RUNTIME_START + PLSR_HSD_RUNTIME_COUNT)
  204. {
  205. return PLC_DEVICE_INVALID_ADDRESS;
  206. }
  207. PlcHsdData.runtime[address - PLSR_HSD_RUNTIME_START] = value;
  208. PlcHsdChangeCounter++;
  209. PlcHsdDirty = 1U;
  210. return PLC_DEVICE_OK;
  211. }
  212. PLC_DEVICE_RESULT PlcDeviceReadHsdPair(uint16_t lowAddress, int64_t *value)
  213. {
  214. uint64_t combined;
  215. uint32_t interruptState;
  216. uint16_t offset;
  217. if (value == NULL)
  218. {
  219. return PLC_DEVICE_NULL_POINTER;
  220. }
  221. if ((lowAddress >= PLSR_HSD_RUNTIME_COUNT)
  222. || ((lowAddress & 1U) != 0U)
  223. || ((uint16_t)(lowAddress + 1U) >= PLSR_HSD_RUNTIME_COUNT))
  224. {
  225. return PLC_DEVICE_INVALID_ADDRESS;
  226. }
  227. offset = (uint16_t)(lowAddress - PLSR_HSD_RUNTIME_START);
  228. interruptState = PlcDeviceEnterCritical();
  229. combined = (uint64_t)(uint32_t)PlcHsdData.runtime[offset];
  230. combined |= ((uint64_t)(uint32_t)PlcHsdData.runtime[offset + 1U]) << 32U;
  231. PlcDeviceExitCritical(interruptState);
  232. *value = (int64_t)combined;
  233. return PLC_DEVICE_OK;
  234. }
  235. PLC_DEVICE_RESULT PlcDevicePublishHsdPair(uint16_t lowAddress, int64_t value)
  236. {
  237. uint64_t rawValue;
  238. uint32_t interruptState;
  239. uint16_t offset;
  240. if ((lowAddress >= PLSR_HSD_RUNTIME_COUNT)
  241. || ((lowAddress & 1U) != 0U)
  242. || ((uint16_t)(lowAddress + 1U) >= PLSR_HSD_RUNTIME_COUNT))
  243. {
  244. return PLC_DEVICE_INVALID_ADDRESS;
  245. }
  246. rawValue = (uint64_t)value;
  247. offset = (uint16_t)(lowAddress - PLSR_HSD_RUNTIME_START);
  248. interruptState = PlcDeviceEnterCritical();
  249. PlcHsdData.runtime[offset] = (int32_t)(uint32_t)rawValue;
  250. PlcHsdData.runtime[offset + 1U] = (int32_t)(uint32_t)(rawValue >> 32U);
  251. PlcHsdChangeCounter++;
  252. PlcHsdDirty = 1U;
  253. PlcDeviceExitCritical(interruptState);
  254. return PLC_DEVICE_OK;
  255. }
  256. PLC_DEVICE_RESULT PlcDeviceCheckpointHsd(void)
  257. {
  258. PLSR_HSD_DATA snapshot;
  259. PLSR_PERSISTENCE_RESULT result;
  260. uint32_t snapshotCounter;
  261. uint32_t interruptState;
  262. if (PlcHsdDirty == 0U)
  263. {
  264. return PLC_DEVICE_OK;
  265. }
  266. interruptState = PlcDeviceEnterCritical();
  267. snapshot = PlcHsdData;
  268. snapshotCounter = PlcHsdChangeCounter;
  269. PlcDeviceExitCritical(interruptState);
  270. result = PlsrPersistenceSaveHsd(&snapshot);
  271. if (result != PLSR_PERSISTENCE_OK)
  272. {
  273. return PLC_DEVICE_PERSISTENCE_ERROR;
  274. }
  275. interruptState = PlcDeviceEnterCritical();
  276. if (PlcHsdChangeCounter == snapshotCounter)
  277. {
  278. PlcHsdDirty = 0U;
  279. }
  280. PlcDeviceExitCritical(interruptState);
  281. return PLC_DEVICE_OK;
  282. }
  283. PLC_DEVICE_RESULT PlcDeviceReadSfd(uint16_t address, int32_t *value)
  284. {
  285. uint32_t interruptState;
  286. if (value == NULL)
  287. {
  288. return PLC_DEVICE_NULL_POINTER;
  289. }
  290. if ((address < PLSR_SFD_CONFIG_START)
  291. || (address >= PLSR_SFD_CONFIG_START + PLSR_SFD_CONFIG_COUNT))
  292. {
  293. return PLC_DEVICE_INVALID_ADDRESS;
  294. }
  295. interruptState = PlcDeviceEnterCritical();
  296. if (PlcSfdOperationActive != 0U)
  297. {
  298. PlcDeviceExitCritical(interruptState);
  299. return PLC_DEVICE_BUSY;
  300. }
  301. *value = PlcSfdData.config[address - PLSR_SFD_CONFIG_START];
  302. PlcDeviceExitCritical(interruptState);
  303. return PLC_DEVICE_OK;
  304. }
  305. PLC_DEVICE_RESULT PlcDeviceWriteSfd(uint16_t address, int32_t value)
  306. {
  307. uint32_t interruptState;
  308. if ((address < PLSR_SFD_CONFIG_START)
  309. || (address >= PLSR_SFD_CONFIG_START + PLSR_SFD_CONFIG_COUNT))
  310. {
  311. return PLC_DEVICE_INVALID_ADDRESS;
  312. }
  313. interruptState = PlcDeviceEnterCritical();
  314. if (PlcSfdOperationActive != 0U)
  315. {
  316. PlcDeviceExitCritical(interruptState);
  317. return PLC_DEVICE_BUSY;
  318. }
  319. PlcSfdData.config[address - PLSR_SFD_CONFIG_START] = value;
  320. PlcSfdDirty = 1U;
  321. PlcDeviceExitCritical(interruptState);
  322. return PLC_DEVICE_OK;
  323. }
  324. PLC_DEVICE_RESULT PlcDeviceLoadSfd(void)
  325. {
  326. if (PlcDeviceBeginSfdOperation() == 0U)
  327. {
  328. return PLC_DEVICE_BUSY;
  329. }
  330. PlcLastSfdLoadResult = PlsrPersistenceLoadSfd(&PlcSfdData);
  331. if ((PlcLastSfdLoadResult != PLSR_PERSISTENCE_OK)
  332. && (PlcLastSfdLoadResult != PLSR_PERSISTENCE_DEFAULTED))
  333. {
  334. PlcDeviceEndSfdOperation();
  335. return PLC_DEVICE_PERSISTENCE_ERROR;
  336. }
  337. PlcSfdDirty = (PlcLastSfdLoadResult == PLSR_PERSISTENCE_OK) ? 0U : 1U;
  338. PlcDeviceEndSfdOperation();
  339. return PLC_DEVICE_OK;
  340. }
  341. PLC_DEVICE_RESULT PlcDeviceSaveSfd(void)
  342. {
  343. PLSR_PERSISTENCE_RESULT result;
  344. if (PlcDeviceBeginSfdOperation() == 0U)
  345. {
  346. return PLC_DEVICE_BUSY;
  347. }
  348. if (PlcSfdDirty == 0U)
  349. {
  350. PlcDeviceEndSfdOperation();
  351. return PLC_DEVICE_OK;
  352. }
  353. result = PlsrPersistenceSaveSfd(&PlcSfdData);
  354. if (result != PLSR_PERSISTENCE_OK)
  355. {
  356. PlcDeviceEndSfdOperation();
  357. return PLC_DEVICE_PERSISTENCE_ERROR;
  358. }
  359. PlcSfdDirty = 0U;
  360. PlcDeviceEndSfdOperation();
  361. return PLC_DEVICE_OK;
  362. }
  363. PLC_DEVICE_RESULT PlcDeviceResetSfdDefaults(void)
  364. {
  365. PLSR_PERSISTENCE_RESULT result;
  366. if (PlcDeviceBeginSfdOperation() == 0U)
  367. {
  368. return PLC_DEVICE_BUSY;
  369. }
  370. result = PlsrPersistenceEraseSfd();
  371. if (result != PLSR_PERSISTENCE_OK)
  372. {
  373. PlcDeviceEndSfdOperation();
  374. return PLC_DEVICE_PERSISTENCE_ERROR;
  375. }
  376. PlcLastSfdLoadResult = PlsrPersistenceLoadSfd(&PlcSfdData);
  377. if (PlcLastSfdLoadResult != PLSR_PERSISTENCE_DEFAULTED)
  378. {
  379. PlcDeviceEndSfdOperation();
  380. return PLC_DEVICE_PERSISTENCE_ERROR;
  381. }
  382. PlcSfdDirty = 1U;
  383. PlcDeviceEndSfdOperation();
  384. return PLC_DEVICE_OK;
  385. }
  386. PLC_DEVICE_RESULT PlcDeviceReadSm(uint16_t address, uint8_t *state)
  387. {
  388. uint8_t axis;
  389. uint8_t mask;
  390. PLC_DEVICE_RESULT result;
  391. if (state == NULL)
  392. {
  393. return PLC_DEVICE_NULL_POINTER;
  394. }
  395. result = PlcDeviceResolveSm(address, &axis, &mask);
  396. if (result != PLC_DEVICE_OK)
  397. {
  398. return result;
  399. }
  400. *state = ((PlcSmFlags[axis] & mask) != 0U) ? 1U : 0U;
  401. return PLC_DEVICE_OK;
  402. }
  403. PLC_DEVICE_RESULT PlcDeviceWriteSm(uint16_t address, uint8_t state)
  404. {
  405. uint8_t axis;
  406. uint8_t mask;
  407. PLC_DEVICE_RESULT result;
  408. (void)state;
  409. result = PlcDeviceResolveSm(address, &axis, &mask);
  410. return (result == PLC_DEVICE_OK) ? PLC_DEVICE_READ_ONLY : result;
  411. }
  412. PLC_DEVICE_RESULT PlcDevicePublishSm(uint8_t axis,
  413. uint8_t pulseActive,
  414. uint8_t direction)
  415. {
  416. uint8_t flags = 0U;
  417. uint32_t interruptState;
  418. if (axis >= PLSR_AXIS_COUNT)
  419. {
  420. return PLC_DEVICE_INVALID_ARGUMENT;
  421. }
  422. if (pulseActive != 0U)
  423. {
  424. flags |= PLC_SM_PULSE_ACTIVE_MASK;
  425. }
  426. if (direction != 0U)
  427. {
  428. flags |= PLC_SM_DIRECTION_MASK;
  429. }
  430. interruptState = PlcDeviceEnterCritical();
  431. if ((pulseActive != 0U) && (PlcSfdOperationActive != 0U))
  432. {
  433. PlcDeviceExitCritical(interruptState);
  434. return PLC_DEVICE_BUSY;
  435. }
  436. PlcSmFlags[axis] = flags;
  437. PlcDeviceExitCritical(interruptState);
  438. return PLC_DEVICE_OK;
  439. }
  440. PLC_DEVICE_RESULT PlcDeviceReadSd(uint16_t address, int32_t *value)
  441. {
  442. int32_t *source;
  443. if (value == NULL)
  444. {
  445. return PLC_DEVICE_NULL_POINTER;
  446. }
  447. source = PlcDeviceResolveSd(address, NULL, NULL);
  448. if (source == NULL)
  449. {
  450. return PLC_DEVICE_INVALID_ADDRESS;
  451. }
  452. *value = *source;
  453. return PLC_DEVICE_OK;
  454. }
  455. PLC_DEVICE_RESULT PlcDeviceWriteSd(uint16_t address, int32_t value)
  456. {
  457. (void)value;
  458. return (PlcDeviceResolveSd(address, NULL, NULL) != NULL)
  459. ? PLC_DEVICE_READ_ONLY
  460. : PLC_DEVICE_INVALID_ADDRESS;
  461. }
  462. PLC_DEVICE_RESULT PlcDevicePublishSd(uint8_t axis,
  463. uint8_t item,
  464. int32_t value)
  465. {
  466. if ((axis >= PLSR_AXIS_COUNT) || (item >= PLSR_SD_AXIS_ITEM_COUNT))
  467. {
  468. return PLC_DEVICE_INVALID_ARGUMENT;
  469. }
  470. PlcSdRuntime[axis][item] = value;
  471. return PLC_DEVICE_OK;
  472. }
  473. PLC_DEVICE_RESULT PlcDeviceGetEventAddress(uint8_t axis,
  474. uint16_t segmentNumber,
  475. uint16_t *eventAddress)
  476. {
  477. if (eventAddress == NULL)
  478. {
  479. return PLC_DEVICE_NULL_POINTER;
  480. }
  481. if ((axis >= PLSR_AXIS_COUNT) || (segmentNumber == 0U)
  482. || (segmentNumber > PLSR_EVENT_AXIS_ITEM_COUNT))
  483. {
  484. return PLC_DEVICE_INVALID_ARGUMENT;
  485. }
  486. *eventAddress = (uint16_t)(PlsrAxisAddressMap[axis].eventBase
  487. + segmentNumber - 1U);
  488. return PLC_DEVICE_OK;
  489. }
  490. uint8_t PlcDeviceIsHsdDirty(void)
  491. {
  492. return PlcHsdDirty;
  493. }
  494. uint8_t PlcDeviceIsSfdDirty(void)
  495. {
  496. return PlcSfdDirty;
  497. }
  498. PLSR_PERSISTENCE_RESULT PlcDeviceGetLastHsdLoadResult(void)
  499. {
  500. return PlcLastHsdLoadResult;
  501. }
  502. PLSR_PERSISTENCE_RESULT PlcDeviceGetLastSfdLoadResult(void)
  503. {
  504. return PlcLastSfdLoadResult;
  505. }