-在烧写Flash时,需要按照事先规划进行具体烧写
-在uboot程序中可以读到这部分内容,也就是Flash区的划分
-这部分区域最好是以页为单位,对应内存中相应的变量,因为Flash擦除是以页为单位的,所以在修改其中一部分内容时,需要将整个页读出来到内存,在内存中修改,然后整个页写回;,一般对于重要数据还要保留至少一个备份(因Flash容易出坏块)
-在划分好区域后,在程序中写专用的程序进行Flash数据的读取、擦除、写这些 *** 作
Author:杨正date:2016921
目的
在u-boot中添加驱动程序。
详细举例介绍
在uboot中 *** 作寄存器,实现对gpio及外围设备的控制有两种方法,一种是直接在arch/arm/lib/boardc中添加对寄存器的 *** 作代码,如:
#define muxctrl_reg5 0x200f0014#define GPIO6_DIR 0x201a0400#define GPIO6_1_DATA 0x201a0008 #define GPIO6_1 (1 << 1)#define readl(addr) ((volatile unsigned int)(addr))#define writel(val, addr) (((volatile unsigned int ) (addr)) = (val)) int clear_irled(void){ unsigned int reg_val; reg_val = writel(0, muxctrl_reg5); // set gpio mode reg_val = readl(GPIO6_DIR); reg_val |= GPIO6_1; writel(reg_val, GPIO6_DIR); reg_val = readl(GPIO6_1_DATA); reg_val &= ~GPIO6_1; writel(reg_val, GPIO6_1_DATA); return 0;}void start_armboot (void){ init_fnc_t init_fnc_ptr; char s;#ifdef CONFIG_HAS_SLAVE char e;#endif#if defined(CONFIG_VFD) || defined(CONFIG_LCD) unsigned long addr;#endif #ifdef CONFIG_HI3516A // defined in the include/configs/hi3516ah clear_irled(); // clear ir led, add by yangzheng 2016921#endif
来自CODE的代码片
snippet_file_0txt
另一种方法:
1、在driver/下新建hi_gpio目录,如:
[yangzheng@centos6 hi_gpio]$ ls
hi_gpioc Makefile
hi_gpioc内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[yangzheng@centos6 hi_gpio]$ cat hi_gpioc/ Copyright: (C) 2016 Yang Zheng<Zhengyang@avatarcontrolscom> All rights reserved Filename: hi_gpioc Description: This file Version: 100(09/21/2016~) Author: Yang Zheng <zhengyang@avatarcontrolscom> ChangeLog: 1, Release initial version on "09/21/2016 05:41:41 PM" /#include<commonh> #define readl(addr) ((volatile unsigned int ) (addr))#define writel(val, addr) ((volatile unsigned int ) (addr) = (val)) #define muxctrl_reg5 0x200f0014#define GPIO6_DIR 0x201a0400#define GPIO6_1_DATA 0x201a0008#define GPIO6_1 1 << 1#define REG_SET 1#define REG_CLR 0 #ifdef DEBUG#define DPRINTF(args) printf(args)#else#define DPRINTF(args)#endif int clear_irled(void){ unsigned int reg_val; reg_val = writel(REG_CLR, muxctrl_reg5); // set gpio mode reg_val = readl(GPIO6_DIR); reg_val |= GPIO6_1; writel(reg_val, GPIO6_DIR); writel(REG_CLR, GPIO6_1_DATA); DPRINTF("clear ir led\n"); return 0;}
来自CODE的代码片
snippet_file_0txt
Makefile如下(可以拷贝driver目录下的各模块模板):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
[yangzheng@centos6 hi_gpio]$ cat Makefile## Copyright 2000-2008# Wolfgang Denk, DENX Software Engineering, wd@denxde## See file CREDITS for list of people who contributed to this# project## This program is free software; you can redistribute it and/or# modify it under the terms of the GNU General Public License as# published by the Free Software Foundation; either version 2 of# the License, or (at your option) any later version## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE See the# GNU General Public License for more details## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc, 59 Temple Place, Suite 330, Boston,# MA 02111-1307 USA# include $(TOPDIR)/configmk LIB := $(obj)libhi_gpioa COBJS-$(CONFIG_HI3516A_GPIO) += hi_gpioo COBJS := $(COBJS-y)SRCS := $(COBJS:o=c)OBJS := $(addprefix $(obj),$(COBJS)) all: $(LIB) $(LIB): $(obj)depend $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) ######################################################################### # defines $(obj)depend targetinclude $(SRCTREE)/rulesmk sinclude $(obj)depend ########################################################################
来自CODE的代码片
snippet_file_0txt
2、在顶层Makefile添加如下代码:
LIBS += drivers/hi_gpio/libhi_gpioa
3、在include/configs/hi3516ah中添加如下代码:
#define CONFIG_HI3516A_GPIO
在include下增加hi_gpioh文件,内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[yangzheng@centos6 u-boot-201006]$ cat include/hi_gpioh/ Copyright: (C) 2016 Yang Zheng<Zhengyang@avatarcontrolscom> All rights reserved Filename: hi_gpioh Description: This head file is control hisi gpio Version: 100(09/21/2016~) Author: Yang Zheng <zhengyang@avatarcontrolscom> ChangeLog: 1, Release initial version on "09/21/2016 06:09:49 PM" /#ifndef __HI_GPIO_H__#define __HI_GPIO_H__ extern int clear_irled(void);#endif
来自CODE的代码片
snippet_file_0txt
4、在arch/arm/lib/boardc 里面调用即可,如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[yangzheng@centos6 u-boot-201006]$ vim arch/arm/lib/boardc void start_armboot (void){ init_fnc_t init_fnc_ptr; char s;#ifdef CONFIG_HAS_SLAVE char e;#endif#if defined(CONFIG_VFD) || defined(CONFIG_LCD) unsigned long addr;#endif #ifdef CONFIG_HI3516A_GPIO clear_irled(); // clear ir led, add by yangzheng 2016921#endif……
来自CODE的代码片
snippet_file_0txt
重新编译即可,调试uboot的方法:
如果设备有网口,可用tftp服务下载:
sf probe 0
mwb 82000000 ff 0x80000
tftp 82000000 u-bootbin
Go 82000000
如果没有网口,可用串口下载:
sf probe 0
mwb 82000000 ff 0x80000
loady 82000000 u-bootbin
go 82000000
本人用的android平台用的bootloader用的是uboot,貌似大多数手持设备平台都不用这个,因为功能过于强大用不上,反而显得太复杂了。不知道这个平台开发者是怎么想的。既然用了那就来分析一下,顺便修改一下其中的几个小问题,以符合我们的要求。
uboot等同于其他所有的bootloader程序,从根本上讲是一个稍复杂的裸机程序,是最底层的东西,要分析裸机程序我们要从它的连接文件开始。连 接文件(lds文件)定义了程序编译之后整个连接过程,这样我们就可以找到这个程序的第一句汇编代码,进而来下一步分析。uboot的链接文件代码在 android\bootable\bootloader\uboot-imx\u-bootlds
[cpp] view plaincopy
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") //文件输出格式
OUTPUT_ARCH(arm)
ENTRY(_start) //首地址标示符
SECTIONS
{
= 0x00000000; //其实地址0
= ALIGN(4); //4字节对齐
text : //代码段
{
board/freescale/mx6q_sabresd/flash_headero (textflasheader) //第一个文件是board/freescale/mx6q_sabresd/flash_headero
cpu/arm_cortexa8/starto //第二个cpu/arm_cortexa8/starto
board/freescale/mx6q_sabresd/libmx6q_sabresda (text)
lib_arm/libarma (text)
net/libneta (text)
drivers/mtd/libmtda (text)
drivers/mmc/libmmca (text)
= DEFINED(env_offset) env_offset : ;
common/env_embeddedo(text)
(text) //剩余的所有代码
}
= ALIGN(4);
rodata : { (SORT_BY_ALIGNMENT(SORT_BY_NAME(rodata))) } //readonly data 段
= ALIGN(4);
data : { (data) } //所有的readonly data
= ALIGN(4);
got : { (got) }
= ;
__u_boot_cmd_start = ; //u_boot_cmd段,里面是所有uboot命令的一个列表
u_boot_cmd : { (u_boot_cmd) }
__u_boot_cmd_end = ;
= ALIGN(4);
_end_of_copy = ;
__bss_start = ; //bss段 就是内存数据段
bss : { (bss) }
_end = ;
}
从上面的代码可以看出我们编译生成的二进制应用程序组成是:代码段->rodata段->uboot命令列表->bss段。我们启动这个应用程序时候是从,0地址开始的,因此我们来看
board/freescale/mx6q_sabresd/flash_headers这个文件。
这个文件中除了分配内存和宏定义的伪汇编指令以外,真正执行的命令有一条
[cpp] view plaincopy
section "textflasheader", "x"
b _start
org CONFIG_FLASH_HEADER_OFFSET
也就是说,这个文件一执行就直接跳到_start 位置处。_start 在android\bootable\bootloader\uboot-imx\cpu\arm_cortexa8\ startS中,因此我们来看这个文件代码
[cpp] view plaincopy
globl _start
_start: b reset
这里直接跳转的reset中接下来看
[csharp] view plaincopy
reset:
/
set the cpu to SVC32 mode cpu设置成32位管理模式
/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr,r0
#if (CONFIG_OMAP34XX) //因为我们的cpu不是ompa的 所以这段不会编译
#endif
/ the mask ROM code should have PLL and others stable /
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
#endif
这里接下来执行cpu_init_crit
[csharp] view plaincopy
/
CPU_init_critical registers
setup important registers
setup memory timing
/
cpu_init_crit:
/
Invalidate L1 I/D
/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
/
disable MMU stuff and caches //关闭mmu
/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB
mcr p15, 0, r0, c1, c0, 0
/
Jump to board specific initialization
The Mask ROM will have already initialized
basic memory Go here to bump up clock rate and handle
wake up conditions
/
mov ip, lr @ persevere link reg across call
bl lowlevel_init @ go setup pll,mux,memory//执行lowlevel_init这个函数代码在
@\bootloader\uboot-imx\board\freescale\mx6q_sabresd\lowlevel_initS中
@主要对时钟,外部ram,rom等进行了初始化代码不贴了。
mov lr, ip @ restore link
mov pc, lr @ back to my caller
初始化完成后,接下来执行
[csharp] view plaincopy
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: @ relocate U-Boot to RAM 将uboot重新定位到内存中
adr r0, _start @ r0 <- current position of code
ldr r1, _TEXT_BASE @ test if we run from flash or RAM
cmp r0, r1 @ don't reloc during debug测试当前代码是否已经在内存中
beq stack_setup @如果在的话就直接跳转到stack_setup
ldr r2, _armboot_start @如果不在的话,加载_armboot_start地址到r2中。_armboot_start是uboot执行的主体c函数。
ldr r3, _bss_start
sub r2, r3, r2 @ r2 <- size of armboot计算bss_start-armboot_start 保存到R2中,也就是uboot的总大小
add r2, r0, r2 @ r2 <- source end address 计算出uboot代码和rodata地址
copy_loop: @ copy 32 bytes at a time //开始拷贝
ldmia r0!, {r3 - r10} @ copy from source address [r0]
stmia r1!, {r3 - r10} @ copy to target address [r1]
cmp r0, r2 @ until source end addreee [r2]
ble copy_loop
#endif / CONFIG_SKIP_RELOCATE_UBOOT /
以上就是关于嵌入式arm/linux应用程序开发中,有时要在flash某一段固定的地址空间存放一些特定数据,或全部的内容,包括:嵌入式arm/linux应用程序开发中,有时要在flash某一段固定的地址空间存放一些特定数据,或、如何在uboot中添加驱动程序、android怎么进入uboot等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)