stm32f407芯片手册 是芯片的BUG吗

STM32调试过程中,读保护,写保护造成的无法擦写芯片问题的解决办法和相关讨论 - STM...
我的图书馆
STM32调试过程中,读保护,写保护造成的无法擦写芯片问题的解决办法和相关讨论 - STM...
23:09 | | |
调试Flash读保护时,Jlink不能下载程序
22:54 | 作者: linew | 来源: StmFans思蜕盟 OPELC 自由电子联盟
调试flash读保护时,点了jlink中Unsecure chip 后 能连接、能擦出芯片,但不能下载程序和读芯片,请问怎样解决···binglin ( 22:59:47)J-Flase ARM里下载程序,芯片型号不对是写不进程序的。检查芯片型号是否配置正确菜单:Options-&CPU页。截图15.jpg在配置CPU时,一定要在Device这项里配置CPU型号,不能在Core这项里配置。linew ( 23:46:31)CPU型号已选对,具体情况是我下载了一个读保护的程序,接着点了jlink-》target-》Unsecure chip ,接着点了擦除芯片,之后就不能读出芯片和烧程序了,但依然可以connect 和 erase chip ; 点 Read back 和 program 时 出现弹出错误提示 PC=··· ,R0=···· R1=···(明天附上图片)linew ( 09:10:56)Jlink出错未命名.JPGlinew ( 09:11:44)- Connecting ...& & - Connected successfully- 128 sectors, 1 range, 0x8000000 - 0x803FFFF- RAM tested O.K.- ERROR: PC of target system has unexpected value after blank checking. (PC = 0xFFFFFFFE)!---------------------------------------------------------------------- Registers -------------------------------------------------------------------------------------& && && && &PC& &= FFFFFFFECurrent:& && &&&R0& &= ,& && &&&R1& &= ,& && &&&R2& &= ,& && &&&R3& &= & && && && &R4& &= ,& && &&&R5& &= 0000B7FC,& && &&&R6& &= 000000FF,& && &&&R7& &= ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ERROR: Failed to read back target memoryDisconnecting ...- Disconnectedlinew ( 13:30:54)binglin在吗binglin ( 14:06:46)你这种现象我上个月也遇到过,当时也是用V4.08l的驱动。你换更换J-LINK的驱动程序,不要用V4.08l版。linew ( 14:16:32)一开始用4.08, 之后我用4.11也是出现同样情况binglin ( 17:12:17)试试用4.04a版本的,这个版本坛子上的下载,你找一下。linew ( 11:24:42)应该不行,我用ISP 读芯片,提示芯片已加密,无法读取信息;还有用ST 的Flash loader demo 串口提示芯片加了读保护,当点解除读保护,提示命令无效binglin ( 11:33:31)配置读保护是可以清除的,我在写入到应用板时都配置的读保护,很多时候修改了程序后要更新程序(要解除读保护更新程序),经无数次实操圾明是没有问题的。ISP也经常用,它在仿真器不能正常仿真目标板时,当用仿真器也无法解锁芯片时,,ISP是最后的也就是最可靠的解锁工具。linew ( 13:03:58)问题已解决,可能是在jlink那里点了Unsecure chip,所以用ISP无法解锁了;在RAM中运行int main(void){ &&RCC_DeInit(); &&FLASH_Unlock();&&FLASH_ReadOutProtection(DISABLE); }问题解决了。参考链接:/bbs/viewth ... B%E4%B8%93%E8%B4%B4linew ( 13:07:11)请问binglin stm32最有效的加密或保护方法是哪种,读保护算不算呢ID加密 或加密算法怎样binglin ( 14:12:33)
问题已解决,可能是在jlink那里点了Unsecure chip,所以用ISP无法解锁了;在RAM中运行int main(void){ &&RCC_DeInit(); &&FLASH_Unlock();&&FLASH_ReadOutProtection(DISABLE); }问题解决了。参考链接:htt ...linew 发表于
在JLINK里捃行了Unsecure chip,ISP同样可以解开的,其实&&“FLASH_Unlock(); FLASH_ReadOutProtection(DISABLE); ”其实与ISP里面的解锁代码是一样的。binglin ( 14:15:28)
请问binglin stm32最有效的加密或保护方法是哪种,读保护算不算呢ID加密 或加密算法怎样linew 发表于
读保护算就是加密了。wqb202 ( 00:39:46)有个问题想请教一下binglin ,如果用secure chip加密,断电重上电后,还可以重新用Jlink重新连接芯片吗?如果能那么是直接下载程序会清除读保护吗?还是在先UNsecure chip才能再下载!现在手上没有开发板,只有在调试项目的板子,没有引出COM口ISP,所以不敢试呀!binglin ( 13:37:53)用secure chip加密,断电重上电后,Jlink当然可以重新连接芯片,如果不能又怎么还能够执行Unsecure chip呢?secure chip加密后,断电或不断电重启都是肯定可以重新连接的。如果在secure chip加密要再次下载,则先连接芯片然后执行UNsecure chip才能再下载,我一般是执行UNsecure chip后直接按F7(自动模式)将程序写进去。注:执行UNsecure chip,JLINK与目标板会自动断开,直接按F7(自动模式)执行时,JLINK会自动联接、擦除芯片、写入及校验以及执行secure chip,这些操作是否全部执行由你的配置决定。
STM32对内部Flash的内容有专门的保护措施转自:21ic& &作者:香水城所有STM32的芯片都提供对Flash的保护,防止对Flash的非法访问——写保护和读保护。读保护是作用于整个Flash存储区,一旦设置了Flash的读保护,内置的Flash存储区只能通过程序的正常执行才能读出,而不能通过下述任何一种方式读出:  通过调试器(JTAG或SWD)  从RAM中启动并执行的程序写保护是以四页(1KB/页)Flash存储区为单位提供保护,对被保护的页实施编程或擦除操作将不被执行,同时产生操作错误标志。以下是一个简单的小结:读保护  写保护  对Flash的操作功能有效   有效   CPU只能读;禁止调试和非法访问有效   无效   CPU可以读写;禁止调试和非法访问;页0~3为写保护无效   有效   CPU可读;允许调试和非法访问无效   无效   CPU可以读写;允许调试和非法访问
下面的则是我的经历:我昨天晚上突然就发现芯片被读保护了,我没有设对应的选项啊,不知怎么回事.今天搞定之后发现还是时不时的会自己变成读保护,郁闷中.我板子的症状:1. 无法有Keil上的jlink方式下载,无法擦除.2. 使用官方的flash loader demo:第一步连接之后,出现红字,提示:the target is read protected. Please click "remove protection" to remove the protectiion. WARNING:when you click "Remove protection" the flash will be mass erased and all data will be lost.然后是remove protection按钮.点击这个按钮:This command is not supported by the target.解决办法:(我是看了多篇文章才知道原来Jlink arm有一个unsecure chip的命令的.)1. 在一个类似于D:\Program Files\SEGGER\JLinkARM_V404a的目录下找到JFlashARM.exe.点击它.2. options-&project settings-&production 勾选secure chip.这一项的作用是让你的另一个菜单项可以使用secure chip 和unsecure chip命令.如图:3. Target-&connect.这里要先连接板子才可以进行unsecure chip 操作.连接的时候我一开始连接不上,很郁闷.但是不小心把启动方的跳线冒弄掉了,却发现可以了.也就是说,我是在从片bootloader的启动方式下(即使用串口的那种方式)连接上的.连接上之后.targer-&unsecure chip.提示成功.4.正常用Keil里的下载方式就可以下载了.问题:1.我现可以下载了,但是用串口方式依然提示读保护状态.而且无法去掉,即串口方式没有改变.2.我用串口启动方式连接的jlink,这种方式可以连接jlink可以对芯片进行操作吗?以前记得是不能的.以前都是接上跳线冒才下载程序的.而我确定的确是可以用了,因为我现在安上跳线冒下载程序也能过了.如果谁能回答我的问题,欢迎讨论一下.
TA的最新馆藏[转]&[转]&[转]&[转]&[转]&[转]&
喜欢该文的人也喜欢是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误 - 其他 - 意法半导体STM32/STM8技术社区
后使用快捷导航没有帐号?
查看: 5301|回复: 16
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
在线时间6 小时
主题帖子好友
初级会员, 积分 80, 距离下一级还需 120 积分
初级会员, 积分 80, 距离下一级还需 120 积分
在使用STM32F407的DMA向外设SPI2发送数据时
使能DMA的半传输 与 传输完成中断
但是当DMA进入中断处理函数后
TCIF HTIF 都被置位
中断进入后发现SXNDTI内的值位8(DMA需要发送的数据个数为16) 在中断中关闭DMA 在半传输的 判断语句中再将DMA打开
结果 中断退出后 很短时间内DMA的FEIF
TCIF HTIF 会再次被置位
//配置SPI2 DMA传输
//配置SPI2 DMA传输
void DMA_SPI_Configuration(void)
& & & & & & & & & & & & DMA_InitTypeDef
& & & & & & & & & & & & SPI_InitTypeDef
& & & & & & & & & & & & GPIO_InitTypeDef GPIO_InitS
& & & & & & & & & & & & NVIC_InitTypeDef NVIC_InitS
& & & &&& RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_DMA1,ENABLE); //使能GPIOA的AHB1时钟RCC_APB2Periph_AFIO|
& & & &&& RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
& & & &&&GPIO_PinAFConfig(GPIO_PORT_KKPJ_SPIX,GPIO_PinSource13, GPIO_AF_SPI2);
GPIO_PinAFConfig( GPIO_PORT_KKPJ_SPIX ,GPIO_PinSource14, GPIO_AF_SPI2);
GPIO_PinAFConfig( GPIO_PORT_KKPJ_SPIX ,GPIO_PinSource15, GPIO_AF_SPI2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd
= GPIO_PuPd_DOWN;
GPIO_Init(GPIO_PORT_XJ128_SPIX, &GPIO_InitStructure);
& & & & & & & & GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
& & & & & & & & GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
& & & & & & & & GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
& & & & & & & & GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
& & & & & & & & GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
& & & & & & & & GPIO_Init(GPIOB, &GPIO_InitStructure);
//设置SPI1 SPI2
& & & & & & & & & & & & & & & & & & & &&&SPI_I2S_DeInit(SPI2);
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullD//;SPI_Direction_1Line_Tx // SPI设置为双线双向全双工 ;
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_Mode = SPI_Mode_M // 设置为主SPI ;
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI发送接收8位帧结构 ;
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_CPOL = SPI_CPOL_H& & & & // Low时钟悬空低 ;
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_CPHA = SPI_CPHA_2E // 数据捕获于第二个时钟沿 ;
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_NSS = SPI_NSS_S
// 内部NSS信号有SSI位控制 ;
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; // 波特率预分频值为4 ;
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
// 数据传输从MSB位开始 ;
& & & & & & & & & & & &&& & & & & SPI_InitStructure.SPI_CRCPolynomial = 7;
// 定义了用于CRC值计算的多项式 7。
& & & & & & & & & & & &&& & & & & SPI_Init(SPI2, &SPI_InitStructure); // 初始化外设SPI1寄存器 ;
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
//DMA通道4 RM0090手册-&gt165
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI2-&DR));
//外设地址
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_Memory0BaseAddr = (u32)SPI1_Buffer_Tx;
//内存地址
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToP
//传输方向
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_BufferSize = 0;
//设置DMA传输时缓冲区大小
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_D
//设置DAM外设地址递增模式,因为目前就一个外设,故此处设置为禁止
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_E
//内存地址递增
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_B
//8位数据位宽度
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_B
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_Mode = DMA_Mode_N
//DMA_Mode_C
//这里必须设置为这个模式
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_Priority = DMA_Priority_H
//DMA_Priority_VeryH
//DMA_Priority_H
//设置优先级
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_D
//DMA_FIFOMode_D
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_F
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_S
& & & & & & & & & & & & & & & & & & & & DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_S
& & & & & & & & & & & & & & & & & & & & DMA_Init(DMA1_Stream4, &DMA_InitStructure);
& & & & & & & & & & & & & & & & & & & &
& & & & & & & & & & & &&&//Enable DMA2 Channel3 Tx Interrupt
& & & & & & & & & & & & & & & & NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;
& & & & & & & & & & & & & & & & NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//抢占优先级设置,值越大,表示优先级越低
& & & & & & & & & & & & & & & & NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//响应优先级设置,值越大,表示优先级越低
& & & & & & & & & & & & & & & & NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
& & & & & & & & & & & & & & & & NVIC_Init(&NVIC_InitStructure);
DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_HTIF4);& & & & //清除数据传输一半中断标志DMA_FLAG_HTIF3
& & & & & & & & & & & & & & & & DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_TCIF4);//清除数据传输完成中断标志& & & &
& & & & & & & & & & & & & & & & DMA_ITConfig(DMA1_Stream4,DMA_IT_TC | DMA_IT_HT,ENABLE);
& & & & & & & &&&& & & & & & & &&&//使能 SPI2 DMA传输
& & & & & & & & & & & & & & & & SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
DMA1_Stream4_IRQHandler(void)
{& & & &&& u16 ty=3;& & & &&&& & & &
DMA1_Stream4 -&CR &= 0xFFFFFFFE; //除能DMA1_Stream3
while( DMA1_Stream4 -&CR & 0x);//确保DMA可以被设置& & & &&&& & & &
//等待 SPI 数据寄存器空& & & &&&
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
& & & &&&SPI_Cmd(SPI2, DISABLE);
& & & & & & & & //若数据传输一半
& & & & & & & & & & & & if(DMA_GetFlagStatus( DMA1_Stream4 ,DMA_FLAG_HTIF4))
& & & & & & & & & & & & & & & &
& & & & & & & & & & & &&&{
& & & & & & & & & & & & & & & & DMA_ClearFlag(KKHG_DMA_Stream,DMA_FLAG_HTIF4);
& & & & & & & & & & & & & & & & SPI_Cmd(SPI2, ENABLE);
& & & & & & & & & & & & & & & &&&DMA1_Stream4 -&CR |= (uint32_t)DMA_SxCR_EN;//打开DMA的数据传输& & & & & & & & & & & & & & & & & & & &
& & & & & & & & & & & &&&}& & & &
& & & & & & & & & & & & if(DMA_GetFlagStatus( DMA1_Stream4 ,DMA_FLAG_TCIF4))
& & & & & & & & //若数据传输完成
数据传输完成后要关闭DMA传输
若想再一次使用DMA传输就必须 重新写入传输数目
& & & & & & & & & & & &&&{& & & & & & & & & & & &
& & & & & & & & & & & & & & & & DMA_ClearFlag( DMA1_Stream4 ,DMA_FLAG_TCIF4);
& & & & & & & & & & & &&&}& & & &
反复搞了几天 实在没辙了
还请 大侠看下
在线时间6 小时
主题帖子好友
初级会员, 积分 80, 距离下一级还需 120 积分
初级会员, 积分 80, 距离下一级还需 120 积分
RE:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
补充下: 若在中断进入时不关闭DMA&&那么数据的发送时正常的
在线时间164 小时
主题帖子好友
金牌会员, 积分 2465, 距离下一级还需 2535 积分
金牌会员, 积分 2465, 距离下一级还需 2535 积分
RE:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
dma传输未完就关闭,再打开dma要重新告诉dma要传送哪个数据。
在线时间6 小时
主题帖子好友
初级会员, 积分 80, 距离下一级还需 120 积分
初级会员, 积分 80, 距离下一级还需 120 积分
回复:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
非常感谢 您的回复
F103 使用半传输中断是不需要重新赋值的 当在半传输中断中再将DMA打开数据会自动继续传输
您的意思是在半传输中断中再次对外设 与 内存地址重新赋值吗? 这样感觉半传输中断就没有意义了
在DMA传输中断中 查询
但是得到的结果是 只有全部数据传输完毕后 读EN位 才会为0
在线时间136 小时
主题帖子好友
金牌会员, 积分 1797, 距离下一级还需 3203 积分
金牌会员, 积分 1797, 距离下一级还需 3203 积分
RE:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
为了解决你这个问题,我上网搜了一下相关的问题,发现出现你这种类似的问题的人还真不少,难道真像你说的是BUG?你现在解决了吗,记得分享一下
在线时间6 小时
主题帖子好友
初级会员, 积分 80, 距离下一级还需 120 积分
初级会员, 积分 80, 距离下一级还需 120 积分
回复:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
不过找到了折中的办法
还没有验证他的准确性
要传输16字节数据
那么只开启传输完成中断
每次传输个数为8
这样在DMA中断中给DMA后8个数据的地址 然后在进行传输
半传输也可以进入
只是不能暂停
找到好的办法再来发布
在线时间164 小时
ST金币1043
主题帖子好友
金牌会员, 积分 3141, 距离下一级还需 1859 积分
金牌会员, 积分 3141, 距离下一级还需 1859 积分
RE:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
能设置中断逐步检查吗
在线时间6 小时
主题帖子好友
初级会员, 积分 80, 距离下一级还需 120 积分
初级会员, 积分 80, 距离下一级还需 120 积分
RE:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
能进入版半中断 但在半中断不能暂停DMA
在半中断中不能关闭DMA&&手册中说 只有DMA传输完毕&&写EN 位 才会有效
在线时间8 小时
主题帖子好友
高级会员, 积分 939, 距离下一级还需 61 积分
高级会员, 积分 939, 距离下一级还需 61 积分
RE:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
那你想怎么改, 总要等中断看看的呀
在线时间6 小时
主题帖子好友
初级会员, 积分 80, 距离下一级还需 120 积分
初级会员, 积分 80, 距离下一级还需 120 积分
回复:STM32F407
是芯片的BUG吗?DMA启动后暂停 在打开而出现的数据错误
大家有没有实际验证过
我没有实现
使用示波器 来查看程序的执行情况
(不要使用串口打印的方式 --太占用时间
) 进入半中断后
在保证数据完整传输的情况下 都没有得到正确的结果
若是DMA 不停止 那么没有问题 可以非常流畅的进入中断
好似 407 的DMA 在传输中就不能被打断吧!!!!
看手册说是 只有数据传输完毕 DMA 才会被允许设置 (EN位)
站长推荐 /2
Tel: 3-8064
备案号: 苏ICP备号-2
|||意法半导体STM32/STM8技术社区
Powered bySTM32F407加入SystemInit();后芯片死掉 - STM32 - 意法半导体STM32/STM8技术社区
后使用快捷导航没有帐号?
查看: 209|回复: 2
STM32F407加入SystemInit();后芯片死掉
在线时间4 小时
主题帖子好友
初级会员, 积分 73, 距离下一级还需 127 积分
初级会员, 积分 73, 距离下一级还需 127 积分
小白刚刚从STM32F103转向407,今天遇到一个神奇的·1事情,之前代码都是好好的,可以正常烧进去,在主函数中加入SystemInit();后,屏幕突然不跑了,程序也烧不进去了,用keil也无法用ST-link读到芯片了,代码如下
#include &stm32f4xx.h&
#include &oled.h&
//#include &TIM2.h&
//USE_STDPERIPH_DRIVER
int main()
& & & & u8
& & & & SystemInit();
& & & & OLED_Init();
& & & & OLED_ON();
& & & & OLED_CLS();
& & & & while(1)
& & & & & & & & for(n=0;n&255;n++)
& & & & & & & & & & & & OLED_ShowNumN(0,0,n,1);
一连两块板子都这样,跪求大佬救命。
在线时间4 小时
主题帖子好友
初级会员, 积分 73, 距离下一级还需 127 积分
初级会员, 积分 73, 距离下一级还需 127 积分
现在发现是Flash被读写保护了,求问如何解锁
在线时间238 小时
ST金币1490
主题帖子好友
现在发现是Flash被读写保护了,求问如何解锁
下载个stlink utility软件 使用STLINK将芯片擦除后重写。
代码的问题得你自己解决。
站长推荐 /2
Tel: 3-8064
备案号: 苏ICP备号-2
|||意法半导体STM32/STM8技术社区
Powered by5260人阅读
STM32(22)
STM32F4Discovery开发包使用的STM32F407VGT6芯片,内部FLASH有1M之多。平时写的代码,烧写完之后还有大量的剩余。有效利用这剩余的FLASH能存储不少数据。因此研究了一下STM32F4读写内部FLASH的一些操作。
【STM32F4 内部Flash的一些信息】
STM32F407VG的内部FLASH的地址是:0x,大小是0x。
写FLASH的时候,如果发现写入地址的FLASH没有被擦除,数据将不会写入。FLASH的擦除操作,只能按Sector进行。不能单独擦除一个地址上的数据。因此在写数据之前需要将地址所在Sector的所有数据擦除。
在STM32F4的编程手册上可找到FLASH的Sector划分,我们现在只操作Main memory:
参考Demo中的例子,将FLASH的页的其实地址(基地址)可定义如下:
/* Base address of the Flash sectors */
#define ADDR_FLASH_SECTOR_0&&&& ((uint32_t)0x) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1&&&& ((uint32_t)0x) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2&&&& ((uint32_t)0x) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3&&&& ((uint32_t)0x) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4&&&& ((uint32_t)0x) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5&&&& ((uint32_t)0x) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6&&&& ((uint32_t)0x) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7&&&& ((uint32_t)0x) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8&&&& ((uint32_t)0x) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9&&&& ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10&&& ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11&&& ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
在库里边,FLASH的Sector编号定义如下,这是供库里边的几个函数使用的。需要将地址转换成Sector编号:
#define FLASH_Sector_0&&&& ((uint16_t)0x0000) /*!& Sector Number 0 */
#define FLASH_Sector_1&&&& ((uint16_t)0x0008) /*!& Sector Number 1 */
#define FLASH_Sector_2&&&& ((uint16_t)0x0010) /*!& Sector Number 2 */
#define FLASH_Sector_3&&&& ((uint16_t)0x0018) /*!& Sector Number 3 */
#define FLASH_Sector_4&&&& ((uint16_t)0x0020) /*!& Sector Number 4 */
#define FLASH_Sector_5&&&& ((uint16_t)0x0028) /*!& Sector Number 5 */
#define FLASH_Sector_6&&&& ((uint16_t)0x0030) /*!& Sector Number 6 */
#define FLASH_Sector_7&&&& ((uint16_t)0x0038) /*!& Sector Number 7 */
#define FLASH_Sector_8&&&& ((uint16_t)0x0040) /*!& Sector Number 8 */
#define FLASH_Sector_9&&&& ((uint16_t)0x0048) /*!& Sector Number 9 */
#define FLASH_Sector_10&&& ((uint16_t)0x0050) /*!& Sector Number 10 */
#define FLASH_Sector_11&&& ((uint16_t)0x0058) /*!& Sector Number 11 */
Demo中有将地址转换成Sector的代码:
uint32_t GetSector(uint32_t Address)
& uint32_t sector = 0;
& if((Address & ADDR_FLASH_SECTOR_1) && (Address &= ADDR_FLASH_SECTOR_0))
&&& sector = FLASH_Sector_0;&&
& else if((Address & ADDR_FLASH_SECTOR_2) && (Address &= ADDR_FLASH_SECTOR_1))
&&& sector = FLASH_Sector_1;&&
& else if((Address & ADDR_FLASH_SECTOR_3) && (Address &= ADDR_FLASH_SECTOR_2))
&&& sector = FLASH_Sector_2;&&
& else if((Address & ADDR_FLASH_SECTOR_4) && (Address &= ADDR_FLASH_SECTOR_3))
&&& sector = FLASH_Sector_3;&&
& else if((Address & ADDR_FLASH_SECTOR_5) && (Address &= ADDR_FLASH_SECTOR_4))
&&& sector = FLASH_Sector_4;&&
& else if((Address & ADDR_FLASH_SECTOR_6) && (Address &= ADDR_FLASH_SECTOR_5))
&&& sector = FLASH_Sector_5;&&
& else if((Address & ADDR_FLASH_SECTOR_7) && (Address &= ADDR_FLASH_SECTOR_6))
&&& sector = FLASH_Sector_6;&&
& else if((Address & ADDR_FLASH_SECTOR_8) && (Address &= ADDR_FLASH_SECTOR_7))
&&& sector = FLASH_Sector_7;&&
& else if((Address & ADDR_FLASH_SECTOR_9) && (Address &= ADDR_FLASH_SECTOR_8))
&&& sector = FLASH_Sector_8;&&
& else if((Address & ADDR_FLASH_SECTOR_10) && (Address &= ADDR_FLASH_SECTOR_9))
&&& sector = FLASH_Sector_9;&&
& else if((Address & ADDR_FLASH_SECTOR_11) && (Address &= ADDR_FLASH_SECTOR_10))
&&& sector = FLASH_Sector_10;&&
& else/*(Address & FLASH_END_ADDR) && (Address &= ADDR_FLASH_SECTOR_11))*/
&&& sector = FLASH_Sector_11;&&
有了这些定义之后,我们就可以开始正式操作FLASH了
首先,要向FLASH写入数据需要先将FLASH解锁。根据手册定义,解锁FLASH需要先向寄存器FLASH_KEYR写入0x之后再向这个寄存器写入0xCDEF89AB。这两个数据在库中已经定义成了:FLASH_KEY1和FLASH_KEY2.
使用库函数不用这么麻烦,函数FLASH_Unlock()即可完成对FLASH的解锁。
解锁FLASH之后,使用函数FLASH_ClearFlag清除FLASH的状态寄存器。然后就可以对FLASH进行写操作了。我按照示例工程,擦除两块FLASH。
下边是操作FLASH的代码,首先擦除两块FLASH,然后向这两块FLASH中写入数据。最后进行校验:
要写入的数据定义:
#define DATA_32&&&&&&&&&&&&&&&& ((uint32_t)0x)
开始FLASH操作:
& FLASH_Unlock(); //解锁FLASH后才能向FLASH中写数据。
//下面这个清flash的状态标志很重要,如果没有清可能会导致擦除flash失败或者不能擦除,我就遇到了这个问题,希望后面的兄弟一定要记得。
& FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |&
&&&&&&&&&&&&&&&&& FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
& /* Get the number of the start and end sectors */
& StartSector = GetSector(FLASH_USER_START_ADDR);& //获取FLASH的Sector编号
& EndSector = GetSector(FLASH_USER_END_ADDR);
& //擦除FLASH
& for (i = StartS i & EndS i += 8)& //每次FLASH编号增加8,可参考上边FLASH Sector的定义。
&&& /* Device voltage range supposed to be [2.7V to 3.6V], the operation will
&&&&&& be done by word */&
&&& if (FLASH_EraseSector(i, VoltageRange_3) != FLASH_COMPLETE)
&&&&& while (1)
& /*擦除完毕*/
& /*开始写入*/
& Address = FLASH_USER_START_ADDR;
&&& while (Address & FLASH_USER_END_ADDR)
&&& if (FLASH_ProgramWord(Address, DATA_32) == FLASH_COMPLETE)&& //将DATA_32写入相应的地址。
&&&&& Address = Address + 4;
&&&&& /* Error occurred while writing data in Flash memory.&
&&&&&&&& User can add here some code to deal with this error */
&&&&& while (1)
& FLASH_Lock();& //读FLASH不需要FLASH处于解锁状态。
//读出数据 检查写入值是否正确
& Address = FLASH_USER_START_ADDR;
& MemoryProgramStatus = 0x0;
&& while (Address & FLASH_USER_END_ADDR)
&&& data32 = *(__IO uint32_t*)A&& //读FLASH中的数据,直接给出地址就行了。跟从内存中读数据一样。
&&& if (data32 != DATA_32)
&&&&& MemoryProgramStatus++;&&
&&& Address = Address + 4;
下边是使用STLink Utility读出的数据,检查一下,确实写进去数据了:
参考文档是ST的 STM32F40xxx and STM32F41xxx Flash programming manual。可在ST网站下载。文档编号:PM0081。FLASH的有不少寄存器,各个含义手册上有详细介绍。我只是简单地看了下。使用库函数操作,好像不大需要详细理解这些寄存器了。
PS:这个实验主要代码来自ST的Demo。这里我只是加入了个人的注释。不当之处,望高人指点。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:118700次
积分:1518
积分:1518
排名:千里之外
原创:22篇
转载:62篇
评论:26条
(1)(4)(21)(6)(2)(1)(5)(12)(3)(3)(1)(8)(2)(14)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'}

我要回帖

更多关于 收购美国芯片 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信