mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-02-01 11:20:25 +08:00
add EMAC driver.
This commit is contained in:
parent
a8106442e1
commit
ff4fcd5b56
@ -14,7 +14,7 @@ LR_IROM1 (0) (1024 * 128)
|
|||||||
}
|
}
|
||||||
|
|
||||||
; RW data
|
; RW data
|
||||||
RW_IRAM1 0x20000000 (1024 * 64)
|
RW_IRAM1 0x20000000 (1024 * 48)
|
||||||
{
|
{
|
||||||
.ANY (+RW +ZI)
|
.ANY (+RW +ZI)
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,14 @@
|
|||||||
void rt_init_thread_entry(void* parameter)
|
void rt_init_thread_entry(void* parameter)
|
||||||
{
|
{
|
||||||
rt_components_init();
|
rt_components_init();
|
||||||
|
|
||||||
|
rt_kprintf("new");
|
||||||
|
|
||||||
|
#ifdef RT_USING_LWIP
|
||||||
|
cme_m7_eth_init();
|
||||||
|
|
||||||
|
//set_if("e0", "192.168.3.99", "192.168.1.1", "255.255.255.0");
|
||||||
|
#endif /* RT_USING_LWIP */
|
||||||
}
|
}
|
||||||
|
|
||||||
int rt_application_init()
|
int rt_application_init()
|
||||||
@ -39,10 +47,4 @@ int rt_application_init()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NMI_Handler(void)
|
|
||||||
{
|
|
||||||
rt_kprintf("NMI_Handler\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
@ -3,7 +3,16 @@ Import('rtconfig')
|
|||||||
from building import *
|
from building import *
|
||||||
|
|
||||||
cwd = os.path.join(str(Dir('#')), 'drivers')
|
cwd = os.path.join(str(Dir('#')), 'drivers')
|
||||||
src = Glob('*.c')
|
|
||||||
|
src = ['board.c']
|
||||||
|
|
||||||
|
# add uart driver.
|
||||||
|
src += ['uart.c']
|
||||||
|
|
||||||
|
# add EMAC driver for Lwip.
|
||||||
|
if GetDepend('RT_USING_LWIP') == True:
|
||||||
|
src += ['emac.c', 'app_phy.c']
|
||||||
|
|
||||||
CPPPATH = [cwd]
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
|
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||||
|
121
bsp/CME_M7/drivers/app_phy.c
Normal file
121
bsp/CME_M7/drivers/app_phy.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "app_phy.h"
|
||||||
|
|
||||||
|
#define PHY_BASE_ADDR 0x7
|
||||||
|
|
||||||
|
#define PHY_REG_CONTROL 0x0
|
||||||
|
#define PHY_REG_STATUS 0x1
|
||||||
|
#define PHY_REG_ANE 0x6
|
||||||
|
#define PHY_REG_SPEC_STATUS 0x11
|
||||||
|
#define PHY_REG_EXTEND_STATUS 0x1B
|
||||||
|
|
||||||
|
#define PHY_BIT_CONTROL_RESET 0x8000 /*!< Control reg : reset */
|
||||||
|
#define PHY_BIT_CONTROL_ANEN 0x1000 /*!< Control reg : auto-negotiation enable */
|
||||||
|
#define PHY_BIT_CONTROL_RSAN 0x0200 /*!< Control reg : auto-negotiation restart */
|
||||||
|
|
||||||
|
#define PHY_BIT_STATUS_ANC 0x0020 /*!< Status reg : auto-negotiation complete */
|
||||||
|
#define PHY_BIT_STATUS_LINK 0x0004 /*!< Status reg : link is up */
|
||||||
|
|
||||||
|
#define PHY_BIT_ANE_LPAN 0x0001 /*!< ANE reg : link partner can auto-neg */
|
||||||
|
|
||||||
|
#define PHY_BIT_SPEED 0xC000 /*!< specific status reg : speed */
|
||||||
|
#define PHY_BIT_DUPLEX 0x2000 /*!< specific status reg : duplex */
|
||||||
|
|
||||||
|
#define PHY_BIT_AUTO_MEDIA_DISABLE 0x8000 /*!< extended status reg : auto media select disable */
|
||||||
|
#define PHY_BIT_AUTO_MEDIA_REG_DISABLE 0x0200 /*!< extended status reg : auto media register select disable */
|
||||||
|
|
||||||
|
void phy_Reset() {
|
||||||
|
ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_CONTROL, PHY_BIT_CONTROL_RESET);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_CONTROL);
|
||||||
|
if ((ret & PHY_BIT_CONTROL_RESET) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void phy_AutoMediaSelect() {
|
||||||
|
uint32_t data;
|
||||||
|
|
||||||
|
// auto media and auto media register selection
|
||||||
|
data = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_EXTEND_STATUS);
|
||||||
|
data &= ~PHY_BIT_AUTO_MEDIA_DISABLE;
|
||||||
|
data &= ~PHY_BIT_AUTO_MEDIA_REG_DISABLE;
|
||||||
|
ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_EXTEND_STATUS, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void phy_AutoNeg() {
|
||||||
|
uint32_t data;
|
||||||
|
|
||||||
|
data = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_CONTROL);
|
||||||
|
data |= (PHY_BIT_CONTROL_ANEN | PHY_BIT_CONTROL_RSAN);
|
||||||
|
ETH_PhyWrite(PHY_BASE_ADDR, PHY_REG_CONTROL, data);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_STATUS);
|
||||||
|
if ((ret & PHY_BIT_STATUS_ANC) == PHY_BIT_STATUS_ANC) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL phy_IsLink() {
|
||||||
|
uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_STATUS);
|
||||||
|
return (ret & PHY_BIT_STATUS_LINK) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL phy_PartnerCanAutoNeg() {
|
||||||
|
uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_ANE);
|
||||||
|
return (ret & PHY_BIT_ANE_LPAN) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t phy_GetSpeed() {
|
||||||
|
uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_SPEC_STATUS);
|
||||||
|
return ((ret & PHY_BIT_SPEED) >> 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t phy_GetDuplex() {
|
||||||
|
uint32_t ret = ETH_PhyRead(PHY_BASE_ADDR, PHY_REG_SPEC_STATUS);
|
||||||
|
return ((ret & PHY_BIT_DUPLEX) >> 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL phy_Init() {
|
||||||
|
phy_AutoMediaSelect();
|
||||||
|
phy_AutoNeg();
|
||||||
|
|
||||||
|
if (!phy_PartnerCanAutoNeg()) {
|
||||||
|
printf("Warning:: PHY's partner can't do auto-negotiation\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!phy_IsLink()) {
|
||||||
|
printf("link is down\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
uint32_t speed = phy_GetSpeed();
|
||||||
|
if (speed == PHY_SPEED_10) {
|
||||||
|
speed = 10;
|
||||||
|
} else if (speed == PHY_SPEED_100) {
|
||||||
|
speed = 100;
|
||||||
|
} else if (speed == PHY_SPEED_1000) {
|
||||||
|
speed = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("PHY runs in %dM speed %s duplex\n",
|
||||||
|
speed, (phy_GetDuplex() == PHY_DUPLEX_HALF) ? "half" : "full");
|
||||||
|
}
|
||||||
|
|
||||||
|
// After auto-negcioation, Mawell PHY need some
|
||||||
|
// time to initial itself.
|
||||||
|
// So we have to delay some time since different
|
||||||
|
// connection way, such as direct wire, hub, switch.
|
||||||
|
// If not to delay, the first several sent frame
|
||||||
|
// may be lost.
|
||||||
|
// Please according to actual environment to tune
|
||||||
|
// this delay.
|
||||||
|
udelay(200000);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
32
bsp/CME_M7/drivers/app_phy.h
Normal file
32
bsp/CME_M7/drivers/app_phy.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef __APP_PHY_H
|
||||||
|
#define __APP_PHY_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cmem7_includes.h"
|
||||||
|
|
||||||
|
#define PHY_SPEED_10 0x0 /*!< SPEED : 10M */
|
||||||
|
#define PHY_SPEED_100 0x1 /*!< SPEED : 100M */
|
||||||
|
#define PHY_SPEED_1000 0x2 /*!< SPEED : 1000M */
|
||||||
|
|
||||||
|
#define PHY_DUPLEX_HALF 0x0 /*!< DUPLEX : half */
|
||||||
|
#define PHY_DUPLEX_FULL 0x1 /*!< DUPLEX : full */
|
||||||
|
|
||||||
|
void phy_Reset(void);
|
||||||
|
void phy_AutoNeg(void);
|
||||||
|
BOOL phy_IsLink(void);
|
||||||
|
BOOL phy_PartnerCanAutoNeg(void);
|
||||||
|
uint32_t phy_GetSpeed(void);
|
||||||
|
uint32_t phy_GetDuplex(void);
|
||||||
|
BOOL phy_Init(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -49,7 +49,10 @@ static void idle_hook(void)
|
|||||||
*/
|
*/
|
||||||
void rt_hw_board_init()
|
void rt_hw_board_init()
|
||||||
{
|
{
|
||||||
rt_thread_idle_sethook(idle_hook);
|
//rt_thread_idle_sethook(idle_hook);
|
||||||
|
|
||||||
|
/* Configure the NVIC Preemption Priority Bits */
|
||||||
|
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
|
||||||
|
|
||||||
SysTick_Config(SYSTEM_CLOCK_FREQ / RT_TICK_PER_SECOND);
|
SysTick_Config(SYSTEM_CLOCK_FREQ / RT_TICK_PER_SECOND);
|
||||||
|
|
||||||
|
457
bsp/CME_M7/drivers/emac.c
Normal file
457
bsp/CME_M7/drivers/emac.c
Normal file
@ -0,0 +1,457 @@
|
|||||||
|
/*
|
||||||
|
* File : emac.c
|
||||||
|
* This file is part of RT-Thread RTOS
|
||||||
|
* COPYRIGHT (C) 2006-2014, RT-Thread Develop Team
|
||||||
|
*
|
||||||
|
* The license and distribution terms for this file may be
|
||||||
|
* found in the file LICENSE in this distribution or at
|
||||||
|
* http://openlab.rt-thread.com/license/LICENSE
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2014-08-29 aozima first implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <netif/ethernetif.h>
|
||||||
|
#include "lwipopts.h"
|
||||||
|
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
#include "app_phy.h"
|
||||||
|
//#include "app_bufferpool.h"
|
||||||
|
//#include "app_bufferqueue.h"
|
||||||
|
|
||||||
|
/* debug option */
|
||||||
|
#define ETH_DEBUG
|
||||||
|
//#define ETH_RX_DUMP
|
||||||
|
//#define ETH_TX_DUMP
|
||||||
|
|
||||||
|
#ifdef ETH_DEBUG
|
||||||
|
#define CME_ETH_PRINTF rt_kprintf
|
||||||
|
#else
|
||||||
|
#define CME_ETH_PRINTF(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_ADDR_LEN 6
|
||||||
|
struct rt_cme_eth
|
||||||
|
{
|
||||||
|
/* inherit from ethernet device */
|
||||||
|
struct eth_device parent;
|
||||||
|
|
||||||
|
/* interface address info. */
|
||||||
|
rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
|
||||||
|
|
||||||
|
uint32_t ETH_Speed;
|
||||||
|
uint32_t ETH_Mode;
|
||||||
|
|
||||||
|
struct rt_semaphore tx_buf_free;
|
||||||
|
struct rt_mutex lock;
|
||||||
|
};
|
||||||
|
static struct rt_cme_eth cme_eth_device;
|
||||||
|
|
||||||
|
#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
|
||||||
|
static void packet_dump(const char * msg, const struct pbuf* p)
|
||||||
|
{
|
||||||
|
const struct pbuf* q;
|
||||||
|
rt_uint32_t i,j;
|
||||||
|
rt_uint8_t *ptr;
|
||||||
|
|
||||||
|
rt_kprintf("%s %d byte\n", msg, p->tot_len);
|
||||||
|
|
||||||
|
i=0;
|
||||||
|
for(q=p; q != RT_NULL; q= q->next)
|
||||||
|
{
|
||||||
|
ptr = q->payload;
|
||||||
|
|
||||||
|
for(j=0; j<q->len; j++)
|
||||||
|
{
|
||||||
|
if( (i%8) == 0 )
|
||||||
|
{
|
||||||
|
rt_kprintf(" ");
|
||||||
|
}
|
||||||
|
if( (i%16) == 0 )
|
||||||
|
{
|
||||||
|
rt_kprintf("\r\n");
|
||||||
|
}
|
||||||
|
rt_kprintf("%02x ",*ptr);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_kprintf("\n\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define packet_dump(...)
|
||||||
|
#endif /* dump */
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
uint32_t rxTotalMemory = 0x2000;
|
||||||
|
uint32_t rxDescNum = 3;
|
||||||
|
uint32_t rxBufSize = 0x400;
|
||||||
|
uint32_t rxBaseAddr = 0x2000C000;// C000-48K
|
||||||
|
uint32_t txBaseAddr = 0x2000E000;// E000-56K
|
||||||
|
uint32_t txTotalMemory = 0x2000;
|
||||||
|
BOOL isRxNoBuf = FALSE;
|
||||||
|
|
||||||
|
#define ETH_MAX_PACKET_SIZE 1520 /* ETH_HEADER + ETH_EXTRA + MAX_ETH_PAYLOAD + ETH_CRC */
|
||||||
|
#define ETH_RXBUFNB 4
|
||||||
|
#define ETH_TXBUFNB 2
|
||||||
|
|
||||||
|
struct eth_rx_buffer
|
||||||
|
{
|
||||||
|
ETH_RX_DESC desc;
|
||||||
|
uint32_t buffer[ETH_MAX_PACKET_SIZE/4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct eth_tx_buffer
|
||||||
|
{
|
||||||
|
ETH_TX_DESC desc;
|
||||||
|
uint32_t buffer[ETH_MAX_PACKET_SIZE/4];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct eth_rx_buffer rx_buffer[ETH_RXBUFNB];
|
||||||
|
static struct eth_tx_buffer tx_buffer[ETH_TXBUFNB];
|
||||||
|
|
||||||
|
static void RxDescChainInit(void)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
// initialize rx descriptor
|
||||||
|
ETH_RX_DESC *desc = &rx_buffer[0].desc;
|
||||||
|
|
||||||
|
for (i = 0; i < ETH_RXBUFNB; i++)
|
||||||
|
{
|
||||||
|
desc->RX_1.RX1_b.SIZE = ETH_MAX_PACKET_SIZE;
|
||||||
|
desc->bufAddr = (uint32_t)rx_buffer[i].buffer;
|
||||||
|
|
||||||
|
if((i+1) == ETH_RXBUFNB)
|
||||||
|
desc->nextDescAddr = (uint32_t)&rx_buffer[0].desc;
|
||||||
|
else
|
||||||
|
desc->nextDescAddr = (uint32_t)&rx_buffer[i+1].desc;
|
||||||
|
|
||||||
|
desc = (ETH_RX_DESC *)desc->nextDescAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ETH_SetRxDescRing(&rx_buffer[0].desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TxDescChainInit(void)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
// initialize tx descriptor
|
||||||
|
ETH_TX_DESC *desc = &tx_buffer[0].desc;
|
||||||
|
|
||||||
|
for (i = 0; i < ETH_TXBUFNB; i++)
|
||||||
|
{
|
||||||
|
desc->TX_1.TX1_b.SIZE = ETH_MAX_PACKET_SIZE;
|
||||||
|
desc->bufAddr = (uint32_t)tx_buffer[i].buffer;
|
||||||
|
|
||||||
|
if((i+1) == ETH_TXBUFNB)
|
||||||
|
desc->nextDescAddr = (uint32_t)&tx_buffer[0].desc;
|
||||||
|
else
|
||||||
|
desc->nextDescAddr = (uint32_t)&tx_buffer[i+1].desc;
|
||||||
|
|
||||||
|
desc = (ETH_TX_DESC *)desc->nextDescAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ETH_SetTxDescRing(&tx_buffer[0].desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* initialize the interface */
|
||||||
|
static rt_err_t rt_cme_eth_init(rt_device_t dev)
|
||||||
|
{
|
||||||
|
struct rt_cme_eth * cme_eth = (struct rt_cme_eth *)dev;
|
||||||
|
|
||||||
|
ETH_InitTypeDef init;
|
||||||
|
ETH_FrameFilter flt;
|
||||||
|
|
||||||
|
init.ETH_Speed = phy_GetSpeed();
|
||||||
|
init.ETH_Duplex = phy_GetDuplex();
|
||||||
|
init.ETH_LinkUp = phy_IsLink();
|
||||||
|
init.ETH_RxEn = TRUE;
|
||||||
|
init.ETH_TxEn = TRUE;
|
||||||
|
init.ETH_ChecksumOffload = FALSE;
|
||||||
|
init.ETH_JumboFrame = FALSE;
|
||||||
|
|
||||||
|
memcpy(init.ETH_MacAddr, cme_eth->dev_addr, sizeof(init.ETH_MacAddr));
|
||||||
|
// init.ETH_MacAddr[0] = 0x00;
|
||||||
|
// init.ETH_MacAddr[1] = 0x1E;
|
||||||
|
// init.ETH_MacAddr[2] = 0xC9;
|
||||||
|
// init.ETH_MacAddr[3] = 0x3B;
|
||||||
|
// init.ETH_MacAddr[4] = 0x11;
|
||||||
|
// init.ETH_MacAddr[5] = 0xF8;
|
||||||
|
|
||||||
|
// Disable broadcast;
|
||||||
|
flt.ETH_BroadcastFilterEnable = FALSE;
|
||||||
|
flt.ETH_OwnFilterEnable = FALSE;
|
||||||
|
flt.ETH_SelfDrop = FALSE;
|
||||||
|
flt.ETH_SourceFilterEnable = FALSE;
|
||||||
|
flt.ETH_SourceDrop = FALSE;
|
||||||
|
|
||||||
|
flt.ETH_SourceMacAddr[0] = 0x00;
|
||||||
|
flt.ETH_SourceMacAddr[1] = 0x1E;
|
||||||
|
flt.ETH_SourceMacAddr[2] = 0xC9;
|
||||||
|
flt.ETH_SourceMacAddr[3] = 0x3B;
|
||||||
|
flt.ETH_SourceMacAddr[4] = 0x11;
|
||||||
|
flt.ETH_SourceMacAddr[5] = 0xF9;
|
||||||
|
|
||||||
|
init.ETH_Filter = &flt;
|
||||||
|
|
||||||
|
if (!phy_Init())
|
||||||
|
{
|
||||||
|
rt_kprintf("phy_Init failed!\n");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ETH_Init(&init))
|
||||||
|
{
|
||||||
|
rt_kprintf("ETH_Init failed!\n");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
RxDescChainInit();
|
||||||
|
TxDescChainInit();
|
||||||
|
|
||||||
|
ETH_EnableInt(ETH_INT_BUS_FATAL_ERROR, TRUE);
|
||||||
|
|
||||||
|
ETH_EnableInt(ETH_INT_RX_COMPLETE_FRAME, TRUE);
|
||||||
|
ETH_EnableInt(ETH_INT_RX_BUF_UNAVAI, TRUE);
|
||||||
|
ETH_EnableInt(ETH_INT_RX_STOP, TRUE);
|
||||||
|
ETH_StartRx();
|
||||||
|
|
||||||
|
ETH_EnableInt(ETH_INT_TX_COMPLETE_FRAME, TRUE);
|
||||||
|
ETH_StartTx();
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t rt_cme_eth_open(rt_device_t dev, rt_uint16_t oflag)
|
||||||
|
{
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_err_t rt_cme_eth_close(rt_device_t dev)
|
||||||
|
{
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rt_size_t rt_cme_eth_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_cme_eth_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_cme_eth_control(rt_device_t dev, rt_uint8_t cmd, void *args)
|
||||||
|
{
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case NIOCTL_GADDR:
|
||||||
|
/* get mac address */
|
||||||
|
if(args) rt_memcpy(args, cme_eth_device.dev_addr, 6);
|
||||||
|
else return -RT_ERROR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ethernet device interface */
|
||||||
|
/* transmit packet. */
|
||||||
|
rt_err_t rt_cme_eth_tx( rt_device_t dev, struct pbuf* p)
|
||||||
|
{
|
||||||
|
rt_err_t result = RT_EOK;
|
||||||
|
ETH_TX_DESC *desc;
|
||||||
|
struct rt_cme_eth * cme_eth = (struct rt_cme_eth *)dev;
|
||||||
|
|
||||||
|
rt_mutex_take(&cme_eth->lock, RT_WAITING_FOREVER);
|
||||||
|
|
||||||
|
#ifdef ETH_TX_DUMP
|
||||||
|
packet_dump("TX dump", p);
|
||||||
|
#endif /* ETH_TX_DUMP */
|
||||||
|
|
||||||
|
/* get free tx buffer */
|
||||||
|
{
|
||||||
|
rt_err_t result;
|
||||||
|
result = rt_sem_take(&cme_eth->tx_buf_free, RT_TICK_PER_SECOND/10);
|
||||||
|
if (result != RT_EOK)
|
||||||
|
{
|
||||||
|
result = -RT_ERROR;
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = ETH_AcquireFreeTxDesc();
|
||||||
|
if(desc == RT_NULL)
|
||||||
|
{
|
||||||
|
CME_ETH_PRINTF("TxDesc not ready!\n");
|
||||||
|
RT_ASSERT(0);
|
||||||
|
result = -RT_ERROR;
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc->TX_0.TX0_b.FS = TRUE;
|
||||||
|
desc->TX_0.TX0_b.LS = TRUE;
|
||||||
|
desc->TX_1.TX1_b.SIZE = p->tot_len;
|
||||||
|
|
||||||
|
pbuf_copy_partial(p, ( void *)(desc->bufAddr), p->tot_len, 0);
|
||||||
|
|
||||||
|
ETH_ReleaseTxDesc(desc);
|
||||||
|
ETH_ResumeTx();
|
||||||
|
|
||||||
|
_exit:
|
||||||
|
rt_mutex_release(&cme_eth->lock);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reception packet. */
|
||||||
|
struct pbuf *rt_cme_eth_rx(rt_device_t dev)
|
||||||
|
{
|
||||||
|
struct pbuf* p = RT_NULL;
|
||||||
|
ETH_RX_DESC *desc;
|
||||||
|
uint32_t framelength;
|
||||||
|
struct rt_cme_eth * cme_eth = (struct rt_cme_eth *)dev;
|
||||||
|
|
||||||
|
rt_mutex_take(&cme_eth->lock, RT_WAITING_FOREVER);
|
||||||
|
|
||||||
|
desc = ETH_AcquireFreeRxDesc();
|
||||||
|
if(desc == RT_NULL)
|
||||||
|
{
|
||||||
|
ETH_EnableInt(ETH_INT_RX_COMPLETE_FRAME, TRUE);
|
||||||
|
ETH_EnableInt(ETH_INT_RX_BUF_UNAVAI, TRUE);
|
||||||
|
ETH_ResumeRx();
|
||||||
|
goto _exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
framelength = desc->RX_0.RX0_b.FL;
|
||||||
|
|
||||||
|
/* allocate buffer */
|
||||||
|
p = pbuf_alloc(PBUF_LINK, framelength, PBUF_RAM);
|
||||||
|
if (p != RT_NULL)
|
||||||
|
{
|
||||||
|
pbuf_take(p, (const void *)(desc->bufAddr), framelength);
|
||||||
|
#ifdef ETH_RX_DUMP
|
||||||
|
packet_dump("RX dump", p);
|
||||||
|
#endif /* ETH_RX_DUMP */
|
||||||
|
}
|
||||||
|
|
||||||
|
ETH_ReleaseRxDesc(desc);
|
||||||
|
|
||||||
|
_exit:
|
||||||
|
rt_mutex_release(&cme_eth->lock);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void NVIC_Configuration(void)
|
||||||
|
{
|
||||||
|
NVIC_InitTypeDef NVIC_InitStructure;
|
||||||
|
|
||||||
|
/* Enable the USARTy Interrupt */
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannel = ETH_INT_IRQn;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelCmd = TRUE;
|
||||||
|
NVIC_Init(&NVIC_InitStructure);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cme_m7_eth_init(void)
|
||||||
|
{
|
||||||
|
// /* PHY RESET: PA4 */
|
||||||
|
// {
|
||||||
|
// GPIO_ResetBits(GPIOA, GPIO_Pin_4);
|
||||||
|
// rt_thread_delay(2);
|
||||||
|
// GPIO_SetBits(GPIOA, GPIO_Pin_4);
|
||||||
|
// rt_thread_delay(2);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// GPIO_Configuration();
|
||||||
|
NVIC_Configuration();
|
||||||
|
|
||||||
|
// cme_eth_device.ETH_Speed = ETH_Speed_100M;
|
||||||
|
// cme_eth_device.ETH_Mode = ETH_Mode_FullDuplex;
|
||||||
|
|
||||||
|
/* OUI 00-80-E1 STMICROELECTRONICS. */
|
||||||
|
cme_eth_device.dev_addr[0] = 0x00;
|
||||||
|
cme_eth_device.dev_addr[1] = 0x80;
|
||||||
|
cme_eth_device.dev_addr[2] = 0xE1;
|
||||||
|
/* generate MAC addr from 96bit unique ID (only for test). */
|
||||||
|
// cme_eth_device.dev_addr[3] = *(rt_uint8_t*)(0x1FFF7A10+4);
|
||||||
|
// cme_eth_device.dev_addr[4] = *(rt_uint8_t*)(0x1FFF7A10+2);
|
||||||
|
// cme_eth_device.dev_addr[5] = *(rt_uint8_t*)(0x1FFF7A10+0);
|
||||||
|
cme_eth_device.dev_addr[3] = 12;
|
||||||
|
cme_eth_device.dev_addr[4] = 34;
|
||||||
|
cme_eth_device.dev_addr[5] = 56;
|
||||||
|
|
||||||
|
cme_eth_device.parent.parent.init = rt_cme_eth_init;
|
||||||
|
cme_eth_device.parent.parent.open = rt_cme_eth_open;
|
||||||
|
cme_eth_device.parent.parent.close = rt_cme_eth_close;
|
||||||
|
cme_eth_device.parent.parent.read = rt_cme_eth_read;
|
||||||
|
cme_eth_device.parent.parent.write = rt_cme_eth_write;
|
||||||
|
cme_eth_device.parent.parent.control = rt_cme_eth_control;
|
||||||
|
cme_eth_device.parent.parent.user_data = RT_NULL;
|
||||||
|
|
||||||
|
cme_eth_device.parent.eth_rx = rt_cme_eth_rx;
|
||||||
|
cme_eth_device.parent.eth_tx = rt_cme_eth_tx;
|
||||||
|
|
||||||
|
/* init EMAC lock */
|
||||||
|
rt_mutex_init(&cme_eth_device.lock, "emac0", RT_IPC_FLAG_PRIO);
|
||||||
|
|
||||||
|
/* init tx buffer free semaphore */
|
||||||
|
rt_sem_init(&cme_eth_device.tx_buf_free,
|
||||||
|
"tx_buf",
|
||||||
|
ETH_TXBUFNB,
|
||||||
|
RT_IPC_FLAG_FIFO);
|
||||||
|
|
||||||
|
/* register eth device */
|
||||||
|
eth_device_init(&(cme_eth_device.parent), "e0");
|
||||||
|
|
||||||
|
return RT_EOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ETH_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* enter interrupt */
|
||||||
|
rt_interrupt_enter();
|
||||||
|
|
||||||
|
if (ETH_GetIntStatus(ETH_INT_TX_COMPLETE_FRAME))
|
||||||
|
{
|
||||||
|
rt_sem_release(&cme_eth_device.tx_buf_free);
|
||||||
|
ETH_ClearInt(ETH_INT_TX_COMPLETE_FRAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ETH_GetIntStatus(ETH_INT_RX_STOP))
|
||||||
|
{
|
||||||
|
CME_ETH_PRINTF("ETH_INT_RX_STOP\n");
|
||||||
|
ETH_ClearInt(ETH_INT_RX_STOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ETH_GetIntStatus(ETH_INT_RX_BUF_UNAVAI)) ||
|
||||||
|
(ETH_GetIntStatus(ETH_INT_RX_COMPLETE_FRAME)))
|
||||||
|
{
|
||||||
|
/* a frame has been received */
|
||||||
|
eth_device_ready(&(cme_eth_device.parent));
|
||||||
|
|
||||||
|
ETH_EnableInt(ETH_INT_RX_COMPLETE_FRAME, FALSE);
|
||||||
|
ETH_EnableInt(ETH_INT_RX_BUF_UNAVAI, FALSE);
|
||||||
|
ETH_ClearInt(ETH_INT_RX_BUF_UNAVAI);
|
||||||
|
ETH_ClearInt(ETH_INT_RX_COMPLETE_FRAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* leave interrupt */
|
||||||
|
rt_interrupt_leave();
|
||||||
|
}
|
||||||
|
|
@ -63,13 +63,15 @@
|
|||||||
#define RT_CONSOLE_DEVICE_NAME "uart2"
|
#define RT_CONSOLE_DEVICE_NAME "uart2"
|
||||||
|
|
||||||
/* SECTION: finsh, a C-Express shell */
|
/* SECTION: finsh, a C-Express shell */
|
||||||
#define RT_USING_FINSH
|
//#define RT_USING_FINSH
|
||||||
/* Using symbol table */
|
/* Using symbol table */
|
||||||
#define FINSH_USING_SYMTAB
|
#define FINSH_USING_SYMTAB
|
||||||
#define FINSH_USING_DESCRIPTION
|
#define FINSH_USING_DESCRIPTION
|
||||||
|
#define FINSH_USING_MSH
|
||||||
|
#define FINSH_USING_MSH_ONLY
|
||||||
|
|
||||||
//#define RT_USING_NEWLIB
|
//#define RT_USING_NEWLIB
|
||||||
//#define RT_USING_ARM_LIBC
|
#define RT_USING_ARM_LIBC
|
||||||
|
|
||||||
/* SECTION: device filesystem */
|
/* SECTION: device filesystem */
|
||||||
/* #define RT_USING_DFS */
|
/* #define RT_USING_DFS */
|
||||||
@ -87,7 +89,7 @@
|
|||||||
#define DFS_FD_MAX 4
|
#define DFS_FD_MAX 4
|
||||||
|
|
||||||
/* SECTION: lwip, a lighwight TCP/IP protocol stack */
|
/* SECTION: lwip, a lighwight TCP/IP protocol stack */
|
||||||
//#define RT_USING_LWIP
|
#define RT_USING_LWIP
|
||||||
/* LwIP uses RT-Thread Memory Management */
|
/* LwIP uses RT-Thread Memory Management */
|
||||||
// #define RT_LWIP_USING_RT_MEM
|
// #define RT_LWIP_USING_RT_MEM
|
||||||
/* Enable ICMP protocol*/
|
/* Enable ICMP protocol*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user