/********************************** (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; }