본문으로 바로가기

[nRF52 ] wdt (watchdog timer) 프로젝트 분석

category Nordic_nRF52 2022. 4. 20. 11:58

 

0> 개요

  :  watchdog 초기화 및 동작을 이해하고 button1 을 눌러 watchdog 리셋이 안되게하기

    (nRF52832 보드 기준 설명입니다.)

1> 프로젝트 위치

   : <InstallFolder>\examples\peripheral\wdt

 

2> 테스트

 2-1> SES 를 이용한 프로젝트 빌드 && download

 2-2> 부팅후 LED (LED1, LED2, LED3, LED4)가 순차적으로  켜지는지 확인

 2-3> Button1 을 2초보다 짧은 간격으로 눌러주면서 watchdog 리셋이 안되는 지 LED를 확인합니다.

      >> LED 4개 전부 켜져있는 상태를 유지하면 OK         

 

3> 소스코드

 3-1> button1  초기화 및 event handler 등록하기

main()
{
    ~~~~ 중략 ~~~~
    app_timer_init();
    bsp_init(BSP_INIT_BUTTONS, bsp_event_callback);
    ~~~~ 중략 ~~~~
    bsp_buttons_enable();
}

uint32_t bsp_init(uint32_t type, bsp_event_callback_t callback)
{
    ~~~~ 중략 ~~~~
    for (num = 0; ((num < BUTTONS_NUMBER) && (err_code == NRF_SUCCESS)); num++)
    {
        bsp_event_to_button_action_assign(num, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_DEFAULT);
    }
     app_button_init((app_button_cfg_t *)app_buttons, BUTTONS_NUMBER, APP_TIMER_TICKS(50));
     app_button_enable();
     // 아래의 app_timer_create() 호출전 app_timer_init() 이 먼저 호출되야 합니다.
     app_timer_create(&m_bsp_button_tmr, APP_TIMER_MODE_SINGLE_SHOT, button_timer_handler);
    ~~~~ 중략 ~~~~
    
}

uint32_t bsp_buttons_enable()
{
    return app_button_enable();
}

// button push 시 호출되는 callback 함수에 button1  case 추가하기
void bsp_event_callback(bsp_event_t event)
{
    switch (event)
    {
        case BSP_EVENT_KEY_0:
            nrf_drv_wdt_channel_feed(m_channel_id);   // clear watchdog 
            break;
        ~~~~ 중략 ~~~~

    }
}

 

  

3-2> watchdog 초기화 및 enable 하기 

// <1=> Run in SLEEP, Pause in HALT 
// <8=> Pause in SLEEP, Run in HALT 
// <9=> Run in SLEEP and HALT 
// <0=> Pause in SLEEP and HALT 
#define NRFX_WDT_CONFIG_BEHAVIOUR 1

#define NRFX_WDT_CONFIG_RELOAD_VALUE 2000
#define NRFX_WDT_DEAFULT_CONFIG                                           \
{                                                                         \
    .behaviour          = (nrf_wdt_behaviour_t)NRFX_WDT_CONFIG_BEHAVIOUR, \
    .reload_value       = NRFX_WDT_CONFIG_RELOAD_VALUE,                   \
    NRFX_WDT_IRQ_CONFIG                                                   \
}

#define NRF_DRV_WDT_DEAFULT_CONFIG  NRFX_WDT_DEAFULT_CONFIG

int main(void)
{
    ~~~~ 중략 ~~~~
     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();
    ~~~~ 중략 ~~~~
}

void nrfx_wdt_enable(void)
{
    nrf_wdt_int_enable(NRF_WDT_INT_TIMEOUT_MASK);
    nrf_wdt_task_trigger(NRF_WDT_TASK_START);
    m_state = NRFX_DRV_STATE_POWERED_ON;
}
#define NRF_WDT_BASE                0x40010000UL
#define NRF_WDT                     ((NRF_WDT_Type*)           NRF_WDT_BASE)

/**
  * @brief Watchdog Timer (WDT)
  */

typedef struct {                                /*!< (@ 0x40010000) WDT Structure                                              */
  __OM  uint32_t  TASKS_START;                  /*!< (@ 0x00000000) Start the watchdog                                         */
  __IM  uint32_t  RESERVED[63];
  __IOM uint32_t  EVENTS_TIMEOUT;               /*!< (@ 0x00000100) Watchdog timeout                                           */
  __IM  uint32_t  RESERVED1[128];
  __IOM uint32_t  INTENSET;                     /*!< (@ 0x00000304) Enable interrupt                                           */
  __IOM uint32_t  INTENCLR;                     /*!< (@ 0x00000308) Disable interrupt                                          */
  __IM  uint32_t  RESERVED2[61];
  __IM  uint32_t  RUNSTATUS;                    /*!< (@ 0x00000400) Run status                                                 */
  __IM  uint32_t  REQSTATUS;                    /*!< (@ 0x00000404) Request status                                             */
  __IM  uint32_t  RESERVED3[63];
  __IOM uint32_t  CRV;                          /*!< (@ 0x00000504) Counter reload value                                       */
  __IOM uint32_t  RREN;                         /*!< (@ 0x00000508) Enable register for reload request registers               */
  __IOM uint32_t  CONFIG;                       /*!< (@ 0x0000050C) Configuration register                                     */
  __IM  uint32_t  RESERVED4[60];
  __OM  uint32_t  RR[8];                        /*!< (@ 0x00000600) Description collection[0]: Reload request 0                */
} NRF_WDT_Type;                                 /*!< Size = 1568 (0x620)      

__STATIC_INLINE void nrf_wdt_int_enable(uint32_t int_mask)
{
    NRF_WDT->INTENSET = int_mask;
}

  

datasheet  Watchdog 베이스 주소및 registers

 

 

 

 

 

  3-3> LED 초기화 및 200msec 간격으로 모든 LED 켜기

int main(void)
{
    ~~~~ 중략 ~~~~
    bsp_board_init(BSP_INIT_LEDS);
    for (uint32_t i = 0; i < LEDS_NUMBER; i++)
    {   nrf_delay_ms(200);
        bsp_board_led_on(i);
    }
    ~~~~ 중략 ~~~~

}
void bsp_board_led_on(uint32_t led_idx)
{
    nrf_gpio_pin_write(m_board_led_list[led_idx], LEDS_ACTIVE_STATE ? 1 : 0);
}

void bsp_board_init(uint32_t init_flags)
{
     bsp_board_leds_init();
}

void bsp_board_leds_init(void)
{
    uint32_t i;
    for (i = 0; i < LEDS_NUMBER; ++i)
    {
        nrf_gpio_cfg_output(m_board_led_list[i]);
    }
    bsp_board_leds_off();
}

 

 

 

4> 참조 영상

   : button1 을 누르면 watchdog 이 초기화 되고 2초동안 누르지 않으면 watchdog reset 이 발생합니다.

 

 

4> Nordic Document

https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.1.0/nrf_dev_wdt_example.html

 

nRF5 SDK v17.1.0: WDT Example

The WDT Example demonstrates the usage of the watchdog peripherals. When the application starts, all LEDs are turned on one after the other. When all LEDs are lit, user input ("feeding the watchdog") is required to avoid system reset. Pressing Button 1 tri

infocenter.nordicsemi.com

 

그럼 수고하세요.

 

반응형