400 lines
10 KiB
C
400 lines
10 KiB
C
#include "erpc_core.h"
|
|
|
|
#include "crc16.h"
|
|
|
|
/**
|
|
* 操作系统相关
|
|
*/
|
|
|
|
erpc_sleep erpc_sleep_tick = NULL;
|
|
|
|
static list_t erpc_hw;
|
|
void clean_cache(erpc_hw_cfg_t *hw)
|
|
{
|
|
for (int i = 0; i < MAX_REC_CMD_CACHE_NUM; i++)
|
|
{
|
|
hw->rec_cache->state = ERPC_CMD_NO_ERROR;
|
|
}
|
|
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
|
|
{
|
|
hw->send_cache[i].state = ERPC_CMD_NO_ERROR;
|
|
}
|
|
}
|
|
/**
|
|
* 注册 hardware 设备
|
|
* 线程不安全
|
|
*/
|
|
u32 erpc_hw_add(erpc_hw_cfg_t *hw)
|
|
{
|
|
list_t *list = &erpc_hw;
|
|
if (list->data == NULL)
|
|
{
|
|
list->data = (void *)hw;
|
|
clean_cache(hw);
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
list_t *list_node = malloc(sizeof(list_t));
|
|
if (list_node == NULL)
|
|
{
|
|
return ERPC_ERR_MALLOC_ERROR;
|
|
}
|
|
list_node->data = (void *)hw;
|
|
u8 hw_ord = hw->ord;
|
|
// 检查hw是否已经存在
|
|
while (list != NULL)
|
|
{
|
|
erpc_hw_cfg_t *hw_cfg = (erpc_hw_cfg_t *)list->data;
|
|
if (hw_cfg->ord == hw_ord)
|
|
{
|
|
return ERPC_ERR_HW_EXIST;
|
|
}
|
|
list = list->next;
|
|
}
|
|
list_t *result = list_append(&erpc_hw, hw);
|
|
if (result == NULL)
|
|
{
|
|
return ERPC_ERR_MALLOC_ERROR;
|
|
}
|
|
clean_cache(hw);
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
/**
|
|
* 注册命令列表
|
|
* 线程不安全
|
|
*/
|
|
u32 erpc_add_cmd_list(erpc_hw_cfg_t *hw, erpc_cmd_list_t *cmd_list)
|
|
{
|
|
list_t *list = &hw->cmd_list;
|
|
if (list->data == NULL)
|
|
{
|
|
list->data = (void *)cmd_list;
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
list = list_append(&hw->cmd_list, cmd_list);
|
|
if (list == NULL)
|
|
{
|
|
return ERPC_ERR_MALLOC_ERROR;
|
|
}
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
/**
|
|
* 移除 hardware 设备
|
|
* 线程不安全
|
|
*/
|
|
u32 erpc_hw_remove(u8 hw)
|
|
{
|
|
list_t *list = &erpc_hw;
|
|
if (list->data == NULL)
|
|
{
|
|
return ERPC_ERR_NOFOND_HW;
|
|
}
|
|
while (list != NULL)
|
|
{
|
|
erpc_hw_cfg_t *hw_cfg = (erpc_hw_cfg_t *)list->data;
|
|
if (hw_cfg->ord == hw)
|
|
{
|
|
list_delete(&erpc_hw, list);
|
|
free(list);
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
list = list->next;
|
|
}
|
|
return ERPC_ERR_NOFOND_HW;
|
|
}
|
|
/**
|
|
* 获取 hardware 设备
|
|
*/
|
|
erpc_hw_cfg_t *erpc_hw_get(u8 hw)
|
|
{
|
|
list_t *list = &erpc_hw;
|
|
if (list->data == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
while (list != NULL)
|
|
{
|
|
erpc_hw_cfg_t *hw_cfg = (erpc_hw_cfg_t *)list->data;
|
|
if (hw_cfg->ord == hw)
|
|
{
|
|
return hw_cfg;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
u32 erpc_send(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len)
|
|
{
|
|
erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw);
|
|
CHECK_IF_ERROR(hw_cfg == NULL, ERPC_ERR_NOFOND_HW);
|
|
u8 cache_ord = 255;
|
|
// 查找可用的发送缓存
|
|
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
|
|
{
|
|
if (hw_cfg->send_cache[i].state == ERPC_CMD_NO_ERROR)
|
|
{
|
|
cache_ord = i;
|
|
break;
|
|
}
|
|
}
|
|
CHECK_IF_ERROR(cache_ord == 255, ERPC_ERR_SEND_CACHE_FULL);
|
|
// 准备数据
|
|
hw_cfg->send_cache[cache_ord].state = ERPC_CMD_DATA_DEAL;
|
|
erpc_cmd_def_t *cmd = (erpc_cmd_def_t *)&hw_cfg->send_cache[cache_ord].data[0];
|
|
cmd->head.dest_id = dest_id;
|
|
cmd->head.port = port;
|
|
cmd->head.msg_len = len;
|
|
cmd->head.type = PACKAGE_TYPE_CMD_REQ;
|
|
cmd->head.src_id = hw_cfg->local_id;
|
|
memcpy(cmd->data, data, len);
|
|
// 计算校验和
|
|
cmd_cal_crc16(cmd);
|
|
// 发送数据
|
|
hw_cfg->send_cache[cache_ord].state = ERPC_CMD_WAIT_SEND;
|
|
// 等待数据发送完成
|
|
int wait_time = CMD_TIMEOUT;
|
|
while (wait_time > 0)
|
|
{
|
|
if (hw_cfg->send_cache[cache_ord].state == ERPC_CMD_SEND_OK)
|
|
{
|
|
break;
|
|
}
|
|
if (hw_cfg->send_cache[cache_ord].state == ERPC_CMD_DEST_BUSY)
|
|
{
|
|
return ERPC_ERR_DEST_BUSY;
|
|
}
|
|
if (erpc_sleep_tick != NULL)
|
|
{
|
|
erpc_sleep_tick(1);
|
|
}
|
|
|
|
wait_time--;
|
|
}
|
|
CHECK_IF_ERROR(wait_time == 0, ERPC_ERR_SEND_TIMEOUT);
|
|
CHECK_IF_ERROR(hw_cfg->send_cache[cache_ord].state == ERPC_CMD_SEND_ONCE, ERPC_ERR_DEST_NO_RESPONSE);
|
|
CHECK_IF_ERROR(hw_cfg->send_cache[cache_ord].state == ERPC_CMD_SEND_REPEAT, ERPC_ERR_DEST_NO_RESPONSE);
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
|
|
u32 erpc_send_data(erpc_hw_cfg_t *hw)
|
|
{
|
|
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
|
|
{
|
|
if (hw->send_cache[i].state == ERPC_CMD_WAIT_SEND)
|
|
{
|
|
erpc_cmd_def_t *cmd = (erpc_cmd_def_t *)&hw->send_cache[i].data[0];
|
|
u32 len = sizeof(erpc_cmd_head_t) + 2 + cmd->head.msg_len;
|
|
hw->send_lock();
|
|
u8 ret = hw->write((u8 *)hw->send_cache[i].data, len);
|
|
hw->send_unlock();
|
|
CHECK_IF_ERROR(ret != 0, ERPC_ERR_HW_SEND_FAIL);
|
|
hw->send_cache[i].state = ERPC_CMD_SEND_ONCE;
|
|
}
|
|
}
|
|
}
|
|
|
|
u32 erpc_rev_ack_package(erpc_hw_cfg_t *hw, erpc_cmd_def_t *cmd_rev)
|
|
{
|
|
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
|
|
{
|
|
if (hw->send_cache[i].state == ERPC_CMD_SEND_ONCE || hw->send_cache[i].state == ERPC_CMD_SEND_REPEAT)
|
|
{
|
|
erpc_cmd_def_t *cmd_send = (erpc_cmd_def_t *)&hw->send_cache[i].data[0];
|
|
if (cmd_rev->head.port == cmd_send->head.port)
|
|
{
|
|
hw->send_cache[i].state = ERPC_CMD_SEND_OK;
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
}
|
|
}
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
|
|
// 重发数据包
|
|
u32 erpc_rev_repeat_package(erpc_hw_cfg_t *hw, erpc_cmd_def_t *cmd_rev)
|
|
{
|
|
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
|
|
{
|
|
if (hw->send_cache[i].state == ERPC_CMD_SEND_ONCE || hw->send_cache[i].state == ERPC_CMD_SEND_REPEAT)
|
|
{
|
|
erpc_cmd_def_t *cmd_send = (erpc_cmd_def_t *)&hw->send_cache[i].data[0];
|
|
if (cmd_rev->head.port == cmd_send->head.port)
|
|
{
|
|
u32 len = sizeof(erpc_cmd_head_t) + 2 + cmd_send->head.msg_len;
|
|
hw->send_lock();
|
|
u8 ret = hw->write((u8 *)hw->send_cache[i].data, len);
|
|
hw->send_unlock();
|
|
hw->send_cache[i].state = ERPC_CMD_SEND_REPEAT;
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
}
|
|
}
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
u32 erpc_send_ack_package(erpc_hw_cfg_t *hw, erpc_cmd_def_t *cmd_rev)
|
|
{
|
|
erpc_cmd_def_t cmd_send;
|
|
cmd_send.head.dest_id = cmd_rev->head.src_id;
|
|
cmd_send.head.port = cmd_rev->head.port;
|
|
cmd_send.head.msg_len = 0;
|
|
cmd_send.head.type = PACKAGE_TYPE_CMD_REQ_ACK;
|
|
cmd_send.head.src_id = hw->local_id;
|
|
cmd_cal_crc16(&cmd_send);
|
|
u32 len = sizeof(erpc_cmd_head_t) + 2 + cmd_send.head.msg_len;
|
|
hw->send_lock();
|
|
u8 ret = hw->write((u8 *)&cmd_send, len);
|
|
hw->send_unlock();
|
|
CHECK_IF_ERROR(ret != 0, ERPC_ERR_HW_SEND_FAIL);
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
|
|
u32 erpc_rev_package(erpc_hw_cfg_t *hw)
|
|
{
|
|
for (int i = 0; i < MAX_REC_CMD_CACHE_NUM; i++)
|
|
{
|
|
if (hw->rec_cache[i].state == ERPC_CMD_WAIT_SERVER_DEAL)
|
|
{
|
|
erpc_cmd_def_t *cmd = (erpc_cmd_def_t *)&hw->rec_cache[i].data[0];
|
|
// 检查crc
|
|
u8 crc_result = cmd_check_crc16(cmd);
|
|
// 丢弃错误数据包
|
|
if (crc_result)
|
|
{
|
|
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
|
|
continue;
|
|
}
|
|
// 丢弃不是本地数据包
|
|
if (cmd->head.dest_id != hw->local_id)
|
|
{
|
|
|
|
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
|
|
continue;
|
|
}
|
|
// 处理数据包
|
|
switch (cmd->head.type)
|
|
{
|
|
case PACKAGE_TYPE_CMD_REQ:
|
|
erpc_send_ack_package(hw, cmd);
|
|
hw->rec_cache[i].state = ERPC_CMD_WAIT_TASK_DEAL;
|
|
break;
|
|
case PACKAGE_TYPE_CMD_REQ_ACK:
|
|
erpc_rev_ack_package(hw, cmd);
|
|
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
|
|
break;
|
|
case PACKAGE_TYPE_CMD_REPEAT:
|
|
erpc_rev_repeat_package(hw, cmd);
|
|
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
|
|
break;
|
|
default:
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void erpc_rev_package_core()
|
|
{
|
|
|
|
list_t *list = &erpc_hw;
|
|
if (list->data == NULL)
|
|
{
|
|
return;
|
|
}
|
|
while (list != NULL)
|
|
{
|
|
erpc_hw_cfg_t *hw = (erpc_hw_cfg_t *)list->data;
|
|
erpc_rev_package(hw);
|
|
list = list->next;
|
|
}
|
|
}
|
|
u32 erpc_set_rev_cahce(u8 hw, u8 *data, u16 len)
|
|
{
|
|
erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw);
|
|
CHECK_IF_ERROR(hw_cfg == NULL, ERPC_ERR_NOFOND_HW);
|
|
for (int i = 0; i < MAX_REC_CMD_CACHE_NUM; i++)
|
|
{
|
|
if (hw_cfg->rec_cache[i].state == ERPC_CMD_NO_ERROR)
|
|
{
|
|
memcpy(hw_cfg->rec_cache[i].data, data, len);
|
|
hw_cfg->rec_cache[i].state = ERPC_CMD_WAIT_SERVER_DEAL;
|
|
return ERPC_NO_ERROR;
|
|
}
|
|
}
|
|
return ERPC_ERR_REC_CACHE_FULL;
|
|
}
|
|
void erpc_send_deal_core()
|
|
{
|
|
list_t *list = &erpc_hw;
|
|
if (list->data == NULL)
|
|
{
|
|
return;
|
|
}
|
|
while (list != NULL)
|
|
{
|
|
erpc_hw_cfg_t *hw = (erpc_hw_cfg_t *)list->data;
|
|
erpc_send_data(hw);
|
|
}
|
|
if (erpc_sleep_tick != NULL)
|
|
{
|
|
erpc_sleep_tick(1);
|
|
}
|
|
}
|
|
|
|
void erpc_rev_deal_core()
|
|
{
|
|
list_t *list = &erpc_hw;
|
|
if (list->data == NULL)
|
|
{
|
|
return;
|
|
}
|
|
while (list != NULL)
|
|
{
|
|
erpc_hw_cfg_t *hw = (erpc_hw_cfg_t *)list->data;
|
|
|
|
for (int j = 0; j < MAX_REC_CMD_CACHE_NUM; j++)
|
|
{
|
|
if (hw->rec_cache[j].state == ERPC_CMD_WAIT_TASK_DEAL)
|
|
{
|
|
// 多线程处理
|
|
hw->deal_lock();
|
|
if (hw->rec_cache[j].state == ERPC_CMD_WAIT_TASK_DEAL)
|
|
{
|
|
// 获取指令的处理权限
|
|
hw->rec_cache[j].state = ERPC_CMD_WAIT_TASK_DEAL_FINISH;
|
|
}
|
|
else
|
|
{
|
|
// 已经有线程抢先执行了
|
|
hw->deal_unlock();
|
|
continue;
|
|
}
|
|
hw->deal_unlock();
|
|
|
|
list_t *list = &hw->cmd_list;
|
|
// 链表是空的
|
|
if (list->data == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
while (list != NULL)
|
|
{
|
|
erpc_cmd_list_t *cmd_list = (erpc_cmd_list_t *)list->data;
|
|
erpc_cmd_def_t *cmd_def = (erpc_cmd_def_t *)hw->rec_cache[j].data;
|
|
if (cmd_list->cmd == cmd_def->head.port)
|
|
{
|
|
if (cmd_list->handle != NULL)
|
|
{
|
|
// 指令调用
|
|
cmd_list->handle(hw->ord, cmd_def->head.src_id, cmd_def->head.dest_id, cmd_def->head.port, cmd_def->data, cmd_def->head.msg_len);
|
|
}
|
|
// 处理完成 丢弃缓存
|
|
hw->rec_cache[j].state = ERPC_CMD_NO_ERROR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (erpc_sleep_tick != NULL)
|
|
{
|
|
erpc_sleep_tick(1);
|
|
}
|
|
} |