PY32F系列MCU在OTA时App区概率性跑不起来的根因分析(3)

接前一篇文章:PY32F系列MCU在OTA时App区概率性跑不起来的根因分析(2)

二、问题分析

3. 最终定位

上一回笔者沿着排查方向

(4)整个过程都没有问题,跳转出现了问题

1)烧录后跳转到App出了问题;

2)不经过烧录过程,直接跳转到App就出问题;

3)Boot或App自身存在问题。

不断改进方案、测试。

但即使笔者已经用了最强手段,问题依旧存在,只是概率上有所降低而已。这就说明也许之前的方向可能就错了,问题可能并不是烧录后跳转才出现,而是启动跳转就会出现。

碰巧在排查问题的过程中,有一天下午在天使用户家里复现了问题。那天并未进行OTA,而是直接一上电MCU程序直接跑飞了(通过指示灯和一般性功能判断)。这就辅证了问题确实不是OTA导致的,而是正常启动过程,由Boot区跳转到App区就存在问题。

还记得之前首先就排除了这种可能(参见PY32F系列MCU在OTA时App区概率性跑不起来的根因分析(1)-CSDN博客),

现在看来,之前的判断有误,正常启动时从Boot跳转到App就会存在问题。那么,问题究竟出在哪里呢?这次范围缩小了,锁定到了APP_Bootloader_Go这个函数。

APP_Bootloader_Go函数代码如下:

cpp 复制代码
typedef  void (*pFunction)(void);
void APP_Bootloader_Go(uint32_t dwAddr)
{
	uint32_t JumpAddress;
	pFunction Jump_To_Application;

	__disable_irq();

	APP_DeInitInterface();

	if (((*(__IO uint32_t*)dwAddr) & 0x2FFC0000 ) == 0x20000000)
	{
		/* Jump to user application */
		JumpAddress = *(__IO uint32_t*) (dwAddr + 4);
		Jump_To_Application = (pFunction) JumpAddress;
		/* Initialize user application's Stack Pointer */
		__set_MSP(*(__IO uint32_t*) dwAddr);
		Jump_To_Application();
	}
}

而普冉官方给出的OTA例程的APP_Bootloader_Go函数代码如下:

cpp 复制代码
typedef  void (*pFunction)(void);
void APP_Bootloader_Go(uint32_t dwAddr)
{
  uint32_t JumpAddress;
  pFunction Jump_To_Application;
  
  CLEAR_BIT(RCC->CFGR, RCC_CFGR_SW);
  while (0 != READ_BIT(RCC->CFGR, RCC_CFGR_SWS));
  
  CLEAR_BIT(RCC->CR, RCC_CR_PLLON);

  if (((*(__IO uint32_t*)dwAddr) & 0x2FFC0000 ) == 0x20000000)
  {
    /* Jump to user application */
    JumpAddress = *(__IO uint32_t*) (dwAddr + 4);
    Jump_To_Application = (pFunction) JumpAddress;
    /* Initialize user application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) dwAddr);
    Jump_To_Application();
  }
}

看起来两个代码差不多,后半段代码完全一致,只是官方例程的代码中多了两段CLEAR_BIT相关代码,而笔者代码中多了APP_DeInitInterface函数。

但实际上笔者工程代码中的APP_DeInitInterface函数已经有了这两段代码。而官方例程将APP_DeInitInterface函数放到了APP_Bootloader_Go函数外边。

cpp 复制代码
/**
 * @brief  This function is used to jump to the user application.
 * @retval An ErrorStatus enumeration value:
 *          - SUCCESS: Go operation done
 *          - ERROR:   Go operation failed or the value of address is not ok
 */
ErrorStatus APP_Go(void)
{
  uint8_t ucMemArea;
  uint32_t dwAddr;

  ucMemArea = GetAddressArea(&dwAddr);
  if ((ucMemArea != FLASH_AREA) && (ucMemArea != RAM_AREA))
  {
    return ERROR;
  }
  
  APP_DeInitInterface();

  APP_Bootloader_Go(dwAddr);

  return SUCCESS;
}

因此,笔者工程代码和官方例程代码基本上一致了。而官方例程普冉的技术支持已经明确说了是非常成熟的方案,已经经过了N多公司的量产考验。

这样看来,问题是出在了细节的差异上。还需要仔细进行差异比对。具体细节请看下回。

相关推荐
jianqiang.xue6 小时前
【CStackGUI 实战】画板 drawpad:鼠标拖拽作图、撤销 / 重做、导出 PNG
单片机·嵌入式·cstackgui·c语言gui·可视化拖拽
嵌入式分享1 天前
BSP调试#01:RTC(RK3588)
嵌入式·实时音视频
嵌入式分享1 天前
嵌入式分享#38:踩坑实录!我在 RK3576 HDMI 搭错线
嵌入式
oku620892 天前
单片机底层系列:C 库运行时——从 libspace 到多任务与中断安全
嵌入式
国科安芯2 天前
航天器健康管理系统中嵌入式控制器的多源状态监测与故障诊断能力评估
mcu·健康管理·抗辐射·空间信息·航天器
Brilliantwxx2 天前
【STM32】基础定时器 TIM 详解:从极简原理到寄存器全解析
stm32·单片机·嵌入式硬件·mcu
小刘max2 天前
从半导体视角理解 NVM 与 Flash:存储单元、阵列架构与应用差异
mcu
Zwawa2 天前
反馈:让系统知道自己做得对不对
c语言·单片机·嵌入式
蓝天居士2 天前
PY32F系列MCU在OTA时App区概率性跑不起来的根因分析(2)
mcu·嵌入式