⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs8900if.c

📁 lwip在ucos上的移植代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Reset the CS8900A chip-wide using a soft reset * * @note You MUST wait 30 ms before accessing the CS8900 * after calling this function. */ IO1SET = SEL1;  IO1CLR = SEL1; IO1SET = SEL1; IO1CLR = SEL1;  cs8900a_write(ADD_PORT, PP_SelfCTL);  cs8900a_write(DATA_PORT, POWER_ON_RESET);      IO1SET = SEL1;  IO1CLR = SEL1; IO1SET = SEL1; IO1CLR = SEL1;   // Wait until chip-reset is done     cs8900a_write(ADD_PORT, PP_SelfST);  // INITD bit still clear?  while ((cs8900a_read(DATA_PORT) & INIT_DONE) == 0) ;      IO1SET = SEL1;  IO1CLR = SEL1; IO1SET = SEL1; IO1CLR = SEL1;	   /*   //空读写使cs8900a进入16位模式   dummy = *(u8_t *)(MEM_BASE + IO_BASE + 0x0D) ;   // Dummy read, put chip in 16bit-mode    dummy = *(u16_t *)(MEM_BASE + IO_BASE + 0x0D) ;    */    IO1SET = SEL1;  IO1CLR = SEL1; IO1SET = SEL1; IO1CLR = SEL1;   cs8900a_write(ADD_PORT,0x0102);  // Configure the CS8900A  for (i = 0; i < sizeof(InitSeq) / sizeof (TInitSeq); ++i)    {      cs8900a_write(ADD_PORT, InitSeq[i].addr);      cs8900a_write(DATA_PORT, InitSeq[i].data);    }    /* Hack - pass the netif structure to the recieve thread through a global variable. */   //用一个全局变量传递给接收线程一个网络接口   cs8900if_netif = netif;}/*-----------------------------------------------------------------------------------*//* * cs8900a_output(): * @return error code * - ERR_OK: packet transferred to hardware * - ERR_CONN: no link or link failure * - ERR_IF: could not transfer to link (hardware buffer full?) * * * 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. * *	我想在数据接收和发送的过程中应该用信号量来保证数据的完整性。 *//*-----------------------------------------------------------------------------------*/static err_tcs8900a_output(struct netif *netif, struct pbuf *p){    struct pbuf *q;    struct cs8900if *cs8900if;  int tries = 0;  err_t result;	cs8900if = netif->state;  // exit if link has failed  	cs8900a_write(ADD_PORT,PP_LineST);	if ((cs8900a_read(DATA_PORT) & 0x0080U/*LinkOK*/) == 0) return ERR_CONN; // no Ethernet link	  result = ERR_OK;         // issue 'transmit' command to CS8900   cs8900a_write(TX_CMD_PORT, TX_START_ALL_BYTES);  /* send length (in bytes) of packet to send, but at least minimum frame length */  cs8900a_write(TX_LEN_PORT, (p->tot_len < ETH_MIN_FRAME_LEN? ETH_MIN_FRAME_LEN: p->tot_len));	cs8900a_write(ADD_PORT,PP_BusST);  // not ready for transmission and still within 100 retries?  //如果当前不能发送,尝试100次  while (((cs8900a_read(DATA_PORT) & 0x0100U/*Rdy4TxNOW*/) == 0) && (tries++ < 10))  {    // throw away the last committed received frame    cs8900a_write(ADD_PORT,PP_RxCFG);    cs8900a_write(DATA_PORT,0x0003U | 0x0040U/*Skip_1*/ | 0x0100U/*RxOKiE*/);     cs8900a_write(ADD_PORT,PP_BusST);  }    //drop the padding word  #if ETH_PAD_SIZE  	pbuf_header(p,-ETH_PAD_SIZE);  #endif    // ready to transmit?如果准备好则发送数据  if ((cs8900a_read(DATA_PORT) & 0x0100U/*Rdy4TxNOW*/) != 0)  {  	unsigned long sent_bytes = 0;    /* q traverses through linked list of pbuf's     * This list MUST consist of a single packet ONLY */    for (q = p; q != NULL; q = q->next)    {      u16_t i;      u16_t *ptr = (u16_t *)q->payload;      /* Send the data from the pbuf to the interface, one pbuf at a       * time. The size of the data in each pbuf is kept in the ->len       * variable.       可能有多个缓冲区中的数据要发送,我们争取全部把它们发送出去       */      for (i = 0; i < q->len; i += 2)      {        /** TODO: this routine assumes 16-bit boundary pbufs... */        cs8900a_write(TX_FRAME_PORT,*ptr++);        sent_bytes += 2;              }    }    /* provide any additional padding to comply with minimum Ethernet     * frame length (RFC10242)如果数据过短就补充0,达到以太网最小的数据包 */    while (sent_bytes < ETH_MIN_FRAME_LEN)    {      cs8900a_write(TX_FRAME_PORT,0x0000);      sent_bytes += 2;    }  }  else  {    // { not ready to transmit!? }    /* return not connected */    result = ERR_IF;  }    //reclaim the padding word  #if ETH_PAD_SIZE  	pbuf_header(p,-ETH_PAD_SIZE);  #endif   #if LINK_STATS		lwip_stats.link.xmit++;	#endif /* LINK_STATS */	  return result;}/*-----------------------------------------------------------------------------------*//* * cs8900a_input(): * * Should allocate a pbuf and transfer the bytes of the incoming * packet from the interface into the pbuf. * * Move a received packet from the cs8900 into a new pbuf. * * Must be called after reading an ISQ event containing the * "Receiver Event" register, before reading new ISQ events. * * This function copies a frame from the CS8900A. * It is designed failsafe: * - It does not assume a frame is actually present. * - It checks for non-zero length * - It does not overflow the frame buffer *//*-----------------------------------------------------------------------------------*/static struct pbuf *cs8900a_input(struct netif *netif){	struct cs8900if *cs8900if;	struct pbuf *p = NULL, *q = NULL;  u16_t len = 0;  u16_t event_type;  u16_t i;  u16_t *ptr = NULL;	cs8900if = netif->state;  // read RxStatus  event_type = cs8900a_read(RX_FRAME_PORT);  // correctly received frame, either broadcast or individual address?  // TODO: maybe defer these conditions to cs8900_input()  if ((event_type & 0x0100U/*RxOK*/) && (event_type & 0x0c00U/*Broadcast | Individual*/))  {    event_type = 0;    // read RxLength    len = cs8900a_read(RX_FRAME_PORT);    LWIP_DEBUGF(NETIF_DEBUG, ("cs8900_input: packet len %u\n", len));    // positive length?    if (len > 0)    {      // allocate a pbuf chain with total length 'len'      p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);      if (p != NULL)      {      #if ETH_PAD_SIZE    		pbuf_header(p, -ETH_PAD_SIZE);			/* drop the padding word */		#endif        for (q = p; q != 0; q = q->next)			{	 		 	LWIP_DEBUGF(NETIF_DEBUG, ("cs8900_input: pbuf @%p tot_len %u len %u\n", q, q->tot_len, q->len));	  			ptr = q->payload;          // TODO: CHECK: what if q->len is odd? we don't use the last byte?	          for (i = 0; i < (q->len + 1) / 2; i++)	          {	            *ptr = cs8900a_read(RX_FRAME_PORT);	            ptr++;	          }        }    #if ETH_PAD_SIZE    	pbuf_header(p, ETH_PAD_SIZE);			/* reclaim the padding word */	#endif       }      // could not allocate a pbuf      else      {        // skip received frame        // TODO: maybe do not skip the frame at this point in time?        cs8900a_skip_frame();        len = 0;                #if LINK_STATS    			lwip_stats.link.memerr++;    			lwip_stats.link.drop++;				#endif /* LINK_STATS */         }    }    // length was zero    else    {    }  }  return p;}/** * cs8900if_input(): * * Read a received packet from the CS8900. * * This function should be called when a packet is received by the CS8900 * and is fully available to read. It moves the received packet to a pbuf * which is forwarded to the IP network layer or ARP module. It transmits * a resulting ARP reply or queued packet. * * @param netif The lwIP network interface to read from. * * @internal Uses cs8900_input() to move the packet from the CS8900 to a * newly allocated pbuf. * * * This function should be called when a packet is ready to be read * from the interface. It uses the function low_level_input() that * should handle the actual reception of bytes from the network * interface. * *//*-----------------------------------------------------------------------------------*/void cs8900if_input(struct netif *netif){  struct cs8900if *cs8900if;  struct eth_hdr *ethhdr;  struct pbuf *p; cs8900if = netif->state;/* move received packet into a new pbuf */  p = cs8900a_input(netif);  /* no packet could be read */  if (p == NULL) {    /* silently ignore this */    return;  }  /* points to packet payload, which starts with an Ethernet header */  ethhdr = p->payload;#if LINK_STATS  lwip_stats.link.recv++;#endif /* LINK_STATS */ switch (htons(ethhdr->type)) {  /* IP packet? */  case ETHTYPE_IP:    /* update ARP table */    etharp_ip_input(netif, p);    /* skip Ethernet header */    pbuf_header(p, -sizeof(struct eth_hdr));    /* pass to network layer */    netif->input(p, netif);    break;          case ETHTYPE_ARP:      /* pass p to ARP module  */      etharp_arp_input(netif, cs8900if->ethaddr, p);      break;    default:      pbuf_free(p);      p = NULL;      break;  }}/** * cs8900if_output(): * * Writing an IP packet (to be transmitted) to the CS8900. * * Before writing a frame to the CS8900, the ARP module is asked to resolve the * Ethernet MAC address. The ARP module might undertake actions to resolve the * address first, and queue this packet for later transmission. * * @param netif The lwIP network interface data structure belonging to this device. * @param p pbuf to be transmitted (or the first pbuf of a chained list of pbufs). * @param ipaddr destination IP address. * * @return ERR_OK if the packet was sent or queued. There is no way to * find out if a packet really makes it onto the network link. *  * @internal It uses the function cs8900_input() that should handle the actual * reception of bytes from the network interface. * * This function is called by the TCP/IP stack when an IP packet * should be sent. It calls the function called low_level_output() to * do the actual transmission of the packet. * */err_tcs8900if_output(struct netif *netif, struct pbuf *p,      struct ip_addr *ipaddr){   /* resolve hardware address, then send (or queue) packet */  return etharp_output(netif, ipaddr, p); }/** *  arp_timer. */static void arp_timer(void *arg){  etharp_tmr();  sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);} void cs8900a_send_test(void);/** * cs8900if_init(): * Initialize the CS8900 Ethernet MAC/PHY and its device driver. * * @param netif The lwIP network interface data structure belonging to this device. * MAY be NULL as we do not support multiple devices yet. * * Should be called at the beginning of the program to set up the * network interface. It calls the function low_level_init() to do the * actual setup of the hardware. * */ err_tcs8900if_init(struct netif *netif){  struct cs8900if *cs8900if;    //协议栈有自己的内存管理机制    cs8900if = mem_malloc(sizeof(struct cs8900if));  if (cs8900if == NULL)  {    LWIP_DEBUGF(NETIF_DEBUG, ("cs8900if_init: out of memory\n"));    return ERR_MEM;  }  // initialize cs8900 specific interface state data pointer  netif->state = cs8900if;  netif->name[0] = IFNAME0;  netif->name[1] = IFNAME1;  netif->output = cs8900if_output;  netif->linkoutput = cs8900a_output;    cs8900if->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);    // intialize the cs8900a chip  cs8900a_init(netif);  	etharp_init();    sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);    //cs8900a_send_test();    return ERR_OK;}/*-----------------------------------------------------------------------------------*//** *		TODO:写出不依赖于上层程序的驱动测试程序。先实现 *		 */ /* static const u8_t arpdata[60] =  { 	0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x08,0x06,0x00,0x01, 	0x08,0x00,0x06,0x04,0x00,0x01,0x00,0x01,0x02,0x03,0x04,0x05,0xd2,0x1d,0x68,0x08, 	0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0x1d,0x68,0x1e,0x00,0x00,0x00,0x00,0x00,0x00, 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };  void cs8900a_send_test(void) { 	u16_t u;  // Transmit command  cs8900a_write(TX_CMD_PORT, TX_START_ALL_BYTES);  cs8900a_write(TX_LEN_PORT, 60);  // Maximum number of retries  u = 8;  for (;;)    {      // Check for avaliable buffer space      cs8900a_write(ADD_PORT, PP_BusST);      if (cs8900a_read(DATA_PORT) & READY_FOR_TX_NOW)        break;      if (u -- == 0)        return;      // No space avaliable, skip a received frame and try again      cs8900a_skip_frame();    }    // Send uip_len bytes of header  for (u = 0; u < 60; u += 2)    {    cs8900a_write(TX_FRAME_PORT,*(u16_t *)&arpdata[u]);         } }*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -