/*
 * @Author       : stark1898y 1658608470@qq.com
 * @Date         : 2024-12-15 16:13:41
 * @LastEditors  : stark1898y 1658608470@qq.com
 * @LastEditTime : 2025-05-21 13:11:02
 * @FilePath     : \BLE_TYQ_CH584M\BSP\src\bsp_iwdg.c
 * @Description  :
 *
 * Copyright (c) 2024 by yzy, All Rights Reserved.
 */
#include "bsp_iwdg.h"

#include "bsp_uart.h"
#include "log.h"
#include "bsp_tim.h"

// https://www.cnblogs.com/debugdabiaoge/p/17580033.html
// https://www.cnblogs.com/risc5-ble/p/17853714.html

#undef LOG_ENABLE
#define LOG_ENABLE 1

#undef LOG_TAG
#define LOG_TAG "idwg"

uint8_t IWDGTaskId;

uint16_t IWDG_ProcessEvent(uint8_t task_id, uint16_t events)
{
    if (events & IWIG_FEED_EVENT)
    {
        // uint32_t seconds = 0;
        // uint16_t tick_1sec = 0;
        // seconds = CH5XX_GetTimeStamp(&tick_1sec);
        // logDebug("seconds = %d.%d", seconds, tick_1sec * 1000 / 32768);
        FEED_IWDG();
        // logDebug("IWDG feed");
        // 获取tmos系统堆的剩余内存大小
        // uint8_t* a = tmos_msg_allocate(1);
        logDebug("tmos_memory_getlen = %d" , tmos_memory_getlen());
        // tmos_start_task(task_id, IWIG_FEED_EVENT, MS1_TO_SYSTEM_TIME(IWDG_FEED_MS));
        return (events ^ IWIG_FEED_EVENT);
    }
    return 0;
}

// 32k rc
// div 0:4  | 1:8   | 2:16  | 3:32  |
//     4:64 | 5:128 | 6:256 | 7:512(32K分频512，时钟62.5Hz) |
// reload max 4095

// 独立看门狗（IWDG）由专用的内部低速时钟（LSI）驱动，能够在低功耗模式下正常工作。
// 根据寄存器描述，IWDG最大时间可以是(0xFFF/(32K/512))=65.52s
void IWDG_Init(uint16_t ms)
{
    uint16_t div = 512;
    // float tick_ms = 1000 / (32000 / 512);
    uint8_t tick_ms = 16;

    uint16_t reload = (ms / tick_ms) + 1;

    // 解除IWDG保护
    R32_IWDG_KR  = 0x5555;

    // R32_IWDG_CFG = (RB_PR & (div << 12)) | (RB_STOP_EN) | (reload & RB_RLR);
    R32_IWDG_CFG |= (7 << 12); // 32K分频512，时钟62.5Hz
    R32_IWDG_CFG &= 0xFFFFF000;
    // R32_IWDG_CFG |= 0x7D * 3; // 看门狗时间约6 s（0x10/(32K/512))
    R32_IWDG_CFG |= reload;

    // 开启IWDG保护
    R32_IWDG_KR  = 0xCCCC;
    // uint32_t d = R32_IWDG_CFG;
    // logHexDumpAll(d, 4);
    logDebug("IWDG = %d, %.1f ms", reload, (reload * 1000) / 62.5);

    // sys_safe_access_enable();
    // R8_SAFE_LRST_CTRL |= RB_IWDG_RST_EN;
    // sys_safe_access_disable();

    IWDGTaskId = TMOS_ProcessEventRegister(IWDG_ProcessEvent);
    // tmos_set_event(IWDGTaskId, IWIG_FEED_EVENT);
    tmos_start_reload_task(IWDGTaskId, IWIG_FEED_EVENT, MS1_TO_SYSTEM_TIME(IWDG_FEED_MS));
}

// #define  RB_RESET_FLAG      0x07                      // RO: recent reset flag
// #define  RST_FLAG_SW        0x00
// #define  RST_FLAG_RPOR      0x01
// #define  RST_FLAG_WTR       0x02
// #define  RST_FLAG_MR        0x03
// //#define  RST_FLAG_GPWSM     0x04                      // RO, power on reset flag during sleep/shutdown: 0=no power on reset during sleep/shutdown, 1=power on reset occurred during sleep/shutdown
// #define  RST_FLAG_GPWSM     0x05
// // RB_RESET_FLAG: recent reset flag
// //   000 - SR, software reset, by RB_SOFTWARE_RESET=1 @RB_WDOG_RST_EN=0
// //   001 - RPOR, real power on reset
// //   010 - WTR, watch-dog timer-out reset
// //   011 - MR, external manual reset by RST pin input low
// //   101 - GRWSM, global reset by waking under shutdown mode
//   1?? - LRW, power on reset occurred during sleep

// 打印复位状态寄存器，显示复位原因
// 最近一次复位状态：
// 000：软件复位 SR（RB_WDOG_RST_EN=0时软件复位可产生此状态，否则可复位但不产生此状态）；
// 001：上电复位 RPOR；
// 010：看门狗超时复位 WTR；
// 011：外部手动复位 MR；
// 101：从下电模式唤醒时的复位 GRWSM；
// 100/110/111：唤醒复位 LRW，且此前的上一次复位分别是 SR/WTR/MR。
void ShowRestartReason(void)
{
    uint8_t reason = R8_RESET_STATUS&0x07;
    logDebug("R8_RESET_STATUS = %02x", reason);
    switch (reason)
    {
    case RST_FLAG_SW:
        logDebug("RST_FLAG_SW");
        break;
    case RST_FLAG_RPOR:
        logDebug("RST_FLAG_RPOR");
        break;
    case RST_FLAG_WTR:
        logDebug("RST_FLAG_WTR");
        break;
    case RST_FLAG_MR:
        logDebug("RST_FLAG_MR");
        break;

    case RST_FLAG_GPWSM:
        logDebug("RST_FLAG_GPWSM");
        break;

    case 0x04:
        logDebug("LRW, last SR");
        break;
    case 0x06:
        logDebug("LRW, last WTR");
        break;
    case 0x07:
        logDebug("LRW, last MR");

    default:
        break;
    }
}




