OpenEdv-开源电子网

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

请问如何初始化flash?

[复制链接]

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
发表于 2018-9-4 12:05:14 | 显示全部楼层 |阅读模式
1金钱
各位大神好!我在程序中定义一个变量x=1,在没有设置之前,x的值就是1. 然后我想给X设置了一个另外的值,比如是2,我把这个值写入到flash中,以便下次x初始化可以直接调用。然后我的初始化程序就不晓得怎么写了,我之前的操作是直接读取flash中的值赋值给x,因为flash中的初始值一般都为0,(在AVR中我也有遇到是256的),所以需要上电后自行设置一次,很麻烦。不知道SEGGER可不可以直接写?如果可以在keil上直接写就更方便了。或者有更简洁的方法,感谢各位不吝赐教!

最佳答案

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

u8* ptr = test; 这要做转换 u8* ptr = (u8*)test; *test==(U16)*ptr
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-4 12:05:15 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-7 18:54 编辑

u8* ptr = test;  这要做转换 u8* ptr = (u8*)test;

*test==(U16)*ptr<<8|*(ptr+1) , 不对, ARM默认是小端(即低字节在前)应该是 *test==(U16)*(ptr+1)<<8  | *ptr;

*(test+1)的值应该是0x0002, 因为test是u16数组的指针(不容许被修改的指针), test+1, 就不是加一个字节, 而是加两个字节
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-4 12:28:00 | 显示全部楼层
本帖最后由 edmund1234 于 2018-9-4 12:29 编辑

用const u32 x_defaultvale = 123;
类型是否u32 自己改


初始时
x=x_defaultvalue;

回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-4 15:26:19 | 显示全部楼层
edmund1234 发表于 2018-9-4 12:28
用const u32 x_defaultvale = 123;
类型是否u32 自己改

你好,初始值x=x_defaultvalue; 请问如果我要读取flash的值怎么办呢?我不是太明白,请教

x_Init()
{
      const u32 x_defaultvale = 123;
      x=x_defaultvalue;
      x=readflashvalue(flashaddr);   //最后还是读的是flash里边的值呀。
}
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-4 16:21:46 | 显示全部楼层
fight281 发表于 2018-9-4 15:26
你好,初始值x=x_defaultvalue; 请问如果我要读取flash的值怎么办呢?我不是太明白,请教

x_Init()

const u32 x_defaultvale = 123, 这一句要放函数外, 放函数外就是个全局的常数,编译器就自动的帮你写到Flash去, 这应该就是你要的初始化Flash吧

x = x_defaultvale ;  这一句就是从Flash读出来, 给x赋值啊
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-4 16:22:43 | 显示全部楼层
要放在外面

const u32 x_defaultvale = 123;

x_Init()
{      
      x=x_defaultvalue;
      x=readflashvalue(flashaddr);   //最后还是读的是flash里边的值呀。
}
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-5 22:09:13 | 显示全部楼层
edmund1234 发表于 2018-9-4 16:21
const u32 x_defaultvale = 123, 这一句要放函数外, 放函数外就是个全局的常数,编译器就自动的帮你写 ...

你好,我明白你的意思了,非常感谢!  
但我是想第一次开机就用初始默认值,第二次开机从flash里边读,这个怎么做?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-5 22:21:40 | 显示全部楼层
也可以啊, 那就把const u32 x_defaultvale的内容在第一次开机后改写
怎么写Flash可以看ST的库例程, 就调用几个函数而已, 不复杂
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-6 09:39:10 | 显示全部楼层
edmund1234 发表于 2018-9-5 22:21
也可以啊, 那就把const u32 x_defaultvale的内容在第一次开机后改写
怎么写Flash可以看ST的库例程, 就调 ...

呃 我知道 我的意思是 我的程序中 初始化肯定是要从flash中读取数据的,所以这个const u32 x_defaultvale对我来说没有意义。而第一次上电的时候 我的flash里边没有数据,所以在flash没写入数据的这个第一次上电,设置x为默认值,而不是从flash中读取。
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-6 12:12:42 | 显示全部楼层
fight281 发表于 2018-9-6 09:39
呃 我知道 我的意思是 我的程序中 初始化肯定是要从flash中读取数据的,所以这个const u32 x_defaultvale ...

要在Flash里存放数据, 而保证第一次上电后确认数据是之前自己的程式所存入的, 通常的方法是在Flash里多放一标识, 比如  Flash_Mask = 0xaa55aa55。
每次复位后先判断这Flash_Mask是否==0xaa55aa55, 判断Flash里的数据是否需要初始化
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-6 16:44:10 | 显示全部楼层
edmund1234 发表于 2018-9-6 12:12
要在Flash里存放数据, 而保证第一次上电后确认数据是之前自己的程式所存入的, 通常的方法是在Flash里多 ...

明白了,flash里边的值都是0吗?
另外我还有一个问题,也希望你能帮我解答一下,比如我定义一个数组  u8 test[10]={}; 我想请问这里的u8是指test的指针大小还是指test的数组值大小?
如果上述的数组 我定义为u16 test[10]={}; ,那么*test和*(u8*)test的大小是不是有可能不一样?
按照我的理解,如果我定义了u8  那么编译器会把这个地址分配到8位的地址以内(假设总地址数是32位的,分配到0x00000000----0x000000ff);如果我定义了u16  那么编译器会把这个地址分配到16位的地址以内(分配到0x00000100----0x0000ffff);
以上仅是我的猜想,不知道去哪里可以看到关于这方面的东西。所以我再想如果u8定义的很多个的话,不会造成地址混乱啊?
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-6 17:15:21 | 显示全部楼层
fight281 发表于 2018-9-6 16:44
明白了,flash里边的值都是0吗?
另外我还有一个问题,也希望你能帮我解答一下,比如我定义一个数组  u8 ...

Flash的值出厂时理论上是FF吧, 但这不重要, 就是随机的, 标识会被随机碰到的机会是2^-32, 这应该足够了吧

u8是指指针指着的变量是u8, 在stm32里指针一定是32位的
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-6 17:25:50 | 显示全部楼层
u16 test[10]={}; ,
*test 是个16位数
*(u8*)test是个8位数

在stm32中,关于指针的地址分配, 与它是u8*还是u16*无关, 你认为编译器会把u8*放zero page的想法应该是一些8位机的经验
u8*与u16*是可以互换的, 前题是对齐

比如u16 test[10]={1,2,3,4};
u8* ptr = test; 即你可以把test 里的每个u16的数拆开为两个字节, 一个字节一个字节读或写的
u16指针转u8指针没有对齐的问题
但反过来u8指针转u16的指针就要对齐
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-9-7 01:52:00 | 显示全部楼层
学习我们的  flash模拟eeprom例程
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-7 18:36:51 | 显示全部楼层
edmund1234 发表于 2018-9-6 17:25
u16 test[10]={}; ,
*test 是个16位数
*(u8*)test是个8位数

非常感谢您的指点,我汇总一下我的错误和新的理解:
       1.u16的指针就是这个指针指向的是u16类型的数据,而不是这个指针是16位的。指针的位数应该是和内存大小一致的。
       2.*(u8*)test是指将U16指针转换为u8指针,然后对所在指针的位置取值。
       3. 以u16 test[10]={1,2,3,4};
           u8* ptr = test; 为例,
           *test==(U16)*ptr<<8|*(ptr+1);
        4.疑问:
           *(test+1)的值是0x0100吗?意思就是test和ptr的指针都是一样的,指向的都是同一个地址,但是test是一次读一个u16上来,ptr一次读一个u8上来,区别就是这里吧?
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-7 18:39:58 | 显示全部楼层
正点原子 发表于 2018-9-7 01:52
学习我们的  flash模拟eeprom例程

嗯,就是学习了之后才想到这些问题的。原子哥的教程还是比较详细的。
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-7 23:05:19 | 显示全部楼层
edmund1234 发表于 2018-9-7 18:51
u8* ptr = test;  这要做转换 u8* ptr = (u8*)test;

*test==(U16)*ptr

感谢您的回答,我本来以为有些明朗了,您这么说我又有点迷糊了。
1.u8* ptr = (u8*)test;必须要做转换吗? 按我的理解ptr和test指向的都是同一个地址才对,如果我不加 (u8*),这个ptr的取值会取2个字节吗?
2.这个我刚才试了,确实是小端,谢谢指教。
3. test+1, 就不是加一个字节, 而是加两个字节,这个是为什么呢?按下图的理解,ptr和test都应该和地址0的值一样才是。+1的话不都是应该+到地址1上才对吗?
QQ图片20180907224445.png
那么再请教一下  &test[1]=&test[0]+1吗?还是+2呢?

又或者地址的分配是这样的?这样的话 ptr+2和test+1作为同一个地址又不对了呀?所以关于u16*和u8*我又搞迷糊了
图形1.png


回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-7 23:52:49 | 显示全部楼层
edmund1234 发表于 2018-9-7 18:51
u8* ptr = test;  这要做转换 u8* ptr = (u8*)test;

*test==(U16)*ptr

刚刚试了一下:
1.u8* ptr = test;编译器不通过,必须u8* ptr = (u8*)test; 看来不能像u8 i=0x0022一样截取低8位。
2.搞明白了:指针P+1 = 指针P + sizeof(指针的类型) *  1     指针不仅仅是单纯的内存地址。
   十分感谢您!
3.另外关于C标准库中的sscanf函数,举个例子:
    char str[]="192.168.0.1";
    u8 str_to_u8[4];
    sscanf("%d.%d.%d.%d",str_to_u8,str_to_u8+1,str_to_u8+2,str_to_u8+3);
    这个是可以得到正确的值的。
    但是下面这个第一个值没有正确得到,请教下:
    char strtemp[100]="AT+CIFSR\r\n+CIFSR:\"192.168.1.102\"\r\n+CIFSR:\"12:34:56:78:90:de\"\r\n";
              u8 Sever_IP[4]={0};
         u8 mac[6]={0};
     sscanf(strtemp,"%*[^\"]\"%d.%d.%d.%d\"%*[^\"]\"%02x:%02x:%02x:%02x:%02x:%02x\"",&Sever_IP[0],&Sever_IP[1],&Sever_IP[2],&Sever_IP[3],&mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]);
     printf("severIP is:%d.%d.%d.%d\r\nmac is %02x:%02x:%02x:%02x:%02x:%02x",Sever_IP[0],Sever_IP[1],Sever_IP[2],Sever_IP[3],mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);

     运行的结果却是:
severIP is:0.168.1.102
mac is 12:34:56:78:90:de

少了个192,我认为可能是后面把前面的覆盖了,但不确定也不知道哪里出了问题,请指教!!
回复

使用道具 举报

3

主题

1907

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4106
金钱
4106
注册时间
2018-8-14
在线时间
696 小时
发表于 2018-9-8 01:20:30 | 显示全部楼层
fight281 发表于 2018-9-7 23:52
刚刚试了一下:
1.u8* ptr = test;编译器不通过,必须u8* ptr = (u8*)test; 看来不能像u8 i=0x0022一样 ...

这个我也没看出什么问题
我几乎没用过库里的函数, 这个帮不上忙了
回复

使用道具 举报

9

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2018-3-28
在线时间
30 小时
 楼主| 发表于 2018-9-9 22:32:43 | 显示全部楼层
edmund1234 发表于 2018-9-8 01:20
这个我也没看出什么问题
我几乎没用过库里的函数, 这个帮不上忙了

好的 谢谢!
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-20 06:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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