This repository has been archived on 2023-07-17. You can view files and clone it, but cannot push or open issues or pull requests.
bl_mcu_sdk/examples/peripherals/emac/emac_basic/main.c
2022-12-21 20:25:59 +08:00

186 lines
6.3 KiB
C

#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)
ATTR_NOCACHE_NOINIT_RAM_SECTION static uint8_t test_pattern[TEST_PATTERN_LEN] = { 0 };
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,
};
struct bflb_emac_phy_cfg_s phy_cfg = {
.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);
printf("EMAC ARP Packet test!\r\n");
/* 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);
}
}