概述
記錄下DM9000AE在rt-thread上的使用
-
FMC的配置
-
rt-thread的網絡設備驅動注冊
硬件連接
-
16bit總線
-
掛在FMC_A0 地址0x6000_0000
FMC的配置
FMC是STM32H7的一個外設,通過FMC把DM9000當做一個SRAM來訪問,只需要配置好FCM的時序就可以了。
DM9000時序描述
來看一下DM9000的數據手冊上對時序的描述
從手冊上來看DM9000的時序情況如下
訪問方式 | 數據建立時間 | 地址建立時間 |
---|---|---|
讀取 | 最小 10ns | 80ns (F0寄存器需要80ns) |
寫入 | 最小 10ns | 40ns |
FMC的時序配置
STM32H7的FMC外設,支持讀寫時序分離配置,也可以讀寫使用同一個時序配置,這里為了簡單就直接使用一個,會犧牲效率, 性能優化可以在這里把讀寫分開,因為DM9000的讀寫速度明顯不一樣。
FMC的時鐘配置,將地址建立時間大于80ns, 數據建立時間大于10ns
Timing.BusTurnAroundDuration = 2; // 片選信號,高脈寬
這個參數,實測影響的是片選信號的高電平,如果設置為0,則相當于片選一直有效
但是DM9000的SD口是地址和數據復用的,需要一定的切換時間,所以這個值需要設置,不然會發生異常。
這里設置為2,只是參考值,讀者可以根據實際情況設置。
MPU配置(重要)
STM32H7有專用的內存保護單元,能夠管理內存的訪問權限。
這里FMC是掛在0x6000_0000的內存區域,為了能夠正常訪問外部的DM9000需要對該區域進行權限訪問。
網絡設備驅動注冊
rt-thread的網絡設備驅動的注冊還是比較易懂的,我們需要實現的是操作硬件的接口即可。
這里重點關注這三個函數
-
rt_dm9000_init // DM9000的初始化
-
rt_dm9000_rx // DM9000讀取網絡數據包
-
rt_dm9000_tx // 發送網絡數據包
實際上DM9000負責收發以太網幀, lwip負責協議處理。
dm9000的初始化沒有什么特別的,按照初始化流程走,硬件、軟件復位、校驗ID、配置中斷、使能等。
重點看看接收和發送
// DM9000
DM90000 INT-> rt_dm9000_isr-> eth_device_ready(&(dm9000_device.parent));-> return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev);// 通過信號量通知接收線程-> eth_rx_thread_entry -> if (rt_mb_recv(ð_rx_thread_mb, (rt_ubase_t *)&device, RT_WAITING_FOREVER) == RT_EOK) // 等待信號量, DM9000中斷觸發while(1) // 注意這里,循環讀取,所以在eth_rx接口中,**讀取一幀**就立即返回即可。{-> p = device->eth_rx(&(device->parent)); // 注冊驅動時指定的 讀取DM9000的接口-> if( device->netif->input(p, device->netif) != ERR_OK ) // 提交給lwip協議棧}
DM9000的收發
DM9000有一個16KB的硬件FIFO, 默認配置下,前3KB用于發送,后13KB用于接收,這個大小可以通過配置相應的寄存器修改。
發送過程
-
數據放入發送FIFO
-
告訴DM9000數據總量
-
啟動發送
-
可以輪詢等待,也可以等中斷通知
// 概要
rt_err_t rt_dm9000_tx( rt_device_t dev, struct pbuf* p)-> dm9000_io_write(DM9000_IMR, IMR_PAR); // 屏蔽中斷,防止干擾-> DM9000_IO = DM9000_MWCMD; // 寫入操作while(1){-> word[word_index++] = ((u8_t*)q->payload)[pbuf_index++];-> DM9000_DATA = (word[1] << 8) | word[0]; // write two bytes to DM9000_DATA 每次2字節寫入}-> dm9000_io_write(DM9000_TXPLL, p->tot_len & 0xff);-> dm9000_io_write(DM9000_TXPLH, (p->tot_len >> 8) & 0xff);-> dm9000_io_write(DM9000_TCR, TCR_TXREQ); // 使能bit0啟動發送,發送完成后會自動清除-> dm9000_io_write(DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM | ISR_ROS | ISR_ROOS); // 恢復中斷
接收過程
接收過程需要注意的地方多一點,主要是數據幀的組織和讀取動作。
先來看看數據幀在FIFI中分布
-
數據幀:4B的頭+pyload+4B CRC
-
多個數據幀連續排布
特別注意
-
DM9000的FIFO是雙字節對齊的
當pyload為奇數時,會出現一下情況,在最后一個字節會多一字節,讓下一幀對齊地址。
-
DM9000觸發中斷后RX-FIFO可能會有多幀
在rt-thread的網絡驅動中,接收函數只需要構建一幀數據就好,在驅動線程中會一次性讀取完,直到讀取到空數據為止。 -
DM9000的RX-FIFO每一幀都有4B的CRC
協議棧不需要這4B 需要丟棄掉
dummy_u16 = DM9000_DATA; dummy_u16 = DM9000_DATA;
ps: 源碼放最后,感謝看完本篇的你!
源碼
#ifndef __DRV_DM9000_H__
#define __DRV_DM9000_H__
?
// #define DM9000_IO_BASE ? ? 0x64000000 ?
// // #define DM9000_DATA_BASE ? 0x64000100 // FSMC_A7 -- CMD = 1
// #define DM9000_DATA_BASE ? (0x64000000 + 0x00000002) // FSMC_A7 -- CMD = 1
?
// #define DM9000_IO (*((volatile rt_uint16_t *) DM9000_IO_BASE)) ? // CMD = 0
// #define DM9000_DATA (*((volatile rt_uint16_t *) DM9000_DATA_BASE)) // CMD = 1
?#include "main.h"typedef __IO uint32_t ?vu32;typedef __IO uint16_t vu16;typedef __IO uint8_t ?vu8;
?typedef uint32_t ?u32;typedef uint16_t u16;typedef uint8_t ?u8;
//DM9000地址結構體
typedef struct
{vu16 REG;vu16 DATA;
}DM9000_TypeDef;
#define DM9000_BASE ? ? ? ((u32)(0x60000000))
#define DM9000 ? ? ? ? ? ? ((DM9000_TypeDef *) DM9000_BASE)
?
#define DM9000_IO_BASE ? ? (DM9000->REG) ?
#define DM9000_DATA_BASE ? (DM9000->DATA) ?// FSMC_A0 -- CMD = 1
#define DM9000_IO (DM9000->REG) ? ?// CMD = 0
#define DM9000_DATA (DM9000->DATA) ?// CMD = 1
?
// #define DM9000_IO_BASE ? ? 0x64000000 ?
// #define DM9000_DATA_BASE ? (0x64000000 + 0x2) // FSMC_A0 -- CMD = 1
?
// #define DM9000_IO (*((volatile rt_uint16_t *) DM9000_IO_BASE)) ? // CMD = 0
// #define DM9000_DATA (*((volatile rt_uint16_t *) DM9000_DATA_BASE)) // CMD = 1
?
?
// #define DM9000_inb(r) (*(volatile rt_uint8_t *)r)
// #define DM9000_outb(r, d) (*(volatile rt_uint8_t *)r = d)
// #define DM9000_inw(r) (*(volatile rt_uint16_t *)r)
// #define DM9000_outw(r, d) (*(volatile rt_uint16_t *)r = d)
?
#define DM9000_ID ? 0x90000A46 ?/* DM9000 ID */
#define DM9000_PKT_MAX 1536 ? ?/* Received packet max size */
#define DM9000_PKT_RDY 0x01 ? ?/* Packet ready to receive */
?
#define DM9000_NCR ? ? ? ? 0x00
#define DM9000_NSR ? ? ? ? 0x01
#define DM9000_TCR ? ? ? ? 0x02
#define DM9000_TSR1 ? ? ? ? 0x03
#define DM9000_TSR2 ? ? ? ? 0x04
#define DM9000_RCR ? ? ? ? 0x05
#define DM9000_RSR ? ? ? ? 0x06
#define DM9000_ROCR ? ? ? ? 0x07
#define DM9000_BPTR ? ? ? ? 0x08
#define DM9000_FCTR ? ? ? ? 0x09
#define DM9000_FCR ? ? ? ? 0x0A
#define DM9000_EPCR ? ? ? ? 0x0B
#define DM9000_EPAR ? ? ? ? 0x0C
#define DM9000_EPDRL ? ? ? 0x0D
#define DM9000_EPDRH ? ? ? 0x0E
#define DM9000_WCR ? ? ? ? 0x0F
?
#define DM9000_PAR ? ? ? ? 0x10
#define DM9000_MAR ? ? ? ? 0x16
?
#define DM9000_GPCR ? ? ? ? 0x1e
#define DM9000_GPR ? ? ? ? 0x1f
#define DM9000_TRPAL ? ? ? 0x22
#define DM9000_TRPAH ? ? ? 0x23
#define DM9000_RWPAL ? ? ? 0x24
#define DM9000_RWPAH ? ? ? 0x25
?
#define DM9000_VIDL ? ? ? ? 0x28
#define DM9000_VIDH ? ? ? ? 0x29
#define DM9000_PIDL ? ? ? ? 0x2A
#define DM9000_PIDH ? ? ? ? 0x2B
?
#define DM9000_CHIPR ? ? ? 0x2C
#define DM9000_TCR2 0x2D
#define DM9000_OTCR 0x2E
#define DM9000_SMCR ? ? ? ? 0x2F
?
#define DM9000_ETCR 0x30 /* early transmit control/status register */
#define DM9000_CSCR 0x31 /* check sum control register */
#define DM9000_RCSSR 0x32 /* receive check sum status register */
?
#define DM9000_MRCMDX ? ? ? 0xF0
#define DM9000_MRCMD ? ? ? 0xF2
#define DM9000_MRRL ? ? ? ? 0xF4
#define DM9000_MRRH ? ? ? ? 0xF5
#define DM9000_MWCMDX ? ? ? 0xF6
#define DM9000_MWCMD ? ? ? 0xF8
#define DM9000_MWRL ? ? ? ? 0xFA
#define DM9000_MWRH ? ? ? ? 0xFB
#define DM9000_TXPLL ? ? ? 0xFC
#define DM9000_TXPLH ? ? ? 0xFD
#define DM9000_ISR ? ? ? ? 0xFE
#define DM9000_IMR ? ? ? ? 0xFF
?
#define CHIPR_DM9000A ? ? ? 0x19
#define CHIPR_DM9000B ? ? ? 0x1B
?
#define NCR_EXT_PHY ? ? ? ? (1<<7)
#define NCR_WAKEEN ? ? ? ? (1<<6)
#define NCR_FCOL ? ? ? ? ? (1<<4)
#define NCR_FDX ? ? ? ? ? ? (1<<3)
#define NCR_LBK ? ? ? ? ? ? (3<<1)
#define NCR_RST ? ? ? ? ? ? (1<<0)
?
#define NSR_SPEED ? ? ? ? ? (1<<7)
#define NSR_LINKST ? ? ? ? (1<<6)
#define NSR_WAKEST ? ? ? ? (1<<5)
#define NSR_TX2END ? ? ? ? (1<<3)
#define NSR_TX1END ? ? ? ? (1<<2)
#define NSR_RXOV ? ? ? ? ? (1<<1)
?
#define TCR_TJDIS ? ? ? ? ? (1<<6)
#define TCR_EXCECM ? ? ? ? (1<<5)
#define TCR_PAD_DIS2 ? ? ? (1<<4)
#define TCR_CRC_DIS2 ? ? ? (1<<3)
#define TCR_PAD_DIS1 ? ? ? (1<<2)
#define TCR_CRC_DIS1 ? ? ? (1<<1)
#define TCR_TXREQ ? ? ? ? ? (1<<0)
?
#define TSR_TJTO ? ? ? ? ? (1<<7)
#define TSR_LC ? ? ? ? ? ? (1<<6)
#define TSR_NC ? ? ? ? ? ? (1<<5)
#define TSR_LCOL ? ? ? ? ? (1<<4)
#define TSR_COL ? ? ? ? ? ? (1<<3)
#define TSR_EC ? ? ? ? ? ? (1<<2)
?
#define RCR_WTDIS ? ? ? ? ? (1<<6)
#define RCR_DIS_LONG ? ? ? (1<<5)
#define RCR_DIS_CRC ? ? ? ? (1<<4)
#define RCR_ALL ? ? ? ? ? ? (1<<3)
#define RCR_RUNT ? ? ? ? ? (1<<2)
#define RCR_PRMSC ? ? ? ? ? (1<<1)
#define RCR_RXEN ? ? ? ? ? (1<<0)
?
#define RSR_RF ? ? ? ? ? ? (1<<7)
#define RSR_MF ? ? ? ? ? ? (1<<6)
#define RSR_LCS ? ? ? ? ? ? (1<<5)
#define RSR_RWTO ? ? ? ? ? (1<<4)
#define RSR_PLE ? ? ? ? ? ? (1<<3)
#define RSR_AE ? ? ? ? ? ? (1<<2)
#define RSR_CE ? ? ? ? ? ? (1<<1)
#define RSR_FOE ? ? ? ? ? ? (1<<0)
?
#define FCTR_HWOT(ot) ? ? ? (( ot & 0xf ) << 4 )
#define FCTR_LWOT(ot) ? ? ? ( ot & 0xf )
?
#define IMR_PAR ? ? ? ? ? ? (1<<7)
#define IMR_ROOM ? ? ? ? ? (1<<3)
#define IMR_ROM ? ? ? ? ? ? (1<<2)
#define IMR_PTM ? ? ? ? ? ? (1<<1)
#define IMR_PRM ? ? ? ? ? ? (1<<0)
?
#define ISR_ROOS ? ? ? ? ? (1<<3)
#define ISR_ROS ? ? ? ? ? ? (1<<2)
#define ISR_PTS ? ? ? ? ? ? (1<<1)
#define ISR_PRS ? ? ? ? ? ? (1<<0)
#define ISR_CLR_STATUS ? ? (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
?
#define EPCR_REEP ? ? ? ? ? (1<<5)
#define EPCR_WEP ? ? ? ? ? (1<<4)
#define EPCR_EPOS ? ? ? ? ? (1<<3)
#define EPCR_ERPRR ? ? ? ? (1<<2)
#define EPCR_ERPRW ? ? ? ? (1<<1)
#define EPCR_ERRE ? ? ? ? ? (1<<0)
?
#define GPCR_GEP_CNTL ? ? ? (1<<0)
?
/* 原子例程 dm9000內部的phy寄存器 */
#define DM9000_PHY_BMCR 0X00
#define DM9000_PHY_BMSR 0X01
#define DM9000_PHY_PHYID1 0X02
#define DM9000_PHY_PHYID2 0X03
#define DM9000_PHY_ANAR 0X04
#define DM9000_PHY_ANLPAR 0X05
#define DM9000_PHY_ANER 0X06
#define DM9000_PHY_DSCR 0X10
#define DM9000_PHY_DSCSR 0X11
#define DM9000_PHY_10BTCSR 0X12
#define DM9000_PHY_PWDOR 0X13
#define DM9000_PHY_SCR 0X14
?
#ifdef __cplusplus
extern "C" {
#endif
?
int rt_hw_dm9000_init(void);
?
#ifdef __cplusplus
}
#endif
?
#endif // __DRV_DM9000_H__
#include "drv_dm9000.h"
?
#define DBG_TAG ? ? ? ? ? ? ? ? ? ? ? "dm9k"
#define DBG_LVL ? ? ? ? ? ? ? ? ? ? ? DBG_LOG
#include <rtdbg.h>
?
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
?
#include <netif/ethernetif.h>
?
#include "stm32h7xx_hal_sram.h"
?
// #define DM9000_DEBUG
#ifdef DM9000_DEBUG
#define DM9000_TRACE ? rt_kprintf
#else
#define DM9000_TRACE(...)
#endif
?
/* dm9000 reset pin : GPIOD PIN7, LOW is RESET */
#define DM9000_RST_0 ? ? ? rt_pin_write(GET_PIN(A, 10), PIN_LOW)
#define DM9000_RST_1 ? ? ? rt_pin_write(GET_PIN(A, 10), PIN_HIGH)
?
#define MAX_ADDR_LEN ? ? ? 6 ? ? ? /* max length of hw address */
?
#define DM9000_PHY ? ? ? ? 0x40 ? ?/* PHY address 0x01 */
?
#define PIN_NRESET GET_PIN(A, 10) // 復位引腳
#define PIN_IRQ GET_PIN(A, 15) ? ?// 例如:PA0 作為中斷引腳
?
enum DM9000_PHY_mode
{DM9000_10MHD = 0, DM9000_100MHD = 1,DM9000_10MFD = 4, DM9000_100MFD = 5,DM9000_AUTO ?= 8, DM9000_1M_HPNA = 0x10
};
?
enum DM9000_TYPE
{TYPE_DM9000E,TYPE_DM9000A,TYPE_DM9000B
};
?
struct rt_dm9000_eth
{/* inherit from ethernet device */struct eth_device parent;
?enum DM9000_TYPE type;enum DM9000_PHY_mode mode;
?rt_uint8_t packet_cnt; ? ? ? ? ? ? ? ?/* packet I or II */rt_uint16_t queue_packet_len; ? ? ? ? ?/* queued packet (packet II) */
?/* interface address info. */rt_uint8_t ?dev_addr[MAX_ADDR_LEN]; ? ? /* hw address ? */rt_uint8_t ?init_complete; ? ? ? ? ? /* init complete flag */
};
?
static struct rt_dm9000_eth dm9000_device;
static struct rt_semaphore sem_ack, sem_lock;
int dm_irq_cnt, dm_pkg_max;
?
// 這個一定要放在全局作用域下
//static SRAM_HandleTypeDef DM9000_Handler; ? ? ? ? ? //DM9000句柄
?
/* --- */
?
static inline void dm9000_delay_ms(rt_uint32_t ms)
{rt_thread_mdelay(ms); return;
}
?
/* Read a byte from I/O port */
rt_inline rt_uint16_t dm9000_io_read(rt_uint16_t reg) {DM9000_IO = reg;return DM9000_DATA;
}
?
/* Write a byte to I/O port */
rt_inline void dm9000_io_write(rt_uint16_t reg, rt_uint16_t value) {DM9000_IO = reg;DM9000_DATA = value;
}
?
/* Get DeviceID of DM9000 */
static rt_uint32_t dm9000_get_device_id(void)
{rt_uint32_t value;value ?= dm9000_io_read(DM9000_VIDL);value |= dm9000_io_read(DM9000_VIDH) << 8;value |= dm9000_io_read(DM9000_PIDL) << 16;value |= dm9000_io_read(DM9000_PIDH) << 24;return value;
}
?
/* Reset DM9000 */
static void dm9000_reset(void) {DM9000_TRACE("enter dm9000_reset\n");DM9000_RST_0; // set rst pin lowdm9000_delay_ms(10);
?DM9000_RST_1;dm9000_delay_ms(100); ?// hardware rst over
?dm9000_io_write(DM9000_GPCR, 0x01);dm9000_io_write(DM9000_GPR, 0);dm9000_io_write(DM9000_NCR, (0x02 | NCR_RST)); // soft rst
?do{dm9000_delay_ms(25);}while(dm9000_io_read(DM9000_NCR) & 1); // wait for soft rst over
?dm9000_io_write(DM9000_NCR,0);dm9000_io_write(DM9000_NCR, (0x02 | NCR_RST)); // soft rst again
?do{dm9000_delay_ms(25);}while (dm9000_io_read(DM9000_NCR) & 1);
}
?
?
/* Read a word from phyxcer */
rt_inline rt_uint16_t dm9000_phy_read(rt_uint16_t reg) {rt_uint16_t val;
?/* Fill the phyxcer register into REG_0C */dm9000_io_write(DM9000_EPAR, DM9000_PHY | reg);dm9000_io_write(DM9000_EPCR, 0x0C); /* Issue phyxcer read command */
?dm9000_delay_ms(100); ? ? ? /* Wait read complete */
?dm9000_io_write(DM9000_EPCR, 0x00); /* Clear phyxcer read command */val = (dm9000_io_read(DM9000_EPDRH) << 8) | dm9000_io_read(DM9000_EPDRL);
?return val;
}
?
/* Write a word to phyxcer */
rt_inline void dm9000_phy_write(rt_uint16_t reg, rt_uint16_t value)
{/* Fill the phyxcer register into REG_0C */dm9000_io_write(DM9000_EPAR, DM9000_PHY | reg);
?/* Fill the written data into REG_0D & REG_0E */dm9000_io_write(DM9000_EPDRL, (value & 0xFF));dm9000_io_write(DM9000_EPDRH, ((value >> 8) & 0xFF));dm9000_io_write(DM9000_EPCR, 0x0A); /* Issue phyxcer write command */
?dm9000_delay_ms(500); ? ? ? /* Wait write complete */
?dm9000_io_write(DM9000_EPCR, 0x00); /* Clear phyxcer write command */
}
?
/* Set PHY operationg mode */
rt_inline void dm9000_phy_mode_set(rt_uint8_t mode)
{rt_uint16_t phy_BMCR, phy_ANAR;switch(mode){case DM9000_10MHD:phy_BMCR = 0X0000;phy_ANAR = 0X21;break;case DM9000_10MFD:phy_BMCR = 0X0100;phy_ANAR = 0X41;break;case DM9000_100MHD:phy_BMCR = 0X2000;phy_ANAR = 0X81;break;case DM9000_100MFD:phy_BMCR = 0X2100;phy_ANAR = 0X101;break;case DM9000_AUTO:phy_BMCR = 0X1000;phy_ANAR = 0X01E1;break;}
?dm9000_phy_write(DM9000_PHY_BMCR, phy_BMCR);dm9000_phy_write(DM9000_PHY_ANAR, phy_ANAR); /* Set PHY media mode */
?dm9000_io_write(DM9000_GPCR, 0x01); /* Let GPIO0 output */dm9000_io_write(DM9000_GPR, 0X00); ?/* enable PHY */
}
?
/* interrupt service routine */
void rt_dm9000_isr(void *arg)
{rt_uint16_t int_status;rt_uint16_t last_io;
// ? rt_uint32_t eint_pend;
?last_io = DM9000_IO;
?/* Disable all interrupts */dm9000_io_write(DM9000_IMR, IMR_PAR);
?/* Got DM9000 interrupt status */int_status = dm9000_io_read(DM9000_ISR); ? ?/* Got ISR */dm9000_io_write(DM9000_ISR, int_status); ? ?/* Clear ISR status */
?DM9000_TRACE("dm9000 isr: int status %04x\n", int_status);
?/* receive overflow */if (int_status & ISR_ROS){LOG_W("overflow, ISR:%02x", int_status);}
?if (int_status & ISR_ROOS){LOG_W("overflow counter overflow, ISR:%02x", int_status);}
?/* Received the coming packet */if (int_status & ISR_PRS){/* a frame has been received */eth_device_ready(&(dm9000_device.parent));dm_irq_cnt ++;}
?/* Transmit Interrupt check */if (int_status & ISR_PTS){/* clear int_status */dm9000_io_write(DM9000_ISR, ISR_PTS);
?/* transmit done */int tx_status = dm9000_io_read(DM9000_NSR); /* Got TX status */
?if (tx_status & (NSR_TX2END | NSR_TX1END)){dm9000_device.packet_cnt --;if (dm9000_device.packet_cnt > 0){DM9000_TRACE("dm9000 isr: tx second packet\n");
?/* transmit packet II *//* Set TX length to DM9000 */dm9000_io_write(DM9000_TXPLL, dm9000_device.queue_packet_len & 0xff);dm9000_io_write(DM9000_TXPLH, (dm9000_device.queue_packet_len >> 8) & 0xff);
?/* Issue TX polling command */dm9000_io_write(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */}
?/* One packet sent complete *//* clear tx isr */if (sem_ack.value != 0) {LOG_W("isr: trying to release sem_ack while its value > 0 / failed");} else {rt_sem_release(&sem_ack);}}}
?/* Re-enable interrupt mask */dm9000_io_write(DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM | ISR_ROS | ISR_ROOS);
?DM9000_IO = last_io;
}
?
static void dm9000_softrst_wait(rt_uint32_t ms)
{dm9000_io_write(DM9000_NCR, NCR_RST);do{rt_thread_mdelay(ms);} while (dm9000_io_read(DM9000_NCR) & 1); /* wait for soft rst over */
?/* initialize regs */
?/* GPIO0 on pre-activate PHY */dm9000_io_write(DM9000_GPR, 0x00); ? ? ? ? ? ? ?/* REG_1F bit0 activate phyxcer */dm9000_io_write(DM9000_GPCR, GPCR_GEP_CNTL); ? ?/* Let GPIO0 output */dm9000_io_write(DM9000_GPR, 0x00); ? ? ? ? ? ? ? /* Enable PHY */
?/* Set PHY */dm9000_phy_mode_set(dm9000_device.mode);
?/* Program operating register */dm9000_io_write(DM9000_NCR, 0x0); ? /* only intern phy supported by now */dm9000_io_write(DM9000_TCR, 0); ? ? /* TX Polling clear */dm9000_io_write(DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */dm9000_io_write(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8)); ?/* Flow Control : High/Low Water */dm9000_io_write(DM9000_FCR, 0x0); ? /* SH FIXME: This looks strange! Flow Control */dm9000_io_write(DM9000_SMCR, 0); ? ?/* Special Mode */dm9000_io_write(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); ?/* clear TX status */dm9000_io_write(DM9000_ISR, 0x0f); ?/* Clear interrupt status */dm9000_io_write(DM9000_TCR2, 0x80); /* Switch LED to mode 1 */
?/* Activate DM9000 */dm9000_io_write(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */dm9000_io_write(DM9000_IMR, IMR_PAR);
}
?
/* RT-Thread Device Interface */
/* initialize the interface */
static rt_err_t rt_dm9000_init(rt_device_t dev)
{LOG_I("Driver dm9000 init / start");int i, oft, lnk;rt_uint32_t dm9000_id;
?/* RESET device */dm9000_reset();dm9000_delay_ms(100);
?/* identfy DM9000 */dm9000_id = dm9000_get_device_id();LOG_I("dm9000 id: 0x%x", dm9000_id);if (dm9000_id != DM9000_ID) {LOG_E("dm9000 id error");return -RT_ERROR;}
?/* set mac address */for (i = 0, oft = DM9000_PAR; i < 6; ++i, ++oft)dm9000_io_write(oft, dm9000_device.dev_addr[i]);/* set multicast address */for (i = 0, oft = DM9000_MAR; i < 8; ++i, ++oft)dm9000_io_write(oft, 0xff);
?dm9000_softrst_wait(25); /* init regs here */
?if (dm9000_device.mode == DM9000_AUTO){i = 0;while (!(dm9000_phy_read(1) & 0x20)){/* autonegation complete bit */rt_thread_delay( RT_TICK_PER_SECOND/10 );i++;if (i > 30 ) /* wait 3s */{LOG_E("could not establish link");return 0;}}}
?/* send a notify */eth_device_linkchange(&dm9000_device.parent, RT_TRUE);
?/* see what we've got */lnk = dm9000_phy_read(17) >> 12;switch (lnk){case 1:LOG_I("10M half duplex ");break;case 2:LOG_I("10M full duplex ");break;case 4:LOG_I("100M half duplex ");break;case 8:LOG_I("100M full duplex ");break;default:LOG_I("unknown: %d ", lnk);break;}
?/* Enable TX/RX interrupt mask */dm9000_io_write(DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM | ISR_ROS | ISR_ROOS);
?LOG_I("Driver dm9000 init / end");dm9000_device.init_complete = 1;return RT_EOK;
}
?
static rt_err_t rt_dm9000_open(rt_device_t dev, rt_uint16_t oflag)
{return RT_EOK;
}
?
static rt_err_t rt_dm9000_close(rt_device_t dev)
{/* RESET devie */dm9000_phy_write(0, 0x8000); ? ?/* PHY RESET */dm9000_io_write(DM9000_GPR, 0x01); ?/* Power-Down PHY */dm9000_io_write(DM9000_IMR, 0x80); ?/* Disable all interrupt */dm9000_io_write(DM9000_RCR, 0x00); ?/* Disable RX */
?return RT_EOK;
}
?
static rt_size_t rt_dm9000_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{rt_set_errno(-RT_ENOSYS);return 0;
}
?
static rt_size_t rt_dm9000_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{rt_set_errno(-RT_ENOSYS);return 0;
}
?
static rt_err_t rt_dm9000_control(rt_device_t dev, int cmd, void *args)
{switch (cmd){case NIOCTL_GADDR:/* get mac address */if (args) rt_memcpy(args, dm9000_device.dev_addr, 6);else return -RT_ERROR;break;
?default :break;}
?return RT_EOK;
}
?
/* ethernet device interface */
/* transmit packet. */
rt_err_t rt_dm9000_tx( rt_device_t dev, struct pbuf* p)
{
// ? LOG_D("enter rt_dm9000_tx, p->tot_len: %d\n", p->tot_len);DM9000_TRACE("rt_dm9000_tx: %d\n", p->tot_len);
?/* lock DM9000 device */rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
?/* disable dm9000a interrupt */dm9000_io_write(DM9000_IMR, IMR_PAR);
?/* Move data to DM9000 TX RAM */// DM9000_outb(DM9000_IO_BASE, DM9000_MWCMD);DM9000_IO = DM9000_MWCMD;
?{/* q traverses through linked list of pbuf's* This list MUST consist of a single packet ONLY */struct pbuf *q;rt_uint16_t pbuf_index = 0;rt_uint8_t word[2], word_index = 0;
?q = p;/* Write data into dm9000a, two bytes at a time* Handling pbuf's with odd number of bytes correctly* No attempt to optimize for speed has been made */while (q){if (pbuf_index < q->len){word[word_index++] = ((u8_t*)q->payload)[pbuf_index++];if (word_index == 2){// DM9000_outw(DM9000_DATA_BASE, (word[1] << 8) | word[0]);DM9000_DATA = (word[1] << 8) | word[0]; // write two bytes to DM9000_DATAword_index = 0;}}else{q = q->next;pbuf_index = 0;}}/* One byte could still be unsent */if (word_index == 1){// DM9000_outw(DM9000_DATA_BASE, word[0]);DM9000_DATA = word[0]; // write one byte to DM9000_DATA}}
?
// ? /* Set TX length to DM9000 */
// ? dm9000_io_write(DM9000_TXPLL, p->tot_len & 0xff);
// ? dm9000_io_write(DM9000_TXPLH, (p->tot_len >> 8) & 0xff);
//
// ? /* Issue TX polling command */
// ? dm9000_io_write(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
?if (dm9000_device.packet_cnt == 0){DM9000_TRACE("dm9000 tx: first packet\n");
?dm9000_device.packet_cnt ++;/* Set TX length to DM9000 */dm9000_io_write(DM9000_TXPLL, p->tot_len & 0xff);dm9000_io_write(DM9000_TXPLH, (p->tot_len >> 8) & 0xff);
?/* Issue TX polling command */dm9000_io_write(DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */}else{DM9000_TRACE("dm9000 tx: second packet\n");
?dm9000_device.packet_cnt ++;dm9000_device.queue_packet_len = p->tot_len;}
?/* enable dm9000a all interrupt */dm9000_io_write(DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM | ISR_ROS | ISR_ROOS);
?/* unlock DM9000 device */rt_sem_release(&sem_lock);
?/* wait ack */rt_sem_take(&sem_ack, RT_WAITING_FOREVER);
?DM9000_TRACE("rt_dm9000_tx done\n");
?return RT_EOK;
}
?
/* reception packet. */
struct pbuf *rt_dm9000_rx(rt_device_t dev)
{struct pbuf* p;rt_uint32_t rx_ready; /* first rx byte */rt_uint16_t rx_status, rx_len;rt_uint16_t* data;rt_uint8_t dummy_u8;rt_uint16_t dummy_u16; // used for dummyrt_int32_t len;
?/* init p pointer */p = RT_NULL;
?/* lock DM9000 device */rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
?/* disable dm9000a interrupt */dm9000_io_write(DM9000_IMR, IMR_PAR);
?/* Check packet ready or not */// dm9000_io_read(DM9000_MRRH); // 讀取這兩個寄存器// dm9000_io_read(DM9000_MRRL);dm9000_io_read(DM9000_MRCMDX); ? ? ? ? ? ? ?/* Dummy read */// rx_ready = DM9000_inb(DM9000_DATA_BASE); ? ? /* Got most updated data */rx_ready = (u8)DM9000_DATA; ? ? ?/* Got most updated data */if (rx_ready == 0x01){/* A packet ready now & Get status/length */// DM9000_outb(DM9000_IO_BASE, DM9000_MRCMD);// rx_status = DM9000_inw(DM9000_DATA_BASE) & 0xff00;// rx_len = DM9000_inw(DM9000_DATA_BASE);
?DM9000_IO = DM9000_MRCMD;rx_status = DM9000_DATA & 0xff00;rx_len = DM9000_DATA;
?DM9000_TRACE("dm9000 rx: status %04x len %d\n", rx_status, rx_len);
?/* error handle */if ((rx_status & 0xbf00) || (rx_len < 0x40) || (rx_len > DM9000_PKT_MAX)){LOG_E("rx error: status %04x, rx_len: %d", rx_status, rx_len);
?if (rx_status & 0x100){LOG_E("rx fifo error");}if (rx_status & 0x200){LOG_E("rx crc error");}if (rx_status & 0x8000){LOG_E("rx length error");}if (rx_len > DM9000_PKT_MAX){LOG_E("rx length too big");}
?/* software-reset and re-init */dm9000_softrst_wait(25);
?/* it issues an error, release pbuf */if (p != RT_NULL)pbuf_free(p);p = RT_NULL;goto _rx_end;}
?/* allocate buffer */// p = pbuf_alloc(PBUF_LINK, rx_len, PBUF_RAM);rx_len -= 4; // remove 4B CRCp = pbuf_alloc(PBUF_RAW, rx_len, PBUF_POOL);if (p != RT_NULL){// RT_ASSERT(p->type == PBUF_RAM); /* set PBUF_RAM above */// if (p->type == PBUF_RAM) {/* p is one large chunk */
// ? ? ? ? ? ? ? int i;
?// RT_ASSERT(p->next == RT_NULL);// RT_ASSERT(p->len == p->tot_len);
?data = (rt_uint16_t*)p->payload;len = p->len;
?while (len > 1) {// *data = DM9000_inw(DM9000_DATA_BASE);*data = DM9000_DATA;data++;len -= 2;}
?/* just read a byte, protect memory */if (len == 1) {// dummy_u8 = DM9000_inb(DM9000_DATA_BASE);dummy_u8 = (u8)DM9000_DATA;((rt_uint8_t*)p->payload)[p->len - 1] = dummy_u8;}
?dummy_u16 = DM9000_DATA;dummy_u16 = DM9000_DATA;
?// } else { /* p is not one large chunk */// ? ? struct pbuf* q;// ? ? rt_int32_t len;
?// ? ? for (q = p; q != RT_NULL; q= q->next)// ? ? {// ? ? ? ? data = (rt_uint16_t*)q->payload;// ? ? ? ? len = q->len;
?// ? ? ? ? while (len > 0)// ? ? ? ? {// ? ? ? ? ? ? *data = DM9000_inw(DM9000_DATA_BASE);// ? ? ? ? ? ? data ++;// ? ? ? ? ? ? len -= 2;// ? ? ? ? }// ? ? }// }}else /* pbuf allocate failed */{LOG_E("dm9000 rx: no pbuf, rx_len:%d", rx_len);len = rx_len;
?/* no pbuf, discard data from DM9000 */while (len > 1){// dummy_u16 = DM9000_inw(DM9000_DATA_BASE); /* dummy read 2 bytes */dummy_u16 = DM9000_DATA; /* dummy read 2 bytes */len -= 2;}
?/* len == 1, if remaining 1 byte not read */if (len == 1){// dummy_u8 = DM9000_inb(DM9000_DATA_BASE); /* dummy read 1 byte */dummy_u8 = DM9000_DATA;}}}else if (rx_ready > 0x01) /* error, stop interface and wait to reset */{LOG_E("dm9000 rx: rx error, stop device rx_ready:%d", rx_ready);
?dm9000_io_write(DM9000_ISR, 0x80); ?/* Stop INT request */dm9000_io_write(DM9000_ISR, 0x0F); ?/* Clear ISR status */dm9000_io_write(DM9000_RCR, 0x00); ?/* Stop Rx Function */
?dm9000_softrst_wait(5); /* software-reset and re-init */goto _rx_end;}/*else rx_ready == 0x00, no message should be read */
?
_rx_end:
?/* clear packet received latch status */dm9000_io_write(DM9000_ISR, ISR_PRS);
?/* restore receive interrupt */dm9000_io_write(DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM | ISR_ROS | ISR_ROOS);
?/* unlock DM9000 device */rt_sem_release(&sem_lock);
?return p;
}
?
static uint32_t FMC_Initialized = 0;
?
static void DM9000_GPIO_Init(void)
{/* USER CODE BEGIN FMC_MspInit 0 */
?__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOD_CLK_ENABLE();__HAL_RCC_GPIOE_CLK_ENABLE();__HAL_RCC_GPIOF_CLK_ENABLE();/* USER CODE END FMC_MspInit 0 */GPIO_InitTypeDef GPIO_InitStruct = {0};if (FMC_Initialized){return;}FMC_Initialized = 1;
?/* Peripheral clock enable */__HAL_RCC_FMC_CLK_ENABLE();
?/** FMC GPIO ConfigurationPF0 ? ------> FMC_A0PE7 ? ------> FMC_D4PE8 ? ------> FMC_D5PE9 ? ------> FMC_D6PE10 ? ------> FMC_D7PE11 ? ------> FMC_D8PE12 ? ------> FMC_D9PE13 ? ------> FMC_D10PE14 ? ------> FMC_D11PE15 ? ------> FMC_D12PD8 ? ------> FMC_D13PD9 ? ------> FMC_D14PD10 ? ------> FMC_D15PD14 ? ------> FMC_D0PD15 ? ------> FMC_D1PC7 ? ------> FMC_NE1PD0 ? ------> FMC_D2PD1 ? ------> FMC_D3PD4 ? ------> FMC_NOEPD5 ? ------> FMC_NWE*//* GPIO_InitStruct */GPIO_InitStruct.Pin = GPIO_PIN_0;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
?HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
?/* GPIO_InitStruct */GPIO_InitStruct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
?HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
?/* GPIO_InitStruct */GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15 | GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
?HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
?/* GPIO_InitStruct */GPIO_InitStruct.Pin = GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF9_FMC;
?HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
?/* USER CODE BEGIN FMC_MspInit 1 */
?/* USER CODE END FMC_MspInit 1 */
}
?
SRAM_HandleTypeDef hsram1;
?
/* FMC initialization function */
void DM9000_FMC_Config(void)
{/* USER CODE BEGIN FMC_Init 0 */
?/* USER CODE END FMC_Init 0 */
?FMC_NORSRAM_TimingTypeDef Timing = {0};
?/* USER CODE BEGIN FMC_Init 1 */DM9000_GPIO_Init();/* USER CODE END FMC_Init 1 */
?hsram1.Instance = FMC_NORSRAM_DEVICE;hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;/* hsram1.Init */hsram1.Init.NSBank ? ? ? ? ? ? ?= FMC_NORSRAM_BANK1;hsram1.Init.DataAddressMux ? ? ?= FMC_DATA_ADDRESS_MUX_DISABLE;hsram1.Init.MemoryType ? ? ? ? ?= FMC_MEMORY_TYPE_SRAM;hsram1.Init.MemoryDataWidth ? ? = FMC_NORSRAM_MEM_BUS_WIDTH_16; hsram1.Init.BurstAccessMode ? ? = FMC_BURST_ACCESS_MODE_DISABLE;hsram1.Init.WaitSignalPolarity ?= FMC_WAIT_SIGNAL_POLARITY_LOW;hsram1.Init.WaitSignalActive ? ?= FMC_WAIT_TIMING_BEFORE_WS;hsram1.Init.WriteOperation ? ? ?= FMC_WRITE_OPERATION_ENABLE;hsram1.Init.WaitSignal ? ? ? ? ?= FMC_WAIT_SIGNAL_DISABLE;hsram1.Init.ExtendedMode ? ? ? ?= FMC_EXTENDED_MODE_DISABLE;hsram1.Init.AsynchronousWait ? ?= FMC_ASYNCHRONOUS_WAIT_DISABLE;hsram1.Init.WriteBurst ? ? ? ? ?= FMC_WRITE_BURST_DISABLE;hsram1.Init.ContinuousClock ? ? = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;hsram1.Init.WriteFifo ? ? ? ? ? = FMC_WRITE_FIFO_DISABLE;hsram1.Init.PageSize ? ? ? ? ? ?= FMC_PAGE_SIZE_NONE;
?
?// 使用的HCLK 120M = 8.3ns/* Timing */Timing.AddressSetupTime ? ? ? ? = 10; ? ? ? // DM9000手冊建議地址建立時間為大于80ns F0寄存器Timing.AddressHoldTime ? ? ? ? ?= 0; ? ? ? ?// 模式A沒用上Timing.DataSetupTime ? ? ? ? ? ?= 2; ? ? ? ?// DM9000手冊建議數據建立時間為大于10ns ?Timing.BusTurnAroundDuration ? ?= 2; ? ? ? ?// 片選信號,高脈寬Timing.CLKDivision ? ? ? ? ? ? ?= 0; ? ? ? ?// 模式A沒用上Timing.DataLatency ? ? ? ? ? ? ?= 0; ? ? ? ?// 模式A沒用上Timing.AccessMode ? ? ? ? ? ? ? = FMC_ACCESS_MODE_A;if (HAL_SRAM_Init(&hsram1, &Timing, NULL) != HAL_OK){Error_Handler();}
?/* USER CODE BEGIN FMC_Init 2 *///設置引腳為輸入模式(下降沿觸發)rt_pin_mode(PIN_IRQ, PIN_MODE_INPUT);rt_pin_attach_irq(PIN_IRQ, PIN_IRQ_MODE_FALLING, rt_dm9000_isr, RT_NULL);rt_pin_irq_enable(PIN_IRQ, PIN_IRQ_ENABLE);/* USER CODE END FMC_Init 2 */
}
?
// 獲取DM9000的連接速度和雙工模式
// 返回值: 0,100M半雙工
// ? ? ? ? ? 1,100M全雙工
// ? ? ? ? ? 2,10M半雙工
// ? ? ? ? ? 3,10M全雙工
// ? ? ? ? ? 0XFF,連接失敗!
u8 DM9000_Get_SpeedAndDuplex(void)
{u8 temp;u8 i = 0;if (dm9000_device.mode == DM9000_AUTO) // 如果開啟了自動協商模式一定要等待協商完成{while (!(dm9000_phy_read (0X01) & 0X0020)) // 等待自動協商完成{dm9000_delay_ms(10);i++;if (i > 100)return 0XFF; // 自動協商失敗}}else // 自定義模式,一定要等待連接成功{while (!(dm9000_io_read(DM9000_NSR) & 0X40)) // 等待連接成功{dm9000_delay_ms(10);i++;if (i > 100)return 0XFF; // 連接失敗}}temp = ((dm9000_io_read(DM9000_NSR) >> 6) & 0X02); ?// 獲取DM9000的連接速度temp |= ((dm9000_io_read(DM9000_NCR) >> 3) & 0X01); // 獲取DM9000的雙工狀態return temp;
}
?
static void phy_linkchange()
{static rt_uint8_t phy_speed = 0;rt_uint8_t temp;
?temp = DM9000_Get_SpeedAndDuplex(); // 獲取DM9000的連接速度和雙工狀態if (temp != 0XFF) ? ? ? ? ? ? ? ? ? // 連接成功,通過串口顯示連接速度和雙工狀態{if(phy_speed != temp) // 如果連接狀態發生變化{phy_speed = temp;LOG_D("DM9000 Speed:%dMbps,Duplex:%s duplex mode", (temp & 0x02) ? 10 : 100, (temp & 0x01) ? "Full" : "Half");eth_device_linkchange(&dm9000_device.parent, RT_TRUE);}else{return; // 沒有變化,直接返回}}else{LOG_D("link down");phy_speed = 0;eth_device_linkchange(&dm9000_device.parent, RT_FALSE);}
}
?
void phy_state_check(void *arg)
{LOG_D("phy_state_check started");while(1){if (dm9000_device.init_complete == 1) phy_linkchange();rt_thread_mdelay(1000); // 每隔1秒檢測一次PHY狀態}
}
?
int rt_hw_dm9000_init(void) {/* stm32 hal lib dm9000 specific init */rt_uint32_t temp;DM9000_FMC_Config(); // FMC配置
?/* general dm9000 init */rt_sem_init(&sem_ack, "tx_ack", 0, RT_IPC_FLAG_FIFO); ? // 同步信號量,初始為0,發送tx后等待中斷釋放信號量表示tx完成rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO); // 互斥信號量,初始為1,用于保護tx和rx過程不沖突dm9000_device.type ?= TYPE_DM9000A;dm9000_device.mode ?= DM9000_AUTO;dm9000_device.packet_cnt = 0;dm9000_device.queue_packet_len = 0;
?/** SRAM Tx/Rx pointer automatically return to start address,* Packet Transmitted, Packet Received*/// temp = *(volatile rt_uint16_t*)(0x1FFFF7E8); ? ? ? ? ? ? ? //獲取STM32的唯一ID的前24位作為MAC地址后三字節temp = HAL_GetUIDw0();dm9000_device.dev_addr[0] = 0x02;dm9000_device.dev_addr[1] = 0x00;dm9000_device.dev_addr[2] = 0x00;dm9000_device.dev_addr[3] = (temp >> 16) & 0xFF; ? ?//低三字節用STM32的唯一IDdm9000_device.dev_addr[4] = (temp >> 8) & 0xFFF;dm9000_device.dev_addr[5] = temp ?&0xFF;
?dm9000_device.parent.parent.init ? ? ? = rt_dm9000_init;dm9000_device.parent.parent.open ? ? ? = rt_dm9000_open;dm9000_device.parent.parent.close ? ? ?= rt_dm9000_close;dm9000_device.parent.parent.read ? ? ? = rt_dm9000_read;dm9000_device.parent.parent.write ? ? ?= rt_dm9000_write;dm9000_device.parent.parent.control ? ?= rt_dm9000_control;dm9000_device.parent.parent.user_data ?= RT_NULL;
?dm9000_device.parent.eth_rx ?= rt_dm9000_rx;dm9000_device.parent.eth_tx ?= rt_dm9000_tx;eth_device_init(&(dm9000_device.parent), "e0");
?rt_thread_t tid;tid = rt_thread_create("phy", phy_state_check, RT_NULL, 512, RT_THREAD_PRIORITY_MAX - 2, 2);rt_thread_startup(tid);
?return RT_EOK;
}
?
INIT_DEVICE_EXPORT(rt_hw_dm9000_init);
?
void dm9000a(void)
{rt_kprintf("\n");rt_kprintf("NCR ? (%02X): %02x\n", DM9000_NCR, ? dm9000_io_read(DM9000_NCR));rt_kprintf("NSR ? (%02X): %02x\n", DM9000_NSR, ? dm9000_io_read(DM9000_NSR));rt_kprintf("TCR ? (%02X): %02x\n", DM9000_TCR, ? dm9000_io_read(DM9000_TCR));rt_kprintf("TSRI (%02X): %02x\n", DM9000_TSR1, ?dm9000_io_read(DM9000_TSR1));rt_kprintf("TSRII (%02X): %02x\n", DM9000_TSR2, ?dm9000_io_read(DM9000_TSR2));rt_kprintf("RCR ? (%02X): %02x\n", DM9000_RCR, ? dm9000_io_read(DM9000_RCR));rt_kprintf("RSR ? (%02X): %02x\n", DM9000_RSR, ? dm9000_io_read(DM9000_RSR));rt_kprintf("ORCR (%02X): %02x\n", DM9000_ROCR, ?dm9000_io_read(DM9000_ROCR));rt_kprintf("CRR ? (%02X): %02x\n", DM9000_CHIPR, dm9000_io_read(DM9000_CHIPR));rt_kprintf("CSCR (%02X): %02x\n", DM9000_CSCR, ?dm9000_io_read(DM9000_CSCR));rt_kprintf("RCSSR (%02X): %02x\n", DM9000_RCSSR, dm9000_io_read(DM9000_RCSSR));rt_kprintf("ISR ? (%02X): %02x\n", DM9000_ISR, ? dm9000_io_read(DM9000_ISR));rt_kprintf("IMR ? (%02X): %02x\n", DM9000_IMR, ? dm9000_io_read(DM9000_IMR));rt_kprintf("pin_G_6: %d\n", rt_pin_read(GET_PIN(G, 6)));rt_kprintf("\n");
}
?
#ifdef RT_USING_FINSH
#include <finsh.h>
MSH_CMD_EXPORT(dm9000a, dm9000a register dump);
#endif
?