애플리케이션에서 주기적인 작업이나 이벤트가 필요한 경우 Timer를 이용한다. nRF52의 Application Timer는 RTC1을 사용하며, 응용 프로그램에 작업을 위해 정확한 타이밍 소스를 제공한다.
1. Application Timer 개요
nRF52840에서 Application Timer는 RTC1을 기반으로 하여 동작합니다. 이 타이머는 초저전력 모드에서도 동작 가능하며, 주기적인 작업이나 이벤트 처리에 적합합니다. 일반적으로 배터리 구동 장치나 저전력 IoT 애플리케이션에서 타이머가 필요한 경우 많이 사용됩니다.
타이머는 반복 모드(repeated)와 단일 실행 모드(single shot)를 지원하며, 타이머가 종료되거나 시간이 만료될 때 특정 작업을 수행하는 콜백 함수(Handler)를 등록할 수 있습니다.
2. Application Timer의 주요 특징
nRF52840의 Application Timer는 아래와 같은 주요 특징을 가지고 있습니다:
- 다양한 타이머 모드: 타이머 카운터 및 PWM 모드 등 다양한 타이밍 관련 작업을 지원하여 여러 종류의 타이밍 요구 사항을 해결할 수 있습니다.
- 저전력 동작: 타이머는 저전력 모드에서도 효율적으로 동작하여 배터리 수명이 중요한 애플리케이션에서 유용합니다.
- 정확한 타이밍 소스: RTC1을 사용하여 높은 정확도의 타이밍을 제공합니다.
- 주기적인 작업 처리: 주기적으로 데이터를 수집하거나 이벤트를 처리하는 데 적합하며, 반복적으로 특정 작업을 수행하는 데 활용할 수 있습니다.
3. Application Timer 구성타이머를 사용하려면 먼저 프로젝트 설정에서 sdk_config.h 파일을 수정해야 합니다. CMSIS Configuration Wizard를 사용하여 쉽게 설정할 수 있으며, 타이머의 다양한 옵션을 설정할 수 있습니다.
3.1 sdk_config.h
#define APP_TIMER_ENABLED 1
#define APP_TIMER_CONFIG_RTC_FREQUENCY 0
#define APP_TIMER_CONFIG_IRQ_PRIORITY 6
#define APP_TIMER_CONFIG_OP_QUEUE_SIZE 10
#define APP_TIMER_CONFIG_USE_SCHEDULER 0
#define APP_TIMER_KEEPS_RTC_ACTIVE 0
#define APP_TIMER_SAFE_WINDOW_MS 300000
#define APP_TIMER_WITH_PROFILER 0
#define APP_TIMER_CONFIG_SWI_NUMBER 0
#define CLOCK_CONFIG_IRQ_PRIORITY 6
- APP_TIMER_ENABLED: 타이머 기능을 활성화하는 플래그입니다. 1로 설정하여 타이머를 사용합니다.
- APP_TIMER_CONFIG_RTC_FREQUENCY: RTC의 주파수를 설정하는 항목으로, 기본값은 0이며 이는 32.768kHz를 의미합니다.
- APP_TIMER_CONFIG_IRQ_PRIORITY: 타이머와 관련된 인터럽트의 우선순위를 설정합니다. 일반적으로 값이 낮을수록 높은 우선순위를 가지므로, 다른 작업보다 타이머가 우선적으로 처리될 수 있게 설정합니다.
위 설정은 sdk_config.h에서 찾아볼 수 있으며, 각 프로젝트에 맞게 조정해야 합니다.
3.2 nRF_Driver
- ./integration/nrfx/legacy/nrf_drv_clock.c
3.3 nRF_Library
- ./components/libraries/timer/app_timer.c
- ./components/libraries/util/app_util_platform.c
4. Application Timer 초기화
Application Timer는 LFCLK(Low Frequency Clock)를 사용하여 동작합니다. SoftDevice를 사용하는 애플리케이션에서는 LFCLK가 자동으로 활성화되지만, SoftDevice를 사용하지 않는 경우에는 수동으로 LFCLK를 활성화해야 합니다. 아래 코드를 통해 LFCLK를 요청하고 Application Timer를 초기화할 수 있습니다.
lfclk_request();
app_timer_init();
main() 함수의 시작 부분에 lfclk_request(); 함수를 호출하여 LFCLK를 활성화합니다. SoftDevice를 사용 중인 경우 이 과정은 필요하지 않으며, LFCLK가 자동으로 설정됩니다. 그 다음 app_timer_init(); 함수를 호출하여 타이머 시스템을 초기화합니다.
5. Application Timer 생성
이제 타이머 인스턴스를 생성하고, 타임아웃 이벤트 핸들러를 만들어서 타이머를 사용할 준비를 할 수 있습니다. 먼저 APP_TIMER_DEF 매크로를 사용하여 타이머 인스턴스를 정의한 후, app_timer_create() 함수를 호출하여 타이머를 생성합니다.
APP_TIMER_DEF(m_repeated_timer_id); // Timer 인스턴스 정의
static void my_timer_handler(void * p_context)
{
// 타이머 종료 시 실행될 작업
}
void create_timer(void)
{
ret_code_t err_code;
// 타이머 생성
err_code = app_timer_create(&m_repeated_timer_id,
APP_TIMER_MODE_REPEATED, // 반복 모드 (단일 모드는 APP_TIMER_MODE_SINGLE_SHOT)
my_timer_handler);
APP_ERROR_CHECK(err_code);
}
이 코드에서 app_timer_create() 함수는 총 세 개의 인수를 받습니다. 두 번째 인수는 타이머 모드로, 반복 모드(APP_TIMER_MODE_REPEATED) 또는 단일 실행 모드(APP_TIMER_MODE_SINGLE_SHOT)를 선택할 수 있습니다. 타임아웃 시 실행될 작업은 세 번째 인수로 전달되는 핸들러 함수에서 정의합니다.
6. Application Timer 시작
타이머를 생성한 후에는 app_timer_start() 함수를 통해 타이머를 시작할 수 있습니다. 이 함수는 타이머가 몇 밀리초(ms) 후에 동작할지 지정하고, 필요 시 추가 매개변수를 핸들러 함수로 전달합니다.
void my_timer_start(void)
{
ret_code_t err_code;
err_code = app_timer_start(m_repeated_timer_id, APP_TIMER_TICKS(200), NULL);
APP_ERROR_CHECK(err_code);
}
위 코드에서 APP_TIMER_TICKS(200)은 타이머가 200ms 후에 동작할 것을 의미합니다. 타이머가 시작되면, 설정한 주기에 따라 반복적으로 타임아웃 이벤트가 발생하고 핸들러 함수가 호출됩니다. 이때 NULL은 핸들러에 전달할 추가 인수가 없음을 나타냅니다.
7. 사례와 주의 사항
Application Timer는 주기적인 작업이나 이벤트 처리를 효율적으로 도와주지만, 잘못 사용하면 코드의 복잡성을 증가시키고 시스템 성능에 영향을 줄 수 있습니다. 타이머를 사용할 때 고려해야 할 몇 가지 모범 사례와 주의 사항을 아래와 같이 정리할 수 있습니다.
7.1 타이머 사용 최소화
너무 많은 타이머를 동시에 사용하는 것은 시스템 리소스를 과도하게 소모할 수 있습니다. 타이머가 필요한 작업을 중앙 집중식으로 관리하거나, 여러 작업을 하나의 타이머에서 처리할 수 있는 방법을 고려해야 합니다.
7.2 타이머 간 인터벌 관리
타이머가 너무 짧은 간격으로 반복 실행되면 CPU가 깨어나는 빈도가 증가하여 전력 소비가 커질 수 있습니다. 전력 소모가 중요한 경우, 타이머의 인터벌을 가능한 긴 주기로 설정하는 것이 좋습니다.
7.3 타임아웃 핸들러에서의 작업 관리
타임아웃 핸들러에서 시간이 오래 걸리는 작업을 수행하면 다른 타이머 이벤트의 처리에 지연을 초래할 수 있습니다. 핸들러 함수에서는 가능한 짧은 시간 내에 작업을 완료하고, 필요한 경우 이벤트 큐를 사용하여 나중에 추가 작업을 처리하는 방법을 고려해야 합니다.
8. 결론
nRF52840의 Application Timer는 저전력 애플리케이션에서 주기적인 작업을 처리하는 데 매우 유용한 도구입니다. 이 글에서는 타이머의 설정부터 생성, 시작 및 주의해야 할 모범 사례까지 자세히 다루었습니다. 주기적으로 센서 데이터를 읽거나, 특정 작업을 일정 시간 간격으로 반복해야 하는 경우, Application Timer는 매우 적합한 솔루션입니다.
타이머를 사용할 때는 너무 많은 타이머 인스턴스를 생성하지 않도록 주의하고, 타임아웃 핸들러에서 복잡한 작업을 수행하는 대신 빠르게 처리하여 시스템 성능에 영향을 주지 않도록 해야 합니다. 적절한 사용으로 타이머를 활용하면 임베디드 시스템의 효율성을 크게 향상시킬 수 있을 것입니다.
'nRF52' 카테고리의 다른 글
nRF52 RTC(Real-Time Clock)를 활용한 캘린더 구현 (0) | 2024.09.16 |
---|---|
nRF52 Application Scheduler (0) | 2024.09.15 |
nRF52를 이용한 BLE Central 가이드 (0) | 2024.09.13 |
nRF52 BLE Peripheral에서 Advertising Service Data 활용하기 (0) | 2024.09.12 |
nRF52 BLE Advertising Interval 설정과 최적화 (0) | 2024.09.11 |