浅谈分析Arm linux 内核移植及系统初始化的过程二

发布者:大酉幽华1最新更新时间:2016-06-15 来源: eefocus关键字:Arm  linux  内核移植  系统初始化 手机看文章 扫描二维码
随时随地手机看文章
4.1. 处理器、设备4.2. 描述
设备描述主要两个结构体完成:struct resource和struct platform_device。
先来看看着两个结构体的定义:
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
Resource结构体主要是描述了设备在系统中的起止地址、名称、标志以及为了链式描述方便指向本结构体类型的指针。Resource定义的实例将被添加到platform_device结构体对象中去。
struct platform_device {
const char * name;
u32 id;
struct device dev;
u32 num_resources;
struct resource * resource;
};
Platform_device结构体包括结构体的名称、ID号、平台相关的信息、设备的数目以及上面定义的resource信息。Platform_device结构对象将被直接通过设备操作函数注册导系统中去。具体注册和注销过程在下一节介绍。
4.3. 处理器、设备4.4. 操作
(1) int platform_device_register(struct platform_device * pdev);    注册设备
(2) void platform_device_unregister(struct platform_device * pdev); 注销设备
(3) int platform_add_devices(struct platform_device **devs, int num);添加设备,通过调用上面两个函数实现。
4.5. 添加Nand flash设备4.6. 
下面以nand flash 设备的描述为例,具体介绍下设备的描述和注册过程。
// resource结构体实例s3c_nand_resource 对nand flash 控制器描述,包括控制器的起止地址和标志。
static struct resource s3c_nand_resource[] = {
[0] = {
.start = S3C2410_PA_NAND,
.end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,
.flags = IORESOURCE_MEM,
}
};
//platform_device结构体实例s3c_device_nand定义了设备的名称、ID号并把resource对象作为其成员之一。
struct platform_device s3c_device_nand = {
.name   = "s3c2410-nand",
.id   = -1,
.num_resources   = ARRAY_SIZE(s3c_nand_resource),
.resource   = s3c_nand_resource,
};
// nand flash 的分区情况,由mtd_partition结构体定义。
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "Boot Agent",
.size = SZ_16K,
.offset = 0,
},
[1] = {
.name = "S3C2410 flash partition 1",
.offset = 0,
.size = SZ_2M,
},
[2] = {
.name = "S3C2410 flash partition 2",
.offset = SZ_4M,
.size = SZ_4M,
},
[3] = {
.name = "S3C2410 flash partition 3",
.offset = SZ_8M,
.size = SZ_2M,
},
[4] = {
.name = "S3C2410 flash partition 4",

 .offset = SZ_1M * 10,
.size = SZ_4M,
},
[5] = {
.name = "S3C2410 flash partition 5",
.offset = SZ_1M * 14,
.size = SZ_1M * 10,
},
[6] = {
.name = "S3C2410 flash partition 6",
.offset = SZ_1M * 24,
.size = SZ_1M * 24,
},
[7] = {
.name = "S3C2410 flash partition 7",
.offset = SZ_1M * 48,
.size = SZ_16M,
}
};

static struct s3c2410_nand_set smdk_nand_sets[] = {
[0] = {
.name = "NAND",
.nr_chips = 1,
.nr_partitions = ARRAY_SIZE(smdk_default_nand_part),
.partitions = smdk_default_nand_part,
},
};

/* choose a set of timings which should suit most 512Mbit
 * chips and beyond.
*/

static struct s3c2410_platform_nand smdk_nand_info = {
.tacls = 20,
.twrph0 = 60,
.twrph1 = 20,
.nr_sets = ARRAY_SIZE(smdk_nand_sets),
.sets = smdk_nand_sets,
};

/* devices we initialise */
// 最后将nand flash 设备加入到系统即将注册的设备集合中。 
static struct platform_device __initdata *smdk_devs[] = {
&s3c_device_nand,
&smdk_led4,
&smdk_led5,
&smdk_led6,
&smdk_led7,
};

然后通过smdk_machine_init()函数,调用设备添加函数platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs)) 完成设备的注册。具体过程参见系统初始化的相关部分。
5. 系统初始化
5.1. 系统初始化的主干线
Start_kernel() èsetup_arch() èreset_init() è kernel_thread(init …) è init() è do_basic_setup() èdriver_init() è do_initcall()

Start_kernel()函数负责初始化内核各个子系统,最后调用reset_init(),启动一个叫做init的内核线程,继续初始化。Start_kernel()函数在init/main.c中实现。

asmlinkage void __init start_kernel(void)
{
char * command_line;
extern struct kernel_param __start___param[], __stop___param[];

smp_setup_processor_id();

/*
 * Need to run as early as possible, to initialize the
 * lockdep hash:
 */
lockdep_init();

local_irq_disable();
early_boot_irqs_off();
early_init_irq_lock_class();

/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
lock_kernel();
boot_cpu_init();
page_address_init();
printk(KERN_NOTICE);
printk(linux_banner);
setup_arch(&command_line); 
 //setup processor and machine and destinate some pointers for do_initcalls() s

5、浅谈分析Arm linux 内核移植及系统初始化的过程 咨询QQ:313807838
 // for example init_machine pointer is initialized with smdk_machine_init() , and //init_machine() is called by customize_machine(), and the is processed by //arch_initcall(fn). Therefore  smdk_machine_init() is issured.    by edwin
setup_per_cpu_areas();
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */

/*
 * 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 ing scheduler.
 */
sched_init();
/*
 * Disable preemption - early bootup scheduling is extremely
 * fragile until we cpu_idle() for the first time.
 */
preempt_disable();
build_all_zonelists();
page_alloc_init();
printk(KERN_NOTICE "Kernel command line: %sn", saved_command_line);
parse_early_param();
parse_args("Booting kernel", command_line, __start___param,
   __stop___param - __start___param,
   &unknown_bootoption);
sort_main_extable();
unwind_init();
trap_init();
rcu_init();
init_IRQ();
pidhash_init();
init_timers();
hrtimers_init();
softirq_init();
timekeeping_init();
time_init();
profile_init();
if (!irqs_disabled())
printk("start_kernel(): bug: interrupts were enabled earlyn");
early_boot_irqs_on();
local_irq_enable();

/*
 * 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.
 */
console_init();
if (panic_later)
panic(panic_later, panic_param);

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:
 */
locking_selftest();

#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
initrd_start < min_low_pfn << PAGE_SHIFT) {
printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
 
6、浅谈分析Arm linux 内核移植及系统初始化的过程  咨询QQ:313807838
     "disabling it.n",initrd_start,min_low_pfn << PAGE_SHIFT);
initrd_start = 0;
}
#endif
vfs_caches_init_early();
cpuset_init_early();
mem_init();
kmem_cache_init();
setup_per_cpu_pageset();
numa_policy_init();
if (late_time_init)
late_time_init();
calibrate_delay();
pidmap_init();
pgtable_cache_init();
prio_tree_init();
anon_vma_init();
#ifdef CONFIG_X86
if (efi_enabled)
efi_enter_virtual_mode();
#endif
fork_init(num_physpages);
proc_caches_init();
buffer_init();
unnamed_dev_init();
key_init();
security_init();
vfs_caches_init(num_physpages);
radix_tree_init();
signals_init();
/* rootfs populating might need page-writeback */
page_writeback_init();
#ifdef CONFIG_PROC_FS
proc_root_init();
#endif
cpuset_init();
taskstats_init_early();
delayacct_init();

check_bugs();

acpi_early_init(); /* before LAPIC and SMP init */

/* Do the rest non-__init'ed, we're now alive */
rest_init();
}

分析start_kernel()源码, 其中setup_arch() 和 reset_init()是两个比较关键的函数。下面将具体分析这两个函数。
5.2. setup_arch()函数分析
首先我们来分析下setup_arch()函数。
Setup_arch()函数主要工作是安装cpu和machine,并为start_kernel()后面的初始化函数指针指定值。
其中setup_processor()函数调用linux/arch/arm/kernel/head_common.S 中的lookup_processor_type函数查询处理器的型号并安装。

Setup_machine()函数调用inux/arch/arm/kernel/head_common.S 中的lookup_machine_type(__machine_arch_type)函数根据体系结构号__machine_arch_type,在 __arch_info_begin和__arch_info_end段空间查询体系结构。问题是__machine_arch_type是在什么时候赋 的初值?__arch_info_begin和__arch_info_end段空间到底放的是什么内容?
__machine_arch_type是一个全局变量,在linux/boot/decompress/misc.c的解压缩函数中得以赋值。
decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, int arch_id)
{
__machine_arch_type = arch_id;
}

__arch_info_begin和__arch_info_end段空间到底放的内容由链接器决定,存放是.arch.info.init段的 内容。这个段是通过段属性__attribute__指定的。Grep一下.arch.info.init 得到./include/asm/mach/arch.h:53: __attribute__((__section__(".arch.info.init"))) = {       在linux/include/asm-arm/mach/arch.h 中发现MACHINE_START宏定义。

#define MACHINE_START(_type,_name) 
static const struct machine_desc __mach_desc_##_type 
 __attribute_used__ 
 __attribute__((__section__(".arch.info.init"))) = { 
.nr = MACH_TYPE_##_type, 
.name = _name,

#define MACHINE_END 
};

inux/arch/arm/mach-s3c2410/mach-smdk2410.c中对.arch.info.init段的初始化如下。

 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
    * to SMDK2410 */
/* Maintainer: Jonas Dietsche */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = smdk2410_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = smdk_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END

由此可见在.arch.info.init段内存放了__desc_mach_desc_SMDK2410结构体。初始化了相应的初始化函数指针。问题又来了, 这些初始化指针函数是什么时候被调用的呢?
分析发现,不一而同。
如 s3c24xx_init_irq()函数是通过start_kernel()里的init_IRQ()函数调用init_arch_irq()实现的。 因为在MACHINE_START结构体中  .init_irq = s3c24xx_init_irq,而在setup_arch()函数中init_arch_irq = mdesc->init_irq, 所以调用init_arch_irq()就相当于调用了s3c24xx_init_irq()。
又如smdk_machine_init()函数 的初始化。在MACHINE_START结构体中,函数指针赋值,.init_machine = smdk_machine_init。而init_machine()函数被linux/arch/arm/kernel/setup.c文件中的 customize_machine()函数调用并被arch_initcall(Fn)宏处 理,arch_initcall(customize_machine)。 被arch_initcall(Fn)宏处理过函数将linux/init/main.c
do_initcalls()函数调用。 具体参看下边的部分。

void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
struct machine_desc *mdesc;
char *from = default_command_line;

setup_processor();
mdesc = setup_machine(machine_arch_type);//machine_arch_type =SMDK2410  by edwin
machine_name = mdesc->name;

if (mdesc->soft_reboot)
reboot_setup("s");

if (mdesc->boot_params)
tags = phys_to_virt(mdesc->boot_params);

/*
 * If we have the old style parameters, convert them to
 * a tag list.
 */
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
if (tags->hdr.tag != ATAG_CORE)
tags = (struct tag *)&init_tags;

if (mdesc->fixup)
mdesc->fixup(mdesc, tags, &from, &meminfo);

if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
parse_tags(tags);
}

init_mm.start_code = (unsigned long) &_text;
init_mm.end_code   = (unsigned long) &_etext;
init_mm.end_data   = (unsigned long) &_edata;
init_mm.brk    = (unsigned long) &_end;

memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
  
8、浅谈分析Arm linux 内核移植及系统初始化的过程  咨询QQ:313807838
 saved_command_line[COMMAND_LINE_SIZE-1] = '';
parse_cmdline(cmdline_p, from);
paging_init(&meminfo, mdesc);
request_standard_resources(&meminfo, mdesc);

#ifdef CONFIG_SMP
smp_init_cpus();
#endif

cpu_init();

/*
 * Set up various architecture-specific pointers
 */
init_arch_irq = mdesc->init_irq;
system_timer = mdesc->timer;
init_machine = mdesc->init_machine;

#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con;
#endif
#endif
}
5.3. rest_init()函数分析
下面我们来分析下rest_init()函数。
Start_kernel() 函数负责初始化内核各子系统,最后调用reset_init(),启动一个叫做init的内核线程,继续初始化。在init内核线程中,将执行下列 init()函数的程序。Init()函数负责完成根文件系统的挂接、初始化设备驱动程序和启动用户空间的init进程等重要工作。

static void noinline rest_init(void)
__releases(kernel_lock)
{
kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
numa_default_policy();
unlock_kernel();

/*
 * The boot idle thread must execute schedule()
 * at least one to get things moving:
 */
preempt_enable_no_resched();
schedule();
preempt_disable();

/* Call into cpu_idle with preempt disabled */
cpu_idle();
}


static int init(void * unused)
{
lock_kernel();
/*
 * init can run on any cpu.
 */
set_cpus_allowed(current, CPU_MASK_ALL);
/*
 * Tell the world that we're going to be the grim
 * reaper of innocent orphaned children.
 *
 * We don't want people to have to make incorrect
 * assumptions about where in the task array this
 * can be found.
 */
child_reaper = current;

smp_prepare_cpus(max_cpus);

do_pre_smp_initcalls();

smp_init();
sched_init_smp();

cpuset_init_smp();

/*
 * Do this before initcalls, because some drivers want to access
 * firmware files.
 */
populate_rootfs();   //挂接根文件系统

do_basic_setup();   //初始化设备驱动程序

/*
 * check if there is an early userspace init.  If yes, let it do all
 * the work        //启动用户空间的init进程
 
9、浅谈分析Arm linux 内核移植及系统初始化的过程 咨询QQ:313807838
  */

if (!ramdisk_execute_command)
ramdisk_execute_command = "/init";

if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
ramdisk_execute_command = NULL;
prepare_namespace();
}

/*
 * Ok, we have completed the initial bootup, and
 * we're essentially up and running. Get rid of the
 * initmem segments and start the user-mode stuff..
 */
free_initmem();
unlock_kernel();
mark_rodata_ro();
system_state = SYSTEM_RUNNING;
numa_default_policy();

if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console.n");

(void) sys_dup(0);
(void) sys_dup(0);

if (ramdisk_execute_command) {
run_init_process(ramdisk_execute_command);
printk(KERN_WARNING "Failed to execute %sn",
ramdisk_execute_command);
}

/*
 * We try each of these until one succeeds.
 *
 * The Bourne shell can be used instead of init if we are 
 * trying to recover a really broken machine.
 */
if (execute_command) {
run_init_process(execute_command);
printk(KERN_WARNING "Failed to execute %s.  Attempting "
"defaults...n", execute_command);
}
run_init_process("/sbin/init");
run_init_process("/etc/init");
run_init_process("/bin/init");
run_init_process("/bin/sh");

panic("No init found.  Try passing init= option to kernel.");
}

5.3.1. 挂接根文件系统
Linux/init/ramfs.c
void __init populate_rootfs(void)
{
char *err = unpack_to_rootfs(__initramfs_start,
 __initramfs_end - __initramfs_start, 0);
if (err)
panic(err);
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start) {
#ifdef CONFIG_BLK_DEV_RAM
int fd;
printk(KERN_INFO "checking if image is initramfs...");
err = unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start, 1);
if (!err) {
printk(" it isn");
unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start, 0);
free_initrd();
return;
}
printk("it isn't (%s); looks like an initrdn", err);

 fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
if (fd >= 0) {
sys_write(fd, (char *)initrd_start,
initrd_end - initrd_start);
sys_close(fd);
free_initrd();
}
#else
printk(KERN_INFO "Unpacking initramfs...");
err = unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start, 0);
if (err)
panic(err);
printk(" donen");
free_initrd();
#endif
}
#endif
}

5.3.2. 初始化设备5.3.3. 驱动程序
linux/init/main.c
static void __init do_basic_setup(void)
{
/* drivers will send hotplug events */
init_workqueues();
usermodehelper_init();
driver_init();   /* 初始化驱动程序模型。调用驱动初始化函数初始化子系统。 */

#ifdef CONFIG_SYSCTL
sysctl_init();
#endif

do_initcalls();
}


linux/init/main.c
extern initcall_t __initcall_start[], __initcall_end[];

static void __init do_initcalls(void)
{
initcall_t *call;
int count = preempt_count();

for (call = __initcall_start; call < __initcall_end; call++) {
char *msg = NULL;
char msgbuf[40];
int result;

if (initcall_debug) {
printk("Calling initcall 0x%p", *call);
print_fn_deor_symbol(": %s()",
(unsigned long) *call);
printk("n");
}

result = (*call)();

……
……
……
}

/* Make sure there is no pending stuff from the initcall sequence */
flush_scheduled_work();
}
分 析上面一段代码可以看出,设备的初始化是通过do_basic_setup()函数调用do_initcalls()函数,实现 __initcall_start, __initcall_end段之间的指针函数执行的。而到底是那些驱动函数怎么会被集中到这个段内的呢?我们知道系统内存空间的分配是由链接器ld读取 链接脚本文件决定。链接器将同样属性的文件组织到相同的段里面去,如所有的.text段都被放在一起。在链接脚本里面可以获得某块内存空间的具体地址。我 们来看下linux-2.6.18.8archarmkernelvmlinux.lds.S文件。由于文件过长,只贴出和 __initcall_start, __initcall_end相关的部分。
__initcall_start = .;
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
__initcall_end = .;
从 脚本文件中我们可以看出, 在__initcall_start, __initcall_end之间放置的是属行为(.initcall*.init)的函数数据 。在linux/include/linux/init.h文件中可以知道,(.initcall*.init)属性是由 __define_initcall(level, fn)宏设定的。

#define __define_initcall(level,fn) 
static initcall_t __initcall_##fn __attribute_used__ 
 
11、浅谈分析Arm linux 内核移植及系统初始化的过程咨询QQ:313807838 
 __attribute__((__section__(".initcall" level ".init"))) = fn

#define core_initcall(fn) __define_initcall("1",fn)
#define postcore_initcall(fn) __define_initcall("2",fn)
#define arch_initcall(fn) __define_initcall("3",fn)
#define subsys_initcall(fn) __define_initcall("4",fn)
#define fs_initcall(fn) __define_initcall("5",fn)
#define device_initcall(fn) __define_initcall("6",fn)
#define late_initcall(fn) __define_initcall("7",fn)
#define __initcall(fn)      device_initcall(fn)

由此可以判断,所有的设备驱动函数都必然通过*_initcall(fn)宏的处理。以此为入口,可以查询所有的设备驱动。
core_initcall(fn)
static int __init consistent_init(void)        linux/arch/arm/mm/consistent.c
static int __init v6_userpage_init(void)      linux/arch/arm/mm/copypage-v6.c
static int __init init_dma(void)             linux/arch/arm/kernel/dma.c
static int __init s3c2410_core_init(void)     linux/arch/arm/mach-s3c2410/s3c2410.c

postcore_initcall(fn)
static int ecard_bus_init(void)  linux/arch/arm/kernel/ecard.c

arch_initcall(fn)
static __init int bast_irq_init(void)  linux/arch/arm/mach-s3c2410/bast-irq.c
static int __init s3c_arch_init(void)  linux/arch/arm/mach-s3c2410/cpu.c
static __init int pm_simtec_init(void)      linux/arch/arm/mach-s3c2410/pm-simtec.c
static int __init customize_machine(void)  linux/arch/arm/kernel/setup.c

subsys_initcall(fn)
static int __init ecard_init(void)  linux/arch/arm/kernel/ecard.c
int __init scoop_init(void)  linux/arch/arm/common/scoop.c
static int __init topology_init(void)  linux/arch/arm/kernel/setup.c

fs_initcall(fn)
static int __init alignment_init(void)  linux/arch/arm/mm/alignment.c

device_initcall(fn)
static int __init leds_init(void)  linux/arch/arm/kernel/time.c
static int __init timer_init_sysfs(void)  linux/arch/arm/kernel/time.c

late_initcall(fn)
static int __init crunch_init(void)  arch/arm/kernel/crunch.c
static int __init arm_mrc_hook_init(void)  linux/arch/arm/kernel/traps.c

关键字:Arm  linux  内核移植  系统初始化 引用地址:浅谈分析Arm linux 内核移植及系统初始化的过程二

上一篇:ARM中定时器浅谈
下一篇:浅谈分析Arm linux 内核移植及系统初始化的过程四

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

软银拟重新让Arm在美国上市
据英国《每日电讯报》报道,一名市场消息人士透露,软银集团(SoftBank)正在考虑让其微芯片设计公司Arm重新在美国纳斯达克交易所上市。 据悉,Arm在全球智能手机芯片设计市场占据主导地位,目前正进军服务器和笔记本电脑市场,其硅芯片设计因其高能效而受到青睐。软银集团于2016年以240亿英镑的巨额收购ARM并将该公司私有化。此后,一系列在英国上市的科技公司被外国买家抢购一空,其中包括安全软件提供商Sophos和另一家微芯片设计公司Imagination Technologies。 软银曾公开表示,其目标是在2023年将ARM重新上市,但并未指明上市的具体地点。消息人士称,Arm最快将于明年年底上市。 软银的一位股东表
[手机便携]
基于ARM和FPGA的全彩独立视频LED系统
目前,显示屏按数据的传输方式主要有两类:一类是采用与计算机显示同一内容的实时视频屏;另一类为通过USB、以太网等通信手段把显示内容发给显示屏的独立视频源显示屏,若采用无线通信方式,还可以随时更新显示内容,灵活性高。此外,用一套嵌入式系统取代计算机来提供视频源,既可以降低成本,又具有很高的可行性和灵活性,易于工程施工。因此,独立视频源LED显示系统的需求越来越大。 本系统采用ARM+FPGA的架构,充分利用了ARM的超强处理能力和丰富的接口,实现真正的网络远程操作,因此不仅可以作为一般的LED显示屏控制器,更可以将各显示节点组成大型的户外广告传媒网络。而FPGA是一种非常灵活的可编程逻辑器件,可以像软件一样编程来配置,从而可以
[单片机]
基于<font color='red'>ARM</font>和FPGA的全彩独立视频LED<font color='red'>系统</font>
基于B/S模式的嵌入式视频监控系统的设计
视频监控系统将被监控现场的实时图像和数据等信息准确、清晰、快速地传送到监控中心服务器,监控中心将实时、直接地掌握各个被监控现场的当前情况(包括图像、声音及其他敏感数据),从而对敏感事件进行快速反应 。视频监控正朝着数字化、网络化、集成化的嵌入式视频监控方向蓬勃发展。相比传统的视频采集监控系统,嵌入式视频监控系统具有可靠性高、组网方便、可远程监控等优点,因而更适用于工业控制、银行、政府部门的安防系统中 。   本文设计了一种具有用户零维护、价格低廉、性能稳定等特点的嵌入式视频监控系统。该系统以ARM处理器S3C2440和嵌入式Linux操作系统为核心平台,通过USB摄像头采集视频数据,基于TCP/IP协议进行网络传输,用户通
[安防电子]
基于B/S模式的嵌入式视频监控<font color='red'>系统</font>的设计
OK6410A 开发板 (八) 110 linux-5.11 OK6410A 从流程去熟悉文件系统1-挂载
挂载的时机有两种 1. 注册文件系统之后就挂载 2. 在用户空间挂载 2.1 fstab中挂载 2.2 用户手动用mount 命令挂载 挂载流程变迁史 在内核空间的挂载直接用 kern_mount挂载 在用户空间的挂载 用 用户空间的 mount 函数 , mount 往下调用,陷入内核 ,SYSCALL_DEFINE5(mount 这些接口都没变,变的是 内部实现 老的文件系统中 仍然用 mount 成员 去 创建 super_block 成员 当前(5.11)内核中file_system_type 结构体 中的 mount 成员 即将被抛弃 但是目前依靠 新挂载流程 中 的 legacy_init_
[单片机]
那些联网汽车为什么选择Linux开源平台?
    这是汽车行业的黄金时代。开源软件(OSS)、“万物互联”,以及无数用来支持主动安全系统、驾驶员信息显示和车载电子产品等技术的硬件涌现聚集,让即使是最普通的汽车也具备了成为真正超级巨星的潜力。 这不只是关于汽车数字基础架构内部元件的连接,而是关于汽车与外界的连接——比如和其它汽车、互联网以及云的连接。虽然硬件厂商不断做出重大贡献,但重点已经转向了推动互联汽车的软件。事实上,用于嵌入式系统的软件开发,包括原型设计、调试、测试和验证,现在占据了汽车制造的大部分时间。     现在制造的汽车在不久的将来可能会有大约2000万行代码(已经超过一架美国F-35喷气式战斗机),预计豪华高端汽车的代码还有可能超过1亿行。汽车软件的开发
[汽车电子]
ARM7与FPGA在工控和故障检测中的应用
工业控制中往往需要完成多通道故障检测及多通道命令控制(这种多任务设置非常普遍),单独的CPU芯片由于其外部控制接口数量有限而难以直接完成多路检控任务,故利用ARM芯片与FPGA相结合来扩展检控通道是一个非常好的选择。这里介绍用Atmel公司ARM7处理器(AT91FR40162)和ALTERA公司的低成本FPGA芯片(cyclone2)结合使用完成多通道检控任务的一种实现方法。 各部分功能简介   图1为此系统的结构连接框图。如图所示,ARM芯片与FPGA芯片之间通过数据总线、地址总线及读写控制线相连,而与终端PC则通过串口通信;FPGA与目标设备通过命令控制总线和故障检测总线相连。                  
[测试测量]
<font color='red'>ARM</font>7与FPGA在工控和故障检测中的应用
基于ARM和FPGA架构的三维图形加速系统
引言   随着图形处理的巨额运算量,CPU变得不堪重负。此时,需要使用特定的硬件设备来为嵌入式CPU承担图形处理的任务。   具有三维图形硬件加速能力的ARM+FPGA架构嵌入式图形系统就是其中一种解决方案。其中,ARM处理器负责运行嵌入式操作系统、执行上层图形应用程序,而三维图形处理所需的大量运算则由FPGA实现的GPU(图形处理单元)进行。   图形API简介   在图形系统中预先定义了一组图形API,作为一个抽象层将图形应用程序和图形系统的具体实现隔离开来。具体的图形应用程序都将通过这些图形API来完成所有与绘制图形相关的工作。这样,同样的应用程序就可以在不同的目标图形系统上运行。   目前应用较为广泛的标准图形
[嵌入式]
基于<font color='red'>ARM</font>和FPGA架构的三维图形加速<font color='red'>系统</font>
嵌入式定位系统的实用设计与软件算法实现
  定位系统自问世后便得到了蓬勃发展,其应用已渗入到各行各业。个人消费领域引领移动定位类型科技产品集中涌现,其他领域和行业也有大量技术更新。目前各领域的定位系统主要集中在平台和地图的研发上,平台配合应用要求选用硬件,地图根据显示要求实现软件算法。因而,它们在定位系统的研究工作中各成体系,兼容性不强。   近年来,在定位系统设计中,硬件选择越来越集中在几个品牌的几个型号上。而软件设计方面比较分散。因而在一个兼容性强的平台上实现软件的集中研发,将是未来的研发方向。   这里提出一种系统构造模式,弱化硬件平台的影响而力求最大限度的统一软件设计。    1 系统整体设计方案   这里提出一种实用的设计方案,通过对系统的各方
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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