diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f980ab9 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 8f9ce70..964e7d2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,6 +11,8 @@ "cor.h": "c", "eprc_core.h": "c", "erpc_core.h": "c", - "type_traits": "c" + "type_traits": "c", + "list": "c", + "list.h": "c" } } \ No newline at end of file diff --git a/config.h b/config.h index b9c966d..b39ffb5 100644 --- a/config.h +++ b/config.h @@ -1,7 +1,7 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define ERPC_VERSION "0.0.1" + #define u8 unsigned char diff --git a/crc16.c b/crc16.c index 7cfea11..190d082 100644 --- a/crc16.c +++ b/crc16.c @@ -42,12 +42,12 @@ uint16_t crc16(const unsigned char *buf, size_t len) { u16 cmd_cal_crc16(erpc_cmd_def_t *cmd) { u16 crc = 0; u32 counter = 0; - crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->src_id) & 0x00FF]; - crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->dest_id) & 0x00FF]; - crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->msg_len) & 0x00FF]; - crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->type) & 0x00FF]; - crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->port) & 0x00FF]; - for (counter = 0; counter < cmd->msg_len; counter++) + crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.src_id) & 0x00FF]; + crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.dest_id) & 0x00FF]; + crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.msg_len) & 0x00FF]; + crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.type) & 0x00FF]; + crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.port) & 0x00FF]; + for (counter = 0; counter < cmd->head.msg_len; counter++) crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->data[counter]) & 0x00FF]; cmd->crc_16[0] = (u8)(crc >> 8); cmd->crc_16[1] = (u8)(crc & 0x00FF); diff --git a/crc16.o b/crc16.o new file mode 100644 index 0000000..6f0997b Binary files /dev/null and b/crc16.o differ diff --git a/erpc_core.c b/erpc_core.c index 4526e07..fa0db9d 100644 --- a/erpc_core.c +++ b/erpc_core.c @@ -2,70 +2,399 @@ #include "crc16.h" -u32 erpc_report_node_self(node_cfg_t *node_cfg) { - erpc_cmd_def_t cmd; - cmd.src_id = node_cfg->local_id; - cmd.dest_id = 0xFF; - cmd.msg_len = 0; - cmd.type = PACKAGE_TYPE_DEV_POWER_ON; - cmd_cal_crc16(&cmd); - return node_cfg->write((u8 *)&cmd, sizeof(erpc_cmd_def_t)); -} +/** + * 操作系统相关 + */ -u32 erpc_search_all_node(node_cfg_t *node_cfg) { - erpc_cmd_def_t cmd; - cmd.src_id = node_cfg->local_id; - cmd.dest_id = 0xFF; - cmd.msg_len = 0; - cmd.type = PACKAGE_TYPE_CMD_SERCH_DEV_ONLINE; - cmd_cal_crc16(&cmd); - return node_cfg->write((u8 *)&cmd, sizeof(erpc_cmd_def_t)); -} +erpc_sleep erpc_sleep_tick = NULL; -u32 erpc_send_cmd(node_cfg_t *node_cfg, u8 dest_id, u8 *data, u32 len) { - erpc_cmd_def_t cmd; - cmd.src_id = node_cfg->local_id; - cmd.dest_id = dest_id; - cmd.msg_len = len; - cmd.type = PACKAGE_TYPE_CMD_REQ; - cmd.data = data; - cmd_cal_crc16(&cmd); - return node_cfg->write((u8 *)&cmd, sizeof(erpc_cmd_def_t) + len); -} - -u32 erpc_send_cmd_ack(node_cfg_t *node_cfg, erpc_cmd_def_t *cmd_rec, - u8 is_ack) { - erpc_cmd_def_t cmd_send; - cmd_send.src_id = node_cfg->local_id; - cmd_send.dest_id = cmd_rec->src_id; - if (is_ack) - cmd_send.type = PACKAGE_TYPE_CMD_REQ_ACK; - else - cmd_send.type = PACKAGE_TYPE_CMD_RESP_NACK; - cmd_send.msg_len = 0; - cmd_cal_crc16(&cmd_send); - return node_cfg->write((u8 *)&cmd_send, sizeof(erpc_cmd_def_t)); -} - -u32 erpc_send_repeat(node_cfg_t *node_cfg,u8 dest_id) +static list_t erpc_hw; +void clean_cache(erpc_hw_cfg_t *hw) { - erpc_cmd_def_t cmd; - cmd.src_id = node_cfg->local_id; - cmd.dest_id = dest_id; - cmd.type = PACKAGE_TYPE_CMD_REPEAT; - cmd.msg_len = 0; - cmd_cal_crc16(&cmd); - return node_cfg->write((u8 *)&cmd, sizeof(erpc_cmd_def_t)); -} -u32 erpc_send_msg(node_cfg_t *node_cfg, u8 dest_id, u8 *data, u32 len) { - int retry = CMD_MAX_RETRY; - node_cfg->bus_lock(); - u32 ret = 0; - while (retry-- > 0) { - u32 ret = erpc_send_cmd(node_cfg, dest_id, data, len); - + 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; } - return ret; } -u32 erpc_rec_msg_core(node_cfg_t *node_cfg, u8 *data, u32 len) { +/** + * 注册 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); + } } \ No newline at end of file diff --git a/erpc_core.h b/erpc_core.h index 9ebbfc9..cfbe330 100644 --- a/erpc_core.h +++ b/erpc_core.h @@ -2,56 +2,124 @@ #define ERPC_CORE_H_ #include "config.h" +#include "list.h" +#include +#include +#include +#define ERPC_VERSION "0.0.1" -#define MAX_CMD_LEN (256 - 5) // crc16最大支持256字节 -#define CMD_MAX_RETRY 5 // 最大重发次数 -#define CMD_TIMEOUT 30 // 超时时间 tick -#define MAX_COM 20 // 最大支持端口打开数量,可认为是同时通讯的号 - -typedef enum erpc_error { - DEST_SYS_BUSY = 0, // 目标系统繁忙,接收到nack - DEST_SYS_TIMEOUT, // 目标系统处理超时 - BUS_CRC_ERROR, // 总线CRC错误,可能是总线通讯质量不佳 -}; -typedef enum package_type { +typedef enum package_type +{ PACKAGE_TYPE_DEV_POWER_ON = 0, PACKAGE_TYPE_CMD_REQ, PACKAGE_TYPE_CMD_REQ_ACK, PACKAGE_TYPE_CMD_RESP, PACKAGE_TYPE_CMD_RESP_ACK, - PACKAGE_TYPE_CMD_RESP_NACK, - PACKAGE_TYPE_CMD_REPEAT, // crc校验失败,请求重发 + PACKAGE_TYPE_CMD_REPEAT, // crc校验失败,请求重发 PACKAGE_TYPE_DEV_POWER_OFF, PACKAGE_TYPE_CMD_SERCH_DEV_ONLINE, } package_type; -typedef struct node_cfg_t { - u8 local_id; - struct port_t { - u16 com_id; - volatile u32 time_out; - void (*pre_deal)(u8 *data, u32 len); // 数据预处理接口 - u8 send_ack : 2; // 0:没有ack返回,1:ack返回 2:nack返回 - u8 rec_crc : 1; // 0:crc没有故障, 1: crc有故障 - u8 req_resend : 1; // 1:客户端请求重发 - } port[MAX_COM]; - u32 (*write)(u8 *data, u32 len); - void (*bus_lock)(void); - void (*bus_unlock)(void); - void (*sleep)(void); -} node_cfg_t; - // 广播ID #define ERPC_BOARDCAST_ID 0xff -typedef struct erpc_cmd_def_t { +typedef struct erpc_cmd_head_t +{ u8 src_id; u8 dest_id; package_type type; - u16 port; // 指令号,指令号=端口号 + u16 port; // 指令号,指令号=端口号 u8 msg_len; +} erpc_cmd_head_t; + +typedef struct erpc_cmd_def_t +{ + erpc_cmd_head_t head; u8 crc_16[2]; u8 *data; } erpc_cmd_def_t; +#define MAX_CMD_LEN (256 - sizeof(erpc_cmd_head_t)) // crc16最大支持256字节 +#define CMD_MAX_RETRY 5 // 最大重发次数 +#define CMD_TIMEOUT 30 // 超时时间 tick +#define MAX_REC_CMD_CACHE_NUM 10 // 最大接收指令缓存数量,接受指令优先级>处理指令优先级 +#define MAX_SEND_CMD_CACHE_NUM 10 // 最大发送指令缓存数量,发送指令优先级>接收指令优先级 +typedef enum erpc_status +{ + ERPC_CMD_NO_ERROR, // 发送cache,接收cache空闲 + ERPC_CMD_DATA_DEAL, // 发送cache数据组织中 + ERPC_CMD_WAIT_SERVER_DEAL, // 等待服务线程处理接受cache + ERPC_CMD_WAIT_TASK_DEAL, // 等待任务线程处理指令 + ERPC_CMD_WAIT_TASK_DEAL_FINISH, // 等待任务线程处理指令完成 + ERPC_CMD_WAIT_SEND, // 等待服务线程处理发送cache + ERPC_CMD_SEND_ONCE, // 发送指令成功 + ERPC_CMD_SEND_REPEAT, // 发送指令重发 + ERPC_CMD_SEND_OK, // 发送指令成功 + ERPC_CMD_DEST_BUSY, // 目标设备忙 +}erpc_status; + +typedef struct erpc_data_cache_t +{ + u8 state; + u8 data[256]; +} erpc_data_cache_t; + +typedef u32 (*erpc_cmd_handle_t)(u8 src_id, u8 dest_id, u16 port, u8 *data, u16 len); + +typedef struct erpc_cmd_list_t +{ + u16 cmd; + u32 (*handle)(u8 hw, u8 src_id, u8 dest_id, u16 port, u8 *data, u16 len); +} erpc_cmd_list_t; + +typedef struct erpc_hw_cfg_t +{ + u8 ord; + u8 local_id; + u8 (*write)(u8 *data, u16 len); + void (*send_lock)(void); + void (*send_unlock)(void); + erpc_data_cache_t rec_cache[MAX_REC_CMD_CACHE_NUM]; + erpc_data_cache_t send_cache[MAX_SEND_CMD_CACHE_NUM]; + void (*deal_lock)(void); + void (*deal_unlock)(void); + list_t cmd_list; +} erpc_hw_cfg_t; + +#define CHECK_IF_ERROR(condition, error) \ + if (condition) \ + { \ + return error; \ + } + +typedef enum erpc_error +{ + ERPC_NO_ERROR = 0, + ERPC_ERR_NOFOND_HW, + ERPC_ERR_SEND_CACHE_FULL, + ERPC_ERR_SEND_TIMEOUT, + ERPC_ERR_HW_SEND_FAIL, // 硬件层发来的错误 erpc_hw_cfg_t.write返回错误 + ERPC_ERR_DEST_BUSY, + ERPC_ERR_DEST_NO_RESPONSE, // 目标设备无响应 + ERPC_ERR_MALLOC_ERROR, // malloc失败,内存不足 + ERPC_ERR_HW_EXIST, // 硬件已经存在 + ERPC_ERR_HW_NOT_EXIST, // 硬件不存在 + ERPC_ERR_REC_CACHE_FULL, // 接收缓存满 +}erpc_error; +typedef void (*erpc_sleep)(u32 tick); + + +void erpc_send_deal_core(); // 发送指令处理线程 +u32 erpc_set_rev_cahce(u8 hw, u8 *data, u16 len); // 写入接受缓存 +void erpc_rev_package_core(); // 处理接受到的包,通讯层面处理 +void erpc_rev_deal_core(); // 处理接受到的指令,业务层面处理 +extern erpc_sleep erpc_sleep_tick; + + + +u32 erpc_hw_add(erpc_hw_cfg_t *hw); +u32 erpc_add_cmd_list(erpc_hw_cfg_t *hw, erpc_cmd_list_t *cmd_list); + + +u32 erpc_send(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len); #endif /* ERPC_CORE_H_ */ \ No newline at end of file diff --git a/erpc_core.o b/erpc_core.o new file mode 100644 index 0000000..afdbadc Binary files /dev/null and b/erpc_core.o differ diff --git a/erpc设计文档.md b/erpc设计文档.md index 74a6089..d3f5a12 100644 --- a/erpc设计文档.md +++ b/erpc设计文档.md @@ -1,58 +1 @@ - - -CRC16 校验长度为 16-256字节较为合适。 - -ACK丢了不重发 - - - - -# 发送指令流程 -1.发送数据后,始终要等待ack -2.接收数据后,始终要回复ack -3.获得ack不代表指令成功 -4.crc校验不成功,发送repeat包 -5.指令号=端口号 - -## 正常传输 -| host | slave | -| ---------------- | ---------------- | -| 发送指令 | 等待指令 | -| 等待ACK回复 | 发送ACK | -| 等待指令处理完成 | 处理指令 | -| 等待指令处理完成 | 发送resp | -| 发送resp_ack | 等待resp_ack回复 | -| 处理完成 | 处理完成 | -## 指令丢失 -| host | slave | -| ---------------- | --------------------- | -| 发送指令 | 等待指令 | -| 发送指令丢失 | 等待指令 | -| 超时重发指令 | 等待指令 | -| 等待ACK回复 | 指令接收成功,发送ACK | -| 等待指令处理完成 | 处理指令 | -| 等待指令处理完成 | 发送resp | -| 发送resp_ack | 等待resp_ack回复 | -| 处理完成 | 处理完成 | -## cmd ack 丢失 -| host | slave | -| ---------------- | -------------------------- | -| 发送指令 | 等待指令 | -| 等待ACK回复 | 指令接收成功,发送ACK | -| 超时重发 | 指令已经开始行,发现重发包,发送ACK| -| 等待ACK回复 | 处理指令 | -| 等待指令处理完成 | 处理指令 | -| 等待指令处理完成 | 发送resp | -| 发送resp_ack | 等待resp_ack回复 | -| 处理完成 | 处理完成 | -## resp ack 丢失 -| host | slave | -| ---------------- | ---------------- | -| 发送指令 | 等待指令 | -| 等待ACK回复 | 发送ACK | -| 等待指令处理完成 | 处理指令 | -| 等待指令处理完成 | 发送resp | -| 发送resp_ack | 等待resp_ack回复 | -| 处理完成 |发送resp | -| 发送resp_ack | 处理完成 | \ No newline at end of file diff --git a/list.c b/list.c new file mode 100644 index 0000000..582a34d --- /dev/null +++ b/list.c @@ -0,0 +1,89 @@ +#include "list.h" +#include "stdio.h" + +list_t *list_create(void *data) +{ + list_t *node = (list_t *)malloc(sizeof(list_t)); + if (node == NULL) + { + return NULL; + } + node->data = data; + node->next = NULL; + return node; +} + +list_t *list_append(list_t *head, void *data) +{ + list_t *node = list_create(data); + if (node == NULL) + { + return NULL; + } + if (head == NULL) + { + return NULL; + } + else + { + list_t *tail = head; + while (tail->next != NULL) + { + tail = tail->next; + } + tail->next = node; + } + return head; +} + +void list_print(list_t *head) +{ + list_t *node = head; + while (node != NULL) + { + printf("%p\n", node->data); + node = node->next; + } +} + +/** + * Destroy a list and all its nodes. + * @param head The head of the list. + */ +void list_destroy(list_t *head) +{ + list_t *node = head; + while (node != NULL) + { + list_t *next = node->next; + free(node); + node = next; + } +} +/** + * Delete a node from the list. + * @param head The head of the list. + */ +void list_delete(list_t *head, void *data) +{ + list_t *node = head; + list_t *prev = NULL; + while (node != NULL) + { + if (node->data == data) + { + if (prev == NULL) + { + head = node->next; + } + else + { + prev->next = node->next; + } + free(node); + return; + } + prev = node; + node = node->next; + } +} diff --git a/list.h b/list.h new file mode 100644 index 0000000..786051e --- /dev/null +++ b/list.h @@ -0,0 +1,17 @@ +#ifndef _LIST_H_ +#define _LIST_H_ + + +typedef struct list_t { + void *data; + struct list_t *next; +} list_t; + +list_t *list_create(void *data); +list_t *list_append(list_t *head, void *data); +void list_print(list_t *head); +void list_destroy(list_t *head); +void list_delete(list_t *head, void *data); + + +#endif /* _LIST_H_ */ \ No newline at end of file diff --git a/list.o b/list.o new file mode 100644 index 0000000..e32bab7 Binary files /dev/null and b/list.o differ diff --git a/makefile b/makefile new file mode 100644 index 0000000..9460005 --- /dev/null +++ b/makefile @@ -0,0 +1,36 @@ +# Makefile for the mutex example project + +# 指定编译器 +CC = gcc +# 指定编译选项 +CFLAGS = -Wall -Wextra -std=c11 + +# 源文件 +SRCS = erpc_core.c \ + port_self.c \ + crc16.c\ + list.c + +# 目标文件 +OBJS = $(SRCS:.c=.o) + +# 可执行文件 +TARGET = port_self.exe + +# 默认目标 +all: $(TARGET) + +# 链接目标 +$(TARGET): $(OBJS) + $(CC) -o $@ $^ + +# 编译源文件 +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# 清理目标 +clean: + rm -f $(OBJS) $(TARGET) + +# 伪目标 +.PHONY: all clean diff --git a/port_self.c b/port_self.c new file mode 100644 index 0000000..adc5278 --- /dev/null +++ b/port_self.c @@ -0,0 +1,133 @@ + +// #ifndef WINDOWS +// #error "This file is for Windows only" +// #endif + +#include "erpc_core.h" +#include "windows.h" +#include +void hellworld() +{ + printf("Hello World!\n"); +} +void hello_cat() +{ + printf("Hello Cat!\n"); +} +erpc_cmd_list_t erpc_cmd_list[] = { + {.cmd = 0x01, hellworld}, + {.cmd = 0x02, hello_cat}, +}; + +HANDLE deal_lock; +HANDLE send_lock; + +static void deal_lock_h() +{ + WaitForSingleObject(deal_lock, INFINITE); +} + +static void deal_unlock_h() +{ + ReleaseMutex(deal_lock); +} +static void send_lock_h() +{ + WaitForSingleObject(send_lock, INFINITE); +} + +static void send_unlock_h() +{ + ReleaseMutex(send_lock); +} +u8 data[300]; +static u8 data_write(u8 *data, u32 len) +{ + erpc_set_rev_cahce(0, data, len); + return 0; +} + +erpc_hw_cfg_t self_hw_cfg = { + .ord = 0, + .deal_lock = deal_lock_h, + .deal_unlock = deal_unlock_h, + .send_lock = send_lock_h, + .send_unlock = send_unlock_h, + .local_id = 0x01, + .write = data_write, +}; +void erpc_cmd_config() +{ + for (int i = 0; i < sizeof(erpc_cmd_list) / sizeof(erpc_cmd_list[0]); i++) + { + erpc_add_cmd_list(&self_hw_cfg, &erpc_cmd_list[i]); + } +} +void sys_sleep(u32 ms) +{ + Sleep(ms); +} + +DWORD WINAPI send_task(LPVOID lpParam) +{ + while (1) + { + erpc_send_deal_core(); + } +} +DWORD WINAPI rev_task(LPVOID lpParam) +{ + + while (1) + { + erpc_rev_deal_core(); + } +} + +DWORD WINAPI test_task(LPVOID lpParam) +{ + printf("test_task\n"); + while (1) + { + printf("[test_task]send\n"); + u32 ret = erpc_send(self_hw_cfg.ord, self_hw_cfg.local_id, 0x01, NULL, 0); + printf("[test_task]send ret:%d\n", ret); + sys_sleep(1000); + } +} + +int main(int argc, char *argv[]) +{ + u32 ret = 0; + printf("erpc_port_self start\n"); + ret = erpc_hw_add(&self_hw_cfg); + printf("erpc_hw_add ret:%d\n", ret); + CHECK_IF_ERROR(ret, 0); + erpc_cmd_config(); + printf("erpc_cmd_config ret:%d\n", ret); + erpc_sleep_tick = sys_sleep; + + HANDLE threadHandle[3]; + deal_lock = CreateMutex(NULL, FALSE, NULL); + if (deal_lock == NULL) + { + printf("创建互斥锁失败,错误代码:%d\n", GetLastError()); + return 1; + } + send_lock = CreateMutex(NULL, FALSE, NULL); + if (send_lock == NULL) + { + printf("创建互斥锁失败,错误代码:%d\n", GetLastError()); + return 1; + } + threadHandle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)send_task, NULL, 0, NULL); + threadHandle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)rev_task, NULL, 0, NULL); + threadHandle[2] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test_task, NULL, 0, NULL); + + WaitForSingleObject(threadHandle[0], INFINITE); + WaitForSingleObject(threadHandle[1], INFINITE); + WaitForSingleObject(threadHandle[2], INFINITE); + CloseHandle(threadHandle[0]); + CloseHandle(threadHandle[1]); + return 0; +} \ No newline at end of file diff --git a/port_self.exe b/port_self.exe new file mode 100644 index 0000000..3894270 Binary files /dev/null and b/port_self.exe differ diff --git a/port_self.h b/port_self.h new file mode 100644 index 0000000..e69de29 diff --git a/port_self.o b/port_self.o new file mode 100644 index 0000000..5b4f9b4 Binary files /dev/null and b/port_self.o differ diff --git a/unit_test.c b/unit_test.c new file mode 100644 index 0000000..2bf60ca --- /dev/null +++ b/unit_test.c @@ -0,0 +1,2 @@ +#include "erpc_core.h" +