erpc/erpc_core.c

314 lines
11 KiB
C

#include "erpc_core.h"
#include <stdio.h>
#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;
}