1)当前运行的二进制代码。该代码通常称之为text,所处的虚拟内存区域称之为text段。
2)程序使用的动态库的代码
3)用于保存全局变量和动态产生的数据的堆(应该还包括静态变量)
4)用于保存局部变量和实现函数/过程调用的栈。
5)环境变量和命令行参数的段
6)将文件内容映射到虚拟地址空间中的内存映射。
下图说明了大多数体系结构的虚拟地址地址空间中的布局情况。
text段如何映射到虚拟地址空间中由ELF标准确定。每个体系结构都指定了一个特定的起始地址:IA-32系统起始于0x08048000,在text段的起始地址与最低的可用地址之间有大约128M的间距,用于捕获NULL指针。其他体系结构也有类似的缺口:UltraSparc计算机使用0x100000000作为text段的起始点,而AMD64使用0x0000000000400000。堆紧接着text段开始,向上增长。
栈起始于STACK_TOP,如果设置了PF_RANDOMIZE,则起始点会减少一个小的随机值。每个体系结构都必须定义STACK_TOP,大多数都设置为TASK_SIZE,即用户地址空间中最高的可用地址。进程的参数列表和环境变量都是栈的初始数据。
用于内存映射的区域起始于mm_struct->mmap_base,通常设置为TASK_UNMAPPED_BASE,每个体系结构都需要定义。几乎所有的情况下,其值都是TASK_SIZE/3。要注意,如果使用内核的默认设置,则mmap区域的起始点不是随机的。
如果计算机提供了巨大的虚拟地址空间,那么使用上述的地址空间布局会工作得非常好。但在32位计算机上可能会出现问题。考虑IA-32的情况:虚拟地址空间从0到0xC0000000,每个用户进程有3G可用。TASK_UNMAPPED_BASE起始于0x40000000,即1G处。糟糕的是,这意味着堆只有1G空间可供使用,继续增长则会进入到mmap区域,这显然不是我们想要的。
问题在于,内存映射区域位于虚拟地址空间的中间。这也是在内核版本2.6.7开发期间为IA-32计算机引入一个新的虚拟地址空间布局的原因(经典布局仍然可以使用)。新的布局如下图所示:
其想法在于使用固定值限制栈的最大长度。由于栈是有界的,因此安置内存映射的区域可以在栈末端的下方立即开始。与经典方法相反,
该区域现在是自顶向下扩展。由于堆仍然位于虚拟地址空间中较低的区域并向上增长,因此mmap区域和堆可以相对扩展,直至耗尽虚拟地址空间中剩余的区域。为确保栈与mmap区域不发生冲突,两者之间设置了一个安全隙。
一、编写源程序(init.S、testledC.lds、testledC.c、Makefile)
@******************************************************************************
@ File:init.S
@ 功能:通过它转入C程序
@******************************************************************************
.text
.global _start
_start:
ldr r0, =0x53000000 @ WATCHDOG寄存器地址
mov r1, #0x0
str r1, [r0] @ 写入0,禁止WATCHDOG,否则CPU会不断重启
ldr sp, =1024*4 @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
@ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
bl main @ 调用C程序中的main函数
halt_loop:
b halt_loop
/***********************************
*功能:链接文件TestledC.lds
*************************************/
SECTIONS {
. = 0x00;
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata)}
.data ALIGN(4) : { *(.data) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}
SECTIONS {
. = 0x00;
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata)}
.data ALIGN(4) : { *(.data) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}
/**************************************
*编写testledC.c源程序
*************************************/
/*************************************************
* File: testledC.c
* funtion:stream light
* author:zhaochuang
* data: 2013.5.8
* vision 1.0
**************************************************/
#define rGPBCON (*(volatile unsigned *)0x56000010)
#define rGPBDAT (*(volatile unsigned *)0x56000014)
#define rGPBUP (*(volatile unsigned *)0x56000018)
void msdelay(int time)
{
volatile unsigned int i,j;
for(i=0;i<2000;i++)
for(j=0;j<time;j++);
}
void GPIO_init()
{
rGPBCON &= ~((3<<10)|(3<<12)|(3<<14)|(3<<16));
rGPBCON |= (1<<10)|(1<<12)|(1<<14)|(1<<16);
//rGPBCON = 0x15400;//0001 0101 0100 0000 0000
rGPBUP = 0xff;
}
void ledtestC()
{
volatile unsigned int i;
while(1)
{
for(i=0;i<4;i++)
{
rGPBDAT = 0x000;
rGPBDAT |=(1<<(5+i));
msdelay(5);
rGPBDAT &=~(1<<(5+i));
msdelay(5);
}
}
}
int main(int argc, char **argv)
{
GPIO_init();
ledtestC();
return 0;
}
/*************************************************/
/*********************************************************************************************
* File: int_test.c
* Author: Hanson
* 嵌入式家园 www.embedclub.com
* 上海嵌入式家园-开发板商城 http://embedclub.taobao.com
* Desc: LED test using c code
* History: May 16th 2011
*
*********************************************************************************************/
/*------------------------------------------------------------------------------------------*/
/* include files */
/*------------------------------------------------------------------------------------------
#define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
#define U32 unsigned long
#define LED1_ON ~(1<<5)
#define LED2_ON ~(1<<6)
#define LED3_ON ~(1<<7)
#define LED4_ON ~(1<<8)
#define LED1_OFF (1<<5)
#define LED2_OFF (1<<6)
#define LED3_OFF (1<<7)
#define LED4_OFF (1<<8)
void dely(U32 tt)
{
U32 i;
for(;tt>0;tt--)
{
for(i=0;i<10000;i++){}
}
}
int main()
{
rGPBCON &= ~((3<<10)|(3<<12)|(3<<14)|(3<<16));
rGPBCON |= (1<<10)|(1<<12)|(1<<14)|(1<<16);
rGPBDAT = rGPBDAT|(LED1_OFF)|(LED2_OFF)|(LED3_OFF)|(LED4_OFF);
while (1)
{
rGPBDAT = rGPBDAT&(LED1_ON);
dely(100);
rGPBDAT = rGPBDAT|(LED1_OFF)|(LED2_OFF)|(LED3_OFF)|(LED4_OFF);
dely(100);
rGPBDAT = rGPBDAT&(LED2_ON);
dely(100);
rGPBDAT = rGPBDAT|(LED1_OFF)|(LED2_OFF)|(LED3_OFF)|(LED4_OFF);
dely(100);
rGPBDAT = rGPBDAT&(LED3_ON);
dely(100);
rGPBDAT = rGPBDAT|(LED1_OFF)|(LED2_OFF)|(LED3_OFF)|(LED4_OFF);
dely(100);
rGPBDAT = rGPBDAT&(LED4_ON);
dely(100);
rGPBDAT = rGPBDAT|(LED1_OFF)|(LED2_OFF)|(LED3_OFF)|(LED4_OFF);
dely(100);
}
}
***********************************************************************/
/*********************************************************************************
*Makefile编写规则
***********************************************************************************/
CFLAGS := -Wall -O2
testledC.bin : init.S testledC.c
arm-linux-gcc $(CFLAGS) -c -o init.o init.S
arm-linux-gcc $(CFLAGS) -c -o testledC.o testledC.c
arm-linux-ld -TtestledC.lds init.o testledC.o -o testledC_elf
arm-linux-objcopy -O binary -S testledC_elf testledC.bin
arm-linux-objdump -D -m arm testledC_elf > testledC.dis
clean:
rm -f testledC.bin testledC_elf testledC.dis *.o
二、使用在lunux下make,生成可执行文件testled.bin
三、下载testledC.bin到开发板中
1、使用supervivi 下载,打到NOR命令行,-v
2、使用DNW下载二进制testledC.bin文件到开发板中
3、拨到Nand flash 下,重启开发板即可
快捷键 1 复制粘贴 用Ctrl-@ 设置起点, 然后移动光标到终点, 为了确认你的起点和终点,可以用 C-x C-x 将光标在起点和终点间切换,如果没问题了,可以用 Alt-w 来复制。 用 C-y 来来黏贴 2 取消 Ctrl-x u 3 打开或创建buffer Ctrl-x Ctrl-f 4 关闭 Ctrl-x Ctrl-c 5 删除到行尾 Ctrl-k 6 只保留当前窗口 Ctrl-x 1 7 横向切分窗口 Ctrl-x 2 8 纵向切分窗口 Ctrl-x 3 9 切换buffer Ctrl-x b