esp_modbus_slave.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /* Copyright 2018 Espressif Systems (Shanghai) PTE LTD
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include "esp_err.h" // for esp_err_t
  16. #include "sdkconfig.h" // for KConfig defines
  17. #include "mbc_slave.h" // for slave private type definitions
  18. #include "esp_modbus_common.h" // for common defines
  19. #include "esp_modbus_slave.h" // for public slave defines
  20. #include "esp_modbus_callbacks.h" // for modbus callbacks function pointers declaration
  21. #include "mbc_serial_slave.h" // for create function of serial port
  22. #ifdef CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT
  23. #define MB_ID_BYTE0(id) ((uint8_t)(id))
  24. #define MB_ID_BYTE1(id) ((uint8_t)(((uint16_t)(id) >> 8) & 0xFF))
  25. #define MB_ID_BYTE2(id) ((uint8_t)(((uint32_t)(id) >> 16) & 0xFF))
  26. #define MB_ID_BYTE3(id) ((uint8_t)(((uint32_t)(id) >> 24) & 0xFF))
  27. #define MB_CONTROLLER_SLAVE_ID (CONFIG_FMB_CONTROLLER_SLAVE_ID)
  28. #define MB_SLAVE_ID_SHORT (MB_ID_BYTE3(CONFIG_FMB_CONTROLLER_SLAVE_ID))
  29. // Slave ID constant
  30. static uint8_t mb_slave_id[] = { MB_ID_BYTE0(MB_CONTROLLER_SLAVE_ID),
  31. MB_ID_BYTE1(MB_CONTROLLER_SLAVE_ID),
  32. MB_ID_BYTE2(MB_CONTROLLER_SLAVE_ID) };
  33. #endif
  34. // Common interface pointer for slave port
  35. static mb_slave_interface_t* slave_interface_ptr = NULL;
  36. /**
  37. * Initialization of Modbus slave controller
  38. */
  39. esp_err_t mbc_slave_init(mb_port_type_t port_type, void** handler)
  40. {
  41. void* port_handler = NULL;
  42. esp_err_t error = ESP_ERR_NOT_SUPPORTED;
  43. switch(port_type)
  44. {
  45. case MB_PORT_SERIAL_SLAVE:
  46. // Call constructor function of actual port implementation
  47. error = mbc_serial_slave_create(port_type, &port_handler);
  48. break;
  49. case MB_PORT_TCP_SLAVE:
  50. // Not yet supported
  51. //error = mbc_tcp_slave_create(port_type, &port_handler);
  52. return ESP_ERR_NOT_SUPPORTED;
  53. default:
  54. return ESP_ERR_NOT_SUPPORTED;
  55. }
  56. MB_SLAVE_CHECK((port_handler != NULL),
  57. ESP_ERR_INVALID_STATE,
  58. "Slave interface initialization failure, error=(0x%x), port type=(0x%x).",
  59. error, (uint16_t)port_type);
  60. if ((port_handler != NULL) && (error == ESP_OK)) {
  61. slave_interface_ptr = (mb_slave_interface_t*) port_handler;
  62. *handler = port_handler;
  63. }
  64. return error;
  65. }
  66. /**
  67. * Modbus controller destroy function
  68. */
  69. esp_err_t mbc_slave_destroy(void)
  70. {
  71. esp_err_t error = ESP_OK;
  72. // Is initialization done?
  73. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  74. ESP_ERR_INVALID_STATE,
  75. "Slave interface is not correctly initialized.");
  76. // Check if interface has been initialized
  77. MB_SLAVE_CHECK((slave_interface_ptr->destroy != NULL),
  78. ESP_ERR_INVALID_STATE,
  79. "Slave interface is not correctly initialized.");
  80. // Call the slave port destroy function
  81. error = slave_interface_ptr->destroy();
  82. MB_SLAVE_CHECK((error == ESP_OK),
  83. ESP_ERR_INVALID_STATE,
  84. "SERIAL slave destroy failure error=(0x%x).", error);
  85. return error;
  86. }
  87. /**
  88. * Setup Modbus controller parameters
  89. */
  90. esp_err_t mbc_slave_setup(void* comm_info)
  91. {
  92. esp_err_t error = ESP_OK;
  93. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  94. ESP_ERR_INVALID_STATE,
  95. "Slave interface is not correctly initialized.");
  96. MB_SLAVE_CHECK((slave_interface_ptr->setup != NULL),
  97. ESP_ERR_INVALID_STATE,
  98. "Slave interface is not correctly initialized.");
  99. error = slave_interface_ptr->setup(comm_info);
  100. MB_SLAVE_CHECK((error == ESP_OK),
  101. ESP_ERR_INVALID_STATE,
  102. "SERIAL slave setup failure error=(0x%x).", error);
  103. return error;
  104. }
  105. /**
  106. * Start Modbus controller start function
  107. */
  108. esp_err_t mbc_slave_start(void)
  109. {
  110. esp_err_t error = ESP_OK;
  111. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  112. ESP_ERR_INVALID_STATE,
  113. "Slave interface is not correctly initialized.");
  114. MB_SLAVE_CHECK((slave_interface_ptr->start != NULL),
  115. ESP_ERR_INVALID_STATE,
  116. "Slave interface is not correctly initialized.");
  117. #ifdef CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT
  118. // Set the slave ID if the KConfig option is selected
  119. eMBErrorCode status = eMBSetSlaveID(MB_SLAVE_ID_SHORT, TRUE, (UCHAR*)mb_slave_id, sizeof(mb_slave_id));
  120. MB_SLAVE_CHECK((status == MB_ENOERR), ESP_ERR_INVALID_STATE, "mb stack set slave ID failure.");
  121. #endif
  122. error = slave_interface_ptr->start();
  123. MB_SLAVE_CHECK((error == ESP_OK),
  124. error, "SERIAL slave start failure error=(0x%x).", error);
  125. return error;
  126. }
  127. /**
  128. * Blocking function to get event on parameter group change for application task
  129. */
  130. mb_event_group_t mbc_slave_check_event(mb_event_group_t group)
  131. {
  132. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  133. MB_EVENT_NO_EVENTS,
  134. "Slave interface is not correctly initialized.");
  135. MB_SLAVE_CHECK((slave_interface_ptr->check_event != NULL),
  136. MB_EVENT_NO_EVENTS,
  137. "Slave interface is not correctly initialized.");
  138. mb_event_group_t event = slave_interface_ptr->check_event(group);
  139. return event;
  140. }
  141. /**
  142. * Function to get notification about parameter change from application task
  143. */
  144. esp_err_t mbc_slave_get_param_info(mb_param_info_t* reg_info, uint32_t timeout)
  145. {
  146. esp_err_t error = ESP_OK;
  147. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  148. ESP_ERR_INVALID_STATE,
  149. "Slave interface is not correctly initialized.");
  150. MB_SLAVE_CHECK((slave_interface_ptr->get_param_info != NULL),
  151. ESP_ERR_INVALID_STATE,
  152. "Slave interface is not correctly initialized.");
  153. error = slave_interface_ptr->get_param_info(reg_info, timeout);
  154. MB_SLAVE_CHECK((error == ESP_OK),
  155. error, "SERIAL slave get parameter info failure error=(0x%x).", error);
  156. return error;
  157. }
  158. /**
  159. * Function to set area descriptors for modbus parameters
  160. */
  161. esp_err_t mbc_slave_set_descriptor(mb_register_area_descriptor_t descr_data)
  162. {
  163. esp_err_t error = ESP_OK;
  164. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  165. ESP_ERR_INVALID_STATE,
  166. "Slave interface is not correctly initialized.");
  167. MB_SLAVE_CHECK((slave_interface_ptr->set_descriptor != NULL),
  168. ESP_ERR_INVALID_STATE,
  169. "Slave interface is not correctly initialized.");
  170. error = slave_interface_ptr->set_descriptor(descr_data);
  171. MB_SLAVE_CHECK((error == ESP_OK),
  172. error, "SERIAL slave set descriptor failure error=(0x%x).", error);
  173. return error;
  174. }
  175. /**
  176. * Below are stack callback functions to read/write registers
  177. */
  178. eMBErrorCode eMBRegDiscreteCB(UCHAR * pucRegBuffer, USHORT usAddress,
  179. USHORT usNDiscrete)
  180. {
  181. eMBErrorCode error = MB_ENOERR;
  182. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  183. ESP_ERR_INVALID_STATE,
  184. "Slave interface is not correctly initialized.");
  185. MB_SLAVE_CHECK((slave_interface_ptr->slave_reg_cb_discrete != NULL),
  186. error,
  187. "Slave interface is not correctly initialized.");
  188. error = slave_interface_ptr->slave_reg_cb_discrete(pucRegBuffer, usAddress, usNDiscrete);
  189. return error;
  190. }
  191. eMBErrorCode eMBRegCoilsCB(UCHAR* pucRegBuffer, USHORT usAddress,
  192. USHORT usNCoils, eMBRegisterMode eMode)
  193. {
  194. eMBErrorCode error = MB_ENOERR;
  195. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  196. ESP_ERR_INVALID_STATE,
  197. "Slave interface is not correctly initialized.");
  198. MB_SLAVE_CHECK((slave_interface_ptr->slave_reg_cb_coils != NULL),
  199. ESP_ERR_INVALID_STATE,
  200. "Slave interface is not correctly initialized.");
  201. error = slave_interface_ptr->slave_reg_cb_coils(pucRegBuffer, usAddress,
  202. usNCoils, eMode);
  203. return error;
  204. }
  205. eMBErrorCode eMBRegHoldingCB(UCHAR * pucRegBuffer, USHORT usAddress,
  206. USHORT usNRegs, eMBRegisterMode eMode)
  207. {
  208. eMBErrorCode error = MB_ENOERR;
  209. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  210. ESP_ERR_INVALID_STATE,
  211. "Slave interface is not correctly initialized.");
  212. MB_SLAVE_CHECK((slave_interface_ptr->slave_reg_cb_holding != NULL),
  213. ESP_ERR_INVALID_STATE,
  214. "Slave interface is not correctly initialized.");
  215. error = slave_interface_ptr->slave_reg_cb_holding(pucRegBuffer, usAddress,
  216. usNRegs, eMode);
  217. return error;
  218. }
  219. eMBErrorCode eMBRegInputCB(UCHAR * pucRegBuffer, USHORT usAddress,
  220. USHORT usNRegs)
  221. {
  222. eMBErrorCode error = MB_ENOERR;
  223. MB_SLAVE_CHECK((slave_interface_ptr != NULL),
  224. ESP_ERR_INVALID_STATE,
  225. "Slave interface is not correctly initialized.");
  226. MB_SLAVE_CHECK((slave_interface_ptr->slave_reg_cb_input != NULL),
  227. ESP_ERR_INVALID_STATE,
  228. "Slave interface is not correctly initialized.");
  229. error = slave_interface_ptr->slave_reg_cb_input(pucRegBuffer, usAddress, usNRegs);
  230. return error;
  231. }