#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_base(erpc_hw_cfg_t *hw_cfg, u8 dest_id, u16 port, u8 package_type, u8 *data, u16 len) { 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) { ERPC_DEBUG("find send cache %d\n", i); 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; if (data == NULL) { cmd->head.msg_len = 0; len = 0; } cmd->head.type = package_type; cmd->head.src_id = hw_cfg->local_id; if (len > 0 && data != NULL) { for (int i = 0; i < len; i++) { cmd->data[i] = data[i]; } } // 计算校验和 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--; } u32 ret = ERPC_NO_ERROR; do { if (wait_time == 0) { printf("send timeout,state:%d\n", hw_cfg->send_cache[cache_ord].state); ret = ERPC_ERR_SEND_TIMEOUT; break; } if (hw_cfg->send_cache[cache_ord].state == ERPC_CMD_SEND_ONCE) { ret = ERPC_ERR_DEST_NO_RESPONSE; break; } if (hw_cfg->send_cache[cache_ord].state == ERPC_CMD_SEND_REPEAT) { ret = ERPC_ERR_DEST_NO_RESPONSE; break; } } while (0); hw_cfg->send_cache[cache_ord].state = ERPC_CMD_NO_ERROR; return ret; } u32 erpc_send(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len) { erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw); u32 ret = erpc_send_base(hw_cfg, dest_id, port, PACKAGE_TYPE_CMD_REQ, data, len); return ret; } u32 erpc_wait_resp_package(u8 hw, u8 dest_id, u16 port, u8 *reply_data, u16 *reply_len, u32 time_out) { erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw); CHECK_IF_ERROR(hw_cfg == NULL, ERPC_ERR_NOFOND_HW); while (time_out > 0) { for (int i = 0; i < MAX_REC_CMD_CACHE_NUM; i++) { erpc_data_cache_t *rec_cahce = &hw_cfg->rec_cache[i]; if (rec_cahce->state != ERPC_CMD_RESP_OK) { continue; } erpc_cmd_def_t *cmd = (erpc_cmd_def_t *)&rec_cahce->data[0]; if (cmd->head.port != port) { continue; } if (cmd->head.src_id != dest_id) { continue; } if (reply_data != NULL) { // memccpy(reply_data, cmd->data, 0, cmd->head.msg_len); memcpy(reply_data, cmd->data, cmd->head.msg_len); if (reply_len != NULL) { *reply_len = cmd->head.msg_len; } } rec_cahce->state = ERPC_CMD_NO_ERROR; return ERPC_NO_ERROR; } if (erpc_sleep_tick != NULL) { erpc_sleep_tick(1); } time_out--; } CHECK_IF_ERROR(time_out == 0, ERPC_ERR_DEST_NO_REPLY); return ERPC_NO_ERROR; } u32 erpc_send_wait_reply(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len, u8 *reply_data, u16 *reply_len, u32 timeout) { u32 ret = erpc_send(hw, dest_id, port, data, len); if (reply_len != NULL) { *reply_len = 0; } CHECK_IF_ERROR(ret != ERPC_NO_ERROR, ret); ret = erpc_wait_resp_package(hw, dest_id, port, reply_data, reply_len, timeout); CHECK_IF_ERROR(ret != ERPC_NO_ERROR, ret); return ERPC_NO_ERROR; } u32 erpc_replay(u8 hw, u8 dest_id, u16 port, u8 *data_out, u16 len) { erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw); u32 ret = erpc_send_base(hw_cfg, dest_id, port, PACKAGE_TYPE_CMD_RESP, data_out, len); return ret; } 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; } } return ERPC_NO_ERROR; } 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_resp_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_RESP_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_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(); u32 ret = hw->write((u8 *)hw->send_cache[i].data, len); hw->send_unlock(); hw->send_cache[i].state = ERPC_CMD_SEND_REPEAT; CHECK_IF_ERROR(ret, ERPC_ERR_HW_SEND_FAIL); // 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_DEBUG("find cmd wait server deal %d\n", i); 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_DEBUG("{REQ}\n"); erpc_send_ack_package(hw, cmd); hw->rec_cache[i].state = ERPC_CMD_WAIT_TASK_DEAL; break; case PACKAGE_TYPE_CMD_REQ_ACK: ERPC_DEBUG("{ACK}\n"); 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; case PACKAGE_TYPE_CMD_RESP: ERPC_DEBUG("{RESP}\n"); erpc_rev_resp_package(hw, cmd); hw->rec_cache[i].state = ERPC_CMD_RESP_OK; break; case PACKAGE_TYPE_CMD_RESP_ACK: ERPC_DEBUG("{RESP_ACK}\n"); erpc_rev_ack_package(hw, cmd); hw->rec_cache[i].state = ERPC_CMD_NO_ERROR; break; default: break; } } } return ERPC_NO_ERROR; } 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) { ERPC_DEBUG("set rev cache %d\r\n", i); 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) { continue; } } { // 多线程下,抢占处理权限 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 *cmd_list = &hw->cmd_list; // 链表是空的 if (cmd_list->data == NULL) { continue; } // 获取指令指针 erpc_cmd_def_t *cmd_def = (erpc_cmd_def_t *)hw->rec_cache[j].data; while (cmd_list != NULL) { // 搜索指令列表 erpc_cmd_list_t *cmd_obj = (erpc_cmd_list_t *)cmd_list->data; if (cmd_obj->cmd == cmd_def->head.port) { if (cmd_obj->handle != NULL) { // 指令调用 cmd_obj->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); } break; } cmd_list = cmd_list->next; } } // 处理完成 丢弃缓存 , 无论是否执行指令,都需要把数据包丢弃 hw->rec_cache[j].state = ERPC_CMD_NO_ERROR; } } list = list->next; } if (erpc_sleep_tick != NULL) { erpc_sleep_tick(1); } }