完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
使用STM32H743VIT6芯片时,系统时钟为400MHz,从片上Flash读取数据时,有时会进入hardfault。对flash全部擦除后再次下载后,从片上Flash读取数据恢复正常。有没有大牛知道该如何解决这个问题?这是芯片本身的bug吗?
系统时钟配置如下: //时钟设置函数 //Fvco=Fs*(plln/pllm); //Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp)); //Fq=Fvco/pllq=Fs*(plln/(pllm*pllq)); //Fvco:VCO频率 //Fsys:系统时钟频率,也是PLL1的p分频输出时钟频率 //Fq:PLL1的q分频输出时钟频率 //Fs:PLL输入时钟频率,可以是HSI,CSI,HSE等. //plln:PLL1倍频系数(PLL倍频),取值范围:4~512. //pllm:PLL1预分频系数(进PLL之前的分频),取值范围:2~63. //pllp:PLL1的p分频系数(PLL之后的分频),分频后作为系统时钟,取值范围:2~128.(且必须是2的倍数) //pllq:PLL1的q分频系数(PLL之后的分频),取值范围:1~128. //CPU频率(rcc_c_ck)=sys_d1cpre_ck=400Mhz //rcc_aclk=rcc_hclk3=200Mhz //AHB1/2/3/4(rcc_hclk1/2/3/4)=200Mhz //APB1/2/3/4(rcc_pclk1/2/3/4)=100Mhz //FMC时钟频率=pll2_r_ck=((25/25)*512/2)=256Mhz //外部晶振为25M的时候,推荐值:plln=160,pllm=5,pllp=2,pllq=2. //得到:Fvco=25*(160/5)=800Mhz // Fsys=800/2=400Mhz // Fq=800/2=400Mhz //外部晶振为16M的时候,推荐值:plln=250,pllm=5,pllp=2,pllq=2. //得到:Fvco=16*(250/5)=800Mhz // Fsys=800/2=400Mhz // Fq=800/2=400Mhz //返回值:0,成功;1,失败。 void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq) { HAL_StatusTypeDef ret=HAL_OK; RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; RCC_PeriphCLKInitTypeDef periphClkInitStruct; MODIFY_REG(PWR->CR3,PWR_CR3_SCUEN, 0); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); while ((PWR->D3CR (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) {} RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState=RCC_HSE_ON; RCC_OscInitStruct.HSIState=RCC_HSI_OFF; RCC_OscInitStruct.CSIState=RCC_CSI_OFF; RCC_OscInitStruct.PLL.PLLState=RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource=RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLN=plln; RCC_OscInitStruct.PLL.PLLM=pllm; RCC_OscInitStruct.PLL.PLLP=pllp; RCC_OscInitStruct.PLL.PLLQ=pllq; RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2; ret=HAL_RCC_OscConfig( RCC_OscInitStruct); if(ret!=HAL_OK) while(1); //选中 PLL 作为系统时钟源并且配置 HCLK,PCLK1、 PCLK2、 PCLK3 和 PCLK4 RCC_ClkInitStruct.ClockType=(RCC_CLOCKTYPE_SYSCLK| RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_D3PCLK1); RCC_ClkInitStruct.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;//系统时钟源 PLL RCC_ClkInitStruct.SYSCLKDivider=RCC_SYSCLK_DIV1;//SYSCLK 分频系数 1 RCC_ClkInitStruct.AHBCLKDivider=RCC_HCLK_DIV2;//AHB 分频系数 2 RCC_ClkInitStruct.APB1CLKDivider=RCC_APB1_DIV2;//APB1 分频系数 2 RCC_ClkInitStruct.APB2CLKDivider=RCC_APB2_DIV2;//APB2 分频系数 2 RCC_ClkInitStruct.APB3CLKDivider=RCC_APB3_DIV2;//APB3 分频系数 2 RCC_ClkInitStruct.APB4CLKDivider=RCC_APB4_DIV2;//APB4 分频系数 2 /*ST 官方例程使用的就是 4 个 WS, 其实大于 2 个 WS 都可以(最大不 能超过 7 个 WS),延时越久越稳定,但是肯定影响性能 */ FLASH->ACR = ~FLASH_ACR_WRHIGHFREQ_Msk; FLASH->ACR |= FLASH_ACR_WRHIGHFREQ_2;//rcc_aclk 设置的是 200Mhz,设置 WRHIGHFREQ[1:0]=10 即可 ret=HAL_RCC_ClockConfig( RCC_ClkInitStruct, FLASH_LATENCY_4); if(ret!=HAL_OK) while(1); //设置SPI1的时钟源 periphClkInitStruct.PeriphClockSelection=RCC_PERIPHCLK_SPI1 | RCC_PERIPHCLK_SPI3 | RCC_PERIPHCLK_SPI6; //设置SPI1 、 SPI3、SPI6时钟源 periphClkInitStruct.Spi123ClockSelection=RCC_SPI123CLKSOURCE_PLL; //SPI1时钟源使用PLL1Q periphClkInitStruct.Spi6ClockSelection =RCC_SPI6CLKSOURCE_D3PCLK1; //SPI6时钟源使用PCLK4 100MHz ret=HAL_RCCEx_PeriphCLKConfig( periphClkInitStruct); if(ret!=HAL_OK) while(1); __HAL_RCC_CSI_ENABLE() ; __HAL_RCC_SYSCFG_CLK_ENABLE() ; HAL_EnableCompensationCell(); } flash 读写函数具体如下: #include "hal_flash.h" //读取指定地址的字(32 位数据) //addr:读地址 //返回值:对应数据 uint32_t HAL_FLASH_ReadWord(uint32_t addr) { uint32_t value = 0; value = *(__IO uint32_t*)addr;//此处进入hardfault,传入的地址为0x08060000 return value; } uint16_t HAL_FLASH_GetFlashSector(uint32_t addr) { if(addr= ADDR_FLASH_BANK1_START addr <= ADDR_FLASH_BANK1_END) return FLASH_BANK_1; else if(addr >= ADDR_FLASH_BANK2_START addr <= ADDR_FLASH_BANK2_END) return FLASH_BANK_2; else return 0; } uint32_t HAL_FLASH_EraseSector(uint32_t addr)//擦除片区 { FLASH_EraseInitTypeDef FlashEraseInit; uint32_t SectorError=0; uint8_t FLASH_BANK = 0; FLASH_BANK = HAL_FLASH_GetFlashBank(addr); //操作 BANK FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS; //擦除类型 FlashEraseInit.Sector=HAL_FLASH_GetFlashSector(addr);//要擦除的扇区 FlashEraseInit.Banks= FLASH_BANK; FlashEraseInit.NbSectors=1; //一次只擦除一个扇区 FlashEraseInit.VoltageRange=FLASH_VOLTAGE_RANGE_3; //电压范围 if(HAL_FLASHEx_Erase( FlashEraseInit, SectorError)!=HAL_OK) { return 1; //发生错误了 } SCB_CleanInvalidateDCache(); //清除无效的 D-C return 0; } //从指定地址开始写入指定长度的数据 //特别注意:因为 STM32H7 的扇区实在太大,没办法本地保存扇区数据,所以本函数 // 写地址如果非 0XFF,那么会先擦除整个扇区且不保存扇区数据.所以 // 写非 0XFF 的地址,将导致整个扇区数据丢失.建议写之前确保扇区里 // 没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写. //该函数对 OTP 区域也有效!可以用来写 OTP 区! //OTP 区域地址范围:0X1FF0F000~0X1FF0F41F //WriteAddr:起始地址(此地址必须为 4 的倍数!!) //pBuffer:数据指针 //NumToWrite:字(32 位)数(就是要写入的 32 位数据的个数.) void HAL_FLASH_Write(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite) { FLASH_EraseInitTypeDef FlashEraseInit; HAL_StatusTypeDef FlashStatus=HAL_OK; uint32_t SectorError=0; uint32_t addrx=0; uint32_t endaddr=0; uint8_t FLASH_BANK = 0; if(WriteAddr |
|
相关推荐
1个回答
|
|
应该是HAL_FLASH_Write(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite)函数写入数据异常导致下次读取数据有问题。
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1792 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1626 浏览 1 评论
1094 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
732 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1682 浏览 2 评论
1943浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
744浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
578浏览 3评论
601浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
563浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 19:27 , Processed in 0.856133 second(s), Total 83, Slave 65 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号