본문 바로가기
Embedded Program

STM32 Flash Program (Write)

by rlawnsghtest 2024. 4. 11.

임베디드 프로그램을 하다 보면 log 기능이라던지, Configure 데이터를 Flash에 저장 해야 할 경우들이 발생 합니다.

이때 STM은 HAL  드라이버를 제공하지만, 라인없 별로 일부 차이가 있어서 검토 자료를 남겨 놓습니다.

 

  • stm32l4xx_hal_flash.c 는 HAL_FALSH_Program 은 64 bit 용데이터를 받습니다.

TypeProgram : 프로그램 유형을 나타내는 매개변수 입니다. 다음 값 중 하나를 사용할 수 있습니다.

   - FLASH_TYPEPROGRAM_DOUBLEWORD : 더블 워드(64비트)를 지정된 주소에 프로그램합니다.

   - FLASH_TYPEPROGRAM_FAST : 32개의 더블 워드(64비트)를 빠르게 프로그램합니다.

   - FLASH_TYPEPROGRAM_FAST_AND_LAST : 마지막 행에 대한 빠른 프로그램 작업을 수행합니다.

Address : 프로그램 할 메모리 주소 입니다.

Data : 프로그램 할 데이터 입니다.

//stm32l4xx_hal_flash.c

HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{
  HAL_StatusTypeDef status = HAL_ERROR;
  uint32_t prog_bit = 0;

  /* 프로세스 잠금 */
  __HAL_LOCK(&pFlash);

  /* 매개변수 확인 */
  assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));

  /* 마지막 작업이 완료될 때까지 대기 */
  status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

  if(status == HAL_OK)
  {
    pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;

    /* 데이터 캐시가 활성화되어 있는 경우 데이터 불일치를 방지하기 위해 비활성화합니다. */
    if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != 0U)
    {
      /* 데이터 캐시 비활성화 */
      __HAL_FLASH_DATA_CACHE_DISABLE();
      pFlash.CacheToReactivate = FLASH_CACHE_DCACHE_ENABLED;
    }
    else
    {
      pFlash.CacheToReactivate = FLASH_CACHE_DISABLED;
    }

    if(TypeProgram == FLASH_TYPEPROGRAM_DOUBLEWORD)
    {
      /* 지정된 주소에 더블 워드(64비트)를 프로그램합니다. */
      // 본 함수를 호출할 경우에는 Address 위치를 8바이트씩 옮겨야 합니다.
      // stm32f0xx_hal_flash.c 와는 다르게 FLASH_Program_HalfWord 함수가 없습니다.
      // FLASH_Program_DoubleWord 함수 내부에서는 word 단위로 2번 Write 하는 구문이 있습니다.
      FLASH_Program_DoubleWord(Address, Data);
      prog_bit = FLASH_CR_PG;
    }
    else if((TypeProgram == FLASH_TYPEPROGRAM_FAST) || (TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST))
    {
      /* 지정된 주소에 32행 더블 워드(64비트)를 빠르게 프로그램합니다. */
      FLASH_Program_Fast(Address, (uint32_t)Data);

      /* 마지막 행이면, 작업이 끝날 때 비트가 클리어됩니다. */
      if(TypeProgram == FLASH_TYPEPROGRAM_FAST_AND_LAST)
      {
        prog_bit = FLASH_CR_FSTPG;
      }
    }
    else
    {
      /* 아무것도 하지 않습니다. */
    }

    /* 마지막 작업이 완료될 때까지 대기 */
    status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);

    /* 프로그램 작업이 완료되면 PG 또는 FSTPG 비트를 비활성화합니다. */
    if (prog_bit != 0U)
    {
      CLEAR_BIT(FLASH->CR, prog_bit);
    }

    /* 데이터 일관성을 확보하기 위해 캐시를 플러시합니다. */
    FLASH_FlushCaches();
  }

  /* 프로세스 잠금 해제 */
  __HAL_UNLOCK(&pFlash);

  return status;
}

 

특히한 점은 "stm32f0xx_hal_flash.c"에서 정의 하고 있는 HAL_FLASH_Program() 함수에서는 하프워드(16비트), 워드(32비트), 더블워드(64비트)를 TypeProgram 으로 넘겨서 사용할 수 있지만, stm32l4xx_hal_flash.c 에서는 기본이 double word 라는 점 입니다.

 

  • stm32f0xx_hal_flash.c 는 HAL_FALSH_Program 은 하프워드(16비트), 워드(32비트), 더블워드(64비트)를 TypeProgram 으로 넘겨서 사용할 수 있습니다.

TypeProgram : 프로그램 유형을 나타내는 매개변수 입니다. 다음 값 중 하나를 사용할 수 있습니다.

   - FLASH_TYPEPROGRAM_HALFWORD : 하프워드(16비트)를 지정된 주소에 프로그램합니다.

   - FLASH_TYPEPROGRAM_WORD : 워드(32비트)를 지정된 주소에 프로그램합니다.

   - FLASH_TYPEPROGRAM_DOUBLEWORD : 더블워드(64비트)를 지정된 주소에 프로그램합니다.

Address : 프로그램 할 메모리 주소 입니다.

Data : 프로그램 할 데이터 입니다.

//stm32f0xx_hal_flash.c

HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{
  HAL_StatusTypeDef status = HAL_ERROR;
  uint8_t index = 0U;
  uint8_t nbiterations = 0U;
  
  /* 프로세스 잠금 */
  __HAL_LOCK(&pFlash);

  /* 매개변수 확인 */
  assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
  assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));

  /* 마지막 작업이 완료될 때까지 대기 */
  status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
  
  if(status == HAL_OK)
  {
    if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD)
    {
      /* 지정된 주소에 하프워드(16비트)를 프로그램합니다. */
      nbiterations = 1U;
    }
    else if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
    {
      /* 지정된 주소에 워드(32비트 = 2*16비트)를 프로그램합니다. */
      nbiterations = 2U;
    }
    else
    {
      /* 지정된 주소에 더블워드(64비트 = 4*16비트)를 프로그램합니다. */
      nbiterations = 4U;
    }

    for (index = 0U; index < nbiterations; index++)
    {
      // 실제로는 하프웨드(16bit) 씩 반복해서 데이터를 Write 함. 
      FLASH_Program_HalfWord((Address + (2U*index)), (uint16_t)(Data >> (16U*index)));

      /* 마지막 작업이 완료될 때까지 대기 */
      status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    
      /* 프로그램 작업이 완료되면 PG 비트를 비활성화합니다. */
      CLEAR_BIT(FLASH->CR, FLASH_CR_PG);

      /* 에러 발생 시 프로그래밍 절차 중단 */
      if (status != HAL_OK)
      {
        break;
      }
    }
  }

  /* 프로세스 잠금 해제 */
  __HAL_UNLOCK(&pFlash);

  return status;
}

 

겸용으로 사용하기 위해서는  TypeProgram 을  FLASH_TYPEPROGRAM_DOUBLEWORD 로 선언하고 사용하는 것이 좋겠습니다.