天天看点

ARM体系结构之点亮LED灯(C语言篇)

要在裸机上运行C语言程序,我们需要在运行C语言程序之前设置栈底指针,因为C语言中的变量与函数调用都是基于堆栈的。

怎么设置栈底指针呢,一句话就可以了

ldr pc,=1024*4
           

至于为什么设置成4k,是因为的这块板子SRAM最大只有4K的地址空间。

当然,我们还需要做的一件事情是关闭看门狗,这个,我也不是特别清楚,应该照做就好了吧,反正挺简单的

ldr r0, =0x53000000
mov r1, #0
str r1, [r0]
           

所以程序需要做这几件事情

关闭看门狗

设置栈底指针

跳转到C语言的函数中运行(一般是main函数)

.text
.global _start
_start:
	@关闭看门狗
	ldr r0, =0x53000000
	mov r1, #0
	str r1, [r0]
	
	@设置栈底指针
	ldr sp, =4096
	
	@跳转到C语言中运行
	bl main
	
halt_hoop:
	b halt_hoop	
           
#define LEDCON (*(volatile unsigned long *)0x56000050)
#define LEDDAT (*(volatile unsigned long *)0x56000054)

#define E_LED1 (0x01 << 2*4)
#define E_LED2 (0x01 << 2*5)
#define E_LED3 (0x01 << 2*6)

#define ON_LED1 (0x1 << 4)
#define ON_LED2 (0x1 << 5)
#define ON_LED3 (0x1 << 6)

void allLedEnable()
{
	LEDCON |= (E_LED1 | E_LED2 | E_LED3);
}

void sleep()
{
	int i = 0x5555;
	for(; i ; i--);
}

int main()
{
	
	allLedEnable();
	while(1){
		sleep();
		LEDDAT &= ~ON_LED1;
		LEDDAT |= ON_LED2;
		LEDDAT |= ON_LED3;
		sleep();
		LEDDAT |= ON_LED1;
		LEDDAT &= ~ON_LED2;
		LEDDAT |= ON_LED3;
		sleep();
		LEDDAT |= ON_LED1;
		LEDDAT |= ON_LED2;
		LEDDAT &= ~ON_LED3;
	}
	
	return 0;
}
           
led_on.bin:led_on.c crt0.S
	arm-linux-gcc -g -c -o led_on.o led_on.c
	arm-linux-gcc -g -c -o crt.o crt0.S
	arm-linux-ld -Ttext 0x00000000 -g crt.o led_on.o -o led_on_elf
	arm-linux-objcopy -O binary -S led_on_elf led_on.bin
	arm-linux-objdump -S -m arm led_on_elf > led_on_elf.dis
	
clean:
	rm -f led_on.bin led_on_elf *.o *.bak
	
           

这个程序之前已经写过两遍了,可是今天写时,无论如何led灯都不亮,后来对着书一个一个查,就是少了个volatile关键字,坑爹啊.