精华内容
下载资源
问答
  • Linux内存从0到1学习笔记(6.1,物理内存初始化之内核启动)
    千次阅读
    2022-03-09 11:43:57

    写在前面

    该篇博客大致梳理了从引导阶段的memblock.memory到预留内存和动态内存的分配,再到分页机制的建立,以及内存节点有效section的初始化和mem_section下每个有效页框的映射关系,最后seciton下页框属性的初始化。

    kernel启动阶段的物理内存初始化流程如下:

    1. 获取线性地址大小,记录物理内存的起始地址,以及通过memblock分配器来初始化系统预留内存。
    2. 初始化系统分页机制;
    3. 初始化内存基本数据结构包括内存节点,内存域;
    4. 初始化zonelist;
    5. 初始化内存分配器;

    一、 memblock简介

            在Memblock之前还有一个在内核2.3.23版本引入的bootmem引导内存分配器。随着内存检测从简单的bios询问扩展内存块的大小演变为处理复杂的表,快,库和群集。人们开始使用memblock作为引导内存分配器。为什么我们把memlbock称之为引导内存分配器?很显然这是在kernel启动早期,系统还处于引导阶段。Memblock刚开始被称为LMB,Logical Memory Block。后来Yinghai Lu提了一个patch将其重命名为memblock

    更多相关内容
  • DPDK : 解析内存初始化的过程

    千次阅读 2019-05-01 17:41:09
    这一篇文章主要是对DPDK的EAL(Environment Abstraction Layer)中内存初始化的解析,这是DPDK内存管理的基础。 注:在DPDK中,初始化由primary process完成,而其他process统称为secondary process,其可以通过读取...

    说明

           这一篇文章主要是对DPDK的EAL(Environment Abstraction Layer)中内存的初始化的解析,这是DPDK内存管理的基础
           由于个人水平所限,若所写的博文中存在错误,希望大家能帮忙指出。

           注:
                  1,在DPDK中,初始化由primary process完成。而其他process统称为secondary process,其可以通过读取一些文件来获取primary process的初始化信息,从而使得自身与primary process保持相同的内存映像。
                  2, DPDK采用了一种集中式控制的方式,比如在多进程的场景中,若一个secondary process要申请内存,则向primary process发起请求,由primary process完成相应操作后在通知secondary process(DPDK : 进程间通信以及在内存管理的应用)。

    一,初始化相关的代码入口

    从lib/librte_eal/linux/eal/eal.c中的方法int rte_eal_init(int argc,char **argv)开始:

    int
    rte_eal_init(int argc, char **argv){
    	······
    	rte_config_init();
    	if (internal_config.no_hugetlbfs == 0) {
    		/* rte_config isn't initialized yet */
    		ret = internal_config.process_type == RTE_PROC_PRIMARY ?
    				eal_hugepage_info_init() :
    				eal_hugepage_info_read();
    		······
    	}
    	······
    	if (rte_eal_memzone_init() < 0) { ······ }
    	if (rte_eal_memory_init() < 0) { ······ }
        if (rte_eal_malloc_heap_init() < 0) { ······  }
    }
    

    从上面可以看出,内存的初始化过程主要包含5个方面的初始化, rte_config_init(), eal_hugepage_info_init(), rte_eal_memzone_init(), rte_eal_memory_init(), rte_eal_malloc_heap_init(), 下面依次对这五个方面进行解析:

    二,相关的结构体的说明

    在开始之前,先对一些结构体中关于内存的变量进行一些说明(使用······说明省略了一些变量,不影响理解DPDK内存初始化):

    ********************rte_eal.h********************
    struct rte_config { //运行时环境的配置
    	······
    	/** PA or VA mapping mode */
    	enum rte_iova_mode iova_mode; //指明了DMA使用虚拟地址(virtual address, 简称VA), 还是物理地址(physical address, 简称PA)
    
    	/**
    	 * Pointer to memory configuration, which may be shared across multiple
    	 * DPDK instances
    	 */
    	 //这个指针指向的内存空间存放了一个DPDK instance的内存分布情况
    	 //DPDK内存初始化过程主要是初始化struct rte_mem_config中的每一项
    	struct rte_mem_config *mem_config;
    } __attribute__((__packed__));
    ********************eal_internal_cfg.h*******************
    struct hugepage_info {//用于存放每一个hugepage的信息
    	uint64_t hugepage_sz;	/**< size of a huge page */
    	char hugedir[PATH_MAX];	/**< dir where hugetlbfs is mounted */
    	uint32_t num_pages[RTE_MAX_NUMA_NODES];	/**< number of hugepages of that size on each socket */
    
    	int lock_descriptor;    /**< file descriptor for hugepage dir */
    	//lock_descriptor指的是挂载点(即hugedir字段)对应的file descriptor
    };
    
    /**
     * internal configuration
     */
    struct internal_config { //DPDK的全局配置信息
    	volatile size_t memory;           /**< amount of asked memory */ 	
    	//请求分配的内存数量
    	·······
    	volatile unsigned no_hugetlbfs;   /**< true to disable hugetlbfs */  
    	//是否允许使用hugetlbfs
    	
    	unsigned hugepage_unlink;         /**< true to unlink backing files */ 
    	//是否删除hugepage文件(DPDK在memalloc时将每一个hugepage当做一个文件处理)
    	·······
    	volatile unsigned no_shconf;      /**< true if there is no shared config */ 
    	//是否允许共享,不允许的话primary process不会将初始化信息写入到文件 
    	
    	volatile unsigned in_memory;
    	/**< true if DPDK should operate entirely in-memory and not create any
    	 * shared files or runtime data.
    	 */
    	volatile enum rte_proc_type_t process_type; /**< multi-process proc type */  
    	//用于区分primary process, 或者secondary process
    	
    	/** true to try allocating memory on specific sockets */
    	volatile unsigned force_sockets; //强制在指定的socket上分配内存
    	volatile uint64_t socket_mem[RTE_MAX_NUMA_NODES]; /**< amount of memory per socket */  
    	//表示每一个socket分配的内存数量
    	
    	volatile unsigned force_socket_limits; //设置是否限制socket分配的内存
    	volatile uint64_t socket_limit[RTE_MAX_NUMA_NODES]; /**< limit amount of memory per socket */  
    	//每一个socket分配的内存的上限
    	
    	uintptr_t base_virtaddr;          /**< base address to try and reserve memory from */
    	volatile unsigned legacy_mem; //指明是legacy mode, 或者dynamic mode
    	/**< true to enable legacy memory behavior (no dynamic allocation,
    	 * IOVA-contiguous segments).
    	 */
    	volatile unsigned match_allocations;
    	/**< true to free hugepages exactly as allocated */
    	volatile unsigned single_file_segments; //指明是single-file-segments mode, 或者 page-per-file mode
    	/**< true if storing all pages within single files (per-page-size,
    	 * per-node) non-legacy mode only.
    	 */
    	 
    	unsigned num_hugepage_sizes;      /**< how many sizes on this system */
    	struct hugepage_info hugepage_info[MAX_HUGEPAGE_SIZES];
    };
    ********************rte_eal_memconfig.h*******************
    struct rte_mem_config {
    	volatile uint32_t magic;   /**< Magic number - Sanity check. */
    	/* memory topology */
    	uint32_t nchannel;    /**< Number of channels (0 if unknown). */
    	uint32_t nrank;       /**< Number of ranks (0 if unknown). */
    	······
    	/* memory segments amemnd zones */
    	struct rte_fbarray memzones; /**< Memzone descriptors. */
    	
    	//每一个struct rte_memseg_list中使用<socket id, pagesz>进行标识
    	//memsegs 可能存在多个具有相同<socket id, page_sz>的struct rte_memseg_list
    	struct rte_memseg_list memsegs[RTE_MAX_MEMSEG_LISTS];
    	/**< list of dynamic arrays holding memsegs */
    	······
    	/* Heaps of Malloc */
    	struct malloc_heap malloc_heaps[RTE_MAX_HEAPS];
        ······
    	/* address of mem_config in primary process. used to map shared config into
    	 * exact same address the primary process maps it.
    	 */
    	uint64_t mem_cfg_addr; //这个地址等于struct rte_config中的struct rte_mem_config *mem_config
    
    	/* legacy mem and single file segments options are shared */
    	uint32_t legacy_mem;	//指明内存是legacy mode, 还是dynamic mode
    	uint32_t single_file_segments; // 指明memalloc是single-file-segments mode, 还是page-per-file mode
        ······
    } __attribute__((__packed__));
    
    struct rte_memseg_list {//每一个rte_memseg_list由page_sz和socket_id唯一标识
    	RTE_STD_C11
    	union {
    		void *base_va;
    		/**< Base virtual address for this memseg list. */
    		uint64_t addr_64;
    		/**< Makes sure addr is always 64-bits */
    	};//指向一块用于存放rte_memseg的内存空间
    	uint64_t page_sz; /**< Page size for all memsegs in this list. */
    	int socket_id; /**< Socket ID for all memsegs in this list. */
    	······
    	size_t len; /**< Length of memory area covered by this memseg list. */
    	 //指明具有base_va所指向的内存空间的字节数总量
    	······
    	struct rte_fbarray memseg_arr; //用于管理base_va指向的内存空间,包含rte_memseg相关的元数据
    };
    
    ********************rte_memory.h*******************
    struct rte_memseg { //一个rte_memseg等同于一个hugepage
    	RTE_STD_C11
    	union {
    		phys_addr_t phys_addr;  /**< deprecated - Start physical address. */
    		rte_iova_t iova;        /**< Start IO address. */
    	};
    	RTE_STD_C11
    	union {
    		void *addr;         /**< Start virtual address. */
    		uint64_t addr_64;   /**< Makes sure addr is always 64 bits */
    	};
    	size_t len;               /**< Length of the segment. */
    	uint64_t hugepage_sz;       /**< The pagesize of underlying memory */
    	int32_t socket_id;          /**< NUMA socket ID. */
    	uint32_t nchannel;          /**< Number of channels. */
    	uint32_t nrank;             /**< Number of ranks. */
    	uint32_t flags;             /**< Memseg-specific flags */
    } __rte_packed;
    ********************eal_hugepages.h*******************
    struct hugepage_file {
    	void *orig_va;      /**< virtual addr of first mmap() */
    	void *final_va;     /**< virtual addr of 2nd mmap() */
    	uint64_t physaddr;  /**< physical addr */
    	size_t size;        /**< the page size */
    	int socket_id;      /**< NUMA socket ID */
    	int file_id;        /**< the '%d' in HUGEFILE_FMT */  	//这是第file_id个大小为size的hugepage
    	
    	char filepath[MAX_HUGEPAGE_PATH]; /**< path to backing file on filesystem */
    	//filepath指明hugepage对应的文件
    };
    

    三,对于primary process的内存初始化过程:

    1, rte_config_init() :

           这个函数主要是为struct rte_config中的struct rte_mem_config *mem_config(简称mcfg)申请一块内存空间,并且在运行时目录下创建一个名字为config的文件,并且将mcfg的内容写进此文件。这样,secondary process在初始化时就能通过读取config文件来创建和primary process一样的内存映像。

           在这里采用了mmap()的方式将config文件和mcfg进行了映射,所以在后面的初始化操作中,一旦对config进行了写操作,也能够立刻反映到其他的进程中(类似于使用共享内存通信)。

    2, eal_hugepage_info_init() : 读取系统中的hugepage的信息。

           在linux系统中,会打开系统目录/sys/kernel/mm/hugepages,遍历每一个目录项下获取系统支持的hugepage size。然后从/proc/mounts中根据hugepage size获取对应挂载点(mount point), 然后计算在不同socket中每一种free hugepage的数量,。将每一种大页的相关信息存放在internal_config->hugepage_info中。

           然后会在runtime dir下创建一个名字为hugepage_info的文件,将internal_config->hugepage_info写入到该文件。

    3,rte_eal_memzone_init()

           初始化mcfg->memzones, 申请一块内存空间,用于保存以后内存分配时使用到的struct memzone。(memzone所使用的内存空间也是从rte_heap中分配的,rte_memzone_reserve和rte_malloc之间的区别尚未解决)

    4,rte_eal_memory_init() : 这是内存初始化过程的核心,其中包括了memseg_primary_init(), eal_memalloc_init(), rte_eal_hugepage_init(), rte_eal_memdevice_init().

           1), memseg_primary_init() :

    	确定每一种类型(由socket id和page sz确定)的struct rte_memseg_list的数量,及其所包含的mem segment的数量。
    	然后,根据确定的数量为mcfg->memsegs中的struct rte_memseg_list分配虚拟内存空间。
    

           2), eal_memalloc_init() :

    	初始化struct fd_list
    		如果是single-file-segments mode, 则对于一个rte_memseg_list,只使用一个file descriptor(fd_list中的memseg_list_fd)
    		如果是file-per-page, 则对于一个rte_memseg_list中的每一个mem segment, 都会使用一个file descriptor(fd_list中的fds)
    

           3), rte_eal_hugepage_init()

    	*如果是legacy mem, 则调用eal_legacy_hugepage_init()
    		1), 根据internal_config->hugepage_info初始化hugepage_file, 并且将这些hugepage_file, 根据<socket id, pagesz>
    			对应的rte_memseg_list中的rte_memseg进行映射。
    		2),然后对hugepage_file排序(使得按照页的size降序排序,同一种size按照物理地址升序排序),
    			然后根据internal_config->socket_mem计算hugepage在不同socket的分布,
    		3),之后对所有的hugepage_file进行重映射,使得虚拟内存连续的mem segments在物理内存上也是连续的,
    			并且同一个rte_memseg_list所有的mem_sgement的虚拟地址和物理地址都是单调递增。
    		4),接着,设置fd_list中对应的file descriptor。
    		5),这个方法会将hugepage_file写入到hugepage_data文件。
    		
    		在实现的过程中采用了read-ahead, 目的是为了保证虚拟内存连续的mem segments在物理内存上也是连续的,
    	同时也能够提前载入物理页,提高系统的性能。
    		而对于nohugepage的情况,将其视为legacy, single-file mode,采用的页的大小为4K。
    		
    	*如果是dynamic mem, 则调用eal_hugepage_init()
    		根据socket_mem的需求,计算hugepage在不同socket的分布。然后使用了eal_memalloc_alloc_seg_bluk进行分配,
    	  由于这个方法是一个一个mem segment进行分配,所以不能保证分配完成后,虚拟空间上连续的mem segments在物理上也是连续的.
    		采用了pre-allocate,能够提高系统的性能。
    

           4), rte_eal_memdevice_init().:

    	设置mcfg->nchannel, mcfg->nrank
    
    5, rte_eal_malloc_heap_init()

           初始化mcfg->malloc_heaps;并且注册进程间通信的handle,用于多进程环境下的内存分配;初始化heap的结构。
           其中每一个socket会对应一个heap。

    初始化完成后heap的结构如下(一个例子) :

    heap

           假设系统支持两种大小的hugepage(2MB, 1GB)
           上图的heap包含两个rte_memseg_list, 每一个都包含3个contiguous mem segments(其中可能包含一个或多个hugepage), 总共有6个contiguous mem segments(图中浅黄色的部分). 每一个contigous mem segments都包含一个malloc_elem,用于记录此contiguous mem segments的元数据。每一个struct malloc_heap都会指向第一个malloc_elem和最后一个malloc_elem;并且一个heap中,所有的malloc_elem会组成一个双向链表。

    四,对于secondary process的内存初始化过程:

    1, rte_config_init()

           使用mmap()将config文件映射到此进程的mcfg,这样可以直接读取primary process的内存映像.

    2, eal_hugepage_info_init() :

           读取hugepage文件的内容,并保存在struct internal_config->hugepage_info中。

    3,rte_eal_memzone_init()

           根据config文件中关于memzones的内容, 创建一个和primary process具有相同内存映像的mcfg->memzones

    4,rte_eal_memory_init() : 这是内存初始化过程的核心,其中包括了memseg_secondary_init(), eal_memalloc_init(), rte_eal_hugepage_attach(), rte_eal_memdevice_init().

           1), memseg_secondary_init() :

    	直接根据**config**文件的内容创建和primary process相同的虚拟内存空间视图。
    

           2), eal_memalloc_init() :

    	对mcfg中的struct rte_memseg_list, 创建一个本地副本(即local_memsegs),用于同步memory hotplug
    	初始化struct fd_list
    		如果是single-file-segments mode, 则对于一个rte_memseg_list,只使用一个file descriptor(fd_list中的memseg_list_fd)
    		如果是file-per-page, 则对于一个rte_memseg_list中的每一个mem segment, 都会使用一个file descriptor(fd_list中的fds)
    

           3)rte_eal_hugepage_attach()

    	如果是legacy mem, eal_legacy_hugepage_attach()
    		读取hugepage_data文件,根据文件的内容建立与primary process相应的内存映像,并且设置fd_list中相应的file descriptor.
    	如果是dynamic mem, eal_hugepage_attach()
    		调用eal_memalloc_sync_with_primary(), 将primary process的mcfg->memsegs同步到此进程的local_memsegs.
    

            4)rte_eal_memdevice_init() :

    	不做任何操作.
    
    5, rte_eal_malloc_heap_init()

           初始化mcfg->malloc_heaps;并且注册进程间通信的handle,用于多进程环境下的内存分配;初始化heap的结构。

    五,总结

           1,如果没有采用hugetlbfs,则默认采用系统页(大小为4K)
           2, DPDK有两种内存模式 :

    	legacy mode : 保证虚拟空间连续的contiguous mem segments在物理空间上也是连续的
    	dynamic mode : 分配hugepage时是一个一个分配的,不能和legacy mode有一样的保证
    

           3, DPDK在memalloc时有两种模式single-file-segments, page-per-file, 每一种都在hugetlbfs的挂载点上有相应的文件形式(即存在于内存中的文件),这样在内存分配时可以使用对file descriptor操作的系统调用对内存进行操作。
           4,每一个socket有一个heap, 每一个heap包含若干个rte_memseg_list, 每一个rte_memseg_list包含若干rte_memseg, 一个rte_memseg对应于一个memory page
           5, 在分配内存时,采用了read-ahead, pre-allocated等方法,能够减少由于页错误而阻塞的情况,提高系统的性能。

    展开全文
  • 1、new和delete以及new[]和delete[] #include<iostream> using namespace std; int main() { int* p1 = new int;...//动态分配一个4字节(一个int)的空间,并初始化为10。 int* p3 = new i...

    1、new和delete以及new[]和delete[]

    
    #include<iostream>
    using namespace std;
    int  main() {
    	int* p1 = new int;//动态分配一个4字节(int)空间
    	int* p2 = new int(10);//动态分配一个4字节(一个int)的空间,并初始化为10。
    	int* p3 = new int[10];//动态分配40个字节(10个int)的空间。
     
    	delete p1;
    	delete p2;
    	delete[] p3;
     
    	return 0;
    }
    

    通过上述的代码,就是说明了C++在使用new时常用的三种方式, //2020.7.14

    int *p = new int  //new  数据类型

    int *p = new int (10);//new 数据类型(初始值)

    int *p = new int [100]; //new 数据类型[常量表达式]

    2、malloc和free的使用

    首先使用malloc函数的函数的时候需要加上头文件#include <malloc.h>

    #include <iostream>
    #include<malloc.h>
    
    using namespace std;
    int main()
    {
        //[1]给指针申请内存
        char *p = (char *)malloc(100);//申请一块内存,然后再释放
        free(p);
    
        //[2]较多的用法
        int *p1 = (int*)malloc(sizeof(int));
        *p1 = 10;
        printf("%d\n", *p1);
       
        //[3]申请int型的指针变量内存
        int* b = (int*)malloc(sizeof(int)*4);
        return 0;
    }

    参考博客:C++ 动态内存管理(new /delete-new[]/delete[]-N次释放)_porryCn的博客-CSDN博客_new 什么时候释放

    参考博客:C语言指针之二malloc的用法及详解_修炼之路-CSDN博客_malloc函数用法

    c++学习之概述--从C到C++_OrangeRen-CSDN博客

    注意:关于malloc的增加内容//2022.2

    关于malloc的内存申请上述分配内容是有问题的,具体可以参考博客:c语言之内存的申请malloc() 和释放free() - stevenwuzheng - 博客园

    指出两点问题:

    1、malloc申请内存有可能不成功,所以需要增加判断 ,必须使用if(NULL!=p)语句来验证内存确实分配成功了

    2、当free掉p之后,变成野指针的p,需要将它设置成p = NULL,这样才能防止野指针带来的问题。

    展开全文
  • memset能够对char数组进行内存初始化,但是怎样对结构体中有int 和double 型数据的数组进行初始化呢?有没有比用for循环效率更高的初始化方法呢? 例如这个结构体 typedef struct QueeNode{ int a; int b; int c;...
  • 内存初始化

    千次阅读 2017-03-29 10:23:13
    内存初始化

    内存的分类

    内存由于具备访问速度快,访问方式简单等优点,成为了PC或者是嵌入式硬件平台上不可或缺的元件。在开始学习如何使用内存之前,非常有必要先了解一下内存的分类:

    这里写图片描述

    DRAM:它的基本原件是小电容,电容可以在两个极板上保留电荷,但是需要定期的充电(刷新),否则数据会丢失。缺点:由于要定期刷新存储介质,存取速度较慢。

    SRAM:它是一种具有静止存取功能的内存,不需要定期刷新电路就能保存它内部存储的数据。其优点:存取速度快; 但是缺点是:功耗大,成本高。常用作存储容量不高,但存取速度快的场合,比如stepping stone。

    在嵌入式硬件体系中,除了CPU内部的“垫脚石”采用SRAM外,板载内存一般会采用DRAM,而DRAM又可以分为SDRAM,DDR,DDR2等。

    SDRAM(Synchronous Dynamic Random AccessMemory):同步动态随机存储器
    同步: 内存工作需要有同步时钟,内部的命令的发送与数据的传输都以该时钟为基准。
    动态:存储阵列需要不断的刷新来保证数据不丢失。
    随机:是指数据不是线性依次存储,而是自由指定地址进行数据读写。

    DDR (Double Data Rate SDRAM),即“双倍速率同步动态随机存储器”。与早期的SDRAM相比,DDR 除了可以在时钟脉冲的上升沿传输数据,还可以在下降沿传输信号,这意味着在相同的工作频率下,DDR 的理论传输速率为SDRAM的两倍。DDR2 则在DDR 的基础上再次进行了改进,使得数据传输速率在DDR 的基础上再次翻倍。

    内存的内部结构

    表结构:
    内存的内部如同表格,数据就存放在每个单元格中。数
    据读写时,先指定行号(行地址),再指定列号(列地
    址) ,我们就可以准确地找到所需要的单元格。而这张表格的称为:Logical Bank(L-Bank)。

    这里写图片描述

    由于技术、成本等原因,一块内存不可能把所有的单元格都做到一个L-Bank,现在内存内部基本都会分割成4个L-Bank。

    这里写图片描述

    需要向芯片提供以下3个信息来做到寻址:
    1、L-Bank选择信号
    2、行地址
    3、列地址

    OK6410开发板上的内存资源:
    128M字节Mobile DDR内存。
    2片KSX51163PC芯片:
    每一片为:32M*16,总共128M

    上面的16有两重含义:1、每个内存单元的大小为16位; 2、内存芯片的数据宽度为16位。ARM芯片的数据线为32位,剩下的16位连入另一个内存芯片。

    这里写图片描述
    4 * 2^13 * 2^10 = 32M

    2440内存初始化

    2440开发板配置的是SDRAM内存。

    S3c2440芯片对外提供的引脚上,只给出了27根地址线Addr[0:26]。单靠芯片上的 27 根引脚,它只能访问128M 的外设空间。

    为了扩大外设的访问范围,S3c2440芯片又提供了8个片选信号nGCS0~nGCS7。当某个片选信号nGCSx有效时,则可以通过27根地址线去访问对应这个片选的128MB空间。由于有8个片选,所以2440芯片能访问的外设空间总共为8*128MB=1GB。而1G (0x40000000)以上的空间,则安排给了2440内部的寄存器,访问这些内部的寄存器,则是通过32位的处理器内部总线来完成的。

    这里写图片描述

    一般把内存放置在片选6和片选7的位置,因此编写程序时,内存的起始地址为0x30000000。

    这里写图片描述

    对于某一个地址,首先有存储控制器进行分解,然后对相应的存储设备进行操作。因此,对内存的初始化,其实就是对存储控制器的初始化。

    初始化存储寄存器:(mini2440开发板)

    #define mem_contrl 0x48000000
    init_sdram:
        ldr r0, =mem_contrl 
        add r3, r0, #4*13 @最后一个地址
        adrl r1, mem_data
    
    0:
        ldr r2, [r1], #4 @加载并且更新地址
        str r2, [r0], #4 @存储并且更新地址
        cmp r0, r3
        bne 0b           @不等于就跳到分支
        mov pc, lr
    
    mem_data:
        .long 0x22000000 
        .long 0x00000700
        .long 0x00000700
        .long 0x00000700
        .long 0x00000700
        .long 0x00000700
        .long 0x00000700
        .long 0x00018001
        .long 0x00018001
        .long 0x008c04f5
        .long 0x000000b1
        .long 0x00000030
        .long 0x00000030

    6410内存初始化

    6410开发板配置的是DDR内存。

    S3C6410处理器拥32位地址总线,其寻址空间为4GB。其中高2GB为保留区,低2GB区域又可划分为两部分:主存储区和外设区。

    这里写图片描述

    保留区没有使用。外设区放置6410芯片中的寄存器,访问这些内部寄存器就通过这些地址。主存储区

    主存储区的划分:

    这里写图片描述

    boot启动镜像区:
    这个区域的作用正如它的名字所述,是用来启动ARM系统的。但是这个区域并没有固定的存储 介质与之对应。而是通过修改启动选项,把不同的启动介质映射到该区域。比如说选择了IROM 启动方式后,就把IROM映射到该区域。

    内部存储区:
    这个区域对应着内部的内存地址,iROM和SRAM都是分布在这个区间。0x08000000~0x0bffffff对应着内部ROM,但是IROM实际只有32KB,选择从IROM启动的时候,首先运行就是这里面的程序BL0,BL0这部分代码由三星固化。0x0c000000~0x0fffffff对应内部SRAM,实际就是8KB的Steppingstone。

    静态存储区:
    这个区域用于访问挂在外部总线上的设备,比如说NOR flash、oneNand等。这个区域被分割为6个bank,每个bank为128MB,数据宽度最大支持16bit,每个bank由片选Xm0CS[0]~Xm0CS[5] 选中。

    动态存储区:
    该区域从0x50000000~0x6fffffff,又分为2个区间,分别占256MB,可以片选Xm1CS[0]~Xm1CS[1]来进行着2个区间的选择。我们6410开发板上256MB的DDR内存就安排在这个区域,这也就是为什么6410的内存地址是从0x50000000开始的原因。

    内存芯片的连接方式:
    这里写图片描述

    6410芯片手册中的存储控制器
    芯片手册第5章,DRAM CONTROLLER

    5.4节介绍了内存控制器初始化的流程。

    uboot代码中的cpu\s3c64xx\s3c6410文件下的cpu_init.S文件下的标号mem _ ctrl _ asm _ init下的代码就是对存储控制器进行初始化的代码。

    代码举例:(OK6410开发板)

    .text
    .global mem_init
    mem_init:
    
        ldr r0, =0x7e00f120 @设置数据线
        mov r1, #0x8
        str r1, [r0]
    
        ldr r0, =0x7e001004  @make DRAM Controller enter ‘Config’ state
        mov r1, #0x4         
        str r1, [r0]
    
        ldr r0, =0x7e001010  @鍒锋柊瀵勫瓨鍣ㄥ湴鍧€
        ldr r1, =( ( 7800 / ( 1000000000/133000000 ) + 1 ) )      @璁剧疆鍒锋柊鏃堕棿
        str r1, [r0]
    
        ldr r0, =0x7e001014  @CAS latency瀵勫瓨鍣?
        mov r1, #(3 << 1)
        str r1, [r0]
    
        ldr r0, =0x7e001018  @t_DQSS瀵勫瓨鍣?
        mov r1, #0x1
        str r1, [r0]
    
        ldr r0, =0x7e00101c  @T_MRD瀵勫瓨鍣?
        mov r1, #0x2
        str r1, [r0]
    
        ldr r0, =0x7e001020   @t_RAS瀵勫瓨鍣?
        ldr r1, =( ( 45 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]
    
        ldr r0, =0x7e001024   @t_RC瀵勫瓨鍣?
        ldr r1, =( ( 68 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]
    
        ldr r0, =0x7e001028   @t_RCD瀵勫瓨鍣?
        ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]
    
        ldr r0, =0x7e00102c   @t_RFC瀵勫瓨鍣?
        ldr r1, =( ( 80 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]
    
        ldr r0, =0x7e001030   @t_RP瀵勫瓨鍣?
        ldr r1, =( ( 23 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]
    
        ldr r0, =0x7e001034   @t_rrd瀵勫瓨鍣?
        ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]
    
        ldr r0, =0x7e001038   @t_wr瀵勫瓨鍣?
        ldr r1, =( ( 15 / ( 1000000000 / 133000000 ) + 1 ) )
     @  ldr r2, [r0]
        str r1, [r0]
    
        ldr r0, =0x7e00103c   @t_wtr瀵勫瓨鍣?
        mov r1, #0x07
        str r1, [r0]
    
        ldr r0, =0x7e001040   @t_xp瀵勫瓨鍣?
        mov r1, #0x02
        str r1, [r0]
    
        ldr r0, =0x7e001044   @t_xsr瀵勫瓨鍣?
        ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]
    
        ldr r0, =0x7e001048   @t_esr瀵勫瓨鍣?
        ldr r1, =( ( 120 / ( 1000000000 / 133000000 ) + 1 ) )
        str r1, [r0]
    
        ldr r0, =0x7e00100c   @鍐呭瓨鎺у埗閰嶇疆瀵勫瓨鍣?
        ldr r1, =0x00010012   @閰嶇疆鎺у埗鍣?
        str r1, [r0]
    
        ldr r0, =0x7e00104c   @32浣岲RAM閰嶇疆鎺у埗瀵勫瓨鍣?
        ldr r1, =0x0b45
        str r1, [r0]
    
        ldr r0, =0x7e001200   @鐗囬€夊瘎瀛樺櫒
        ldr r1, =0x150f8
        str r1, [r0]
    
        ldr r0, =0x7e001304   @鐢ㄦ埛閰嶇疆瀵勫瓨鍣?
        mov r1, #0x0
        str r1, [r0]
    
        ldr r0, =0x7e001008   @从这一步开始,初始化内存,设置mem_cmd为nop
        ldr r1, =0x000c0000
        str r1, [r0]
    
        ldr r1, =0x00000000   @‘Prechargeall’ 
        str r1, [r0]
    
        ldr r1, =0x00040000   @‘Autorefresh’2次
        str r1, [r0]
        str r1, [r0]
    
        ldr r1, =0x000a0000   @MRS
        str r1, [r0]
    
        ldr r1, =0x00080032   @Mode Reg
        str r1, [r0]
    
        ldr r0, =0x7e001004   @memc_cmd‘3’b000’
        mov r1, #0x0          @DRAM Controller enter ‘Ready’ state
        str r1, [r0]
    
    check_dmc1_ready:         @检查内存状态 ‘2’b01’, which means'Ready’
        ldr r0, =0x7e001000 
        ldr r1, [r0]
        mov r2, #0x3
        and r1, r1, r2
        cmp r1, #0x1
        bne check_dmc1_ready
        nop
        mov pc, lr

    210内存初始化

    210开发板配置的是DDR2内存。
    这里写图片描述

    内存起始地址为0x20000000

    210开发板的内存通常采用8片或者4片128M*8bit芯片级联的办法。

    代码举例(OK210开发板)

    #define DMC_PHYCONTROL0 0xf0000018
    #define DMC_PHYCONTROL1 0xf000001c
    #define DMC_CONCONTROL  0xf0000000
    #define DMC_MEMCONTROL  0xf0000004
    #define DMC_MEMCONFIG0  0xf0000008
    #define DMC_MEMCONFIG1  0xf000000c
    #define DMC_PRECHCONFIG 0xf0000014
    #define DMC_TIMINGAREF  0xf0000030
    #define DMC_TIMINGROW   0xf0000034
    #define DMC_TIMINGDATA  0xf0000038
    #define DMC_TIMINGPOWER 0xf000003c
    #define DMC_PHYSTATUS   0xf0000040
    #define DMC_DIRECTCMD   0xf0000010
    #define DMC_PWRDNCONFIG 0xf0000028
    
    #define DMC0_MEMCONTROL         0x00202400
    #define DMC0_MEMCONFIG_0        0x20F00313  
    #define DMC0_MEMCONFIG_1        0x00F00313  
    
    #define DMC0_TIMINGA_REF        0x00000618
    #define DMC0_TIMING_ROW         0x2B34438A
    #define DMC0_TIMING_DATA        0x24240000
    #define DMC0_TIMING_PWR         0x0BDC0343      
    
    .globl mem_init
    mem_init:
        @ step 2.1
        ldr r0, =DMC_PHYCONTROL0
        ldr r1, =0x00101000             
        str r1, [r0]
    
        @ step 2.2
        ldr r0, =DMC_PHYCONTROL0
        ldr r1, =0x00101002                 
        str r1, [r0]
    
        @ step 4
        ldr r0, =DMC_PHYCONTROL0
        ldr r1, =0x00101003                 
        str r1, [r0]
    
        @ step 5
        ldr r0, =DMC_CONCONTROL             
        ldr r1, =0x0FFF1350
        str r1, [r0]
    
        @ step 6
        ldr r0, =DMC_MEMCONTROL
        ldr r1, =DMC0_MEMCONTROL                
        str r1, [r0]
    
        @ step 7
        ldr r0, =DMC_MEMCONFIG0
        ldr r1, =DMC0_MEMCONFIG_0               
        str r1, [r0]
    
        @ step 8
        ldr r0, =DMC_PRECHCONFIG
        ldr r1, =0xFF000000                 
        str r1, [r0]
    
        @ step 9.1
        ldr r0, =DMC_TIMINGAREF
        ldr r1, =DMC0_TIMINGA_REF               
        str r1, [r0]
    
        @ step 9.2
        ldr r0, =DMC_TIMINGROW
        ldr r1, =DMC0_TIMING_ROW                
        str r1, [r0]
    
        @ step 9.3
        ldr r0, =DMC_TIMINGDATA
        ldr r1, =DMC0_TIMING_DATA               
        str r1, [r0]
    
        @ step 9.4
        ldr r0, =DMC_TIMINGPOWER
        ldr r1, =DMC0_TIMING_PWR                
        str r1, [r0]
    
        @ step 11
    wait_lock:
        ldr r0, =DMC_PHYSTATUS 
        ldr r1, [r0]            
        and r2, r1, #0x4
        cmp r2, #0x4                    
        bne wait_lock
    
        @ step 14
        ldr r0, =DMC_DIRECTCMD
        ldr r1, =0x07000000                 
        str r1, [r0]
    
        @ step 16
        ldr r1, =0x01000000                 
        str r1, [r0]
    
        @ step 17
        ldr r1, =0x00020000                 
        str r1, [r0]
    
        @ step 18
        ldr r1, =0x00030000                 
        str r1, [r0]
    
        @ step 19
        ldr r1, =0x00010400                 
        str r1, [r0]
    
        @ step 20
        ldr r1, =0x00000542                 
        str r1, [r0]
    
        @ step 21
        ldr r1, =0x01000000                 
        str r1, [r0]
    
        @ step 22.1 
        ldr r1, =0x05000000                 
        str r1, [r0]
    
        @ step 22.2
        ldr r1, =0x05000000                 
        str r1, [r0]
    
        @ step 23
        ldr r1, =0x00000442                 
        str r1, [r0]
    
        @ step 25.1
        ldr r1, =0x00010780                 
        str r1, [r0]
    
        @ step 25.2
        ldr r1, =0x00010400                 
        str r1, [r0]
    
        @ step 26, repeat step14~step25
        ldr r1, =0x07100000                 
        str r1, [r0]
    
        ldr r1, =0x01100000                 
        str r1, [r0]
    
        ldr r1, =0x00120000                 
        str r1, [r0]
    
        ldr r1, =0x00130000                 
        str r1, [r0]
    
        ldr r1, =0x00110400                 
        str r1, [r0]
    
        ldr r1, =0x00100542                 
        str r1, [r0]
    
        ldr r1, =0x01100000                 
        str r1, [r0]
    
        ldr r1, =0x05100000                 
        str r1, [r0]
    
        ldr r1, =0x05100000                 
        str r1, [r0]
    
        ldr r1, =0x00100442                 
        str r1, [r0]
    
        ldr r1, =0x00110780                 
        str r1, [r0]
    
        ldr r1, =0x00110400                 
        str r1, [r0]
    
        @ step 27
        ldr     r0, =DMC_CONCONTROL
        ldr r1, =0x0FF02030                 
        str r1, [r0]
    
        ldr     r0, =DMC_PWRDNCONFIG
        ldr r1, =0xFFFF00FF                 
        str r1, [r0]
    
        ldr     r0, =DMC_CONCONTROL
        ldr r1, =0x00202400                 
        str r1, [r0]
    
        mov pc, lr
    展开全文
  • ...C++在new时的初始化的规律可能为:对于有构造函数的类,不论有没有括号,都用...如果没有构造函数,则不加括号的new只分配内存空间,不进行内存初始化,而加了括号的new会在分配内存的同时初始化为0。  
  • 特别对于ROM,内存初始化就显得比较重要。当然你完全可以手工在QUARTUS II打开mif文件的表格里或是在EXCEL中逐个输入,几十项(字)或是近百项(字)你还可以接受,如果上千项或是更多呢?估计能累的人吐血! ...
  • Uboot 内存初始化(2440)

    千次阅读 2014-03-13 21:49:46
    Uboot 内存初始化(2440) 内存分类,DRAM:需要定期充电(刷新),否则数据会丢失,存取速度慢。SRAM:具有静止存储功能的内存,不需要定期刷新操作就能保存它内部存储的数据,存取速度快,CPU内部的steppingstone...
  • UCOSIII操作系统UCOSIII操作系统——系统初始化篇(2)CPU,SysTick,内存初始化 UCOSIII其他内容导航不迷路 UCOSIII操作系统-简介 UCOSIII操作系统——任务篇(1)创建任务 UCOSIII操作系统——任务篇(2)相关API...
  • 初始化内存函数:memset()

    千次阅读 2019-05-26 08:19:16
    每种类型的变量都各自的初始化方法,memset()函数可以说是初始化内存空间的“万能函数”,通常为新申请的内存进行初始化工作,他是直接操作内存空间的,mem即是“内存”的意思,该函数的原型: #include<string.h...
  • Linux内存初始化:bootmem到buddy的过渡

    千次阅读 2014-02-19 13:04:04
    Linux的内存管理是一个Masterpiece,想把它完全彻底的搞懂真的不容易,今天主要讲一下从bootmem到buddy的过渡。 众所周知,Linux内存管理的核心是伙伴系统(buddy system)。其实在linux启动的那一刻,内存管理就...
  • 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 ...在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换
  • C++ new 动态内存 对象初始化

    千次阅读 2018-08-21 16:40:57
    User a[2]=User(23,24);这种写法对数组的每一个对象调用有参数的构造函数,是功能实现最完备的形式。 User a(23,24);这种写法可以调用有参数的构造函数。...这种写法不初始化,仅分配内存,里面是乱码。 int a=...
  • 关于STM32使用LWIP协议栈二次初始化时无法成功初始化TCP服务器----内存碎片化问题以及解决方法 关于LWIP协议栈的话后期再出一个相关的系列文章吧,关于使用LAN8720芯片断网线重连的问题可以参考:我的这篇博客 这里...
  • C语言数组初始化及malloc初始化

    千次阅读 2021-05-06 20:39:20
    数组赋值初始化的三个方式 1、{0} 初始化 例如: int nums[3] = {0}; 但是经常出现的是给定长度(变量)然后需要进行初始化,如果写成下式: int main(){ int numsSize=0; scanf("%d",&numsSize); int ...
  • 动态内存分配——new的初始化

    千次阅读 2019-11-22 15:27:09
    最近在C++用new进行动态内存分配的时候,发现在new一个内置类型时,new是不会对其进行初始化的。可以总结一下new一个内置类型时,可以采用的初始化方法。 单变量初始化 可以采用以下形式: int*p = new int();//此时...
  • C++学习之内存的分配和初始化

    千次阅读 2018-10-06 13:46:50
    1. 使用new动态分配和初始化对象 在自由空间分配的内存是无名的,new返回一个指向分配的对象的指针。 int *pi = new int; // pi指向一个动态分配的、未初始化的无名对象 默认情况下,动态分配的对象是默认初始...
  • C语言内存初始化

    千次阅读 2016-05-08 02:17:47
    我们编写C语言的时候需要给变量申请一块内存区域,当我们创建一个内存区域的时候,内存中的数据十有八九是乱七八糟的(因为其他代码用过后遗留的数据并没有及时清掉) 例如: int main() { char str[10];//分配的...
  • 通过下述代码:可以分别输出:最大堆内存和Jvm初始化内存(单位是M) public static void main(String[] args) { System.out.println(Runtime.getRuntime().maxMemory()>>20); System.out.println(Runtime...
  • 动态分配内存初始化

    千次阅读 2016-08-12 17:09:00
    内存的动态分配区域中分配一个长度为size的连续空间,如果分配成功,则返回所分配内存空间的首地址,否则返回NULL,申请的内存不会进行初始化。 2)calloc 函数: void *calloc(unsigned int num, unsigned int ...
  • 关于C初始化内存

    千次阅读 2015-04-23 09:23:12
    关于C初始化内存
  • c语言结构体学习整理(结构体初始化,结构体指针)

    万次阅读 多人点赞 2018-11-01 20:22:12
    请注意,在我们进行数组初始化的时候如果定义的数组过长,而我们只初始化了一部分数据,对于未初始化的数据如果是数值型,则会自动赋值为0,对于字符型,会自动赋初值为NULL,即‘\0’ 即不足的元素补以默认值 这里...
  • 堆:先进先出 FIFO:First in first out 手动分配、释放栈:后进先出 FILO:First in last out 自动分配释放裸机情况下使用动态内存heap:在启动文件(startup_stm32f103xe.s)中调整:Heap_Size EQU 0x00000200然后...
  • 嵌入式系统初始化过程

    千次阅读 2018-05-21 16:32:29
    系统初始化过程可以分为 3 个主要环节,按照自底向上、从硬件到软件的次序依次为:片级初始化、板级初始化和系统级初始化。1.片级初始化 完成嵌入式微处理器的初始化,包括设置嵌入式微处理器的核心寄存器和控制...
  • 一、没有为指针分配内存定义了指针变量,但是没有为指针分配...1、结构体成员指针未初始化struct student { char *name; int score; }stu,*pstu; int main() { strcpy(stu.name,"Jimy"); stu.score = 99; return ...
  • 明明已经定义了due,为什么还会报警说“使用了未初始化内存due?” ``` #include main() { float money,due; char ontime; printf("How much do you owe?"); scanf_s("%f", &money); printf("On ...
  • // 分配100个字节的内存空间下面的两种写法是等价的:// calloc() 分配内存空间并初始化 char *str1 = (char *)calloc(10, 2); // malloc() 分配内存空间并用 memset() 初始化 char *str2 = (char *)malloc(20
  • malloc到未初始化内存

    千次阅读 2016-09-20 09:41:23
    在最近开发过程中发现一个malloc到未初始化内存的错误. 在使用CLISH(一款命令行开源软件)的时候,每次这个程序退出的时候都会发生core dump,错误为invalid pointer: 0x00007ffff02b35d8 . 但是这个错误只在某一台...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,377,091
精华内容 550,836
关键字:

内存的初始化