Compare commits

..

1 Commits
main ... new

Author SHA1 Message Date
chenyf 38dafddb01 fix:null 2024-12-08 09:14:22 +08:00
15 changed files with 392 additions and 732 deletions

View File

@ -1,7 +1,5 @@
{
"files.associations": {
"*.ndjson": "jsonl",
"*.dbclient-js": "javascript",
"spi_port.h": "c",
"cmd_def.h": "c",
"config.h": "c",
@ -23,9 +21,7 @@
"string.h": "c",
"stdio.h": "c",
"stdlib.h": "c",
"algorithm": "c",
"initializer_list": "c",
"utility": "c"
"algorithm": "c"
},
"makefile.launchConfigurations": [
{

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -9,14 +9,7 @@
#define u32 unsigned int
#define UNUSED(x) (void)(x)
#define ERPC_DEBUG_ENABLE 1
#if(ERPC_DEBUG_ENABLE == 1)
#define ERPC_DEBUG(...) printf(__VA_ARGS__)
#else
#define ERPC_DEBUG(...)
#endif
// #define ERPC_DEBUG(...)
#endif /* _CONFIG_H_ */

15
crc16.c
View File

@ -31,7 +31,16 @@ static const u16 crc16tab[256] = {
0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
inline u16 crc16_cal(u16 data,u16 crc)
/**
* @brief CRC16校验码
* @param buf
* @param crc CRC值 0
* @param len
*/
u16 crc16(u8 *buf, u16 crc, u32 len)
{
return (crc << 8) ^ crc16tab[((crc >> 8) ^ data) & 0x00FF];
}
u32 counter;
for (counter = 0; counter < (int)len; counter++)
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ *buf++) & 0x00FF];
return crc;
}

View File

@ -8,8 +8,7 @@ extern "C" {
#include <stddef.h>
#include <stdint.h>
#include "config.h"
u16 crc16_cal(u16 data,u16 crc);
u16 crc16(u8 *buf,u16 crc, u32 len);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -1,413 +1,314 @@
#include "erpc_core.h"
#include <stdio.h>
#include "crc16.h"
#include "string.h"
void cal_crc16(erpc_msg_t *msg)
/**
* @brief
*/
erpc_packet_cache_t *erpc_hw_get_free_rec_cache(erpc_hardware_t *hw)
{
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++)
for (int i = 0; i < ERPC_HW_CACHE_SIZE; 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)
if (hw->recv_cache->state == ERPC_CACHE_STA_FREE)
{
return &hw->send_cache[i];
return hw->recv_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
* @brief
* DMA方式接收数据
*/
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)
u8 *erpc_get_hw_free_rec_data_addr(erpc_hardware_t *hw)
{
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_packet_cache_t *cache = erpc_hw_get_free_rec_cache(hw);
if (cache == NULL)
{
erpc_cache_t *rec = find_response_cache(hw, dest_id, port);
if (rec != 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)
{
// 拷贝数据
int len = rec->msg.len;
if (len > *len_in)
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)
{
len = *len_in;
continue;
}
memcpy(data_in, rec->msg.data, len);
*len_in = len;
rec->state = CACHE_FREE;
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;
}
recv_timeout--;
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);
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 send_response(erpc_hw_t *hw, erpc_cache_t *cache_rec, u8 *data, u16 len, u16 timeout, u8 retry)
u32 erpc_send_ack(erpc_hardware_t *hw, erpc_package_t *rec_package, u32 timeout)
{
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;
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 write_rec_cache(erpc_hw_t *hw, u8 *data, u16 len)
u32 erpc_data_out_core(erpc_hardware_t *hw)
{
for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++)
for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++)
{
if (hw->recv_cache[i].state == CACHE_FREE)
u32 ret = 0;
switch (hw->send_cache[i].state)
{
hw->lock();
u8 *data_in = (u8 *)&hw->recv_cache[i].msg;
for (int j = 0; j < len; j++)
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)
{
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;
hw->send_cache[i].state = ERPC_CACHE_HW_SEND_ERR;
}
break;
case ERPC_MSG_TYPE_RESPONSE:
case ERPC_CACHE_SEND_REPEAT:
case ERPC_CACHE_SEND_ONCE:
hw->send_cache[i].timeout--;
if (hw->send_cache[i].timeout == 0)
{
cache->state = CACHE_GET_RESP;
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;
case ERPC_MSG_TYPE_REQUEST:
{
cache->state = CACHE_WAIT_HANDLE;
}
break;
default:
break;
}
}
break;
default:
break;
}
}
hw->sleep(1);
return 0;
}
void recv_handle(erpc_hw_t *hw)
/**
* @brief
*/
void erpc_write_recv_cache(erpc_hardware_t *hw, u8 *data, u16 len)
{
for (int i = 0; i < ERPC_MSG_CACHE_SIZE; i++)
erpc_packet_cache_t *recv_cache = erpc_hw_get_free_rec_cache(hw);
if (recv_cache == NULL)
{
erpc_cache_t *cache = &hw->recv_cache[i];
if (cache->state == CACHE_WAIT_HANDLE)
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)
{
cache->state = CACHE_FREE;
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;
}

View File

@ -1,110 +1,108 @@
#ifndef _ERPC_CORE_H_
#define _ERPC_CORE_H_
#include "config.h"
#include "list.h"
#define ERPC_VERSION_MAJOR 1
#define ERPC_VERSION_MAJOR 0
#define ERPC_VERSION_MINOR 0
#define ERPC_VERSION_PATCH 0
#define ERPC_VERSION_PATCH 1
#define ERPC_MSG_HEADER_SIZE 9
#define ERPC_MSG_DATA_MAX_SIZE (256 - ERPC_MSG_HEADER_SIZE + 2)
#define ERPC_MSG_CACHE_SIZE 16 // Maximum number of messages in cache
#define ERPC_SEND_TIMEOUT 30 // 发送超时时间单位tick
typedef struct erpc_msg_t
#define ERPC_HW_CACHE_SIZE 10 // erpc 硬件缓存大小,单位为包
#define ERPC_SEND_ONCE_TIMEOUT 30 // ERPC_数据包发送超时时间单位为tick
#define ERPC_SEND_RETRY_COUNT 3 // ERPC_数据包重发次数
#define ERPC_ACK_TIMEOUT ERPC_SEND_ONCE_TIMEOUT // ERPC_ack超时时间单位为tick
typedef struct erpc_package_head_t
{
u8 src_id;
u8 dest_id;
u8 type;
u8 src_id;
u16 port;
u8 type;
u16 len;
} erpc_package_head_t;
// crc16 只能保护256字节的有效数据所以这里限制最大数据长度为256-sizeof(erpc_package_head_t)
#define ERPC_DATA_MAX_LEN (256 - sizeof(erpc_package_head_t))
typedef struct erpc_package_t
{
erpc_package_head_t head;
u16 crc;
u8 data[ERPC_MSG_DATA_MAX_SIZE];
} erpc_msg_t;
u8 data[ERPC_DATA_MAX_LEN];
} erpc_package_t;
typedef struct erpc_cache_t
typedef struct erpc_packet_cache_t
{
u8 state;
erpc_msg_t msg;
} erpc_cache_t;
typedef enum erpc_msg_type
{
ERPC_MSG_TYPE_REQUEST = 0,
ERPC_MSG_TYPE_ACK,
ERPC_MSG_TYPE_RESPONSE,
}erpc_msg_type;
typedef enum erpc_cache_state
{
CACHE_FREE = 0,
// 占用
CACHE_IN_USE,
// 发送cache
CACHE_WAIT_SEND,
CACHE_SEND_OK,
CACHE_SEND_HW_ERR,
// 接收cache
CACHE_GET_DATA, // 发现数据
CACHE_GET_MSG, // 发现完整消息
CACHE_REC_ACK, // 收到ACK
CACHE_GET_RESP, // 收到RESP数据包
CACHE_WAIT_HANDLE, // 等待处理
} erpc_cache_state;
typedef enum erpc_error
{
ERPC_OK = 0,
// 发送REQ
ERPC_ERR_NO_FREE_SEND_CACHE, // 没有空闲的发送缓存
ERPC_ERR_SEND_TIMEOUT, // 发送REQ超时
ERPC_ERR_SEND_ACK_TIMEOUT, // 发送REQ成功但是没有收到ACK
ERPC_ERR_SEND_PORT_IS_INUSE, // 发送失败,端口已被占用
ERPC_ERR_SEND_HW_ERR, // 发送失败,硬件错误
// 接收REQ
ERPC_ERR_NO_CMD_RETURN, // 发生REQ成功但是没有收到RESP包
} erpc_error;
typedef struct erpc_hw_t
{
u8 local_id;
void (*lock)(void);
void (*unlock)(void);
void (*sleep)(u32 ms);
u32 (*send)(u8 *data, u16 len);
erpc_cache_t send_cache[ERPC_MSG_CACHE_SIZE];
erpc_cache_t recv_cache[ERPC_MSG_CACHE_SIZE];
list_t handler_list;
} erpc_hw_t;
u8 retry_count;
u8 timeout;
erpc_package_t package;
} erpc_packet_cache_t;
typedef struct handler_list_t
typedef enum cache_state
{
ERPC_CACHE_STA_FREE = 0, // 空闲状态
ERPC_CACHE_WAIT_SEND, // data包等待发送
ERPC_CACHE_SEND_ONCE, // 已经发送过一次等待ack
ERPC_CACHE_SEND_REPEAT, // data包多次发送
ERPC_CACHE_SEND_GET_ACK, // data包发送完成得到ack
ERPC_CACHE_HW_SEND_ERR, // 硬件发送失败
ERPC_CACHE_ERR_NO_RESP, // dest 无响应
ERPC_CACHE_RESP_DATA, // 收到响应包
ERPC_CACHE_REV_PACKAGE, // 收到数据包,但是还没有进行处理
ERPC_CACHE_RESP_ACK, // 接收到数据包正在回复ack
ERPC_CACHE_WAIT_DEAL, // 等待处理线程处理数据,处理线程已经获取到处理权限
} cache_state;
typedef enum erpc_package_type
{
ERPC_PKG_TYPE_REQUEST = 0,
ERPC_PKG_TYPE_RESPONSE,
ERPC_PKG_TYPE_ACK,
} erpc_package_type;
typedef enum erpc_transport_error
{
ERPC_ERR_SEND_CACHE_FULL = 1,
ERPC_ERR_SEND_TIMEOUT,
ERPC_ERR_DATA_LEN_OVERFLOW,
ERPC_ERR_HW_SEND_FAIL,
ERPC_ERR_DEST_NO_RESP,
} erpc_transport_state;
typedef struct erpc_handle_list_t
{
u16 port;
void (*handle)(erpc_hw_t *hw, erpc_cache_t *cache, u8 *data, u16 len);
} handler_list_t;
#define CHECK_DEAL(condition, error) \
if ((condition)) \
return error;
void (*handle)(void *hw, u8 src_id, u16 port);
} erpc_handle_list_t;
/**
* sleep
*
*/
void send_core(erpc_hw_t *hw);
void recv_core(erpc_hw_t *hw);
void recv_handle(erpc_hw_t *hw);
typedef struct erpc_hardware_t
{
erpc_packet_cache_t send_cache[ERPC_HW_CACHE_SIZE];
erpc_packet_cache_t recv_cache[ERPC_HW_CACHE_SIZE];
u8 local_id; // hardware 节点ID
u32 (*send)(u8 *data, u32 len); // 需要在内部实现lock功能,确保send函数是原子操作
u32 (*sleep)(u32 ms); // 睡眠函数
void (*lock)(void); // 锁函数
void (*unlock)(void); // 解锁函数
erpc_handle_list_t *handle_list; // 处理函数列表
} erpc_hardware_t;
/**
*
*/
u32 send_request(erpc_hw_t *hw, u8 dest_id, u16 port, u8 *data, u16 len, u16 timeout, u8 retry);
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);
u32 send_response(erpc_hw_t *hw, erpc_cache_t *cache, u8 *data, u16 len, u16 timeout, u8 retry);
u32 write_rec_cache(erpc_hw_t *hw, u8 *data, u16 len);
/**
*
*/
#define EXPORT_ERPC_HANDLE(hw, _port, _handle) \
static handler_list_t _A##_handle = \
{ \
.port = _port,\
.handle = _handle,\
};\
EXPORT_LIST_NODE(hw.list,_A##_handle);
#define CHECK_RETURN(condition, ret) \
if (condition) \
{ \
return ret; \
}
#define CHECK_RETURN_DO(condition, ret, handle) \
if (condition) \
{ \
handle; \
return ret; \
}
#endif /* _ERPC_CORE_H_ */
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);
u32 erpc_resp(erpc_hardware_t *hw, u8 dest_id, u16 port, u8 *data, u16 len, u32 timeout);
u32 erpc_data_out_core(erpc_hardware_t *hw);
void erpc_write_recv_cache(erpc_hardware_t *hw, u8 *data, u16 len);
u32 erpc_data_in_core(erpc_hardware_t *hw);
u32 erpc_deal_core(erpc_hardware_t *hw);
#endif // _ERPC_CORE_H_

View File

@ -1,104 +1,7 @@
#include "erpc_core.h"
#include <windows.h>
#include <stdio.h>
HANDLE hMutex;
static void lock()
{
WaitForSingleObject(hMutex, INFINITE);
}
static void unlock()
{
ReleaseMutex(hMutex);
}
static void sleep(u32 ms)
{
Sleep(ms);
}
extern erpc_hw_t port_self;
static u32 erpc_send(u8 *data, u16 len)
{
write_rec_cache(&port_self,data,len);
}
erpc_hw_t port_self = {
.lock = lock,
.unlock = unlock,
.sleep = sleep,
.local_id = 0x12,
.send = erpc_send,
};
static void test1(){
}
DWORD WINAPI fun(LPVOID lpParam)
{
UNUSED(lpParam);
while (1)
{
Sleep(1000);
}
}
DWORD WINAPI send_thread(LPVOID lpParam)
{
UNUSED(lpParam);
while (1)
{
send_core(&port_self);
Sleep(1);
}
}
DWORD WINAPI recv_thread(LPVOID lpParam)
{
UNUSED(lpParam);
while (1)
{
recv_core(&port_self);
Sleep(1);
}
}
DWORD WINAPI recv_handle_thread(LPVOID lpParam)
{
UNUSED(lpParam);
while (1)
{
recv_handle(&port_self);
Sleep(1);
}
}
int main()
{
hMutex = CreateMutex(NULL, FALSE, TEXT("MyMutex"));
if (hMutex == NULL)
{
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
HANDLE hThreads[4];
hThreads[0] = CreateThread(NULL, 0, fun, NULL, 0, NULL);
hThreads[1] = CreateThread(NULL, 0, send_thread, NULL, 0, NULL);
hThreads[2] = CreateThread(NULL, 0, recv_thread, NULL, 0, NULL);
hThreads[3] = CreateThread(NULL, 0, recv_handle_thread, NULL, 0, NULL);
// 等待所有线程完成
WaitForMultipleObjects(4, hThreads, TRUE, INFINITE);
// 关闭线程句柄
for (int i = 0; i < 4; i++)
{
CloseHandle(hThreads[i]);
}
// 关闭Mutex句柄
CloseHandle(hMutex);
return 0;
}
}

86
list.c
View File

@ -1,86 +0,0 @@
#include "list.h"
#include <stdio.h>
#include <stdlib.h>
int list_node_add(list_t *list, void *data)
{
list_node_t *new_node = (list_node_t *)malloc(sizeof(list_node_t));
if (new_node == NULL)
{
return LIST_ERR_MALLOC_FAILED;
}
new_node->data = data;
new_node->next = NULL;
if (*list == NULL)
{
*list = new_node;
}
else
{
list_node_t *node = *list;
while (node->next != NULL)
{
node = node->next;
}
node->next = new_node;
}
return LIST_OK;
}
int list_node_remove(list_t *list, void *data)
{
if (*list == NULL)
{
return LIST_ERR_LIST_IS_NULL;
}
list_node_t *node = *list;
list_node_t *prev = NULL;
while (node != NULL)
{
if (node->data == data)
{
if (prev == NULL)
{
if (node->next != NULL)
{
*list = node->next;
}
else
{
*list = NULL;
}
}
else
{
if (node->next != NULL)
{
prev->next = node->next;
}
else
{
prev->next = NULL;
}
}
free(node);
return LIST_OK;
}
prev = node;
node = node->next;
}
return 0;
}
int list_size(list_t *list)
{
if (*list == NULL)
{
return -1;
}
int size = 0;
list_node_t *node = *list;
while (node != NULL)
{
size++;
node = node->next;
}
return size;
}

47
list.h
View File

@ -1,47 +0,0 @@
#ifndef LIST_H
#define LIST_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
typedef struct list_node_t
{
void *data;
struct list_node_t *next;
} list_node_t;
typedef list_node_t *list_t;
typedef enum list_error
{
LIST_OK = 0,
LIST_ERR_LIST_IS_NULL = 1,
LIST_ERR_MALLOC_FAILED,
} list_error;
/**
* @brief list为NULL
* @param list
* @param data
*/
int list_node_add(list_t *list, void *data);
/**
* @brief
* @param list
* @param data
*/
int list_node_remove(list_t *list, void *data);
int list_size(list_t *list);
/**
* @param list
* @param data
* @warning
*/
#define EXPORT_LIST_NODE(list, data) \
int __attribute__((constructor)) export_list_node_##list_##data(void) \
{ \
return list_node_add(&list, (void *)&data); \
}
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // LIST_H

View File

@ -1,36 +1,30 @@
# Makefile for the mutex example project
# 指定编译器
# 定义编译器
CC = gcc
# 指定编译选项
CFLAGS = -Wall -Wextra -std=c11 -g
BUILD_DIR = build
# 源文件
SRCS = erpc_core.c \
erpc_port_self.c \
crc16.c\
list.c
INCLUDE_PATH = ./
# 目标文件
OBJS = $(SRCS:.c=.o)
# 用户可以指定输出文件夹
OUTPUT_DIR = ./build
# 可执行文件
Target = port_self.exe
# 查找所有的 .c 文件和对应的 .h 文件
SOURCES = $(wildcard $(INCLUDE_PATH)/*.c)
HEADERS = $(wildcard $(INCLUDE_PATH)/*.h)
OBJECTS = $(patsubst %.c,$(OUTPUT_DIR)/%.o,$(SOURCES))
# 定义最终可执行文件的路径
TARGET = $(OUTPUT_DIR)/program
# 默认目标
all: $(Target)
all: $(TARGET)
# 链接目标
$(Target): $(OBJS)
$(CC) -o $@ $(addprefix $(BUILD_DIR)/, $^)
# 编译源文件
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $(BUILD_DIR)/$@
# 定义每个目标文件的依赖关系
$(OUTPUT_DIR)/%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $@
# 清理目标
# 生成可执行文件
$(TARGET): $(OBJECTS)
$(CC) -o $(TARGET) $(OBJECTS)
# 清理生成的文件
clean:
rm -f $(OBJS) $(TARGET)
# 伪目标
.PHONY: all clean
rm -rf $(OUTPUT_DIR)/* $(TARGET)

Binary file not shown.