본문 바로가기
Study/nRF51xxx(BLE)

nRF51 DK 예제 18 -WDT(Watch Dog Timer)

by Answer Choi 2015. 3. 16.
반응형


Watch Dog Timer(와치독 타이머)는 시스템이 어떤 원인으로 


인해 뻗어버리는 것을 방지하기 위한 목적으로 쓰입니다.


일정시간 지정해 놓으면, 타이머가 동작하게 되고, 


시스템이 재부팅됩니다.


시스템이 살아있다면 Watch Dog Timer가 동작하기전에 


Timer를 reset시켜 재부팅 되는 것을 막습니다.



nrf51에서는 위 식을 이용하여 타이머를 구하는데, CRV에 값을 넣어주면, 


그 시간만큼 타이머가 동작합니다.


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
int main(void)
{
    uint32_t err_code = NRF_SUCCESS;
   
    LEDS_CONFIGURE(LEDS_MASK);
    LEDS_OFF(LEDS_MASK);
   
    for(uint32_t i = 0; i < LEDS_NUMBER; i++)
    {   nrf_delay_ms(200);
        LEDS_ON(BSP_LED_0_MASK << i);
    }
   
    err_code = nrf_drv_clock_init(NULL);
    APP_ERROR_CHECK(err_code);
    nrf_drv_clock_lfclk_request();
 
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
    APP_GPIOTE_INIT(1);
    err_code = bsp_init(BSP_INIT_BUTTONS, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), bsp_event_callback);
    APP_ERROR_CHECK(err_code);
    err_code = bsp_buttons_enable(1 << FEED_BUTTON_ID);
    APP_ERROR_CHECK(err_code);
   
    nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG;
    err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
    APP_ERROR_CHECK(err_code);
    nrf_drv_wdt_enable();
 
    while(1)
    {
        __SEV();
        __WFE();
        __WFE();
    }
}
cs


Line 5~6 : LED를 설정합니다.


Line 8~11 : LED를 차례대로 켜줍니다.(부팅되는것 표시용도)


Line 13~15 : Clock driver 설정(LFCLK), default로 lfclk을 초기화합니다.


Line 17~22 : BSP설정을 통해 button1을 설정합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
void bsp_event_callback(bsp_event_t event)
{
    switch(event)
    {
        case BSP_EVENT_KEY_0:
            nrf_drv_wdt_channel_feed(m_channel_id);
            break;
       
        default :
            //Do nothing.
            break;
    }
}
cs


버튼1을 누르면 들어가게 되는 callback 함수입니다.(설명은 밑에서~)


Line 24~29 : WDT를 위한 초기화 부분입니다.


Line 24 : WDT config값을 default로 설정합니다.


1
2
3
4
5
#if (WDT_ENABLED == 1)
#define WDT_CONFIG_BEHAVIOUR     NRF_WDT_BEHAVIOUR_RUN_SLEEP
#define WDT_CONFIG_RELOAD_VALUE  2000
#define WDT_CONFIG_IRQ_PRIORITY  APP_IRQ_PRIORITY_HIGH
#endif
cs



Line 25~26 : default값으로 초기화를 합니다.


CRV값은 2000*32768/1000=65536이 됩니다.


포스트 위의 WDT 구하는 식에 넣어보면 (65536+1)/32768=약 2초가 나옵니다.


즉, WDT가 동작시작후 2초가 지나면 다시 초기화가 됩니다.


WDT의 callback 함수는


1
2
3
4
void wdt_event_handler(void)
{
    LEDS_OFF(LEDS_MASK);
cs


그냥 LED를 모두 꺼주고, 초기화를 진행하게 됩니다.


Line 27~28 : RR[0](Reload Request register 0번채널)을 이용합니다.


Line 29 : WDT를 사용합니다.


1
2
3
4
5
6
7
8
void nrf_drv_wdt_enable(void)
{
    ASSERT(m_alloc_index != 0);
    ASSERT(m_state == NRF_DRV_STATE_INITIALIZED);
    nrf_wdt_int_enable(NRF_WDT_INT_TIMEOUT_MASK);
    nrf_wdt_task_set(NRF_WDT_TASKS_START);
    m_state = NRF_DRV_STATE_POWERED_ON;
}
cs


5 : WDT 인터럽트를 enable합니다.


6 : WDT를 시작합니다.(여기서부터 WDT가 동작시작합니다.)


이렇게 WDT가 시작되고 2초가 경과하면, WDT의 callback함수가 호출되고, 


보드는 초기화가 되서 Line 1 부터 다시 시작합니다.


하지만 WDT가 2초가 되기전에 버튼1을 눌러주면, 앞서 설정한 BSP callback함수가 실행됩니다.


BSP callback함수에서는 WDT의 RR[0]에 NRF_WDT_RR_VALUE를 넣어주어 WDT가 초기화 됩니다.


즉 다시 카운트를 시작합니다.


계속해서 누르게 되면 보드는 초기화가 되지 않습니다.




반응형

인기글