739 lines
23 KiB
C
739 lines
23 KiB
C
/****************************************************************************
|
|
|
|
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
|
|
|
|
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
|
|
be copied by any method or incorporated into another program without
|
|
the express written consent of Aerospace C.Power. This Information or any portion
|
|
thereof remains the property of Aerospace C.Power. The Information contained herein
|
|
is believed to be accurate and Aerospace C.Power assumes no responsibility or
|
|
liability for its use in any way and conveys no license or title under
|
|
any patent or copyright and makes no representation or warranty that this
|
|
Information is free from patent or copyright infringement.
|
|
|
|
****************************************************************************/
|
|
/* os_ship header files */
|
|
#include "os_timer_api.h"
|
|
#include "os_utils_api.h"
|
|
|
|
/* iot common header files */
|
|
#include "iot_io_api.h"
|
|
#include "iot_module_api.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_task_api.h"
|
|
#include "iot_pkt_api.h"
|
|
#include "iot_ipc_api.h"
|
|
#include "iot_sg_ext_api.h"
|
|
#include "iot_board_api.h"
|
|
#include "iot_oem_api.h"
|
|
#include "iot_plc_api.h"
|
|
#include "iot_mem_pool_api.h"
|
|
|
|
#include "iot_pkt_api.h"
|
|
#include "iot_proto_common.h"
|
|
#include "iot_proto_ge.h"
|
|
#include "iot_modbus_task.h"
|
|
#include "iot_modbus_ext.h"
|
|
#include "iot_gpio_api.h"
|
|
|
|
#define IOT_MODBUS_EXT_DATA_DUMP 1
|
|
|
|
#define IOT_MB_EXT_RESP_TIMER_PERIOD (2000) /* units:ms */
|
|
|
|
extern iot_mb_task_t mb_task;
|
|
|
|
mb_ext_cmd_current_t current_handle_cmd;
|
|
|
|
uint8_t mb_ext_gpio_config_flag = 0;
|
|
|
|
void iot_mb_ext_data_dump(uint8_t * buf, uint32_t len, uint32_t line)
|
|
{
|
|
#if IOT_MODBUS_EXT_DATA_DUMP
|
|
uint32_t i;
|
|
|
|
iot_printf("[mb_task]DUMP(%03d)@line:%d", len, line);
|
|
for (i = 0; i < len; i++) {
|
|
iot_printf(" %02X", buf[i]);
|
|
}
|
|
iot_printf("\n");
|
|
#endif
|
|
}
|
|
|
|
mb_extend_fn_hdr_t * iot_mb_ext_get_current_cmd_head()
|
|
{
|
|
return &(current_handle_cmd.hdr);
|
|
}
|
|
|
|
static uint8_t iot_mb_ext_resp_transmit(uint8_t * data, uint32_t len, mb_transmit_direction_e dir)
|
|
{
|
|
iot_pkt_t *p_pkt = NULL;
|
|
|
|
iot_mb_ext_data_dump(data, len, __LINE__);
|
|
|
|
/* response */
|
|
if (dir == MODBUS_CMD_FROM_UART) {
|
|
p_pkt = iot_pkt_alloc(len, IOT_MODBUS_MID);
|
|
if (NULL == p_pkt) {
|
|
iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__);
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
os_mem_cpy(iot_pkt_put(p_pkt, len), data, len);
|
|
|
|
iot_mb_task_msg_post_to_uart(mb_task.uart_h, p_pkt);
|
|
|
|
} else if (dir == MODBUS_CMD_FROM_PLC) {
|
|
p_pkt = iot_modbus_fn160_appdata_pack(data, len, 0, 1);
|
|
if (NULL == p_pkt) {
|
|
iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__);
|
|
IOT_ASSERT(0);
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
/* parser ge command and post to task */
|
|
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
|
|
iot_mb_task_post_uart_cmd, 0);
|
|
iot_pkt_free(p_pkt);
|
|
}
|
|
|
|
os_mem_set(¤t_handle_cmd, 0, sizeof(current_handle_cmd));
|
|
|
|
if (os_is_timer_active(mb_task.mb_ext_resp_timer)) {
|
|
os_stop_timer(mb_task.mb_ext_resp_timer);
|
|
}
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint8_t modbus_ext_set_resp_handler(iot_pkt_t *p_pkt_frame)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
uint16_t crc16 = 0;
|
|
uint32_t data_len = 0;
|
|
ge_frame_cmd_cfm_set_subfn20_t *cfm = (ge_frame_cmd_cfm_set_subfn20_t *)
|
|
iot_pkt_data(p_pkt_frame);
|
|
mb_ext_frame_set_resp_t *mb_resp_frm = NULL;
|
|
iot_pkt_t *mb_resp_pkt = NULL;
|
|
|
|
if (mb_ext_gpio_config_flag) {
|
|
mb_ext_gpio_config_flag = 0;
|
|
goto out;
|
|
}
|
|
|
|
mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head();
|
|
if ((cfm->result == ERR_OK) && ((cur_cmd->fn == MODBUS_EXT_SET_SINGLE_REG_FN)
|
|
|| (cur_cmd->fn == MODBUS_EXT_SET_MULTI_REG_FN))) {
|
|
data_len = sizeof(mb_ext_frame_set_resp_t);
|
|
mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID);
|
|
IOT_ASSERT(mb_resp_pkt);
|
|
mb_resp_frm = (mb_ext_frame_set_resp_t*)iot_pkt_put(mb_resp_pkt,
|
|
sizeof(mb_ext_frame_set_resp_t));
|
|
os_mem_cpy(&(mb_resp_frm->hdr), &(current_handle_cmd.hdr),
|
|
sizeof(mb_extend_fn_hdr_t));
|
|
mb_resp_frm->data = current_handle_cmd.data;
|
|
crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2);
|
|
mb_resp_frm->tail.check_sum = crc16;
|
|
iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len,
|
|
current_handle_cmd.dir);
|
|
|
|
iot_pkt_free(mb_resp_pkt);
|
|
ret = ERR_OK;
|
|
}
|
|
|
|
return ret;
|
|
out:
|
|
|
|
return ERR_OK;
|
|
|
|
}
|
|
|
|
uint8_t modbus_ext_aid_query_resp_handler(iot_pkt_t *p_pkt_frame)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
uint16_t crc16 = 0;
|
|
uint32_t data_len = 0;
|
|
ge_frame_nid_resp_subfn16_t *resp_cmd = (ge_frame_nid_resp_subfn16_t *)
|
|
iot_pkt_data(p_pkt_frame);
|
|
iot_pkt_t *mb_resp_pkt = NULL;
|
|
mb_ext_frame_aid_query_resp_t* mb_resp_frm = NULL;
|
|
|
|
mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head();
|
|
if ((cur_cmd->fn == MODBUS_EXT_QUERY_FN) &&
|
|
(big_little_swap16(cur_cmd->reg_addr) == AID_QUERY_RA)) {
|
|
data_len = sizeof(mb_ext_frame_aid_query_resp_t);
|
|
mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID);
|
|
IOT_ASSERT(mb_resp_pkt);
|
|
mb_resp_frm = (mb_ext_frame_aid_query_resp_t*)iot_pkt_put(mb_resp_pkt,
|
|
sizeof(mb_ext_frame_aid_query_resp_t));
|
|
mb_resp_frm->adapt_id = big_little_swap16(resp_cmd->nid);
|
|
|
|
mb_resp_frm->sa = current_handle_cmd.hdr.sa;
|
|
mb_resp_frm->fn = current_handle_cmd.hdr.fn;
|
|
mb_resp_frm->data_len = sizeof(*mb_resp_frm) - 5;
|
|
crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2);
|
|
mb_resp_frm->tail.check_sum = crc16;
|
|
iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len,
|
|
current_handle_cmd.dir);
|
|
|
|
iot_pkt_free(mb_resp_pkt);
|
|
ret = ERR_OK;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint8_t modbus_ext_gpio_query_resp_handler(iot_pkt_t *p_pkt_frame)
|
|
{
|
|
uint8_t ret = ERR_FAIL;
|
|
uint16_t crc16 = 0;
|
|
uint32_t data_len = 0;
|
|
ge_frame_query_gpio_resp_subfn27_t *resp_cmd =
|
|
(ge_frame_query_gpio_resp_subfn27_t *)iot_pkt_data(p_pkt_frame);
|
|
mb_ext_frame_gpio_query_resp_t* mb_resp_frm = NULL;
|
|
data_len = sizeof(mb_ext_frame_gpio_query_resp_t);
|
|
|
|
mb_extend_fn_hdr_t * cur_cmd = iot_mb_ext_get_current_cmd_head();
|
|
if ((cur_cmd->fn == MODBUS_EXT_QUERY_FN) &&
|
|
(big_little_swap16(cur_cmd->reg_addr) >= GPIO_QUERY_BASE_RA)) {
|
|
iot_pkt_t *mb_resp_pkt = NULL;
|
|
mb_resp_pkt = iot_pkt_alloc(data_len, IOT_GREE_APP_MID);
|
|
IOT_ASSERT(mb_resp_pkt);
|
|
mb_resp_frm = (mb_ext_frame_gpio_query_resp_t*)iot_pkt_put(mb_resp_pkt,
|
|
sizeof(mb_ext_frame_gpio_query_resp_t));
|
|
mb_resp_frm->gpio_value = big_little_swap16(resp_cmd->value);
|
|
|
|
mb_resp_frm->sa = current_handle_cmd.hdr.sa;
|
|
mb_resp_frm->fn = current_handle_cmd.hdr.fn;
|
|
mb_resp_frm->data_len = sizeof(*mb_resp_frm) - 5;
|
|
crc16 = iot_modbus_rtu_crc16((uint8_t*)mb_resp_frm, data_len - 2);
|
|
mb_resp_frm->tail.check_sum = crc16;
|
|
iot_mb_ext_resp_transmit((uint8_t*)mb_resp_frm, data_len,
|
|
current_handle_cmd.dir);
|
|
|
|
iot_pkt_free(mb_resp_pkt);
|
|
ret = ERR_OK;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint8_t iot_mb_ext_handle_resp_from_ge(iot_pkt_t *p_pkt_frame)
|
|
{
|
|
ge_extend_fn_hdr_t *hdr = (ge_extend_fn_hdr_t *)iot_pkt_data(p_pkt_frame);
|
|
|
|
if ((hdr->hdr.fn == PROTO_GE_PLC_SET_CMD) &&
|
|
(hdr->subfn == PROTO_CMD_CFM_CMD)) {
|
|
if (ERR_OK == modbus_ext_set_resp_handler(p_pkt_frame)) {
|
|
goto out;
|
|
}
|
|
} else if ((hdr->hdr.fn == PROTO_GE_PLC_RESP_CMD) &&
|
|
(hdr->subfn == PROTO_NID_QUERY_CMD)) {
|
|
if (ERR_OK == modbus_ext_aid_query_resp_handler(p_pkt_frame)) {
|
|
goto out;
|
|
}
|
|
} else if ((hdr->hdr.fn == PROTO_GE_PLC_RESP_CMD) &&
|
|
(hdr->subfn == PROTO_GE_GPIO_QUERY_CMD)) {
|
|
if (ERR_OK == modbus_ext_gpio_query_resp_handler(p_pkt_frame)) {
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
return ERR_FAIL;
|
|
out:
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
void iot_mb_ext_resp_cmd_timeout_or_failed()
|
|
{
|
|
if (os_is_timer_active(mb_task.mb_ext_resp_timer)) {
|
|
os_stop_timer(mb_task.mb_ext_resp_timer);
|
|
}
|
|
os_mem_set(¤t_handle_cmd, 0, sizeof(current_handle_cmd));
|
|
|
|
return;
|
|
}
|
|
|
|
static uint8_t modbus_ext_gpio_config(uint8_t gpio_num, uint8_t dir_mode,
|
|
uint8_t pull_mode, uint8_t default_value)
|
|
{
|
|
ge_frame_gpio_config_subfn164_t *pack_frm = NULL;
|
|
uint32_t pack_frm_len = sizeof(ge_frame_gpio_config_subfn164_t);
|
|
iot_pkt_t *p_pkt = NULL;
|
|
uint16_t crc16 = 0;
|
|
|
|
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
|
|
if (NULL == p_pkt) {
|
|
iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__);
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
/* pack ge frame. */
|
|
pack_frm = (ge_frame_gpio_config_subfn164_t *)iot_pkt_put(p_pkt, pack_frm_len);
|
|
pack_frm->hdr.hdr.preamble = 0xAAAA;
|
|
pack_frm->hdr.hdr.data_len = 0x11;
|
|
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
|
|
pack_frm->hdr.subfn = PROTO_GE_GPIO_CONFIG_CMD;
|
|
|
|
pack_frm->seq = 0;
|
|
iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac);
|
|
iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac);
|
|
pack_frm->gpio_num = gpio_num;
|
|
pack_frm->dir_mode = dir_mode;
|
|
pack_frm->pull_mode = pull_mode;
|
|
pack_frm->output_value = default_value;
|
|
|
|
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
|
|
pack_frm->tail.check_sum = crc16;
|
|
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
|
|
|
|
/* post ge command to ge task */
|
|
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
|
|
iot_mb_task_post_uart_cmd, 0);
|
|
iot_pkt_free(p_pkt);
|
|
|
|
return ERR_OK;
|
|
}
|
|
|
|
bool_t modbus_ext_aid_query_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
ge_frame_nid_query_subfn16_t *pack_frm = NULL;
|
|
uint32_t pack_frm_len = sizeof(ge_frame_nid_query_subfn16_t);
|
|
iot_pkt_t *p_pkt = NULL;
|
|
mb_ext_frame_aid_query_t *frm = (mb_ext_frame_aid_query_t *)data;
|
|
uint16_t crc16 = 0;
|
|
|
|
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
|
|
if (NULL == p_pkt) {
|
|
iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__);
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t));
|
|
current_handle_cmd.data = frm->reg_count;
|
|
current_handle_cmd.dir = dir;
|
|
|
|
/* pack ge frame. */
|
|
pack_frm = (ge_frame_nid_query_subfn16_t *)iot_pkt_put(p_pkt, pack_frm_len);
|
|
pack_frm->hdr.hdr.preamble = 0xAAAA;
|
|
pack_frm->hdr.hdr.data_len = 0x01;
|
|
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_QUERY_CMD;
|
|
pack_frm->hdr.subfn = PROTO_NID_QUERY_CMD;
|
|
|
|
pack_frm->seq = 0;
|
|
|
|
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
|
|
pack_frm->tail.check_sum = crc16;
|
|
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
|
|
|
|
/* post ge command to ge task */
|
|
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
|
|
iot_mb_task_post_uart_cmd, 0);
|
|
iot_pkt_free(p_pkt);
|
|
|
|
os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool_t modbus_ext_sa_query_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
iot_pkt_t *p_pkt = NULL;
|
|
mb_ext_frame_sa_query_resp_t *resp_frm = NULL;
|
|
uint32_t resp_frm_len = sizeof(mb_ext_frame_sa_query_resp_t);
|
|
uint16_t crc16 = 0;
|
|
|
|
mb_ext_frame_sa_query_t *frm = (mb_ext_frame_sa_query_t *)data;
|
|
|
|
p_pkt = iot_pkt_alloc(resp_frm_len, IOT_MODBUS_MID);
|
|
if (NULL == p_pkt) {
|
|
iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__);
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
resp_frm = (mb_ext_frame_sa_query_resp_t *)iot_pkt_put(p_pkt, resp_frm_len);
|
|
resp_frm->sa = frm->hdr.sa;
|
|
resp_frm->fn = frm->hdr.fn;
|
|
resp_frm->data_len = 2;
|
|
resp_frm->slaver_addr = big_little_swap16(mb_task.slave_addr);
|
|
crc16 = iot_modbus_rtu_crc16((uint8_t*)resp_frm, resp_frm_len - 2);
|
|
resp_frm->tail.check_sum = crc16;
|
|
iot_mb_ext_resp_transmit((uint8_t*)resp_frm, resp_frm_len, dir);
|
|
|
|
iot_pkt_free(p_pkt);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool_t modbus_ext_wl_item_count_query_handler(uint8_t *data,
|
|
uint8_t len, mb_transmit_direction_e dir)
|
|
{
|
|
(void)data;
|
|
(void)len;
|
|
(void)dir;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool_t modbus_ext_wl_item_query_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
(void)data;
|
|
(void)len;
|
|
(void)dir;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool_t modbus_ext_gpio_query_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
ge_frame_gpio_query_subfn27_t *pack_frm = NULL;
|
|
uint32_t pack_frm_len = sizeof(ge_frame_gpio_query_subfn27_t);
|
|
iot_pkt_t *p_pkt = NULL;
|
|
mb_ext_frame_gpio_query_t *frm = (mb_ext_frame_gpio_query_t *)data;
|
|
uint16_t crc16 = 0, reg_addr = 0;
|
|
uint8_t gpio_num = 0xff;
|
|
|
|
reg_addr = big_little_swap16(frm->hdr.reg_addr);
|
|
if ((reg_addr - GPIO_QUERY_BASE_RA) % 8 != 0) {
|
|
goto param_err;
|
|
} else {
|
|
gpio_num = (reg_addr - GPIO_QUERY_BASE_RA) / 8;
|
|
//if (gpio_num >= GPIO_PIN_COUNT) {
|
|
// goto param_err;
|
|
//}
|
|
}
|
|
|
|
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
|
|
if (NULL == p_pkt) {
|
|
iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__);
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t));
|
|
current_handle_cmd.data = frm->reg_count;
|
|
current_handle_cmd.dir = dir;
|
|
|
|
mb_ext_gpio_config_flag = 1;
|
|
modbus_ext_gpio_config(gpio_num, IOT_GE_GPIO_DIR_INPUT, IOT_GE_GPIO_PULL_NONE, 0);
|
|
|
|
/* pack ge frame. */
|
|
pack_frm = (ge_frame_gpio_query_subfn27_t *)iot_pkt_put(p_pkt, pack_frm_len);
|
|
pack_frm->hdr.hdr.preamble = 0xAAAA;
|
|
pack_frm->hdr.hdr.data_len = 0x0E;
|
|
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_QUERY_CMD;
|
|
pack_frm->hdr.subfn = PROTO_GE_GPIO_QUERY_CMD;
|
|
|
|
pack_frm->seq = 0;
|
|
iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac);
|
|
iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac);
|
|
pack_frm->gpio_num = gpio_num;
|
|
|
|
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
|
|
pack_frm->tail.check_sum = crc16;
|
|
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
|
|
|
|
/* post ge command to ge task */
|
|
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
|
|
iot_mb_task_post_uart_cmd, 0);
|
|
iot_pkt_free(p_pkt);
|
|
|
|
os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD);
|
|
|
|
return true;
|
|
|
|
param_err:
|
|
iot_printf("[%s][err]param err @line %d\n", __FUNCTION__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
static mb_fnhdl_tbl_t modbus_query_ra_tbl[] = {
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
{AID_QUERY_RA, modbus_ext_aid_query_handler, 0},
|
|
{WL_ITEM_COUNT_QUERY_RA, modbus_ext_wl_item_count_query_handler, 0},
|
|
{WL_ITEM_QUERY_BASE_RA, modbus_ext_wl_item_query_handler, 0},
|
|
#endif
|
|
{SA_QUERY_RA, modbus_ext_sa_query_handler, 0},
|
|
{GPIO_QUERY_BASE_RA, modbus_ext_gpio_query_handler, 0},
|
|
};
|
|
|
|
static bool_t iot_mb_ext_cmd_query_fn_handler(uint8_t *data,
|
|
uint8_t len, mb_transmit_direction_e dir)
|
|
{
|
|
uint8_t i, ret = ERR_FAIL;
|
|
uint16_t reg_addr = 0;
|
|
mb_extend_fn_hdr_t *mb_head = (mb_extend_fn_hdr_t *)data;
|
|
uint8_t fncode_hdlr_cnt =
|
|
sizeof(modbus_query_ra_tbl)/sizeof(mb_fnhdl_tbl_t);
|
|
MODBUS_FN_HANDLE handler = NULL;
|
|
|
|
reg_addr = big_little_swap16(mb_head->reg_addr);
|
|
|
|
for (i = 0; i < fncode_hdlr_cnt; i++) {
|
|
if (modbus_query_ra_tbl[i].cmdid == reg_addr) {
|
|
handler = modbus_query_ra_tbl[i].cmd_handle_fn;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
if (reg_addr > WL_ITEM_QUERY_BASE_RA) {
|
|
handler = modbus_ext_wl_item_query_handler;
|
|
}
|
|
#endif
|
|
|
|
if (reg_addr > GPIO_QUERY_BASE_RA) {
|
|
handler = modbus_ext_gpio_query_handler;
|
|
}
|
|
|
|
if (handler) {
|
|
ret = handler(data, len, dir);
|
|
ret = (ret == true)? ERR_OK: ERR_FAIL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool_t modbus_ext_aid_set_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
ge_frame_cco_nid_set_subfn17_t *pack_frm = NULL;
|
|
uint32_t pack_frm_len = sizeof(ge_frame_cco_nid_set_subfn17_t);
|
|
iot_pkt_t *p_pkt = NULL;
|
|
mb_ext_frame_aid_set_t *frm = (mb_ext_frame_aid_set_t *)data;
|
|
uint16_t crc16 = 0;
|
|
|
|
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
|
|
if (NULL == p_pkt) {
|
|
iot_printf("[mb_ext][err]no mem@line %d\n", __LINE__);
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t));
|
|
current_handle_cmd.data = frm->adapt_id;
|
|
current_handle_cmd.dir = dir;
|
|
|
|
/* pack ge frame. */
|
|
pack_frm = (ge_frame_cco_nid_set_subfn17_t *)iot_pkt_put(p_pkt, pack_frm_len);
|
|
pack_frm->hdr.hdr.preamble = 0xAAAA;
|
|
pack_frm->hdr.hdr.data_len = 0X07;
|
|
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
|
|
pack_frm->hdr.subfn = PROTO_CCO_NID_SET_CMD;
|
|
|
|
pack_frm->nid = (frm->adapt_id) >> 8;
|
|
pack_frm->seq = 0;
|
|
iot_mac_addr_cpy(pack_frm->mac, mb_task.local_mac);
|
|
|
|
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
|
|
pack_frm->tail.check_sum = crc16;
|
|
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
|
|
|
|
/* post ge command to ge task */
|
|
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
|
|
iot_mb_task_post_uart_cmd, 0);
|
|
iot_pkt_free(p_pkt);
|
|
|
|
os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool_t modbus_ext_sa_set_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
mb_ext_frame_sa_set_t *frm = (mb_ext_frame_sa_set_t *)data;
|
|
uint8_t new_sa = (frm->slaver_addr) >> 8;
|
|
|
|
if (mb_task.slave_addr != new_sa) {
|
|
mb_task.slave_addr = new_sa;
|
|
}
|
|
|
|
iot_mb_ext_resp_transmit(data, len, dir);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool_t modbus_ext_wl_set_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
(void)data;
|
|
(void)len;
|
|
(void)dir;
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool_t modbus_ext_gpio_set_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
ge_frame_gpio_set_subfn165_t *pack_frm = NULL;
|
|
uint32_t pack_frm_len = sizeof(ge_frame_gpio_set_subfn165_t);
|
|
iot_pkt_t *p_pkt = NULL;
|
|
mb_ext_frame_gpio_set_t *frm = (mb_ext_frame_gpio_set_t *)data;
|
|
uint16_t crc16 = 0, reg_addr = 0;
|
|
uint8_t gpio_num = 0xff;
|
|
|
|
reg_addr = big_little_swap16(frm->hdr.reg_addr);
|
|
|
|
if ((reg_addr - GPIO_SET_BASE_RA) % 8 != 0) {
|
|
goto param_err;
|
|
} else {
|
|
gpio_num = (reg_addr - GPIO_SET_BASE_RA) / 8;
|
|
//if (gpio_num >= GPIO_PIN_COUNT) {
|
|
// goto param_err;
|
|
//}
|
|
}
|
|
|
|
p_pkt = iot_pkt_alloc(pack_frm_len, IOT_MODBUS_MID);
|
|
if (NULL == p_pkt) {
|
|
iot_printf("[%s][err]no mem@line %d\n", __FUNCTION__, __LINE__);
|
|
IOT_ASSERT(0);
|
|
return false;
|
|
}
|
|
|
|
os_mem_cpy(&(current_handle_cmd.hdr), &(frm->hdr), sizeof(mb_extend_fn_hdr_t));
|
|
current_handle_cmd.data = frm->gpio_value;
|
|
current_handle_cmd.dir = dir;
|
|
|
|
mb_ext_gpio_config_flag = 1;
|
|
modbus_ext_gpio_config(gpio_num, IOT_GE_GPIO_DIR_OUTPUT, IOT_GE_GPIO_PULL_NONE, 0);
|
|
|
|
/* pack ge frame. */
|
|
pack_frm = (ge_frame_gpio_set_subfn165_t *)iot_pkt_put(p_pkt, pack_frm_len);
|
|
pack_frm->hdr.hdr.preamble = 0xAAAA;
|
|
pack_frm->hdr.hdr.data_len = 0x0F;
|
|
pack_frm->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
|
|
pack_frm->hdr.subfn = PROTO_GE_GPIO_SET_CMD;
|
|
|
|
pack_frm->seq = 0;
|
|
iot_mac_addr_cpy(pack_frm->dest_mac, mb_task.local_mac);
|
|
iot_mac_addr_cpy(pack_frm->src_mac, mb_task.local_mac);
|
|
pack_frm->gpio_num = gpio_num;
|
|
pack_frm->value = (frm->gpio_value) >> 8;
|
|
|
|
crc16 = ge_frm_checksum_calc((uint8_t *)pack_frm, pack_frm_len - 3);
|
|
pack_frm->tail.check_sum = crc16;
|
|
pack_frm->tail.tail = GE_FRM_TAIL_CODE;
|
|
|
|
/* post ge command to ge task */
|
|
iot_proto_data_parse_and_post(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt),
|
|
iot_mb_task_post_uart_cmd, 0);
|
|
iot_pkt_free(p_pkt);
|
|
|
|
os_start_timer(mb_task.mb_ext_resp_timer, IOT_MB_EXT_RESP_TIMER_PERIOD);
|
|
|
|
return true;
|
|
|
|
param_err:
|
|
iot_printf("[%s][err]param err @line %d\n", __FUNCTION__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool_t modbus_ext_wl_add_item_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
(void)data;
|
|
(void)len;
|
|
(void)dir;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool_t modbus_ext_wl_remove_item_handler(uint8_t *data, uint8_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
(void)data;
|
|
(void)len;
|
|
(void)dir;
|
|
|
|
return true;
|
|
}
|
|
|
|
static mb_fnhdl_tbl_t modbus_set_ra_tbl[] = {
|
|
#if PLC_SUPPORT_CCO_ROLE
|
|
{AID_SET_RA, modbus_ext_aid_set_handler, 0},
|
|
{WL_SET_RA, modbus_ext_wl_set_handler,0},
|
|
{WL_ADD_ITEM_SET_RA, modbus_ext_wl_add_item_handler, 0},
|
|
{WL_RM_ITEM_SET_RA, modbus_ext_wl_remove_item_handler, 0},
|
|
#endif
|
|
{SA_SET_RA, modbus_ext_sa_set_handler,0},
|
|
{GPIO_SET_BASE_RA, modbus_ext_gpio_set_handler, 0},
|
|
};
|
|
|
|
static bool_t iot_mb_ext_cmd_set_handler(uint8_t *data,
|
|
uint8_t len, mb_transmit_direction_e dir)
|
|
{
|
|
uint8_t i, ret = ERR_FAIL;
|
|
mb_extend_fn_hdr_t *mb_head = (mb_extend_fn_hdr_t *)data;;
|
|
uint8_t fncode_hdlr_cnt =
|
|
sizeof(modbus_set_ra_tbl)/sizeof(mb_fnhdl_tbl_t);
|
|
MODBUS_FN_HANDLE handler = NULL;
|
|
uint16_t reg_addr = big_little_swap16(mb_head->reg_addr);
|
|
|
|
for (i = 0; i < fncode_hdlr_cnt; i++) {
|
|
if (modbus_set_ra_tbl[i].cmdid == reg_addr) {
|
|
handler = modbus_set_ra_tbl[i].cmd_handle_fn;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (reg_addr > GPIO_SET_BASE_RA) {
|
|
handler = modbus_ext_gpio_set_handler;
|
|
}
|
|
|
|
if (handler) {
|
|
ret = handler(data, len, dir);
|
|
ret = (ret == true)? ERR_OK: ERR_FAIL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* fncode handler table */
|
|
static mb_fnhdl_tbl_t mb_fn_hdl_tbl[] = {
|
|
{MODBUS_EXT_QUERY_FN, iot_mb_ext_cmd_query_fn_handler, 0 },
|
|
{MODBUS_EXT_SET_SINGLE_REG_FN, iot_mb_ext_cmd_set_handler, 0 },
|
|
{MODBUS_EXT_SET_MULTI_REG_FN, iot_mb_ext_cmd_set_handler, 0 },
|
|
};
|
|
|
|
uint8_t iot_mb_ext_cmd_handler(uint8_t * data, uint16_t len,
|
|
mb_transmit_direction_e dir)
|
|
{
|
|
uint8_t i, ret = ERR_FAIL;
|
|
mb_extend_fn_hdr_t *mb_head = NULL;
|
|
uint8_t fncode_hdlr_cnt =
|
|
sizeof(mb_fn_hdl_tbl)/sizeof(mb_fnhdl_tbl_t);
|
|
|
|
if ((data == NULL) || (len == 0)) {
|
|
iot_printf("[%s][err] invalid data, data:%p, len:%d\n", __FUNCTION__, data, len);
|
|
goto out;
|
|
}
|
|
|
|
iot_mb_ext_data_dump(data, len, __LINE__);
|
|
mb_head = (mb_extend_fn_hdr_t *)data;
|
|
|
|
/* look for fncode handler to handle modbus cmd frame */
|
|
for (i = 0; i < fncode_hdlr_cnt; i++) {
|
|
if (mb_head->fn == mb_fn_hdl_tbl[i].cmdid) {
|
|
/* increase each fn counter */
|
|
mb_fn_hdl_tbl[i].cmd_num++;
|
|
mb_fn_hdl_tbl[i].cmd_handle_fn(data, len, dir);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ret = ERR_OK;
|
|
out:
|
|
return ret;
|
|
}
|