//=====================================================================
//文件名称：isr.c（中断处理程序源文件）
//框架提供：SD-ARM（sumcu.suda.edu.cn）
//版本更新：20170801-20191020
//功能描述：提供中断处理程序编程框架
//移植规则：【固定】
//=====================================================================
#include "includes.h"

//======================================================================
//中断名称：UART2_IRQHandler
//功能概要：UART2接收中断，处理接收到的数据。
//参  数: 无
//返  回: 无
//说  明: 需要启动中断并注册才可使用
//======================================================================
void UART_UPDATE_Handler(void)
{
    //（1）变量声明
    uint8_t uflag;  //更新接收标志?
    uint8_t flag,ch;
    uint8_t buf[100]; //100字节数据用于存放返回数据
    uint16_t bufLen;  //返回数据长度
    uint8_t i=0;
    uint32_t count=0;
    //（2）未触发串口接收中断，退出
    if(!uart_get_re_int(UART_UPDATE)) goto UART_UPDATE_Handler_EXIT;
    //（3）收到一个字节，读出该字节数据
    ch = uart_re1(UART_UPDATE,&flag);        //调用接收一个字节的函数
    if(!flag) goto UART_UPDATE_Handler_EXIT; //实际未收到数据，退出
    //（4）至此，一定是收到一个字节，该字节进入帧内组帧
    //若全局变量gcRecvLen=0，表示组帧尚未完成，继续组帧?
    if(gcRecvLen == 0)  gcRecvLen =emuart_frame(ch,(uint8_t*)gcRecvBuf);
    //（5）字节进入组帧后，判断gcRecvLen=0？若为0，表示组帧尚未完成，
    //     下次收到一个字节，再继续组帧
    if(gcRecvLen == 0) goto UART_UPDATE_Handler_EXIT;
    //（6）至此，gcRecvLen≠0,表示组帧完成，gcRecvLen为帧的长度,
    //     根据gcRecvBuf[0]进行跳?
    switch(gcRecvBuf[0])  //帧标识
    {
    
        //（6.1）gcRecvBuf[0]=0～5，表示更新数据
        case 0:  //更新开始
        ueupdate_init(GEC_USER_SECTOR_START,GEC_USER_SECTOR_END,
                        MCU_SECTORSIZE);  //ueupdate初始化
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
        uflag = ueupdate_reframe((uint8_t*)gcRecvBuf,gcRecvLen);
        switch(uflag)
        {
            case 1:  //整体替换更新,跳转BIOS程序后继续执行
            memcpy((void*)gcUpdateFlag,"uart\0",5);
            NVIC_SystemReset();
            break;
            case 4:  //丢帧?
            ueupdate_checkGet(buf,&bufLen);
            emuart_sendN(bufLen,buf);  //返回丢帧信息
            break;
            case 6:  //替换更新操作成功
            gFunFlag = 0;  //代码更新完毕，转向用户代码
            uart_send_string (UART_UPDATE,(uint8_t *)
                               "  【BIOS提示】：User程序下载完毕，为运行User程序做准备...\r\n");
            while (count< 0x20000)
            {
                count++;
            }                      //增加20ms延时更稳定
            count=0;
            NVIC_SystemReset();
            break;
            case 7:  //保留更新操作成功
            NVIC_SystemReset(); //系统复位，运行新的User程序
            break;
            default:
            ueupdate_backGet(buf,&bufLen);
            emuart_sendN(bufLen,buf);  //返回信息
            break;
        }
        break;
        //（6.2）gcRecvBuf[0]=10，表示握手数据
        case 10:  //上位机串口握手
        if(strncmp((char *)(gcRecvBuf+1),"shake",5) == 0)
        {
            //返回握手帧数据，供上位机判断
            emuart_sendN(sizeof(struct shakeData),(uint8_t*)&gShakeData);
            gcRecvLen = 0;
        }
        break;
        //（6.3） gcRecvBuf[0]=20～21，表示动态命令数据
        case 20:   //判断写机器码
        if(gcRecvLen==7)    //1帧头+4字节CRC32校验+2长度
        {
            gcRecvDCLen=gcRecvBuf[5]*256+gcRecvBuf[6];
            if(gcRecvDCLen>((GEC_DYNAMIC_END-GEC_DYNAMIC_START+1)*
               MCU_SECTORSIZE))//超过长度限制
            {
                gcRecvDCLen=0xFFFF;
                emuart_sendN(2,(uint8_t *)"no");
                break;
            }
            else
            {
				emuart_sendN(3,(uint8_t *)"new");
                for(i=GEC_DYNAMIC_START;i<=GEC_DYNAMIC_END;i++)
                {
                    flash_erase(i);
                }
                gcRecvDCLen=0;
                break;
            }
            break;
        }
        else
        {
            if(gcRecvDCLen==(gcRecvBuf[5]*256+gcRecvBuf[6]-gcRecvLen+7))
            {
                emuart_sendN(2,(uint8_t *)"ok");
            }
            else
            {
                emuart_sendN(3,(uint8_t *)"get");
            }
            flash_write_physical((GEC_DYNAMIC_START+
                (gcRecvDCLen/MCU_SECTORSIZE))*MCU_SECTORSIZE+gcRecvDCLen-
                (gcRecvDCLen/MCU_SECTORSIZE)*MCU_SECTORSIZE,gcRecvLen-7,
                (uint8_t *)(gcRecvBuf+7));
            gcRecvDCLen+=gcRecvLen-7;
            break;
        }
        break;
        case 21://执行动态命令
             dynamic_cmd(gcRecvBuf,&gcRecvLen);
        
        break;
    }
    gcRecvLen = 0;  //恢复接收状态
    //退出处
    UART_UPDATE_Handler_EXIT:
    return;
}


/*
知识要素：
1.本文件中的中断处理函数调用的均是相关设备封装好的具体构件，在更换芯片
时，只需保证设备的构件接口一致，即可保证本文件的相关中断处理函数不做任何
更改，从而达到芯片无关性的要求。
*/


