modbus.c 14 KB

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