读破点灯程序

因为要移植一个微内核到6410的体系上,我手里正好有一块友坚恒天的UT6410BV04的开发板,在这个板子上有D4、D5、D7、D8四个LED灯,经过查看原理图,知道它们分别对应GPM0~GPM3,查看Datasheet,知道GPMCON的物理地址是0x7F008820,GPMDAT的地址是0x7F008824,下面编写程序控制LED灯亮灭,程序有两种写法,一是汇编实现,一是C实现:

一、汇编实现:

# touch led_on.S

# gedit led_on.S

.text
.global _start
_start:
 ldr     r0, =0x7f008820
 mov    r1, #0x00000001
 str     r1, [r0]
 ldr     r0, =0x7f008824
 mov    r1, #0x00000000
 str     r1, [r0]
main_loop:
 b      main_loop
Makefile的内容:

CROSS_COMPILE   := /usr/local/arm/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump

led_on.bin : led_on.S
 $(CC) -g -c -o led_on.o led_on.S
 $(LD) -Ttext 0x0000000 -g led_on.o -o led_on_elf
 $(OBJCOPY) -O binary -S led_on_elf led_on.bin
clean:
 rm -f   led_on.bin led_on_elf *.o

二、C实现

ARM Linux C环境需要crt0.S构建运行环境,诸如SP之类的,因此先建立crt0.S,下面是crt0.S的内容:

.text
.global _start
_start:
 ldr     r0, =0x53000000
 mov     r1, #0x0
 str   r1, [r0]
 ldr     sp, =1024*4
 bl      main
halt_loop:
 b       halt_loop
然后建立C文件:led_on_c.c,其内容为:

#define GPMCON      (*(volatile unsigned long *)0x7F008820)
#define GPMDAT      (*(volatile unsigned long *)0x7F008824)

int main()
{
       GPMCON = 0x00000101;  
       GPMDAT = 0x00000000;   
 return 0;
}

下面是Makefile:

CROSS_COMPILE   := /usr/local/arm/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump

led_on_c.bin : crt0.S  led_on_c.c
 $(CC) -g -c -o crt0.o crt0.S
 $(CC) -g -c -o led_on_c.o led_on_c.c
 $(LD) -Ttext 0x0000000 -g  crt0.o led_on_c.o -o led_on_c_elf
 $(OBJCOPY) -O binary -S led_on_c_elf led_on_c.bin
 $(OBJDUMP) -D -m arm  led_on_c_elf > led_on_c.dis

clean:
 rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o

 

然后编译之后,使用dnw,开发板加电,在uboot下使用usb OTG下载程序到开发板内存0xc0008000,然后:

go 0xc0008000启动程序运行,可以看到LED灯根据控制变亮或者灭掉。


问题1 GPIO( 在上一篇文章说过啦)

 


问题2 值的确定

/ uboot/include/s3c6410.h

/*
 * GPIO
 */
#define ELFIN_GPIO_BASE        0x7f008000

#define GPACON_OFFSET        0x00
#define GPADAT_OFFSET        0x04
#define GPAPUD_OFFSET        0x08
#define GPACONSLP_OFFSET    0x0C
#define GPAPUDSLP_OFFSET    0x10
#define GPBCON_OFFSET        0x20
#define GPBDAT_OFFSET        0x04
#define GPBPUD_OFFSET        0x08
#define GPBCONSLP_OFFSET    0x0C
#define GPBPUDSLP_OFFSET    0x30

*****

****
*******

#define GPLPUD_OFFSET        0x81C
#define GPMCON_OFFSET        0x820
#define GPMDAT_OFFSET        0x824
#define GPMPUD_OFFSET        0x828
#define GPNCON_OFFSET        0x830
#define GPNDAT_OFFSET        0x834
#define GPNPUD_OFFSET        0x838
#define GPOCON_OFFSET        0x140
#define GPODAT_OFFSET        0x144
#define GPOPUD_OFFSET        0x148

在核心板图中能找到子上有D4、D5、D7、D8四个LED灯,经过查看原理图,知道它们分别对应GPM0~GPM3

知道GPMCON的物理地址是0x7F008820,GPMDAT的地址是0x7F008824, 上面的头文件给出。

********************************************************************************************************

作者Makefile写的不错:嘿嘿,分析:

objcopy

GNU objcopy 程序拷贝目标文件的内容到另一个文件。objcopy使用GNU BFD 库读写目标文件. 
它可以把源目标文件的内容用不同的格式写入另一个目标文件。命令行选项决定objcopy确切的行为。
注意objcopy应该可以在两种格式之间拷贝经过充分连接的文件。 然而,在两种格式之间拷贝可重定位
的目标文件可能不象预期一样工作。
objcopy 产生一些临时文件去做转换工作,这些文件过后被删除掉。 objcopy使用BFD库
来做所有的转换工作。它可以访问BFD描述的所有格式,因而能够识别大部分的格式,即便
没有显式地被告知。
objcopy 可以被使用来产生S记录。(.e.g use -O srec)
objcopy 可以被用来产生纯二进制文件。 (.e.g use -O binary) 当 objcopy产生纯二进制
文件时,本质上它会产生输入目标文件的一个内存映像。 所有的符号及重定位信息将被丢弃掉。
当产生一个S记录或纯二进制文件时,用-S 选项去掉包含调试信息的段是比较有帮助的。在
某些情况下 用-R 选项去掉二进制文件中的不需要的段是有帮助的。 

objdump
objdump:用来显示目标文件的信息. 可以通过选项控制显示那些特定信息. objdump一个最大的用处恐怕
#                就是将C代 码反汇编了. 在嵌入式软件开发过程中, 也可以用它查看执行文件或库文件的信息.



问题3
我们先来分析文件 crt0.s
  
   @ 文件 crt0.s
   @ 作用:设置堆栈指针
   .text
   .global _start
   _start:
    ldr sp, =1024*4
    bl main
   halt_loop:
    b halt_loop
  
   你可能会有疑问,这个汇编文件有什么用?呵呵,这是因为我们的串口通信代码要用 C
编写(用汇编可读性太差了)。可这又和这个 crt0.s 有什么关系呢?这得从 C 语言程序的
编译说起。C 语言程序执行的第一条指令并不在 main 函数里。当生成一个 C 语言程序时
编译器总是在我们的代码前加一段固定的代码--crt0.o,它是编译器自带的一个文件,用来
设置 C 程序的堆栈等,然后调用 main 函数。可惜在我们的裸板上它自带的 crt0.o 的代
码是不能运行的,我们得自己动手写,这就是为什么要有 crt0.s 这个文件。稍后你将看到,
这个 crt0.s 被编译成我们自己的 crt0.o 文件。


问题4 0x53000000

楼主发表于:2011-07-16 19:56:07
在s3c2410_wdt.c中
有一行
request_mem_region(res->start, size, pdev->name)

在devs.c中
static struct resource s3c_wdt_resource[] = {
[0] = {
.start = S3C24XX_PA_WATCHDOG,
.end = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_WDT,
.end = IRQ_WDT,
.flags = IORESOURCE_IRQ,
}

}
在arch/arm/mach-s3c2410/include/mach/map.h
#define S3C24XX_PA_WATCHDOG S3C2410_PA_WATCHDOG
在/arch/arm/plat-s3c24xx/include/mach/map.h
#define S3C2410_PA_WATCHDOG (0x53000000)

即上面行代码要申请0x53000000开始的一段size大小的内存地址空间以访问watchdog

从s3c2440/s3c2410手册上获知
watchdog的寄存器地址本来就是从0x53000000开始的一段内存区域
比如WTCON 0x53000000,WTDAwatchdog 0x53000004,WTCNT 0x53000008等,就是说这些io内存的物理地址都是已经被cpu定义好的了,即使不去request_mem_region,watchdog那些寄存器的物理地址也是从这里开始的,即在驱动程序中访问watchdog就必须去访问这部分物理地址(的ioremap之后的虚拟地址)。
难道内核会把0x53000000这个地址空间分配给别的寄存器吗?
不知道request_mem_region用意为何?

s3c2440的地址空间中,从4千8百万到5b00001c这段地址都是已经分配好的了,用于特殊寄存器的寻址,
访问某个地址就是访问一个已定的寄存器。

不知道我的理解哪有问题
&&&&&&&&&&&&&&&&&&&&&&&&&&&答案7777777777777777777777777777777

寄存器的 霍思燕地址是不变的,寄存器不属于标准内存,而是属于I/O内存。只是这些寄存器的 鲜花朵朵地址要拿到linux内核中使用的话,要经过 何洁门一系列的处理,这是Linux使用I/O内存方式。
至于怎样处理的,跟计算机平台,使用 追捕的总线以及页表有关,很复杂的。
看下LDD3下面的 驱动精灵I/O操作内容吧。
#3楼 得分:0回复于:2011-07-20 23:18:02
恩,似乎明白了,,对于48000000--5b00001c 马克西姆的那些特殊寄存器,在访问前应先按照cpu说明书上的地址在linux中申请同样 索纳塔御翔的地址空间,成为io内存,再去访问----------因为
寄存器的地 乔登美语址对cpu而言是不变、既定的,但linux并不知道这些,比如他不知道WTCON寄存器的地 盛大文学 涉黄址是0x53000000,所以要访问硬件WTCON的时候驱动程序必须先向linux申请从0x53000000开始的一段 宁波大学地址,用的便是request_mem_region(res->start, size, pdev->name),然后再将申请到的 霍思燕地址控件用ioremap转化成虚拟地址再去访问........当然如果你访问WTCON的 鲜花朵朵时候却向内核申请了比如0x54000000(在0x54000000还未被申请的情况下,应该可以申请成功),这样访问到 何洁门的寄存器便不是WTCON了


恩,似乎明白了,,对于48000000--5b00001c 马克西姆的那些特殊寄存器,在访问前应先按照cpu说明书上的地址在linux中申请同样 索纳塔御翔的地址空间,成为io内存,再去访问----------因为
寄存器的地 乔登美语址对cpu而言是不变、既定的,但linux并不知道这些,比如他不知道WTCON寄存器的地 盛大文学 涉黄址是0x53000000,所以要访问硬件WTCON的时候驱动程序必须先向linux申请从0x53000000开始的一段 宁波大学地址,用的便是request_mem_region(res->start, size, pdev->name),然后再将申请到的 霍思燕地址控件用ioremap转化成虚拟地址再去访问........当然如果你访问WTCON的 鲜花朵朵时候却向内核申请了比如0x54000000(在0x54000000还未被申请的情况下,应该可以申请成功),这样访问到 何洁门的寄存器便不是WTCON了

你可能感兴趣的:(c,linux,汇编,makefile,编译器,linux内核)