Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
+526
View File
@@ -0,0 +1,526 @@
/*!
\file gd32h7xx_enet_eval.c
\brief ethernet hardware configuration
\version 2025-02-19, V2.1.0, demo for GD32H7xx
*/
/*
Copyright (c) 2024, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "gd32h7xx_enet.h"
#include "main.h"
/**
* PHY 复位 GPIO 阶段在调度器启动之前执行,禁止使用 vTaskDelay。
* 使用 DWT CYCCNT 忙等毫秒级延时(与 app/main.c 中 delay_ms 思路一致)。
*/
static void enet_phy_gpio_reset_delay_ms(uint32_t ms)
{
uint32_t start;
uint32_t ticks;
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
start = DWT->CYCCNT;
ticks = (SystemCoreClock / 1000U) * ms;
while ((DWT->CYCCNT - start) < ticks) {
__NOP();
}
}
static __IO uint32_t enet_init_status = 0U;
uint8_t enet_hw_is_ready(void)
{
return (enet_init_status != 0U) ? 1U : 0U;
}
static void enet_gpio_config(void);
static void enet_mac_dma_config(void);
static void enet_gpio_resetConfig(void);
/*!
\brief setup ethernet system(GPIOs, clocks, MAC, DMA, systick)
\param[in] none
\param[out] none
\retval none
*/
void enet_system_setup(void)
{
enet_gpio_resetConfig(); //PHY复位
/* configure the GPIO ports for ethernet pins */
enet_gpio_config();
/* configure the ethernet MAC/DMA */
enet_mac_dma_config();
if (0U == enet_init_status) {
/* 不自旋死锁:无网线/PHY 异常时仍应能进 FreeRTOS,运行灯可闪烁 */
return;
}
#ifdef USE_ENET0
enet_interrupt_enable(ENET0, ENET_DMA_INT_NIE);
enet_interrupt_enable(ENET0, ENET_DMA_INT_RIE);
#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
enet_desc_select_enhanced_mode(ENET0);
#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */
#endif /* USE_ENET0 */
#ifdef USE_ENET1
enet_interrupt_enable(ENET1, ENET_DMA_INT_NIE);
enet_interrupt_enable(ENET1, ENET_DMA_INT_RIE);
#ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
enet_desc_select_enhanced_mode(ENET1);
#endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */
#endif /* USE_ENET1 */
}
/*!
\brief configures the ethernet interface
\param[in] none
\param[out] none
\retval none
*/
static void enet_mac_dma_config(void)
{
ErrStatus reval_state = ERROR;
#ifdef USE_ENET0
/* enable ethernet clock */
rcu_periph_clock_enable(RCU_ENET0);
rcu_periph_clock_enable(RCU_ENET0TX);
rcu_periph_clock_enable(RCU_ENET0RX);
/* reset ethernet on AHB bus */
enet_deinit(ENET0);
reval_state = enet_software_reset(ENET0);
if (ERROR == reval_state) {
enet_init_status = 0U;
return;
}
#ifdef CHECKSUM_BY_HARDWARE
enet_init_status = enet_init(ENET0, ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS);
#else
enet_init_status = enet_init(ENET0, ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS);
#endif /* CHECKSUM_BY_HARDWARE */
#endif /* USE_ENET0 */
#ifdef USE_ENET1
/* enable ethernet clock */
rcu_periph_clock_enable(RCU_ENET1);
rcu_periph_clock_enable(RCU_ENET1TX);
rcu_periph_clock_enable(RCU_ENET1RX);
/* reset ethernet on AHB bus */
enet_deinit(ENET1);
reval_state = enet_software_reset(ENET1);
if (ERROR == reval_state) {
enet_init_status = 0U;
return;
}
#ifdef CHECKSUM_BY_HARDWARE
enet_init_status = enet_init(ENET1, ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS);
#else
enet_init_status = enet_init(ENET1, ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS);
#endif /* CHECKSUM_BY_HARDWARE */
#endif /* USE_ENET1 */
}
/*!
\brief configures the different GPIO ports
\param[in] none
\param[out] none
\retval none
*/
static void enet_gpio_config(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
// rcu_periph_clock_enable(RCU_GPIOD);
// rcu_periph_clock_enable(RCU_GPIOE);
// rcu_periph_clock_enable(RCU_GPIOG);
// rcu_periph_clock_enable(RCU_GPIOH);
// gpio_af_set(GPIOA, GPIO_AF_0, GPIO_PIN_8);
// gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
// gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8);
/* enable SYSCFG clock */
rcu_periph_clock_enable(RCU_SYSCFG);
#ifdef MII_MODE
#ifdef PHY_CLOCK_MCO
/* output HXTAL clock (25MHz) on CKOUT0 pin(PA8) to clock the PHY */
rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL, RCU_CKOUT0_DIV1);
#endif /* PHY_CLOCK_MCO */
#ifdef USE_ENET0
syscfg_enet_phy_interface_config(ENET0, SYSCFG_ENET_PHY_MII);
#endif /* USE_ENET0 */
#ifdef USE_ENET1
syscfg_enet_phy_interface_config(ENET1, SYSCFG_ENET_PHY_MII);
#endif /* USE_ENET1 */
#elif defined RMII_MODE
/* choose DIV12 to get 50MHz from 600MHz on CKOUT0 pin (PA8) to clock the PHY */
// rcu_ckout0_config(RCU_CKOUT0SRC_PLL0P, RCU_CKOUT0_DIV12);
#ifdef USE_ENET0
syscfg_enet_phy_interface_config(ENET0, SYSCFG_ENET_PHY_RMII);
#endif /* USE_ENET0 */
#ifdef USE_ENET1
syscfg_enet_phy_interface_config(ENET1, SYSCFG_ENET_PHY_RMII);
#endif /* USE_ENET1 */
#endif /* MII_MODE */
#ifdef USE_ENET0
#ifdef MII_MODE
/* PA1: ETH0_MII_RX_CLK */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_1);
/* PA2: ETH0_MDIO */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_2);
/* PA7: ETH0_MII_RX_DV */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1);
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2);
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7);
/* PB8: ETH0_MII_TXD3 */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8);
/* PB10: ETH0_MII_RX_ER */
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10);
gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_8);
gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_10);
/* PC1: ETH0_MDC */
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_1);
/* PC2: ETH0_MII_TXD2 */
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_2);
/* PC3: ETH0_MII_TX_CLK */
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_3);
/* PC4: ETH0_MII_RXD0 */
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_4);
/* PC5: ETH0_MII_RXD1 */
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_5);
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1);
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_2);
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_3);
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4);
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5);
/* PH2: ETH0_MII_CRS */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_2);
/* PH3: ETH0_MII_COL */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_3);
/* PH6: ETH0_MII_RXD2 */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
/* PH7: ETH0_MII_RXD3 */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);
gpio_af_set(GPIOH, GPIO_AF_11, GPIO_PIN_2);
gpio_af_set(GPIOH, GPIO_AF_11, GPIO_PIN_3);
gpio_af_set(GPIOH, GPIO_AF_11, GPIO_PIN_6);
gpio_af_set(GPIOH, GPIO_AF_11, GPIO_PIN_7);
/* PG11: ETH0_MII_TX_EN */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
/* PG13: ETH0_MII_TXD0 */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_13);
/* PG14: ETH0_MII_TXD1 */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_14);
gpio_af_set(GPIOG, GPIO_AF_11, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_11, GPIO_PIN_13);
gpio_af_set(GPIOG, GPIO_AF_11, GPIO_PIN_14);
/* PD8: ETH0_INT */
gpio_mode_set(GPIOD, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_8);
#elif defined RMII_MODE
/* PC1: ETH0_MDC */
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_1);
/* PA2: ETH0_MDIO */
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_2);
/* PB12: ETH0_RMII_TXD0 */
gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_12);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_12);
/* PB13: ETH0_RMII_TXD1 */
gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_13);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_13);
/* PB11: ETH0_RMII_TX_EN */
gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_11);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
/* PC4: ETH0_RMII_RXD0 */
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_4);
/* PC5: ETH0_RMII_RXD1 */
gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_5);
/* PA7: ETH0_RMII_CRS_DV */
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);
/* PA1: ETH0_RMII_REF_CLK */
gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_1);
#endif /* MII_MODE */
#endif /* USE_ENET0 */
#ifdef USE_ENET1
#ifdef MII_MODE
/* PH6: ETH1_MII_RXD2 */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
/* PH7: ETH1_MII_RXD3 */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);
/* PH8: ETH1_MII_RXD0 */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8);
/* PH9: ETH1_MII_RXD1 */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_9);
/* PH10: ETH1_MII_RX_ER */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10);
/* PH11: ETH1_MII_RX_DV */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
/* PH12: ETH1_MII_RX_CLK */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_12);
/* PH13: ETH1_MII_COL */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_13);
/* PH14: ETH1_MDIO */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_14);
/* PH15: ETH1_MII_CRS */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_15);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_6);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_7);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_8);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_9);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_10);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_11);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_12);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_13);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_14);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_15);
/* PG6: ETH1_MDC */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
/* PG9: ETH1_MII_TX_CLK */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_9);
/* PG11: ETH1_MII_TX_EN */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
/* PG12: ETH1_MII_TXD2 */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_12);
/* PG13: ETH1_MII_TXD0 */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_13);
/* PG14: ETH1_MII_TXD1 */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_14);
/* PG15: ETH1_MII_TXD3 */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_15);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_6);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_9);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_12);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_13);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_14);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_15);
/* PE1: ETH1_INT */
gpio_mode_set(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_1);
#elif defined RMII_MODE
/* PH8: ETH1_RMII_RXD0 */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8);
/* PH9: ETH1_RMII_RXD1 */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_9);
/* PH11: ETH1_RMII_CRS_DV */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
/* PH12: ETH1_RMII_REF_CLK */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_12);
/* PH14: ETH1_MDIO */
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_14);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_8);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_9);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_11);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_12);
gpio_af_set(GPIOH, GPIO_AF_6, GPIO_PIN_14);
/* PG6: ETH1_MDC */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
/* PG11: ETH1_RMII_TX_EN */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
/* PG13: ETH1_RMII_TXD0 */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_13);
/* PG14: ETH1_RMII_TXD1 */
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_14);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_6);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_13);
gpio_af_set(GPIOG, GPIO_AF_6, GPIO_PIN_14);
#endif /* MII_MODE */
#endif /* USE_ENET1 */
}
static void enet_gpio_resetConfig(void) //PHY复位引脚:PA0
{
rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_0);
gpio_bit_set(GPIOA, GPIO_PIN_0);
enet_phy_gpio_reset_delay_ms(10U);
gpio_bit_reset(GPIOA, GPIO_PIN_0); /* 复位 PHY */
enet_phy_gpio_reset_delay_ms(30U);
gpio_bit_set(GPIOA, GPIO_PIN_0);
/* 复位后勿立刻配置 MAC,至少 250ms(调度器未起,不可用 vTaskDelay */
enet_phy_gpio_reset_delay_ms(250U);
}
+47
View File
@@ -0,0 +1,47 @@
/*!
\file gd32h7xx_enet_eval.h
\brief the header file of gd32h7xx_enet_eval
\version 2025-02-19, V2.1.0, demo for GD32H7xx
*/
/*
Copyright (c) 2024, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef GD32H7xx_ENET_EVAL_H
#define GD32H7xx_ENET_EVAL_H
#include <stdint.h>
#include "netif.h"
/* function declarations */
/* setup ethernet system(GPIOs, clocks, MAC, DMA, systick) */
void enet_system_setup(void);
/* 非 0 表示 MAC/PHY 初始化成功,可安全启用 lwIP 与 ENET 中断 */
uint8_t enet_hw_is_ready(void);
#endif /* GD32H7xx_ENET_EVAL_H */
+39
View File
@@ -0,0 +1,39 @@
#include "eth_link.h"
#include "lwip/netif.h"
#include "app_init/app_init.h"
#include "wdt_task/wdt_task.h"
#include "net_lwip/netconf.h"
/**
* @brief Ethernet link state monitor thread.
*
* @details
* - Aligns task architecture with reference project's ethernet_link_thread.
* - Polls link state of the given netif.
* - Feeds watchdog flag for EthLink task.
*
* @param argument Must be a pointer to struct netif.
*/
void ethernet_link_thread(void *argument)
{
struct netif *netif = (struct netif *)argument;
if (netif == NULL) {
for (;;) {
v_wdt_setFlag(TASK_ID_EthLink);
mSleep(MY_GET_SLEEP_TIME(TASK_ID_EthLink));
}
}
for (;;) {
(void)netif_is_link_up(netif);
v_wdt_setFlag(TASK_ID_EthLink);
mSleep(MY_GET_SLEEP_TIME(TASK_ID_EthLink));
}
}
int is_eth_link_up(void)
{
return (int)netif_is_link_up(NETCONF_ETH_NETIF);
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef ETH_LINK_H
#define ETH_LINK_H
void ethernet_link_thread(void *argument);
int is_eth_link_up(void);
#endif
+220
View File
@@ -0,0 +1,220 @@
/*!
\file lwipopts.h
\brief LwIP options configuration
\version 2025-02-19, V2.1.0, demo for GD32H7xx
*/
/*
Copyright (c) 2024, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef LWIPOPTS_H
#define LWIPOPTS_H
#define ETHARP_TRUST_IP_MAC 0
#define ARP_QUEUEING 0
#define SYS_LIGHTWEIGHT_PROT 1 /* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection
for certain critical regions during buffer allocation,
deallocation and memory allocation and deallocation */
#define NO_SYS 0 /* NO_SYS==1: provides VERY minimal functionality.
Otherwise, use lwIP facilities */
/* memory options */
#define MEM_ALIGNMENT 4 /* should be set to the alignment of the CPU for which lwIP
is compiled. 4 byte alignment -> define MEM_ALIGNMENT
to 4, 2 byte alignment -> define MEM_ALIGNMENT to 2 */
#define MEM_SIZE (14*1024) /* the size of the heap memory, if the application will
send a lot of data that needs to be copied, this should
be set high */
/* Relocate the LwIP RAM heap pointer */
#define LWIP_RAM_HEAP_POINTER (0x30004000)
#define MEMP_NUM_PBUF 100 /* the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory),
this should be set high */
#define MEMP_NUM_UDP_PCB 6 /* the number of UDP protocol control blocks, one
per active UDP "connection" */
#define MEMP_NUM_TCP_PCB 10 /* the number of simulatenously active TCP connections */
#define MEMP_NUM_TCP_PCB_LISTEN 5 /* the number of listening TCP connections */
#define MEMP_NUM_TCP_SEG 20 /* the number of simultaneously queued TCP segments */
#define MEMP_NUM_SYS_TIMEOUT 10 /* the number of simulateously active timeouts */
#define MEMP_NUM_NETBUF 8 /* the number of struct netbufs */
/* Pbuf options */
#define PBUF_POOL_SIZE 40 /* the number of buffers in the pbuf pool */
#define PBUF_POOL_BUFSIZE 1514 /* the size of each pbuf in the pbuf pool */
#define IP_REASS_MAX_PBUFS 20 /* total maximum amount of pbufs waiting to be reassembled */
/* TCP options */
#define LWIP_TCP 1
#define TCP_TTL 255
#define TCP_QUEUE_OOSEQ 0 /* controls if TCP should queue segments that arrive out of
order, Define to 0 if your device is low on memory. */
#define TCP_MSS (1500 - 40) /* TCP Maximum segment size,
TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
#define TCP_SND_BUF (4*TCP_MSS) /* TCP sender buffer space (bytes) */
#define TCP_SND_QUEUELEN ((4* TCP_SND_BUF)/TCP_MSS) /* TCP sender buffer space (pbufs), this must be at least
as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work */
#define TCP_WND (4*TCP_MSS) /* TCP receive window */
/* ICMP options */
#define LWIP_ICMP 1
/* DHCP options */
#define LWIP_DHCP 0 /* define to 1 if you want DHCP configuration of interfaces,
DHCP is not implemented in lwIP 0.5.1, however, so
turning this on does currently not work. */
/* UDP options */
#define LWIP_UDP 1
#define UDP_TTL 255
/* DNS options */
#define LWIP_DNS 1
#define DNS_TABLE_SIZE 2
#define DNS_MAX_NAME_LENGTH 64
#define DNS_MAX_SERVERS 1
#define DNS_MAX_RETRIES 3
#define MEMP_NUM_DNS_API_MSG 2
#define MEMP_NUM_NETDB 1
#define LWIP_DNS_SECURE LWIP_DNS_SECURE_RAND_XID
/* statistics options */
#define LWIP_STATS 0
#define LWIP_PROVIDE_ERRNO 1
/* checksum options */
#define CHECKSUM_BY_HARDWARE /* computing and verifying the IP, UDP, TCP and ICMP
checksums by hardware */
/* sequential layer options */
#define LWIP_NETCONN 1 /* set to 1 to enable netconn API (require to use api_lib.c) */
#define MEMP_NUM_NETCONN 10 /* netconn pool, raise to avoid ENOBUFS during socket create */
/* socket options */
#define LWIP_SOCKET 1 /* set to 1 to enable socket API (require to use sockets.c) */
#define LWIP_SO_RCVTIMEO 1 /* set to 1 to enable receive timeout for sockets/netconns and
SO_RCVTIMEO processing */
/* Lwip debug options */
#define LWIP_DEBUG 0
#ifdef CHECKSUM_BY_HARDWARE
/* CHECKSUM_GEN_IP==0: generate checksums by hardware for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 0
/* CHECKSUM_GEN_UDP==0: generate checksums by hardware for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 0
/* CHECKSUM_GEN_TCP==0: generate checksums by hardware for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 0
/* CHECKSUM_CHECK_IP==0: check checksums by hardware for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 0
/* CHECKSUM_CHECK_UDP==0: check checksums by hardware for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 0
/* CHECKSUM_CHECK_TCP==0: check checksums by hardware for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 0
#define CHECKSUM_GEN_ICMP 0
#else
/* CHECKSUM_GEN_IP==1: generate checksums in software for outgoing IP packets.*/
#define CHECKSUM_GEN_IP 1
/* CHECKSUM_GEN_UDP==1: generate checksums in software for outgoing UDP packets.*/
#define CHECKSUM_GEN_UDP 1
/* CHECKSUM_GEN_TCP==1: generate checksums in software for outgoing TCP packets.*/
#define CHECKSUM_GEN_TCP 1
/* CHECKSUM_CHECK_IP==1: check checksums in software for incoming IP packets.*/
#define CHECKSUM_CHECK_IP 1
/* CHECKSUM_CHECK_UDP==1: check checksums in software for incoming UDP packets.*/
#define CHECKSUM_CHECK_UDP 1
/* CHECKSUM_CHECK_TCP==1: check checksums in software for incoming TCP packets.*/
#define CHECKSUM_CHECK_TCP 1
#define CHECKSUM_GEN_ICMP 1
#endif
/*
---------------------------------
---------- OS options ----------
---------------------------------
*/
#include "FreeRTOSConfig.h"
#include "FreeRTOS.h"
#include "task.h"
#include "app_init/app_init.h"
#include <stdint.h>
/* 与 CCU601E_D 一致:关闭 lwIP FreeRTOS 端“多线程严格检查”,避免与第三方驱动并发风格冲突 */
#ifndef LWIP_FREERTOS_CHECK_CORE_LOCKING
#define LWIP_FREERTOS_CHECK_CORE_LOCKING 0
#endif
#define MEM_LIBC_MALLOC 1
#define mem_clib_free vPortFree
#define mem_clib_malloc pvPortMalloc
uint32_t get_current_seconds(void);
#define LWIP_RAND() ((u32_t)get_current_seconds())
/* TCPIP 线程参数直接引用 app_init 任务表,保证单一配置源。 */
#define TCPIP_THREAD_NAME MY_TCPIP_NAME
#define TCPIP_THREAD_STACKSIZE MY_TCPIP_SIZE
#define TCPIP_THREAD_PRIO MY_TCPIP_PRIO
#define TCPIP_MBOX_SIZE 8
#define DEFAULT_THREAD_STACKSIZE 1024
#define LWIP_COMPAT_MUTEX 1
#define DEFAULT_TCP_RECVMBOX_SIZE 6
#define DEFAULT_UDP_RECVMBOX_SIZE 6
#define DEFAULT_ACCEPTMBOX_SIZE 6
/* ethernetif.c 收包模式:0=仅中断唤醒(默认),1=中断+超时兜底轮询 */
#ifndef ENET_RX_FALLBACK_POLLING
#define ENET_RX_FALLBACK_POLLING 0
#endif
#endif /* LWIPOPTS_H */
+39
View File
@@ -0,0 +1,39 @@
/*!
\file net_init.c
\brief deferred Ethernet + lwIP bring-up (FreeRTOS task)
*/
#include "net_init.h"
#include "enet_PHY.h"
#include "netconf.h"
/* Match app_init.h: TASK_SIZE_SIZE_2048 == configMINIMAL_STACK_SIZE * 16 */
#ifndef NET_INIT_TASK_STACK_WORDS
#define NET_INIT_TASK_STACK_WORDS ((uint16_t)((configMINIMAL_STACK_SIZE * 16U) / sizeof(StackType_t)))
#endif
static void v_net_init_task(void *arg)
{
(void)arg;
/* 等待系统其余任务先进入稳定运行态,再启动网络 */
vTaskDelay(pdMS_TO_TICKS(NET_INIT_DELAY_MS));
enet_system_setup();
if (enet_hw_is_ready() != 0U) {
lwip_stack_init();
}
vTaskDelete(NULL);
}
BaseType_t net_init_task_create(void)
{
return xTaskCreate(v_net_init_task,
"NetInit",
NET_INIT_TASK_STACK_WORDS,
NULL,
(UBaseType_t)(tskIDLE_PRIORITY + 1U),
NULL);
}
+18
View File
@@ -0,0 +1,18 @@
/*!
\file net_init.h
\brief deferred Ethernet + lwIP bring-up (FreeRTOS task)
*/
#ifndef NET_INIT_H
#define NET_INIT_H
#include "FreeRTOS.h"
#include "task.h"
#ifndef NET_INIT_DELAY_MS
#define NET_INIT_DELAY_MS 1000U
#endif
BaseType_t net_init_task_create(void);
#endif /* NET_INIT_H */
+346
View File
@@ -0,0 +1,346 @@
/*!
\file netconf.c
\brief network connection configuration
\version 2025-02-19, V2.1.0, demo for GD32H7xx
*/
/*
Copyright (c) 2024, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/dhcp.h"
#include "lwip/dns.h"
#include "ethernetif.h"
#include "main.h"
#include "netconf.h"
#include "publicdata/publicdata.h"
#include "lwip/tcpip.h"
#include <stdio.h>
#include "lwip/errno.h"
#include "queue.h"
#define DHCP_TRIES_MAX_TIMES 3
int errno;
typedef enum
{
DHCP_ADDR_NONE = 0,
DHCP_ADDR_BEGIN,
DHCP_ADDR_GOT,
DHCP_ADDR_FAIL
}dhcp_addr_status_enum;
#ifdef USE_DHCP
dhcp_addr_status_enum dhcp_state = DHCP_ADDR_NONE;
#endif /* USE_DHCP */
#ifdef USE_ENET0
struct netif g_mynetif0;
#endif /* USE_ENET0 */
#ifdef USE_ENET1
struct netif g_mynetif1;
#endif /* USE_ENET1 */
ip_addr_t ip_address = {0};
static uint8_t netconf_is_all_value(const U8_T *buf, U8_T value)
{
return (uint8_t)((buf[0] == value) && (buf[1] == value) && (buf[2] == value) && (buf[3] == value));
}
static uint8_t netconf_is_valid_host_ip(const U8_T *ip)
{
if (netconf_is_all_value(ip, 0x00U) || netconf_is_all_value(ip, 0xFFU)) {
return 0U;
}
if ((ip[0] == 0U) || (ip[0] == 127U) || (ip[0] >= 224U)) {
return 0U;
}
return 1U;
}
static uint8_t netconf_is_valid_netmask(const U8_T *mask)
{
uint32_t m;
uint8_t seen_zero = 0U;
if (netconf_is_all_value(mask, 0x00U) || netconf_is_all_value(mask, 0xFFU)) {
return 0U;
}
m = ((uint32_t)mask[0] << 24) | ((uint32_t)mask[1] << 16) | ((uint32_t)mask[2] << 8) | (uint32_t)mask[3];
for (uint32_t bit = 0U; bit < 32U; bit++) {
uint8_t cur = (uint8_t)((m >> (31U - bit)) & 0x1U);
if (cur == 0U) {
seen_zero = 1U;
} else if (seen_zero != 0U) {
return 0U;
}
}
return 1U;
}
static uint8_t netconf_is_same_subnet(const U8_T *ip, const U8_T *gw, const U8_T *mask)
{
uint32_t ip32 = ((uint32_t)ip[0] << 24) | ((uint32_t)ip[1] << 16) | ((uint32_t)ip[2] << 8) | (uint32_t)ip[3];
uint32_t gw32 = ((uint32_t)gw[0] << 24) | ((uint32_t)gw[1] << 16) | ((uint32_t)gw[2] << 8) | (uint32_t)gw[3];
uint32_t m32 = ((uint32_t)mask[0] << 24) | ((uint32_t)mask[1] << 16) | ((uint32_t)mask[2] << 8) | (uint32_t)mask[3];
return (uint8_t)(((ip32 & m32) == (gw32 & m32)) ? 1U : 0U);
}
static void netconf_get_static_ip_from_cfg(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw)
{
const U8_T *cfg_ip = g_t_share_data.t_sys_fix_cfg.s_net_cfg.u8_eth_ip;
const U8_T *cfg_mask = g_t_share_data.t_sys_fix_cfg.s_net_cfg.u8_eth_mask;
const U8_T *cfg_gw = g_t_share_data.t_sys_fix_cfg.s_net_cfg.u8_eth_gate;
uint8_t use_cfg = 1U;
if (netconf_is_valid_host_ip(cfg_ip) == 0U) {
use_cfg = 0U;
}
if (netconf_is_valid_host_ip(cfg_gw) == 0U) {
use_cfg = 0U;
}
if (netconf_is_valid_netmask(cfg_mask) == 0U) {
use_cfg = 0U;
}
if ((use_cfg != 0U) && (netconf_is_same_subnet(cfg_ip, cfg_gw, cfg_mask) == 0U)) {
use_cfg = 0U;
}
if (use_cfg != 0U) {
IP4_ADDR(ip, cfg_ip[0], cfg_ip[1], cfg_ip[2], cfg_ip[3]);
IP4_ADDR(mask, cfg_mask[0], cfg_mask[1], cfg_mask[2], cfg_mask[3]);
IP4_ADDR(gw, cfg_gw[0], cfg_gw[1], cfg_gw[2], cfg_gw[3]);
printf("[NETCONF] static ip from cfg: %u.%u.%u.%u, mask=%u.%u.%u.%u, gw=%u.%u.%u.%u\r\n",
cfg_ip[0], cfg_ip[1], cfg_ip[2], cfg_ip[3],
cfg_mask[0], cfg_mask[1], cfg_mask[2], cfg_mask[3],
cfg_gw[0], cfg_gw[1], cfg_gw[2], cfg_gw[3]);
} else {
IP4_ADDR(ip, BOARD_IP_ADDR0, BOARD_IP_ADDR1, BOARD_IP_ADDR2, BOARD_IP_ADDR3);
IP4_ADDR(mask, BOARD_NETMASK_ADDR0, BOARD_NETMASK_ADDR1, BOARD_NETMASK_ADDR2, BOARD_NETMASK_ADDR3);
IP4_ADDR(gw, BOARD_GW_ADDR0, BOARD_GW_ADDR1, BOARD_GW_ADDR2, BOARD_GW_ADDR3);
printf("[NETCONF] cfg ip invalid, fallback board ip: %u.%u.%u.%u\r\n",
BOARD_IP_ADDR0, BOARD_IP_ADDR1, BOARD_IP_ADDR2, BOARD_IP_ADDR3);
}
}
/*!
\brief after the netif is fully configured, it will be called to initialize the function of telnet, client and udp
\param[in] netif: the struct used for lwIP network interface
\param[out] none
\retval none
*/
void lwip_netif_status_callback(struct netif *netif)
{
if(((netif->flags & NETIF_FLAG_UP) != 0) && (0 != netif->ip_addr.addr)) {
}
}
/*!
\brief initializes the LwIP stack
\param[in] none
\param[out] none
\retval none
*/
void lwip_stack_init(void)
{
ip_addr_t gd_ipaddr;
ip_addr_t gd_netmask;
ip_addr_t gd_gw;
/* create tcp_ip stack thread */
tcpip_init(NULL, NULL);
/* IP address setting */
#ifdef USE_DHCP
gd_ipaddr.addr = 0;
gd_netmask.addr = 0;
gd_gw.addr = 0;
#else
netconf_get_static_ip_from_cfg(&gd_ipaddr, &gd_netmask, &gd_gw);
#endif /* USE_DHCP */
#ifdef USE_ENET0
/* add a new network interface */
netif_add(&g_mynetif0, &gd_ipaddr, &gd_netmask, &gd_gw, NULL, &ethernetif_init, &tcpip_input);
/* set a default network interface */
netif_set_default(&g_mynetif0);
/* set a callback when interface is up/down */
netif_set_status_callback(&g_mynetif0, lwip_netif_status_callback);
/* set the flag of netif as NETIF_FLAG_LINK_UP */
netif_set_link_up(&g_mynetif0);
/* bring an interface up and set the flag of netif as NETIF_FLAG_UP */
netif_set_up(&g_mynetif0);
#if LWIP_DNS
/* 静态 IP 时无 DHCP 下发 DNS,需手动设置 */
{
ip_addr_t dns_server;
IP_ADDR4(&dns_server, 114, 114, 114, 114);
dns_setserver(0, &dns_server);
}
#endif /* LWIP_DNS */
#endif /* USE_ENET0 */
#ifdef USE_ENET1
/* add a new network interface */
netif_add(&g_mynetif1, &gd_ipaddr, &gd_netmask, &gd_gw, NULL, &ethernetif_init, &tcpip_input);
/* set a default network interface */
netif_set_default(&g_mynetif1);
/* set a callback when interface is up/down */
netif_set_status_callback(&g_mynetif1, lwip_netif_status_callback);
/* set the flag of netif as NETIF_FLAG_LINK_UP */
netif_set_link_up(&g_mynetif1);
/* bring an interface up and set the flag of netif as NETIF_FLAG_UP */
netif_set_up(&g_mynetif1);
#if LWIP_DNS
{
ip_addr_t dns_server;
IP_ADDR4(&dns_server, 114, 114, 114, 114);
dns_setserver(0, &dns_server);
}
#endif /* LWIP_DNS */
#endif /* USE_ENET1 */
}
#ifdef USE_DHCP
/*!
\brief dhcp_task
\param[in] none
\param[out] none
\retval none
*/
void dhcp_task(void * pvParameters)
{
ip_addr_t gd_ipaddr;
ip_addr_t gd_netmask;
ip_addr_t gd_gw;
#ifdef USE_ENET0
struct dhcp *dhcp_client0;
#endif /* USE_ENET0 */
#ifdef USE_ENET1
struct dhcp *dhcp_client1;
#endif /* USE_ENET1 */
for(;;){
#ifdef USE_ENET0
switch(dhcp_state){
case DHCP_ADDR_NONE:
dhcp_start(&g_mynetif0);
/* IP address should be set to 0 every time we want to assign a new DHCP address*/
ip_address.addr = 0;
dhcp_state = DHCP_ADDR_BEGIN;
break;
case DHCP_ADDR_BEGIN:
/* got the IP address */
ip_address.addr = g_mynetif0.ip_addr.addr;
if(0 != ip_address.addr){
dhcp_state = DHCP_ADDR_GOT;
printf("\r\nDHCP -- eval board ip address: %d.%d.%d.%d \r\n", ip4_addr1_16(&ip_address), \
ip4_addr2_16(&ip_address), ip4_addr3_16(&ip_address), ip4_addr4_16(&ip_address));
}else{
/* DHCP timeout */
dhcp_client0 = netif_dhcp_data(&g_mynetif0);
if(dhcp_client0->tries > DHCP_TRIES_MAX_TIMES){
dhcp_state = DHCP_ADDR_FAIL;
/* stop DHCP */
dhcp_stop(&g_mynetif0);
/* use static address as IP address */
IP4_ADDR(&gd_ipaddr, BOARD_IP_ADDR0, BOARD_IP_ADDR1, BOARD_IP_ADDR2, BOARD_IP_ADDR3);
IP4_ADDR(&gd_netmask, BOARD_NETMASK_ADDR0, BOARD_NETMASK_ADDR1, BOARD_NETMASK_ADDR2, BOARD_NETMASK_ADDR3);
IP4_ADDR(&gd_gw, BOARD_GW_ADDR0, BOARD_GW_ADDR1, BOARD_GW_ADDR2, BOARD_GW_ADDR3);
netif_set_addr(&g_mynetif0, &gd_ipaddr, &gd_netmask, &gd_gw);
}
}
break;
default:
break;
}
#endif /* USE_ENET0 */
#ifdef USE_ENET1
switch(dhcp_state){
case DHCP_ADDR_NONE:
dhcp_start(&g_mynetif1);
/* IP address should be set to 0 every time we want to assign a new DHCP address*/
ip_address.addr = 0;
dhcp_state = DHCP_ADDR_BEGIN;
break;
case DHCP_ADDR_BEGIN:
/* got the IP address */
ip_address.addr = g_mynetif1.ip_addr.addr;
if(0 != ip_address.addr){
dhcp_state = DHCP_ADDR_GOT;
printf("\r\nDHCP -- eval board ip address: %d.%d.%d.%d \r\n", ip4_addr1_16(&ip_address), \
ip4_addr2_16(&ip_address), ip4_addr3_16(&ip_address), ip4_addr4_16(&ip_address));
}else{
/* DHCP timeout */
dhcp_client1 = netif_dhcp_data(&g_mynetif1);
if(dhcp_client1->tries > DHCP_TRIES_MAX_TIMES){
dhcp_state = DHCP_ADDR_FAIL;
/* stop DHCP */
dhcp_stop(&g_mynetif1);
/* use static address as IP address */
IP4_ADDR(&gd_ipaddr, BOARD_IP_ADDR0, BOARD_IP_ADDR1, BOARD_IP_ADDR2, BOARD_IP_ADDR3);
IP4_ADDR(&gd_netmask, BOARD_NETMASK_ADDR0, BOARD_NETMASK_ADDR1, BOARD_NETMASK_ADDR2, BOARD_NETMASK_ADDR3);
IP4_ADDR(&gd_gw, BOARD_GW_ADDR0, BOARD_GW_ADDR1, BOARD_GW_ADDR2, BOARD_GW_ADDR3);
netif_set_addr(&g_mynetif1, &gd_ipaddr, &gd_netmask, &gd_gw);
}
}
break;
default:
break;
}
#endif /* USE_ENET1 */
/* wait 250 ms */
vTaskDelay(250);
}
}
#endif /* USE_DHCP */
+68
View File
@@ -0,0 +1,68 @@
/*!
\file netconf.h
\brief the header file of netconf
\version 2025-02-19, V2.1.0, demo for GD32H7xx
*/
/*
Copyright (c) 2024, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef NETCONF_H
#define NETCONF_H
#include "main.h"
struct netif;
#if defined(USE_ENET0) && defined(USE_ENET1)
#error "USE_ENET0 and USE_ENET1 cannot both be defined (see main.h)"
#endif
#if !defined(USE_ENET0) && !defined(USE_ENET1)
#error "Define either USE_ENET0 or USE_ENET1 in main.h for Ethernet netif"
#endif
#ifdef USE_ENET0
extern struct netif g_mynetif0;
#define NETCONF_ETH_NETIF (&g_mynetif0)
#endif
#ifdef USE_ENET1
extern struct netif g_mynetif1;
#define NETCONF_ETH_NETIF (&g_mynetif1)
#endif
/* function declarations */
/* initializes the LwIP stack */
void lwip_stack_init(void);
/* dhcp_task */
void dhcp_task(void * pvParameters);
/* netif status callback function */
//void lwip_netif_status_callback(struct netif *netif);
#endif /* NETCONF_H */