网络MAC地址从哪里获得?可以获取mcu的CPU ID,然后从CPU ID获取MAC地址
unsigned char _eth_phy_mac[6] = {0x8, 0x2e,0,0,0,0};
void Eth_GenMAC(){
/*
SerialID[0] = *(unsigned int*)(0x1FFFF7E8);
SerialID[1] = *(unsigned int*)(0x1FFFF7EC);
SerialID[2] = *(unsigned int*)(0x1FFFF7F0);
*/
unsigned char *cpu_id = (unsigned char *)0x1FFFF7E8;
unsigned int crc32_value;
crc32_value = crc32(cpu_id, 12);
_eth_phy_mac[2] = (char)(crc32_value >> 0);
_eth_phy_mac[3] = (char)(crc32_value >> 8);
_eth_phy_mac[4] = (char)(crc32_value >> 16);
_eth_phy_mac[5] = (char)(crc32_value >> 24);
};
stm32的ethernet 初始化,主要是PHY的驱动,
void stm32f107_eth_init(void)
{
RCC_ClocksTypeDef RCC_Clocks;
Eth_GenMAC();
eth_phy_clk_init();
eth_phy_gpio_init();
eth_phy_nvic_init();
eth_phy_mco_init();
eth_phy_confugration();
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.SYSCLK_Frequency / 100);
NVIC_SetPriority (SysTick_IRQn, 1);
}
然后Lwip初始化操作
int Eth_LwipRegisterWithDHCP(){
struct ip_addr ipaddr;
struct ip_addr netmask;
struct ip_addr gw;
setIsDHCP();
mem_init();
memp_init();
ipaddr.addr = 0;
netmask.addr = 0;
gw.addr = 0;
Set_MAC_Address(_eth_phy_mac);
netif_add(ð_phy_netif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);
netif_set_default(ð_phy_netif);
dhcp_start(ð_phy_netif);
netif_set_up(ð_phy_netif);
return 0;
}
移植LWIP到stm32上无操作系统时,注意不同的phy芯片,网卡驱动不同,所以,第一步应该是网卡驱动的改写,然后时候网络数据收发使用DMA的两个描述符,收和发,采用环形链表的数据结构。DMA的描述符结构如下:
typedef struct {
__IO uint32_t Status; /*!< Status */
uint32_t ControlBufferSize; /*!< Control and Buffer1, Buffer2 lengths */
uint32_t Buffer1Addr; /*!< Buffer1 address pointer */
uint32_t Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */
/* Enhanced ETHERNET DMA PTP Descriptors */
#ifdef USE_ENHANCED_DMA_DESCRIPTORS
uint32_t ExtendedStatus; /* Extended status for PTP receive descriptor */
uint32_t Reserved1; /* Reserved */
uint32_t TimeStampLow; /* Time Stamp Low value for transmit and receive */
uint32_t TimeStampHigh; /* Time Stamp High value for transmit and receive */
#endif /* USE_ENHANCED_DMA_DESCRIPTORS */
} ETH_DMADESCTypeDef;
如果定义的是接收结构体数组类型可以使用函数ETH_DMARxDescChainInit()ETH_DMATxDescChainInit()完成链表的构成。
使用结构体指针完成对两个TX和RX的描述符跟踪
__IO ETH_DMADESCTypeDef *DMATxDescToSet;
__IO ETH_DMADESCTypeDef *DMARxDescToGet;
注意对收发数据的内存管理,通常使用动态的分配内容空间,并且接收数据是使用中断接收的方式处理
void ETH_IRQHandler(void)
{
while(ETH_GetRxPktSize(DMARxDescToGet)!=0) //¼ì²âÊÇ·ñÊÕµ½Êý¾Ý°ü
{
lwip_pkt_handle();
}
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
}