YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
timer_rp2350.cpp
1// ---------------------------------------------
2// This file is part of
3// _ _ __ _ _ __ __
4// ( \/ ) /__\ ( )_( ) /__\ ( )
5// \ / /(__)\ ) _ ( /(__)\ )(__
6// (__)(__)(__)(_) (_)(__)(__)(____)
7//
8// Yet Another HW Abstraction Library
9// Copyright (C) Andreas Terstegge
10// BSD Licensed (see file LICENSE)
11//
12// ---------------------------------------------
13//
14// Timer implementation for RP2350.
15//
16#include "timer_rp2350.h"
17#include "system_rp2350.h"
18#include <cassert>
19
20using namespace _TIMER1_;
21using namespace _RESETS_;
22
23timer_rp2350 * timer_rp2350::_timerinst[8];
24function<void()> timer_rp2350::_callback[8];
25
26timer_rp2350::timer_rp2350(int8_t index) {
27 // Locate a free slot if no index was given
28 if (index == -1) {
29 // Find next free timer
30 for (index=0; index < 7; ++index) {
31 if (!_timerinst[index]) break;
32 }
33 }
34 assert(index < 8);
35 assert(_timerinst[index] == nullptr);
36
37 // Initialize members
38 _index = index;
39 _mask = 1 << (index % 4);
40 _mode = TIMER::ONE_SHOT;
41 _period = 0;
42
43 // Set the timer pointer and enable IRQs
44 if (index < 4) {
45 _timer = &TIMER0;
46 _alarm = &(TIMER0.ALARM[index]);
47 TIMER0_SET.INTE = _mask;
48 } else {
49 _timer = &TIMER1;
50 _alarm = &(TIMER1.ALARM[index-4]);
51 TIMER1_SET.INTE = _mask;
52 }
53 // Register timer instance pointer
54 _timerinst[index] = this;
55 // enable IRQ in NVIC. Default priority is 0 (highest).
56 NVIC_EnableIRQ(IRQn_Type(TIMER0_IRQ_0_IRQn + index));
57}
58
59timer_rp2350::~timer_rp2350() {
60 if (_timer->ARMED & _mask) {
61 _timer->ARMED = _mask;
62 }
63 _timerinst[_index] = nullptr;
64}
65
66void timer_rp2350::setPeriod(uint32_t us, TIMER::timer_mode mode) {
67 _period = us * timer_ticks_per_us;
68 _mode = mode;
69}
70
71void timer_rp2350::setPeriod_ns(uint32_t ns, TIMER::timer_mode mode) {
72 _period = (ns * timer_ticks_per_us) / 1000;
73 _mode = mode;
74}
75
76uint32_t timer_rp2350::getPeriod() {
77 return _period / timer_ticks_per_us;
78}
79
80void timer_rp2350::setCallback(function<void()> f) {
81 timer_rp2350::_callback[_index] = f;
82}
83
84void timer_rp2350::start() {
85 *_alarm = _timer->TIMERAWL + _period;
86}
87
88void timer_rp2350::stop() {
89 if (isRunning()) {
90 // Clear 'armed'-bit
91 _timer->ARMED = _mask;
92 }
93}
94
95bool timer_rp2350::isRunning() {
96 return _timer->ARMED & _mask;
97}
98
99void timer_rp2350::reset() {
100 // If timer is running, immediately
101 // trigger a re-start.
102 if (isRunning()) start();
103}
104
105void timer_rp2350::irqHandler() {
106 // Clear interrupt
107 _timer->INTR = _mask;
108 // Re-trigger timer if periodic
109 if (_mode == TIMER::PERIODIC) {
110 *_alarm += _period;
111 }
112 // Call the user-provided handler
113 _callback[_index]();
114}
115
116// Interrupt handler
118extern "C" {
119
120void TIMER0_IRQ_0_Handler(void) {
121 timer_rp2350::_timerinst[0]->irqHandler();
122}
123
124void TIMER0_IRQ_1_Handler(void) {
125 timer_rp2350::_timerinst[1]->irqHandler();
126}
127
128void TIMER0_IRQ_2_Handler(void) {
129 timer_rp2350::_timerinst[2]->irqHandler();
130}
131
132void TIMER0_IRQ_3_Handler(void) {
133 timer_rp2350::_timerinst[3]->irqHandler();
134}
135
136void TIMER1_IRQ_0_Handler(void) {
137 timer_rp2350::_timerinst[4]->irqHandler();
138}
139
140void TIMER1_IRQ_1_Handler(void) {
141 timer_rp2350::_timerinst[5]->irqHandler();
142}
143
144void TIMER1_IRQ_2_Handler(void) {
145 timer_rp2350::_timerinst[6]->irqHandler();
146}
147
148void TIMER1_IRQ_3_Handler(void) {
149 timer_rp2350::_timerinst[7]->irqHandler();
150}
151
152} // extern "C"