Files
kunlun/common/plc_lib/src/iot_plc_lib.c
2024-09-28 14:24:04 +08:00

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;
}
}