Files
ch32v20x-examples/EVT/EXAM/BLE/LWNS/APP/lwns_rucft_example.c
T
2023-02-01 14:19:13 +08:00

209 lines
7.0 KiB
C

/********************************** (C) COPYRIGHT *******************************
* File Name : lwns_rucft_example.c
* Author : WCH
* Version : V1.0
* Date : 2021/06/30
* Description : reliable unicast file transfer,可靠单播文件传输例子
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "lwns_rucft_example.h"
//每个文件单独debug打印的开关,置0可以禁止本文件内部打印
#define DEBUG_PRINT_IN_THIS_FILE 1
#if DEBUG_PRINT_IN_THIS_FILE
#define PRINTF(...) PRINT(__VA_ARGS__)
#else
#define PRINTF(...) \
do \
{ \
} while(0)
#endif
#if 1
static lwns_addr_t dst_addr = {{0x66, 0xdf, 0x38, 0xe4, 0xc2, 0x84}}; //目标节点地址,测试时,请根据电路板芯片MAC地址不同进行修改。修改为接收方的MAC地址,请勿使用自己的MAC地址
#else
static lwns_addr_t dst_addr = {{0xd9, 0x37, 0x3c, 0xe4, 0xc2, 0x84}};
#endif
static uint8_t rucft_taskID;
static lwns_rucft_controller rucft; //声明rucft控制结构体
#define FILESIZE 4000
static char strsend[FILESIZE]; //发送缓冲区
static char *strp;
static void write_file(lwns_controller_ptr ptr, const lwns_addr_t *sender,
int offset, int flag, char *data, int datalen);
static int read_file(lwns_controller_ptr ptr, int offset, char *to);
static void timedout_rucft(lwns_controller_ptr ptr);
/**
* lwns 可靠单播文件传输回调函数结构体,注册回调函数
*/
const static struct lwns_rucft_callbacks rucft_callbacks = {write_file,
read_file, timedout_rucft};
uint16_t lwns_rucft_ProcessEvent(uint8_t task_id, uint16_t events);
/*********************************************************************
* @fn write_file
*
* @brief lwns rucft接收回调函数,作为写入文件回调函数
*
* @param ptr - 本次接收到的数据所属的netflood控制结构体指针.
* @param sender - 本次接收到的数据的发送者地址指针.
* @param offset - 本次接收到的数据的偏移量,也是本次文件传输接收已经收到的数据量.
* @param flag - 本次接收到数据的标志,LWNS_RUCFT_FLAG_NONE/LWNS_RUCFT_FLAG_NEWFILE/LWNS_RUCFT_FLAG_END.
* @param data - 本次接收到的数据的头指针.
* @param datalen - 本次接收到的数据的长度.
*
* @return None.
*/
static void write_file(lwns_controller_ptr ptr, const lwns_addr_t *sender,
int offset, int flag, char *data, int datalen)
{
//sender为发送方的地址
//如果需要接收不同的文件,需要在此函数中做好接口
if(datalen > 0)
{ //声明个缓冲从data里取数据打印
PRINTF("r:%c\n", *data);
}
if(flag == LWNS_RUCFT_FLAG_END)
{
PRINTF("re\n");
//本次文件传输的最后一个包
}
else if(flag == LWNS_RUCFT_FLAG_NONE)
{
PRINTF("ru\n");
//本次文件传输正常的包
}
else if(flag == LWNS_RUCFT_FLAG_NEWFILE)
{
PRINTF("rn\n");
//本次文件传输的第一个包
}
}
/*********************************************************************
* @fn read_file
*
* @brief lwns rucft发送完成回调函数,作为读取文件回调函数
*
* @param ptr - 本次接收到的数据所属的netflood控制结构体指针.
* @param offset - 本次接收到的数据的偏移量,也是本次文件传输发送已经发送的数据量.
* @param to - 本次需要发送的数据缓冲区的头指针,用户将数据拷贝到此指针指向的内存空间。.
*
* @return size - 返回的size即为本次需要发送的数据长度,不可大于LWNS_RUCFT_DATASIZE.
*/
static int read_file(lwns_controller_ptr ptr, int offset, char *to)
{
//to为需要保存数据过去的指针
//如果需要发送不同的文件,需要在此函数中做好接口
int size = LWNS_RUCFT_DATASIZE;
if(offset >= FILESIZE)
{
//上次已经发完,本次是最后确认
PRINTF("Send done\n");
tmos_start_task(rucft_taskID, RUCFT_EXAMPLE_TX_PERIOD_EVT,
MS1_TO_SYSTEM_TIME(5000)); //5秒钟后继续发送测试
return 0;
}
else if(offset + LWNS_RUCFT_DATASIZE >= FILESIZE)
{
size = FILESIZE - offset;
}
//把本次需要发送的内容压进包缓冲
tmos_memcpy(to, strp + offset, size);
return size;
}
/*********************************************************************
* @fn timedout_rucft
*
* @brief lwns rucft发送超时回调函数
*
* @param ptr - 本次发送完成的ruc控制结构体指针.
*
* @return None.
*/
static void timedout_rucft(lwns_controller_ptr ptr)
{
//rucft中,发送方再重发次数超过最大重发次数后,会调用该回调。
//接收方超时没接收到下一个包也会调用
PRINTF("rucft %d timedout\r\n", get_lwns_object_port(ptr));
}
/*********************************************************************
* @fn lwns_rucft_process_init
*
* @brief lwns rucft例程初始化.
*
* @param None.
*
* @return None.
*/
void lwns_rucft_process_init(void)
{
lwns_addr_t MacAddr;
rucft_taskID = TMOS_ProcessEventRegister(lwns_rucft_ProcessEvent);
lwns_rucft_init(&rucft, 137, //端口号
HTIMER_SECOND_NUM / 10, //等待目标节点ack时间
5, //最大重发次数,与ruc中的ruc_send的重发次数功能一样
&rucft_callbacks //回调函数
); //返回0代表打开失败。返回1打开成功。
int i;
for(i = 0; i < FILESIZE; i++)
{ //LWNS_RUCFT_DATASIZE个LWNSNK_RUCFT_DATASIZE个b,等等,初始化需要发送的数据
strsend[i] = 'a' + i / LWNS_RUCFT_DATASIZE;
}
strp = strsend;
FLASH_GetMACAddress(MacAddr.v8);
if(lwns_addr_cmp(&MacAddr, &dst_addr))
{
}
else
{
tmos_start_task(rucft_taskID, RUCFT_EXAMPLE_TX_PERIOD_EVT,
MS1_TO_SYSTEM_TIME(1000));
}
}
/*********************************************************************
* @fn lwns_rucft_ProcessEvent
*
* @brief lwns rucft Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The TMOS assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return events not processed.
*/
uint16_t lwns_rucft_ProcessEvent(uint8_t task_id, uint16_t events)
{
if(events & RUCFT_EXAMPLE_TX_PERIOD_EVT)
{
PRINTF("send\n");
lwns_rucft_send(&rucft, &dst_addr); //开始发送至目标节点,用户启用发送时要配置好回调函数中的数据包读取
return events ^ RUCFT_EXAMPLE_TX_PERIOD_EVT;
}
if(events & SYS_EVENT_MSG)
{
uint8_t *pMsg;
if((pMsg = tmos_msg_receive(task_id)) != NULL)
{
// Release the TMOS message
tmos_msg_deallocate(pMsg);
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
return 0;
}