Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
人间散章
rt-thread
提交
1e396417
R
rt-thread
项目概览
人间散章
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1e396417
编写于
7月 25, 2014
作者:
A
ArdaFu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Revert "[BSP] tm4c129x:"
This reverts commit
666d1298
.
上级
666d1298
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
2 addition
and
1475 deletion
+2
-1475
bsp/lm4f232/rtconfig.h
bsp/lm4f232/rtconfig.h
+1
-1
bsp/tm4c129x/applications/application.c
bsp/tm4c129x/applications/application.c
+0
-6
bsp/tm4c129x/applications/board.c
bsp/tm4c129x/applications/board.c
+1
-1
bsp/tm4c129x/drivers/drv_eth.c
bsp/tm4c129x/drivers/drv_eth.c
+0
-1446
bsp/tm4c129x/drivers/drv_eth.h
bsp/tm4c129x/drivers/drv_eth.h
+0
-20
bsp/tm4c129x/libraries/driverlib/emac.c
bsp/tm4c129x/libraries/driverlib/emac.c
+0
-1
未找到文件。
bsp/lm4f232/rtconfig.h
浏览文件 @
1e396417
...
...
@@ -93,7 +93,7 @@
#define DFS_FD_MAX 4
/* SECTION: lwip, a lighwight TCP/IP protocol stack */
#define RT_USING_LWIP
/* #define RT_USING_LWIP */
/* LwIP uses RT-Thread Memory Management */
#define RT_LWIP_USING_RT_MEM
/* Enable ICMP protocol*/
...
...
bsp/tm4c129x/applications/application.c
浏览文件 @
1e396417
...
...
@@ -16,9 +16,6 @@
#include <board.h>
#include <components.h>
#ifdef RT_USING_LWIP
#include "drv_eth.h"
#endif
/* thread phase init */
void
rt_init_thread_entry
(
void
*
parameter
)
{
...
...
@@ -27,9 +24,6 @@ void rt_init_thread_entry(void *parameter)
#ifdef RT_USING_FINSH
finsh_set_device
(
RT_CONSOLE_DEVICE_NAME
);
#endif
#ifdef RT_USING_LWIP
rt_hw_tiva_eth_init
();
#endif
}
int
rt_application_init
(
void
)
...
...
bsp/tm4c129x/applications/board.c
浏览文件 @
1e396417
...
...
@@ -92,7 +92,7 @@ void rt_hw_board_init()
/*init uart device*/
rt_hw_uart_init
();
//redirect RTT stdio to CONSOLE device
//redirect RTT stdio to CONSOLE device
rt_console_set_device
(
RT_CONSOLE_DEVICE_NAME
);
//
// Enable interrupts to the processor.
...
...
bsp/tm4c129x/drivers/drv_eth.c
已删除
100644 → 0
浏览文件 @
666d1298
/*
* File : drv_eth.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2009-2013 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://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2014-07-25 ArdaFu Port to TM4C129X
*/
/**
* @file - tivaif.c
* lwIP Ethernet interface for Stellaris LM4F Devices
*
*/
/**
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICui32AR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
* Author: Adam Dunkels <adam@sics.se>
*
*/
/**
* Copyright (c) 2008-2012 Texas Instruments Incorporated
*
* This file is derived from the ``ethernetif.c'' skeleton Ethernet network
* interface driver for lwIP.
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include <lwip/stats.h>
#include <lwip/snmp.h>
#include "lwip/tcpip.h"
#include "netif/etharp.h"
#include "netif/ppp_oe.h"
/**
* Sanity Check: This interface driver will NOT work if the following defines
* are incorrect.
*
*/
#if (PBUF_LINK_HLEN != 16)
#error "PBUF_LINK_HLEN must be 16 for this interface driver!"
#endif
#if (ETH_PAD_SIZE != 0)
#error "ETH_PAD_SIZE must be 0 for this interface driver!"
#endif
#if (!SYS_LIGHTWEIGHT_PROT)
#error "SYS_LIGHTWEIGHT_PROT must be enabled for this interface driver!"
#endif
/**
* Set the physical address of the PHY we will be using if this is not
* specified in lwipopts.h. We assume 0 for the internal PHY.
*/
#ifndef PHY_PHYS_ADDR
#define PHY_PHYS_ADDR 0
#endif
#if 0
#ifndef EMAC_PHY_CONFIG
#define EMAC_PHY_CONFIG (EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN | \
EMAC_PHY_AN_100B_T_FULL_DUPLEX)
#endif
#endif
/**
* If necessary, set the defaui32t number of transmit and receive DMA descriptors
* used by the Ethernet MAC.
*
*/
#ifndef NUM_RX_DESCRIPTORS
#define NUM_RX_DESCRIPTORS 4
#endif
#ifndef NUM_TX_DESCRIPTORS
#define NUM_TX_DESCRIPTORS 8
#endif
/**
* Setup processing for PTP (IEEE-1588).
*
*/
#if LWIP_PTPD
extern
uint32_t
g_ui32SysClk
;
extern
uint32_t
g_ui32PTPTickRate
;
extern
void
lwIPHostGetTime
(
u32_t
*
time_s
,
u32_t
*
time_ns
);
#endif
/**
* Stellaris DriverLib Header Files required for this interface driver.
*
*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_emac.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/emac.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/flash.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom_map.h"
#include "driverlib/gpio.h"
#include <netif/ethernetif.h>
#include "lwipopts.h"
#include "drv_eth.h"
/**
* A structure used to keep track of driver state and error counts.
*/
typedef
struct
{
uint32_t
ui32TXCount
;
uint32_t
ui32TXCopyCount
;
uint32_t
ui32TXCopyFailCount
;
uint32_t
ui32TXNoDescCount
;
uint32_t
ui32TXBufQueuedCount
;
uint32_t
ui32TXBufFreedCount
;
uint32_t
ui32RXBufReadCount
;
uint32_t
ui32RXPacketReadCount
;
uint32_t
ui32RXPacketErrCount
;
uint32_t
ui32RXPacketCBErrCount
;
uint32_t
ui32RXNoBufCount
;
}
tDriverStats
;
tDriverStats
g_sDriverStats
;
#ifdef DEBUG
/**
* Note: This rather weird construction where we invoke the macro with the
* name of the field minus its Hungarian prefix is a workaround for a problem
* experienced with GCC which does not like concatenating tokens after an
* operator, specifically '.' or '->', in a macro.
*/
#define DRIVER_STATS_INC(x) do{ g_sDriverStats.ui32##x++; } while(0)
#define DRIVER_STATS_DEC(x) do{ g_sDriverStats.ui32##x--; } while(0)
#define DRIVER_STATS_ADD(x, inc) do{ g_sDriverStats.ui32##x += (inc); } while(0)
#define DRIVER_STATS_SUB(x, dec) do{ g_sDriverStats.ui32##x -= (dec); } while(0)
#else
#define DRIVER_STATS_INC(x)
#define DRIVER_STATS_DEC(x)
#define DRIVER_STATS_ADD(x, inc)
#define DRIVER_STATS_SUB(x, dec)
#endif
/**
* Helper struct holding a DMA descriptor and the pbuf it currently refers
* to.
*/
typedef
struct
{
tEMACDMADescriptor
Desc
;
struct
pbuf
*
pBuf
;
}
tDescriptor
;
typedef
struct
{
tDescriptor
*
pDescriptors
;
uint32_t
ui32NumDescs
;
uint32_t
ui32Read
;
uint32_t
ui32Write
;
}
tDescriptorList
;
/**
* Helper struct to hold private data used to operate your ethernet interface.
* Keeping the ethernet address of the MAC in this struct is not necessary
* as it is already kept in the struct netif.
* But this is only an example, anyway...
*/
typedef
struct
{
struct
eth_addr
*
ethaddr
;
/* Add whatever per-interface state that is needed here. */
tDescriptorList
*
pTxDescList
;
tDescriptorList
*
pRxDescList
;
}
tStellarisIF
;
/**
* Global variable for this interface's private data. Needed to allow
* the interrupt handlers access to this information outside of the
* context of the lwIP netif.
*
*/
tDescriptor
g_pTxDescriptors
[
NUM_TX_DESCRIPTORS
];
tDescriptor
g_pRxDescriptors
[
NUM_RX_DESCRIPTORS
];
tDescriptorList
g_TxDescList
=
{
g_pTxDescriptors
,
NUM_TX_DESCRIPTORS
,
0
,
0
};
tDescriptorList
g_RxDescList
=
{
g_pRxDescriptors
,
NUM_RX_DESCRIPTORS
,
0
,
0
};
static
tStellarisIF
g_StellarisIFData
=
{
0
,
&
g_TxDescList
,
&
g_RxDescList
};
/**
* Interrupt counters (for debug purposes).
*/
volatile
uint32_t
g_ui32NormalInts
;
volatile
uint32_t
g_ui32AbnormalInts
;
/**
* A macro which determines whether a pointer is within the SRAM address
* space and, hence, points to a buffer that the Ethernet MAC can directly
* DMA from.
*/
#define PTR_SAFE_FOR_EMAC_DMA(ptr) (((uint32_t)(ptr) >= 0x2000000) && \
((uint32_t)(ptr) < 0x20070000))
typedef
struct
{
/* inherit from ethernet device */
struct
eth_device
parent
;
tStellarisIF
*
dma_if
;
/* for rx_thread async get pbuf */
rt_mailbox_t
rx_pbuf_mb
;
}
net_device
;
typedef
net_device
*
net_device_t
;
static
char
rx_pbuf_mb_pool
[
8
*
4
];
static
struct
rt_mailbox
eth_rx_pbuf_mb
;
static
net_device
eth_dev_entry
;
static
net_device_t
eth_dev
=
&
eth_dev_entry
;
/**
* Initialize the transmit and receive DMA descriptor lists.
*/
void
InitDMADescriptors
(
void
)
{
uint32_t
ui32Loop
;
/* Transmit list - mark all descriptors as not owned by the hardware */
for
(
ui32Loop
=
0
;
ui32Loop
<
NUM_TX_DESCRIPTORS
;
ui32Loop
++
)
{
g_pTxDescriptors
[
ui32Loop
].
pBuf
=
(
struct
pbuf
*
)
0
;
g_pTxDescriptors
[
ui32Loop
].
Desc
.
ui32Count
=
0
;
g_pTxDescriptors
[
ui32Loop
].
Desc
.
pvBuffer1
=
0
;
g_pTxDescriptors
[
ui32Loop
].
Desc
.
DES3
.
pLink
=
((
ui32Loop
==
(
NUM_TX_DESCRIPTORS
-
1
))
?
&
g_pTxDescriptors
[
0
].
Desc
:
&
g_pTxDescriptors
[
ui32Loop
+
1
].
Desc
);
g_pTxDescriptors
[
ui32Loop
].
Desc
.
ui32CtrlStatus
=
DES0_TX_CTRL_INTERRUPT
|
DES0_TX_CTRL_CHAINED
|
DES0_TX_CTRL_IP_ALL_CKHSUMS
;
}
g_TxDescList
.
ui32Read
=
0
;
g_TxDescList
.
ui32Write
=
0
;
/* Receive list - tag each descriptor with a pbuf and set all fields to
* allow packets to be received.
*/
for
(
ui32Loop
=
0
;
ui32Loop
<
NUM_RX_DESCRIPTORS
;
ui32Loop
++
)
{
g_pRxDescriptors
[
ui32Loop
].
pBuf
=
pbuf_alloc
(
PBUF_RAW
,
PBUF_POOL_BUFSIZE
,
PBUF_POOL
);
g_pRxDescriptors
[
ui32Loop
].
Desc
.
ui32Count
=
DES1_RX_CTRL_CHAINED
;
if
(
g_pRxDescriptors
[
ui32Loop
].
pBuf
)
{
/* Set the DMA to write directly into the pbuf payload. */
g_pRxDescriptors
[
ui32Loop
].
Desc
.
pvBuffer1
=
g_pRxDescriptors
[
ui32Loop
].
pBuf
->
payload
;
g_pRxDescriptors
[
ui32Loop
].
Desc
.
ui32Count
|=
(
g_pRxDescriptors
[
ui32Loop
].
pBuf
->
len
<<
DES1_RX_CTRL_BUFF1_SIZE_S
);
g_pRxDescriptors
[
ui32Loop
].
Desc
.
ui32CtrlStatus
=
DES0_RX_CTRL_OWN
;
}
else
{
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"tivaif_init: pbuf_alloc error
\n
"
));
/* No pbuf available so leave the buffer pointer empty. */
g_pRxDescriptors
[
ui32Loop
].
Desc
.
pvBuffer1
=
0
;
g_pRxDescriptors
[
ui32Loop
].
Desc
.
ui32CtrlStatus
=
0
;
}
g_pRxDescriptors
[
ui32Loop
].
Desc
.
DES3
.
pLink
=
((
ui32Loop
==
(
NUM_RX_DESCRIPTORS
-
1
))
?
&
g_pRxDescriptors
[
0
].
Desc
:
&
g_pRxDescriptors
[
ui32Loop
+
1
].
Desc
);
}
g_TxDescList
.
ui32Read
=
0
;
g_TxDescList
.
ui32Write
=
0
;
//
// Set the descriptor pointers in the hardware.
//
EMACRxDMADescriptorListSet
(
EMAC0_BASE
,
&
g_pRxDescriptors
[
0
].
Desc
);
EMACTxDMADescriptorListSet
(
EMAC0_BASE
,
&
g_pTxDescriptors
[
0
].
Desc
);
}
/**
* In this function, the hardware should be initialized.
* Called from tivaif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static
void
tivaif_hwinit
(
struct
netif
*
psNetif
)
{
uint16_t
ui16Val
;
/* Initialize the DMA descriptors. */
InitDMADescriptors
();
/* Clear any stray PHY interrupts that may be set. */
ui16Val
=
EMACPHYRead
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_MISR1
);
ui16Val
=
EMACPHYRead
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_MISR2
);
/* Configure and enable the link status change interrupt in the PHY. */
ui16Val
=
EMACPHYRead
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_SCR
);
ui16Val
|=
(
EPHY_SCR_INTEN_EXT
|
EPHY_SCR_INTOE_EXT
);
EMACPHYWrite
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_SCR
,
ui16Val
);
EMACPHYWrite
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_MISR1
,
(
EPHY_MISR1_LINKSTATEN
|
EPHY_MISR1_SPEEDEN
|
EPHY_MISR1_DUPLEXMEN
|
EPHY_MISR1_ANCEN
));
/* Read the PHY interrupt status to clear any stray events. */
ui16Val
=
EMACPHYRead
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_MISR1
);
/**
* Set MAC filtering options. We receive all broadcast and mui32ticast
* packets along with those addressed specifically for us.
*/
EMACFrameFilterSet
(
EMAC0_BASE
,
(
EMAC_FRMFILTER_HASH_AND_PERFECT
|
EMAC_FRMFILTER_PASS_MULTICAST
));
#if LWIP_PTPD
//
// Enable timestamping on all received packets.
//
// We set the fine clock adjustment mode and configure the subsecond
// increment to half the 25MHz PTPD clock. This will give us maximum control
// over the clock rate adjustment and keep the arithmetic easy later. It
// should be possible to synchronize with higher accuracy than this with
// appropriate juggling of the subsecond increment count and the addend
// register value, though.
//
EMACTimestampConfigSet
(
EMAC0_BASE
,
(
EMAC_TS_ALL_RX_FRAMES
|
EMAC_TS_DIGITAL_ROLLOVER
|
EMAC_TS_PROCESS_IPV4_UDP
|
EMAC_TS_ALL
|
EMAC_TS_PTP_VERSION_1
|
EMAC_TS_UPDATE_FINE
),
(
1000000000
/
(
25000000
/
2
)));
EMACTimestampAddendSet
(
EMAC0_BASE
,
0x80000000
);
EMACTimestampEnable
(
EMAC0_BASE
);
#endif
/* Clear any pending MAC interrupts. */
EMACIntClear
(
EMAC0_BASE
,
EMACIntStatus
(
EMAC0_BASE
,
false
));
/* Enable the Ethernet MAC transmitter and receiver. */
EMACTxEnable
(
EMAC0_BASE
);
EMACRxEnable
(
EMAC0_BASE
);
/* Enable the Ethernet RX and TX interrupt source. */
EMACIntEnable
(
EMAC0_BASE
,
(
EMAC_INT_RECEIVE
|
EMAC_INT_TRANSMIT
|
EMAC_INT_TX_STOPPED
|
EMAC_INT_RX_NO_BUFFER
|
EMAC_INT_RX_STOPPED
|
EMAC_INT_PHY
));
/* Enable the Ethernet interrupt. */
IntEnable
(
INT_EMAC0
);
/* Enable all processor interrupts. */
IntMasterEnable
();
/* Tell the PHY to start an auto-negotiation cycle. */
EMACPHYWrite
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_BMCR
,
(
EPHY_BMCR_ANEN
|
EPHY_BMCR_RESTARTAN
));
}
#ifdef DEBUG
/**
* Dump the chain of pbuf pointers to the debug output.
*/
void
tivaif_trace_pbuf
(
const
char
*
pcTitle
,
struct
pbuf
*
p
)
{
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"%s %08x (%d, %d)"
,
pcTitle
,
p
,
p
->
tot_len
,
p
->
len
));
do
{
p
=
p
->
next
;
if
(
p
)
{
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"->%08x(%d)"
,
p
,
p
->
len
));
}
else
{
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"->%08x"
,
p
));
}
}
while
((
p
!=
NULL
)
&&
(
p
->
tot_len
!=
p
->
len
));
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"
\n
"
));
}
#endif
/**
* This function is used to check whether a passed pbuf contains only buffers
* resident in regions of memory that the Ethernet MAC can access. If any
* buffers in the chain are outside a directly-DMAable section of memory,
* the pbuf is copied to SRAM and a different pointer returned. If all
* buffers are safe, the pbuf reference count is incremented and the original
* pointer returned.
*/
static
struct
pbuf
*
tivaif_check_pbuf
(
struct
pbuf
*
p
)
{
struct
pbuf
*
pBuf
;
rt_err_t
Err
;
pBuf
=
p
;
#ifdef DEBUG
tivaif_trace_pbuf
(
"Original:"
,
p
);
#endif
/* Walk the list of buffers in the pbuf checking each. */
do
{
/* Does this pbuf's payload reside in memory that the Ethernet DMA
* can access?
*/
if
(
!
PTR_SAFE_FOR_EMAC_DMA
(
pBuf
->
payload
))
{
/* This buffer is outside the DMA-able memory space so we need
* to copy the pbuf.
*/
pBuf
=
pbuf_alloc
(
PBUF_RAW
,
p
->
tot_len
,
PBUF_POOL
);
/* If we got a new pbuf... */
if
(
pBuf
)
{
/* ...copy the old pbuf into the new one. */
Err
=
pbuf_copy
(
pBuf
,
p
);
/* If we failed to copy the pbuf, free the newly allocated one
* and make sure we return a NULL to show a problem.
*/
if
(
Err
!=
RT_EOK
)
{
DRIVER_STATS_INC
(
TXCopyFailCount
);
pbuf_free
(
pBuf
);
pBuf
=
NULL
;
}
else
{
#ifdef DEBUG
tivaif_trace_pbuf
(
"Copied:"
,
pBuf
);
#endif
DRIVER_STATS_INC
(
TXCopyCount
);
/* Reduce the reference count on the original pbuf since
* we're not going to hold on to it after returning from
* tivaif_transmit. Note that we already bumped
* the reference count at the top of tivaif_transmit.
*/
pbuf_free
(
p
);
}
}
/* Send back the new pbuf pointer or NULL if an error occurred. */
return
(
pBuf
);
}
/* Move on to the next buffer in the queue */
pBuf
=
pBuf
->
next
;
}
while
(
pBuf
);
/**
* If we get here, the passed pbuf can be safely used without needing to
* be copied.
*/
return
(
p
);
}
/**
* 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 psNetif 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 RT_EOK if the packet coui32d be sent
* an err_t value if the packet coui32dn't be sent
*/
static
rt_err_t
tivaif_transmit
(
net_device_t
dev
,
struct
pbuf
*
p
)
{
tStellarisIF
*
pIF
;
tDescriptor
*
pDesc
;
struct
pbuf
*
pBuf
;
uint32_t
ui32NumChained
,
ui32NumDescs
;
bool
bFirst
;
SYS_ARCH_DECL_PROTECT
(
lev
);
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"tivaif_transmit 0x%08x, len %d
\n
"
,
p
,
p
->
tot_len
));
/**
* This entire function must run within a "critical section" to preserve
* the integrity of the transmit pbuf queue.
*/
SYS_ARCH_PROTECT
(
lev
);
/* Update our transmit attempt counter. */
DRIVER_STATS_INC
(
TXCount
);
/**
* Increase the reference count on the packet provided so that we can
* hold on to it until we are finished transmitting its content.
*/
pbuf_ref
(
p
);
/**
* Determine whether all buffers passed are within SRAM and, if not, copy
* the pbuf into SRAM-resident buffers so that the Ethernet DMA can access
* the data.
*/
p
=
tivaif_check_pbuf
(
p
);
/* Make sure we still have a valid buffer (it may have been copied) */
if
(
!
p
)
{
LINK_STATS_INC
(
link
.
memerr
);
SYS_ARCH_UNPROTECT
(
lev
);
return
(
-
RT_ENOMEM
);
}
/* Get our state data from the netif structure we were passed. */
//pIF = (tStellarisIF *)psNetif->state;
pIF
=
dev
->
dma_if
;
/* Make sure that the transmit descriptors are not all in use */
pDesc
=
&
(
pIF
->
pTxDescList
->
pDescriptors
[
pIF
->
pTxDescList
->
ui32Write
]);
if
(
pDesc
->
pBuf
)
{
/**
* The current write descriptor has a pbuf attached to it so this
* implies that the ring is fui32l. Reject this transmit request with a
* memory error since we can't satisfy it just now.
*/
pbuf_free
(
p
);
LINK_STATS_INC
(
link
.
memerr
);
DRIVER_STATS_INC
(
TXNoDescCount
);
SYS_ARCH_UNPROTECT
(
lev
);
return
(
-
RT_ENOMEM
);
}
/* How many pbufs are in the chain passed? */
ui32NumChained
=
(
uint32_t
)
pbuf_clen
(
p
);
/* How many free transmit descriptors do we have? */
ui32NumDescs
=
(
pIF
->
pTxDescList
->
ui32Read
>
pIF
->
pTxDescList
->
ui32Write
)
?
(
pIF
->
pTxDescList
->
ui32Read
-
pIF
->
pTxDescList
->
ui32Write
)
:
((
NUM_TX_DESCRIPTORS
-
pIF
->
pTxDescList
->
ui32Write
)
+
pIF
->
pTxDescList
->
ui32Read
);
/* Do we have enough free descriptors to send the whole packet? */
if
(
ui32NumDescs
<
ui32NumChained
)
{
/* No - we can't transmit this whole packet so return an error. */
pbuf_free
(
p
);
LINK_STATS_INC
(
link
.
memerr
);
DRIVER_STATS_INC
(
TXNoDescCount
);
SYS_ARCH_UNPROTECT
(
lev
);
return
(
-
RT_ENOMEM
);
}
/* Tag the first descriptor as the start of the packet. */
bFirst
=
true
;
pDesc
->
Desc
.
ui32CtrlStatus
=
DES0_TX_CTRL_FIRST_SEG
;
/* Here, we know we can send the packet so write it to the descriptors */
pBuf
=
p
;
while
(
ui32NumChained
)
{
/* Get a pointer to the descriptor we will write next. */
pDesc
=
&
(
pIF
->
pTxDescList
->
pDescriptors
[
pIF
->
pTxDescList
->
ui32Write
]);
/* Fill in the buffer pointer and length */
pDesc
->
Desc
.
ui32Count
=
(
uint32_t
)
pBuf
->
len
;
pDesc
->
Desc
.
pvBuffer1
=
pBuf
->
payload
;
/* Tag the first descriptor as the start of the packet. */
if
(
bFirst
)
{
bFirst
=
false
;
pDesc
->
Desc
.
ui32CtrlStatus
=
DES0_TX_CTRL_FIRST_SEG
;
}
else
{
pDesc
->
Desc
.
ui32CtrlStatus
=
0
;
}
pDesc
->
Desc
.
ui32CtrlStatus
|=
(
DES0_TX_CTRL_IP_ALL_CKHSUMS
|
DES0_TX_CTRL_CHAINED
);
/* Decrement our descriptor counter, move on to the next buffer in the
* pbuf chain. */
ui32NumChained
--
;
pBuf
=
pBuf
->
next
;
/* Update the descriptor list write index. */
pIF
->
pTxDescList
->
ui32Write
++
;
if
(
pIF
->
pTxDescList
->
ui32Write
==
NUM_TX_DESCRIPTORS
)
{
pIF
->
pTxDescList
->
ui32Write
=
0
;
}
/* If this is the last descriptor, mark it as the end of the packet. */
if
(
!
ui32NumChained
)
{
pDesc
->
Desc
.
ui32CtrlStatus
|=
(
DES0_TX_CTRL_LAST_SEG
|
DES0_TX_CTRL_INTERRUPT
);
/* Tag the descriptor with the original pbuf pointer. */
pDesc
->
pBuf
=
p
;
}
else
{
/* Set the lsb of the pbuf pointer. We use this as a signal that
* we should not free the pbuf when we are walking the descriptor
* list while processing the transmit interrupt. We only free the
* pbuf when processing the last descriptor used to transmit its
* chain.
*/
pDesc
->
pBuf
=
(
struct
pbuf
*
)((
uint32_t
)
p
+
1
);
}
DRIVER_STATS_INC
(
TXBufQueuedCount
);
/* Hand the descriptor over to the hardware. */
pDesc
->
Desc
.
ui32CtrlStatus
|=
DES0_TX_CTRL_OWN
;
}
/* Tell the transmitter to start (in case it had stopped). */
EMACTxDMAPollDemand
(
EMAC0_BASE
);
/* Update lwIP statistics */
LINK_STATS_INC
(
link
.
xmit
);
SYS_ARCH_UNPROTECT
(
lev
);
return
(
RT_EOK
);
}
/**
* This function will process all transmit descriptors and free pbufs attached
* to any that have been transmitted since we last checked.
*
* This function is called only from the Ethernet interrupt handler.
*
* @param netif the lwip network interface structure for this ethernetif
* @return None.
*/
static
void
tivaif_process_transmit
(
tStellarisIF
*
pIF
)
{
tDescriptorList
*
pDescList
;
uint32_t
ui32NumDescs
;
/* Get a pointer to the transmit descriptor list. */
pDescList
=
pIF
->
pTxDescList
;
/* Walk the list until we have checked all descriptors or we reach the
* write pointer or find a descriptor that the hardware is still working
* on.
*/
for
(
ui32NumDescs
=
0
;
ui32NumDescs
<
pDescList
->
ui32NumDescs
;
ui32NumDescs
++
)
{
/* Has the buffer attached to this descriptor been transmitted? */
if
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32CtrlStatus
&
DES0_TX_CTRL_OWN
)
{
/* No - we're finished. */
break
;
}
/* Does this descriptor have a buffer attached to it? */
if
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
)
{
/* Yes - free it if it's not marked as an intermediate pbuf */
if
(
!
((
uint32_t
)(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
)
&
1
))
{
pbuf_free
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
);
DRIVER_STATS_INC
(
TXBufFreedCount
);
}
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
=
NULL
;
}
else
{
/* If the descriptor has no buffer, we are finished. */
break
;
}
/* Move on to the next descriptor. */
pDescList
->
ui32Read
++
;
if
(
pDescList
->
ui32Read
==
pDescList
->
ui32NumDescs
)
{
pDescList
->
ui32Read
=
0
;
}
}
}
/**
* This function will process all receive descriptors that contain newly read
* data and pass complete frames up the lwIP stack as they are found. The
* timestamp of the packet will be placed into the pbuf structure if PTPD is
* enabled.
*
* This function is called only from the Ethernet interrupt handler.
*
* @param psNetif the lwip network interface structure for this ethernetif
* @return None.
*/
static
void
tivaif_receive
(
net_device_t
dev
)
{
tDescriptorList
*
pDescList
;
tStellarisIF
*
pIF
;
struct
pbuf
*
pBuf
;
uint32_t
ui32DescEnd
;
/* Get a pointer to our state data */
pIF
=
dev
->
dma_if
;
/* Get a pointer to the receive descriptor list. */
pDescList
=
pIF
->
pRxDescList
;
/* Start with a NULL pbuf so that we don't try to link chain the first
* time round.
*/
pBuf
=
NULL
;
/* Determine where we start and end our walk of the descriptor list */
ui32DescEnd
=
pDescList
->
ui32Read
?
(
pDescList
->
ui32Read
-
1
)
:
(
pDescList
->
ui32NumDescs
-
1
);
/* Step through the descriptors that are marked for CPU attention. */
while
(
pDescList
->
ui32Read
!=
ui32DescEnd
)
{
/* Does the current descriptor have a buffer attached to it? */
if
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
)
{
/* Yes - determine if the host has filled it yet. */
if
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32CtrlStatus
&
DES0_RX_CTRL_OWN
)
{
/* The DMA engine still owns the descriptor so we are finished */
break
;
}
DRIVER_STATS_INC
(
RXBufReadCount
);
/* If this descriptor contains the end of the packet, fix up the
* buffer size accordingly.
*/
if
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32CtrlStatus
&
DES0_RX_STAT_LAST_DESC
)
{
/* This is the last descriptor for the frame so fix up the
* length. It is safe for us to modify the internal fields
* directly here (rather than calling pbuf_realloc) since we
* know each of these pbufs is never chained.
*/
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
->
len
=
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32CtrlStatus
&
DES0_RX_STAT_FRAME_LENGTH_M
)
>>
DES0_RX_STAT_FRAME_LENGTH_S
;
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
->
tot_len
=
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
->
len
;
}
if
(
pBuf
)
{
/* Link this pbuf to the last one we looked at since this buffer
* is a continuation of an existing frame (split across mui32tiple
* pbufs). Note that we use pbuf_cat() here rather than
* pbuf_chain() since we don't want to increase the reference
* count of either pbuf - we only want to link them together.
*/
pbuf_cat
(
pBuf
,
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
);
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
=
pBuf
;
}
/* Remember the buffer associated with this descriptor. */
pBuf
=
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
;
/* Is this the last descriptor for the current frame? */
if
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32CtrlStatus
&
DES0_RX_STAT_LAST_DESC
)
{
/* Yes - does the frame contain errors? */
if
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32CtrlStatus
&
DES0_RX_STAT_ERR
)
{
/* This is a bad frame so discard it and update the relevant
* statistics.
*/
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"tivaif_receive: packet error
\n
"
));
pbuf_free
(
pBuf
);
LINK_STATS_INC
(
link
.
drop
);
DRIVER_STATS_INC
(
RXPacketErrCount
);
}
else
{
/* This is a good frame so pass it up the stack. */
LINK_STATS_INC
(
link
.
recv
);
DRIVER_STATS_INC
(
RXPacketReadCount
);
#if LWIP_PTPD
/* Place the timestamp in the PBUF if PTPD is enabled */
pBuf
->
time_s
=
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32IEEE1588TimeHi
;
pBuf
->
time_ns
=
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32IEEE1588TimeLo
;
#endif
#if NO_SYS
if
(
ethernet_input
(
pBuf
,
psNetif
)
!=
RT_EOK
)
{
#else
//if(tcpip_input(pBuf, psNetif) != RT_EOK)
if
((
rt_mb_send
(
dev
->
rx_pbuf_mb
,
(
rt_uint32_t
)
pBuf
)
!=
RT_EOK
)
||
(
eth_device_ready
(
&
(
dev
->
parent
))
!=
RT_EOK
))
{
#endif
/* drop the packet */
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"tivaif_input: input error
\n
"
));
pbuf_free
(
pBuf
);
/* Adjust the link statistics */
LINK_STATS_INC
(
link
.
memerr
);
LINK_STATS_INC
(
link
.
drop
);
DRIVER_STATS_INC
(
RXPacketCBErrCount
);
}
/* We're finished with this packet so make sure we don't try
* to link the next buffer to it.
*/
pBuf
=
NULL
;
}
}
}
/* Allocate a new buffer for this descriptor */
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
=
pbuf_alloc
(
PBUF_RAW
,
PBUF_POOL_BUFSIZE
,
PBUF_POOL
);
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32Count
=
DES1_RX_CTRL_CHAINED
;
if
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
)
{
/* We got a buffer so fill in the payload pointer and size. */
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
pvBuffer1
=
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
->
payload
;
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32Count
|=
(
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
pBuf
->
len
<<
DES1_RX_CTRL_BUFF1_SIZE_S
);
/* Give this descriptor back to the hardware */
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
ui32CtrlStatus
=
DES0_RX_CTRL_OWN
;
}
else
{
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"tivaif_receive: pbuf_alloc error
\n
"
));
pDescList
->
pDescriptors
[
pDescList
->
ui32Read
].
Desc
.
pvBuffer1
=
0
;
/* Update the stats to show we coui32dn't allocate a pbuf. */
DRIVER_STATS_INC
(
RXNoBufCount
);
LINK_STATS_INC
(
link
.
memerr
);
/* Stop parsing here since we can't leave a broken descriptor in
* the chain.
*/
break
;
}
/* Move on to the next descriptor in the chain, taking care to wrap. */
pDescList
->
ui32Read
++
;
if
(
pDescList
->
ui32Read
==
pDescList
->
ui32NumDescs
)
{
pDescList
->
ui32Read
=
0
;
}
}
}
/**
* Process interrupts from the PHY.
*
* should be called from the Stellaris Ethernet Interrupt Handler. This
* function will read packets from the Stellaris Ethernet fifo and place them
* into a pbuf queue. If the transmitter is idle and there is at least one packet
* on the transmit queue, it will place it in the transmit fifo and start the
* transmitter.
*
*/
void
tivaif_process_phy_interrupt
(
net_device_t
dev
)
{
uint16_t
ui16Val
,
ui16Status
;
uint32_t
ui32Config
,
ui32Mode
,
ui32RxMaxFrameSize
;
/* Read the PHY interrupt status. This clears all interrupt sources.
* Note that we are only enabling sources in EPHY_MISR1 so we don't
* read EPHY_MISR2.
*/
ui16Val
=
EMACPHYRead
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_MISR1
);
/*
* Dummy read PHY REG EPHY_BMSR, it will force update the EPHY_STS register
*/
EMACPHYRead
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_BMSR
);
/* Read the current PHY status. */
ui16Status
=
EMACPHYRead
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
EPHY_STS
);
/* Has the link status changed? */
if
(
ui16Val
&
EPHY_MISR1_LINKSTAT
)
{
/* Is link up or down now? */
if
(
ui16Status
&
EPHY_STS_LINK
)
{
/* Tell lwIP the link is up. */
#if NO_SYS
netif_set_link_up
(
psNetif
);
#else
//tcpip_callback((tcpip_callback_fn)netif_set_link_up, psNetif);
eth_device_linkchange
(
&
(
dev
->
parent
),
RT_TRUE
);
#endif
/* In this case we drop through since we may need to reconfigure
* the MAC depending upon the speed and half/fui32l-duplex settings.
*/
}
else
{
/* Tell lwIP the link is down */
#if NO_SYS
netif_set_link_down
(
psNetif
);
#else
//tcpip_callback((tcpip_callback_fn)netif_set_link_down, psNetif);
eth_device_linkchange
(
&
(
dev
->
parent
),
RT_FALSE
);
#endif
}
}
/* Has the speed or duplex status changed? */
if
(
ui16Val
&
(
EPHY_MISR1_SPEED
|
EPHY_MISR1_SPEED
|
EPHY_MISR1_ANC
))
{
/* Get the current MAC configuration. */
EMACConfigGet
(
EMAC0_BASE
,
&
ui32Config
,
&
ui32Mode
,
&
ui32RxMaxFrameSize
);
/* What speed is the interface running at now?
*/
if
(
ui16Status
&
EPHY_STS_SPEED
)
{
/* 10Mbps is selected */
ui32Config
&=
~
EMAC_CONFIG_100MBPS
;
}
else
{
/* 100Mbps is selected */
ui32Config
|=
EMAC_CONFIG_100MBPS
;
}
/* Are we in fui32l- or half-duplex mode? */
if
(
ui16Status
&
EPHY_STS_DUPLEX
)
{
/* Fui32l duplex. */
ui32Config
|=
EMAC_CONFIG_FULL_DUPLEX
;
}
else
{
/* Half duplex. */
ui32Config
&=
~
EMAC_CONFIG_FULL_DUPLEX
;
}
/* Reconfigure the MAC */
EMACConfigSet
(
EMAC0_BASE
,
ui32Config
,
ui32Mode
,
ui32RxMaxFrameSize
);
}
}
/**
* Process tx and rx packets at the low-level interrupt.
*
* should be called from the Stellaris Ethernet Interrupt Handler. This
* function will read packets from the Stellaris Ethernet fifo and place them
* into a pbuf queue. If the transmitter is idle and there is at least one packet
* on the transmit queue, it will place it in the transmit fifo and start the
* transmitter.
*
*/
void
tivaif_interrupt
(
net_device_t
dev
,
uint32_t
ui32Status
)
{
/* Update our debug interrupt counters. */
if
(
ui32Status
&
EMAC_INT_NORMAL_INT
)
{
g_ui32NormalInts
++
;
}
if
(
ui32Status
&
EMAC_INT_ABNORMAL_INT
)
{
g_ui32AbnormalInts
++
;
}
/* Is this an interrupt from the PHY? */
if
(
ui32Status
&
EMAC_INT_PHY
)
{
tivaif_process_phy_interrupt
(
dev
);
}
/* Process the transmit DMA list, freeing any buffers that have been
* transmitted since our last interrupt.
*/
if
(
ui32Status
&
EMAC_INT_TRANSMIT
)
{
tivaif_process_transmit
(
dev
->
dma_if
);
}
/**
* Process the receive DMA list and pass all successfui32ly received packets
* up the stack. We also call this function in cases where the receiver has
* stalled due to missing buffers since the receive function will attempt to
* allocate new pbufs for descriptor entries which have none.
*/
if
(
ui32Status
&
(
EMAC_INT_RECEIVE
|
EMAC_INT_RX_NO_BUFFER
|
EMAC_INT_RX_STOPPED
))
{
tivaif_receive
(
dev
);
}
}
#if NETIF_DEBUG
/* Print an IP header by using LWIP_DEBUGF
* @param p an IP packet, p->payload pointing to the IP header
*/
void
tivaif_debug_print
(
struct
pbuf
*
p
)
{
struct
eth_hdr
*
ethhdr
=
(
struct
eth_hdr
*
)
p
->
payload
;
u16_t
*
plen
=
(
u16_t
*
)
p
->
payload
;
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"ETH header:
\n
"
));
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"Packet Length:%5"
U16_F
"
\n
"
,
*
plen
));
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"Destination: %02"
X8_F
"-%02"
X8_F
"-%02"
X8_F
"-%02"
X8_F
"-%02"
X8_F
"-%02"
X8_F
"
\n
"
,
ethhdr
->
dest
.
addr
[
0
],
ethhdr
->
dest
.
addr
[
1
],
ethhdr
->
dest
.
addr
[
2
],
ethhdr
->
dest
.
addr
[
3
],
ethhdr
->
dest
.
addr
[
4
],
ethhdr
->
dest
.
addr
[
5
]));
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"Source: %02"
X8_F
"-%02"
X8_F
"-%02"
X8_F
"-%02"
X8_F
"-%02"
X8_F
"-%02"
X8_F
"
\n
"
,
ethhdr
->
src
.
addr
[
0
],
ethhdr
->
src
.
addr
[
1
],
ethhdr
->
src
.
addr
[
2
],
ethhdr
->
src
.
addr
[
3
],
ethhdr
->
src
.
addr
[
4
],
ethhdr
->
src
.
addr
[
5
]));
LWIP_DEBUGF
(
NETIF_DEBUG
,
(
"Packet Type:0x%04"
U16_F
"
\n
"
,
ethhdr
->
type
));
}
#endif
/* NETIF_DEBUG */
void
lwIPEthernetIntHandler
(
void
)
{
uint32_t
ui32Status
;
#ifdef DEF_INT_TEMPSTAMP
uint32_t
ui32TimerStatus
;
#endif
//
// Read and Clear the interrupt.
//
ui32Status
=
MAP_EMACIntStatus
(
EMAC0_BASE
,
true
);
//
// If the interrupt really came from the Ethernet and not our
// timer, clear it.
//
if
(
ui32Status
)
{
MAP_EMACIntClear
(
EMAC0_BASE
,
ui32Status
);
}
#ifdef DEF_INT_TEMPSTAMP
//
// Check to see whether a hardware timer interrupt has been reported.
//
if
(
ui32Status
&
EMAC_INT_TIMESTAMP
)
{
//
// Yes - read and clear the timestamp interrupt status.
//
ui32TimerStatus
=
EMACTimestampIntStatus
(
EMAC0_BASE
);
//
// If a timer interrupt handler has been registered, call it.
//
if
(
g_pfnTimerHandler
)
{
g_pfnTimerHandler
(
EMAC0_BASE
,
ui32TimerStatus
);
}
}
#endif
//
// The handling of the interrupt is different based on the use of a RTOS.
//
//
// No RTOS is being used. If a transmit/receive interrupt was active,
// run the low-level interrupt handler.
//
if
(
ui32Status
)
{
tivaif_interrupt
(
eth_dev
,
ui32Status
);
}
//
// Service the lwIP timers.
//
//lwIPServiceTimers();
}
// OUI:00-12-37 (hex) Texas Instruments, only for test
static
int
tiva_eth_mac_addr_init
(
void
)
{
int
retVal
=
0
;
uint32_t
ulUser
[
2
];
uint8_t
mac_addr
[
6
];
MAP_FlashUserGet
(
&
ulUser
[
0
],
&
ulUser
[
1
]);
if
((
ulUser
[
0
]
==
0xffffffff
)
||
(
ulUser
[
1
]
==
0xffffffff
))
{
rt_kprintf
(
"Fail to get mac address from eeprom.
\n
"
);
rt_kprintf
(
"Using default mac address
\n
"
);
// OUI:00-12-37 (hex) Texas Instruments, only for test
// Configure the hardware MAC address
ulUser
[
0
]
=
0x00371200
;
ulUser
[
1
]
=
0x00563412
;
//FlashUserSet(ulUser0, ulUser1);
retVal
=-
1
;
}
//Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
//address needed to program the hardware registers, then program the MAC
//address into the Ethernet Controller registers.
mac_addr
[
0
]
=
((
ulUser
[
0
]
>>
0
)
&
0xff
);
mac_addr
[
1
]
=
((
ulUser
[
0
]
>>
8
)
&
0xff
);
mac_addr
[
2
]
=
((
ulUser
[
0
]
>>
16
)
&
0xff
);
mac_addr
[
3
]
=
((
ulUser
[
1
]
>>
0
)
&
0xff
);
mac_addr
[
4
]
=
((
ulUser
[
1
]
>>
8
)
&
0xff
);
mac_addr
[
5
]
=
((
ulUser
[
1
]
>>
16
)
&
0xff
);
//
// Program the hardware with its MAC address (for filtering).
//
MAP_EMACAddrSet
(
EMAC0_BASE
,
0
,
mac_addr
);
return
retVal
;
}
#ifndef EMAC_PHY_CONFIG
#define EMAC_PHY_CONFIG (EMAC_PHY_TYPE_INTERNAL | \
EMAC_PHY_INT_MDIX_EN | \
EMAC_PHY_AN_100B_T_FULL_DUPLEX)
#endif
void
tiva_eth_lowlevel_init
(
void
)
{
MAP_SysCtlPeripheralEnable
(
SYSCTL_PERIPH_GPIOF
);
//
// PF1/PK4/PK6 are used for Ethernet LEDs.
//
MAP_GPIOPinConfigure
(
GPIO_PF0_EN0LED0
);
MAP_GPIOPinConfigure
(
GPIO_PF4_EN0LED1
);
GPIOPinTypeEthernetLED
(
GPIO_PORTF_BASE
,
GPIO_PIN_0
);
GPIOPinTypeEthernetLED
(
GPIO_PORTF_BASE
,
GPIO_PIN_4
);
//
// Enable the ethernet peripheral.
//
MAP_SysCtlPeripheralEnable
(
SYSCTL_PERIPH_EMAC0
);
MAP_SysCtlPeripheralReset
(
SYSCTL_PERIPH_EMAC0
);
//
// Enable the internal PHY if it's present and we're being
// asked to use it.
//
if
((
EMAC_PHY_CONFIG
&
EMAC_PHY_TYPE_MASK
)
==
EMAC_PHY_TYPE_INTERNAL
)
{
//
// We've been asked to configure for use with the internal
// PHY. Is it present?
//
if
(
SysCtlPeripheralPresent
(
SYSCTL_PERIPH_EPHY0
))
{
//
// Yes - enable and reset it.
//
MAP_SysCtlPeripheralEnable
(
SYSCTL_PERIPH_EPHY0
);
MAP_SysCtlPeripheralReset
(
SYSCTL_PERIPH_EPHY0
);
}
else
{
//
// Internal PHY is not present on this part so hang here.
//
rt_kprintf
(
"Internal PHY is not present on this part.
\n
"
);
while
(
1
)
{
}
}
}
//
// Wait for the MAC to come out of reset.
//
while
(
!
MAP_SysCtlPeripheralReady
(
SYSCTL_PERIPH_EMAC0
))
{
}
//
// Configure for use with whichever PHY the user requires.
//
MAP_EMACPHYConfigSet
(
EMAC0_BASE
,
EMAC_PHY_CONFIG
);
//
// Initialize the MAC and set the DMA mode.
//
MAP_EMACInit
(
EMAC0_BASE
,
120000000
,
//system clock = 120MHz
EMAC_BCONFIG_MIXED_BURST
|
EMAC_BCONFIG_PRIORITY_FIXED
,
4
,
4
,
0
);
//
// Set MAC configuration options.
//
MAP_EMACConfigSet
(
EMAC0_BASE
,
(
EMAC_CONFIG_FULL_DUPLEX
|
EMAC_CONFIG_CHECKSUM_OFFLOAD
|
EMAC_CONFIG_7BYTE_PREAMBLE
|
EMAC_CONFIG_IF_GAP_96BITS
|
EMAC_CONFIG_USE_MACADDR0
|
EMAC_CONFIG_SA_FROM_DESCRIPTOR
|
EMAC_CONFIG_BO_LIMIT_1024
),
(
EMAC_MODE_RX_STORE_FORWARD
|
EMAC_MODE_TX_STORE_FORWARD
|
EMAC_MODE_TX_THRESHOLD_64_BYTES
|
EMAC_MODE_RX_THRESHOLD_64_BYTES
),
0
);
EMACIntRegister
(
EMAC0_BASE
,
lwIPEthernetIntHandler
);
}
static
rt_err_t
eth_dev_init
(
rt_device_t
device
)
{
net_device_t
net_dev
=
(
net_device_t
)
device
;
struct
netif
*
psNetif
=
(
net_dev
->
parent
.
netif
);
LWIP_ASSERT
(
"psNetif != NULL"
,
(
psNetif
!=
NULL
));
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
psNetif
->
hostname
=
"t4mc"
;
#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_INIT_SNMP(psNetif, snmp_ifType_ethernet_csmacd, 1000000);
net_dev
->
dma_if
=
&
g_StellarisIFData
;
/* Remember our MAC address. */
g_StellarisIFData
.
ethaddr
=
(
struct
eth_addr
*
)
&
(
psNetif
->
hwaddr
[
0
]);
/* Initialize the hardware */
tivaif_hwinit
(
psNetif
);
return
RT_EOK
;
}
/* control the interface */
static
rt_err_t
eth_dev_control
(
rt_device_t
dev
,
rt_uint8_t
cmd
,
void
*
args
)
{
switch
(
cmd
)
{
case
NIOCTL_GADDR
:
/* get mac address */
if
(
args
)
MAP_EMACAddrGet
(
EMAC0_BASE
,
0
,
(
uint8_t
*
)
args
);
else
return
-
RT_ERROR
;
break
;
default
:
break
;
}
return
RT_EOK
;
}
/* Open the interface */
static
rt_err_t
eth_dev_open
(
rt_device_t
dev
,
rt_uint16_t
oflag
)
{
return
RT_EOK
;
}
/* Close the interface */
static
rt_err_t
eth_dev_close
(
rt_device_t
dev
)
{
return
RT_EOK
;
}
/* Read */
static
rt_size_t
eth_dev_read
(
rt_device_t
dev
,
rt_off_t
pos
,
void
*
buffer
,
rt_size_t
size
)
{
rt_set_errno
(
-
RT_ENOSYS
);
return
0
;
}
/* Write */
static
rt_size_t
eth_dev_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
eth_dev_tx
(
rt_device_t
dev
,
struct
pbuf
*
p
)
{
return
tivaif_transmit
((
net_device_t
)
dev
,
p
);
}
static
struct
pbuf
*
eth_dev_rx
(
rt_device_t
dev
)
{
rt_err_t
result
;
rt_uint32_t
temp
=
0
;
net_device_t
net_dev
=
(
net_device_t
)
dev
;
result
=
rt_mb_recv
(
net_dev
->
rx_pbuf_mb
,
&
temp
,
RT_WAITING_NO
);
return
(
result
==
RT_EOK
)
?
(
struct
pbuf
*
)
temp
:
RT_NULL
;
}
rt_err_t
rt_hw_tiva_eth_init
(
void
)
{
rt_err_t
result
;
/* Clock GPIO and etc */
tiva_eth_lowlevel_init
();
tiva_eth_mac_addr_init
();
/* init rt-thread device interface */
eth_dev
->
parent
.
parent
.
init
=
eth_dev_init
;
eth_dev
->
parent
.
parent
.
open
=
eth_dev_open
;
eth_dev
->
parent
.
parent
.
close
=
eth_dev_close
;
eth_dev
->
parent
.
parent
.
read
=
eth_dev_read
;
eth_dev
->
parent
.
parent
.
write
=
eth_dev_write
;
eth_dev
->
parent
.
parent
.
control
=
eth_dev_control
;
eth_dev
->
parent
.
eth_rx
=
eth_dev_rx
;
eth_dev
->
parent
.
eth_tx
=
eth_dev_tx
;
result
=
rt_mb_init
(
&
eth_rx_pbuf_mb
,
"epbuf"
,
&
rx_pbuf_mb_pool
[
0
],
sizeof
(
rx_pbuf_mb_pool
)
/
4
,
RT_IPC_FLAG_FIFO
);
RT_ASSERT
(
result
==
RT_EOK
);
eth_dev
->
rx_pbuf_mb
=
&
eth_rx_pbuf_mb
;
result
=
eth_device_init
(
&
(
eth_dev
->
parent
),
"e0"
);
return
result
;
}
#ifdef RT_USING_FINSH
#include "finsh.h"
void
PHY_Read
(
uint8_t
addr
)
{
uint16_t
data
=
EMACPHYRead
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
addr
);
rt_kprintf
(
"R PHY_REG[0x%02X] = 0x%04X
\n
"
,
addr
,
data
);
}
FINSH_FUNCTION_EXPORT
(
PHY_Read
,
(
add
));
void
PHY_Write
(
uint8_t
addr
,
uint16_t
data
)
{
EMACPHYWrite
(
EMAC0_BASE
,
PHY_PHYS_ADDR
,
addr
,
data
);
rt_kprintf
(
"W PHY_REG[0x%02X] = 0x%04X
\n
"
,
addr
,
data
);
}
FINSH_FUNCTION_EXPORT
(
PHY_Write
,
(
add
,
data
));
void
PHY_SetAdd
(
uint8_t
addr0
,
uint8_t
addr1
,
uint8_t
addr2
,
uint8_t
addr3
,
uint8_t
addr4
,
uint8_t
addr5
)
{
uint32_t
ulUser
[
2
];
ulUser
[
0
]
=
(((
addr2
<<
8
)
|
addr1
)
<<
8
)
|
addr0
;
ulUser
[
1
]
=
(((
addr5
<<
8
)
|
addr4
)
<<
8
)
|
addr3
;
MAP_FlashUserSet
(
ulUser
[
0
],
ulUser
[
1
]);
MAP_FlashUserSave
();
rt_kprintf
(
"Save to EEPROM. please reboot."
);
}
FINSH_FUNCTION_EXPORT
(
PHY_SetAdd
,
(
add0
-
add5
));
#endif //RT_USING_FINSH
bsp/tm4c129x/drivers/drv_eth.h
已删除
100644 → 0
浏览文件 @
666d1298
/*
* File : drv_eth.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2009-2013 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://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2014-07-25 ArdaFu Port to TM4C129X
*/
#ifndef __TIVA_ETH_H__
#define __TIVA_ETH_H__
rt_err_t
rt_hw_tiva_eth_init
(
void
);
#endif
bsp/tm4c129x/libraries/driverlib/emac.c
浏览文件 @
1e396417
...
...
@@ -2917,7 +2917,6 @@ EMACPHYRead(uint32_t ui32Base, uint8_t ui8PhyAddr, uint8_t ui8RegAddr)
//
HWREG
(
ui32Base
+
EMAC_O_MIIADDR
)
=
((
HWREG
(
ui32Base
+
EMAC_O_MIIADDR
)
&
EMAC_MIIADDR_CR_M
)
|
EMAC_MIIADDR_CR_100_150
|
(
ui8RegAddr
<<
EMAC_MIIADDR_MII_S
)
|
(
ui8PhyAddr
<<
EMAC_MIIADDR_PLA_S
)
|
EMAC_MIIADDR_MIIB
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录