STM32L152的IAP移植筆記

本文將針對STML152的IAP移植過程作一個筆記。

首先得下載AN3310的示例代碼,地址爲:http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32-standard-peripheral-libraries-expansions/stsw-stm32075.html

下載完成後,我們需要做些修改,我們將在NUCLEO-L152RE板子上進行驗證測試。

由於NUCLEO-L152RE板子默認MCU是沒有外掛晶振的,但可以通過ByPass方式使用ST-LInk的8M晶振,但這裏只是作爲IAP,且只需要使用到串口,因此可以只使用HSI,於是,在AN3310的工程中打開system_stm32l1xx.c文件找到SystemInit函數,註釋掉//SetSysClock();,讓系統使用默認的HSI即可。

void SystemInit (void)
{
  /*!< Set MSION bit */
  RCC->CR |= (uint32_t)0x00000100;

  /*!< Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], MCOSEL[2:0] and MCOPRE[2:0] bits */
  RCC->CFGR &= (uint32_t)0x88FFC00C;

  /*!< Reset HSION, HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xEEFEFFFE;

  /*!< Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /*!< Reset PLLSRC, PLLMUL[3:0] and PLLDIV[1:0] bits */
  RCC->CFGR &= (uint32_t)0xFF02FFFF;

  /*!< Disable all interrupts */
  RCC->CIR = 0x00000000;

#ifdef DATA_IN_ExtSRAM
  SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */

  /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */
  //SetSysClock();

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}

然後修改man.c文件中的main函數,註釋掉一些按鍵,讓程序默認進入到升級模式:

int main(void)
{
  /* Unlock the Flash Program Erase controller */
  FLASH_If_Init();

  /* Initialize Key Button mounted on STM32L15xx-EVAL board */
  //STM_EVAL_PBInit(BUTTON_KEY, BUTTON_MODE_GPIO);

  /* Test if Key push-button on STM32L15xx-EVAL Board is pressed */
  //if (STM_EVAL_PBGetState(BUTTON_KEY) != 0x00)
  {
    /* Execute the IAP driver in order to reprogram the Flash */
    IAP_Init();
    /* Display main menu */
    Main_Menu ();
  }
#if 0
  /* Keep the user application running */
  else
  {
    /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */
    if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
    {
      /* Jump to user application */
      JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
      Jump_To_Application = (pFunction) JumpAddress;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
      Jump_To_Application();
    }
  }
#endif
  while (1)
  {}
}


由於NUCLEO板子默認使用的是USART2,因此需要修改使用的串口:

void IAP_Init(void)
{
 USART_InitTypeDef USART_InitStructure;
  /* USART resources configuration (Clock, GPIO pins and USART registers) ----*/
  /* USART configured as follow:
        - BaudRate = 115200 baud
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
  */
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  //STM_EVAL_COMInit(COM2, &USART_InitStructure);
  USART2_Init(&USART_InitStructure);
}


USART2_Init()函數爲新添加的串口初始化函數,其定義如下:

void USART2_Init(USART_InitTypeDef* USART_InitStruct)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Enable GPIO clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

  /* Enable UART clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

  /* Connect PXx to USARTx_Tx */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);

  /* Connect PXx to USARTx_Rx */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);

  /* Configure USART Tx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USART Rx as alternate function push-pull */
  //GPIO_InitStructure.GPIO_Pin = COM_RX_PIN[COM];
  //GPIO_Init(COM_RX_PORT[COM], &GPIO_InitStructure);

  /* USART configuration */
  USART_Init(USART2, USART_InitStruct);

  /* Enable USART */
  USART_Cmd(USART2, ENABLE);
}


接下來需要修改程序中使用到的打印函數:

void SerialPutChar(uint8_t c)
{
  USART_SendData(USART2, c);
  while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
  {
  }
}


uint32_t SerialKeyPressed(uint8_t *key)
{

  if ( USART_GetFlagStatus(USART2, USART_FLAG_RXNE) != RESET)
  {
    *key = (uint8_t)USART2->DR;
    return 1;
  }
  else
  {
    return 0;
  }
}


基本上就移植好了,編譯燒錄進NUCLEO板中運行。


接下來需要找一個PC端軟件超級終端。

由於我使用的是64位Windows7,默認是不帶Hyper Terminal的,需要下載個:http://download.csdn.net/detail/crifan/3508497

我是下載的這個,是XP中帶的那個,還不錯吧。


除了IAP程序,我們還得準備APP程序,由於IAP支持燒錄的是BIN文件,因此,我們得生成BIN文件,HEX是不行的。

在APP工程中我們得注意幾項內容,以IAR爲例:

1 在option->Linker下:

  config->Edit..--->Vector Table 的起始地址改爲:0x08003000

  ---->Memory Regions->ROM改爲:0x08003000


2 option->Output Converter->修改生成BIN文件


3  sysytem_stm32l1xx.c文件下

 找到宏定義

    #define VECT_TAB_OFFSET  0x3000

 偏移位置必須改爲0x3000

到此基本可以了,APP就這樣。


最後就是測試了。


測試:

首先得將IAP燒錄進MCU,然後再通過IAP燒錄APP。

通過IAP燒錄APP過程如下:

打開超級終端,連接上串口,有如下界面:

波特率:115200 data bis:8 parity:none stop bits:1 Flow control:none

通過鍵盤輸入1:

從菜單transfer->Send file打開如下界面,輸入APP的BIN文件路徑,並使用Ymodem傳輸協議,如下圖:

點擊Send,開始燒錄。。。

傳輸結束後,按下3,運行APP程序,至此,整個IAP與APP都可以正常工作了。


結束語:

這個只是個示例,實際IAP是還需要修改的,得判斷是進行升級模式還是直接跳過進入APP,這個就需要看設計如何了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章