#include "includes.h"
#include "Lan8720.h"
#include "gd32f4xx.h"
//#include "gd32f4xx_gpio.h"
#include "pdebug.h"
#include "bsp_os.h"
//#include "gd32f4xx_enet.h"
#include "gd32f4xx_it.h"
#include "lwip/tcpip.h"
#include "lwip/raw.h"
#include "lwip/icmp.h"
#include "lwip/dhcp.h"
#include "lwip/netif.h"
#include "lwip/sys.h"
#include "lwip/timers.h"
#include "lwip/inet_chksum.h"
#include "lwip/init.h"
#include "netif/etharp.h"

unsigned char g_local_ip[4]  = {192,168,8,200};     //本地默认ip
unsigned char g_local_mac[] = {0x42, 0x00, 0x00, 0x00, 0x00, 0x01};  //默认mac地址42:00:00:00:00:01
unsigned char g_netmask[4]   = {255,255,255,0};      //子网掩码
unsigned char g_gateway[4]   = {172,16,19,254};      //网关

//unsigned char gCfgLoca_MAC[] = {0x02, 0x0A, 0x0D, 0x0E, 0x0F, 0x06};
unsigned char gCfgLoca_MAC[] = {0x42, 0x00, 0x00, 0x00, 0x00, 0x01};

uint8_t gCfgLoca_MAC[];

__IO uint32_t enet_init_status = 0;//用于以太网初始化状态判断
char Enet_init_status;
struct netif fsl_netif0;
extern err_t ethernetif_init(struct netif *netif);

extern err_t ethernetif_input(struct netif *netif);


//初始化交换机
static void Lan8720_gpio_Init(void)
{
	//IO总线时钟使能
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_GPIOD);
	rcu_periph_clock_enable(RCU_GPIOG);
	rcu_periph_clock_enable(RCU_GPIOH);
	rcu_periph_clock_enable(RCU_GPIOI);
	//使能系统时钟
	rcu_periph_clock_enable(RCU_SYSCFG);

	//选择RMII模式
	syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_RMII);

	//PA1：REF_CLK 时钟引脚，外部PHY提供50M
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_1);
	
	//PA2: ETH_MDIO
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_2);
	
	//PA7: ETH_RMII_CRS_DV
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_7);   
	//引脚复用
	gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1);
	gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2);
	gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7);
	
	//PB11: ETH_RMII_TX_EN 
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_11);
	
	//PB12: ETH_RMII_TXD0 
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_12);
	
	//PB13: ETH_RMII_TXD1 
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_13);   
	
	gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_11);
	gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_12);
	gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_13);

	//PC1: ETH_MDC 
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_1);

	//PC4: ETH_RMII_RXD0 
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_4);
	
	//PC5: ETH_RMII_RXD1 
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_5); 
	
	gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1);
	gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4);
	gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5);
}

//初始化MAC/DMA
static void Enet_MAC_DMA_config(void)
{
    ErrStatus reval_state = ERROR;
    
    rcu_periph_clock_enable(RCU_ENET);//使能以太网总线时钟
    rcu_periph_clock_enable(RCU_ENETTX);//使能发送时钟
    rcu_periph_clock_enable(RCU_ENETRX);//使能接收时钟
    
    enet_deinit();//复位总线时钟AHB

    reval_state = enet_software_reset();//等待时钟复位完成
    if(ERROR == reval_state){//复位失败
        while(1){
        }
    }
    
   
    
    

//以太网设备初始化
#ifdef CHECKSUM_BY_HARDWARE//不定义
    enet_init_status = enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS);
#else  //PHY自动协商、禁用IP帧校验功能、地址过滤器通过所有接收到的广播帧 ENET_100M_FULLDUPLEX/ENET_AUTO_NEGOTIATION
    enet_init_status = enet_init(ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS);
#endif /* CHECKSUM_BY_HARDWARE */
    /*注：当前使用的LAN8720PHY芯片只能使用自动协商模式，手动模式无法通信（LAN8720自身bug）*/
}



//中断嵌套向量配置
static void Nvic_configuration(void)
{
	//配置中断嵌套基地址,,,使用Flash base address基地址，偏移量位应用程序偏移量（待boot使用后使能）
//	nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x0);
	//使能以太网中断请求
//	nvic_irq_enable(ENET_IRQn, 2, 3);
        nvic_irq_enable(ENET_IRQn, 1, 0);
}


void Lan8720_Init(void)
{
  
  // 中断嵌套向量配置 
  Nvic_configuration();   
  
  // RMII模式、时钟、引脚配置 
  Lan8720_gpio_Init();
  
  //MAC/DMA配置 
  Enet_MAC_DMA_config();
  
  if(0 == enet_init_status){//初始化DMA失败
    Enet_init_status = 0;
    term_printf("\n               Lan8720 Init fail 0        \r\n\r\n");
  }else{
    term_printf("\n               Lan8720 Init success 1       \r\n\r\n");
    Enet_init_status = 1;
  }
  //以太网正常中断启用
  enet_interrupt_enable(ENET_DMA_INT_NIE);
  //接收中断使能
  enet_interrupt_enable(ENET_DMA_INT_RIE);
  
  BSP_IntVectSet(77,ENET_IRQHandler);
  BSP_IntEn(77);
  
}



unsigned int Lwip_init(void)
{
    ip_addr_t fsl_netif0_ipaddr, fsl_netif0_netmask, fsl_netif0_gw;
    pdebug(DEBUG_LEVEL_INFO,"tcp ip init begin!\r\n"); 
    tcpip_init(NULL, NULL);
    OSTimeDlyHMSM(0, 0, 0, 100);
    pdebug(DEBUG_LEVEL_INFO,"tcp ip init ok!\r\n");    

#if LWIP_DHCP					 
    fsl_netif0_ipaddr.addr=0;
    fsl_netif0_netmask.addr=0;
    fsl_netif0_gw.addr=0;
#else    
    IP4_ADDR(&fsl_netif0_ipaddr, g_local_ip[0],g_local_ip[1],g_local_ip[2],g_local_ip[3]);
    IP4_ADDR(&fsl_netif0_netmask,  g_netmask[0],g_netmask[1],g_netmask[2],g_netmask[3]);
    IP4_ADDR(&fsl_netif0_gw, g_gateway[0],g_gateway[1],g_gateway[2],g_gateway[3]);
	
	u8_t *ip = (u8_t*)&fsl_netif0_ipaddr.addr;
    pdebug(DEBUG_LEVEL_INFO,"set net ip: %u.%u.%u.%u \r\n",ip[0], ip[1],ip[2], ip[3]);
    
    ip = (u8_t*)&fsl_netif0_netmask.addr;
    pdebug(DEBUG_LEVEL_INFO,"set net mask: %u.%u.%u.%u \r\n",ip[0], ip[1],ip[2], ip[3]);
    
    ip = (u8_t*)&fsl_netif0_gw.addr;
    pdebug(DEBUG_LEVEL_INFO,"set net gw: %u.%u.%u.%u \r\n",ip[0], ip[1],ip[2], ip[3]);
#endif 
  
    netif_add(&fsl_netif0, &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, NULL, ethernetif_init, ethernet_input);
    netif_set_default(&fsl_netif0);
    netif_set_up(&fsl_netif0);
#if LWIP_DHCP	    
    dhcp_start(&fsl_netif0);
    int i = sys_now();
	int time = 0;
    while((fsl_netif0.dhcp->offered_ip_addr.addr == 0) || (fsl_netif0.dhcp->offered_gw_addr.addr == 0) || (fsl_netif0.dhcp->offered_sn_mask.addr == 0))
    {    
        if(sys_now()- i > 8000) {
            i = sys_now();
            dhcp_start(&fsl_netif0);
			// 超时3次
			time++;
			if (time > 3) {
			    break;
			}
        }
        OSTimeDlyHMSM(0, 0, 0, 100);
    }
    
    dhcp_fine_tmr();
    netif_set_addr(&fsl_netif0, &(fsl_netif0.dhcp->offered_ip_addr), &(fsl_netif0.dhcp->offered_sn_mask), &(fsl_netif0.dhcp->offered_gw_addr));
    netif_set_default(&fsl_netif0);
    netif_set_up(&fsl_netif0);
        
    u8_t *ip = (u8_t*)&fsl_netif0.ip_addr.addr;    
    ip = (u8_t*)&fsl_netif0.dhcp->offered_sn_mask;    
    ip = (u8_t*)&fsl_netif0.dhcp->offered_gw_addr;
   
#endif  
    term_printf("\n               Lwip Init success        \r\n\r\n");
    return 0;
}   


                         
/// 以太网模块初始化 
///
/// 初始化底层mac控制器，phy芯片，OSLwip,创建任务
/// @param  none   
/// @param  none
/// @return none 
/// @note   修改日志
///         gkl与2017-05-26创建
///         LH于2022-05-12修改
void init_enet_module()
{           
	// 初始化mac控制器，phy芯片
	Lan8720_Init();
        // 初始化Lwip_Init相关功能模块
	Lwip_init();
}






