Linux bootloader全程详解(ARM S3C2410)

发布者:dadigt最新更新时间:2016-12-03 来源: eefocus关键字:Linux  bootloader  ARM  S3C2410 手机看文章 扫描二维码
随时随地手机看文章

写在前面:这篇文章已经写的很详细了。主要参考的就是正果过程,如果要是移植bootloader的话应该找一套现成的源码,至少我是这么认为的,虽然我还没有移植过。 

网上关于Linux的BOOTLOADER文章不少了,但是大都是vivi,blob等比较庞大的程序,读起来不太方便,编译出的文件也比较大,而且更多的是面向开发用的引导代码,做成产品时还要裁减,这一定程度影响了开发速度,对初学者学习开销也比较大,在此分析一种简单的BOOTLOADER,是在三星公司提供的S3C2410 BOOTLOADER上稍微修改后的结果,编译出来的文件大小不超过4k,希望对大家有所帮助.

1.几个重要的概念

  • COMPRESSED KERNEL and DECOMPRESSED KERNEL 
    压缩后的KERNEL,按照文档资料,现在不提倡使用DECOMPRESSED KERNEL,而要使用COMPRESSED KERNEL,它包括了解压器.因此要在ram分配时给压缩和解压的KERNEL提供足够空间,这样它们不会相互覆盖. 
    当执行指令跳转到COMPRESSED KERNEL后,解压器就开始工作,如果解压器探测到解压的代码会覆盖掉COMPRESSED KERNEL,那它会直接跳到COMPRESSED KERNEL后存放数据,并且重新定位KERNEL,所以如果没有足够空间,就会出错.

  • Jffs2 File System 
    可以使armlinux应用中产生的数据保存在FLASH上,我的板子还没用到这个.

  • RAMDISK 
    使用RAMDISK可以使ROOT FILE SYSTEM在没有其他设备的情况下启动.一般有两种加载方式,我就介绍最常用的吧,把COMPRESSED RAMDISK IMAGE放到指定地址,然后由BOOTLOADER把这个地址通过启动参数的方式ATAG_INITRD2传递给KERNEL.具体看代码分析.

  • 启动参数(摘自IBM developer) 
    在调用内核之前,应该作一步准备工作,即:设置 Linux 内核的启动参数。Linux 2.4.x以后的内核都期望以标记列表(tagged list)的形式来传递启动参数。启动参数标记列表以标记 ATAG_CORE 开始,以标记 ATAG_NONE 结束。每个标记由标识被传递参数的tag_header 结构以及随后的参数值数据结构来组成。数据结构 tag 和 tag_header 定义在 Linux 内核源码的include/asm/setup.h 头文件中. 
    在嵌入式 Linux 系统中,通常需要由 BOOTLOADER 设置的常见启动参数有:ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、ATAG_INITRD等。 
    (注)参数也可以用COMMANDLINE来设定,在我的BOOTLOADER里,我两种都用了.

2.开发环境和开发板配置: 
CPU:S3C2410,BANK6上有64M的SDRAM(两块),BANK0上有32M NOR FLASH,串口当然是逃不掉的.这样,按照数据手册,地址分配如下: 
0x4000_0000开始是4k的片内DRAM. 
0x0000_0000开始是32M FLASH 16bit宽度 
0x3000_0000开始是64M SDRAM 32bit宽度 
注意:控制寄存器中的BANK6和BANK7部分必须相同. 
0x4000_0000(片内DRAM)存放4k以内的BOOTLOADER IMAGE 
0x3000_0100开始存放启动参数 
0x3120_0000 存放COMPRESSED KERNEL IMAGE 
0x3200_0000 存放COMPRESSED RAMDISK 
0x3000_8000 指定为DECOMPRESSED KERNEL IMAGE ADDRESS 
0x3040_0000 指定为DECOMPRESSED RAMDISK IMAGE ADDRESS 
开发环境:Redhat Linux,armgcc toolchain, armlinux KERNEL

如何建立armgcc的编译环境:建议使用toolchain,而不要自己去编译armgcc,偶试过好多次,都以失败告终. 
先下载arm-gcc 3.3.2 toolchain 
将arm-linux-gcc-3.3.2.tar.bz2 解压到 /toolchain 
# tar jxvf arm-linux-gcc-3.3.2.tar.bz2 
# mv /usr/local/arm/3.3.2 /toolchain 
在makefile 中在把arch=arm CROSS_COMPILE设置成toolchain的路径 
还有就是INCLUDE = -I ../include -I /root/my/usr/local/arm/3.3.2/include.,否则库函数就不能用了

3.启动方式: 
可以放在FLASH里启动,或者用Jtag仿真器.由于使用NOR FLASH,根据2410的手册,片内的4K DRAM在不需要设置便可以直接使用,而其他存储器必须先初始化,比如告诉memory controller,BANK6里有两块SDRAM,数据宽度是32bit,= =.否则memory control会按照复位后的默认值来处理存储器.这样读写就会产生错误. 
所以第一步,通过仿真器把执行代码放到0x4000_0000,(在编译的时候,设定TEXT_BAS 
E=0x40000000) 。
第二步,通过 AxD把linux KERNEL IMAGE放到目标地址(SDRAM)中,等待调用 
第三步,执行BOOTLOADER代码,从串口得到调试数据,引导armlinux

4.代码分析 
讲了那么多执行的步骤,是想让大家对启动有个大概印象,接着就是BOOTLOADER内部的代码分析了,BOOTLOADER文章内容网上很多,我这里精简了下,删除了不必要的功能. 
BOOTLOADER一般分为2部分,汇编部分和c语言部分,汇编部分执行简单的硬件初始化,C部分负责复制数据,设置启动参数,串口通信等功能. 
BOOTLOADER的生命周期: 
1. 初始化硬件,比如设置UART(至少设置一个),检测存储器= =. 
2. 设置启动参数,这是为了告诉内核硬件的信息,比如用哪个启动界面,波特率 = =. 
3. 跳转到Linux KERNEL的首地址. 
4. 消亡 

当然,在引导阶段,象vivi等,都用虚地址,如果你嫌烦的话,就用实地址,都一样. 
我们来看代码: 
2410init.s 
.global _start//开始执行处 
_start: 
//下面是中断向量 
b reset @ Supervisor Mode//重新启动后的跳转 
…… 
…… 
reset: 
ldr r0,=WTCON /WTCON地址为53000000,watchdog的控制寄存器 */ 
ldr r1,=0x0 /*关watchdog*/ 
str r1,[r0] 

ldr r0,=INTMSK 
ldr r1,=0xffffffff /*屏蔽所有中断*/ 
str r1,[r0] 

ldr r0,=INTSUBMSK 
ldr r1,=0x3ff /*子中断也一样*/ 
str r1,[r0] 
/*Initialize Ports...for display LED.*/ 
ldr r0, =GPFCON 
ldr r1, =0x55aa 
str r1, [r0] 
ldr r0, =GPFUP 
ldr r1, =0xff 
str r1, [r0] 
ldr r0,=GPFDAT 
ldr r1,=POWEROFFLED1 
str r1,[r0] 
/* Setup clock Divider control register 
* you must configure CLKDIVN before LOCKTIME or MPLL UPLL 
* because default CLKDIVN 1,1,1 set the SDMRAM Timing Conflict 
nop 
* FCLK:HCLK:PCLK = 1:2:4 in this case 
*/ 
ldr r0,=CLKDIVN 
ldr r1,=0x3 
str r1,[r0] 

/*To reduce PLL lock time, adjust the LOCKTIME register. */ 
ldr r0,=LOCKTIME 
ldr r1,=0xffffff 
str r1,[r0] 
/*Configure MPLL */ 
ldr r0,=MPLLCON 
ldr r1,=((M_MDIV<<12)+(M_PDIV<<4)+M_SDIV) //Fin=12MHz,Fout=203MHz 
str r1,[r0] 
ldr r1,=GSTATUS2 
ldr r10,[r1] 
tst r10,#OFFRST

bne 1000f 
//以上这段,我没动,就用三星写的了,下面是主要要改的地方 
/* MEMORY C0NTROLLER(MC)设置*/ 
add r0,pc,#MCDATA - (.+8)// r0指向MCDATA地址,那里存放着MC初始化要用到的数据 
ldr r1,=BWSCON // r1指向MC控制器寄存器的首地址 
add r2,r0,#52 // 复制次数,偏移52字 

1: //按照偏移量进行循环复制 
ldr r3,[r0],#4 
str r3,[r1],#4 
cmp r2,r0 
bne 1b 
.align 2 

MCDATA: 
.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)
+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28)) 
上面这行就是BWSCON的数据,具体参数意义如下: 

需要更改设置DW6 和DW7都设置成10,即32bit,DW0 设置成01,即16bit 
下面都是每个BANK的控制器数据,大都是时钟相关,可以用默认值,设置完MC后,就跳到调用main函数的部分 
.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)
+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC)) 
.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)
+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC)) 
.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)
+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC)) 
.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)
+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC)) 
.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)
+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC)) 
.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)
+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC)) 
.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN)) 
.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN)) 
.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT) 
.word 0xB2 /* REFRESH Control Register */ 
.word 0x30 /* BANKSIZE Register : Burst Mode */ 
.word 0x30 /* SDRAM Mode Register */ 

.align 2 
.global call_main //调用main函数,函数参数都为0 
call_main: 
ldr sp,STACK_START 
mov fp,#0 /* no previous frame, so fp=0*/ 
mov a1, #0 /* set argc to 0*/ 
mov a2, #0 /* set argv to NUL*/ 
bl main /* call main*/ 
STACK_START: 
.word STACK_BASE 
undefined_instruction: 
software_interrupt: 
prefetch_abort: 
data_abort: 
not_used: 
irq: 
fiq: 
/*以上是主要的汇编部分,实现了时钟设置,串口设置watchdog关闭,中断关闭功能(如果有需要还可以降频使用),然后转入main*/ 
2410init.c file 
int main(int argc,char **argv) 

u32 test = 0; 
//压缩后的IMAGE地址
void (*theKERNEL)(int zero, int arch, unsigned long params_addr) = 
(void (*)(int, int, unsigned long))RAM_COMPRESSED_KERNEL_BASE; 
int i,k=0; 
// downPt=(RAM_COMPRESSED_KERNEL_BASE); 
chkBs=(_RAM_STARTADDRESS);//SDRAM开始的地方 
// fromPt=(FLASH_LINUXKERNEL); 
MMU_EnableICache(); 
ChangeClockDivider(1,1); // 1:2:4 
ChangeMPllvalue(M_MDIV,M_PDIV,M_SDIV); //Fin=12MHz FCLK=200MHz 
Port_Init();//设置I/O端口,在使用com口前,必须调用这个函数,否则通信芯片根本得不到数据 
Uart_Init(PCLK, 115200);//PCLK使用默认的200000,拨特率115200 
/*******************(检查ram空间)*******************/ 
Uart_SendString("\n\tLinux S3C2410 Nor BOOTLOADER\n"); 
Uart_SendString("\n\tChecking SDRAM 2410loader.c...\n"); 
for(;chkBs<0x33FA0140;chkBs=chkBs+0x4,test++)//

/* 
根据我的经验,最好以一个字节为递增,我们的板子,在256byte递增检测的时候是没问题的,但是以1byte递增就出错了,第13跟数据线随几的会冒”1”,检测出来是硬件问题,现象如下 
用仿真器下代码测试SDRAM,开始没贴28F128A3J FLASH片子,测试结果很好,但在上了FLASH片子之后,测试数据(data)为0x00000400连续成批写入读出时,操作大约1k左右内存空间就会出错,而且随机。那个出错数据总是变为0x00002400,数据总线10位和13位又没短路发生。用其他数据//测试比如0x00000200;0x00000800没这问题。dx帮忙。
至今没有解决,所以我用不了Flash. */


chkPt1 = chkBs; 
*(u32 *)chkPt1 = test;//写数据 
if(*(u32 *)chkPt1==1024))//读数据和写入的是否一样? 

chkPt1 += 4; 
Led_Display(1); 
Led_Display(2); 
Led_Display(3); 
Led_Display(4); 

else 
goto error; 

Uart_SendString("\n\tSDRAM Check Successful!\n\tMemory Maping..."); 
get_memory_map();

//获得可用memory 信息,做成列表,后面会作为启动参数传给KERNEL 
//所谓内存映射就是指在4GB 物理地址空间中有哪些地址范围被分配用来寻址系统的 RAM 单元。 
Uart_SendString("\n\tMemory Map Successful!\n"); 
/*我用仿真器把KERNEL,RAMDISK直接放在SDRAM上,所以下面这段是不需要的,但是如果KERNEL,RAMDISK在FLASH里,那就需要. */

/*******************(copy linux KERNEL)*******************/ 
Uart_SendString("\tLoading KERNEL IMAGE from FLASH... \n "); 
Uart_SendString("\tand copy KERNEL IMAGE to SDRAM at 0x31000000\n"); 
Uart_SendString("\t\tby LEIJUN DONG dongleijun4000@hotmail.com \n");

//3*1024*1024/32linux KERNEL des,src,length=3M
for(k = 0;k < 196608;k++,downPt += 1,fromPt += 1) 
* (u32 *)downPt = * (u32 *)fromPt;

/*******************(load RAMDISK)*******************/ 
Uart_SendString("\t\tloading COMPRESSED RAMDISK...\n"); 
downPt=(RAM_COMPRESSED_RAMDISK_BASE); 
fromPt=(FLASH_RAMDISK_BASE);

//3*1024*1024/32linux KERNEL des,src,length=3M
for(k = 0;k < 196608;k++,downPt += 1,fromPt += 1) 
* (u32 *)downPt = * (u32 *)fromPt;

/******jffs2文件系统,在开发中如果用不到FLASH,这段也可以不要********/

Uart_SendString("\t\tloading jffs2...\n"); 
downPt=(RAM_JFFS2); 
fromPt=(FLASH_JFFS2); 
for(k = 0;k < (1024*1024/32);k++,downPt += 1,fromPt += 1) 
* (u32 *)downPt = * (u32 *)fromPt; 
Uart_SendString( "Load Success...Run...\n ");

/*******************(setup param)*******************/ 
setup_start_tag();//开始设置启动参数 
setup_memory_tags();//内存印象 
setup_commandline_tag("console=ttyS0,115200n8");//启动命令行 
setup_initrd2_tag();//root device 
setup_RAMDISK_tag();//ramdisk image 
setup_end_tag();

/*关I-cache */ 
asm ("mrc p15, 0, %0, c1, c0, 0": "=r" (i)); 
i &= ~0x1000; 
asm ("mcr p15, 0, %0, c1, c0, 0": : "r" (i)); 
/* flush I-cache */ 
asm ("mcr p15, 0, %0, c7, c5, 0": : "r" (i));

//下面这行就跳到了COMPRESSED KERNEL的首地址 
theKERNEL(0, ARCH_NUMBER, (unsigned long *)(RAM_BOOT_PARAMS));

/*启动kernel时候,I-cache可以开也可以关,r0必须是0,r1必须是CPU型号 
(可以从linux/arch/arm/tools/mach-types中找到),r2必须是参数的物理开始地址*/
/*******************END*******************/ 
error: 
Uart_SendString("\n\nPanic SDRAM check error!\n"); 
return 0; 
}

static void setup_start_tag(void) 

params = (struct tag *)RAM_BOOT_PARAMS;//启动参数开始的地址 
params->hdr.tag = ATAG_CORE; 
params->hdr.size = tag_size(tag_core); 
params->u.core.flags = 0; 
params->u.core.pagesize = 0; 
params->u.core.rootdev = 0; 
params = tag_next(params); 



static void setup_memory_tags(void) 

int i; 

for(i = 0; i < NUM_MEM_AREAS; i++) { 
if(memory_map[i].used) { 
params->hdr.tag = ATAG_MEM; 
params->hdr.size = tag_size(tag_mem32); 
params->u.mem.start = memory_map[i].start; 
params->u.mem.size = memory_map[i].len; 
params = tag_next(params); 





static void setup_commandline_tag(char *commandline) 

int i = 0; 
/* skip non-existent command lines so the kernel will still 
* use its default command line. 
*/ 
params->hdr.tag = ATAG_CMDLINE; 
params->hdr.size = 8; 
//console=ttyS0,115200n8 
strcpy(params->u.cmdline.cmdline, p); 
params = tag_next(params); 



static void setup_initrd2_tag(void) 

/* an ATAG_INITRD node tells the kernel where the compressed 
* ramdisk can be found. ATAG_RDIMG is a better name, actually. 
*/ 
params->hdr.tag = ATAG_INITRD2; 
params->hdr.size = tag_size(tag_initrd); 
params->u.initrd.start = RAM_COMPRESSED_RAMDISK_BASE; 
params->u.initrd.size = 2047;//k byte 
params = tag_next(params); 
}


static void setup_ramdisk_tag(void) 

/* an ATAG_RAMDISK node tells the kernel how large the 
* decompressed ramdisk will become. 
*/ 
params->hdr.tag = ATAG_RAMDISK; 
params->hdr.size = tag_size(tag_ramdisk); 
params->u.ramdisk.start = RAM_DECOMPRESSED_RAMDISK_BASE; 
params->u.ramdisk.size = 7.8*1024; //k byte 
params->u.ramdisk.flags = 1; // automatically load ramdisk 
params = tag_next(params); 



static void setup_end_tag(void) 

params->hdr.tag = ATAG_NONE; 
params->hdr.size = 0; 
} void Uart_Init(int pclk,int baud)//串口是很重要的 

int i; 
if(pclk == 0) 
pclk = PCLK; 
rUFCON0 = 0x0; //UART channel 0 FIFO control register, FIFO disable 
rUMCON0 = 0x0; //UART chaneel 0 MODEM control register, AFC disable 

//UART0 
rULCON0 = 0x3; //Line control register : Normal,No parity,1 stop,8 bits 
下面这段samsung好象写的不太对,但是我按照Normal,No parity,1 stop,8 bits算出来的确是0x245 

// [10] [9] [8] [7] [6] [5] [4] [3:2] [1:0] 
// Clock Sel, Tx Int, Rx Int, Rx Time Out, Rx err, Loop-back, Send break, Transmit Mode, Receive Mode 
// 0 1 0 , 0 1 0 0 , 01 01 
// PCLK Level Pulse Disable Generate Normal Normal Interrupt or Polling 
rUCON0 = 0x245; // Control register 
rUBRDIV0=( (int)(PCLK/16./ baud) -1 ); //Baud rate divisior register 0 
delay(10); 
}

经过以上的折腾,接下来就是kernel的活了.能不能启动kernel,得看你编译kernel的水平了. 这个BOOTLOADER不象blob那样需要交互信息,使用虚拟地址,总的来说非常简洁明了.


关键字:Linux  bootloader  ARM  S3C2410 引用地址:Linux bootloader全程详解(ARM S3C2410)

上一篇:u-boot在s3c2410研发板上移植(NAND Flash Boot)过程
下一篇:关于linux的framebuffer和s3c2410的硬件接口与时序问题

推荐阅读最新更新时间:2024-03-16 15:22

为什么苹果和三星不买已垄断芯片市场的ARM
    本文来自爱范儿   早前软银(Softbank)提出以天价收购ARM后,这个貌似躲在幕后操控、掌握逾 4000 亿美元智能手机市场的“黑手”,突然浮出水面。但是,在大家突然发现这个的神秘存在体,突然就有各种不同的猜想:   有人觉得苹果在芯片设计上已经被软银掐住脖子,如果未来软银停止向苹果授权,则苹果的开发将会大受影响;   有分析师指觉得苹果被掐住咽喉了,所以苹果应该抢先一步先把ARM买到手;   有媒体觉得与其竞逐ARM,不如买ARM的替代MIPS;   为什么ARM在智能手机上扮演了如此重要的角色?根据ARM公司在2015年9月的资料,逾95%智能手机采用 ARM 处理器,在平板上的渗透率也超过85%。
[手机便携]
ARM汇编中的:比较指令CMN / CMP / TEQ / TST
1. 简介 CMP / CMN : 算术指令 TEQ / TST : 逻辑指令 它们总是会影响CPSR条件标志位. APSR(CPSR)与condition的关系图: 2. CMN -- 比较取负的值 CMN{条件}{P} op1 , op2 status = op1 - (-op2) 相加操作 CMN R0, #1 @把R0与-1进行比较 3. CMP CMP{条件}{P} op1 , op2 status = op1 - (op2) 相减操作 会影响标志位.
[单片机]
<font color='red'>ARM</font>汇编中的:比较指令CMN / CMP / TEQ / TST
Arm、高通等相继投入研发 智能手机自体AI化时代即将启航
不再依赖云端或服务器系统的智能手机,可以自己直接执行人工智能(AI)功能,未来也许不再是梦,因为一种“基于装置的机器学习”(on-device machine learning)时代正在开启。韩媒ChosunBiz引述业界消息,指出以2018年为起点,三星电子(Samsung Electronics)、华为与联发科等业者,预料将相继推出支持机器学习的移动应用处理器(AP)。   过去一段时间以来,机器学习多透过高阶中央处理器(CPU)、图形处理器(GPU)等复杂硬件实现。然而,高通(Qualcomm)从2015年开始,透过一项名为Zeroth的研发计划,期望利用移动系统单芯片(SoC),有效率且自动执行机器学习,目标是将机器学习芯
[半导体设计/制造]
一种基于ARM9的彩色TFT-LCD模块设计及实现
1 引 言 TFT-LCD因其厚度薄且画面质量优异,可以实现信息的高速度、高亮度及高对比度显示,已广泛应用于图像显示系统中。虽然TFT-LCD具有良好的显示性能,但TFT-LCD的驱动信号非常复杂,同时外围的控制单元需要处理的数据量非常大,以一个分辨率为640×480的彩色TFT-LCD为例,显示一幅彩色图像就需要处理900kbyte的数据量,这对于传统的单片机等处理器显得无能为力。由于图像数据量大,目前图像大都采用压缩后再存储,其中JPEG (Joint PhotographicExperts Group)格式的压缩图像应用最为广泛。 为了解决图像等大容量数据在TFT-LCD显示屏上的应用,本文提出了一种基于ARM9处理
[单片机]
一种基于<font color='red'>ARM</font>9的彩色TFT-LCD模块设计及实现
ARM裸机篇---启动代码分析
先搞清楚启动代码和Bootloader的区别,启动代码是指CPU复位后到进入C语言的main函数之前需要执行的那段汇编代码。 下面的代码先暂且这样吧,没啥注释的,时间关系,我还是先搞些应用再说^_^ ;========================================= ; NAME: 2410INIT.S ; DESC: C start up codes ; Configure memory, ISR ,stacks ; Initialize C-variables ; HISTORY: ; 2002.02.25:kwtark: ver 0.0 ; 2002.03.20:purnnamu: Add
[单片机]
ARM单片机入门-推荐
推荐书籍: Keil Cx51 V7.0单..用实践 深入浅出ARM7 ARM嵌入式系统基础教程 嵌入式Linux应用开发..手册 Windows CE嵌入式系统 Windows CE 嵌入式高级编程及其实例详解 ARM入门最好的文章 一 首先说说ARM的发展 可以用一片大好来形容,翻开各个公司的网站,招聘里面嵌入式占据了大半工程师职位。 广义的嵌入式无非几种:传统的什么51、AVR、PIC称做嵌入式微控制器;ARM是嵌入式微处理器;DSP;FPGA。 客观的讲,工作需求量上DSP的需求比ARM要多,而ARM和FPGA差不多。 DSP因为数字处理与通信领域的空前发展而火暴,小到MP3 射象头,大到我们**里的控
[单片机]
Google拟与ARM洽谈Android 3.0标准化
  据消息人士透露,Google正在考虑推动Android 3.0标准化,并希望新战略能解决操作系统的缺陷;Google还可能与ARM洽谈,专门针对ARM架构产品实现标准化。   目前,Android 3.0平板电脑在用户界面上存在一些缺陷,同时还缺少应用程序的支持。虽然Android市场有25万个应用程序,但是大多针对智能手机,只有少数程序能运行在大显示屏设备上,如平板电脑。   另外Google Books服务只在美国推出,而音乐服务还没有问世,缺少内容已经影响到了Android 3.0的开发工作。   消息人士称,通过将平台标准化,Google可以解决ARM架构升级困难问题,明显缩短下游合作伙伴研发周期,并提高产品质量。   
[手机便携]
Linux 2.6 内核的嵌入式系统应用
  随着多媒体技术与通讯技术相结合的信息技术的快速发展和互联网的广泛应用,PC 时代也过渡到了后PC时代。在数字信息技术和网络技术高速发展的后PC时代,嵌入式技术越来越与人们的生活紧密结合。   操作系统为用户使用计算机及其外部设备提供最基本的接口程序,管理计算机上的资源。随着应用领域的扩大,为了适应不同的应用场合,考虑到系统的灵活性、可伸缩性以及可裁剪性,一种以应用为中心、以计算机技术为基础、软硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗要求严格的专用计算机系统——嵌入式操作系统随之延生。   Linux 操作系统是一种性能优良、源码公开且被广泛应用的免费操作系统,由于其体积小、可裁减
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved