关于嵌入式Linux系统的启动(很好的嵌入式linux启动过程分析)

浅析嵌入式Linux系统的构成和启动过程 在我们的周围,大量的嵌入式设备都是基于Linux系统来构建的,嵌入式Linux与主机Linux相比有着自己的一些特点,本文就嵌入式Linux系统的构成和启动过程做一些总结。  一、嵌入式Linux系统构成 上图是一个嵌入式Linux系统的典型结构,划分成了4个区: 1、Bootloader区存放的是Bootloader,它负责嵌入式系统最初的硬件初始化、驱动和内核加载。 2、参 阅读详情

lw:虽然zImage的开头是head_armv.S的8个空循环,但是实际是先执行compressed/head.S进行解压操作。

=================================

#1  关于嵌入式系统的启动(SHARE FOR ALL)

嵌入式Linux启动分为两个部分,系统引导与Linux启动。系统引导将完成Linux装入内存前,初始化CPU和相关IO设备,并将Linux调入内存的工作。系统引导主要由BootLoader实现。在BootLoader将Linux内核调入内存之后,将权力交给LinuxKernel,进入Linux的启动部分。以下详细分析启动的过程与使用的文件。

一、系统引导与BootLoader
        BootLoader
因嵌入式系统的不同与PC机有很大不同,这里将以Hyper250(Inter Xscale GDPXA250)的启动为例来分析。由于没有BIOS驱动主板,EnbeddedOS必须由bootloader驱动所有的硬件,并完成硬件的初始化工作。
       
所有的初始化文件在hyper250/Bootloader目录下。
       
       
首先分析开机运行的分件:
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/start_xscale.S
       
文件包含两个库文件:
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/include/config.h
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/include/start_xscale.h
       
文件config.h主要完成系统各硬件的宏定义与设定,xscale.h主要完成对系统芯片的及系统操作的设定。

       
以下分析config.h文件:
        (1)
存储总线设备的宏定义:定义Flash的大小、字长等信息,定义SRAM的基址、大小和块大小。
        (2)
动态内存设定:定义DRAM的大小、基址。
        (3)
软件包信息:包名称、版本号。
        (4)
设定BOOT LOADER的位置:在DRAM和SRAM的最大值、DRAM装入位置、栈的基址。
        (5)
设定kernel的位置:在DRAM和SRAM的基址、KERNEL的最大值、KERNEL中块的数量。
        (6)
设定文件系统的位置:根目录在DRAM和SRAM的基址、文件系统的最大值、文件系统中块的数量。
        (7)
设定LOADER程序:LOADER程序的静态内存基址、LOADER程序的最大值、块的数量。
        (8)
网络设定
       
       
以下分析start_xcalse.h文件:
        (1)
定义内存基址(A0000000)
        (2)
定义中断基址(40D00000)和中断保护栈的偏移量
        (3)
定义时钟管理基址(41300000)和寄存器偏移及其初始值
        (4)
定义GPIO接口寄存器基址(40E00000)及各寄存器的偏移
        (5)
定义GPIO接口各寄存器的初始值
        (6)
定义内存控制寄存器基址(48000000)和各寄存器的偏移
        (7)
定义内存控制寄存器的初始值
        (8)
定义电源管理寄存器的参数
        (9)
定义FFUART寄存器的基址(40100000)和各寄存器的偏移
        (10)
定义FFUART各寄存器的初始值
       
       
以下分析start_xcalse.S文件:
        (1)
设定中断基址(40D00000),完成中断保护栈的初始化
        (2)
初始化GPIO接口
        (3)
初始化内存SDRAM
        (4)
将Bootloader从Flash拷贝到SDRAM中
        (5)
装入Linux内核镜像,将内核从Flash(000C 0000)装入SDRAM(A0008000)中.
        (6)
设定保护栈
        (7)
调用main.c的主函数c_main()       
       
       
以上start_xcalse.S通过APCS的编程标准书写的汇编文件初始化了系统相关的硬件,并且完成了BootLoader的装入内存和Linux内核的装入,最后将权力转交给main.c。
       
以下将分析main.c文件:
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/main.c
       
以及两个库文件
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/include/main.h
                hyper250/Bootloader/X-Hyper250R1.1-Boot/src/include/scc.h

#2  

二、Linux启动过程分析

        1.Makefile
分析:
       
在分析arch/arm/boot/compressed目录下的文件的时候,对于Makefile的分析是很重要的,因为内核将在这个目录相产生。这里主要工作是对内核的压缩和解压工作。本目录在编译完成后将产生vmlinux、head.o、misc.o、head-xscale.o、piggy.o这几个文件。其中vmlinux是(没有--lw:zImage是压缩过的内核)压缩过的内核。head.o是内核的头部文件,负责初始设置。misc.o将主要负责内核的解压工作,它在head.o之后。head-xscale.o文件主要针对Xscale的初始化,将在链接时与head.o合并。piggy.o是一个中间文件,其实是一个压缩的内核,只不过没有和初始化文件及解压文件链接而已。
       
        2.Decompress
分析:
       
在BootLoader完成系统的引导以后并将Linux内核调入内存之后,调用bootLinux(),这个函数将跳转到kernel的起始位置。如果kernel没有压缩,就可以启动了。如果kernel压缩过,则要进行解压,在压缩过的kernel头部有解压程序。压缩过得kernel入口第一个文件源码位置在arch/arm/boot/compressed/head.S。它将调用函数decompress_kernel(),这个函数在文件arch/arm/boot/compressed/misc.c中,decompress_kernel()又调用proc_decomp_setup(),arch_decomp_setup()进行设置,然后使用在打印出信息“Uncompressing Linux...”后,调用gunzip()。将内核放于指定的位置。
       
启动首先运行的文件有:
                arch/arm/boot/compressed/head.S
                arch/arm/boot/compressed/head-xscale.S
                arch/arm/boot/compressed/misc.c
       
这些文件主要用于解压内核和以及启动内核映象。一旦内核启动,则这些文件所占内存空间将被释放。而且,一旦系统通过reset重起,当BootLoader将压缩过的内核放入内存中,首先执行的必然是这些代码。
       
       
以下分析head.S文件:
        (1)
对于各种Arm CPU的DEBUG输出设定,通过定义宏来统一操作。
        (2)
设置kernel开始和结束地址,保存architecture ID。
        (3)
如果在ARM2以上的CPU中,用的是普通用户模式,则升到超级用户模式,然后关中断。
        (4)
分析LC0结构delta offset,判断是否需要重载内核地址(r0存入偏移量,判断r0是否为零)。
       
这里是否需要重载内核地址,我以为主要分析arch/arm/boot/Makefile、arch/arm/boot/compressed/Makefile和arch/arm/boot/compressed/vmlinux.lds.in三个文件,主要看vmlinux.lds.in链接文件的主要段的位置,LOAD_ADDR(_load_addr)=0xA0008000,而对于TEXT_START(_text、_start)的位置只设为0,BSS_START(__bss_start)=ALIGN(4)。对于这样的结果依赖于,对内核解压的运行方式,也就是说,内核解压前是在内存(RAM)中还是在FLASH上,因为这里,我们的BOOTLOADER将压缩内核(zImage)移到了RAM的0xA0008000位置,我们的压缩内核是在内存(RAM)从0xA0008000地址开始顺序排列,因此我们的r0获得的偏移量是载入地址(0xA0008000)。接下来的工作是要把内核镜像的相对地址转化为内存的物理地址,即重载内核地址。
        (5)
需要重载内核地址,将r0的偏移量加到BSS region和GOT table中。
        (6)
清空bss堆栈空间r2-r3。
        (7)
建立C程序运行需要的缓存,并赋于64K的栈空间。
        (8)
这时r2是缓存的结束地址,r4是kernel的最后执行地址,r5是kernel境象文件的开始地址。检查是否地址有冲突。
               
将r5等于r2,使decompress后的kernel地址就在64K的栈之后。
        (9)
调用文件misc.c的函数decompress_kernel(),解压内核于缓存结束的地方(r2地址之后)。此时各寄存器值有如下变化:
                r0
为解压后kernel的大小
                r4
为kernel执行时的地址
                r5
为解压后kernel的起始地址
                r6
为CPU类型值(processor ID)
                r7
为系统类型值(architecture ID)
        (10)
将reloc_start代码拷贝之kernel之后(r5+r0之后),首先清除缓存,而后执行reloc_start。
        (11)reloc_start
将r5开始的kernel重载于r4地址处。
        (12)
清除cache内容,关闭cache,将r7中architecture ID赋于r1,执行r4开始的kernel代码。
       
       
关于head-xscale.S文件,它定义了xcale处理器的64k的cache缓存的实现代码和关闭MMU及缓存的代码,这些代码将在链接过程中与head.S的合并。
       
       
关于misc.c文件,它引入了以下几个文件:
                include/linux/kernel.h
                include/asm-arm/arch-pxa/uncompress.h
                include/asm-arm/proc-armv/uncompress.h
                include/asm-arm/uaccess.h
                lib/inflate.c
       
以下分析misc.c文件的decompress_kernel()函数:
        (1)
首先传入参数:解压后内核地址,缓存开始地址,缓存结束地址,arch id。这些参数通过寄存器r0(r5),r1,r2,r3(r7)传入。
        (2)
接着执行proc_decomp_setup(),它在include/asm-arm/proc-armv/uncompress.h文件中。主要刷新并起用i cache,锁住交换缓存,这是一段嵌入的arm汇编代码。
        (3)
接着执行arch_decomp_setup(),它在include/asm-arm/arch-pxa/uncompress.h文件中,是一个空函数,用于扩展。
        (4)
然后执行makecrc(),它在lib/inflate.c中,主要将产生CRC-32 table,进行循环冗余校验。
        (5)
调用gunzip()解压kernel,它也在lib/inflate.c中。
        (6)
返回head.S,解压后kernel的长度传给r0,解压后的内核地址预先在r5中定义了。

 

#3  

3.kernel
进入文件分析:
       
随后系统将调入文件:arch/arm/kernel/head_armv.S或arch/arm/kernel/head_armo.S。对于arm的kernel而言,有两套.S文件:_armv.S 和 _armo.S. 选择_armv.S 还是_armo.S 依赖于处理器。ARM的version 1, version 2, 都只支持26位的地址空间。version 3开始支持32位的地址空间,同时还向后兼容26位的地址空间。version 4开始不再向后兼容26位的地址空间。这里由于Hyper250使用的是version7,故只涉及文件head_armv.S。

       
head_armv.S是内核的入口点,在内核被解压到预定位置后,它将运行,这里简要说明其主要工作:
        (1)
首先,关中断并进入保护模式,这里将建立虚拟地址到物理地址的映射。(见第二章内存分析)

        (2)
调用lookup_processor_type,查询CUP和其ID是否在.proc.info表中,如果存在,则令r10指向此结构,在CPU的内核入口文件中。如果不是则提示error:p并挂起。关于r10指向的结构,他所属的内核入口文件,以Hyper250为例:arch/arm/mm/proc-xcale.S。
       
这里要要注意的是,此处操作的对象是由vmlinux-armv.lds.in链接文件定位的段.proc.info中,这个段定义在proc-xcale.S文件末尾,这里要注意,上面并没有使系统进入保护模式,所以在这里对.proc.info寻址的时候,为了得到相对地址,做了一个相对寻址的变换。这里好象只用了这个结构的前3位:处理器类型值(value),处理器值掩码(mask),MMU标志值(mmuflags)。这3个值在分别放在寄存器r5(0x69052100)、r6(0xfffff7f0)、r8(0x00000c0e)中,r5和r6只是用于和获得的处理器的ID相比较,而r8则有两个可能的值,分别表示MMU的状态:如果MMU开启,即CACHE_WRITE_THROUGH,则r8=0x00000c0a,否则r8=0x00000c0e。这里r8的值将会保持到初始页表时使用。
        r10
此时指向段.proc.info的开始地址。

        (3)
寄存器r1中的系统类型值(unique architecture number),这个系统类型值的定义,并且由bootloader传入。在文件arch/arm/tools/mach-types中:
        machine_is_xxx        CONFIG_xxxx                        MACH_TYPE_xxx                number
        xhyper250R1        ARCH_PXA_XHYPER250R1                PXA_XHYPER250R1                200

        (4)
调用lookup_architecture_type,将以r1的值检查.arch.info表,这是个struct machine_desc由文件arch/arm/mach-pxa/xhyper250R1.c中的MACHINE_START()创建。假如没有此结构则提示error:a并挂起。
       
这里要注意的是,段.arch.info的定位在vmlinux-armv.lds.in文件中紧接.proc.info,这个段定义在include/asm-arm/mach/arch.h文件中,使用了宏定义MACHINE_START()。文件首先定义了一个结构体machine_desc,段.arch.info主体部分使用了宏定义MACHINE_START()其中嵌入这个结构体。
       
通常来讲MACHINE_START()的实现应该在文件arch/arm/kernel/arch.c中,而这里hyper250的源码中,MACHINE_START()宏定义在arch/arm/mach-pxa/xhyper250R1.c中完成了定义,下面详细分析这个结构:
        (A)MACHINE_START
        MACHINE_START(_type,_name)
这宏开始处嵌入一个静态结构machine_desc,并且立即声明段.arch.info。
        _type
是MACH_TYPE(PXA_XHYPER250R1),用以赋值给machine_desc中的nr,这就是系统类型值number(200)。
        _name
是描述系统类型的字符串,用以赋值给machine_desc中的name为char*。
       
以下几个宏定义均在包含在machine_desc的赋值中,也在段.arch.info中。
        (B)MAINTAINER
        MAINTAINER(n)
,这个n并没有赋值给machine_desc结构,n是"Hybus Co,. ltd."字符串,公司名字罢了。
        (C)BOOT_MEM
        BOOT_MEM(_pram,_pio,_vio)
,这里面很关键,又3个变量:
        _pram
,传值给phys_ram:物理内存的开始地址,程序中赋值为:0xa0000000。
        _pio
,传值给phys_io:物理io的开始地址,程序中赋值为:0x40000000。
        _vio
,传值给io_pg_offst:io页表的偏移,程序中赋值为:_vio=0xfc000000,不过要进行转换:((_vio)>>18)&0xfffc=0x3f00
        (D)BOOT_PARAMS
        BOOT_PARAMS(_params)
这个宏定义了启动参数页表的偏移:param_offset,程序中赋值为:0xa0000100。       
        (E)FIXUP(
接下来三个宏定义分别是三个函数指针:这些函数都在machine_desc结构中定义并且在xhyper250R1.c中实现。)
        FIXUP(fixup_xhyper250R1)
宏指向fixup_xhyper250R1函数,这个函数有4个参数:
        fixup_xhyper250R1(struct machine_desc *desc, struct param_struct *params, char **cmdline, struct meminfo *mi)       
        struct machine_desc
:这个结构体前面已经提过了。
        param_struct
:这个结构体定义在include/asm/setup.h中,这是一个向kernel传递参数的结构体。
        char **cmdline
:好像用于定义输出窗口行数。
        struct meminfo
:这个结构体定义在include/asm/setup.h中,这是一个对物理内存区间描述的结构体,它将整个地址空间分为8个区间,通常一个区必须是连续的地址并且是同一类型的设备,而用于特殊目的的地址将划分为一个独立的区。首先定义nr_banks:块号,然后是结构体bank[NR_BANKS],NR_BANKS为8。结构体bank[NR_BANKS]中有:start、size、node。
       
下面分析这个函数fixup_xhyper250R1的工作,
       
首先,调用宏SET_BANK并赋值为SET_BANK(0, 0xa0000000, 64*1024*1024),这个宏定义在arch/arm/mach-pxa/generic.h文件中。SET_BANK主要完成设置结构体meminfo中bank[_nr]的start、size和node。以上为例,则完成了bank[0]区间中的start=0xa0000000,size=64*1024*1024=64M,node=(__start) - PHYS_OFFSET) >> 27=0
       
接着,使mi的nr_banks=1,好象设定了这个结构只有一个区。要注意的是meminfo将在page_init()中用于初始化页面。       
        (F)MAPIO
        MAPIO(xhyper250R1_map_io)
宏指向xhyper250R1_map_io函数,这个函数没有参数,主要用于io地址从虚拟地址到物理地址的映射关系。
       
这个函数调用了pxa_map_io()和iotable_init(xhyper250R1_io_desc):
        pxa_map_io()
函数定义在arch/arm/mach-pxa/generic.h文件中,实现在arch/arm/mach-pxa/generic.c中,主要调用了iotable_init()函数来进行io地址的区间映象。iotable_init(struct map_desc *)函数中,参数map_desc结构体定义在文件include/asm-arm/map.h中,主要有:virtual、physical、length和一些标志位:domain、read、write、cache、buffer等。iotable_init()函数在文件arch/arm/mm/mm-armv.c中,循环调用create_mapping()来处理map_desc的映射关系。create_mapping函数主要工作就是将io的虚拟地址到物理地址的映射关系按照PAGE_SIZE(4K)的页来进行映射,同时还有段的映射关系。(关于内存的映射将在第2章中详细分析)       
        (G)INITIRQ
        INITIRQ(xhyper250R1_init_irq)
指向了xhyper250R1_init_irq函数,这个函数将主要完成中断的初始化,这里主要调用了函数 pxa_init_irq(),这个函数实现在arch/arm/mach-pxa/irq.c中。接着调用了set_GPIO_IRQ_edge()函数,这个函数也在irq.c中。(关于中断的分析将在以后进行)

       
我们以上通过分析宏MACHINE_START而分析了结构体machine_desc的一个实例的赋值,我们这里其实只用这个结构体很少一部分信息,主要有三个参数内存物理内存的开始地址、物理io的开始地址、io页表的偏移,分别存于寄存器r5(phys_ram=0xa0000000)、r6(phys_io=0x40000000)、r7(io_pg_offst=0x3f00)中,并返回。

        (5)
初始化页表,映射了4M的RAM,以使内核运行。
       
这里值得注意的是:r5此时为物理内存开始地址(0xa0000000),程序利用宏定义pgtbl,将r4成为页表首地址0xC0004000。然后清空内核目录swapper_pg_dir开始的16K空间。
       
        (6)
设置lr为返回地址__ret,以使下面的程序得以跳转返回。
        (7)
使pc=[r10+12],也就是跳转到_xscale_proc_init结构中的b __xscale_setup位置,这个结构在arch/arm/mm/proc-xcale.S中。我们来看看这个结构:
        __pxa250_proc_info:                <--r10
指向这个地址
                .long   0x69052100
                .long   0xfffff7f0
        #if CACHE_WRITE_THROUGH
                .long   0x00000c0a
        #else
                .long   0x00000c0e        <--
这个参数传入了r8中
        #endif
                b       __xscale_setup    <--[r10+12]
                .long   cpu_arch_name
                .long   cpu_elf_name
                .long   HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
                .long   cpu_pxa250_info
                .long   xscale_processor_functions
                .size   __pxa250_proc_info, . - __pxa250_proc_info
       
        __xscale_setup
相关的程序多是对协处理器cp15的操作,之中用到了宏F_BIT|I_BIT|SVC_MODE,       
       
相关的宏定义在文件include/asm-arm/proc-armv/ptrace.h中。
        #define SVC_MODE        0x13
        #define T_BIT           0x20
        #define F_BIT           0x40
        #define I_BIT           0x80
       
        (8)
通过proc-xcale.S中__xscale_setup设置MMU,并通过__ret返回head_armv.S。
        (9)
在__ret返回处设置lr通过__switch_data返回到__mmap_switched。
        (10)
打开MMU,将pipeline清空,以使所有的内存得以正确的访问。并返回到__mmap_switched。
        (11)__mmap_switched
通过__switch_data获得数据,并设置了stack pointer。
        (12)
清空BSS,并保存CPU类型值(processor ID)以及系统类型(machine type)等。
        (13)
跳转到start_kernel。

 

 

【从零开始学习 UVM】1.2、UVM 概述 —— UVM Installation(UVM 安装) 阅读详情

相关推荐

Win10文件夹只读属性自动恢复?彻底解决方法解析

Win10文件夹只读属性自动恢复?彻底解决方法解析在Windows系统使用过程中,文件权限管理常会遇到棘手问题。最近多位用户反馈:取消文件夹只读属性后,系统却自动恢复该设置,导致无法正常复制或修改文件。本文将深入分析该现象的产生原因,并提供多种解决方案,帮助开发者彻底摆脱权限困扰。

mmoo_python的博客 7528

ARM+Linux 的启动分析

基于ARM 的Linux 的启动分析报告 摘要:本文主要分析基于ARM 的Linux-2.2.26 内核启动过程。将首先从/ arch/arm/Makefile着手,介绍三种不同的启动方案,再剖析典型的压缩内核 zImage启动方案的代码结构,最后将详细分析这种方案的启动过程,直到调用 start_kernel()为止。 1、Linux 内核的启动方案: 由/arch/arm/Make

thinkpadlove的专栏 2778

别再死记硬背了!用51单片机的AD/DA和PWM,亲手做个简易示波器信号发生器

本文详细介绍了如何利用51单片机的PWM和AD/DA功能制作简易示波器信号发生器。通过PWM模拟DAC输出波形,结合XPT2046 ADC进行信号测量,实现方波、三角波和正弦波的生成与显示。项目不仅成本低廉,还能帮助电子爱好者深入理解51单片机的核心功能,是理论与实践结合的绝佳案例。

weixin_28675839的博客 265

Linux启动过程详解(转)

 本原创文章属于《Linux大棚》博客,博客地址为http://roclinux.cn。文章作者为rocrocket。为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅。===[正文开始]启动第一步--加载BIOS当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、

loyal_baby的专栏 1835

告别虚拟机!用ZYNQ7000和PYNQ 2.6.0打造一个能实时识别人脸的“智能摄像头”

本文详细介绍了如何利用Xilinx ZYNQ7000开发板和PYNQ 2.6.0框架构建实时人脸识别系统。通过硬件加速和嵌入式开发技术,该系统实现了低延迟、低功耗的独立运行能力,适用于边缘计算和物联网应用。文章包含从环境搭建到核心功能实现的完整指南,并提供了性能优化和问题排查的实用技巧。

weixin_42543046的博客 392

到底是什么决定了二极管的最高工作频率?

硬件工程师,应该都用过二极管的吧,不过也许有一个误区,大多数人可能并不知道,或者说是理解有问题,下面就来细细说下。 一个问题 先提一个问题:到底是什么决定了二极管的最高工作频率? 估计有不少人会回答是二极管反向恢复时间Trr,也有人会说是二极管结电容,那到底谁是对的呢?或者说都一样,反向恢复时间由结电容决定? 到底什么决定了二极管的最高工作频率,我们暂且不论,不过需要知道的是,二极管的反向恢复时间和结电容根本就是两回事,反向恢复时间绝不能等同于结电容的充放电时间。 为什么我这么说呢?.

weixin_42005993的博客 4834

启动流程分析

xilinx zynqmp 7ev linux驱动

qq_43467135的博客 2614

3.2 直流无刷电机(BLDC):状态空间模型与传递函数

状态空间模型和传递函数是分析BLDC电机动态特性的重要工具。状态空间模型通过微分方程描述系统内部状态与输入输出关系,适用于多变量系统分析;传递函数则在频域表征系统特性,便于控制器设计。本文详细推导了三相坐标系和dq坐标系下的BLDC电机状态空间模型,讨论了线性化方法,并介绍了从状态空间模型到传递函数的转换过程。这些模型为BLDC电机的控制系统设计提供了理论基础。

技术工作者 246

【Linux kernel】Linux电源管理(3)_Generic PM之Reboot过程

本文是我们在分析Linux内核时第一次遇到Architecture和Machine的概念,顺便解释一下。内核代码中最常见的目录结构就是:arch/xxx/mach-xxx/(例如arch/arm/mach-bcm/)。由该目录结构可知,Architecture(简称arch)是指具体的体系结构,如ARM、X86等等。Machine呢,是指具体体系结构下的一个或一系列的SOC,如bcm等。

weixin_41028159的博客 2859

全球SAR卫星大盘点与回波数据处理专栏目录

本专栏将详细介绍各国各地区的SAR卫星的特点和性能,以及SAR回波数据的处理方法和技巧。主要介绍民用和商用SAR卫星,帮助你了解商业SAR卫星的最新动态和技术,MATLAB代码将全部开源。以下是专栏目录,持续更新中。

3165

Microsoft Dynamics 365软件二次开发:Dynamics365部署与版本控制策略

在Microsoft Dynamics 365中,自定义实体允许开发者扩展系统以满足特定业务需求。自定义实体可以包含字段、选项集、关系和其他属性,与标准实体类似,但完全由用户定义。1. 登录到Dynamics 365环境。2. 转到“解决方案”区域,选择“自定义”。3. 在“自定义”菜单中,选择“实体”。4. 点击“新建”,输入实体名称,例如“客户反馈”。5. 添加字段,如“反馈类型”、“反馈日期”、“描述”等。6. 设置主键和唯一标识符。7. 定义关系,如与“客户”实体的关联。

kkchenjj的博客 2208

解压缩内核

4.2.2解压缩内核解压缩内核使用的是decompress_kernel函数,来自arch/x86/boot/compressed/misc.c:301asmlinkage void decompress_kernel(void *rmode, memptr heap, 302                                  unsigned char *input_data, 303                                  unsigned long input

云(存储),松(耦合) 3240

PCL 计算点云的体积密度(C++详细过程版)

本文提出了一种基于点云体积密度的计算与可视化方法。算法通过KdTree搜索每个点的邻域,利用球体积公式计算单位体积内的点数作为密度值,并存储在点云强度属性中。代码实现了点云读取、密度计算和可视化功能,使用PCL库完成邻域搜索和密度渲染。结果显示,该方法能有效反映点云密度分布,为后续点云处理提供密度特征参考。文章附有完整C++代码实现和可视化效果图,适用于点云密度分析和特征提取应用。

点云侠的博客 308

嵌入式Linux系统启动过程

一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader), Linux 内核,文件系统,应用程序。 当系统首次引导时,或系统被重置时,处理器会执行一个位于Flash/ROM中的已知位置处的代码,Bootloader就是这第一段代码。它主要用来初始化处理器及外设,然后调用 Linux 内核。Linux 内核在完成系统的初始化之后需要挂载某个文件系统作为根文件系统(Root Filesystem),然后加载必要的内核模块,启动应用程序。这就是嵌入式Linux系统启动过程

fengruoying93的专栏 2919

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Linux、嵌入式 系统的启动过程分析,freeRtos安装过程举例

Linux系统的启动过程是一个复杂但有序的过程,涉及到多个阶段和组件的协同工作。需要注意的是,不同的Linux发行版在启动过程中可能会有一些细微的差异,但大体上都是遵循上述步骤的。此外,随着技术的发展和Linux内核的更新,启动过程也可能会有所变化。

xie__jin__cheng的博客 1736

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

系统上电后 bootloader的执行流程及 ARM Linux的启动过程分析

声明:本文章转自:http://www.go-gddq.com/html/QianRuShiXiTong-JiShu/2012-08/1042290.htm 为学习方便起见,内容转载如下: 内容摘要: 嵌入式 Linux 的可移植性使得我们可以在各种电子产品上看到它的身影。对于不同体系结构的处理器来说Linux的启动过程也有所不同。本文以S3C2410 ARM处理器为例,详细分析了系统上电

blue_carrot的博客 8609

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

操作系统的启动过程——Windows、嵌入式系统、Linux

深入分析WIndows操作系统、Linux操作系统、嵌入式系统的系统启动过程,并附加介绍了Linux操作系统中,init进程的启动级别。

仅以此博客记录日常学习工作中所思所得,水平有限,难登大雅,万望海涵。 1284

嵌入式Linux的启动过程

嵌入式Linux的启动过程

hinewcc的博客 2387

嵌入linux启动过程,嵌入式Linux系统启动过程

嵌入式Linux系统启动过程一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader), Linux内核,文件系统,应用程序。当系统首次引导时,或系统被重置时,处理器会执行一个位于Flash/ROM中的已知位置处的代码,Bootloader就是这第一段代码。它主要用来初始化处理器及外设,然后调用Linux 内核。Linux 内核在完成系统的初始化之后需要挂载某个...

weixin_39618456的博客 384

嵌入式linux系统运行程序,嵌入式Linux系统启动过程

一个嵌入式 Linux 系统从软件角度看可以分为四个部分:引导加载程序(Bootloader), Linux内核,文件系统,应用程序。当系统首次引导时,或系统被重置时,处理器会执行一个位于Flash/ROM中的已知位置处的代码,Bootloader就是这第一段代码。它主要用来初始化处理器及外设,然后调用Linux 内核。Linux 内核在完成系统的初始化之后需要挂载某个文件系统作为根文件系统(Ro...

weixin_42398730的博客 920

嵌入式Linux系统启动过程分析

一 启动 嵌入式系统在启动时,引导代码、操作系统的运行和应用程序的加载主要有两种架构,一种是直接从Nor Flash启动的架构,另一种是直接从Nand Flash启动的架构。 1 从Nor Flash启动 NorFlash具有芯片内执行(XIP,eXecute In Place)的特点,在嵌入式系统中常做为存放启动代码的首选。从NorFlash启动的架构又可细分为只使用Nor Flash

bad_good_man的专栏 1383

嵌入式linux系统启动过程说明

设备启动的整个过程可以分为: 上电-----&gt;启动uboot---&gt;加载linux内核-----&gt;挂载rootfs-----&gt;执行应用程序 下面分步骤详细说明启动各阶段关键信息: 1、运行uboot (1)设备上电后,CPU开始运行,通常CPU会从某一个固定的物理地址开始运行,这个物理地址一般是Flash芯片的起始物理地址,通常存放的是uboot,于是设备启动首先运...

weixin_40597998的博客 1460

嵌入式linux系统的启动过程

一、启动过程 上电---->向执行U-boot---->加载内核到内存,并启动内核---->挂载根文件系统---->执行脚本、应用程序,进入shell命令行

qq_33789039的博客 1027

全面分析嵌入式linux系统启动过程中uboot的作用

全面分析嵌入式linux系统启动过程中uboot的作用 1.为什么要有uboot 1.1、计算机系统的主要部件 (1)计算机系统就是以CPU为核心来运行的系统。典型的计算机系统有:PC机(台式机+笔记本)、嵌入式设备(手机、平板电脑、游戏机)、单片机(家用电器像电饭锅、空调) (2)计算机系统的组成部件非常多,不同的计算机系统组成部件也不同。但是所有的计算机系统运行时需要的主要核心部件都是3个...

Shijia Yin 552
上一篇: 内核线程
下一篇: 嵌入式设备上的 Linux 系统开发
ryman
博客等级 码龄22年 77粉丝 104原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值