Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
RT-Thread Studio
SRAM
10
rtt studio使用外部SRAM
发布于 2022-01-12 16:20:57 浏览:3040
订阅该版
rtt studio怎么使用外部的SDRAM呢?目前加载了 drv_sram.c,使用了memheap 内存管理, ``` rt_memheap_init(&sdram_heap, "sdram", (void *)SRAM_BANK_ADDR, SRAM_SIZE); ``` log如下: ``` [16:15:09.729]收←◆[0m[D/drv.sram] sram init success, mapped at 0x68000000, size is 1048576 bytes, data width is 16[0m \ | / - RT - Thread Operating System / | \ 4.1.0 build Jan 12 2022 15:50:27 2006 - 2021 Copyright by rt-thread team msh >free [16:18:10.433]收←◆free total : 126488 used : 7196 maximum : 7196 msh >list_memheap [16:18:15.369]收←◆list_memheap memheap pool size max used size available size -------- ---------- ------------- -------------- sdram 1048576 48 1048528 heap 126488 7196 119292 msh >sram_test [16:18:27.572]收←◆sram_test [0m[D/drv.sram] Writing the 1048576 bytes data, waiting....[0m [16:18:27.682]收←◆[0m[D/drv.sram] Write data success, total time: 0.103S.[0m [0m[D/drv.sram] start Reading and verifying data, waiting....[0m [16:18:27.848]收←◆[0m[D/drv.sram] SRAM test success![0m msh > ``` 怎么能像使用内部RAM一样使用外部SDRAM呢?比如说定义的变量太大了,然后内部RAM放不下了,自动的放到外部的SDRAM呢?这种应该怎么配置呢?链接脚本如下: ![image.png](https://oss-club.rt-thread.org/uploads/20220112/a971abeff3a87acd18c8364933cf8e3f.png) ------ ------ 问题补充: 根据官方文档 “memheap 工作机制如下图所示,首先将多块内存加入 memheap_item 链表进行粘合。当分配内存块时,会先从默认内存堆去分配内存,当分配不到时会查找 memheap_item 链表,尝试从其他的内存堆上分配内存块。应用程序不用关心当前分配的内存块位于哪个内存堆上,就像是在操作一个内存堆。” 我用 list_memheap 命令打印出来了两块内存,然后我在 sram_test 函数中使用 rt_malloc 不断的申请内存,代码如下所示: ``` static int sram_test(void) { ... ... /* 省略掉前面的读写测试代码 */ char *ptr_t; for(i=0; i<5; i++) { ptr_t = rt_malloc(1024*50); LOG_D("ptr_t: %p", ptr_t); } return RT_EOK; } MSH_CMD_EXPORT(sram_test, sram test); ``` 测试结果发现,不断申请时,当申请的空间小于内部RAM的剩余空间时,可以申请成功,当申请的空间大于内部RAM的剩余空间时,申请失败,程序死掉,log如下: ``` [17:04:03.293]收←◆[0m[D/drv.sram] sram init success, mapped at 0x68000000, size is 1048576 bytes, data width is 16[0m \ | / - RT - Thread Operating System / | \ 4.1.0 build Jan 12 2022 15:50:27 2006 - 2021 Copyright by rt-thread team msh >list_memheap [17:04:08.730]收←◆list_memheap memheap pool size max used size available size -------- ---------- ------------- -------------- sdram 1048576 48 1048528 heap 126488 7196 119292 msh >sram_test [17:04:13.830]收←◆sram_test [0m[D/drv.sram] Writing the 1048576 bytes data, waiting....[0m [17:04:13.940]收←◆[0m[D/drv.sram] Write data success, total time: 0.103S.[0m [0m[D/drv.sram] start Reading and verifying data, waiting....[0m [17:04:14.100]收←◆[0m[D/drv.sram] SRAM test success![0m [0m[D/drv.sram] ptr_t: 20002dec[0m [0m[D/drv.sram] ptr_t: 2000f604[0m psr: 0x01000000 r00: 0x00000000 r01: 0xffffffff r02: 0x6800c818 r03: 0x68000000 r04: 0xdeadbeef r05: 0xdeadbeef r06: 0xdeadbeef r07: 0x20002c58 r08: 0xdeadbeef r09: 0xdeadbeef r10: 0xdeadbeef r11: 0xdeadbeef r12: 0x20001b26 lr: 0x08001241 pc: 0x08002964 hard fault on thread: tshell thread pri status sp stack size max used left tick error -------- --- ------- ---------- ---------- ------ ---------- --- tshell 20 running 0x000000cc 0x00001000 11% 0x00000006 000 tidle0 31 ready 0x0000005c 0x00000400 12% 0x00000020 000 main 10 suspend 0x000000bc 0x00000800 14% 0x00000012 000 bus fault: SCB_CFSR_BFSR:0x04 IMPRECISERR ```
查看更多
2
个回答
默认排序
按发布时间排序
crystal266
2022-01-13
嵌入式
自问自答一下: 使用下面的函数可以把片外的 SRAM 添加到 memheap_item 链表中,在控制台使用命令 list_memheap 可以查看是否成功添加到该链表中。 ``` rt_memheap_init(&sram_heap, "sram", (void *)SRAM_BANK_ADDR, SRAM_SIZE); ``` 如果成功添加到 memheap_item 链表中,执行命令 list_memheap 后能够显示出添加的外部 SRAM 的信息,表示 rt_memheap_init 初始化成功,并成功添加到 memheap_item 链表中。 ``` msh >list_memheap [13:24:01.018]收←◆list_memheap memheap pool size max used size available size -------- ---------- ------------- -------------- sram 1048576 48 1048528 heap 126416 7196 119220 msh > ``` 从里面可以看出来 rt_memheap_init 初始化后,SRAM 已经使用了48字节的大小,经过分析使用的部分的作用是类似于fatfs的引导扇区,将48字节的内容打印出来可以看到如下所示。 ``` 0x1EA0 0x1EA0 0x1014 0x2000 0xFFE8 0x680F 0xFFE8 0x680F 0x1040 0x2000 0x1040 0x2000 0xCFDA 0x9220 0xFE24 0xFA92 0x99F7 0x087A 0x58F0 0x4856 0x3F77 0x3D0C 0xEACF 0x0041 ``` 查看 rt_memheap_init 源码发现如下所示内容,其中 #define RT_MEMHEAP_MAGIC 0x1ea01ea0,所以笔者认为前面的48字节是RTT在初始化时存储了一些引导信息或SDRAM的信息。 ``` item->magic = (RT_MEMHEAP_MAGIC | RT_MEMHEAP_FREED); ``` ------------------------ ------------------------ 对于 SRAM 的使用,在分析源码时发现,rt_malloc 实际执行的是 _memheap_alloc,执行这个函数传递的第一个参数是 &system_heap,也就是片上RAM区域构成的heap空间,所以使用 rt_malloc 申请空间时一直申请的是片上的RAM,这也就解释了为什么在问题补充中申请空间超过片上RAM的剩余空间时报程序死掉的原因。 ``` rt_malloc(size) /* rt-thread/src/kservice.c */ |-> _MEM_MALLOC(size) /* rt-thread/src/kservice.c */ |-> _memheap_alloc(&system_heap, _size) /* rt-thread/src/kservice.c */ |-> rt_memheap_alloc(heap, size); /* rt-thread/src/memheap.c */ ``` ------------------------ ------------------------ 那么片外的SRAM应该怎么用呢,发现 rt_memheap_alloc 在使用时传递了一个 heap 的参数,所以我实验了使用 rt_memheap_alloc 函数来申请空间,代码如下,但是在实际执行的过程中还是会死掉,后面分析了一下发现在 sram_test 这个函数中最开始会把整个片外的 SRAM 都写成0x5555,这样破坏了 rt_memheap_init 初始化时生成的引导信息,导致分配内存失败。 ``` static struct rt_memheap sdram_heap; static int sram_test(void) { int i = 0; uint32_t start_time = 0, time_cast = 0; #if SRAM_DATA_WIDTH == 8 char data_width = 1; uint8_t data = 0; #elif SRAM_DATA_WIDTH == 16 char data_width = 2; uint16_t data = 0; #else char data_width = 4; uint32_t data = 0; #endif /* write data */ LOG_D("Writing the %ld bytes data, waiting....", SRAM_SIZE); start_time = rt_tick_get(); for (i = 1024; i < SRAM_SIZE / data_width; i++) { #if SRAM_DATA_WIDTH == 8 *(__IO uint8_t *)(SRAM_BANK_ADDR + i * data_width) = (uint8_t)0x55; #elif SRAM_DATA_WIDTH == 16 *(__IO uint16_t *)(SRAM_BANK_ADDR + i * data_width) = (uint16_t)0x5555; #else *(__IO uint32_t *)(SRAM_BANK_ADDR + i * data_width) = (uint32_t)0x55555555; #endif } time_cast = rt_tick_get() - start_time; LOG_D("Write data success, total time: %d.%03dS.", time_cast / RT_TICK_PER_SECOND, time_cast % RT_TICK_PER_SECOND / ((RT_TICK_PER_SECOND * 1 + 999) / 1000)); /* read data */ LOG_D("start Reading and verifying data, waiting...."); for (i = 0; i < SRAM_SIZE / data_width; i++) { #if SRAM_DATA_WIDTH == 8 data = *(__IO uint8_t *)(SRAM_BANK_ADDR + i * data_width); if (data != 0x55) { LOG_E("SRAM test failed!"); break; } #elif SRAM_DATA_WIDTH == 16 data = *(__IO uint16_t *)(SRAM_BANK_ADDR + i * data_width); rt_kprintf("0x%04X \n", data); if (data != 0x5555) { LOG_E("SRAM test failed!"); break; } #else data = *(__IO uint32_t *)(SRAM_BANK_ADDR + i * data_width); if (data != 0x55555555) { LOG_E("SRAM test failed!"); break; } #endif } if (i >= SRAM_SIZE / data_width) { LOG_D("SRAM test success!"); } char *ptr_t; for(i=0; i<5; i++) { ptr_t = rt_memheap_alloc(&sdram_heap, 1024); if(ptr_t != RT_NULL) LOG_D("ptr_t: %p", ptr_t); } } MSH_CMD_EXPORT(sram_test, sram test); ``` 后面把 sram_test 自带的直接按照地址读写的相关代码注释掉后,代码如下 ``` static int sram_test(void) { int i = 0; char *ptr_t; for(i=0; i<5; i++) { ptr_t = rt_memheap_alloc(&sdram_heap, 1024); if(ptr_t != RT_NULL) LOG_D("ptr_t: %p", ptr_t); } return RT_EOK; } MSH_CMD_EXPORT(sram_test, sram test); ``` 上述代码的执行结果如下,测试后发现可以成功申请到空间,冰鞋申请的内存地址也为片外SRAM的范围内,片上RAM的使用内存大小没有变化,证明成功申请到了片外的SRAM内存。 ``` msh >list_memheap [13:47:47.193]收←◆list_memheap memheap pool size max used size available size -------- ---------- ------------- -------------- sdram 1048576 48 1048528 heap 126416 7196 119220 msh >sram_test [13:47:55.897]收←◆sram_test [D/drv.sram] ptr_t: 68000018 [D/drv.sram] ptr_t: 68000430 [D/drv.sram] ptr_t: 68000848 [D/drv.sram] ptr_t: 68000c60 [D/drv.sram] ptr_t: 68001078 msh >list_memheap [13:48:06.162]收←◆list_memheap memheap pool size max used size available size -------- ---------- ------------- -------------- sdram 1048576 5288 1043288 heap 126416 7196 119220 msh > ``` --------- --------- 疑问: 1. 这里是列表文本这里是列表文本按照官方文档的说法使用memheap可以实现 “当分配内存块时,会先从默认内存堆去分配内存,当分配不到时会查找 memheap_item 链表,尝试从其他的内存堆上分配内存块。应用程序不用关心当前分配的内存块位于哪个内存堆上,就像是在操作一个内存堆。” 为什么实际测试的结果需要指定从哪个内存堆上来申请空间,而不能由系统自动分配,是不是哪里使用的还有错误???? 2. 上面使用 rt_memheap_alloc 申请的内存第一次申请的起始地址为0x68000018,是从第24个字节的位置开始分配的,这个与 rt_memheap_init 初始化成功后的48个字节的引导信息内存重叠了,是不是对 rt_memheap_init 初始化后的48字节的引导信息存储的位置理解有误???? 注意: 1. 使用 rt_memheap_alloc 申请的空间里面内容是乱的,使用前最好用memset清空一下。
星云0
2024-06-20
这家伙很懒,什么也没写!
谢谢分享,收藏一下👍👍👍
撰写答案
登录
注册新账号
关注者
3
被浏览
3k
关于作者
crystal266
嵌入式
提问
33
回答
547
被采纳
161
关注TA
发私信
相关问题
1
rt_thread studio 啥时候能用呢
2
RT_Thread使用反馈帖子
3
RTT studio 下的 AT指令问题。
4
什么时候RTT Sdudio支持Ubuntu,Deepin和UOS操作系统
5
rt thread Studio 关于J-LINK下载问题
6
RT-Thread studio 调试设置问题
7
RTT-Studio 如何设置调试配置参数?
8
rt_thread studio 软件包配置
9
RT-Studio目前只能开发STM32的项目吗?
10
rtt studio 生成hex名字修改
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
开源共生 商业共赢 | RT-Thread 2024开发者大会议程正式发布!
2
【24嵌入式设计大赛】基于RT-Thread星火一号的智慧家居系统
3
RT-Thread EtherKit开源以太网硬件正式发布
4
如何在master上的BSP中添加配置yml文件
5
使用百度AI助手辅助编写一个rt-thread下的ONVIF设备发现功能的功能代码
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
MicroPython
C++_cpp
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
19
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
6
个答案
2
次被采纳
用户名由3_15位
13
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
RTT_逍遥
1
篇文章
6
次点赞
大龄码农
1
篇文章
5
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部