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 */
|