(1)汇编点亮LED

1、查阅原理图、数据手册
1.1、因为Tiny 210的LED在核心板上,所以通过通过查阅核心板,获得控制LED的GPIO引脚
(1)汇编点亮LED_第1张图片
(1)汇编点亮LED_第2张图片
得知控制LED的主要引脚是GPJ2_(0~3)
1.2、查阅s5pv210数据手册
(1)首先要明白这里控制LED的寄存器主要有两个:
GPJ2CON:设置引脚的状态
GPJ2DAT:该寄存器中的内容与GPJ2引脚高低电平状态同步,换句话说就是可以通过在该寄存器中写入内容来控制GPJ2引脚的高低电平,1为高电平,0为低电平。
(1)汇编点亮LED_第3张图片
(1)汇编点亮LED_第4张图片
在这里插入图片描述
(2)主要寄存器地址
GPJ2CON 0xE020_0280
GPJ2DAT 0xE020_0284
2、编程
2.1、start.s

/*
 *		代码:让LED灯闪烁
 *		日期:2020.7.5 
 *		作者:glass love
 *
 */
 
 
//首先通过查阅原理图,得到控制4颗LED灯的引脚
//GPJ2_(0~3)对应LED(1~4)
//通过查阅数据手册与用户手册得到
//与控制LED有关的寄存器为GPJ2CON、GPJ2DAT
//GPJ2CON的地址为0xE020_0280、0xE020_0280的地址为0xE020_0284
//需要将GPJ2CON的bit(0~15)设置为0x1111
//如果要LED亮需要将GPJ2DAT的bit(0~3)设置为0x0
//如果要LED灭需要将GPJ2DAT的bit(0~3)设置为0xf


.global _start

//设置GPJ2CON的bit(0~15),配置GPJ2_0/1/2/3引脚为输出模式
_start:
	ldr r0, =0x1111
	ldr r1, =0xE0200280
	str r0, [r1]
	
//此处赋给r2一个随机数0x1000,目的是为后面的循环是设定一个时间	
	mov r2, #0x1000
led_blink:
	
//LED亮
	ldr r0, =0x0
	ldr r1, =0xE0200284
	str r0, [r1]
	
//延时
	bl delay
	
//LED灭
	ldr r0, =0xf
	ldr r1, =0xE0200284
	str r0, [r1]

//延时
	bl delay
	

//下面为循环函数

	sub r2, r2, #1
	cmp r2, #0
	beq led_blink         

//此时mov r2, #0x1000和后面的循环函数
//两者中间为循环体一般仿佛声明了

//在汇编函数结尾需要一个死循环

half:
	b half


//前面bl delay调用了函数delay
//需要在这里写出delay函数


delay:
	mov r0, #0x100000
delay_loop:
	sub r0, r0, #1
	cmp r0, #0
	beq delay_loop
//调用完函数需要返回,所以mov pc, lr起到返回作用
	mov pc, lr

2.2、Makefile

led.bin: start.o 
	arm-linux-ld -Ttext 0x0 -o led.elf $^                 
	arm-linux-objcopy -O binary led.elf led.bin			  
	arm-linux-objdump -D led.elf > led_elf.dis   		  
	gcc mkv210_image.c -o mkmini210              		  
	./mkmini210 led.bin 210.bin 						  
	
%.o : %.S
	arm-linux-gcc -o $@ $< -c

%.o : %.c
	arm-linux-gcc -o $@ $< -c 

clean:
	rm *.o *.elf *.bin *.dis mkmini210 -f

arm-linux-ld(链接)、arm-linux-gcc(编译)、arm-linux-objcopy(生成可以烧录的bin文件)、 arm-linux-objdump(反编译工具)均为交叉编译工具 。
mkv210_image.c为将led.bin转换为210.bin的c代码
%.o : %.S、%.o : %.c就是将.c、.s文件编译为.o文件

2.3、mkv210_image.c

/* 在BL0阶段,Irom内固化的代码读取nandflash或SD卡前16K的内容,
 * 并比对前16字节中的校验和是否正确,正确则继续,错误则停止。
 */
#include 
#include 
#include 

#define BUFSIZE                 (16*1024)
#define IMG_SIZE                (16*1024)
#define SPL_HEADER_SIZE         16
#define SPL_HEADER              "S5PC110 HEADER  "

int main (int argc, char *argv[])
{
	FILE		*fp;
	char		*Buf, *a;
	int		BufLen;
	int		nbytes, fileLen;
	unsigned int	checksum, count;
	int		i;
	
	// 1. 3个参数
	if (argc != 3)
	{
		printf("Usage: mkbl1  \n");
		return -1;
	}

	// 2. 分配16K的buffer
	BufLen = BUFSIZE;
	Buf = (char *)malloc(BufLen);
	if (!Buf)
	{
		printf("Alloc buffer failed!\n");
		return -1;
	}

	memset(Buf, 0x00, BufLen);

	// 3. 读源bin到buffer
	// 3.1 打开源bin
	fp = fopen(argv[1], "rb");
	if( fp == NULL)
	{
		printf("source file open error\n");
		free(Buf);
		return -1;
	}
	// 3.2 获取源bin长度
	fseek(fp, 0L, SEEK_END);
	fileLen = ftell(fp);
	fseek(fp, 0L, SEEK_SET);
	// 3.3 源bin长度不得超过16K-16byte
	count = (fileLen < (IMG_SIZE - SPL_HEADER_SIZE))
		? fileLen : (IMG_SIZE - SPL_HEADER_SIZE);
	// 3.4 buffer[0~15]存放"S5PC110 HEADER  "
	memcpy(&Buf[0], SPL_HEADER, SPL_HEADER_SIZE);
	// 3.5 读源bin到buffer[16]
	nbytes = fread(Buf + SPL_HEADER_SIZE, 1, count, fp);
	if ( nbytes != count )
	{
		printf("source file read error\n");
		free(Buf);
		fclose(fp);
		return -1;
	}
	fclose(fp);

	// 4. 计算校验和
 	// 4.1 从第16byte开始统计buffer中共有几个1
	a = Buf + SPL_HEADER_SIZE;
	for(i = 0, checksum = 0; i < IMG_SIZE - SPL_HEADER_SIZE; i++)
		checksum += (0x000000FF) & *a++;
	// 4.2 将校验和保存在buffer[8~15]
	a = Buf + 8;
	*( (unsigned int *)a ) = checksum;

	// 5. 拷贝buffer中的内容到目的bin
	// 5.1 打开目的bin
	fp = fopen(argv[2], "wb");
	if (fp == NULL)
	{
		printf("destination file open error\n");
		free(Buf);
		return -1;
	}
	// 5.2 将16k的buffer拷贝到目的bin中
	a = Buf;
	nbytes	= fwrite( a, 1, BufLen, fp);
	if ( nbytes != BufLen )
	{
		printf("destination file write error\n");
		free(Buf);
		fclose(fp);
		return -1;
	}

	free(Buf);
	fclose(fp);

	return 0;
}

注:这个代码是我搬砖过来的
代码主要内容:
第一步 分配 16k 的 buffer;
第二步 将 led.bin 读到buffer 的第 16byte 开始的地方;
第三步 计算校验和,并将校验和保存在 buffer 第 8~11byte 中;
第四步 将 16k 的 buffer 拷贝到 210.bin 中

2.4、write2 sd

#!/bin/sh
sudo dd iflag=dsync oflag=dsync if=210.bin of=/dev/sdb seek=1

dd 是一个读写命令, if 是输入, of 是输出, seek 表示从扇区 1 开始读写。sd 启动时, IROM 里的固化代码是从扇区1 开始拷贝代码的。sdb 为本文档编写时 sd 卡的设备节点。

3、生成可烧录镜像文件
3.1、将sd卡插入PC ,在ubuntu(我用的ubuntu,也可以是其他的)终端 执行如下命令 :
首先你要cd 到你放代码的文件夹(例如我放在1.led_s下)
cd 1.led_s
make
chmod 777 write2sd
./write2sd
就可以把生成的210.bin文件烧录到sd卡的1扇区。

你可能感兴趣的:(ARM,#,s5pv210,ARM,A8,S5PV210,tiny210)