mirror of
https://gitee.com/Lamdonn/varch.git
synced 2026-04-30 19:09:14 +08:00
Add the initial version icom(internal communication)
This commit is contained in:
parent
2d13818a5a
commit
af9120c9f8
86
doc/icom.en.md
Normal file
86
doc/icom.en.md
Normal file
@ -0,0 +1,86 @@
|
||||
# ICOM module documentation
|
||||
|
||||
## Overview
|
||||
|
||||
ICOM (Internal Communication) is a simple C language internal communication module, which is used to realize efficient bidirectional data communication in embedded systems. It provides a communication mechanism based on shared memory to support multi-channel data transmission and state management.
|
||||
|
||||
## Core features
|
||||
|
||||
- **Bidirectional communication** : Support for separate send and receive channels
|
||||
- **State management** : Provides four channel states: initialized, idle, busy, and error
|
||||
- **Data length control** : Supports dynamic data length setting and validation
|
||||
- **Live detection** : Automatically detects the online state of the communication peer
|
||||
- **Cache control** : Supports cache invalidation and writeback operations
|
||||
- **Multi-channel support** : Multiple send and receive channels can be configured
|
||||
|
||||
## Architectural Design
|
||||
|
||||
### Communication protocol format
|
||||
| offset | field | size | description |
|
||||
| :----: | :--: | :--: | :--------- |
|
||||
| 0 | Flag | 4 | Channel status flag |
|
||||
| 4 | Tcnt | 4 | Send channel count |
|
||||
| 8 | Rcnt | 4 | Receive channel count |
|
||||
| 12 | Dlen | 4 | data length |
|
||||
| 16 | Data | N | actual data |
|
||||
|
||||
### State Machine design
|
||||
|
||||
- **INIT** : The initial state
|
||||
- **BUSY** : Busy (in data transfer)
|
||||
- **IDLE** : Idle state (transferable)
|
||||
- **ERROR** : An error state
|
||||
|
||||
## API explained in detail
|
||||
|
||||
### Initialization functions
|
||||
```c
|
||||
int icom_init(ICOM *icom);
|
||||
```
|
||||
Initialize the ICOM module and configure the sending and receiving channels.
|
||||
|
||||
### Task handlers
|
||||
```c
|
||||
int icom_task(ICOM *icom);
|
||||
```
|
||||
Handle the periodic tasks of the ICOM module, including online state detection and data reception processing.
|
||||
|
||||
### Data sending function
|
||||
```c
|
||||
int icom_transmit(ICOM *icom, uint16_t channel, uint8_t *data, uint32_t length);
|
||||
```
|
||||
Send data over the specified channel.
|
||||
|
||||
### Data receiving functions
|
||||
```c
|
||||
int icom_receive(ICOM *icom, uint16_t channel, uint8_t *data, uint32_t *length);
|
||||
```
|
||||
Handle the periodic tasks of the ICOM module, including online state detection and data reception processing. Receives data from the specified channel.
|
||||
|
||||
### Online presence checks
|
||||
```c
|
||||
int icom_txchannel_online(ICOM *icom, uint16_t channel, uint8_t *online);
|
||||
int icom_rxchannel_online(ICOM *icom, uint16_t channel, uint8_t *online);
|
||||
```
|
||||
Check the online status of the send/receive channel.
|
||||
|
||||
## Instructions
|
||||
|
||||
1. Initialize the ICOM struct and configure the channel
|
||||
2. Call icom_init() for initialization
|
||||
3. Periodic calls to icom_task() for state management and data reception processing
|
||||
4. Use icom_transmit() to send data
|
||||
5. Use icom_receive() to receive data
|
||||
|
||||
## Advanced features
|
||||
|
||||
* Manual receive mode: You can manually check the receive status without using callbacks
|
||||
* Cache control: Cache control via 'inv' and 'wbinv' callbacks
|
||||
* Private data: Each channel maintains 4 private data words for extended functionality
|
||||
|
||||
## Use cases
|
||||
|
||||
* Inter-Processor Communication (IPC)
|
||||
* Data exchange between multiple cores
|
||||
* Modular system component communication
|
||||
* Embedded systems that require shared memory communication
|
||||
86
doc/icom.md
Normal file
86
doc/icom.md
Normal file
@ -0,0 +1,86 @@
|
||||
# ICOM 模块文档
|
||||
|
||||
## 概述
|
||||
|
||||
ICOM (Internal Communication) 是一个简单的C语言内部通信模块,用于在嵌入式系统中实现高效的双向数据通信。它提供了基于共享内存的通信机制,支持多通道数据传输和状态管理。
|
||||
|
||||
## 核心特性
|
||||
|
||||
- **双向通信**:支持独立的发送和接收通道
|
||||
- **状态管理**:提供初始化、空闲、忙碌、错误四种通道状态
|
||||
- **数据长度控制**:支持动态数据长度设置和校验
|
||||
- **在线检测**:自动监测通信对端在线状态
|
||||
- **缓存控制**:支持缓存无效化和回写操作
|
||||
- **多通道支持**:可配置多个发送和接收通道
|
||||
|
||||
## 架构设计
|
||||
|
||||
### 通信协议格式
|
||||
| 偏移量 | 字段 | 大小 | 描述 |
|
||||
| :----: | :---: | :--: | :--------- |
|
||||
| 0 | Flag | 4 | 通道状态标志 |
|
||||
| 4 | Tcnt | 4 | 发送通道计数 |
|
||||
| 8 | Rcnt | 4 | 接收通道计数 |
|
||||
| 12 | Dlen | 4 | 数据长度 |
|
||||
| 16 | Data | N | 实际数据 |
|
||||
|
||||
### 状态机设计
|
||||
|
||||
- **INIT** : 初始化状态
|
||||
- **BUSY** : 忙碌状态(数据传输中)
|
||||
- **IDLE** : 空闲状态(可传输)
|
||||
- **ERROR** : 错误状态
|
||||
|
||||
## API接口详解
|
||||
|
||||
### 初始化函数
|
||||
```c
|
||||
int icom_init(ICOM *icom);
|
||||
```
|
||||
初始化ICOM模块,配置发送和接收通道。
|
||||
|
||||
### 任务处理函数
|
||||
```c
|
||||
int icom_task(ICOM *icom);
|
||||
```
|
||||
处理ICOM模块的周期性任务,包括在线状态检测和数据接收处理。
|
||||
|
||||
### 数据发送函数
|
||||
```c
|
||||
int icom_transmit(ICOM *icom, uint16_t channel, uint8_t *data, uint32_t length);
|
||||
```
|
||||
通过指定通道发送数据。
|
||||
|
||||
### 数据接收函数
|
||||
```c
|
||||
int icom_receive(ICOM *icom, uint16_t channel, uint8_t *data, uint32_t *length);
|
||||
```
|
||||
处理ICOM模块的周期性任务,包括在线状态检测和数据接收处理。从指定通道接收数据。
|
||||
|
||||
### 在线状态检查
|
||||
```c
|
||||
int icom_txchannel_online(ICOM *icom, uint16_t channel, uint8_t *online);
|
||||
int icom_rxchannel_online(ICOM *icom, uint16_t channel, uint8_t *online);
|
||||
```
|
||||
检查发送/接收通道的在线状态。
|
||||
|
||||
## 使用指南
|
||||
|
||||
1. 初始化ICOM结构体并配置通道
|
||||
2. 调用icom_init()进行初始化
|
||||
3. 周期性调用icom_task()
|
||||
4. 使用icom_transmit()发送数据
|
||||
5. 使用icom_receive()接收数据
|
||||
|
||||
## 高级功能
|
||||
|
||||
* 手动接收模式:可以不使用回调函数,手动检查接收状态
|
||||
* 缓存控制:通过 `inv` 和 `wbinv` 回调函数实现缓存控制
|
||||
* 私有数据:每个通道维护4个私有数据字,用于扩展功能
|
||||
|
||||
## 应用场景
|
||||
|
||||
* 处理器间通信(IPC)
|
||||
* 多核间数据交换
|
||||
* 模块化系统组件通信
|
||||
* 需要共享内存通信的嵌入式系统
|
||||
631
source/06_performance/icom.c
Normal file
631
source/06_performance/icom.c
Normal file
@ -0,0 +1,631 @@
|
||||
/*********************************************************************************************************
|
||||
* ------------------------------------------------------------------------------------------------------
|
||||
* file description
|
||||
* ------------------------------------------------------------------------------------------------------
|
||||
* \file icom.c
|
||||
* \unit icom
|
||||
* \brief This is a simple internal communication module for C language
|
||||
* \author Lamdonn
|
||||
* \version v0.1.0
|
||||
* \license GPL-2.0
|
||||
* \copyright Copyright (C) 2026 Lamdonn.
|
||||
********************************************************************************************************/
|
||||
#include "icom.h"
|
||||
|
||||
/**
|
||||
* \brief: ICOM header field
|
||||
* \note: This size is used to store the flag, transmit channel count, receive channel count, and data length of the channel
|
||||
*/
|
||||
|
||||
#define ICOM_FLAG_SIZE (4) /**< ICOM flag size */
|
||||
#define ICOM_TCNT_SIZE (4) /**< ICOM transmit channel count size */
|
||||
#define ICOM_RCNT_SIZE (4) /**< ICOM receive channel count size */
|
||||
#define ICOM_DLEN_SIZE (4) /**< ICOM data length size */
|
||||
|
||||
/**
|
||||
* \brief: ICOM header field index
|
||||
* \note: This index is used to access the flag, transmit channel count, receive channel count, and data length of the channel
|
||||
*/
|
||||
|
||||
#define ICOM_FLAG_INDEX (0)
|
||||
#define ICOM_TCNT_INDEX (ICOM_FLAG_INDEX + ICOM_FLAG_SIZE)
|
||||
#define ICOM_RCNT_INDEX (ICOM_TCNT_INDEX + ICOM_TCNT_SIZE)
|
||||
#define ICOM_DLEN_INDEX (ICOM_RCNT_INDEX + ICOM_RCNT_SIZE)
|
||||
#define ICOM_DATA_INDEX (ICOM_DLEN_INDEX + ICOM_DLEN_SIZE)
|
||||
|
||||
/**
|
||||
* \brief: ICOM header size
|
||||
* \note:
|
||||
* | Offset | Field | Size | Description |
|
||||
* | :----: | :---: | :--: | :--------- |
|
||||
* | 0 | Flag | 4 | Channel flag |
|
||||
* | 4 | Tcnt | 4 | Transmit channel count |
|
||||
* | 8 | Rcnt | 4 | Receive channel count |
|
||||
* | 12 | Dlen | 4 | Data length |
|
||||
*/
|
||||
#define ICOM_HEAD_SIZE (ICOM_FLAG_SIZE + ICOM_TCNT_SIZE + ICOM_RCNT_SIZE + ICOM_DLEN_SIZE)
|
||||
|
||||
/**
|
||||
* \brief: ICOM channel flag
|
||||
* \note: This flag is used to indicate the status of the channel
|
||||
*/
|
||||
|
||||
#define ICOM_F_INIT ((uint8_t)0x12) /**< ICOM channel flag: initialized */
|
||||
#define ICOM_F_BUSY ((uint8_t)0x34) /**< ICOM channel flag: busy */
|
||||
#define ICOM_F_IDLE ((uint8_t)0x56) /**< ICOM channel flag: idle */
|
||||
#define ICOM_F_ERROR ((uint8_t)0x78) /**< ICOM channel flag: error */
|
||||
|
||||
#define getTxBase(i) (icom->txconfig[i].base) /**< ICOM transmit channel base address */
|
||||
#define getTxSize(i) (icom->txconfig[i].size) /**< ICOM transmit channel size */
|
||||
#define getTxFlag(i) (getTxBase(i)[ICOM_FLAG_INDEX]) /**< ICOM transmit channel flag */
|
||||
#define getTxDlen(i) (getTxBase(i)[ICOM_DLEN_INDEX]) /**< ICOM transmit channel data length */
|
||||
#define getTxData(i) (getTxBase(i)[ICOM_DATA_INDEX]) /**< ICOM transmit channel data */
|
||||
#define getTxTcnt(i) (getTxBase(i)[ICOM_TCNT_INDEX]) /**< ICOM transmit channel count */
|
||||
#define getTxRcnt(i) (getTxBase(i)[ICOM_RCNT_INDEX]) /**< ICOM transmit channel receive count */
|
||||
|
||||
#define getRxBase(i) (icom->rxconfig[i].base) /**< ICOM receive channel base address */
|
||||
#define getRxSize(i) (icom->rxconfig[i].size) /**< ICOM receive channel size */
|
||||
#define getRxFlag(i) (getRxBase(i)[ICOM_FLAG_INDEX]) /**< ICOM receive channel flag */
|
||||
#define getRxDlen(i) (getRxBase(i)[ICOM_DLEN_INDEX]) /**< ICOM receive channel data length */
|
||||
#define getRxData(i) (getRxBase(i)[ICOM_DATA_INDEX]) /**< ICOM receive channel data */
|
||||
#define getRxTcnt(i) (getRxBase(i)[ICOM_TCNT_INDEX]) /**< ICOM receive channel count */
|
||||
#define getRxRcnt(i) (getRxBase(i)[ICOM_RCNT_INDEX]) /**< ICOM receive channel receive count */
|
||||
|
||||
#define getTxPrivate(i) (icom->txconfig[i].private) /**< ICOM transmit channel private data */
|
||||
#define getRxPrivate(i) (icom->rxconfig[i].private) /**< ICOM receive channel private data */
|
||||
#define getPrivateOnline(p) ((p)[0]) /**< ICOM private data: online */
|
||||
#define getPrivateOffCnt(p) ((p)[1]) /**< ICOM private data: offline count */
|
||||
#define getPrivatePCount(p) ((p)[2]) /**< ICOM private data: process count */
|
||||
#define getPrivateCCount(p) ((p)[3]) /**< ICOM private data: complete count */
|
||||
|
||||
/**
|
||||
* \brief: ICOM cache invalidate function
|
||||
* \param addr: Cache address
|
||||
* \param size: Cache size
|
||||
*/
|
||||
#define Cache_Inv(addr, size) do { if (icom->inv) (icom->inv)((addr), (size)); } while (0)
|
||||
|
||||
/**
|
||||
* \brief: ICOM cache write-back invalidate function
|
||||
* \param addr: Cache address
|
||||
* \param size: Cache size
|
||||
*/
|
||||
#define Cache_wbInv(addr, size) do { if (icom->wbinv) (icom->wbinv)((addr), (size)); } while (0)
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmitter ready function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Channel number
|
||||
* \return: 1 means ready, 0 means not ready
|
||||
*/
|
||||
static int icom_transmitter_ready(ICOM *icom, uint16_t channel)
|
||||
{
|
||||
int ret = 0;
|
||||
Cache_Inv(&getRxFlag(channel), ICOM_FLAG_SIZE);
|
||||
switch (getRxFlag(channel))
|
||||
{
|
||||
case ICOM_F_INIT:
|
||||
{
|
||||
getRxFlag(channel) = ICOM_F_IDLE;
|
||||
Cache_wbInv(&getRxFlag(channel), ICOM_FLAG_SIZE);
|
||||
ret = 1;
|
||||
} break;
|
||||
case ICOM_F_IDLE:
|
||||
case ICOM_F_BUSY:
|
||||
{
|
||||
ret = 1;
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
ret = 0;
|
||||
} break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM set data length function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Channel number
|
||||
* \param length: Data length
|
||||
*/
|
||||
static void icom_set_data_length(ICOM *icom, uint16_t channel, uint32_t length)
|
||||
{
|
||||
/* Data length is stored in little-endian format */
|
||||
getTxBase(channel)[ICOM_DLEN_INDEX] = length & 0xFF;
|
||||
getTxBase(channel)[ICOM_DLEN_INDEX + 1] = (length >> 8) & 0xFF;
|
||||
getTxBase(channel)[ICOM_DLEN_INDEX + 2] = (length >> 16) & 0xFF;
|
||||
getTxBase(channel)[ICOM_DLEN_INDEX + 3] = (length >> 24) & 0xFF;
|
||||
Cache_wbInv(&(getTxBase(channel)[ICOM_DLEN_INDEX]), ICOM_DLEN_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM get data length function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Channel number
|
||||
* \return: Data length
|
||||
*/
|
||||
static uint32_t icom_get_data_length(ICOM *icom, uint16_t channel)
|
||||
{
|
||||
uint32_t length = 0;
|
||||
Cache_Inv(&(getRxBase(channel)[ICOM_DLEN_INDEX]), ICOM_DLEN_SIZE);
|
||||
/* Data length is stored in little-endian format */
|
||||
length = (uint32_t)((getRxBase(channel)[ICOM_DLEN_INDEX]) |
|
||||
(getRxBase(channel)[ICOM_DLEN_INDEX + 1] << 8) |
|
||||
(getRxBase(channel)[ICOM_DLEN_INDEX + 2] << 16) |
|
||||
(getRxBase(channel)[ICOM_DLEN_INDEX + 3] << 24));
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM control online function
|
||||
* \param icom: ICOM handle
|
||||
* \param private: Private data
|
||||
* \param count: Process count
|
||||
* \note: If process count is equal to complete count, then set online to 1.
|
||||
* If offline count is less than 5, then set offline count to 1.
|
||||
* Otherwise, set online to 0.
|
||||
* If online is 1, then set offline count to 0.
|
||||
* If offline count is greater than 5, then set online to 0.
|
||||
*/
|
||||
static void icom_control_online(ICOM *icom, uint32_t *private, uint32_t count)
|
||||
{
|
||||
getPrivateCCount(private) = count;
|
||||
if (getPrivateCCount(private) == getPrivatePCount(private))
|
||||
{
|
||||
if (getPrivateOffCnt(private) <= 5)
|
||||
{
|
||||
getPrivateOffCnt(private)++;
|
||||
}
|
||||
/* If offline count is greater than 5, then set online to 0 */
|
||||
else
|
||||
{
|
||||
getPrivateOnline(private) = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getPrivateOnline(private) = 1;
|
||||
getPrivateOffCnt(private) = 0;
|
||||
}
|
||||
getPrivatePCount(private) = getPrivateCCount(private);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM online handle function
|
||||
* \param icom: ICOM handle
|
||||
* \note: If online is 1, then increment transmitter count.
|
||||
* If offline count is greater than 5, then set online to 0.
|
||||
*/
|
||||
static void icom_online_handle(ICOM *icom)
|
||||
{
|
||||
uint16_t channel;
|
||||
|
||||
/* Handle tx channal */
|
||||
if (icom->txconfig && icom->txcount > 0)
|
||||
{
|
||||
for (channel = 0; channel < icom->txcount; channel++)
|
||||
{
|
||||
Cache_Inv(&getTxTcnt(channel), ICOM_TCNT_SIZE);
|
||||
/* Increase tx count to indicate tx channal is online */
|
||||
(*((uint32_t *)(&getTxTcnt(channel))))++;
|
||||
Cache_wbInv(&getTxTcnt(channel), ICOM_TCNT_SIZE);
|
||||
Cache_Inv(&getTxRcnt(channel), ICOM_RCNT_SIZE);
|
||||
/* Control online status */
|
||||
icom_control_online(icom, getTxPrivate(channel), (*((uint32_t *)&getTxRcnt(channel))));
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle rx channal */
|
||||
if (icom->rxconfig && icom->rxcount > 0)
|
||||
{
|
||||
for (channel = 0; channel < icom->rxcount; channel++)
|
||||
{
|
||||
Cache_Inv(&getRxRcnt(channel), ICOM_RCNT_SIZE);
|
||||
/* Increase rx count to indicate rx channal is online */
|
||||
(*((uint32_t *)(&getRxRcnt(channel))))++;
|
||||
Cache_wbInv(&getRxRcnt(channel), ICOM_RCNT_SIZE);
|
||||
Cache_Inv(&getRxTcnt(channel), ICOM_TCNT_SIZE);
|
||||
/* Control online status */
|
||||
icom_control_online(icom, getRxPrivate(channel), (*((uint32_t *)&getRxTcnt(channel))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM rxdata handle function
|
||||
* \param icom: ICOM handle
|
||||
* \note: If rx channal is ready, then check data length.
|
||||
* If data length is valid, then call callback function.
|
||||
* Otherwise, set rx channal to idle.
|
||||
*/
|
||||
static void icom_rxdata_handle(ICOM *icom)
|
||||
{
|
||||
uint16_t channel;
|
||||
uint32_t length = 0;
|
||||
|
||||
/* Handle Rx */
|
||||
if (icom->rxconfig && icom->rxcount > 0)
|
||||
{
|
||||
for (channel = 0; channel < icom->rxcount; channel++)
|
||||
{
|
||||
/* Check rx channal is ready */
|
||||
if (icom_transmitter_ready(icom, channel))
|
||||
{
|
||||
Cache_Inv(&getRxFlag(channel), ICOM_FLAG_SIZE);
|
||||
/* Check rx channal is busy.
|
||||
* Indicate that rx channal is ready to receive data.
|
||||
*/
|
||||
if (getRxFlag(channel) == ICOM_F_BUSY)
|
||||
{
|
||||
/* Get data length and check data length is valid */
|
||||
length = icom_get_data_length(icom, channel);
|
||||
if (length <= getRxSize(channel) - ICOM_HEAD_SIZE)
|
||||
{
|
||||
/* Call callback function */
|
||||
if (icom->rxconfig[channel].callback)
|
||||
{
|
||||
Cache_Inv(&getRxData(channel), length);
|
||||
icom->rxconfig[channel].callback(channel, &getRxData(channel), length);
|
||||
/* Set rx channal to idle */
|
||||
getRxFlag(channel) = ICOM_F_IDLE;
|
||||
Cache_wbInv(&getRxFlag(channel), ICOM_FLAG_SIZE);
|
||||
}
|
||||
else /* Receive manual */
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM initialize function
|
||||
* \param icom: ICOM handle
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_init(ICOM *icom)
|
||||
{
|
||||
uint16_t channel;
|
||||
|
||||
/* Input value validity check */
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (icom->init) return ICOM_E_OK;
|
||||
|
||||
/* Initialize tx channal */
|
||||
if (icom->txconfig && icom->txcount > 0)
|
||||
{
|
||||
for (channel = 0; channel < icom->txcount; channel++)
|
||||
{
|
||||
if (getTxBase(channel) != NULL)
|
||||
{
|
||||
/* Initialize tx channal flag */
|
||||
getTxFlag(channel) = ICOM_F_INIT;
|
||||
Cache_wbInv(&getTxFlag(channel), ICOM_FLAG_SIZE);
|
||||
}
|
||||
|
||||
/* Initialize tx channal private data */
|
||||
memset(getTxPrivate(channel), 0, sizeof(getTxPrivate(channel)));
|
||||
|
||||
/* Initialize tx channal callback function, default is NULL */
|
||||
icom->txconfig[channel].callback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize rx channal */
|
||||
if (icom->rxconfig && icom->rxcount > 0)
|
||||
{
|
||||
for (channel = 0; channel < icom->rxcount; channel++)
|
||||
{
|
||||
if (getRxBase(channel) != NULL)
|
||||
{
|
||||
/* Initialize rx channal flag */
|
||||
icom_transmitter_ready(icom, channel);
|
||||
}
|
||||
|
||||
/* Initialize rx channal private data */
|
||||
memset(getRxPrivate(channel), 0, sizeof(getRxPrivate(channel)));
|
||||
}
|
||||
}
|
||||
|
||||
/* ICOM controller hs been initialized. */
|
||||
icom->init = 1;
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM task function
|
||||
* \param icom: ICOM handle
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_task(ICOM *icom)
|
||||
{
|
||||
/* Input value validity check */
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
|
||||
/* Handle online status */
|
||||
icom_online_handle(icom);
|
||||
/* Handle rxdata */
|
||||
icom_rxdata_handle(icom);
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmit getbuffer function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Transmit channal index
|
||||
* \param buffer: Pointer to store data buffer
|
||||
* \param length: Pointer to store data length
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_transmit_getbuffer(ICOM *icom, uint16_t channel, uint8_t **buffer, uint32_t *length)
|
||||
{
|
||||
/* Input value validity check */
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
if (channel >= icom->txcount) return ICOM_E_IOUT;
|
||||
if (!getTxBase(channel)) return ICOM_E_NBASE;
|
||||
if (!buffer) return ICOM_E_IBUFFER;
|
||||
|
||||
/* Get transmit buffer */
|
||||
*buffer = &getTxData(channel);
|
||||
|
||||
/* Get data length */
|
||||
if (length) *length = getTxSize(channel) - ICOM_HEAD_SIZE;
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmit trigger function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Transmit channal index
|
||||
* \param length: Data length
|
||||
* \note: Data length must be less than or equal to the transmit buffer size minus ICOM_HEAD_SIZE
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_transmit_trigger(ICOM *icom, uint16_t channel, uint32_t length)
|
||||
{
|
||||
/* Input value validity check */
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
if (channel >= icom->txcount) return ICOM_E_IOUT;
|
||||
if (!getTxBase(channel)) return ICOM_E_NBASE;
|
||||
if (length + ICOM_HEAD_SIZE > getTxSize(channel)) return ICOM_E_LOUT;
|
||||
if (getTxFlag(channel) != ICOM_F_IDLE) return ICOM_E_BUSY;
|
||||
|
||||
/* Set data length */
|
||||
icom_set_data_length(icom, channel, length);
|
||||
/* Set tx channal to busy, need rx object receive data and set to ICOM_F_IDLE */
|
||||
getTxFlag(channel) = ICOM_F_BUSY;
|
||||
Cache_wbInv(&getTxFlag(channel), ICOM_FLAG_SIZE);
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmit function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Transmit channal index
|
||||
* \param data: Pointer to data buffer
|
||||
* \param length: Data length
|
||||
* \note: Data length must be less than or equal to the transmit buffer size minus ICOM_HEAD_SIZE
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_transmit(ICOM *icom, uint16_t channel, uint8_t *data, uint32_t length)
|
||||
{
|
||||
int ret = ICOM_E_OK;
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t blength = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
/* Get transmit buffer */
|
||||
ret = icom_transmit_getbuffer(icom, channel, &buffer, &blength);
|
||||
if (ICOM_E_OK != ret) return ret;
|
||||
if (length > blength) return ICOM_E_LOUT;
|
||||
|
||||
/* Copy data to transmit buffer */
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
buffer[i] = data[i];
|
||||
}
|
||||
Cache_wbInv(buffer, length);
|
||||
|
||||
/* Trigger transmit */
|
||||
ret = icom_transmit_trigger(icom, channel, length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive getbuffer function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \param buffer: Pointer to store data buffer
|
||||
* \param length: Pointer to store data length
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_receive_getbuffer(ICOM *icom, uint16_t channel, uint8_t **buffer, uint32_t *length)
|
||||
{
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
if (channel >= icom->txcount) return ICOM_E_IOUT;
|
||||
if (!getRxBase(channel)) return ICOM_E_NBASE;
|
||||
if (!buffer) return ICOM_E_IBUFFER;
|
||||
|
||||
*buffer = &getRxData(channel);
|
||||
|
||||
if (length) *length = getRxSize(channel) - ICOM_HEAD_SIZE;
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive indicate function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \param length: Pointer to store data length
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_receive_indicate(ICOM *icom, uint16_t channel, uint32_t *length)
|
||||
{
|
||||
/* Input value validity check */
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
if (channel >= icom->rxcount) return ICOM_E_IOUT;
|
||||
if (!getRxBase(channel)) return ICOM_E_NBASE;
|
||||
|
||||
/* Check if the rx channal is ready */
|
||||
if (icom_transmitter_ready(icom, channel))
|
||||
{
|
||||
Cache_Inv(&getRxFlag(channel), ICOM_FLAG_SIZE);
|
||||
if (getRxFlag(channel) == ICOM_F_BUSY)
|
||||
{
|
||||
/* Get data length */
|
||||
if (length) *length = icom_get_data_length(icom, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ICOM_E_NRECEIVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ICOM_E_NRECEIVE;
|
||||
}
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive end function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_receive_end(ICOM *icom, uint16_t channel)
|
||||
{
|
||||
/* Input value validity check */
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
if (channel >= icom->rxcount) return ICOM_E_IOUT;
|
||||
|
||||
/* Check if the rx channal is ready */
|
||||
if (icom_transmitter_ready(icom, channel))
|
||||
{
|
||||
Cache_Inv(&getRxFlag(channel), ICOM_FLAG_SIZE);
|
||||
if (getRxFlag(channel) == ICOM_F_BUSY)
|
||||
{
|
||||
/* Set rx channal to idle */
|
||||
getRxFlag(channel) = ICOM_F_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ICOM_E_NRECEIVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ICOM_E_NRECEIVE;
|
||||
}
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \param data: Pointer to data buffer
|
||||
* \param length: Pointer to store data length
|
||||
* \note: Data length must be less than or equal to the receive buffer size minus ICOM_HEAD_SIZE
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_receive(ICOM *icom, uint16_t channel, uint8_t *data, uint32_t *length)
|
||||
{
|
||||
int ret = ICOM_E_OK;
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t rxlength = 0;
|
||||
uint32_t blength = 0;
|
||||
uint32_t ilength = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
/* Input value validity check */
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
if (channel >= icom->rxcount) return ICOM_E_IOUT;
|
||||
if (!getRxBase(channel)) return ICOM_E_NBASE;
|
||||
if (!data) return ICOM_E_IBUFFER;
|
||||
|
||||
if (!length) return ICOM_E_ILENGTH;
|
||||
ilength = *length;
|
||||
|
||||
/* Determine if there is any data to receive */
|
||||
ret = icom_receive_indicate(icom, channel, &rxlength);
|
||||
if (ICOM_E_OK != ret) return ret;
|
||||
|
||||
/* Get receive buffer */
|
||||
ret = icom_receive_getbuffer(icom, channel, &buffer, &blength);
|
||||
if (ICOM_E_OK != ret) return ret;
|
||||
|
||||
if (rxlength > blength) return ICOM_E_LOUT;
|
||||
|
||||
/* Copy data from receive buffer */
|
||||
for (i = 0; i < rxlength; i++)
|
||||
{
|
||||
data[i] = buffer[i];
|
||||
}
|
||||
|
||||
/* End receive */
|
||||
icom_receive_end(icom, channel);
|
||||
|
||||
*length = rxlength;
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmit channal online check function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Transmit channal index
|
||||
* \param online: Pointer to store online status
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_txchannel_online(ICOM *icom, uint16_t channel, uint8_t *online)
|
||||
{
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
if (channel >= icom->txcount) return ICOM_E_IOUT;
|
||||
if (!online) return ICOM_E_IBUFFER;
|
||||
|
||||
*online = getPrivateOnline(getTxPrivate(channel));
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive channal online check function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \param online: Pointer to store online status
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_rxchannel_online(ICOM *icom, uint16_t channel, uint8_t *online)
|
||||
{
|
||||
if (!icom) return ICOM_E_IHANDLE;
|
||||
if (!icom->init) return ICOM_E_NINIT;
|
||||
if (channel >= icom->rxcount) return ICOM_E_IOUT;
|
||||
if (!online) return ICOM_E_IBUFFER;
|
||||
|
||||
*online = getPrivateOnline(getRxPrivate(channel));
|
||||
|
||||
return ICOM_E_OK;
|
||||
}
|
||||
|
||||
|
||||
193
source/06_performance/icom.h
Normal file
193
source/06_performance/icom.h
Normal file
@ -0,0 +1,193 @@
|
||||
/*********************************************************************************************************
|
||||
* ------------------------------------------------------------------------------------------------------
|
||||
* file description
|
||||
* ------------------------------------------------------------------------------------------------------
|
||||
* \file icom.h
|
||||
* \unit icom
|
||||
* \brief This is a simple internal communication module for C language
|
||||
* \author Lamdonn
|
||||
* \version v0.1.0
|
||||
* \license GPL-2.0
|
||||
* \copyright Copyright (C) 2026 Lamdonn.
|
||||
********************************************************************************************************/
|
||||
#ifndef __icom_H
|
||||
#define __icom_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Version infomation */
|
||||
|
||||
#define ICOM_V_MAJOR 0
|
||||
#define ICOM_V_MINOR 1
|
||||
#define ICOM_V_PATCH 0
|
||||
|
||||
/**
|
||||
* \brief: ICOM error code
|
||||
* \note: 0 means success, negative value means error
|
||||
*/
|
||||
|
||||
#define ICOM_E_OK (0) /* OK, no error */
|
||||
#define ICOM_E_IHANDLE (-1) /* Invalid icom handle */
|
||||
#define ICOM_E_NINIT (-2) /* Not initialized */
|
||||
#define ICOM_E_IOUT (-3) /* Iterator out of range */
|
||||
#define ICOM_E_NBASE (-4) /* NULL base address */
|
||||
#define ICOM_E_LOUT (-5) /* Length out of range */
|
||||
#define ICOM_E_BUSY (-6) /* Current channel is busy */
|
||||
#define ICOM_E_IBUFFER (-7) /* Invalid buffer */
|
||||
#define ICOM_E_ILENGTH (-8) /* Invalid length */
|
||||
#define ICOM_E_NRECEIVE (-9) /* No data received */
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive callback function
|
||||
* \param channel: Channel number
|
||||
* \param data: Data buffer
|
||||
* \param length: Data length
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
typedef int (*icom_callback_t)(uint16_t channel, uint8_t *data, uint32_t length);
|
||||
|
||||
/**
|
||||
* \brief: ICOM cache invalidate function
|
||||
* \param address: Cache address
|
||||
* \param size: Cache size
|
||||
*/
|
||||
typedef void (*icom_cache_inv_t)(uint8_t *address, uint32_t size);
|
||||
|
||||
/**
|
||||
* \brief: ICOM cache write-back invalidate function
|
||||
* \param address: Cache address
|
||||
* \param size: Cache size
|
||||
*/
|
||||
typedef void (*icom_cache_wbinv_t)(uint8_t *address, uint32_t size);
|
||||
|
||||
/**
|
||||
* \brief: ICOM channel configuration structure
|
||||
* \note: This structure is used to configure the ICOM channel
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *base; /**< Base address of the channel */
|
||||
uint32_t size; /**< Size of the channel */
|
||||
icom_callback_t callback; /**< Callback function */
|
||||
uint32_t private[4]; /**< Private data */
|
||||
} ICOM_CHNCFG;
|
||||
|
||||
/**
|
||||
* \brief: ICOM structure
|
||||
* \note: This structure is used to manage the ICOM module
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t init; /**< Initialize flag */
|
||||
ICOM_CHNCFG *txconfig; /**< Transmit channel configuration */
|
||||
ICOM_CHNCFG *rxconfig; /**< Receive channel configuration */
|
||||
uint16_t txcount; /**< Transmit channel count */
|
||||
uint16_t rxcount; /**< Receive channel count */
|
||||
icom_cache_inv_t inv; /**< Cache invalidate function */
|
||||
icom_cache_wbinv_t wbinv; /**< Cache write-back invalidate function */
|
||||
} ICOM;
|
||||
|
||||
/**
|
||||
* \brief: ICOM initialize function
|
||||
* \param icom: ICOM handle
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_init(ICOM *icom);
|
||||
|
||||
/**
|
||||
* \brief: ICOM task function
|
||||
* \param icom: ICOM handle
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_task(ICOM *icom);
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmit getbuffer function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Transmit channal index
|
||||
* \param buffer: Pointer to store data buffer
|
||||
* \param length: Pointer to store data length
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_transmit_getbuffer(ICOM *icom, uint16_t channel, uint8_t **buffer, uint32_t *length);
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmit trigger function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Transmit channal index
|
||||
* \param length: Data length
|
||||
* \note: Data length must be less than or equal to the transmit buffer size minus ICOM_HEAD_SIZE
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_transmit_trigger(ICOM *icom, uint16_t channel, uint32_t length);
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmit function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Transmit channal index
|
||||
* \param data: Pointer to data buffer
|
||||
* \param length: Data length
|
||||
* \note: Data length must be less than or equal to the transmit buffer size minus ICOM_HEAD_SIZE
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_transmit(ICOM *icom, uint16_t channel, uint8_t *data, uint32_t length);
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive getbuffer function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \param buffer: Pointer to store data buffer
|
||||
* \param length: Pointer to store data length
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_receive_getbuffer(ICOM *icom, uint16_t channel, uint8_t **buffer, uint32_t *length);
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive indicate function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \param length: Pointer to store data length
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_receive_indicate(ICOM *icom, uint16_t channel, uint32_t *length);
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive end function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_receive_end(ICOM *icom, uint16_t channel);
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \param data: Pointer to data buffer
|
||||
* \param length: Pointer to store data length
|
||||
* \note: Data length must be less than or equal to the receive buffer size minus ICOM_HEAD_SIZE
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_receive(ICOM *icom, uint16_t channel, uint8_t *data, uint32_t *length);
|
||||
|
||||
/**
|
||||
* \brief: ICOM transmit channal online check function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Transmit channal index
|
||||
* \param online: Pointer to store online status
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_txchannel_online(ICOM *icom, uint16_t channel, uint8_t *online);
|
||||
|
||||
/**
|
||||
* \brief: ICOM receive channal online check function
|
||||
* \param icom: ICOM handle
|
||||
* \param channel: Receive channal index
|
||||
* \param online: Pointer to store online status
|
||||
* \return: ICOM error code
|
||||
*/
|
||||
int icom_rxchannel_online(ICOM *icom, uint16_t channel, uint8_t *online);
|
||||
|
||||
#endif
|
||||
@ -45,6 +45,7 @@ TEST_LIST += romt
|
||||
TEST_LIST += cant
|
||||
TEST_LIST += slup
|
||||
# TEST_LIST += cpul
|
||||
TEST_LIST += icom
|
||||
TEST_LIST += date
|
||||
TEST_LIST += unitt
|
||||
TEST_LIST += coroutine
|
||||
|
||||
327
test/test_icom.c
Normal file
327
test/test_icom.c
Normal file
@ -0,0 +1,327 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined(TEST_TARGET_icom)
|
||||
#include <varch/command.h>
|
||||
#include <varch/unitt.h>
|
||||
#include <varch/icom.h>
|
||||
#else
|
||||
#include "init.h"
|
||||
#include "command.h"
|
||||
#include "unitt.h"
|
||||
#include "kern.h"
|
||||
#include "icom.h"
|
||||
#endif
|
||||
|
||||
/************************************************************************************/
|
||||
/************************************* Unit Test ************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
// #define EXIT_TEST
|
||||
extern uint64_t unitt_clock(void);
|
||||
|
||||
static int test_0(void)
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
if (0)
|
||||
{
|
||||
|
||||
#if defined (EXIT_TEST)
|
||||
exit(0);
|
||||
#endif
|
||||
return UNITT_E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return UNITT_E_OK;
|
||||
}
|
||||
|
||||
static void unitt_task(void)
|
||||
{
|
||||
static UNITT_TCASE rand_tests[] = {
|
||||
UNITT_TCASE(test_0),
|
||||
// UNITT_TCASE(test_1),
|
||||
// UNITT_TCASE(test_2),
|
||||
};
|
||||
|
||||
static UNITT suites[] = {
|
||||
{ "icom suite", rand_tests, sizeof(rand_tests) / sizeof(rand_tests[0]) , unitt_clock },
|
||||
};
|
||||
|
||||
UNITT_EXE(suites);
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
/************************************* Base Test ************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
static uint8_t icomBuffer0[1024] = {0};
|
||||
static uint8_t icomBuffer1[1024] = {0};
|
||||
|
||||
static int dev0_rx_callback(uint16_t channel, uint8_t *data, uint32_t length);
|
||||
static int dev1_rx_callback(uint16_t channel, uint8_t *data, uint32_t length);
|
||||
|
||||
static ICOM dev0ICOM = {
|
||||
.init = 0,
|
||||
.txconfig = (ICOM_CHNCFG[1]){
|
||||
{
|
||||
.base = icomBuffer0,
|
||||
.size = sizeof(icomBuffer0),
|
||||
.callback = NULL,
|
||||
},
|
||||
},
|
||||
.rxconfig = (ICOM_CHNCFG[1]){
|
||||
{
|
||||
.base = icomBuffer1,
|
||||
.size = sizeof(icomBuffer1),
|
||||
.callback = dev0_rx_callback,
|
||||
},
|
||||
},
|
||||
.txcount = 1,
|
||||
.rxcount = 1,
|
||||
.inv = NULL,
|
||||
.wbinv = NULL,
|
||||
};
|
||||
|
||||
static ICOM dev1ICOM = {
|
||||
.init = 0,
|
||||
.txconfig = (ICOM_CHNCFG[1]){
|
||||
{
|
||||
.base = icomBuffer1,
|
||||
.size = sizeof(icomBuffer1),
|
||||
.callback = NULL,
|
||||
},
|
||||
},
|
||||
.rxconfig = (ICOM_CHNCFG[1]){
|
||||
{
|
||||
.base = icomBuffer0,
|
||||
.size = sizeof(icomBuffer0),
|
||||
// .callback = dev1_rx_callback,
|
||||
.callback = NULL,
|
||||
},
|
||||
},
|
||||
.txcount = 1,
|
||||
.rxcount = 1,
|
||||
.inv = NULL,
|
||||
.wbinv = NULL,
|
||||
};
|
||||
|
||||
static int dev0_rx_callback(uint16_t channel, uint8_t *data, uint32_t length)
|
||||
{
|
||||
printf("[%d]: %s\r\n", length, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dev1_rx_callback(uint16_t channel, uint8_t *data, uint32_t length)
|
||||
{
|
||||
printf("[%d]: %s\r\n", length, data);
|
||||
// printf("[%d]\r\n", length);
|
||||
// for (int i = 0; i < length; i++)
|
||||
// {
|
||||
// printf("%02x ", data[i]);
|
||||
// }
|
||||
// printf("\r\n");
|
||||
icom_transmit(&dev1ICOM, 0, "Copy that!", 11);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dev0_task(void);
|
||||
static void dev1_task(void);
|
||||
|
||||
static void dev0_task(void)
|
||||
{
|
||||
static uint8_t init = 0;
|
||||
static uint32_t count = 0;
|
||||
|
||||
if (!init)
|
||||
{
|
||||
icom_init(&dev0ICOM);
|
||||
init = 1;
|
||||
}
|
||||
|
||||
count += 10;
|
||||
if (count >= 25200000) count = 0;
|
||||
|
||||
if (count % 10 == 0)
|
||||
{
|
||||
icom_task(&dev0ICOM);
|
||||
}
|
||||
|
||||
if (count % 1000 == 0)
|
||||
{
|
||||
uint8_t txonline = 0, rxonline = 0;
|
||||
icom_txchannel_online(&dev0ICOM, 0, &txonline);
|
||||
icom_rxchannel_online(&dev0ICOM, 0, &rxonline);
|
||||
printf("online %d,%d\r\n", txonline, rxonline);
|
||||
icom_transmit(&dev0ICOM, 0, "Hello dev1", 11);
|
||||
|
||||
static int time = 0;
|
||||
if (time >= 3)
|
||||
{
|
||||
task_create(10, dev1_task);
|
||||
}
|
||||
else
|
||||
{
|
||||
time++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dev1_task(void)
|
||||
{
|
||||
static uint8_t init = 0;
|
||||
static uint32_t count = 0;
|
||||
|
||||
if (!init)
|
||||
{
|
||||
icom_init(&dev1ICOM);
|
||||
init = 1;
|
||||
}
|
||||
|
||||
count += 10;
|
||||
if (count >= 25200000) count = 0;
|
||||
|
||||
char rxBuffer[1024];
|
||||
uint32_t length = sizeof(rxBuffer);
|
||||
if (ICOM_E_OK == icom_receive(&dev1ICOM, 0, rxBuffer, &length))
|
||||
{
|
||||
printf("[%d]: %s\r\n", length, rxBuffer);
|
||||
}
|
||||
|
||||
if (count % 10 == 0)
|
||||
{
|
||||
icom_task(&dev1ICOM);
|
||||
}
|
||||
|
||||
if (count % 1000 == 0)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void test_base(void)
|
||||
{
|
||||
task_create(10, dev0_task);
|
||||
// task_create(10, dev1_task);
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
/************************************* Command ************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: icom [opt] [arg] ...\n"
|
||||
"\n"
|
||||
"options:\n"
|
||||
" -e <execute> Specifies the function to execute, the default is the <base> test\n"
|
||||
" <base> Test base function\n"
|
||||
" <ut> Unit test\n"
|
||||
" ...\n"
|
||||
" -h Print help\n"
|
||||
" -v Print version\n"
|
||||
" -u [<period>] Unit test period, unit ms, the default is 1000ms\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
static int test(int argc, char *argv[])
|
||||
{
|
||||
char *execute = NULL;
|
||||
int ut_period = 1000;
|
||||
|
||||
/* reset getopt */
|
||||
command_opt_init();
|
||||
|
||||
while (1)
|
||||
{
|
||||
int opt = command_getopt(argc, argv, "e:hvu::");
|
||||
if (opt == -1) break;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
// Add others opt here
|
||||
case 'u' :
|
||||
if (command_optarg) ut_period = atoi(command_optarg);
|
||||
break;
|
||||
case 'e' :
|
||||
execute = command_optarg;
|
||||
break;
|
||||
case 'v' :
|
||||
printf("icom version %d.%d.%d\r\n", ICOM_V_MAJOR, ICOM_V_MINOR, ICOM_V_PATCH);
|
||||
return 0;
|
||||
case '?':
|
||||
printf("Unknown option `%c`\r\n", command_optopt);
|
||||
return -1;
|
||||
case 'h' :
|
||||
default:
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (execute)
|
||||
{
|
||||
if (!strcmp(execute, "base"))
|
||||
{
|
||||
test_base();
|
||||
}
|
||||
else if (!strcmp(execute, "ut"))
|
||||
{
|
||||
#if defined(TEST_TARGET_icom)
|
||||
while (1)
|
||||
{
|
||||
unitt_task();
|
||||
usleep(1000 * ut_period);
|
||||
}
|
||||
#else
|
||||
printf("create task %d\r\n", task_create(ut_period, unitt_task));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
test_base();
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (1 == command_optind) // no opt
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
for (int index = command_optind; index < argc; index++)
|
||||
{
|
||||
if (!strcmp(argv[index], "base"))
|
||||
{
|
||||
test_base();
|
||||
}
|
||||
}
|
||||
|
||||
if (1 == argc)
|
||||
{
|
||||
test_base();
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
/************************************ Test entry ************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
#if defined(TEST_TARGET_icom)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return test(argc, argv);
|
||||
}
|
||||
#else
|
||||
void test_icom(void)
|
||||
{
|
||||
command_export("icom", test);
|
||||
}
|
||||
init_export_app(test_icom);
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user