Skip to content

Commit 34caf43

Browse files
authored
Merge pull request #2238 from OpenNuvoton/nuc472
[NUC472] Add NUMAKER-PFM-NUC472
2 parents afe431b + a4b2517 commit 34caf43

File tree

107 files changed

+60339
-3
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+60339
-3
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (c) 2012-2015, ARM Limited, All Rights Reserved
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
* not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#ifndef LWIPOPTS_CONF_H
19+
#define LWIPOPTS_CONF_H
20+
21+
#define LWIP_TRANSPORT_ETHERNET 1
22+
#define ETH_PAD_SIZE 2
23+
24+
#define MEM_SIZE (16*1024)//(8*1024)//(16*1024)
25+
26+
#endif
Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
/*
2+
* Copyright (c) 2013 Nuvoton Technology Corp.
3+
*
4+
* See file CREDITS for list of people who contributed to this
5+
* project.
6+
*
7+
* This program is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU General Public License as
9+
* published by the Free Software Foundation; either version 2 of
10+
* the License, or (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20+
* MA 02111-1307 USA
21+
*
22+
* Description: NUC472 MAC driver source file
23+
*/
24+
#include "nuc472_eth.h"
25+
#include "lwip/opt.h"
26+
#include "lwip/def.h"
27+
28+
29+
#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
30+
#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
31+
#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)
32+
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)
33+
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
34+
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)
35+
36+
#ifdef __ICCARM__
37+
#pragma data_alignment=4
38+
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
39+
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
40+
#else
41+
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
42+
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
43+
#endif
44+
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
45+
46+
u8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
47+
u8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
48+
49+
extern void ethernetif_input(u16_t len, u8_t *buf, u32_t s, u32_t ns);
50+
extern void ethernetif_loopback_input(struct pbuf *p);
51+
52+
// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
53+
// Assume we want to set each tick to 100ns.
54+
// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
55+
// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
56+
// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
57+
58+
59+
60+
static void mdio_write(u8_t addr, u8_t reg, u16_t val)
61+
{
62+
63+
EMAC->MIIMDAT = val;
64+
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
65+
66+
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
67+
68+
}
69+
70+
71+
static u16_t mdio_read(u8_t addr, u8_t reg)
72+
{
73+
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
74+
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
75+
76+
return(EMAC->MIIMDAT);
77+
}
78+
79+
static int reset_phy(void)
80+
{
81+
82+
u16_t reg;
83+
u32_t delay;
84+
85+
86+
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
87+
88+
delay = 2000;
89+
while(delay-- > 0) {
90+
if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
91+
break;
92+
93+
}
94+
95+
if(delay == 0) {
96+
printf("Reset phy failed\n");
97+
return(-1);
98+
}
99+
100+
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
101+
ADVERTISE_10HALF |
102+
ADVERTISE_10FULL |
103+
ADVERTISE_100HALF |
104+
ADVERTISE_100FULL);
105+
106+
reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);
107+
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
108+
109+
delay = 200000;
110+
while(delay-- > 0) {
111+
if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
112+
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
113+
break;
114+
}
115+
116+
if(delay == 0) {
117+
printf("AN failed. Set to 100 FULL\n");
118+
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
119+
return(-1);
120+
} else {
121+
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
122+
123+
if(reg & ADVERTISE_100FULL) {
124+
printf("100 full\n");
125+
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
126+
} else if(reg & ADVERTISE_100HALF) {
127+
printf("100 half\n");
128+
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
129+
} else if(reg & ADVERTISE_10FULL) {
130+
printf("10 full\n");
131+
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
132+
} else {
133+
printf("10 half\n");
134+
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
135+
}
136+
}
137+
138+
return(0);
139+
}
140+
141+
142+
static void init_tx_desc(void)
143+
{
144+
u32_t i;
145+
146+
147+
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
148+
149+
for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
150+
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
151+
tx_desc[i].buf = &tx_buf[i][0];
152+
tx_desc[i].status2 = 0;
153+
tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
154+
155+
}
156+
EMAC->TXDSA = (unsigned int)&tx_desc[0];
157+
return;
158+
}
159+
160+
static void init_rx_desc(void)
161+
{
162+
u32_t i;
163+
164+
165+
cur_rx_desc_ptr = &rx_desc[0];
166+
167+
for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
168+
rx_desc[i].status1 = OWNERSHIP_EMAC;
169+
rx_desc[i].buf = &rx_buf[i][0];
170+
rx_desc[i].status2 = 0;
171+
rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
172+
}
173+
EMAC->RXDSA = (unsigned int)&rx_desc[0];
174+
return;
175+
}
176+
177+
static void set_mac_addr(u8_t *addr)
178+
{
179+
180+
EMAC->CAM0M = (addr[0] << 24) |
181+
(addr[1] << 16) |
182+
(addr[2] << 8) |
183+
addr[3];
184+
185+
EMAC->CAM0L = (addr[4] << 24) |
186+
(addr[5] << 16);
187+
188+
EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | EMAC_CAMCTL_AMP_Msk | EMAC_CAMCTL_ABP_Msk;
189+
EMAC->CAMEN = 1; // Enable CAM entry 0
190+
191+
}
192+
193+
static void __eth_clk_pin_init()
194+
{
195+
/* Enable IP clock */
196+
CLK_EnableModuleClock(EMAC_MODULE);
197+
// Configure MDC clock rate to HCLK / (127 + 1) = 656 kHz if system is running at 84 MHz
198+
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
199+
/*---------------------------------------------------------------------------------------------------------*/
200+
/* Init I/O Multi-function */
201+
/*---------------------------------------------------------------------------------------------------------*/
202+
// Configure RMII pins
203+
SYS->GPC_MFPL |= SYS_GPC_MFPL_PC0MFP_EMAC_REFCLK |
204+
SYS_GPC_MFPL_PC1MFP_EMAC_MII_RXERR |
205+
SYS_GPC_MFPL_PC2MFP_EMAC_MII_RXDV |
206+
SYS_GPC_MFPL_PC3MFP_EMAC_MII_RXD1 |
207+
SYS_GPC_MFPL_PC4MFP_EMAC_MII_RXD0 |
208+
SYS_GPC_MFPL_PC6MFP_EMAC_MII_TXD0 |
209+
SYS_GPC_MFPL_PC7MFP_EMAC_MII_TXD1;
210+
211+
212+
SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_MII_TXEN;
213+
// Enable high slew rate on all RMII pins
214+
PC->SLEWCTL |= 0x1DF;
215+
216+
// Configure MDC, MDIO at PB14 & PB15
217+
SYS->GPB_MFPH |= SYS_GPB_MFPH_PB14MFP_EMAC_MII_MDC | SYS_GPB_MFPH_PB15MFP_EMAC_MII_MDIO;
218+
219+
}
220+
221+
void ETH_init(u8_t *mac_addr)
222+
{
223+
// init CLK & pins
224+
__eth_clk_pin_init();
225+
226+
// Reset MAC
227+
EMAC->CTL = EMAC_CTL_RST_Msk;
228+
229+
init_tx_desc();
230+
init_rx_desc();
231+
232+
set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc...
233+
reset_phy();
234+
235+
EMAC->CTL |= EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk | EMAC_CTL_RMIIEN_Msk | EMAC_CTL_RMIIRXCTL_Msk;
236+
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
237+
EMAC_INTEN_RXGDIEN_Msk |
238+
EMAC_INTEN_RDUIEN_Msk |
239+
EMAC_INTEN_RXBEIEN_Msk |
240+
EMAC_INTEN_TXIEN_Msk |
241+
EMAC_INTEN_TXABTIEN_Msk |
242+
EMAC_INTEN_TXCPIEN_Msk |
243+
EMAC_INTEN_TXBEIEN_Msk;
244+
EMAC->RXST = 0; // trigger Rx
245+
}
246+
247+
248+
249+
void ETH_halt(void)
250+
{
251+
252+
EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);
253+
}
254+
255+
256+
257+
void EMAC_RX_IRQHandler(void)
258+
{
259+
unsigned int cur_entry, status;
260+
261+
status = EMAC->INTSTS & 0xFFFF;
262+
EMAC->INTSTS = status;
263+
if (status & EMAC_INTSTS_RXBEIF_Msk) {
264+
// Shouldn't goes here, unless descriptor corrupted
265+
printf("RX descriptor corrupted \r\n");
266+
//return;
267+
}
268+
ack_emac_rx_isr();
269+
}
270+
271+
void EMAC_RX_Action(void)
272+
{
273+
unsigned int cur_entry, status;
274+
do {
275+
276+
cur_entry = EMAC->CRXDSA;
277+
278+
if ((cur_entry == (u32_t)cur_rx_desc_ptr) && (!(status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures
279+
break;
280+
status = cur_rx_desc_ptr->status1;
281+
282+
if(status & OWNERSHIP_EMAC)
283+
break;
284+
285+
if (status & RXFD_RXGD) {
286+
// Lwip will invoke osMutexWait for resource protection, so ethernetif_input can't be called in EMAC_RX_IRQHandler.
287+
ethernetif_input(status & 0xFFFF, cur_rx_desc_ptr->buf, cur_rx_desc_ptr->status2, (u32_t)cur_rx_desc_ptr->next);
288+
289+
}
290+
291+
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
292+
cur_rx_desc_ptr = cur_rx_desc_ptr->next;
293+
294+
} while (1);
295+
296+
ETH_TRIGGER_RX();
297+
// eth_arch_tcpip_thread();
298+
}
299+
300+
void EMAC_TX_IRQHandler(void)
301+
{
302+
unsigned int cur_entry, status;
303+
304+
status = EMAC->INTSTS & 0xFFFF0000;
305+
EMAC->INTSTS = status;
306+
if(status & EMAC_INTSTS_TXBEIF_Msk) {
307+
// Shouldn't goes here, unless descriptor corrupted
308+
return;
309+
}
310+
311+
cur_entry = EMAC->CTXDSA;
312+
313+
while (cur_entry != (u32_t)fin_tx_desc_ptr) {
314+
315+
fin_tx_desc_ptr = fin_tx_desc_ptr->next;
316+
}
317+
318+
}
319+
320+
u8_t *ETH_get_tx_buf(void)
321+
{
322+
if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
323+
return(NULL);
324+
else
325+
return(cur_tx_desc_ptr->buf);
326+
}
327+
328+
void ETH_trigger_tx(u16_t length, struct pbuf *p)
329+
{
330+
struct eth_descriptor volatile *desc;
331+
cur_tx_desc_ptr->status2 = (unsigned int)length;
332+
desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
333+
cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;
334+
cur_tx_desc_ptr = desc;
335+
336+
ETH_TRIGGER_TX();
337+
338+
}
339+
340+
int ETH_link_ok()
341+
{
342+
/* first, a dummy read to latch */
343+
mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
344+
if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
345+
return 1;
346+
return 0;
347+
}

0 commit comments

Comments
 (0)