1 /*
2 * Copyright (c) 2019 - 2020, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <nrfx.h>
33
34 #if NRFX_CHECK(NRFX_EGU_ENABLED)
35
36 #if !(NRFX_CHECK(NRFX_EGU0_ENABLED) || \
37 NRFX_CHECK(NRFX_EGU1_ENABLED) || \
38 NRFX_CHECK(NRFX_EGU2_ENABLED) || \
39 NRFX_CHECK(NRFX_EGU3_ENABLED) || \
40 NRFX_CHECK(NRFX_EGU4_ENABLED) || \
41 NRFX_CHECK(NRFX_EGU5_ENABLED))
42 #error "No enabled EGU instances. Check <nrfx_config.h>."
43 #endif
44
45 #if NRFX_CHECK(NRFX_EGU0_ENABLED) && ((1 << 0) & NRFX_EGUS_USED)
46 #error "EGU instance 0 is reserved for use outside of nrfx."
47 #endif
48 #if NRFX_CHECK(NRFX_EGU1_ENABLED) && ((1 << 1) & NRFX_EGUS_USED)
49 #error "EGU instance 1 is reserved for use outside of nrfx."
50 #endif
51 #if NRFX_CHECK(NRFX_EGU2_ENABLED) && ((1 << 2) & NRFX_EGUS_USED)
52 #error "EGU instance 2 is reserved for use outside of nrfx."
53 #endif
54 #if NRFX_CHECK(NRFX_EGU3_ENABLED) && ((1 << 3) & NRFX_EGUS_USED)
55 #error "EGU instance 3 is reserved for use outside of nrfx."
56 #endif
57 #if NRFX_CHECK(NRFX_EGU4_ENABLED) && ((1 << 4) & NRFX_EGUS_USED)
58 #error "EGU instance 4 is reserved for use outside of nrfx."
59 #endif
60 #if NRFX_CHECK(NRFX_EGU5_ENABLED) && ((1 << 5) & NRFX_EGUS_USED)
61 #error "EGU instance 5 is reserved for use outside of nrfx."
62 #endif
63
64 #include <nrfx_egu.h>
65
66 typedef struct
67 {
68 nrfx_egu_event_handler_t handler;
69 void * p_context;
70 nrfx_drv_state_t state;
71 } egu_control_block_t;
72
73 static egu_control_block_t m_cb[NRFX_EGU_ENABLED_COUNT];
74
egu_event_mask_get_and_clear(NRF_EGU_Type * p_reg,uint32_t int_mask)75 static uint32_t egu_event_mask_get_and_clear(NRF_EGU_Type * p_reg, uint32_t int_mask)
76 {
77 uint32_t event_mask = 0;
78 while (int_mask)
79 {
80 uint8_t event_idx = __CLZ(__RBIT(int_mask));
81 int_mask &= ~(1uL << event_idx);
82
83 nrf_egu_event_t event = nrf_egu_triggered_event_get(event_idx);
84 if (nrf_egu_event_check(p_reg, event))
85 {
86 nrf_egu_event_clear(p_reg, event);
87 event_mask |= (1uL << event_idx);
88 }
89 }
90 return event_mask;
91 }
92
nrfx_egu_init(nrfx_egu_t const * p_instance,uint8_t interrupt_priority,nrfx_egu_event_handler_t event_handler,void * p_context)93 nrfx_err_t nrfx_egu_init(nrfx_egu_t const * p_instance,
94 uint8_t interrupt_priority,
95 nrfx_egu_event_handler_t event_handler,
96 void * p_context)
97 {
98 NRFX_ASSERT(p_instance);
99
100 egu_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
101
102 if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
103 {
104 return NRFX_ERROR_INVALID_STATE;
105 }
106
107 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
108 p_cb->p_context = p_context;
109 p_cb->handler = event_handler;
110 if (event_handler)
111 {
112 NRFX_IRQ_ENABLE(nrfx_get_irq_number(p_instance->p_reg));
113 NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(p_instance->p_reg), interrupt_priority);
114 }
115
116 return NRFX_SUCCESS;
117 }
118
nrfx_egu_int_enable(nrfx_egu_t const * p_instance,uint32_t mask)119 void nrfx_egu_int_enable(nrfx_egu_t const * p_instance, uint32_t mask)
120 {
121 NRFX_ASSERT(p_instance);
122 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
123 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].handler);
124
125 (void)egu_event_mask_get_and_clear(p_instance->p_reg, mask);
126 nrf_egu_int_enable(p_instance->p_reg, mask);
127 }
128
nrfx_egu_int_disable(nrfx_egu_t const * p_instance,uint32_t mask)129 void nrfx_egu_int_disable(nrfx_egu_t const * p_instance, uint32_t mask)
130 {
131 NRFX_ASSERT(p_instance);
132 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
133
134 nrf_egu_int_disable(p_instance->p_reg, mask);
135 }
136
nrfx_egu_trigger(nrfx_egu_t const * p_instance,uint8_t event_idx)137 void nrfx_egu_trigger(nrfx_egu_t const * p_instance, uint8_t event_idx)
138 {
139 NRFX_ASSERT(p_instance);
140 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
141 NRFX_ASSERT(event_idx < nrf_egu_channel_count(p_instance->p_reg));
142
143 nrf_egu_task_trigger(p_instance->p_reg, nrf_egu_trigger_task_get(event_idx));
144 }
145
nrfx_egu_uninit(nrfx_egu_t const * p_instance)146 void nrfx_egu_uninit(nrfx_egu_t const * p_instance)
147 {
148 NRFX_ASSERT(p_instance);
149
150 egu_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
151
152 nrf_egu_int_disable(p_instance->p_reg, ~0uL);
153 NRFX_IRQ_DISABLE(nrfx_get_irq_number(p_instance->p_reg));
154
155 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
156 }
157
egu_irq_handler(NRF_EGU_Type * p_reg,egu_control_block_t * p_cb)158 static void egu_irq_handler(NRF_EGU_Type * p_reg, egu_control_block_t * p_cb)
159 {
160 uint32_t int_mask = nrf_egu_int_enable_check(p_reg, ~0uL);
161
162 /* Check (and clear) only the events that are set to generate interrupts.
163 Leave the other ones untouched. */
164 uint32_t event_mask = egu_event_mask_get_and_clear(p_reg, int_mask);
165 while (event_mask)
166 {
167 uint8_t event_idx = __CLZ(__RBIT(event_mask));
168 event_mask &= ~(1uL << event_idx);
169 p_cb->handler(event_idx, p_cb->p_context);
170 }
171 }
172
173 #if NRFX_CHECK(NRFX_EGU0_ENABLED)
nrfx_egu_0_irq_handler(void)174 void nrfx_egu_0_irq_handler(void)
175 {
176 egu_irq_handler(NRF_EGU0, &m_cb[NRFX_EGU0_INST_IDX]);
177 }
178 #endif
179
180 #if NRFX_CHECK(NRFX_EGU1_ENABLED)
nrfx_egu_1_irq_handler(void)181 void nrfx_egu_1_irq_handler(void)
182 {
183 egu_irq_handler(NRF_EGU1, &m_cb[NRFX_EGU1_INST_IDX]);
184 }
185 #endif
186
187 #if NRFX_CHECK(NRFX_EGU2_ENABLED)
nrfx_egu_2_irq_handler(void)188 void nrfx_egu_2_irq_handler(void)
189 {
190 egu_irq_handler(NRF_EGU2, &m_cb[NRFX_EGU2_INST_IDX]);
191 }
192 #endif
193
194 #if NRFX_CHECK(NRFX_EGU3_ENABLED)
nrfx_egu_3_irq_handler(void)195 void nrfx_egu_3_irq_handler(void)
196 {
197 egu_irq_handler(NRF_EGU3, &m_cb[NRFX_EGU3_INST_IDX]);
198 }
199 #endif
200
201 #if NRFX_CHECK(NRFX_EGU4_ENABLED)
nrfx_egu_4_irq_handler(void)202 void nrfx_egu_4_irq_handler(void)
203 {
204 egu_irq_handler(NRF_EGU4, &m_cb[NRFX_EGU4_INST_IDX]);
205 }
206 #endif
207
208 #if NRFX_CHECK(NRFX_EGU5_ENABLED)
nrfx_egu_5_irq_handler(void)209 void nrfx_egu_5_irq_handler(void)
210 {
211 egu_irq_handler(NRF_EGU5, &m_cb[NRFX_EGU5_INST_IDX]);
212 }
213 #endif
214
215 #endif // NRFX_CHECK(NRFX_EGU_ENABLED)
216