feat(core): OTA可用版本,添加看门狗功能并优化系统初始化日志
- 添加watchdog组件用于系统监控 - 在system_gd32e50x.c中增加USART0诊断输出,在IRC8M和PLL配置后 发送"APP"和"CLK"标识 - 优化AppSpiCommand类中的日志处理机制,使用临界区保护 - 添加对全0xFF数据包的过滤处理,避免无效命令处理 - 将OTA重启延时从滴答计数改为毫秒级延时,提高响应速度 - 移除温度传感器相关文件,添加看门狗相关文件到项目配置 - 更新FWDGT API调用方式,使用新的配置函数 - 增加详细的启动日志输出,便于调试和追踪初始化过程
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +52,4 @@ private:
|
||||
static void logDeferredFmt(const char *fmt, uint8_t val);
|
||||
};
|
||||
|
||||
#endif /* DEVICE_APP_SPI_COMMAND_H */
|
||||
#endif /* DEVICE_APP_SPI_COMMAND_H */
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -36,7 +36,6 @@ public:
|
||||
|
||||
private:
|
||||
static volatile bool s_rebootPending;
|
||||
static uint32_t s_rebootCountdown;
|
||||
};
|
||||
|
||||
#endif /* SYS_OTA_BOOT_REQUEST_H */
|
||||
|
||||
Reference in New Issue
Block a user