7.2(stm32以太网)

《7.2》
1.SPI的写入整个扇区W25QXX_Write_NoCheck()--->W25QXX_Write_Page()--->SPI1_ReadWriteByte();
  void W25QXX_Write_NoCheck(pBuffer , addr,num)
  {
     u8 pageremain;
     pageremain = addr - addr%256;
     if(num<=pageremain) pageremain = num;
     while(1)
     {          
 W25QXX_Write_Page(pBuffer,addr,256);//这个的作用是直接调用就可以写入256个字节
 if(num=pageremain) break;
          else
          {
          num-=pageremain;
          addr+=256;
                pBuffer+=pageremain;         //pBuffer中的内容写出了pageremain长度后要后移
          if(num<=256)pageremain = num;//如果num剩余量小于一页值则直接写入
                else pageremain = 256;       //num大于一页值则256字节,其他的在循环中处理
          }               
     }      
  }
  注意该函数是写入256字节而不用考虑校验,因为在其上层函数W25QXX_Write()已经对扇区secremain
进行了校验,所以此时可以不用考虑。
总结:1.因此对于W25QXX_Write_NoCheck()实际上并不进行写操作,真正进行写操作的是其内部的函数  


      W25QXX_Write_Page(),它的作用相当于对循环判断,自动换页(page 256字节)。
      2.同理,对于W25QXX_Write()实际上是W25QXX_Write_NoCheck()上层函数,也不进行实际写,其
        作用是对循环判断,自动换扇区(sector 4096字节)。
        区别:在于W25QXX_Write()进行校验,而W25QXX_Write_NoCheck()不进行。且前者是上层函数
,读写范围也大些。




2.SRAM实验中的地址线:19根线,即2^19=2^10*2^9=512k 。其寻址范围512k.但决定不了其寻址容量,
还 取决数据宽度!!! 数据宽度为16,所以一个地址存储2byte,则容量为1Mbtye.


3.SRAM的FMSC_SRAM_WriteBuffer(u8 * pBuffer,u32 WriteAddr ,u32 n)的写函数,只需要将pBuffer中
的内容直接赋给地址Bank1_Sram3_ADDR((u32) (0x68000000))即可。
    原因在与FMSC总线能够处理数据的发送,不需要人为的管理时序。就像ARM9中的存储管理其的使用!


4.SRAM使用FMSC总线,其中寄存器BCR主要用来设置存储器的写使能、数据宽度8或16位。
                        寄存器BTR主要用来设置存储器的写操作的时序问题
                        寄存器BWTR主要用来在读/写不同时序的情况下,设置写的时序。


5.内存管理实验中:内存块(一起就是内存池,32字节)在SRAM的低地址首部,内存管理表则在其地址后
面,用来防止内存块和内存管理表的位置叠加。
  注意:(1).对于内存管理表其相对于内存块来说,所占的内存较少。
        (2).内存池用来定义使用了前端的内存地址,内存管理器定义其后的内存地址。


代码分析一:
const u32 memtblsize[SRAMBANK] =
{MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE,MEM3_ALLOC_TABLE_SIZE};
//3个不同SRAM分别的内存管理表项个数
const u32 memblksize[SRAMBANK] = {MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE,MEM3_BLOCK_SIZE};
//内存池的内存块分别所占字节大小(3个相同为32字节)
const u32 memsize[SAMBANK] = {MEM1_MAX_SIZE,MEM2_MAX_SIZE,MEM3_MAX_SIZE};
//3个不同的SRAM分别占多少个字节
其中的SRAMBANK为SRAM的数目,即stm32f407片内100kb的SRAM、外部1M的SRAM、内部的CCM内存池,总共 
 3个。


代码分析二:
   memx为所属的内存块,后面的SRAMBANK的含义,等于3。
   malloc.c中的一些定义都是针对malloc.h中的_m_mallco_dev结构体中元素而定义的,然后通过内存
管理控制器struct _m_mallco_dev mallco_dev={  },进行赋值而进行传递的。
   my_mem_init()中可知对于SRAM都是向其中写入0,而对于16M的利用spi读写的W25Q128(flash)则是
向其中写入oxff来进行检验。注意:IS62WV51216是1M的SRAM,要进行区分对比!!!!


代码分析三:
   my_mem_malloc(u8 memx,u32 size)其中size参数用来设置内存的大小,先求出需要的连续内存块大
小nmemb,等于size/memblksize[memx]加上if(size%memblksize[memx])nmemb++;其中重要的思想在于对
整个内存区域找连续内存块的方法:在偏移量offset最大的memtblsize[memx]开始,如果有
if(memmap[memx][offset])为零,即空闲,则定义一个连续空闲计数变量cmemb++,else 将之前的空闲
计数归零,在循环中进行。当检测到if(cmemb = nmemb)时,将从开始的mallco_dev.memmap[memx]
[offset+i]处全标记为连续的内存空计数值nmemb;最后返回内存管理表基地址与连续空闲内存块的偏移
量地址:offset*memblksize[memx]     注意是偏移地址!!!!
    void *mymalloc()调用了my_mem_malloc(memx,size)=offset, 其中offset的值位my_mem_malloc中
得到的offset*memblksize[memx],即offset*32。 到了mymalloc()中后,它返回值为
(void*)((u32)mallco_dev.membase[memx]+offset)的值。


6.以太网实验的LAN8720:(STM32F4 LWIP开发手册_V2.0.pdf)
LAN8720分为两个部分:
      LAN8720中的BCR和BSR。其中这两个寄存器是PHY中通用的部分,在使stm32f47x_eth_conf.h中有
定义这两个寄存器。但是对于特殊功能寄存器对于不同的PHY芯片,在stm32f4x7_eth_conf.h必须根据具
体的芯片操作。LAN8720只是PHY芯片中的一种而已!!!!!!!!
      LAN8720初始化中并没有看到我们直接操作PHY寄存器,原因在与我们ETH_init()的调用会根据我
们输入参数配置LAN8720相关寄存器。     LAN8720<<--->>BSR寄存器
      以太网库中的ETH_Init()函数通过读取PHY的BSR寄存器来判断连接是否建立、自协商是否完成等

信息。


7.LWIP源码的内容:
      doc文件夹里面有两个比较重要的文档:rawapi.txt和sys_arch.txt。前者告诉读者怎么使用
raw/callback API编程,sys_arch.txt包含了移植说明,在移植的时候会用到。src文件夹是我们的重点
,里面包含LWIP的源码。test是LWIP提供的一些测试程序,这里用不到。
      src文件夹由4个文件夹组成:api、core、include、netif四个文件夹。api文件夹里面是LWIP的
sequential API(Netconn)和socket API两种接口函数的源码,要使用这两种API需要操作系统支持。
core文件夹是LWIP内核源码,include文件夹里面是LWIP使用到的头文件,netif文件夹里面是与网络底
层接口有关的文件。


8.STM32F407以太网模块中的接受/发送FIFO和内存之间的以太网数据包传输是以太网DMA使用DMA描述符  
完成的。一共有两个描述符列表:一个用于接收,一个用于发送两个列表的基址分别写ETH_DMARDLAR和
ETH_DMATDLAR寄存器中。
  Tx DMA和Rx DMA常规描述符有4个“寄存器”:TDES0、TDES1、TDES2、TDES3,如果是增强描述符的话
就有8个“寄存器”。注意:这里的4个“寄存器”并非真实存在,他们是由ETH_DMADESCTypeDef结构体
描述的,称之为“软件寄存器”。
  以太网驱动库中描述符与buffer缓冲区的关系,如图1.3.3.4ST.
  在stm32f4x7_eth.c文件中定义了两个DMA描述符数组,一个用于DMA接收,一个用于DMA发送,代码:
  ETHDMADESCTypeDef  DMARxDscrTab[ETH_RXBUFNB];
  ETHDMADESCTypeDef  DMATxDscrTab[ETH_TXBUFNB];
  要将这两个数组改为链接结构还需要调用stm32f4x7_eth.c文件中两个函数ETH_DMARxDescChainInit()
和ETH_DMATxDescChainInit()。
  如果采用链接结构的话ETH_DMADESCTypeDef结构体中的Buffer1Addr成员变量存放缓冲区地址,在
stm32f4x7_eth.c中定义了两个数组用来作为发送和接收的缓冲区,代码如下:
uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
其中:
ETH_RXBUFNB     5字节
ETH_TXBUFNB      5字节
ETH_RX_BUF_SIZE  1524字节
ETH_TX_BUF_SIZE  1524字节
   在stm32f4x7_eth.c文件中为了追踪Rx/Tx DMA描述符还定义了两个非常重要的全局指针变量,如下代
码。
__IO ETH_DMADESCTypeDef  *DMATxDescToSet;
__IO ETH_DMADESCTypeDef  *DMARxDescToGet;
   这两个指针变量指向ETH_DMADESCTypeDef结构体,在使用中他们两个分别指向下一个要发送或者接收


的数据包。
   在LWIP无操作系统移植实验中,其中有一个ETHERNET文件,在这个文件中有lan8720.c和lan8720.h。
这两个文件中包含了LAN8720和STM32F407自带的MAC的驱动程序。而stm32f4x7_eth.c中包含了以太网的


驱动。
   LWIP无操作系统移植实验的LWIP文件夹可以发现有一个lwip_app文件夹,将这个文件夹复制到自己工
程中,lwip_app文件夹用来放我们以后所有实验的代码。在lwip_app下有一个lwip_commm文件夹,这个文
件中有lwip_commn.c、lwip_comm.h和lwipopts.h这三个文件,lwip_comm.c和lwip_comm.h是将LWIP源码
和前面的以太网驱动库结合起来桥梁!!!!注意:这两个文件非常重要,这两个文件由ALIENTEK提供
。lwipopts.h是用来剪裁和配置LWIP的文件,以后我们想要使用LWIP的什么功能的话就在这个文件中配
置就行了。
  LWIP源码建立:一、基本源码:LWIP_NETIF和LWIP_API、LWIP_CORE文件夹
                二、中间文件:LWIP_ARCH文件夹
                三、通用文件:LWIP_APP文件夹


9.以太网实验难点: LAN8720的驱动 和 LWIP的移植。实现功能:移植成功后开机初始化LAN8720,
LAN8720通过自协商确定自身的工作速度以及双工模式,通过串口打印MAC地址、IP地址、子网掩码和默

认网关等信息。

10.

(1)LAN8720与STM32F407链接部分  
ETH MDIO        PA2
ETH MDC         PC1


RMII_TXD0       PG13
RMII_TXD1       PG14
RMII_TX_EN      PG11


RMII_RXD0       PC4
RMII_RXD1       PC5


RMII_CRS_DV     PA7


RMII_REF_CLK    PA1


ETH_RESET       PD3
(2)LAN8720与RJ45链接部分:
LED1/REGOFF(LAN8720)<-->LINK_LED(RJ45) 
LED2/nINTSEL(LAN8720)<-->SPEED_LED(RJ45)   


Lan8720.c与stm32f4x7_eth.c的联系:
    1、注意后者为ST公司提供的函数,在Lan8720.c的ETH_MACDMA_Config()中的重要结构体
ETH_Initstructure,在stm32f4x7_eth.c中已经进行了一些默认的设置,即给ETH_Initstructure结构体
进行赋值,然后在自身ETH_MACDMA_Config()中又进行了一些LAN8720.c根据用户自身网卡进行的配置,
完成ETH_Initstructure结构体初始化。
    2、在ETH_MACDMA_Config()(LAN8720.c)的最后调用了ETH_Init()(stm32f4x7_eth.c)将前面
ETH_Initstructure结构体中的成员真正的赋值到ETH->XXX寄存器中,这才是真正构造

ETH_Initstructure进行默认赋值和根据网卡不懂赋值的真正作用和目的!!!!

LAN8720初始化中并没有看到我们直接操作PHY寄存器,原因在与当我们调用ETH_Init()后就会根据我们的输入的参数来配置LAN8720的相应寄存器了。
知识点:(1).站管理接口(SMI)允许应用程序通过时钟(MDC)和数据线(MDIO)访问任意的PHY寄存器。
        (2).MII用于MAC与PHY层的数据传输。
        (3).ARP 以太网地址解析协议;IP 包括IPv4和IPv6,支持多网络接口的下数据转发;
            ICMP 用于网络调试和维护;UDP 用户数据报协议。
            TCP  支持TCP拥塞控制,RTT估计,快速回复于重传;
            LWIP支持的用户编程接口方式:raw/callback API、sequenial API、BSD-style socket    API.
            DNS 域名解析
   DHCP:动态主机配置协议。
   AUTOIP:ip地址自动配置
            PPP:点对点,支持PPPoE
    stm32f4x7_eth.c为以太网驱动,LAN8720.c为lan8720和DM的驱动。
    
TCP/IP协议的分层:
应用层(应用和表示、会话层)->传输层(传输层)->互联层(网络层)->链路层(数据链路层、物理层)
    PHY层芯片LAN8720相当于物理层,STM32F407自带的MAC层相当于数据链路层。

    lwip_comm.c的头文件定义了__lwip_dev结构体,其中成员来存放ip地址和子网掩码、网关、DCHP
    typedef struct{
       u8 mac[6];        //MAC地址
       u8 remoteip[4];   //远端主机IP地址
       u8 ip[4];       
       u8 netmask[4];
       u8 gateway[4];
     
       vu8 dhcpstatus; //dhcp状态
     }
     netif.c头文件中netif.h定义了结构体netif()通用的数据结构类型。

你可能感兴趣的:(学习笔记)