ITOP4412裸机编程-点亮LED灯

参考博文
ITOP4412裸机开发—LED
tiny4412裸机程序之点灯

文章目录

  • 前言:
  • 启动原理:
  • 源码:
    •        修改start.S
    •        修改s3c4412_gpio.h
    •        修改Makefile
    •        修改myboot.lds
  • 烧录SD卡:
    •        方法1:
      •        修改mkbl2.c
    •        方法2:
  • 现象:
  • 源码获取:

前言:

       这是我的第一篇博客,不足之处还请批评指正,涉及侵权问题请与我联系,转载注明出处即可。
       本文介绍用SD卡启动的裸机编程,学会这个裸机编程,移植uboot之类的也不再话下了,由于Exynos4412这个芯片有两种封装方式pop和scp,这两个芯片对应着不同的BL1,盲目烧写错的BL1可能实现不了目标,详细实现功能请向下翻阅,博主的板子是迅为的精英板4412 pop1G封装。
ITOP4412裸机编程-点亮LED灯_第1张图片

启动原理:

ITOP4412裸机编程-点亮LED灯_第2张图片
       图片是迅为提供的uboot文档中截的,从图中看开发板在上电时会经过以上三个步骤,就是图中的圆圈中的123了,第一步,开发板上电会去执行IROM,这个IROM会由OM的控制决定从哪个介质开始引导加载程序。
ITOP4412裸机编程-点亮LED灯_第3张图片
       如图由五位二进制编码决定,详细不再讲,我们这里讲SD卡启动,就将开发板的拨码开关拨到SD卡启动。第二步,程序会从SD卡中加载第一段代码BL1到IRAM中;第三步,OS系统会被加载到DRAM中,至此引导结束。
       但是这个地方有个问题,第一步和第二步都对,但是第三步,BL1会从SD卡中的第18个扇区开始读取16K代码到internal SRAM中并跳转到这段代码的起始位置。如下图第一个:ITOP4412裸机编程-点亮LED灯_第4张图片

       加载的这个BL2实际上是uboot的前16K,uboot后面的大部分代码会被BL2加载到DRAM中,然后跳转到DRAM中uboot开始的位置开始执行,我们这里讲裸机程序,实际上就是把BL2替换成裸机程序,但是这个裸机程序必须小于14K,为什么要小于14K呢?如下图BL2的结构:
ITOP4412裸机编程-点亮LED灯_第5张图片
       如图BL2的结构实际上是BL2的程序+4Byte的校验和+256Byte的签名+补全0=16K,因为BL1加载BL2到IRAM后要验证校验和是否正确,所以我们写好的裸机程序最终还要加上4字节的校验和后等于14K,官方提供的uboot中有制作校验和的源码,后面会介绍。

源码:

       新建文件夹及文件

mkdir leds
cd leds
touch start.S s3c4412_gpio.h myboot.lds Makefile mkbl2.c

       修改start.S

       这个汇编代码0x1002330c是PS_HOLD_CONTROL寄存器,保证电源管理芯片正常工作,0x11000c08是GPX0组控制上下拉的寄存器,有个ONO(GPX0_2)在控制电源管理。

#include "s3c4412_gpio.h"
.global _start

.word 0x2000
.word 0x0
.word 0x0
.word 0x0

_start:
   ldr	r10,=0x1002330c
   ldr	r11,[r10]
   orr	r11,r11,#0x300
   str	r11,[r10]

   ldr	r10,=0x11000c08
   ldr	r11,=0x0
   str	r11,[r10]

   ldr	r10,=GPL2CON
   mov	r11,#(0x01<<0)
   str	r11,[r10]

   ldr	r10,=GPK1CON
   mov	r11,#(0x01<<4)
   str	r11,[r10]

1:
   ldr	r10,=GPK1DAT
   mov	r11,#0x02
   str	r11,[r10]

   ldr	r10,=GPL2DAT
   mov	r11,#0x01
   str	r11,[r10]

   b	1b

       修改s3c4412_gpio.h

#ifndef S3C4412_GPIO_H
#define S3C4412_GPIO_H

#define GPX1CON (0x11000000+0x0c20)
#define GPX1DAT (0x11000000+0x0c24)
#define GPX1PUD (0x11000000+0x0c28)
#define GPX1DRV (0x11000000+0x0c2c)

#define GPK1CON (0x11000000+0x0060)
#define GPK1DAT (0x11000000+0x0064)
#define GPK1PUD (0x11000000+0x0068)
#define GPK1DRV (0x11000000+0x006c)

#define GPL2CON (0x11000000+0x0100)
#define GPL2DAT (0x11000000+0x0104)
#define GPL2PUD (0x11000000+0x0108)
#define GPL2DRV (0x11000000+0x010c)

#endif

       修改Makefile

CROSS_COMPILE = arm-linux-gnueabihf-
%.o : %.S
	$(CROSS_COMPILE)gcc -o $@ $< -c 
%.o : %.c
	$(CROSS_COMPILE)gcc -o $@ $< -c 

.PHONY: all
all : 	led.elf

led.elf : start.o myboot.lds
	$(CROSS_COMPILE)ld -T myboot.lds -o led.elf $^
	$(CROSS_COMPILE)objcopy -O binary led.elf led.bin
	$(CROSS_COMPILE)objdump -D led.elf > led.dis 

.PHONY : clean
clean:
	rm -rf *.o *.elf *.bin *.dis

       修改myboot.lds

SECTIONS
{
	. = 0x02023400;
	.text : {
		start.o
		* (.text)
	}
	.rodata ALIGN(4) : {
		* (.rodata*)
	}

	.data ALIGN(4) : {
		* (.data*)
	}
	.bss ALIGN(4) : {
		* (.bss)
		* (COMMON)
	}
}

修改完上诉文件使用指令make生成led.bin下面要用到

烧录SD卡:

       方法1:

       修改mkbl2.c

#include 
#include 
#include 

int main (int argc, char *argv[])
{
    FILE *fp;
    unsigned char src;
    char *buf, *a;
    int buf_len;
    int nbytes, file_len;
    unsigned int checksum = 0;
    int i;

    if (argc != 4) {
        printf("Usage: mkbl2    \n");
        return -1;
    }

    buf_len = atoi(argv[3]);
    buf = (char *)malloc(buf_len);
    memset(buf, 0x00, buf_len);

    fp = fopen(argv[1], "rb");
    if( fp == NULL) {
        printf("source file open error\n");
        free(buf);
        return -1;
    }

    fseek(fp, 0L, SEEK_END);
    file_len = ftell(fp);
    fseek(fp, 0L, SEEK_SET);

    nbytes = fread(buf, 1, file_len, fp);

    if (nbytes != file_len) {
        printf("source file read error\n");
        free(buf);
        fclose(fp);
        return -1;
    }

    fclose(fp);

    for(i = 0; i < (14 * 1024) - 4; i++)
        checksum += (unsigned char)(buf[i]);

    *(unsigned int*)(buf + i) = checksum;

    fp = fopen(argv[2], "wb");
    if (fp == NULL) {
        printf("destination file open error\n");
        free(buf);
        return -1;
    }

    a = buf;
    nbytes = fwrite(a, 1, buf_len, fp);

    if (nbytes != buf_len) {
        printf("destination file write error\n");
        free(buf);
        fclose(fp);
        return -1;
    }

    free(buf);
    fclose(fp);
    return 0;
}

用GCC编译工具编译上诉源码生成mkbl2校验和制作工具

gcc mkbl2.c -o mkbl2

制作BL2

./mkbl2 led.bin bl2.bin 14336

用ssh把bl1(E4412.S.BL1.SSCR.EVT1.1.bin)上传到leds文件夹内
插入SD卡并查看自己的盘符节点,我的是sdb,所以下面会用sdb,根据自己的实际情况更改盘符

df -l

sdb
清零SD卡中前1M的内容

dd if=/dev/zero of=/dev/sdb bs=512 seek=1 iflag=dsync oflag=dsync count=2048

烧写BL1

dd if=E4412.S.BL1.SSCR.EVT1.1.bin of=/dev/sdb bs=512 seek=1 iflag=dsync oflag=dsync 

烧写BL2

dd if=bl2.bin of=/dev/sdb bs=512 seek=17 iflag=dsync oflag=dsync

SD卡制作完毕,拔掉SD插入开发板观察现象

       方法2:

方法2非常简单,使用shell脚本,一行指令制作BL2并烧录进SD卡,下载sd_fuse压缩包,解压后用ssh上传到leds文件夹内,插入SD卡使用下列脚本命令烧录。

cd sd_fuse/itop4412
./sd_fusing.sh /dev/sdb ../../led.bin

现象:

ITOP4412裸机编程-点亮LED灯_第6张图片

源码获取:

可以加入群聊:667039215找群主获取
CSDN获取: leds压缩包
sd_fuse获取:sd_fuse压缩包
github下载:git clone https://github.com/HOU1354696096/ITOP4412.git

你可能感兴趣的:(嵌入式linux系统)