arm Linux系统启动之start_kernel函数

发布者:pingbashou最新更新时间:2016-06-16 来源: eefocus关键字:arm  Linux系统  start_kernel函数 手机看文章 扫描二维码
随时随地手机看文章
head-common.S
---具体做了哪些动作
---跳转到init/main.c 
---b start_kernel
//关于start_kernel的强文深入理解linux内核,第八章
main.c
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern struct kernel_param __start___param[], __stop___param[];
//来设置smp process id,当然目前看到的代码里面这里是空的
smp_setup_processor_id();
/*
* Need to run as early as possible, to initialize the
* lockdep hash:
*/
//lockdep是linux内核的一个调试模块,用来检查内核互斥机制尤其是自旋锁潜在的死锁问题。
//自旋锁由于是查询方式等待,不释放处理器,比一般的互斥机制更容易死锁,
//故引入lockdep检查以下几种情况可能的死锁(lockdep将有专门的文章详细介绍,在此只是简单列举):
//
//·同一个进程递归地加锁同一把锁;
//
//·一把锁既在中断(或中断下半部)使能的情况下执行过加锁操作,
// 又在中断(或中断下半部)里执行过加锁操作。这样该锁有可能在锁定时由于中断发生又试图在同一处理器上加锁;
//
//·加锁后导致依赖图产生成闭环,这是典型的死锁现象。
lockdep_init();
debug_objects_early_init();
/*
* Set up the the initial canary ASAP:
*/
//初始化stack_canary栈3
//stack_canary的是带防止栈溢出攻击保护的堆栈。
//  当user space的程序通过int 0x80进入内核空间的时候,CPU自动完成一次堆栈切换, 
//从user space的stack切换到kernel space的stack。
//   在这个进程exit之前所发生的所有系统调用所使用的kernel stack都是同一个。
//kernel stack的大小一般为4096/8192,
//内核堆栈示意图帮助大家理解:
//
//   内存低址                                                              内存高址
//                      |                 |<-----------------------------esp|   
//   +-----------------------------------4096-------------------------------+
//   |        72        |     4           |       x < 4016    |     4       |
//   +------------------+-----------------+---------------------------------+
//   |thread_info  |    | STACK_END_MAGIC |   var/call chain  |stack_canary |
//   +------------------+-----------------+---------------------------------+
//   |     28      | 44 |                 |                                 |
//                 V    |                                                   |
//             restart_block                                                V
//
//esp+0x0                                                                   +0x40
//    +---------------------------------------------------------------------------+
//    |ebx|ecx|edx|esi|edi|ebp|eax|ds|es|fs|gs|orig_eax|eip|cs|eflags|oldesp|oldss|
//    +---------------------------------------------------------------------------+
//    |             kernel完成                          |         cpu自动完成       |
//http://hi.baidu.com/wzt85/blog/item/112a37132f6116c2f6039e44.html
boot_init_stack_canary(); 
// cgroup: 它的全称为control group.即一组进程的行为控制.
// 比如,我们限制进程/bin/sh的CPU使用为20%.我们就可以建一个cpu占用为20%的cgroup.
// 然后将/bin/sh进程添加到这个cgroup中.当然,一个cgroup可以有多个进程.
//http://blogold.chinaunix.net/u1/51562/showart_1736813.html
cgroup_init_early();
//更新kernel中的所有的立即数值,但是包括哪些需要再看?
core_imv_update();
//关闭当前CUP中断
local_irq_disable();
//修改标记early_boot_irqs_enabled;
//通过一个静态全局变量 early_boot_irqs_enabled来帮助我们调试代码,
//通过这个标记可以帮助我们知道是否在”early bootup code”,也可以通过这个标志警告是有无效的终端打开
early_boot_irqs_off();
//每一个中断都有一个IRQ描述符(struct irq_desc)来进行描述。
//这个函数的主要作用是设置所有的 IRQ描述符(struct irq_desc)的锁是统一的锁,
//还是每一个IRQ描述符(struct irq_desc)都有一个小锁。
early_init_irq_lock_class();
/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
// 大内核锁(BKL--Big Kernel Lock)
//大内核锁本质上也是自旋锁,但是它又不同于自旋锁,自旋锁是不可以递归获得锁的,因为那样会导致死锁。
//但大内核锁可以递归获得锁。大内核锁用于保护整个内核,而自旋锁用于保护非常特定的某一共享资源。
//进程保持大内核锁时可以发生调度,具体实现是:
//在执行schedule时,schedule将检查进程是否拥有大内核锁,如果有,它将被释放,以致于其它的进程能够获得该锁,
//而当轮到该进程运行时,再让它重新获得大内核锁。注意在保持自旋锁期间是不运行发生调度的。
//需要特别指出,整个内核只有一个大内核锁,其实不难理解,内核只有一个,而大内核锁是保护整个内核的,当然有且只有一个就足够了。
//还需要特别指出的是,大内核锁是历史遗留,内核中用的非常少,一般保持该锁的时间较长,因此不提倡使用它。
//从2.6.11内核起,大内核锁可以通过配置内核使其变得可抢占(自旋锁是不可抢占的),这时它实质上是一个互斥锁,使用信号量实现。
//大内核锁的API包括:
//
//void lock_kernel(void);
//
//该函数用于得到大内核锁。它可以递归调用而不会导致死锁。
//
//void unlock_kernel(void);
//
//该函数用于释放大内核锁。当然必须与lock_kernel配对使用,调用了多少次lock_kernel,就需要调用多少次unlock_kernel。
//大内核锁的API使用非常简单,按照以下方式使用就可以了:
//lock_kernel(); //对被保护的共享资源的访问 … unlock_kernel();
//http://blog.csdn.net/universus/archive/2010/05/25/5623971.aspx
lock_kernel();
//初始化time ticket,时钟
tick_init();
//函数 tick_init() 很简单,调用 clockevents_register_notifier 函数向 clockevents_chain 通知链注册元素:
// tick_notifier。这个元素的回调函数指明了当时钟事件设备信息发生变化(例如新加入一个时钟事件设备等等)时,
//应该执行的操作,该回调函数为 tick_notify 
//http://blogold.chinaunix.net/u3/97642/showart_2050200.html
boot_cpu_init();
//初始化页地址,当然对于arm这里是个空函数
//http://book.chinaunix.net/special/ebook/PrenticeHall/PrenticeHallPTRTheLinuxKernelPrimer/0131181637/ch08lev1sec5.html
page_address_init();
printk(KERN_NOTICE "%s", linux_banner);
//系结构相关的内核初始化过程
//http://www.cublog.cn/u3/94690/showart_2238008.html
setup_arch(&command_line);
//初始化内存管理
mm_init_owner(&init_mm, &init_task);
//处理启动命令,这里就是设置的cmd_line
setup_command_line(command_line);
//这个在定义了SMP的时候有作用,现在这里为空函数;对于smp的使用,后面在看。。。
setup_nr_cpu_ids();
//如果没有定义CONFIG_SMP宏,则这个函数为空函数。
//如果定义了CONFIG_SMP宏,则这个setup_per_cpu_areas()函数给每个CPU分配内存,
//并拷贝.data.percpu段的数据。为系统中的每个CPU的per_cpu变量申请空间。
setup_per_cpu_areas();
//定义在include/asm-x86/smp.h。
//如果是SMP环境,则设置boot CPU的一些数据。在引导过程中使用的CPU称为boot CPU
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
//设置node 和 zone 数据结构
//内存管理的讲解:http://blog.chinaunix.net/space.php?uid=361890&do=blog&cuid=2146541
build_all_zonelists(NULL);
//初始化page allocation相关结构
page_alloc_init();
printk(KERN_NOTICE "Kernel command line: %s/n", boot_command_line);
//解析内核参数
//对内核参数的解析:http://hi.baidu.com/yuhuntero/blog/item/654a7411e45ce519b8127ba9.html
parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
  __stop___param - __start___param,
  &unknown_bootoption);
/*
* These use large bootmem allocations and must precede
* kmem_cache_init()
*/
//初始化hash表,以便于从进程的PID获得对应的进程描述指针,按照实际的物理内存初始化pid hash表
//这里涉及到进程管理http://blog.csdn.net/satanwxd/archive/2010/03/27/5422053.aspx
pidhash_init();
//初始化VFS的两个重要数据结构dcache和inode的缓存。
//http://blog.csdn.net/yunsongice/archive/2011/02/01/6171324.aspx
vfs_caches_init_early();
//把编译期间,kbuild设置的异常表,也就是__start___ex_table和__stop___ex_table之中的所有元素进行排序
sort_main_extable();
//初始化中断向量表
//http://blog.csdn.net/yunsongice/archive/2011/02/01/6171325.aspx
trap_init();
//memory map初始化
//http://blog.csdn.net/huyugv_830913/archive/2010/09/15/5886970.aspx
mm_init();
/*
* Set up the scheduler prior starting any interrupts (such as the
* timer interrupt). Full topology setup happens at smp_init()
* time - but meanwhile we still have a functioning scheduler.
*/
//核心进程调度器初始化,调度器的初始化的优先级要高于任何中断的建立,
//并且初始化进程0,即idle进程,但是并没有设置idle进程的NEED_RESCHED标志,
//所以还会继续完成内核初始化剩下的事情。
//这里仅仅为进程调度程序的执行做准备。
//它所做的具体工作是调用init_bh函数(kernel/softirq.c)把timer,tqueue,immediate三个人物队列加入下半部分的数组
sched_init();
/*
* Disable preemption - early bootup scheduling is extremely
* fragile until we cpu_idle() for the first time.
*/
//抢占计数器加1 
preempt_disable();
//检查中断是否打开
if (!irqs_disabled()) {
printk(KERN_WARNING "start_kernel(): bug: interrupts were "
"enabled *very* early, fixing it/n");
local_irq_disable();
}
//Read-Copy-Update的初始化
//RCU机制是Linux2.6之后提供的一种数据一致性访问的机制,
//从RCU(read-copy-update)的名称上看,我们就能对他的实现机制有一个大概的了解,
//在修改数据的时候,首先需要读取数据,然后生成一个副本,对副本进行修改,
//修改完成之后再将老数据update成新的数据,此所谓RCU。
//http://blog.ednchina.com/tiloog/193361/message.aspx
//http://blogold.chinaunix.net/u1/51562/showart_1341707.html
rcu_init();
//定义在lib/radix-tree.c。
//Linux使用radix树来管理位于文件系统缓冲区中的磁盘块,
//radix树是trie树的一种
//http://blog.csdn.net/walkland/archive/2009/03/19/4006121.aspx
radix_tree_init();
/* init some links before init_ISA_irqs() */
//early_irq_init 则对数组中每个成员结构进行初始化, 
//例如, 初始每个中断源的中断号.其他的函数基本为空. 
early_irq_init();
//初始化IRQ中断和终端描述符。
//初始化系统中支持的最大可能的中断描述结构struct irqdesc变量数组irq_desc[NR_IRQS],
//把每个结构变量irq_desc[n]都初始化为预先定义好的坏中断描述结构变量bad_irq_desc,
//并初始化该中断的链表表头成员结构变量pend
init_IRQ();
//prio-tree是一棵查找树,管理的是什么?
//http://blog.csdn.net/dog250/archive/2010/06/28/5700317.aspx
prio_tree_init();
//初始化定时器Timer相关的数据结构
//http://www.ibm.com/developerworks/cn/linux/l-cn-clocks/index.html
init_timers();
//对高精度时钟进行初始化
hrtimers_init();
//软中断初始化
//http://blogold.chinaunix.net/u1/51562/showart_494363.html
softirq_init();
//初始化时钟源
timekeeping_init();
//初始化系统时间,
//检查系统定时器描述结构struct sys_timer全局变量system_timer是否为空,
//如果为空将其指向dummy_gettimeoffset()函数。
//http://www.ibm.com/developerworks/cn/linux/l-cn-clocks/index.html
time_init();
//profile只是内核的一个调试性能的工具,
//这个可以通过menuconfig中的Instrumentation Support->profile打开。
//http://www.linuxdiyf.com/bbs//thread-71446-1-1.html
profile_init();
if (!irqs_disabled())
printk(KERN_CRIT "start_kernel(): bug: interrupts were "
"enabled early/n");
//与开始的early_boot_irqs_off相对应
early_boot_irqs_on();
//与local_irq_disbale相对应,开中断
local_irq_enable();
/* Interrupts are enabled now so all GFP allocations are safe. */
gfp_allowed_mask = __GFP_BITS_MASK;
//memory cache的初始化
//http://my.chinaunix.net/space.php?uid=7588746&do=blog&id=153184
kmem_cache_init_late();
/*
* HACK ALERT! This is early. We're enabling the console before
* we've done PCI setups etc, and console_init() must be aware of
* this. But we do want output early, in case something goes wrong.
*/
//初始化控制台以显示printk的内容,在此之前调用的printk,只是把数据存到缓冲区里,
//只有在这个函数调用后,才会在控制台打印出内容
//该函数执行后可调用printk()函数将log_buf中符合打印级别要求的系统信息打印到控制台上。
console_init();
if (panic_later)
panic(panic_later, panic_param);
//如果定义了CONFIG_LOCKDEP宏,那么就打印锁依赖信息,否则什么也不做
lockdep_info();
/*
* Need to run this when irqs are enabled, because it wants
* to self-test [hard/soft]-irqs on/off lock inversion bugs
* too:
*/
//如果定义CONFIG_DEBUG_LOCKING_API_SELFTESTS宏
//则locking_selftest()是一个空函数,否则执行锁自测
locking_selftest();
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
   page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
   "disabling it./n",
   page_to_pfn(virt_to_page((void *)initrd_start)),
   min_low_pfn);
initrd_start = 0;
}
#endif
//页面初始化,可以参考上面的cgroup机制
page_cgroup_init();
//页面分配debug启用
enable_debug_pagealloc();
//此处函数为空
kmemtrace_init();
//memory lead侦测初始化,如何侦测???
kmemleak_init();
//
//Called after the kmem_caches are functional to setup a dedicated
//cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag
//prevents that the debug code is called on kmem_cache_free() for the
//debug tracker objects to avoid recursive calls.
//在kmem_caches之后表示建立一个高速缓冲池,建立起SLAB_DEBUG_OBJECTS标志。???
debug_objects_mem_init();
//idr在linux内核中指的就是整数ID管理机制,
//从本质上来说,这就是一种将整数ID号和特定指针关联在一起的机制
//idr机制适用在那些需要把某个整数和特定指针关联在一起的地方。
//http://blogold.chinaunix.net/u3/93255/showart_2524027.html
idr_init_cache();
//是否是对SMP的支持,单核是否需要??这个要分析
setup_per_cpu_pageset();
//NUMA (Non Uniform Memory Access) policy 
//具体是什么不懂
numa_policy_init();
if (late_time_init)
late_time_init();
//初始化调度时钟
sched_clock_init();
//calibrate_delay()函数可以计算出cpu在一秒钟内执行了多少次一个极短的循环,
//计算出来的值经过处理后得到BogoMIPS 值,
//Bogo是Bogus(伪)的意思,MIPS是millions of instructions per second(百万条指令每秒)的缩写。
//这样我们就知道了其实这个函数是linux内核中一个cpu性能测试函数。
//http://blogold.chinaunix.net/u2/86768/showart_2196664.html
calibrate_delay();
//PID是process id的缩写
//http://blog.csdn.net/satanwxd/archive/2010/03/27/5422053.aspx
pidmap_init();
//来自mm/rmap.c
//分配一个anon_vma_cachep作为anon_vma的slab缓存。
//这个技术是PFRA(页框回收算法)技术中的组成部分。
//这个技术为定位而生——快速的定位指向同一页框的所有页表项。
anon_vma_init();
#ifdef CONFIG_X86
if (efi_enabled)
efi_enter_virtual_mode();
#endif
//创建thread_info缓存
thread_info_cache_init();
//申请了一个slab来存放credentials??????如何理解?
cred_init();
//根据物理内存大小计算允许创建进程的数量
//http://www.jollen.org/blog/2006/11/jollen_linux_3_fork_init.html
fork_init(totalram_pages);
//给进程的各种资源管理结构分配了相应的对象缓存区
//http://www.shangshuwu.cn/index.php/Linux内核的进程创建
proc_caches_init();
//创建 buffer_head SLAB 缓存
buffer_init();
//初始化key的management stuff
key_init();
//关于系统安全的初始化,主要是访问控制
//http://blog.csdn.net/nhczp/archive/2008/04/29/2341194.aspx
security_init();
//与debug kernel相关
dbg_late_init();
//调用kmem_cache_create()函数来为VFS创建各种SLAB分配器缓存
//包括:names_cachep、filp_cachep、dquot_cachep和bh_cachep等四个SLAB分配器缓存
vfs_caches_init(totalram_pages);
//创建信号队列
signals_init();
/* rootfs populating might need page-writeback */
//回写相关的初始化
//http://blog.csdn.net/yangp01/archive/2010/04/06/5454822.aspx
page_writeback_init();
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
//它将剩余的subsys初始化.然后将init_css_set添加进哈希数组css_set_table[ ]中.
//在上面的代码中css_set_hash()是css_set_table的哈希函数.
//它是css_set->subsys为哈希键值,到css_set_table[ ]中找到对应项.然后调用hlist_add_head()将init_css_set添加到冲突项中.
//然后,注册了cgroup文件系统.这个文件系统也是我们在用户空间使用cgroup时必须挂载的.
//最后,在proc的根目录下创建了一个名为cgroups的文件.用来从用户空间观察cgroup的状态.
//http://blogold.chinaunix.net/u1/51562/showart_1736813.html
cgroup_init();
//http://blogold.chinaunix.net/u1/51562/showart_1777937.html
cpuset_init();
////进程状态初始化,实际上就是分配了一个存储线程状态的高速缓存
taskstats_init_early();
delayacct_init();
//此处为一空函数
imv_init_complete();
//测试CPU的各种缺陷,记录检测到的缺陷,以便于内核的其他部分以后可以使用他们工作。
check_bugs();
//电源相关的初始化
//http://blogold.chinaunix.net/u/548/showart.php?id=377952
acpi_early_init(); /* before LAPIC and SMP init */
//
sfi_init_late();
ftrace_init();
/* Do the rest non-__init'ed, we're now alive */
//创建1号进程,详细分析之
rest_init();
}
关键字:arm  Linux系统  start_kernel函数 引用地址:arm Linux系统启动之start_kernel函数

上一篇:ARM Linux 大小核切换
下一篇:ARM Linux根文件系统Root Filesystem的制作

推荐阅读最新更新时间:2024-03-16 14:57

ARM、Imagination合伙瓜分MIPS
半年多前传出消息称, 传统处理器设计厂商MIPS正在寻求卖掉自己 ,而潜在的买家有高通、博通、 AMD、Google 等等,但最终得手的却是移动CPU、GPU领域的两个领头羊:ARM、Imagination。他俩一个收购专利、一个收购公司,合伙把MIPS给瓜分了个干净。 MIPS目前拥有专利和专利资产总计580项,其中82项最关键的被称为“保留专利资产”(Retained Patent Properties),直接与MIPS处理器架构设计核心有关,全部归属Imagination,另外498项被称为“剥离专利资产”(Divested Patent Properties),涵盖微处理器设计、SoC设计和其它技术领域,都卖给了ARM母
[半导体设计/制造]
<font color='red'>ARM</font>、Imagination合伙瓜分MIPS
LPC2XXX系列ARM带CAN的波特率计算
最近正在学习ARM的CAN部分,发现CAN的波特率计算方法网上竟然查不到,我就自己推到一个吧,有什么不对的地方大家指正啊。 当VPB时钟为4*11059200Hz时,常用波特率与总线时序器对照表(周立功给的,11059200kHz的波特率都是近似的,有误差) BPS = (SAM 23)|(TSEG2 20)|(TSEG1 16)|(SJW 14)| BRP #define BPS_5K (1 23)|(1 20)|(6 16)|(0 14)| 879 #define BPS_10K (1 23)|(1 20)|(6 16)|(0 14)| 439 #defin
[单片机]
LPC2XXX系列<font color='red'>ARM</font>带CAN的波特率计算
嵌入式Linux系统CGI程序设计技术
摘要:在详细介绍一种嵌入式Web服务器BOA的实现与配置方法的基础上,以一个Web在线远程监控GPIO(通用输入/输出)的程序为实例,介绍嵌入式Linux系统下CPU程序设计技术。 关键词:嵌入式系统Linux BOA CGI GPIO 1 概述 随着互联网应用的普及,越来越多的信息化产品需要接入互联网通过Web页面进行远程访问。嵌入式Web系统提供了一种经济、实用的互联网嵌入式接入方案。这里结合一种嵌入式Web Server BOA来介绍嵌入式Linux系统下的CGI程序设计技术。 2 Web Server BOA的实现与配置 2.1 uClinux下,主要有三个Web Server:HTTPD、THTTPD和BOA
[嵌入式]
Arm:生态圈有望增10倍
对于苹果近期有意布局RISC-V、避开Arm架构传闻,Arm中国台湾区总裁曾志光7日表示不评论单一客户,但强调OEM自造IC大势所趋,Arm生态圈有望增长5-10倍。 据钜亨网报道,曾志光认为,OEM自造IC背后是希望借此提供更顺畅的系统使用习惯,不仅要降低功耗,还要维持甚至增加功能,因此自造IC趋势将会延续,也凸显了IC设计价值持续向上。 而Arm作为IP龙头,核心信念为两大重点,一是保持技术领先,也是客户选择Arm的最重要理由,二是优化商业模式使客户愿意接受,Arm将不断降低产业门槛、进入成本,扶持初创客户,提供更灵活的资金空间给予IC设计初创公司。 曾志光强调,Arm将维持技术领衔优势,有信心向客户提供最好的解决方案,确保客
[手机便携]
arm汇编adrl以及ldr与adr的区别
看《嵌入式linux应用开发》第六章实例中看到个句: adrl r2,men_cfg_val 最初对adr1相当不解,后来发现,那个不是数字1,而是字母l(认真看头部,有点区别的) 这里记录下ADRL的用法: 功能:将相对于程序或相对于寄存器的地址载入寄存器中。 与 ADR 指令相似。ADRL 生成两个数据处理指令,因此它比 ADR 加载的地址范围要宽。 语法 ADRL{cond} Rd,label 其中: cond:是一个可选的条件代码。Rd:是要加载的寄存器。label:是相对于程序或寄存器的表达式。 上面给出的范围是相对于位于当前指令地址后的、距离当前指令四个字节(在 Thumb 代码中)或两
[单片机]
基于三星S3C2410的ARM-Linux电子控制油门设计
  引言   巡航控制系统(CCS)是20世纪60年代发展起来的,又称为恒速行驶系统。巡航控制系统工作时,ECU根据各种传感器输送来的信号判断汽车的运行状况,通过执行元件自动调节节气门的开度使汽车的行驶速度与设定的车速保持一致。汽车在良好路面上长时间行驶时,驾驶员启动巡航控制系统并设定行驶速度,不需驾驶员操纵加速踏板,通过巡航控制系统即可自动保持既定的行驶速度,不仅减轻了驾驶员的劳动强度,同时利用先进的电子控制技术控制节气门的开度,比驾驶员操纵节气门更精确,汽车燃料经济性、排放污染性也可得到改善。   1 系统原理   1.1 电控油门原理   工作时,由驾驶员发出转速的控制指令,由节气门开度传感器采集发动机的转速参数,
[单片机]
基于三星S3C2410的<font color='red'>ARM</font>-Linux电子控制油门设计
一款基于ARM7的嵌入式实验平台设计
1 前 言 嵌入式系统是先进的计算机技术、半导体技术、电子技术与各个行业的具体应用相结合后的产物, 它是硬件与软件是紧密捆绑在一起的系统, 这一特点就决定了它必然是一个技术密集、高度分散、不断创新的知识集成系统。目前的嵌入式系统人才多数是在工作岗位上培养起来的, 国内高校还很少设立嵌入式系统这个本科专业, 只是为了适应社会的需要, 对某些专业的学生开设了相关课程, 学习。嵌入式系统设计是一门实践性非常强的课程, 其理论还在不断的发展当中, 如果没有很好的实践平台, 嵌入式系统技术很难掌握, 学生的技能就得不到提高, 培养的学生就不能适应市场的需要。 现有的一些嵌入式系统实验平台已经非常成熟,产品也覆盖了ARM7至A
[单片机]
一款基于<font color='red'>ARM</font>7的嵌入式实验平台设计
快速学Arm(4)--ADS编译方法
看了一天书,琢磨怎么把一个可用的demo下载到LPC2400开发板中并运行起来,争取把环境调试通,这样就可以边学边练了.由于没有搞清楚ASD中的一些配置参数,始终没有做到.为了节约时间,还是请有经验的同事帮了个忙,把环境试验成功了. 那么我们要使用的软件工具有这样几个: 1. ASD1.2 2. H-JATG V0.7.0 BETA.EXE 或者 FlashMagic.exe 先将一下ASD1.2的编译: 1. 要使用 2400光盘中自带的Sample来试验,例如出厂演示目录中的Sample: 2.使用ASD打开项目文件:SmartARM2400_demo.mcp 在点击编译按钮时,我们可能会遇到报错
[单片机]
快速学<font color='red'>Arm</font>(4)--ADS编译方法
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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