#include "sr_config.h"

#include "sr_log.h"
#include "sr_osal.h"

#include "sr_pm.h"

// 合宙头文件
#include "bsp_common.h"
#include "luat_debug.h"

// #include "luat_pm.h"



/*-----------自动初始化---------*/

static int bsp_init_start(void)
{
    return 0;
}
SR_INIT_BSP_EXPORT(bsp_init_start, "0");

static int bsp_init_end(void)
{
    return 0;
}
SR_INIT_BSP_EXPORT(bsp_init_end, "3.end");

static int component_init_start(void)
{
    return 0;
}
SR_INIT_COMPONENT_EXPORT(component_init_start, "0");

static int component_init_end(void)
{
    return 0;
}
SR_INIT_COMPONENT_EXPORT(component_init_end, "3.end");

static int app_init_start(void)
{
    return 0;
}
SR_INIT_APP_EXPORT(app_init_start, "0");

static int app_init_end(void)
{
    return 0;
}
SR_INIT_APP_EXPORT(app_init_end, "3.end");

// 遍历SR_INIT_BSP_EXPORT声明的初始化函数
static void _BspInit(void)
{
    const init_func_t *fn_ptr;

    for (fn_ptr = &_sr_init_bsp_init_start + 1; fn_ptr < &_sr_init_bsp_init_end; fn_ptr++)
    {
        (*fn_ptr)();
    }
}

// 遍历SR_INIT_COMPONENT_EXPORT声明的初始化函数
static void _ComponentInit(void)
{
    const init_func_t *fn_ptr;

    for (fn_ptr = &_sr_init_component_init_start + 1; fn_ptr < &_sr_init_component_init_end; fn_ptr++)
    {
        (*fn_ptr)();
    }
}

// 遍历SR_INIT_APP_EXPORT声明的初始化函数
static void _AppInit(void)
{
    const init_func_t *fn_ptr;

    for (fn_ptr = &_sr_init_app_init_start + 1; fn_ptr < &_sr_init_app_init_end; fn_ptr++)
    {
        (*fn_ptr)();
    }
}

/*-----------周期调度---------*/
static uint32_t gTickCnt = 0; // 每隔10ms加1


/**
 * @brief  空处理,用于定位段入口
 */
static void _nop_process(void)
{
}

// 起始
SR_USED poll_task_t poll_task_start SR_SECTION(".sunrise.poll_task.0") = {
    _nop_process, 0, 0};
// 结束
SR_USED poll_task_t poll_task_end SR_SECTION(".sunrise.poll_task.3.end") = {
    _nop_process, 0, 0};

/**
 * @brief       周期轮询任务处理，通过遍历使用SR_POLL_TASK_EXPORT声明的任务函数，这些函数分布在poll_task_start和poll_task_end之间
 * @param       none
 * @return      none
 */
uint32_t pLastTick = 0;
uint16_t periodMs = 0;

static void _poll_task(void)
{
    poll_task_t *t;
    for (t = &poll_task_start + 1; t < &poll_task_end; t++)
    {

#if 0
			if((gTickCnt - t->lastTick) >= t->periodMs) 
			{
			   pLastTick = t->lastTick;
			   periodMs = t->periodMs;
			    t->lastTick = gTickCnt;  //这句赋值不起作用，猜测由于段定义在flash上，只读
			    t->func();
			}
#else

        if (!(gTickCnt % t->periodMs)) // 对周期取余数为0
        {
            pLastTick = t->lastTick;
            periodMs = t->periodMs;
            t->func();
        }

#endif
    }
}

static void _PollThread(void *arg)
{

    BSP_LOG(INFO,"_PollThread Enter...\n");

    while (1)
    {
        osDelay(10);
        gTickCnt++;

        _poll_task();
    }
}




// BSP初始化(硬件开发者编写)，预留。当平台不支持自动初始化机制时可使用该函数
// 作用和自动初始化机制的_bsp_init()一样
SR_WEAK void SR_UserBspInit(void)
{
}

// Componet初始化（弱定义，应用开发者重写）
// 作用和自动初始化机制的_component_init()一样
SR_WEAK void SR_UserComponentInit(void)
{
}

// APP初始化（弱定义，应用开发者重写）
// 作用和自动初始化机制的_app_init()一样
SR_WEAK void SR_UserAppInit(void)
{
}

SR_WEAK void SR_MainEntry(void *arg)
{
    BSP_LOG(INFO,"Default SR_MainEntry Enter...\r\n");

    while (1)
    {
        osDelay(1000);
        BSP_LOG(INFO,"Default SR_MainEntry Loop...\r\n");
    }
}

// 预初始化
static void _PreEntry(void *arg)
{
    int pwrReason = 0, lastState = 0, rtcOrPad = 0, srReason = 0;

    /*
    出现异常后默认为死机重启
    demo这里设置为LUAT_DEBUG_FAULT_HANG_RESET出现异常后尝试上传死机信息给PC工具，上传成功或者超时后重启
    如果为了方便调试，可以设置为LUAT_DEBUG_FAULT_HANG，出现异常后死机不重启
    但量产出货一定要设置为出现异常重启！！！！！！！！！
    */
    luat_debug_set_fault_mode(LUAT_DEBUG_FAULT_HANG_RESET);
    // luat_debug_set_fault_mode(LUAT_DEBUG_FAULT_HANG);

    /*遍历自动初始化函数*/
    _BspInit(); // 朝阳内部使用的BSP初始化
#ifdef  SR_USE_LOG
    SR_LogUartInit(); // 朝阳调试串口初始化
#endif
    SR_UserBspInit(); // 开放给用户使用的BSP初始化，弱定义，用户重写

    _ComponentInit();       // 朝阳内部使用的组件初始化
    SR_UserComponentInit(); // 开放给用户使用的组件初始化，弱定义，用户重写

    _AppInit();       // 朝阳内部使用的APP初始化
    SR_UserAppInit(); // 开放给用户使用的APP初始化，弱定义，用户重写

    
#ifdef SR_PON_REASON_LOG
	/*开机原因查询,原厂API	*/
	pwrReason = luat_pm_get_poweron_reason();
	luat_pm_last_state(&lastState, &rtcOrPad);
	SR_LOG(INFO,"pwrResn = %d, lastState = %d, rtcOrPad = %d\r\n", pwrReason, lastState, rtcOrPad);

    srReason = SR_HalPmGetPoweronReason();
    SR_LOG(INFO,"[PwrReason] %d\r\n", srReason);

#endif


    // 创建周期调度线程
    osThreadId_t pollThd = SR_NULL;
    const osThreadAttr_t thdAttr =
        {
            .name = "poll",
            .stack_size = 2048,
        };
    pollThd = osThreadNew(_PollThread, SR_NULL, &thdAttr);

    SR_MainEntry(arg); // 主函数入口,弱定义，用户重写
    osThreadExit();    // 退出线程
}

static void _MainEntry(void)
{
    osThreadId_t mainThd = SR_NULL;
    BSP_LOG(INFO,"_MainEntry Enter...\n");

    const osThreadAttr_t thdAttr =
        {
            .name = "main",
            .stack_size = 4096,
        };

    mainThd = osThreadNew(_PreEntry, SR_NULL, &thdAttr);
}
INIT_TASK_EXPORT(_MainEntry, "0"); // TASK 优先级0


