对IAR5.11的NXP的example进行解释
对MAC的初始化
1.对时钟进行初始化
regVal = PCONP;
regVal |= PCONP_EMAC_CLOCK;
PCONP = regVal;
2.使能MAC层 针对LPC2378不同批次的芯片进行使能,通过读出MAC_MODULEID判断芯片的批次。因为有些批次的芯片上电默认MAC是不使能的,有些默认是使能的。
3.禁止RX 和TX
4.初始化物理层
5.设置MAC地址, /* write the station address registers MAC地址*/
MAC_SA0 = EMAC_ADDR12;
MAC_SA1 = EMAC_ADDR34;
MAC_SA2 = EMAC_ADDR56;
设置双工 CRC 速率等参数
6.初始化DMA指针
及对以下寄存器进行初始化
#define MAC_RXDESCRIPTOR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x108)) /* Rx descriptor base address reg */
#define MAC_RXSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x10C)) /* Rx status base address reg */
#define MAC_RXDESCRIPTORNUM (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x110)) /* Rx number of descriptors reg */
#define MAC_RXPRODUCEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x114)) /* Rx produce index reg (RO) */
#define MAC_RXCONSUMEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x118)) /* Rx consume index reg */
#define MAC_TXDESCRIPTOR (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x11C)) /* Tx descriptor base address reg */
#define MAC_TXSTATUS (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x120)) /* Tx status base address reg */
#define MAC_TXDESCRIPTORNUM (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x124)) /* Tx number of descriptors reg */
#define MAC_TXPRODUCEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x128)) /* Tx produce index reg */
#define MAC_TXCONSUMEINDEX (*(volatile unsigned long *)(MAC_BASE_ADDR + 0x12C)) /* Tx consume index reg (RO) */
使这些寄存器内的值为ENTHERNET RAM中的一些地址
DWORD i;
DWORD *tx_desc_addr, *tx_status_addr;
MAC_TXDESCRIPTOR = TX_DESCRIPTOR_ADDR; /*ENTHERNET RAM START+15K 大小是8*16 共有16个DESCRIPTOR 每个大小是2个32bit字*/
MAC_TXSTATUS = TX_STATUS_ADDR; /*ENTHERNET RAM START+15K+8*16 */
MAC_TXDESCRIPTORNUM = EMAC_TX_DESCRIPTOR_COUNT - 1; /* number of tx descriptors, 15*/
//下面的代码是初始化DESCRIPTORNUM RAM 、STATUS RAM中的值
for ( i = 0; i < EMAC_TX_DESCRIPTOR_COUNT; i++ )// EMAC_TX_DESCRIPTOR_COUNT大小是16
{
tx_desc_addr = (DWORD *)(TX_DESCRIPTOR_ADDR + i * 8); /*每个TXDESCRIPTOR是两个32bit字 */
*tx_desc_addr = (DWORD)(EMAC_TX_BUFFER_ADDR + i * EMAC_BLOCK_SIZE);/**/
*(tx_desc_addr+1) = (DWORD)(EMAC_TX_DESC_INT | (EMAC_BLOCK_SIZE - 1)); /* set size only */
}
for ( i = 0; i < EMAC_TX_DESCRIPTOR_COUNT; i++ )
{
tx_status_addr = (DWORD *)(TX_STATUS_ADDR + i * 4); /* TX status, one word only, status info. */
*tx_status_addr = (DWORD)0; /* initially, set status info to 0 */
}
MAC_TXPRODUCEINDEX = 0x0; /* TX descriptors point to zero */
7.设置Filter 是否接收广播多播组播的数据包 哈希
8.清除中断,并设置中断响应函数
9.使能中断
10.使能发送和接受
发送数据的方法
将LPC2378的ENTHERNET 16K的SRAM分成三部分 前7.5K的SRAM为发送数据区 接下来的7.5K为接收数据区 最后1K中的后面0X80*3+0X40=448个字节存放descriptors、status等等,7.5K中又以1536个字节为一个Block 共划分成5个Block,每个Block中可以放置一个数据包。
例子中是发送有效数据为100的数据包,包的总长度为118,。 前14个字节依次是对方的MAC地址6字节、自己的MAC地址6字节,有效数据的长度2字节(值为100)中间的100个字节为数据,后面四个字节为CRC校验。
下面对MAC_TXDESCRIPTOR、MAC_TXSTATUS、MAC_TXDESCRIPTORNUM、MAC_TXPRODUCEINDEX 、MAC_TXCONSUMEINDEX、五个寄存器进行说明:
MAC_TXDESCRIPTOR指向DESCRIPTOR表的首地址,这个表里面有MAC_TXDESCRIPTORNUM个DESCRIPTOR,每一个DESCRIPTOR分为两个32位字,第一个32位字要写入的是要发送的数据区的首地址,第二个32位字要写入的是要发送的数据长度,因为共有MAC_TXDESCRIPTORNUM个DESCRIPTOR,就相当于DESCRIPTOR的一个数组,当要发送数据时先把数据区的首指针和数据区的长度写入一个DESCRIPTOR中,然后将这个DESCRIPTOR在DESCRIPTOR表中的偏移量写到MAC_TXPRODUCEINDEX中,数据就开始发送了。 简单来说,先写RAM中的DESCRIPTOR,再写MAC_TXPRODUCEINDEX寄存器就实现了发送。