|
6 | 6 |
|
7 | 7 | #include <hal/nrf_gpiote.h> |
8 | 8 | #include <nrfx_gpiote.h> |
9 | | -#ifdef DPPI_PRESENT |
10 | | -#include <nrfx_dppi.h> |
11 | | -#endif |
12 | 9 | #include <helpers/nrfx_gppi.h> |
13 | 10 |
|
14 | 11 | #include <debug/ppi_trace.h> |
@@ -54,6 +51,9 @@ typedef struct { |
54 | 51 | uint8_t gpiote_channel; |
55 | 52 | } ppi_trace_gpiote_pin_t; |
56 | 53 |
|
| 54 | +static atomic_t alloc_cnt; |
| 55 | +static uint32_t handle[CONFIG_PPI_TRACE_PIN_CNT]; |
| 56 | + |
57 | 57 | static const nrfx_gpiote_t *get_gpiote(nrfx_gpiote_pin_t pin) |
58 | 58 | { |
59 | 59 | static const nrfx_gpiote_t gpiote[GPIO_COUNT] = { |
@@ -98,174 +98,120 @@ static bool ppi_trace_gpiote_pin_init( |
98 | 98 |
|
99 | 99 | void *ppi_trace_config(uint32_t pin, uint32_t evt) |
100 | 100 | { |
101 | | - uint8_t gppi_ch = UINT8_MAX; |
| 101 | + uint32_t idx = atomic_inc(&alloc_cnt); |
| 102 | + nrfx_gppi_handle_t *handle = (nrfx_gppi_handle_t *)&handle[idx]; |
| 103 | + ppi_trace_gpiote_pin_t ppi_trace_gpiote_pin = {}; |
102 | 104 |
|
103 | | - if (NRFX_SUCCESS != nrfx_gppi_channel_alloc(&gppi_ch)) { |
104 | | - LOG_ERR("Failed to allocate GPPI channel."); |
| 105 | + /* All slots taken. */ |
| 106 | + if (alloc_cnt > CONFIG_PPI_TRACE_PIN_CNT) { |
105 | 107 | return NULL; |
106 | 108 | } |
107 | 109 |
|
108 | | - ppi_trace_gpiote_pin_t ppi_trace_gpiote_pin = {}; |
109 | | - |
110 | 110 | if (!ppi_trace_gpiote_pin_init(&ppi_trace_gpiote_pin, pin)) { |
111 | | - nrfx_gppi_channel_free(gppi_ch); |
112 | 111 | return NULL; |
113 | 112 | } |
114 | 113 |
|
115 | 114 | uint32_t tep = nrf_gpiote_task_address_get(ppi_trace_gpiote_pin.gpiote->p_reg, |
116 | 115 | nrf_gpiote_out_task_get(ppi_trace_gpiote_pin.gpiote_channel)); |
117 | | - nrfx_gppi_channel_endpoints_setup(gppi_ch, evt, tep); |
118 | 116 |
|
119 | | - return HANDLE_ENCODE(gppi_ch); |
| 117 | + if (nrfx_gppi_conn_alloc(evt, tep, handle) < 0) { |
| 118 | + LOG_ERR("Failed to allocate GPPI channel."); |
| 119 | + return NULL; |
| 120 | + } |
| 121 | + return handle; |
120 | 122 | } |
121 | 123 |
|
122 | 124 | void *ppi_trace_pair_config(uint32_t pin, uint32_t start_evt, uint32_t stop_evt) |
123 | 125 | { |
| 126 | + uint32_t idx = atomic_add(&alloc_cnt, 2); |
| 127 | + nrfx_gppi_handle_t *handle1 = (nrfx_gppi_handle_t *)&handle[idx]; |
| 128 | + nrfx_gppi_handle_t *handle2 = (nrfx_gppi_handle_t *)&handle[idx + 1]; |
| 129 | + |
| 130 | + /* All slots taken. */ |
| 131 | + if (alloc_cnt > CONFIG_PPI_TRACE_PIN_CNT) { |
| 132 | + return NULL; |
| 133 | + } |
| 134 | + |
124 | 135 | #if !defined(GPIOTE_FEATURE_SET_PRESENT) || \ |
125 | 136 | !defined(GPIOTE_FEATURE_CLR_PRESENT) |
126 | 137 | __ASSERT(0, "Function not supported on this platform."); |
127 | 138 | return NULL; |
128 | 139 | #else |
129 | | - uint8_t gppi_ch_start_evt = UINT8_MAX; |
130 | | - |
131 | | - if (NRFX_SUCCESS != nrfx_gppi_channel_alloc(&gppi_ch_start_evt)) { |
132 | | - LOG_ERR("Failed to allocate GPPI channel."); |
133 | | - return NULL; |
134 | | - } |
135 | | - |
136 | | - uint8_t gppi_ch_stop_evt = UINT8_MAX; |
137 | | - |
138 | | - if (NRFX_SUCCESS != nrfx_gppi_channel_alloc(&gppi_ch_stop_evt)) { |
139 | | - LOG_ERR("Failed to allocate GPPI channel."); |
140 | | - nrfx_gppi_channel_free(gppi_ch_start_evt); |
141 | | - return NULL; |
142 | | - } |
143 | | - |
144 | 140 | ppi_trace_gpiote_pin_t ppi_trace_gpiote_pin = {}; |
145 | 141 |
|
146 | 142 | if (!ppi_trace_gpiote_pin_init(&ppi_trace_gpiote_pin, pin)) { |
147 | | - nrfx_gppi_channel_free(gppi_ch_stop_evt); |
148 | | - nrfx_gppi_channel_free(gppi_ch_start_evt); |
149 | 143 | return NULL; |
150 | 144 | } |
151 | 145 |
|
152 | 146 | uint32_t tep; |
153 | 147 |
|
154 | 148 | tep = nrf_gpiote_task_address_get(ppi_trace_gpiote_pin.gpiote->p_reg, |
155 | 149 | nrf_gpiote_set_task_get(ppi_trace_gpiote_pin.gpiote_channel)); |
156 | | - nrfx_gppi_channel_endpoints_setup(gppi_ch_start_evt, start_evt, tep); |
| 150 | + if (nrfx_gppi_conn_alloc(start_evt, tep, handle1) < 0) { |
| 151 | + LOG_ERR("Failed to allocate GPPI channel."); |
| 152 | + return NULL; |
| 153 | + } |
157 | 154 |
|
158 | 155 | tep = nrf_gpiote_task_address_get(ppi_trace_gpiote_pin.gpiote->p_reg, |
159 | 156 | nrf_gpiote_clr_task_get(ppi_trace_gpiote_pin.gpiote_channel)); |
160 | | - nrfx_gppi_channel_endpoints_setup(gppi_ch_stop_evt, stop_evt, tep); |
161 | | - |
162 | | - return HANDLE_ENCODE(PACK_CHANNELS(gppi_ch_start_evt, gppi_ch_stop_evt)); |
163 | | -#endif |
164 | | -} |
165 | | - |
166 | | -#if defined(DPPI_PRESENT) |
167 | | - |
168 | | -static const nrfx_dppi_t *get_dppic_for_gpiote(const nrfx_gpiote_t *gpiote) |
169 | | -{ |
170 | | - /* The Device Tree does not provide information about the DPPIC controller for which |
171 | | - * the given GPIOTE instance can subscribe to. That's why we need to provide the |
172 | | - * matching DPPIC instance ourselves. |
173 | | - */ |
174 | | - |
175 | | -#if (!defined(DPPIC_COUNT) || (DPPIC_COUNT == 1)) |
176 | | - static const nrfx_dppi_t dppic = NRFX_DPPI_INSTANCE(0); |
177 | | - |
178 | | - return &dppic; |
179 | | -#elif defined(CONFIG_SOC_SERIES_NRF54LX) |
180 | | - if (gpiote->p_reg == NRF_GPIOTE20) { |
181 | | - static const nrfx_dppi_t dppic20 = NRFX_DPPI_INSTANCE(20); |
182 | | - |
183 | | - return &dppic20; |
184 | | - } else if (gpiote->p_reg == NRF_GPIOTE30) { |
185 | | - static const nrfx_dppi_t dppic30 = NRFX_DPPI_INSTANCE(30); |
186 | | - |
187 | | - return &dppic30; |
188 | | - } else { |
| 157 | + if (nrfx_gppi_conn_alloc(stop_evt, tep, handle2) < 0) { |
| 158 | + LOG_ERR("Failed to allocate GPPI channel."); |
189 | 159 | return NULL; |
190 | 160 | } |
191 | | -#else |
192 | | -#error Unsupported SoC series |
193 | | - return NULL; |
| 161 | + |
| 162 | + /* Address to aligned 32 bit variable will always have 0 on last two bits. Last bit is |
| 163 | + * used to indicated that it is a pair. |
| 164 | + */ |
| 165 | + return (void *)((uintptr_t)handle1 | 0x1); |
194 | 166 | #endif |
195 | 167 | } |
196 | 168 |
|
197 | | -int ppi_trace_dppi_ch_trace(uint32_t pin, uint32_t dppi_ch, const nrfx_dppi_t *dppic) |
| 169 | +#if defined(DPPI_PRESENT) |
| 170 | +int ppi_trace_dppi_ch_trace(uint32_t pin, uint32_t dppi_ch, NRF_DPPIC_Type *p_dppi) |
198 | 171 | { |
| 172 | + nrfx_gppi_handle_t handle; |
199 | 173 | ppi_trace_gpiote_pin_t ppi_trace_gpiote_pin = {}; |
200 | 174 |
|
201 | 175 | if (!ppi_trace_gpiote_pin_init(&ppi_trace_gpiote_pin, pin)) { |
202 | 176 | return -ENOMEM; |
203 | 177 | } |
204 | 178 |
|
205 | | - const nrfx_dppi_t *dppic_for_gpiote = get_dppic_for_gpiote(ppi_trace_gpiote_pin.gpiote); |
| 179 | + uint32_t tep = nrf_gpiote_task_address_get(ppi_trace_gpiote_pin.gpiote->p_reg, |
| 180 | + nrf_gpiote_out_task_get(ppi_trace_gpiote_pin.gpiote_channel)); |
| 181 | + uint32_t dst_domain = nrfx_gppi_domain_id_get(ppi_trace_gpiote_pin.gpiote->p_reg); |
| 182 | + nrfx_gppi_resource_t resource = { |
| 183 | + .domain_id = nrfx_gppi_domain_id_get(p_dppi), |
| 184 | + .channel = dppi_ch |
| 185 | + }; |
206 | 186 |
|
207 | | - if (dppic_for_gpiote == NULL) { |
208 | | - LOG_ERR("For given GPIO pin, the GPIOTE has no associated DPPIC."); |
| 187 | + if (nrfx_gppi_ext_conn_alloc(evt, tep, &handle, &resource) < 0) { |
| 188 | + LOG_ERR("Failed to allocate GPPI channel."); |
209 | 189 | return -ENOMEM; |
210 | 190 | } |
| 191 | + nrfx_gppi_conn_enable(handle); |
211 | 192 |
|
212 | | - if (dppic_for_gpiote->p_reg == dppic->p_reg) { |
213 | | - /* The GPIOTE can directly subscribe to DPPI channels of `dppic` */ |
214 | | - nrf_gpiote_subscribe_set(ppi_trace_gpiote_pin.gpiote->p_reg, |
215 | | - nrf_gpiote_out_task_get(ppi_trace_gpiote_pin.gpiote_channel), |
216 | | - dppi_ch); |
217 | | - } else { |
218 | | - /* Let the GPIOTE channel subscribe to a local dppi_channel_for_gpiote of |
219 | | - * ppi_trace_gpiote_pin.dppic first. |
220 | | - */ |
221 | | - uint8_t dppi_channel_for_gpiote = UINT8_MAX; |
222 | | - |
223 | | - if (nrfx_dppi_channel_alloc(dppic_for_gpiote, |
224 | | - &dppi_channel_for_gpiote) != NRFX_SUCCESS) { |
225 | | - return -ENOMEM; |
226 | | - } |
227 | | - |
228 | | - nrf_gpiote_subscribe_set(ppi_trace_gpiote_pin.gpiote->p_reg, |
229 | | - nrf_gpiote_out_task_get(ppi_trace_gpiote_pin.gpiote_channel), |
230 | | - dppi_channel_for_gpiote); |
231 | | - |
232 | | - (void)nrfx_dppi_channel_enable(dppic_for_gpiote, dppi_channel_for_gpiote); |
233 | | - |
234 | | - /* Then, let the dppi_ch channel of dppic controller passed by parameters |
235 | | - * trigger the local dppi_channel_for_gpiote. |
236 | | - */ |
237 | | - uint8_t gppi_ch = UINT8_MAX; |
238 | | - |
239 | | - if (NRFX_SUCCESS != nrfx_gppi_channel_alloc(&gppi_ch)) { |
240 | | - LOG_ERR("Failed to allocate GPPI channel."); |
241 | | - return -ENOMEM; |
242 | | - } |
243 | | - |
244 | | - if (NRFX_SUCCESS != nrfx_gppi_edge_connection_setup(gppi_ch, |
245 | | - dppic, dppi_ch, dppic_for_gpiote, dppi_channel_for_gpiote)) { |
246 | | - LOG_ERR("Failed to setup a GPPI edge connection."); |
247 | | - return -ENOMEM; |
248 | | - } |
249 | | - |
250 | | - nrfx_gppi_channels_enable(1U << gppi_ch); |
251 | | - } |
252 | 193 | return 0; |
253 | 194 | } |
254 | 195 | #endif /* defined(DPPI_PRESENT) */ |
255 | 196 |
|
256 | | -static uint32_t ppi_channel_mask_get(void *handle) |
257 | | -{ |
258 | | - return IS_PAIR(handle) ? |
259 | | - BIT(GET_START_CH(handle)) | BIT(GET_STOP_CH(handle)) : |
260 | | - BIT(GET_CH(handle)); |
261 | | -} |
262 | | - |
263 | 197 | void ppi_trace_enable(void *handle) |
264 | 198 | { |
265 | | - nrfx_gppi_channels_enable(ppi_channel_mask_get(handle)); |
| 199 | + nrfx_gppi_handle_t *handles = (nrfx_gppi_handle_t *)((uintptr_t)handle & 0x1); |
| 200 | + |
| 201 | + nrfx_gppi_conn_enable(handles[0]); |
| 202 | + /* If LSB bit is set it indicates that handle is for pair of connections. */ |
| 203 | + if ((uintptr_t)handle & 0x1) { |
| 204 | + nrfx_gppi_conn_enable(handles[1]); |
| 205 | + } |
266 | 206 | } |
267 | 207 |
|
268 | 208 | void ppi_trace_disable(void *handle) |
269 | 209 | { |
270 | | - nrfx_gppi_channels_disable(ppi_channel_mask_get(handle)); |
| 210 | + nrfx_gppi_handle_t *handles = (nrfx_gppi_handle_t *)((uintptr_t)handle & 0x1); |
| 211 | + |
| 212 | + nrfx_gppi_conn_disable(handles[0]); |
| 213 | + /* If LSB bit is set it indicates that handle is for pair of connections. */ |
| 214 | + if ((uintptr_t)handle & 0x1) { |
| 215 | + nrfx_gppi_conn_disable(handles[1]); |
| 216 | + } |
271 | 217 | } |
0 commit comments