#include "erpc_core.h" #include "crc16.h" #include "string.h" void cal_crc16(erpc_msg_t *msg) { u16 crc = 0; crc = crc16_cal(msg->src_id, crc); crc = crc16_cal(msg->dest_id, crc); crc = crc16_cal(msg->type, crc); crc = crc16_cal(msg->len, crc); for (int i = 0; i < msg->len; i++) { crc = crc16_cal(msg->data[i], crc); } msg->crc = crc; } u8 check_crc16(erpc_msg_t *msg) { u16 crc = 0; crc = crc16_cal(msg->src_id, crc); crc = crc16_cal(msg->dest_id, crc); crc = crc16_cal(msg->type, crc); crc = crc16_cal(msg->len, crc); for (int i = 0; i < msg->len; i++) { crc = crc16_cal(msg->data[i], crc); } return crc == msg->crc; } static erpc_cache_t *find_free_cache(erpc_hw_t *hw) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { if (hw->send_cache[i].state == CACHE_FREE) { return &hw->send_cache[i]; } } return NULL; } // static erpc_cache_t *clean_ack_cache(erpc_hw_t *hw, u8 dest_id) // { // return NULL; // } static erpc_cache_t *find_ack_cache(erpc_hw_t *hw, u8 dest_id, u16 port) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { erpc_cache_t *cache = &hw->send_cache[i]; if (cache->state == CACHE_REC_ACK && cache->msg.src_id == dest_id && cache->msg.port == port) { return cache; } } return NULL; } static u8 check_port_send_available(erpc_hw_t *hw, u8 port) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { erpc_cache_t *cache = &hw->send_cache[i]; if (cache->state != CACHE_FREE) { if (cache->msg.port == port) { return 0; } } } return 1; } static void free_port_ack_cache(erpc_hw_t *hw, u16 port) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { erpc_cache_t *cache = &hw->recv_cache[i]; if (cache->state == CACHE_REC_ACK) { if (cache->msg.port == port) { cache->state = CACHE_FREE; } } } } static u32 send_data(erpc_hw_t *hw, erpc_cache_t *cache, u16 port, u16 *timeout) { free_port_ack_cache(hw, port); cache->state = CACHE_WAIT_SEND; // 等待发送完成 while (*timeout) { if (cache->state == CACHE_SEND_OK) { return 0; } else if (cache->state == CACHE_SEND_HW_ERR) { return ERPC_ERR_SEND_HW_ERR; } else { hw->sleep(1); } (*timeout)--; } if (*timeout == 0) { return ERPC_ERR_SEND_TIMEOUT; } return 0; } static u32 wait_ack(erpc_hw_t *hw, erpc_cache_t *rec, u8 dest_id, u16 port, u16 *timeout) { while (*timeout) { rec = find_ack_cache(hw, dest_id, port); if (rec != NULL) { return 0; } hw->sleep(1); (*timeout)--; } if (timeout == 0) { return ERPC_ERR_SEND_ACK_TIMEOUT; } return 0; } u32 send_request(erpc_hw_t *hw, u8 dest_id, u16 port, u8 *data, u16 len, u16 timeout, u8 retry) { erpc_cache_t *cache = find_free_cache(hw); CHECK_DEAL(cache == NULL, ERPC_ERR_NO_FREE_SEND_CACHE); hw->lock(); if (check_port_send_available(hw, port) == 0) { hw->unlock(); return ERPC_ERR_SEND_PORT_IS_INUSE; } cache->msg.dest_id = dest_id; cache->state = CACHE_IN_USE; hw->unlock(); cache->msg.src_id = hw->local_id; cache->msg.type = ERPC_MSG_TYPE_REQUEST; cache->msg.len = len; cache->msg.port = port; memcpy(cache->msg.data, data, len); cal_crc16(&cache->msg); erpc_cache_t *rec = NULL; u16 timeout_copy = timeout; while (retry--) { /** * 发送失败应该立即返回,不能retry */ u32 ret = send_data(hw, cache, port, &timeout); if (ret) { cache->state = CACHE_FREE; return ret; } // 等待ack ret = wait_ack(hw, rec, dest_id, port, &timeout); if (ret == 0) { break; } timeout = timeout_copy; } CHECK_DEAL(retry == 0, ERPC_ERR_SEND_ACK_TIMEOUT); // 释放cache cache->state = CACHE_FREE; rec->state = CACHE_FREE; return 0; } static erpc_cache_t *find_response_cache(erpc_hw_t *hw, u8 dest_id, u16 port) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { erpc_cache_t *cache = &hw->recv_cache[i]; if (cache->state == CACHE_GET_RESP && cache->msg.src_id == dest_id && cache->msg.port == port) { return cache; } } return NULL; } static void free_response_cache(erpc_hw_t *hw, u8 dest_id, u16 port) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { erpc_cache_t *cache = &hw->recv_cache[i]; if (cache->state == CACHE_GET_RESP && cache->msg.src_id == dest_id && cache->msg.port == port) { cache->state = CACHE_FREE; } } } static u32 send_ack(erpc_hw_t *hw, u8 dest_id, u16 port, u16 time_out) { erpc_cache_t *cache = find_free_cache(hw); CHECK_DEAL(cache == NULL, ERPC_ERR_NO_FREE_SEND_CACHE); hw->lock(); if (check_port_send_available(hw, port) == 0) { hw->unlock(); return ERPC_ERR_SEND_PORT_IS_INUSE; } cache->msg.dest_id = dest_id; cache->state = CACHE_IN_USE; hw->unlock(); cache->msg.src_id = hw->local_id; cache->msg.type = ERPC_MSG_TYPE_ACK; cache->msg.len = 0; cache->msg.port = port; cal_crc16(&cache->msg); u32 ret = send_data(hw, cache, port, &time_out); return ret; } /** * 发送请求,等待响应 * @param hw 硬件接口 * @param dest_id 目标ID * @param port 端口号 * @param data_out 请求数据 * @param len_out 请求数据长度 * @param data_in 响应数据 * @param len_in 响应数据长度 * @param send_timeout 发送超时时间 * @param recv_timeout 接收超时时间 * @param retry 重试次数 * @return 0 成功,其他失败 */ u32 send_request_wait_response(erpc_hw_t *hw, u8 dest_id, u16 port, u8 *data_out, u16 len_out, u8 *data_in, u16 *len_in, u16 send_timeout, u16 recv_timeout, u8 retry) { free_response_cache(hw, dest_id, port); u32 ret = send_request(hw, dest_id, port, data_out, len_out, send_timeout, retry); CHECK_DEAL(ret != 0, ret); while (recv_timeout) { erpc_cache_t *rec = find_response_cache(hw, dest_id, port); if (rec != NULL) { // 拷贝数据 int len = rec->msg.len; if (len > *len_in) { len = *len_in; } memcpy(data_in, rec->msg.data, len); *len_in = len; rec->state = CACHE_FREE; break; } recv_timeout--; hw->sleep(1); } CHECK_DEAL(recv_timeout == 0, ERPC_ERR_NO_CMD_RETURN); ret = send_ack(hw, dest_id, port, send_timeout); CHECK_DEAL(ret != 0, ret); return 0; } u32 send_response(erpc_hw_t *hw, erpc_cache_t *cache_rec, u8 *data, u16 len, u16 timeout, u8 retry) { erpc_cache_t *cache = find_free_cache(hw); CHECK_DEAL(cache == NULL, ERPC_ERR_NO_FREE_SEND_CACHE); hw->lock(); if (check_port_send_available(hw, cache->msg.port) == 0) { hw->unlock(); return ERPC_ERR_SEND_PORT_IS_INUSE; } cache->msg.dest_id = cache_rec->msg.src_id; cache->state = CACHE_IN_USE; hw->unlock(); cache->msg.src_id = hw->local_id; cache->msg.type = ERPC_MSG_TYPE_ACK; cache->msg.len = 0; cache->msg.port = cache_rec->msg.port; memcpy(cache->msg.data, data, len); cal_crc16(&cache->msg); u16 timeout_copy = timeout; erpc_cache_t *rec = NULL; while (retry--) { u32 ret = send_data(hw, cache, cache->msg.port, &timeout); if (ret) { cache->state = CACHE_FREE; return ret; } // 等待ack ret = wait_ack(hw, rec,cache->msg.dest_id,cache->msg.port, &timeout); if (ret == 0) { break; } timeout = timeout_copy; } CHECK_DEAL(retry == 0, ERPC_ERR_SEND_ACK_TIMEOUT); // 释放cache cache->state = CACHE_FREE; rec->state = CACHE_FREE; return 0; } u32 write_rec_cache(erpc_hw_t *hw, u8 *data, u16 len) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { if (hw->recv_cache[i].state == CACHE_FREE) { hw->lock(); u8 *data_in = (u8 *)&hw->recv_cache[i].msg; for (int j = 0; j < len; j++) { data_in[j] = data[j]; } hw->recv_cache[i].state = CACHE_GET_DATA; hw->unlock(); return 0; } } return 1; } void send_core(erpc_hw_t *hw) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { erpc_cache_t *cache = &hw->send_cache[i]; if (cache->state == CACHE_WAIT_SEND) { u32 ret = hw->send((u8 *)&cache->msg, cache->msg.len + ERPC_MSG_HEADER_SIZE); if (ret == 0) { cache->state = CACHE_SEND_OK; } else { cache->state = CACHE_SEND_HW_ERR; } } } } void recv_core(erpc_hw_t *hw) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { erpc_cache_t *cache = &hw->recv_cache[i]; if (cache->state == CACHE_GET_DATA) { if (check_crc16(&cache->msg) == 1) { cache->state = CACHE_GET_MSG; } else { cache->state = CACHE_FREE; } } switch (cache->state) { case CACHE_GET_MSG: { switch (cache->msg.type) { case ERPC_MSG_TYPE_ACK: { cache->state = CACHE_REC_ACK; } break; case ERPC_MSG_TYPE_RESPONSE: { cache->state = CACHE_GET_RESP; } break; case ERPC_MSG_TYPE_REQUEST: { cache->state = CACHE_WAIT_HANDLE; } break; default: break; } } break; default: break; } } } void recv_handle(erpc_hw_t *hw) { for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++) { erpc_cache_t *cache = &hw->recv_cache[i]; if (cache->state == CACHE_WAIT_HANDLE) { cache->state = CACHE_FREE; } } }