314 lines
11 KiB
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;
|
|
} |