2022-10-21 10:17:49 +08:00
|
|
|
#include "bflb_mtimer.h"
|
|
|
|
#include "board.h"
|
|
|
|
#include "log.h"
|
|
|
|
|
|
|
|
#include "bflb_emac.h"
|
|
|
|
#include "ethernet_phy.h"
|
|
|
|
|
|
|
|
#define EMAC_TEST_INTERVAL (9)
|
|
|
|
#define EMAC_TEST_TX_INTERVAL_US (3000)
|
|
|
|
|
|
|
|
static const uint8_t test_frame[42] = {
|
|
|
|
/* ARP reply to 192.168.123.221(e4:54:e8:ca:31:16): 192.168.1.220 is at 18:b9:05:12:34:56 */
|
|
|
|
0xb0, 0x7b, 0x25, 0x00, 0x89, 0x53, // dst mac b0:7b:25:00:89:53
|
|
|
|
0x18, 0xB9, 0x05, 0x12, 0x34, 0x56, // src mac
|
|
|
|
0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x02, // arp reply
|
|
|
|
0x18, 0xB9, 0x05, 0x12, 0x34, 0x56, // src mac
|
|
|
|
0xc0, 0xa8, 0x7b, 0x64, // src ip 192.168.123.100
|
|
|
|
0xb0, 0x7b, 0x25, 0x00, 0x89, 0x53, // dst mac b0:7b:25:00:89:53
|
|
|
|
0xc0, 0xa8, 0x7b, 0xb2 // dst ip 192.168.123.178
|
|
|
|
};
|
|
|
|
#define TEST_PATTERN_LEN (ETH_MAX_PACKET_SIZE - 32)
|
2022-11-05 10:44:08 +08:00
|
|
|
ATTR_NOCACHE_NOINIT_RAM_SECTION static uint8_t test_pattern[TEST_PATTERN_LEN] = { 0 };
|
2022-10-21 10:17:49 +08:00
|
|
|
|
|
|
|
static volatile uint32_t tx_pkg_cnt = 0;
|
|
|
|
static volatile uint32_t tx_err_cnt = 0;
|
|
|
|
|
|
|
|
static volatile uint32_t rx_pkg_cnt = 0;
|
|
|
|
static volatile uint32_t rx_err_cnt = 0;
|
|
|
|
|
|
|
|
static volatile uint32_t rx_bytes = 0;
|
|
|
|
|
|
|
|
static uint32_t time = 0;
|
|
|
|
static uint32_t last_time = 0;
|
|
|
|
#define ETH_RXBUFNB 5
|
|
|
|
#define ETH_TXBUFNB 5
|
|
|
|
|
|
|
|
ATTR_NOCACHE_NOINIT_RAM_SECTION __attribute__((aligned(4))) uint8_t ethRxBuff[ETH_RXBUFNB][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */
|
|
|
|
ATTR_NOCACHE_NOINIT_RAM_SECTION __attribute__((aligned(4))) uint8_t ethTxBuff[ETH_TXBUFNB][ETH_TX_BUFFER_SIZE]; /* Ethernet Transmit Buffers */
|
|
|
|
|
|
|
|
struct bflb_device_s *emac0;
|
|
|
|
|
|
|
|
void emac_isr(int irq, void *arg)
|
|
|
|
{
|
|
|
|
uint32_t int_sts_val;
|
|
|
|
uint32_t index = 0;
|
|
|
|
int_sts_val = bflb_emac_get_int_status(emac0);
|
|
|
|
// printf("emac int:%08lx\r\n", int_sts_val);
|
|
|
|
if (int_sts_val & EMAC_INT_STS_TX_DONE) {
|
|
|
|
index = bflb_emac_bd_get_cur_active(emac0, EMAC_BD_TYPE_TX);
|
|
|
|
bflb_emac_bd_tx_dequeue(index);
|
|
|
|
bflb_emac_int_clear(emac0, EMAC_INT_STS_TX_DONE);
|
|
|
|
tx_pkg_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (int_sts_val & EMAC_INT_STS_TX_ERROR) {
|
|
|
|
bflb_emac_int_clear(emac0, EMAC_INT_STS_TX_ERROR);
|
|
|
|
index = bflb_emac_bd_get_cur_active(emac0, EMAC_BD_TYPE_TX);
|
|
|
|
bflb_emac_bd_tx_on_err(index);
|
|
|
|
|
|
|
|
printf("EMAC tx error !!!\r\n");
|
|
|
|
tx_err_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (int_sts_val & EMAC_INT_STS_RX_DONE) {
|
|
|
|
bflb_emac_int_clear(emac0, EMAC_INT_STS_RX_DONE);
|
|
|
|
index = bflb_emac_bd_get_cur_active(emac0, EMAC_BD_TYPE_RX);
|
|
|
|
bflb_emac_bd_rx_enqueue(index);
|
|
|
|
|
|
|
|
uint32_t rx_len;
|
|
|
|
bflb_emac_bd_rx_dequeue(-1, &rx_len, NULL);
|
|
|
|
|
|
|
|
if (rx_len) {
|
|
|
|
rx_pkg_cnt++;
|
|
|
|
rx_bytes += rx_len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (int_sts_val & EMAC_INT_STS_RX_ERROR) {
|
|
|
|
bflb_emac_int_clear(emac0, EMAC_INT_STS_RX_ERROR);
|
|
|
|
index = bflb_emac_bd_get_cur_active(emac0, EMAC_BD_TYPE_TX);
|
|
|
|
bflb_emac_bd_tx_on_err(index);
|
|
|
|
|
|
|
|
printf("EMAC rx error!!!\r\n");
|
|
|
|
rx_err_cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (int_sts_val & EMAC_INT_STS_RX_BUSY) {
|
|
|
|
printf("emac rx busy at %s:%d\r\n", __func__, __LINE__);
|
|
|
|
bflb_emac_int_clear(emac0, EMAC_INT_STS_RX_BUSY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
|
|
|
struct bflb_emac_config_s emac_cfg = {
|
|
|
|
.inside_clk = EMAC_CLK_USE_EXTERNAL,
|
|
|
|
.mii_clk_div = 49,
|
|
|
|
.min_frame_len = 64,
|
|
|
|
.max_frame_len = ETH_MAX_PACKET_SIZE,
|
|
|
|
.mac_addr[0] = 0x18,
|
|
|
|
.mac_addr[1] = 0xB9,
|
|
|
|
.mac_addr[2] = 0x05,
|
|
|
|
.mac_addr[3] = 0x12,
|
|
|
|
.mac_addr[4] = 0x34,
|
|
|
|
.mac_addr[5] = 0x56,
|
|
|
|
};
|
|
|
|
|
2022-12-21 20:25:59 +08:00
|
|
|
struct bflb_emac_phy_cfg_s phy_cfg = {
|
2022-10-21 10:17:49 +08:00
|
|
|
.auto_negotiation = 1, /*!< Speed and mode auto negotiation */
|
|
|
|
.full_duplex = 0, /*!< Duplex mode */
|
|
|
|
.speed = 0, /*!< Speed mode */
|
|
|
|
.phy_address = 1, /*!< PHY address */
|
|
|
|
.phy_id = 0x7c0f0, /*!< PHY OUI, masked */
|
|
|
|
.phy_state = PHY_STATE_DOWN,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32_t rx_len = 0;
|
|
|
|
uint32_t loop = 0;
|
|
|
|
|
|
|
|
board_init();
|
|
|
|
/* emac gpio init */
|
|
|
|
board_emac_gpio_init();
|
|
|
|
|
|
|
|
/* emac & BD init and interrupt attach */
|
|
|
|
emac0 = bflb_device_get_by_name("emac0");
|
|
|
|
bflb_emac_init(emac0, &emac_cfg);
|
|
|
|
bflb_emac_bd_init(emac0, (uint8_t *)ethTxBuff, ETH_TXBUFNB, (uint8_t *)ethRxBuff, ETH_RXBUFNB);
|
|
|
|
bflb_irq_attach(emac0->irq_num, emac_isr, emac0);
|
|
|
|
bflb_emac_int_clear(emac0, EMAC_INT_EN_ALL);
|
|
|
|
bflb_emac_int_enable(emac0, EMAC_INT_EN_ALL, 1);
|
|
|
|
|
2022-12-21 20:25:59 +08:00
|
|
|
printf("EMAC ARP Packet test!\r\n");
|
2022-10-21 10:17:49 +08:00
|
|
|
|
|
|
|
/* phy module init */
|
|
|
|
ethernet_phy_init(emac0, &phy_cfg);
|
|
|
|
printf("ETH PHY init ok!\r\n");
|
|
|
|
ethernet_phy_status_get();
|
|
|
|
if (PHY_STATE_UP == phy_cfg.phy_state) {
|
|
|
|
printf("PHY[%lx] @%d ready on %dMbps, %s duplex\n\r", phy_cfg.phy_id, phy_cfg.phy_address, phy_cfg.speed, phy_cfg.full_duplex ? "full" : "half");
|
|
|
|
} else {
|
|
|
|
printf("PHY Init fail\n\r");
|
|
|
|
while (1) {
|
|
|
|
bflb_mtimer_delay_ms(10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* test data */
|
|
|
|
memset(test_pattern, 0x5a, TEST_PATTERN_LEN);
|
|
|
|
memcpy(test_pattern, test_frame, sizeof(test_frame));
|
|
|
|
|
|
|
|
/* EMAC transmit start */
|
|
|
|
printf("EMAC start\r\n");
|
|
|
|
bflb_emac_start(emac0);
|
|
|
|
bflb_irq_enable(emac0->irq_num);
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
/* start tx queue and rx queue */
|
|
|
|
bflb_emac_bd_tx_enqueue(EMAC_NORMAL_PACKET, sizeof(test_frame), test_pattern);
|
|
|
|
test_pattern[27]++;
|
|
|
|
bflb_emac_bd_rx_dequeue(EMAC_NORMAL_PACKET, &rx_len, NULL);
|
|
|
|
bflb_emac_bd_tx_enqueue(EMAC_NORMAL_PACKET, sizeof(test_frame), test_pattern);
|
|
|
|
test_pattern[27]++;
|
|
|
|
bflb_emac_bd_tx_enqueue(EMAC_NORMAL_PACKET, sizeof(test_frame), test_pattern);
|
|
|
|
test_pattern[27]++;
|
|
|
|
bflb_emac_bd_rx_dequeue(EMAC_NORMAL_PACKET, &rx_len, NULL);
|
|
|
|
loop++;
|
|
|
|
if ((loop & 0xfffff) == 0) {
|
|
|
|
time = bflb_mtimer_get_time_ms();
|
|
|
|
printf("\r\nCurrent Bandwidth: %ldMbps\r\n", ((tx_pkg_cnt * 64 * 8) / (time * 1000)));
|
|
|
|
printf("tx cnt: %ld, lose cnt: %ld\n\r", tx_pkg_cnt, tx_err_cnt);
|
|
|
|
printf("rx cnt: %ld, lose cnt: %ld, bytes: %ld\n\r", rx_pkg_cnt, rx_err_cnt, rx_bytes);
|
|
|
|
last_time = time;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
LOG_F("emac basic\r\n");
|
|
|
|
LOG_E("emac basic\r\n");
|
|
|
|
LOG_W("emac basic\r\n");
|
|
|
|
LOG_I("emac basic\r\n");
|
|
|
|
LOG_D("emac basic\r\n");
|
|
|
|
LOG_T("emac basic\r\n");
|
|
|
|
bflb_mtimer_delay_ms(1000);
|
|
|
|
}
|
|
|
|
}
|