#include "erpc_core.h" #include #include "crc16.h" /** * @brief 获取空闲的接受缓存 */ erpc_packet_cache_t *erpc_hw_get_free_rec_cache(erpc_hardware_t *hw) { for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++) { if (hw->recv_cache->state == ERPC_CACHE_STA_FREE) { return hw->recv_cache + i; } } return NULL; } /** * @brief 获取空闲的发送缓存对应的空闲数据地址 * 这个接口主要用于DMA方式接收数据 */ u8 *erpc_get_hw_free_rec_data_addr(erpc_hardware_t *hw) { erpc_packet_cache_t *cache = erpc_hw_get_free_rec_cache(hw); if (cache == NULL) { return NULL; } return (u8 *)&cache->package; } /** * @brief 获取空闲的发送缓存 */ erpc_packet_cache_t *erpc_hw_get_free_send_cache(erpc_hardware_t *hw) { for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++) { if (hw->send_cache->state == ERPC_CACHE_STA_FREE) { return hw->send_cache + i; } } return NULL; } /** * @brief 设置包信息 */ void erpc_set_package(erpc_package_t *package, u8 src_id, u8 dest_id, u8 type, u16 port, u8 *data, u16 len) { package->head.src_id = src_id; package->head.dest_id = dest_id; package->head.type = type; package->head.port = port; package->head.len = len; if (data != NULL && len > 0) { for (int i = 0; i < len; i++) { package->data[i] = data[i]; } } // 计算crc u16 crc = 0; crc = crc16((u8 *)&package->head, crc, sizeof(erpc_package_head_t)); if (data != NULL && len > 0) { crc = crc16(package->data, crc, len); } package->crc = crc; } #define FUN_WAIT_ACK(time_out, hw, send_cache, error) \ while (timeout) \ { \ if (send_cache->state == ERPC_CACHE_SEND_GET_ACK) \ { \ break; \ } \ CHECK_RETURN_DO(send_cache->state == ERPC_CACHE_HW_SEND_ERR, ERPC_ERR_HW_SEND_FAIL, send_cache->state = ERPC_CACHE_STA_FREE); \ CHECK_RETURN_DO(send_cache->state == ERPC_CACHE_ERR_NO_RESP, ERPC_ERR_DEST_NO_RESP, send_cache->state = ERPC_CACHE_STA_FREE); \ timeout--; \ hw->sleep(1); \ } \ send_cache->state = ERPC_CACHE_STA_FREE; \ CHECK_RETURN(timeout == 0, error); /** * @brief 发送请求包并等待从机回复 */ u32 erpc_send_and_wait_resp(erpc_hardware_t *hw, u8 dest_id, u16 port, u8 *data, u16 len, u8 *resp_data, u16 *resp_len, u32 timeout) { if (len > ERPC_DATA_MAX_LEN) { return ERPC_ERR_DATA_LEN_OVERFLOW; } erpc_packet_cache_t *send_cache = erpc_hw_get_free_send_cache(hw); CHECK_RETURN(send_cache == NULL, ERPC_ERR_SEND_CACHE_FULL); // 发送request包 erpc_set_package(&send_cache->package, hw->local_id, dest_id, ERPC_PKG_TYPE_REQUEST, port, data, len); send_cache->state = ERPC_CACHE_WAIT_SEND; // 等待ack包 FUN_WAIT_ACK(timeout, hw, send_cache, ERPC_ERR_SEND_TIMEOUT); // 等待response包 while (timeout) { // 寻找response包 erpc_packet_cache_t *recv_cache = NULL; for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++) { if (hw->recv_cache[i].state != ERPC_CACHE_RESP_DATA) { continue; } if (hw->recv_cache[i].package.head.port != port) { continue; } if (hw->recv_cache[i].package.head.src_id != dest_id) { continue; } if (hw->recv_cache[i].package.head.type != ERPC_PKG_TYPE_RESPONSE) { continue; } recv_cache = hw->recv_cache + i; } // 接收到response包 if (recv_cache != NULL) { u16 max_len = *resp_len; if (max_len > recv_cache->package.head.len) { max_len = recv_cache->package.head.len; } for (int i = 0; i < max_len; i++) { resp_data[i] = recv_cache->package.data[i]; } *resp_len = max_len; recv_cache->state = ERPC_CACHE_STA_FREE; break; } timeout--; hw->sleep(1); } CHECK_RETURN(timeout == 0, ERPC_ERR_SEND_TIMEOUT); return 0; } /** * @brief 发送response包 */ u32 erpc_resp(erpc_hardware_t *hw, u8 dest_id, u16 port, u8 *data, u16 len, u32 timeout) { if (len > ERPC_DATA_MAX_LEN) { return ERPC_ERR_DATA_LEN_OVERFLOW; } erpc_packet_cache_t *send_cache = erpc_hw_get_free_send_cache(hw); CHECK_RETURN(send_cache == NULL, ERPC_ERR_SEND_CACHE_FULL); // 发送response包 erpc_set_package(&send_cache->package, hw->local_id, dest_id, ERPC_PKG_TYPE_RESPONSE, port, data, len); FUN_WAIT_ACK(timeout, hw, send_cache, ERPC_ERR_SEND_TIMEOUT); return 0; } u32 erpc_send_ack(erpc_hardware_t *hw, erpc_package_t *rec_package, u32 timeout) { erpc_packet_cache_t *send_cache = erpc_hw_get_free_send_cache(hw); CHECK_RETURN(send_cache == NULL, ERPC_ERR_SEND_CACHE_FULL); // 发送ack包 erpc_set_package(&send_cache->package, hw->local_id, rec_package->head.src_id, ERPC_PKG_TYPE_ACK, rec_package->head.port, NULL, 0); FUN_WAIT_ACK(timeout, hw, send_cache, ERPC_ERR_SEND_TIMEOUT); return 0; } u32 erpc_data_out_core(erpc_hardware_t *hw) { for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++) { u32 ret = 0; switch (hw->send_cache[i].state) { case ERPC_CACHE_STA_FREE: break; case ERPC_CACHE_WAIT_SEND: hw->send_cache[i].retry_count = 0; hw->send_cache[i].state = ERPC_CACHE_SEND_ONCE; ret = hw->send((u8 *)&hw->send_cache[i].package, hw->send_cache[i].package.head.len + sizeof(erpc_package_head_t)); if (ret) { hw->send_cache[i].state = ERPC_CACHE_HW_SEND_ERR; } break; case ERPC_CACHE_SEND_REPEAT: case ERPC_CACHE_SEND_ONCE: hw->send_cache[i].timeout--; if (hw->send_cache[i].timeout == 0) { if (hw->send_cache[i].retry_count < ERPC_SEND_RETRY_COUNT) { hw->send_cache[i].retry_count++; hw->send_cache[i].state = ERPC_CACHE_SEND_REPEAT; ret = hw->send((u8 *)&hw->send_cache[i].package, hw->send_cache[i].package.head.len + sizeof(erpc_package_head_t)); if (ret) { hw->send_cache[i].state = ERPC_CACHE_HW_SEND_ERR; } } else { hw->send_cache[i].state = ERPC_CACHE_ERR_NO_RESP; } } break; default: break; } } hw->sleep(1); return 0; } /** * @brief 手动写入接收缓存 */ void erpc_write_recv_cache(erpc_hardware_t *hw, u8 *data, u16 len) { erpc_packet_cache_t *recv_cache = erpc_hw_get_free_rec_cache(hw); if (recv_cache == NULL) { return; } recv_cache->state = ERPC_CACHE_REV_PACKAGE; for (int i = 0; i < len; i++) { recv_cache->package.data[i] = data[i]; } } u32 erpc_data_in_core(erpc_hardware_t *hw) { for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++) { u32 ret = 0; switch (hw->recv_cache[i].state) { case ERPC_CACHE_STA_FREE: break; case ERPC_CACHE_REV_PACKAGE: hw->recv_cache[i].retry_count = 0; while (hw->recv_cache[i].retry_count < ERPC_SEND_RETRY_COUNT) { ret = erpc_send_ack(hw, &hw->recv_cache[i].package, ERPC_ACK_TIMEOUT); if (ret == 0) { hw->recv_cache[i].state = ERPC_CACHE_RESP_ACK; break; } else { hw->recv_cache[i].retry_count++; } } break; default: break; } } hw->sleep(1); return 0; } u32 erpc_deal_core(erpc_hardware_t *hw) { for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++) { if (hw->send_cache[i].state != ERPC_CACHE_RESP_ACK) { continue; } if (hw->lock != NULL && hw->unlock != NULL) { hw->lock(); } if (hw->send_cache[i].state != ERPC_CACHE_RESP_ACK) { if (hw->unlock != NULL) { hw->unlock(); } continue; } hw->send_cache[i].state = ERPC_CACHE_WAIT_DEAL; if (hw->unlock != NULL) { hw->unlock(); } // 处理接收到的包 erpc_handle_list_t *handle_list = hw->handle_list; while (handle_list != NULL) { if (handle_list->port == hw->send_cache[i].package.head.port) { handle_list->handle(hw, hw->send_cache[i].package.head.src_id, hw->send_cache[i].package.head.port); break; } handle_list++; } hw->send_cache[i].state = ERPC_CACHE_STA_FREE; } hw->sleep(1); return 0; }