nRF52

nRF52 fstorage 사용 가이드

임베디드 친구 2024. 9. 17. 18:11
반응형

nRF fstorage는 Nordic Semiconductor에서 개발한 경량 데이터 저장 라이브러리입니다. 이 라이브러리는 nRF52 시리즈와 같은 임베디드 시스템에서 효율적으로 데이터를 관리하고 저장하는 데 특화되어 있습니다. 이 글에서는 nRF fstorage의 특징, 설정, 초기화 방법, 그리고 실제 데이터를 읽고 쓰는 방법을 설명합니다. 또한, SoftDevice 사용 여부에 따른 API 변경점과 주요 사용 방법을 상세히 다룹니다.

1. nRF fstorage 개요

nRF fstorage는 플래시 메모리 관리와 같은 중요한 기능을 수행하는 경량 라이브러리입니다. 이는 주로 작은 크기의 데이터를 빠르고 안정적으로 저장할 수 있도록 설계되었으며, 제한된 리소스를 가진 임베디드 시스템에 최적화되어 있습니다. 특히, 플래시 메모리의 읽기 및 쓰기 성능을 극대화하며, 이를 통해 메모리 효율성을 높이는 것이 주요 목표입니다.

2. nRF fstorage의 특징

nRF fstorage는 다음과 같은 주요 특징을 가지고 있습니다:

  • 경량성: 제한된 리소스를 가진 임베디드 시스템에서도 사용 가능한 경량 라이브러리로, 메모리 소모가 적습니다.
  • 빠른 데이터 접근: 데이터의 읽기 및 쓰기 속도가 빠르며, 이를 통해 시스템 성능을 저하시키지 않습니다.
  • 안정성: 플래시 메모리와 관련된 오류 처리 메커니즘이 잘 설계되어 있어 안정적인 동작을 보장합니다.
  • 유연성: 다양한 용도로 사용할 수 있도록 커스터마이징이 가능하며, SoftDevice 사용 여부에 따라 동작을 최적화할 수 있습니다.

3. nRF fstorage 모듈 설정

nRF fstorage를 사용하기 위해서는 SDK 내에서 해당 모듈을 활성화해야 합니다. 이를 위해 sdk_config.h 파일에서 관련 설정을 진행합니다.

// fstorage 모듈 활성화
#define NRF_FSTORAGE_ENABLED 1

fstorage 모듈 파일 경로.

./components/libraries/fstorage/nrf_fstorage.c
./components/libraries/fstorage/nrf_fstorage_sd.c

이 설정은 기본적인 fstorage 모듈을 활성화하며, 이후의 작업은 플래시 메모리에 데이터를 저장하거나 읽기 위한 작업을 수행합니다.

4. nRF fstorage 초기화

fstorage를 사용하려면 플래시 메모리의 시작 주소와 끝 주소를 명시하고, 이벤트 핸들러를 설정해야 합니다. 또한, SoftDevice가 활성화된 경우와 비활성화된 경우에 따라 사용하는 백엔드가 달라집니다.

SoftDevice에 따른 초기화 API

  • SoftDevice 활성화(SOFTDEVICE_PRESENT): nrf_fstorage_sd 백엔드를 사용합니다.
  • SoftDevice 비활성화 또는 미사용: nrf_fstorage_nvmc 백엔드를 사용합니다. SoftDevice가 활성화된 상태에서 nrf_fstorage_nvmc를 사용하면 오류가 발생합니다.

다음은 초기화 과정의 코드 예시입니다.

static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);

NRF_FSTORAGE_DEF(nrf_fstorage_t aika_fstorage) =
{
    .evt_handler = fstorage_evt_handler,
    .start_addr = 0xF0000,   // 플래시 시작 주소
    .end_addr   = 0x100000,  // 플래시 끝 주소
};

static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
    if (p_evt->result != NRF_SUCCESS)
    {
        NRF_LOG_INFO("--> fstorage 작업 중 오류 발생.");
        return;
    }

    switch (p_evt->id)
    {
        case NRF_FSTORAGE_EVT_WRITE_RESULT:
            NRF_LOG_INFO("플래시에 쓰기 완료");
            break;
        case NRF_FSTORAGE_EVT_ERASE_RESULT:
            NRF_LOG_INFO("플래시 지우기 완료");
            break;
        default:
            break;
    }
}

int aika_flash_init(void)
{
    ret_code_t ret;
    nrf_fstorage_api_t * p_fs_api;

#ifdef SOFTDEVICE_PRESENT
    p_fs_api = &nrf_fstorage_sd;  // SoftDevice 활성화 상태에서는 SD 백엔드를 사용
#else
    p_fs_api = &nrf_fstorage_nvmc;  // SoftDevice가 없을 경우 NVMC 사용
#endif

    ret = nrf_fstorage_init(&aika_fstorage, p_fs_api, NULL);
    APP_ERROR_CHECK(ret);

    print_flash_info(&aika_fstorage); // 디버깅용 플래시 정보 출력
    NRF_LOG_INFO("플래시 끝 주소: 0x%x", nrf5_flash_end_addr_get());

    return 0;
}

5. nRF fstorage 사용 방법

fstorage의 기본 기능인 데이터 읽기, 쓰기, 삭제는 각각 다음과 같은 함수들을 통해 수행됩니다.

ret_code_t nrf_fstorage_erase(nrf_fstorage_t const* p_fs, uint32_t page_addr, uint32_t len, void* p_param);
ret_code_t nrf_fstorage_read(nrf_fstorage_t const* p_fs, uint32_t addr, void* p_dest, uint32_t len);
ret_code_t nrf_fstorage_write(nrf_fstorage_t const* p_fs, uint32_t dest, void const* p_src, uint32_t len, void * p_param);

이 함수들은 비동기적으로 동작하므로 작업이 완료되면 설정된 이벤트 핸들러를 통해 결과를 받아볼 수 있습니다.

6. nRF fstorage 코드 예시

여기에서는 위의 기본 함수를 활용하여 데이터를 플래시에 저장하고 읽어오는 함수들을 정의합니다. 이 함수들은 사용자가 보다 쉽게 플래시를 관리할 수 있도록 단순화된 형태입니다.

// 4KB 단위로 플래시 페이지 삭제
ret_code_t aika_storage_erase(uint32_t page_addr, uint32_t block_cnt)
{
    if((0 != (0x0FFF & page_addr)))
        return NRF_ERROR_INVALID_ADDR;  // 페이지 주소가 4KB 단위가 아닌 경우 오류 반환

    return nrf_fstorage_erase(&aika_fstorage, page_addr, block_cnt, NULL);
}

// 플래시에서 데이터 읽기
ret_code_t aika_storage_read(uint32_t src_addr, void* p_dest, uint32_t src_len)
{
    return nrf_fstorage_read(&aika_fstorage, src_addr, p_dest, src_len);
}

// 플래시에 데이터 쓰기
ret_code_t aika_storage_write(uint32_t dest_addr, void const* p_src, uint32_t src_len)
{
    if(0 == (0x0FFF & dest_addr))
        aika_storage_erase(dest_addr, 1);  // 쓰기 전 블록 삭제

    return nrf_fstorage_write(&aika_fstorage, dest_addr, p_src, src_len, NULL);
}

이 코드 예시는 aika_storage_write() 함수에서 쓰기 전에 플래시 블록을 자동으로 삭제하는 로직을 포함하고 있어 사용이 간편합니다. 플래시는 일반적으로 쓰기 전에 반드시 해당 블록을 삭제해야 하므로 이를 자동으로 처리하도록 구현하였습니다.

7. 주의 사항

  • SoftDevice 활성 상태에서의 NVMC 사용 금지: SoftDevice가 활성화된 상태에서 NVMC 백엔드를 사용하면 하드 폴트가 발생합니다. 반드시 SoftDevice 상태에 맞는 백엔드를 사용해야 합니다.
  • 플래시 수명 관리: 플래시 메모리는 일정 횟수 이상 쓰기 및 삭제 작업을 하면 성능이 저하될 수 있습니다. 이를 고려하여 중요한 데이터는 자주 쓰지 않도록 설계하는 것이 좋습니다.
  • 비동기 작업 처리: fstorage의 읽기 및 쓰기 작업은 비동기적으로 동작하므로 이벤트 핸들러를 통해 작업의 완료 여부를 확인해야 합니다. 이를 처리하는 이벤트 루틴을 구현하는 것이 중요합니다.

8. 결론

nRF fstorage는 임베디드 시스템에서 플래시 메모리를 간단하고 효율적으로 관리할 수 있는 라이브러리입니다. SoftDevice 사용 여부에 따른 API 변경에 유의해야 하며, 플래시 수명과 비동기 처리 등을 고려한 안정적인 시스템 설계가 중요합니다. 위의 코드 예시와 설명을 통해 nRF52840과 같은 칩에서 플래시 메모리 작업을 보다 쉽게 구현할 수 있을 것입니다.
fstorage는 경량 시스템에서도 뛰어난 성능을 제공하므로, 소형 디바이스의 데이터 저장 솔루션으로 적합한 선택입니다.

반응형