• LED灯C语言的点亮方式


    在上一篇进行了汇编语言的编写后,这一节采用C语言来编写,毕竟C语言才是我们使用最多的语言。

    本节要点:

    1)用C语言方式点亮LED灯;

    2)分析反汇编代码;了解函数调用栈,深入的分析代码;

    3)编写C语言的库函数版本,方便以后开发;

    首先贴出一段代码:

    start.s

    .text
    .global _start
    
    _start:
    
        /* 设置内存: sp 栈 */
        ldr sp, =4096  /* nand启动 */
    //    ldr sp, =0x40000000+4096  /* nor启动 */
    
        /* 调用main */
        bl main
    
    halt:
        b halt

    LED.c:

    int main()
    {
        unsigned int *pGPFCON = (unsigned int *)0x56000050;
        unsigned int *pGPFDAT = (unsigned int *)0x56000054;
        /* 配置GPF4为输出引脚 */
        *pGPFCON = 0x100;
        
        /* 设置GPF4输出0 */
        *pGPFDAT = 0;
            
        return 0;
    }

    在传统的IDE开发当中,我们只用从main函数开始写代码就行了,但是IDE隐藏了太多技术细节。

    我们在arm嵌入式linux开发过程中,都需要自己来,这对初学者是不友好,但是对深入学习却很有帮助。

    首先,nand flash启动,使用片内4K sram。

    我们都知道,函数调用和局部变量的存储需要使用到一种叫做栈的数据结构。

    说明:s3c2440,采用默认的栈生长方式,这也是我们最常见的方式,高地址往低地址生长。

    要调用main函数,我们需要开辟栈,这里使用片内4K内存作为栈。

    看一下反汇编:

    led.elf:     file format elf32-littlearm
    
    Disassembly of section .text:
    <_start>:
       0:    e3a0da01     mov    sp, #4096    ; 0x1000
       4:    eb000000     bl    c <main>
    <halt>:
       8:    eafffffe     b    8 <halt>
    
    0000000c <main>:
       c:    e1a0c00d     mov    ip, sp
      10:    e92dd800     stmdb    sp!, {fp, ip, lr, pc}
      14:    e24cb004     sub    fp, ip, #4    ; 0x4
      18:    e24dd008     sub    sp, sp, #8    ; 0x8
      1c:    e3a03456     mov    r3, #1442840576    ; 0x56000000
      20:    e2833050     add    r3, r3, #80    ; 0x50
      24:    e50b3010     str    r3, [fp, #-16]
      28:    e3a03456     mov    r3, #1442840576    ; 0x56000000
      2c:    e2833054     add    r3, r3, #84    ; 0x54
      30:    e50b3014     str    r3, [fp, #-20]
      34:    e51b2010     ldr    r2, [fp, #-16]
      38:    e3a03c01     mov    r3, #256    ; 0x100
      3c:    e5823000     str    r3, [r2]
      40:    e51b2014     ldr    r2, [fp, #-20]
      44:    e3a03000     mov    r3, #0    ; 0x0
      48:    e5823000     str    r3, [r2]
      4c:    e3a03000     mov    r3, #0    ; 0x0
      50:    e1a00003     mov    r0, r3
      54:    e24bd00c     sub    sp, fp, #12    ; 0xc
      58:    e89da800     ldmia    sp, {fp, sp, pc}
    Disassembly of section .comment:
    <.comment>:
       0:    43434700     cmpmi    r3, #0    ; 0x0
       4:    4728203a     undefined
       8:    2029554e     eorcs    r5, r9, lr, asr #10
       c:    2e342e33     mrccs    14, 1, r2, cr4, cr3, {1}
      10:    Address 0x10 is out of bounds.

    说明:

    <.comment>:在上面的反汇编当中,它不是汇编代码的一部分,是注解,给我们一些提示,便于我们阅读、理解的。在讲解这个汇编之前,我们需要先看一个arm寄存器的别名表。

    现在开始分析,其中最重要的也是新出现的两个指令:

    stmdb,ldmia

    简单说明,db表示事先递减方式,ia表示事后递增方式。

     详细介绍可以参见 arm嵌入式系统开发P58。

    先对反汇编进行注解:

    led.elf:     file format elf32-littlearm
      
      Disassembly of section .text:
    <_start>:
        0:    e3a0da01     mov    sp, #4096    ; 赋值4096给sp堆栈寄存器
        4:    eb000000     bl    c <main>    ;跳转到main函数,同时保存main函数返回地址到lr寄存器,返回地址为下一条指令的地址,这里lr应为8
    <halt>:
       8:    eafffffe     b    8 <halt>;死循环
     
     0000000c <main>:
        c:    e1a0c00d     mov    ip, sp;备份sp寄存器的值到ip,ip是r12寄存器的别名
    10:    e92dd800     stmdb    sp!, {fp, ip, lr, pc}
    ; 这条指令需要重点讲解,首先,fp,ip,lr,pc分别对应寄存器:r11,r12,r14,r15
    ; stm指令多寄存器操作的时候,后面的寄存器从编号高的先开始存储,把后面几个寄存器的值写入sp所对应的内存块中,(注意和但寄存器操作区分开来)后缀db表示 先减后存储
    ; sp后面加了一个感叹号!,表示sp最后的值等于最后被修改的值,不加感叹号就算操作使sp更改过,sp也等于最初的值
    ; 首先操作r15,即pc,sp先减,sp=sp-4,此时sp=4092,pc等于当前指令地址加8,即此时pc=0x10+8=0x18,相当于把0x18写入sram地址4092
    ; 同理操作r14,即lr,sp=sp-4,lr=8,相当于把0x8写入4088地址
    ; r12,ip是等于4096的,上面的move指令,r11,fp的值此时未定
    14:    e24cb004     sub    fp, ip, #4    ; fp=ip-4=4092
      18:    e24dd008     sub    sp, sp, #8    ; sp=sp-8=4072
      1c:    e3a03456     mov    r3, #1442840576    ;#1442840576等于十六机制0x56000000,把这个数存放在r3中
      20:    e2833050     add    r3, r3, #80    ;r3=r3+80=0x56000050
      24:    e50b3010     str    r3, [fp, #-16];fp-16=4076,把0x56000050放入内存4076中
      28:    e3a03456     mov    r3, #1442840576    ; 0x56000000
      2c:    e2833054     add    r3, r3, #84    ; r3=0x56000054
      30:    e50b3014     str    r3, [fp, #-20];fp=fp-20=4072,把0x56000054放入内存4072中
      34:    e51b2010     ldr    r2, [fp, #-16];r2=[fp-16=4076]=0x56000050
      38:    e3a03c01     mov    r3, #256; r3==256=0x100
      3c:    e5823000     str    r3, [r2];把0x100存入[0x56000050]
      40:    e51b2014     ldr    r2, [fp, #-20];r2=[fp-20=4072]=0x56000054
      44:    e3a03000     mov    r3, #0    ; r3=0=0x0
      48:    e5823000     str    r3, [r2];把0x0存入0x56000054内存中
      4c:    e3a03000     mov    r3, #0    ; r3=0x0
      50:    e1a00003     mov    r0, r3;r0=r3=0x0,这里编译器有点笨,可以直接r0给0的,这里对应return 0.
      54:    e24bd00c     sub    sp, fp, #12    ; sp=fp-12=4080
    

      

    58:    e89da800     ldmia    sp, {fp, sp, pc}
      ;恢复保存的现场,ldmia,事后增加,从sp所对应内存块中取出数据存放到后面的寄存器,高编号的寄存器放在高地址,低编号的寄存器
      ;放在低地址,此时sp=4080,从低地址往高地址开始恢复,这也符合ia后缀
      ;先恢复fp,此时4080地址存放的值,注意是值不是地址,等于4092,恰好就是等于fp,即一顿操作之后,fp还是等于原来的fp
      ;再恢复sp,sp=sp+4=4084,内存4084对应的值是4096,即一顿操作之后,sp又等于4096了;
      ;最后恢复pc,sp=sp+4=4088,内存4088对应的值是8,即一段操作之后,pc=8了,pc等于8意味着什么?意味着函数从main函数返回了,将去执行那个死循环halt

    为了更好的理解函数入栈,让我们深入理解C语言底层汇编,画出内存示意图:

    你可能会说。0-4096不是4097了吗?这样问非常好,不放过任何有疑问的细节,但是,4096,可以是4096的开始,也可以是4095的结尾,这里表示的是4095的结尾,因为4096我们一来是要先减4的。上图的4096是没用使用到真正属于4096地址后扩4字节的,而是在刚好到达4096时,之前的内存。

    到这里,终于完成了一大半,我们知道了函数入栈之后,似乎函数调用的参数传递,也要用到栈啊,那么我们继续挖掘汇编。这里又需要补充几点arm方面的知识。

    现在编写汇编代码, 传递一个参数:

    .text
    .global _start
    
    _start:
    
        /* 设置内存: sp 栈 */
        ldr sp, =4096  /* nand启动 */
    //    ldr sp, =0x40000000+4096  /* nor启动 */
    
        mov r0, #4
        bl led_on
    
        ldr r0, =100000
        bl delay
    
        mov r0, #5
        bl led_on
    
    halt:
        b halt
    void delay(volatile int d)
    {
        while (d--);
    }
    
    int led_on(int which)
    {
        unsigned int *pGPFCON = (unsigned int *)0x56000050;
        unsigned int *pGPFDAT = (unsigned int *)0x56000054;
    
        if (which == 4)
        {
            /* 配置GPF4为输出引脚 */
            *pGPFCON = 0x100;
        }
        else if (which == 5)
        {
            /* 配置GPF5为输出引脚 */
            *pGPFCON = 0x400;
        }
        
        /* 设置GPF4/5输出0 */
        *pGPFDAT = 0;
    
        return 0;
    }

    上面汇编中,只对应一个参数,所以只用r0就可以达到函数参数传递的效果,汇编比较简单就不赘述了。

    这个例子是为了让我们了解汇编通过寄存器传递函数参数,前提是必须先设置sp寄存器。

    甚至不必编写main函数,当然不建议这样做,这样示例是为让你明白一点,main函数也是因为启动代码去调用了它,我们通过改写启动代码,可以没有main函数。

     终于到了我们最熟悉的阶段了,编写C语言应用程序,一般来说,复杂的和可复用性更高的代码我们肯定是用C语言编写,全用汇编编写代码真是很慢而且麻烦,更不用说机器码编程了,但是了解它们对我们深入学习又十分有用,这或许就是arm对初学者不友好的原因吧,因为现在为止我们还没有大型项目需要编写复杂的Makefile,后面还有很多技能需要get,这也是在买了板子大半年了才真的开始上手的原因,需要花时间补习其他知识。

    言归正传,如上面的C语言程序,虽然完成了要求,可是复用性太差,既然你觉得你C语言最熟悉,那么就请封装一个复用性高的代码出来看看吧。

    我想使用复用性非常强的C代码,可以方便移植,快速开发,例如下面编写的mylib库函数:

    #include "s3c2440_gpio.h"
    int main(void)
    {
    
        Reset_gpio(OUT, GPIOF,GPIO_PinSource4);
        Set_gpio(OUT, GPIOF,GPIO_PinSource5);
        Reset_gpio(OUT, GPIOF,GPIO_PinSource6);
        return 0;
    }

    就是这样的代码,可以调用一个函数,达到指定IO输出高低电平或者设置模式。

    s3c2440_gpio.c:

    #include "s3c2440_gpio.h"
    
    void Set_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource)
    {
        if(new==OUT)
        {
            //CON复位值为0,配置为输出
            GPIO_InitStruct->CON |=1<<GPIO_PinSource*2;/*乘法优先级高于左移*/
            //DAT复位值udf
            GPIO_InitStruct->DAT |=(1<<GPIO_PinSource);/*对应位清零,输出1*/
        }
        else if(new==IN)
        {
            //CON复位值为0,配置为输入
            GPIO_InitStruct->CON &=(3<<GPIO_PinSource*2);/*乘法优先级高于左移*/
        }
        else
        {
            /*预留*/
        }
    }
    
    void Reset_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource)
    {
        if(new==OUT)
        {
            //CON复位值为0,配置为输出
            GPIO_InitStruct->CON |=1<<GPIO_PinSource*2;/*乘法优先级高于左移*/
            GPIO_InitStruct->DAT &=~(1<<GPIO_PinSource);/*对应位清零,输出0,低电平*/    
        }
    }

    s3c2440_gpio.h:

    #ifndef _S3C2440_GPIO_H_
    #define _S3C2440_GPIO_H_
    typedef unsigned           char uint8_t;
    typedef unsigned short     int uint16_t;
    typedef unsigned           int uint32_t;
    #define __IO  volatile
    typedef struct
    {
      __IO uint32_t CON;
      __IO uint32_t DAT;
      __IO uint32_t UP;
      __IO uint32_t Reserved;
    } GPIO_TypeDef;
    
    typedef enum
    {
        IN = 0, 
        OUT = 1,
        EINT=2
    } IOState;
    
    #define GPIO_PinSource0            ((uint8_t)0x00)
    #define GPIO_PinSource1            ((uint8_t)0x01)
    #define GPIO_PinSource2            ((uint8_t)0x02)
    #define GPIO_PinSource3            ((uint8_t)0x03)
    #define GPIO_PinSource4            ((uint8_t)0x04)
    #define GPIO_PinSource5            ((uint8_t)0x05)
    #define GPIO_PinSource6            ((uint8_t)0x06)
    #define GPIO_PinSource7            ((uint8_t)0x07)
    
    #define GPIOA_BASE            (0x56000000)
    #define GPIOB_BASE            (0x56000010)
    #define GPIOC_BASE            (0x56000020)
    #define GPIOD_BASE            (0x56000030)
    #define GPIOE_BASE            (0x56000040)
    #define GPIOF_BASE            (0x56000050)
    #define GPIOG_BASE            (0x56000060)
    #define GPIOH_BASE            (0x56000070)
    #define GPIOJ_BASE            (0x560000d0)
    
    #define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)
    #define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)
    #define GPIOC               ((GPIO_TypeDef *) GPIOC_BASE)
    #define GPIOD               ((GPIO_TypeDef *) GPIOD_BASE)
    #define GPIOE               ((GPIO_TypeDef *) GPIOE_BASE)
    #define GPIOF               ((GPIO_TypeDef *) GPIOF_BASE)
    #define GPIOG               ((GPIO_TypeDef *) GPIOG_BASE)
    #define GPIOH               ((GPIO_TypeDef *) GPIOH_BASE)
    #define GPIOJ               ((GPIO_TypeDef *) GPIOJ_BASE)
    
    void Set_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource);
    void Reset_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource);
    
    #endif /*s3c2440_gpio.h*/

    编写出这样的库函数需要有过库函数编程经验并且具备一定的C语言基础和思维。

    再看看加了-g选项也就是调试信息的反汇编:

    led.elf:     file format elf32-littlearm
    
    Disassembly of section .text:
    <_start>:
    .global  _start
    
    _start:
    
        ldr sp,=4096 //nandflash启动,设置栈
       0:    e3a0da01     mov    sp, #4096    ; 0x1000
        //调用main函数
        bl main
       4:    eb000000     bl    c <main>
    <halt>:
    
    halt:
        b halt
       8:    eafffffe     b    8 <halt>
    
    0000000c <main>:
    #include "s3c2440_gpio.h"
    int main(void)
    {
       c:    e1a0c00d     mov    ip, sp
      10:    e92dd800     stmdb    sp!, {fp, ip, lr, pc}
      14:    e24cb004     sub    fp, ip, #4    ; 0x4
    
        Reset_gpio(OUT, GPIOF,GPIO_PinSource4);
      18:    e3a00001     mov    r0, #1    ; 0x1
      1c:    e3a01456     mov    r1, #1442840576    ; 0x56000000
      20:    e2811050     add    r1, r1, #80    ; 0x50
      24:    e3a02004     mov    r2, #4    ; 0x4
      28:    eb000042     bl    138 <Reset_gpio>
        Set_gpio(OUT, GPIOF,GPIO_PinSource5);
      2c:    e3a00001     mov    r0, #1    ; 0x1
      30:    e3a01456     mov    r1, #1442840576    ; 0x56000000
      34:    e2811050     add    r1, r1, #80    ; 0x50
      38:    e3a02005     mov    r2, #5    ; 0x5
      3c:    eb000007     bl    60 <Set_gpio>
        Reset_gpio(OUT, GPIOF,GPIO_PinSource6);
      40:    e3a00001     mov    r0, #1    ; 0x1
      44:    e3a01456     mov    r1, #1442840576    ; 0x56000000
      48:    e2811050     add    r1, r1, #80    ; 0x50
      4c:    e3a02006     mov    r2, #6    ; 0x6
      50:    eb000038     bl    138 <Reset_gpio>
        return 0;
      54:    e3a03000     mov    r3, #0    ; 0x0
    }
      58:    e1a00003     mov    r0, r3
      5c:    e89da800     ldmia    sp, {fp, sp, pc}
    <Set_gpio>:
    #include "s3c2440_gpio.h"
    
    void Set_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource)
    {
      60:    e1a0c00d     mov    ip, sp
      64:    e92dd800     stmdb    sp!, {fp, ip, lr, pc}
      68:    e24cb004     sub    fp, ip, #4    ; 0x4
      6c:    e24dd00c     sub    sp, sp, #12    ; 0xc
      70:    e50b0010     str    r0, [fp, #-16]
      74:    e50b1014     str    r1, [fp, #-20]
      78:    e1a03002     mov    r3, r2
      7c:    e54b3016     strb    r3, [fp, #-22]
      80:    e1a03443     mov    r3, r3, asr #8
      84:    e54b3015     strb    r3, [fp, #-21]
        if(new==OUT)
      88:    e51b3010     ldr    r3, [fp, #-16]
      8c:    e3530001     cmp    r3, #1    ; 0x1
      90:    1a000017     bne    f4 <Set_gpio+0x94>
        {
            //CON复位值为0,配置为输出
            GPIO_InitStruct->CON |=1<<GPIO_PinSource*2;/*乘法优先级高于左移*/
      94:    e51b0014     ldr    r0, [fp, #-20]
      98:    e51b1014     ldr    r1, [fp, #-20]
      9c:    e24b3016     sub    r3, fp, #22    ; 0x16
      a0:    e5d32000     ldrb    r2, [r3]
      a4:    e5d33001     ldrb    r3, [r3, #1]
      a8:    e1823403     orr    r3, r2, r3, lsl #8
      ac:    e1a02083     mov    r2, r3, lsl #1
      b0:    e3a03001     mov    r3, #1    ; 0x1
      b4:    e1a02213     mov    r2, r3, lsl r2
      b8:    e5913000     ldr    r3, [r1]
      bc:    e1833002     orr    r3, r3, r2
      c0:    e5803000     str    r3, [r0]
            //DAT复位值udf
            GPIO_InitStruct->DAT |=(1<<GPIO_PinSource);/*对应位清零,输出1*/
      c4:    e51b1014     ldr    r1, [fp, #-20]
      c8:    e51b0014     ldr    r0, [fp, #-20]
      cc:    e24b3016     sub    r3, fp, #22    ; 0x16
      d0:    e5d32000     ldrb    r2, [r3]
      d4:    e5d33001     ldrb    r3, [r3, #1]
      d8:    e1822403     orr    r2, r2, r3, lsl #8
      dc:    e3a03001     mov    r3, #1    ; 0x1
      e0:    e1a02213     mov    r2, r3, lsl r2
      e4:    e5903004     ldr    r3, [r0, #4]
      e8:    e1833002     orr    r3, r3, r2
      ec:    e5813004     str    r3, [r1, #4]
      f0:    ea00000e     b    130 <Set_gpio+0xd0>
        }
        else if(new==IN)
      f4:    e51b3010     ldr    r3, [fp, #-16]
      f8:    e3530000     cmp    r3, #0    ; 0x0
      fc:    1a00000b     bne    130 <Set_gpio+0xd0>
        {
            //CON复位值为0,配置为输入
            GPIO_InitStruct->CON &=(3<<GPIO_PinSource*2);/*乘法优先级高于左移*/
     100:    e51b0014     ldr    r0, [fp, #-20]
     104:    e51b1014     ldr    r1, [fp, #-20]
     108:    e24b3016     sub    r3, fp, #22    ; 0x16
     10c:    e5d32000     ldrb    r2, [r3]
     110:    e5d33001     ldrb    r3, [r3, #1]
     114:    e1823403     orr    r3, r2, r3, lsl #8
     118:    e1a02083     mov    r2, r3, lsl #1
     11c:    e3a03003     mov    r3, #3    ; 0x3
     120:    e1a02213     mov    r2, r3, lsl r2
     124:    e5913000     ldr    r3, [r1]
     128:    e0033002     and    r3, r3, r2
     12c:    e5803000     str    r3, [r0]
        }
        else
        {
            /*预留*/
        }
    }
     130:    e24bd00c     sub    sp, fp, #12    ; 0xc
     134:    e89da800     ldmia    sp, {fp, sp, pc}
    <Reset_gpio>:
    
    void Reset_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource)
    {
     138:    e1a0c00d     mov    ip, sp
     13c:    e92dd800     stmdb    sp!, {fp, ip, lr, pc}
     140:    e24cb004     sub    fp, ip, #4    ; 0x4
     144:    e24dd00c     sub    sp, sp, #12    ; 0xc
     148:    e50b0010     str    r0, [fp, #-16]
     14c:    e50b1014     str    r1, [fp, #-20]
     150:    e1a03002     mov    r3, r2
     154:    e54b3016     strb    r3, [fp, #-22]
     158:    e1a03443     mov    r3, r3, asr #8
     15c:    e54b3015     strb    r3, [fp, #-21]
        if(new==OUT)
     160:    e51b3010     ldr    r3, [fp, #-16]
     164:    e3530001     cmp    r3, #1    ; 0x1
     168:    1a000017     bne    1cc <Reset_gpio+0x94>
        {
            //CON复位值为0,配置为输出
            GPIO_InitStruct->CON |=1<<GPIO_PinSource*2;/*乘法优先级高于左移*/
     16c:    e51b0014     ldr    r0, [fp, #-20]
     170:    e51b1014     ldr    r1, [fp, #-20]
     174:    e24b3016     sub    r3, fp, #22    ; 0x16
     178:    e5d32000     ldrb    r2, [r3]
     17c:    e5d33001     ldrb    r3, [r3, #1]
     180:    e1823403     orr    r3, r2, r3, lsl #8
     184:    e1a02083     mov    r2, r3, lsl #1
     188:    e3a03001     mov    r3, #1    ; 0x1
     18c:    e1a02213     mov    r2, r3, lsl r2
     190:    e5913000     ldr    r3, [r1]
     194:    e1833002     orr    r3, r3, r2
     198:    e5803000     str    r3, [r0]
            GPIO_InitStruct->DAT &=~(1<<GPIO_PinSource);/*对应位清零,输出0,低电平*/    
     19c:    e51b0014     ldr    r0, [fp, #-20]
     1a0:    e51b1014     ldr    r1, [fp, #-20]
     1a4:    e24b3016     sub    r3, fp, #22    ; 0x16
     1a8:    e5d32000     ldrb    r2, [r3]
     1ac:    e5d33001     ldrb    r3, [r3, #1]
     1b0:    e1822403     orr    r2, r2, r3, lsl #8
     1b4:    e3a03001     mov    r3, #1    ; 0x1
     1b8:    e1a03213     mov    r3, r3, lsl r2
     1bc:    e1e02003     mvn    r2, r3
     1c0:    e5913004     ldr    r3, [r1, #4]
     1c4:    e0033002     and    r3, r3, r2
     1c8:    e5803004     str    r3, [r0, #4]
        }
    }
     1cc:    e24bd00c     sub    sp, fp, #12    ; 0xc
     1d0:    e89da800     ldmia    sp, {fp, sp, pc}
    Disassembly of section .comment:
    <.comment>:
       0:    43434700     cmpmi    r3, #0    ; 0x0
       4:    4728203a     undefined
       8:    2029554e     eorcs    r5, r9, lr, asr #10
       c:    2e342e33     mrccs    14, 1, r2, cr4, cr3, {1}
      10:    47000035     smladxmi    r0, r5, r0, r0
      14:    203a4343     eorcss    r4, sl, r3, asr #6
      18:    554e4728     strplb    r4, [lr, #-1832]
      1c:    2e332029     cdpcs    0, 3, cr2, cr3, cr9, {1}
      20:    00352e34     eoreqs    r2, r5, r4, lsr lr
    Disassembly of section .debug_aranges:
    <.debug_aranges>:
       0:    0000001c     andeq    r0, r0, ip, lsl r0
       4:    00000002     andeq    r0, r0, r2
       8:    00040000     andeq    r0, r4, r0
        ...
      14:    0000000c     andeq    r0, r0, ip
        ...
      20:    0000001c     andeq    r0, r0, ip, lsl r0
      24:    003a0002     eoreqs    r0, sl, r2
      28:    00040000     andeq    r0, r4, r0
      2c:    00000000     andeq    r0, r0, r0
      30:    0000000c     andeq    r0, r0, ip
      34:    00000054     andeq    r0, r0, r4, asr r0
        ...
      40:    0000001c     andeq    r0, r0, ip, lsl r0
      44:    00c90002     sbceq    r0, r9, r2
      48:    00040000     andeq    r0, r4, r0
      4c:    00000000     andeq    r0, r0, r0
      50:    00000060     andeq    r0, r0, r0, rrx
      54:    00000174     andeq    r0, r0, r4, ror r1
        ...
    Disassembly of section .debug_pubnames:
    <.debug_pubnames>:
       0:    00000017     andeq    r0, r0, r7, lsl r0
       4:    003a0002     eoreqs    r0, sl, r2
       8:    008f0000     addeq    r0, pc, r0
       c:    006f0000     rsbeq    r0, pc, r0
      10:    616d0000     cmnvs    sp, r0
      14:    00006e69     andeq    r6, r0, r9, ror #28
      18:    2a000000     bcs    20 <main+0x14>
      1c:    02000000     andeq    r0, r0, #0    ; 0x0
      20:    0000c900     andeq    ip, r0, r0, lsl #18
      24:    0001c100     andeq    ip, r1, r0, lsl #2
      28:    00012e00     andeq    r2, r1, r0, lsl #28
      2c:    74655300     strvcbt    r5, [r5], #-768
      30:    6970675f     ldmvsdb    r0!, {r0, r1, r2, r3, r4, r6, r8, r9, sl, sp, lr}^
      34:    017b006f     cmneq    fp, pc, rrx
      38:    65520000     ldrvsb    r0, [r2]
      3c:    5f746573     swipl    0x00746573
      40:    6f697067     swivs    0x00697067
      44:    00000000     andeq    r0, r0, r0
        ...
    Disassembly of section .debug_info:
    <.debug_info>:
       0:    00000036     andeq    r0, r0, r6, lsr r0
       4:    00000002     andeq    r0, r0, r2
       8:    01040000     tsteq    r4, r0
        ...
      14:    0000000c     andeq    r0, r0, ip
      18:    72617473     rsbvc    r7, r1, #1929379840    ; 0x73000000
      1c:    00532e74     subeqs    r2, r3, r4, ror lr
      20:    6d6f682f     stcvsl    8, cr6, [pc, #-188]!
      24:    68732f65     ldmvsda    r3!, {r0, r2, r5, r6, r8, r9, sl, fp, sp}^
      28:    00657261     rsbeq    r7, r5, r1, ror #4
      2c:    20554e47     subcss    r4, r5, r7, asr #28
      30:    32205341     eorcc    r5, r0, #67108865    ; 0x4000001
      34:    0035312e     eoreqs    r3, r5, lr, lsr #2
      38:    008b8001     addeq    r8, fp, r1
      3c:    00020000     andeq    r0, r2, r0
      40:    00000014     andeq    r0, r0, r4, lsl r0
      44:    00360104     eoreqs    r0, r6, r4, lsl #2
      48:    00600000     rsbeq    r0, r0, r0
      4c:    000c0000     andeq    r0, ip, r0
      50:    4e470000     cdpmi    0, 4, cr0, cr7, cr0, {0}
      54:    20432055     subcs    r2, r3, r5, asr r0
      58:    2e342e33     mrccs    14, 1, r2, cr4, cr3, {1}
      5c:    6d010035     stcvs    0, cr0, [r1, #-212]
      60:    2e6e6961     cdpcs    9, 6, cr6, cr14, cr1, {3}
      64:    682f0063     stmvsda    pc!, {r0, r1, r5, r6}
      68:    2f656d6f     swics    0x00656d6f
      6c:    72616873     rsbvc    r6, r1, #7536640    ; 0x730000
      70:    75020065     strvc    r0, [r2, #-101]
      74:    6769736e     strvsb    r7, [r9, -lr, ror #6]!
      78:    2064656e     rsbcs    r6, r4, lr, ror #10
      7c:    72616863     rsbvc    r6, r1, #6488064    ; 0x630000
      80:    02080100     andeq    r0, r8, #0    ; 0x0
      84:    726f6873     rsbvc    r6, pc, #7536640    ; 0x730000
      88:    6e752074     mrcvs    0, 3, r2, cr5, cr4, {3}
      8c:    6e676973     mcrvs    9, 3, r6, cr7, cr3, {3}
      90:    69206465     stmvsdb    r0!, {r0, r2, r5, r6, sl, sp, lr}
      94:    0200746e     andeq    r7, r0, #1845493760    ; 0x6e000000
      98:    6e750207     cdpvs    2, 7, cr0, cr5, cr7, {0}
      9c:    6e676973     mcrvs    9, 3, r6, cr7, cr3, {3}
      a0:    69206465     stmvsdb    r0!, {r0, r2, r5, r6, sl, sp, lr}
      a4:    0400746e     streq    r7, [r0], #-1134
      a8:    6d010307     stcvs    3, cr0, [r1, #-28]
      ac:    006e6961     rsbeq    r6, lr, r1, ror #18
      b0:    87010301     strhi    r0, [r1, -r1, lsl #6]
      b4:    0c000000     stceq    0, cr0, [r0], {0}
      b8:    60000000     andvs    r0, r0, r0
      bc:    01000000     tsteq    r0, r0
      c0:    6e69025b     mcrvs    2, 3, r0, cr9, cr11, {2}
      c4:    05040074     streq    r0, [r4, #-116]
      c8:    0001bd00     andeq    fp, r1, r0, lsl #26
      cc:    4a000200     bmi    8d4 <Reset_gpio+0x79c>
      d0:    04000000     streq    r0, [r0]
      d4:    00006c01     andeq    r6, r0, r1, lsl #24
      d8:    0001d400     andeq    sp, r1, r0, lsl #8
      dc:    00006000     andeq    r6, r0, r0
      e0:    554e4700     strplb    r4, [lr, #-1792]
      e4:    33204320     teqcc    r0, #-2147483648    ; 0x80000000
      e8:    352e342e     strcc    r3, [lr, #-1070]!
      ec:    33730100     cmncc    r3, #0    ; 0x0
      f0:    34343263     ldrcct    r3, [r4], #-611
      f4:    70675f30     rsbvc    r5, r7, r0, lsr pc
      f8:    632e6f69     teqvs    lr, #420    ; 0x1a4
      fc:    6f682f00     swivs    0x00682f00
     100:    732f656d     teqvc    pc, #457179136    ; 0x1b400000
     104:    65726168     ldrvsb    r6, [r2, #-360]!
     108:    6e750200     cdpvs    2, 7, cr0, cr5, cr0, {0}
     10c:    6e676973     mcrvs    9, 3, r6, cr7, cr3, {3}
     110:    63206465     teqvs    r0, #1694498816    ; 0x65000000
     114:    00726168     rsbeqs    r6, r2, r8, ror #2
     118:    75030801     strvc    r0, [r3, #-2049]
     11c:    31746e69     cmncc    r4, r9, ror #28
     120:    00745f36     rsbeqs    r5, r4, r6, lsr pc
     124:    00610402     rsbeq    r0, r1, r2, lsl #8
     128:    73020000     tstvc    r2, #0    ; 0x0
     12c:    74726f68     ldrvcbt    r6, [r2], #-3944
     130:    736e7520     cmnvc    lr, #134217728    ; 0x8000000
     134:    656e6769     strvsb    r6, [lr, #-1897]!
     138:    6e692064     cdpvs    0, 6, cr2, cr9, cr4, {3}
     13c:    07020074     smlsdxeq    r2, r4, r0, r0
     140:    6e697503     cdpvs    5, 6, cr7, cr9, cr3, {0}
     144:    5f323374     swipl    0x00323374
     148:    05020074     streq    r0, [r2, #-116]
     14c:    00000087     andeq    r0, r0, r7, lsl #1
     150:    736e7502     cmnvc    lr, #8388608    ; 0x800000
     154:    656e6769     strvsb    r6, [lr, #-1897]!
     158:    6e692064     cdpvs    0, 6, cr2, cr9, cr4, {3}
     15c:    07040074     smlsdxeq    r4, r4, r0, r0
     160:    0000dc04     andeq    sp, r0, r4, lsl #24
     164:    0d021000     stceq    0, cr1, [r2]
     168:    4e4f4305     cdpmi    3, 4, cr4, cr15, cr5, {0}
     16c:    dc090200     sfmle    f0, 4, [r9], {0}
     170:    02000000     andeq    r0, r0, #0    ; 0x0
     174:    44050023     strmi    r0, [r5], #-35
     178:    02005441     andeq    r5, r0, #1090519040    ; 0x41000000
     17c:    0000e10a     andeq    lr, r0, sl, lsl #2
     180:    04230200     streqt    r0, [r3], #-512
     184:    00505505     subeqs    r5, r0, r5, lsl #10
     188:    00e60b02     rsceq    r0, r6, r2, lsl #22
     18c:    23020000     tstcs    r2, #0    ; 0x0
     190:    65520508     ldrvsb    r0, [r2, #-1288]
     194:    76726573     undefined
     198:    02006465     andeq    r6, r0, #1694498816    ; 0x65000000
     19c:    0000eb0c     andeq    lr, r0, ip, lsl #22
     1a0:    0c230200     sfmeq    f0, 4, [r3]
     1a4:    00770600     rsbeqs    r0, r7, r0, lsl #12
     1a8:    77060000     strvc    r0, [r6, -r0]
     1ac:    06000000     streq    r0, [r0], -r0
     1b0:    00000077     andeq    r0, r0, r7, ror r0
     1b4:    00007706     andeq    r7, r0, r6, lsl #14
     1b8:    50470300     subpl    r0, r7, r0, lsl #6
     1bc:    545f4f49     ldrplb    r4, [pc], #3913    ; 1c4 <Reset_gpio+0x8c>
     1c0:    44657079     strmibt    r7, [r5], #-121
     1c4:    02006665     andeq    r6, r0, #105906176    ; 0x6500000
     1c8:    0000970d     andeq    r9, r0, sp, lsl #14
     1cc:    011f0700     tsteq    pc, r0, lsl #14
     1d0:    02040000     andeq    r0, r4, #0    ; 0x0
     1d4:    4e490810     mcrmi    8, 2, r0, cr9, cr0, {0}
     1d8:    4f080000     swimi    0x00080000
     1dc:    01005455     tsteq    r0, r5, asr r4
     1e0:    4e494508     cdpmi    5, 4, cr4, cr9, cr8, {0}
     1e4:    00020054     andeq    r0, r2, r4, asr r0
     1e8:    534f4903     cmppl    pc, #49152    ; 0xc000
     1ec:    65746174     ldrvsb    r6, [r4, #-372]!
     1f0:    04140200     ldreq    r0, [r4], #-512
     1f4:    09000001     stmeqdb    r0, {r0}
     1f8:    00000175     andeq    r0, r0, r5, ror r1
     1fc:    74655301     strvcbt    r5, [r5], #-769
     200:    6970675f     ldmvsdb    r0!, {r0, r1, r2, r3, r4, r6, r8, r9, sl, sp, lr}^
     204:    0401006f     streq    r0, [r1], #-111
     208:    00006001     andeq    r6, r0, r1
     20c:    00013800     andeq    r3, r1, r0, lsl #16
     210:    0a5b0100     beq    16c0618 <__bss_end__+0x16b8444>
     214:    0077656e     rsbeqs    r6, r7, lr, ror #10
     218:    011f0301     tsteq    pc, r1, lsl #6
     21c:    91020000     tstls    r2, r0
     220:    000f0b70     andeq    r0, pc, r0, ror fp
     224:    03010000     tsteq    r1, #0    ; 0x0
     228:    00000175     andeq    r0, r0, r5, ror r1
     22c:    0b6c9102     bleq    1b2463c <__bss_end__+0x1b1c468>
     230:    00000000     andeq    r0, r0, r0
     234:    00510301     subeqs    r0, r1, r1, lsl #6
     238:    91020000     tstls    r2, r0
     23c:    040c006a     streq    r0, [ip], #-106
     240:    000000f0     streqd    r0, [r0], -r0
     244:    6552010d     ldrvsb    r0, [r2, #-269]
     248:    5f746573     swipl    0x00746573
     24c:    6f697067     swivs    0x00697067
     250:    01180100     tsteq    r8, r0, lsl #2
     254:    00000138     andeq    r0, r0, r8, lsr r1
     258:    000001d4     ldreqd    r0, [r0], -r4
     25c:    6e0a5b01     fmacdvs    d5, d10, d1
     260:    01007765     tsteq    r0, r5, ror #14
     264:    00011f17     andeq    r1, r1, r7, lsl pc
     268:    70910200     addvcs    r0, r1, r0, lsl #4
     26c:    00000f0b     andeq    r0, r0, fp, lsl #30
     270:    75170100     ldrvc    r0, [r7, #-256]
     274:    02000001     andeq    r0, r0, #1    ; 0x1
     278:    000b6c91     muleq    fp, r1, ip
     27c:    01000000     tsteq    r0, r0
     280:    00005117     andeq    r5, r0, r7, lsl r1
     284:    6a910200     bvs    fe440a8c <__bss_end__+0xfe4388b8>
        ...
    Disassembly of section .debug_abbrev:
    <.debug_abbrev>:
       0:    10001101     andne    r1, r0, r1, lsl #2
       4:    12011106     andne    r1, r1, #-2147483647    ; 0x80000001
       8:    1b080301     blne    200c14 <__bss_end__+0x1f8a40>
       c:    13082508     tstne    r8, #33554432    ; 0x2000000
      10:    00000005     andeq    r0, r0, r5
      14:    10011101     andne    r1, r1, r1, lsl #2
      18:    11011206     tstne    r1, r6, lsl #4
      1c:    13082501     tstne    r8, #4194304    ; 0x400000
      20:    1b08030b     blne    200c54 <__bss_end__+0x1f8a80>
      24:    02000008     andeq    r0, r0, #8    ; 0x8
      28:    08030024     stmeqda    r3, {r2, r5}
      2c:    0b3e0b0b     bleq    f82c60 <__bss_end__+0xf7aa8c>
      30:    2e030000     cdpcs    0, 0, cr0, cr3, cr0, {0}
      34:    030c3f00     tsteq    ip, #0    ; 0x0
      38:    3b0b3a08     blcc    2ce860 <__bss_end__+0x2c668c>
      3c:    490c270b     stmmidb    ip, {r0, r1, r3, r8, r9, sl, sp}
      40:    12011113     andne    r1, r1, #-1073741820    ; 0xc0000004
      44:    000a4001     andeq    r4, sl, r1
      48:    11010000     tstne    r1, r0
      4c:    12061001     andne    r1, r6, #1    ; 0x1
      50:    25011101     strcs    r1, [r1, #-257]
      54:    030b1308     tsteq    fp, #536870912    ; 0x20000000
      58:    00081b08     andeq    r1, r8, r8, lsl #22
      5c:    00240200     eoreq    r0, r4, r0, lsl #4
      60:    0b0b0803     bleq    2c2074 <__bss_end__+0x2b9ea0>
      64:    00000b3e     andeq    r0, r0, lr, lsr fp
      68:    03001603     tsteq    r0, #3145728    ; 0x300000
      6c:    3b0b3a08     blcc    2ce894 <__bss_end__+0x2c66c0>
      70:    0013490b     andeqs    r4, r3, fp, lsl #18
      74:    01130400     tsteq    r3, r0, lsl #8
      78:    0b0b1301     bleq    2c4c84 <__bss_end__+0x2bcab0>
      7c:    0b3b0b3a     bleq    ec2d6c <__bss_end__+0xebab98>
      80:    0d050000     stceq    0, cr0, [r5]
      84:    3a080300     bcc    200c8c <__bss_end__+0x1f8ab8>
      88:    490b3b0b     stmmidb    fp, {r0, r1, r3, r8, r9, fp, ip, sp}
      8c:    000a3813     andeq    r3, sl, r3, lsl r8
      90:    00350600     eoreqs    r0, r5, r0, lsl #12
      94:    00001349     andeq    r1, r0, r9, asr #6
      98:    01010407     tsteq    r1, r7, lsl #8
      9c:    3a0b0b13     bcc    2c2cf0 <__bss_end__+0x2bab1c>
      a0:    000b3b0b     andeq    r3, fp, fp, lsl #22
      a4:    00280800     eoreq    r0, r8, r0, lsl #16
      a8:    0d1c0803     ldceq    8, cr0, [ip, #-12]
      ac:    2e090000     cdpcs    0, 0, cr0, cr9, cr0, {0}
      b0:    3f130101     swicc    0x00130101
      b4:    3a08030c     bcc    200cec <__bss_end__+0x1f8b18>
      b8:    270b3b0b     strcs    r3, [fp, -fp, lsl #22]
      bc:    1201110c     andne    r1, r1, #3    ; 0x3
      c0:    000a4001     andeq    r4, sl, r1
      c4:    00050a00     andeq    r0, r5, r0, lsl #20
      c8:    0b3a0803     bleq    e820dc <__bss_end__+0xe79f08>
      cc:    13490b3b     cmpne    r9, #60416    ; 0xec00
      d0:    00000a02     andeq    r0, r0, r2, lsl #20
      d4:    0300050b     tsteq    r0, #46137344    ; 0x2c00000
      d8:    3b0b3a0e     blcc    2ce918 <__bss_end__+0x2c6744>
      dc:    0213490b     andeqs    r4, r3, #180224    ; 0x2c000
      e0:    0c00000a     stceq    0, cr0, [r0], {10}
      e4:    0b0b000f     bleq    2c0128 <__bss_end__+0x2b7f54>
      e8:    00001349     andeq    r1, r0, r9, asr #6
      ec:    3f012e0d     swicc    0x00012e0d
      f0:    3a08030c     bcc    200d28 <__bss_end__+0x1f8b54>
      f4:    270b3b0b     strcs    r3, [fp, -fp, lsl #22]
      f8:    1201110c     andne    r1, r1, #3    ; 0x3
      fc:    000a4001     andeq    r4, sl, r1
        ...
    Disassembly of section .debug_line:
    <.debug_line>:
       0:    00000032     andeq    r0, r0, r2, lsr r0
       4:    001b0002     andeqs    r0, fp, r2
       8:    01020000     tsteq    r2, r0
       c:    000a0efb     streqd    r0, [sl], -fp
      10:    01010101     tsteq    r1, r1, lsl #2
      14:    01000000     tsteq    r0, r0
      18:    61747300     cmnvs    r4, r0, lsl #6
      1c:    532e7472     teqpl    lr, #1912602624    ; 0x72000000
      20:    00000000     andeq    r0, r0, r0
      24:    02050000     andeq    r0, r5, #0    ; 0x0
      28:    00000000     andeq    r0, r0, r0
      2c:    2d010903     stccs    9, cr0, [r1, #-12]
      30:    0002022e     andeq    r0, r2, lr, lsr #4
      34:    00320101     eoreqs    r0, r2, r1, lsl #2
      38:    00020000     andeq    r0, r2, r0
      3c:    0000001a     andeq    r0, r0, sl, lsl r0
      40:    0efb0102     cdpeq    1, 15, cr0, cr11, cr2, {0}
      44:    0101000a     tsteq    r1, sl
      48:    00000101     andeq    r0, r0, r1, lsl #2
      4c:    6d000100     stfvss    f0, [r0]
      50:    2e6e6961     cdpcs    9, 6, cr6, cr14, cr1, {3}
      54:    00000063     andeq    r0, r0, r3, rrx
      58:    05000000     streq    r0, [r0]
      5c:    00000c02     andeq    r0, r0, r2, lsl #24
      60:    9c651100     stflse    f1, [r5]
      64:    022c9c9c     eoreq    r9, ip, #39936    ; 0x9c00
      68:    01010004     tsteq    r1, r4
      6c:    00000059     andeq    r0, r0, r9, asr r0
      70:    00340002     eoreqs    r0, r4, r2
      74:    01020000     tsteq    r2, r0
      78:    000a0efb     streqd    r0, [sl], -fp
      7c:    01010101     tsteq    r1, r1, lsl #2
      80:    01000000     tsteq    r0, r0
      84:    63337300     teqvs    r3, #0    ; 0x0
      88:    30343432     eorccs    r3, r4, r2, lsr r4
      8c:    6970675f     ldmvsdb    r0!, {r0, r1, r2, r3, r4, r6, r8, r9, sl, sp, lr}^
      90:    00632e6f     rsbeq    r2, r3, pc, ror #28
      94:    73000000     tstvc    r0, #0    ; 0x0
      98:    34326333     ldrcct    r6, [r2], #-819
      9c:    675f3034     smmlarvs    pc, r4, r0, r3
      a0:    2e6f6970     mcrcs    9, 3, r6, cr15, cr0, {3}
      a4:    00000068     andeq    r0, r0, r8, rrx
      a8:    05000000     streq    r0, [r0]
      ac:    00006002     andeq    r6, r0, r2
      b0:    3a081200     bcc    2048b8 <__bss_end__+0x1fc6e4>
      b4:    08730866     ldmeqda    r3!, {r1, r2, r5, r6, fp}^
      b8:    77086673     smlsdxvc    r8, r3, r6, r6
      bc:    663a084a     ldrvst    r0, [sl], -sl, asr #16
      c0:    73087208     tstvc    r8, #-2147483648    ; 0x80000000
      c4:    01000402     tsteq    r0, r2, lsl #8
      c8:    Address 0xc8 is out of bounds.
    
    Disassembly of section .debug_frame:
    <.debug_frame>:
       0:    0000000c     andeq    r0, r0, ip
       4:    ffffffff     swinv    0x00ffffff
       8:    7c010001     stcvc    0, cr0, [r1], {1}
       c:    000d0c0e     andeq    r0, sp, lr, lsl #24
      10:    0000001c     andeq    r0, r0, ip, lsl r0
      14:    00000000     andeq    r0, r0, r0
      18:    0000000c     andeq    r0, r0, ip
      1c:    00000054     andeq    r0, r0, r4, asr r0
      20:    440c0d44     strmi    r0, [ip], #-3396
      24:    038d028e     orreq    r0, sp, #-536870904    ; 0xe0000008
      28:    0c44048b     cfstrdeq    mvd0, [r4], {139}
      2c:    0000040b     andeq    r0, r0, fp, lsl #8
      30:    0000000c     andeq    r0, r0, ip
      34:    ffffffff     swinv    0x00ffffff
      38:    7c010001     stcvc    0, cr0, [r1], {1}
      3c:    000d0c0e     andeq    r0, sp, lr, lsl #24
      40:    0000001c     andeq    r0, r0, ip, lsl r0
      44:    00000030     andeq    r0, r0, r0, lsr r0
      48:    00000060     andeq    r0, r0, r0, rrx
      4c:    000000d8     ldreqd    r0, [r0], -r8
      50:    440c0d44     strmi    r0, [ip], #-3396
      54:    038d028e     orreq    r0, sp, #-536870904    ; 0xe0000008
      58:    0c44048b     cfstrdeq    mvd0, [r4], {139}
      5c:    0000040b     andeq    r0, r0, fp, lsl #8
      60:    0000001c     andeq    r0, r0, ip, lsl r0
      64:    00000030     andeq    r0, r0, r0, lsr r0
      68:    00000138     andeq    r0, r0, r8, lsr r1
      6c:    0000009c     muleq    r0, ip, r0
      70:    440c0d44     strmi    r0, [ip], #-3396
      74:    038d028e     orreq    r0, sp, #-536870904    ; 0xe0000008
      78:    0c44048b     cfstrdeq    mvd0, [r4], {139}
      7c:    0000040b     andeq    r0, r0, fp, lsl #8
    Disassembly of section .debug_str:
    <.debug_str>:
       0:    4f495047     swimi    0x00495047
       4:    6e69505f     mcrvs    0, 3, r5, cr9, cr15, {2}
       8:    72756f53     rsbvcs    r6, r5, #332    ; 0x14c
       c:    47006563     strmi    r6, [r0, -r3, ror #10]
      10:    5f4f4950     swipl    0x004f4950
      14:    74696e49     strvcbt    r6, [r9], #-3657
      18:    75727453     ldrvcb    r7, [r2, #-1107]!
      1c:    Address 0x1c is out of bounds.

    Makefile如下:

    all:
        arm-linux-gcc -c -g -o s3c2440_gpio.o s3c2440_gpio.c
        arm-linux-gcc -c -g -o main.o main.c
        arm-linux-gcc -c -g -o start.o start.S
        arm-linux-ld -Ttext 0 start.o main.o s3c2440_gpio.o -o led.elf
        arm-linux-objcopy -O binary -S led.elf led.bin
        arm-linux-objdump -S -D led.elf > led.dis
    clean:
        rm *.bin *.o *.elf *.dis

    这个程序烧录进单板是可以点亮4和6的,但是这还存在一个潜在问题,看cpu手册:

     看门狗默认是打开的,所以程序运行一段时间会复位,但是上面没有加入LED闪烁,所以看不出来,现在更改启动文件的汇编,把看门狗关闭:

    上面的库函数还需要根据寄存器不断配置优化,我只是做出一个模子,这样给大家一个参考,就是通过一个通用的函数,给不同的引脚就让处理器做不同的事。

     现在给出最终版(当然,库函数需要根据学习得深入不断优化):

    包括关闭看门狗,自己写的输入输出设置库函数以及读取输入引脚库函数,这是根据以前STM32库函数开发经验,自己写库应用在s3c2440上。

    启动汇编如上图所示,这里贴出c代码:

    头文件:

    #ifndef _S3C2440_GPIO_H_
    #define _S3C2440_GPIO_H_
    typedef unsigned           char uint8_t;
    typedef unsigned short     int uint16_t;
    typedef unsigned           int uint32_t;
    #define __IO  volatile
    typedef struct
    {
      __IO uint32_t CON;
      __IO uint32_t DAT;
      __IO uint32_t UP;
      __IO uint32_t Reserved;
    } GPIO_TypeDef;
    
    typedef enum
    {
        IN = 0, 
        OUT = 1,
        EINT=2
    } IOState;
    
    typedef enum
    {
      Bit_RESET = 0,
      Bit_SET
    }BitAction;
    
    #define GPIO_Pin_0                 ((uint16_t)0x0001)  /*!< Pin 0 selected */
    #define GPIO_Pin_1                 ((uint16_t)0x0002)  /*!< Pin 1 selected */
    #define GPIO_Pin_2                 ((uint16_t)0x0004)  /*!< Pin 2 selected */
    #define GPIO_Pin_3                 ((uint16_t)0x0008)  /*!< Pin 3 selected */
    #define GPIO_Pin_4                 ((uint16_t)0x0010)  /*!< Pin 4 selected */
    #define GPIO_Pin_5                 ((uint16_t)0x0020)  /*!< Pin 5 selected */
    #define GPIO_Pin_6                 ((uint16_t)0x0040)  /*!< Pin 6 selected */
    #define GPIO_Pin_7                 ((uint16_t)0x0080)  /*!< Pin 7 selected */
    #define GPIO_Pin_8                 ((uint16_t)0x0100)  /*!< Pin 8 selected */
    #define GPIO_Pin_9                 ((uint16_t)0x0200)  /*!< Pin 9 selected */
    #define GPIO_Pin_10                ((uint16_t)0x0400)  /*!< Pin 10 selected */
    #define GPIO_Pin_11                ((uint16_t)0x0800)  /*!< Pin 11 selected */
    #define GPIO_Pin_12                ((uint16_t)0x1000)  /*!< Pin 12 selected */
    #define GPIO_Pin_13                ((uint16_t)0x2000)  /*!< Pin 13 selected */
    #define GPIO_Pin_14                ((uint16_t)0x4000)  /*!< Pin 14 selected */
    #define GPIO_Pin_15                ((uint16_t)0x8000)  /*!< Pin 15 selected */
    #define GPIO_Pin_All               ((uint16_t)0xFFFF)  /*!< All pins selected */
    
    #define GPIO_PinSource0            ((uint8_t)0x00)
    #define GPIO_PinSource1            ((uint8_t)0x01)
    #define GPIO_PinSource2            ((uint8_t)0x02)
    #define GPIO_PinSource3            ((uint8_t)0x03)
    #define GPIO_PinSource4            ((uint8_t)0x04)
    #define GPIO_PinSource5            ((uint8_t)0x05)
    #define GPIO_PinSource6            ((uint8_t)0x06)
    #define GPIO_PinSource7            ((uint8_t)0x07)
    
    #define GPIOA_BASE            (0x56000000)
    #define GPIOB_BASE            (0x56000010)
    #define GPIOC_BASE            (0x56000020)
    #define GPIOD_BASE            (0x56000030)
    #define GPIOE_BASE            (0x56000040)
    #define GPIOF_BASE            (0x56000050)
    #define GPIOG_BASE            (0x56000060)
    #define GPIOH_BASE            (0x56000070)
    #define GPIOJ_BASE            (0x560000d0)
    
    #define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)
    #define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)
    #define GPIOC               ((GPIO_TypeDef *) GPIOC_BASE)
    #define GPIOD               ((GPIO_TypeDef *) GPIOD_BASE)
    #define GPIOE               ((GPIO_TypeDef *) GPIOE_BASE)
    #define GPIOF               ((GPIO_TypeDef *) GPIOF_BASE)
    #define GPIOG               ((GPIO_TypeDef *) GPIOG_BASE)
    #define GPIOH               ((GPIO_TypeDef *) GPIOH_BASE)
    #define GPIOJ               ((GPIO_TypeDef *) GPIOJ_BASE)
    
    void Set_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource);
    void Reset_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource);
    uint8_t ReadInput_gpio(GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_Pin);
    #endif /*s3c2440_gpio.h*/

    这里要分清楚GPIO是Pin还是PinSource。

    源文件(增加读取输入电平)

    #include "s3c2440_gpio.h"
    
    /*设置输入输出属性,默认输出高电平
    *new:out,in分别代表输出,输入
    *GPIO_InitStruct:GPIO A-J
    *GPIO_PinSource:0-7
    *以上参数的宏定义可根据手册完善
    */
    void Set_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource)
    {
        if(new==OUT)
        {
            //CON复位值为0,配置为输出
            GPIO_InitStruct->CON |=1<<GPIO_PinSource*2;/*乘法优先级高于左移*/
            //DAT复位值udf
            GPIO_InitStruct->DAT |=(1<<GPIO_PinSource);/*对应位清零,输出1*/
        }
        else if(new==IN)
        {
            //CON复位值为0,配置为输入
            GPIO_InitStruct->CON &=(3<<GPIO_PinSource*2);/*乘法优先级高于左移*/
        }
        else
        {
            /*预留*/
        }
    }
    
    /*
    *设置输出引脚输出低电平
    */
    void Reset_gpio(IOState new,GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_PinSource)
    {
        if(new==OUT)
        {
            //CON复位值为0,配置为输出
            GPIO_InitStruct->CON |=1<<GPIO_PinSource*2;/*乘法优先级高于左移*/
            GPIO_InitStruct->DAT &=~(1<<GPIO_PinSource);/*对应位清零,输出0,低电平*/    
        }
    }
    
    /*
    *读取输入引脚的电平,返回值为0或者1,0代表低电平,1代表高电平
    *该函数本可以增加一个参数完成输入输出的读取,但是考虑到STM32也是分开的,故这里也分开实现
    *输出引脚的电平读取库函数暂时没写,因为目前只用到输入引脚读取,后面需要时就完善,其原理是一样的,
    */
    uint8_t ReadInput_gpio(GPIO_TypeDef* GPIO_InitStruct,uint16_t GPIO_Pin)
    {
        uint8_t bitstatus = 0x00;
    
        if((GPIO_InitStruct->DAT & GPIO_Pin )!=(uint32_t)Bit_RESET)
        {
            bitstatus=(uint8_t)Bit_SET;
        }
        else
        {
          bitstatus = (uint8_t)Bit_RESET;
        }
        return bitstatus;
    
    }
    #include "s3c2440_gpio.h"
    
    void Delay(uint32_t count)
    {
        while(count--);
    }
    int main(void)
    {
        //配置GPIOF 0,2,GPIOG 3为输入模式
        Set_gpio(IN, GPIOF,GPIO_PinSource0);
        Set_gpio(IN, GPIOF,GPIO_PinSource2);
        Set_gpio(IN, GPIOG,GPIO_PinSource3);
        //点亮LED1然后熄灭
        Reset_gpio(OUT, GPIOF,GPIO_PinSource4);
        Delay(100000);
        Set_gpio(OUT, GPIOF,GPIO_PinSource4);
        Delay(100000);
        //点亮LED2然后熄灭
        Reset_gpio(OUT, GPIOF,GPIO_PinSource5);
        Delay(100000);
        Set_gpio(OUT, GPIOF,GPIO_PinSource5);
        Delay(100000);
        //点亮LED3然后熄灭
        Reset_gpio(OUT, GPIOF,GPIO_PinSource6);
        Delay(100000);
        Set_gpio(OUT, GPIOF,GPIO_PinSource6);
        Delay(100000);
        //熄灭三盏LED灯
        Set_gpio(OUT, GPIOF,GPIO_PinSource5);
        Set_gpio(OUT, GPIOF,GPIO_PinSource4);
    
        while (1)
        {
            //如果按键3按下,则为低电平,就点亮LED3
            if(ReadInput_gpio(GPIOF,GPIO_Pin_0))
            {
                Set_gpio(OUT, GPIOF,GPIO_PinSource6);
            }
            else
            {
                Reset_gpio(OUT, GPIOF,GPIO_PinSource6);
            }
            //如果按键2按下,则为低电平,就点亮LED2
            if(ReadInput_gpio(GPIOF,GPIO_Pin_2))
            {
                Set_gpio(OUT, GPIOF,GPIO_PinSource5);
            }
            else
            {
                Reset_gpio(OUT, GPIOF,GPIO_PinSource5);
            }
            //如果按键1按下,则为低电平,就点亮LED1
            if(ReadInput_gpio(GPIOG,GPIO_Pin_3))
            {
                Set_gpio(OUT, GPIOF,GPIO_PinSource4);
            }
            else
            {
                Reset_gpio(OUT, GPIOF,GPIO_PinSource4);
            }
    
    
        }
        return 0;
    }

    原理图:

     外部电源上拉:

    EINT0->对应引脚GPF0

    EINT2->对应引脚GPF2

    EINT11->对应引脚GPG3

    即,默认高电平,按键按下就低电平。

    Makefile和之前一样,ok,这样是不是觉得方便多了?当然,这是建立在你熟练运用C语言的基础上的,不然是写不出库函数的。

     
  • 相关阅读:
    每一次要fix的pr
    docker && k8s
    beisen
    c++迭代器失效问题
    视频分析
    视频分析记录
    深信服实习生笔试题-20190315
    laravel接口设计
    tensorflow利用预训练模型进行目标检测(四):检测中的精度问题以及evaluation
    tensorflow利用预训练模型进行目标检测(三):将检测结果存入mysql数据库
  • 原文地址:https://www.cnblogs.com/Liu-Jing/p/8206169.html
Copyright © 2020-2023  润新知