一、系统时钟
通过对官方源码时钟的配置,可用CUBEMX 得到如下图
MCU 最高工作时钟为 72M ,但是目前使用的是 8M,
之所以为什么要修改这,是因为 将 APP 文件拖到 电脑的 磁盘中,首先会执行擦除功能,擦除的地址范围 从 50K - 256K ,一共103 page ,老是出现擦除失败,
具体表现为 FAIL.TXT 中出现
// ERROR_IAP_ERASE_ALL
"In application programming mass erase failed.",
所以我在擦除的函数内,添加的失败预防措施。简单来说,就是当检测到擦除失败了,再擦一下,重复三次,通过打印的信息来看,103页,有那么2-3页会失败,基本上这几页 再擦一次就行了。
uint32_t EraseSector(uint32_t adr)
{
FLASH_EraseInitTypeDef erase_init;
uint32_t error;
uint32_t ret = 0; // O.K.
HAL_StatusTypeDef ret_hal = HAL_OK;
uint32_t trycnt = 3;
#if 0
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR );
memset(&erase_init, 0, sizeof(erase_init));
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Banks = FLASH_BANK_1;
erase_init.PageAddress = adr;
erase_init.NbPages = 1;
if (HAL_FLASHEx_Erase(&erase_init, &error) != HAL_OK)
{
ret = 1;
DEBUG("Addr : 0x%X",adr);
}
HAL_FLASH_Lock();
#endif
if (HAL_FLASH_Unlock() == HAL_OK)
{
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR );
memset(&erase_init, 0, sizeof(erase_init));
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Banks = FLASH_BANK_1;
erase_init.PageAddress = adr;
erase_init.NbPages = 1;
while ( trycnt-- )
{
ret_hal = HAL_FLASHEx_Erase(&erase_init, &error);
if ( ret_hal != HAL_OK )
{
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR );
DEBUG("Try : Erase Error, Page Num : 0x%X! Error Flag = %d Cnt [%d]", error, ret_hal,trycnt );
}
else
{
trycnt = 3;
break;
}
if (trycnt == 0)
{
trycnt = 3;
break;
}
}
if ( ret_hal != HAL_OK)
{
DEBUG("Erase Flash Page Error, Page Num : 0x%X! Error Flag = %d", error, ret_hal );
}
else
{
//DEBUG("Erase Complete ! Page Num : 0x%X! ", adr );
}
HAL_FLASH_Lock();
}
else
{
DEBUG("FLASH unlock fail! ")
}
return ret;
}
解决了上述擦除失败,还是会有 FAIL.TXT ,表现为写入失败
// ERROR_IAP_WRITE
"In application programming write failed.",
所以添加了,写入失败的打印信息
uint32_t ProgramPage(uint32_t adr, uint32_t sz, uint32_t *buf)
{
uint32_t i;
uint32_t ret = 0; // O.K.
HAL_StatusTypeDef ret_hal = HAL_OK;
uint32_t trycnt = 3;
HAL_FLASH_Unlock();
util_assert(sz % 4 == 0);
for (i = 0; i < sz / 4; i++) {
while ( trycnt-- )
{
ret_hal = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, adr + i * 4, buf[i]);
if ( ret_hal != HAL_OK )
{
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR );
DEBUG("Try : Program Error, Page Num : 0x%X! Error Flag = %d Cnt [%d]", (adr + i * 4), ret_hal,trycnt );
}
else
{
trycnt = 3;
break;
}
if (trycnt == 0)
{
trycnt = 3;
break;
}
}
if ( ret_hal != HAL_OK)
{
DEBUG("Program Flash Page Error, Page Num : 0x%X! Error Flag = %d", adr, ret_hal );
ret = 1;
break;
}
}
HAL_FLASH_Lock();
return ret;
}
果然出现了,大量的写入失败信息出来,大部分 重新写一次就行了,还是存在写三次都失败的地方。
所以回到了,文章的开头,MCU的工作时钟问题,尝试把系统的时钟工作在72M,那么源代码需要做如下修改
sdk.c 文件中 void sdk_init() ,屏蔽下面的
//SystemCoreClockUpdate();
使用外部8M的晶振,配置主频为 72M ,(可使用cubemx 配置 生成代码,复制过来即可 )
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
/* Initialization Error */
util_assert(0);
}
/* USB 配置 */
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
/* Initialization Error */
util_assert(0);
}
系统时间更改,保持 1000HZ ,系统的主频为 72M ,
72M / 2 / 36000 = 1000
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
HAL_StatusTypeDef ret;
RCC_ClkInitTypeDef clk_init;
uint32_t unused;
uint32_t prescaler;
uint32_t source_clock;
HAL_RCC_GetClockConfig(&clk_init, &unused);
/* Compute the prescaler value to have TIMx counter clock equal to 4000 Hz */
//source_clock = SystemCoreClock / tim2_clk_div(clk_init.APB1CLKDivider);
//prescaler = (uint32_t)(source_clock / 4000) - 1;
/* Set TIMx instance */
timer.Instance = TIM2;
timer.Init.Period = 0xFFFF;
timer.Init.Prescaler = 36000 - 1;//prescaler;
timer.Init.ClockDivision = TIM_CLOCKDIVISION_DIV2;
timer.Init.CounterMode = TIM_COUNTERMODE_UP;
timer.Init.RepetitionCounter = 0;
__HAL_RCC_TIM2_CLK_ENABLE();
ret = HAL_TIM_Base_DeInit(&timer);
if (ret != HAL_OK) {
return ret;
}
time_count = 0;
ret = HAL_TIM_Base_Init(&timer);
if (ret != HAL_OK) {
return ret;
}
ret = HAL_TIM_Base_Start(&timer);
if (ret != HAL_OK) {
return ret;
}
return HAL_OK;
}
uint32_t HAL_GetTick(void)
{
cortex_int_state_t state;
state = cortex_int_get_and_disable();
const uint32_t ticks = __HAL_TIM_GET_COUNTER(&timer) ;;/// 4; /* 去掉 */
time_count += (ticks - time_count) & 0x3FFF; /* CNT 寄存器 15bit */
cortex_int_restore(state);
return time_count;
}
结果就是 不再出现 写入错误