參考博文:
ITOP4412裸機開發—LED
tiny4412裸機程序之點燈
文章目錄
前言:
這是我的第一篇博客,不足之處還請批評指正,涉及侵權問題請與我聯繫,轉載註明出處即可。
本文介紹用SD卡啓動的裸機編程,學會這個裸機編程,移植uboot之類的也不再話下了,由於Exynos4412這個芯片有兩種封裝方式pop和scp,這兩個芯片對應着不同的BL1,盲目燒寫錯的BL1可能實現不了目標,詳細實現功能請向下翻閱,博主的板子是迅爲的精英板4412 pop1G
封裝。
啓動原理:
圖片是迅爲提供的uboot文檔中截的,從圖中看開發板在上電時會經過以上三個步驟,就是圖中的圓圈中的123了,第一步,開發板上電會去執行IROM,這個IROM會由OM的控制決定從哪個介質開始引導加載程序。
如圖由五位二進制編碼決定,詳細不再講,我們這裏講SD卡啓動,就將開發板的撥碼開關撥到SD卡啓動。第二步,程序會從SD卡中加載第一段代碼BL1到IRAM中;第三步,OS系統會被加載到DRAM中,至此引導結束。
但是這個地方有個問題,第一步和第二步都對,但是第三步,BL1會從SD卡中的第18個扇區開始讀取16K代碼到internal SRAM中並跳轉到這段代碼的起始位置。如下圖第一個:
加載的這個BL2實際上是uboot的前16K,uboot後面的大部分代碼會被BL2加載到DRAM中,然後跳轉到DRAM中uboot開始的位置開始執行,我們這裏講裸機程序,實際上就是把BL2替換成裸機程序,但是這個裸機程序必須小於14K,爲什麼要小於14K呢?如下圖BL2的結構:
如圖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寄存器,保證電源管理芯片正常工作,0x11000c80是GPX0組控制上下拉的寄存器,防止檢測TF是否插入導致復位。
#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 <stdio.h>
#include <string.h>
#include <stdlib.h>
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 <source file> <destination file> <size> \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
清零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
現象:
源碼獲取:
可以加入羣聊:667039215找羣主獲取
CSDN獲取:leds壓縮包
sd_fuse壓縮包
github下載:git clone https://github.com/HOU1354696096/ITOP4412.git