/* Includes ------------------------------------------------------------------*/ #include "ethernetif_dm9k.h" #include "dm9k.h" #include "lwip/tcpip.h" #include "lwip/timeouts.h" #include "lwip_dm9k.h" #include "memory_manager.h" #include "netif/etharp.h" #include "netif/ethernet.h" // #include "snmp.h" #include "lwip_init.h" #include "string.h" #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 *dm9k_mutex = NULL; static struct netif *low_netif = NULL; /* ********************************************************************************************************* * 函 数 名: VariableMemInit * 功能说明: 申请串口相关的变量内存 * 形 参: 无 * 返 回 值: 无 ********************************************************************************************************* */ static void VariableMemInit(void) { uint16_t idx = 0; for (idx = 0; idx < DM9K_RX_DESC_CNT; idx++) { if (Rx_Buff[idx] == 0) Rx_Buff[idx] = pMemoryMalloc(&SRAM0, DM9K_RX_Lenth); // 因为不释放,避免重复申请 if (custom_pbuf[idx] == 0) custom_pbuf[idx] = pMemoryMalloc(&SRAM0, sizeof(struct pbuf_custom)); // 因为不释放,避免重复申请 } } static void low_level_init(struct netif *netif) { INT32U idx = 0; VariableMemInit(); INT8U err; /* set MAC hardware address length */ netif->hwaddr_len = ETHARP_HWADDR_LEN; /* set MAC hardware address */ /* 网卡的 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; for (idx = 0; idx < DM9K_RX_DESC_CNT; idx++) { custom_pbuf[idx]->custom_free_function = pbuf_free_custom; } if (NULL == dm9k_mutex) { dm9k_mutex = OSMutexCreate(1, &err); } /* 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); // ethernet_link_check_state(netif); } /** * @brief This function should do the actual transmission of the packet. The packet is * contained in the pbuf that is passed to the function. This pbuf * might be chained. * * @param netif the lwip network interface structure for this ethernetif * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) * @return ERR_OK if the packet could be sent * an err_t value if the packet couldn't be sent * * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to * strange results. You might consider waiting for space in the DMA queue * to become available since the stack doesn't retry to send a packet * dropped because of memory failure (except for the TCP timers). */ 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); OSMutexPend(dm9k_mutex, 1000, &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); OSMutexPost(dm9k_mutex); return errval; } static struct pbuf *low_level_input(struct netif *netif) { struct pbuf *p = NULL; uint32_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) { // 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; } #if 1 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; } } } } #else void ethernetif_input(void *argument) { struct pbuf *p; // struct netif *netif = (struct netif *)argument; INT8U err; for (;;) { OSSemPend(g_dm9k_rx_sem, 0, &err); // if (err == OS) // { if (err == ERR_OK) { do { LOCK_TCPIP_CORE(); p = low_level_input(low_netif); if (p != NULL) { err = low_netif->input(p, low_netif); if (err != ERR_OK) { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n")); pbuf_free(p); } } UNLOCK_TCPIP_CORE(); } while (p != NULL); } // } } } #endif 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); /* 执行接收处理程序 */ } 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 EXTI15_10_IRQHandler(void) { OSIntEnter(); EXTI_ClearITPendingBit(EXTI_Line15); /* 清除中断标志位 */ if (EXTI_GetITStatus(EXTI_Line15) != RESET) { BSP_GPIO15_EXTI_Callback(); } OSIntExit(); } void ethernet_link_check_state(struct netif *netif) { uint8_t linkchanged = 0; linkchanged = dm9k_linkstat(); if (netif_is_link_up(netif) && (linkchanged == 0)) { netif_set_down(netif); netif_set_link_down(netif); } else if (!netif_is_link_up(netif) && (linkchanged == 1)) { netif_set_up(netif); netif_set_link_up(netif); } }