diff --git a/GD32E508_DCU_APP/GD32E508_DCU_APP.cproject.yml b/GD32E508_DCU_APP/GD32E508_DCU_APP.cproject.yml index f655c49..98262a3 100644 --- a/GD32E508_DCU_APP/GD32E508_DCU_APP.cproject.yml +++ b/GD32E508_DCU_APP/GD32E508_DCU_APP.cproject.yml @@ -32,7 +32,9 @@ project: - file: ./device/Timer.h - file: ./device/Timer.cpp - file: ./device/temp_sensor.h + - file: ./device/watchdog.h - file: ./device/temp_sensor.cpp + - file: ./device/watchdog.cpp # List components to use for your application. # A software component is a re-usable unit that may be configurable. @@ -54,6 +56,7 @@ project: - component: Device:GD32E50x_StdPeripherals:TIMER - component: Device:GD32E50x_StdPeripherals:USART - component: Device:GD32E50x_libopt + - component: Device:GD32E50x_StdPeripherals:FWDGT # List executable file formats to be generated. output: diff --git a/GD32E508_DCU_APP/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c b/GD32E508_DCU_APP/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c new file mode 100644 index 0000000..0e18853 --- /dev/null +++ b/GD32E508_DCU_APP/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c @@ -0,0 +1,227 @@ +/*! + \file gd32e50x_fwdgt.c + \brief FWDGT driver + + \version 2026-02-09, V1.7.0, firmware for GD32E50x +*/ + +/* + Copyright (c) 2025, 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 "gd32e50x_fwdgt.h" + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief configure the free watchdog timer counter prescaler value + \param[in] prescaler_value: specify prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + ErrStatus status = SUCCESS; + + /* enable write access to FWDGT_PSC */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_value; + + /* wait until the PUD flag to be reset */ + do { + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { + status = ERROR; + } + + return status; +} + +/*! + \brief configure the free watchdog timer counter reload value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_reload_value_config(uint16_t reload_value) +{ + uint32_t timeout = FWDGT_RLD_TIMEOUT; + uint32_t flag_status = RESET; + ErrStatus status = SUCCESS; + + /* enable write access to FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* configure FWDGT_RLD */ + FWDGT_RLD = RLD_RLD(reload_value); + + /* wait until the RUD flag to be reset */ + do { + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { + status = ERROR; + } + + return status; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_value: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_value) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + ErrStatus status = SUCCESS; + + /* start the free watchdog timer counter */ + FWDGT_CTL = FWDGT_KEY_ENABLE; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* configure FWDGT PSC */ + FWDGT_PSC = (uint32_t)prescaler_value; + + /* wait until the PUD flag to be reset */ + do { + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { + status = ERROR; + } + + if(SUCCESS == status) { + /* configure FWDGT_RLD */ + FWDGT_RLD = RLD_RLD(reload_value); + + /* wait until the RUD flag to be reset */ + timeout = FWDGT_RLD_TIMEOUT; + do { + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { + status = ERROR; + } + } + + if(SUCCESS == status) { + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + } + + return status; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + FlagStatus flag_status = RESET; + if(FWDGT_STAT & flag) { + flag_status = SET; + } + return flag_status; +} diff --git a/GD32E508_DCU_APP/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 b/GD32E508_DCU_APP/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 new file mode 100644 index 0000000..0e18853 --- /dev/null +++ b/GD32E508_DCU_APP/RTE/Device/GD32E508VE/gd32e50x_fwdgt.c.base@1.5.0 @@ -0,0 +1,227 @@ +/*! + \file gd32e50x_fwdgt.c + \brief FWDGT driver + + \version 2026-02-09, V1.7.0, firmware for GD32E50x +*/ + +/* + Copyright (c) 2025, 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 "gd32e50x_fwdgt.h" + +/*! + \brief enable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_enable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; +} + +/*! + \brief disable write access to FWDGT_PSC and FWDGT_RLD + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_write_disable(void) +{ + FWDGT_CTL = FWDGT_WRITEACCESS_DISABLE; +} + +/*! + \brief start the free watchdog timer counter + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_enable(void) +{ + FWDGT_CTL = FWDGT_KEY_ENABLE; +} + +/*! + \brief configure the free watchdog timer counter prescaler value + \param[in] prescaler_value: specify prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_prescaler_value_config(uint16_t prescaler_value) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + ErrStatus status = SUCCESS; + + /* enable write access to FWDGT_PSC */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* configure FWDGT */ + FWDGT_PSC = (uint32_t)prescaler_value; + + /* wait until the PUD flag to be reset */ + do { + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { + status = ERROR; + } + + return status; +} + +/*! + \brief configure the free watchdog timer counter reload value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_reload_value_config(uint16_t reload_value) +{ + uint32_t timeout = FWDGT_RLD_TIMEOUT; + uint32_t flag_status = RESET; + ErrStatus status = SUCCESS; + + /* enable write access to FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* configure FWDGT_RLD */ + FWDGT_RLD = RLD_RLD(reload_value); + + /* wait until the RUD flag to be reset */ + do { + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { + status = ERROR; + } + + return status; +} + +/*! + \brief reload the counter of FWDGT + \param[in] none + \param[out] none + \retval none +*/ +void fwdgt_counter_reload(void) +{ + FWDGT_CTL = FWDGT_KEY_RELOAD; +} + +/*! + \brief configure counter reload value, and prescaler divider value + \param[in] reload_value: specify reload value(0x0000 - 0x0FFF) + \param[in] prescaler_value: FWDGT prescaler value + only one parameter can be selected which is shown as below: + \arg FWDGT_PSC_DIV4: FWDGT prescaler set to 4 + \arg FWDGT_PSC_DIV8: FWDGT prescaler set to 8 + \arg FWDGT_PSC_DIV16: FWDGT prescaler set to 16 + \arg FWDGT_PSC_DIV32: FWDGT prescaler set to 32 + \arg FWDGT_PSC_DIV64: FWDGT prescaler set to 64 + \arg FWDGT_PSC_DIV128: FWDGT prescaler set to 128 + \arg FWDGT_PSC_DIV256: FWDGT prescaler set to 256 + \param[out] none + \retval ErrStatus: ERROR or SUCCESS +*/ +ErrStatus fwdgt_config(uint16_t reload_value, uint8_t prescaler_value) +{ + uint32_t timeout = FWDGT_PSC_TIMEOUT; + uint32_t flag_status = RESET; + ErrStatus status = SUCCESS; + + /* start the free watchdog timer counter */ + FWDGT_CTL = FWDGT_KEY_ENABLE; + + /* enable write access to FWDGT_PSC,and FWDGT_RLD */ + FWDGT_CTL = FWDGT_WRITEACCESS_ENABLE; + + /* configure FWDGT PSC */ + FWDGT_PSC = (uint32_t)prescaler_value; + + /* wait until the PUD flag to be reset */ + do { + flag_status = FWDGT_STAT & FWDGT_STAT_PUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { + status = ERROR; + } + + if(SUCCESS == status) { + /* configure FWDGT_RLD */ + FWDGT_RLD = RLD_RLD(reload_value); + + /* wait until the RUD flag to be reset */ + timeout = FWDGT_RLD_TIMEOUT; + do { + flag_status = FWDGT_STAT & FWDGT_STAT_RUD; + } while((--timeout > 0U) && ((uint32_t)RESET != flag_status)); + + if((uint32_t)RESET != flag_status) { + status = ERROR; + } + } + + if(SUCCESS == status) { + /* reload the counter */ + FWDGT_CTL = FWDGT_KEY_RELOAD; + } + + return status; +} + +/*! + \brief get flag state of FWDGT + \param[in] flag: flag to get + only one parameter can be selected which is shown as below: + \arg FWDGT_FLAG_PUD: a write operation to FWDGT_PSC register is on going + \arg FWDGT_FLAG_RUD: a write operation to FWDGT_RLD register is on going + \param[out] none + \retval FlagStatus: SET or RESET +*/ +FlagStatus fwdgt_flag_get(uint16_t flag) +{ + FlagStatus flag_status = RESET; + if(FWDGT_STAT & flag) { + flag_status = SET; + } + return flag_status; +} diff --git a/GD32E508_DCU_APP/RTE/Device/GD32E508VE/system_gd32e50x.c b/GD32E508_DCU_APP/RTE/Device/GD32E508VE/system_gd32e50x.c index 07bc968..a8c94d2 100644 --- a/GD32E508_DCU_APP/RTE/Device/GD32E508VE/system_gd32e50x.c +++ b/GD32E508_DCU_APP/RTE/Device/GD32E508VE/system_gd32e50x.c @@ -1,4 +1,4 @@ -/*! +/*! \file system_gd32e50x.c \brief CMSIS Cortex-M33 Device Peripheral Access Layer Source File for GD32E50x Device Series @@ -162,6 +162,33 @@ static void _soft_delay_(uint32_t time) */ void SystemInit (void) { + /* ===== DIAG: raw USART0 output at IRC8M (8MHz) ===== */ + /* Enable AFIO + GPIOA + USART0 clocks via raw register */ + *((volatile uint32_t *)0x40021018U) |= (1U << 14) | (1U << 2) | (1U << 0); + /* PA9 = AF_PP, 50MHz (CTL=0b11, MD=0b11) -> CTL1 bit[4..7]=0b1011 */ + { + volatile uint32_t ctl = *((volatile uint32_t *)0x40010804U); + ctl &= ~(0xFU << 4); + ctl |= (0xBU << 4); /* AF_PP 50MHz */ + *((volatile uint32_t *)0x40010804U) = ctl; + } + /* USART0 baud: BAUD = 8000000/115200 = 69 */ + *((volatile uint32_t *)0x40013808U) = 69U; + /* USART0 CTL0: TE + EN = bit3 + bit13 */ + *((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13); + /* Send "APP" via USART0 DATA register */ + *((volatile uint32_t *)0x40013804U) = 'A'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + *((volatile uint32_t *)0x40013804U) = 'P'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + *((volatile uint32_t *)0x40013804U) = 'P'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + *((volatile uint32_t *)0x40013804U) = '\r'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + *((volatile uint32_t *)0x40013804U) = '\n'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + /* ===== END DIAG ===== */ + /* FPU settings */ #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ @@ -196,6 +223,22 @@ void SystemInit (void) /* configure the system clock source, PLL Multiplier, AHB/APBx prescalers and Flash settings */ system_clock_config(); + + /* ===== DIAG: after PLL config, at 180MHz, send "CLK" ===== */ + /* Re-enable USART0 at 180MHz: BAUD = 180000000/115200 = 1562.5 = 1563 */ + *((volatile uint32_t *)0x40013808U) = 1563U; + *((volatile uint32_t *)0x40013800U) = (1U << 3) | (1U << 13); + *((volatile uint32_t *)0x40013804U) = 'C'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + *((volatile uint32_t *)0x40013804U) = 'L'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + *((volatile uint32_t *)0x40013804U) = 'K'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + *((volatile uint32_t *)0x40013804U) = '\r'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + *((volatile uint32_t *)0x40013804U) = '\n'; + while ((*((volatile uint32_t *)0x40013800U) & (1U << 7)) == 0U) {} + /* ===== END DIAG ===== */ #ifdef VECT_TAB_SRAM nvic_vector_table_set(NVIC_VECTTAB_RAM,VECT_TAB_OFFSET); diff --git a/GD32E508_DCU_APP/device/app_spi_command.cpp b/GD32E508_DCU_APP/device/app_spi_command.cpp index 1c5c046..5454916 100644 --- a/GD32E508_DCU_APP/device/app_spi_command.cpp +++ b/GD32E508_DCU_APP/device/app_spi_command.cpp @@ -44,6 +44,19 @@ static constexpr uint16_t kRxBufSize = 128U; static constexpr uint16_t kTxBufSize = 64U; static constexpr uint16_t kLogBufSize = 128U; +static bool isAllBytesValue(const uint8_t *data, uint8_t len, uint8_t value) +{ + if (!data || len == 0U) { + return false; + } + for (uint8_t i = 0U; i < len; ++i) { + if (data[i] != value) { + return false; + } + } + return true; +} + /* ============================================================ * 静态成员 * ============================================================ */ @@ -300,9 +313,19 @@ void AppSpiCommand::processCommand() void AppSpiCommand::poll() { + char log_copy[kLogBufSize] = {}; + bool has_log = false; + + __disable_irq(); if (s_logPending) { + memcpy(log_copy, s_logBuf, sizeof(log_copy)); s_logPending = false; - printf("%s\r\n", s_logBuf); + has_log = true; + } + __enable_irq(); + + if (has_log) { + printf("%s\r\n", log_copy); } } @@ -327,6 +350,10 @@ void AppSpiCommand::onCsRelease() } s_csActive = false; spi_i2s_interrupt_disable(SPI0, SPI_I2S_INT_TBE); + if (isAllBytesValue(s_rxBuf, s_rxLen, 0xFFU)) { + s_rxLen = 0U; + return; + } processCommand(); } @@ -394,4 +421,4 @@ extern "C" void SPI0_IRQHandler(void) extern "C" void EXTI10_15_IRQHandler(void) { AppSpiCommand::onCsExtiInterrupt(); -} \ No newline at end of file +} diff --git a/GD32E508_DCU_APP/device/app_spi_command.h b/GD32E508_DCU_APP/device/app_spi_command.h index 9185221..49c3ab6 100644 --- a/GD32E508_DCU_APP/device/app_spi_command.h +++ b/GD32E508_DCU_APP/device/app_spi_command.h @@ -52,4 +52,4 @@ private: static void logDeferredFmt(const char *fmt, uint8_t val); }; -#endif /* DEVICE_APP_SPI_COMMAND_H */ \ No newline at end of file +#endif /* DEVICE_APP_SPI_COMMAND_H */ diff --git a/GD32E508_DCU_APP/device/watchdog.cpp b/GD32E508_DCU_APP/device/watchdog.cpp index 5950631..182a626 100644 --- a/GD32E508_DCU_APP/device/watchdog.cpp +++ b/GD32E508_DCU_APP/device/watchdog.cpp @@ -14,8 +14,8 @@ void Watchdog::init() { fwdgt_write_enable(); - fwdgt_prescaler_config(CONFIG_FWDGT_PSC); - fwdgt_reload_config(CONFIG_FWDGT_RLD); + fwdgt_prescaler_value_config(CONFIG_FWDGT_PSC); + fwdgt_reload_value_config(CONFIG_FWDGT_RLD); fwdgt_write_disable(); fwdgt_enable(); } diff --git a/GD32E508_DCU_APP/main.cpp b/GD32E508_DCU_APP/main.cpp index a67aba9..bf0eb76 100644 --- a/GD32E508_DCU_APP/main.cpp +++ b/GD32E508_DCU_APP/main.cpp @@ -1,4 +1,4 @@ -/** +/** * @file main.cpp * @brief 应用主入口与顶层流程实现。 */ @@ -36,8 +36,12 @@ void App::printBanner() const */ int App::run() { + printf("[APP] >>> main() entered, SystemCoreClock=%lu\r\n", (unsigned long)SystemCoreClock); + printf("[APP] >>> calling AppInitializer::init()...\r\n"); AppInitializer::init(); + printf("[APP] >>> init done, calling TaskRunner::init()...\r\n"); TaskRunner::init(); + printf("[APP] >>> TaskRunner ready, entering main loop\r\n"); printBanner(); while(1) { diff --git a/GD32E508_DCU_APP/sys/initial.cpp b/GD32E508_DCU_APP/sys/initial.cpp index 0968051..8139035 100644 --- a/GD32E508_DCU_APP/sys/initial.cpp +++ b/GD32E508_DCU_APP/sys/initial.cpp @@ -25,14 +25,24 @@ */ void AppInitializer::init() { + printf("[APP] init: SysTick...\r\n"); SysTickTimer::initMs(); + printf("[APP] init: USART0...\r\n"); Usart0::configurePins(); Usart0::init(); + printf("[APP] init: TempSensor...\r\n"); TempSensor::init(); + printf("[APP] init: CANFD...\r\n"); CanFd::init(); + printf("[APP] init: OtaBootRequest...\r\n"); OtaBootRequest::init(); + printf("[APP] init: AppSpiCommand...\r\n"); AppSpiCommand::init(); + printf("[APP] init: TaskManager...\r\n"); TaskManager::init(); + printf("[APP] init: SchedulerTimer...\r\n"); SchedulerTimer::init(); + printf("[APP] init: Watchdog...\r\n"); Watchdog::init(); + printf("[APP] init: all done\r\n"); } diff --git a/GD32E508_DCU_APP/sys/ota_boot_request.cpp b/GD32E508_DCU_APP/sys/ota_boot_request.cpp index 078bc92..02fc4cd 100644 --- a/GD32E508_DCU_APP/sys/ota_boot_request.cpp +++ b/GD32E508_DCU_APP/sys/ota_boot_request.cpp @@ -18,7 +18,7 @@ constexpr uint32_t kAppLatestCheckAddr = kOtaConfigPageAddr + 0x10U; constexpr uint32_t kOtaAval = 0x00000000U; constexpr uint32_t kOtaNotAval = 0xFFFFFFFFU; constexpr uint32_t kFmcPageSize = 0x00000800U; -constexpr uint32_t kRebootDelayTicks = 2U; +constexpr uint32_t kRebootDelayMs = 20U; static bool writeWord(uint32_t addr, uint32_t value) { @@ -89,8 +89,6 @@ static bool requestMagicValid(const uint8_t *data, uint8_t length) /** @brief 已写入 OTA 标志并等待软复位的挂起标志。 */ volatile bool OtaBootRequest::s_rebootPending = false; -/** @brief 复位前的调度延迟计数,给 SPI/CAN 应答留出发送时间。 */ -uint32_t OtaBootRequest::s_rebootCountdown = 0U; /** * @brief 初始化进入 Bootloader 请求模块的运行态。 @@ -98,7 +96,6 @@ uint32_t OtaBootRequest::s_rebootCountdown = 0U; void OtaBootRequest::init() { s_rebootPending = false; - s_rebootCountdown = 0U; } /** @@ -115,7 +112,6 @@ bool OtaBootRequest::requestEnterBoot() } if(ok) { - s_rebootCountdown = kRebootDelayTicks; s_rebootPending = true; } return ok; @@ -142,8 +138,11 @@ bool OtaBootRequest::handleCanFrame(uint8_t channel, uint32_t id, const uint8_t } /** - * @brief 在主循环任务中执行延迟软复位。 + * @brief 在主循环任务中执行短延迟软复位。 * @note 不在 SPI/CAN 中断里直接复位,避免应答还没发出就重启。 + * 这里使用毫秒级短延时,而不是 1s 心跳计数;否则一次 SPI 请求 + * 实际会拖到 2~3 秒后才复位,ESP32 第二次 OTA 时很容易在 APP 还没 + * 真正重启进入 BOOT 之前就发出 HANDSHAKE_REQ。 */ void OtaBootRequest::process() { @@ -151,11 +150,8 @@ void OtaBootRequest::process() return; } - if(s_rebootCountdown > 0U) { - --s_rebootCountdown; - return; - } - + s_rebootPending = false; + SysTickTimer::delayMs(kRebootDelayMs); __disable_irq(); NVIC_SystemReset(); while(1) { diff --git a/GD32E508_DCU_APP/sys/ota_boot_request.h b/GD32E508_DCU_APP/sys/ota_boot_request.h index ccb0207..2555898 100644 --- a/GD32E508_DCU_APP/sys/ota_boot_request.h +++ b/GD32E508_DCU_APP/sys/ota_boot_request.h @@ -36,7 +36,6 @@ public: private: static volatile bool s_rebootPending; - static uint32_t s_rebootCountdown; }; #endif /* SYS_OTA_BOOT_REQUEST_H */