261 lines
7.1 KiB
C
261 lines
7.1 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.
|
|
|
|
****************************************************************************/
|
|
|
|
/* common includes */
|
|
#include "iot_errno.h"
|
|
#include "iot_module.h"
|
|
#include "iot_config.h"
|
|
#include "iot_utils.h"
|
|
#include "iot_ipc.h"
|
|
#include "iot_plc_api.h"
|
|
#include "iot_dbglog_api.h"
|
|
#include "iot_task.h"
|
|
#include "iot_oem_api.h"
|
|
|
|
/* plc lib internal includes */
|
|
#include "plc_lib_internal.h"
|
|
|
|
#ifndef PLC_LIB_STANDALONE_TASK
|
|
#define PLC_LIB_STANDALONE_TASK 0
|
|
#endif
|
|
|
|
#ifndef PLC_LIB_TASK_PRIO
|
|
#define PLC_LIB_TASK_PRIO 7
|
|
#endif
|
|
|
|
plc_lib_global_t *p_plc_lib = NULL;
|
|
|
|
static inline void plc_lib_handle_ipc_event(plc_lib_global_t *glb,
|
|
iot_pkt_t *buf)
|
|
{
|
|
iot_pkt_t *tmp_pkt = NULL;
|
|
iot_plc_msg_header_t *header = NULL;
|
|
iot_plc_app_t *app = NULL;
|
|
uint8_t index = 0;
|
|
uint32_t buf_len = 0;
|
|
|
|
|
|
/* as the message is delivered from internal plc stack, so skip security
|
|
* check to improve efficient.
|
|
*/
|
|
buf_len = iot_pkt_block_len(buf, IOT_PKT_BLOCK_ALL);
|
|
header = (iot_plc_msg_header_t *)iot_pkt_block_ptr(buf, IOT_PKT_BLOCK_DATA);
|
|
|
|
os_acquire_mutex(glb->lock);
|
|
if (header->app_id == IOT_PLC_APP_ID_BCAST) {
|
|
/* if it's a broadcast message, broadcast it to all apps */
|
|
for (index = 0; index < PLC_LIB_APP_SUPP_MAX; index++) {
|
|
if (p_plc_lib->app[index].app_id) {
|
|
tmp_pkt = iot_pkt_alloc(buf_len, IOT_PLC_LIB_MID);
|
|
if (tmp_pkt) {
|
|
/* allocate a new pkt to for each app broadcasting */
|
|
iot_pkt_cpy(tmp_pkt, buf);
|
|
p_plc_lib->app[index].recv(
|
|
p_plc_lib->app[index].param, tmp_pkt);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* free the original packet */
|
|
iot_pkt_free(buf);
|
|
} else {
|
|
app = plc_lib_find_app(header->app_id);
|
|
if (app) {
|
|
app->recv(app->param, buf);
|
|
} else {
|
|
iot_pkt_free(buf);
|
|
}
|
|
}
|
|
|
|
os_release_mutex(glb->lock);
|
|
}
|
|
|
|
/* ipc callback to receive packet from plc stack */
|
|
static void plc_lib_ipc_recv(void *param, iot_ipc_addr_t *addr,
|
|
iot_pkt_t *pkt)
|
|
{
|
|
(void)param;
|
|
(void)addr;
|
|
|
|
if (PLC_LIB_STANDALONE_TASK) {
|
|
iot_task_msg_t *msg = iot_task_alloc_msg(p_plc_lib->task_h);
|
|
plc_lib_msg_t *plc_msg = (plc_lib_msg_t *)msg;
|
|
if (msg) {
|
|
plc_msg->data = pkt;
|
|
msg->id = PLC_LIB_MSG_IPC_EVENT;
|
|
iot_task_queue_msg(p_plc_lib->task_h, msg, PLC_LIB_MSG_QUEUE_HP);
|
|
} else {
|
|
iot_pkt_free(pkt);
|
|
IOT_ASSERT(0);
|
|
}
|
|
} else {
|
|
plc_lib_handle_ipc_event(p_plc_lib, pkt);
|
|
}
|
|
}
|
|
|
|
/* plc lib internal msg handling function */
|
|
static void plc_lib_handle_msg(iot_task_h task_h, iot_task_msg_t *msg)
|
|
{
|
|
plc_lib_msg_t *plc_msg = (plc_lib_msg_t *)msg;
|
|
|
|
switch (msg->id) {
|
|
case PLC_LIB_MSG_IPC_EVENT:
|
|
plc_lib_handle_ipc_event(p_plc_lib, plc_msg->data);
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
iot_task_free_msg(task_h, msg);
|
|
}
|
|
|
|
/* plc lib internal msg cancel function */
|
|
static void plc_lib_handle_msg_cancel(iot_task_h task_h,
|
|
iot_task_msg_t *msg)
|
|
{
|
|
plc_lib_msg_t *plc_msg = (plc_lib_msg_t *)msg;
|
|
|
|
switch (msg->id) {
|
|
case PLC_LIB_MSG_IPC_EVENT:
|
|
iot_pkt_free((iot_pkt_t *)plc_msg->data);
|
|
break;
|
|
default:
|
|
IOT_ASSERT(0);
|
|
break;
|
|
}
|
|
iot_task_free_msg(task_h, msg);
|
|
}
|
|
|
|
iot_plc_app_t *plc_lib_find_app(uint8_t app_id)
|
|
{
|
|
uint8_t i;
|
|
|
|
for (i = 0; i < PLC_LIB_APP_SUPP_MAX; i++) {
|
|
if (p_plc_lib->app[i].app_id == app_id)
|
|
return &p_plc_lib->app[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
iot_plc_app_t *plc_lib_find_free_app()
|
|
{
|
|
uint8_t i;
|
|
iot_plc_app_t *ret = NULL;
|
|
|
|
for (i = 0; i < PLC_LIB_APP_SUPP_MAX; i++) {
|
|
if (p_plc_lib->app[i].app_id == 0) {
|
|
ret = &p_plc_lib->app[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
uint32_t iot_plc_lib_init(uint8_t proto)
|
|
{
|
|
uint32_t ret = 0;
|
|
iot_ipc_client_t client;
|
|
|
|
if (p_plc_lib)
|
|
goto out;
|
|
|
|
p_plc_lib = os_mem_malloc(IOT_PLC_LIB_MID, sizeof(*p_plc_lib));
|
|
if (p_plc_lib == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
|
|
p_plc_lib->lock = os_create_mutex(IOT_PLC_LIB_MID);
|
|
if (p_plc_lib->lock == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto err;
|
|
}
|
|
p_plc_lib->proto = proto;
|
|
|
|
os_mem_set(&p_plc_lib->task_cfg, 0, sizeof(p_plc_lib->task_cfg));
|
|
if (PLC_LIB_STANDALONE_TASK) {
|
|
/* create plc lib task */
|
|
p_plc_lib->task_cfg.stack_size = 0;
|
|
p_plc_lib->task_cfg.task_prio = PLC_LIB_TASK_PRIO;
|
|
p_plc_lib->task_cfg.msg_size = sizeof(plc_lib_msg_t);
|
|
p_plc_lib->task_cfg.msg_cnt = PLC_LIB_MSG_POOL_SIZE;
|
|
p_plc_lib->task_cfg.queue_cnt = PLC_LIB_MSG_QUEUE_MAX_PRIO;
|
|
p_plc_lib->task_cfg.queue_cfg[PLC_LIB_MSG_QUEUE_HP].quota = 0;
|
|
p_plc_lib->task_cfg.msg_exe_func = plc_lib_handle_msg;
|
|
p_plc_lib->task_cfg.msg_cancel_func = plc_lib_handle_msg_cancel;
|
|
|
|
p_plc_lib->task_h = iot_task_create(IOT_PLC_LIB_MID,
|
|
&p_plc_lib->task_cfg);
|
|
|
|
if (p_plc_lib->task_h == NULL)
|
|
goto err_task;
|
|
}
|
|
|
|
/* register ipc to communicate with plc stack */
|
|
client.addr.f_id = IOT_IPC_FID_PLC;
|
|
client.addr.c_id = IOT_IPC_CID_PLC_LIB;
|
|
client.recv = plc_lib_ipc_recv;
|
|
client.param = p_plc_lib;
|
|
p_plc_lib->ipc_h = iot_ipc_register_client(&client);
|
|
if (p_plc_lib->ipc_h == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto err_ipc;
|
|
}
|
|
|
|
#if HW_PLATFORM == HW_PLATFORM_SIMU
|
|
|
|
extern uint8_t ucIsClientMode;
|
|
p_plc_lib->client = ucIsClientMode;
|
|
|
|
#else /* HW_PLATFORM == HW_PLATFORM_SIMU */
|
|
|
|
iot_oem_base_cfg_t *oem_cfg = NULL;
|
|
iot_oem_get_base_cfg(&oem_cfg);
|
|
if (oem_cfg->module_type == MODULE_TYPE_CCO) {
|
|
p_plc_lib->client = 0;
|
|
} else {
|
|
p_plc_lib->client = 1;
|
|
}
|
|
|
|
#endif /* HW_PLATFORM == HW_PLATFORM_SIMU */
|
|
|
|
goto out;
|
|
|
|
err_ipc:
|
|
if (p_plc_lib->task_h) {
|
|
iot_task_delete(p_plc_lib->task_h);
|
|
}
|
|
err_task:
|
|
os_delete_mutex(p_plc_lib->lock);
|
|
err:
|
|
os_mem_free(p_plc_lib);
|
|
p_plc_lib = NULL;
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
void iot_plc_lib_deinit()
|
|
{
|
|
if (p_plc_lib) {
|
|
iot_ipc_deregister_client(p_plc_lib->ipc_h);
|
|
iot_task_delete(p_plc_lib->task_h);
|
|
os_delete_mutex(p_plc_lib->lock);
|
|
os_mem_free(p_plc_lib);
|
|
p_plc_lib = NULL;
|
|
}
|
|
}
|