以前の記事
以前にもタイマーに関連する記事を書きました。
ちなみにこの時にはnRFXタイマーは使えないと書いています。
nRFXタイマーは使える
でもふと疑問に思ったのです。その後PPIを使えるようにしたのですが、nRFXタイマーが使えないとしたらPPIをどうやって使えばいいんだ・・・?もちろんPPIはタイマー以外のペリフェラル結合でも使えますが、PPIで一番使いたいのはタイマーじゃないのかな、と。
以前はIRQ_CONNECTが足りていなかった
当時、何がダメでnRFXタイマーが動かないと判断したのか、実は覚えていません。調べた順番の前後も覚えていないのでもしかしたらタイマーの前にTWIMやSPIMを動かしているかも知れないのですが、当時足りていなかったのはおそらくIRQ_CONNECTではないかと思います。
改めて動作確認
せっかく動作確認するのだからタイマー0から4まで全部動かしてみようと思います。
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/zephyr.h>
#include <nrfx_timer.h>
static const nrfx_timer_t m_timer0 = NRFX_TIMER_INSTANCE(0);
static const nrfx_timer_t m_timer1 = NRFX_TIMER_INSTANCE(1);
static const nrfx_timer_t m_timer2 = NRFX_TIMER_INSTANCE(2);
static const nrfx_timer_t m_timer3 = NRFX_TIMER_INSTANCE(3);
static const nrfx_timer_t m_timer4 = NRFX_TIMER_INSTANCE(4);
static void timer_event_handler(nrf_timer_event_t event_type, void * context)
{
switch (event_type)
{
case NRF_TIMER_EVENT_COMPARE0:
printk("timer 0\n");
break;
case NRF_TIMER_EVENT_COMPARE1:
printk("timer 1\n");
break;
case NRF_TIMER_EVENT_COMPARE2:
printk("timer 2\n");
break;
case NRF_TIMER_EVENT_COMPARE3:
printk("timer 3\n");
break;
case NRF_TIMER_EVENT_COMPARE4:
printk("timer 4\n");
break;
default:
printk("timer Other\n");
break;
}
}
void main(void)
{
nrfx_err_t err;
uint32_t time_ticks;
nrfx_timer_config_t timer_cfg = {
.frequency = NRF_TIMER_FREQ_16MHz,
.mode = NRF_TIMER_MODE_TIMER,
.bit_width = NRF_TIMER_BIT_WIDTH_32,
};
// Configure timer driver
err = nrfx_timer_init(&m_timer0, &timer_cfg, timer_event_handler);
IRQ_CONNECT(TIMER0_IRQn, IRQ_PRIO_LOWEST, nrfx_timer_0_irq_handler, NULL, 0);
time_ticks = nrfx_timer_ms_to_ticks(&m_timer0, 1000);
nrfx_timer_extended_compare(&m_timer0, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
err = nrfx_timer_init(&m_timer1, &timer_cfg, timer_event_handler);
IRQ_CONNECT(TIMER1_IRQn, IRQ_PRIO_LOWEST, nrfx_timer_1_irq_handler, NULL, 0);
time_ticks = nrfx_timer_ms_to_ticks(&m_timer1, 2000);
nrfx_timer_extended_compare(&m_timer1, NRF_TIMER_CC_CHANNEL1, time_ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);
err = nrfx_timer_init(&m_timer2, &timer_cfg, timer_event_handler);
IRQ_CONNECT(TIMER2_IRQn, IRQ_PRIO_LOWEST, nrfx_timer_2_irq_handler, NULL, 0);
time_ticks = nrfx_timer_ms_to_ticks(&m_timer2, 3000);
nrfx_timer_extended_compare(&m_timer2, NRF_TIMER_CC_CHANNEL2, time_ticks, NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK, true);
err = nrfx_timer_init(&m_timer3, &timer_cfg, timer_event_handler);
IRQ_CONNECT(TIMER3_IRQn, IRQ_PRIO_LOWEST, nrfx_timer_3_irq_handler, NULL, 0);
time_ticks = nrfx_timer_ms_to_ticks(&m_timer3, 4000);
nrfx_timer_extended_compare(&m_timer3, NRF_TIMER_CC_CHANNEL3, time_ticks, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK, true);
err = nrfx_timer_init(&m_timer4, &timer_cfg, timer_event_handler);
IRQ_CONNECT(TIMER4_IRQn, IRQ_PRIO_LOWEST, nrfx_timer_4_irq_handler, NULL, 0);
time_ticks = nrfx_timer_ms_to_ticks(&m_timer4, 5000);
nrfx_timer_extended_compare(&m_timer4, NRF_TIMER_CC_CHANNEL4, time_ticks, NRF_TIMER_SHORT_COMPARE4_CLEAR_MASK, true);
// Enable timer driver
nrfx_timer_enable(&m_timer0);
nrfx_timer_enable(&m_timer1);
nrfx_timer_enable(&m_timer2);
nrfx_timer_enable(&m_timer3);
nrfx_timer_enable(&m_timer4);
}
コンフィギュレーション
CONFIG_NRFX_TIMER0=y
CONFIG_NRFX_TIMER1=y
CONFIG_NRFX_TIMER2=y
CONFIG_NRFX_TIMER3=y
CONFIG_NRFX_TIMER4=y
CONFIG_DEBUG_THREAD_INFO=y
CONFIG_DEBUG_OPTIMIZATIONS=y
余談ですが、VSCodeになってからはprj.confはKconfigの設定画面を使うと楽にできます。
タイマー0も使える
もしかしたらBluetoothを使っていないから解放されているだけかも知れませんが、タイマー0も普通に使えるみたいです。
ていうか、じゃあZephyrのタイムスライスっていったい誰がやっているんでしょう・・・?もしかしてLFCLKベースなのでしょうか?
nRF SDKではAPP TIMERと呼ばれていたタイマーのことです。