STM32F107 以太网 + RL-TCPnet
来源:互联网 发布:微信 数据库修复失败 编辑:程序博客网 时间:2024/06/06 08:53
本文版权:成都至诚恒远物联网技术有限公司
网址: www.heryit.cn
联系电话: 028-87657875
13060063607
介绍一下STM32F107以太网的配置和移植RL-TCPnet协议栈,官方所给的例程为lwip,这里介绍一下怎样使用RL-TCPnet。(需要包含stm32_eth.c和stm32_eth.h)
这里是描述符的定义,什么是描述符请看《STM32中文参考手册》以太网章节
/* 描述符数量和缓存大小定义 */#define NUM_RX_BUF 4 //接收描述符数量和缓存数量#define NUM_TX_BUF 2 //发送描述符数量和缓存数量#define ETH_BUF_SIZE 1536 //每个缓存大小/* 接收描述符和发送描述符结构体类型定义(含义请参考STM32中文参考手册) */typedef struct { U32 volatile Stat; U32 Ctrl; U32 Addr; U32 Next;} RX_Desc;typedef struct { U32 volatile CtrlStat; U32 Size; U32 Addr; U32 Next;} TX_Desc;/* 当前使用的描述符序号 */static U8 TxBufIndex;static U8 RxBufIndex;/* DMA描述符声明 */static RX_Desc Rx_Desc[NUM_RX_BUF];static TX_Desc Tx_Desc[NUM_TX_BUF];/* 描述符所指向的内存 */static U32 rx_buf[NUM_RX_BUF][ETH_BUF_SIZE>>2];static U32 tx_buf[NUM_TX_BUF][ETH_BUF_SIZE>>2];
要使用RL-TCPnet协议栈需要为RL-TCPnet提供接口函数:
void init_ethernet (void);
void send_frame (OS_FRAME *frame);
void int_enable_eth (void);
void int_disable_eth (void);
以下为对应函数:
//以太网硬件初始化(提供给RL-TCPnet的接口)void init_ethernet (void) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; ETH_InitTypeDef ETH_InitStructure; #define TIME_OUT 0x0003FFFFul uint32_t time = 0; /* 使能时钟 */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE); /* 使能GPIO时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE); /* 选择中断向量表 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 使能以太网全局中断*/ NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* 以太网引脚配置 当前使用RMII接口,无重映射 需要使用MII接口请自行参照手册修改 */ /* AF Output Push Pull: -ETH_RMII_MDIO: PA2 -ETH_RMII_MDC: PC1 -ETH_RMII_TX_EN: PB11 -ETH_RMII_TXD0: PB12 -ETH_RMII_TXD1: PB13 */ /* Configure PA2 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure PC1 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Configure PB5, PB8, PB11, PB12 and PB13 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Input: -ETH_RMII_REF_CLK: PA1 -ETH_RMII_CRS_DV: PA7 -ETH_RMII_RXD0: PC4 -ETH_RMII_RXD1: PC5 */ /* Configure PA1 and PA7 as input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure PC4 and PC5 as input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOC, &GPIO_InitStructure); /* 选择配置为MII或者RMII,当前为RMII*/ GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII); /* 重置以太网 */ ETH_DeInit(); ETH_SoftwareReset(); /*等待重置完成*/ while (ETH_GetSoftwareResetStatus() == SET); /* 以太网配置, 填充ETH_InitStructure结构体,最后调用 ETH_Init()配置以太网*/ ETH_StructInit(Ð_InitStructure); /*------------------------ MAC -----------------------------------*/ ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable ; ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable; ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable; ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable; ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable; ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable; ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable; ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect; ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect; #ifdef CHECKSUM_BY_HARDWARE ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable; #endif /*------------------------ DMA -----------------------------------*/ ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable; ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable; ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable; ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable; ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable; ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable; ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable; ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable; ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat; ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat; ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1; /*初始化以太网,第二个参数为PHY芯片地址*/ ETH_Init(Ð_InitStructure, LAN9303_VPHY_ADDR); //接收描述符初始化 rx_descr_init(); //发送描述符初始化 tx_descr_init(); /* 使能正常总中断和接收中断*/ ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE); //使能发送和接收 ETH->DMAOMR |= DOMR_ST | DOMR_SR; ETH->MACCR |= MCR_RE | MCR_TE; //配置MAC地址,否则只能收到广播数据 ETH_MACAddressConfig(ETH_MAC_Address0, own_hw_adr);}//使能和禁止以太网中断void int_enable_eth (void) { /* Ethernet Interrupt Enable function. */ NVIC->ISER[1] = 1 << 29;}void int_disable_eth (void) { /* Ethernet Interrupt Disable function. */ NVIC->ICER[1] = 1 << 29;}//发送一帧数据(提供给RL-TCPnet的接口函数)void send_frame (OS_FRAME *frame) { U32 *sp,*dp; U32 i,j; j = TxBufIndex; /* 等待之前数据发送完 */ while (Tx_Desc[j].CtrlStat & DMA_TX_OWN); sp =** (U32 *)&frame->data[0]; dp = (U32 *)Tx_Desc[j].Addr; /* 拷贝需要发送的数据到发送描述符指定的内存 */ for (i = (frame->length + 3) >> 2; i; i--) { *dp++ = *sp++; } //发送数据量 Tx_Desc[j].Size = frame->length; //修改发送描述符属于DMA Tx_Desc[j].CtrlStat |= DMA_TX_OWN; /* 往DMATPDR中写数据开始DMA传输 */ if((ETH->DMASR | DSR_TBUS) !*= 0) { ETH->DMASR = DSR_TBUS; ETH->DMATPDR = 0; } if (++j == NUM_TX_BUF) j = 0; TxBufIndex = j;}
以上即为需要提供给RL-TCPnet的接口函数。
中断服务函数,用于接收以太网数据。
//以太网中断服务函数(用于接收以太网数据)void ETH_IRQHandler (void) { /* Ethernet Controller Interrupt function. */ OS_FRAME *frame; U32 i,RxLen; U32 *sp,*dp; i = RxBufIndex; do { /* Valid frame has been received. */* if (Rx_Desc[i].Stat & DMA_RX_ERROR_MASK) { goto rel; } if ((Rx_Desc[i].Stat & DMA_RX_SEG_MASK) != DMA_RX_SEG_MASK) { goto rel; } RxLen = ((Rx_Desc[i].Stat >> 16) & 0x3FFF) - 4; if (RxLen > ETH_MTU) { /* Packet too big, ignore it and free buffer. */ goto rel; } /* Flag 0x80000000 to skip sys_error() call when out of memory. */ frame = alloc_mem (RxLen | 0x80000000); /* if 'alloc_mem()' has failed, ignore this packet. */ if (frame != NULL) { sp = (U32 *)(Rx_Desc[i].Addr & ~3); dp = (U32 *)&frame->data[0]; for (RxLen = (RxLen + 3) >> 2; RxLen; RxLen--) { *dp++ = *sp++; } put_in_queue (frame); } /* Release this frame from ETH IO buffer. */ rel: Rx_Desc[i].Stat = DMA_RX_OWN; if (++i == NUM_RX_BUF) i = 0; } while ((Rx_Desc[i].Stat & DMA_RX_OWN) == 0); RxBufIndex = i; if (ETH->DMASR & INT_RBUIE) { /* Rx DMA suspended, resume DMA reception. */ ETH->DMASR = INT_RBUIE; ETH->DMARPDR = 0; } /* Clear the interrupt pending bits. */ ETH->DMASR = INT_NISE | INT_RIE;}
接收描述符初始化
//接收描述符初始化static void rx_descr_init (void) { /* Initialize Receive DMA Descriptor array. */ U32 i,next; RxBufIndex = 0; for (i = 0, next = 0; i < NUM_RX_BUF; i++) { if (++next == NUM_RX_BUF) next = 0; Rx_Desc[i].Stat = DMA_RX_OWN; Rx_Desc[i].Ctrl = DMA_RX_RCH | ETH_BUF_SIZE; Rx_Desc[i].Addr = (U32)&rx_buf[i]; Rx_Desc[i].Next = (U32)&Rx_Desc[next]; } //指向第一个描述符 ETH->DMARDLAR = (U32)&Rx_Desc[0];}
发送描述符初始化
//发送描述符初始化static void tx_descr_init (void) { /* Initialize Transmit DMA Descriptor array. */ U32 i,next; TxBufIndex = 0; for (i = 0, next = 0; i < NUM_TX_BUF; i++) { if (++next == NUM_TX_BUF) next = 0; Tx_Desc[i].CtrlStat = DMA_TX_TCH | DMA_TX_LS | DMA_TX_FS; Tx_Desc[i].Addr = (U32)&tx_buf[i]; Tx_Desc[i].Next = (U32)&Tx_Desc[next]; } //指向第一个描述符 ETH->DMATDLAR = (U32)&Tx_Desc[0];}
到此,在工程中加入RL-TCPnet库和配置文件即可使用RL-TCPnet,使用方法请参照RL-arm帮助文档。
0 0
- STM32F107 以太网 + RL-TCPnet
- STM32移植RL-TCPnet
- RL-TCPnet移植到enc28j60
- 基于RL-TCPnet的Web Server应用
- 在RL-TCPnet下的UDP通信
- 基于DM9161的RL-TCPnet实现
- RL-TCPNet的移植与使用简介
- RL-TCPNet库提供的函数整理
- RL-TCPnet之TCP服务器(enc28j60)
- MDK 5.0的RL Tcp/ip库和MDK 4.0的RL-TCPNet的区别
- STM32F107 以太网PHY选择和电路设计
- RL分析器
- RL论文
- 以太网
- 以太网
- 以太网
- 以太网
- 以太网
- 游标使用方法
- SAS进阶《深入分析SAS》之数据汇总和展现
- 【流媒體】jrtplib—VS2010下RTP开源协议库JRTPLIB3.9.1编译
- Linux下好用的类似QQ截图工具
- 垃圾回收算法历程
- STM32F107 以太网 + RL-TCPnet
- 下载opengl的glut.h头文件和库
- 几个JavaScript的浏览器差异处理问题
- Unity Shader.Find 找不到内置shader
- Fresco介绍 - 一个新的android图片加载库
- js-实现双向链表
- OpenStack商用需要跨过的坎 -- 3. 存储系统的选择和实现
- __cplusplus
- IOS代理模式(监听器模式)