1195 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1195 lines
		
	
	
		
			38 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_task_api.h"
 | 
						|
#include "os_event_api.h"
 | 
						|
#include "os_timer_api.h"
 | 
						|
#include "os_utils_api.h"
 | 
						|
#include "os_lock_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_grapp.h"
 | 
						|
#include "iot_proto_common.h"
 | 
						|
#include "iot_proto_ge.h"
 | 
						|
#include "iot_modbus_task.h"
 | 
						|
#include "iot_modbus_ext.h"
 | 
						|
 | 
						|
#if IOT_GE_MODBUS_TASK_ENABLE
 | 
						|
 | 
						|
#if (IOT_PSRAM_ENABLE)
 | 
						|
#define IOT_MODBUS_TASK_UART_BUF_SIZE       (2048)
 | 
						|
#else
 | 
						|
#define IOT_MODBUS_TASK_UART_BUF_SIZE       (256 + 64)
 | 
						|
#endif
 | 
						|
/* define ge FE A0 cmd max data len */
 | 
						|
#define IOT_GE_FE_A0_DATA_LEN_MAX           (GE_FRM_PLD_MAX_LEN - IOT_MAC_ADDR_LEN)
 | 
						|
/* print data buff in hex formate. */
 | 
						|
#define IOT_MODBUS_TASK_DATA_DUMP           (1)
 | 
						|
/* modbus bradcast addr is 0 */
 | 
						|
#define IOT_MODBUS_BROADCAST_ADDR           (0x0)
 | 
						|
/* modbus default slaver address */
 | 
						|
#define IOT_MODBUS_DEFAULT_SLAVER_ADDR      (0xff)
 | 
						|
 | 
						|
 | 
						|
#if PLC_SUPPORT_CCO_ROLE // master REQUEST
 | 
						|
const iot_mb_data_check_t mb_check[] = {
 | 
						|
    {0x02, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x01, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x05, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x0F, 1 + 6 + 2, 1, 0x06}, // 1 + 6 + n + 2
 | 
						|
    {0x04, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x03, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x06, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x10, 1 + 6 + 2, 1, 0x06}, // 1 + 6 + n + 2
 | 
						|
    {0x17, 1 + 10 + 2,1, 0x0A}, // 1 + 10 + n + 2
 | 
						|
    {0x16, 1 + 7 + 2, 0, 0xFF}, // 1 + 7 + 2
 | 
						|
};
 | 
						|
#else // slave RESPONSE
 | 
						|
const iot_mb_data_check_t mb_check[] = {
 | 
						|
    {0x02, 1 + 2 + 2, 1, 0x02}, // 1 + 2 + n + 2
 | 
						|
    {0x01, 1 + 2 + 2, 1, 0x02}, // 1 + 2 + n + 2
 | 
						|
    {0x05, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x0F, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x04, 1 + 2 + 2, 1, 0x02}, // 1 + 2 + n + 2
 | 
						|
    {0x03, 1 + 2 + 2, 1, 0x02}, // 1 + 2 + n + 2
 | 
						|
    {0x06, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x10, 1 + 5 + 2, 0, 0xff}, // 1 + 5 + 2
 | 
						|
    {0x17, 1 + 2 + 2, 1, 0x02}, // 1 + 2 + n + 2
 | 
						|
    {0x16, 1 + 7 + 2, 0, 0xff}, // 1 + 7 + 2
 | 
						|
};
 | 
						|
#endif
 | 
						|
const uint8_t max_func_code_num = sizeof(mb_check) / sizeof(mb_check[0]);
 | 
						|
 | 
						|
/** modbus_task message */
 | 
						|
typedef struct _iot_mb_task_msg {
 | 
						|
    /* iot task message */
 | 
						|
    iot_task_msg_t  task_msg;
 | 
						|
    /* pointer to message data */
 | 
						|
    void            *data;
 | 
						|
    /* another data field */
 | 
						|
    uint32_t        data2;
 | 
						|
} iot_mb_task_msg_t;
 | 
						|
 | 
						|
iot_mb_task_t mb_task;
 | 
						|
 | 
						|
#if IOT_MODBUS_RT_TABLE_SUPPORT
 | 
						|
 | 
						|
/* route entry max nums */
 | 
						|
#define IOT_MODBUS_MAC_RT_ENTRY_MAX          (32)
 | 
						|
/* route entry timeout, unit is second. */
 | 
						|
#define IOT_MODBUS_MAC_RT_ENTRY_TTL          (60)
 | 
						|
/* route entry update interval, unit is second. */
 | 
						|
#define IOT_MODBUS_MAC_RT_UPDATE_INTERVAL    (20)
 | 
						|
 | 
						|
/** iot mac address hash table entry */
 | 
						|
typedef struct _iot_modbus_addr_rout_entry {
 | 
						|
    struct _iot_modbus_addr_rout_entry *next;
 | 
						|
    /* modbus device id */
 | 
						|
    uint8_t             slaver_addr;
 | 
						|
    /** mac address of the entry */
 | 
						|
    uint8_t             addr[IOT_MAC_ADDR_LEN];
 | 
						|
    /* ttl of the route item. unit is s */
 | 
						|
    int                 ent_ttl;
 | 
						|
} iot_modbus_addr_rout_entry_t;
 | 
						|
 | 
						|
/* iot mac address hash table */
 | 
						|
typedef struct _iot_modbus_addr_rout_table {
 | 
						|
    /* number of entries supported */
 | 
						|
    uint16_t                entry_cnt;
 | 
						|
    /* size of each entry */
 | 
						|
    uint16_t                entry_size;
 | 
						|
    /* entry point for each entry item */
 | 
						|
    iot_modbus_addr_rout_entry_t   *rout_ent;
 | 
						|
    /* entry pool */
 | 
						|
    iot_mem_pool_t          *entry_p;
 | 
						|
} iot_modbus_addr_rout_table_t;
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_rt_update_timer_exe() - timer timeout callback function.
 | 
						|
 * @timer_id : timer id with that timer who causes this api-call.
 | 
						|
 * @arg : param past to this callback api.
 | 
						|
 */
 | 
						|
static void iot_mb_task_rt_update_timer_exe(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)arg;
 | 
						|
    if (timer_id == mb_task.uart_timer) {
 | 
						|
        iot_mb_task_msg_post(IOT_MODBUS_TASK_MT_TIMER,
 | 
						|
            IOT_MODBUS_TASK_MSG_ID_TMR_RT_UPDATE_TIMEOUT, NULL);
 | 
						|
        os_reset_timer(timer_id);
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_addr_rout_alloc_entry() - Alloc a rout entry from the mem pool.
 | 
						|
 */
 | 
						|
static iot_modbus_addr_rout_entry_t *iot_modbus_addr_rout_alloc_entry(
 | 
						|
    iot_modbus_addr_rout_table_t *table)
 | 
						|
{
 | 
						|
    return iot_mem_pool_alloc(table->entry_p);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_addr_rout_table_free_entry() - Free a rout entry of the mem pool.
 | 
						|
 */
 | 
						|
static void iot_modbus_addr_rout_table_free_entry(
 | 
						|
    iot_modbus_addr_rout_table_t *table, iot_modbus_addr_rout_entry_t *entry)
 | 
						|
{
 | 
						|
    iot_mem_pool_free(table->entry_p, entry);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_addr_rout_table_create() - Create a rout table.
 | 
						|
 */
 | 
						|
static iot_modbus_addr_rout_table_h iot_modbus_addr_rout_table_create(
 | 
						|
    module_id_t module, uint16_t entry_cnt, uint16_t entry_size)
 | 
						|
{
 | 
						|
    uint32_t ret;
 | 
						|
    iot_modbus_addr_rout_table_t *table = NULL;
 | 
						|
 | 
						|
    table = os_mem_malloc(module, sizeof(*table));
 | 
						|
    if (table == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = iot_mem_pool_new(module, entry_cnt,
 | 
						|
        entry_size, &table->entry_p, 1);
 | 
						|
    if (ret)
 | 
						|
        goto err_table;
 | 
						|
 | 
						|
    table->entry_cnt = entry_cnt;
 | 
						|
    table->entry_size = entry_size;
 | 
						|
    goto out;
 | 
						|
 | 
						|
err_table:
 | 
						|
    os_mem_free(table);
 | 
						|
    table = NULL;
 | 
						|
out:
 | 
						|
    return table;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_addr_rout_table_clean() - Clean the modbus rout table.
 | 
						|
 */
 | 
						|
void iot_modbus_addr_rout_table_clean(iot_modbus_addr_rout_table_h handle)
 | 
						|
{
 | 
						|
    iot_modbus_addr_rout_table_t *table = handle;
 | 
						|
    iot_modbus_addr_rout_entry_t *entry = table->rout_ent;
 | 
						|
    iot_modbus_addr_rout_entry_t *tmp = NULL;
 | 
						|
 | 
						|
    while (entry) {
 | 
						|
        tmp = entry;
 | 
						|
        iot_mem_pool_free(table->entry_p, tmp);
 | 
						|
        entry = entry->next;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_addr_rout_table_find() - Find the rout entry by device id.
 | 
						|
 */
 | 
						|
static iot_modbus_addr_rout_entry_t *iot_modbus_addr_rout_table_find(
 | 
						|
    iot_modbus_addr_rout_table_h handle, uint8_t slave_addr)
 | 
						|
{
 | 
						|
    iot_modbus_addr_rout_table_t *table = handle;
 | 
						|
    iot_modbus_addr_rout_entry_t *entry = NULL;
 | 
						|
 | 
						|
    entry = table->rout_ent;
 | 
						|
    while (entry) {
 | 
						|
        if (entry->slaver_addr == slave_addr) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        entry = entry->next;
 | 
						|
    }
 | 
						|
 | 
						|
    return entry;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_addr_rout_table_find_replaced() - Find the smallest ttl
 | 
						|
 *                                   entry and return to replace it.
 | 
						|
 */
 | 
						|
static iot_modbus_addr_rout_entry_t *iot_modbus_addr_rout_table_find_replaced(
 | 
						|
    iot_modbus_addr_rout_table_h handle)
 | 
						|
{
 | 
						|
    iot_modbus_addr_rout_table_t *table = handle;
 | 
						|
    iot_modbus_addr_rout_entry_t *entry , *tmp;
 | 
						|
 | 
						|
    entry = table->rout_ent;
 | 
						|
 | 
						|
    if (entry == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    tmp = entry->next;
 | 
						|
 | 
						|
    while (tmp) {
 | 
						|
        if (entry->ent_ttl > tmp->ent_ttl) {
 | 
						|
            entry = tmp;
 | 
						|
        }
 | 
						|
        tmp = tmp->next;
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    return entry;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_add_addr_rt() - Add the MAC address and the corresponding
 | 
						|
 *                                   device id to the routing table .
 | 
						|
 */
 | 
						|
static uint8_t iot_modbus_add_addr_rt(iot_modbus_addr_rout_table_h rt_table,
 | 
						|
    uint8_t *dst_addr, uint8_t slave_addr)
 | 
						|
{
 | 
						|
    iot_modbus_addr_rout_entry_t *entry;
 | 
						|
    iot_modbus_addr_rout_table_t *table = rt_table;
 | 
						|
 | 
						|
    entry = (iot_modbus_addr_rout_entry_t *)iot_modbus_addr_rout_table_find(
 | 
						|
        rt_table, slave_addr);
 | 
						|
 | 
						|
    if (entry) {
 | 
						|
        entry->ent_ttl = IOT_MODBUS_MAC_RT_ENTRY_TTL;
 | 
						|
        if(!iot_mac_addr_cmp(dst_addr, entry->addr)) {
 | 
						|
                iot_mac_addr_cpy(entry->addr, dst_addr);
 | 
						|
            }
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    /* entry not exist, try to add it */
 | 
						|
    entry = (iot_modbus_addr_rout_entry_t *)iot_modbus_addr_rout_alloc_entry(
 | 
						|
        rt_table);
 | 
						|
    if (entry == NULL) {
 | 
						|
        /* force get the entry that it's ttl is the smallest */
 | 
						|
        entry = iot_modbus_addr_rout_table_find_replaced(rt_table);
 | 
						|
        if (entry == NULL) {
 | 
						|
        } else {
 | 
						|
            entry->slaver_addr = slave_addr;
 | 
						|
            iot_mac_addr_cpy(entry->addr, dst_addr);
 | 
						|
            entry->ent_ttl = IOT_MODBUS_MAC_RT_ENTRY_TTL;
 | 
						|
        }
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    entry->slaver_addr = slave_addr;
 | 
						|
    iot_mac_addr_cpy(entry->addr, dst_addr);
 | 
						|
    entry->ent_ttl = IOT_MODBUS_MAC_RT_ENTRY_TTL;
 | 
						|
 | 
						|
    entry->next = table->rout_ent;
 | 
						|
    table->rout_ent = entry;
 | 
						|
 | 
						|
    iot_printf("[%s][info] update rt table successfully!\n", __FUNCTION__);
 | 
						|
 | 
						|
out:
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_update_addr_rt() - Update route table every 20 seconds .
 | 
						|
 */
 | 
						|
static void iot_modbus_update_addr_rt(iot_modbus_addr_rout_table_h rt_table)
 | 
						|
{
 | 
						|
    iot_modbus_addr_rout_table_t *table = (iot_modbus_addr_rout_table_t *)rt_table;
 | 
						|
    iot_modbus_addr_rout_entry_t *tmp, *entry = table->rout_ent;
 | 
						|
 | 
						|
    if (entry == NULL) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    tmp = entry->next;
 | 
						|
 | 
						|
    while(tmp) {
 | 
						|
        if (tmp->ent_ttl <= 0) {
 | 
						|
            entry->next = tmp->next;
 | 
						|
            iot_modbus_addr_rout_table_free_entry(table, tmp);
 | 
						|
            tmp = entry->next;
 | 
						|
        } else {
 | 
						|
            tmp->ent_ttl -= IOT_MODBUS_MAC_RT_UPDATE_INTERVAL;
 | 
						|
            entry = entry->next;
 | 
						|
            tmp = entry->next;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    entry = table->rout_ent;
 | 
						|
 | 
						|
    if (entry) {
 | 
						|
        if (entry->ent_ttl <= 0) {
 | 
						|
            table->rout_ent = entry->next;
 | 
						|
            iot_modbus_addr_rout_table_free_entry(table, entry);
 | 
						|
        } else {
 | 
						|
            entry->ent_ttl -= IOT_MODBUS_MAC_RT_UPDATE_INTERVAL;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_modbus_get_addr_rt() - Get the MAC address by looking up the
 | 
						|
 *                                   routing table with the device id.
 | 
						|
 */
 | 
						|
static uint8_t iot_modbus_get_addr_rt(iot_modbus_addr_rout_table_h rt_table,
 | 
						|
    uint8_t slave_addr, uint8_t *dst_addr)
 | 
						|
{
 | 
						|
    iot_modbus_addr_rout_entry_t *entry;
 | 
						|
 | 
						|
    if (dst_addr == NULL) {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    entry = (iot_modbus_addr_rout_entry_t *)iot_modbus_addr_rout_table_find(
 | 
						|
        rt_table, slave_addr);
 | 
						|
 | 
						|
    if (entry) {
 | 
						|
        iot_mac_addr_cpy(dst_addr, entry->addr);
 | 
						|
    } else {
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_printf("[%s][info] get rt entry successfully!\n", __FUNCTION__);
 | 
						|
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
static uint8_t iot_mb_task_get_slaver_addr(uint8_t *modbus_data)
 | 
						|
{
 | 
						|
    return modbus_data[0];
 | 
						|
}
 | 
						|
 | 
						|
void iot_mb_task_data_dump(uint8_t * buf, uint32_t len, uint32_t line)
 | 
						|
{
 | 
						|
#if IOT_MODBUS_TASK_DATA_DUMP
 | 
						|
    uint32_t i;
 | 
						|
 | 
						|
    iot_cus_printf("[mb_task]DUMP(%03d)@line:%d", len, line);
 | 
						|
    for (i = 0; i < len; i++) {
 | 
						|
        iot_cus_printf(" %02X", buf[i]);
 | 
						|
    }
 | 
						|
    iot_cus_printf("\n");
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_msg_post_to_uart() - send data to uart port.
 | 
						|
 * @param p_pkt_frame: pointer of pkt frame data buffer.
 | 
						|
 * @return ERR_OK
 | 
						|
 */
 | 
						|
uint32_t iot_mb_task_msg_post_to_uart(iot_uart_h uart_h, iot_pkt_t *p_pkt_frame)
 | 
						|
{
 | 
						|
    uint32_t ret;
 | 
						|
 | 
						|
    ret = iot_uart_send(uart_h, p_pkt_frame, NULL);
 | 
						|
 | 
						|
    return (ERR_OK == ret) ? ERR_OK : ERR_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
static uint32_t iot_mb_task_msg_msg_from_ge(iot_pkt_t *p_pkt_frame)
 | 
						|
{
 | 
						|
    ge_frame_data_send_set_subfn160_t *p_subfn160;
 | 
						|
    ge_fn160_appdata_mb_t *p_fn160_appdata; /* modbus proto in ge fn160 */
 | 
						|
    uint32_t fn160_applen;                  /* fn160 append data len */
 | 
						|
    iot_pkt_t *p_mb_pkt;        /* pkt for task message post to uart */
 | 
						|
    uint32_t mb_len;            /* current ge modbus frame length */
 | 
						|
    static uint8_t frame_idx_count; /* check current frame index order */
 | 
						|
    uint8_t slaver_addr = 0;
 | 
						|
    uint8_t src_mac[IOT_MAC_ADDR_LEN] = {0};
 | 
						|
 | 
						|
    if (p_pkt_frame == NULL) {
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
 | 
						|
    iot_cus_printf("[mb_task]frame receive from GE.\n");
 | 
						|
    iot_mb_task_data_dump(iot_pkt_data(p_pkt_frame),
 | 
						|
        iot_pkt_data_len(p_pkt_frame), __LINE__);
 | 
						|
 | 
						|
    p_subfn160 = (ge_frame_data_send_set_subfn160_t*)iot_pkt_data(p_pkt_frame);
 | 
						|
    if (p_subfn160->hdr.hdr.fn == PROTO_GE_PLC_SET_CMD
 | 
						|
        && p_subfn160->hdr.subfn == PROTO_GE_DATA_CMD) {
 | 
						|
        /* subfn160 appdata */
 | 
						|
        p_fn160_appdata = (ge_fn160_appdata_mb_t *)p_subfn160->data;
 | 
						|
        fn160_applen = p_subfn160->hdr.hdr.data_len - IOT_MAC_ADDR_LEN;
 | 
						|
        if (p_fn160_appdata->type == IOT_FN160_TYPE_MODBUS) {
 | 
						|
            iot_mac_addr_cpy(src_mac, p_fn160_appdata->src_mac);
 | 
						|
#if PLC_SUPPORT_STA_ROLE
 | 
						|
            /* save cco mac addr */
 | 
						|
            iot_mac_addr_cpy(mb_task.dest_cco_mac, p_fn160_appdata->src_mac);
 | 
						|
#endif
 | 
						|
            /* first frame need reset ge buff len and frame index check count */
 | 
						|
            if (p_fn160_appdata->frame_idx == 0) {
 | 
						|
                mb_task.ge_mb_len = 0;
 | 
						|
                frame_idx_count = 0;
 | 
						|
            }
 | 
						|
            /* Is the current frame index order correct?  */
 | 
						|
            if  (frame_idx_count != p_fn160_appdata->frame_idx) {
 | 
						|
                iot_cus_printf("[mb_task][err] ge frame index error\n");
 | 
						|
                frame_idx_count = 0;
 | 
						|
                iot_pkt_free(p_pkt_frame);
 | 
						|
                return ERR_FAIL;
 | 
						|
            } else {
 | 
						|
                frame_idx_count++;
 | 
						|
            }
 | 
						|
            /* remove other append data, get modbus data length */
 | 
						|
            mb_len = fn160_applen - sizeof(ge_fn160_appdata_mb_t);
 | 
						|
            /* remain ge buffer size >= current modbus frame size. */
 | 
						|
            if (mb_len <= sizeof(mb_task.ge_mb_buf) - mb_task.ge_mb_len) {
 | 
						|
                /* copy current modbus data to ge buff offset index */
 | 
						|
                os_mem_cpy(mb_task.ge_mb_buf + mb_task.ge_mb_len ,
 | 
						|
                    p_fn160_appdata->data, mb_len);
 | 
						|
                mb_task.ge_mb_len += mb_len;
 | 
						|
            } else {
 | 
						|
                iot_cus_printf("[mb_task][warning] ge modbus data overflow, dropped!!!\n");
 | 
						|
            }
 | 
						|
            iot_pkt_free(p_pkt_frame);
 | 
						|
 | 
						|
            /* last modbus frame, malloc pkt, then send modbus pkt to uart. */
 | 
						|
            if (p_fn160_appdata->frame_idx == p_fn160_appdata->frame_total - 1) {
 | 
						|
 | 
						|
                if (mb_task.ge_mb_len) {
 | 
						|
                    p_mb_pkt = iot_pkt_alloc(mb_task.ge_mb_len, IOT_MODBUS_TASK_ID);
 | 
						|
                    if (NULL == p_mb_pkt) {
 | 
						|
                        iot_cus_printf("[mb_task][err]no mem@line %d\n", __LINE__);
 | 
						|
                        IOT_ASSERT(0);
 | 
						|
                        return ERR_FAIL;
 | 
						|
                    }
 | 
						|
 | 
						|
                    os_mem_cpy(iot_pkt_put(p_mb_pkt, mb_task.ge_mb_len),
 | 
						|
                        mb_task.ge_mb_buf, mb_task.ge_mb_len);
 | 
						|
 | 
						|
                    slaver_addr = iot_mb_task_get_slaver_addr(mb_task.ge_mb_buf);
 | 
						|
#if IOT_MODBUS_RT_TABLE_SUPPORT
 | 
						|
                    if (slaver_addr != IOT_MODBUS_BROADCAST_ADDR) {
 | 
						|
                        /* add rt entry */
 | 
						|
                        iot_modbus_add_addr_rt(mb_task.rt_table, src_mac, slaver_addr);
 | 
						|
                    }
 | 
						|
#endif
 | 
						|
 | 
						|
                    if ((slaver_addr == mb_task.slave_addr) ||
 | 
						|
                        (IOT_MODBUS_BROADCAST_ADDR == slaver_addr)) {
 | 
						|
                        iot_mb_ext_cmd_handler(mb_task.ge_mb_buf, mb_task.ge_mb_len,
 | 
						|
                            MODBUS_CMD_FROM_PLC);
 | 
						|
                    }
 | 
						|
 | 
						|
                    mb_task.ge_mb_len = 0;
 | 
						|
                    frame_idx_count = 0;
 | 
						|
 | 
						|
                    if ((slaver_addr != mb_task.slave_addr) ||
 | 
						|
                        (IOT_MODBUS_BROADCAST_ADDR == slaver_addr)) {
 | 
						|
                        iot_mb_task_msg_post_to_uart(mb_task.uart_h, p_mb_pkt);
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            goto out;
 | 
						|
        }
 | 
						|
        goto ge2uart;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ERR_OK == iot_mb_ext_handle_resp_from_ge(p_pkt_frame)) {
 | 
						|
        iot_pkt_free(p_pkt_frame);
 | 
						|
        goto out;
 | 
						|
    }
 | 
						|
ge2uart:
 | 
						|
    iot_mb_task_msg_post_to_uart(mb_task.uart_h, p_pkt_frame);
 | 
						|
out:
 | 
						|
    return ERR_OK;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_post_uart_cmd() - recveived command from uart, send to
 | 
						|
 *                                       common proto
 | 
						|
 * @param data: command data.
 | 
						|
 * @param len : command data length.
 | 
						|
 * @return    : ERR_OK   - send successfully.
 | 
						|
 *              ERR_FAIL - send failed.
 | 
						|
 */
 | 
						|
uint8_t iot_mb_task_post_uart_cmd(uint8_t * data, uint16_t len, uint32_t param)
 | 
						|
{
 | 
						|
    (void)param;
 | 
						|
    iot_pkt_t* send_pkt;
 | 
						|
 | 
						|
    iot_cus_printf("[%s][info] data:%p, len:%d\n", __FUNCTION__, data, len);
 | 
						|
 | 
						|
    send_pkt = iot_pkt_alloc(len, IOT_MODBUS_TASK_ID);
 | 
						|
    if (send_pkt) {
 | 
						|
        /* copy data from buf to data packet */
 | 
						|
        os_mem_cpy(iot_pkt_put(send_pkt, len), data, len);
 | 
						|
 | 
						|
        /* alloc message to insert proto task msg queue */
 | 
						|
        iot_mb_task_msg_post(IOT_MODBUS_TASK_MT_UART,
 | 
						|
              IOT_MODBUS_TASK_MSG_ID_CMD_HANDLE, send_pkt);
 | 
						|
        return ERR_OK;
 | 
						|
    } else {
 | 
						|
        iot_cus_printf("[mb_task][err]no mem@line %d\n", __LINE__);
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return ERR_FAIL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* Compute the MODBUS RTU CRC. */
 | 
						|
uint16_t iot_modbus_rtu_crc16(uint8_t *buf, uint32_t len)
 | 
						|
{
 | 
						|
    uint16_t crc = 0xFFFF;
 | 
						|
 | 
						|
    for (uint32_t pos = 0; pos < len; pos++) {
 | 
						|
        crc ^= (uint16_t)buf[pos];        /* XOR byte into least sig. byte of crc */
 | 
						|
        for (uint8_t i = 8; i != 0; i--) {/* Loop over each bit */
 | 
						|
            if ((crc & 0x0001) != 0) {    /* If the LSB is set */
 | 
						|
                crc >>= 1;                /* Shift right and XOR 0xA001 */
 | 
						|
                crc ^= 0xA001;
 | 
						|
            } else {                      /* Else LSB is not set */
 | 
						|
                crc >>= 1;                /* Just shift right */
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    /* Note, this number has low and high bytes swapped,
 | 
						|
    so use it accordingly (or swap bytes) */
 | 
						|
    return crc;
 | 
						|
}
 | 
						|
 | 
						|
iot_pkt_t *iot_modbus_fn160_appdata_pack(uint8_t *mb_data, uint32_t mb_len,
 | 
						|
    uint32_t curr_idx, uint32_t total_idx)
 | 
						|
{
 | 
						|
    ge_frame_data_send_set_subfn160_t *p_subfn160;
 | 
						|
    ge_fn160_appdata_mb_t *p_fn160_appdata;
 | 
						|
    uint32_t appdata_len = sizeof(ge_fn160_appdata_mb_t) + mb_len;
 | 
						|
    /* subfn160 header + appdata + crc16(2 bytes) + proto end frame(1 bytes) */
 | 
						|
    uint32_t alloc_len = sizeof(ge_frame_data_send_set_subfn160_t) + appdata_len
 | 
						|
        + 2 + 1;
 | 
						|
    uint16_t crc16;
 | 
						|
    iot_pkt_t* p_ge_pkt;
 | 
						|
 | 
						|
    p_ge_pkt = iot_pkt_alloc(alloc_len, IOT_MODBUS_TASK_ID);
 | 
						|
    if (NULL == p_ge_pkt) {
 | 
						|
        iot_cus_printf("[mb_task][err]no mem@line %d\n", __LINE__);
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    p_subfn160 = (ge_frame_data_send_set_subfn160_t*)iot_pkt_put(p_ge_pkt, alloc_len);
 | 
						|
    /* fix header */
 | 
						|
    p_subfn160->hdr.hdr.preamble = GE_FRM_PREAMBLE_CODE;
 | 
						|
    p_subfn160->hdr.hdr.fn = PROTO_GE_PLC_SET_CMD;
 | 
						|
    p_subfn160->hdr.hdr.data_len = appdata_len + IOT_MAC_ADDR_LEN;
 | 
						|
    p_subfn160->hdr.subfn = PROTO_GE_DATA_CMD;
 | 
						|
    /* resv 2 bytes */
 | 
						|
    p_subfn160->force_tx_connless = 0;
 | 
						|
    p_subfn160->force_noaggr = 1;
 | 
						|
    p_subfn160->recv_connless = 0;
 | 
						|
    p_subfn160->data_type = 0;
 | 
						|
    /* payload */
 | 
						|
#if PLC_SUPPORT_STA_ROLE
 | 
						|
    iot_mac_addr_cpy(p_subfn160->dest_mac, mb_task.dest_cco_mac);
 | 
						|
#endif
 | 
						|
#if IOT_MODBUS_RT_TABLE_SUPPORT
 | 
						|
    uint8_t dest_mac[IOT_MAC_ADDR_LEN];
 | 
						|
    uint8_t slave_addr = iot_mb_task_get_slaver_addr(mb_data);
 | 
						|
    if (ERR_OK != iot_modbus_get_addr_rt(mb_task.rt_table, slave_addr, dest_mac)) {
 | 
						|
        os_mem_set(p_subfn160->dest_mac, 0xff, IOT_MAC_ADDR_LEN);
 | 
						|
    } else {
 | 
						|
        iot_mac_addr_cpy(p_subfn160->dest_mac, dest_mac);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    /* subfn160 appdata */
 | 
						|
    p_fn160_appdata = (ge_fn160_appdata_mb_t *)p_subfn160->data;
 | 
						|
    p_fn160_appdata->type = IOT_FN160_TYPE_MODBUS; /* modbus proto */
 | 
						|
    iot_mac_addr_cpy(p_fn160_appdata->src_mac, mb_task.local_mac);
 | 
						|
    p_fn160_appdata->frame_idx = curr_idx;
 | 
						|
    p_fn160_appdata->frame_total = total_idx;
 | 
						|
    /* modbus raw data */
 | 
						|
    os_mem_cpy(p_fn160_appdata->data, mb_data, mb_len);
 | 
						|
 | 
						|
    crc16 = ge_frm_checksum_calc((uint8_t *)p_subfn160, alloc_len - 3);
 | 
						|
    *((uint8_t*)p_subfn160 + alloc_len - 3) = crc16 & 0xff;
 | 
						|
    *((uint8_t*)p_subfn160 + alloc_len - 2) = (crc16 >> 8) & 0xff;
 | 
						|
    *((uint8_t*)p_subfn160 + alloc_len - 1) = GE_FRM_TAIL_CODE;
 | 
						|
 | 
						|
    return p_ge_pkt;
 | 
						|
}
 | 
						|
 | 
						|
static uint8_t iot_modbus_data_check(uint8_t *p_buffer, uint32_t buffer_len)
 | 
						|
{
 | 
						|
    iot_pkt_t *p_pkt;
 | 
						|
    uint32_t buf_index;
 | 
						|
    uint32_t buf_offset;
 | 
						|
    uint32_t buf_len;
 | 
						|
    uint32_t curr_idx;
 | 
						|
    uint32_t total_idx;
 | 
						|
    uint32_t lookup_fc_idx; //look up func code index
 | 
						|
    uint32_t mb_total_len;
 | 
						|
    uint16_t crc16;
 | 
						|
    uint8_t have_modbus_frame = 0, slaver_addr = 0;
 | 
						|
 | 
						|
    for (buf_index = 0; (buffer_len >= 5) && (buf_index <= buffer_len - 5); ) {
 | 
						|
        uint8_t *p_buf_index = p_buffer + buf_index;
 | 
						|
        iot_cus_printf("index=%d\r\n", buf_index);
 | 
						|
        /* lookup function code index */
 | 
						|
        for (lookup_fc_idx = 0; lookup_fc_idx < max_func_code_num; lookup_fc_idx++) {
 | 
						|
            if (mb_check[lookup_fc_idx].func_code == p_buf_index[1] ||
 | 
						|
                (mb_check[lookup_fc_idx].func_code | 0x80) == p_buf_index[1]) {
 | 
						|
                iot_cus_printf("func_code=%d\r\n", p_buf_index[1]);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        /* can not find valid func code */
 | 
						|
        if (lookup_fc_idx == max_func_code_num) {
 | 
						|
            buf_index++;
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        /* from func code get modbus total len, then checkout modbus crc16 */
 | 
						|
        if ((p_buf_index[1] & 0x80) == 0) { /* normal function code */
 | 
						|
            mb_total_len = mb_check[lookup_fc_idx].min_len +
 | 
						|
                (mb_check[lookup_fc_idx].not_fix_len ?
 | 
						|
                    p_buf_index[mb_check[lookup_fc_idx].byte_count_idx] : 0);
 | 
						|
        } else { /* error function code */
 | 
						|
            mb_total_len = 5;
 | 
						|
        }
 | 
						|
        iot_cus_printf("mb_total_len=%d, buffer_len-index=%d\r\n",
 | 
						|
            mb_total_len,  (buffer_len - buf_index));
 | 
						|
        /* modbus lenth <= remain buffer lenth. */
 | 
						|
        if (mb_total_len > buffer_len - buf_index) {
 | 
						|
            buf_index++;
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        /* check modbus crc */
 | 
						|
        crc16 = iot_modbus_rtu_crc16(p_buf_index, mb_total_len - 2);
 | 
						|
        if (crc16 !=
 | 
						|
            (((uint16_t)p_buf_index[mb_total_len-1]<<8) | p_buf_index[mb_total_len-2])) {
 | 
						|
            buf_index++;
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        iot_cus_printf("uart----------------------modbus\r\n");
 | 
						|
 | 
						|
        slaver_addr = iot_mb_task_get_slaver_addr(p_buf_index);
 | 
						|
 | 
						|
        if ((slaver_addr != mb_task.slave_addr) ||
 | 
						|
            (IOT_MODBUS_BROADCAST_ADDR == slaver_addr)) {
 | 
						|
            total_idx = (mb_total_len /
 | 
						|
                (IOT_GE_FE_A0_DATA_LEN_MAX - sizeof(ge_fn160_appdata_mb_t))) + 1;
 | 
						|
            /* front frame */
 | 
						|
            for (curr_idx = 0; curr_idx < total_idx - 1; curr_idx++) {
 | 
						|
                buf_offset = (IOT_GE_FE_A0_DATA_LEN_MAX -
 | 
						|
                    sizeof(ge_fn160_appdata_mb_t)) * curr_idx;
 | 
						|
                buf_len = IOT_GE_FE_A0_DATA_LEN_MAX - sizeof(ge_fn160_appdata_mb_t);
 | 
						|
                p_pkt = iot_modbus_fn160_appdata_pack(p_buf_index + buf_offset,
 | 
						|
                    buf_len, curr_idx, total_idx);
 | 
						|
                if (NULL == p_pkt) {
 | 
						|
                    iot_cus_printf("[mb_task][err]no mem@line %d\n", __LINE__);
 | 
						|
                    IOT_ASSERT(0);
 | 
						|
                    return -1;
 | 
						|
                }
 | 
						|
                iot_mb_task_data_dump(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt), __LINE__);
 | 
						|
                /* 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);
 | 
						|
            }
 | 
						|
            /* last frame */
 | 
						|
            buf_offset = (IOT_GE_FE_A0_DATA_LEN_MAX -
 | 
						|
                sizeof(ge_fn160_appdata_mb_t)) * curr_idx;
 | 
						|
            buf_len = mb_total_len % (IOT_GE_FE_A0_DATA_LEN_MAX -
 | 
						|
                sizeof(ge_fn160_appdata_mb_t));
 | 
						|
            p_pkt = iot_modbus_fn160_appdata_pack(p_buf_index + buf_offset, buf_len,
 | 
						|
                curr_idx, total_idx);
 | 
						|
            if (NULL == p_pkt) {
 | 
						|
                iot_cus_printf("[mb_task][err]no mem@line %d\n", __LINE__);
 | 
						|
                IOT_ASSERT(0);
 | 
						|
                return -1;
 | 
						|
            }
 | 
						|
            iot_mb_task_data_dump(iot_pkt_data(p_pkt), iot_pkt_data_len(p_pkt), __LINE__);
 | 
						|
            /* 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);
 | 
						|
        }
 | 
						|
 | 
						|
        if ((slaver_addr == mb_task.slave_addr) ||
 | 
						|
            (IOT_MODBUS_BROADCAST_ADDR == slaver_addr)) {
 | 
						|
            iot_mb_ext_cmd_handler(p_buf_index, mb_total_len, MODBUS_CMD_FROM_UART);
 | 
						|
        }
 | 
						|
 | 
						|
        buf_index += mb_total_len;
 | 
						|
        have_modbus_frame = 1;
 | 
						|
    }
 | 
						|
    return have_modbus_frame;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_uart_msg_process() - process the data from uart.
 | 
						|
 * @param p_modbus_msg: message received from uart. msg->data will be
 | 
						|
 *   freed by this handle but msg will not.
 | 
						|
 */
 | 
						|
static void iot_mb_task_uart_msg_process(iot_mb_task_msg_t *msg)
 | 
						|
{
 | 
						|
    iot_pkt_t * p_pkt = (iot_pkt_t*)msg->data;
 | 
						|
 | 
						|
    switch (msg->task_msg.id) {
 | 
						|
        case IOT_MODBUS_TASK_MSG_ID_CMD_HANDLE:
 | 
						|
        {
 | 
						|
            /* trans to GE command */
 | 
						|
            iot_cus_task_message_to_ge(iot_pkt_data(p_pkt),
 | 
						|
                iot_pkt_data_len(p_pkt));
 | 
						|
            iot_pkt_free(p_pkt);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        default:
 | 
						|
        {
 | 
						|
            iot_cus_printf("[mb_task]unknown uart message id #%d.\n",
 | 
						|
                msg->task_msg.id);
 | 
						|
            IOT_ASSERT(0);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_timer_msg_process() - process data from local timer.
 | 
						|
 * @msg : message.
 | 
						|
 */
 | 
						|
static void iot_mb_task_timer_msg_process(iot_mb_task_msg_t *msg)
 | 
						|
{
 | 
						|
    switch (msg->task_msg.id) {
 | 
						|
        case IOT_MODBUS_TASK_MSG_ID_TMR_GE_START_MONITOR:
 | 
						|
        {
 | 
						|
            if (iot_grapp_init_success()) {
 | 
						|
                iot_grapp_reg_fn_receive_from_ge(HOST_PORT_CUSTOM_TASK,
 | 
						|
                    iot_mb_task_msg_msg_from_ge);
 | 
						|
                iot_grapp_set_uart_config(mb_task.uart_h);
 | 
						|
                os_stop_timer(mb_task.ge_start_timer);
 | 
						|
                /* update local mac addr. */
 | 
						|
                iot_mac_addr_cpy(mb_task.local_mac, prototask_contxt.local_dev.mac);
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        case IOT_MODBUS_TASK_MSG_ID_TMR_UART_MB_TIMEOUT:
 | 
						|
        {
 | 
						|
            if (mb_task.uart_mb_len > 0) {
 | 
						|
                /* if not have modbus frame, then send data use ge proto. */
 | 
						|
                if (iot_modbus_data_check(mb_task.uart_mb_buf,
 | 
						|
                    mb_task.uart_mb_len) == 0) {
 | 
						|
                    iot_cus_printf("uart----------------------ge\r\n");
 | 
						|
                    /* parser ge command and post to task */
 | 
						|
                    iot_proto_data_parse_and_post(mb_task.uart_mb_buf,
 | 
						|
                        mb_task.uart_mb_len, iot_mb_task_post_uart_cmd, 0);
 | 
						|
                }
 | 
						|
                mb_task.uart_mb_len = 0;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        }
 | 
						|
#if IOT_MODBUS_RT_TABLE_SUPPORT
 | 
						|
        case IOT_MODBUS_TASK_MSG_ID_TMR_RT_UPDATE_TIMEOUT:
 | 
						|
        {
 | 
						|
            iot_modbus_update_addr_rt(mb_task.rt_table);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
#endif
 | 
						|
        case IOT_MODBUS_MSG_ID_TMR_MB_EXT_RESP_TIMEOUT:
 | 
						|
        {
 | 
						|
            iot_mb_ext_resp_cmd_timeout_or_failed();
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        default:
 | 
						|
        {
 | 
						|
            iot_cus_printf("[mb_task]unknown timer message id #%d.\n",
 | 
						|
                msg->task_msg.id);
 | 
						|
            IOT_ASSERT(0);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_internal_msg_process() - process the data from modbus-task.
 | 
						|
 * @param msg: message received from modbus-task. msg->data
 | 
						|
 *   will be freed by this handle but msg will not.
 | 
						|
 */
 | 
						|
static void iot_mb_task_internal_msg_process(iot_mb_task_msg_t *msg)
 | 
						|
{
 | 
						|
    iot_pkt_t * p_pkt = (iot_pkt_t*)msg->data;
 | 
						|
    uint8_t *p_data = NULL;
 | 
						|
    uint32_t data_len = 0;
 | 
						|
 | 
						|
    switch (msg->task_msg.id) {
 | 
						|
        case IOT_MODBUS_TASK_MSG_ID_CMD_HANDLE:
 | 
						|
        {
 | 
						|
            p_data = iot_pkt_data(p_pkt);
 | 
						|
            data_len = iot_pkt_data_len(p_pkt);
 | 
						|
            iot_cus_printf("uart buf index=%d\n", mb_task.uart_mb_len);
 | 
						|
            /* save all uart data to uart recv buff, if timer timeout, task begin to
 | 
						|
            checkout modbus frame. */
 | 
						|
            if (data_len <= sizeof(mb_task.uart_mb_buf) - mb_task.uart_mb_len) {
 | 
						|
                /* copy data to uart recv buffer. */
 | 
						|
                os_mem_cpy(mb_task.uart_mb_buf + mb_task.uart_mb_len, p_data, data_len);
 | 
						|
                mb_task.uart_mb_len += data_len;
 | 
						|
            } else {
 | 
						|
                iot_cus_printf("[mb_task][warning] uart modbus data overflow, dropped!!!\n");
 | 
						|
            }
 | 
						|
            iot_pkt_free(p_pkt);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        default:
 | 
						|
        {
 | 
						|
            IOT_ASSERT(0);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_msg_exe_func() - messages handle function.
 | 
						|
 * @param task_h: handle of task.
 | 
						|
 * @param p_msg: message that will be processed.
 | 
						|
 */
 | 
						|
static void iot_mb_task_msg_exe_func(iot_task_h task_h, iot_task_msg_t *p_msg)
 | 
						|
{
 | 
						|
    iot_mb_task_msg_t *p_mb_msg = (iot_mb_task_msg_t *)p_msg;
 | 
						|
 | 
						|
    switch (p_mb_msg->task_msg.type)
 | 
						|
    {
 | 
						|
        case IOT_MODBUS_TASK_MT_UART:
 | 
						|
        {
 | 
						|
            iot_mb_task_uart_msg_process(p_mb_msg);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        case IOT_MODBUS_TASK_MT_TIMER:
 | 
						|
        {
 | 
						|
            iot_mb_task_timer_msg_process(p_mb_msg);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        case IOT_MODBUS_TASK_MT_INTERNAL:
 | 
						|
        {
 | 
						|
            iot_mb_task_internal_msg_process(p_mb_msg);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        default:
 | 
						|
        {
 | 
						|
            if (NULL != p_mb_msg->data) {
 | 
						|
                iot_pkt_free(p_mb_msg->data);
 | 
						|
            }
 | 
						|
            IOT_ASSERT(0);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    iot_task_free_msg(task_h, p_msg);
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_msg_cancel_func() - pull back messages that sent to this
 | 
						|
 *   task.
 | 
						|
 * @param task_h: handle of task.
 | 
						|
 * @param p_msg: message that will be pull back.
 | 
						|
 */
 | 
						|
static void iot_mb_task_msg_cancel_func(iot_task_h task_h, iot_task_msg_t *p_msg)
 | 
						|
{
 | 
						|
    iot_mb_task_msg_t *p_mb_msg = (iot_mb_task_msg_t *)p_msg;
 | 
						|
 | 
						|
    switch(p_mb_msg->task_msg.type)
 | 
						|
    {
 | 
						|
        case IOT_MODBUS_TASK_MT_UART:
 | 
						|
        case IOT_MODBUS_TASK_MT_TIMER:
 | 
						|
        case IOT_MODBUS_TASK_MT_INTERNAL:
 | 
						|
        {
 | 
						|
            iot_pkt_free(p_mb_msg->data);
 | 
						|
        }
 | 
						|
        default:
 | 
						|
        {
 | 
						|
            IOT_ASSERT(0);
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    iot_task_free_msg(task_h, p_msg);
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_uart_receive_func() - Uart driver callback function
 | 
						|
 *   when data received.
 | 
						|
 * @param buffer: pointer of data buffer.
 | 
						|
 * @param buffer_len: length of data received.
 | 
						|
 * @param is_full_frame: tell if this is a whole frame in this buffer.
 | 
						|
 * @param invalid_data_len: length of invalid data received. we ignore this.
 | 
						|
 */
 | 
						|
static void iot_mb_task_uart_receive_func(uint8_t* p_buffer, uint32_t buffer_len,
 | 
						|
    bool_t is_full_frame, uint32_t invalid_data_len)
 | 
						|
{
 | 
						|
    iot_pkt_t *p_pkt;
 | 
						|
 | 
						|
    iot_cus_printf("[mb_task] uart received, len:%d \n", buffer_len);
 | 
						|
    iot_mb_task_data_dump(p_buffer, buffer_len, __LINE__);
 | 
						|
 | 
						|
    /* timer to montor uart recv data timeout. */
 | 
						|
    if (0 == os_is_timer_active(mb_task.uart_timer)) {
 | 
						|
        iot_cus_printf("start timer\n");
 | 
						|
       os_start_timer(mb_task.uart_timer, IOT_MODBUS_TASK_UART_MB_TIMER_PERIOD);
 | 
						|
    } else {
 | 
						|
        iot_cus_printf("reset timer\n");
 | 
						|
        os_reset_timer(mb_task.uart_timer);
 | 
						|
    }
 | 
						|
    p_pkt = iot_pkt_alloc(buffer_len, IOT_MODBUS_TASK_ID);
 | 
						|
    if (p_pkt) {
 | 
						|
        /* copy data from buf to data packet */
 | 
						|
        os_mem_cpy(iot_pkt_put(p_pkt, buffer_len), p_buffer, buffer_len);
 | 
						|
        /* alloc message to insert proto task msg queue */
 | 
						|
        iot_mb_task_msg_post(IOT_MODBUS_TASK_MT_INTERNAL,
 | 
						|
              IOT_MODBUS_TASK_MSG_ID_CMD_HANDLE, p_pkt);
 | 
						|
    } else {
 | 
						|
        iot_cus_printf("[mb_task][err]no mem@line %d\n", __LINE__);
 | 
						|
        IOT_ASSERT(0);
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
void iot_mb_task_msg_post(uint16_t msg_type, uint16_t msg_id, iot_pkt_t *data)
 | 
						|
{
 | 
						|
    iot_task_msg_t *msg;
 | 
						|
    iot_mb_task_msg_t *task_msg;
 | 
						|
 | 
						|
    msg = iot_task_alloc_msg_with_reserved(mb_task.task, 0);
 | 
						|
    if (NULL == msg) {
 | 
						|
        if (NULL != data) {
 | 
						|
            iot_pkt_free(data);
 | 
						|
        }
 | 
						|
        IOT_ASSERT(0);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    task_msg = (iot_mb_task_msg_t*)msg;
 | 
						|
    task_msg->task_msg.type = msg_type;
 | 
						|
    task_msg->task_msg.id = msg_id;
 | 
						|
    task_msg->data = data;
 | 
						|
    task_msg->data2 = 0;
 | 
						|
    iot_task_queue_msg(mb_task.task, &task_msg->task_msg, 0);
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_ge_start_timer_exe() - timer timeout callback function.
 | 
						|
 * @timer_id : timer id with that timer who causes this api-call.
 | 
						|
 * @arg : param past to this callback api.
 | 
						|
 */
 | 
						|
static void iot_mb_task_ge_start_timer_exe(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)arg;
 | 
						|
    if (timer_id == mb_task.ge_start_timer) {
 | 
						|
        iot_mb_task_msg_post(IOT_MODBUS_TASK_MT_TIMER,
 | 
						|
            IOT_MODBUS_TASK_MSG_ID_TMR_GE_START_MONITOR, NULL);
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_uart_mb_timer_exe() - timer timeout callback function.
 | 
						|
 * @timer_id : timer id with that timer who causes this api-call.
 | 
						|
 * @arg : param past to this callback api.
 | 
						|
 */
 | 
						|
static void iot_mb_task_uart_mb_timer_exe(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)arg;
 | 
						|
    if (timer_id == mb_task.uart_timer) {
 | 
						|
        iot_mb_task_msg_post(IOT_MODBUS_TASK_MT_TIMER,
 | 
						|
            IOT_MODBUS_TASK_MSG_ID_TMR_UART_MB_TIMEOUT, NULL);
 | 
						|
        os_stop_timer(timer_id);
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_ext_resp_timer_exe() - timer timeout callback function.
 | 
						|
 * @timer_id : timer id with that timer who causes this api-call.
 | 
						|
 * @arg : param past to this callback api.
 | 
						|
 */
 | 
						|
void iot_mb_ext_resp_timer_exe(timer_id_t timer_id, void * arg)
 | 
						|
{
 | 
						|
    (void)arg;
 | 
						|
    if (timer_id == mb_task.mb_ext_resp_timer) {
 | 
						|
        iot_mb_ext_resp_cmd_timeout_or_failed();
 | 
						|
    }
 | 
						|
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_deinit() - Uninitialize modbus task.
 | 
						|
 */
 | 
						|
static void iot_mb_task_deinit(void)
 | 
						|
{
 | 
						|
    iot_cus_printf("[mb_task]mb_task deinit!\n");
 | 
						|
    if (NULL != mb_task.uart_h) {
 | 
						|
        iot_uart_close(mb_task.uart_h);
 | 
						|
    }
 | 
						|
    if (NULL != mb_task.task) {
 | 
						|
        iot_task_delete(mb_task.task);
 | 
						|
        mb_task.task = NULL;
 | 
						|
    }
 | 
						|
    if (0 != mb_task.ge_start_timer) {
 | 
						|
        os_delete_timer(mb_task.ge_start_timer);
 | 
						|
        mb_task.ge_start_timer = 0;
 | 
						|
    }
 | 
						|
    if (0 != mb_task.uart_timer) {
 | 
						|
        os_delete_timer(mb_task.uart_timer);
 | 
						|
        mb_task.uart_timer = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    os_mem_set(&mb_task, 0x0, sizeof(iot_mb_task_t));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief iot_mb_task_init() - Initialize modbus task.
 | 
						|
 */
 | 
						|
static uint32_t iot_mb_task_init(void)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_OK;
 | 
						|
    iot_task_config_t task_cfg;
 | 
						|
    uint8_t uart_port;
 | 
						|
 | 
						|
    iot_cus_printf("[mb_task]mb_task init!\n");
 | 
						|
 | 
						|
    /* task configration. */
 | 
						|
    os_mem_set(&task_cfg, 0x0, sizeof(task_cfg));
 | 
						|
    task_cfg.stack_size = IOT_MODBUS_TASK_TASK_STACK_SIZE;
 | 
						|
    task_cfg.task_prio = IOT_MODBUS_TASK_PROTO_TASK_PRIO;
 | 
						|
    task_cfg.msg_size = sizeof(iot_mb_task_msg_t);
 | 
						|
    task_cfg.msg_cnt = IOT_MODBUS_TASK_TASK_POOL_SIZE;
 | 
						|
    task_cfg.queue_cnt = 1;
 | 
						|
    task_cfg.queue_cfg[0].quota = 0;
 | 
						|
    task_cfg.task_event_func = NULL;
 | 
						|
    task_cfg.msg_exe_func = iot_mb_task_msg_exe_func;
 | 
						|
    task_cfg.msg_cancel_func = iot_mb_task_msg_cancel_func;
 | 
						|
 | 
						|
    os_mem_set(&mb_task, 0, sizeof(iot_mb_task_t));
 | 
						|
 | 
						|
    /* default value of slave address is 0xff. */
 | 
						|
    mb_task.slave_addr = IOT_MODBUS_DEFAULT_SLAVER_ADDR;
 | 
						|
 | 
						|
    /* IIC:0x3D0A0108(61.10.1.8) */
 | 
						|
    iot_cus_printf("[mb_task]hardware ver:%08x\n", iot_board_hw_version_hex());
 | 
						|
    uart_port = iot_board_get_uart(UART_RS485_PORT);
 | 
						|
    if (uart_port >= iot_uart_get_max_port_num()) {
 | 
						|
        iot_cus_printf("[mb_task]open 485 port err, try to open meter port\n");
 | 
						|
        uart_port = iot_board_get_uart(UART_METER_PORT);
 | 
						|
        /* if need to set meter port as rs485,
 | 
						|
         * use function iot_uart_enable_rs485 after iot_uart_open success.
 | 
						|
         * iot_uart_enable_rs485(mb_task.uart_h,
 | 
						|
         *     iot_board_get_gpio(GPIO_RS485_TXE))
 | 
						|
         */
 | 
						|
    }
 | 
						|
    mb_task.uart_h = iot_uart_open(uart_port,
 | 
						|
        iot_mb_task_uart_receive_func, IOT_MODBUS_TASK_UART_BUF_SIZE, NULL);
 | 
						|
    if (NULL == mb_task.uart_h) {
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto init_err_handle;
 | 
						|
    }
 | 
						|
 | 
						|
    mb_task.task = iot_task_create(IOT_MODBUS_TASK_ID, &task_cfg);
 | 
						|
    if (NULL == mb_task.task) {
 | 
						|
        iot_cus_printf("[mb_task]create task failed.\n");
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto init_err_handle;
 | 
						|
    }
 | 
						|
 | 
						|
    /* ge start monitor timer. */
 | 
						|
    mb_task.ge_start_timer = os_create_timer(IOT_MODBUS_TASK_ID, true,
 | 
						|
        iot_mb_task_ge_start_timer_exe, NULL);
 | 
						|
    if (0 == mb_task.ge_start_timer) {
 | 
						|
        iot_cus_printf("[mb_task]create ge start timer failed.\n");
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto init_err_handle;
 | 
						|
    }
 | 
						|
    os_start_timer(mb_task.ge_start_timer, IOT_MODBUS_TASK_GE_START_TIMER_PERIOD);
 | 
						|
 | 
						|
    /* uart mmodbus recv monitor timer. */
 | 
						|
    mb_task.uart_timer = os_create_timer(IOT_MODBUS_TASK_ID, true,
 | 
						|
        iot_mb_task_uart_mb_timer_exe, NULL);
 | 
						|
    if (0 == mb_task.uart_timer) {
 | 
						|
        iot_cus_printf("[mb_task]create uart modbus timer failed.\n");
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto init_err_handle;
 | 
						|
    }
 | 
						|
 | 
						|
    /* modbus ext resp timer. */
 | 
						|
    mb_task.mb_ext_resp_timer = os_create_timer(IOT_MODBUS_TASK_ID, true,
 | 
						|
        iot_mb_ext_resp_timer_exe, NULL);
 | 
						|
    if (0 == mb_task.mb_ext_resp_timer) {
 | 
						|
        iot_cus_printf("[mb_task]create mb_ext resp timer failed.\n");
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto init_err_handle;
 | 
						|
    }
 | 
						|
 | 
						|
#if IOT_MODBUS_RT_TABLE_SUPPORT
 | 
						|
 | 
						|
    mb_task.rt_table = iot_modbus_addr_rout_table_create(IOT_MODBUS_TASK_ID,
 | 
						|
            IOT_MODBUS_MAC_RT_ENTRY_MAX, sizeof(iot_modbus_addr_rout_entry_t));
 | 
						|
 | 
						|
    /* rout table update timer. */
 | 
						|
    mb_task.rt_update_timer = os_create_timer(IOT_MODBUS_TASK_ID, true,
 | 
						|
        iot_mb_task_rt_update_timer_exe, mb_task.rt_table);
 | 
						|
    if (0 == mb_task.rt_update_timer) {
 | 
						|
        iot_cus_printf("[%s][err]create route talbe update timer failed.\n", __FUNCTION__);
 | 
						|
        ret = ERR_FAIL;
 | 
						|
        goto init_err_handle;
 | 
						|
    }
 | 
						|
    os_start_timer(mb_task.rt_update_timer, IOT_MODBUS_TASK_RT_TIMER_PERIOD);
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
    iot_cus_printf("[mb_task]task create successfully.\n");
 | 
						|
 | 
						|
    goto out;
 | 
						|
 | 
						|
init_err_handle:
 | 
						|
    iot_mb_task_deinit();
 | 
						|
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t app_modbus_task_entry(void)
 | 
						|
{
 | 
						|
    uint32_t ret = ERR_PENDING;
 | 
						|
 | 
						|
    if (ERR_OK == iot_mb_task_init()) {
 | 
						|
        ret = ERR_OK;
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* IOT_GE_EXT_TASK_ENABLE */
 |