Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
|
38dafddb01 |
|
@ -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": [
|
||||
{
|
||||
|
|
BIN
build/crc16.o
BIN
build/crc16.o
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/list.o
BIN
build/list.o
Binary file not shown.
9
config.h
9
config.h
|
@ -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
15
crc16.c
|
@ -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;
|
||||
}
|
||||
|
|
3
crc16.h
3
crc16.h
|
@ -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 */
|
||||
|
|
633
erpc_core.c
633
erpc_core.c
|
@ -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;
|
||||
}
|
178
erpc_core.h
178
erpc_core.h
|
@ -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_
|
|
@ -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
86
list.c
|
@ -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
47
list.h
|
@ -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
|
48
makefile
48
makefile
|
@ -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)
|
||||
|
|
BIN
port_self.exe
BIN
port_self.exe
Binary file not shown.
Loading…
Reference in New Issue