feat(can): CAN休眠唤醒移动到BOOT以进行以支持40k硬件看门狗
- 更新深度睡眠实现,在跳转到bootloader前记录睡眠状态到Flash - 添加gd32c10x_fmc.h头文件以支持Flash内存控制功能 - 将prepare_deep_sleep重命名为app_prepare_deep_sleep以提高命名清晰度 - 在CAN通信检测中添加应用层休眠准备功能 - 在接收OTA启动ID时解锁FMC、设置APP为非激活状态并锁定FMC - 移除main.cpp中的看门狗复位休眠逻辑 - 在config.h中添加睡眠配置相关的常量定义 - 改进OTA_SET函数的Flash写入逻辑,优化数据更新流程 - 在OTA初始化和应用移动过程中添加FMC解锁锁定操作
This commit is contained in:
+54
-46
@@ -34,10 +34,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "systick.h"
|
||||
#include "Can.h"
|
||||
#include "config.h"
|
||||
#include "core_cmFunc.h"
|
||||
#include "flash.h"
|
||||
#include "gd32c10x.h"
|
||||
#include "gd32c10x_exti.h"
|
||||
#include "gd32c10x_fmc.h"
|
||||
#include "initial.h"
|
||||
#include "motor.h"
|
||||
#include <cstdio>
|
||||
@@ -125,58 +127,64 @@ void system_soft_reset(void) {
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void prepare_deep_sleep(bool save_data) {
|
||||
void app_prepare_deep_sleep(bool save_data) {
|
||||
if (save_data) {
|
||||
flashEEP.save_system_config(true);
|
||||
}
|
||||
// 将SIT1044设置为低功耗待机模式
|
||||
// CAN0_transmiter.CAN_Sleep();
|
||||
motor_sleep();
|
||||
// 在睡眠前调整看门狗超时时间为最大值,使其在唤醒前不会触发
|
||||
fwdgt_write_enable();
|
||||
fwdgt_config(0xFFF, FWDGT_PSC_DIV256); // 设置最大超时时间
|
||||
fwdgt_write_disable();
|
||||
|
||||
// 关闭不必要的外设时钟
|
||||
rcu_periph_clock_disable(RCU_TIMER0); // 关闭定时器时钟
|
||||
rcu_periph_clock_disable(RCU_TIMER1);
|
||||
rcu_periph_clock_disable(RCU_SPI0); // 关闭SPI时钟
|
||||
rcu_periph_clock_disable(RCU_I2C0); // 关闭I2C时钟
|
||||
rcu_periph_clock_disable(RCU_ADC0); // 关闭ADC时钟
|
||||
// 注意不要关闭GPIOB和AF的时钟,因为需要它们来处理唤醒中断
|
||||
|
||||
// 设置深睡眠模式下的电压以进一步降低功耗
|
||||
rcu_deepsleep_voltage_set(RCU_DEEPSLEEP_V_0_8); // 设置最低电压
|
||||
|
||||
// 配置PB8为输入模式,用于外部中断
|
||||
rcu_periph_clock_enable(RCU_GPIOB);
|
||||
rcu_periph_clock_enable(RCU_AF);
|
||||
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
|
||||
|
||||
// 配置EXTI中断(连接到PB8引脚)
|
||||
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB,
|
||||
GPIO_PIN_SOURCE_8); // 配置GPIOB的PIN8作为EXTI8的源
|
||||
exti_init(EXTI_8, EXTI_INTERRUPT, EXTI_TRIG_RISING); // 边沿触发
|
||||
exti_interrupt_enable(EXTI_8);
|
||||
nvic_irq_enable(EXTI5_9_IRQn, 0, 0); //
|
||||
|
||||
// 确保中断标志已被清除
|
||||
exti_interrupt_flag_clear(EXTI_8);
|
||||
|
||||
watchdog_init(5000); // 看门狗初始化
|
||||
// 进入深度睡眠
|
||||
pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief EXTI5_9中断处理函数
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void EXTI5_9_IRQHandler(void) {
|
||||
if (exti_interrupt_flag_get(EXTI_8) != RESET) {
|
||||
// 清除中断标志
|
||||
exti_interrupt_flag_clear(EXTI_8);
|
||||
// 禁用EXTI线8的中断,防止重复触发
|
||||
exti_interrupt_disable(EXTI_8);
|
||||
|
||||
printf("MCU wake up\r\n");
|
||||
system_soft_reset();
|
||||
__disable_irq();
|
||||
// 遍历最后一个数字,后一个地址写+1
|
||||
for (u32 address = SLEEP_CONFIG_END - SIZE_U32;
|
||||
address >= SLEEP_CONFIG_START; address -= SIZE_U32) { // 遍历睡眠存储区
|
||||
volatile u32 *flash_ptr = (volatile u32 *)address;
|
||||
u32 sleep_enable = *flash_ptr;
|
||||
if (sleep_enable == FLASH_EMPTY and
|
||||
address > SLEEP_CONFIG_START) { // 空数据且未到头跳过
|
||||
continue;
|
||||
} else { // 有数据的话读取
|
||||
#if SLEEP_DEBUG
|
||||
printf("app sleep found %08x at %08x\r\n", sleep_enable, address);
|
||||
#endif
|
||||
if (address == SLEEP_CONFIG_END - SIZE_U32) {
|
||||
fmc_unlock();
|
||||
fmc_state_enum fmc_status =
|
||||
fmc_page_erase(SLEEP_CONFIG_START); // 擦除已满的页
|
||||
if (fmc_status != FMC_READY) { // 擦除失败报错
|
||||
fmc_lock();
|
||||
flashEEP.EEPROMStatus = FLASH_EEPROM_ERASE_ERROR;
|
||||
return;
|
||||
}
|
||||
address = SLEEP_CONFIG_START - SIZE_U32; // 重新开始写入
|
||||
}
|
||||
address += SIZE_U32;
|
||||
#if SLEEP_DEBUG
|
||||
printf("app sleep prepare write %08x at %08x\r\n", SLEEP_ENABLE,
|
||||
address);
|
||||
#endif
|
||||
fmc_state_enum fmc_status =
|
||||
write_ADDRESS(address, SLEEP_ENABLE); // 写入数据
|
||||
#if SLEEP_DEBUG
|
||||
volatile u32 *flash_ptr = (volatile u32 *)address;
|
||||
u32 sleep_check = *flash_ptr;
|
||||
printf("app sleep wrote %08x at %08x\r\n", sleep_check, address);
|
||||
#endif
|
||||
if (fmc_status != FMC_READY) { // 写入失败报错
|
||||
flashEEP.EEPROMStatus = FLASH_EEPROM_WRITE_ERROR;
|
||||
#if SLEEP_DEBUG
|
||||
printf("app wrote %08x at %08x ERROR\r\n", SLEEP_ENABLE,
|
||||
address);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
jumpToBOOT(); // 跳转到bootloader正式休眠,进入低功耗待机模式
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user