이번 예제는 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는 켜지고는 그대로있네요;;
'Study > nRF51xxx(BLE)' 카테고리의 다른 글
nRF51 DK 예제 16 -TIMER (0) | 2015.03.13 |
---|---|
nRF51 DK 예제 15 -TEMPERATURE (0) | 2015.03.12 |
nRF51 DK 예제 13 - Random Number Generator(RNG) (0) | 2015.03.12 |
nRF51 DK 예제 12 - ram retention (0) | 2015.03.12 |
nRF51 SDK 업데이트 (0) | 2015.03.09 |