第1节 eop常见问题
1、未连接op/eop到电脑
2、有其他程序在使用op/eop(同一时间只能有一个程序使用它)
3、JTAG线未接
4、开发板未上电
5、oflash xxx.bin 时当前文件夹下没有xxx.bin
6、烧写完后没有正确设置启动开关
7、烧写完后,op/eop--------开发板之间的排线未断开,导致程序无法运行
第2节 使用uboot烧写裸板程序
1、使用op/eop把u-boot.bin烧到nor flash
2、开发板设置为nor启动,上电后马上在串口输入空格键,使板子进入UBOOT,而不是启动板子上的内核
3、连接PC------开发板的usb device口,安装驱动
4、在UBOOT的串口菜单中输入n(表示接受USB文件并烧到NAND)
5、使用dnw_100ask.exe发送bin文件
6、uboot即会自动接受、烧写bin文件
7、断电,设为nand启动,上电,运行nand上烧好的程序
第3节 恢复出厂设置
1、使用op/eop烧写uboot到nor/nand,设置为nor/nand启动
2、上电后马上在串口输入空格,使板子进入UBOOT而不是启动内核
3、连接PC------开发板的usb device口,安装驱动
4、下载内核:在UBOOT的串口菜单中输入k
5、使用dnw_100ask.exe发送uImage文件
6、uboot即会自动接收、烧写uImage文件
7、下载文件系统:在UBOOT的串口菜单中输入y
8、使用dnw_100ask.exe发送fs_qtopia.yaffs2文件
9、uboot即会自动接收、烧写根文件系统
10、输入q退出UBOOT串口菜单,执行命令删除参数分区:nand erase params
11、重启(对于QT文件系统,第一次重启会要求校准触摸屏)
(如果触摸不准,可以等系统启动后在串口执行:rm /etc/pointercal)
第4节 jz2440 GPIO操作

怎么让GPF4输出1/0
1.配置为输出引脚


将GPFCON[9:8]配置成0b01,GPF4配置为输出引脚
把0x100写入GFPFCON,即写到地址0x56000050上
2.设置状态
配置GPF4DAT[4] = 1:输出高电平,LED熄灭;
把0x10写到地址0x56000054上
GPF4DAT[4] = 0: 输出低电平,LED点亮;
把0写到地址0x56000054上
几条汇编代码
1.LDR:读内存, LDR R0, [R1]
(load) 假设 R1的值是x,读取地址x上的数据(4字节),保存到R0中
2.STR:写内存命令,STR R0, [R1]
(store) 假设R1的值是x,把R0的值写到地址x(4字节)
3.B :跳转
4. MOV: MOV R0, R1 把R1的值赋给R0 R0 = R1
(move) MOV R0, # 0x100, R0 = 0x100
5.LDR R0, = 0x12345678 : R0 = 0x12345678
伪指令,它会被分为几条真正的RAM指令
MOV R0,#12345678(是错误的!!!!!!!!!!!!!!!!!!!!)
ARM指令32位
31| R0 |0
表示MOV 表示R0
剩下的不足32位,不能表示任意值,只能表示简单值(被称为立即数)
6.add: add r0, r1, #4 : r0 = r1 + 4
sub:sub r0, r1, #4 :r0 = r1 - 4
sub r0, r1, r2 :r0 = r1 - r2
7.BL: brarch and Link
bl xxx ==》1.跳转到xxx
2.把返回地址保存到lr寄存器(下一条指令的地址)
8.ldm ====》读内存,写入多个寄存器(ldm m:many)
stm ====》把多个寄存器的值写入内存
ia(Increment After):过后增加、ib(Increment Before):预先增加、
da(Decrement After):过后减少、db(Decrement Before):预先减少
idmia
r11,r12,r14,r15
stmdb stmdb sp!, {fp, ip, lr, pc} 假设sp = 4096,db:先减后存
高编号寄存器存在高地址 sp!:sp=最终的,被修改的sp值4080
地址
pc <--4096 1.先减:sp' = sp - 4 = 4092
lr <--4092 2.后存:4092~4095存放pc的值
ip <--4088 3.先减:sp' = sp - 4 = 4092 - 4 = 4088
fp <--4084 4.后存:4088 ~ 4091存放lr的值
<--4080
高编号寄存器存放高地址内存值
ldmia sp, {fp, sp, pc} 假设sp = 4080 ia:先读后增;sp:没有!,修改后的地址值不存入sp中
r11, r13, r15
pc <--4096 1.先读:fp=4080~4083的值 = 原来保存的fp
lr <--4092 2.后增: sp = sp + 4 = 4084
ip <--4088 3.先读:sp = 4084 ~ 4087的值 = 原来保存的ip
fp <--4084 4.后增:sp' = sp + 4 = 4088
<--4080 5.先读:pc = 4088 ~ 4091的值 = 原来保存的lr的值
6.后增: sp' = sp + 4 = 4092
汇编点亮led灯:
led_on.S
/**点亮LED: GPF4*/.text.global _start_start:/*配置GPF4为输出引脚*把0x100写到地址0x56000050*/ldr r1, =0x56000050ldr r0, =0x100 /*mov r0, #0x100*/str r0, [r1]/*设置GPF4为输出高电平*把0写到地址0x56000054*/ldr r1, =0x56000054ldr r0, =0 /*mov r0, #0*/str r0, [r1]halt:b halt
将程序通过Filezilla将程序传到主机编译,
Makefile如下:
all:arm-linux-gcc -c -o led_on.o led_on.S arm-linux-ld -Ttext 0 led_on.o -o led_on.elfarm-linux-objcopy -O binary -S led_on.elf led_on.binclean:rm *.S *.elf *.bin
通过make all编译得到led_on.S、led_on.elf、led_on.bin;
使用make clean可清除led_on.S、led_on.elf、led_on.bin;
将led_on.bin传到windows通过eopJTAG烧写到jz2440开发板,oflash len_on.bin,选择烧写到Nand flash,烧写完毕,断开eopJTAG线,选择Nand启动,重新上电,led点亮成功。
在c语言中怎么表示
int a = 96;
int a = 0140; 0开头表示8进制
int a = 0x60; 0x开头表示16进制
0b01110111 0b开头表示二进制
编写C语言点亮led
int main()
{unsigned int *pGPGCON = (unsigned int *)0x56000050;unsigned int *pGPGDAT = (unsigned int *)0x56000054;/*配置GPF4为输出引脚*/*pGPGCON = 0x100;/*设置GPF4为输出0*/*pGPGDAT = 0;return 0;
}
编写汇编调用main函数
.text
.global _start_start:/*设置内存 sp 栈*///ldr sp, =4096 /*nand启动*/ldr sp, =0x40000000+4096 /*nor启动*//*调用main*/bl mainhalt:b halt
编写Makefile
all:arm-linux-gcc -c -o led.o led.c arm-linux-gcc -c -o start.o start.Sarm-linux-ld -Ttext 0 start.o led.o -o led.elfarm-linux-objcopy -O binary -S led.elf led.binarm-linux-objdump -D led.elf > led.disclean:rm *.o *.elf *.bin *.dis
第5节 s3c2440框架及启动过程
框架

启动过程:多数ARM芯片从0地址启动
1.Nor启动:Nor Flash基地址为0,片内RAM地址为0x400000000
CPU读出Nor上第一个指令(前4字节)执行
CPU继续读出其他指令执行
2.Nand 启动:片内4KRAM基地址为0,Nor Flash不可访问
2440硬件把Nand前4K内容复制到片内RAM
然后CPU从0地址取出第一条指令执行
第6节 字节序与位操作
字节序
int a = 0x12345678
高位 低位
内存:
低位存在低地址:小字节序、小端
0x12 A+3
0x34 A+2
0x56 A+1
0x78 A
高位存在低地址:大字节序、大端
0x78 A+3
0x56 A+2
0x34 A+1
0x12 A
位操作:
8421 左移两位
0001,0010,0011 ==> 0111,1000,1100
1 2 3 4 8 c
移位:左移:int a = 0x123; int b = a << 2; b = 0x48c
=0x123 * 2^2 = 0x123 * 4
右移:int a = 0x123; int b = a>>2; b = 0x48 = 0x123 / 4
1 2 3 右移两位 0 4 8
0001,0010,0011 ==> 0000,0100,1000
取反:原来为0的位变为1,原来为1的位变为0;
int a = 0x123; 00...,0001,0010,0011
int b = ~a; 取反 11...,1110,1101,1100
=0xfffffedc fffff e d c
位与:1&1=1; int a = 0x123; 0001,0010,0011
1&0=0; int b = 0x456; 0100,0101,0110
0&1=0; int c = a&b; & 0000,0000,0010
0&0=0; =2 2
位或:1|1=1; int a = 0x123; 0001,0010,0011
1|0=1; int b = 0x456; 0100,0101,0110
0|1=1; int c = a|b; | 0101,0111,0111
0|0=0; = 0x577 5 7 7
置位:int a = 0x123 0001,0010,0011
把bit7,8置位 1000,0000
int b = a | (1<<7) | (1 << 8) | 1,0000,0000
=0x1a3 0001,1010,0011
1 a 3
清位:int a = 0x123 0001,0010,0011
把bit7,8清位 1000,0000
int b = (a &~(1<<7))&(~(1<<8))
0001,0010,0011 0001,0010,0011
& 1111,0111,1111 1110,1111,1111
0001,0010,0011 0000,0010,0011
1 2 3 2 3
int b = 0x23
第7节 解析c程序的内部机制
start.S:1.设置栈
2.调用main,并把返回地址保存在lr中
led.c: main :1.定义两个局部变量
2.设置变量
3.return 0
>1为何要设置栈?
因为c函数要用
>2怎么使用栈?
a.保存局部变量;
b.保存lr等寄存器
>3调用者如何传参数给被调用者?
>4被调用者如何传返回值给调用者?
>5怎么从栈中恢复那些寄存器?
寄存器 r0 、r1 、 r2 、 r3用于存放参数/结果
r0~r3
调用者 <---------> 被调用者
在函数中,寄存器r4 r5 r6 r7 r8 r9 r10 r11可能被使用,所以:
在入口保存它们,在出口恢复它们
led.c
int main()
{unsigned int *pGPGCON = (unsigned int *)0x56000050;unsigned int *pGPGDAT = (unsigned int *)0x56000054;/*配置GPF4为输出引脚*/*pGPGCON = 0x100;/*设置GPF4为输出0*/*pGPGDAT = 0;return 0;
}
编写汇编调用main函数
led.c的反汇编如下
led.elf: file format elf32-littlearmDisassembly of section .text:00000000 <_start>:0: e59fd004 ldr sp, [pc, #4] ; c <.text+0xc>4: eb000001 bl 10 <main>00000008 <halt>:8: eafffffe b 8 <halt>c: 40001000 andmi r1, r0, r000000010 <main>:10: e1a0c00d mov ip, sp //ip=sp=409614: e92dd800 stmdb sp!, {fp, ip, lr, pc} //r11 r12 r14 r1518: e24cb004 sub fp, ip, #4 ; 0x4 //fp=ip-4=40921c: e24dd008 sub sp, sp, #8 ; 0x8 //sp=sp-8=4080-8=407220: e3a03456 mov r3, #1442840576 ; 0x56000000 //r3=0x5600000024: e2833050 add r3, r3, #80 ; 0x50 //r3=0x5600005028: e50b3010 str r3, [fp, #-16] //r3存入[fp-16]=[4076]2c: e3a03456 mov r3, #1442840576 ; 0x5600000030: e2833054 add r3, r3, #84 ; 0x54 //r3=0x5600005434: e50b3014 str r3, [fp, #-20] //r3存入[fp-20]=[4072]38: e51b2010 ldr r2, [fp, #-16] //r2=[fp-16]=[4076]=0x560000503c: e3a03c01 mov r3, #256 ; 0x100 //r3=0x10040: e5823000 str r3, [r2] //r3存入[0x56000050] c语言中*pGPFCON=0x10044: e51b2014 ldr r2, [fp, #-20] //r2=[fp-20]=[4072]=0x5600005448: e3a03000 mov r3, #0 ; 0x04c: e5823000 str r3, [r2] //r3(0)存入[56000054] c语言设置GPGF4输出050: e3a03000 mov r3, #0 ; 0x0 //r3=054: e1a00003 mov r0, r3 //return 058: e24bd00c sub sp, fp, #12 ; 0xc //sp=fp-12=4092-12=40805c: e89da800 ldmia sp, {fp, sp, pc} //从栈中恢复寄存器//fp=[4080]=原来保存的fp//sp=[4084]=4096//pc=[4088]=8 跳回0x8的地址,main返回
Disassembly of section .comment:00000000 <.comment>:0: 43434700 cmpmi r3, #0 ; 0x04: 4728203a undefined8: 2029554e eorcs r5, r9, lr, asr #10c: 2e342e33 mrccs 14, 1, r2, cr4, cr3, {1}10: Address 0x10 is out of bounds.
栈:sp所指向的内存
<--4096
pc = 0x22 <--4092
rl = 8 <--4088
ip=4096 <--4084
fp未知 <--sp'=4096-4*4=4080
0x56000050 <--4076
0x56000054 <--4072
......................
e89da500 <--5c
.......................
eb000001 <--4
e59fd004 <--0
片内4KRAM
函数传参led.c
void delay(volatile int d)
{while (d--);
}int led_on(int which)
{unsigned int *pGPGCON = (unsigned int *)0x56000050;unsigned int *pGPGDAT = (unsigned int *)0x56000054;if (which == 4){/*配置GPF4为输出引脚*/*pGPGCON = 0x100;}else if (which == 5){/*配置GPF5为输出引脚*/*pGPGCON = 0x400;}/*设置GPF4/5为输出0*/*pGPGDAT = 0;return 0;
}
汇编调用函数led_on与delay
.text
.global _start_start:/*设置内存 sp 栈*/ldr sp, =4096 /*nand启动*///ldr sp, =0x40000000+4096 /*nor启动*//*调用c函数*/mov r0, #4bl led_onldr r0, =100000bl delaymov r0, #5bl led_onhalt:b halt
第8节 完善led程序,按键点亮
循环点亮三个灯
void delay(volatile int d)
{while (d--);
}#define GPFCON (*((volatile unsigned int *)0x56000050))
#define GPFDAT (*((volatile unsigned int *)0x56000054))int main(void)
{//unsigned int *pGPGCON = (unsigned int *)0x56000050;//unsigned int *pGPGDAT = (unsigned int *)0x56000054;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;
}
汇编调用main
.text
.global _start_start:/*关闭看门狗*/ldr r0, =0x53000000ldr r1, =0str r1,[r0]/*设置内存 sp 栈*//*分辨是nor/nand启动*写到0地址,再读出来*如果得到0,表示0地址上的内容被修改了,它对应ram,这就是nand启动*否则就是nor启动*/mov r1, #0ldr 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] /*恢复原来的值*//*调用main*/bl mainhalt:b halt
按键点亮
#define GPFCON (*((volatile unsigned int *)0x56000050))
#define GPFDAT (*((volatile unsigned int *)0x56000054))#define GPGCON (*((volatile unsigned long *)0x56000060))
#define GPGDAT (*((volatile unsigned long *)0x56000064))int main(void)
{//unsigned int *pGPGCON = (unsigned int *)0x56000050;//unsigned int *pGPGDAT = (unsigned int *)0x56000054;int val1;int 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;
}
Makefile
all:arm-linux-gcc -c -o key_led.o key_led.c arm-linux-gcc -c -o start.o start.Sarm-linux-ld -Ttext 0 start.o key_led.o -o key_led.elfarm-linux-objcopy -O binary -S key_led.elf key_led.binarm-linux-objdump -D key_led.elf > key_led.disclean:rm *.o *.elf *.bin *.dis






![[BigData]16家大数据分析平台](http://www.dratio.com/files/image2/201402/251053065183.jpg)







