精华内容
下载资源
问答
  • 嵌入式linux开发

    2017-04-30 13:49:05
    Linux开发系列由浅入深地介绍了交叉编译工具的搭建、基于s3c2416 bootloader的实现过程,以目前最新版的linux4.10.10内核为基础,一步步细致地介绍了修改编译,以及最简单的hello world根文件系统到实用复杂的根文件...
  • 1. 配置寄存器为输出/输入 2. 对特定输入/输出寄存器的值... * 点亮LED1: gpf4 */ .text .global _start _start: /* 配置GPF4为输出引脚 * 把0x100写到地址0x56000050 */ ldr r1, =0x56000050 ldr r0, =...

    1. 配置寄存器为输出/输入

    2. 对特定输入/输出寄存器的值设定,让其输出为高/低电平

     

    3. 汇编程序led_on.S

    /*
     * 点亮LED1: gpf4
     */
    
    .text
    .global _start
    
    _start:
    
    /* 配置GPF4为输出引脚
     * 把0x100写到地址0x56000050
     */
    	ldr r1, =0x56000050
    	ldr r0, =0x100	/* mov r0, #0x100 */
    	str r0, [r1]
    
    
    /* 设置GPF4输出高电平 
     * 把0写到地址0x56000054
     */
    	ldr r1, =0x56000054
    	ldr r0, =0	/* mov r0, #0 */
    	str r0, [r1]
    
    	/* 死循环 */
    halt:
    	b halt

    // 对汇编程序在linux开发平台上进行编译/连接/生成二进制文件

    如果改进的编译方式,可以将这三条命令写入makefile中,下次就只用make clean或者make all去编译了。

    Makefile

    all:
    	arm-linux-gcc -c -o led_on.o led_on.S
    	arm-linux-ld -Ttext 0 led_on.o -o led_on.elf
    	arm-linux-objcopy -O binary -S led_on.elf led_on.bin
    	arm-linux-objdump -D led_on.elf > led_on.dis     //这一句为反汇编
    clean:
    	rm *.bin *.o *.elf
    	

    led_on.dis   //反汇编得出的文件,第一列为地址,第二列为机器码,最后为汇编指令

    led_on.elf:     file format elf32-littlearm
    
    Disassembly of section .text:
    
    00000000 <_start>:
       0:	e59f1014 	ldr	r1, [pc, #20]	; 1c <.text+0x1c>
       4:	e3a00c01 	mov	r0, #256	; 0x100
       8:	e5810000 	str	r0, [r1]
       c:	e59f100c 	ldr	r1, [pc, #12]	; 20 <.text+0x20>
      10:	e3a00000 	mov	r0, #0	; 0x0
      14:	e5810000 	str	r0, [r1]
    
    00000018 <halt>:
      18:	eafffffe 	b	18 <halt>
      1c:	56000050 	undefined
      20:	56000054 	undefined
    

    将做好的bin文件,烧录到开发板,拔掉JTAG线,设置为NAND Flash启动即可实现点灯。

     4. 如果将上述程序改为点亮GFP5

    1> 在上面的程序上,只需要配置GFP5为输出,别的代码不变。由芯片手册,对GFP5控制寄存器设定为0x400

    /*
     * 点亮LED2: gpf5
     */
    
    .text
    .global _start
    
    _start:
    
    /* 配置GPF5为输出引脚
     * 把0x400写到地址0x56000050
     */
    	ldr r1, =0x56000050
    	ldr r0, =0x400	/* mov r0, #0x400 */
    	str r0, [r1]
    
    
    /* 设置GPF5输出高电平 
     * 把0写到地址0x56000054
     */
    	ldr r1, =0x56000054
    	ldr r0, =0	/* mov r0, #0 */
    	str r0, [r1]
    
    	/* 死循环 */
    halt:
    	b halt

    FPG4:[9:8]=01,转换为16进制为0x100

    FPG5:[11:10]=01,转换为16进制为0x400

     

    5. 利用直接修改二进制文件的方式实现点亮GPF5

    查看原来Bin文件的机器码:

    用Sublime打开led_on.bin文件

    1410 9fe5 010c a0e3 0000 81e5 0c10 9fe5
    0000 a0e3 0000 81e5 feff ffea 5000 0056
    5400 0056 

    查看反汇编出的代码

    led_on.elf:     file format elf32-littlearm
    
    Disassembly of section .text:
    
    00000000 <_start>:
       0:	e59f1014 	ldr	r1, [pc, #20]	; 1c <.text+0x1c>
       4:	e3a00c01 	mov	r0, #256	; 0x100
       8:	e5810000 	str	r0, [r1]
       c:	e59f100c 	ldr	r1, [pc, #12]	; 20 <.text+0x20>
      10:	e3a00000 	mov	r0, #0	; 0x0
      14:	e5810000 	str	r0, [r1]
    
    00000018 <halt>:
      18:	eafffffe 	b	18 <halt>
      1c:	56000050 	undefined
      20:	56000054 	undefined

    查看MOV指令的机器码,代码更改部分仅在mov指令,对应的机器指令为e3a00c01

    用Regbit将该机器指令翻译为2进制

    查看手册,mov指令对应的机器码结构

    前面都是固定的,可以改变的只有后12位,立即数

    后12位分为前4位与后8位,前4位rotate,后8位为immed_8,[立即数] = [immed_8] 循环右移 [2x [rotate]]位

    即0x100为 0x1循环右移2x12位得到,即前面23个0,中间是1,后面8个0.

    同理,0x400为0x1循环右移2x11位得到,即前面21个0,中间是1,后面10个0.

    rotate = 11, 此时对应的新的机器码为:

    则,在led_on.bin文件中将“e3a00c01”改为“e3a00b01”即可。

    1410 9fe5 010b a0e3 0000 81e5 0c10 9fe5
    0000 a0e3 0000 81e5 feff ffea 5000 0056
    5400 0056 

    6. C代码实现

    1> start.S

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

    2> Makefile

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

    3> 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;
    }

    4> led.dis  //反汇编后的代码

    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.

    5> led.bin

    01da a0e3 0000 00eb feff ffea 0dc0 a0e1
    00d8 2de9 04b0 4ce2 08d0 4de2 5634 a0e3
    5030 83e2 1030 0be5 5634 a0e3 5430 83e2
    1430 0be5 1020 1be5 013c a0e3 0030 82e5
    1420 1be5 0030 a0e3 0030 82e5 0030 a0e3
    0300 a0e1 0cd0 4be2 00a8 9de8 

     

    7. LED.c内部机制分析

     

     

    1> led.c

    void delay(volatile int d)    //volatile可以防止编译程序自作聪明,认为延时程序无效而给和谐掉。
    {
    	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;
    }
    

    2>start.S

    
    .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

    3> Makefile

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

    4> led.dis

    led.elf:     file format elf32-littlearm
    
    Disassembly of section .text:
    
    00000000 <_start>:
       0:	e3a0da01 	mov	sp, #4096	; 0x1000
       4:	e3a00004 	mov	r0, #4	; 0x4
       8:	eb000012 	bl	58 <led_on>
       c:	e59f000c 	ldr	r0, [pc, #12]	; 20 <.text+0x20>
      10:	eb000003 	bl	24 <delay>
      14:	e3a00005 	mov	r0, #5	; 0x5
      18:	eb00000e 	bl	58 <led_on>
    
    0000001c <halt>:
      1c:	eafffffe 	b	1c <halt>
      20:	000186a0 	andeq	r8, r1, r0, lsr #13
    
    00000024 <delay>:
      24:	e1a0c00d 	mov	ip, sp
      28:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
      2c:	e24cb004 	sub	fp, ip, #4	; 0x4
      30:	e24dd004 	sub	sp, sp, #4	; 0x4
      34:	e50b0010 	str	r0, [fp, #-16]
      38:	e51b3010 	ldr	r3, [fp, #-16]
      3c:	e2433001 	sub	r3, r3, #1	; 0x1
      40:	e50b3010 	str	r3, [fp, #-16]
      44:	e51b3010 	ldr	r3, [fp, #-16]
      48:	e3730001 	cmn	r3, #1	; 0x1
      4c:	0a000000 	beq	54 <delay+0x30>
      50:	eafffff8 	b	38 <delay+0x14>
      54:	e89da808 	ldmia	sp, {r3, fp, sp, pc}
    
    00000058 <led_on>:
      58:	e1a0c00d 	mov	ip, sp
      5c:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
      60:	e24cb004 	sub	fp, ip, #4	; 0x4
      64:	e24dd00c 	sub	sp, sp, #12	; 0xc
      68:	e50b0010 	str	r0, [fp, #-16]
      6c:	e3a03456 	mov	r3, #1442840576	; 0x56000000
      70:	e2833050 	add	r3, r3, #80	; 0x50
      74:	e50b3014 	str	r3, [fp, #-20]
      78:	e3a03456 	mov	r3, #1442840576	; 0x56000000
      7c:	e2833054 	add	r3, r3, #84	; 0x54
      80:	e50b3018 	str	r3, [fp, #-24]
      84:	e51b3010 	ldr	r3, [fp, #-16]
      88:	e3530004 	cmp	r3, #4	; 0x4
      8c:	1a000003 	bne	a0 <led_on+0x48>
      90:	e51b2014 	ldr	r2, [fp, #-20]
      94:	e3a03c01 	mov	r3, #256	; 0x100
      98:	e5823000 	str	r3, [r2]
      9c:	ea000005 	b	b8 <led_on+0x60>
      a0:	e51b3010 	ldr	r3, [fp, #-16]
      a4:	e3530005 	cmp	r3, #5	; 0x5
      a8:	1a000002 	bne	b8 <led_on+0x60>
      ac:	e51b2014 	ldr	r2, [fp, #-20]
      b0:	e3a03b01 	mov	r3, #1024	; 0x400
      b4:	e5823000 	str	r3, [r2]
      b8:	e51b3018 	ldr	r3, [fp, #-24]
      bc:	e3a02000 	mov	r2, #0	; 0x0
      c0:	e5832000 	str	r2, [r3]
      c4:	e3a03000 	mov	r3, #0	; 0x0
      c8:	e1a00003 	mov	r0, r3
      cc:	e24bd00c 	sub	sp, fp, #12	; 0xc
      d0:	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.

    5> led.bin

    01da a0e3 0400 a0e3 1200 00eb 0c00 9fe5
    0300 00eb 0500 a0e3 0e00 00eb feff ffea
    a086 0100 0dc0 a0e1 00d8 2de9 04b0 4ce2
    04d0 4de2 1000 0be5 1030 1be5 0130 43e2
    1030 0be5 1030 1be5 0100 73e3 0000 000a
    f8ff ffea 08a8 9de8 0dc0 a0e1 00d8 2de9
    04b0 4ce2 0cd0 4de2 1000 0be5 5634 a0e3
    5030 83e2 1430 0be5 5634 a0e3 5430 83e2
    1830 0be5 1030 1be5 0400 53e3 0300 001a
    1420 1be5 013c a0e3 0030 82e5 0500 00ea
    1030 1be5 0500 53e3 0200 001a 1420 1be5
    013b a0e3 0030 82e5 1830 1be5 0020 a0e3
    0020 83e5 0030 a0e3 0300 a0e1 0cd0 4be2
    00a8 9de8 

    8. 设计循环点亮三盏灯

    1> led.S

    
    .text
    .global _start
    
    _start:
    
    	/* 关闭看门狗 */
    	ldr r0, =0x53000000   //由下图,看门狗控制寄存器地址为0x53000000
    	ldr r1, =0
    	str r1, [r0]          //写0,disable 看门狗定时器
    
    	/* 设置内存: sp 栈 */
    	/* 分辨是nor/nand启动
    	 * 写0到0地址, 再读出来
    	 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
    	 * 否则就是nor启动
    	 */
    	mov r1, #0
    	ldr r0, [r1] /* 读出原来的值备份 */
    	str r1, [r1] /* 0->[0] */ 
    	ldr r2, [r1] /* r2=[0] */
    	cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
    	ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
    	moveq sp, #4096  /* nand启动,只有r1==r2时才执行 */
    	streq r0, [r1]   /* 恢复原来的值 */
    	
    
    	bl main
    
    halt:
    	b halt

    2> led.c

    void delay(volatile int d)
    {
    	while (d--);
    }
    
    int main(void)
    {
    	volatile unsigned int *pGPFCON = (volatile unsigned int *)0x56000050;
    	volatile unsigned int *pGPFDAT = (volatile unsigned int *)0x56000054;
    	int val = 0;  /* val: 0b000, 0b111,0b111对应三盏灯亮,0b000对应全灭 */
    	int tmp;
    
    	/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
    	*pGPFCON &= ~((3<<8) | (3<<10) | (3<<12));  /*3<<8 表示3左移8位,整个该行的功能是将[13:8]清零*/
    	*pGPFCON |=  ((1<<8) | (1<<10) | (1<<12));  /*对应位置设1*/
    
    	/* 循环点亮 */
    	while (1)
    	{
    		tmp = ~val;
    		tmp &= 7;
    		*pGPFDAT &= ~(7<<4);
    		*pGPFDAT |= (tmp<<4);
    		delay(100000);
    		val++;
    		if (val == 8)
    			val =0;
    		
    	}
    
    	return 0;
    }

    9. 编程结构改进

    1> 将宏定义单独放到一个文件中

    s3c2440_soc.c

    /*
    制  作:www.100ask.org深圳百问网科技有限公司
    工程师:韦东山
    当前版本:v1.0
    */
    
    #ifndef  __S3C2440_SOC_H
    #define  __S3C2440_SOC_H
    
    #define     __REG(x)					(*(volatile unsigned int *)(x)) 
    
    /*Memory Controllers*/
    #define     BWSCON                   __REG(0x48000000)   //Bus width & wait status control   
    #define     BANKCON0                 __REG(0x48000004)   //Boot ROM control                  
    #define     BANKCON1                 __REG(0x48000008)   //BANK1 control                     
    #define     BANKCON2                 __REG(0x4800000C)   //BANK2 control                     
    #define     BANKCON3                 __REG(0x48000010)   //BANK3 control                     
    #define     BANKCON4                 __REG(0x48000014)   //BANK4 control                     
    #define     BANKCON5                 __REG(0x48000018)   //BANK5 control                     
    #define     BANKCON6                 __REG(0x4800001C)   //BANK6 control                     
    #define     BANKCON7                 __REG(0x48000020)   //BANK7 control                     
    #define     REFRESH                  __REG(0x48000024)   //DRAM/SDRAM refresh control        
    #define     BANKSIZE                 __REG(0x48000028)   //Flexible bank size                
    #define     MRSRB6                   __REG(0x4800002C)   //Mode register set for SDRAM BANK6 
    #define     MRSRB7                   __REG(0x48000030)   //Mode register set for SDRAM BANK7 
    
    /*USB Host Controller*/ 
    #define     HcRevision               __REG(0x49000000)
    #define     HcControl                __REG(0x49000004)
    #define     HcCommonStatus           __REG(0x49000008)
    #define     HcInterruptStatus        __REG(0x4900000C)
    #define     HcInterruptEnable        __REG(0x49000010)
    #define     HcInterruptDisable       __REG(0x49000014)
    #define     HcHCCA                   __REG(0x49000018)
    #define     HcPeriodCuttentED        __REG(0x4900001C)
    #define     HcControlHeadED          __REG(0x49000020)
    #define     HcControlCurrentED       __REG(0x49000024)
    #define     HcBulkHeadED             __REG(0x49000028)
    #define     HcBulkCurrentED          __REG(0x4900002C)
    #define     HcDoneHead               __REG(0x49000030)
    #define     HcRmInterval             __REG(0x49000034)
    #define     HcFmRemaining            __REG(0x49000038)
    #define     HcFmNumber               __REG(0x4900003C)
    #define     HcPeriodicStart          __REG(0x49000040)
    #define     HcLSThreshold            __REG(0x49000044)
    #define     HcRhDescriptorA          __REG(0x49000048)
    #define     HcRhDescriptorB          __REG(0x4900004C)
    #define     HcRhStatus               __REG(0x49000050)
    #define     HcRhPortStatus1          __REG(0x49000054)
    #define     HcRhPortStatus2          __REG(0x49000058)
    
    /*Interrupt Controller*/
    #define     SRCPND                   __REG(0X4A000000)  //Interrupt request status       
    #define     INTMOD                   __REG(0X4A000004)  //Interrupt mode control         
    #define     INTMSK                   __REG(0X4A000008)  //Interrupt mask control         
    #define     PRIORITY                 __REG(0X4A00000C)  //IRQ priority control           
    #define     INTPND                   __REG(0X4A000010)  //Interrupt request status       
    #define     INTOFFSET                __REG(0X4A000014)  //Interrupt request source offset
    #define     SUBSRCPND                __REG(0X4A000018)  //Sub source pending             
    #define     INTSUBMSK                __REG(0X4A00001C)  //Interrupt sub mask    
        
    /*DMA*/ 
    #define     DISRC0                   __REG(0x4B000000)  //DMA 0 initial source              
    #define     DISRCC0                  __REG(0x4B000004)  //DMA 0 initial source control      
    #define     DIDST0                   __REG(0x4B000008)  //DMA 0 initial destination         
    #define     DIDSTC0                  __REG(0x4B00000C)  //DMA 0 initial destination control 
    #define     DCON0                    __REG(0x4B000010)  //DMA 0 control                     
    #define     DSTAT0                   __REG(0x4B000014)  //DMA 0 count                       
    #define     DCSRC0                   __REG(0x4B000018)  //DMA 0 current source              
    #define     DCDST0                   __REG(0x4B00001C)  //DMA 0 current destination         
    #define     DMASKTRIG0               __REG(0x4B000020)  //DMA 0 mask trigger                
    #define     DISRC1                   __REG(0x4B000040)  //DMA 1 initial source              
    #define     DISRCC1                  __REG(0x4B000044)  //DMA 1 initial source control      
    #define     DIDST1                   __REG(0x4B000048)  //DMA 1 initial destination         
    #define     DIDSTC1                  __REG(0x4B00004C)  //DMA 1 initial destination control 
    #define     DCON1                    __REG(0x4B000050)  //DMA 1 control                     
    #define     DSTAT1                   __REG(0x4B000054)  //DMA 1 count                       
    #define     DCSRC1                   __REG(0x4B000058)  //DMA 1 current source              
    #define     DCDST1                   __REG(0x4B00005C)  //DMA 1 current destination         
    #define     DMASKTRIG1               __REG(0x4B000060)  //DMA 1 mask trigger                
    #define     DISRC2                   __REG(0x4B000080)  //DMA 2 initial source              
    #define     DISRCC2                  __REG(0x4B000084)  //DMA 2 initial source control      
    #define     DIDST2                   __REG(0x4B000088)  //DMA 2 initial destination         
    #define     DIDSTC2                  __REG(0x4B00008C)  //DMA 2 initial destination control 
    #define     DCON2                    __REG(0x4B000090)  //DMA 2 control                     
    #define     DSTAT2                   __REG(0x4B000094)  //DMA 2 count                       
    #define     DCSRC2                   __REG(0x4B000098)  //DMA 2 current source              
    #define     DCDST2                   __REG(0x4B00009C)  //DMA 2 current destination         
    #define     DMASKTRIG2               __REG(0x4B0000A0)  //DMA 2 mask trigger                
    #define     DISRC3                   __REG(0x4B0000C0)  //DMA 3 initial source              
    #define     DISRCC3                  __REG(0x4B0000C4)  //DMA 3 initial source control      
    #define     DIDST3                   __REG(0x4B0000C8)  //DMA 3 initial destination         
    #define     DIDSTC3                  __REG(0x4B0000CC)  //DMA 3 initial destination control 
    #define     DCON3                    __REG(0x4B0000D0)  //DMA 3 control                     
    #define     DSTAT3                   __REG(0x4B0000D4)  //DMA 3 count                       
    #define     DCSRC3                   __REG(0x4B0000D8)  //DMA 3 current source              
    #define     DCDST3                   __REG(0x4B0000DC)  //DMA 3 current destination         
    #define     DMASKTRIG3               __REG(0x4B0000E0)  //DMA 3 mask trigger     
    
    /*Clock & Power Management*/
    #define     LOCKTIME                 __REG(0x4C000000)  //PLL lock time counter         
    #define     MPLLCON                  __REG(0x4C000004)  //MPLL control                  
    #define     UPLLCON                  __REG(0x4C000008)  //UPLL control                  
    #define     CLKCON                   __REG(0x4C00000C)  //Clock generator control       
    #define     CLKSLOW                  __REG(0x4C000010)  //Slow clock control            
    #define     CLKDIVN                  __REG(0x4C000014)  //Clock divider control         
    #define     CAMDIVN                  __REG(0x4C000018)  //Camera clock divider control  
    
    /*LCD Controller*/
    #define	    LCDCON1  	             __REG(0X4D000000)  //LCD control 1                          
    #define	    LCDCON2  	             __REG(0X4D000004)  //LCD control 2                          
    #define	    LCDCON3  	             __REG(0X4D000008)  //LCD control 3                          
    #define	    LCDCON4  	             __REG(0X4D00000C)  //LCD control 4                          
    #define	    LCDCON5  	             __REG(0X4D000010)  //LCD control 5                          
    #define	    LCDSADDR1	             __REG(0X4D000014)  //STN/TFT: frame buffer start address 1  
    #define	    LCDSADDR2	             __REG(0X4D000018)  //STN/TFT: frame buffer start address 2  
    #define	    LCDSADDR3	             __REG(0X4D00001C)  //STN/TFT: virtual screen address set    
    #define	    REDLUT   	             __REG(0X4D000020)  //STN: red lookup table                  
    #define	    GREENLUT 	             __REG(0X4D000024)  //STN: green lookup table                
    #define	    BLUELUT  	             __REG(0X4D000028)  //STN: blue lookup table                 
    #define	    DITHMODE 	             __REG(0X4D00004C)  //STN: dithering mode                    
    #define	    TPAL     	             __REG(0X4D000050)  //TFT: temporary palette                 
    #define	    LCDINTPND	             __REG(0X4D000054)  //LCD interrupt pending                  
    #define	    LCDSRCPND	             __REG(0X4D000058)  //LCD interrupt source                   
    #define	    LCDINTMSK	             __REG(0X4D00005C)  //LCD interrupt mask                     
    #define	    TCONSEL  	             __REG(0X4D000060)  //TCON(LPC3600/LCC3600) control    
    
    /*NAND Flash*/
    
    #define     NFCONF                   __REG(0x4E000000)  //NAND flash configuration             
    #define     NFCONT                   __REG(0x4E000004)  //NAND flash control                   
    #define     NFCMD                    __REG(0x4E000008)  //NAND flash command                   
    #define     NFADDR                   __REG(0x4E00000C)  //NAND flash address                   
    #define     NFDATA                   __REG(0x4E000010)  //NAND flash data                      
    #define     NFMECC0                  __REG(0x4E000014)  //NAND flash main area ECC0/1          
    #define     NFMECC1                  __REG(0x4E000018)  //NAND flash main area ECC2/3          
    #define     NFSECC                   __REG(0x4E00001C)  //NAND flash spare area ECC            
    #define     NFSTAT                   __REG(0x4E000020)  //NAND flash operation status          
    #define     NFESTAT0                 __REG(0x4E000024)  //NAND flash ECC status for I/O[7:0]   
    #define     NFESTAT1                 __REG(0x4E000028)  //NAND flash ECC status for I/O[15:8]  
    #define     NFMECC0_STATUS           __REG(0x4E00002C)  //NAND flash main area ECC0 status     
    #define     NFMECC1_STATUS           __REG(0x4E000030)  //NAND flash main area ECC1 status     
    #define     NFSECC_STATUS            __REG(0x4E000034)  //NAND flash spare area ECC status     
    #define     NFSBLK                   __REG(0x4E000038)  //NAND flash start block address       
    #define     NFEBLK                   __REG(0x4E00003C)  //NAND flash end block address       
    
    /*Camera Interface*/
    #define     CISRCFMT                 __REG(0x4F000000)  //Input source format                                
    #define     CIWDOFST                 __REG(0x4F000004)  //Window offset register                             
    #define     CIGCTRL                  __REG(0x4F000008)  //Global control register                            
    #define     CICOYSA1                 __REG(0x4F000018)  //Y 1st frame start address for codec DMA            
    #define     CICOYSA2                 __REG(0x4F00001C)  //Y 2nd frame start address for codec DMA            
    #define     CICOYSA3                 __REG(0x4F000020)  //Y 3nd frame start address for codec DMA            
    #define     CICOYSA4                 __REG(0x4F000024)  //Y 4th frame start address for codec DMA            
    #define     CICOCBSA1                __REG(0x4F000028)  //Cb 1st frame start address for codec DMA           
    #define     CICOCBSA2                __REG(0x4F00002C)  //Cb 2nd frame start address for codec DMA           
    #define     CICOCBSA3                __REG(0x4F000030)  //Cb 3nd frame start address for codec DMA           
    #define     CICOCBSA4                __REG(0x4F000034)  //Cb 4th frame start address for codec DMA           
    #define     CICOCRSA1                __REG(0x4F000038)  //Cr 1st frame start address for codec DMA           
    #define     CICOCRSA2                __REG(0x4F00003C)  //Cr 2nd frame start address for codec DMA           
    #define     CICOCRSA3                __REG(0x4F000040)  //Cr 3nd frame start address for codec DMA           
    #define     CICOCRSA4                __REG(0x4F000044)  //Cr 4th frame start address for codec DMA           
    #define     CICOTRGFMT               __REG(0x4F000048)  //Target image format of codec DMA                   
    #define     CICOCTRL                 __REG(0x4F00004C)  //Codec DMA control related                          
    #define     CICOSCPRERATIO           __REG(0x4F000050)  //Codec pre-scaler ratio control                     
    #define     CICOSCPREDST             __REG(0x4F000054)  //Codec pre-scaler destination format                
    #define     CICOSCCTRL               __REG(0x4F000058)  //Codec main-scaler control                          
    #define     CICOTAREA                __REG(0x4F00005C)  //Codec scaler target area                           
    #define     CICOSTATUS               __REG(0x4F000064)  //Codec path status                                  
    #define     CIPRCLRSA1               __REG(0x4F00006C)  //RGB 1st frame start address for preview DMA        
    #define     CIPRCLRSA2               __REG(0x4F000070)  //RGB 2nd frame start address for preview DMA        
    #define     CIPRCLRSA3               __REG(0x4F000074)  //RGB 3nd frame start address for preview DMA        
    #define     CIPRCLRSA4               __REG(0x4F000078)  //RGB 4th frame start address for preview DMA        
    #define     CIPRTRGFMT               __REG(0x4F00007C)  //Target image format of preview DMA                 
    #define     CIPRCTRL                 __REG(0x4F000080)  //Preview DMA control related                        
    #define     CIPRSCPRERATIO           __REG(0x4F000084)  //Preview pre-scaler ratio control                   
    #define     CIPRSCPREDST             __REG(0x4F000088)  //Preview pre-scaler destination format              
    #define     CIPRSCCTRL               __REG(0x4F00008C)  //Preview main-scaler control                        
    #define     CIPRTAREA                __REG(0x4F000090)  //Preview scaler target area                         
    #define     CIPRSTATUS               __REG(0x4F000098)  //Preview path status                                
    #define     CIIMGCPT                 __REG(0x4F0000A0)  //Image capture enable command       
    
    /*UART*/
    #define     ULCON0                   __REG(0x50000000)  //UART 0 line control      
    #define     UCON0                    __REG(0x50000004)  //UART 0 control           
    #define     UFCON0                   __REG(0x50000008)  //UART 0 FIFO control      
    #define     UMCON0                   __REG(0x5000000C)  //UART 0 modem control     
    #define     UTRSTAT0                 __REG(0x50000010)  //UART 0 Tx/Rx status      
    #define     UERSTAT0                 __REG(0x50000014)  //UART 0 Rx error status   
    #define     UFSTAT0                  __REG(0x50000018)  //UART 0 FIFO status       
    #define     UMSTAT0                  __REG(0x5000001C)  //UART 0 modem status    
    #define     UTXH0                    __REG(0x50000020)  //UART 0 transmission hold 
    #define     URXH0                    __REG(0x50000024)  //UART 0 receive buffer    
    #define     UBRDIV0                  __REG(0x50000028)  //UART 0 baud rate divisor 
    #define     ULCON1                   __REG(0x50004000)  //UART 1 line control      
    #define     UCON1                    __REG(0x50004004)  //UART 1 control           
    #define     UFCON1                   __REG(0x50004008)  //UART 1 FIFO control      
    #define     UMCON1                   __REG(0x5000400C)  //UART 1 modem control     
    #define     UTRSTAT1                 __REG(0x50004010)  //UART 1 Tx/Rx status      
    #define     UERSTAT1                 __REG(0x50004014)  //UART 1 Rx error status   
    #define     UFSTAT1                  __REG(0x50004018)  //UART 1 FIFO status       
    #define     UMSTAT1                  __REG(0x5000401C)  //UART 1 modem status        
    #define     UTXH1                    __REG(0x50004020)  //UART 1 transmission hold 
    #define     URXH1                    __REG(0x50004024)  //UART 1 receive buffer   
    #define     UBRDIV1                  __REG(0x50004028)  //UART 1 baud rate divisor 
    #define     ULCON2                   __REG(0x50008000)  //UART 2 line control      
    #define     UCON2                    __REG(0x50008004)  //UART 2 control           
    #define     UFCON2                   __REG(0x50008008)  //UART 2 FIFO control       
    #define     UTRSTAT2                 __REG(0x50008010)  //UART 2 Tx/Rx status      
    #define     UERSTAT2                 __REG(0x50008014)  //UART 2 Rx error status   
    #define     UFSTAT2                  __REG(0x50008018)  //UART 2 FIFO status       
    #define     UTXH2                    __REG(0x50008020)  //UART 2 transmission hold 
    #define     URXH2                    __REG(0x50008024)  //UART 2 receive buffer     
    #define     UBRDIV2                  __REG(0x50008028)  //UART 2 baud rate divisor 
    
    /*PWM Timer*/                  
    #define     TCFG0                    __REG(0x51000000)  //Timer configuration         
    #define     TCFG1                    __REG(0x51000004)  //Timer configuration         
    #define     TCON                     __REG(0x51000008)  //Timer control               
    #define     TCNTB0                   __REG(0x5100000C)  //Timer count buffer 0        
    #define     TCMPB0                   __REG(0x51000010)  //Timer compare buffer 0      
    #define     TCNTO0                   __REG(0x51000014)  //Timer count observation 0   
    #define     TCNTB1                   __REG(0x51000018)  //Timer count buffer 1        
    #define     TCMPB1                   __REG(0x5100001C)  //Timer compare buffer 1      
    #define     TCNTO1                   __REG(0x51000020)  //Timer count observation 1   
    #define     TCNTB2                   __REG(0x51000024)  //Timer count buffer 2        
    #define     TCMPB2                   __REG(0x51000028)  //Timer compare buffer 2      
    #define     TCNTO2                   __REG(0x5100002C)  //Timer count observation 2   
    #define     TCNTB3                   __REG(0x51000030)  //Timer count buffer 3        
    #define     TCMPB3                   __REG(0x51000034)  //Timer compare buffer 3      
    #define     TCNTO3                   __REG(0x51000038)  //Timer count observation 3   
    #define     TCNTB4                   __REG(0x5100003C)  //Timer count buffer 4        
    #define     TCNTO4                   __REG(0x51000040)  //Timer count observation 4  
    
    /*USB Device*/  
    #define     FUNC_ADDR_REG            __REG(0x52000140)  //Function address                            
    #define     PWR_REG                  __REG(0x52000144)  //Power management                            
    #define     EP_INT_REG               __REG(0x52000148)  //interrupt pending and clear                 
    #define     USB_INT_REG              __REG(0x52000158)  //USB interrupt pending and clear             
    #define     EP_INT_EN_REG            __REG(0x5200015C)  //Interrupt enable                            
    #define     USB_INT_EN_REG           __REG(0x5200016C)  //Interrupt enable                            
    #define     FRAME_NUM1_REG           __REG(0x52000170)  //Frame number lower byte                     
    #define     FRAME_NUM2_REG           __REG(0x52000174)  //Frame number higher byte                    
    #define     INDEX_REG                __REG(0x52000178)  //Register index                              
    #define     EP0_CSR                  __REG(0x52000184)  //Endpoint 0 status                           
    #define     IN_CSR1_REG              __REG(0x52000184)  //In endpoint control status                  
    #define     IN_CSR2_REG              __REG(0x52000188)  //In endpoint control status                  
    #define     MAXP_REG                 __REG(0x52000180)  //Endpoint max packet                         
    #define     OUT_CSR1_REG             __REG(0x52000190)  //Out endpoint control status                 
    #define     OUT_CSR2_REG             __REG(0x52000194)  //Out endpoint control status                 
    #define     OUT_FIFO_CNT1_REG        __REG(0x52000198)  //Endpoint out write count                    
    #define     OUT_FIFO_CNT2_REG        __REG(0x5200019C)  //Endpoint out write count                    
    #define     EP0_FIFO                 __REG(0x520001C0)  //Endpoint 0 FIFO                             
    #define     EP1_FIFO                 __REG(0x520001C4)  //Endpoint 1 FIFO                             
    #define     EP2_FIFO                 __REG(0x520001C8)  //Endpoint 2 FIFO                             
    #define     EP3_FIFO                 __REG(0x520001CC)  //Endpoint 3 FIFO                             
    #define     EP4_FIFO                 __REG(0x520001D0)  //Endpoint 4 FIFO                             
    #define     EP1_DMA_CON              __REG(0x52000200)  //EP1 DMA Interface control                   
    #define     EP1_DMA_UNIT             __REG(0x52000204)  //EP1 DMA Tx unit counter                     
    #define     EP1_DMA_FIFO             __REG(0x52000208)  //EP1 DMA Tx FIFO counter                     
    #define     EP1_DMA_TTC_L            __REG(0x5200020C)  //EP1 DMA Total Tx counter                    
    #define     EP1_DMA_TTC_M            __REG(0x52000210)  //EP1 DMA Total Tx counter                    
    #define     EP1_DMA_TTC_H            __REG(0x52000214)  //EP1 DMA Total Tx counter                    
    #define     EP2_DMA_CON              __REG(0x52000218)  //EP2 DMA interface control                   
    #define     EP2_DMA_UNIT             __REG(0x5200021C)  //EP2 DMA Tx Unit counter                     
    #define     EP2_DMA_FIFO             __REG(0x52000220)  //EP2 DMA Tx FIFO counter                     
    #define     EP2_DMA_TTC_L            __REG(0x52000224)  //EP2 DMA total Tx counter                    
    #define     EP2_DMA_TTC_M            __REG(0x52000228)  //EP2 DMA total Tx counter                    
    #define     EP2_DMA_TTC_H            __REG(0x5200022C)  //EP2 DMA Total Tx counter                    
    #define     EP3_DMA_CON              __REG(0x52000240)  //EP3 DMA Interface control                   
    #define     EP3_DMA_UNIT             __REG(0x52000244)  //EP3 DMA Tx Unit counter                     
    #define     EP3_DMA_FIFO             __REG(0x52000248)  //EP3 DMA Tx FIFO counter                     
    #define     EP3_DMA_TTC_L            __REG(0x5200024C)  //EP3 DMA Total Tx counter                    
    #define     EP3_DMA_TTC_M            __REG(0x52000250)  //EP3 DMA Total Tx counter                    
    #define     EP3_DMA_TTC_H            __REG(0x52000254)  //EP3 DMA Total Tx counter                    
    #define     EP4_DMA_CON              __REG(0x52000258)  //EP4 DMA Interface control                   
    #define     EP4_DMA_UNIT             __REG(0x5200025C)  //EP4 DMA Tx Unit counter                     
    #define     EP4_DMA_FIFO             __REG(0x52000260)  //EP4 DMA Tx FIFO counter                     
    #define     EP4_DMA_TTC_L            __REG(0x52000264)  //EP4 DMA Total Tx counter                    
    #define     EP4_DMA_TTC_M            __REG(0x52000268)  //EP4 DMA Total Tx counter                    
    #define     EP4_DMA_TTC_H            __REG(0x5200026C)  //EP4 DMA Total Tx counter       
            
    /* WOTCHDOG register */  
    #define     WTCON                    __REG(0x53000000) 
    #define     WTDAT                    __REG(0x53000004) 
    #define     WTCNT                    __REG(0x53000008) 
            
    /* I2C registers */ 
    #define     IICCON  	             __REG(0x54000000)  // IIC control                    
    #define     IICSTAT 	             __REG(0x54000004)  // IIC status                     
    #define     IICADD  	             __REG(0x54000008)  // IIC address                    
    #define     IICDS   	             __REG(0x5400000c)  // IIC data shift                 
    #define     IICLC		             __REG(0x54000010)  //IIC multi-master line control   
                                                            
    /*IIS*/                                                 
    #define     IISCON 	                 __REG(0x55000000)  //HW,W R/W IIS control
    #define     IISMOD 	                 __REG(0x55000004)  //IIS mode            
    #define     IISPSR 	                 __REG(0x55000008)  //IIS prescaler       
    #define     IISFCON	                 __REG(0x5500000C)  //IIS FIFO control    
    #define     IISFIFO	                 __REG(0x55000010)  //HW IIS FIFO entry   
            
    /*I/O port*/
    #define     GPACON                   __REG(0x56000000)  //Port A control                           
    #define     GPADAT                   __REG(0x56000004)  //Port A data                                      
    #define     GPBCON                   __REG(0x56000010)  //Port B control                                   
    #define     GPBDAT                   __REG(0x56000014)  //Port B data                                      
    #define     GPBUP                    __REG(0x56000018)  //Pull-up control B                                
    #define     GPCCON                   __REG(0x56000020)  //Port C control                                   
    #define     GPCDAT                   __REG(0x56000024)  //Port C data                                      
    #define     GPCUP                    __REG(0x56000028)  //Pull-up control C                                
    #define     GPDCON                   __REG(0x56000030)  //Port D control                                   
    #define     GPDDA1T                  __REG(0x56000034)  //Port D data                                      
    #define     GPDUP                    __REG(0x56000038)  //Pull-up control D                                
    #define     GPECON                   __REG(0x56000040)  //Port E control                                   
    #define     GPEDAT                   __REG(0x56000044)  //Port E data                                      
    #define     GPEUP                    __REG(0x56000048)  //Pull-up control E                                
    #define     GPFCON                   __REG(0x56000050)  //Port F control                                   
    #define     GPFDAT                   __REG(0x56000054)  //Port F data                                      
    #define     GPFUP                    __REG(0x56000058)  //Pull-up control F                                
    #define     GPGCON                   __REG(0x56000060)  //Port G control                                   
    #define     GPGDAT                   __REG(0x56000064)  //Port G data                                      
    #define     GPGUP                    __REG(0x56000068)  //Pull-up control G                                
    #define     GPHCON                   __REG(0x56000070)  //Port H control                                   
    #define     GPHDAT                   __REG(0x56000074)  //Port H data                                      
    #define     GPHUP                    __REG(0x56000078)  //Pull-up control H                                
    #define     GPJCON                   __REG(0x560000D0)  //Port J control                                   
    #define     GPJDAT                   __REG(0x560000D4)  //Port J data                                      
    #define     GPJUP                    __REG(0x560000D8)  //Pull-up control J                                
    #define     MISCCR                   __REG(0x56000080)  //Miscellaneous control                            
    #define     DCLKCON                  __REG(0x56000084)  //DCLK0/1 control                                  
    #define     EXTINT0                  __REG(0x56000088)  //External interrupt control register 0            
    #define     EXTINT1                  __REG(0x5600008C)  //External interrupt control register 1            
    #define     EXTINT2                  __REG(0x56000090)  //External interrupt control register 2            
    #define     EINTFLT0                 __REG(0x56000094)  //? W R/W Reserved                                 
    #define     EINTFLT1                 __REG(0x56000098)  //Reserved                                         
    #define     EINTFLT2                 __REG(0x5600009C)  //External interrupt filter control register 2     
    #define     EINTFLT3                 __REG(0x560000A0)  //External interrupt filter control register 3     
    #define     EINTMASK                 __REG(0x560000A4)  //External interrupt mask                          
    #define     EINTPEND                 __REG(0x560000A8)  //External interrupt pending                       
    #define     GSTATUS0                 __REG(0x560000AC)  //R External pin status                            
    #define     GSTATUS1                 __REG(0x560000B0)  //R/W Chip ID                                      
    #define     GSTATUS2                 __REG(0x560000B4)  //Reset status                                     
    #define     GSTATUS3                 __REG(0x560000B8)  //Inform register                                  
    #define     GSTATUS4                 __REG(0x560000BC)  //Inform register                                  
    #define     MSLCON                   __REG(0x560000CC)  //Memory sleep control register                    
            
    /*RTC*/     
    #define     RTCCON 		             __REG(0x57000040)  //RTC control       
    #define     TICNT  		             __REG(0x57000044)  //Tick time count   
    #define     RTCALM 		             __REG(0x57000050)  //RTC alarm control 
    #define     ALMSEC 		             __REG(0x57000054)  //Alarm second      
    #define     ALMMIN 		             __REG(0x57000058)  //Alarm minute      
    #define     ALMHOUR		             __REG(0x5700005C)  //Alarm hour        
    #define     ALMDATE		             __REG(0x57000060)  //alarm day         
    #define     ALMMON 		             __REG(0x57000064)  //Alarm month       
    #define     ALMYEAR		             __REG(0x57000068)  //Alarm year        
    #define     BCDSEC 		             __REG(0x57000070)  //BCD second        
    #define     BCDMIN 		             __REG(0x57000074)  //BCD minute        
    #define     BCDHOUR		             __REG(0x57000078)  //BCD hour          
    #define     BCDDATE		             __REG(0x5700007C)  //BCD day           
    #define     BCDDAY 		             __REG(0x57000080)  //BCD date          
    #define     BCDMON 		             __REG(0x57000084)  //BCD month         
    #define     BCDYEAR		             __REG(0x57000088)  //BCD year      
            
    /*A/D Converte*/
    #define     ADCCON                   __REG(0x58000000)  //ADC control                        
    #define     ADCTSC                   __REG(0x58000004)  //ADC touch screen control           
    #define     ADCDLY                   __REG(0x58000008)  //ADC start or interval delay        
    #define     ADCDAT0                  __REG(0x5800000C)  //ADC conversion data                
    #define     ADCDAT1                  __REG(0x58000010)  //ADC conversion data                
    #define     ADCUPDN                  __REG(0x58000014)  //Stylus up or down interrupt status 
    
    /*SPI CONTROL REGISTER*/ 
    #define     SPCON0                   __REG(0x59000000)  //SPI channel 0 control register
    #define     SPSTA0                   __REG(0x59000004)  //SPI channel 0 status register
    #define     SPPIN0                   __REG(0x59000008)  //SPI channel 0 pin control register
    #define     SPPRE0                   __REG(0x5900000C)  //SPI cannel 0 baud rate prescaler register
    #define     SPTDAT0                  __REG(0x59000010)  //SPI channel 0 Tx data register
    #define     SPRDAT0                  __REG(0x59000014)  //SPI channel 0 Rx data register
    #define     SPCON1                   __REG(0x59000020)  //SPI channel 1 control register                                     
    #define     SPSTA1                   __REG(0x59000024)  //SPI channel 1 status register                                     
    #define     SPPIN1                   __REG(0x59000028)  // SPI channel 1 pin control register
    #define     SPPRE1                   __REG(0x5900002C)  //SPI cannel 1 baud rate prescaler register
    #define     SPTDAT1                  __REG(0x59000030)  //SPI channel 1 Tx data register                                    
    #define     SPRDAT1                  __REG(0x59000034)  //SPI channel 1 Rx data register
    
    /*SD Interface*/
    #define     SDICON   		         __REG(0x5A000000)  //SDI control            
    #define     SDIPRE   		         __REG(0x5A000004)  //SDI baud rate prescaler
    #define     SDICARG  		         __REG(0x5A000008)  //SDI command argument   
    #define     SDICCON  		         __REG(0x5A00000C)  //SDI command control    
    #define     SDICSTA  		         __REG(0x5A000010)  //SDI command status     
    #define     SDIRSP0  		         __REG(0x5A000014)  //SDI response           
    #define     SDIRSP1  		         __REG(0x5A000018)  //SDI response           
    #define     SDIRSP2  		         __REG(0x5A00001C)  //SDI response           
    #define     SDIRSP3  		         __REG(0x5A000020)  //SDI response           
    #define     SDIDTIMER		         __REG(0x5A000024)  //SDI data / busy timer  
    #define     SDIBSIZE 		         __REG(0x5A000028)  //SDI block size         
    #define     SDIDCON  		         __REG(0x5A00002C)  //SDI data control       
    #define     SDIDCNT  		         __REG(0x5A000030)  //SDI data remain counter
    #define     SDIDSTA  		         __REG(0x5A000034)  //SDI data status        
    #define     SDIFSTA  		         __REG(0x5A000038)  //SDI FIFO status        
    #define     SDIIMSK  		         __REG(0x5A00003C)  //SDI interrupt mask     
    #define     SDIDAT   		         __REG(0x5A000040)  //SDI data               
    
    #endif
    

    2> start.S

    .text
    .global _start
    
    _start:
    
    	/* 关闭看门狗 */
    	ldr r0, =0x53000000
    	ldr r1, =0
    	str r1, [r0]
    
    	/* 设置内存: sp 栈 */
    	/* 分辨是nor/nand启动
    	 * 写0到0地址, 再读出来
    	 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
    	 * 否则就是nor启动
    	 */
    	mov r1, #0
    	ldr r0, [r1] /* 读出原来的值备份 */
    	str r1, [r1] /* 0->[0] */ 
    	ldr r2, [r1] /* r2=[0] */
    	cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
    	ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
    	moveq sp, #4096  /* nand启动 */
    	streq r0, [r1]   /* 恢复原来的值 */
    	
    
    	bl main
    
    halt:
    	b halt

    3> led.c

    
    #include "s3c2440_soc.h"
    
    void delay(volatile int d)
    {
    	while (d--);
    }
    
    int main(void)
    {
    	int val = 0;  /* val: 0b000, 0b111 */
    	int tmp;
    
    	/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
    	GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
    	GPFCON |=  ((1<<8) | (1<<10) | (1<<12));
    
    	/* 循环点亮 */
    	while (1)
    	{
    		tmp = ~val;
    		tmp &= 7;
    		GPFDAT &= ~(7<<4);
    		GPFDAT |= (tmp<<4);
    		delay(100000);
    		val++;
    		if (val == 8)
    			val =0;
    		
    	}
    
    	return 0;
    }
    

    4> Makefile

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

    5> led.dis

    
    led.elf:     file format elf32-littlearm
    
    Disassembly of section .text:
    
    00000000 <_start>:
       0:	e3a00453 	mov	r0, #1392508928	; 0x53000000
       4:	e3a01000 	mov	r1, #0	; 0x0
       8:	e5801000 	str	r1, [r0]
       c:	e3a01000 	mov	r1, #0	; 0x0
      10:	e5910000 	ldr	r0, [r1]
      14:	e5811000 	str	r1, [r1]
      18:	e5912000 	ldr	r2, [r1]
      1c:	e1510002 	cmp	r1, r2
      20:	e59fd00c 	ldr	sp, [pc, #12]	; 34 <.text+0x34>
      24:	03a0da01 	moveq	sp, #4096	; 0x1000
      28:	05810000 	streq	r0, [r1]
      2c:	eb00000e 	bl	6c <main>
    
    00000030 <halt>:
      30:	eafffffe 	b	30 <halt>
      34:	40001000 	andmi	r1, r0, r0
    
    00000038 <delay>:
      38:	e1a0c00d 	mov	ip, sp
      3c:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
      40:	e24cb004 	sub	fp, ip, #4	; 0x4
      44:	e24dd004 	sub	sp, sp, #4	; 0x4
      48:	e50b0010 	str	r0, [fp, #-16]
      4c:	e51b3010 	ldr	r3, [fp, #-16]
      50:	e2433001 	sub	r3, r3, #1	; 0x1
      54:	e50b3010 	str	r3, [fp, #-16]
      58:	e51b3010 	ldr	r3, [fp, #-16]
      5c:	e3730001 	cmn	r3, #1	; 0x1
      60:	0a000000 	beq	68 <delay+0x30>
      64:	eafffff8 	b	4c <delay+0x14>
      68:	e89da808 	ldmia	sp, {r3, fp, sp, pc}
    
    0000006c <main>:
      6c:	e1a0c00d 	mov	ip, sp
      70:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
      74:	e24cb004 	sub	fp, ip, #4	; 0x4
      78:	e24dd008 	sub	sp, sp, #8	; 0x8
      7c:	e3a03000 	mov	r3, #0	; 0x0
      80:	e50b3010 	str	r3, [fp, #-16]
      84:	e3a02456 	mov	r2, #1442840576	; 0x56000000
      88:	e2822050 	add	r2, r2, #80	; 0x50
      8c:	e3a03456 	mov	r3, #1442840576	; 0x56000000
      90:	e2833050 	add	r3, r3, #80	; 0x50
      94:	e5933000 	ldr	r3, [r3]
      98:	e3c33c3f 	bic	r3, r3, #16128	; 0x3f00
      9c:	e5823000 	str	r3, [r2]
      a0:	e3a02456 	mov	r2, #1442840576	; 0x56000000
      a4:	e2822050 	add	r2, r2, #80	; 0x50
      a8:	e3a03456 	mov	r3, #1442840576	; 0x56000000
      ac:	e2833050 	add	r3, r3, #80	; 0x50
      b0:	e5933000 	ldr	r3, [r3]
      b4:	e3833c15 	orr	r3, r3, #5376	; 0x1500
      b8:	e5823000 	str	r3, [r2]
      bc:	e51b3010 	ldr	r3, [fp, #-16]
      c0:	e1e03003 	mvn	r3, r3
      c4:	e50b3014 	str	r3, [fp, #-20]
      c8:	e51b3014 	ldr	r3, [fp, #-20]
      cc:	e2033007 	and	r3, r3, #7	; 0x7
      d0:	e50b3014 	str	r3, [fp, #-20]
      d4:	e3a02456 	mov	r2, #1442840576	; 0x56000000
      d8:	e2822054 	add	r2, r2, #84	; 0x54
      dc:	e3a03456 	mov	r3, #1442840576	; 0x56000000
      e0:	e2833054 	add	r3, r3, #84	; 0x54
      e4:	e5933000 	ldr	r3, [r3]
      e8:	e3c33070 	bic	r3, r3, #112	; 0x70
      ec:	e5823000 	str	r3, [r2]
      f0:	e3a01456 	mov	r1, #1442840576	; 0x56000000
      f4:	e2811054 	add	r1, r1, #84	; 0x54
      f8:	e3a03456 	mov	r3, #1442840576	; 0x56000000
      fc:	e2833054 	add	r3, r3, #84	; 0x54
     100:	e51b2014 	ldr	r2, [fp, #-20]
     104:	e1a02202 	mov	r2, r2, lsl #4
     108:	e5933000 	ldr	r3, [r3]
     10c:	e1833002 	orr	r3, r3, r2
     110:	e5813000 	str	r3, [r1]
     114:	e3a00b61 	mov	r0, #99328	; 0x18400
     118:	e2800e2a 	add	r0, r0, #672	; 0x2a0
     11c:	ebffffc5 	bl	38 <delay>
     120:	e51b3010 	ldr	r3, [fp, #-16]
     124:	e2833001 	add	r3, r3, #1	; 0x1
     128:	e50b3010 	str	r3, [fp, #-16]
     12c:	e51b3010 	ldr	r3, [fp, #-16]
     130:	e3530008 	cmp	r3, #8	; 0x8
     134:	1affffe0 	bne	bc <main+0x50>
     138:	e3a03000 	mov	r3, #0	; 0x0
     13c:	e50b3010 	str	r3, [fp, #-16]
     140:	eaffffdd 	b	bc <main+0x50>
    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.
    
    

    6> led.bin

    5304 a0e3 0010 a0e3 0010 80e5 0010 a0e3
    0000 91e5 0010 81e5 0020 91e5 0200 51e1
    0cd0 9fe5 01da a003 0000 8105 0e00 00eb
    feff ffea 0010 0040 0dc0 a0e1 00d8 2de9
    04b0 4ce2 04d0 4de2 1000 0be5 1030 1be5
    0130 43e2 1030 0be5 1030 1be5 0100 73e3
    0000 000a f8ff ffea 08a8 9de8 0dc0 a0e1
    00d8 2de9 04b0 4ce2 08d0 4de2 0030 a0e3
    1030 0be5 5624 a0e3 5020 82e2 5634 a0e3
    5030 83e2 0030 93e5 3f3c c3e3 0030 82e5
    5624 a0e3 5020 82e2 5634 a0e3 5030 83e2
    0030 93e5 153c 83e3 0030 82e5 1030 1be5
    0330 e0e1 1430 0be5 1430 1be5 0730 03e2
    1430 0be5 5624 a0e3 5420 82e2 5634 a0e3
    5430 83e2 0030 93e5 7030 c3e3 0030 82e5
    5614 a0e3 5410 81e2 5634 a0e3 5430 83e2
    1420 1be5 0222 a0e1 0030 93e5 0230 83e1
    0030 81e5 610b a0e3 2a0e 80e2 c5ff ffeb
    1030 1be5 0130 83e2 1030 0be5 1030 1be5
    0800 53e3 e0ff ff1a 0030 a0e3 1030 0be5
    ddff ffea 

    9. 按键点灯

    1>key_led.c

    
    #include "s3c2440_soc.h"
    
    void delay(volatile int d)
    {
    	while (d--);
    }
    
    int main(void)
    {
    	int val1, val2;
    	
    	/* 设置GPFCON让GPF4/5/6配置为输出引脚 */
    	GPFCON &= ~((3<<8) | (3<<10) | (3<<12));
    	GPFCON |=  ((1<<8) | (1<<10) | (1<<12));
    
    	/* 配置3个按键引脚为输入引脚:
    	 * GPF0(S2),GPF2(S3),GPG3(S4)
    	 */
    	GPFCON &= ~((3<<0) | (3<<4));  /* gpf0,2 */
    	GPGCON &= ~((3<<6));  /* gpg3 */
    
    	/* 循环点亮 */
    	while (1)
    	{
    		val1 = GPFDAT;
    		val2 = GPGDAT;
    
    		if (val1 & (1<<0)) /* s2 --> gpf6 */
    		{
    			/* 松开 */
    			GPFDAT |= (1<<6);
    		}
    		else
    		{
    			/* 按下 */
    			GPFDAT &= ~(1<<6);
    		}
    
    		if (val1 & (1<<2)) /* s3 --> gpf5 */
    		{
    			/* 松开 */
    			GPFDAT |= (1<<5);
    		}
    		else
    		{
    			/* 按下 */
    			GPFDAT &= ~(1<<5);
    		}
    
    		if (val2 & (1<<3)) /* s4 --> gpf4 */
    		{
    			/* 松开 */
    			GPFDAT |= (1<<4);
    		}
    		else
    		{
    			/* 按下 */
    			GPFDAT &= ~(1<<4);
    		}
    
    		
    	}
    
    	return 0;
    }

     

    展开全文
  • 嵌入式Linux开发教程(下册)讲述了内核模块与驱动,里面有LED GPIO IIC驱动范例
  • 嵌入式Linux开发 Day3

    2020-02-23 01:17:14
    本章的内容为《嵌入式Linux>【第二期】手把手教你学Linux之ARM(MX6U)裸机篇》中8.1、8.2讲的内容。 C语言版本LED开发实验 1、设置处理器工作模式 设置i.MX6ULL处在SVC模式下,即设置CPSR寄存器的bit4-0,即设置...

    本章的内容为《嵌入式Linux>【第二期】手把手教你学Linux之ARM(MX6U)裸机篇》中8.1、8.2讲的内容。

    C语言版本LED开发实验

    1、设置处理器工作模式

    设置i.MX6ULL处在SVC模式下,即设置CPSR寄存器的bit4-0,即设置为0x13。
    MRS指令和MSR指令:
    MRS R0, CPSR:将特殊寄存器如(CPSR和SPSR)中的数据复制给R0;
    MSR CPSR, R0:将R0中的数据复制到CPSR中。

    2、设置SP指针

    sp可以指向内部RAM,也可以指向DDR, 在本例中将其DDR,正点原子的开发板中的地址为0x80000000~0x9FFFFFFF的地址,sp指针的地址可以设置为以上地址中的任意一个地方,sp指针设置的堆栈的大小设置为0x200000=2MB。
    对于cortex A7而言,sp指针的增长方式为向下增长,即sp的初始地址应设置为高地址,因此,sp的指针初始地址设置为0x80200000。

    3、跳转到C语言的函数

    使用b指令,跳转到main函数。
    start.s文件如下:

    .global _start
    
    _start:
        //设置处理器进入SVC模式.
        mrs r0, cpsr        //读取cpsr到r0
        bic r0, r0, #0x1f   //清楚r0的低5位
        orr r0, r0, #0x13   //设置SVC模式
        msr cpsr, r0        //将r0写入到cpsr
    
        //设置sp指针
        ldr sp, =0x80200000
        b main              //跳转到main函数
        
    

    4、C语言程序实现

    main.h

    /**
    * Copyright @ JianshuZhao Co., Ltd. 2019-2049. All rights reserved.
    * Name:main.h
    * Description:学习Linux开发的实验程序
    * Function: 点亮LED相关寄存器地址定义,包括CCM, IOMUXC,GPIO1
    * Author:JianshuZhao
    * Version:V1.0.0
    * Date:2020.2.22
    */
    
    #ifndef __MAIN_H
    #define __MAIN_H
    
    
    //define the CCM clock gating register
    #define CCM_CCGR0 			*((volatile unsigned int *)0X020C4068)
    #define CCM_CCGR1 			*((volatile unsigned int *)0X020C406C)
    #define CCM_CCGR2 			*((volatile unsigned int *)0X020C4070)
    #define CCM_CCGR3 			*((volatile unsigned int *)0X020C4074)
    #define CCM_CCGR4 			*((volatile unsigned int *)0X020C4078)
    #define CCM_CCGR5 			*((volatile unsigned int *)0X020C407C)
    #define CCM_CCGR6 			*((volatile unsigned int *)0X020C4080)
    
    //define the IOMUXC config register
    #define SW_MUX_GPIO1_IO03 	*((volatile unsigned int *)0X020E0068)
    #define SW_PAD_GPIO1_IO03 	*((volatile unsigned int *)0X020E02F4)
    
    
    //define the GPIO config register
    #define GPIO1_DR 			*((volatile unsigned int *)0X0209C000)
    #define GPIO1_GDIR 			*((volatile unsigned int *)0X0209C004)
    #define GPIO1_PSR 			*((volatile unsigned int *)0X0209C008)
    #define GPIO1_ICR1 			*((volatile unsigned int *)0X0209C00C)
    #define GPIO1_ICR2 			*((volatile unsigned int *)0X0209C010)
    #define GPIO1_IMR 			*((volatile unsigned int *)0X0209C014)
    #define GPIO1_ISR 			*((volatile unsigned int *)0X0209C018)
    #define GPIO1_EDGE_SEL 		*((volatile unsigned int *)0X0209C01C)
    
    #endif
    

    main.c

    /**
    * Copyright @ JianshuZhao Co., Ltd. 2019-2049. All rights reserved.
    * Name:main.c
    * Description:学习Linux开发的实验程序
    * Function: 实现点亮LED.
    * Author:JianshuZhao
    * Version:V1.0.0
    * Date:2020.2.22
    */
    #include "main.h"
    void enable_clk(void)
    {
        CCM_CCGR0 = 0xFFFFFFFF;
        CCM_CCGR1 = 0xFFFFFFFF;
        CCM_CCGR2 = 0xFFFFFFFF;
        CCM_CCGR3 = 0xFFFFFFFF;
        CCM_CCGR4 = 0xFFFFFFFF;
        CCM_CCGR5 = 0xFFFFFFFF;
        CCM_CCGR6 = 0xFFFFFFFF;
    }
    
    void init_led(void)
    {
        SW_MUX_GPIO1_IO03 = 0x5;     //config as GPIO1_IO03
        SW_PAD_GPIO1_IO03 = 0x10B0;  //config GPIO1_IO03 parameter
    }
    
    void Open_led(void)
    {
        GPIO1_GDIR = 0x8;       //config to output
        GPIO1_DR &= ~(1<<3);         //Set GPIO1_IO03 to High
    }
    
    void Close_led(void)
    {
        GPIO1_GDIR = 0x8;       //config to output
        GPIO1_DR |= (1<<3);         //Set GPIO1_IO03 to High
    }
    
    void delay_short(volatile unsigned int n)
    {
        while(n--){}
    }
    
    void delay_1ms(volatile unsigned int n)
    {
        while(n--)
        {
            delay_short(0x7FF); //F = 396MHz
        }
    }
    int main(void)
    {
        //initialize clock and iomuxc
        enable_clk();
    
        //tinwkle the led
        init_led();
        while(1)
        {
            Open_led();
            delay_1ms(1000);
            Close_led();
            delay_1ms(1000);
        }
    
        return 0;
    }
    

    makefile 文件

    objs = start.o main.o 
    
    ledc.bin:	$(objs)
    	arm-linux-gnueabihf-ld -Ttext 0x87800000 $^ -o ledc.elf
    	arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
    	arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis
    
    %.o: %.s
    	arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
    
    %.o: %.c
    	arm-linux-gnueabihf-gcc -Wall -nostdlib -c -o $@ $<
    
    
    
    clean:
    	rm -rf *.o ledc.bin ledc.elf ledc.dis
    
    

    5、链接脚本文件

    主要目的为链接.o文件至.elf文件中,指定某一个文件应该放到哪一段指定区域中,最终形成可执行文件。一般编译出来的文件包括text, data, bss, rodata四个段内。
    具体脚本文件如下:

    SECTIONS{
        . = 0x87800000;
        .text :
        {
            start.o
            *(.text)
        }
        .rodata ALIGN(4) : { *(.rodata*) }
        .data ALIGN(4) :{ *(.data) }
        __bss_start =.;
        .bss ALIGN(4) : { *(.bss) *(COMMMON) }
        __bss_end =.;
    }
    

    附上最终输出的汇编文件:

    
    ledc.elf:     file format elf32-littlearm
    
    
    Disassembly of section .text:
    
    87800000 <_start>:
    87800000:	e10f0000 	mrs	r0, CPSR
    87800004:	e3c0001f 	bic	r0, r0, #31
    87800008:	e3800013 	orr	r0, r0, #19
    8780000c:	e129f000 	msr	CPSR_fc, r0
    87800010:	e51fd000 	ldr	sp, [pc, #-0]	; 87800018 <_start+0x18>
    87800014:	ea000041 	b	87800120 <__main_from_arm>
    87800018:	80200000 	eorhi	r0, r0, r0
    8780001c:	00001e41 	andeq	r1, r0, r1, asr #28
    87800020:	61656100 	cmnvs	r5, r0, lsl #2
    87800024:	01006962 	tsteq	r0, r2, ror #18
    87800028:	00000014 	andeq	r0, r0, r4, lsl r0
    8780002c:	412d3705 	teqmi	sp, r5, lsl #14
    87800030:	070a0600 	streq	r0, [sl, -r0, lsl #12]
    87800034:	09010841 	stmdbeq	r1, {r0, r6, fp}
    87800038:	00040a02 	andeq	r0, r4, r2, lsl #20
    
    8780003c <enable_clk>:
    8780003c:	b4f0      	push	{r4, r5, r6, r7}
    8780003e:	f244 0078 	movw	r0, #16504	; 0x4078
    87800042:	f244 0768 	movw	r7, #16488	; 0x4068
    87800046:	f244 066c 	movw	r6, #16492	; 0x406c
    8780004a:	f244 0570 	movw	r5, #16496	; 0x4070
    8780004e:	f244 0474 	movw	r4, #16500	; 0x4074
    87800052:	f244 017c 	movw	r1, #16508	; 0x407c
    87800056:	f44f 4281 	mov.w	r2, #16512	; 0x4080
    8780005a:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
    8780005e:	f2c0 270c 	movt	r7, #524	; 0x20c
    87800062:	f2c0 260c 	movt	r6, #524	; 0x20c
    87800066:	f2c0 250c 	movt	r5, #524	; 0x20c
    8780006a:	f2c0 240c 	movt	r4, #524	; 0x20c
    8780006e:	f2c0 200c 	movt	r0, #524	; 0x20c
    87800072:	f2c0 210c 	movt	r1, #524	; 0x20c
    87800076:	f2c0 220c 	movt	r2, #524	; 0x20c
    8780007a:	603b      	str	r3, [r7, #0]
    8780007c:	6033      	str	r3, [r6, #0]
    8780007e:	602b      	str	r3, [r5, #0]
    87800080:	6023      	str	r3, [r4, #0]
    87800082:	6003      	str	r3, [r0, #0]
    87800084:	bcf0      	pop	{r4, r5, r6, r7}
    87800086:	600b      	str	r3, [r1, #0]
    87800088:	6013      	str	r3, [r2, #0]
    8780008a:	4770      	bx	lr
    
    8780008c <init_led>:
    8780008c:	2268      	movs	r2, #104	; 0x68
    8780008e:	f44f 733d 	mov.w	r3, #756	; 0x2f4
    87800092:	f2c0 220e 	movt	r2, #526	; 0x20e
    87800096:	2005      	movs	r0, #5
    87800098:	f2c0 230e 	movt	r3, #526	; 0x20e
    8780009c:	f241 01b0 	movw	r1, #4272	; 0x10b0
    878000a0:	6010      	str	r0, [r2, #0]
    878000a2:	6019      	str	r1, [r3, #0]
    878000a4:	4770      	bx	lr
    878000a6:	bf00      	nop
    
    878000a8 <Open_led>:
    878000a8:	f24c 0204 	movw	r2, #49156	; 0xc004
    878000ac:	f44f 4340 	mov.w	r3, #49152	; 0xc000
    878000b0:	f2c0 2209 	movt	r2, #521	; 0x209
    878000b4:	f2c0 2309 	movt	r3, #521	; 0x209
    878000b8:	2108      	movs	r1, #8
    878000ba:	6011      	str	r1, [r2, #0]
    878000bc:	681a      	ldr	r2, [r3, #0]
    878000be:	f022 0208 	bic.w	r2, r2, #8
    878000c2:	601a      	str	r2, [r3, #0]
    878000c4:	4770      	bx	lr
    878000c6:	bf00      	nop
    
    878000c8 <Close_led>:
    878000c8:	f24c 0204 	movw	r2, #49156	; 0xc004
    878000cc:	f44f 4340 	mov.w	r3, #49152	; 0xc000
    878000d0:	f2c0 2209 	movt	r2, #521	; 0x209
    878000d4:	2108      	movs	r1, #8
    878000d6:	f2c0 2309 	movt	r3, #521	; 0x209
    878000da:	6011      	str	r1, [r2, #0]
    878000dc:	681a      	ldr	r2, [r3, #0]
    878000de:	430a      	orrs	r2, r1
    878000e0:	601a      	str	r2, [r3, #0]
    878000e2:	4770      	bx	lr
    
    878000e4 <delay_short>:
    878000e4:	b082      	sub	sp, #8
    878000e6:	9001      	str	r0, [sp, #4]
    878000e8:	9b01      	ldr	r3, [sp, #4]
    878000ea:	1e5a      	subs	r2, r3, #1
    878000ec:	9201      	str	r2, [sp, #4]
    878000ee:	2b00      	cmp	r3, #0
    878000f0:	d1fa      	bne.n	878000e8 <delay_short+0x4>
    878000f2:	b002      	add	sp, #8
    878000f4:	4770      	bx	lr
    878000f6:	bf00      	nop
    
    878000f8 <delay_1ms>:
    878000f8:	b082      	sub	sp, #8
    878000fa:	9001      	str	r0, [sp, #4]
    878000fc:	9b01      	ldr	r3, [sp, #4]
    878000fe:	1e5a      	subs	r2, r3, #1
    87800100:	9201      	str	r2, [sp, #4]
    87800102:	b153      	cbz	r3, 8780011a <delay_1ms+0x22>
    87800104:	f240 73ff 	movw	r3, #2047	; 0x7ff
    87800108:	461a      	mov	r2, r3
    8780010a:	3b01      	subs	r3, #1
    8780010c:	2a00      	cmp	r2, #0
    8780010e:	d1fb      	bne.n	87800108 <delay_1ms+0x10>
    87800110:	9b01      	ldr	r3, [sp, #4]
    87800112:	1e5a      	subs	r2, r3, #1
    87800114:	9201      	str	r2, [sp, #4]
    87800116:	2b00      	cmp	r3, #0
    87800118:	d1f4      	bne.n	87800104 <delay_1ms+0xc>
    8780011a:	b002      	add	sp, #8
    8780011c:	4770      	bx	lr
    8780011e:	bf00      	nop
    
    87800120 <__main_from_arm>:
    87800120:	e51ff004 	ldr	pc, [pc, #-4]	; 87800124 <__main_from_arm+0x4>
    87800124:	87800129 	strhi	r0, [r0, r9, lsr #2]
    
    Disassembly of section .text.startup:
    
    87800128 <main>:
    87800128:	f244 0268 	movw	r2, #16488	; 0x4068
    8780012c:	f244 066c 	movw	r6, #16492	; 0x406c
    87800130:	b480      	push	{r7}
    87800132:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
    87800136:	f2c0 220c 	movt	r2, #524	; 0x20c
    8780013a:	f2c0 260c 	movt	r6, #524	; 0x20c
    8780013e:	f244 0770 	movw	r7, #16496	; 0x4070
    87800142:	f244 0174 	movw	r1, #16500	; 0x4074
    87800146:	6013      	str	r3, [r2, #0]
    87800148:	f2c0 270c 	movt	r7, #524	; 0x20c
    8780014c:	6033      	str	r3, [r6, #0]
    8780014e:	f244 0278 	movw	r2, #16504	; 0x4078
    87800152:	f244 067c 	movw	r6, #16508	; 0x407c
    87800156:	603b      	str	r3, [r7, #0]
    87800158:	f2c0 210c 	movt	r1, #524	; 0x20c
    8780015c:	f2c0 220c 	movt	r2, #524	; 0x20c
    87800160:	f2c0 260c 	movt	r6, #524	; 0x20c
    87800164:	f24c 0404 	movw	r4, #49156	; 0xc004
    87800168:	2508      	movs	r5, #8
    8780016a:	f44f 4040 	mov.w	r0, #49152	; 0xc000
    8780016e:	f44f 4781 	mov.w	r7, #16512	; 0x4080
    87800172:	600b      	str	r3, [r1, #0]
    87800174:	f2c0 270c 	movt	r7, #524	; 0x20c
    87800178:	6013      	str	r3, [r2, #0]
    8780017a:	2168      	movs	r1, #104	; 0x68
    8780017c:	6033      	str	r3, [r6, #0]
    8780017e:	f44f 723d 	mov.w	r2, #756	; 0x2f4
    87800182:	f2c0 2409 	movt	r4, #521	; 0x209
    87800186:	f2c0 2009 	movt	r0, #521	; 0x209
    8780018a:	462e      	mov	r6, r5
    8780018c:	603b      	str	r3, [r7, #0]
    8780018e:	f2c0 210e 	movt	r1, #526	; 0x20e
    87800192:	f2c0 220e 	movt	r2, #526	; 0x20e
    87800196:	2705      	movs	r7, #5
    87800198:	f241 03b0 	movw	r3, #4272	; 0x10b0
    8780019c:	600f      	str	r7, [r1, #0]
    8780019e:	6013      	str	r3, [r2, #0]
    878001a0:	6026      	str	r6, [r4, #0]
    878001a2:	f44f 717a 	mov.w	r1, #1000	; 0x3e8
    878001a6:	6803      	ldr	r3, [r0, #0]
    878001a8:	f023 0308 	bic.w	r3, r3, #8
    878001ac:	6003      	str	r3, [r0, #0]
    878001ae:	460b      	mov	r3, r1
    878001b0:	3901      	subs	r1, #1
    878001b2:	b14b      	cbz	r3, 878001c8 <main+0xa0>
    878001b4:	f240 73ff 	movw	r3, #2047	; 0x7ff
    878001b8:	461a      	mov	r2, r3
    878001ba:	3b01      	subs	r3, #1
    878001bc:	2a00      	cmp	r2, #0
    878001be:	d1fb      	bne.n	878001b8 <main+0x90>
    878001c0:	460b      	mov	r3, r1
    878001c2:	3901      	subs	r1, #1
    878001c4:	2b00      	cmp	r3, #0
    878001c6:	d1f5      	bne.n	878001b4 <main+0x8c>
    878001c8:	6025      	str	r5, [r4, #0]
    878001ca:	f44f 717a 	mov.w	r1, #1000	; 0x3e8
    878001ce:	6803      	ldr	r3, [r0, #0]
    878001d0:	f043 0308 	orr.w	r3, r3, #8
    878001d4:	6003      	str	r3, [r0, #0]
    878001d6:	460b      	mov	r3, r1
    878001d8:	3901      	subs	r1, #1
    878001da:	2b00      	cmp	r3, #0
    878001dc:	d0e0      	beq.n	878001a0 <main+0x78>
    878001de:	f240 73ff 	movw	r3, #2047	; 0x7ff
    878001e2:	461a      	mov	r2, r3
    878001e4:	3b01      	subs	r3, #1
    878001e6:	2a00      	cmp	r2, #0
    878001e8:	d1fb      	bne.n	878001e2 <main+0xba>
    878001ea:	e7f4      	b.n	878001d6 <main+0xae>
    
    Disassembly of section .comment:
    
    00000000 <.comment>:
       0:	3a434347 	bcc	10d0d24 <_start-0x8672f2dc>
       4:	694c2820 	stmdbvs	ip, {r5, fp, sp}^
       8:	6f72616e 	svcvs	0x0072616e
       c:	43434720 	movtmi	r4, #14112	; 0x3720
      10:	392e3420 	stmdbcc	lr!, {r5, sl, ip, sp}
      14:	3130322d 	teqcc	r0, sp, lsr #4
      18:	31302e37 	teqcc	r0, r7, lsr lr
      1c:	2e342029 	cdpcs	0, 3, cr2, cr4, cr9, {1}
      20:	00342e39 	eorseq	r2, r4, r9, lsr lr
    
    Disassembly of section .ARM.attributes:
    
    00000000 <.ARM.attributes>:
       0:	00003041 	andeq	r3, r0, r1, asr #32
       4:	61656100 	cmnvs	r5, r0, lsl #2
       8:	01006962 	tsteq	r0, r2, ror #18
       c:	00000026 	andeq	r0, r0, r6, lsr #32
      10:	412d3705 	teqmi	sp, r5, lsl #14
      14:	070a0600 	streq	r0, [sl, -r0, lsl #12]
      18:	09010841 	stmdbeq	r1, {r0, r6, fp}
      1c:	12040a02 	andne	r0, r4, #8192	; 0x2000
      20:	15011404 	strne	r1, [r1, #-1028]	; 0x404
      24:	18031701 	stmdane	r3, {r0, r8, r9, sl, ip}
      28:	1b021a01 	blne	86834 <_start-0x877797cc>
      2c:	22011c03 	andcs	r1, r1, #768	; 0x300
      30:	Address 0x0000000000000030 is out of bounds.
    
    
    
    展开全文
  • 41.1 LinuxLED 灯驱动原理 Linux 下的任何外设驱动,最终都是要配置相应的硬件寄存器。所以本章的 LED 灯驱动最 终也是对 I.MX6ULL 的 IO 口进行配置,与裸机实验不同的是,在 Linux 下编写驱动要符合 Linux 的...

    41.1 Linux 下 LED 灯驱动原理

    Linux 下的任何外设驱动,最终都是要配置相应的硬件寄存器。所以本章的 LED 灯驱动最
    终也是对 I.MX6ULL 的 IO 口进行配置,与裸机实验不同的是,在 Linux 下编写驱动要符合 Linux
    的驱动框架。
    41.1.1 地址映射
    在编写驱动之前,我们需要先简单了解一下 MMU 这个神器, MMU 全称叫做 Memory
    Manage Unit,也就是内存管理单元。在老版本的 Linux 中要求处理器必须有 MMU,但是现在
    Linux 内核已经支持无 MMU 的处理器了。 MMU 主要完成的功能如下:
    ①、完成虚拟空间到物理空间的映射。
    ②、内存保护,设置存储器的访问权限,设置虚拟存储空间的缓冲特性。
    我们重点来看一下第①点,也就是虚拟空间到物理空间的映射,也叫做地址映射。首先了
    解两个地址概念:虚拟地址(VA,Virtual Address)、物理地址(PA, Physcical Address)。对于 32 位
    的处理器来说,虚拟地址范围是 2^32=4GB,我们的开发板上有 512MB 的 DDR3,这 512MB 的
    内存就是物理内存,经过 MMU 可以将其映射到整个 4GB 的虚拟空间。
    物理内存只有 512MB,虚拟内存有 4GB,那么肯定存在多个虚拟地址映射到同一个物理地
    址上去,虚拟地址范围比物理地址范围大的问题处理器自会处理,这里我们不要去深究,因为
    MMU 是很复杂的一个东西。
    Linux 内核启动的时候会初始化 MMU,设置好内存映射,设置好以后 CPU 访问的都是虚
    拟 地 址 。 比 如 I.MX6ULL 的 GPIO1_IO03 引 脚 的 复 用 寄 存 器
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的地址为 0X020E0068。如果没有开启 MMU 的话
    直接向 0X020E0068 这个寄存器地址写入数据就可以配置 GPIO1_IO03 的复用功能。现在开启
    了 MMU,并且设置了内存映射,因此就不能直接向 0X020E0068 这个地址写入数据了。我们必
    须得到 0X020E0068 这个物理地址在 Linux 系统里面对应的虚拟地址,这里就涉及到了物理内
    存和虚拟内存之间的转换,需要用到两个函数: ioremap 和 iounmap。
    1、 ioremap 函数
    ioremap 函 数 用 于 获 取 指 定 物 理 地 址 空 间 对 应 的 虚 拟 地 址 空 间 , 定 义 在
    arch/arm/include/asm/io.h 文件中,定义如下:
    示例代码 41.1.1.1 ioremap 函数
    1 #define ioremap(cookie,size) __arm_ioremap((cookie), (size),MT_DEVICE)
    2 void __iomem * __arm_ioremap(phys_addr_t phys_addr, size_t size,unsigned int mtype)
    4 {
        5 return arch_ioremap_caller(phys_addr, size, mtype,__builtin_return_address(0));
    6 }
    ioremap 是个宏,有两个参数: cookie 和 size,真正起作用的是函数__arm_ioremap,此函
    数有三个参数和一个返回值,这些参数和返回值的含义如下:
    phys_addr:要映射给的物理起始地址。
    size:要映射的内存空间大小。
    mtype: ioremap 的类型,可以选择 MT_DEVICE、 MT_DEVICE_NONSHARED、
    MT_DEVICE_CACHED 和 MT_DEVICE_WC, ioremap 函数选择 MT_DEVICE。
    返回值: __iomem 类型的指针,指向映射后的虚拟空间首地址。
    假如我们要获取 I.MX6ULL 的 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 寄存器对应
    的虚拟地址,使用如下代码即可:
    #define SW_MUX_GPIO1_IO03_BASE (0X020E0068)
    static void __iomem* SW_MUX_GPIO1_IO03;
    SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4);
    宏 SW_MUX_GPIO1_IO03_BASE 是寄存器物理地址, SW_MUX_GPIO1_IO03 是映射后
    的虚拟地址。对于 I.MX6ULL 来说一个寄存器是 4 字节(32)的,因此映射的内存长度为 4。
    映射完成以后直接对 SW_MUX_GPIO1_IO03 进行读写操作即可。
    
    2、 iounmap 函数
    卸载驱动的时候需要使用 iounmap 函数释放掉 ioremap 函数所做的映射, iounmap 函数原
    型如下:
    示例代码 41.1.1.2 iounmap 函数原型
    void iounmap (volatile void __iomem *addr)
    iounmap 只有一个参数 addr,此参数就是要取消映射的虚拟地址空间首地址。假如我们现
    在要取消掉 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 寄存器的地址映射,使用如下代码
    即可:
    iounmap(SW_MUX_GPIO1_IO03);
    
    41.1.2 I/O 内存访问函数
    这里说的 I/O 是输入/输出的意思,并不是我们学习单片机的时候讲的 GPIO 引脚。这里涉
    及到两个概念: I/O 端口和 I/O 内存。当外部寄存器或内存映射到 IO 空间时,称为 I/O 端口。
    当外部寄存器或内存映射到内存空间时,称为 I/O 内存。但是对于 ARM 来说没有 I/O 空间这个
    概念,因此 ARM 体系下只有 I/O 内存(可以直接理解为内存)。使用 ioremap 函数将寄存器的物
    理地址映射到虚拟地址以后,我们就可以直接通过指针访问这些地址,但是 Linux 内核不建议
    这么做,而是推荐使用一组操作函数来对映射后的内存进行读写操作。
    1、读操作函数
    读操作函数有如下几个:
    示例代码 41.1.2.1 读操作函数
    1 u8 readb(const volatile void __iomem *addr)
    2 u16 readw(const volatile void __iomem *addr)
    3 u32 readl(const volatile void __iomem *addr)
    readb、 readw 和 readl 这三个函数分别对应 8bit、 16bit 和 32bit 读操作,参数 addr 就是要
    读取写内存地址,返回值就是读取到的数据。
    2、写操作函数
    写操作函数有如下几个:
    示例代码 41.1.2.2 写操作函数
    1 void writeb(u8 value, volatile void __iomem *addr)
    2 void writew(u16 value, volatile void __iomem *addr)
    3 void writel(u32 value, volatile void __iomem *addr)
    writeb、 writew 和 writel 这三个函数分别对应 8bit、 16bit 和 32bit 写操作,参数 value 是要
    写入的数值, addr 是要写入的地址。
    

    41.3 实验程序编写

    本实验对应的例程路径为: 开发板光盘-> 2、 Linux 驱动例程-> 2_led。
    示例代码 41.3.1.1 led.c 驱动文件代码
    第 94~114 行, led_write 函数,实现对 LED 灯的开关操作,当应用程序调用 write 函数向
    led 设备写数据的时候此函数就会执行。首先通过函数 copy_from_user 获取应用程序发送过来
    的操作信息(打开还是关闭 LED),最后根据应用程序的操作信息来打开或关闭 LED 灯。
    第 140~185 行,驱动入口函数 led_init,此函数实现了 LED 的初始化工作, 147~151 行通过
    ioremap 函数获取物理寄存器地址映射后的虚拟地址,得到寄存器对应的虚拟地址以后就可以
    完成相关初始化工作了。比如是能 GPIO1 时钟、设置 GPIO1_IO03 复用功能、配置 GPIO1_IO03
    的属性等等。最后,最重要的一步!使用 register_chrdev 函数注册 led 这个字符设备。
    第 192~202 行,驱动出口函数 led_exit,首先使用函数 iounmap 取消内存映射,最后使用函
    数 unregister_chrdev 注销 led 这个字符设备。
    第 205~206 行,使用 module_init 和 module_exit 这两个函数指定 led 设备驱动加载和卸载
    函数。
    第 207~208 行,添加 LICENSE 和作者信息。
    
    41.3.2 编写测试 APP
    编写测试 APP, led 驱动加载成功以后手动创建/dev/led 节点,应用 APP 通过操作/dev/led
    文件来完成对 LED 设备的控制。向/dev/led 文件写 0 表示关闭 LED 灯,写 1 表示打开 LED 灯。
    新建 ledApp.c 文件
    

    41.4 运行测试

    41.4.1 编译驱动程序和测试 APP
    1、编译驱动程序
    编写 Makefile 文件,本章实验的 Makefile 文件和第四十章实验基本一样,只是将 obj-m 变
    量的值改为 led.o
    输入如下命令编译出驱动模块文件:
    make -j32
    编译成功以后就会生成一个名为“ led.ko”的驱动模块文件。
    2、编译测试 APP
    输入如下命令编译测试 ledApp.c 这个测试程序:
    arm-linux-gnueabihf-gcc ledApp.c -o ledApp
    
    41.4.2 运行测试
    将上一小节编译出来的 led.ko和 ledApp这两个文件拷贝到 rootfs/lib/modules/4.1.15 目录中,
    重启开发板,进入到目录 lib/modules/4.1.15 中,输入如下命令加载 led.ko 驱动模块:
    depmod //第一次加载驱动的时候需要运行此命令
    modprobe led.ko //加载驱动
    驱动加载成功以后创建“ /dev/led”设备节点,命令如下:
    mknod /dev/led c 200 0
    驱动节点创建成功以后就可以使用 ledApp 软件来测试驱动是否工作正常,输入如下命令打
    开 LED 灯:
    ./ledApp /dev/led 1 //打开 LED 灯
    在输入如下命令关闭 LED 灯:
    ./ledApp /dev/led 0 //关闭 LED 灯
    如果要卸载驱动的话输入如下命令即可:
    rmmod led.ko
    

    参考文献

    【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.3.pdf

    展开全文
  • 个人深刻觉得像这种嵌入式开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门。 不能再扯了,涉及到linux的驱动开发知识面灰常广,再...

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的。个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的住,不然真像一些人说的,学了一年嵌入式感觉还没找到门。

    不能再扯了,涉及到linux的驱动开发知识面灰常广,再扯文章就会变得灰常长。首先还是回到led驱动的本身上,自从linux被移植到arm上后,做驱动开发的硬件知识要求有所降低,很多都回归到了软件上,这是系统编程的一大特点,当然 ,也不排除有很多设备的驱动需要我们从头做起。

    led的驱动虽然看似很简单,但是要描述清楚估计上万字都不一定够用,本篇文章从初学者的角度出发,重点关注在整个软件的开发的流程和思想,而不过多局限与细节的分析,初学者应该首先把握某一类编程的流程和思想,这样才能入门快,进步迅速。作为一个初学者我一直觉得这样入门效率最高。

    下面我们进入主题led驱动的书写:

    既然是在linux系统下设备驱动开发,就不同于以往我们单片机下设置一个高电平而了事,在linux系统下开发的驱动程序要想在linux正常工作,一定要符合linux系统的规范,linux下设备被分为三个类型字符设备/块设备/网络设备。上述的三种设备不可能面面俱到,因此还提出了一个杂设备作为补充,看了下网上大部分人都把led的驱动设备归到了杂设备,这是为什么呢?原来是友善之臂的手册上把它归为了杂设备,哈哈,所以杂设备这种版本比较流行,木有追求的人们啊! 那我们把它归为那种设备呢?当然是杂设备了,嘿嘿。。。。。。

    既然对led我们准备把它作为一个杂设备加入系统,是不是应该有一个名字吧,还应该有个操作符号吧。。。。。。

    stop,停止你的YY,关于这个设备的标准形式大神已经帮你定义好了,具体它存在于系统的include下,里面有一个miscdivice.h。

     

    struct miscdevice  {
            int minor;
            const char *name;
            const struct file_operations *fops;
            struct list_head list;
            struct device *parent;
            struct device *this_device;
            const char *nodename;
            mode_t mode;
    };

    好吧,原来为了统一规范,我们只需按照标准来填充内容就可以啦!要想正确的使用这个描述设备的结构体,必须清楚的了解到其中的每个成员。天空飘来四个字 f u c k

    好,让我们平复一下心情,继续了解它。查了下minor这个单词是次要的,在这里是次设备号的意思。这是因为杂设备为了节约主设备号,采用共用主设备号的方式,次设备号加以区分的方式来描述设备,因此来看这个minor是要必须填写啦!不愧是过了四级的人,第二个直接看懂啦!欧耶~

    之前做过一个了解,这第三个在linux驱动中非常的重要,可以称之为核心,我们很大的工作 都要围绕这个file_operations来操作,因此必须要隆重的研究下这个file_operatios这个结构体。

    file_operations这个结构体的存在是linux中将所有设备看做文件的基础,这是为什么呢?因为通俗的说就是这个结构体是文件操作和驱动操作的一个关系映射,对于系统的操作函数(诸如read/write)在这个结构体里都有与之对应的对硬件进行操作的函数。wow这个函数居然如此之酷!这样以来,我们还弄清楚了另外一个问题,就是为什么我们不能直接越过操作系统来操作硬件,都是因为有它啊!可见这个结构体在内核中的地位,以及在linux操作系统中的地位。哈哈下面的几个成员,就先不分析啦!我们这次也用不上,感觉在linux下开发驱动真是个力气活啊!

    见过file_operations的厉害之后,我们自然知道 现在只要把这个结构体弄清楚就可以敲代码写驱动啦!so,let‘s go!

    首先在系统目录include/linux/fs.h中找到这个牛逼的结构体:

    struct file_operations {
             struct module *owner;
             loff_t (*llseek) (struct file *, loff_t, int);
             ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
              ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
             ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
             ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
             int (*readdir) (struct file *, void *, filldir_t);
             unsigned int (*poll) (struct file *, struct poll_table_struct *);
             int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
             long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
             long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
             int (*mmap) (struct file *, struct vm_area_struct *);
             int (*open) (struct inode *, struct file *);
             int (*flush) (struct file *, fl_owner_t id);
             int (*release) (struct inode *, struct file *);
             int (*fsync) (struct file *, struct dentry *, int datasync);
             int (*aio_fsync) (struct kiocb *, int datasync);
             int (*fasync) (int, struct file *, int);
             int (*lock) (struct file *, int, struct file_lock *);
             ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
             unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
              int (*check_flags)(int);
             int (*flock) (struct file *, int, struct file_lock *);
             ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
             ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
             int (*setlease)(struct file *, long, struct file_lock **);
     };

    复制代码

     

     

    当我知道有这么多成员的时候,当时我就尿了,不过,还好我们只需要实现本次驱动需要的东东!查看了一下手册上的驱动,欧耶~这次我们只需要研究两个成员ower和ioctl。上面可以看出ower是一个结构体成员就是是那个模块,而ioctl是个函数。

    那为什么是ioctl函数呢?这个问题弄清楚灰常重要!因为我们前边说过file_operations内的函数是对文件操作的的映射,我们要控制led,实质是控制IO口的电平,这点不管它操作系统的驱动还是单片机的驱动实质都是一样的啦!此时,我瞬间明白鸟,icctl不就是IO Control的缩写吗?不就是文件的控制IO吗?因为我们要控制led,所以需要控制IO口,要控制IO对应的系统调用函数不就是ioctl吗?我们在驱动中需要做的就是给这个ioctl函数进行编写,然后系统就可以通过调用ioctl这个系统函数来通过file_operactions来关联到真正的驱动函数。欧耶 ~      终于都清楚啦!

    现在,软件方面的核心都打通啦!既然是驱动,当然少不了硬件啦!

    这四个led与固定的四个IO口连接,像这样的东西开发板原理图上是交代的很清楚的,我们必须按照开发板上的关系来进行。这四个led占用的IO寄存器分别为GPB5/GPB6/GPB7/GPB8;这就 好比当年我们单片机的P0/P1一样一样的,P0/P1都被定义在了reg51.h里面,而这里的IO口同样也被定义到了<arch/regs-gpio.h>里,这里我们声明这四个IO口寄存器,这样我们操作IO口就可以控制led了。

     

     

     static unsigned long led_table []= {
             S3C2410_GPB(5),
             S3C2410_GPB(6),
             S3C2410_GPB(7),
             S3C2410_GPB(8),
    };

     

     

     

    这里需要注意的是与led连接的GPIO口可以用于输入/输出或者其他功能,我们的开发板上led接的是共阳极的,所以我们需要这些GPIO口作为输出口,只要我们输出低电平就可以让led亮了。既然这个IO口有多种功能,那一定有相关的配置寄存器 。所以我们需要将每个led对应的寄存器定义为输出。

     

     

     static unsigned int led_cfg_table  []={
             S3C2410_GPIO_OUTPUT,
             S3C2410_GPIO_OUTPUT,
             S3C2410_GPIO_OUTPUT,
             S3C2410_GPIO_OUTPUT,
     };

     

     

    做好了前面的所有工作,现在就是驱动的核心了。如何控制 ?这的确是一个question?这时忽然想起了,前面分析的file_operations,这个玩意不就是系统和驱动的纽带吗?控制led系统需要ioctl函数,所以在flie_operations中我们也需要一个和驱动直接联系的ioctl函数,那么我们命名这个函数为heatnan_leds_ioctl;函数的原型前面file_operaction 中已经给出了,有种直接领表填单的赶脚!而且下面的开发思路也都清晰起来,那就是需要什么样的功能直接参考file_operactions结构体的参数模型就是了。

    针对于led的驱动,要实现应用程序控制led的亮灭——>需要系统调用ioctl函数——>要使系统的ioctl函数能够控制硬件——>需要在file_operations中建立一个真正控制led驱动的函数——>新建控制led的函数(这里命名为heatnan_leds_ioctl).

    首先我们建立连接关系:
     

     static struct file_operations dev_fops={
            .owner = THIS_MODULE,
            .ioctl= heatnan_leds_ioctl,
    };

     

    建立这个核心纽带后,就要书写heatnan_leds_ioctl这个函数啦!

    要书写这个函数必须要对这个函数的两种形式有所了解,即需要对ioctl函数做功课,ioctl在系统函数中有三个参数,第三个参数可选,第一个参数代表操作设备的号,第二个参数代表操作命令,第三个可选参数可以以不同数据类型作为参数传递也不是必须的。

    与之在file_operactions中对应的ioctl则多了一个参数,它的前两个参数对应系统函数的第一个参数,控制命令则进行原封不动的接收。

     

     

     static int heatnan_leds_ioctl(
              struct inode *inode,
             struct file *file,
             unsigned int cmd,
             unsigned long arg)
     {
            if(arg<0||arg>3)
            {
                return -EINVAL;
            }
            switch(cmd)
            {
                 case 0:
                 case 1:
                     {
                           s3c2410_gpio_setpin(led_table[arg],!cmd);
                           return 0;
                     }
                 default:
                           return -EINVAL;
     
            }
      }

    当你翻开代码一看居然有一些诸如s3c2410_gpio_setpin的函数的时候,你一定心中一声感叹!艹,这个函数那来的?

    为什么会有这些函数呢?原因是linux平台对arm体系是有支持的,比如这些基本的函数,当我们开发程序的时候就可以用,有人觉得为什么要用它的自己写不是更cool吗?个人觉得从学习角度来说未尝不可,但从开发觉得还是高效最重要,为什么在应用程序里C++比C更流行,正是因为C++的效率更高,有更多库的支持,因此我觉得不管是我们软件应用开发也好或者硬件的应用开发也好,开发的难度一定是越来越小,开发效率是越来越高!所以,平台给我们提供的函数能用则用!

    这个函数一旦建立,我们就可以通过通过操作系统的ioctl函数来间接操作heatnan_leds.ioctl,从而控制led。

    下面就是一些程式化的东西了,模块的初始化,模块的退出以及设备的注册等一些列比较俗的问题了。

    ×××××××××××××××××××累的赶脚,活剥不起来la,linux驱动开发感觉累累的!@

    下面贴出整个led驱动代码,主要是仿照数据手册写的,这次主要是入门的学习以及对驱动开发的理解。明天就要进入脱离数据手册的驱动编写辣!好赤鸡的感觉!

     

     

     #include<linux/kernel.h>
     #include<linux/module.h>
     #include<linux/miscdevice.h>
     #include<linux/gpio.h>
     #include<linux/fs.h>
     #include<linux/init.h>
     #include<mach/regs-gpio.h>
     #include<mach/hardware.h>
     
     #define DEVICE_NAME "heat_leds"
     
     
     static unsigned long led_table []= {
             S3C2410_GPB(5),
             S3C2410_GPB(6),
             S3C2410_GPB(7),
             S3C2410_GPB(8),
     };
     static unsigned int led_cfg_table  []={
             S3C2410_GPIO_OUTPUT,
             S3C2410_GPIO_OUTPUT,
             S3C2410_GPIO_OUTPUT,
             S3C2410_GPIO_OUTPUT,
     };
     static int heatnan_leds_ioctl(
             struct inode *inode,
             struct file *file,
             unsigned int cmd,
             unsigned long arg)
     {
            if(arg<0||arg>3)
            {
                return -EINVAL;
            }
            switch(cmd)
            {
                 case 0:
                 case 1:
                     {
                           s3c2410_gpio_setpin(led_table[arg],!cmd);
                           return 0;
                     }
                 default:
                           return -EINVAL;
     
            }
     }
     static struct file_operations dev_fops={
             .owner = THIS_MODULE,
             .ioctl= heatnan_leds_ioctl,
     };
     static struct miscdevice misc={
             .minor=MISC_DYNAMIC_MINOR,
             .name=DEVICE_NAME,
             .fops=&dev_fops,
     };
     static int __init led_init(void)
     {
             int ret;
             int i;
             for(i=0;i<4;i++)
             {
                     s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);
                     s3c2410_gpio_cfgpin(led_table[i],0);
             }
             ret=misc_register(&misc);
             printk(DEVICE_NAME"\tinitialized\n");
             return ret;
     }
     static void __exit led_exit(void)
     {
             misc_deregister(&misc);
     }
     module_init(led_init);
     module_exit(led_exit);
     MODULE_LICENSE("GPL");

     

    终于tmd写完了这个驱动函数,可如果事情到这里结束那也是相当完美啊!按照昨天的方法顺利把驱动模块化编译成功弄到了开发板上,

    结果

    。。。。。。。。

    结果,烧上驱动测试程序后灯真的没亮,我用lsmod和dev下豆发现了模块正在运行,灯就是不亮。。。。。。

    后来我猜想可能是开发板的内核中已经有了led驱动,我这个led驱动和那个led驱动本质是一样的只是名字不一样那个,应该是冲突了。。。。。

    于是卸下屏幕观看,开机,灯全亮,加载我的驱动,灯全灭,欧耶~看来我猜的有道理???????

    好了,不说那些桑心的事啦!整理整理发型,明天继续!

    等串口线回来了,一定要把这个问题弄清楚,看是不是这样的!如果有遇到这个问题的大牛不妨分享下经验,灰常感谢!

     

    驱动编程有感:

    1 驱动编程有种瞻前顾后的感觉,在linux系统中的编程,眼光停留在硬件上远远不够的,还要注意linux系统的外部接口,只有这样才能做到外部接口和自己写的驱动接口完美衔接。

    2 感觉驱动开发就像带着脚镣跳舞,底层的硬件的基本相关函数,linux已经支持,上层的系统接口,linux系统也已经制定了,我们能做的,就是再硬件和系统之间合理周旋。是一个非常考验人的活!前期感觉是累,后期恐怕就是智商挑战了吧!

    3 分析linux驱动的时候,可以适当采用倒叙分析,先从操作系统接口开始,一步一步找到和硬件完美的契合点。。。

     

     

    展开全文
  • 嵌入式Linux应用开发完全手册》从最简单的点亮一个LED开始,由浅入深地讲解,使读者最终可以配置、移植、裁剪内核,编写驱动程序,移植GUI系统,掌握整个嵌入式Linux系统的开发方法。 《嵌入式Linux应用开发完全...
  • 有上图可以看出到,开发板上有三盏LED,分别通过LED1、'LED2'和'LED4'四条线连接,从图上可以看出如果对于三盏LED来说,右侧如果为低电平,那么LED将可以被点亮 2440连接LED灯的引脚 在开发板的原理图上可以搜索到...
  • 嵌入式Linux应用开发完全手册.pdf

    热门讨论 2013-02-17 16:18:23
     第1篇 嵌入式Linux开发环境构建篇 第1章 嵌入式Linux开发概述 第2章 嵌入式Linux开发环境构建 第3章 嵌入式编程基础知识 第4章 Windows、Linux环境下相关工具、命令的使用  第2篇 ARM9嵌入式系统基础...
  • 文章目录实验环境准备第一步:测试三个系统是否连通第二步:编写并编译驱动与测试程序1.LED灯驱动程序编写 实验环境准备 实验材料:GEC6818实验箱、电脑、 实验环境:VMware下Linux系统、arm-linux-交叉编译环境,...
  • 1)资料下载:点击资料即可下载2)对正点原子Linux感兴趣的同学可以加群讨论:9354467413)关注正点原子公众号,获取最新资料更新第四十一章嵌入式Linux LED驱动开发实验上一章我们详细的讲解了字符设备驱动开发步骤,...
  • led.c #include "s3c2440_soc.h" void delay(volatile int d) { while (d--); } int led_test(void) { int val = 0; /* val: 0b000, 0b111 */ int tmp; /* 设置GPFCON让GPF4/5/6配置为输出引脚 */ G...
  • 嵌入式Linux裸机开发(一)——点亮Led开发板:友善之臂smart210一、电路图查阅1、底板电路图查阅开发板底板电路图,查阅LED相关部分LED电路工作原理:LED的正极接3.3V,负极接地时导通,LED发光。开发板共有四颗LED...
  • 关于驱动程序框架,请参考: 嵌入式Linux驱动开发(一)——字符设备驱动框架入门 ...嵌入式Linux开发——裸板程序点亮开发板上的LED灯 首先为了操作硬件,看接线原理图是必不可少的一步,这几个LED的原理图相对来说
  • 上一篇文章写的是linux下通过gcc完成程序源文件的编译执行的过程。以及makefile文件的编写,最后在终端平台输出myhello word! 有了这个基础,这次学习的就是通过...因为还不涉及到系统移植,所以还是裸板程序开发
  • 1)实验平台:正点原子Linux开发板2)摘自《正点原子I.MX6U嵌入式Linux驱动开发指南》关注官方微信号公众号,获取更多资料:正点原子第四十一章嵌入式Linux LED驱动开发实验上一章我们详细的讲解了字符设备驱动开发...
  • 本文主要是以一个最简单的LED驱动开发流程,来窥探一下Linux驱动开发为何物。 基本流程: 1.编写驱动文件xxxx.c 这个文件的主要作用是对设备硬件初始化,主要是xxx_init(),其中也包括设备的注册。  对file_...
  • 1)资料下载:点击资料即可下载2)对正点原子Linux感兴趣的同学可以加群讨论:9354467413)关注正点原子公众号,获取最新资料更新第四十一章嵌入式Linux LED驱动开发实验上一章我们详细的讲解了字符设备驱动开发步骤,...
  • 前言:使用eclipse开发嵌入式linux程序和pc linux程序几乎没有区别,并且使用eclipse图形界面的集成开发环境上手简单,方便学习,这里就教大家开发第一个嵌入式linux程序,程序功能就是测试上次写好的LED驱动程序。...
  • 精品文档 精品文档 收集于网络如有侵权请联系管理员删除 收集于网络如有侵权请联系管理员删除 精品文档 收集于网络如有侵权请联系管理员删除 嵌入式Linux应用开发 中断按键点亮LED实验 一中断控制设计流程 由中断...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 505
精华内容 202
关键字:

led嵌入式linux开发

linux 订阅