임베디드 프로그램을 하다 보면 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 로 선언하고 사용하는 것이 좋겠습니다.
'Embedded Program' 카테고리의 다른 글
임베디드 시스템에서의 UART, SPI, I2C 통신 프로토콜 (0) | 2025.02.06 |
---|---|
임베디드 시스템에서 효율적인 전력 관리 방법 (0) | 2025.02.04 |
인터럽트(Interrupt)와 폴링(Polling)의 차이점과 최적의 선택법 (1) | 2025.02.04 |
마이크로컨트롤러(MCU) 선택 가이드 - 어떤 칩이 나에게 맞을까? (0) | 2025.02.03 |
펌웨어 (Firmware) 란? (2) | 2025.02.03 |