3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

nRF52でPPIを使ってGPIOTE EventでTIMER Taskを起動する

Posted at

GPIOTE EventでTIMER Taskを起動する

Nordic SDK 14.20のサンプルプロジェクトpin_change_intとppiを参考に
PPIを使って、GPIOTEのIO変化を契機にTIMERを開始するサンプルを書いてみた。
以下にコードと各関数の処理概要を記す。

input_sampling_event_init関数では、GPIOTEとTIMER、PPIの初期設定を行う。
GPIOTEは、PIN_IN(DK Boardのボタン1)のH→L変化を捉えて、in_pin_handlerが呼ばれる。
TIMER0は、1ms毎にtimer_handlerが呼ばれる。
PPIで、GPIOTEとTIMER0を連携する。

input_sampling_event_enable関数では、input_sampling_event_init関数で設定したPPIを有効化する。これで、GPIOTEによるEventでTIMER0のTaskが起動する。
なお、今サンプルでは、TIEMR0のTaskは開始するが停止については書いていない。

main関数では、input_sampling_event_init関数とinput_sampling_event_enable関数を呼び、空ループに入る。

main.c
#include <stdbool.h>
#include "nrf.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "app_error.h"
#include "boards.h"

#ifdef BSP_BUTTON_0
    #define PIN_IN BSP_BUTTON_0
#endif
#ifndef PIN_IN
    #error "Please indicate input pin"
#endif

#ifdef BSP_LED_0
    #define PIN_OUT BSP_LED_0
#endif
#ifndef PIN_OUT
    #error "Please indicate output pin"
#endif


static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
static nrf_ppi_channel_t     m_ppi_channel;

static uint32_t m_counter = 0;


void timer_handler(nrf_timer_event_t event_type, void * p_context)
{
    m_counter++;
}


void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    m_counter = 0;
}


static void input_sampling_event_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    in_config.pull = NRF_GPIO_PIN_PULLUP;
    in_config.hi_accuracy = false;
    err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, in_pin_handler);
    APP_ERROR_CHECK(err_code);

    
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;

    err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event every 1ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 1);
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   true);

    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    uint32_t gpiote_in_event_addr = nrf_drv_gpiote_in_event_addr_get(PIN_IN);
    uint32_t timer_task_addr      = nrf_drv_timer_task_address_get(&m_timer, NRF_TIMER_TASK_START);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          gpiote_in_event_addr,
                                          timer_task_addr);
    APP_ERROR_CHECK(err_code);


    nrf_drv_gpiote_in_event_enable(PIN_IN, true);

}


void input_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);

    APP_ERROR_CHECK(err_code);
}


/**
 * @brief Function for application main entry.
 */
int main(void)
{
    input_sampling_event_init();
    input_sampling_event_enable();

    while (true)
    {
        // Do nothing.
    }
}


/** @} */

実は少し前、pin_change_intを参考に、IO変化のコールバック関数内でTIMERの開始を行うコードを書いていたのだが、ふとPPIを使っても出来ると思ったのでやってみた。
積極的にPPI(ハードウェア処理)に任せていくのがいいのだと思う。

応用すれば、GPIOTE(Event)→PPI→TIMER(Task/Event)→PPI→SAADC(Task)
のような数珠繋ぎにして、スイッチを押したら定期ADサンプリングを開始
するような書き方も出来る。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?