OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6436|回复: 25

很多初学者都经历问题,请高手都进来看看解决下吧!谢谢

[复制链接]

38

主题

165

帖子

0

精华

高级会员

Rank: 4

积分
646
金钱
646
注册时间
2014-3-5
在线时间
67 小时
发表于 2015-6-12 10:24:14 | 显示全部楼层 |阅读模式
5金钱

现在只想到这些问题,百思不得其解,希望大神给解决下,谢谢!

一、在FLASH模拟EEPROM试验中提到“该函数的实现基本类似第 25 章的 SPI_Flash_Write 函数,不过该函数对写入地址是有要求的,必须保证以下两点:1 该地址必须是用户代码区以外的地址。2, 该地址必须是 的倍数。”

1、那么我写入数据时如何知道代码区以外的地址是多少呢?

 

二、我们在 STM32 FLASH 写入的时候,需要一个 1024 字节的 16 位数组,实际上占用了 2K 字节,而这个数组几乎只能给 STMFLASH_Write 一个函数使用,其实这是非常浪费内存的一种做法,好的办法是:我需要的时候,申请 2K 字节,用完了我释放掉。

   1FLASH模拟EEPROM是为了掉电保存还是为了申请堆?

   2、如果是为了申请堆,那么为什么自己写mymalloc而不直接用malloc呢?

三、从上图可以看出,分块式内存管理由内存池和内存管理表两部分组成。内存池被等分为 n
块,对应的内存管理表,大小也为 n,内存管理表的每一个项对应内存池的一块内存。

 const u32 memtblsize=MEM_ALLOC_TABLE_SIZE; //内存表大小

 const u32 memblksize=MEM_BLOCK_SIZE; //内存分块大小

 const u32 memsize=MEM_MAX_SIZE; //内存总大小

   1、内存表、内存块在随着动态分配时不是需要改变吗?那么为什么他是固定的?

//内存参数设定.

#define MEM_BLOCK_SIZE 32       //内存块大小为32字节

#define MEM_MAX_SIZE 42*1024   //最大管理内存 42K

#define MEM_ALLOC_TABLE_SIZE MEM_MAX_SIZE/MEM_BLOCK_SIZE //内存表大小

   2、这个内存管理的数据都是在堆中吗?还是在什么地方?

 

四、文件系统中DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void *buff )接口:

1、在文件系统中,GET_SECTOR_SIZE、GET_BLOCK_SIZE、GET_SECTOR_COUNT这三者我在网上看见几种不同的答案,看完了不知道我理解的对不对,第一个代表扇区大小,如果SD卡的话,那么就把buff装512返回就行了码?第二个代表簇大小,也就比如现在一个簇中有4个扇区,那么把buff返回4吗?第三个是SD卡总容量,也就比如现在1G的SD卡,那么buff返回1024 *1024吗?

 

五、exfuns工程中,为什么需要申请这几个内存?我看有个例子没有加这个也可以用。

u8 exfuns_init(void)

{

fs[0]=(FATFS*)mymalloc(sizeof(FATFS)); //为磁盘0工作区申请内存

fs[1]=(FATFS*)mymalloc(sizeof(FATFS)); //为磁盘1工作区申请内存

file=(FIL*)mymalloc(sizeof(FIL)); //file申请内存

ftemp=(FIL*)mymalloc(sizeof(FIL)); //ftemp申请内存

fatbuf=(u8*)mymalloc(512); //fatbuf申请内存

if(fs[0]&&fs[1]&&file&&ftemp&&fatbuf)return 0;  //申请有一个失败,即失败.

else return 1;

}








最佳答案

查看完整内容[请看2#楼]

2.flash模拟EPPROM既不是为了掉电保护(那是BKP寄存器干的事),也不是为了申请堆(堆是建立在RAM里面的),它实际目的是为了存储用户修改的数据,我现在在处理网络部分,就用到了,例如用户修改了IP地址,而这个需要芯片重启后才能配置,一般来说重启的话RAM数据丢失了,实际IP并没有修改,这就需要吧这个数据写入FLASH中,当重启后读取FLASH覆盖原始地址,就完成了数据修改,flash是为了保存数据,掉电不消失的,但与掉电保护无关 ...
Hard work!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-6-12 10:24:15 | 显示全部楼层
2.flash模拟EPPROM既不是为了掉电保护(那是BKP寄存器干的事),也不是为了申请堆(堆是建立在RAM里面的),它实际目的是为了存储用户修改的数据,我现在在处理网络部分,就用到了,例如用户修改了IP地址,而这个需要芯片重启后才能配置,一般来说重启的话RAM数据丢失了,实际IP并没有修改,这就需要吧这个数据写入FLASH中,当重启后读取FLASH覆盖原始地址,就完成了数据修改,flash是为了保存数据,掉电不消失的,但与掉电保护无关。
3.malloc理论上也是可以的,但是C库函数在碎片化方面处理的并不好,这对于嵌入式很小的RAM是问题很大的,而且系统分配地址在溢出时因为地址不可控,可能会操作非法地址,而使整个系统崩坏,而自己设计的是在块中的,即使溢出问题也不会太严重。当然如果习惯好,区别到是不大
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-6-12 10:24:15 | 显示全部楼层

1.不是在堆中,是在静态储存区
全局变量和静态变量 静态存储区
动态变量 栈
局部变量 堆
设计mymalloc,其实就是在静态存储区中模拟动态变量在栈中申请内存的过程,所以肯定是固定的
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-6-12 10:24:15 | 显示全部楼层
四:
文件系统我没用过,这个需要用过的人来讲
五:
你这是指针没学好啊,指针在申请时如果不是指定已经存在的代码块,就要进行分配内存,这是为了防止内存越界和内存溢出错误
当然不分配也能用,但成不成功就是概率性事件了。
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-6-12 10:32:49 | 显示全部楼层
1,keil可以设置代码区


你可以吧IROM1设置小些,但一定要大于你实际代码容量,如上图,那么(0x8020000~0x800000+实际rom大小)区域后面就是非代码区
回复

使用道具 举报

38

主题

165

帖子

0

精华

高级会员

Rank: 4

积分
646
金钱
646
注册时间
2014-3-5
在线时间
67 小时
 楼主| 发表于 2015-6-12 11:50:45 | 显示全部楼层
回复【3楼】zc123:
---------------------------------
自己写的malloc申请的内存都来自FLASH吧?
Hard work!
回复

使用道具 举报

38

主题

165

帖子

0

精华

高级会员

Rank: 4

积分
646
金钱
646
注册时间
2014-3-5
在线时间
67 小时
 楼主| 发表于 2015-6-12 12:00:58 | 显示全部楼层
回复【5楼】zc123:
---------------------------------
五: 
你这是指针没学好啊,指针在申请时如果不是指定已经存在的代码块,就要进行分配内存,这是为了防止内存越界和内存溢出错误 
当然不分配也能用,但成不成功就是概率性事件了。

目的是要保证下一地址必须为空吗?如果不为空可能指针越界是吧?
Hard work!
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-6-12 12:39:47 | 显示全部楼层
回复【6楼】杂牌电子:
---------------------------------
1.malloc内存肯定来自于RAM啊,所有在代码中处理的变量除非是const或者define的,其它都是在ram中处理的。
2.是为了保证一定有内存可用,
  如char *p = "hello";
     就是在p地址开始把6位都分配存储hello\0,如果你提前不申请,谁也不能保证p和他后面的5位地址是否被其它数据占用,如果实际被占用了就发生错误了。不是为保证下一地址地址为空,而且为了保证这块地址没有被其他数据占用
回复

使用道具 举报

38

主题

165

帖子

0

精华

高级会员

Rank: 4

积分
646
金钱
646
注册时间
2014-3-5
在线时间
67 小时
 楼主| 发表于 2015-6-12 13:40:44 | 显示全部楼层
回复【8楼】zc123:
---------------------------------
2.是为了保证一定有内存可用, 
  如char *p = "hello"; 
     就是在p地址开始把6位都分配存储hello\0,如果你提前不申请,谁也不能保证p和他后面的5位地址是否被其它数据占用,如果实际被占用了就发生错误了。不是为保证下一地址地址为空,而且为了保证这块地址没有被其他数据占用

那么很多时候的指针是未知长度的,肯定是无法使用malloc吧?

顺便想问问,堆和栈都是存在RAM中,为什么还要把堆和栈区分开来呢? 

以前没了解过堆栈,所以问的问题比较傻!  希望能得到回答,谢谢!
Hard work!
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-6-12 14:01:04 | 显示全部楼层
1.我上面说了啊,用指针申请内存块时才需要,而指向已存在内存不需要
    char *p;
    char  a = 1;
    p = &a;
    像这样就不需要
    对于未知长度且需要申请内存的指针,我们一般都是往大了申请
    例如 char *p = (char *)malloc(MAX_SIZE*sizof(char));其实和数组一样,我们用数组存储数,在不知道数目多少的时候也是往大了设置啊
   这句话等同于
   char a[MAX_SIZE];
   char *p;
   p = a;//但这时数据是建立在堆上的
  2.堆的好处是回收是由系统处理的,速度快,不会出错,如子函数申请中的变量,调用结束内存就释放了。像局部变量数组。
     栈的好处在如上面的处理中其实和堆没有区别,只是申请和处理都是由用户决定的,最大区别主要涉及指针的高级用法,链表和树,堆上面申请的内存都要连续的,而栈中申请的话,只要内存满足最小数据块要求,就可以申请,且数据处理,删除,增加(打断链表,重新链接就行了)都很方便。而堆中的数组如果中间增加一个数,要涉及大量的复制,这就是栈的优势
回复

使用道具 举报

38

主题

165

帖子

0

精华

高级会员

Rank: 4

积分
646
金钱
646
注册时间
2014-3-5
在线时间
67 小时
 楼主| 发表于 2015-6-12 14:57:49 | 显示全部楼层
回复【10楼】zc123:
---------------------------------

zc123  太感谢你了,终于明白了!
Hard work!
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-6-12 14:58:46 | 显示全部楼层
回复【11楼】杂牌电子:
---------------------------------
客气,互相交流,语言就是这样,明白就超级简单,不明白就满头雾水
回复

使用道具 举报

38

主题

165

帖子

0

精华

高级会员

Rank: 4

积分
646
金钱
646
注册时间
2014-3-5
在线时间
67 小时
 楼主| 发表于 2015-6-12 15:02:32 | 显示全部楼层
回复【12楼】zc123:
---------------------------------
分享点经验:昨天理解完malloc,今天实验FATFS遇到的问题,完美解决!
[mw_shl_code=c,true]FATFS *fs[1]; //逻辑磁盘工作区. //在调用这个时,程序跑到void MemManage_Handler(void)中 f_mount(fs[0],"0:",1); //挂载SD卡 [/mw_shl_code]
Hard work!
回复

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2015-6-12 15:34:58 | 显示全部楼层
回复【10楼】zc123:
---------------------------------
厉害,对C理解之深入望尘莫及,赞一个
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复

使用道具 举报

6

主题

56

帖子

0

精华

高级会员

Rank: 4

积分
835
金钱
835
注册时间
2015-6-11
在线时间
119 小时
发表于 2015-8-13 10:35:15 | 显示全部楼层
受教了
回复

使用道具 举报

86

主题

983

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1848
金钱
1848
注册时间
2013-4-15
在线时间
163 小时
发表于 2015-8-24 15:30:28 | 显示全部楼层
回复【10楼】zc123:
---------------------------------
全局变量,静态变量,以及内存管理所用的内存,都是属于"堆"区
合肥-文盲
回复

使用道具 举报

86

主题

983

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1848
金钱
1848
注册时间
2013-4-15
在线时间
163 小时
发表于 2015-8-26 10:32:02 | 显示全部楼层
回复【4楼】zc123:
---------------------------------
原子说:函数的局部变量,都是存放在"栈"里面,不是在堆里面的
合肥-文盲
回复

使用道具 举报

86

主题

983

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1848
金钱
1848
注册时间
2013-4-15
在线时间
163 小时
发表于 2015-8-26 10:32:47 | 显示全部楼层
回复【4楼】zc123:
---------------------------------
怪不得上次我看你说局部变量存在堆里面,感觉很奇怪
合肥-文盲
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-8-26 16:09:21 | 显示全部楼层
回复【18楼】合肥-文盲:
---------------------------------
我去查了下,我搞反了,
局部变量所在内存为 栈区
malloc申请的内存为 堆区
汗!
回复

使用道具 举报

86

主题

983

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1848
金钱
1848
注册时间
2013-4-15
在线时间
163 小时
发表于 2015-8-26 17:00:29 | 显示全部楼层
回复【19楼】zc123:
---------------------------------
我查了下,发现SRAM好像是分4个区,堆+栈+全局变量区(静态区)+字符串常量区

局部变量和函数参数存在栈区,由系统(编译器)来管理。优点是速度快;缺点是不受控制。而且一般编译器默认的很小,STM32大容量的好像是2K字节,当然也可以自己改栈顶地址。

malloc管理的就是堆区。优点是可以自己管理,使用很自由。缺点可能是速度相对慢点。

全局变量和静态变量都存在全局变量区,这个区又分为两部分,初始化的区和未初始化的区。关于这个区有一点疑惑,这个区是不是在地址<0x2000 0000的里面开辟的,不是太确定。

像一些字符串,存储在字符串常量区,但是这个区,是在什么地址段,我也不太清楚。这两点疑惑吧,不知道可有人知道?
合肥-文盲
回复

使用道具 举报

86

主题

983

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1848
金钱
1848
注册时间
2013-4-15
在线时间
163 小时
发表于 2015-8-26 17:01:45 | 显示全部楼层
回复【19楼】zc123:
---------------------------------
堆肯定是向上生长,栈一般是向下增长
合肥-文盲
回复

使用道具 举报

86

主题

983

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1848
金钱
1848
注册时间
2013-4-15
在线时间
163 小时
发表于 2015-8-26 17:21:44 | 显示全部楼层
全局变量在什么地址段?多大的空间?还可以再配置吗?
宏定义的应该也算常量,这个存在什么地址段?难道是flash里面?用的时候再根据变量类型分配吗
合肥-文盲
回复

使用道具 举报

0

主题

12

帖子

0

精华

新手上路

积分
42
金钱
42
注册时间
2015-2-27
在线时间
2 小时
发表于 2015-9-11 10:45:29 | 显示全部楼层
太感谢了, 涨知识了
回复

使用道具 举报

38

主题

165

帖子

0

精华

高级会员

Rank: 4

积分
646
金钱
646
注册时间
2014-3-5
在线时间
67 小时
 楼主| 发表于 2015-9-11 16:15:39 | 显示全部楼层
回复【12楼】zc123:
---------------------------------
遇到个问题,想在请教一下,怎么处理好malloc的碎片问题?只有运行一段时间重启吗?
Hard work!
回复

使用道具 举报

3

主题

401

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1769
金钱
1769
注册时间
2015-6-11
在线时间
313 小时
发表于 2015-9-14 11:26:02 | 显示全部楼层
回复【24楼】杂牌电子:
---------------------------------
malloc问题目前我主要的解决办法是
1.除非必用指针,尽量用数组代替,然后用指向数组的指针处理数据,而不是用动态内存
2.malloc不要嵌套,就是按照malloc-free-malloc-free这种方式,避免malloc-malloc-free-free这种方式
3.用内存池模拟malloc动态分配过程(这个原子例程有),这个是一劳永逸,但是程序要在静态存储区划出一片内存池区
stm32的内存都是按照kb算的,不能像计算机上面挥霍,碎片问题造成的后果也更加严重,所以不推荐使用动态内存
回复

使用道具 举报

38

主题

165

帖子

0

精华

高级会员

Rank: 4

积分
646
金钱
646
注册时间
2014-3-5
在线时间
67 小时
 楼主| 发表于 2015-9-15 11:22:25 | 显示全部楼层
回复【25楼】zc123:
---------------------------------
太感谢了!
Hard work!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-17 16:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表