ソースを参照

FIX: Merged ljt8015's patch, add DM9161 support.
NOTE: The project.uv2 left not modified.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@546 bbd45198-f89e-11dd-88c7-29a3b14d5316

mbbill 15 年 前
コミット
9592d89769
6 ファイル変更184 行追加21 行削除
  1. 4 2
      bsp/sam7x/board.c
  2. 2 2
      bsp/sam7x/project.uvproj
  3. 118 13
      bsp/sam7x/sam7x_emac.c
  4. 50 1
      bsp/sam7x/sam7x_emac.h
  5. 9 3
      bsp/sam7x/serial.c
  6. 1 0
      bsp/sam7x/startup.c

+ 4 - 2
bsp/sam7x/board.c

@@ -10,6 +10,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2006-08-23     Bernard      first implementation
+ * 2010-03-09     ljt8015      Fix a bug in rt_hw_console_init()
  */
 
 #include <rtthread.h>
@@ -128,8 +129,9 @@ static void rt_hw_console_init()
 {
 	/* Enable Clock for USART0 */
 	AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_US0;
-	/* Enable RxD0 and TxDO Pin */
-	AT91C_BASE_PIOA->PIO_PDR = (1 << 5) | (1 << 6);
+	/* Enable RxD0 and TxD0 Pin */
+	//AT91C_BASE_PIOA->PIO_PDR = (1 << 5) | (1 << 6);
+	AT91C_BASE_PIOA->PIO_PDR = 1 | (1 << 1);//fix bug 2010-3-9
 
 	AT91C_BASE_US0->US_CR = AT91C_US_RSTRX	|		/* Reset Receiver      */
 				AT91C_US_RSTTX		|		/* Reset Transmitter   */

+ 2 - 2
bsp/sam7x/project.uvproj

@@ -116,7 +116,7 @@
           <Simulator>
             <UseSimulator>1</UseSimulator>
             <LoadApplicationAtStartup>1</LoadApplicationAtStartup>
-            <RunToMain>1</RunToMain>
+            <RunToMain>0</RunToMain>
             <RestoreBreakpoints>1</RestoreBreakpoints>
             <RestoreWatchpoints>1</RestoreWatchpoints>
             <RestoreMemoryDisplay>1</RestoreMemoryDisplay>
@@ -343,7 +343,7 @@
             <uThumb>0</uThumb>
             <VariousControls>
               <MiscControls></MiscControls>
-              <Define></Define>
+              <Define>RT_DEBUG</Define>
               <Undefine></Undefine>
               <IncludePath>.;..\..\include;..\sam7x;..\..\finsh;..\..\net\lwip\src\include;..\..\net\lwip\src;..\..\net\lwip\src\arch\include;..\..\net\lwip\src\include\ipv4;;..\..\filesystem\dfs;..\..\filesystem\dfs\include;..\..\filesystem\dfs\filesystems\efsl\src\include;..\..\filesystem\dfs\filesystems\efsl\src\base\include;..\..\filesystem\dfs\filesystems\efsl\src\fs\vfat\include</IncludePath>
             </VariousControls>

+ 118 - 13
bsp/sam7x/sam7x_emac.c

@@ -7,6 +7,27 @@
 #include "lwipopts.h"
 
 #define MAX_ADDR_LEN 6
+
+#ifdef DM9161
+#define EMAC_PIO_CFG	(AT91C_PB8_EMDC         | \
+						 AT91C_PB9_EMDIO         | \
+						 AT91C_PB2_ETX0          | \
+						 AT91C_PB3_ETX1          | \
+						 AT91C_PB10_ETX2         | \
+						 AT91C_PB11_ETX3         | \
+						 AT91C_PB1_ETXEN         | \
+						 AT91C_PB0_ETXCK_EREFCK  | \
+						 AT91C_PB15_ERXDV_ECRSDV | \
+						 AT91C_PB5_ERX0			| \
+						 AT91C_PB6_ERX1			| \
+						 AT91C_PB12_ETXER        | \
+						 AT91C_PB13_ERX2			| \
+						 AT91C_PB14_ERX3			| \
+						 AT91C_PB17_ERXCK		| \
+						 AT91C_PB16_ECOL			| \
+						 AT91C_PB4_ECRS			| \
+						 AT91C_PB7_ERXER)
+#else
 #define EMAC_PIO_CFG	(AT91C_PB0_ETXCK_EREFCK | \
 		AT91C_PB1_ETXEN        | \
 		AT91C_PB2_ETX0         | \
@@ -25,6 +46,7 @@
 		AT91C_PB15_ERXDV_ECRSDV| \
 		AT91C_PB16_ECOL        | \
 		AT91C_PB17_ERXCK)
+#endif
 
 #define RB_BUFFER_SIZE		8			/* max number of receive buffers */
 #define ETH_RX_BUF_SIZE		128
@@ -61,7 +83,6 @@ rt_inline void write_phy(rt_uint8_t addr, rt_uint32_t value)
 {
 	AT91C_BASE_EMAC->EMAC_MAN = ((0x01<<30) | (2 << 16) | (1 << 28) |
 								 (AT91C_PHY_ADDR << 23) | (addr << 18))  | value;
-
 	/* Wait until IDLE bit in Network Status register is cleared */
 	while (!(AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE));
 }
@@ -83,7 +104,7 @@ rt_inline void sam7xether_reset_tx_desc(void)
 
 	if(tb_descriptors[index].status & TxDESC_STATUS_USED)
 	{
-		while(!tb_descriptors[index].status & TxDESC_STATUS_LAST_BUF)
+		while(!(tb_descriptors[index].status & TxDESC_STATUS_LAST_BUF))
 		{
 			index ++;
 			if(index >= TB_BUFFER_SIZE)index = 0;
@@ -96,6 +117,7 @@ rt_inline void sam7xether_reset_tx_desc(void)
 	}
 }
 
+
 /* interrupt service routing */
 static void sam7xether_isr(int irq)
 {
@@ -128,15 +150,81 @@ static void sam7xether_isr(int irq)
 
 rt_inline void linksetup(void)
 {
-	rt_uint32_t value;
-
-	/* Check if this is a RTL8201 PHY. */
-	rt_uint16_t id1 = read_phy(PHY_REG_PHYID1);
-	rt_uint16_t id2 = read_phy(PHY_REG_PHYID2);
+	rt_uint32_t value, tout, id1, id2;
+#ifdef DM9161
+	rt_uint32_t ulBMSR,ulBMCR,i;
+#endif
+
+#ifdef DM9161
+  	//PHY has internal pull down : disable MII isolate
+  	tout = read_phy(PHY_REG_BMCR);
+  	tout = read_phy(PHY_REG_BMCR);
+  	tout &= ~BMCR_ISOLATE;
+  	write_phy(PHY_REG_BMCR, tout);
+
+	/* Check if this is a RTL8201 or DM9161 PHY. */
+	id1 = read_phy(PHY_REG_PHYID1);
+	id2 = read_phy(PHY_REG_PHYID2);
+
+	if (((id1 << 16) | (id2 & 0xfff0)) == MII_DM9161_ID)
+	{
+		rt_kprintf("read MII_DM9161_ID ok!\n");	
+
+        tout = DM9161_NP | DM9161_TX_FDX | DM9161_TX_HDX |
+               DM9161_10_FDX | DM9161_10_HDX | DM9161_AN_IEEE_802_3;
+        write_phy(PHY_REG_ANAR, tout);
+   	    // Wait for PHY auto negotiation completed
+		i = 0;
+  	    do {
+    		ulBMSR = read_phy(PHY_REG_BMSR);
+			ulBMSR = read_phy(PHY_REG_BMSR);
+			i++;
+
+			if(i >= 0xffff)
+			   break;
+  	    }while (!(ulBMSR & BMSR_ANEGCOMPLETE));
+
+		if(i >= 0xffff)
+		   rt_kprintf("PHY No Link!\n");
+		else
+		   rt_kprintf("PHY auto negotiation completed!\n");
+
+		/* Update the MAC register NCFGR. */
+		AT91C_BASE_EMAC->EMAC_NCFGR = 0;
+		ulBMCR = read_phy(PHY_REG_BMCR);
+			
+	    if (ulBMCR & BMCR_ANENABLE)
+	    {				
+			/* AutoNegotiation is enabled. */
+			if(!(ulBMSR & BMSR_ANEGCOMPLETE))
+			{
+			    /* Auto-negotitation in progress. */		
+				rt_kprintf("Auto-negotitation in progress!\n");
+			    return;			
+			}		
+
+	    	if (ulBMCR & BMCR_SPEED100) 
+	    	{
+		    	/* Speed 100Mbit is enabled. */
+		    	AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_SPD;
+		    	    
+	    	}
+	    	if (ulBMCR & BMCR_FULLDPLX) 
+	    	{
+		    	/* Full duplex is enabled. */
+		    	AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_FD;		    
+	    	}
+       }
+    }
+#else
+	/* Check if this is a RTL8201 or DM9161 PHY. */
+	id1 = read_phy(PHY_REG_PHYID1);
+	id2 = read_phy(PHY_REG_PHYID2);
 
 	if (((id2 << 16) | (id1 & 0xfff0)) == MII_RTL8201_ID)
 	{
-		rt_uint32_t tout;
+	    rt_kprintf("read MII_RTL8201_ID ok!\n");	
+
 
 		/* Configure the PHY device */
 		/* Use autonegotiation about the link speed. */
@@ -156,7 +244,6 @@ rt_inline void linksetup(void)
 			if (value & BMSR_LINKST) break; /* Link is on. */
 		}
 	}
-
 	value = read_phy (PHY_REG_ANLPAR);
 
 	/* Update the MAC register NCFGR. */
@@ -166,6 +253,7 @@ rt_inline void linksetup(void)
 	if (value & 0xA000) AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_FD;
 	/* set speed */
 	if (value & 0xC000) AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_SPD;
+ #endif 
 }
 
 /*
@@ -214,6 +302,8 @@ rt_inline void sam7xether_desc_init()
 /* initialize the interface */
 rt_err_t sam7xether_init(rt_device_t dev)
 {
+	rt_uint32_t i;
+	
 	/* enable peripheral clock for EMAC and PIO B */
 	AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB | 1 << AT91C_ID_EMAC;
 
@@ -240,10 +330,21 @@ rt_err_t sam7xether_init(rt_device_t dev)
 
 	AT91C_BASE_RSTC->RSTC_RMR = 0xA5000000 | (0x08 << 8) ;
 	AT91C_BASE_RSTC->RSTC_RCR = 0xA5000000 | AT91C_RSTC_EXTRST;
-	while(!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL));
+
+	i = 0;
+	while(!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL))
+	{
+	   i++;
+	   if(i >= 0xfffff)
+	     break;
+	}
+
+    for(i=0; i<0xfffff; i++);//* 等待一段指定的时间,使PHY就绪
 
 	linksetup();
 
+	rt_kprintf("linksetup ok!\n");
+
 	/* Disable management port in MAC control register. */
 	AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
 
@@ -262,13 +363,16 @@ rt_err_t sam7xether_init(rt_device_t dev)
 								  AT91C_EMAC_RLES| AT91C_EMAC_COL | AT91C_EMAC_UBR);
 
 	/* Configure EMAC operation mode. */
-	AT91C_BASE_EMAC->EMAC_NCFGR |= (AT91C_EMAC_BIG | AT91C_EMAC_DRFCS);
+	//AT91C_BASE_EMAC->EMAC_NCFGR |= (AT91C_EMAC_BIG | AT91C_EMAC_DRFCS);
+ 	//                   复制所有有效帧到接收缓冲区   *不复制FCS字段       不接收广播帧    不接收1526字节长帧                 
+	AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_CAF |AT91C_EMAC_DRFCS | AT91C_EMAC_NBC | AT91C_EMAC_BIG;
 	AT91C_BASE_EMAC->EMAC_NCR   |= (AT91C_EMAC_TE  | AT91C_EMAC_RE | AT91C_EMAC_WESTAT);
 
 	/* update MAC address */
 	update_mac_address(sam7x_dev);
 
 	/* enable interrupt */
+	AT91C_BASE_EMAC->EMAC_IDR = 0x3fff;
 	AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
 
 	/* setup interrupt */
@@ -496,12 +600,13 @@ struct pbuf *sam7xether_rx(rt_device_t dev)
 			if (pkt_len > 0) break;
 
 			index ++;
-			if (index > RB_BUFFER_SIZE) index = 0;
+			if (index >= RB_BUFFER_SIZE) index = 0;
 		}
 
 		if (pkt_len)
 		{
-			p = pbuf_alloc(PBUF_LINK, pkt_len, PBUF_RAM);
+			//p = pbuf_alloc(PBUF_LINK, pkt_len, PBUF_RAM);
+			p = pbuf_alloc(PBUF_RAW, pkt_len, PBUF_POOL);
 			if(p != RT_NULL)
 			{
 				sam7xether_read_frame(RT_NULL, 0, pkt_len);

+ 50 - 1
bsp/sam7x/sam7x_emac.h

@@ -1,8 +1,20 @@
 #ifndef __SAM7X_EMAC_H__
 #define __SAM7X_EMAC_H__
 
+//#define DM9161
+#define RTL8201 
+
+
+
+
+#ifdef 	 DM9161
+   #define AT91C_PHY_ADDR	31
+#else
 #define AT91C_PHY_ADDR      0x01
-#define MII_RTL8201_ID		0x82010000
+#endif
+
+#define MII_DM9161_ID       0x0181b8a0
+#define MII_RTL8201_ID      0x82010000
 
 /* RTL8201 PHY registers. */
 #define PHY_REG_BMCR        0x00        /* Basic mode control register       */
@@ -22,6 +34,18 @@
 #define PHY_REG_DISCR       0x17        /* Disconnect Counter register       */
 #define PHY_REG_RLSR        0x18        /* Hardware Reset Latch State reg.   */
 
+/* Basic mode control register. */
+#define BMCR_RESV               0x007f  /* Unused...                   */
+#define BMCR_CTST               0x0080  /* Collision test              */
+#define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
+#define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
+#define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */
+#define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */
+#define BMCR_SPEED100           0x2000  /* Select 100Mbps              */
+#define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */
+#define BMCR_RESET              0x8000  /* Reset the DP83840           */
+
 #define PHY_FULLD_100M      0x2100      /* Full Duplex 100Mbit               */
 #define PHY_HALFD_100M      0x2000      /* Half Duplex 100Mbit               */
 #define PHY_FULLD_10M       0x0100      /* Full Duplex 10Mbit                */
@@ -59,6 +83,31 @@
 #define	TxDESC_STATUS_WRAP			(1U << 30)
 #define	TxDESC_STATUS_USED			(1U << 31)
 
+//----dm9161 define----
+#define DM9161_RESET             (1 << 15) // 1= Software Reset; 0=Normal Operation
+#define DM9161_LOOPBACK          (1 << 14) // 1=loopback Enabled; 0=Normal Operation
+#define DM9161_SPEED_SELECT      (1 << 13) // 1=100Mbps; 0=10Mbps
+#define DM9161_AUTONEG           (1 << 12) // Auto-negotiation Enable
+#define DM9161_POWER_DOWN        (1 << 11) // 1=Power down 0=Normal operation
+#define DM9161_ISOLATE           (1 << 10) // 1 = Isolates 0 = Normal operation
+#define DM9161_RESTART_AUTONEG   (1 << 9)  // 1 = Restart auto-negotiation 0 = Normal operation
+#define DM9161_DUPLEX_MODE       (1 << 8)  // 1 = Full duplex operation 0 = Normal operation
+#define DM9161_COLLISION_TEST    (1 << 7)  // 1 = Collision test enabled 0 = Normal operation
+
+
+#define DM9161_NP               (1 << 15) // Next page Indication
+#define DM9161_ACK              (1 << 14) // Acknowledge
+#define DM9161_RF               (1 << 13) // Remote Fault
+//      Reserved                12 to 11  // Write as 0, ignore on read
+#define DM9161_FCS              (1 << 10) // Flow Control Support
+#define DM9161_T4               (1 << 9)  // 100BASE-T4 Support
+#define DM9161_TX_FDX           (1 << 8)  // 100BASE-TX Full Duplex Support
+#define DM9161_TX_HDX           (1 << 7)  // 100BASE-TX Support
+#define DM9161_10_FDX           (1 << 6)  // 10BASE-T Full Duplex Support
+#define DM9161_10_HDX           (1 << 5)  // 10BASE-T Support
+//      Selector                 4 to 0   // Protocol Selection Bits
+#define DM9161_AN_IEEE_802_3      0x0001
+
 int sam7xether_register(char *name);
 
 #endif

+ 9 - 3
bsp/sam7x/serial.c

@@ -12,6 +12,7 @@
  * 2006-08-23     Bernard      first version
  * 2009-05-14     Bernard      add RT-THread device interface
  * 2010-03-14     MingBai      US_IMR is read-only.
+ * 2010-03-16     MingBai      Changed interrupt source mode to level sensitive.
  */
 
 #include <rthw.h>
@@ -148,12 +149,14 @@ static rt_err_t rt_serial_init (rt_device_t dev)
 	if (serial->peripheral_id == AT91C_ID_US0)
 	{
 		/* set pinmux */
-		AT91C_PIO_PDR = (1 << 5) | (1 << 6);
+		//AT91C_PIO_PDR = (1 << 5) | (1 << 6);
+		AT91C_PIO_PDR = 1 | (1 << 1);  //fix bug 2010-3-9
 	}
 	else if (serial->peripheral_id == AT91C_ID_US1)
 	{
 		/* set pinmux */
-		AT91C_PIO_PDR = (1 << 21) | (1 << 22);
+		//AT91C_PIO_PDR = (1 << 21) | (1 << 22);
+		AT91C_PIO_PDR = (1 << 5) | (1 << 6);  //fix bug 2010-3-9
 	}
 
 	serial->hw_base->US_CR = AT91C_US_RSTRX	    | 	/* Reset Receiver      */
@@ -200,7 +203,10 @@ static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
 
 		/* install UART handler */
 		rt_hw_interrupt_install(serial->peripheral_id, rt_hw_serial_isr, RT_NULL);
-		AT91C_AIC_SMR(serial->peripheral_id) = 5 | (0x01 << 5);
+		// SAM7X Datasheet 30.5.3:
+		// It is notrecommended to use the USART interrupt line in edge sensitive mode
+		//AT91C_AIC_SMR(serial->peripheral_id) = 5 | (0x01 << 5);
+		AT91C_AIC_SMR(serial->peripheral_id) = 5;
 		rt_hw_interrupt_umask(serial->peripheral_id);
 	}
 

+ 1 - 0
bsp/sam7x/startup.c

@@ -23,6 +23,7 @@
 
 #ifdef RT_USING_LWIP
 #include "sam7x_emac.h"
+extern rt_err_t eth_system_device_init(void);
 #endif
 
 #ifdef RT_USING_FINSH