Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lfmiao0
rt-thread
提交
a7babadb
R
rt-thread
项目概览
lfmiao0
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
0
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,发现更多精彩内容 >>
未验证
提交
a7babadb
编写于
1月 20, 2019
作者:
B
Bernard Xiong
提交者:
GitHub
1月 20, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #2241 from Bluebear233/nuvoton_m487
[bsp][nuvoton_m487]Add EMAC drive
上级
0889bafd
6802bb15
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
878 addition
and
34 deletion
+878
-34
bsp/nuvoton_m487/README.md
bsp/nuvoton_m487/README.md
+1
-0
bsp/nuvoton_m487/driver/SConscript
bsp/nuvoton_m487/driver/SConscript
+2
-1
bsp/nuvoton_m487/driver/board.c
bsp/nuvoton_m487/driver/board.c
+0
-2
bsp/nuvoton_m487/driver/board.h
bsp/nuvoton_m487/driver/board.h
+2
-17
bsp/nuvoton_m487/driver/drv_emac.c
bsp/nuvoton_m487/driver/drv_emac.c
+733
-0
bsp/nuvoton_m487/driver/drv_emac.h
bsp/nuvoton_m487/driver/drv_emac.h
+126
-0
bsp/nuvoton_m487/driver/drv_uart.c
bsp/nuvoton_m487/driver/drv_uart.c
+3
-8
bsp/nuvoton_m487/rtconfig.h
bsp/nuvoton_m487/rtconfig.h
+11
-6
未找到文件。
bsp/nuvoton_m487/README.md
浏览文件 @
a7babadb
...
...
@@ -42,6 +42,7 @@
| 驱动 | 支持情况 | 备注 |
| ------ | ---- | :------: |
| UART | 支持 | UART0|
| EMAC | 支持 | EH0|
### 4.1 IO在板级支持包中的映射情况
...
...
bsp/nuvoton_m487/driver/SConscript
浏览文件 @
a7babadb
# RT-Thread building script for component
# RT-Thread building script for component
from
building
import
*
...
...
@@ -6,6 +6,7 @@ cwd = GetCurrentDir()
src
=
Split
(
'''
board.c
drv_uart.c
drv_emac.c
'''
)
CPPPATH
=
[
cwd
]
...
...
bsp/nuvoton_m487/driver/board.c
浏览文件 @
a7babadb
...
...
@@ -8,9 +8,7 @@
* 2018-11-16 bluebear233 first version
*/
#include <rtconfig.h>
#include <rtthread.h>
#include <rthw.h>
#include "NuMicro.h"
#include "drv_uart.h"
#include "board.h"
...
...
bsp/nuvoton_m487/driver/board.h
浏览文件 @
a7babadb
...
...
@@ -15,22 +15,7 @@
#define SRAM_SIZE (160)
#define SRAM_END (0x20000000 + SRAM_SIZE * 1024)
#define RT_UART_485_MODE 1
#define RT_UART_FLOW_CTS_CTRL 2
#define RT_UART_FLOW_RTS_CTRL 3
#define RT_UART_CLEAR_BUF 4
void
rt_hw_pdma_init
(
void
);
void
rt_hw_uart_handle
(
void
);
void
rt_hw_sc_init
(
void
);
void
rt_hw_usart_init
(
void
);
void
rt_hw_uusart_init
(
void
);
void
rt_hw_io_init
(
void
);
void
phy_error_led
(
void
);
unsigned
char
*
eth_get_default_mac
(
void
);
void
eth_set_mac
(
const
unsigned
char
*
mac
);
void
wdt_reload
(
void
);
unsigned
int
get_uid
(
void
);
void
rt_hw_board_init
(
void
);
void
rt_hw_cpu_reset
(
void
);
#endif
/* BOARD_H_ */
bsp/nuvoton_m487/driver/drv_emac.c
0 → 100644
浏览文件 @
a7babadb
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-1-20 bluebear233 first version
*/
#include <rtthread.h>
#ifdef RT_USING_LWIP
#include "NuMicro.h"
#include "drv_emac.h"
#include <netif/ethernetif.h>
#include <netif/etharp.h>
#include <lwip/icmp.h>
#include "lwipopts.h"
#define ETH_DEBUG
//#define ETH_RX_DUMP
//#define ETH_TX_DUMP
#ifdef ETH_DEBUG
#define ETH_TRACE rt_kprintf
#else
#define ETH_TRACE(...)
#endif
/* ETH_DEBUG */
#if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
static
void
packet_dump
(
const
char
*
msg
,
const
struct
pbuf
*
p
)
{
rt_uint32_t
i
;
rt_uint8_t
*
ptr
=
p
->
payload
;
ETH_TRACE
(
"%s %d byte
\n
"
,
msg
,
p
->
tot_len
);
for
(
i
=
0
;
i
<
p
->
tot_len
;
i
++
)
{
if
(
(
i
%
8
)
==
0
)
{
ETH_TRACE
(
" "
);
}
if
(
(
i
%
16
)
==
0
)
{
ETH_TRACE
(
"
\r\n
"
);
}
ETH_TRACE
(
"%02x "
,
*
ptr
);
ptr
++
;
}
ETH_TRACE
(
"
\n\n
"
);
}
#endif
/* dump */
#define ETH_TRIGGER_RX() EMAC->RXST = 0
#define ETH_TRIGGER_TX() EMAC->TXST = 0
#define ETH_ENABLE_TX() EMAC->CTL |= EMAC_CTL_TXON
#define ETH_ENABLE_RX() EMAC->CTL |= EMAC_CTL_RXON
#define ETH_DISABLE_TX() EMAC->CTL &= ~EMAC_CTL_TXON
#define ETH_DISABLE_RX() EMAC->CTL &= ~EMAC_CTL_RXON
#define EMAC_DMARXDESC_CRCEIF_Msk (1ul << 17)
#define ETH_TID_STACK 256
static
rt_uint8_t
volatile
phy_speed
=
0
;
static
rt_uint8_t
eth_addr
[
6
];
static
struct
eth_device
eth
;
static
struct
rt_semaphore
eth_sem
;
static
struct
rt_thread
eth_tid
;
static
rt_uint32_t
eth_stack
[
ETH_TID_STACK
/
4
];
static
struct
eth_descriptor
volatile
*
cur_tx_desc_ptr
,
*
cur_rx_desc_ptr
,
*
fin_tx_desc_ptr
;
static
struct
eth_descriptor
rx_desc
[
RX_DESCRIPTOR_NUM
];
static
struct
eth_descriptor
tx_desc
[
TX_DESCRIPTOR_NUM
];
static
rt_uint32_t
rx_buf
[
RX_DESCRIPTOR_NUM
][
PACKET_BUFFER_SIZE
];
static
rt_uint32_t
tx_buf
[
TX_DESCRIPTOR_NUM
][
PACKET_BUFFER_SIZE
];
static
void
mdio_write
(
rt_uint8_t
addr
,
rt_uint8_t
reg
,
rt_uint16_t
val
)
{
EMAC
->
MIIMDAT
=
val
;
EMAC
->
MIIMCTL
=
(
addr
<<
EMAC_MIIMCTL_PHYADDR_Pos
)
|
reg
|
EMAC_MIIMCTL_BUSY_Msk
|
EMAC_MIIMCTL_WRITE_Msk
|
EMAC_MIIMCTL_MDCON_Msk
;
while
(
EMAC
->
MIIMCTL
&
EMAC_MIIMCTL_BUSY_Msk
);
}
static
rt_uint16_t
mdio_read
(
rt_uint8_t
addr
,
rt_uint8_t
reg
)
{
EMAC
->
MIIMCTL
=
(
addr
<<
EMAC_MIIMCTL_PHYADDR_Pos
)
|
reg
|
EMAC_MIIMCTL_BUSY_Msk
|
EMAC_MIIMCTL_MDCON_Msk
;
while
(
EMAC
->
MIIMCTL
&
EMAC_MIIMCTL_BUSY_Msk
);
return
EMAC
->
MIIMDAT
;
}
static
void
init_tx_desc
(
void
)
{
rt_uint32_t
i
;
cur_tx_desc_ptr
=
fin_tx_desc_ptr
=
&
tx_desc
[
0
];
for
(
i
=
0
;
i
<
TX_DESCRIPTOR_NUM
;
i
++
)
{
tx_desc
[
i
].
status1
=
TXFD_PADEN
|
TXFD_CRCAPP
|
TXFD_INTEN
;
tx_desc
[
i
].
buf
=
(
rt_uint8_t
*
)
tx_buf
[
i
];
tx_desc
[
i
].
status2
=
0
;
tx_desc
[
i
].
next
=
&
tx_desc
[(
i
+
1
)
%
TX_DESCRIPTOR_NUM
];
}
EMAC
->
TXDSA
=
(
unsigned
int
)
&
tx_desc
[
0
];
return
;
}
static
void
init_rx_desc
(
void
)
{
rt_uint32_t
i
;
cur_rx_desc_ptr
=
&
rx_desc
[
0
];
for
(
i
=
0
;
i
<
RX_DESCRIPTOR_NUM
;
i
++
)
{
rx_desc
[
i
].
status1
=
OWNERSHIP_EMAC
;
rx_desc
[
i
].
buf
=
(
rt_uint8_t
*
)
rx_buf
[
i
];
rx_desc
[
i
].
status2
=
0
;
rx_desc
[
i
].
next
=
&
rx_desc
[(
i
+
1
)
%
RX_DESCRIPTOR_NUM
];
}
EMAC
->
RXDSA
=
(
unsigned
int
)
&
rx_desc
[
0
];
return
;
}
static
void
add_mac_addr
(
const
rt_uint8_t
*
addr
)
{
rt_uint32_t
*
EMAC_CAMxM
;
rt_uint32_t
*
EMAC_CAMxL
;
rt_uint8_t
index
=
0
;
rt_uint8_t
mac
[
6
];
for
(;
index
<
13
;
index
++
)
{
EMAC_CAMxM
=
(
rt_uint32_t
*
)((
rt_uint32_t
)
&
EMAC
->
CAM0M
+
(
index
*
8
));
EMAC_CAMxL
=
(
rt_uint32_t
*
)((
rt_uint32_t
)
&
EMAC
->
CAM0L
+
(
index
*
8
));
mac
[
0
]
=
(
*
EMAC_CAMxM
>>
24
)
&
0xff
;
mac
[
1
]
=
(
*
EMAC_CAMxM
>>
16
)
&
0xff
;
mac
[
2
]
=
(
*
EMAC_CAMxM
>>
8
)
&
0xff
;
mac
[
3
]
=
(
*
EMAC_CAMxM
)
&
0xff
;
mac
[
4
]
=
(
*
EMAC_CAMxL
>>
24
)
&
0xff
;
mac
[
5
]
=
(
*
EMAC_CAMxL
>>
16
)
&
0xff
;
if
(
memcmp
(
mac
,
addr
,
sizeof
(
mac
))
==
0
)
{
return
;
}
if
(
*
EMAC_CAMxM
==
0
&&
*
EMAC_CAMxL
==
0
)
{
break
;
}
}
RT_ASSERT
(
index
<
13
)
*
EMAC_CAMxM
=
(
addr
[
0
]
<<
24
)
|
(
addr
[
1
]
<<
16
)
|
(
addr
[
2
]
<<
8
)
|
addr
[
3
];
*
EMAC_CAMxL
=
(
addr
[
4
]
<<
24
)
|
(
addr
[
5
]
<<
16
);
EMAC
->
CAMEN
|=
(
1
<<
index
);
}
void
EMAC_init
()
{
// Reset MAC
EMAC
->
CTL
=
EMAC_CTL_RST_Msk
;
while
(
EMAC
->
CTL
&
EMAC_CTL_RST_Msk
);
init_tx_desc
();
init_rx_desc
();
EMAC
->
CAMCTL
=
EMAC_CAMCTL_CMPEN_Msk
|
EMAC_CAMCTL_ABP_Msk
;
add_mac_addr
(
eth_addr
);
EMAC
->
CTL
|=
EMAC_CTL_STRIPCRC_Msk
|
EMAC_CTL_RXON_Msk
|
EMAC_CTL_TXON_Msk
|
EMAC_CTL_RMIIEN_Msk
;
EMAC
->
INTEN
=
EMAC_INTEN_RXIEN_Msk
|
EMAC_INTEN_RXGDIEN_Msk
|
EMAC_INTEN_RDUIEN_Msk
|
EMAC_INTEN_RXBEIEN_Msk
|
EMAC_INTEN_TXIEN_Msk
|
EMAC_INTEN_TXBEIEN_Msk
;
/* Limit the max receive frame length to 1514 + 4 */
EMAC
->
MRFL
=
PACKET_BUFFER_SIZE
;
EMAC
->
RXST
=
0
;
// trigger Rx
}
void
EMAC_Reinit
(
void
)
{
rt_uint32_t
EMAC_CAMxM
[
13
];
rt_uint32_t
EMAC_CAMxL
[
13
];
rt_uint32_t
EMAC_CAMEN
;
EMAC_CAMEN
=
EMAC
->
CAMEN
;
for
(
rt_uint8_t
index
=
0
;
index
<
13
;
index
++
)
{
rt_uint32_t
*
CAMxM
=
(
rt_uint32_t
*
)((
rt_uint32_t
)
&
EMAC
->
CAM0M
+
(
index
*
8
));
rt_uint32_t
*
CAMxL
=
(
rt_uint32_t
*
)((
rt_uint32_t
)
&
EMAC
->
CAM0L
+
(
index
*
8
));
EMAC_CAMxM
[
index
]
=
*
CAMxM
;
EMAC_CAMxL
[
index
]
=
*
CAMxL
;
}
EMAC_init
();
for
(
rt_uint8_t
index
=
0
;
index
<
13
;
index
++
)
{
rt_uint32_t
*
CAMxM
=
(
rt_uint32_t
*
)((
rt_uint32_t
)
&
EMAC
->
CAM0M
+
(
index
*
8
));
rt_uint32_t
*
CAMxL
=
(
rt_uint32_t
*
)((
rt_uint32_t
)
&
EMAC
->
CAM0L
+
(
index
*
8
));
*
CAMxM
=
EMAC_CAMxM
[
index
];
*
CAMxL
=
EMAC_CAMxL
[
index
];
}
EMAC
->
CAMEN
=
EMAC_CAMEN
;
phy_speed
=
0
;
}
void
ETH_halt
(
void
)
{
EMAC
->
CTL
&=
~
(
EMAC_CTL_RXON_Msk
|
EMAC_CTL_TXON_Msk
);
}
__inline
static
rt_uint8_t
*
emac_get_tx_buf
(
void
)
{
if
(
cur_tx_desc_ptr
->
status1
&
OWNERSHIP_EMAC
)
{
return
(
RT_NULL
);
}
else
{
return
(
cur_tx_desc_ptr
->
buf
);
}
}
__inline
static
void
ETH_trigger_tx
(
rt_uint16_t
length
)
{
struct
eth_descriptor
volatile
*
desc
;
cur_tx_desc_ptr
->
status2
=
(
unsigned
int
)
length
;
desc
=
cur_tx_desc_ptr
->
next
;
// in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
cur_tx_desc_ptr
->
status1
|=
OWNERSHIP_EMAC
;
cur_tx_desc_ptr
=
desc
;
}
#if LWIP_IPV4 && LWIP_IGMP
static
err_t
igmp_mac_filter
(
struct
netif
*
netif
,
const
ip4_addr_t
*
ip4_addr
,
u8_t
action
)
{
rt_uint8_t
mac
[
6
];
const
uint8_t
*
p
=
(
const
uint8_t
*
)
ip4_addr
;
mac
[
0
]
=
0x01
;
mac
[
1
]
=
0x00
;
mac
[
2
]
=
0x5E
;
mac
[
3
]
=
*
(
p
+
1
)
&
0x7F
;
mac
[
4
]
=
*
(
p
+
2
);
mac
[
5
]
=
*
(
p
+
3
);
add_mac_addr
(
mac
);
if
(
1
)
{
rt_kprintf
(
"%s %s %s "
,
__FUNCTION__
,
(
action
==
NETIF_ADD_MAC_FILTER
)
?
"add"
:
"del"
,
ip4addr_ntoa
(
ip4_addr
));
rt_kprintf
(
"%02X:%02X:%02X:%02X:%02X:%02X
\n
"
,
mac
[
0
],
mac
[
1
],
mac
[
2
],
mac
[
3
],
mac
[
4
],
mac
[
5
]);
}
return
0
;
}
#endif
/* LWIP_IPV4 && LWIP_IGMP */
/*
* M480 EMAC Driver for RT-Thread
* Change Logs:
* Date Author Notes
* 2017-12-31 Bluebear233 first implementation
*/
void
EMAC_RX_IRQHandler
(
void
)
{
/* enter interrupt */
rt_interrupt_enter
();
unsigned
int
status
=
EMAC
->
INTSTS
;
if
(
status
&
EMAC_INTSTS_RDUIF_Msk
)
{
EMAC
->
INTEN
&=
~
(
EMAC_INTEN_RDUIEN_Msk
|
EMAC_INTEN_RXGDIEN_Msk
);
eth_device_ready
(
&
eth
);
}
else
if
(
status
&
EMAC_INTSTS_RXGDIF_Msk
)
{
EMAC
->
INTEN
&=
~
EMAC_INTEN_RXGDIEN_Msk
;
eth_device_ready
(
&
eth
);
}
if
(
status
&
EMAC_INTSTS_RXBEIF_Msk
)
{
ETH_TRACE
(
"Reinit Rx EMAC
\n
"
);
EMAC
->
INTSTS
=
EMAC_INTSTS_RXBEIF_Msk
;
EMAC_Reinit
();
}
/* leave interrupt */
rt_interrupt_leave
();
}
void
EMAC_TX_IRQHandler
(
void
)
{
rt_interrupt_enter
();
unsigned
int
status
=
EMAC
->
INTSTS
;
if
(
status
&
EMAC_INTSTS_TXCPIF_Msk
)
{
EMAC
->
INTEN
&=
~
EMAC_INTEN_TXCPIEN_Msk
;
rt_sem_release
(
&
eth_sem
);
}
if
(
status
&
EMAC_INTSTS_TXBEIF_Msk
)
{
ETH_TRACE
(
"Reinit Tx EMAC
\n
"
);
EMAC
->
INTSTS
=
EMAC_INTSTS_TXBEIF_Msk
;
EMAC_Reinit
();
}
rt_interrupt_leave
();
}
#define PHY_LINK_MASK (1<<0)
#define PHY_10FULL_MASK (1<<1)
#define PHY_100FULL_MASK (1<<2)
#define PHY_10HALF_MASK (1<<3)
#define PHY_100HALF_MASK (1<<4)
#define PHY_ANLPA_DR100_TX_FULL (1UL << 8UL)
#define PHY_ANLPA_DR100_TX_HALF (1UL << 7UL)
#define PHY_ANLPA_DR10_TX_FULL (1UL << 6UL)
#define PHY_ANLPA_DR10_TX_HALF (1UL << 5UL)
void
eth_entry
(
void
*
param
)
{
uint8_t
phy_addr
=
0xFF
;
uint8_t
phy_speed_new
=
0
;
/* phy search */
{
rt_uint32_t
i
;
rt_uint16_t
temp
;
for
(
i
=
0
;
i
<=
0x1F
;
i
++
)
{
temp
=
mdio_read
(
i
,
0x02
);
if
(
temp
!=
0xFFFF
)
{
phy_addr
=
i
;
break
;
}
}
}
/* phy search */
if
(
phy_addr
==
0xFF
)
{
ETH_TRACE
(
"phy not probe!
\n
"
);
return
;
}
else
{
ETH_TRACE
(
"found a phy, address:0x%02X
\n
"
,
phy_addr
);
}
/* RESET PHY */
mdio_write
(
phy_addr
,
MII_BMCR
,
BMCR_RESET
);
while
(
1
)
{
rt_thread_delay
(
RT_TICK_PER_SECOND
);
rt_uint16_t
reg
=
mdio_read
(
phy_addr
,
MII_BMCR
);
if
((
reg
&
BMCR_RESET
)
==
0
)
{
break
;
}
}
mdio_write
(
phy_addr
,
MII_ADVERTISE
,
ADVERTISE_CSMA
|
ADVERTISE_10HALF
|
ADVERTISE_10FULL
|
ADVERTISE_100HALF
|
ADVERTISE_100FULL
);
{
uint16_t
reg
=
mdio_read
(
phy_addr
,
MII_BMCR
);
mdio_write
(
phy_addr
,
MII_BMCR
,
reg
|
BMCR_ANRESTART
);
}
while
(
1
)
{
uint16_t
status
=
mdio_read
(
phy_addr
,
MII_BMSR
);
phy_speed_new
=
0
;
if
((
status
&
(
BMSR_ANEGCAPABLE
|
BMSR_LSTATUS
))
==
(
BMSR_ANEGCAPABLE
|
BMSR_LSTATUS
))
{
phy_speed_new
=
PHY_LINK_MASK
;
status
=
mdio_read
(
phy_addr
,
MII_LPA
);
if
(
status
&
PHY_ANLPA_DR100_TX_FULL
)
{
phy_speed_new
|=
PHY_100FULL_MASK
;
}
else
if
(
status
&
PHY_ANLPA_DR100_TX_HALF
)
{
phy_speed_new
|=
PHY_100HALF_MASK
;
}
else
if
(
status
&
PHY_ANLPA_DR10_TX_FULL
)
{
phy_speed_new
|=
PHY_10FULL_MASK
;
}
else
if
(
status
&
PHY_ANLPA_DR10_TX_HALF
)
{
phy_speed_new
|=
PHY_10HALF_MASK
;
}
}
/* linkchange */
if
(
phy_speed_new
!=
phy_speed
)
{
if
(
phy_speed_new
&
PHY_LINK_MASK
)
{
ETH_TRACE
(
"link up "
);
if
(
phy_speed_new
&
PHY_100FULL_MASK
)
{
ETH_TRACE
(
"100Mbps full-duplex
\n
"
);
EMAC
->
CTL
|=
(
EMAC_CTL_OPMODE_Msk
|
EMAC_CTL_FUDUP_Msk
);
}
else
if
(
phy_speed_new
&
PHY_100HALF_MASK
)
{
ETH_TRACE
(
"100Mbps half-duplex
\n
"
);
EMAC
->
CTL
=
(
EMAC
->
CTL
&
~
EMAC_CTL_FUDUP_Msk
)
|
EMAC_CTL_OPMODE_Msk
;
}
else
if
(
phy_speed_new
&
PHY_10FULL_MASK
)
{
ETH_TRACE
(
"10Mbps full-duplex
\n
"
);
EMAC
->
CTL
=
(
EMAC
->
CTL
&
~
EMAC_CTL_OPMODE_Msk
)
|
EMAC_CTL_FUDUP_Msk
;
}
else
{
ETH_TRACE
(
"10Mbps half-duplex
\n
"
);
EMAC
->
CTL
&=
~
(
EMAC_CTL_OPMODE_Msk
|
EMAC_CTL_FUDUP_Msk
);
}
/* send link up. */
eth_device_linkchange
(
&
eth
,
RT_TRUE
);
}
/* link up. */
else
{
ETH_TRACE
(
"link down
\r\n
"
);
/* send link down. */
eth_device_linkchange
(
&
eth
,
RT_FALSE
);
}
/* link down. */
phy_speed
=
phy_speed_new
;
}
/* linkchange */
rt_thread_delay
(
RT_TICK_PER_SECOND
);
}
/* while(1) */
}
static
rt_err_t
rt_m480_emac_init
(
rt_device_t
dev
)
{
/* Unlock protected registers */
SYS_UnlockReg
();
CLK_EnableModuleClock
(
EMAC_MODULE
);
// Configure MDC clock rate to HCLK / (127 + 1) = 1.5 MHz if system is running at 192 MHz
CLK_SetModuleClock
(
EMAC_MODULE
,
0
,
CLK_CLKDIV3_EMAC
(
127
));
// Configure RMII pins
// SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
SYS
->
GPA_MFPL
|=
SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV
;
SYS
->
GPC_MFPL
|=
SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1
|
SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0
;
SYS
->
GPC_MFPH
|=
SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK
;
SYS
->
GPE_MFPH
|=
SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC
|
SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO
|
SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0
|
SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1
|
SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN
;
// Enable high slew rate on all RMII TX output pins
PE
->
SLEWCTL
=
(
GPIO_SLEWCTL_HIGH
<<
GPIO_SLEWCTL_HSREN10_Pos
)
|
(
GPIO_SLEWCTL_HIGH
<<
GPIO_SLEWCTL_HSREN11_Pos
)
|
(
GPIO_SLEWCTL_HIGH
<<
GPIO_SLEWCTL_HSREN12_Pos
);
/* Lock protected registers */
SYS_LockReg
();
EMAC_init
();
NVIC_SetPriority
(
EMAC_TX_IRQn
,
1
);
NVIC_EnableIRQ
(
EMAC_TX_IRQn
);
NVIC_SetPriority
(
EMAC_RX_IRQn
,
1
);
NVIC_EnableIRQ
(
EMAC_RX_IRQn
);
rt_sem_init
(
&
eth_sem
,
"eth_sem"
,
0
,
RT_IPC_FLAG_FIFO
);
rt_thread_init
(
&
eth_tid
,
"eth"
,
eth_entry
,
RT_NULL
,
eth_stack
,
sizeof
(
eth_stack
),
RT_THREAD_PRIORITY_MAX
-
2
,
10
);
rt_thread_startup
(
&
eth_tid
);
#if LWIP_IPV4 && LWIP_IGMP
netif_set_igmp_mac_filter
(
eth
.
netif
,
igmp_mac_filter
);
#endif
/* LWIP_IPV4 && LWIP_IGMP */
return
RT_EOK
;
}
static
rt_err_t
rt_m480_emac_open
(
rt_device_t
dev
,
rt_uint16_t
oflag
)
{
return
RT_EOK
;
}
static
rt_err_t
rt_m480_emac_close
(
rt_device_t
dev
)
{
return
RT_EOK
;
}
static
rt_size_t
rt_m480_emac_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_m480_emac_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_m480_emac_control
(
rt_device_t
dev
,
int
cmd
,
void
*
args
)
{
switch
(
cmd
)
{
case
NIOCTL_GADDR
:
/* get mac address */
if
(
args
)
rt_memcpy
(
args
,
eth_addr
,
6
);
else
return
-
RT_ERROR
;
break
;
default
:
break
;
}
return
RT_EOK
;
}
rt_err_t
rt_m480_emac_tx
(
rt_device_t
dev
,
struct
pbuf
*
p
)
{
struct
pbuf
*
q
;
rt_uint32_t
offset
;
rt_uint8_t
*
buf
;
buf
=
emac_get_tx_buf
();
/* get free tx buffer */
if
(
buf
==
RT_NULL
)
{
rt_sem_control
(
&
eth_sem
,
RT_IPC_CMD_RESET
,
0
);
EMAC
->
INTSTS
=
EMAC_INTSTS_TXCPIF_Msk
;
EMAC
->
INTEN
|=
EMAC_INTEN_TXCPIEN_Msk
;
do
{
rt_sem_take
(
&
eth_sem
,
1
);
buf
=
emac_get_tx_buf
();
}
while
(
buf
==
RT_NULL
);
}
offset
=
0
;
for
(
q
=
p
;
q
!=
NULL
;
q
=
q
->
next
)
{
rt_uint8_t
*
ptr
;
rt_uint32_t
len
;
len
=
q
->
len
;
ptr
=
q
->
payload
;
// todo 优化复制
memcpy
(
&
buf
[
offset
],
ptr
,
len
);
offset
+=
len
;
}
#ifdef ETH_TX_DUMP
packet_dump
(
"TX dump"
,
p
);
#endif
ETH_trigger_tx
(
offset
);
if
(
EMAC
->
INTSTS
&
EMAC_INTSTS_TDUIF_Msk
)
{
EMAC
->
INTSTS
=
EMAC_INTSTS_TDUIF_Msk
;
ETH_TRIGGER_TX
();
}
/* Return SUCCESS */
return
RT_EOK
;
}
struct
pbuf
*
rt_m480_emac_rx
(
rt_device_t
dev
)
{
unsigned
int
status
;
struct
pbuf
*
p
;
/* init p pointer */
p
=
RT_NULL
;
start:
status
=
cur_rx_desc_ptr
->
status1
;
if
(
status
&
OWNERSHIP_EMAC
)
{
goto
end
;
}
if
((
status
&
RXFD_RXGD
)
&&
!
(
status
&
EMAC_DMARXDESC_CRCEIF_Msk
))
{
p
=
pbuf_alloc
(
PBUF_RAW
,
status
&
0xFFFF
,
PBUF_RAM
);
if
(
p
!=
RT_NULL
)
{
RT_ASSERT
(
p
->
next
==
RT_NULL
);
const
char
*
from
=
(
const
char
*
)(
cur_rx_desc_ptr
->
buf
);
// todo 优化复制
memcpy
(
p
->
payload
,
from
,
p
->
len
);
}
}
#ifdef ETH_RX_DUMP
packet_dump
(
"RX dump"
,
p
);
#endif
/* ETH_RX_DUMP */
cur_rx_desc_ptr
->
status1
=
OWNERSHIP_EMAC
;
cur_rx_desc_ptr
=
cur_rx_desc_ptr
->
next
;
if
(
p
==
RT_NULL
)
{
goto
start
;
}
return
p
;
end:
if
(
!
(
EMAC
->
INTEN
&
EMAC_INTEN_RDUIEN_Msk
))
{
EMAC
->
INTSTS
=
(
EMAC_INTSTS_RDUIF_Msk
|
EMAC_INTSTS_RXGDIF_Msk
);
EMAC
->
INTEN
|=
(
EMAC_INTEN_RDUIEN_Msk
|
EMAC_INTEN_RXGDIEN_Msk
);
ETH_TRIGGER_RX
();
}
else
{
EMAC
->
INTSTS
=
EMAC_INTSTS_RXGDIF_Msk
;
EMAC
->
INTEN
|=
EMAC_INTEN_RXGDIEN_Msk
;
}
return
RT_NULL
;
}
static
void
rt_hw_m480_emac_register
(
char
*
dev_name
)
{
rt_uint32_t
value
=
0
;
SYS_UnlockReg
();
FMC_Open
();
for
(
rt_uint8_t
i
=
0
;
i
<
3
;
i
++
)
{
value
+=
FMC_ReadUID
(
i
);
}
FMC_Close
();
SYS_LockReg
();
eth_addr
[
0
]
=
0x00
;
eth_addr
[
1
]
=
0x00
;
eth_addr
[
2
]
=
0x00
;
eth_addr
[
3
]
=
(
value
>>
16
)
&
0xff
;
eth_addr
[
4
]
=
(
value
>>
8
)
&
0xff
;
eth_addr
[
5
]
=
(
value
)
&
0xff
;
eth
.
parent
.
init
=
rt_m480_emac_init
;
eth
.
parent
.
open
=
rt_m480_emac_open
;
eth
.
parent
.
close
=
rt_m480_emac_close
;
eth
.
parent
.
read
=
rt_m480_emac_read
;
eth
.
parent
.
write
=
rt_m480_emac_write
;
eth
.
parent
.
control
=
rt_m480_emac_control
;
eth
.
parent
.
user_data
=
RT_NULL
;
eth
.
eth_rx
=
rt_m480_emac_rx
;
eth
.
eth_tx
=
rt_m480_emac_tx
;
/* register eth device */
eth_device_init
(
&
eth
,
dev_name
);
}
static
int
rt_hw_nuc487_emac_init
(
void
)
{
rt_hw_m480_emac_register
(
"eh0"
);
return
RT_EOK
;
}
INIT_APP_EXPORT
(
rt_hw_nuc487_emac_init
);
#endif
bsp/nuvoton_m487/driver/drv_emac.h
0 → 100644
浏览文件 @
a7babadb
/*
* Copyright (c) 2016 Nuvoton Technology Corp.
* Description: M480 EMAC driver header file
*/
#include "NuMicro.h"
#ifndef _M480_ETH_
#define _M480_ETH_
/* Generic MII registers. */
#define MII_BMCR 0x00
/* Basic mode control register */
#define MII_BMSR 0x01
/* Basic mode status register */
#define MII_PHYSID1 0x02
/* PHYS ID 1 */
#define MII_PHYSID2 0x03
/* PHYS ID 2 */
#define MII_ADVERTISE 0x04
/* Advertisement control reg */
#define MII_LPA 0x05
/* Link partner ability reg */
#define MII_EXPANSION 0x06
/* Expansion register */
#define MII_DCOUNTER 0x12
/* Disconnect counter */
#define MII_FCSCOUNTER 0x13
/* False carrier counter */
#define MII_NWAYTEST 0x14
/* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15
/* Receive error counter */
#define MII_SREVISION 0x16
/* Silicon revision */
#define MII_RESV1 0x17
/* Reserved... */
#define MII_LBRERROR 0x18
/* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19
/* PHY address */
#define MII_RESV2 0x1a
/* Reserved... */
#define MII_TPISTATUS 0x1b
/* TPI status for 10mbps */
#define MII_NCONFIG 0x1c
/* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x007f
/* Unused... */
#define BMCR_CTST 0x0080
/* Collision test */
#define BMCR_FULLDPLX 0x0100
/* Full duplex */
#define BMCR_ANRESTART 0x0200
/* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400
/* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800
/* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000
/* Enable auto negotiation */
#define BMCR_SPEED100 0x2000
/* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000
/* TXD loopback bits */
#define BMCR_RESET 0x8000
/* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001
/* Ext-reg capability */
#define BMSR_JCD 0x0002
/* Jabber detected */
#define BMSR_LSTATUS 0x0004
/* Link status */
#define BMSR_ANEGCAPABLE 0x0008
/* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010
/* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020
/* Auto-negotiation complete */
#define BMSR_RESV 0x07c0
/* Unused... */
#define BMSR_10HALF 0x0800
/* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000
/* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000
/* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000
/* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000
/* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f
/* Selector bits */
#define ADVERTISE_CSMA 0x0001
/* Only selector supported */
#define ADVERTISE_10HALF 0x0020
/* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040
/* Try for 10mbps full-duplex */
#define ADVERTISE_100HALF 0x0080
/* Try for 100mbps half-duplex */
#define ADVERTISE_100FULL 0x0100
/* Try for 100mbps full-duplex */
#define ADVERTISE_100BASE4 0x0200
/* Try for 100mbps 4k packets */
#define ADVERTISE_RESV 0x1c00
/* Unused... */
#define ADVERTISE_RFAULT 0x2000
/* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000
/* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000
/* Next page bit */
#define RX_DESCRIPTOR_NUM 4 // Max Number of Rx Frame Descriptors
#define TX_DESCRIPTOR_NUM 2 // Max number of Tx Frame Descriptors
#define PACKET_BUFFER_SIZE 1520
#define CONFIG_PHY_ADDR 1
// Frame Descriptor's Owner bit
#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC
//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU
// Rx Frame Descriptor Status
#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received
#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available
// Tx Frame Descriptor's Control bits
#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable
#define TXFD_INTEN 0x04 // Interrupt Enable
#define TXFD_CRCAPP 0x02 // Append CRC
#define TXFD_PADEN 0x01 // Padding Enable
// Tx Frame Descriptor Status
#define TXFD_TXCP 0x00080000 // Transmission Completion
#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available
// Tx/Rx buffer descriptor structure
struct
eth_descriptor
;
struct
eth_descriptor
{
uint32_t
status1
;
uint8_t
*
buf
;
uint32_t
status2
;
struct
eth_descriptor
*
next
;
#ifdef TIME_STAMPING
u32_t
backup1
;
u32_t
backup2
;
u32_t
reserved1
;
u32_t
reserved2
;
#endif
};
#ifdef TIME_STAMPING
#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)
#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)
s32_t
ETH_settime
(
u32_t
sec
,
u32_t
nsec
);
s32_t
ETH_gettime
(
u32_t
*
sec
,
u32_t
*
nsec
);
s32_t
ETH_updatetime
(
u32_t
neg
,
u32_t
sec
,
u32_t
nsec
);
s32_t
ETH_adjtimex
(
int
ppm
);
void
ETH_setinc
(
void
);
#endif
#endif
/* _M480_ETH_ */
bsp/nuvoton_m487/driver/drv_uart.c
浏览文件 @
a7babadb
...
...
@@ -315,11 +315,6 @@ static rt_err_t usart_control(struct rt_serial_device *serial,
}
break
;
// TODO 完善DMA接口
// case RT_DEVICE_FLAG_DMA_TX:
// USART_DMACmd(dev->usart_base, USART_DMAReq_Tx, ENABLE);
// stm32_uart_tx_dma_configure(dev, RT_TRUE);
// stm32_uart_tx_dma_nvic(dev, RT_TRUE);
// break;
default:
RT_ASSERT
(
0
)
;
...
...
@@ -365,9 +360,9 @@ static int usart_receive(struct rt_serial_device *serial)
/**
* @brief 串口设备注册
* @param uart : UART设备结构体
* @param uart_base :
STM32
UART外设基地址
* @param name :
STM32
UART设备名
* @param tx_dma_channel :
STM32
UART TX的DMA通道基地址(可选)
* @param uart_base : UART外设基地址
* @param name : UART设备名
* @param tx_dma_channel : UART TX的DMA通道基地址(可选)
*/
static
void
rt_hw_uart_register
(
usart_t
usart
,
UART_T
*
uart_base
,
char
*
name
)
{
...
...
bsp/nuvoton_m487/rtconfig.h
浏览文件 @
a7babadb
...
...
@@ -36,6 +36,7 @@
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 128
#define RT_CONSOLE_DEVICE_NAME "uart0"
#define RT_VER_NUM 0x40000
/* RT-Thread Components */
...
...
@@ -147,11 +148,6 @@
/* RT-Thread online packages */
/* system packages */
/* RT-Thread GUI Engine */
/* IoT - internet of things */
...
...
@@ -163,6 +159,9 @@
/* Wiced WiFi */
/* IoT Cloud */
/* security packages */
...
...
@@ -175,10 +174,16 @@
/* tools packages */
/* system packages */
/* peripheral libraries and drivers */
/* miscellaneous packages */
/*
example package: hello
*/
/*
samples: kernel and components samples
*/
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录