#============================================================================
#文件名称：gpio.S
#功能概要：KL25 GPIO底层驱动构件（汇编）程序文件
#============================================================================

.include "gpio.inc"

.section .text
#---------------------以下为外部接口函数------------------------------------
#============================================================================
# 函数名称：gpio_init   
# 函数返回：无                
# 参数说明：r0:(端口号|(引脚号)),例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
#          r2:引脚方向（0=输入,1=输出,可用引脚方向宏定义）
#          r3:端口引脚初始状态（0=低电平，1=高电平）
# 功能概要：初始化指定端口引脚作为GPIO引脚功能，并定义为输入或输出。若是输出，
#          还指定初始状态是低电平或高电平
# 备    注：端口x的每个引脚控制寄存器PORTx_PCRn的地址=PORT_PCR_BASE+x*0x1000+n*4
#           其中:x=0~4，对应A~E;n=0~31
#============================================================================
gpio_init:
    push {r4-r7,lr}              @保存现场，pc(lr)入栈
    #------------------------------------------------------------------------
    #从入口参数r0中解析出端口号引脚号，分别放在r0和r1中
    bl gpio_port_pin_resolution  @调用内部解析函数,r0=端口号,r1=引脚号
    #获得待操作端口的第一个PCR寄存器的地址
    mov r7,r0                    @r7=r0=端口号
    ldr r4,=0x1000               @r4=各端口基地址差值(0x1000)
    mul r7,r7,r4                 @r7=待操作端口与A口的偏移地址
    ldr r4,=PORT_PCR_BASE        @r4=端口A的PCR基地址(即PORT_PCR_BASE)
    add r7,r4                    @r7=待操作端口的第一个PCR寄存器的地址
    #获得待操作引脚PCR寄存器的地址
    mov r4,r1                    @r4=r1=引脚号
    mov r5,#4                    @各引脚的PCR寄存器地址之间差为0x04
    mul r4,r4,r5                 @r4=待操作引脚PCR寄存器的偏移地址
    add r7,r4                    @r7=待操作引脚PCR寄存器的地址
    #待操作引脚PCR寄存器的MUX位（10-8位）清0
    ldr r4,=0xfffff8ff
    ldr r5,[r7]                  @r5=待操作引脚PCR寄存器中的内容
    and r5,r4                    @待操作引脚PCR寄存器的MUX字段清零，其余位不变
    #待操作引脚PCR寄存器的MUX位（10-8位）置001,即设置为GPIO功能
    ldr r4,=0x00000100
    orr r5,r4                    @或运算设MUX=001，引脚被配置为GPIO功能
    str r5,[r7]                  @将r5中的MUX值更新到待操作引脚PCR寄存器中
    #求待操作GPIO口的基地址（也就是PDOR的地址）
    ldr r4,=PORT_GPIO            @r4=PORTA基地址（GPIO的基地址）
    mov r7,r0                    @r7=r0=端口号
    mov r6,#0x40                 @r6=各GPIO口基地址差值（40h）
    mul r6,r6,r7                 @r6=待操作GPIO口的地址偏移
    add r4,r6                    @r4=待操作GPIO口的地址,也就是PDOR的地址

    #根据入口参数r3，通过对PDOR的编程，设置相应引脚为低电平或者高电平
    mov r6,#1
    lsl r6,r6,r1                 @r6=待操作的PDOR掩码（为1的位由r1决定）
    cmp r3,#1
    bne gpio_init_1              @r3≠1转gpio_init_1，r3=1继续执行
    #r3=1，设置PDOR相应位为1
    ldr r5,[r4]                  @r5=PDOR中内容
    orr r5,r6                    @或运算设置PDOR相应位为1
    str r5,[r4]                  @将r5中的值更新到待操作端口PDOR寄存器中
    bl gpio_init_2
gpio_init_1:
    #r3=0，设置PDOR相应位为0
    mvn r6,r6                    @r6进行取反，即0变1,1变0
    ldr r5,[r4]                  @r5=PDOR中内容
    and r5,r6                    @与运算设置PDOR相应位为0
    str r5,[r4]                  @将r5中的值更新到待操作端口PDOR寄存器中
gpio_init_2:
    add r4,#0x14                 @r4=待操作GPIO口PDDR寄存器的地址
    #根据入口参数r2，通过对PDDR进行编程，确定引脚为输入或者输出（0为输入，1为输出）
    mov r6,#1
    lsl r6,r6,r1                 @r6=待操作引脚的PDDR掩码（为1的位由r1决定）
    cmp r2,#1
    bne gpio_init_3              @r2≠1转gpio_init_3，r2=1继续执行
    #r2=1，设置PDDR相应位为1
    ldr r5,[r4]                  @r5=PDDR中内容
    orr r5,r6                    @或运算设置PDDR相应位为1
    str r5,[r4]                  @将r5中的值更新到待操作端口PDDR寄存器中
    bl gpio_init_4
gpio_init_3:
    #r2=0，设置PDDR相应位为0
    mvn r6,r6                    @r6进行取反,即0变1,1变0
    ldr r5,[r4]                  @r5=PDDR中内容
    and r5,r6                    @与运算设置PDDR相应位为0
    str r5,[r4]                  @将r5中的值更新到待操作端口PDDR寄存器中
gpio_init_4:
    #-----------------------------------------------------------------------
    pop {r4-r7,pc}               @恢复现场，lr出栈到pc（即子程序返回）
    
#============================================================================
# 函数名称：gpio_set
# 函数返回：无
# 参数说明：r0:(端口号)|(引脚号),例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
#         r3：希望设置的端口引脚状态（0=低电平，1=高电平）
# 功能概要： 当指定端口引脚被定义为GPIO功能且为输出时，本函数设定引脚状态
#============================================================================
gpio_set:
    push {r4-r7,lr}              @保存现场，pc(lr)入栈
    #------------------------------------------------------------------------
    #从入口参数r0中解析出端口号引脚号，分别放在r0和r1中
    bl gpio_port_pin_resolution  @调用内部函数，r0=端口号,r1=引脚号
    #通过对PSOR进行编程，将PDOR相应位置1
    mov r5,r0                    @r5=r0=端口号
    mov r6,#0x40                 @r6=各GPIO口的基地址差值（40h）
    mul r6,r6,r5                 @r6=待操作GPIO口与PORTA的地址偏移
    cmp r3,#1                    @判断引脚初始状态
    bne gpio_set_1               @若为低电平，转到gpio_set_1，将PDOR相应位清0
    ldr r5,=PORT_GPIO+0x04       @r5=PORTA的输出置1寄存器PSOR的地址
    add r5,r6                    @r5=待操作引脚PSOR的地址
    mov r6,#1
    lsl r6,r6,r1                 @r6=待操作引脚的PSOR掩码（为1的位由r1决定）
    str r6,[r5]                  @将相应引脚的PSOR寄存器置1
    bl  gpio_set_2
gpio_set_1:
    #通过对PCOR进行编程，将PDOR相应位清0
    ldr r5,=PORT_GPIO+0x08       @r5=PORTA的PCOR的地址
    add r5,r6                    @r5=待操作引脚PCOR的地址
    mov r6,#1
    lsl r6,r6,r1                 @r6=待操作的PCOR掩码（为1的位由r1决定）
    str r6,[r5]                  @将相应引脚的PCOR寄存器置1
gpio_set_2:
    #------------------------------------------------------------------------
    pop {r4-r7,pc}               @恢复现场，lr出栈到pc（即子程序返回）
    
#============================================================================
# 函数名称：gpio_get
# 函数返回：r2:指定端口引脚的状态（1或0）
# 参数说明：r0:(端口号)|(引脚号),例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
# 功能概要：当指定端口引脚被定义为GPIO功能且为输入时，本函数获取指定引脚状态
#============================================================================
gpio_get:
    push {r4-r7,lr}              @保存现场，pc(lr)入栈
    #------------------------------------------------------------------------
    bl gpio_port_pin_resolution  @调用内部函数，r0=端口号,r1=引脚号
    #求待操作GPIO口的基地址（也就是PDIR的地址）
    mov r5,r0                    @r5=r0=端口号
    mov r6,#0x40                 @r6=各GPIO口基地址差值（40h）
    mul r6,r6,r5                 @r6=待操作GPIO口与PORTA的地址偏移
    ldr r5,=PORT_GPIO+0x10       @r5=PORTA的PDIR地址
    add r5,r6                    @r5=待操作GPIO口的PDIR的地址
    #读取PDIR相应位
    mov r6,#1
    lsl r6,r6,r1                 @r6=待操作引脚的PDIR掩码
    ldr r4,[r5]                  @r4=PDIR中内容
    and r4,r6
    cmp r4,#0                    @判断引脚状态是否为低电平
    bne gpio_get_1
    mov r2,#0                    @r2=指定引脚状态
    bl gpio_get_2
gpio_get_1:
    mov r2,#1                    @r2=指定引脚状态
gpio_get_2:
    #------------------------------------------------------------------------
    pop {r4-r7,pc}               @恢复现场，lr出栈到pc（即子程序返回）

#============================================================================
# 函数名称：gpio_reverse
# 函数返回：无
# 参数说明：r0:(端口号)|(引脚号),例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
# 功能概要：反转指定引脚状态
#============================================================================
gpio_reverse:
    push {r4-r7,lr}              @保存现场，pc(lr)入栈
    #------------------------------------------------------------------------
    bl gpio_port_pin_resolution  @调用内部函数，r0=端口号，r1=引脚号
    #求待操作GPIO口的基地址（也就是PTOR的地址）
    mov r5,r0                    @r5=r0=端口号
    mov r6,#0x40                 @r6=各GPIO口基地址差值（40h）
    mul r6,r6,r5                 @r6=待操作GPIO口的地址偏移
    ldr r5,=PORT_GPIO+0x0c       @r5=PORTA的PTOR的地址
    add r5,r6                    @r5=待操作引脚PTOR的地址
    #**********此段代码仅为观察PTOR对PTDR的影响，无实际意义，R7保存修改之前PTDR寄存器的值**************
    ldr r4,=PORT_GPIO            @r4=PORTA的PTDR的地址
    add r4,r6                    @r4=待操作引脚PTDR的地址
    ldr r7,[r4]                  @r7=引脚输出数据寄存器内容，以待观察变化
    #*******************************************************************************************
    #设置PTOR相应位为1
    mov r6,#1
    lsl r6,r6,r1                 @r6=待操作的PTOR掩码
    str r6,[r5]                  @将r6中的值更新到待操作端口PTOR寄存器中
    #***********此段代码仅为观察PTOR对PTDR的影响，无实际意义，R7保存修改之后PTDR寄存器的值***********
    ldr r7,[r4]                  @r7=引脚输出数据寄存器内容，观察变化操作PTOR寄存器后对PTDR的影响
    #*****************************************************************************************
    #------------------------------------------------------------------------
    pop {r4-r7,pc}               @恢复现场，lr出栈到pc（即子程序返回）

#============================================================================
# 函数名称：gpio_pull
# 函数返回：无
# 参数说明：r0:(端口号)|(引脚号),例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
#           r3:引脚拉高低电平（ 0=拉低电平，1=拉高电平，2=关闭上下拉）
# 功能概要：使指定引脚上拉高电平、下拉低电平或关闭上下拉
#============================================================================
gpio_pull:
    push {r4-r7,lr}              @保存现场，pc(lr)入栈	            #------------------------------------------------------------------------
    bl gpio_port_pin_resolution  @调用内部函数，r0=端口号,r1=引脚号
    #获得待操作端口的第一个PCR寄存器的地址
    mov r7,r0                    @r7=r0=端口号
    ldr r4,=0x1000               @r4=各端口基地址差值(0x1000)
    mul r7,r7,r4                 @r7=待操作端口与A口的偏移地址
    ldr r4,=PORT_PCR_BASE        @r4=端口A的PCR基地址(即PORT_PCR_BASE）
    add r7,r4                    @r7=待操作端口的第一个PCR寄存器的地址
    #获得待操作引脚PCR寄存器的地址
    mov r4,r1                    @r4=r1=引脚号
    mov r5,#4                    @各引脚的PCR寄存器地址之间差为0x04
    mul r4,r4,r5                 @r4=待操作引脚PCR寄存器的偏移地址
    add r7,r4                    @r7=待操作引脚PCR寄存器的地址
    #待操作引脚PCR寄存器的MUX位（10-8位）清0
    ldr r4,=0xfffff8ff
    ldr r5,[r7]                  @r5=待操作引脚PCR寄存器中的内容
    and r5,r4                    @待操作引脚PCR寄存器的MUX字段清零，其余位不变
    #待操作引脚PCR寄存器的MUX位（10-8位）置001,即设置为GPIO功能
    ldr r4,=0x00000100
    orr r5,r4                    @或运算设MUX=001，引脚被配置为GPIO功能
    str r5,[r7]                  @将r5中的MUX值更新到待操作引脚PCR寄存器中
    #根据入口参数r3，通过对PCR的PE及PS位的编程，使能或关闭相应引脚的上下拉功能
    cmp r3,#0
    beq gpio_pull_0              @r3=0，转到下拉配置子程序
    cmp r3,#1
	beq gpio_pull_1              @r3=1，转到上拉配置子程序
	cmp r3,#2
	beq gpio_pull_2              @r3=2，转到关闭上下拉子程序
	bl gpio_pull_3               @r3=其他值，函数直接返回
gpio_pull_0:
	ldr r4,=0x00000002
	orr r5,r4                    @或运算，将对应引脚PCR寄存器的PE位置1，使能引脚上下拉功能
	ldr r4,=0xFFFFFFFE
	and r5,r4                    @与运算，将对应引脚PCR寄存器的PS位清0，使指定引脚下拉低电平
	str r5,[r7]                  @将r5中的PE、PS值更新到待操作引脚PCR寄存器中
	bl gpio_pull_3
gpio_pull_1:
	ldr r4,=0x00000002
	orr r5,r4                    @或运算，将对应引脚PCR寄存器的PE位置1，使能引脚上下拉功能
	ldr r4,=0x00000001
	orr r5,r4                    @或运算，将对应引脚PCR寄存器的PS位置1，使指定引脚上拉高电平
	str r5,[r7]                  @将r5中的PE、PS值更新到待操作引脚PCR寄存器中
	bl gpio_pull_3
gpio_pull_2:
	ldr r4,=0xFFFFFFFD
	and r5,r4                    @与运算，将对应引脚PCR寄存器的PE位清0，关闭引脚上下拉功能
gpio_pull_3:	    
    #-----------------------------------------------------------------------
    pop {r4-r7,pc}               @恢复现场，lr出栈到pc（即子程序返回）

#===========================================================================
#函数名称：gpio_drive_strength
#函数返回：无
#参数说明：r0：(端口号)|(引脚号),例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
#          r3：控制引脚的驱动能力，0=正常驱动能力(5mA),默认
#                   1=高驱动能力(18mA),对KL25/KW01只有PTB0,PTB1,PTD6,PTD7可配
#功能概要：当指定端口引脚被定义为GPIO功能，设定引脚驱动能力
#备    注：引脚驱动能力是指引脚输入或输出电流的承受力，一般用mA单位度量
#===========================================================================
gpio_drive_strength:
    push {r4-r7,lr}              @保存现场，pc(lr)入栈
    #------------------------------------------------------------------------
    bl gpio_port_pin_resolution  @调用内部函数，r0=端口号,r1=引脚号
    #获得待操作端口的第一个PCR寄存器的地址
    mov r7,r0                    @r7=r0=端口号
    ldr r4,=0x1000               @r4=各端口基地址差值(0x1000)
    mul r7,r7,r4                 @r7=待操作端口与A口的偏移地址
    ldr r4,=PORT_PCR_BASE        @r4=端口A的PCR基地址(即PORT_PCR_BASE）
    add r7,r4                    @r7=待操作端口的第一个PCR寄存器的地址
    #获得待操作引脚PCR寄存器的地址
    mov r4,r1                    @r4=r1=引脚号
    mov r5,#4                    @各引脚的PCR寄存器地址之间差为0x04
    mul r4,r4,r5                 @r4=待操作引脚PCR寄存器的偏移地址
    add r7,r4                    @r7=待操作引脚PCR寄存器的地址
    #待操作引脚PCR寄存器的DSE位（6位）清0
    ldr r4,=0xffffffbf
    ldr r5,[r7]                  @r5=待操作引脚PCR寄存器中的内容
    and r5,r4                    @待操作引脚PCR寄存器的DSE位清零，其余位不变
    #对待操作引脚PCR寄存器的DSE位（6位）进行设置
    mov r6,r3                    @r6=r3=DSE位的设置值
    lsl r6,r6,#6                 @r6=设置值左移到DSE位
    orr r5,r6                    @r5=最终得到的待操作引脚PCR寄存器的值
    str r5,[r7]                  @将r5中的值更新到待操作引脚PCR寄存器中
    #------------------------------------------------------------------------
    pop {r4-r7,pc}               @恢复现场，lr出栈到pc（即子程序返回）

#============================================================================
# 函数名称：gpio_enable_int
# 函数返回：无
# 参数说明：r0:(端口号)|(引脚号),例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
#           r3:引脚中断类型，由宏定义给出，再次列举如下：
#                  LOW_LEVEL    8      低电平触发
#                  HIGH_LEVEL   12     高电平触发
#                  RISING_EDGE  9      上升沿触发
#                  FALLING_EDGE 10     下降沿触发
#                  DOUBLE_EDGE  11     双边沿触发
# 功能概要：当指定端口引脚被定义为GPIO功能且为输入时，本函数开启引脚中断，并设置
#           中断触发条件。
# 备    注： KL25芯片，只有PORTA、PORTD口具有GPIO类中断功能
#           KW01芯片，只有PORTA、PORTC、PORTD口具有GPIO类中断功能
#============================================================================
gpio_enable_int:
    push {r4-r7,lr}              @保存现场，pc(lr)入栈	            #------------------------------------------------------------------------
    bl gpio_port_pin_resolution  @调用内部函数，r0=端口号,r1=引脚号
    #获得待操作端口的第一个PCR寄存器的地址
    mov r7,r0                    @r7=r0=端口号
    ldr r4,=0x1000               @r4=各端口基地址差值(0x1000)
    mul r7,r7,r4                 @r7=待操作端口与A口的偏移地址
    ldr r4,=PORT_PCR_BASE        @r4=端口A的PCR基地址(即PORT_PCR_BASE）
    add r7,r4                    @r7=待操作端口的第一个PCR寄存器的地址
    #获得待操作引脚PCR寄存器的地址
    mov r4,r1                    @r4=r1=引脚号
    mov r5,#4                    @各引脚的PCR寄存器地址之间差为0x04
    mul r4,r4,r5                 @r4=待操作引脚PCR寄存器的偏移地址
    add r7,r4                    @r7=待操作引脚PCR寄存器的地址
    #待操作引脚PCR寄存器的ISF位（第24位）置1（清除引脚中断标志）
    ldr r4,=0x01000000           @r4=对应引脚PCR_ISF位的掩码
    ldr r5,[r7]                  @r5=待操作引脚PCR寄存器中的内容
    orr r5,r4                    @待操作引脚PCR寄存器的ISF位置1，其余位不变
    #待操作引脚PCR寄存器的IRQC字段（19-16位）清0
    ldr r4,=0xfff0ffff
    and r5,r4                    @待操作引脚PCR寄存器的IRQC字段清零，其余位不变
    #待操作引脚PCR寄存器的IRQC字段（19-16位）置为r3的值，即设置中断类型
    mov r4,r3                    @r4=r3=引脚的中断类型
    lsl r4,r4,#16                @r4=待操作的IRQC掩码
    orr r5,r4                    @或运算设MUX=001，引脚被配置为GPIO功能
    str r5,[r7]                  @将r5中的MUX值更新到待操作引脚PCR寄存器中

	#根据引脚号r0，通过对NVIC的ICPR及ISER的编程，使能中断控制器中的对应口的IRQ中断
	cmp r0,#0
	beq gpio_enable_int_0        @r0=0(PTA口)，跳转到相应子程序
	cmp r0,#2
	beq gpio_enable_int_1        @r0=0(PTC口)，跳转到相应子程序
	cmp r0,#3
	beq gpio_enable_int_1        @r0=0(PTD口)，跳转到相应子程序
	bl gpio_enable_int_2         @r0=其他值，函数直接返回
gpio_enable_int_0:                   @开中断控制器中PTA的IRQ中断
	#将PTA口对应的NVIC_ICPR置1（清挂起中断）
	ldr r6,=0xE000E100           @r6=NVIC的基地址
	ldr r4,=0x180                @r4=ICPR的偏移地址
	mov r7,r6
	add r7,r4                    @r7=NVIC_ICPR的地址
	ldr r5,[r7]                  @r5=NVIC_ICPR寄存器的值
	mov r4,#1;
	lsl r4,r4,#30                @r4=PTA的NVIC_ICPR掩码
	orr r5,r4                    @或运算，清PTA的挂起中断
	str r5,[r7]                  @将r5中的值更新到NVIC_ICPR寄存器中
	#将PTA口对应的NVIC_ISER置1（使能中断）
	ldr r4,=0x0                  @r4=ISER的偏移地址
	mov r7,r6
	add r7,r4                    @r7=NVIC_ISER的地址
	ldr r5,[r7]                  @r5=NVIC_ICPR寄存器的值
	mov r4,#1;
	lsl r4,r4,#30                @r4=PTA的NVIC_ISER掩码
	orr r5,r4                    @或运算，使能PTA中断
	str r5,[r7]                  @将r5中的值更新到NVIC_ISER寄存器中
	bl gpio_enable_int_2
gpio_enable_int_1:                   @开中断控制器中PTC、PTD的IRQ中断
	#将PTC、PTD口对应的NVIC_ICPR置1（清挂起中断）
	ldr r6,=0xE000E100           @r6=NVIC的基地址
	ldr r4,=0x180                @r4=ICPR的偏移地址
	mov r7,r6
	add r7,r4                    @r7=NVIC_ICPR的地址
	ldr r5,[r7]                  @r5=NVIC_ICPR寄存器的值
	mov r4,#1;
	lsl r4,r4,#31                @r4=PTC、PTD的NVIC_ICPR掩码
	orr r5,r4                    @或运算，清PTC、PTD的挂起中断
	str r5,[r7]                  @将r5中的值更新到NVIC_ICPR寄存器中
	#将PTA口对应的NVIC_ISER置1（使能中断）
	ldr r4,=0x0                  @r4=ISER的偏移地址
	mov r7,r6
	add r7,r4                    @r7=NVIC_ISER的地址
	ldr r5,[r7]                  @r5=NVIC_ICPR寄存器的值
	mov r4,#1;
	lsl r4,r4,#31                @r4=PTA的NVIC_ISER掩码
	orr r5,r4                    @或运算，使能PTC、PTD中断
	str r5,[r7]                  @将r5中的值更新到NVIC_ISER寄存器中
gpio_enable_int_2:	    
    #-----------------------------------------------------------------------
    pop {r4-r7,pc}                   @恢复现场，lr出栈到pc（即子程序返回）

#============================================================================
# 函数名称：gpio_disable_int
# 函数返回：无
# 参数说明：r0:(端口号)|(引脚号),例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
# 功能概要：当指定端口引脚被定义为GPIO功能且为输入时，本函数关闭引脚中断
# 备    注： KL25芯片，只有PORTA、PORTD口具有GPIO类中断功能
#           KW01芯片，只有PORTA、PORTC、PORTD口具有GPIO类中断功能
#============================================================================
gpio_disable_int:
    push {r4-r7,lr}              @保存现场，pc(lr)入栈
    #------------------------------------------------------------------------
    bl gpio_port_pin_resolution  @调用内部函数，r0=端口号,r1=引脚号
    #获得待操作端口的第一个PCR寄存器的地址
    mov r7,r0                    @r7=r0=端口号
    ldr r4,=0x1000               @r4=各端口基地址差值(0x1000)
    mul r7,r7,r4                 @r7=待操作端口与A口的偏移地址
    ldr r4,=PORT_PCR_BASE        @r4=端口A的PCR基地址(即PORT_PCR_BASE）
    add r7,r4                    @r7=待操作端口的第一个PCR寄存器的地址
    #获得待操作引脚PCR寄存器的地址
    mov r4,r1                    @r4=r1=引脚号
    mov r5,#4                    @各引脚的PCR寄存器地址之间差为0x04
    mul r4,r4,r5                 @r4=待操作引脚PCR寄存器的偏移地址
    add r7,r4                    @r7=待操作引脚PCR寄存器的地址
    #待操作引脚PCR寄存器的IRQC字段（19-16位）清0(禁用引脚中断)
    ldr r4,=0xfff0ffff
    ldr r5,[r7]                  @r5=待操作引脚PCR寄存器中的内容
    and r5,r4                    @待操作引脚PCR寄存器的IRQC字段清零，其余位不变

	#获取NVIC_ICER寄存器的地址
	ldr r6,=0xE000E100           @r6=NVIC的基地址
	ldr r4,=0x80                 @r4=ICER的偏移地址
	add r6,r4                    @r6=NVIC_ICER的地址
	ldr r5,[r6]                  @r5=NVIC_ICER寄存器的值

	#根据引脚号r0，通过对NVIC的ICER寄存器的编程，关闭中断控制器中的对应口的IRQ中断
	cmp r0,#0
	beq gpio_disable_int_0       @r0=0(PTA口)，跳转到相应子程序
	cmp r0,#2
	beq gpio_disable_int_1       @r0=0(PTC口)，跳转到相应子程序
	cmp r0,#3
	beq gpio_disable_int_1       @r0=0(PTD口)，跳转到相应子程序
	bl gpio_disable_int_2        @r0=其他值，函数直接返回
gpio_disable_int_0:                  @关中断控制器中PTA的IRQ中断
	#将PTA口对应的NVIC_ICER置1（关闭中断）
	mov r4,#1;
	lsl r4,r4,#30                @r4=PTA的NVIC_ICER掩码
	orr r5,r4                    @或运算，关闭PTA口的中断
	str r5,[r6]                  @将r5中的值更新到NVIC_ICER寄存器中
	bl gpio_enable_int_2
gpio_disable_int_1:                  @关中断控制器中PTC、PTD的IRQ中断
	#将PTC、PTD口对应的NVIC_ICER置1（关闭中断）
	mov r4,#1;
	lsl r4,r4,#31                @r4=PTC、PTD的NVIC_ICER掩码
	orr r5,r4                    @或运算，关闭PTC、PTD口的中断
	str r5,[r6]                  @将r5中的值更新到NVIC_ICER寄存器中
gpio_disable_int_2:
    #-----------------------------------------------------------------------
    pop {r4-r7,pc}                   @恢复现场，lr出栈到pc（即子程序返回）

#---------------------------外部接口函数结束-------------------------------------

#-----------------------以下为内部函数存放处---------------------------------
#============================================================================
#函数名称：gpio_port_pin_resolution
#函数返回：无
#参数说明：r0：端口号|引脚号,例:(PTB_NUM|(5u))表示B口5脚,头文件中有宏定义
#功能概要：将传进参数r0进行解析，得出具体端口号与引脚号（如：PORTB|(5)
#          解析为PORTB与5，并将其分别赋值给r0与r1）。
#============================================================================
gpio_port_pin_resolution:
    push {lr}             @保存现场，pc(lr)入栈
    #------------------------------------------------------------------------
    mov r4,r0             @r4=r0=端口号|引脚号
    mov r5,r0             @r5=r0=端口号|引脚号
    lsr r4,#8             @逻辑左移获得端口号，r4=端口号
    mov r0,r4             @r0=r4=端口号
    mov r6,#0x000000ff
    and r5,r6             @r5=引脚号
    mov r1,r5             @r1=r5=引脚号
    #-----------------------------------------------------------------------
    pop {pc}              @恢复现场，lr出栈到pc（即子程序返回）
#============================================================================
#-----------------------内部函数结束-----------------------------------------



