/* Includes ------------------------------------------------------------------*/ #include "ethernetif_dm9k.h" #include "dm9k.h" #include "lwip/tcpip.h" #include "lwip/timeouts.h" #include "lwip_dm9k.h" #include "lwip_init.h" #include "netif/etharp.h" #include "netif/ethernet.h" #include "string.h" #include #define DM9K_RX_TASK_PRIO 4 #define DM9K_RX_TASK_STK_SIZE 2048 CPU_STK dm9k_rx_task_stk[DM9K_RX_TASK_STK_SIZE]; /* Define those to better describe your network interface. */ #define IFNAME0 'D' #define IFNAME1 '2' #define DM9K_RX_DESC_CNT 4 #define DM9K_RX_Lenth 1536UL /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ static uint8_t *Rx_Buff[DM9K_RX_DESC_CNT] = {0}; /* Ethernet Rx Buffer */ uint8_t current_pbuf_idx = 0; /* Zero-copy RX PBUF pool */ static struct pbuf_custom *custom_pbuf[DM9K_RX_DESC_CNT] = {0}; /* Private function prototypes -----------------------------------------------*/ static void pbuf_free_custom(struct pbuf *p); static void ethernetif_input(void *pvParameters); // static void ethernet_link_check_state(struct netif *netif); static OS_EVENT *g_dm9k_rx_sem = NULL; static OS_EVENT *g_dm9k_tx_sem = NULL; // static OS_EVENT *dm9k_mutex = NULL; static struct netif *low_netif = NULL; static void low_level_init(struct netif *netif) { /* set MAC hardware address length */ netif->hwaddr_len = ETHARP_HWADDR_LEN; /* 网卡的 MAC 修改2 */ netif->hwaddr[0] = dm9kdev.mac[0]; netif->hwaddr[1] = dm9kdev.mac[1]; netif->hwaddr[2] = dm9kdev.mac[2]; netif->hwaddr[3] = dm9kdev.mac[3]; netif->hwaddr[4] = dm9kdev.mac[4]; netif->hwaddr[5] = dm9kdev.mac[5]; /* maximum transfer unit */ netif->mtu = 1500; /* device capabilities */ /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */ netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; low_netif = netif; /* create binary semaphore used for informing ethernetif of frame reception */ if (NULL == g_dm9k_rx_sem) { g_dm9k_rx_sem = OSSemCreate(0); } OSTaskCreateExt((void (*)(void *))ethernetif_input, (void *)0, (OS_STK *)&dm9k_rx_task_stk[DM9K_RX_TASK_STK_SIZE - 1], (INT8U)DM9K_RX_TASK_PRIO, (INT16U)DM9K_RX_TASK_PRIO, (OS_STK *)&dm9k_rx_task_stk[0], (INT32U)DM9K_RX_TASK_STK_SIZE, (void *)0, (INT16U)OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR | OS_TASK_OPT_SAVE_FP); } static err_t low_level_output(struct netif *netif, struct pbuf *p) { INT8U err; err_t errval = ERR_OK; uint32_t i = 0, framelen = 0, calc_len = 0; struct pbuf *q; SYS_ARCH_DECL_PROTECT(sr); if (NULL == g_dm9k_tx_sem) { g_dm9k_tx_sem = OSSemCreate(1); } OSSemPend(g_dm9k_tx_sem, 0, &err); SYS_ARCH_PROTECT(sr); // dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF); /* 关闭 dm9kA 中断 */ NET_REG_ADDR = DM9K_REG_MWCMD; for (q = p; q != NULL; q = q->next) { framelen = framelen + q->len; calc_len = (q->len + 1) >> 1; for (i = 0; i < calc_len; i++) { NET_REG_DATA = ((uint16_t *)q->payload)[i]; } } dm9k_WriteReg(DM9K_REG_TXPLH, (framelen >> 8) & 0xff); /* 设置传送封包的长度 */ dm9k_WriteReg(DM9K_REG_TXPLL, framelen & 0xff); dm9k_WriteReg(DM9K_REG_TCR, DM9K_TCR_SET); /* 进行传送 */ while ((dm9k_ReadReg(DM9K_REG_ISR) & 0x02) == 0) ; /* 等待发送完成 */ // dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_SET); /* 开启 dm9kA 中断 */ SYS_ARCH_UNPROTECT(sr); // OSSemPost(g_dm9k_tx_sem); return errval; } static struct pbuf *low_level_input(struct netif *netif) { struct pbuf *p = NULL; uint16_t framelen = 0; // dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF); /* 关闭 DM9000A 中断 */ framelen = etherdev_read(Rx_Buff[current_pbuf_idx]); // dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_SET); /* 开启 DM9000A 中断 */ if (framelen) { printf("REC LEM: %d\r\n", framelen); p = pbuf_alloc(PBUF_RAW, framelen, PBUF_POOL); // p = pbuf_alloced_custom(PBUF_RAW, framelen, PBUF_REF, custom_pbuf[current_pbuf_idx], Rx_Buff[current_pbuf_idx], Max_Ethernet_Lenth); // if (current_pbuf_idx < (DM9K_RX_DESC_CNT - 1)) // { // current_pbuf_idx++; // } // else // { // current_pbuf_idx = 0; // } } return p; } void ethernetif_input(void *pvParameters) { struct pbuf *p; INT8U err; SYS_ARCH_DECL_PROTECT(sr); for (;;) { OSSemPend(g_dm9k_rx_sem, 100, &err); TRY_GET_NEXT_FRAME: SYS_ARCH_PROTECT(sr); p = low_level_input(low_netif); SYS_ARCH_UNPROTECT(sr); if (p != NULL) { if (ERR_OK != low_netif->input(p, low_netif)) { pbuf_free(p); } else { goto TRY_GET_NEXT_FRAME; } } } } err_t ethernetif_dm9k_init(struct netif *netif) { LWIP_ASSERT("netif != NULL", (netif != NULL)); #if LWIP_NETIF_HOSTNAME /* Initialize interface hostname */ netif->hostname = "DM9000"; #endif /* LWIP_NETIF_HOSTNAME */ /* * Initialize the snmp variables and counters inside the struct netif. * The last argument should be replaced with your link speed, in units * of bits per second. */ // MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS); netif->name[0] = IFNAME0; netif->name[1] = IFNAME1; /* We directly use etharp_output() here to save a function call. * You can instead declare your own function an call etharp_output() * from it if you have to do some checks before sending (e.g. if link * is available...) */ netif->output = etharp_output; netif->linkoutput = low_level_output; /* initialize the hardware */ low_level_init(netif); return ERR_OK; } /** * @brief Custom Rx pbuf free callback * @param pbuf: pbuf to be freed * @retval None */ // static void pbuf_free_custom(struct pbuf *p) // { // if (p != NULL) // { // memset(p, 0, sizeof(struct pbuf)); // } // } void dm9k_interrupt(void) { uint8_t save_reg; uint16_t isr_status; save_reg = NET_REG_ADDR; /* 暂存所使用的位置 */ // dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_OFF); /* 关闭 DM9KA 中断 */ isr_status = dm9k_ReadReg(DM9K_REG_ISR); /* 取得中断产生值 */ // isr_status = isr_status & DM9K_RX_INTR; if (isr_status & DM9K_RX_INTR) { /* 检查是否为接收中断 */ OSSemPost(g_dm9k_rx_sem); // dm9k_receive_packet(); /* 执行接收处理程序 */ } dm9k_WriteReg(DM9K_REG_IMR, DM9K_IMR_SET); /* 开启 DM9KA 中断 */ NET_REG_ADDR = save_reg; /* 回复所使用的位置 */ } /** * @brief Ethernet Rx Transfer completed callback * @param heth: ETH handle * @retval None */ void BSP_GPIO15_EXTI_Callback(void) { uint8_t save_reg; uint8_t isr_status; save_reg = NET_REG_ADDR; /* 暂存所使用的位置 */ isr_status = dm9k_ReadReg(DM9K_REG_ISR); /* 取得中断产生值 */ dm9k_WriteReg(DM9K_REG_ISR, isr_status); /* 清除中断产生值 */ // isr_status = isr_status & DM9K_RX_INTR; if (isr_status & DM9K_RX_INTR) /* 检查是否为接收中断 */ { OSSemPost(g_dm9k_rx_sem); /* 执行接收处理程序 */ } if (isr_status & DM9K_TX_INTR) // 发送中断 { OSSemPost(g_dm9k_tx_sem); // 发送完成中断,用户自己添加代码 } NET_REG_ADDR = save_reg; /* 回复所使用的位置 */ } // 中断处理函数,注意不是中断服函数,需要在中断服务函数中调用 void DMA9K_ISRHandler(void) { u16 int_status; u16 last_io; last_io = NET_REG_ADDR; int_status = dm9k_ReadReg(DM9K_REG_ISR); dm9k_WriteReg(DM9K_REG_ISR, int_status); // 清除中断标志位 if (int_status & DM9K_RX_INTR) // 接收中断 { OSSemPost(g_dm9k_rx_sem); // 接收完成中断,用户自己添加代码 } if (int_status & DM9K_TX_INTR) // 发送中断 { // OSSemPost(g_dm9k_tx_sem); // 发送完成中断,用户自己添加代码 } NET_REG_ADDR = last_io; } void ethernet_link_check_state(struct netif *netif) { uint8_t linkchanged = 0; linkchanged = dm9k_linkstat(); if (netif_is_link_up(netif) && (linkchanged == 0)) { printf("dm9k LwIP Error interface....\r\n"); netif_set_down(netif); netif_set_link_down(netif); } else if (!netif_is_link_up(netif) && (linkchanged == 1)) { printf("dm9k LwIP Finish interface....\r\n"); netif_set_up(netif); netif_set_link_up(netif); } }