mirror of
https://github.com/openharmony/device_board_hpmicro.git
synced 2026-07-01 21:54:00 -04:00
committed by
huohongpeng
parent
0054c50963
commit
4d7c4e71dd
@@ -23,7 +23,7 @@ kernel_module(module_name) {
|
||||
"driver/uart.c"
|
||||
]
|
||||
deps = [
|
||||
"littlefs"
|
||||
"littlefs",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user