IAP注意事项

使用正点原子F407的IAP例程时,发现了一个问题,在进行IAP升级后,APP中的串口无法使使用,串口接收不到中断,printf会卡死。

造成这种现象的原因可能是因为外设在bootloader中初始化的时候,对串口进行了一些映射无法被复位中断重置。

在经过不(tong)懈(ku)的debug后,发现在跳转到APP之前,需要先关闭所有中断响应,并将初始化后的外设复位,跳转到app后再打开中断就解决了。

//jump2app之前操作
INTX_DISABLE();
USART_DeInit(USART1);
//进入main之后操作
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x10000);
INTX_ENABLE();

其中的开启中断和关闭中断是用汇编实现的,学过arm课程的应该都很容易看懂,没学过的也不用深究。

//关闭所有中断(但是不包括fault和NMI中断)
__asm void INTX_DISABLE(void)
{
	CPSID   I
	BX      LR	  
}
//开启所有中断
__asm void INTX_ENABLE(void)
{
	CPSIE   I
	BX      LR  
}

而对中断向量表进行偏移设置,网上包括原子都有大量文献说明。

对于工程:
其中bootloader其实什么都不用做修改。
IAP注意事项_第1张图片

target这里也不需要做什么修改。
IAP注意事项_第2张图片

代码这里做下修改就可以了。
IAP注意事项_第3张图片

而APP在编译前需要修改target:
IAP注意事项_第4张图片
如果不做修改,生成的map对应会有问题。app会从8000000开始找代码运行。

如果在下载那里改成对应的地址区域,就可以直接下载到0x08010000开始的地址。
IAP注意事项_第5张图片

下面随便记录一下其他内容~

void USART_DeInit(USART_TypeDef* USARTx)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));

  if (USARTx == USART1)
  {
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);
  }
  //省略其他外设枚举
}

再往下看可以发现:

void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB2_RESET_PERIPH(RCC_APB2Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB2RSTR |= RCC_APB2Periph;
  }
  else
  {
    RCC->APB2RSTR &= ~RCC_APB2Periph;
  }
}

查阅手册发现:
IAP注意事项_第6张图片
那么这里的操作就是先复位串口1,再取消复位串口1。
这样就可以解决因为bootloader初始化外设之后留下的bug。

你可能感兴趣的:(stm32)