《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()通用的数据结构类型。