你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

f407zgt6 IAP,bootloader跳转到app,app中HAL_GetTick()总是等于0

[复制链接]
dogpi 提问时间:2024-2-29 18:42 / 已解决

下面是Bootloader代码,按下按键(引脚电平为低)进入bootloader命令界面;按键不按下,跳转到APP。

int main(void)
{ 
  // col = R;
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_USART1_UART_Init();

  printmsg("iap version 0.1\r\n");

  // red and green led off
  HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET);
  HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);


  if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==GPIO_PIN_RESET){
    // jump to bootloader / red led on
    printmsg("jump to bootloader!\r\n");
    HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);
    jump_to_bootloader();
  }
  else{
    // jump to application / green led on
    printmsg("jump to application!\r\n");
    HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);
    jump_to_application();
  }
}

下面是跳转到APP的代码:

/**
 * @brief 跳转到用户application,执行用户程序。
 * 
 */
void jump_to_application(void)
{
  int i = 0;
  void (*application_reset_handler)(void);

  uint32_t msp_value = *(volatile uint32_t*)APP_FLASH_BASE_ADDRESS;
  printmsg("MSP value : %#x\r\n",msp_value);



  uint32_t reset_handller_address = *(volatile uint32_t *)(APP_FLASH_BASE_ADDRESS+4);
  application_reset_handler = (void *)reset_handller_address;
  __set_MSP(msp_value);
        printmsg("application reset handler address : %#x\r\n",application_reset_handler);

  application_reset_handler();
}

APP 代码为:


int main(void)
{
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();  MX_USART1_UART_Init();

  while (1)
  {
    printmsg("hello world!\r\n");
    uint32_t current_tick = HAL_GetTick();
    while(HAL_GetTick()<=current_tick+1000);

  }
}

经排查,发现是jump_to_bootloader()中调用了HAL_FLASHX_Erase()函数导致无法跳转,HAL_FLASHX_Erase()中__HAL_LOCK(&pFlash)中使用到了枚举类型进行比较,这个比较导致APP无法正常运行。

注释掉jump_to_bootloader(),APP可以循环打印“hello world!”。

为了模拟现象,在Bootloader程序中创建enum对象,并对其赋值:

typedef enum {
  R=0,
  G,
  B
} COLOR;

typedef struct 
{
  /* data */
  COLOR c;
} _COLOR;

COLOR  col;
_COLOR _col;
int main(void)
{ 
  col = R;    // ******** 这里赋值
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_USART1_UART_Init();

  printmsg("iap version 0.1\r\n");

  // red and green led off
  HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_SET);
  HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_SET);


  if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)==GPIO_PIN_RESET){
    // jump to bootloader / red led on
    printmsg("jump to bootloader!\r\n");
    HAL_GPIO_WritePin(GPIOF,GPIO_PIN_9,GPIO_PIN_RESET);
    //jump_to_bootloader();
  }
  else{
    // jump to application / green led on
    printmsg("jump to application!\r\n");
    HAL_GPIO_WritePin(GPIOF,GPIO_PIN_10,GPIO_PIN_RESET);
    jump_to_application();
  }
}

这样就跳转到APP后就只打印一次“hello world!”,然后卡在while中,调试发现HAL_GetTick()一直等于0。

收藏 评论5 发布时间:2024-2-29 18:42

举报

5个回答
传说中的路过 最优答案 回答时间:2024-3-1 10:22:34

dogpi 发表于 2024-3-1 10:15</p>
<pre><code class="language-c">
int main(void)
{

[md]你改的偏移是灰色的,因为他上一级`/* #define USER_VECT_TAB_ADDRESS */`这个宏定义你要打开,就在你截图上面没截到的地方就是 把注释去掉试试
dogpi 回答时间:2024-3-1 10:29:35
传说中的路过 发表于 2024-3-1 10:22
[md]你改的偏移是灰色的,因为他上一级`/* #define USER_VECT_TAB_ADDRESS */`这个宏定义你要打开,就在 ...

[md]![image.png](data/attachment/forum/202403/01/102828gk6lee337kakq34k.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")

添加宏定义后OK了,感谢大佬帮助。
image.png
xmshao 回答时间:2024-3-1 09:55:07
一般来讲,IAP和APP是两个独立的工程。


在从IAP区跳转到APP前,保证将刚才使能的中断都禁用掉,比方你开启过的UART中断、定时器中断啊什么的,
都逐个将其中断使能位清零,当然直接对外设做复位也可以殊途同归。


另外,基于ST库组织的代码的话,那个systick定时器默认使能并启用了相关中断,记得跳转前将其中断使能
禁用或令其停止计数操作。下面三个操作任一个都可以达到目的。


SysTick->CTRL &=~SysTick_CTRL_TICKINT_Msk;

SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk

SysTick->LOAD  = 0 ;  



具体到这里 ,跳转过去后 是否发生了因中断优先级问题导致互斥现象。


不知你的Printmsg具体实现,你先屏蔽它看看。 当然前面提到的跳转前


的准备工作要先做足。
传说中的路过 回答时间:2024-3-1 10:00:33

需要把你APP初始化是怎么做的放出来

dogpi 回答时间:2024-3-1 10:15:46

传说中的路过 发表于 2024-3-1 10:00
需要把你APP初始化是怎么做的放出来

int main(void)
{
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();  
  MX_USART1_UART_Init();

  while (1)
  {
    printmsg("hello world!\r\n");
    uint32_t current_tick = HAL_GetTick();
    while(HAL_GetTick()<=current_tick+1000);

  }
}

上面就是APP的全部内容,但是我修改了flash的偏移地址,原本是0x00000000,修改为:0x00010000

image.png

APP的target配置:

image.png

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版