Compare commits

...

1 Commits
main ... new

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

View File

@ -1,16 +0,0 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.17 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.17">
<diagram name="第 1 页" id="iJ2ThG75liGc15h7RsxG">
<mxGraphModel dx="1036" dy="614" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="KNYXeKKRTsCmKzyxKpLt-1" value="host" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="60" y="280" width="90" height="40" as="geometry" />
</mxCell>
<mxCell id="KNYXeKKRTsCmKzyxKpLt-2" value="slave" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="270" y="280" width="90" height="40" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -20,7 +20,8 @@
"windows.h": "c",
"string.h": "c",
"stdio.h": "c",
"stdlib.h": "c"
"stdlib.h": "c",
"algorithm": "c"
},
"makefile.launchConfigurations": [
{

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -10,5 +10,6 @@
#define UNUSED(x) (void)(x)
#define ERPC_DEBUG(...) printf(__VA_ARGS__)
// #define ERPC_DEBUG(...)
#endif /* _CONFIG_H_ */

46
crc16.c
View File

@ -1,6 +1,6 @@
#include "crc16.h"
static const uint16_t crc16tab[256] = {
static const u16 crc16tab[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108,
0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210,
0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b,
@ -31,38 +31,16 @@ static const uint16_t crc16tab[256] = {
0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
// uint16_t crc16(const unsigned char *buf, size_t len) {
// int counter;
// uint16_t crc = 0;
// for (counter = 0; counter < (int)len; counter++)
// crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ *buf++) & 0x00FF];
// return crc;
// }
u16 cmd_cal_crc16(erpc_cmd_def_t *cmd) {
u16 crc = 0;
u32 counter = 0;
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.src_id) & 0x00FF];
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.dest_id) & 0x00FF];
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.msg_len) & 0x00FF];
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.type) & 0x00FF];
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->head.port) & 0x00FF];
for (counter = 0; counter < cmd->head.msg_len; counter++)
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ cmd->data[counter]) & 0x00FF];
cmd->crc_16[0] = (u8)(crc >> 8);
cmd->crc_16[1] = (u8)(crc & 0x00FF);
/**
* @brief CRC16校验码
* @param buf
* @param crc CRC值 0
* @param len
*/
u16 crc16(u8 *buf, u16 crc, u32 len)
{
u32 counter;
for (counter = 0; counter < (int)len; counter++)
crc = (crc << 8) ^ crc16tab[((crc >> 8) ^ *buf++) & 0x00FF];
return crc;
}
/**
* crc16校验
* return 0:
* return 1:
*/
u8 cmd_check_crc16(erpc_cmd_def_t *cmd) {
u16 crc = cmd_cal_crc16(cmd);
if (cmd->crc_16[0] != (u8)(crc >> 8) ||
cmd->crc_16[1] != (u8)(crc & 0x00FF)) {
return 1;
}
return 0;
}

View File

@ -8,10 +8,7 @@ extern "C" {
#include <stddef.h>
#include <stdint.h>
#include "config.h"
#include "erpc_core.h"
uint16_t crc16(const unsigned char *buf, size_t len);
u8 cmd_check_crc16(erpc_cmd_def_t *cmd);
u16 cmd_cal_crc16(erpc_cmd_def_t *cmd);
u16 crc16(u8 *buf,u16 crc, u32 len);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -1,614 +1,314 @@
#include "erpc_core.h"
#include <stdio.h>
#include "crc16.h"
/**
*
* @brief
*/
erpc_sleep erpc_sleep_tick = NULL;
static list_t erpc_hw;
void clean_cache(erpc_hw_cfg_t *hw)
erpc_packet_cache_t *erpc_hw_get_free_rec_cache(erpc_hardware_t *hw)
{
for (int i = 0; i < MAX_REC_CMD_CACHE_NUM; i++)
{
hw->rec_cache->state = ERPC_CMD_NO_ERROR;
}
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
{
hw->send_cache[i].state = ERPC_CMD_NO_ERROR;
}
}
/**
* hardware
* 线
*/
u32 erpc_hw_add(erpc_hw_cfg_t *hw)
{
list_t *list = &erpc_hw;
if (list->data == NULL)
{
list->data = (void *)hw;
clean_cache(hw);
return ERPC_NO_ERROR;
}
list_t *list_node = malloc(sizeof(list_t));
if (list_node == NULL)
{
return ERPC_ERR_MALLOC_ERROR;
}
list_node->data = (void *)hw;
u8 hw_ord = hw->ord;
// 检查hw是否已经存在
while (list != NULL)
{
erpc_hw_cfg_t *hw_cfg = (erpc_hw_cfg_t *)list->data;
if (hw_cfg->ord == hw_ord)
for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++)
{
return ERPC_ERR_HW_EXIST;
if (hw->recv_cache->state == ERPC_CACHE_STA_FREE)
{
return hw->recv_cache + i;
}
}
list = list->next;
}
list_t *result = list_append(&erpc_hw, hw);
if (result == NULL)
{
return ERPC_ERR_MALLOC_ERROR;
}
clean_cache(hw);
return ERPC_NO_ERROR;
}
/**
*
* 线
*/
u32 erpc_add_cmd_list(erpc_hw_cfg_t *hw, erpc_cmd_list_t *cmd_list)
{
list_t *list = &hw->cmd_list;
if (list->data == NULL)
{
list->data = (void *)cmd_list;
return ERPC_NO_ERROR;
}
list = list_append(&hw->cmd_list, cmd_list);
if (list == NULL)
{
return ERPC_ERR_MALLOC_ERROR;
}
return ERPC_NO_ERROR;
}
/**
* hardware
* 线
*/
u32 erpc_hw_remove(u8 hw)
{
list_t *list = &erpc_hw;
if (list->data == NULL)
{
return ERPC_ERR_NOFOND_HW;
}
while (list != NULL)
{
erpc_hw_cfg_t *hw_cfg = (erpc_hw_cfg_t *)list->data;
if (hw_cfg->ord == hw)
{
list_delete(&erpc_hw, list);
free(list);
return ERPC_NO_ERROR;
}
list = list->next;
}
return ERPC_ERR_NOFOND_HW;
}
/**
* hardware
*/
erpc_hw_cfg_t *erpc_hw_get(u8 hw)
{
list_t *list = &erpc_hw;
if (list->data == NULL)
{
return NULL;
}
while (list != NULL)
{
erpc_hw_cfg_t *hw_cfg = (erpc_hw_cfg_t *)list->data;
if (hw_cfg->ord == hw)
{
return hw_cfg;
}
}
return NULL;
}
u32 erpc_send_base(erpc_hw_cfg_t *hw_cfg, u8 dest_id, u16 port, u8 package_type,
u8 *data, u16 len)
/**
* @brief
* DMA方式接收数据
*/
u8 *erpc_get_hw_free_rec_data_addr(erpc_hardware_t *hw)
{
CHECK_IF_ERROR(hw_cfg == NULL, ERPC_ERR_NOFOND_HW);
u8 cache_ord = 255;
// 查找可用的发送缓存
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
{
if (hw_cfg->send_cache[i].state == ERPC_CMD_NO_ERROR)
erpc_packet_cache_t *cache = erpc_hw_get_free_rec_cache(hw);
if (cache == NULL)
{
// ERPC_DEBUG("find send cache %d\n", i);
cache_ord = i;
break;
return NULL;
}
}
return (u8 *)&cache->package;
}
CHECK_IF_ERROR(cache_ord == 255, ERPC_ERR_SEND_CACHE_FULL);
// 准备数据
hw_cfg->send_cache[cache_ord].state = ERPC_CMD_DATA_DEAL;
erpc_cmd_def_t *cmd =
(erpc_cmd_def_t *)&hw_cfg->send_cache[cache_ord].data[0];
cmd->head.dest_id = dest_id;
cmd->head.port = port;
cmd->head.msg_len = len;
if (data == NULL)
{
cmd->head.msg_len = 0;
len = 0;
}
cmd->head.type = package_type;
cmd->head.src_id = hw_cfg->local_id;
if (len > 0 && data != NULL)
{
/**
* @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++)
{
cmd->data[i] = data[i];
recv_cache->package.data[i] = data[i];
}
}
// 计算校验和
cmd_cal_crc16(cmd);
// 发送数据
hw_cfg->send_cache[cache_ord].state = ERPC_CMD_WAIT_SEND;
// 等待数据发送完成
int wait_time = CMD_TIMEOUT;
while (wait_time > 0)
{
if (hw_cfg->send_cache[cache_ord].state == ERPC_CMD_SEND_OK)
{
break;
}
if (hw_cfg->send_cache[cache_ord].state == ERPC_CMD_DEST_BUSY)
{
return ERPC_ERR_DEST_BUSY;
}
if (erpc_sleep_tick != NULL)
{
erpc_sleep_tick(1);
}
wait_time--;
}
u32 ret = ERPC_NO_ERROR;
do
{
if (wait_time == 0)
{
printf("send timeout,state:%d\n", hw_cfg->send_cache[cache_ord].state);
ret = ERPC_ERR_SEND_TIMEOUT;
break;
}
if (hw_cfg->send_cache[cache_ord].state == ERPC_CMD_SEND_ONCE)
{
ret = ERPC_ERR_DEST_NO_RESPONSE;
break;
}
if (hw_cfg->send_cache[cache_ord].state == ERPC_CMD_SEND_REPEAT)
{
ret = ERPC_ERR_DEST_NO_RESPONSE;
break;
}
} while (0);
hw_cfg->send_cache[cache_ord].state = ERPC_CMD_NO_ERROR;
return ret;
}
u32 erpc_boardcast(u16 port, u8 *data, u16 len)
u32 erpc_data_in_core(erpc_hardware_t *hw)
{
list_t *list = &erpc_hw;
if (list->data == NULL)
{
return ERPC_ERR_NOFOND_HW;
}
while (list != NULL)
{
erpc_hw_cfg_t *hw_cfg = (erpc_hw_cfg_t *)list->data;
u8 cache_ord = 255;
// 查找可用的发送缓存
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
for (int i = 0; i < ERPC_HW_CACHE_SIZE; i++)
{
if (hw_cfg->send_cache[i].state == ERPC_CMD_NO_ERROR)
{
// ERPC_DEBUG("find send cache %d\n", i);
cache_ord = i;
break;
}
}
if (cache_ord == 255)
{
continue;
}
// 准备数据
hw_cfg->send_cache[cache_ord].state = ERPC_CMD_DATA_DEAL;
erpc_cmd_def_t *cmd =
(erpc_cmd_def_t *)&hw_cfg->send_cache[cache_ord].data[0];
cmd->head.dest_id = ERPC_BOARDCAST_ID;
cmd->head.port = port;
cmd->head.src_id = hw_cfg->local_id;
cmd->head.msg_len = len;
if (data == NULL)
{
cmd->head.msg_len = 0;
}
if (len > 0 && data != NULL)
{
for (int i = 0; i < len; i++)
{
cmd->data[i] = data[i];
}
}
// 计算校验和
cmd_cal_crc16(cmd);
hw_cfg->send_cache[cache_ord].state = ERPC_CMD_WAIT_SEND;
}
}
u32 erpc_send(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len)
{
erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw);
u32 ret =
erpc_send_base(hw_cfg, dest_id, port, PACKAGE_TYPE_CMD_REQ, data, len);
return ret;
}
u32 erpc_wait_resp_package(u8 hw, u8 dest_id, u16 port, u8 *reply_data,
u16 *reply_len, u32 time_out)
{
erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw);
CHECK_IF_ERROR(hw_cfg == NULL, ERPC_ERR_NOFOND_HW);
while (time_out > 0)
{
for (int i = 0; i < MAX_REC_CMD_CACHE_NUM; i++)
{
erpc_data_cache_t *rec_cahce = &hw_cfg->rec_cache[i];
if (rec_cahce->state != ERPC_CMD_RESP_OK)
{
continue;
}
erpc_cmd_def_t *cmd = (erpc_cmd_def_t *)&rec_cahce->data[0];
if (cmd->head.port != port)
{
continue;
}
if (cmd->head.src_id != dest_id)
{
continue;
}
if (reply_data != NULL)
{
// memccpy(reply_data, cmd->data, 0, cmd->head.msg_len);
memcpy(reply_data, cmd->data, cmd->head.msg_len);
if (reply_len != NULL)
u32 ret = 0;
switch (hw->recv_cache[i].state)
{
*reply_len = cmd->head.msg_len;
}
}
rec_cahce->state = ERPC_CMD_NO_ERROR;
return ERPC_NO_ERROR;
}
if (erpc_sleep_tick != NULL)
{
erpc_sleep_tick(1);
}
time_out--;
}
CHECK_IF_ERROR(time_out == 0, ERPC_ERR_DEST_NO_REPLY);
return ERPC_NO_ERROR;
}
u32 erpc_send_wait_reply(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len,
u8 *reply_data, u16 *reply_len, u32 timeout)
{
u32 ret = erpc_send(hw, dest_id, port, data, len);
if (reply_len != NULL)
{
*reply_len = 0;
}
CHECK_IF_ERROR(ret != ERPC_NO_ERROR, ret);
ret =
erpc_wait_resp_package(hw, dest_id, port, reply_data, reply_len, timeout);
CHECK_IF_ERROR(ret != ERPC_NO_ERROR, ret);
return ERPC_NO_ERROR;
}
u32 erpc_replay(u8 hw, u8 dest_id, u16 port, u8 *data_out, u16 len)
{
erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw);
u32 ret = erpc_send_base(hw_cfg, dest_id, port, PACKAGE_TYPE_CMD_RESP,
data_out, len);
return ret;
}
u32 erpc_send_data(erpc_hw_cfg_t *hw)
{
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
{
if (hw->send_cache[i].state == ERPC_CMD_WAIT_SEND)
{
erpc_cmd_def_t *cmd = (erpc_cmd_def_t *)&hw->send_cache[i].data[0];
u32 len = sizeof(erpc_cmd_head_t) + 2 + cmd->head.msg_len;
hw->send_lock();
u8 ret = hw->write((u8 *)hw->send_cache[i].data, len);
hw->send_unlock();
CHECK_IF_ERROR(ret != 0, ERPC_ERR_HW_SEND_FAIL);
hw->send_cache[i].state = ERPC_CMD_SEND_ONCE;
}
}
return ERPC_NO_ERROR;
}
u32 erpc_rev_ack_package(erpc_hw_cfg_t *hw, erpc_cmd_def_t *cmd_rev)
{
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
{
if (hw->send_cache[i].state == ERPC_CMD_SEND_ONCE ||
hw->send_cache[i].state == ERPC_CMD_SEND_REPEAT)
{
erpc_cmd_def_t *cmd_send = (erpc_cmd_def_t *)&hw->send_cache[i].data[0];
if (cmd_rev->head.port == cmd_send->head.port)
{
hw->send_cache[i].state = ERPC_CMD_SEND_OK;
return ERPC_NO_ERROR;
}
}
}
return ERPC_NO_ERROR;
}
u32 erpc_rev_resp_package(erpc_hw_cfg_t *hw, erpc_cmd_def_t *cmd_rev)
{
erpc_cmd_def_t cmd_send;
cmd_send.head.dest_id = cmd_rev->head.src_id;
cmd_send.head.port = cmd_rev->head.port;
cmd_send.head.msg_len = 0;
cmd_send.head.type = PACKAGE_TYPE_CMD_RESP_ACK;
cmd_send.head.src_id = hw->local_id;
cmd_cal_crc16(&cmd_send);
u32 len = sizeof(erpc_cmd_head_t) + 2 + cmd_send.head.msg_len;
hw->send_lock();
u8 ret = hw->write((u8 *)&cmd_send, len);
hw->send_unlock();
CHECK_IF_ERROR(ret != 0, ERPC_ERR_HW_SEND_FAIL);
return ERPC_NO_ERROR;
}
// 重发数据包
u32 erpc_rev_repeat_package(erpc_hw_cfg_t *hw, erpc_cmd_def_t *cmd_rev)
{
for (int i = 0; i < MAX_SEND_CMD_CACHE_NUM; i++)
{
if (hw->send_cache[i].state == ERPC_CMD_SEND_ONCE ||
hw->send_cache[i].state == ERPC_CMD_SEND_REPEAT)
{
erpc_cmd_def_t *cmd_send = (erpc_cmd_def_t *)&hw->send_cache[i].data[0];
if (cmd_rev->head.port == cmd_send->head.port)
{
u32 len = sizeof(erpc_cmd_head_t) + 2 + cmd_send->head.msg_len;
hw->send_lock();
u32 ret = hw->write((u8 *)hw->send_cache[i].data, len);
hw->send_unlock();
hw->send_cache[i].state = ERPC_CMD_SEND_REPEAT;
CHECK_IF_ERROR(ret, ERPC_ERR_HW_SEND_FAIL); //
return ERPC_NO_ERROR;
}
}
}
return ERPC_NO_ERROR;
}
u32 erpc_send_ack_package(erpc_hw_cfg_t *hw, erpc_cmd_def_t *cmd_rev)
{
erpc_cmd_def_t cmd_send;
cmd_send.head.dest_id = cmd_rev->head.src_id;
cmd_send.head.port = cmd_rev->head.port;
cmd_send.head.msg_len = 0;
cmd_send.head.type = PACKAGE_TYPE_CMD_REQ_ACK;
cmd_send.head.src_id = hw->local_id;
cmd_cal_crc16(&cmd_send);
u32 len = sizeof(erpc_cmd_head_t) + 2 + cmd_send.head.msg_len;
hw->send_lock();
u8 ret = hw->write((u8 *)&cmd_send, len);
hw->send_unlock();
CHECK_IF_ERROR(ret != 0, ERPC_ERR_HW_SEND_FAIL);
return ERPC_NO_ERROR;
}
u32 erpc_rev_package(erpc_hw_cfg_t *hw)
{
for (int i = 0; i < MAX_REC_CMD_CACHE_NUM; i++)
{
if (hw->rec_cache[i].state == ERPC_CMD_WAIT_SERVER_DEAL)
{
hw->deal_lock();
if (hw->rec_cache[i].state == ERPC_CMD_WAIT_SERVER_DEAL)
{
hw->rec_cache[i].state = ERPC_CMD_SERVER_DEAL;
}
else
{
hw->deal_unlock();
continue;
}
hw->deal_unlock();
// ERPC_DEBUG("find cmd wait server deal %d\n", i);
erpc_cmd_def_t *cmd = (erpc_cmd_def_t *)&hw->rec_cache[i].data[0];
// 检查crc
u8 crc_result = cmd_check_crc16(cmd);
// 丢弃错误数据包
if (crc_result)
{
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
continue;
}
// 丢弃不是本地数据包
if (cmd->head.dest_id != hw->local_id)
{
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
continue;
}
// 处理数据包
switch (cmd->head.type)
{
case PACKAGE_TYPE_CMD_REQ:
ERPC_DEBUG("{REQ}\n");
erpc_send_ack_package(hw, cmd);
hw->rec_cache[i].state = ERPC_CMD_WAIT_TASK_DEAL;
break;
case PACKAGE_TYPE_CMD_REQ_ACK:
ERPC_DEBUG("{ACK}\n");
erpc_rev_ack_package(hw, cmd);
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
break;
case PACKAGE_TYPE_CMD_REPEAT:
erpc_rev_repeat_package(hw, cmd);
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
break;
case PACKAGE_TYPE_CMD_RESP:
ERPC_DEBUG("{RESP}\n");
erpc_rev_resp_package(hw, cmd);
hw->rec_cache[i].state = ERPC_CMD_RESP_OK;
break;
case PACKAGE_TYPE_CMD_RESP_ACK:
ERPC_DEBUG("{RESP_ACK}\n");
erpc_rev_ack_package(hw, cmd);
hw->rec_cache[i].state = ERPC_CMD_NO_ERROR;
break;
default:
break;
}
}
}
return ERPC_NO_ERROR;
}
void erpc_rev_package_core()
{
list_t *list = &erpc_hw;
if (list->data == NULL)
{
return;
}
while (list != NULL)
{
erpc_hw_cfg_t *hw = (erpc_hw_cfg_t *)list->data;
erpc_rev_package(hw);
list = list->next;
}
}
u32 erpc_set_rev_cahce(u8 hw, u8 *data, u16 len)
{
erpc_hw_cfg_t *hw_cfg = erpc_hw_get(hw);
CHECK_IF_ERROR(hw_cfg == NULL, ERPC_ERR_NOFOND_HW);
for (int i = 0; i < MAX_REC_CMD_CACHE_NUM; i++)
{
if (hw_cfg->rec_cache[i].state == ERPC_CMD_NO_ERROR)
{
// ERPC_DEBUG("set rev cache %d\r\n", i);
memcpy(hw_cfg->rec_cache[i].data, data, len);
hw_cfg->rec_cache[i].state = ERPC_CMD_WAIT_SERVER_DEAL;
return ERPC_NO_ERROR;
}
}
return ERPC_ERR_REC_CACHE_FULL;
}
void erpc_send_deal_core()
{
list_t *list = &erpc_hw;
if (list->data == NULL)
{
return;
}
while (list != NULL)
{
erpc_hw_cfg_t *hw = (erpc_hw_cfg_t *)list->data;
erpc_send_data(hw);
}
if (erpc_sleep_tick != NULL)
{
erpc_sleep_tick(1);
}
}
void erpc_rev_deal_core()
{
list_t *list = &erpc_hw;
if (list->data == NULL)
{
return;
}
while (list != NULL)
{
erpc_hw_cfg_t *hw = (erpc_hw_cfg_t *)list->data;
{ // 遍历接收缓存
for (int j = 0; j < MAX_REC_CMD_CACHE_NUM; j++)
{
{ // 发现等待处理的数据包
if (hw->rec_cache[j].state != ERPC_CMD_WAIT_TASK_DEAL)
{
continue;
}
}
{ // 多线程下,抢占处理权限
hw->deal_lock();
if (hw->rec_cache[j].state == ERPC_CMD_WAIT_TASK_DEAL)
{
// 获取指令的处理权限
hw->rec_cache[j].state = ERPC_CMD_WAIT_TASK_DEAL_FINISH;
}
else
{
// 已经有线程抢先执行了
hw->deal_unlock();
continue;
}
hw->deal_unlock();
}
{ // 处理指令
// 搜索指令列表
list_t *cmd_list = &hw->cmd_list;
// 链表是空的
if (cmd_list->data == NULL)
{
continue;
}
// 获取指令指针
erpc_cmd_def_t *cmd_def = (erpc_cmd_def_t *)hw->rec_cache[j].data;
while (cmd_list != NULL)
{ // 搜索指令列表
erpc_cmd_list_t *cmd_obj = (erpc_cmd_list_t *)cmd_list->data;
if (cmd_obj->cmd == cmd_def->head.port)
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)
{
if (cmd_obj->handle != NULL)
{
// 指令调用
cmd_obj->handle(hw->ord, cmd_def->head.src_id,
cmd_def->head.dest_id, cmd_def->head.port,
cmd_def->data, cmd_def->head.msg_len);
}
break;
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++;
}
}
cmd_list = cmd_list->next;
}
break;
default:
break;
}
// 处理完成 丢弃缓存 , 无论是否执行指令,都需要把数据包丢弃
hw->rec_cache[j].state = ERPC_CMD_NO_ERROR;
}
}
list = list->next;
}
if (erpc_sleep_tick != NULL)
{
erpc_sleep_tick(1);
}
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,145 +1,108 @@
#ifndef ERPC_CORE_H_
#define ERPC_CORE_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _ERPC_CORE_H_
#define _ERPC_CORE_H_
#include "config.h"
#include "list.h"
#define ERPC_VERSION "0.0.1"
typedef enum package_type {
PACKAGE_TYPE_DEV_POWER_ON = 0,
PACKAGE_TYPE_CMD_REQ,
PACKAGE_TYPE_CMD_REQ_ACK,
PACKAGE_TYPE_CMD_RESP,
PACKAGE_TYPE_CMD_RESP_ACK,
PACKAGE_TYPE_CMD_REPEAT, // crc校验失败请求重发
PACKAGE_TYPE_DEV_POWER_OFF,
PACKAGE_TYPE_CMD_SERCH_DEV_ONLINE,
} package_type;
#define ERPC_VERSION_MAJOR 0
#define ERPC_VERSION_MINOR 0
#define ERPC_VERSION_PATCH 1
// 广播ID
#define ERPC_BOARDCAST_ID 0xff
#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 dest_id;
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_DATA_MAX_LEN];
} erpc_package_t;
typedef struct erpc_cmd_head_t {
u8 src_id;
u8 dest_id;
u8 type; // package_type
u16 port; // 指令号,指令号=端口号
u8 msg_len;
} erpc_cmd_head_t;
typedef struct erpc_packet_cache_t
{
u8 state;
u8 retry_count;
u8 timeout;
erpc_package_t package;
} erpc_packet_cache_t;
#define MAX_CMD_LEN (256 - sizeof(erpc_cmd_head_t)) // crc16最大支持256字节
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, // 收到响应包
typedef struct erpc_cmd_def_t {
erpc_cmd_head_t head;
u8 crc_16[2];
u8 data[MAX_CMD_LEN];
} erpc_cmd_def_t;
ERPC_CACHE_REV_PACKAGE, // 收到数据包,但是还没有进行处理
ERPC_CACHE_RESP_ACK, // 接收到数据包正在回复ack
ERPC_CACHE_WAIT_DEAL, // 等待处理线程处理数据,处理线程已经获取到处理权限
} cache_state;
#define CMD_MAX_RETRY 5 // 最大重发次数
#define CMD_TIMEOUT 30 // 超时时间 tick
#define MAX_REC_CMD_CACHE_NUM \
10 // 最大接收指令缓存数量,接受指令优先级>处理指令优先级
#define MAX_SEND_CMD_CACHE_NUM \
10 // 最大发送指令缓存数量,发送指令优先级>接收指令优先级
typedef enum erpc_status {
ERPC_CMD_NO_ERROR, // 发送cache接收cache空闲
ERPC_CMD_DATA_DEAL, // 发送cache数据组织中
ERPC_CMD_WAIT_SERVER_DEAL, // 等待服务线程处理接受cache
ERPC_CMD_SERVER_DEAL, // 服务线程处理接受cache
ERPC_CMD_WAIT_TASK_DEAL, // 等待任务线程处理指令
ERPC_CMD_WAIT_TASK_DEAL_FINISH, // 等待任务线程处理指令完成
ERPC_CMD_WAIT_SEND, // 等待服务线程处理发送cache
ERPC_CMD_SEND_ONCE, // 发送指令成功
ERPC_CMD_SEND_REPEAT, // 发送指令重发
ERPC_CMD_SEND_OK, // 发送指令成功
ERPC_CMD_DEST_BUSY, // 目标设备忙
ERPC_CMD_RESP_OK, // 指令响应成功
} erpc_status;
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_data_cache_t {
u8 state;
u8 data[256];
} erpc_data_cache_t;
typedef u32 (*erpc_cmd_handle_t)(u8 src_id, u8 dest_id, u16 port, u8 *data,
u16 len);
typedef struct erpc_cmd_list_t {
u16 cmd;
u32 (*handle)(u8 hw, u8 src_id, u8 dest_id, u16 port, u8 *data, u16 len);
} erpc_cmd_list_t;
typedef enum ERPC_ROLE {
ERPC_ROLE_MASTER,
ERPC_ROLE_SLAVE,
} ERPC_ROLE;
typedef struct erpc_hw_cfg_t {
u8 ord;
u8 local_id;
u8 (*write)(u8 *data, u16 len);
void (*send_lock)(void);
void (*send_unlock)(void);
erpc_data_cache_t rec_cache[MAX_REC_CMD_CACHE_NUM];
erpc_data_cache_t send_cache[MAX_SEND_CMD_CACHE_NUM];
void (*deal_lock)(void);
void (*deal_unlock)(void);
list_t cmd_list;
} erpc_hw_cfg_t;
#define CHECK_IF_ERROR(condition, error) \
if (condition) { \
return error; \
}
#define CHECK_IF_ERROR_AND_DO(condition, error, action) \
if (condition) { \
action; \
return error; \
}
typedef enum erpc_error {
ERPC_NO_ERROR = 0,
ERPC_ERR_NOFOND_HW,
ERPC_ERR_SEND_CACHE_FULL,
ERPC_ERR_SEND_TIMEOUT,
ERPC_ERR_HW_SEND_FAIL, // 硬件层发来的错误 erpc_hw_cfg_t.write返回错误
ERPC_ERR_DEST_BUSY,
ERPC_ERR_DEST_NO_RESPONSE, // 目标设备无响应
ERPC_ERR_DEST_NO_REPLY, // 目标设备无回复或者回复超时
ERPC_ERR_MALLOC_ERROR, // malloc失败,内存不足
ERPC_ERR_HW_EXIST, // 硬件已经存在
ERPC_ERR_HW_NOT_EXIST, // 硬件不存在
ERPC_ERR_REC_CACHE_FULL, // 接收缓存满
} erpc_error;
typedef void (*erpc_sleep)(u32 tick);
void erpc_send_deal_core(); // 发送指令处理线程
u32 erpc_set_rev_cahce(u8 hw, u8 *data, u16 len); // 写入接受缓存
void erpc_rev_package_core(); // 处理接受到的包,通讯层面处理
void erpc_rev_deal_core(); // 处理接受到的指令,业务层面处理
extern erpc_sleep erpc_sleep_tick;
u32 erpc_hw_add(erpc_hw_cfg_t *hw);
u32 erpc_add_cmd_list(erpc_hw_cfg_t *hw, erpc_cmd_list_t *cmd_list);
typedef struct erpc_handle_list_t
{
u16 port;
void (*handle)(void *hw, u8 src_id, u16 port);
} erpc_handle_list_t;
/**
*
*
*/
u32 erpc_send(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len);
/**
*
*/
u32 erpc_send_wait_reply(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len,
u8 *reply_data, u16 *reply_len, u32 timeout);
/**
*
*/
u32 erpc_replay(u8 hw, u8 dest_id, u16 port, u8 *data_out, u16 len);
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 erpc_boardcast(u16 port, u8 *data, u16 len);
#define CHECK_RETURN(condition, ret) \
if (condition) \
{ \
return ret; \
}
#define CHECK_RETURN_DO(condition, ret, handle) \
if (condition) \
{ \
handle; \
return ret; \
}
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);
#endif /* ERPC_CORE_H_ */
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,3 +0,0 @@
#include "erpc_net.h"
#include "erpc_core.h"

View File

@ -1,3 +0,0 @@
#include "erpc_core.h"
u32 erpc_find_all();

7
erpc_port_self.c Normal file
View File

@ -0,0 +1,7 @@
#include "erpc_core.h"
#include <windows.h>
int main()
{
return 0;
}

View File

@ -1,39 +0,0 @@
## 协议设计
### 指令通讯
1. 指令发送方法:<br>
采用send-ack模式即主机发送指令后等待目标设备的ack确认确认后才认为指令发送成功。
2. notify-noreply模式<br>
接口:<br>
```c
u32 erpc_sand(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len)
```
描述:<br>
主机对目标设备发送一条指令,并不期待回复。其本质就是发送一次指令。
![](./picture/1.jpg)
3. notify-reply模式<br>
接口:<br>
```c
//主机:
u32 erpc_send_wait_reply(u8 hw, u8 dest_id, u16 port, u8 *data, u16 len, u8 *reply_data, u16 *reply_len, u32 timeout);
//目标设备:
u32 erpc_replay(u8 hw, u8 dest_id, u16 port, u8 *data_out, u16 len);
```
描述:<br>
本质由2条指令组成。<br>
主机发送req指令从机直接回复。主机开始等待从机指令。<br>
从机处理完成后向主机发送rep指令并附带回复数据。<br>
主机收到rep指令后开始等待rep指令的ack确认。<br>
![](./picture/2.jpg)
4. 指令工作在单线程模式下:<br>
指令发送后等待ack确认直到确认后才认为指令发送成功。如果确认超时则认为指令发送失败。
可以在上述的接口中发现 cmd 并不定义为cmd而是用了port的称呼。port的取值范围为0~65535可以用来表示不同的指令。<br>
4. 多device通讯方法<br>
每个port工作是单线程的这就意味着如果有多个device需要同时发送指令则需要多线程或多进程。也就意味着需要定义不同的port号来区分不同的线程哪怕他是相同的指令。<br>
例如节点0x03中挂在了3个电机需要这3个电机同时运动此时理论上指令是相同的但是device不同的。通讯库没有做device id的区分。为此需要将port号划分为cmd + device id的形式。cmd相同的指令device id不同这样就可以实现多device通讯。<br>
u16(port) = u8(cmd) + u8(device_id);<br>
这样一个cmd号需要链接到多个port上。此时的cmd可叫做cmd组
![](./picture/3.jpg)

90
list.c
View File

@ -1,90 +0,0 @@
#include "list.h"
#include "stdio.h"
#include "stdlib.h"
#include "config.h"
list_t *list_create(void *data)
{
list_t *node = (list_t *)malloc(sizeof(list_t));
if (node == NULL)
{
return NULL;
}
node->data = data;
node->next = NULL;
return node;
}
list_t *list_append(list_t *head, void *data)
{
list_t *node = list_create(data);
if (node == NULL)
{
return NULL;
}
if (head == NULL)
{
return NULL;
}
else
{
list_t *tail = head;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = node;
}
return head;
}
void list_print(list_t *head)
{
list_t *node = head;
while (node != NULL)
{
ERPC_DEBUG("%p\n", node->data);
node = node->next;
}
}
/**
* Destroy a list and all its nodes.
* @param head The head of the list.
*/
void list_destroy(list_t *head)
{
list_t *node = head;
while (node != NULL)
{
list_t *next = node->next;
free(node);
node = next;
}
}
/**
* Delete a node from the list.
* @param head The head of the list.
*/
void list_delete(list_t *head, void *data)
{
list_t *node = head;
list_t *prev = NULL;
while (node != NULL)
{
if (node->data == data)
{
if (prev == NULL)
{
head = node->next;
}
else
{
prev->next = node->next;
}
free(node);
return;
}
prev = node;
node = node->next;
}
}

17
list.h
View File

@ -1,17 +0,0 @@
#ifndef _LIST_H_
#define _LIST_H_
typedef struct list_t {
void *data;
struct list_t *next;
} list_t;
list_t *list_create(void *data);
list_t *list_append(list_t *head, void *data);
void list_print(list_t *head);
void list_destroy(list_t *head);
void list_delete(list_t *head, void *data);
#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 \
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.

Before

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,208 +0,0 @@
// #ifndef WINDOWS
// #error "This file is for Windows only"
// #endif
#include "erpc_core.h"
#include "windows.h"
#include <stdio.h>
u32 hellworld(u8 hw, u8 src_id, u8 dest_id, u16 port, u8 *data, u16 len)
{
ERPC_DEBUG("Hello World:\n");
ERPC_DEBUG("len = %d, msg :%s\n", len, data);
// 防止编译警告
UNUSED(hw);
UNUSED(src_id);
UNUSED(dest_id);
UNUSED(port);
UNUSED(data);
UNUSED(len);
return 0;
}
u32 hello_cat(u8 hw, u8 src_id, u8 dest_id, u16 port, u8 *data, u16 len)
{
ERPC_DEBUG("Hello Cat!\n");
// 防止编译警告
UNUSED(hw);
UNUSED(src_id);
UNUSED(dest_id);
UNUSED(port);
UNUSED(data);
UNUSED(len);
return 0;
}
u32 hello_dog(u8 hw, u8 src_id, u8 dest_id, u16 port, u8 *data, u16 len)
{
ERPC_DEBUG("Hello Dog!\n");
// 防止编译警告
u8 data_out[10] = "12345";
u32 ret = erpc_replay(hw, dest_id, port, data_out, sizeof(data_out));
ERPC_DEBUG("erpc_replay ret:%d\n", ret);
// 防止编译警告
UNUSED(ret);
UNUSED(hw);
UNUSED(src_id);
UNUSED(dest_id);
UNUSED(port);
UNUSED(data);
UNUSED(len);
return 0;
}
erpc_cmd_list_t erpc_cmd_list[] = {
{.cmd = 0x01, hellworld},
{.cmd = 0x02, hello_cat},
{.cmd = 0x03, hello_dog},
};
HANDLE deal_lock;
HANDLE send_lock;
static void deal_lock_h()
{
WaitForSingleObject(deal_lock, INFINITE);
}
static void deal_unlock_h()
{
ReleaseMutex(deal_lock);
}
static void send_lock_h()
{
WaitForSingleObject(send_lock, INFINITE);
}
static void send_unlock_h()
{
ReleaseMutex(send_lock);
}
u8 data[300];
static u8 data_write(u8 *data, u16 len)
{
erpc_set_rev_cahce(0, data, len);
return 0;
}
erpc_hw_cfg_t self_hw_cfg = {
.ord = 0,
.deal_lock = deal_lock_h,
.deal_unlock = deal_unlock_h,
.send_lock = send_lock_h,
.send_unlock = send_unlock_h,
.local_id = 0x01,
.write = data_write,
};
void erpc_cmd_config()
{
for (int i = 0; i < (int)sizeof(erpc_cmd_list) / (int)sizeof(erpc_cmd_list[0]); i++)
{
erpc_add_cmd_list(&self_hw_cfg, &erpc_cmd_list[i]);
}
}
void sys_sleep(u32 ms)
{
Sleep(ms);
}
DWORD WINAPI send_task(LPVOID lpParam)
{
UNUSED(lpParam);
while (1)
{
erpc_send_deal_core();
}
}
DWORD WINAPI rev_package_task(LPVOID lpParam)
{
UNUSED(lpParam);
while (1)
{
// ERPC_DEBUG("rev_task\n");
erpc_rev_package_core();
erpc_rev_deal_core();
}
}
DWORD WINAPI rev_deal_task(LPVOID lpParam)
{
UNUSED(lpParam);
while (1)
{
// ERPC_DEBUG("rev_task\n");
erpc_rev_package_core();
erpc_rev_deal_core();
}
}
DWORD WINAPI test_task(LPVOID lpParam)
{
UNUSED(lpParam);
ERPC_DEBUG("test_task\n");
while (1)
{
// ERPC_DEBUG("[test_task]send\n");
char msg[] = "miao miao miao\n";
u32 ret = erpc_send(self_hw_cfg.ord, self_hw_cfg.local_id, 0x01, (u8 *)msg, sizeof(msg));
ERPC_DEBUG("[test_task]send ret:%d\n", ret);
ret = erpc_send(self_hw_cfg.ord, self_hw_cfg.local_id, 0x02, NULL, 0);
ERPC_DEBUG("[test_task]send ret:%d\n", ret);
u16 reply_len = 30;
u8 data[reply_len];
ret = erpc_send_wait_reply(self_hw_cfg.ord, self_hw_cfg.local_id, 0x03, NULL, 0, data, &reply_len, 1000);
ERPC_DEBUG("[test_task]send ret:%d\n", ret);
for (int i = 0; i < reply_len; i++)
{
ERPC_DEBUG("%c", data[i]);
}
ERPC_DEBUG("\n");
UNUSED(ret);
sys_sleep(1000);
}
}
int main(int argc, char *argv[])
{
UNUSED(argc);
UNUSED(argv);
u32 ret = 0;
ERPC_DEBUG("erpc_port_self start\n");
ret = erpc_hw_add(&self_hw_cfg);
ERPC_DEBUG("erpc_hw_add ret:%d\n", ret);
CHECK_IF_ERROR(ret, 0);
erpc_cmd_config();
ERPC_DEBUG("erpc_cmd_config ret:%d\n", ret);
erpc_sleep_tick = sys_sleep;
HANDLE threadHandle[4];
deal_lock = CreateMutex(NULL, FALSE, NULL);
if (deal_lock == NULL)
{
ERPC_DEBUG("创建互斥锁失败\n");
return 1;
}
send_lock = CreateMutex(NULL, FALSE, NULL);
if (send_lock == NULL)
{
ERPC_DEBUG("创建互斥锁失败\n");
return 1;
}
threadHandle[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)send_task, NULL, 0, NULL);
threadHandle[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)rev_package_task, NULL, 0, NULL);
threadHandle[3] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)rev_deal_task, NULL, 0, NULL);
threadHandle[4] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)test_task, NULL, 0, NULL);
WaitForSingleObject(threadHandle[0], INFINITE);
WaitForSingleObject(threadHandle[1], INFINITE);
WaitForSingleObject(threadHandle[2], INFINITE);
WaitForSingleObject(threadHandle[3], INFINITE);
CloseHandle(threadHandle[0]);
CloseHandle(threadHandle[1]);
CloseHandle(threadHandle[2]);
CloseHandle(threadHandle[3]);
return 0;
}

Binary file not shown.

View File

View File

View File

@ -1,3 +0,0 @@
#include "spi_port.h"

View File

@ -1 +0,0 @@
#include "config.h"

View File

@ -1,2 +0,0 @@
#include "erpc_core.h"

View File

@ -1,45 +0,0 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.17 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.17">
<diagram name="第 1 页" id="iJ2ThG75liGc15h7RsxG">
<mxGraphModel dx="1050" dy="629" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="EQYeASZG-p6UUSDICV0d-25" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="EQYeASZG-p6UUSDICV0d-19" target="EQYeASZG-p6UUSDICV0d-23">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-19" value="port1" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="151" y="392" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="EQYeASZG-p6UUSDICV0d-20" target="EQYeASZG-p6UUSDICV0d-23">
<mxGeometry relative="1" as="geometry">
<mxPoint x="410" y="550" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-20" value="port2" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="151" y="490" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-27" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="EQYeASZG-p6UUSDICV0d-21" target="EQYeASZG-p6UUSDICV0d-23">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-21" value="..." style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="151" y="583" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="EQYeASZG-p6UUSDICV0d-22" target="EQYeASZG-p6UUSDICV0d-23">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-22" value="portn" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="151" y="680" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="EQYeASZG-p6UUSDICV0d-23" target="EQYeASZG-p6UUSDICV0d-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-23" value="cmd组" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="414" y="530" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="EQYeASZG-p6UUSDICV0d-24" value="相同的处理函数" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="630" y="530" width="120" height="60" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>