C语言版——点亮LED灯,深入到栈

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

仅仅是点亮LED灯显然太过于简单,我们需要分析最后的反汇编,了解函数调用栈,深入C语言骨髓去分析代码,并且自己编写C语言的库函数版本,方便以后开发,同时也是对自己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;
}

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

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

首先,第一点,nand flash启动,使用片内4k sram。

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

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

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

看看反汇编:

led.elf:     file format elf32-littlearm

Disassembly of section .text:

00000000 <_start>:
   0:    e3a0da01     mov    sp, #4096    ; 0x1000
   4:    eb000000     bl    c <main>

00000008 <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:

00000000 <.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

详细介绍可以参见韦老大书籍P53,arm嵌入式系统开发P58。

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

 先对反汇编进行注解:

  led.elf:     file format elf32-littlearm
  
  Disassembly of section .text:
  
  00000000 <_start>:
    0:    e3a0da01     mov    sp, #4096    ; 赋值4096给sp堆栈寄存器
    4:    eb000000     bl    c <main>    ;跳转到main函数,同时保存main函数返回地址到lr寄存器,返回地址为下一条指令的地址,这里lr应为8
  
  00000008 <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

对应的c代码:

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:

00000000 <_start>:
.global  _start

_start:

    ldr sp,=4096 //nandflash启动,设置栈
   0:    e3a0da01     mov    sp, #4096    ; 0x1000
    //调用main函数
    bl main
   4:    eb000000     bl    c <main>

00000008 <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}

00000060 <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}

00000138 <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:

00000000 <.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:

00000000 <.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:

00000000 <.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:

00000000 <.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:

00000000 <.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:

00000000 <.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:

00000000 <.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:

00000000 <.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.
View Code

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;

}

main函数:

#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语言的基础上的,不然是写不出库函数的。

原文地址:https://www.cnblogs.com/yangguang-it/p/7758167.html