mirror of https://github.com/ARMmbed/mbed-os.git
M487, NUC472 EMAC code fulfill astyle
parent
68e9f4a8ed
commit
cda40b2788
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Nuvoton Technology Corp.
|
* Copyright (c) 2018 Nuvoton Technology Corp.
|
||||||
* Copyright (c) 2018 ARM Limited
|
* Copyright (c) 2018 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
|
@ -28,18 +28,18 @@
|
||||||
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0)
|
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0)
|
||||||
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
|
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
|
||||||
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0)
|
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0)
|
||||||
|
|
||||||
#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel))
|
#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel))
|
||||||
#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel))
|
#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel))
|
||||||
|
|
||||||
MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
|
MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
|
||||||
MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
|
MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
|
||||||
|
|
||||||
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
|
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
|
||||||
|
|
||||||
__attribute__ ((section("EMAC_RAM")))
|
__attribute__((section("EMAC_RAM")))
|
||||||
MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
|
MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
|
||||||
__attribute__ ((section("EMAC_RAM")))
|
__attribute__((section("EMAC_RAM")))
|
||||||
MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
|
MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
eth_callback_t nu_eth_txrx_cb = NULL;
|
eth_callback_t nu_eth_txrx_cb = NULL;
|
||||||
|
|
@ -74,7 +74,7 @@ static uint16_t mdio_read(uint8_t addr, uint8_t reg)
|
||||||
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
|
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
|
||||||
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
|
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
|
||||||
|
|
||||||
return(EMAC->MIIMDAT);
|
return (EMAC->MIIMDAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reset_phy(void)
|
static int reset_phy(void)
|
||||||
|
|
@ -87,16 +87,17 @@ static int reset_phy(void)
|
||||||
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
|
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
|
||||||
|
|
||||||
delayCnt = 2000;
|
delayCnt = 2000;
|
||||||
while(delayCnt > 0) {
|
while (delayCnt > 0) {
|
||||||
delayCnt--;
|
delayCnt--;
|
||||||
if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
|
if ((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(delayCnt == 0) {
|
if (delayCnt == 0) {
|
||||||
NU_DEBUGF(("Reset phy failed\n"));
|
NU_DEBUGF(("Reset phy failed\n"));
|
||||||
return(-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
|
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
|
||||||
|
|
@ -109,28 +110,29 @@ static int reset_phy(void)
|
||||||
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
|
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
|
||||||
|
|
||||||
delayCnt = 200000;
|
delayCnt = 200000;
|
||||||
while(delayCnt > 0) {
|
while (delayCnt > 0) {
|
||||||
delayCnt--;
|
delayCnt--;
|
||||||
if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
|
if ((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
|
||||||
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
|
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(delayCnt == 0) {
|
if (delayCnt == 0) {
|
||||||
NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
|
NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
|
||||||
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
||||||
return(-1);
|
return (-1);
|
||||||
} else {
|
} else {
|
||||||
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
|
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
|
||||||
phyLPAval = reg;
|
phyLPAval = reg;
|
||||||
|
|
||||||
if(reg & ADVERTISE_100FULL) {
|
if (reg & ADVERTISE_100FULL) {
|
||||||
NU_DEBUGF(("100 full\n"));
|
NU_DEBUGF(("100 full\n"));
|
||||||
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
||||||
} else if(reg & ADVERTISE_100HALF) {
|
} else if (reg & ADVERTISE_100HALF) {
|
||||||
NU_DEBUGF(("100 half\n"));
|
NU_DEBUGF(("100 half\n"));
|
||||||
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
|
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
|
||||||
} else if(reg & ADVERTISE_10FULL) {
|
} else if (reg & ADVERTISE_10FULL) {
|
||||||
NU_DEBUGF(("10 full\n"));
|
NU_DEBUGF(("10 full\n"));
|
||||||
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
|
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -138,10 +140,10 @@ static int reset_phy(void)
|
||||||
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1));
|
printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1));
|
||||||
printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2));
|
printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2));
|
||||||
|
|
||||||
return(0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -152,7 +154,7 @@ static void init_tx_desc(void)
|
||||||
|
|
||||||
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
|
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
|
||||||
|
|
||||||
for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
|
for (i = 0; i < TX_DESCRIPTOR_NUM; i++) {
|
||||||
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
|
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
|
||||||
tx_desc[i].buf = &tx_buf[i][0];
|
tx_desc[i].buf = &tx_buf[i][0];
|
||||||
tx_desc[i].status2 = 0;
|
tx_desc[i].status2 = 0;
|
||||||
|
|
@ -170,7 +172,7 @@ static void init_rx_desc(void)
|
||||||
|
|
||||||
cur_rx_desc_ptr = &rx_desc[0];
|
cur_rx_desc_ptr = &rx_desc[0];
|
||||||
|
|
||||||
for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
|
for (i = 0; i < RX_DESCRIPTOR_NUM; i++) {
|
||||||
rx_desc[i].status1 = OWNERSHIP_EMAC;
|
rx_desc[i].status1 = OWNERSHIP_EMAC;
|
||||||
rx_desc[i].buf = &rx_buf[i][0];
|
rx_desc[i].buf = &rx_buf[i][0];
|
||||||
rx_desc[i].status2 = 0;
|
rx_desc[i].status2 = 0;
|
||||||
|
|
@ -201,13 +203,13 @@ static void __eth_clk_pin_init()
|
||||||
|
|
||||||
/* Enable IP clock */
|
/* Enable IP clock */
|
||||||
CLK_EnableModuleClock(EMAC_MODULE);
|
CLK_EnableModuleClock(EMAC_MODULE);
|
||||||
|
|
||||||
// Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH
|
// Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH
|
||||||
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
|
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
|
||||||
|
|
||||||
/* Update System Core Clock */
|
/* Update System Core Clock */
|
||||||
SystemCoreClockUpdate();
|
SystemCoreClockUpdate();
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------------------------------*/
|
||||||
/* Init I/O Multi-function */
|
/* Init I/O Multi-function */
|
||||||
/*---------------------------------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
@ -221,10 +223,10 @@ static void __eth_clk_pin_init()
|
||||||
SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |
|
SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |
|
||||||
SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);
|
SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);
|
||||||
SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
|
SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
|
||||||
SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
|
SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
|
||||||
SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
|
SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
|
||||||
SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
|
SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
|
||||||
SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
|
SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
|
||||||
|
|
||||||
// Enable high slew rate on all RMII TX output pins
|
// Enable high slew rate on all RMII TX output pins
|
||||||
PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
|
PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
|
||||||
|
|
@ -240,13 +242,13 @@ static void __eth_clk_pin_init()
|
||||||
|
|
||||||
void numaker_eth_init(uint8_t *mac_addr)
|
void numaker_eth_init(uint8_t *mac_addr)
|
||||||
{
|
{
|
||||||
|
|
||||||
// init CLK & pins
|
// init CLK & pins
|
||||||
__eth_clk_pin_init();
|
__eth_clk_pin_init();
|
||||||
|
|
||||||
// Reset MAC
|
// Reset MAC
|
||||||
EMAC->CTL = EMAC_CTL_RST_Msk;
|
EMAC->CTL = EMAC_CTL_RST_Msk;
|
||||||
while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
|
while (EMAC->CTL & EMAC_CTL_RST_Msk) {}
|
||||||
|
|
||||||
init_tx_desc();
|
init_tx_desc();
|
||||||
init_rx_desc();
|
init_rx_desc();
|
||||||
|
|
@ -272,17 +274,15 @@ void numaker_eth_init(uint8_t *mac_addr)
|
||||||
EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
|
EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
|
||||||
EMAC_CAMCTL_AMP_Msk |
|
EMAC_CAMCTL_AMP_Msk |
|
||||||
EMAC_CAMCTL_ABP_Msk;
|
EMAC_CAMCTL_ABP_Msk;
|
||||||
EMAC->CAMEN = 1; // Enable CAM entry 0
|
EMAC->CAMEN = 1; // Enable CAM entry 0
|
||||||
/* Limit the max receive frame length to 1514 + 4 */
|
/* Limit the max receive frame length to 1514 + 4 */
|
||||||
EMAC->MRFL = NU_ETH_MAX_FLEN;
|
EMAC->MRFL = NU_ETH_MAX_FLEN;
|
||||||
|
|
||||||
/* Set RX FIFO threshold as 8 words */
|
/* Set RX FIFO threshold as 8 words */
|
||||||
EMAC->FIFOCTL = 0x00200100;
|
EMAC->FIFOCTL = 0x00200100;
|
||||||
|
|
||||||
if (isPhyReset != true)
|
if (isPhyReset != true) {
|
||||||
{
|
if (!reset_phy()) {
|
||||||
if (!reset_phy())
|
|
||||||
{
|
|
||||||
isPhyReset = true;
|
isPhyReset = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -298,9 +298,9 @@ void numaker_eth_init(uint8_t *mac_addr)
|
||||||
} else {
|
} else {
|
||||||
NU_DEBUGF(("10 half\n"));
|
NU_DEBUGF(("10 half\n"));
|
||||||
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EMAC_ENABLE_RX();
|
EMAC_ENABLE_RX();
|
||||||
EMAC_ENABLE_TX();
|
EMAC_ENABLE_TX();
|
||||||
|
|
||||||
|
|
@ -323,11 +323,15 @@ void EMAC_RX_IRQHandler(void)
|
||||||
if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
|
if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
|
||||||
// Shouldn't goes here, unless descriptor corrupted
|
// Shouldn't goes here, unless descriptor corrupted
|
||||||
mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status);
|
mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status);
|
||||||
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('B', nu_userData);
|
if (nu_eth_txrx_cb != NULL) {
|
||||||
|
nu_eth_txrx_cb('B', nu_userData);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk));
|
EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk));
|
||||||
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('R', nu_userData);
|
if (nu_eth_txrx_cb != NULL) {
|
||||||
|
nu_eth_txrx_cb('R', nu_userData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -342,31 +346,35 @@ int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)
|
||||||
unsigned int cur_entry, status;
|
unsigned int cur_entry, status;
|
||||||
|
|
||||||
cur_entry = EMAC->CRXDSA;
|
cur_entry = EMAC->CRXDSA;
|
||||||
if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures
|
if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) { // cur_entry may equal to cur_rx_desc_ptr if RDU occures
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
status = cur_rx_desc_ptr->status1;
|
status = cur_rx_desc_ptr->status1;
|
||||||
|
|
||||||
if(status & OWNERSHIP_EMAC)
|
if (status & OWNERSHIP_EMAC) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (status & RXFD_RXGD) {
|
if (status & RXFD_RXGD) {
|
||||||
*buf = cur_rx_desc_ptr->buf;
|
*buf = cur_rx_desc_ptr->buf;
|
||||||
*len = status & 0xFFFF;
|
*len = status & 0xFFFF;
|
||||||
// length of payload should be <= 1514
|
// length of payload should be <= 1514
|
||||||
if ( *len > (NU_ETH_MAX_FLEN - 4) ) {
|
if (*len > (NU_ETH_MAX_FLEN - 4)) {
|
||||||
NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
|
NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
|
||||||
*len = 0; // Skip this unexpected long packet
|
*len = 0; // Skip this unexpected long packet
|
||||||
}
|
}
|
||||||
if (*len == (NU_ETH_MAX_FLEN - 4)) NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
|
if (*len == (NU_ETH_MAX_FLEN - 4)) {
|
||||||
|
NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_rx_next(void)
|
void numaker_eth_rx_next(void)
|
||||||
{
|
{
|
||||||
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
|
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
|
||||||
cur_rx_desc_ptr = cur_rx_desc_ptr->next;
|
cur_rx_desc_ptr = cur_rx_desc_ptr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EMAC_TX_IRQHandler(void)
|
void EMAC_TX_IRQHandler(void)
|
||||||
{
|
{
|
||||||
|
|
@ -374,10 +382,12 @@ void EMAC_TX_IRQHandler(void)
|
||||||
|
|
||||||
status = EMAC->INTSTS & 0xFFFF0000;
|
status = EMAC->INTSTS & 0xFFFF0000;
|
||||||
EMAC->INTSTS = status;
|
EMAC->INTSTS = status;
|
||||||
if(status & EMAC_INTSTS_TXBEIF_Msk) {
|
if (status & EMAC_INTSTS_TXBEIF_Msk) {
|
||||||
// Shouldn't goes here, unless descriptor corrupted
|
// Shouldn't goes here, unless descriptor corrupted
|
||||||
mbed_error_printf("### TX Bus error [0x%x]\r\n", status);
|
mbed_error_printf("### TX Bus error [0x%x]\r\n", status);
|
||||||
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('B', nu_userData);
|
if (nu_eth_txrx_cb != NULL) {
|
||||||
|
nu_eth_txrx_cb('B', nu_userData);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -387,16 +397,19 @@ void EMAC_TX_IRQHandler(void)
|
||||||
|
|
||||||
fin_tx_desc_ptr = fin_tx_desc_ptr->next;
|
fin_tx_desc_ptr = fin_tx_desc_ptr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('T', nu_userData);
|
if (nu_eth_txrx_cb != NULL) {
|
||||||
|
nu_eth_txrx_cb('T', nu_userData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *numaker_eth_get_tx_buf(void)
|
uint8_t *numaker_eth_get_tx_buf(void)
|
||||||
{
|
{
|
||||||
if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
|
if (cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC) {
|
||||||
return(NULL);
|
return (NULL);
|
||||||
else
|
} else {
|
||||||
return(cur_tx_desc_ptr->buf);
|
return (cur_tx_desc_ptr->buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_trigger_tx(uint16_t length, void *p)
|
void numaker_eth_trigger_tx(uint16_t length, void *p)
|
||||||
|
|
@ -413,11 +426,12 @@ void numaker_eth_trigger_tx(uint16_t length, void *p)
|
||||||
|
|
||||||
int numaker_eth_link_ok(void)
|
int numaker_eth_link_ok(void)
|
||||||
{
|
{
|
||||||
/* first, a dummy read to latch */
|
/* first, a dummy read to latch */
|
||||||
mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
|
mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
|
||||||
if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
|
if (mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) {
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
|
void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
|
||||||
|
|
@ -439,8 +453,7 @@ void mbed_mac_address(char *mac)
|
||||||
// http://en.wikipedia.org/wiki/MAC_address
|
// http://en.wikipedia.org/wiki/MAC_address
|
||||||
uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
|
uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
|
||||||
|
|
||||||
if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash
|
if (word0 == 0xFFFFFFFF) { // Not burn any mac address at 1st 2 words of Data Flash
|
||||||
{
|
|
||||||
// with a semi-unique MAC address from the UUID
|
// with a semi-unique MAC address from the UUID
|
||||||
/* Enable FMC ISP function */
|
/* Enable FMC ISP function */
|
||||||
SYS_UnlockReg();
|
SYS_UnlockReg();
|
||||||
|
|
@ -448,34 +461,36 @@ void mbed_mac_address(char *mac)
|
||||||
// = FMC_ReadUID(0);
|
// = FMC_ReadUID(0);
|
||||||
uID1 = FMC_ReadUID(1);
|
uID1 = FMC_ReadUID(1);
|
||||||
word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
|
word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
|
||||||
word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);
|
word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF) << 12) | (FMC_ReadUID(2) & 0xFFF);
|
||||||
/* Disable FMC ISP function */
|
/* Disable FMC ISP function */
|
||||||
FMC_Close();
|
FMC_Close();
|
||||||
/* Lock protected registers */
|
/* Lock protected registers */
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
}
|
}
|
||||||
|
|
||||||
word1 |= 0x00000200;
|
word1 |= 0x00000200;
|
||||||
word1 &= 0x0000FEFF;
|
word1 &= 0x0000FEFF;
|
||||||
|
|
||||||
mac[0] = (word1 & 0x0000ff00) >> 8;
|
mac[0] = (word1 & 0x0000ff00) >> 8;
|
||||||
mac[1] = (word1 & 0x000000ff);
|
mac[1] = (word1 & 0x000000ff);
|
||||||
mac[2] = (word0 & 0xff000000) >> 24;
|
mac[2] = (word0 & 0xff000000) >> 24;
|
||||||
mac[3] = (word0 & 0x00ff0000) >> 16;
|
mac[3] = (word0 & 0x00ff0000) >> 16;
|
||||||
mac[4] = (word0 & 0x0000ff00) >> 8;
|
mac[4] = (word0 & 0x0000ff00) >> 8;
|
||||||
mac[5] = (word0 & 0x000000ff);
|
mac[5] = (word0 & 0x000000ff);
|
||||||
|
|
||||||
NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));
|
NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_enable_interrupts(void) {
|
void numaker_eth_enable_interrupts(void)
|
||||||
|
{
|
||||||
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
|
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
|
||||||
EMAC_INTEN_TXIEN_Msk ;
|
EMAC_INTEN_TXIEN_Msk ;
|
||||||
NVIC_EnableIRQ(EMAC_RX_IRQn);
|
NVIC_EnableIRQ(EMAC_RX_IRQn);
|
||||||
NVIC_EnableIRQ(EMAC_TX_IRQn);
|
NVIC_EnableIRQ(EMAC_TX_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_disable_interrupts(void) {
|
void numaker_eth_disable_interrupts(void)
|
||||||
NVIC_DisableIRQ(EMAC_RX_IRQn);
|
{
|
||||||
NVIC_DisableIRQ(EMAC_TX_IRQn);
|
NVIC_DisableIRQ(EMAC_RX_IRQn);
|
||||||
|
NVIC_DisableIRQ(EMAC_TX_IRQn);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Nuvoton Technology Corp.
|
* Copyright (c) 2018 Nuvoton Technology Corp.
|
||||||
* Copyright (c) 2018 ARM Limited
|
* Copyright (c) 2018 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
|
@ -28,18 +28,18 @@
|
||||||
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0)
|
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0)
|
||||||
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
|
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
|
||||||
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0)
|
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0)
|
||||||
|
|
||||||
#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel))
|
#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel))
|
||||||
#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel))
|
#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel))
|
||||||
|
|
||||||
MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
|
MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
|
||||||
MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
|
MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
|
||||||
|
|
||||||
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
|
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
|
||||||
|
|
||||||
__attribute__ ((section("EMAC_RAM")))
|
__attribute__((section("EMAC_RAM")))
|
||||||
MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
|
MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
|
||||||
__attribute__ ((section("EMAC_RAM")))
|
__attribute__((section("EMAC_RAM")))
|
||||||
MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
|
MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
eth_callback_t nu_eth_txrx_cb = NULL;
|
eth_callback_t nu_eth_txrx_cb = NULL;
|
||||||
|
|
@ -73,7 +73,7 @@ static uint16_t mdio_read(uint8_t addr, uint8_t reg)
|
||||||
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
|
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
|
||||||
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
|
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
|
||||||
|
|
||||||
return(EMAC->MIIMDAT);
|
return (EMAC->MIIMDAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reset_phy(void)
|
static int reset_phy(void)
|
||||||
|
|
@ -86,16 +86,17 @@ static int reset_phy(void)
|
||||||
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
|
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
|
||||||
|
|
||||||
delayCnt = 2000;
|
delayCnt = 2000;
|
||||||
while(delayCnt > 0) {
|
while (delayCnt > 0) {
|
||||||
delayCnt--;
|
delayCnt--;
|
||||||
if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
|
if ((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(delayCnt == 0) {
|
if (delayCnt == 0) {
|
||||||
NU_DEBUGF(("Reset phy failed\n"));
|
NU_DEBUGF(("Reset phy failed\n"));
|
||||||
return(-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
|
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
|
||||||
|
|
@ -108,28 +109,29 @@ static int reset_phy(void)
|
||||||
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
|
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
|
||||||
|
|
||||||
delayCnt = 200000;
|
delayCnt = 200000;
|
||||||
while(delayCnt > 0) {
|
while (delayCnt > 0) {
|
||||||
delayCnt--;
|
delayCnt--;
|
||||||
if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
|
if ((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
|
||||||
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
|
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(delayCnt == 0) {
|
if (delayCnt == 0) {
|
||||||
NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
|
NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
|
||||||
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
||||||
return(-1);
|
return (-1);
|
||||||
} else {
|
} else {
|
||||||
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
|
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
|
||||||
phyLPAval = reg;
|
phyLPAval = reg;
|
||||||
|
|
||||||
if(reg & ADVERTISE_100FULL) {
|
if (reg & ADVERTISE_100FULL) {
|
||||||
NU_DEBUGF(("100 full\n"));
|
NU_DEBUGF(("100 full\n"));
|
||||||
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
||||||
} else if(reg & ADVERTISE_100HALF) {
|
} else if (reg & ADVERTISE_100HALF) {
|
||||||
NU_DEBUGF(("100 half\n"));
|
NU_DEBUGF(("100 half\n"));
|
||||||
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
|
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
|
||||||
} else if(reg & ADVERTISE_10FULL) {
|
} else if (reg & ADVERTISE_10FULL) {
|
||||||
NU_DEBUGF(("10 full\n"));
|
NU_DEBUGF(("10 full\n"));
|
||||||
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
|
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -137,10 +139,10 @@ static int reset_phy(void)
|
||||||
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1));
|
printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1));
|
||||||
printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2));
|
printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2));
|
||||||
|
|
||||||
return(0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -151,7 +153,7 @@ static void init_tx_desc(void)
|
||||||
|
|
||||||
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
|
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
|
||||||
|
|
||||||
for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
|
for (i = 0; i < TX_DESCRIPTOR_NUM; i++) {
|
||||||
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
|
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
|
||||||
tx_desc[i].buf = &tx_buf[i][0];
|
tx_desc[i].buf = &tx_buf[i][0];
|
||||||
tx_desc[i].status2 = 0;
|
tx_desc[i].status2 = 0;
|
||||||
|
|
@ -169,7 +171,7 @@ static void init_rx_desc(void)
|
||||||
|
|
||||||
cur_rx_desc_ptr = &rx_desc[0];
|
cur_rx_desc_ptr = &rx_desc[0];
|
||||||
|
|
||||||
for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
|
for (i = 0; i < RX_DESCRIPTOR_NUM; i++) {
|
||||||
rx_desc[i].status1 = OWNERSHIP_EMAC;
|
rx_desc[i].status1 = OWNERSHIP_EMAC;
|
||||||
rx_desc[i].buf = &rx_buf[i][0];
|
rx_desc[i].buf = &rx_buf[i][0];
|
||||||
rx_desc[i].status2 = 0;
|
rx_desc[i].status2 = 0;
|
||||||
|
|
@ -199,7 +201,7 @@ static void __eth_clk_pin_init()
|
||||||
{
|
{
|
||||||
/* Unlock protected registers */
|
/* Unlock protected registers */
|
||||||
SYS_UnlockReg();
|
SYS_UnlockReg();
|
||||||
/* Enable IP clock */
|
/* Enable IP clock */
|
||||||
CLK_EnableModuleClock(EMAC_MODULE);
|
CLK_EnableModuleClock(EMAC_MODULE);
|
||||||
// Configure MDC clock rate to HCLK / (127 + 1) = 656 kHz if system is running at 84 MHz
|
// Configure MDC clock rate to HCLK / (127 + 1) = 656 kHz if system is running at 84 MHz
|
||||||
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
|
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
|
||||||
|
|
@ -209,16 +211,16 @@ static void __eth_clk_pin_init()
|
||||||
/* Init I/O Multi-function */
|
/* Init I/O Multi-function */
|
||||||
/*---------------------------------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------------------------------*/
|
||||||
// Configure RMII pins
|
// Configure RMII pins
|
||||||
SYS->GPC_MFPL &= ~( SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk |
|
SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk |
|
||||||
SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk |
|
SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk |
|
||||||
SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk );
|
SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk);
|
||||||
SYS->GPC_MFPL |= SYS_GPC_MFPL_PC0MFP_EMAC_REFCLK |
|
SYS->GPC_MFPL |= SYS_GPC_MFPL_PC0MFP_EMAC_REFCLK |
|
||||||
SYS_GPC_MFPL_PC1MFP_EMAC_MII_RXERR |
|
SYS_GPC_MFPL_PC1MFP_EMAC_MII_RXERR |
|
||||||
SYS_GPC_MFPL_PC2MFP_EMAC_MII_RXDV |
|
SYS_GPC_MFPL_PC2MFP_EMAC_MII_RXDV |
|
||||||
SYS_GPC_MFPL_PC3MFP_EMAC_MII_RXD1 |
|
SYS_GPC_MFPL_PC3MFP_EMAC_MII_RXD1 |
|
||||||
SYS_GPC_MFPL_PC4MFP_EMAC_MII_RXD0 |
|
SYS_GPC_MFPL_PC4MFP_EMAC_MII_RXD0 |
|
||||||
SYS_GPC_MFPL_PC6MFP_EMAC_MII_TXD0 |
|
SYS_GPC_MFPL_PC6MFP_EMAC_MII_TXD0 |
|
||||||
SYS_GPC_MFPL_PC7MFP_EMAC_MII_TXD1;
|
SYS_GPC_MFPL_PC7MFP_EMAC_MII_TXD1;
|
||||||
|
|
||||||
SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;
|
SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;
|
||||||
SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_MII_TXEN;
|
SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_MII_TXEN;
|
||||||
|
|
@ -229,18 +231,18 @@ static void __eth_clk_pin_init()
|
||||||
SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB14MFP_Msk | SYS_GPB_MFPH_PB15MFP_Msk);
|
SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB14MFP_Msk | SYS_GPB_MFPH_PB15MFP_Msk);
|
||||||
SYS->GPB_MFPH |= SYS_GPB_MFPH_PB14MFP_EMAC_MII_MDC | SYS_GPB_MFPH_PB15MFP_EMAC_MII_MDIO;
|
SYS->GPB_MFPH |= SYS_GPB_MFPH_PB14MFP_EMAC_MII_MDC | SYS_GPB_MFPH_PB15MFP_EMAC_MII_MDIO;
|
||||||
|
|
||||||
/* Lock protected registers */
|
/* Lock protected registers */
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_init(uint8_t *mac_addr)
|
void numaker_eth_init(uint8_t *mac_addr)
|
||||||
{
|
{
|
||||||
// init CLK & pins
|
// init CLK & pins
|
||||||
__eth_clk_pin_init();
|
__eth_clk_pin_init();
|
||||||
|
|
||||||
// Reset MAC
|
// Reset MAC
|
||||||
EMAC->CTL = EMAC_CTL_RST_Msk;
|
EMAC->CTL = EMAC_CTL_RST_Msk;
|
||||||
while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
|
while (EMAC->CTL & EMAC_CTL_RST_Msk) {}
|
||||||
|
|
||||||
init_tx_desc();
|
init_tx_desc();
|
||||||
init_rx_desc();
|
init_rx_desc();
|
||||||
|
|
@ -259,13 +261,11 @@ void numaker_eth_init(uint8_t *mac_addr)
|
||||||
EMAC_INTEN_TXBEIEN_Msk;
|
EMAC_INTEN_TXBEIEN_Msk;
|
||||||
/* Limit the max receive frame length to 1514 + 4 */
|
/* Limit the max receive frame length to 1514 + 4 */
|
||||||
EMAC->MRFL = NU_ETH_MAX_FLEN;
|
EMAC->MRFL = NU_ETH_MAX_FLEN;
|
||||||
|
|
||||||
/* Set RX FIFO threshold as 8 words */
|
/* Set RX FIFO threshold as 8 words */
|
||||||
|
|
||||||
if (isPhyReset != true)
|
if (isPhyReset != true) {
|
||||||
{
|
if (!reset_phy()) {
|
||||||
if (!reset_phy())
|
|
||||||
{
|
|
||||||
isPhyReset = true;
|
isPhyReset = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -281,9 +281,9 @@ void numaker_eth_init(uint8_t *mac_addr)
|
||||||
} else {
|
} else {
|
||||||
NU_DEBUGF(("10 half\n"));
|
NU_DEBUGF(("10 half\n"));
|
||||||
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EMAC_ENABLE_RX();
|
EMAC_ENABLE_RX();
|
||||||
EMAC_ENABLE_TX();
|
EMAC_ENABLE_TX();
|
||||||
|
|
||||||
|
|
@ -306,11 +306,15 @@ void EMAC_RX_IRQHandler(void)
|
||||||
if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
|
if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
|
||||||
// Shouldn't goes here, unless descriptor corrupted
|
// Shouldn't goes here, unless descriptor corrupted
|
||||||
mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status);
|
mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status);
|
||||||
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('B', nu_userData);
|
if (nu_eth_txrx_cb != NULL) {
|
||||||
|
nu_eth_txrx_cb('B', nu_userData);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk));
|
EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk));
|
||||||
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('R', nu_userData);
|
if (nu_eth_txrx_cb != NULL) {
|
||||||
|
nu_eth_txrx_cb('R', nu_userData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -325,31 +329,35 @@ int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)
|
||||||
unsigned int cur_entry, status;
|
unsigned int cur_entry, status;
|
||||||
|
|
||||||
cur_entry = EMAC->CRXDSA;
|
cur_entry = EMAC->CRXDSA;
|
||||||
if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures
|
if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) { // cur_entry may equal to cur_rx_desc_ptr if RDU occures
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
status = cur_rx_desc_ptr->status1;
|
status = cur_rx_desc_ptr->status1;
|
||||||
|
|
||||||
if(status & OWNERSHIP_EMAC)
|
if (status & OWNERSHIP_EMAC) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (status & RXFD_RXGD) {
|
if (status & RXFD_RXGD) {
|
||||||
*buf = cur_rx_desc_ptr->buf;
|
*buf = cur_rx_desc_ptr->buf;
|
||||||
*len = status & 0xFFFF;
|
*len = status & 0xFFFF;
|
||||||
// length of payload should be <= 1514
|
// length of payload should be <= 1514
|
||||||
if ( *len > (NU_ETH_MAX_FLEN - 4) ) {
|
if (*len > (NU_ETH_MAX_FLEN - 4)) {
|
||||||
NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
|
NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
|
||||||
*len = 0; // Skip this unexpected long packet
|
*len = 0; // Skip this unexpected long packet
|
||||||
}
|
}
|
||||||
if (*len == (NU_ETH_MAX_FLEN - 4)) NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
|
if (*len == (NU_ETH_MAX_FLEN - 4)) {
|
||||||
|
NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_rx_next(void)
|
void numaker_eth_rx_next(void)
|
||||||
{
|
{
|
||||||
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
|
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
|
||||||
cur_rx_desc_ptr = cur_rx_desc_ptr->next;
|
cur_rx_desc_ptr = cur_rx_desc_ptr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EMAC_TX_IRQHandler(void)
|
void EMAC_TX_IRQHandler(void)
|
||||||
{
|
{
|
||||||
|
|
@ -357,10 +365,12 @@ void EMAC_TX_IRQHandler(void)
|
||||||
|
|
||||||
status = EMAC->INTSTS & 0xFFFF0000;
|
status = EMAC->INTSTS & 0xFFFF0000;
|
||||||
EMAC->INTSTS = status;
|
EMAC->INTSTS = status;
|
||||||
if(status & EMAC_INTSTS_TXBEIF_Msk) {
|
if (status & EMAC_INTSTS_TXBEIF_Msk) {
|
||||||
// Shouldn't goes here, unless descriptor corrupted
|
// Shouldn't goes here, unless descriptor corrupted
|
||||||
mbed_error_printf("### TX Bus error [0x%x]\r\n", status);
|
mbed_error_printf("### TX Bus error [0x%x]\r\n", status);
|
||||||
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('B', nu_userData);
|
if (nu_eth_txrx_cb != NULL) {
|
||||||
|
nu_eth_txrx_cb('B', nu_userData);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -370,16 +380,19 @@ void EMAC_TX_IRQHandler(void)
|
||||||
|
|
||||||
fin_tx_desc_ptr = fin_tx_desc_ptr->next;
|
fin_tx_desc_ptr = fin_tx_desc_ptr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nu_eth_txrx_cb != NULL) nu_eth_txrx_cb('T', nu_userData);
|
if (nu_eth_txrx_cb != NULL) {
|
||||||
|
nu_eth_txrx_cb('T', nu_userData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *numaker_eth_get_tx_buf(void)
|
uint8_t *numaker_eth_get_tx_buf(void)
|
||||||
{
|
{
|
||||||
if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
|
if (cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC) {
|
||||||
return(NULL);
|
return (NULL);
|
||||||
else
|
} else {
|
||||||
return(cur_tx_desc_ptr->buf);
|
return (cur_tx_desc_ptr->buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_trigger_tx(uint16_t length, void *p)
|
void numaker_eth_trigger_tx(uint16_t length, void *p)
|
||||||
|
|
@ -396,11 +409,12 @@ void numaker_eth_trigger_tx(uint16_t length, void *p)
|
||||||
|
|
||||||
int numaker_eth_link_ok(void)
|
int numaker_eth_link_ok(void)
|
||||||
{
|
{
|
||||||
/* first, a dummy read to latch */
|
/* first, a dummy read to latch */
|
||||||
mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
|
mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
|
||||||
if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
|
if (mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) {
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
|
void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
|
||||||
|
|
@ -422,8 +436,7 @@ void mbed_mac_address(char *mac)
|
||||||
// http://en.wikipedia.org/wiki/MAC_address
|
// http://en.wikipedia.org/wiki/MAC_address
|
||||||
uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
|
uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
|
||||||
|
|
||||||
if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash
|
if (word0 == 0xFFFFFFFF) { // Not burn any mac address at 1st 2 words of Data Flash
|
||||||
{
|
|
||||||
// with a semi-unique MAC address from the UUID
|
// with a semi-unique MAC address from the UUID
|
||||||
/* Enable FMC ISP function */
|
/* Enable FMC ISP function */
|
||||||
SYS_UnlockReg();
|
SYS_UnlockReg();
|
||||||
|
|
@ -431,34 +444,36 @@ void mbed_mac_address(char *mac)
|
||||||
// = FMC_ReadUID(0);
|
// = FMC_ReadUID(0);
|
||||||
uID1 = FMC_ReadUID(1);
|
uID1 = FMC_ReadUID(1);
|
||||||
word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
|
word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
|
||||||
word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);
|
word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF) << 12) | (FMC_ReadUID(2) & 0xFFF);
|
||||||
/* Disable FMC ISP function */
|
/* Disable FMC ISP function */
|
||||||
FMC_Close();
|
FMC_Close();
|
||||||
/* Lock protected registers */
|
/* Lock protected registers */
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
}
|
}
|
||||||
|
|
||||||
word1 |= 0x00000200;
|
word1 |= 0x00000200;
|
||||||
word1 &= 0x0000FEFF;
|
word1 &= 0x0000FEFF;
|
||||||
|
|
||||||
mac[0] = (word1 & 0x0000ff00) >> 8;
|
mac[0] = (word1 & 0x0000ff00) >> 8;
|
||||||
mac[1] = (word1 & 0x000000ff);
|
mac[1] = (word1 & 0x000000ff);
|
||||||
mac[2] = (word0 & 0xff000000) >> 24;
|
mac[2] = (word0 & 0xff000000) >> 24;
|
||||||
mac[3] = (word0 & 0x00ff0000) >> 16;
|
mac[3] = (word0 & 0x00ff0000) >> 16;
|
||||||
mac[4] = (word0 & 0x0000ff00) >> 8;
|
mac[4] = (word0 & 0x0000ff00) >> 8;
|
||||||
mac[5] = (word0 & 0x000000ff);
|
mac[5] = (word0 & 0x000000ff);
|
||||||
|
|
||||||
NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));
|
NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_enable_interrupts(void) {
|
void numaker_eth_enable_interrupts(void)
|
||||||
|
{
|
||||||
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
|
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
|
||||||
EMAC_INTEN_TXIEN_Msk ;
|
EMAC_INTEN_TXIEN_Msk ;
|
||||||
NVIC_EnableIRQ(EMAC_RX_IRQn);
|
NVIC_EnableIRQ(EMAC_RX_IRQn);
|
||||||
NVIC_EnableIRQ(EMAC_TX_IRQn);
|
NVIC_EnableIRQ(EMAC_TX_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void numaker_eth_disable_interrupts(void) {
|
void numaker_eth_disable_interrupts(void)
|
||||||
NVIC_DisableIRQ(EMAC_RX_IRQn);
|
{
|
||||||
NVIC_DisableIRQ(EMAC_TX_IRQn);
|
NVIC_DisableIRQ(EMAC_RX_IRQn);
|
||||||
|
NVIC_DisableIRQ(EMAC_TX_IRQn);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018 Nuvoton Technology Corp.
|
* Copyright (c) 2018 Nuvoton Technology Corp.
|
||||||
* Copyright (c) 2018 ARM Limited
|
* Copyright (c) 2018 ARM Limited
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
#include "numaker_eth_hal.h"
|
#include "numaker_eth_hal.h"
|
||||||
|
|
||||||
/********************************************************************************
|
/********************************************************************************
|
||||||
*
|
*
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
#define NU_BUFF_ALIGNMENT 4
|
#define NU_BUFF_ALIGNMENT 4
|
||||||
#define PHY_LINKED_STATE 1
|
#define PHY_LINKED_STATE 1
|
||||||
|
|
@ -92,24 +92,23 @@ void NUMAKER_EMAC::bus_isr()
|
||||||
|
|
||||||
void NUMAKER_EMAC::tx_isr()
|
void NUMAKER_EMAC::tx_isr()
|
||||||
{
|
{
|
||||||
/* No-op at this stage */
|
/* No-op at this stage */
|
||||||
}
|
}
|
||||||
|
|
||||||
void NUMAKER_EMAC::ethernet_callback(char event, void *param)
|
void NUMAKER_EMAC::ethernet_callback(char event, void *param)
|
||||||
{
|
{
|
||||||
NUMAKER_EMAC *enet = static_cast<NUMAKER_EMAC *>(param);
|
NUMAKER_EMAC *enet = static_cast<NUMAKER_EMAC *>(param);
|
||||||
switch (event)
|
switch (event) {
|
||||||
{
|
case 'R': //For RX event
|
||||||
case 'R': //For RX event
|
enet->rx_isr();
|
||||||
enet->rx_isr();
|
break;
|
||||||
break;
|
case 'T': //For TX event
|
||||||
case 'T': //For TX event
|
enet->tx_isr();
|
||||||
enet->tx_isr();
|
break;
|
||||||
break;
|
case 'B': // For BUS event
|
||||||
case 'B': // For BUS event
|
enet->bus_isr();
|
||||||
enet->bus_isr();
|
default:
|
||||||
default:
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,13 +121,13 @@ bool NUMAKER_EMAC::low_level_init_successful()
|
||||||
/* Init ETH */
|
/* Init ETH */
|
||||||
|
|
||||||
mbed_mac_address((char *)hwaddr);
|
mbed_mac_address((char *)hwaddr);
|
||||||
printf("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]);
|
printf("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
|
||||||
/* Enable clock & set EMAC configuration */
|
/* Enable clock & set EMAC configuration */
|
||||||
/* Enable MAC and DMA transmission and reception */
|
/* Enable MAC and DMA transmission and reception */
|
||||||
numaker_eth_init(hwaddr);
|
numaker_eth_init(hwaddr);
|
||||||
|
|
||||||
numaker_eth_set_cb(&NUMAKER_EMAC::ethernet_callback, this);
|
numaker_eth_set_cb(&NUMAKER_EMAC::ethernet_callback, this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,7 +142,7 @@ int NUMAKER_EMAC::low_level_input(emac_mem_buf_t **buf)
|
||||||
uint32_t payloadoffset = 0;
|
uint32_t payloadoffset = 0;
|
||||||
|
|
||||||
/* get received frame */
|
/* get received frame */
|
||||||
if ( numaker_eth_get_rx_buf(&len, &buffer) != 0) {
|
if (numaker_eth_get_rx_buf(&len, &buffer) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
byteslefttocopy = len;
|
byteslefttocopy = len;
|
||||||
|
|
@ -158,10 +157,10 @@ int NUMAKER_EMAC::low_level_input(emac_mem_buf_t **buf)
|
||||||
for (q = *buf; q != NULL; q = memory_manager->get_next(q)) {
|
for (q = *buf; q != NULL; q = memory_manager->get_next(q)) {
|
||||||
byteslefttocopy = memory_manager->get_len(q);
|
byteslefttocopy = memory_manager->get_len(q);
|
||||||
payloadoffset = 0;
|
payloadoffset = 0;
|
||||||
NU_DEBUGF(("offset=[%d], bytes-to-copy[%d]\r\n",bufferoffset,byteslefttocopy));
|
NU_DEBUGF(("offset=[%d], bytes-to-copy[%d]\r\n", bufferoffset, byteslefttocopy));
|
||||||
/* Copy data in pbuf */
|
/* Copy data in pbuf */
|
||||||
memcpy(static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, static_cast<uint8_t *>(buffer) + bufferoffset, byteslefttocopy);
|
memcpy(static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, static_cast<uint8_t *>(buffer) + bufferoffset, byteslefttocopy);
|
||||||
|
|
||||||
bufferoffset = bufferoffset + byteslefttocopy;
|
bufferoffset = bufferoffset + byteslefttocopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -177,7 +176,7 @@ int NUMAKER_EMAC::low_level_input(emac_mem_buf_t **buf)
|
||||||
* \param[in] pvParameters pointer to the interface data
|
* \param[in] pvParameters pointer to the interface data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void NUMAKER_EMAC::thread_function(void* pvParameters)
|
void NUMAKER_EMAC::thread_function(void *pvParameters)
|
||||||
{
|
{
|
||||||
static struct NUMAKER_EMAC *nu_enet = static_cast<NUMAKER_EMAC *>(pvParameters);
|
static struct NUMAKER_EMAC *nu_enet = static_cast<NUMAKER_EMAC *>(pvParameters);
|
||||||
|
|
||||||
|
|
@ -186,7 +185,7 @@ void NUMAKER_EMAC::thread_function(void* pvParameters)
|
||||||
|
|
||||||
if (flags & FLAG_RX) {
|
if (flags & FLAG_RX) {
|
||||||
nu_enet->packet_rx();
|
nu_enet->packet_rx();
|
||||||
}
|
}
|
||||||
if (flags & FLAG_BUS_RESET) {
|
if (flags & FLAG_BUS_RESET) {
|
||||||
NU_DEBUGF(("BUS error and reset bus\r\n"));
|
NU_DEBUGF(("BUS error and reset bus\r\n"));
|
||||||
nu_enet->bus_reset();
|
nu_enet->bus_reset();
|
||||||
|
|
@ -201,20 +200,20 @@ void NUMAKER_EMAC::thread_function(void* pvParameters)
|
||||||
*/
|
*/
|
||||||
void NUMAKER_EMAC::packet_rx()
|
void NUMAKER_EMAC::packet_rx()
|
||||||
{
|
{
|
||||||
/* move received packet into a new buf */
|
/* move received packet into a new buf */
|
||||||
while (1) {
|
while (1) {
|
||||||
emac_mem_buf_t *p = NULL;
|
emac_mem_buf_t *p = NULL;
|
||||||
if (low_level_input(&p) < 0) {
|
if (low_level_input(&p) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (p) {
|
if (p) {
|
||||||
NU_DEBUGF(("%s ... p=0x%x\r\n",__FUNCTION__,p));
|
NU_DEBUGF(("%s ... p=0x%x\r\n", __FUNCTION__, p));
|
||||||
emac_link_input_cb(p);
|
emac_link_input_cb(p);
|
||||||
}
|
}
|
||||||
numaker_eth_rx_next();
|
numaker_eth_rx_next();
|
||||||
}
|
}
|
||||||
numaker_eth_trigger_rx();
|
numaker_eth_trigger_rx();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -245,15 +244,17 @@ bool NUMAKER_EMAC::link_out(emac_mem_buf_t *buf)
|
||||||
/* Get exclusive access */
|
/* Get exclusive access */
|
||||||
TXLockMutex.lock();
|
TXLockMutex.lock();
|
||||||
buffer = numaker_eth_get_tx_buf();
|
buffer = numaker_eth_get_tx_buf();
|
||||||
NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));
|
NU_DEBUGF(("%s ... buffer=0x%x\r\n", __FUNCTION__, buffer));
|
||||||
if( buffer == NULL ) goto error;
|
if (buffer == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
/* copy frame from buf to driver buffers */
|
/* copy frame from buf to driver buffers */
|
||||||
for (q = buf; q != NULL; q = memory_manager->get_next(q)) {
|
for (q = buf; q != NULL; q = memory_manager->get_next(q)) {
|
||||||
|
|
||||||
/* Get bytes in current lwIP buffer */
|
/* Get bytes in current lwIP buffer */
|
||||||
byteslefttocopy = memory_manager->get_len(q);
|
byteslefttocopy = memory_manager->get_len(q);
|
||||||
payloadoffset = 0;
|
payloadoffset = 0;
|
||||||
NU_DEBUGF(("offset=%d, bytes-to-copy=%d\r\n",bufferoffset, byteslefttocopy));
|
NU_DEBUGF(("offset=%d, bytes-to-copy=%d\r\n", bufferoffset, byteslefttocopy));
|
||||||
/* Check if the length of data to copy is bigger than Tx buffer size*/
|
/* Check if the length of data to copy is bigger than Tx buffer size*/
|
||||||
while ((byteslefttocopy + bufferoffset) > PACKET_BUFFER_SIZE) {
|
while ((byteslefttocopy + bufferoffset) > PACKET_BUFFER_SIZE) {
|
||||||
/* Copy data to Tx buffer*/
|
/* Copy data to Tx buffer*/
|
||||||
|
|
@ -262,20 +263,22 @@ bool NUMAKER_EMAC::link_out(emac_mem_buf_t *buf)
|
||||||
/* Point to next descriptor */
|
/* Point to next descriptor */
|
||||||
numaker_eth_trigger_tx(PACKET_BUFFER_SIZE, NULL);
|
numaker_eth_trigger_tx(PACKET_BUFFER_SIZE, NULL);
|
||||||
buffer = numaker_eth_get_tx_buf();
|
buffer = numaker_eth_get_tx_buf();
|
||||||
if( buffer == NULL ) goto error;
|
if (buffer == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
byteslefttocopy = byteslefttocopy - (PACKET_BUFFER_SIZE - bufferoffset);
|
byteslefttocopy = byteslefttocopy - (PACKET_BUFFER_SIZE - bufferoffset);
|
||||||
payloadoffset = payloadoffset + (PACKET_BUFFER_SIZE - bufferoffset);
|
payloadoffset = payloadoffset + (PACKET_BUFFER_SIZE - bufferoffset);
|
||||||
framelength = framelength + (PACKET_BUFFER_SIZE - bufferoffset);
|
framelength = framelength + (PACKET_BUFFER_SIZE - bufferoffset);
|
||||||
bufferoffset = 0;
|
bufferoffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the remaining bytes */
|
/* Copy the remaining bytes */
|
||||||
memcpy(static_cast<uint8_t *>(buffer) + bufferoffset, static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, byteslefttocopy);
|
memcpy(static_cast<uint8_t *>(buffer) + bufferoffset, static_cast<uint8_t *>(memory_manager->get_ptr(q)) + payloadoffset, byteslefttocopy);
|
||||||
bufferoffset = bufferoffset + byteslefttocopy;
|
bufferoffset = bufferoffset + byteslefttocopy;
|
||||||
framelength = framelength + byteslefttocopy;
|
framelength = framelength + byteslefttocopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare transmit descriptors to give to DMA */
|
/* Prepare transmit descriptors to give to DMA */
|
||||||
numaker_eth_trigger_tx(framelength, NULL);
|
numaker_eth_trigger_tx(framelength, NULL);
|
||||||
|
|
||||||
|
|
@ -294,66 +297,72 @@ error:
|
||||||
|
|
||||||
void NUMAKER_EMAC::phy_task()
|
void NUMAKER_EMAC::phy_task()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Get current status
|
// Get current status
|
||||||
int state;
|
int state;
|
||||||
state = numaker_eth_link_ok();
|
state = numaker_eth_link_ok();
|
||||||
|
|
||||||
|
|
||||||
if ((state & PHY_LINKED_STATE) && !(phy_state & PHY_LINKED_STATE)) {
|
if ((state & PHY_LINKED_STATE) && !(phy_state & PHY_LINKED_STATE)) {
|
||||||
NU_DEBUGF(("Link Up\r\n"));
|
NU_DEBUGF(("Link Up\r\n"));
|
||||||
if (emac_link_state_cb) emac_link_state_cb(true);
|
if (emac_link_state_cb) {
|
||||||
|
emac_link_state_cb(true);
|
||||||
|
}
|
||||||
} else if (!(state & PHY_LINKED_STATE) && (phy_state & PHY_LINKED_STATE)) {
|
} else if (!(state & PHY_LINKED_STATE) && (phy_state & PHY_LINKED_STATE)) {
|
||||||
NU_DEBUGF(("Link Down\r\n"));
|
NU_DEBUGF(("Link Down\r\n"));
|
||||||
if (emac_link_state_cb) emac_link_state_cb(false);
|
if (emac_link_state_cb) {
|
||||||
|
emac_link_state_cb(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
phy_state = state;
|
phy_state = state;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NUMAKER_EMAC::power_up()
|
bool NUMAKER_EMAC::power_up()
|
||||||
{
|
{
|
||||||
/* Initialize the hardware */
|
/* Initialize the hardware */
|
||||||
if (!low_level_init_successful())
|
if (!low_level_init_successful()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Worker thread */
|
/* Worker thread */
|
||||||
thread = create_new_thread("numaker_emac_thread", &NUMAKER_EMAC::thread_function, this, THREAD_STACKSIZE * 2, THREAD_PRIORITY, &thread_cb);
|
thread = create_new_thread("numaker_emac_thread", &NUMAKER_EMAC::thread_function, this, THREAD_STACKSIZE * 2, THREAD_PRIORITY, &thread_cb);
|
||||||
|
|
||||||
/* PHY monitoring task */
|
/* PHY monitoring task */
|
||||||
phy_state = PHY_UNLINKED_STATE;
|
phy_state = PHY_UNLINKED_STATE;
|
||||||
|
|
||||||
phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD_MS, mbed::callback(this, &NUMAKER_EMAC::phy_task));
|
phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD_MS, mbed::callback(this, &NUMAKER_EMAC::phy_task));
|
||||||
|
|
||||||
/* Allow the PHY task to detect the initial link state and set up the proper flags */
|
/* Allow the PHY task to detect the initial link state and set up the proper flags */
|
||||||
osDelay(10);
|
osDelay(10);
|
||||||
numaker_eth_enable_interrupts();
|
numaker_eth_enable_interrupts();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NUMAKER_EMAC::bus_reset()
|
bool NUMAKER_EMAC::bus_reset()
|
||||||
{
|
{
|
||||||
/* Initialize the hardware */
|
/* Initialize the hardware */
|
||||||
if (!low_level_init_successful())
|
if (!low_level_init_successful()) {
|
||||||
return false;
|
return false;
|
||||||
numaker_eth_enable_interrupts();
|
}
|
||||||
return true;
|
numaker_eth_enable_interrupts();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t NUMAKER_EMAC::get_mtu_size() const
|
uint32_t NUMAKER_EMAC::get_mtu_size() const
|
||||||
{
|
{
|
||||||
return NU_ETH_MTU_SIZE;
|
return NU_ETH_MTU_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t NUMAKER_EMAC::get_align_preference() const
|
uint32_t NUMAKER_EMAC::get_align_preference() const
|
||||||
{
|
{
|
||||||
return NU_BUFF_ALIGNMENT;
|
return NU_BUFF_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NUMAKER_EMAC::get_ifname(char *name, uint8_t size) const
|
void NUMAKER_EMAC::get_ifname(char *name, uint8_t size) const
|
||||||
{
|
{
|
||||||
memcpy(name, NU_ETH_IF_NAME, (size < sizeof(NU_ETH_IF_NAME)) ? size : sizeof(NU_ETH_IF_NAME));
|
memcpy(name, NU_ETH_IF_NAME, (size < sizeof(NU_ETH_IF_NAME)) ? size : sizeof(NU_ETH_IF_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t NUMAKER_EMAC::get_hwaddr_size() const
|
uint8_t NUMAKER_EMAC::get_hwaddr_size() const
|
||||||
|
|
@ -369,39 +378,39 @@ bool NUMAKER_EMAC::get_hwaddr(uint8_t *addr) const
|
||||||
|
|
||||||
void NUMAKER_EMAC::set_hwaddr(const uint8_t *addr)
|
void NUMAKER_EMAC::set_hwaddr(const uint8_t *addr)
|
||||||
{
|
{
|
||||||
memcpy(hwaddr, addr, sizeof hwaddr);
|
memcpy(hwaddr, addr, sizeof hwaddr);
|
||||||
numaker_set_mac_addr(const_cast<uint8_t*>(addr));
|
numaker_set_mac_addr(const_cast<uint8_t *>(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void NUMAKER_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
|
void NUMAKER_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
|
||||||
{
|
{
|
||||||
emac_link_input_cb = input_cb;
|
emac_link_input_cb = input_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NUMAKER_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
|
void NUMAKER_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
|
||||||
{
|
{
|
||||||
emac_link_state_cb = state_cb;
|
emac_link_state_cb = state_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NUMAKER_EMAC::add_multicast_group(const uint8_t *addr)
|
void NUMAKER_EMAC::add_multicast_group(const uint8_t *addr)
|
||||||
{
|
{
|
||||||
/* No-op at this stage */
|
/* No-op at this stage */
|
||||||
}
|
}
|
||||||
|
|
||||||
void NUMAKER_EMAC::remove_multicast_group(const uint8_t *addr)
|
void NUMAKER_EMAC::remove_multicast_group(const uint8_t *addr)
|
||||||
{
|
{
|
||||||
/* No-op at this stage */
|
/* No-op at this stage */
|
||||||
}
|
}
|
||||||
|
|
||||||
void NUMAKER_EMAC::set_all_multicast(bool all)
|
void NUMAKER_EMAC::set_all_multicast(bool all)
|
||||||
{
|
{
|
||||||
/* No-op at this stage */
|
/* No-op at this stage */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NUMAKER_EMAC::power_down()
|
void NUMAKER_EMAC::power_down()
|
||||||
{
|
{
|
||||||
/* No-op at this stage */
|
/* No-op at this stage */
|
||||||
}
|
}
|
||||||
|
|
||||||
void NUMAKER_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
|
void NUMAKER_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
|
||||||
|
|
@ -410,13 +419,15 @@ void NUMAKER_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NUMAKER_EMAC &NUMAKER_EMAC::get_instance() {
|
NUMAKER_EMAC &NUMAKER_EMAC::get_instance()
|
||||||
|
{
|
||||||
static NUMAKER_EMAC emac;
|
static NUMAKER_EMAC emac;
|
||||||
return emac;
|
return emac;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Weak so a module can override
|
// Weak so a module can override
|
||||||
MBED_WEAK EMAC &EMAC::get_default_instance() {
|
MBED_WEAK EMAC &EMAC::get_default_instance()
|
||||||
|
{
|
||||||
return NUMAKER_EMAC::get_instance();
|
return NUMAKER_EMAC::get_instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue