Signed-off-by: Hongpeng Huo <hongpeng.huo@hpmicro.com>
This commit is contained in:
Hongpeng Huo
2022-09-22 16:59:48 +08:00
committed by huohongpeng
parent 0054c50963
commit 4d7c4e71dd
9 changed files with 806 additions and 1 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ kernel_module(module_name) {
"driver/uart.c"
]
deps = [
"littlefs"
"littlefs",
]
}
+125
View File
@@ -15,6 +15,8 @@
#include "board.h"
#include <hpm_pllctl_drv.h>
#include <hpm_enet_drv.h>
#include <hpm_gpio_drv.h>
/**
* @brief FLASH configuration option definitions:
* option[0]:
@@ -72,6 +74,15 @@
__attribute__ ((section(".nor_cfg_option"))) const uint32_t option[4] = {0xfcf90001, 0x00000007, 0x0, 0x0};
#endif
void board_delay_us(uint32_t us)
{
clock_cpu_delay_us(us);
}
void board_delay_ms(uint32_t ms)
{
clock_cpu_delay_ms(ms);
}
void board_init_clock(void)
{
@@ -233,3 +244,117 @@ $$ | $$ |$$ | $$ | \\_/ $$ |$$ |\\$$$$$$$\\ $$ | \\$$$$$$ |\r\n\
----------------------------------------------------------------------\r\n"};
printf("%s", banner);
}
static void init_enet_pins(ENET_Type *ptr)
{
if (ptr == HPM_ENET0) {
HPM_IOC->PAD[IOC_PAD_PF00].FUNC_CTL = IOC_PF00_FUNC_CTL_GPIO_F_00;
HPM_IOC->PAD[IOC_PAD_PE22].FUNC_CTL = IOC_PE22_FUNC_CTL_ETH0_MDC;
HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PE23_FUNC_CTL_ETH0_MDIO;
HPM_IOC->PAD[IOC_PAD_PD31].FUNC_CTL = IOC_PD31_FUNC_CTL_ETH0_RXD_0;
HPM_IOC->PAD[IOC_PAD_PE04].FUNC_CTL = IOC_PE04_FUNC_CTL_ETH0_RXD_1;
HPM_IOC->PAD[IOC_PAD_PE02].FUNC_CTL = IOC_PE02_FUNC_CTL_ETH0_RXD_2;
HPM_IOC->PAD[IOC_PAD_PE07].FUNC_CTL = IOC_PE07_FUNC_CTL_ETH0_RXD_3;
HPM_IOC->PAD[IOC_PAD_PE03].FUNC_CTL = IOC_PE03_FUNC_CTL_ETH0_RXCK;
HPM_IOC->PAD[IOC_PAD_PD30].FUNC_CTL = IOC_PD30_FUNC_CTL_ETH0_RXDV;
HPM_IOC->PAD[IOC_PAD_PE06].FUNC_CTL = IOC_PE06_FUNC_CTL_ETH0_TXD_0;
HPM_IOC->PAD[IOC_PAD_PD29].FUNC_CTL = IOC_PD29_FUNC_CTL_ETH0_TXD_1;
HPM_IOC->PAD[IOC_PAD_PD28].FUNC_CTL = IOC_PD28_FUNC_CTL_ETH0_TXD_2;
HPM_IOC->PAD[IOC_PAD_PE05].FUNC_CTL = IOC_PE05_FUNC_CTL_ETH0_TXD_3;
HPM_IOC->PAD[IOC_PAD_PE01].FUNC_CTL = IOC_PE01_FUNC_CTL_ETH0_TXCK;
HPM_IOC->PAD[IOC_PAD_PE00].FUNC_CTL = IOC_PE00_FUNC_CTL_ETH0_TXEN;
} else if (ptr == HPM_ENET1) {
HPM_IOC->PAD[IOC_PAD_PE26].FUNC_CTL = IOC_PE26_FUNC_CTL_GPIO_E_26;
HPM_IOC->PAD[IOC_PAD_PD11].FUNC_CTL = IOC_PD11_FUNC_CTL_ETH1_MDC;
HPM_IOC->PAD[IOC_PAD_PD14].FUNC_CTL = IOC_PD14_FUNC_CTL_ETH1_MDIO;
HPM_IOC->PAD[IOC_PAD_PE20].FUNC_CTL = IOC_PE20_FUNC_CTL_ETH1_RXD_0;
HPM_IOC->PAD[IOC_PAD_PE18].FUNC_CTL = IOC_PE18_FUNC_CTL_ETH1_RXD_1;
HPM_IOC->PAD[IOC_PAD_PE15].FUNC_CTL = IOC_PE15_FUNC_CTL_ETH1_RXDV;
HPM_IOC->PAD[IOC_PAD_PE19].FUNC_CTL = IOC_PE19_FUNC_CTL_ETH1_TXD_0;
HPM_IOC->PAD[IOC_PAD_PE17].FUNC_CTL = IOC_PE17_FUNC_CTL_ETH1_TXD_1;
HPM_IOC->PAD[IOC_PAD_PE14].FUNC_CTL = IOC_PE14_FUNC_CTL_ETH1_TXEN;
HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PAD_FUNC_CTL_LOOP_BACK_MASK | IOC_PE16_FUNC_CTL_ETH1_REFCLK;
}
}
hpm_stat_t board_init_enet_pins(ENET_Type *ptr)
{
init_enet_pins(ptr);
if (ptr == HPM_ENET0) {
gpio_set_pin_output_with_initial(BOARD_ENET_RGMII_RST_GPIO, BOARD_ENET_RGMII_RST_GPIO_INDEX, BOARD_ENET_RGMII_RST_GPIO_PIN, 0);
} else if (ptr == HPM_ENET1) {
gpio_set_pin_output_with_initial(BOARD_ENET_RMII_RST_GPIO, BOARD_ENET_RMII_RST_GPIO_INDEX, BOARD_ENET_RMII_RST_GPIO_PIN, 0);
} else {
return status_invalid_argument;
}
return status_success;
}
hpm_stat_t board_reset_enet_phy(ENET_Type *ptr)
{
if (ptr == HPM_ENET0) {
gpio_write_pin(BOARD_ENET_RGMII_RST_GPIO, BOARD_ENET_RGMII_RST_GPIO_INDEX, BOARD_ENET_RGMII_RST_GPIO_PIN, 0);
//board_delay_ms(1);
gpio_write_pin(BOARD_ENET_RGMII_RST_GPIO, BOARD_ENET_RGMII_RST_GPIO_INDEX, BOARD_ENET_RGMII_RST_GPIO_PIN, 1);
} else if (ptr == HPM_ENET1) {
gpio_write_pin(BOARD_ENET_RMII_RST_GPIO, BOARD_ENET_RMII_RST_GPIO_INDEX, BOARD_ENET_RMII_RST_GPIO_PIN, 0);
//board_delay_ms(1);
gpio_write_pin(BOARD_ENET_RMII_RST_GPIO, BOARD_ENET_RMII_RST_GPIO_INDEX, BOARD_ENET_RMII_RST_GPIO_PIN, 1);
} else {
return status_invalid_argument;
}
return status_success;
}
hpm_stat_t board_init_enet_ptp_clock(ENET_Type *ptr)
{
/* set clock source */
if (ptr == HPM_ENET0) {
/* make sure pll0_clk0 output clock at 400MHz to get a clock at 100MHz for the enet0 ptp function */
clock_set_source_divider(clock_ptp0, clk_src_pll1_clk1, 4); /* 100MHz */
} else if (ptr == HPM_ENET1) {
/* make sure pll0_clk0 output clock at 400MHz to get a clock at 100MHz for the enet1 ptp function */
clock_set_source_divider(clock_ptp1, clk_src_pll1_clk1, 4); /* 100MHz */
} else {
return status_invalid_argument;
}
return status_success;
}
hpm_stat_t board_init_enet_rmii_reference_clock(ENET_Type *ptr, bool internal)
{
if (internal == false) {
return status_success;
}
/* Configure Enet clock to output reference clock */
if (ptr == HPM_ENET0) {
/* make sure pll2_clk1 output clock at 250MHz then set 50MHz for enet0 */
clock_set_source_divider(clock_eth0, clk_src_pll2_clk1, 5);
} else if (ptr == HPM_ENET1) {
/* make sure pll2_clk1 output clock at 250MHz then set 50MHz for enet1 */
clock_set_source_divider(clock_eth1, clk_src_pll2_clk1, 5); /* set 50MHz for enet1 */
} else {
return status_invalid_argument;
}
enet_rmii_enable_clock(ptr, internal);
return status_success;
}
hpm_stat_t board_init_enet_rgmii_clock_delay(ENET_Type *ptr)
{
return enet_rgmii_set_clock_delay(ptr, BOARD_ENET_RGMII_TX_DLY, BOARD_ENET_RGMII_RX_DLY);
}
+29
View File
@@ -23,9 +23,38 @@
#define BOARD_CPU_FREQ (816000000UL)
/* enet section */
#define BOARD_ENET_RGMII_RST_GPIO HPM_GPIO0
#define BOARD_ENET_RGMII_RST_GPIO_INDEX GPIO_DO_GPIOF
#define BOARD_ENET_RGMII_RST_GPIO_PIN (0U)
#define BOARD_ENET_RGMII HPM_ENET0
#define BOARD_ENET_RGMII_TX_DLY (5U)
#define BOARD_ENET_RGMII_RX_DLY (2U)
#define BOARD_ENET_RGMII_PTP_CLOCK (clock_ptp0)
#define BOARD_ENET_RMII_RST_GPIO HPM_GPIO0
#define BOARD_ENET_RMII_RST_GPIO_INDEX GPIO_DO_GPIOE
#define BOARD_ENET_RMII_RST_GPIO_PIN (26U)
#define BOARD_ENET_RMII HPM_ENET1
#define BOARD_ENET_RMII_INT_REF_CLK (1U)
#define BOARD_ENET_RMII_PTP_CLOCK (clock_ptp1)
void board_init(void);
void board_print_clock_freq(void);
void board_print_banner(void);
hpm_stat_t board_reset_enet_phy(ENET_Type *ptr);
hpm_stat_t board_init_enet_pins(ENET_Type *ptr);
hpm_stat_t board_init_enet_rmii_reference_clock(ENET_Type *ptr, bool internal);
hpm_stat_t board_init_enet_rgmii_clock_delay(ENET_Type *ptr);
hpm_stat_t board_init_enet_ptp_clock(ENET_Type *ptr);
#if defined(__cplusplus)
}
#endif /* __cplusplus */
+41
View File
@@ -0,0 +1,41 @@
# Copyright (c) 2022 HPMicro.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//kernel/liteos_m/liteos.gni")
import("$LITEOSTHIRDPARTY/lwip/lwip.gni")
import("$LITEOSTOPDIR/components/net/lwip-2.1/lwip_porting.gni")
module_switch = defined(LOSCFG_NET_LWIP_SACK)
module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = LWIP_PORTING_FILES + LWIPNOAPPSFILES -
[ "$LWIPDIR/api/sockets.c" ] + [
"ethernetif.c",
"hpm_lwip.c" ]
defines = [ "LITEOS_LWIP=1" ]
defines += [ "CHECKSUM_BY_HARDWARE=1" ]
include_dirs = [ "//utils/native/lite/include" ]
visibility += [
"*",
]
}
# path "." must be in first for include lwip_adapter/lwipopts.h
config("public") {
include_dirs = [ "." ] + LWIP_PORTING_INCLUDE_DIRS + LWIP_INCLUDE_DIRS
}
@@ -0,0 +1,324 @@
/*
* Copyright (c) 2022 HPMicro.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hpm_lwip.h"
#include "ethernetif.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "netif/etharp.h"
#include "lwip/err.h"
#include "lwip/timeouts.h"
#include "ethernetif.h"
#include "hpm_enet_drv.h"
#include <string.h>
#include <los_task.h>
#include <los_sem.h>
/**
* In this function, the hardware should be initialized.
* Called from ethernetif_init().
*
* @param netif the already initialized lwip network interface structure
* for this ethernetif
*/
static void low_level_init(struct netif *netif)
{
struct HpmEnetDevice *dev = (struct HpmEnetDevice *)netif->state;
/* set netif MAC hardware address length */
netif->hwaddr_len = ETHARP_HWADDR_LEN;
/* set netif MAC hardware address */
netif->hwaddr[0] = dev->macAddr[0];
netif->hwaddr[1] = dev->macAddr[0];
netif->hwaddr[2] = dev->macAddr[0];
netif->hwaddr[3] = dev->macAddr[0];
netif->hwaddr[4] = dev->macAddr[0];
netif->hwaddr[5] = dev->macAddr[0];
/* set netif maximum transfer unit */
netif->mtu = 1500;
/* need to judge from phy status */
netif->flags |= NETIF_FLAG_LINK_UP;
/* Accept broadcast address and ARP traffic */
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
}
/**
* This function should do the actual transmission of the packet. The packet is
* contained in the pbuf that is passed to the function. This pbuf
* might be chained.
*
* @param netif the lwip network interface structure for this ethernetif
* @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
* @return ERR_OK if the packet could be sent
* an err_t value if the packet couldn't be sent
*
* @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
* strange results. You might consider waiting for space in the DMA queue
* to become availale since the stack doesn't retry to send a packet
* dropped because of memory failure (except for the TCP timers).
*/
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
struct HpmEnetDevice *dev = (struct HpmEnetDevice *)netif->state;
enet_desc_t *desc = &dev->desc;
uint32_t enet_tx_buff_size = desc->tx_buff_cfg.size;
struct pbuf *q;
uint8_t *buffer;
__IO enet_tx_desc_t *dma_tx_desc;
uint16_t frame_length = 0;
uint32_t buffer_offset = 0;
uint32_t bytes_left_to_copy = 0;
uint32_t payload_offset = 0;
enet_tx_desc_t *tx_desc_list_cur = desc->tx_desc_list_cur;
dma_tx_desc = tx_desc_list_cur;
buffer = (uint8_t *)(dma_tx_desc->tdes2_bm.buffer1);
buffer_offset = 0;
for (q = p; q != NULL; q = q->next) {
/* Get bytes in current lwIP buffer */
bytes_left_to_copy = q->len;
payload_offset = 0;
if (dma_tx_desc->tdes0_bm.own != 0) {
return ERR_BUF;
}
/* Check if the length of data to copy is bigger than Tx buffer size*/
while ((bytes_left_to_copy + buffer_offset) > enet_tx_buff_size) {
/* Copy data to Tx buffer*/
memcpy((uint8_t *)((uint8_t *)buffer + buffer_offset),
(uint8_t *)((uint8_t *)q->payload + payload_offset),
enet_tx_buff_size - buffer_offset);
/* Point to next descriptor */
dma_tx_desc = (enet_tx_desc_t *)(dma_tx_desc->tdes3_bm.next_desc);
/* Check if the buffer is available */
if (dma_tx_desc->tdes0_bm.own != 0) {
return ERR_BUF;
}
buffer = (uint8_t *)(dma_tx_desc->tdes2_bm.buffer1);
bytes_left_to_copy = bytes_left_to_copy - (enet_tx_buff_size - buffer_offset);
payload_offset = payload_offset + (enet_tx_buff_size - buffer_offset);
frame_length = frame_length + (enet_tx_buff_size - buffer_offset);
buffer_offset = 0;
}
/* pass payload to buffer */
desc->tx_desc_list_cur->tdes2_bm.buffer1 = (uint32_t)q->payload;
buffer_offset = buffer_offset + bytes_left_to_copy;
frame_length = frame_length + bytes_left_to_copy;
}
/* Prepare transmit descriptors to give to DMA*/
frame_length += 4;
enet_prepare_transmission_descriptors(dev->base, &desc->tx_desc_list_cur, frame_length, desc->tx_buff_cfg.size);
return ERR_OK;
}
/**
* Should allocate a pbuf and transfer the bytes of the incoming
* packet from the interface into the pbuf.
*
* @param netif the lwip network interface structure for this ethernetif
* @return a pbuf filled with the received packet (including MAC header)
* NULL on memory error
*/
static struct pbuf *low_level_input(struct netif *netif)
{
struct HpmEnetDevice *dev = (struct HpmEnetDevice *)netif->state;
enet_desc_t *desc = &dev->desc;
uint32_t enet_rx_buff_size = desc->rx_buff_cfg.size;
struct pbuf *p = NULL, *q;
u32_t len;
uint8_t *buffer;
enet_frame_t frame = {0, 0, 0};
enet_rx_desc_t*dma_rx_desc;
uint32_t buffer_offset = 0;
uint32_t payload_offset = 0;
uint32_t bytes_left_to_copy = 0;
uint32_t i = 0;
/* Check and get a received frame */
if (enet_check_received_frame(&desc->rx_desc_list_cur, &desc->rx_frame_info) == 1) {
frame = enet_get_received_frame(&desc->rx_desc_list_cur, &desc->rx_frame_info);
}
/* Obtain the size of the packet and put it into the "len" variable. */
len = frame.length;
buffer = (uint8_t *)frame.buffer;
if (len > 0) {
/* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
}
if (p != NULL) {
dma_rx_desc = frame.rx_desc;
buffer_offset = 0;
for (q = p; q != NULL; q = q->next) {
bytes_left_to_copy = q->len;
payload_offset = 0;
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
while ((bytes_left_to_copy + buffer_offset) > enet_rx_buff_size) {
/* Copy data to pbuf*/
memcpy((uint8_t *)((uint8_t *)q->payload + payload_offset), (uint8_t *)((uint8_t *)buffer + buffer_offset), (ENET_RX_BUFF_SIZE - buffer_offset));
/* Point to next descriptor */
dma_rx_desc = (enet_rx_desc_t*)(dma_rx_desc->rdes3_bm.next_desc);
buffer = (uint8_t *)(dma_rx_desc->rdes2_bm.buffer1);
bytes_left_to_copy = bytes_left_to_copy - (enet_rx_buff_size - buffer_offset);
payload_offset = payload_offset + (enet_rx_buff_size - buffer_offset);
buffer_offset = 0;
}
/* pass the buffer to pbuf */
q->payload = (void *)buffer;
buffer_offset = buffer_offset + bytes_left_to_copy;
}
} else {
return NULL;
}
/* Release descriptors to DMA */
dma_rx_desc = frame.rx_desc;
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
for (i = 0; i < desc->rx_frame_info.seg_count; i++) {
dma_rx_desc->rdes0_bm.own = 1;
dma_rx_desc = (enet_rx_desc_t*)(dma_rx_desc->rdes3_bm.next_desc);
}
/* Clear Segment_Count */
desc->rx_frame_info.seg_count = 0;
return p;
}
/**
* This function is the ethernetif_input task, it is processed when a packet
* is ready to be read from the interface. It uses the function low_level_input()
* that should handle the actual reception of bytes from the network
* interface. Then the type of the received packet is determined and
* the appropriate input function is called.
*
* @param netif the lwip network interface structure for this ethernetif
*/
/*
invoked after receiving data packet
*/
err_t ethernetif_input(struct netif *netif)
{
err_t err;
struct pbuf *p = NULL;
/* move received packet into a new pbuf */
p = low_level_input(netif);
/* no packet could be read, silently ignore this */
if (p == NULL) {
return ERR_MEM;
}
/* entry point to the LwIP stack */
err = netif->input(p, netif);
if (err != ERR_OK) {
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
}
return err;
}
VOID *ethernetif_recv_thread(UINT32 arg)
{
struct netif *netif = (struct netif *)arg;
while (1) {
ethernetif_input(netif);
LOS_Msleep(5);
}
}
void ethernetif_recv_start(struct netif *netif)
{
struct HpmEnetDevice *dev = (struct HpmEnetDevice *)netif->state;
UINT32 taskID = LOS_ERRNO_TSK_ID_INVALID;
UINT32 ret;
TSK_INIT_PARAM_S task = {0};
/* Create host Task */
task.pfnTaskEntry = (TSK_ENTRY_FUNC)ethernetif_recv_thread;
task.uwStackSize = 4096;
task.pcName = (char *)"recv";
task.usTaskPrio = 20;
task.uwArg = (UINTPTR)netif;
task.uwResved = LOS_TASK_STATUS_DETACHED;
ret = LOS_TaskCreate(&taskID, &task);
if (ret != LOS_OK) {
LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: LOS_TaskCreate error %u\n", ret));
return -1;
}
}
/**
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
* This function should be passed as a parameter to netif_add().
*
* @param netif the lwip network interface structure for this ethernetif
* @return ERR_OK if the loopif is initialized
* ERR_MEM if private data couldn't be allocated
* any other err_t on error
*/
err_t ethernetif_init(struct netif *netif)
{
LWIP_ASSERT("netif != NULL", (netif != NULL));
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */
netif->name[0] = 'e';
netif->name[1] = 'n';
netif->output = etharp_output;
netif->linkoutput = low_level_output;
/* initialize the hardware */
low_level_init(netif);
ethernetif_recv_start(netif);
return ERR_OK;
}
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2022 HPMicro.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef HPMICRO_ETHERNETIF_H
#define HPMICRO_ETHERNETIF_H
#include "lwip/err.h"
#include "lwip/netif.h"
#include "netif/etharp.h"
#ifdef __cplusplus
extern "C" {
#endif
err_t ethernetif_init(struct netif *netif);
err_t ethernetif_input(struct netif *netif);
#ifdef __cplusplus
}
#endif
#endif
+186
View File
@@ -0,0 +1,186 @@
/*
* Copyright (c) 2022 HPMicro.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include "lwip/tcpip.h"
#include "ohos_init.h"
#include "hpm_lwip.h"
#include "ethernetif.h"
#define ENET_DEVICE_NUM 2
static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_DESC_ADDR_ALIGNMENT)
__RW enet_rx_desc_t rxDescTab0[ENET_RX_BUFF_COUNT] ; /* Ethernet Rx DMA Descriptor */
static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_DESC_ADDR_ALIGNMENT)
__RW enet_tx_desc_t txDescTab0[ENET_TX_BUFF_COUNT] ; /* Ethernet Tx DMA Descriptor */
static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_BUFF_ADDR_ALIGNMENT)
__RW uint8_t rxBuff0[ENET_RX_BUFF_COUNT][ENET_RX_BUFF_SIZE]; /* Ethernet Receive Buffer */
static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_BUFF_ADDR_ALIGNMENT)
__RW uint8_t txBuff0[ENET_TX_BUFF_COUNT][ENET_TX_BUFF_SIZE]; /* Ethernet Transmit Buffer */
static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_DESC_ADDR_ALIGNMENT)
__RW enet_rx_desc_t rxDescTab1[ENET_RX_BUFF_COUNT] ; /* Ethernet Rx DMA Descriptor */
static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_DESC_ADDR_ALIGNMENT)
__RW enet_tx_desc_t txDescTab1[ENET_TX_BUFF_COUNT] ; /* Ethernet Tx DMA Descriptor */
static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_BUFF_ADDR_ALIGNMENT)
__RW uint8_t rxBuff1[ENET_RX_BUFF_COUNT][ENET_RX_BUFF_SIZE]; /* Ethernet Receive Buffer */
static ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(ENET_SOC_BUFF_ADDR_ALIGNMENT)
__RW uint8_t txBuff1[ENET_TX_BUFF_COUNT][ENET_TX_BUFF_SIZE]; /* Ethernet Transmit Buffer */
#define MAC_ADDR0 0x98
#define MAC_ADDR1 0x2C
#define MAC_ADDR2 0xBC
#define MAC_ADDR3 0xB1
#define MAC_ADDR4 0x9F
#define MAC_ADDR5 0x17
struct HpmEnetDevice enetDev[2] = {
[0] = {
.isEnable = 1,
.base = BOARD_ENET_RGMII,
.irqNum = IRQn_ENET0,
.infType = enet_inf_rgmii,
.macAddr = {0x98, 0x2C, 0xBC, 0xB1, 0x9F, 0x17},
.desc = {
.tx_desc_list_head = txDescTab0,
.rx_desc_list_head = rxDescTab0,
.tx_buff_cfg = {
.buffer = (uint32_t)txBuff0,
.count = ENET_TX_BUFF_COUNT,
.size = ENET_TX_BUFF_SIZE,
},
.rx_buff_cfg = {
.buffer = (uint32_t)rxBuff0,
.count = ENET_RX_BUFF_COUNT,
.size = ENET_RX_BUFF_SIZE,
},
},
},
[1] = {
.isEnable = 1,
.base = BOARD_ENET_RMII,
.irqNum = IRQn_ENET1,
.infType = enet_inf_rmii,
.macAddr = {0x98, 0x2C, 0xBC, 0xB1, 0x9F, 0x15},
.desc = {
.tx_desc_list_head = txDescTab1,
.rx_desc_list_head = rxDescTab1,
.tx_buff_cfg = {
.buffer = (uint32_t)txBuff1,
.count = ENET_TX_BUFF_COUNT,
.size = ENET_TX_BUFF_SIZE,
},
.rx_buff_cfg = {
.buffer = (uint32_t)rxBuff1,
.count = ENET_RX_BUFF_COUNT,
.size = ENET_RX_BUFF_SIZE,
},
},
},
};
void enetDevInit(struct HpmEnetDevice *dev)
{
if (!dev->isEnable) {
return 0;
}
board_init_enet_pins(dev->base);
board_reset_enet_phy(dev->base);
if (dev->infType == enet_inf_rmii) {
board_init_enet_rmii_reference_clock(dev->base, BOARD_ENET_RMII_INT_REF_CLK);
}
if (dev->infType == enet_inf_rgmii) {
board_init_enet_rgmii_clock_delay(dev->base);
}
memset(dev->desc.rx_desc_list_head, 0x00, sizeof(enet_rx_desc_t) * dev->desc.rx_buff_cfg.count);
memset(dev->desc.tx_desc_list_head, 0x00, sizeof(enet_rx_desc_t) * dev->desc.tx_buff_cfg.count);
enet_mac_config_t macCfg;
macCfg.mac_addr_high[0] = dev->macAddr[5];
macCfg.mac_addr_high[0] <<= 8;
macCfg.mac_addr_high[0] |= dev->macAddr[4];
macCfg.mac_addr_low[0] = dev->macAddr[3];
macCfg.mac_addr_low[0] <<= 8;
macCfg.mac_addr_low[0] |= dev->macAddr[2];
macCfg.mac_addr_low[0] <<= 8;
macCfg.mac_addr_low[0] |= dev->macAddr[1];
macCfg.mac_addr_low[0] <<= 8;
macCfg.mac_addr_low[0] |= dev->macAddr[0];
macCfg.valid_max_count = 1;
uint32_t dmaIntEnable = ENET_DMA_INTR_EN_NIE_SET(1) /* Enable normal interrupt summary */
| ENET_DMA_INTR_EN_RIE_SET(1); /* Enable receive interrupt */
enet_controller_init(dev->base, dev->infType, &dev->desc, &macCfg, dmaIntEnable);
dev->base->INTR_MASK |= 0xFFFFFFFF;
dev->base->MMC_INTR_MASK_RX |= 0xFFFFFFFF;
dev->base->MMC_INTR_MASK_TX |= 0xFFFFFFFF;
if (dev->infType == enet_inf_rgmii) {
rtl8211_config_t phyConfig;
rtl8211_reset(dev->base);
rtl8211_basic_mode_default_config(dev->base, &phyConfig);
rtl8211_basic_mode_init(dev->base, &phyConfig);
}
if (dev->infType == enet_inf_rmii) {
rtl8201_config_t phyConfig;
rtl8201_reset(dev->base);
rtl8201_basic_mode_default_config(dev->base, &phyConfig);
rtl8201_basic_mode_init(dev->base, &phyConfig);
}
ip_addr_t ipaddr;
ip_addr_t netmask;
ip_addr_t gw;
IP_ADDR4(&ipaddr, 192, 168, 1,8);
IP_ADDR4(&netmask, 255, 255, 255, 255);
IP_ADDR4(&gw, 192, 168, 1, 1);
netif_add(&dev->netif, &ipaddr, &netmask, &gw, dev, ethernetif_init, tcpip_input);
}
void HpmLwipInit(void)
{
printf("HpmLwipInit...\n");
enetDevInit(&enetDev[0]);
enetDevInit(&enetDev[1]);
netif_set_default(&enetDev[0].netif);
}
/* SYSEX_SERVICE_INIT(TcpIpPortingInit) is in kernel, it is priority is 2.
* HpmLwipInit() run must at after TcpIpPortingInit, so it is 3
*/
SYSEX_SERVICE_INIT_PRI(HpmLwipInit, 3);
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022 HPMicro.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef HPM_LWIP_H
#define HPM_LWIP_H
#include "hpm_enet_drv.h"
#include "hpm_rtl8211.h"
#include "hpm_rtl8211_regs.h"
#include "hpm_rtl8201.h"
#include "hpm_rtl8201_regs.h"
#include "board.h"
#include "lwip/err.h"
#include "lwip/netif.h"
#define ENET_TX_BUFF_COUNT (10U)
#define ENET_RX_BUFF_COUNT (20U)
#define ENET_RX_BUFF_SIZE ENET_MAX_FRAME_SIZE
#define ENET_TX_BUFF_SIZE ENET_MAX_FRAME_SIZE
struct HpmEnetDevice {
int isEnable;
struct netif netif;
uint8_t macAddr[6];
ENET_Type * base;
uint32_t irqNum;
enet_inf_type_t infType;
enet_desc_t desc;
enet_mac_config_t mac;
};
#endif
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2022 HPMicro.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef HPMICRO_LWIPOPTS_H
#define HPMICRO_LWIPOPTS_H
#include "lwip/lwipopts.h"
#endif