完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、通过GPIO控制点亮LED(通过汇编语言)
1. LED点亮原理 查阅原理图,发现开发板上一共有5颗LED。其中一颗D26的接法是:正极接5V,负极接地。因此这颗LED只要上电就会常亮。因此我们分析这颗LED是电源指示灯。 剩下4颗LED的接法是:正极接3.3V,负极接了SoC上的一个引脚(GPIO),具体详细接法是: D22:GPJ0_3 D23:GPJ0_4 D24:GPJ0_5 D25:PWMTOUT1(GPD0_1) 我们知道LED点亮的原理是是其正负极两端出现电压差,这里LED的正极为3.3V已经固定,因此若想点亮LED秩序将负极电压变为0(共阳极接法)。负极接在了SoC的引脚上,可以通过SoC中编程来控制负极的电压值,想点亮哪个引脚的LED就给这个引脚置0。 2. GPIO说明 GPIO(general purpose input output )通用输入输出:GPIO就是芯片的引脚(芯片上的引脚有些不是GPIO,只有一部分是),它的功能和特点是可以被编程控制它的工作模式,也可以编程控制他的电压高低等。 由于软件操作硬件的接口是:寄存器。 我们当前要操作的硬件是LED,但是LED实际是通过GPIO来间接控制的,所以当前我们实际要操作的设备其实是SoC的GPIO,通过改变GPIO硬件的状态间接影响LED的状态。要操作这些GPIO,必须通过设置他们的寄存器。 查阅数据手册可知,GPJ0相关的寄存器有以下: GPJ0CON, (GPJ0 control)GPJ0控制寄存器,用来配置各引脚的工作模式 GPJ0DAT, (GPJ0 data)当引脚配置为input/output模式时,寄存器的相应位和引脚的电平高低相对应。(这里标黄的两个寄存器起到主要功能) GPJ0PUD, (pull up down)控制引脚内部弱上拉、下拉 GPJ0DRV, (driver)配置GPIO引脚的驱动能力 GPJ0CONPDN,(记得是低功耗模式下的控制寄存器) GPJ0PUDPDN (记得是低功耗模式下的上下拉寄存器) 因此如果想点亮LED,需要: 1、操控GPJ0CON寄存器中,选中output模式 2、操控GPJ0DAT寄存器,相应的位设置为0 3. 用汇编点亮LED 因此我们需要把相应的配置数据写入相应的寄存器中,才能实现LED的点亮。即向GPJ0CON(0xE0200240)寄存器和GPJ0DAT(0xE0200244)寄存器中写入对应的信息,这里要注意:寄存器名字是在数据手册中体现的,而在写代码时,需要对应到该寄存器的地址才能进行控制。 点亮LED代码如下: //led.s文件(方式1:全点亮) _start: // 第一步:把0x11111111写入0xE0200240(GPJ0CON)位置 ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数 ldr r1, =0xE0200240 // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令 str r0, [r1] // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去 // 第二步:把0x0写入0xE0200244(GPJ0DAT)位置 ldr r0, =0x0 //如果要想改变LED点亮的状态,即可修改0x0来控制哪个LED的亮灭 ldr r1, =0xE0200244 str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮 flag: // 这两行写了一个死循环。因为裸机程序是直接在CPU上运行的,CPU会 b flag // 逐行运行裸机程序直到CPU断电关机。如果我们的程序所有的代码都 // 执行完了CPU就会跑飞(跑飞以后是未定义的,所以千万不能让CPU // 跑飞),不让CPU跑飞的办法就是在我们整个程序执行完后添加死循环 //led.s文件(方式2:指定某个点亮) #define GPJ0CON 0xE0200240 //将数改为宏定义的方式 #define GPJ0DAT 0xE0200244 .global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了 _start: // 第一步:把所有引脚都设置为输出模式,代码不变 ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数 ldr r1, =GPJ0CON // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令 str r0, [r1] // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去 // 第二步:把中间LED(GPJ0_4)的输出设置为0,其余两颗设置为1,剩下的其他位不管 ldr r0, =0x28 ldr r1, =GPJ0DAT str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮 b . // .代表当前这一句指令的地址,这个就是高大上的死循环 //led.s文件(方式3:方式2的改版,通过位来进行操作) #define GPJ0CON 0xE0200240 #define GPJ0DAT 0xE0200244 .global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了 _start: // 第一步:把所有引脚都设置为输出模式,代码不变 ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数 ldr r1, =GPJ0CON // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令 str r0, [r1] // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去 // 第二步:把中间LED(GPJ0_4)的输出设置为0,其余两颗设置为1,剩下的其他位不管 //ldr r0, =((1<<3) | (1<<5)) // 等效于0b00101000,即0x28 ldr r0, =((1<<3) | (0<<4) | (1<<5)) // 清清楚楚的看到哪个灭,哪个是亮 ldr r1, =GPJ0DAT str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮 b . // .代表当前这一句指令的地址,这个就是高大上的死循环 流水灯代码如下: #define GPJ0CON 0xE0200240 #define GPJ0DAT 0xE0200244 .global _start // 把_start链接属性改为外部,这样其他文件就可以看见_start了 _start: // 第一步:把所有引脚都设置为输出模式,代码不变 ldr r0, =0x11111111 // 从后面的=可以看出用的是ldr伪指令,因为需要编译器来判断这个数 ldr r1, =GPJ0CON // 是合法立即数还是非法立即数。一般写代码都用ldr伪指令 str r0, [r1] // 寄存器间接寻址。功能是把r0中的数写入到r1中的数为地址的内存中去 // 要实现流水灯,只要在主循环中实现1圈的流水显示效果即可 flash: // 第1步:点亮LED1,其他熄灭 ldr r0, =((0<<3) | (1<<4) | (1<<5)) // 清清楚楚的看到哪个灭,哪个是亮 ldr r1, =GPJ0DAT str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮 // 然后延时 bl delay // 使用bl进行函数调用 // 第2步:点亮LED2,其他熄灭 ldr r0, =((1<<3) | (0<<4) | (1<<5)) // 清清楚楚的看到哪个灭,哪个是亮 ldr r1, =GPJ0DAT str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮 // 然后延时 bl delay // 第3步:点亮LED3,其他熄灭 ldr r0, =((1<<3) | (1<<4) | (0<<5)) // 清清楚楚的看到哪个灭,哪个是亮 ldr r1, =GPJ0DAT str r0, [r1] // 把0写入到GPJ0DAT寄存器中,引脚即输出低电平,LED点亮 // 然后延时 bl delay //这里bl可以实现delay函数调用 b flash //跳转到flash,相当于重新开始一遍,无限跳转实现循环 // 延时函数:函数名:delay delay: ldr r2, =9000000 ldr r3, =0x0 delay_loop: sub r2, r2, #1 //r2 = r2 -1 cmp r2, r3 // cmp会影响Z标志位,如果r2等于r3则Z=1,下一句中eq就会成立 bne delay_loop mov pc, lr // 函数调用返回 二、mkv210_image.c文件解读 本实验针对S5PV210板卡进行实验。由于该板卡具有不同的启动方式,因此需要制作不同的镜像烧写文件,这里简单描述USB镜像文件和SD卡镜像文件的制作。 由于SD卡启动时,需要包含一个头信息的校验,因此需要通过mkv210_image.c文件来对USB启动的镜像文件进行加工,从而生成SD卡的镜像文件。 分析启动过程可知: 210启动后先执行内部iROM中的BL0,BL0执行完后会根据OMpin的配置选择一个外部设备来启动(有很多,我们实际使用的有2个:u***启动和SD卡启动)。在u***启动时内部BL0读取到BL1后不做校验,直接从BL1的实质内部0xd0020010开始执行,因此u***启动的镜像led.bin不需要头信息,因此我们从u***启动时直接将镜像下载到0xd0020010去执行即可,不管头信息了;从SD启动时,BL0会首先读取sd卡得到完整的镜像(完整指的是led.bin和16字节的头),然后BL0会自己根据你的实际镜像(指led.bin)来计算一个校验和checksum,然后和你完整镜像的头部中的checksum来比对。如果对应则执行BL1,如果不对应则启动失败。 //mkv210_image.c文件 /* * mkv210_image.c的主要作用就是由u***启动时使用的led.bin制作得到由sd卡启动的镜像210.bin * 本文件来自于友善之臂的裸机教程,据友善之臂的文档中讲述,本文件是一个热心网友提供,在此表示感谢。 */ /* 在BL0阶段,Irom内固化的代码读取nandflash或SD卡前16K的内容, * 并比对前16字节中的校验和是否正确,正确则继续,错误则停止。 */ #include #include #include #define BUFSIZE (16*1024) //总长度16K大小 #define IMG_SIZE (16*1024) #define SPL_HEADER_SIZE 16 //头长度16字节大小 //#define SPL_HEADER "S5PC110 HEADER " #define SPL_HEADER "****************" int main (int argc, char *argv[]) //argc是用户执行程序时传递参数的个数;argv是一个个的参数 { FILE *fp; char *Buf, *a; int BufLen; int nbytes, fileLen; unsigned int checksum, count; int i; //校验3个参数(./mkx210 led.bin 210.bin) if (argc != 3) { printf("Usage: %s |
|
|
|
只有小组成员才能发言,加入小组>>
4336个成员聚集在这个小组
加入小组3285 浏览 0 评论
航顺(HK)联合电子发烧友推出“近距离体验高性能Cortex-M3,免费申请价值288元评估板
4232 浏览 1 评论
4238 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-20 22:21 , Processed in 0.629197 second(s), Total 74, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号