pigeon0411
pigeon0411

注册于 5 years ago

回答
0
文章
0
关注者
0

一直纠结要使用RTT还是FREE RTOS,,毕竟FREE RTOS是经过成千上万厂家,和十几年的升级优化发展起来的。 现在看来,后期的大型类人机器人,我们也计划使用RTT。

问题已经解决了:增加了线程初始时的堆栈空间大小。

一般情况下,如果线程的堆栈空间不够时,在finsh中会有警告等提示,而调试这个文件系统时,不知道为什么刚好没有提示,所以理所当然地认为堆栈大小应该没问题。
结果最后还是修改了堆栈大小,然后就没出现内存分配的问题了。

另外针对rt_malloc这个函数,我发现在mem.c 和 Slab.c还有Memheap.c文件中都有定义,到底哪个文件里面的更稳定呢?

dfs系统调用的是mem.c中的rt_malloc函数。


dfs_elm_open在第二次调用下面的函数时,出现了指针值异常。


void *rt_malloc(rt_size_t size)
{
rt_size_t ptr, ptr2;
struct heap_mem *mem, *mem2;

RT_DEBUG_NOT_IN_INTERRUPT;

if (size == 0)
return RT_NULL;

if (size != RT_ALIGN(size, RT_ALIGN_SIZE))
RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d, but align to %d
",
size, RT_ALIGN(size, RT_ALIGN_SIZE)));
else
RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d
", size));

/* alignment size */
size = RT_ALIGN(size, RT_ALIGN_SIZE);

if (size > mem_size_aligned)
{
RT_DEBUG_LOG(RT_DEBUG_MEM, ("no memory
"));

return RT_NULL;
}

/* every data block must be at least MIN_SIZE_ALIGNED long */
if (size < MIN_SIZE_ALIGNED)
size = MIN_SIZE_ALIGNED;

/* take memory semaphore */
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);

for (ptr = (rt_uint8_t *)lfree - heap_ptr;
ptr < mem_size_aligned - size;
ptr = ((struct heap_mem *)&heap_ptr[ptr])->next) //********** 这个地方出现了ptr异常,超出了有效范围*******
{
mem = (struct heap_mem *)&heap_ptr[ptr];

if ((!mem->used) && (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size)
{
/* mem is not used and at least perfect fit is possible:
* mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */

if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >=
(size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED))
{
/* (in addition to the above, we test if another struct heap_mem (SIZEOF_STRUCT_MEM) containing
* at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
* -> split large block, create empty remainder,
* remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
* mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
* struct heap_mem would fit in but no data between mem2 and mem2->next
* @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
* region that couldn't hold data, but when mem->next gets freed,
* the 2 regions would be combined, resulting in more free memory
*/
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;

/* create mem2 struct */
mem2 = (struct heap_mem *)&heap_ptr[ptr2];
mem2->used = 0;
mem2->next = mem->next;
mem2->prev = ptr;

/* and insert it between mem and mem->next */
mem->next = ptr2;
mem->used = 1;

if (mem2->next != mem_size_aligned + SIZEOF_STRUCT_MEM)
{
((struct heap_mem *)&heap_ptr[mem2->next])->prev = ptr2;
}
#ifdef RT_MEM_STATS
used_mem += (size + SIZEOF_STRUCT_MEM);
if (max_mem < used_mem)
max_mem = used_mem;
#endif
}
else
{
/* (a mem2 struct does no fit into the user data space of mem and mem->next will always
* be used at this point: if not we have 2 unused structs in a row, plug_holes should have
* take care of this).
* -> near fit or excact fit: do not split, no mem2 creation
* also can't move mem->next directly behind mem, since mem->next
* will always be used at this point!
*/
mem->used = 1;
#ifdef RT_MEM_STATS
used_mem += mem->next - ((rt_uint8_t*)mem - heap_ptr);
if (max_mem < used_mem)
max_mem = used_mem;
#endif
}
/* set memory block magic */
mem->magic = HEAP_MAGIC;

if (mem == lfree)
{
/* Find next free block after mem and update lowest free pointer */
while (lfree->used && lfree != heap_end)
lfree = (struct heap_mem *)&heap_ptr[lfree->next];

RT_ASSERT(((lfree == heap_end) || (!lfree->used)));
}

rt_sem_release(&heap_sem);
RT_ASSERT((rt_uint32_t)mem + SIZEOF_STRUCT_MEM + size <= (rt_uint32_t)heap_end);
RT_ASSERT((rt_uint32_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM) % RT_ALIGN_SIZE == 0);
RT_ASSERT((((rt_uint32_t)mem) & (RT_ALIGN_SIZE-1)) == 0);

RT_DEBUG_LOG(RT_DEBUG_MEM,
("allocate memory at 0x%x, size: %d
",
(rt_uint32_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM),
(rt_uint32_t)(mem->next - ((rt_uint8_t *)mem - heap_ptr))));

RT_OBJECT_HOOK_CALL(rt_malloc_hook,
(((void *)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM)), size));

/* return the memory data except mem struct */
return (rt_uint8_t *)mem + SIZEOF_STRUCT_MEM;
}
}

rt_sem_release(&heap_sem);

return RT_NULL;
}

dfs_elm_open
dfs_elm_read
dfs_elm_close


都不是给用户使用的,给用户使用的是 dfs_file_open等。
或封装后posix兼容的open/read/close

malloc失败先检查可用内存及内存泄露问题。



我实际使用的是封装后posix兼容的open/read/close,为了方便说明问题,就把实际调用的上面的函数列出来了。
我最初也怀疑是内存不够的问题,换了大内存的芯片测试还是一样的问题,查看可用内存还有30多KB。

看了一下rmdir函数原型,看来它同样可以完成rm的功能。

哈哈,显示抛出标题档,然后再抛出bug门?


运行很稳定

写的不错,可以尽量用一些轻松的语调,现实生活中的一些比喻,多一些图形解释。

预计什么时候出版?

可以跟入失败的地方。

挂载前需要格式化,如果从末格式化的话。

如果只能用一次,还不如直接调用好了。



非常感谢这么快速有效的回复 。问题已经解决:

finsh>>mkfs("elm","flash0")
0, 0x00000000
finsh>>
finsh>>
| />>reset()
- RT - Thread Operating System
/ | 2.0.1 build Sep 23 2015
2006 - 2015 Copyright by rt-thread team
W25Q32BV detection
flash0 mount to /.
finsh>>


对RTT越来越喜欢了。

另外还有个问题,类似 INIT_APP_EXPORT 这样的宏是否可以被 多次使用,用来初始化多个不同的函数 ?

关于宏 INIT_APP_EXPORT 的问题
确保DFS及 elm FAT有成功初始化。

另外,贴子理好一点,看的人会多一点。



确实是因为没有将桩中的函数编译进去。在MDK中加入了 --keep __rt_init*,就可以把初始化代码编译进去了。
解决办法 : http://www.rt-thread.org/phpBB3/topic2867-20.html

程序可以正常运行了,不过FLASH加载还没有搞定,下面是提示信息: 求解决


| /
- RT - Thread Operating System
/ | 2.0.1 build Sep 23 2015
2006 - 2015 Copyright by rt-thread team
W25Q32BV detection
flash0 mount to / failed.
msh >

msh >list_thread
thread pri status sp stack size max used left tick error
-------- ---- ------- ---------- ---------- ---------- ---------- ---
tidle 0x1f ready 0x00000040 0x00000400 0x00000058 0x00000011 000
tshell 0x14 ready 0x00000090 0x00001000 0x00000140 0x00000007 000
init 0x0a init 0x00000040 0x00000800 0x00000040 0x00000014 000
msh >

发布
问题