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

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