#include <stdio.h>
#include "err_num.h"
#include "osp_type_def.h"
#include "osp_init.h"
#include "osp_msg.h"
#include "osp_sw_queue.h"
#include "osp_task.h"
#include "osp_timer.h"
#include "osp_mem.h"
#include "osp_cfgfile.h"
#include "smartos.h"    /* OS */
#include "hwque.h"
#include "spu_shell.h"
#include "spu_log.h"

#include "ucp_printf.h"
#include "ape_drv.h"
#include "ucp_utility.h"
#include "ucp_handshake.h"
#include "ucp_heartbeat.h"

int g_ape_id = 0;
int g_que_id = 0;

extern void phy_init();
extern void tod_int_init();
extern void spu_shell_task(void);
extern int  osp_shell_init(void);

#ifdef UCP_TICK_ENABLE
extern osp_msg_tick_info st_tick_info;
void osp_ape_send_msg_task(void* data)
{
    static int s_num = 0;
    static int s_send = 0;
    char *send_addr1 = NULL;
    int  ret = -1;

    s_num++;

    send_addr1 = osp_alloc_msg(20);
    if (NULL == send_addr1)
    {
        UCP_PRINT_LOG("SendTask to ape1: osp_alloc_msg(20) error.....(loop = 0x%08x)\r\n", loop);
        return ;
    }

    do_write(send_addr1, s_num);
    do_write((send_addr1+4), s_num);

    /* 根据用例修改（核内/核间） */
    ret = osp_send_msg((uint32_t)(send_addr1),
                        20,
                        UCP4008_KERNEL_INTER, /* 核内/核间 */
                        g_ape_id,
                        g_ape_id+1,
                        22,
                        24);                  /* task id */

    if (0 != ret)
    {
        UCP_PRINT_LOG("SendTask to ape1: osp_send_msg(20) error.....(loop = 0x%08x)\r\n", loop);
    }
    s_send++;
    debug_write(OSP_DEBUG_POT(g_ape_id, 111), s_send);
    /* 核间 */
    debug_write(OSP_DEBUG_POT(g_ape_id, 206), st_tick_info.u32_send_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 207), st_tick_info.u32_inque1_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 208), st_tick_info.u32_inque2_tick);

#if 1
    /* 核内 */
    debug_write(OSP_DEBUG_POT(g_ape_id, 206), st_tick_info.u32_send_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 207), st_tick_info.u32_sw_enque1_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 208), st_tick_info.u32_sw_enque2_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 209), st_tick_info.u32_sem_post_tick);
#endif
    UCP_PRINT_LOG("APE0(inter) to APE1 addr(0x%x) return ok, s_num = 0x%x\r\n", send_addr1, s_num);
    return ;
}

/* Task: recv msg from Arm's platform */
void osp_ape_rec_msg_task(void* data)
{
    static int s_num = 0;
    //int ret = -1;
    rdmcycle(&st_tick_info.u32_recv_tick);

    s_num++;
    UCP_PRINT_LOG("APE%x: recv from ape0 enter ... s_num = 0x%x\r\n", g_ape_id, s_num);
    debug_write(OSP_DEBUG_POT(g_ape_id, 113), s_num);

#if 1
    /* 核间 */
    debug_write(OSP_DEBUG_POT(g_ape_id, 210), st_tick_info.u32_sem_wait_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 211), st_tick_info.u32_recv_msg_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 212), st_tick_info.u32_deque1_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 213), st_tick_info.u32_deque2_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 214), st_tick_info.u32_callback_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 215), st_tick_info.u32_recv_tick);

    debug_write(OSP_DEBUG_POT(g_ape_id, 216), st_tick_info.u32_irq_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 217), st_tick_info.u32_irq_deque1_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 218), st_tick_info.u32_irq_deque1_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 219), st_tick_info.u32_irq_enque1_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 220), st_tick_info.u32_irq_enque2_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 221), st_tick_info.u32_irq_post_tick);
#endif

#if 1
    /* 核内 */
    debug_write(OSP_DEBUG_POT(g_ape_id, 210), st_tick_info.u32_sem_wait_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 211), st_tick_info.u32_recv_msg_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 212), st_tick_info.u32_deque1_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 213), st_tick_info.u32_deque2_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 214), st_tick_info.u32_callback_tick);
    debug_write(OSP_DEBUG_POT(g_ape_id, 215), st_tick_info.u32_recv_tick);
#endif
    return ;
}

#endif

#if 0
void osp_ape_loop_test_init()
{
    return ;
}

void osp_ape_loop_test_task(void* data)
{
    static int s_num = 0;

    s_num++;
    //UCP_PRINT_LOG("APE0x%08x: loo_test_task (num = 0x%08x)\r\n", g_ape_id, s_num);
    return ;
}

osp_task_inf g_osp_task_inf_tb[] =
{
    {1, 20, (int8_t*)"osp_recv", 20, osp_ape_loop_test_init, osp_ape_loop_test_task, 2048},

    {0xffff,},
};

osp_task_ext_inf g_osp_task_ext_tb[] =
{
    {1, 20, OSP_NORMAL_TYPE, 0, 1, 0},

    {0xffff,},
};
#endif

/*                        Test Code End                              */
/*********************************************************************/


/****************************************/
/* 心跳任务，定时更新心跳值 */
#ifdef HEARTBEAT_ENABLE
static uint32_t gu32OpsHeartbeatCnt = 0;
static uint8_t  gu8FreeInit4kEnable = 1;
extern char *init_st_ptr;

void osp_heartbeat_task(void)
{
    gu32OpsHeartbeatCnt++;
#ifdef OSP_DEBUG_TEST
    debug_write(OSP_DEBUG_POT(g_ape_id, 15), gu32OpsHeartbeatCnt);
#endif
    heart_beat_write();
    
    if(200 == gu32OpsHeartbeatCnt)
    {
        if(gu8FreeInit4kEnable)
        {
            gu8FreeInit4kEnable = 0;
            smart_reclaim_init_res();
        }
    }
    
    return ;
}
#endif

/****************************/
/*
APE侧 OSP业务平台初始化：
    打印组件
    硬件队列
    内存模块
    配置文件模块
    任务模块
    读取配置文件
*/
void osp_init()
{
    int ret;
    uint8_t flag = 0;
    spu_log_init(LOG_ERROR);

    ret = osp_hw_que_init(g_ape_id, g_que_id);
    if (OSP_OK != ret)
    {
        UCP_PRINT_ERROR("osp_hw_que_init failed\r\n");
        return ;
    }
#ifdef OSP_DEBUG_TEST
    debug_write(OSP_DEBUG_POT(g_ape_id, 0), ++flag);  //0x1
#endif

    /* 内存模块初始化 */
    ret = osp_mem_init();   /* 根据讨论平台侧可使用的内存为IM区域 */
    if (OSP_OK != ret){
        UCP_PRINT_ERROR("osp_mem_init failed\r\n");
        return ;
    }
    UCP_PRINT_LOG("osp_mem_init OK\r\n");
#ifdef OSP_DEBUG_TEST
    debug_write(OSP_DEBUG_POT(g_ape_id, 0), ++flag);  //0x2
#endif

    /* 配置文件模块初始化 */
    osp_cfgfile_init();
    UCP_PRINT_LOG("osp_cfgfile_init OK\r\n");
#ifdef OSP_DEBUG_TEST
    debug_write(OSP_DEBUG_POT(g_ape_id, 0), ++flag);  //0x3
#endif

    /* 任务模块初始化 */
    osp_task_init();
    UCP_PRINT_LOG("osp_task_init OK\r\n");
#ifdef OSP_DEBUG_TEST
    debug_write(OSP_DEBUG_POT(g_ape_id, 0), ++flag);  //0x4
#endif

#if 0
    /* DDR二次管理 */
    //osp_heap_mem_init(OSP_PHY_DDR_ADDR, OSP_PHY_DDR_SIZE);
    //debug_write(OSP_DEBUG_POT(g_ape_id, 0), ++flag);  //0x5
#endif

    /* Msg init */
    spu_shell_init();
#ifdef OSP_DEBUG_TEST
    debug_write(OSP_DEBUG_POT(g_ape_id, 0), ++flag);  //0x5
#endif

    osp_task_info_ex ape_shell_recv = {56, (int8_t*)"ape_shell_task", 56, 4096, OSP_NORMAL_TYPE, 1, 0, 0, NULL, (OSP_TASKENTRY_FUNC)spu_shell_task};

    /* 平台任务注册 */
    osp_task_create(&ape_shell_recv);

#ifdef HEARTBEAT_ENABLE
    /* 心跳任务   */
    osp_task_info_ex ape_heartbeat_loop = {62, (int8_t*)"ape_heartbeat_task", 62, 1024, OSP_NORMAL_TYPE, 3, 0, 0, NULL, (OSP_TASKENTRY_FUNC)osp_heartbeat_task};
    osp_task_create(&ape_heartbeat_loop);
#endif

    //osp_task_reg(g_osp_task_inf_tb, g_osp_task_ext_tb, g_ape_id);

#if 0
    /* 握手完成，ARM侧已经读完配置文件，APE侧取文件 */
    //osp_cfgfile_read();
    //debug_write(OSP_DEBUG_POT(g_ape_id, 4), 5);
#endif

    UCP_PRINT_LOG("osp_init done \r\n");
#ifdef OSP_DEBUG_TEST
    debug_write(OSP_DEBUG_POT(g_ape_id, 0), ++flag);  //0x6
#endif

    return ;
}

/*******************************************************************/
start_hook_func osp_init_start_hook[] =
{
    tod_int_init,
    ape_drv_int_init,
    osp_init,
    phy_init,
    NULL,
};

void osp_start()
{
    int32_t core_id = get_core_id();
    int32_t ret = 0;
    g_ape_id = get_core_id();
    g_que_id = g_ape_id;

    ret = smart_os_debug_init((DBG_DDR_OS_ADDR_BASE + core_id*DBG_DDR_OS_LEN), DBG_DDR_OS_LEN);  // 推荐0x40, 实际0x100
    if (0 != ret)
    {
        debug_write(DBG_DDR_ERR_IDX(core_id, 31), ret); // ape0: 0xb7e2407c
    }

    ret = smart_no_idle_sw_init((DBG_DDR_OS_NO_IDLE_BASE + core_id*DBG_DDR_OS_NO_IDLE_LEN), DBG_DDR_OS_NO_IDLE_LEN);  // 推荐0x40, 实际0x100
    if (0 != ret)
    {
        debug_write(DBG_DDR_ERR_IDX(core_id, 47), ret);
    }

    smart_kernel_init(osp_init_start_hook, g_ape_id);
}

void osp_var_init()
{
    /* 设置配置文件标识位 */
    do_write(OSP_CFG_PHY_ADDR, OSP_CFG_FLAG_START);
#ifdef OSP_DEBUG_TEST
    debug_write(OSP_DEBUG_POT(get_core_id(), 100), OSP_CFG_FLAG_START);
#endif
    __ucps2_synch(0);

    return ;
}

