/*******************************************************
*Copytight(C),2022,Shanghai Eastsoft Microelectronics Co.,Ltd.
*文件名：iap_chipcheck.c
*作  者：AE Team
*版  本：v1.0，编译于iDesigner(v4.2.3.186) + 工具链HRCC(v1.2.0.124)
*日  期：2022/12/01
*描  述：IAP读芯片程序校验码，配置字需使能FREN。
        CHECK0:6010H
		CHECK1:6011H	
		校验码共2字节，ICDEN禁止，烧录程序后复位运行，校验码通过UART打印，TX:PB5，baud:9600，无奇偶校验。
        注意：建议IAP操作前关闭WDT，若使能WDT，请设置合理的WDT溢出时间，并合理清狗。
*备  注：本软件仅供学习和演示使用，对用户直接引用代码所带来的风险或后果不承担任何法律责任。
*******************************************************/
#include <hic.h>

#define CLRWDT()   {__Asm CWDT;}    //宏定义清狗指令
unsigned long check_code[2];	            //保存芯片程序校验码,check_code[0]存放CHECK0，check_code[1]存放CHECK1

/******************************************************
函数名：void RAMclear(void)
描  述：RAM区数据清零，RAM区地址0x0000~0x03FF
输入值：无
输出值：无
返回值：无
*******************************************************/
void RAMclear(void)
{
    for (IAAH=0; IAAH<=0x03; IAAH++)
    {
        for (IAAL=0; IAAL<0xFF; IAAL++)
            IAD = 0x00;
        IAD = 0x00;
    }
}

/******************************************************
函数名：void GPIOInit(void)
描  述：首先初始化所有未用到的IO口为输出低电平
输入值：无
输出值：无
返回值：无
*******************************************************/
void GPIOInit(void)
{
    ANSL = 0xFF;        //选择对应端口为数字IO功能
	ANSH = 0xFF;        //选择对应端口为数字IO功能
    PAT = 0x00;         //所有IO设为输出低电平
    PBT = 0x00;
    PCT = 0x00;
    PA = 0x00;
    PB = 0x00;
    PC = 0x00;
}

/*******************************************************
函数名：void FlashRdCheckcode(unsigned long *ptr)
描  述：读芯片校验码
输入值：容量至少为2个Words的数组指针
输出值：无
返回值：无
*******************************************************/
void FlashRdCheckcode(unsigned long *ptr)
{
	unsigned char checkp;
	unsigned char gie_bk = GIE;		//备份GIE
    CLRWDT();
	while(GIE) GIE = 0;
	DATARDEN = 1;                   //数据区和信息区读出使能
	for (checkp = 0; checkp < 2; checkp++)
	{
		FRAH = (0x6010 + checkp) >> 8;
		FRAL = (0x6010 + checkp);
		DATARDTRG = 1;              //读触发
		while(DATARDTRG) ;          //等待读完成
		__Asm TBR;		            //查表读指令
		ptr[checkp] = ((unsigned long)ROMD1H << 24) | ((unsigned long)ROMD1L << 16) | ((unsigned long)ROMDH << 8) | ROMDL;
	}	
    ROMCL = 0x00;                   //退出读操作
	GIE = gie_bk;                   //恢复全局中断
}

/*******************************************************
函数名：void main(void)
描  述：主函数
输入值：无
输出值：无
返回值：无
*******************************************************/
void main(void)
{
	unsigned char check_buf[2];
	unsigned char i;
    RAMclear();
    GPIOInit();
    CLRWDT();

    PBT5 = 0;       //TX输出
    PBT6 = 1;       //RX输入
    RX1LEN = 0;     //8位数据接收格式
    TX1LEN = 0;     //8位数据发送格式
    BRGH1 = 0;      //波特率低速模式：波特率=Fosc/(64*(BRR<7:0>+1))
    BR1R = 0x19;    //波特率=16MHz/(64*(25+1))≈9600bps

    RX1EN = 1;       //打开接收
    TX1EN = 1;       //打开发送

/******************IAP读出(示例)********************/
    FlashRdCheckcode(&check_code);	//读chipID
    CLRWDT();

	for(i = 0; i < 2; i++)
		check_buf[i] = check_code[i] & 0xFF;

	for(i = 0; i < 2; i++)  //将校验码通过UART打印
	{
		while (!TRMT1);
		TX1B = check_buf[i];
		CLRWDT();
	}

    while (1)
    {
        CLRWDT();
    }
}
