# -- coding: utf-8 --
from analyzer import Analyzer
from analyzer import register_analyzer
from analyzer import LogLevel

class EXTDMAAnalyzer(Analyzer):
    def run(self):
        super().run()
        self.log(LogLevel.INFO, f"{self.periph_name}分析启动")
        inst_error = 0
        HPSYS_RCC = self.read_peripheral("hpsys_rcc")
        #self.print_reg(HPSYS_RCC)
        if (HPSYS_RCC.ENR1.EXTDMA!=1):
            self.log(LogLevel.ERROR, f"{self.periph_name}模块时钟未开启",\
                     "需将HPSYS_RCC的ESR1_EXTDMA置1以开启模块时钟")
            inst_error = 1
        if (HPSYS_RCC.RSTR1.EXTDMA!=0):
            self.log(LogLevel.ERROR, f"{self.periph_name}模块被复位",\
                     "需将HPSYS_RCC的RSTR1_EXTDMA置0以释放模块复位")
            inst_error = 1

        if (inst_error==1):
            self.log(LogLevel.ERROR, f"{self.periph_name}上述初始配置发现错误，分析无法继续进行",\
                     "请将上述错误修正后重新启动分析")
            return
        #self.log(LogLevel.INFO, "初始配置分析完成，未发现错误，启动功能分析")

        EXTDMA = self.read_peripheral(f"{self.periph_name}")
        
        if (EXTDMA.CCR.SRCSIZE != 2):
            self.log(LogLevel.ERROR, f"源数据类型不是四字节",\
                     "CCR.SRCSIZE必须为2")
            inst_error = 1
        if (EXTDMA.CCR.DSTSIZE != 2):
            self.log(LogLevel.ERROR, f"目的数据类型不是四字节",\
                     "CCR.DSTSIZE必须为2")
            inst_error = 1
        if (EXTDMA.CCR.SRCINC):
            ch_src_inc_str = "递增"
        else:
            ch_src_inc_str = ""
        if (EXTDMA.CCR.DSTINC):
            ch_dst_inc_str = "递增"
        else:
            ch_dst_inc_str = ""
        if (EXTDMA.CCR.EN):
            ch_en_str = "已使能"
        else:
            ch_en_str = "未使能"
        if (EXTDMA.SRCAR.value == 0 and EXTDMA.DSTAR.value == 0):
            #地址未配置
            self.log(LogLevel.INFO, f"EXTDMA未配置搬运地址")
        else:
            ch_valid = 1
            self.log(LogLevel.INFO, f"0x{EXTDMA.SRCAR.value:08x}四字节{ch_src_inc_str}->\
0x{EXTDMA.DSTAR.value:08x}四字节{ch_dst_inc_str},\
{ch_en_str},剩余{EXTDMA.CNDTR.NDT}次待搬运({4*EXTDMA.CNDTR.NDT}字节)")
            #检查地址是否合法
            if (EXTDMA.SRCAR.value & 3):
                self.log(LogLevel.ERROR, f"源地址0x{EXTDMA.SRCAR.value:08x}不是四字节对齐",\
                         "源地址必须为四字节对齐")
                inst_error = 1
            if (EXTDMA.DSTAR.value & 3):
                self.log(LogLevel.ERROR, f"目的地址0x{EXTDMA.DSTAR.value:08x}不是四字节对齐",\
                         "目的地址必须为四字节对齐")
                inst_error = 1
            if (self.check_addr(EXTDMA.SRCAR.value)):
                self.log(LogLevel.ERROR, f"源地址0x{EXTDMA.SRCAR.value:08x}处于{self.periph_name}无法访问的区间",\
                                 "请检查地址设置")
                inst_error = 1
            if (self.check_addr(EXTDMA.DSTAR.value)):
                self.log(LogLevel.ERROR, f"目的地址0x{EXTDMA.DSTAR.value:08x}处于{self.periph_name}无法访问区间",\
                                 "请检查地址设置")
                inst_error = 1
            #检查中断使能
            if (EXTDMA.CCR.TCIE == 0 and EXTDMA.CCR.HTIE == 0):
                self.log(LogLevel.WARN, f"传输完成中断(TCIE)与传输过半中断(HTIE)均未使能",\
                                 f"请将TCIE或HTIE置1使能中断")
            #检查传输完成标志
            if (EXTDMA.ISR.TCIF):
                self.log(LogLevel.INFO, f"传输完成，中断未处理")
        
        if (inst_error==1):
            self.log(LogLevel.ERROR, f"{self.periph_name}配置发现错误",\
                     "请检查配置")
        else:
            self.log(LogLevel.INFO, f"{self.periph_name}分析结束，未发现错误")

   
    #检查传输地址是否合法,合法返回0
    def check_addr(self,addr):
        if (addr >= 0x20000000 and addr < 0x20080000): #HPSYS RAM
            return 0
        if (addr >= 0x60000000 and addr < 0xa0000000): #MPI
            return 0
        if (addr >= 0x20400000 and addr < 0x20410000): #LPSYS RAM
            return 0
        if (addr >= 0x40000000 and addr < 0x400d0000): #LPSYS PERI
            return 0
        return 1

        
register_analyzer("EXTDMA", EXTDMAAnalyzer)

