完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
荷兰为系列指南的第五章,讲述了STM32F407上MAC层以及其DMA的配置,其中就包含MAC层的DMA,复习一下STM32F4的总线架构图,(图片来自RM0090ST中文STM32F4手册P50):
看到,在上图红框的S6阶段,就是MAC会层的DMA总线,CPU在核心逻辑之外,有专门的时间片轮转周期处理阶段的DMA,所有的数据读写都是DMA来控制的,不需要我们在核心逻辑中 写的。:能写一个自己构建的DP83848Init()函数,就像类似的UARTInit(),DelayInit()等函数一样,在main()函数初始化阶段调用,完成快速启动网卡的操作这个函数包含几个任务: GPIO的初始化 MAC层和DMA配置 配置 网络服务启动 一,GPIO 初始化这个我们在上一章已经完成了。 二,MAC层初始化 2.1 写写以下功能: static void ETH_MACDMA_Config(void) { ETH_InitTypeDef ETH_InitStructure; /* Enable ETHERNET clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx, ENABLE); ETH_DeInit(); /* Reset ETHERNET on AHB Bus */ ETH_SoftwareReset(); /* Software reset */ while (ETH_GetSoftwareResetStatus() == SET); /* Wait for software reset */ /* ETHERNET Configuration * Call ETH_StructInit to get a default structure * if you don't like to configure all ETH_InitStructure parameter */ ETH_StructInit(Ð_InitStructure); /* Fill ETH_InitStructure parametrs */ /*------------------------ MAC -----------------------------------*/ ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable; /* 10M/100M自适应 */ 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_Enable; /* 混杂模式 */ 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; ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable; /* 在IP包收发时使用硬件计算校验和 */ /*------------------------ DMA -----------------------------------*/ /* When we use the Checksum offload feature, we need to enable the Store and Forward mode: the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum, if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */ 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; /* * 初始化时,RJ45变压器如果没有上电,ETH_Init会返回非0值, * 为确保系统上电后正确初始化网络,需要每500ms尝试初始化一次PHY,直到成功 * DP83848_PHY_ADDRESS为上一章分析并定义的0x01 */ while( !ETH_Init(Ð_InitStructure, DP83848_PHY_ADDRESS) ) { vu32 sdelay = 84000000; while(sdelay--); } /* Enable the Ethernet Rx Interrupt */ ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE); } 上面的代码,配合注释简单了,但如果你直接复制到项目中编译,肯定会出现大把的错误,从第一个结构体的定义就找到了,下面还有很多明文的函数也找不到,那么,这个ETH_InitTypeDef结构体,以及下面的ETH_DeInit()、ETH_SoftwareReset()、ETH_StructInit()等函数在哪里呢? 2.2 stm32f4x7_eth.c文件和以太网库函数 在第一章知识储备中,已经讲了,STM32F4标准库中与ETH方面的库函数,在STM32官网搜索LWIP搜索到官方使用LWIP的DEMO,官方文档编号是STSW-STM32070,在这份文档有很多 LWIP 协议栈,还有官方的调用样例,我们可以深入到 ETH 部分的库函数。配套的.h和一个stm32f4x7_eth_conf_template.h文件是比较关键的,爪标准库提供的那些I2C、UART、SPI等库函数文件。 .h,所有配置都保持与官方一致的默认配置,这样在本文 2.1 特定的结构体和那些 ETH 函数,定义了,编译起来也不会出错。 ,我们回过头来看一下2.1段中出现的一段可以初始化MAC层的代码,不是我自己原创想当然瞎写出来的,我们考证一下其出处。 打开STM32F4x7_ETH_LwIP_V1.1.1ProjectStandaloneudp_echo_client srcstm32f4x7_bsp.c文件后,你会发现有相似的代码描述,我们看注释后可以适当的配置调整。 三、中断配置 void ETH_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Enable the Ethernet global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } ETH_IRQn宏定义是STM32库中现成的ETH破坏描述,中断优先级配置的1-0,相对比较高,但仍留了一个优先级给系统定时器中断排在前面。现在来回顾一下,现在我们已经拥有了三个准备好的函数,分别是ETH_GPIO_Config()、ETH_MACDMA_Config()和ETH_NVIC_Config,第一个函数在上一章写得好,两个就是写的。下面一个大致的函数: void ETH_BSP_Config(void) { ETH_GPIO_Config(); ETH_NVIC_Config(); // Config NVIC for Ethernet ETH_MACDMA_Config(); // Configure the Ethernet MAC/DMA } 以上,所有代码皆stm324fx7_eth_bsp.c文件中。 四网络服务启动 我们现在已经在完成了大部分就是初始化配置,下面,我们和需要写代码搜索服务的启动工作,也我们这一章节的核心任务,写DP83848Init()函数: void DP83848Init(uint8_t* HWADDR){ int i; /* Configure ethernet (GPIOs, clocks, MAC, DMA) */ ETH_BSP_Config(); /* initialize MAC address in ethernet MAC */ ETH_MACAddressConfig(ETH_MAC_Address0, HWADDR); /* Initialize Tx Descriptors list: Chain Mode */ ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); /* Initialize Rx Descriptors list: Chain Mode */ ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ for(i = 0; i < ETH_TXBUFNB; i++) { ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab, ETH_DMATxDesc_ChecksumTCPUDPICMPFull); } ETH_Start(); } 其中,ETH_BSP_Config()来自于我们上一阶段封装好的函数,其余的调用仍然来自stm32f4x7_eth.c文件。虽然这里的注释已经非常清晰了,这里有一点需要提一下,在上述代码的第9和第11行就是配置了两个DMA的链状教程,关于链状DMA和环装DMA教程,如果需要了解更多一点,可以解决原子哥的视频,就去面花了一些篇幅介绍,不过我个人感觉视频中讲的也不是特别清楚,视频下载地址:HTTPS://pan.baidu.com/s/1jIvvTcy,我们暂时先这么用吧 按照惯例,上面那一段函数也不是我处突发奇想,心血来潮,闭着眼睛毫无根据的写下的,我们来看看镜头函数的出处,还是在那之前的LWIP文档里面,路径为:STM32F4x7_ETH_LwIP_V1.1.1UtilitiesThird_Partylwip-1.4.1portSTM32F4x7Standaloneethernetif .c,看第76行low_level_init()函数,顾名思义,low_level_init()就是近期初始化的英文,我们重点观察这个函数的后半部分,操作netif结构体的部分我们暂时用不到,部分调用ETH代码截取如下 static void low_level_init(struct netif *netif) { #ifdef CHECKSUM_BY_HARDWARE int i; #endif /* set MAC hardware address length */ netif->hwaddr_len = ETHARP_HWADDR_LEN; /* set MAC hardware address */ netif->hwaddr[0] = MAC_ADDR0; netif->hwaddr[1] = MAC_ADDR1; netif->hwaddr[2] = MAC_ADDR2; netif->hwaddr[3] = MAC_ADDR3; netif->hwaddr[4] = MAC_ADDR4; netif->hwaddr[5] = MAC_ADDR5; /* initialize MAC address in ethernet MAC */ ETH_MACAddressConfig(ETH_MAC_Address0, netif->hwaddr); /* maximum transfer unit */ netif->mtu = 1500; /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; /* Initialize Tx Descriptors list: Chain Mode */ ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); /* Initialize Rx Descriptors list: Chain Mode */ ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); #ifdef CHECKSUM_BY_HARDWARE /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ for(i=0; i ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab, ETH_DMATxDesc_ChecksumTCPUDPICMPFull); } #endif /* Note: TCP, UDP, ICMP checksum checking for received frame are enabled in DMA config */ /* Enable MAC and DMA transmission and reception */ ETH_Start(); } 大提一下,ethernetif.c这个源文件不需要我们的,我们不需要LWIP库中的任何,所有的一切都是例子其网络收发包模块是怎么写的代码。最后,我们再次结一下,经过一遍的对照和参考,我们现在已经有了完整的这个DP83848Init()函数,函数将main()函数总体部分进行整个PHY、MAC、DMA的配置和初始化章。至此,我们这个的任务就只完成了,我可以做到每一行代码出其出处,而不是贴出代码,让读者只知其然不知其然,我想我们找出这些出处后,就可以清晰地根据自己的不同设备和场景来移植。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1641 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1562 浏览 1 评论
990 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
691 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1610 浏览 2 评论
1869浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
655浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
525浏览 3评论
541浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
514浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-26 16:20 , Processed in 0.644743 second(s), Total 49, Slave 42 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号