F๐Ÿ’ปW/Coding

[STM32F030C6T6] Bootloader ๊ตฌํ˜„

์ฒœ์ˆญ์ด 2023. 3. 30. 10:17

 

ํŠนํžˆ ๋ถ€ํŠธ์ฝ”๋“œ๋Š” ์ตœ๋Œ€ํ•œ ๊ฐ€๋ณ๊ณ  ์งง๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ.

 

ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ Flash, UART ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋งŒ ์ž‘์„ฑํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ์ง€์šฐ๋Š” ๊ฒƒ์ด ์ข‹์Œ.

 

<๋ถ€ํŠธ๋กœ๋”>

์ž„๋ฒ ๋””๋“œ ๋ณด๋“œ ์ „์› -> ํ”Œ๋ž˜์‹œ ๋ฉ”๋ชจ๋ฆฌ(ROM)์—์„œ ์‹œ์Šคํ…œ ์†Œํ”„ํŠธ์›จ์–ด ์‹œ์ž‘(H/W ์ดˆ๊ธฐํ™”)->๋ฆฌ๋ˆ…์Šค์ปค๋„์„ ๋ฉ”๋ชจ๋ฆฌ(RAM)์— ์ ์žฌ=์‚ฌ์šฉ์ž๋ช…๋ น์ฒ˜๋ฆฌ์ค€๋น„

 

<ํ”Œ๋ž˜์‹œ ์‚ฌ์ด์ฆˆ ์ธก์ •>

์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” mcu๋Š” STM32F100x6. ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ์‹œํŠธ์˜ Device overview๋ฅผ ์‚ดํŽด๋ณด๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์€ํ‘œ๊ฐ€ ๋‚˜์˜จ๋‹ค.

Memory mapping์€ ์‚ฌ์ด์ฆˆ๊ฐ€ ํฐ mcu๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ ค์ง€๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ๊ทธ๋ฆผ์„ ์ฐธ๊ณ ํ•˜๋ฉด ์•ˆ๋จ!

 

Device overview

 

STM32F100Cx ์—์„œ 4์—ด์€ ์•„๋ž˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ์„ธ๋ถ€ ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ์ˆœ์„œ์ด๋‹ค. C6์— ํ•ด๋‹นํ•˜๋ฏ€๋กœ ๋‘๋ฒˆ์งธ ์—ด์„ ์ฐธ๊ณ ํ•˜๊ธฐ!

 

 

์ˆ˜์ •์ด ํ•„์š”ํ•œ ์ธํ„ฐ๋ŸฝํŠธ ํ•จ์ˆ˜ - ์‹œ๋ฆฌ์–ผ๋กœ ์˜ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ฃผ๊ณ  ๋ฐ”๋กœ clearํ•ด์ฃผ๋Š” ์ž‘์—…

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	uint32_t tmp_flag = 0, tmp_it_source = 0;
	tmp_flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE);
	tmp_it_source = __HAL_UART_GET_IT_SOURCE(&huart1, UART_IT_RXNE);
	if ((tmp_flag != RESET) && (tmp_it_source != RESET)) { 
	  HAL_UART_Receive(&huart1, USART_BUF, 1, 100);
	}
	__HAL_UART_CLEAR_PEFLAG(&huart1);

  /* USER CODE END USART1_IRQn 0 */
	 HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

 

์ˆ˜์ •์ด ํ•„์š”ํ•œ ์ธํ„ฐ๋ŸฝํŠธ ํ•จ์ˆ˜2 - uart enable ํ•จ์ˆ˜๋ฅผ ๋ฐ˜๋“œ์‹œ ์ž‘์„ฑํ•ด์ค˜์•ผ ํ•œ๋‹ค

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==USART1)
  {
  /* USER CODE BEGIN USART1_MspInit 0 */

  /* USER CODE END USART1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART1 GPIO Configuration
    PA9     ------> USART1_TX
    PA10     ------> USART1_RX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN USART1_MspInit 1 */
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); 
  /* USER CODE END USART1_MspInit 1 */
  }

}

 

์ˆ˜์ •์ด ํ•„์š”ํ•œ ์„ค์ •

์ ํ”„ํ•  ์ฃผ์†Œ๊ฐ€ 0x08002800์ด๋ฏ€๋กœ, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋กœ์ ํŠธ์˜ system ํŒŒ์ผ์—์„œ(Bootํ”„๋กœ์ ํŠธ ์•„๋‹˜!!) ํ”Œ๋ž˜์‹œ์˜ ๋ฐฑํ„ฐํ…Œ์ด๋ธ” ์˜คํ”„์…‹์„ 2800์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ ํ•œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  #define USER_VECT_TAB_ADDRESS ๋ถ€๋ถ„์„ ์ฃผ์„ ํ•ด์ œ ํ•ด์•ผํ•œ๋‹ค (์ง„์งœ ์™„์ „ ์ค‘์š” โ˜†โ˜…)

 

 

 

์ฝ”๋“œ

<main.c>

int main(void)
{  
  HAL_FLASH_Unlock();
  
  InternalFlash_Page1024Read(0x08007C00);       // ๋ฉ”๋ชจ๋ฆฌ์˜ ๋ - 1K
  

  if(InterFlash[1023] == 0xAA){     
   	--system init ํ•จ์ˆ˜๋“ค ์ž‘์„ฑ --
    
    while(1){
		-- while ๋ฃจํ”„ ๋‚ด ๋™์ž‘ ์ž‘์„ฑ --
    }
  }
  else{                                // ๋ฉ”๋ชจ๋ฆฌ ๋์ด 0xFF ์ผ ๋•Œ, JUMP TO APP
    if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000) == 0x20000000)
    {
      /* Jump to user application */ // Application ์ฃผ์†Œ๊ฐ€ 0x08002800์œผ๋กœ ์„ค์ •๋œ ์ƒํƒœ
      JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
      Jump_To_Application = (pFunction) JumpAddress;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) 0x08002800);
      Jump_To_Application();
    }
  }
  while (1);
}

 

< ํ•จ์ˆ˜ CommandFunctions() >

void CommandFunctions(void)
{
  uint8_t buff[3];
  uint16_t i;
  uint8_t ptr = 0;
  

        HAL_FLASH_Unlock();

        InterFlashAddr = (0x08002800 +(u32)(SYS_RxBuf[0]*1024));
        memset(InterFlash, 0, 1024);
        memcpy(InterFlash, &Buffer[1], 1024);                // ๋ฒ„ํผ ๋‚ด์šฉ์„ InterFlash์— ๋ณต์‚ฌ
        
        InternalFlash_Page1024Write(InterFlashAddr);            //InterFlash ๋ฐ์ดํ„ฐ ํ”Œ๋ž˜์‰ฌ ์ฃผ์†Œ์— write

        memset(InterFlash, 0, 1024);                            // InterFlash 0์œผ๋กœ ์ดˆ๊ธฐํ™”
        InternalFlash_Page1024Read(InterFlashAddr);             // 
        check = 0;
        for(i=0;i<1024;i++){
          if(InterFlash[i] == Buffer[i+1]) check += 0;
          else check += 1;
        }
        if(check == 0){
          SEND_ACK();      // ACK๋ฅผ ๋ณด๋ƒ„์œผ๋กœ์จ ๋™์ž‘ ํ™•์ธ
        }
        else SEND_NACK();  // ๊ทธ ๋ฐ˜๋Œ€ NACK
       }
       
       else if (SYS_Com == 3) {
         memset(InterFlash, 0xFF, 1024);                        // ๋ฉ”๋ชจ๋ฆฌ ๋๋ถ€๋ถ„ FF๋กœ ์“ฐ๊ธฐ
         InternalFlash_Page1024Write(0x08007C00);
         HOST_ACK();
         _delay_ms(500);
         
         HAL_NVIC_SystemReset();                                    // mcu๋ฆฌ์…‹, ๋ถ€ํŠธ๋ชจ๋“œ ์žฌ์ง„์ž…
       }
     }
     
  }
}

 

< InterFlash_Page1024 Read & Write() >

u8 InternalFlash_Page1024Read(u32 addr)
{
  u32 i;
  u32 ramdata;
  
  ramdata = (u32)InterFlash;
  for(i=0;i<256;i++){
    *(__IO uint32_t *)(ramdata) = *(__IO uint32_t *)(addr);
    addr += 4;
    ramdata += 4;
  }
  return 1;
}


u8 InternalFlash_Page1024Write(u32 addr)
{
  u32 i;
  u32 ramdata;
  
  PAGEError = 0;
  HAL_FLASH_Unlock();                                   // ํ”Œ๋ž˜์‹œ ๋ฉ”๋ชจ๋ฆฌ ์กฐ์ž‘์„ ์œ„ํ•œ ํ”Œ๋ž˜์‹œ Unlock

  EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
  EraseInitStruct.PageAddress = addr;                   // ๋ถ€ํŠธ ๋ฉ”๋ชจ๋ฆฌ์˜ ๋ ์ฃผ์†Œ-1K
  EraseInitStruct.NbPages     = 1;
  
  HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError); 
  
  ramdata = (u32)InterFlash;
  for(i=0;i<256;i++){
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, *(__IO uint32_t *)(ramdata));     // ramdata ํ˜•๋ณ€ํ™˜ ํ•„์ˆ˜
    addr += 4;
    ramdata += 4;
  }
  return 1;
}

 

 


<์—๋Ÿฌ ํ•ด๊ฒฐ ๊ณผ์ •>

 

1. *(u32*) ์ž๋ฃŒํ˜•์„ -> *(__IO uint32_t*) ๋กœ ํ˜•๋ณ€ํ™˜

2. ‘FF’๋ฅผ ๋งˆ์ง€๋ง‰์— ์จ์ฃผ๋Š” ์ž‘์—…์—์„œ HOST์—๊ฒŒ ACK ์‘๋‹ต์„ ๋ณด๋‚ด์•ผํ•œ๋‹ค
 -> JND USBํ†ต์‹ ์„ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ GUI๋ผ ACK๋ฅผ ๋ณด๋‚ด์•ผํ•˜๋Š” ์‹œ์Šคํ…œ์œผ๋กœ ์„ค๊ณ„๋œ ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ์œ ์ถ”ํ•˜์‹ฌ

3. HAL ํ•จ์ˆ˜๋กœ ๋ชจ๋‘ ๋Œ€์ฒดํ•˜๊ณ , Erase๊ด€๋ จ ๊ตฌ์กฐ์ฒด EraseInitstruct ์„ ์„ ์–ธํ•˜๊ณ  ๊ทธ์— ๋งž๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ์ž‘์„ฑ

EraseInitStruct.TypeErase   = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = addr;   // Jumpํ•  address + SYS_RxBuf[0]*1024      
EraseInitStruct.NbPages     = 1;