JZ2440裸板开发练习#1 - 点亮LED

平台:JZ2440开发板——CPU:S3C2440(ARM920)


S3C2440作为一款SOC,一般是用来跑系统(如linux等)居多,这里下降到裸机层面,以最下层的方式熟悉硬件相关的软件开发。学习编程语言的第一个实验就是在黑窗或者其他输出中打印出"hello world",而裸机的"helloworld"则为点亮一个LED灯。

有STC89C51或者STM32等单片机开发经验的都知道,裸板中控制CPU其实就是在做读写寄存器,在此基础上增加我们的业务逻辑,就能让板子按照我们所希望地运行,S3C2440也不例外。

分析

想要控制LED灯亮灭,首先从电路知识可以知道,LED为一种发光二极管,单向导通,只需要在其两端按照方向施加一个电势差(具体视LED定,一般为3.3V即可)就可以将其点亮。因此需要先看下所用板子的原理图,如下:

从原理图可知,板载的LED已经接上3.3V高电势,因此我们只需要控制nLED_x(原理图中,n一般表示低电平有效)连接的引脚输出低电平即可。

同样可以从原题图中找到GPF4/5/6连接着需要控制的三个LED灯。下一步需要去S3C2440的芯片手册查找相应的寄存器信息。查看芯片手册可以知道,控制GPIOF来点亮LED需要控制如下寄存器

其中GPFCON为IO复用功能选择,这里只要设置为output作为输出引脚即可,按照手册可知将相应位设置为01即可。

GPFDATA为数据寄存器,当我们设置为输出引脚时,可以往相应位写入数据即可使其输出高或低电平。

GPFUP为上拉控制寄存器,对应引脚位设置为0即使能上拉,上拉设置后,在没有设置GPFDAT时,引脚会被上拉呈高电平状态,该寄存器reset时被初始化为全0,全部引脚默认打开上拉,板子LED默认熄灭,刚好满足需求,因此可以不用设置它。

程序部分

1.汇编

由于S3C2440为ARM架构,因此使用的是ARM汇编指令集,这里简单地写了下设置寄存器让三个LED点亮,直接写值覆盖的方式很粗糙,后续将用更加常用且安全的方式写寄存器。

.text
.global _start

_start:
	/* 将GPF4,5,6设置为输出引脚 */
	LDR R0,=0x56000050
	LDR R1,=0x1500
	STR R1,[R0]
	
	/* 设置GPF4,5,6输出低电平 */
	LDR R0,=0x56000054
	LDR R1,=0x8f
	STR R1,[R0]
halt:
    b halt

2.C语言

C语言统一的入口为main函数,但是裸板中,需要一个程序来调用我们编写的main,这个程序称为启动程序。由于C语言函数调用传递参数以及自动变量等需要用到栈内存,因此启动程序还要负责将栈设置好,从而让C语言程序正常运行。

Start.S
--------------------------------------------------
.text
.global _start

_start:
	MOV R0,#0
	LDR R1,[R0]  //保存0地址值	
	
	STR R0,[R0]	 //将0值写入,测试是否为NOR_Flash启动
	LDR R2,[R0]
	
	CMP R2,R0
	LDR SP,=0x40000000+4096
	MOVEQ SP,#4096
	STREQ R1,[R0]
	
	bl main
halt:
    b halt
led.c
---------------------------------------------------------------------------
int main()
{
	volatile unsigned int* pGPFCON = (unsigned int*)0x56000050;
	volatile unsigned int* pGPFDAT = (unsigned int*)0x56000054;
	
	//能不影响其他位的寄存器写方式
	*pGPFCON &= ~((3<<8) | (3<<10) | (3<<12));  //寄存器对应的控制位清0
	*pGPFCON |= ((1<<8) | (1<<10) | (1<<12));  //置位对应的控制位
	
	*pGPFDAT &=~((1<<4) | (1<<5) | (1<<6));
	return 0;
}

启动文件中,需要判断是nandflash还是norflash启动方式,是由于S3C2440开发板存在norflash启动方式和nandflash启动方式。查阅S3C2440芯片手册可以看到如下内存映射表,

当norflash方式启动时,默认以norflash的0地址作为内存0地址,而芯片内置SRAM(Boot internal SRAM)地址则为0x40000000+4096。

当nandflash方式启动时,芯片将会将nandflash中前4k数据拷贝到内置SRAM(Boot internal SRAM),并以此为0地址运行,默认可用控制内存块为0-4096。

如果需要使用其他地址内存需要进行相应的初始化,这是后面的内容暂且不谈。norflash只读,启动文件利用这一点尝试写入一个0值到0地址处,并读出与0比较。如果为norflash则写入失败,读出的数据应该不为0,因此将栈地址设置为0x40000000+4096。nandflash可读可写,因此写入0后读出数据也为0,因此将栈设置为4096。

至此,用汇编和C语言分别完成了点灯的操作,很粗糙也很简单但是能够实现功能,效果为板子上三个led都亮起。编译该程序使用交叉编译器,并且使用makefile简化编译操作,避免重复输入,针对C语言的一个粗糙Makefile如下:

all:
    arm-linux-gcc -o Start.o -c Start.S
    arm-linux-gcc -o led.o -c led.c
    arm-linux-ld -o led.elf Start.o led.o
    arm-linux-objcopy -O binary -S led.elf led.bin
    arm-linux-objdump -D led.elf > led.dis

clean:
    rm *.bin *.elf *.dis *.o

其中dis为程序反汇编文件,后续会对反汇编文件做分析,暂且先放在这里。

 
发布了19 篇原创文章 · 获赞 7 · 访问量 6929

猜你喜欢

转载自blog.csdn.net/G_METHOD/article/details/104146636