設置Linux保留物理內存並使用 (1)

发布者:幸福的家园最新更新时间:2023-06-26 来源: elecfans关键字:Linux  tq2440 手机看文章 扫描二维码
随时随地手机看文章

平臺

硬件平臺: TQ2440


Linux版本:Linux 3.14.45


說明


1.在tq2440上,物理內存的起始地址是0x30000000,一共有64MB的內存,所以物理內存地址範圍是: 0x30000000 -> 0x33ffffff


2.可以在uboot傳給kernel的參數bootargs中添加一個"memblock=debug",這樣在Linux啓動的時候,會將設置memblock的信息打印出來



參考博文

Linux内核---41.arm 内存初始化


http://bbs.chinaunix.net/thread-4143403-1-1.html


代碼調用

在Linux啓動的時候會調用machine相關的代碼定製部分系統保留內存,函數調用如下:


start_kernel


    ----> setup_arch


            ----> arm_memblock_init


                     ----> mdesc->reserve()


所以我們可以修改machine相關的代碼,添加reserve函數的實現。


方法一

修改mach-tq2440.c如下:


 1 diff --git a/arch/arm/mach-s3c24xx/mach-tq2440.c b/arch/arm/mach-s3c24xx/mach-tq2440.c

 2 index f9679fb..da75db2 100644

 3 --- a/arch/arm/mach-s3c24xx/mach-tq2440.c

 4 +++ b/arch/arm/mach-s3c24xx/mach-tq2440.c

 5 @@ -23,6 +23,7 @@

 6  #include

 7  #include

 8  #include

 9 +#include

10  

11  #include

12  #include

13 @@ -503,11 +504,28 @@ static void __init tq2440_machine_init(void)

14         s3c_pm_init();

15  }

16  

17 +static void __init tq2440_reserve(void) {

18 +    u32 paddr,size;

19 +

20 +    printk("%s enter.n", __func__);

21 +

22 +    paddr = 0x32000000;

23 +    size = 0x200000;

24 +

25 +    if (memblock_reserve(paddr, size) < 0) {

26 +        pr_err("failed to reserve DRAM - no memoryn");

27 +               return;

28 +    }

29 +

30 +    printk("reserve : reserve %dM memn", size>>20);

31 +}

32 +

33  MACHINE_START(TQ2440, "TQ2440")

34         /* Maintainer: Ben Dooks */

35         .atag_offset    = 0x100,

36  

37         .init_irq       = s3c2440_init_irq,

38 +    .reserve    = tq2440_reserve,

39         .map_io         = tq2440_map_io,

40         .init_machine   = tq2440_machine_init,

41         .init_time      = samsung_timer_init,


上面我們在0x32000000開始的地方保留了2MB的物理內存,然後調用memblock_reserve告訴系統。這個在系統的啓動信息中可以看到:


 1 [    0.000000] Machine: TQ2440

 2 [    0.000000] memblock_reserve: [0x00000030008200-0x0000003057fc03] flags 0x0 arm_memblock_init+0x4c/0x1bc

 3 [    0.000000] memblock_reserve: [0x00000030004000-0x00000030007fff] flags 0x0 arm_memblock_init+0x158/0x1bc

 4 [    0.000000] tq2440_reserve enter.

 5 [    0.000000] memblock_reserve: [0x00000032000000-0x000000321fffff] flags 0x0 tq2440_reserve+0x1c/0x50

 6 [    0.000000] reserve : reserve 2M mem

 7 [    0.000000] MEMBLOCK configuration:

 8 [    0.000000]  memory size = 0x4000000 reserved size = 0x77ba04

 9 [    0.000000]  memory.cnt  = 0x1

10 [    0.000000]  memory[0x0]    [0x00000030000000-0x00000033ffffff], 0x4000000 bytes flags: 0x0

11 [    0.000000]  reserved.cnt  = 0x3

12 [    0.000000]  reserved[0x0]    [0x00000030004000-0x00000030007fff], 0x4000 bytes flags: 0x0

13 [    0.000000]  reserved[0x1]    [0x00000030008200-0x0000003057fc03], 0x577a04 bytes flags: 0x0

14 [    0.000000]  reserved[0x2]    [0x00000032000000-0x000000321fffff], 0x200000 bytes flags: 0x0


上面的第5行和第14行就是我們自己設置的保留內存範圍信息。在Linux啓動後,在debugfs中也可以看到memblock的信息:


[root@TQ2440 /]# cat /sys/kernel/debug/memblock/memory 

   0: 0x30000000..0x33ffffff

[root@TQ2440 /]# cat /sys/kernel/debug/memblock/reserved 

   0: 0x30004000..0x30007fff

   1: 0x30008200..0x3057fc03

   2: 0x32000000..0x321fffff

   3: 0x33f60000..0x33ffbfff

   4: 0x33ffc540..0x33ffc96b

   5: 0x33ffc980..0x33ffc9f7

   6: 0x33ffca00..0x33ffca03

   7: 0x33ffca20..0x33ffca23

   8: 0x33ffca40..0x33ffca43

   9: 0x33ffca60..0x33ffca63

  10: 0x33ffca80..0x33ffcad2

  11: 0x33ffcae0..0x33ffcb32

  12: 0x33ffcb40..0x33ffcb92

  13: 0x33ffcba0..0x33ffcbbb

  14: 0x33ffcbc0..0x33ffcdc7

  15: 0x33ffcdd0..0x33ffffff


其中memory節點中存放的是可用的物理內存地址範圍,reserved表示已經分配出去的物理地址,第2行記錄的就是我們設置的。


既然添加了保留物理內存,那麼如何使用呢?下面我寫了一個簡單的內核模塊,使用我們添加的保留物理內存,下面是內核模塊的代碼:


 1 #include

 2 

 3 #define RESERVE_PHY  0x32000000

 4 #define RESERVE_SIZE 0x200000

 5 

 6 static char str[] = "pengdonglin137@163.comn";

 7 

 8 static __init int reserve_demo_init(void)

 9 {

10     memcpy(phys_to_virt(RESERVE_PHY), str, sizeof(str));

11 

12     printk("%s: virt: %pn", __func__, phys_to_virt(RESERVE_PHY));

13 

14     return 0;

15 }

16 

17 static __exit void reserve_demo_exit(void)

18 {

19     printk("%s: %sn", __func__, (char *)phys_to_virt(RESERVE_PHY));

20 }

21 

22 module_init(reserve_demo_init);

23 module_exit(reserve_demo_exit);

24 MODULE_LICENSE("GPL");


可以看到,我們直接調用函數phys_to_virt將物理地址轉換成虛擬地址,然後直接向這個虛擬地址中寫入數據,在模塊卸載時再將內容打印出出來。


1 [root@TQ2440 /]# insmod nfs/demo.ko 

2 [ 1417.153362] reserve_demo_init: virt: c2000000

3 [root@TQ2440 /]# 

4 [root@TQ2440 /]# rmmod demo

5 [ 1420.986938] reserve_demo_exit: pengdonglin137@163.com

6 [ 1420.986938] 


可以看到,第2行中得到物理地址0x32000000對應的虛擬地址是0xC2000000。在模塊卸載時打印出了我們之前寫入的內容。


這種方法使用與物理內存在Normal區域的情況。


方法二

修改mach-tq2440.c


 1 diff --git a/arch/arm/mach-s3c24xx/mach-tq2440.c b/arch/arm/mach-s3c24xx/mach-tq2440.c

 2 index f9679fb..345a868 100644

 3 --- a/arch/arm/mach-s3c24xx/mach-tq2440.c

 4 +++ b/arch/arm/mach-s3c24xx/mach-tq2440.c

 5 @@ -23,6 +23,7 @@

 6  #include

 7  #include

 8  #include

 9 +#include

10  

11  #include

12  #include

13 @@ -503,11 +504,31 @@ static void __init tq2440_machine_init(void)

14         s3c_pm_init();

15  }

16  

17 +static void __init tq2440_reserve(void) {

18 +    u32 paddr,size;

19 +

20 +    printk("%s enter.n", __func__);

21 +

22 +    paddr = 0x32000000;

23 +    size = 0x200000;

24 +

25 +    if (memblock_reserve(paddr, size) < 0) {

26 +        pr_err("failed to reserve DRAM - no memoryn");

27 +               return;

28 +    }

29 +

30 +    memblock_free(paddr, size);

31 +    memblock_remove(paddr, size);

32 +

33 +    printk("reserve : reserve %dM memn", size>>20);

34 +}

35 +

36  MACHINE_START(TQ2440, "TQ2440")

37         /* Maintainer: Ben Dooks */

38         .atag_offset    = 0x100,

39  

40         .init_irq       = s3c2440_init_irq,

41 +    .reserve    = tq2440_reserve,

42         .map_io         = tq2440_map_io,

43         .init_machine   = tq2440_machine_init,

44         .init_time      = samsung_timer_init,


用新kernel啓動,在啓動信息中可以看到:


 1 [    0.000000] Machine: TQ2440

 2 [    0.000000] memblock_reserve: [0x00000030008200-0x0000003057fc03] flags 0x0 arm_memblock_init+0x4c/0x1bc

 3 [    0.000000] memblock_reserve: [0x00000030004000-0x00000030007fff] flags 0x0 arm_memblock_init+0x158/0x1bc

 4 [    0.000000] tq2440_reserve enter.

 5 [    0.000000] memblock_reserve: [0x00000032000000-0x000000321fffff] flags 0x0 tq2440_reserve+0x1c/0x68

 6 [    0.000000]    memblock_free: [0x00000032000000-0x000000321fffff] tq2440_reserve+0x3c/0x68

 7 [    0.000000] reserve : reserve 2M mem

 8 [    0.000000] MEMBLOCK configuration:

 9 [    0.000000]  memory size = 0x3e00000 reserved size = 0x57ba04

10 [    0.000000]  memory.cnt  = 0x2

11 [    0.000000]  memory[0x0]    [0x00000030000000-0x00000031ffffff], 0x2000000 bytes flags: 0x0

12 [    0.000000]  memory[0x1]    [0x00000032200000-0x00000033ffffff], 0x1e00000 bytes flags: 0x0

13 [    0.000000]  reserved.cnt  = 0x2

14 [    0.000000]  reserved[0x0]    [0x00000030004000-0x00000030007fff], 0x4000 bytes flags: 0x0

15 [    0.000000]  reserved[0x1]    [0x00000030008200-0x0000003057fc03], 0x577a04 bytes flags: 0x0


在kernel啓動後,在memory和reserved節點中:


[root@TQ2440 /]# cat /sys/kernel/debug/memblock/memory 

   0: 0x30000000..0x31ffffff

   1: 0x32200000..0x33ffffff

 可以看到,此時系統中有兩塊物理內存,但是這兩塊物理內存的地址之間不連續,中間有一個大小爲2MB的“洞”。此時在reserved節點看不到這部分內存。


[root@TQ2440 /]# cat /sys/kernel/debug/memblock/reserved 

   0: 0x30004000..0x30007fff

   1: 0x30008200..0x3057fc03

   2: 0x33f60000..0x33ffbfff

   3: 0x33ffc520..0x33ffc94b

   4: 0x33ffc960..0x33ffc9d7

   5: 0x33ffc9e0..0x33ffc9e3

   6: 0x33ffca00..0x33ffca03

   7: 0x33ffca20..0x33ffca23

   8: 0x33ffca40..0x33ffca43

   9: 0x33ffca60..0x33ffcab2

  10: 0x33ffcac0..0x33ffcb12

[1] [2]
关键字:Linux  tq2440 引用地址:設置Linux保留物理內存並使用 (1)

上一篇:基于TQ2440的SPI驱动学习(OLED)
下一篇:s3c2440中GPIO上拉电阻的初步认识

推荐阅读最新更新时间:2024-11-09 07:28

【ARM】一步一步移植Linux Kernel 2.6.13到板子
#1环境搭建所需材料 Linux 内核代码 编译器 文件系统 samba tftp SecureCRT6.0 开发板uboot nfs-kernel-server #2环境搭建所需材料之间的关系 #3所使用的开发板 #4译内核 ##4.1修改makefile ##4.2拷贝配置文件 ##4.3编译得到zImage ##4.4把zImage转成uImage #5开发板串口连接 串口形状 ,在电脑上映射出来的串口设备连接串口 到0回车。。。 #6uboot设置 #7通过tftp服务器下载uImage #8启动内核 这时启动内核后还不会进入文件系统 #9先看挂载文件系统的样子 先看现象
[单片机]
【ARM】一步一步移植<font color='red'>Linux</font> Kernel 2.6.13到板子
linux-2.6.32在mini2440开发板上移植-SD卡驱动移植
1 在内核中注册SD 设备驱动 Linux-2.6.32.2 已经自带了S3C2440 芯片的SD 卡驱动,我们只需在初始化代码中加入SD 平台设备结构就可以,打开arch/arm/mach-s3c2440/mach-mini2440.c,在nand flash 平台结构后面添加如下红色代码: ;在mini2440.c 的顶部添加SD 卡设备结构所需的头文件 #include linux/mmc/host.h #include plat/mci.h static struct platform_device mini2440_device_eth = { .name = dm9000 , .id = -1, .num_resour
[单片机]
TQ2440 linux i2c驱动——at24c02(eeprom)
一.开发环境: (1)开发板:TQ2440开发板 (2)pc系统:ubuntu 13.04-amd64 (3)交错编译器:arm-linux-gcc version-4.3.3 (4)linux kernel:linux 2.6.30。4 二.i2c系统简介 (这里稍微罗嗦几句结构上的东西,摘抄自网络) I2c是philips提出的外设总线.I2C只有两条线,一条串行数据线:SDA,一条是时钟线SCL.正因为这样,它方便了工程人员的布线.另外,I2C是一种多主机控制总线.它和USB总线不同,USB是基于master-slave机制,任何设备的通信必须由主机发起才可以.而I2C是基于multi master机制.一同总线上可允许
[单片机]
<font color='red'>TQ2440</font> <font color='red'>linux</font> i2c驱动——at24c02(eeprom)
Uncompressing Linux...done, booting the kernel解决办法
u-boot是好的,是刚移植成功的,用其他的内核跑过没问题。所以皇莡-boot传参有问题,问题就是出在我移植的内核上面。 我用的是mini2440的配置,linux2.6.35的内核。网上找了很多资料试了都没有,开了CONFIG_DEBUG_LL(这个选项是在Kernel hacking里面,需要你打开Kernel low-level debugging functions & Kernel Low-level debugging message via S3C UART)本来想看下出错信息的,加了之后连Uncompressing Linux...done, booting the kernel都没有了。悲剧。 后来没办法,只能设
[单片机]
OK6410A 开发板 (八) 74 linux-5.11 OK6410A linux 内核同步机制 信号量(count=1)的实现
解决的问题是什么 所有异常原因 限制是什么 加锁函数会引起睡眠,所以不能... 实现 https://elixir.bootlin.com/linux/v4.0/source/kernel/locking/semaphore.c#L53 /* 向下-获取信号量 @sem:要获取的信号量 获取信号量。如果不允许更多任务获取信号量,则调用此函数将使任务进入睡眠状态,直到释放信号量。 不赞成使用此函数,请改用down_interruptible()或down_killable()。 */ void down(struct semaphore *sem) { unsigned long flags; raw_spi
[单片机]
gcc代码反汇编查看内存分布[2]: arm-linux-gcc
arm-none-linux-gnueabi-gcc -v gcc version 4.4.1 (Sourcery G++ Lite 2010q1-202) 重点: 代码中的内存分配, 地址从低到高: 代码段(RO, 保存函数代码) -- 只读数据段(RO, 保存常量) -- 数据段(RW, 已初始化并且初始值不为0的全局变量和静态变量) -- bss段(RW, 未初始化或者初始化为0的全局变量和静态变量). 程序运行起来之后, 堆区和栈区的变量地址是动态分配的. 可以看出arm-none-linux-gnueabi-gcc编译和gcc编译结果是类似的. #include stdio.h #include s
[单片机]
Linux移植之auto.conf、autoconf.h、Mach-types.h的生成过程简析
在Linux移植之make uImage编译过程分析中分析了uImage文件产生的过程,在uImage产生的过程中,顺带还产生了其它的一些中间文件。这里主要介绍几个比较关键的文件 1、linux-2.6.22.6includeconfigauto.conf、inux-2.6.22.6includelinuxautoconf.h文件的生成过程 2、includeasm-armMach-types.h文件的生成过程 1、inux-2.6.22.6includeconfigauto.conf、inux-2.6.22.6includelinuxautoconf.h文件的生成过程 在顶层Makefile中尝试寻找auto.c
[单片机]
移植QT5.6.0到嵌入式linuxS3C2440单板
目前网上关于QT5.6的移植教程还不完善,本博客详细说明QT5.6.0移植到嵌入式linux单板的详细步骤。并将移植好的分享在GitHub上。 一、实验环境 (1)编译工具链 arm-Linux-gcc-4.4.3.tar.gz (2)linux系统 linux-3.4.2 (3)虚拟机 16.04.1-Ubuntu (4)busybox busybox-1.22.1.tar.bz2 (5)tslib tslib-1.4.tar.gz (6)qt5.6 源码 qt-everywhere-opensource-src-5.6.0.tar.gz (7)S3C24
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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