modbus.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. #include "at32f403a_407.h"
  2. #include "common_config.h"
  3. #include "modbus.h"
  4. #include "update.h"
  5. #include "FreeRTOS.h"
  6. #include "task.h"
  7. #include "fr_timers.h"
  8. #include "mb.h"
  9. #include "mbport.h"
  10. #include "mbrtu.h"
  11. #include "tim_delay.h"
  12. #include "modbus_params.h"
  13. #include "common_gpio.h"
  14. #include "io_utils.h"
  15. #include "log.h"
  16. #include "log_api.h"
  17. #include "settings_api.h"
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdbool.h>
  21. #define REG_HOLDING_START ( 1 )
  22. #define REG_HOLDING_NREGS ( 5 )
  23. #undef DBG
  24. #define DBG if(1)
  25. static USHORT usRegHoldingStart = REG_HOLDING_START;
  26. extern UCHAR rcvAddress;
  27. //osThreadId modbus_task_handle;
  28. static void modbus_task(void *params);
  29. //osThreadId modbus_params_handle;
  30. static void modbus_params(void *params);
  31. TimerHandle_t settings_timer_handle;
  32. //osTimerId reset_timer_handle;
  33. //osTimerId settings_timer_handle;
  34. //osTimerId modbus_timer_handle;
  35. void cb_settings_timer(TimerHandle_t timer);
  36. mb_delay_action_t mb_action = MB_NO_ACTION;
  37. uint8_t new_slave_addr;
  38. bool mb_package_flag = false;
  39. //
  40. void mb_init(void)
  41. {
  42. uint32_t baud = 115200;
  43. eMBParity par = MB_PAR_NONE;
  44. UCHAR mb_addr = gpio_get_mbaddr();
  45. unsigned int stop_bits = 1;
  46. const UCHAR ucSlaveID[] = {0xAA, 0xBB, 0xCC};
  47. mb_init_params();
  48. mb_helper_tim_init(baud);
  49. //eMBInit(MB_RTU, mb_addr, 4, baud, par, stop_bits);
  50. settings_init_mb_port(mb_addr);
  51. eMBSetSlaveID(0x34, TRUE, ucSlaveID, 3);
  52. eMBEnable();
  53. xTaskCreate(modbus_task, "modbus_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
  54. xTaskCreate(modbus_params, "modbus_params", 4*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
  55. // Таймер для перехода в IAP
  56. update_create_timer();
  57. settings_timer_handle = xTimerCreate("reset_timer", 10000, pdFALSE, (void *)0, cb_settings_timer);
  58. #if 0
  59. osTimerDef(vResetTimer, modbus_reset);
  60. reset_timer_handle = osTimerCreate(osTimer(vResetTimer), osTimerOnce, NULL);
  61. osTimerDef(vSettingsTimer, settings_timer);
  62. settings_timer_handle = osTimerCreate(osTimer(vSettingsTimer), osTimerOnce, NULL);
  63. osTimerDef(vModbusTimer, modbus_port_timer);
  64. modbus_timer_handle = osTimerCreate(osTimer(vModbusTimer), osTimerOnce, NULL);
  65. #endif
  66. }
  67. //
  68. void modbus_task(void *params)
  69. {
  70. (void)params;
  71. for (;;)
  72. {
  73. eMBPoll();
  74. }
  75. }
  76. //
  77. void modbus_params(void *params)
  78. {
  79. for (;;)
  80. {
  81. if (mb_action != MB_NO_ACTION)
  82. {
  83. switch (mb_action)
  84. {
  85. // Установка нового адреса
  86. case MB_CHANGE_ADDR :
  87. //settings.com_settings.mb_addr = new_slave_addr;
  88. eMBSetSlaveAddr(new_slave_addr);
  89. break;
  90. case MB_PAS_OK :
  91. //set_sys_settings_flag = true;
  92. //osTimerStart(settings_timer_handle, 30000);
  93. xTimerStart(settings_timer_handle, 0);
  94. break;
  95. case MB_CHANGE_PORT_SETTINGS :
  96. #if 0
  97. osDelay(200);
  98. eMBRTUStop();
  99. settings_set_modbus_params(temp_modbus_port);
  100. settings_init_mb_port(settings.com_settings.mb_addr);
  101. MBDBG settings_print_modbus();
  102. eMBRTUStart();
  103. eMBEnable();
  104. mb_package_flag = false;
  105. osTimerStart(modbus_timer_handle, 9800);
  106. #endif
  107. break;
  108. // Полное восстановление дефолтных настроек
  109. case MB_DEF_SETTINGS :
  110. #if 0
  111. settings_set_default(true);
  112. settings_save();
  113. #endif
  114. break;
  115. // Частичное восстановление дефолтных настроек
  116. case MB_PART_DEF_SETTINGS :
  117. #if 0
  118. settings_set_default(false);
  119. settings_save();
  120. #endif
  121. break;
  122. case MB_SAVE_SETTINGS :
  123. #if 0
  124. settings_save();
  125. #endif
  126. break;
  127. case MB_SAVE_SYS_SETTINGS :
  128. #if 0
  129. if (set_sys_settings_flag) {
  130. memcpy(&sys_settings, &temp_sys_settings, sizeof(sys_settings));
  131. sys_settings_save();
  132. }
  133. #endif
  134. break;
  135. case MB_RESET :
  136. vTaskDelay(100);
  137. NVIC_SystemReset();
  138. break;
  139. default : break;
  140. }
  141. mb_action = MB_NO_ACTION;
  142. }
  143. vTaskDelay(10);
  144. }
  145. }
  146. // Отложенная перезагрузка в Bootloader
  147. void modbus_reset(void const * params)
  148. {
  149. #if 0
  150. MBDBG printf("Switch to bootloader!\r\n");
  151. rtc_set_load_mode(1);
  152. HAL_NVIC_SystemReset();
  153. #endif
  154. }
  155. // Запуск таймера для изменение настроек modbus
  156. void modbus_port_timer(void const * params)
  157. {
  158. #if 0
  159. eMBRTUStop();
  160. // Были транзакции по modbus с новыми настройками.
  161. // Нужно сохранить новые настройки.
  162. if (mb_package_flag)
  163. {
  164. settings.com_settings.mb_port = temp_modbus_port;
  165. settings_set_modbus_params(settings.com_settings.mb_port);
  166. settings_init_mb_port(settings.com_settings.mb_addr);
  167. settings_save();
  168. }
  169. // Нужно вернуть старые настройки
  170. else
  171. {
  172. temp_modbus_port = settings.com_settings.mb_port;
  173. settings_set_modbus_params(settings.com_settings.mb_port);
  174. settings_init_mb_port(settings.com_settings.mb_addr);
  175. }
  176. MBDBG settings_print_modbus();
  177. eMBRTUStart();
  178. eMBEnable();
  179. #endif
  180. }
  181. // ------------------------------------------------------------------- //
  182. // Modbus callback's
  183. // ------------------------------------------------------------------- //
  184. //
  185. // 65 (0x41) Read Input Registers
  186. eMBErrorCode
  187. eMBUpdateCB( UCHAR * pucFrame, USHORT * usLen)
  188. {
  189. eMBErrorCode eStatus = MB_ENOERR;
  190. mb_package_flag = true;
  191. // Команда перехода в bootloader.
  192. if (pucFrame[1] == 0x01) {
  193. update_tim_start();
  194. }
  195. return eStatus;
  196. }
  197. eMBErrorCode
  198. eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
  199. {
  200. return MB_ENOREG;
  201. }
  202. // 03 (0x03) Read Holding Registers
  203. // чтение N регистров управления и уставок
  204. // 16 (0x10) Write Multiple registers
  205. // запись N регистров управления и уставок (0x10)
  206. eMBErrorCode
  207. eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
  208. {
  209. eMBErrorCode eStatus = MB_ENOERR;
  210. int iRegIndex;
  211. mb_delay_action_t mb_act = MB_NO_ACTION;
  212. uint16_t regs_cnt = usNRegs;
  213. uint16_t index_param;
  214. uint8_t *ptr_buf = pucRegBuffer;
  215. uint16_t size;
  216. /*
  217. printf("usAddress: 0x%X\r\n", usAddress);
  218. printf("usNRegs: %u\r\n", usNRegs);
  219. printf("eMode: %u\r\n", eMode);
  220. printf("pucRegBuffer :%X\r\n", pucRegBuffer[0]);
  221. */
  222. save_mode_reset_cnt();
  223. mb_package_flag = true;
  224. iRegIndex = (int)(usAddress - usRegHoldingStart);
  225. #if 1
  226. switch (eMode)
  227. {
  228. case MB_REG_READ :
  229. while (regs_cnt)
  230. {
  231. // Поиск регистра
  232. if (!mb_find_param(iRegIndex, &index_param, &size))
  233. {
  234. return MB_ENOREG; // нет запрашиваемого регистра
  235. }
  236. else
  237. {
  238. MBDBG printf("reg: %X, index: %u, size: %u\r\n", iRegIndex, index_param, size);
  239. MBDBG printf("reg: %X\r\n", iRegIndex);
  240. mb_get_param(ptr_buf, index_param); // Вызов функции записи
  241. iRegIndex += size;
  242. ptr_buf += 2*size;
  243. regs_cnt -= size;
  244. }
  245. }
  246. break;
  247. case MB_REG_WRITE :
  248. while (regs_cnt)
  249. {
  250. // Поиск регистра
  251. if (!mb_find_param(iRegIndex, &index_param, &size))
  252. {
  253. return MB_ENOREG; // нет запрашиваемого регистра
  254. }
  255. else
  256. {
  257. MBDBG printf("reg: %X, index: %u, size: %u\r\n", iRegIndex, index_param, size);
  258. mb_act = mb_set_param(ptr_buf, index_param); // Вызов функции записи
  259. if (mb_act != MB_NO_ACTION)
  260. mb_action = mb_act;
  261. iRegIndex += size;
  262. ptr_buf += 2*size;
  263. regs_cnt -= size;
  264. if (mb_act == MB_PAS_ERR)
  265. return MB_EINVAL;
  266. }
  267. }
  268. break;
  269. }
  270. #endif
  271. return eStatus;
  272. }
  273. // 17 (0x11) Report Slave ID (Serial Line only)
  274. // чтение информации об устройстве (0x11)
  275. eMBException
  276. eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
  277. {
  278. #if 1
  279. mb_package_flag = true;
  280. //*usLen = mb_get_info(&pucFrame[1]) + 3;
  281. #endif
  282. return MB_EX_NONE;
  283. }
  284. // чтение/запись значений из нескольких регистров флагов (Coil Status).
  285. // чтения N регистров параметров
  286. eMBErrorCode
  287. eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
  288. {
  289. return MB_ENOREG;
  290. }
  291. eMBErrorCode
  292. eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
  293. {
  294. return MB_ENOREG;
  295. }
  296. // 0x42
  297. // Запрос на изменение адреса
  298. // Если запрос широковещательный, то нужно проверить присланный ID.
  299. eMBException
  300. eMBSetAddrIdCB( UCHAR * pucFrame, USHORT * usLen )
  301. {
  302. #if 0
  303. mb_package_flag = true;
  304. if (rcvAddress == MB_ADDRESS_BROADCAST)
  305. {
  306. if (mb_set_addr_id(&pucFrame[1], &new_slave_addr))
  307. mb_action = MB_CHANGE_ADDR;
  308. }
  309. // Адресный запрос. ID не проверяем
  310. else
  311. {
  312. if (mb_set_addr(&pucFrame[1], &new_slave_addr))
  313. {
  314. pucFrame[1] = new_slave_addr;
  315. mb_action = MB_CHANGE_ADDR;
  316. }
  317. else
  318. pucFrame[1] = MB_BOOT_ERR_WRONG_CONTENT;
  319. }
  320. *usLen = 2;
  321. #endif
  322. return MB_EX_NONE;
  323. }
  324. // 0x43
  325. eMBException
  326. eMBSetAddrSerialCB( UCHAR * pucFrame, USHORT * usLen )
  327. {
  328. #if 0
  329. mb_package_flag = true;
  330. if (rcvAddress == MB_ADDRESS_BROADCAST)
  331. {
  332. if (mb_set_addr_serial(&pucFrame[1], &new_slave_addr))
  333. mb_action = MB_CHANGE_ADDR;
  334. }
  335. // Адресный запрос. ID не проверяем
  336. else
  337. {
  338. if (mb_set_addr(&pucFrame[1], &new_slave_addr))
  339. {
  340. pucFrame[1] = new_slave_addr;
  341. mb_action = MB_CHANGE_ADDR;
  342. }
  343. else
  344. pucFrame[1] = MB_BOOT_ERR_WRONG_CONTENT;
  345. }
  346. *usLen = 2;
  347. #endif
  348. return MB_EX_NONE;
  349. }
  350. eMBException
  351. eMBFuncReadFileRecordCB( UCHAR * pucFrame, USHORT * usLen )
  352. {
  353. uint8_t byte_count;
  354. uint8_t reference_type;
  355. uint16_t record_index = 0;
  356. uint16_t record_num = 0;
  357. #if 0
  358. DBG printf("Recived: ");
  359. for (int i = 0; i < *usLen; i++)
  360. {
  361. DBG printf("%X ", pucFrame[i]);
  362. }
  363. DBG printf("\r\n");
  364. #endif
  365. byte_count = pucFrame[1];
  366. reference_type = pucFrame[2];
  367. record_index = pucFrame[3] << 8;
  368. record_index |= pucFrame[4];
  369. record_num = pucFrame[7] << 8;
  370. record_num |= pucFrame[8];
  371. #if 0
  372. DBG printf("Byte count: %u, reference_type: %u, \r\n",
  373. byte_count, reference_type);
  374. DBG printf("Record index: %u, record num: %u\r\n",
  375. record_index, record_num);
  376. #endif
  377. if (reference_type == MB_ARCHIVE_ENTRY) {
  378. *usLen = 1 + mb_archive_get_entry((uint8_t*)&pucFrame[1], record_index);
  379. }
  380. else if (reference_type == MB_LOG_ENTRY) {
  381. *usLen = 1 + mb_log_get_entry((uint8_t*)&pucFrame[1], record_index);
  382. }
  383. return MB_EX_NONE;
  384. }
  385. //
  386. void cb_settings_timer(TimerHandle_t timer)
  387. {
  388. printf("Settings timer callback\r\n");
  389. //psw_ok = false;
  390. }