赞
踩
进行裸机编程的前提条件
1)U-boot启动 ,但是没有自动启动linux (在3秒倒计时中 ,打断自动启 动)
2)U-boot 提供自己的命令行
Hit any key to stop autoboot: 0
GEC6818#
3)电脑 ----> 开发板上 (串口 、网口)需要配置好对应接口
4)了解6818芯片手册、查看电路图、查找对应配置方法、写代码,arm-linux-gcc编译,再传递到开发板上(EMMC ? DDR3?)
开发板的内存映射图
什么是裸机编程?我认为就是不跑系统,直接基于地址进行编程控制芯片就是裸机编程,比方说要点灯的话 那么我们首先得了解一下芯片的内存映射。
GEC6818芯片为S5PV6818,我们找到
《SEC_S5P6818X_Users_Manual_preliminary_Ver_0.00.pdf》找到memory map 就是P590-P592,然后如下图
描述了内存分布
MCU -S bank ---- NAND / eMMC (0X0000 0000 ~ 0X3FFF FFFF)1G
MCU -A bank ---- DDR3 (0X4000 0000 ~ 0XBFFF FFFF) 2G
GPIO (0XC000 0000 ~ 0XDFFF FFFF) 512M
保留区域 (0XE000 0000 ~ 0XFFFE FFFF) 512M-64K
Internal SRAM (0XFFFF 0000 ~ 0XFFFF FFFF) ---- 64K
接着我们找到GPIO是在0XC000 0000 上,所以我们接下来再跳到芯片手册的GPIO看一下
GPIO相关寄存器设置
1)配置输入输出模式:按组的pin号进行分配, 一共有32个引脚,对应为为0 表示是输入, 为1 表示输出
可以看到偏移地址就是基于基地址0XC001 0000上的
2)输出控制, 高电平和低电平
3) 输出引脚的复用功能选择
ALTFN0 对应的是GPIOX0~GPIOX15 每个引脚的状态用了2bits来表示
ALTFN1 对应的是GPIOX16~GPIOX31 每个引脚的状态用了2bits来表示
4)得到引脚的输入值
5)常用以下写法表示寄存器
(*(volatile unsigned int *) 0xC001E000)
volatile – 直接去寄存器得到当前的寄存器值,而不是用内存中的缓存值,避免编译器优化
unsigned int 寄存器是32位的
(volatile unsigned int ) 0xC001E000 把这个值当成是地址
((volatile unsigned int *) 0xC001E000) 往该地址中写入对应的参数
6)复用功能的选择
注意:BALL不是GPIONX号!! BALL是芯片的焊盘号
需要找GPIOE13(LED对应IO口),确定是属于对应BALL哪个复用功能(funtion0),再直接设置到代码中。
可以看到焊盘E14的这个引脚的AF功能0是GPIOE13(我们需要这个)
写裸机程序
#define GPIOEOUT (*(volatile unsigned int )0xC001E000)
#define GPIOEOUTENB ((volatile unsigned int )0xC001E004)
#define GPIOEALTFN0 ((volatile unsigned int )0xC001E020)
#define GPIOEALTFN1 ((volatile unsigned int *)0xC001E024)
void delay(int val);
void _start(void) //C程序的入口,写在源文件的开始。裸机程序不能使用libc
{
GPIOEALTFN0 &= ~(3<<26); //function0–GPIOE13
GPIOEOUTENB |= (1<<13);//GPIOE13–OUTOPUT
while(1)
{
GPIOEOUT &= ~(1<<13);//GPIOE13 output 0
delay(0x4000000);
GPIOEOUT |= (1<<13);//GPIOE13 output 1
delay(0x4000000);
}
}
void delay(int val)
{
volatile int i=val;
while(i–);
}
这里没有main()函数 取之而来的是_start()函数,事实上,在我们平常用的C库里面,就是调用了_start()函数,然后_start()函数在内部跳转到main()函数的,或者在stm32中的start_upxxx.s里面是用汇编指定了__main()函数的。上面的程序就用到了刚刚贴的寄存器,都是基于0xC001E000这个地址偏移的
写一个Makefile
GCC=arm-linux-gnueabi
led.bin: led.o
$(GCC)-ld -Ttext 0x40000000 -o led.elf $^
$(GCC)-objcopy -O binary led.elf led.bin
$(GCC)-objdump -D led.elf > led.dis
%.o : %.S
$(GCC)-gcc -o $@ $< -c -nostdlib
%.o : %.c
$(GCC)-gcc -o $@ $< -c -nostdlib -O3
clean:
rm *.o *.elf *.bin *.dis -f
其中.dis文件为反汇编文件
把代码放到指定内存中的位置
使用网线传输
1)设置开发板上的网络配置
通过u-boot命令行设置环境变量,配置开发板的IP \ TFTP服务器IP \网关
GEC6818# setenv ipaddr 192.168.21.6 — 开发板的IP
GEC6818# setenv serverip 192.168.21.2 — window TFTP IP
GEC6818# setenv gatewayip 192.168.21.1 — 网关IP
GEC6818# saveenv ----- 保存以上参数,令其生效
Saving Environment to MMC… — 把数据写入到“硬盘”
Writing to MMC(2)… done
2) 可以通过printenv查看对应的环境信息
GEC6818# printenv
baudrate=115200
bootargs=lcd=at070tn92 tp=ft5x06-linux root=/dev/mmcblk0p2 rw rootfstype=ext4 cam=OV5645
bootcmd=ext4load mmc 2:1 0x48000000 uImage;bootm 0x48000000
bootdelay=3 ----- 3秒倒计时
bootfile=uImage
ethact=dwmac.c0060000
ethaddr=00:e2:1c:ba:e8:60
ethprime=RTL8211
fastboot=flash=mmc,2:GECuboot:2nd:0x200,0x78000;flash=mmc,2:2ndboot:2nd:0x200,0x4000;flash=mmc,2:bootloader?0x8000,0x70000;flash=mmc,2?ext4:0x00100000,0x04000000;flash=mmc,2:system:ext4:0x04100000,0x2F200000;flash=mmc,2:cache:ext4:0x33300000,0x1AC00000;flash=mmc,2:misc:emmc:0x4E000000,0x00800000;flash=mmc,2:recovery:emmc:0x4E900000,0x01600000;flash=mmc,2:userdata:ext4:0x50000000,0x0;
filesize=41ee8
gatewayip=192.168.21.1 --网关IP
ipaddr=192.168.21.6 – 自身IP
netmask=255.255.255.0
qtcrc=-2031518379
serverip=192.168.21.2 — tftp服务器IP
stderr=serial
stdin=serial
stdout=serial
Environment size: 853/32764 bytes
3)运行windows中的TFTPF服务器软件,并选中到对应的bin所在目录
4) 在开发板上执行TFTP命令
格式: tftp [存放在DDR3中的0x40000000] [TFTP服务器目录下的文件名]
GEC6818# tftp 0x40000000 led.bin
Speed: 1000, full duplex
Using dwmac.c0060000 device
TFTP from server 192.168.21.2; our IP address is 192.168.21.6
Filename ‘led.bin’.
Load address: 0x40000000
Loading: #
38.1 KiB/s
done
Bytes transferred = 156 (9c hex)
5) 在开发板上指向go命令
go 0x40000000 从0x40000000开始执行
此时灯亮
7.操作常见问题
1)TFTP 传输不了, 一直等待”TTTTTTTT”关闭笔记本电脑WIFI ,关闭防火墙
8.关于烧机(非常不推荐)
A:确定“-驱动\GEC6818系统恢复\GEC6818-fastboot恢复\镜像文件\linux-qt”目录(我自己的)下有fastboot.exe
B: 在开发板启动的时候进入u-boot
在uboot命令行 键入”fastboot”
打印出对应EMMC上的存放分区
GEC6818# fastboot
Writing to MMC(2)… done
Fastboot Partitions:
mmc.2: GECuboot, img : 0x200, 0x78000 在mmc中有个区域叫GECuboot ,数据格式是img, 起始地址和区域大小 —>uboot
mmc.2: 2ndboot, img : 0x200, 0x4000
mmc.2: bootloader, img : 0x8000, 0x70000
mmc.2: boot, fs : 0x100000, 0x4000000 在mmc中有个区域叫boot ,数据格式是fs, 起始地址和区域大小 --》kernel
mmc.2: system, fs : 0x4100000, 0x2f200000 在mmc中有个区域叫boot ,数据格式是fs, 起始地址和区域大小 --》rootfs
C: 此时接上micro usb到OTG USB 口(安卓口)
确保驱动安装完成
如果没有可以选择“驱动人生”等软件自动安装
D: 在“-驱动\GEC6818系统恢复\GEC6818-fastboot恢复\镜像文件\linux-qt”目录下
确认是否有 ubootpak.bin 、boot.img 、qt-rootfs.img 、fastboot.exe
在该目录下把以下内容写入到一空白文件中, 保存为”auto.bat”
fastboot flash GECuboot ubootpak.bin
fastboot flash boot boot.img
fastboot flash system qt-rootfs.img
fastboot reboot
双击运行auto.bat, 观察命令窗口是否有提示,说明是完成了或者是出错了
E: 开发板重启后,拔了MICRO USB , 在uboot命令行依次输入
setenv bootcmd “ext4load mmc 2:1 0x48000000 uImage;bootm 0x48000000”
Save
再次重启就能正常工作了
设置了bootcmd — 启动的命令,就是没有进入,autoboot时候执行的命令
ext4load mmc 2:1 0x48000000 uImage 把mmc 2:1中的内容以uImage格式解压到内存的0x48000000,
bootm 0x48000000 从0x48000000 开始启动
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。