Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

593 linhas
16 KiB

  1. #include "modbus_rtu_slave.h"
  2. #include "plsr.h"
  3. #include <string.h>
  4. #define MODBUS_RTU_ADU_SIZE_MAX (256U)
  5. #define MODBUS_RTU_BITS_PER_CHAR (11UL)
  6. #define MODBUS_RTU_HIGH_BAUD_LIMIT (19200UL)
  7. #define MODBUS_RTU_T15_US (750UL)
  8. #define MODBUS_RTU_T35_US (1750UL)
  9. #define MODBUS_BROADCAST_ADDRESS (0U)
  10. #define MODBUS_SLAVE_ADDRESS_MAX (247U)
  11. #define MODBUS_FC_READ_HOLDING (0x03U)
  12. #define MODBUS_FC_WRITE_SINGLE (0x06U)
  13. #define MODBUS_FC_WRITE_MULTIPLE (0x10U)
  14. #define MODBUS_EX_ILLEGAL_FUNCTION (0x01U)
  15. #define MODBUS_EX_ILLEGAL_ADDRESS (0x02U)
  16. #define MODBUS_EX_ILLEGAL_VALUE (0x03U)
  17. #define MODBUS_EX_SERVER_FAILURE (0x04U)
  18. #define MODBUS_EX_SERVER_BUSY (0x06U)
  19. #define MODBUS_READ_REGISTERS_MAX (125U)
  20. #define MODBUS_WRITE_REGISTERS_MAX (123U)
  21. static UART_HandleTypeDef *ModbusUart;
  22. static uint8_t ModbusSlaveAddress;
  23. static uint8_t ModbusRxDmaBuffer[MODBUS_RTU_ADU_SIZE_MAX];
  24. static uint8_t ModbusRxAssemblyBuffer[MODBUS_RTU_ADU_SIZE_MAX];
  25. static uint8_t ModbusRxFrame[MODBUS_RTU_ADU_SIZE_MAX];
  26. static uint8_t ModbusTxFrame[MODBUS_RTU_ADU_SIZE_MAX];
  27. static uint16_t ModbusRegisterScratch[MODBUS_READ_REGISTERS_MAX];
  28. static volatile uint16_t ModbusRxAssemblyLength;
  29. static volatile uint8_t ModbusRxAssemblyInvalid;
  30. static volatile uint32_t ModbusRxLastByteCycle;
  31. static volatile uint16_t ModbusRxFrameLength;
  32. static volatile uint8_t ModbusRxFrameReady;
  33. static volatile uint8_t ModbusTxBusy;
  34. static uint32_t ModbusRtuCharCycles;
  35. static uint32_t ModbusRtuT15Cycles;
  36. static uint32_t ModbusRtuT35Cycles;
  37. static HAL_StatusTypeDef ModbusStartReceive(void);
  38. static uint32_t ModbusEnterCritical(void)
  39. {
  40. uint32_t primask = __get_PRIMASK();
  41. __disable_irq();
  42. __DMB();
  43. return primask;
  44. }
  45. static void ModbusExitCritical(uint32_t primask)
  46. {
  47. __DMB();
  48. __set_PRIMASK(primask);
  49. }
  50. static uint16_t ModbusCrc16(const uint8_t *data, uint16_t length)
  51. {
  52. uint16_t crc = 0xFFFFU;
  53. uint16_t index;
  54. uint8_t bit;
  55. for (index = 0U; index < length; index++)
  56. {
  57. crc ^= data[index];
  58. for (bit = 0U; bit < 8U; bit++)
  59. {
  60. if ((crc & 1U) != 0U)
  61. {
  62. crc = (uint16_t)((crc >> 1U) ^ 0xA001U);
  63. }
  64. else
  65. {
  66. crc >>= 1U;
  67. }
  68. }
  69. }
  70. return crc;
  71. }
  72. static uint16_t ModbusGetU16Be(const uint8_t *data)
  73. {
  74. return (uint16_t)(((uint16_t)data[0] << 8U) | data[1]);
  75. }
  76. static void ModbusRtuTimingInit(uint32_t baudRate)
  77. {
  78. uint64_t coreClock = SystemCoreClock;
  79. uint64_t charCycleNumerator = coreClock * MODBUS_RTU_BITS_PER_CHAR;
  80. CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  81. DWT->CYCCNT = 0U;
  82. DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
  83. ModbusRtuCharCycles =
  84. (uint32_t)((charCycleNumerator + baudRate - 1UL) / baudRate);
  85. if (ModbusRtuCharCycles == 0UL)
  86. {
  87. ModbusRtuCharCycles = 1UL;
  88. }
  89. if (baudRate > MODBUS_RTU_HIGH_BAUD_LIMIT)
  90. {
  91. ModbusRtuT15Cycles = (uint32_t)(
  92. (coreClock * MODBUS_RTU_T15_US + 999999UL) / 1000000UL);
  93. ModbusRtuT35Cycles = (uint32_t)(
  94. (coreClock * MODBUS_RTU_T35_US + 999999UL) / 1000000UL);
  95. }
  96. else
  97. {
  98. ModbusRtuT15Cycles =
  99. (uint32_t)(((uint64_t)ModbusRtuCharCycles * 3UL + 1UL) / 2UL);
  100. ModbusRtuT35Cycles =
  101. (uint32_t)(((uint64_t)ModbusRtuCharCycles * 7UL + 1UL) / 2UL);
  102. }
  103. }
  104. static void ModbusRxAssemblyFinalize(void)
  105. {
  106. uint16_t length = ModbusRxAssemblyLength;
  107. if (length == 0U)
  108. {
  109. return;
  110. }
  111. if ((ModbusRxAssemblyInvalid == 0U) && (ModbusRxFrameReady == 0U))
  112. {
  113. (void)memcpy(ModbusRxFrame, ModbusRxAssemblyBuffer, length);
  114. ModbusRxFrameLength = length;
  115. ModbusRxFrameReady = 1U;
  116. }
  117. ModbusRxAssemblyLength = 0U;
  118. ModbusRxAssemblyInvalid = 0U;
  119. }
  120. static HAL_StatusTypeDef ModbusStartReceive(void)
  121. {
  122. HAL_StatusTypeDef status;
  123. if ((ModbusUart == NULL) || (ModbusTxBusy != 0U))
  124. {
  125. return HAL_BUSY;
  126. }
  127. status = HAL_UARTEx_ReceiveToIdle_DMA(ModbusUart,
  128. ModbusRxDmaBuffer,
  129. sizeof(ModbusRxDmaBuffer));
  130. if (status == HAL_OK)
  131. {
  132. __HAL_DMA_DISABLE_IT(ModbusUart->hdmarx, DMA_IT_HT);
  133. }
  134. return status;
  135. }
  136. static void ModbusTryFinalizeReceive(void)
  137. {
  138. uint32_t now;
  139. uint32_t primask;
  140. uint8_t restartReceive;
  141. if ((ModbusUart == NULL) || (ModbusRxAssemblyLength == 0U))
  142. {
  143. return;
  144. }
  145. if (((ModbusUart->Instance->CR3 & USART_CR3_DMAR) != 0U)
  146. && (__HAL_DMA_GET_COUNTER(ModbusUart->hdmarx)
  147. < MODBUS_RTU_ADU_SIZE_MAX))
  148. {
  149. return;
  150. }
  151. now = DWT->CYCCNT;
  152. if ((uint32_t)(now - ModbusRxLastByteCycle) < ModbusRtuT35Cycles)
  153. {
  154. return;
  155. }
  156. if (HAL_UART_AbortReceive(ModbusUart) != HAL_OK)
  157. {
  158. primask = ModbusEnterCritical();
  159. ModbusRxAssemblyLength = 0U;
  160. ModbusRxAssemblyInvalid = 0U;
  161. ModbusExitCritical(primask);
  162. (void)HAL_UART_Abort(ModbusUart);
  163. (void)ModbusStartReceive();
  164. return;
  165. }
  166. primask = ModbusEnterCritical();
  167. ModbusRxAssemblyFinalize();
  168. restartReceive = (ModbusRxFrameReady == 0U) ? 1U : 0U;
  169. ModbusExitCritical(primask);
  170. if (restartReceive != 0U)
  171. {
  172. (void)ModbusStartReceive();
  173. }
  174. }
  175. static void ModbusAppendCrc(uint8_t *frame, uint16_t payloadLength)
  176. {
  177. uint16_t crc = ModbusCrc16(frame, payloadLength);
  178. frame[payloadLength] = (uint8_t)(crc & 0x00FFU);
  179. frame[payloadLength + 1U] = (uint8_t)(crc >> 8U);
  180. }
  181. static uint16_t ModbusBuildException(uint8_t function, uint8_t exception)
  182. {
  183. ModbusTxFrame[0] = ModbusSlaveAddress;
  184. ModbusTxFrame[1] = (uint8_t)(function | 0x80U);
  185. ModbusTxFrame[2] = exception;
  186. ModbusAppendCrc(ModbusTxFrame, 3U);
  187. return 5U;
  188. }
  189. static uint16_t ModbusBuildPlsrException(uint8_t function,
  190. PLSR_MB_RESULT result,
  191. uint8_t isBroadcast)
  192. {
  193. uint8_t exception;
  194. if (isBroadcast != 0U)
  195. {
  196. return 0U;
  197. }
  198. switch (result)
  199. {
  200. case PLSR_MB_NOT_HANDLED:
  201. case PLSR_MB_ILLEGAL_ADDRESS:
  202. exception = MODBUS_EX_ILLEGAL_ADDRESS;
  203. break;
  204. case PLSR_MB_ILLEGAL_VALUE:
  205. exception = MODBUS_EX_ILLEGAL_VALUE;
  206. break;
  207. case PLSR_MB_DEVICE_BUSY:
  208. exception = MODBUS_EX_SERVER_BUSY;
  209. break;
  210. case PLSR_MB_SERVER_FAILURE:
  211. default:
  212. exception = MODBUS_EX_SERVER_FAILURE;
  213. break;
  214. }
  215. return ModbusBuildException(function, exception);
  216. }
  217. static uint16_t ModbusProcessReadHolding(const uint8_t *request,
  218. uint16_t requestLength)
  219. {
  220. uint16_t start;
  221. uint16_t quantity;
  222. uint16_t index;
  223. PLSR_MB_RESULT result;
  224. if (requestLength != 8U)
  225. {
  226. return ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_VALUE);
  227. }
  228. start = ModbusGetU16Be(&request[2]);
  229. quantity = ModbusGetU16Be(&request[4]);
  230. if ((quantity == 0U) || (quantity > MODBUS_READ_REGISTERS_MAX))
  231. {
  232. return ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_VALUE);
  233. }
  234. result = PlsrModbusReadHolding(start, quantity, ModbusRegisterScratch);
  235. if (result != PLSR_MB_OK)
  236. {
  237. return ModbusBuildPlsrException(request[1], result, 0U);
  238. }
  239. ModbusTxFrame[0] = ModbusSlaveAddress;
  240. ModbusTxFrame[1] = MODBUS_FC_READ_HOLDING;
  241. ModbusTxFrame[2] = (uint8_t)(quantity * 2U);
  242. for (index = 0U; index < quantity; index++)
  243. {
  244. ModbusTxFrame[3U + index * 2U] =
  245. (uint8_t)(ModbusRegisterScratch[index] >> 8U);
  246. ModbusTxFrame[4U + index * 2U] =
  247. (uint8_t)(ModbusRegisterScratch[index] & 0x00FFU);
  248. }
  249. ModbusAppendCrc(ModbusTxFrame, (uint16_t)(3U + quantity * 2U));
  250. return (uint16_t)(5U + quantity * 2U);
  251. }
  252. static uint16_t ModbusProcessWriteSingle(const uint8_t *request,
  253. uint16_t requestLength,
  254. uint8_t isBroadcast)
  255. {
  256. uint16_t address;
  257. uint16_t value;
  258. PLSR_MB_RESULT result;
  259. if (requestLength != 8U)
  260. {
  261. return (isBroadcast != 0U)
  262. ? 0U
  263. : ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_VALUE);
  264. }
  265. address = ModbusGetU16Be(&request[2]);
  266. value = ModbusGetU16Be(&request[4]);
  267. result = PlsrModbusWriteHolding(address, 1U, &value);
  268. if (result != PLSR_MB_OK)
  269. {
  270. return ModbusBuildPlsrException(request[1], result, isBroadcast);
  271. }
  272. if (isBroadcast != 0U)
  273. {
  274. return 0U;
  275. }
  276. (void)memcpy(ModbusTxFrame, request, 6U);
  277. ModbusAppendCrc(ModbusTxFrame, 6U);
  278. return 8U;
  279. }
  280. static uint16_t ModbusProcessWriteMultiple(const uint8_t *request,
  281. uint16_t requestLength,
  282. uint8_t isBroadcast)
  283. {
  284. uint16_t start;
  285. uint16_t quantity;
  286. uint16_t byteCount;
  287. uint16_t index;
  288. PLSR_MB_RESULT result;
  289. if (requestLength < 9U)
  290. {
  291. return (isBroadcast != 0U)
  292. ? 0U
  293. : ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_VALUE);
  294. }
  295. start = ModbusGetU16Be(&request[2]);
  296. quantity = ModbusGetU16Be(&request[4]);
  297. byteCount = request[6];
  298. if ((quantity == 0U)
  299. || (quantity > MODBUS_WRITE_REGISTERS_MAX)
  300. || (byteCount != (uint16_t)(quantity * 2U))
  301. || (requestLength != (uint16_t)(9U + byteCount)))
  302. {
  303. return (isBroadcast != 0U)
  304. ? 0U
  305. : ModbusBuildException(request[1], MODBUS_EX_ILLEGAL_VALUE);
  306. }
  307. for (index = 0U; index < quantity; index++)
  308. {
  309. ModbusRegisterScratch[index] =
  310. ModbusGetU16Be(&request[7U + index * 2U]);
  311. }
  312. result = PlsrModbusWriteHolding(start, quantity, ModbusRegisterScratch);
  313. if (result != PLSR_MB_OK)
  314. {
  315. return ModbusBuildPlsrException(request[1], result, isBroadcast);
  316. }
  317. if (isBroadcast != 0U)
  318. {
  319. return 0U;
  320. }
  321. ModbusTxFrame[0] = ModbusSlaveAddress;
  322. ModbusTxFrame[1] = MODBUS_FC_WRITE_MULTIPLE;
  323. (void)memcpy(&ModbusTxFrame[2], &request[2], 4U);
  324. ModbusAppendCrc(ModbusTxFrame, 6U);
  325. return 8U;
  326. }
  327. static uint16_t ModbusProcessRequest(const uint8_t *request,
  328. uint16_t requestLength)
  329. {
  330. uint16_t receivedCrc;
  331. uint8_t isBroadcast;
  332. if (requestLength < 4U)
  333. {
  334. return 0U;
  335. }
  336. receivedCrc = (uint16_t)(request[requestLength - 2U]
  337. | ((uint16_t)request[requestLength - 1U] << 8U));
  338. if (ModbusCrc16(request, (uint16_t)(requestLength - 2U)) != receivedCrc)
  339. {
  340. return 0U;
  341. }
  342. if ((request[0] != ModbusSlaveAddress)
  343. && (request[0] != MODBUS_BROADCAST_ADDRESS))
  344. {
  345. return 0U;
  346. }
  347. isBroadcast = (request[0] == MODBUS_BROADCAST_ADDRESS) ? 1U : 0U;
  348. switch (request[1])
  349. {
  350. case MODBUS_FC_READ_HOLDING:
  351. return (isBroadcast != 0U)
  352. ? 0U
  353. : ModbusProcessReadHolding(request, requestLength);
  354. case MODBUS_FC_WRITE_SINGLE:
  355. return ModbusProcessWriteSingle(request,
  356. requestLength,
  357. isBroadcast);
  358. case MODBUS_FC_WRITE_MULTIPLE:
  359. return ModbusProcessWriteMultiple(request,
  360. requestLength,
  361. isBroadcast);
  362. default:
  363. return (isBroadcast != 0U)
  364. ? 0U
  365. : ModbusBuildException(request[1],
  366. MODBUS_EX_ILLEGAL_FUNCTION);
  367. }
  368. }
  369. HAL_StatusTypeDef ModbusSlaveInit(UART_HandleTypeDef *huart,
  370. uint8_t slaveAddress)
  371. {
  372. if ((huart == NULL)
  373. || (huart->Instance == NULL)
  374. || (huart->hdmarx == NULL)
  375. || (huart->hdmatx == NULL)
  376. || (huart->Init.BaudRate == 0UL)
  377. || (slaveAddress == MODBUS_BROADCAST_ADDRESS)
  378. || (slaveAddress > MODBUS_SLAVE_ADDRESS_MAX))
  379. {
  380. return HAL_ERROR;
  381. }
  382. ModbusUart = huart;
  383. ModbusSlaveAddress = slaveAddress;
  384. ModbusRxAssemblyLength = 0U;
  385. ModbusRxAssemblyInvalid = 0U;
  386. ModbusRxLastByteCycle = 0UL;
  387. ModbusRxFrameLength = 0U;
  388. ModbusRxFrameReady = 0U;
  389. ModbusTxBusy = 0U;
  390. ModbusRtuTimingInit(huart->Init.BaudRate);
  391. return ModbusStartReceive();
  392. }
  393. void ModbusSlavePoll(void)
  394. {
  395. uint16_t responseLength;
  396. uint32_t primask;
  397. HAL_StatusTypeDef txStatus = HAL_OK;
  398. if (ModbusUart == NULL)
  399. {
  400. return;
  401. }
  402. ModbusTryFinalizeReceive();
  403. if ((ModbusRxFrameReady == 0U) || (ModbusTxBusy != 0U))
  404. {
  405. return;
  406. }
  407. responseLength = ModbusProcessRequest(ModbusRxFrame,
  408. ModbusRxFrameLength);
  409. primask = ModbusEnterCritical();
  410. ModbusRxFrameReady = 0U;
  411. if (responseLength > 0U)
  412. {
  413. ModbusTxBusy = 1U;
  414. txStatus = HAL_UART_Transmit_DMA(ModbusUart,
  415. ModbusTxFrame,
  416. responseLength);
  417. if (txStatus != HAL_OK)
  418. {
  419. ModbusTxBusy = 0U;
  420. }
  421. }
  422. ModbusExitCritical(primask);
  423. if ((responseLength == 0U) || (txStatus != HAL_OK))
  424. {
  425. (void)ModbusStartReceive();
  426. }
  427. }
  428. void ModbusSlaveOnRxEvent(UART_HandleTypeDef *huart, uint16_t size)
  429. {
  430. HAL_UART_RxEventTypeTypeDef eventType;
  431. uint32_t now;
  432. uint32_t lastByteCycle;
  433. uint32_t firstByteCycle;
  434. uint32_t chunkCycles;
  435. uint32_t interChunkGap;
  436. if ((ModbusUart == NULL) || (huart != ModbusUart))
  437. {
  438. return;
  439. }
  440. eventType = HAL_UARTEx_GetRxEventType(huart);
  441. if (eventType == HAL_UART_RXEVENT_HT)
  442. {
  443. return;
  444. }
  445. if ((size == 0U) || (size > MODBUS_RTU_ADU_SIZE_MAX))
  446. {
  447. ModbusRxAssemblyLength = 0U;
  448. ModbusRxAssemblyInvalid = 0U;
  449. (void)ModbusStartReceive();
  450. return;
  451. }
  452. now = DWT->CYCCNT;
  453. lastByteCycle = now;
  454. if (eventType == HAL_UART_RXEVENT_IDLE)
  455. {
  456. lastByteCycle -= ModbusRtuCharCycles;
  457. }
  458. chunkCycles = (uint32_t)((uint64_t)size * ModbusRtuCharCycles);
  459. firstByteCycle = lastByteCycle - chunkCycles;
  460. if (ModbusRxAssemblyLength > 0U)
  461. {
  462. interChunkGap = (uint32_t)(firstByteCycle
  463. - ModbusRxLastByteCycle);
  464. if (interChunkGap >= ModbusRtuT35Cycles)
  465. {
  466. ModbusRxAssemblyFinalize();
  467. }
  468. else if (interChunkGap > ModbusRtuT15Cycles)
  469. {
  470. ModbusRxAssemblyInvalid = 1U;
  471. }
  472. }
  473. if (size <= (uint16_t)(MODBUS_RTU_ADU_SIZE_MAX
  474. - ModbusRxAssemblyLength))
  475. {
  476. (void)memcpy(&ModbusRxAssemblyBuffer[ModbusRxAssemblyLength],
  477. ModbusRxDmaBuffer,
  478. size);
  479. ModbusRxAssemblyLength += size;
  480. }
  481. else
  482. {
  483. ModbusRxAssemblyInvalid = 1U;
  484. }
  485. ModbusRxLastByteCycle = lastByteCycle;
  486. (void)ModbusStartReceive();
  487. }
  488. void ModbusSlaveOnTxComplete(UART_HandleTypeDef *huart)
  489. {
  490. if ((ModbusUart == NULL) || (huart != ModbusUart))
  491. {
  492. return;
  493. }
  494. ModbusTxBusy = 0U;
  495. (void)ModbusStartReceive();
  496. }
  497. void ModbusSlaveOnUartError(UART_HandleTypeDef *huart)
  498. {
  499. if ((ModbusUart == NULL) || (huart != ModbusUart))
  500. {
  501. return;
  502. }
  503. ModbusTxBusy = 0U;
  504. ModbusRxAssemblyLength = 0U;
  505. ModbusRxAssemblyInvalid = 0U;
  506. ModbusRxFrameLength = 0U;
  507. ModbusRxFrameReady = 0U;
  508. (void)HAL_UART_Abort(huart);
  509. (void)ModbusStartReceive();
  510. }