Study/nRF51xxx(BLE)

nRF51 DK 예제 14 -Real Time Counter(RTC)

Answer Choi 2015. 3. 12. 16:26
반응형


이번 예제는 Real Time Counter입니다.


첨에 RTC(Real Time Clock)인줄 알았는데 


Clock이 아니라 Counter군요.


LED1은 Real Time Counter로 toggle하고, 


LED2는 Counter Compare해서 켜줍니다.



main.c


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main(void)
{
    leds_config();
 
    lfclk_config();
 
    rtc_config();
   
    while (true)
    {
        __SEV();
        __WFE();
        __WFE();
    }
}
cs


단촐한 main문입니다.


Line 3 : LED를 설정해줍니다.


1
2
3
4
5
static void leds_config(void)
{
    LEDS_CONFIGURE(((1<<COMPARE_EVENT_OUTPUT) | (1<<TICK_EVENT_OUTPUT)));
    LEDS_OFF((1<<COMPARE_EVENT_OUTPUT) | (1<<TICK_EVENT_OUTPUT));
}
cs


Line 5 : LFCLK(Low Frequency Clock)를 설정합니다.


1
2
3
4
5
6
7
static void lfclk_config(void)
{
    ret_code_t err_code = nrf_drv_clock_init(NULL);
    APP_ERROR_CHECK(err_code);
 
    nrf_drv_clock_lfclk_request();
}
cs


3: CLOCK설정을 초기화합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
ret_code_t nrf_drv_clock_init(nrf_drv_clock_config_t const * p_config)
{
    uint32_t result = NRF_SUCCESS;
 
    if (m_clock_cb.module_initialized == false)
    {
        m_clock_cb.hfclk_requests     = 0;
#ifndef SOFTDEVICE_PRESENT
        m_clock_cb.lfclk_requests     = 0;
 
        nrf_clock_xtalfreq_set(CLOCK_CONFIG_XTAL_FREQ);
        nrf_clock_lf_src_set((nrf_clock_lf_src_t)CLOCK_CONFIG_LF_SRC);
 
#if CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LF_SRC_RC
 
        m_clock_cb.calibration_in_progress = false;
 
        nrf_clock_event_clear(NRF_CLOCK_EVENTS_HFCLKSTARTED);
        nrf_clock_event_clear(NRF_CLOCK_EVENTS_LFCLKSTARTED);
        nrf_clock_event_clear(NRF_CLOCK_EVENTS_DONE);
        nrf_clock_event_clear(NRF_CLOCK_EVENTS_CTTO);
 
        if (p_config == NULL)
        {
            p_config = &m_default_config;
        }
 
        nrf_clock_cal_timer_timeout_set(p_config->cal_interval);
        nrf_drv_common_irq_enable(POWER_CLOCK_IRQn, p_config->interrupt_priority);
 
#endif // CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LF_SRC_RC
#else // SOFTDEVICE_PRESENT
        uint8_t is_enabled;
        result = sd_softdevice_is_enabled(&is_enabled);
        if((result == NRF_SUCCESS) && !is_enabled)
        {
            result = NRF_ERROR_SOFTDEVICE_NOT_ENABLED;
        }
#endif // SOFTDEVICE_PRESENT
    }
    else
    {
        result = NRF_ERROR_INVALID_STATE;
    }
 
    if (result == NRF_SUCCESS)
    {
        m_clock_cb.module_initialized = true;
    }
 
    return result;
}
cs


5~12 : softdevice가 없으므로 이부분이 실행된 후 값을 return합니다.


7~9 : hfclk와 lfclk를 0으로 초기화합니다.


11: 메인 클럭인 xtal을 16MHz로 설정합니다.


12 : LFCLK source를 32.769kHz crystal oscillator로 설정합니다.


46~51 : 초기화 완료로 설정후 값을 return합니다.


Line 7 : RTC를 초기화합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void rtc_config(void)
{
    uint32_t err_code;
 
    err_code = nrf_drv_rtc_init(&rtc, NULL, rtc_handler);
    APP_ERROR_CHECK(err_code);
 
    nrf_drv_rtc_tick_enable(&rtc,true);
 
    err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME*RTC0_CONFIG_FREQUENCY,true);
    APP_ERROR_CHECK(err_code);
 
    nrf_drv_rtc_enable(&rtc);
}
cs


5~6 : rtc를 초기화 합니다.

nrf_drv_rtc.c


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ret_code_t nrf_drv_rtc_init(nrf_drv_rtc_t const * const p_instance,
                            nrf_drv_rtc_config_t const * p_config,
                            nrf_drv_rtc_handler_t handler)
{
    if (handler)
    {
        m_handlers[p_instance->instance_id] = handler;
    }
    else
    {
        return NRF_ERROR_INVALID_PARAM;
    }
 
    if (p_config == NULL)
    {
        p_config = &m_default_config[p_instance->instance_id];
    }
 
    if (m_cb[p_instance->instance_id].state != NRF_DRV_STATE_UNINITIALIZED)
    {
        return NRF_ERROR_INVALID_STATE;
    }
 
    nrf_drv_common_irq_enable(p_instance->irq, p_config->interrupt_priority);
    nrf_rtc_prescaler_set(p_instance->p_reg, p_config->prescaler);
    m_cb[p_instance->instance_id].reliable     = p_config->reliable;
    m_cb[p_instance->instance_id].tick_latency = p_config->tick_latency;
    m_cb[p_instance->instance_id].state        = NRF_DRV_STATE_INITIALIZED;
 
    return NRF_SUCCESS;
}
cs


5~8 : rtc_handler변수 m_handlers[0]에 handler를 넣어줍니다.


14~17 : p_config에 default값을 넣어줍니다.


default 값은 아래와 같습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define RTC0_CONFIG_FREQUENCY 8
#define RTC0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
#define RTC0_CONFIG_RELIABLE     false
#define RTC0_INSTANCE_INDEX      0
#define NRF_MAXIMUM_LATENCY_US 2000
 
#define NRF_DRV_RTC_DEFAULT_CONFIG(id)                                                            
        {                                                                                        
         .prescaler          = (uint16_t)(RTC_INPUT_FREQ/RTC##id##_CONFIG_FREQUENCY)-1,    
         .interrupt_priority = RTC##id##_CONFIG_IRQ_PRIORITY,                              
         .reliable           = RTC##id##_CONFIG_RELIABLE,                                  
         .tick_latency       = RTC_US_TO_TICKS(NRF_MAXIMUM_LATENCY_US,RTC##id##_CONFIG_FREQUENCY),
 
        }
cs


24~28 : 위 값들을 기준으로 설정해줍니다.


prescaler=(32768/8)-1=4095

interrupt_priority=APP_IRQ_PRIORITY_LOW

reliable=false

tick_latency=0.016


8 : 설정한 rtc tick을 enable 시킵니다.


10~11 : rtc_CC를 설정합니다.


1
nrf_rtc_cc_set(p_instance->p_reg,channel,val);
cs


CC[0]=24가 됩니다.


prescaler가 4095이므로 4095/32768=0.125 즉, CC는 0.125*24일때 들어오게 됩니다.


Line 11~13


SEV : 다중프로세서의 모든코어에 신호를 보낼 이벤트를 발생시킨다라고 되어있네요.


WFE : 이벤트가 설정될 경우 이를 즉시해제하고 원래상태로 되돌린다고 되어있네요;


아직 정확히 이해가 되지는 않습니다. 이부분이 없어도 동작은 합니다;;


더 자세한 정보는 ARM information center에서~


1
2
3
4
5
6
7
8
9
10
11
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    {
        nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
    }
    else if (int_type == NRF_DRV_RTC_INT_TICK)
    {
        nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
    }
}
cs


이부분이 LED를 토글하는 부분입니다.


코드 대로하면 LED1은 0.125초마다 토글되고, LED2는 3초마다 토글되야하는데


LED2는 켜지고는 그대로있네요;;




반응형