123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- /* Includes ------------------------------------------------------------------*/
- #include "ethernetif_dm9k.h"
- #include "dm9k.h"
- #include "lwip/tcpip.h"
- #include "lwip/timeouts.h"
- #include "netif/etharp.h"
- #include "netif/ethernet.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 's'
- #define IFNAME1 't'
- #define DM9K_RX_DESC_CNT 3
- #define DM9K_RX_Lenth 1536UL * 2
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- static uint8_t *Rx_Buff[DM9K_RX_DESC_CNT] = {0}; /* Ethernet Rx Buffer */
- static 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 struct netif *low_netif = NULL;
- static void low_level_init(struct netif *netif)
- {
- // VariableMemInit();
- /* set MAC hardware address length */
- netif->hwaddr_len = ETHARP_HWADDR_LEN;
- /* set MAC hardware address */ /* 网卡的 MAC 修改2 */
- netif->hwaddr[0] = DM9K_MAC_ADDR0;
- netif->hwaddr[1] = DM9K_MAC_ADDR1;
- netif->hwaddr[2] = DM9K_MAC_ADDR2;
- netif->hwaddr[3] = DM9K_MAC_ADDR3;
- netif->hwaddr[4] = DM9K_MAC_ADDR4;
- netif->hwaddr[5] = DM9K_MAC_ADDR5;
- /* 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;
- /* 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)
- {
- err_t errval = ERR_OK;
- uint32_t i = 0, framelen = 0, calc_len = 0;
- struct pbuf *q;
- 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 中断 */
- return errval;
- }
- static struct pbuf *low_level_input(struct netif *netif)
- {
- struct pbuf *p = NULL;
- uint32_t framelen = 0;
- framelen = etherdev_read(Rx_Buff[current_pbuf_idx]);
- if (framelen)
- {
- // 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, 0, &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 = "lwip";
- #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.
- */
- 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 EXTI15_10_IRQHandler(void)
- {
- if (EXTI_GetITStatus(EXTI_Line14) != RESET)
- {
- BSP_GPIO15_EXTI_Callback();
- EXTI_ClearITPendingBit(EXTI_Line14); /* 清除中断标志位 */
- }
- }
- /**
- * @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); /* 清除中断产生值 */
- if (isr_status & DM9K_RX_INTR) /* 检查是否为接收中断 */
- {
- OSSemPost(g_dm9k_rx_sem); /* 执行接收处理程序 */
- }
- NET_REG_ADDR = save_reg; /* 回复所使用的位置 */
- }
- /**
- * @brief Check the ETH link state and update netif accordingly.
- * @param argument: netif
- * @retval None
- */
- 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);
- }
- }
- void ethernet_dm9k_link_thread(void const *argument)
- {
- struct netif *netif = (struct netif *)argument;
- for (;;)
- {
- ethernet_link_check_state(netif);
- OSTimeDly(100);
- }
- }
|