/************************************************************************* 
* 版权所有：	
* 文件版本： V1.00
* 文件名称： main.C主程序
* 生成日期： 2008年8月8日
* 作    者： 
* 功    能： 保护主函数处理，
* 更新信息：
*     更新日志1：
*         日期：      
*         修改者：    
*         修改内容：  
*         修改原因：  
*     更新日志2：
**************************************************************************/



#include "head.h"
#include "rt_printf.h"
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/syscall.h>

// 系统秒，从程序启动时刻算起
u32 g_tick_secs;

// 系统重启定时器
u32 g_restart_count;

#if defined CPU_AM335X || defined CPU_FUXI
extern bool SystemInit_finish_flag __attribute__((aligned(8)));
#endif

/********************************************************************
版权所有：	
文件版本： V1.00
文件名称： main.c
生成日期： 2008年08月26日
作    者：
使用范围：

功    能：主函数
更新信息：
更新日志1：
修改者:
修改日期:
修改内容:
修改原因:
*********************************************************************/
int app_main (void *arg);
int kernel_callback(void);
int dt_cmd_rt_reset(void);
int uart_test(void);
int test_round(void);
int ds18b20_init(void);
int sntp_init(void);
int rtc_test(void);
int adc_test(void);
int bkpt_disable(void);
#ifdef CPU_FUXI
 uint32_t wdt_id_mainloop;
 extern int printf_e907_init(void);
#endif

 void bkpt_isr(void)
 {
 	rt_printf("x\r\n");
 }

#if defined(CPU_AM335X) 
static void check_app_folder_recover(void)
{
	//应用启动后，需要判断 /tmp/app_empty_flag 文件是否存在，如果存在，则说明这次启动 app 分区进行了恢复，你那边记录后把该文件删除掉。
	struct file * pfile = rt_file_open("/tmp/app_empty_flag",O_RDONLY ,0);
	if(IS_ERR(pfile))
	{
		;
	}
	else
	{
		rt_printf("临时文件/tmp/app_empty_flag不存在,之前发生过app分区恢复操作.\r\n");
		soe_record_opt(EV_APP_FOLDER_RECOVER,0);
		rt_file_del("/tmp/app_empty_flag");
	}

}
#endif

int app_main (void *unused)
{
	int ret;
	uint64_t us0,us0_sec;

	// 将BKPT管脚设置为中断，防止由于EMC干扰，导致系统复位。
#ifdef CPU_COLDFIRE	
	bkpt_disable();
	rt_request_irq(12,4,bkpt_isr,"bkpt_isr");
#endif

	//登记bsp回调函数
	rt_irq_level(0);
	SystemInit();
#ifdef CPU_FUXI
	SystemInit_finish_flag = true;	
#endif
#ifdef CPU_FUXI
	printf_e907_init(); 
#endif

#ifdef RCD_STRAN_S
	_rcd_get_waveno();	/*装置地址要读出参数才有效*/
#endif
#ifndef CPU_FUXI
	watchdog_register_all();
#endif
	dt_cmd_rt_reset();
	rt_stat_other_init(RT_STAT_BIG_LOOP,"主循环");
	rt_stat_other_init(1,"5ms_2");
	rt_stat_other_init(2,"5ms_3");
	rt_stat_other_init(3,"测量计算1");
	rt_stat_other_init(4,"测量计算2");
	rt_stat_other_init(5,"SOE保存");
	rt_stat_other_init(6,"临时测试");
	rt_stat_other_init(7,"主循环间隔");
#ifdef SNTP_FUNC	
	sntp_init();
#endif
	{
		// 记录关键文件CRC
		char name[256];
		char log_info[128];
		sprintf(name,"上电完成。校验CRC:程序0x%04x, 资源表0x%04x, 板卡资源0x%04x, 通道配置0x%04x, 点表0x%04x。",
				m_CodeCrc,g_crc_rsc, g_crc_brd_res, g_crc_equ_cfg, g_crc_rectable);	
		
		log_str_time(LOG_ERR,name,0,1);

		sprintf(log_info,"Device is powered on,crc:code=0x%04x,rsc=0x%04x,brd_res=0x%04x,equ_cfg=0x%04x,rectable=0x%04x",
			m_CodeCrc,g_crc_rsc, g_crc_brd_res, g_crc_equ_cfg, g_crc_rectable);

		load_hs_log_rcd(TYPE_DEV_RESTART,true,NULL,log_info,1);
	}

	ret = get_mt_port_proc();
	if(ret != 1) {
		close_inet_port();
	}

#if defined(CPU_AM335X) 
	check_app_folder_recover();
#endif

#ifdef CPU_FUXI
	// noted by sunxi: 经测试发现，装置运行10多分钟后，tmp文件里的rsc.bin和set_desc.bin会莫名消失。
	// 经分析得，伏羲系统会周期(十多分钟)删除掉tmp文件夹中的旧文件(rsc.bin和set_desc.bin 文件是在
	// 系统对时前产生的，所以时间默认比较早)。因此在这里统一对tmp文件夹的文件更新一下。
	system("touch /tmp/*");
	prctl(PR_SET_NAME, "app_main_loop");
#endif
#ifdef RT_THREAD_DEBUG
	rt_printf("Thread created successfully: %s, PID: %d LWP: %d\r\n", 
              	"app_main_loop", (int)getpid(), (int)syscall(SYS_gettid));
#endif

	dp_info_nt("最大定值个数 MAX_SET_NUMBER = %d\r\n", MAX_SET_NUMBER);
	dp_info_nt("装置参数 EQUIP_PARA_NUMBER = %d, PARA_NUM = %d\r\n", EQUIP_PARA_NUMBER, PARA_NUM);
	dp_info_nt("保护定值 SW_SET_NUMBER = %d, SW_SET_NUMBER = %d\r\n", SW_SET_NUMBER, SW_SET_NUMBER);
	dp_info_nt("开关个数 SWITCH_NUM_MAX = %d, 全部开关保护定值总个数 SET_NUMBER = %d\r\n", SWITCH_NUM_MAX, SET_NUMBER);
	dp_info_nt("公共定值 PUB_SET_NUMBER = %d, SET_PUB_NUM = %d\r\n", PUB_SET_NUMBER, SET_PUB_NUM);
	dp_info_nt("内部定值 CSTSET_NUMBER = %d, CSTSET_NUM = %d\r\n", CSTSET_NUMBER, CSTSET_NUM);
	dp_info_nt("固有参数 FIXEDSET_TABLE_NUMBER = %d\r\n", FIXEDSET_TABLE_NUMBER);

	{
		struct timespec ts;
		struct rtc_time_t ct;

		gps_get_time(&ts);
		timespec_to_rtc(ts, &ct, 1);
		rt_printf("当前时间: %04d-%02d-%02d %02d:%02d:%02d\r\n", ct.year+2000, ct.month, ct.day, ct.hour, ct.min, ct.ms/1000);
	}
#if defined(CPU_AM335X)	
	watchdog_unregister_module();
#endif	

#if defined(BSP_CAN_ENABLE)
	// 复位所有子板
	can_app_reset(0);
#endif
#if defined(CAN_SLAVE_BOARD)
	// 复位所有子板
	can_app_reset(0);
#endif

#ifdef CPU_FUXI
	int rc = watchdog_add_item("mainloop", &wdt_id_mainloop,60);
	if(rc != 0) {
		printf("can not add mainloop task to wdt\r\n");
		return -1;
	}
#endif

	us0_sec = bsp_ustimer_get_origin();
	rt_printf("主循环启动...\r\n");
	while(1)
	{
		us0 = bsp_ustimer_get_origin();
//		test_round();
//		uart_test();
//		flash_test();
//		adc_test();
//		gps_test();
				
//		dido_test();
//		rtc_test();
#ifdef CPU_FUXI
		msleep(100);
		// shm_comm_test();
#endif
		// 系统的tick秒
		if(us0 - us0_sec > USTIMER_SEC)
		{
			g_tick_secs++;
			us0_sec += USTIMER_SEC;
			
			if(g_restart_count)
			{
				g_restart_count--;
				if(g_restart_count == 0)
				{
					rt_printf("装置重启\r\n");
					watchdog_reset_cpu(2);	//装置复位
				}
			}
		}

#if defined(BSP_CAN_ENABLE)
		equ_check_period();
		can_task();
#else
	#ifdef CAN_SLAVE_BOARD
		can_task();
	#endif
#endif
#ifdef CPU_FUXI	
		sys_time_check();	
#endif	
		rt_err_app();
		soe_save();
		IECCommTask();
		Maintain_Applay();
		net_debug_app(); 
		IEC104_Ether_App();
		FA_status_write();
		sec_app();
		clk_app();
		AppPolling();		// 设备状态处理，如点灯等
		create_set_file();		

	#ifdef TMP_CHIP_AHT20
		aht20_task();
	#endif
	#ifdef  METERING_ENERGY
		metering_yc_refresh();
		DD_Calc();
	#endif

	#ifdef FUNC_DRIVE
		quit_drive();
	#endif

	#ifdef FUNC_RESET_EQU
		equ_PowerRest();
	#endif
		// 喂主循环软件狗 
		watchdog_feed_mainloop();
		
		//统计大循环时间
		rt_stat_other_in(RT_STAT_BIG_LOOP,bsp_ustimer_get_duration(us0)/USTIMER_US);
#ifdef LINUX_KERNEL_APP
		kernel_callback();
#endif		
		//us0 = ustimer_get_origin();
		rt_stat_other_in(7,bsp_ustimer_get_duration(us0)/USTIMER_US);
	}
#ifdef CPU_FUXI
	watchdog_remove_item(wdt_id_mainloop);
#endif

	return 0;
} 
#if 0 // sunxi 20191018
#ifndef LIB_61850_SW
 int gi_platelib_state=2;
 int app_goose_init(int fn) 
 {
	return 0;
 }
 void app_goose_pub_data_handle(char *gse_data, int gseoutnum)
 {
  return;
 }
 
 int app_goose_recv_data_handle(unsigned int index, char *buf, const int buflen, char *outdata)
 {
  return 0;
 }
 
 void app_goose_timer_data_handle(const uint32_t us_diff)
 {
  return;
 }
 
 void goose_pub_init(char *gse_data, int gseoutnum)
 {
  return;
 }
 void app_goose_exit(void)
 {
  return;
 }
 
 void app_goose_inf_print(void)
 {
 
 }
 
 void lib61850_set_task_exit(void)
 {
 }
 int lib61850_start_task(void *arg)
 {	return 0;
 }
#endif
#endif // sunxi 20191018

