Pico GPS Teseo I2C
Loading...
Searching...
No Matches
pico_divider_nesting_test.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <math.h>
10#include "pico/stdlib.h"
11#include "hardware/dma.h"
12#include "hardware/irq.h"
13#include "hardware/sync.h"
14
15volatile bool failed;
16volatile uint32_t count[3];
17volatile bool done;
18
19#define FAILED() ({ failed = true; })
20//#define FAILED() ({ failed = true; __breakpoint(); })
21
22//#define DOUBLE_ONLY 1
23
25 count[0]++;
26 static int z;
27#if !DOUBLE_ONLY
28 for (int i=0; i<100;i++) {
29 z += 23;
30 int a = z / 7;
31 int b = z % 7;
32 if (z != a * 7 + b) {
33 FAILED();
34 }
35 a = z / -7;
36 b = z % -7;
37 if (z != a * -7 + b) {
38 FAILED();
39 }
40 }
41#else
42 for(int i=0;i<10;i++) {
43#endif
44 float fz = (float) z;
45 float fa = fz / 11.0f;
46// float fb = fmodf(fz, 11.0f);
47// if (fabs(fz - (fa * 11.0f + fb)) > 1e-9f) {
48// FAILED();
49// }
50 union {
51 float f;
52 uint32_t i;
53 } fi, fi2;
54 fi.f = fabsf(fz - fa * 11.0f);
55 // make a float which is close to 1ulp
56 fi2.i = fi.i & 0x7f800000u;
57 fi2.i++;
58 if (fi.f > fi2.f) {
59 FAILED();
60 }
61 double dz = z;
62 double da = dz / 11.0;
63// double db = fmod(dz, 11.0);
64// if (abs(dz - (da * 11.0 + db)) > 1e-9) {
65// FAILED();
66// }
67 if (fabs(dz - da * 11.0) > 1e-6f) {
68 FAILED();
69 }
70#if DOUBLE_ONLY
71 }
72#endif
73 return !done;
74}
75
77 static uint32_t word[2];
78 assert(ch < 2);
79 dma_channel_config c = dma_channel_get_default_config(ch);
80 // todo remove this; landing in a separate PR
81#ifndef DREQ_DMA_TIMER0
82#define DREQ_DMA_TIMER0 0x3b
83#endif
84 channel_config_set_dreq(&c, DREQ_DMA_TIMER0);
85 dma_channel_configure(ch, &c, &word[ch], &word[ch], 513 + ch * 23, true);
86}
87
88double d0c, d0s, d0t, dz;
89float f0c, f0s, f0t, fz;
90
91double flarn = 25.5;
92double zzd = 13.3;
93
95 count[1]++;
96 dma_hw->ints0 |= 1u;
97 static uint z;
98 static uint dz;
99 for (int i=0; i<80;i++) {
100#if !DOUBLE_ONLY
101 z += 31;
102 uint a = z / 11;
103 uint b = z % 11;
104 if (z != a * 11 + b) {
105 FAILED();
106 }
107#else
108 zzd += flarn/(flarn + 1.35);
109 break;
110#endif
111 }
112 if (done) dma_channel_abort(0);
113 else do_dma_start(0);
114}
115
117 static uint z;
118 dma_hw->ints1 |= 2u;
119 count[2]++;
120 for (int i=0; i<130;i++) {
121#if !DOUBLE_ONLY
122 z += 47;
123 uint a = z / -13;
124 uint b = z % -13;
125 if (z != a * -13 + b) {
126 FAILED();
127 }
128 static uint64_t z64;
129 z64 -= 47;
130 uint64_t a64 = z64 / -13;
131 uint64_t b64 = z64 % -13;
132 if (z64 != a64 * -13 + b64) {
133 FAILED();
134 }
135#else
136 zzd += flarn/123.3;
137 break;
138#endif
139 }
140
141 if (done) dma_channel_abort(1);
142 else do_dma_start(1);
143}
144
146 uint z = 0;
147
148 // We have 3 different IRQ handlers, one for timer, two for DMA completion (on DMA_IRQ0/1)
149 // thus we expect re-entrancy even between IRQs
150 //
151 // They all busily make use of the dividers, to expose any issues with nested use
152
154 add_repeating_timer_us(929, timer_callback, NULL, &timer);
157
158 dma_set_irq0_channel_mask_enabled(1u, true);
159 dma_set_irq1_channel_mask_enabled(2u, true);
160 dma_hw->timer[0] = (1 << 16) | 32; // run at 1/32 system clock
161
164 do_dma_start(0);
165 do_dma_start(1);
166 absolute_time_t end = delayed_by_ms(get_absolute_time(), 10000);
167 int count_local=0;
168 while (!time_reached(end)) {
169 for(uint i=0;i<100;i++) {
170 z += 31;
171 uint a = z / 11;
172 uint b = z % 11;
173 if (z != a * 11 + b) {
174 FAILED();
175 }
176 int zz = (int)z;
177 int aa = zz / -11;
178 int bb = zz % -11;
179 if (zz != aa * -11 + bb) {
180 FAILED();
181 }
182 aa = -zz / -11;
183 bb = -zz % -11;
184 if (-zz != aa * -11 + bb) {
185 FAILED();
186 }
187 aa = -zz / 11;
188 bb = -zz % 11;
189 if (-zz != aa * 11 + bb) {
190 FAILED();
191 }
192 a = 0xffffffffu / 11;
193 b = 0xffffffffu % 11;
194 if (0xffffffffu != a * 11 + b) {
195 FAILED();
196 }
197 static uint64_t z64;
198 z64 -= 47;
199 uint64_t a64 = z64 / -13635;
200 uint64_t b64 = z64 % -13635;
201 if (z64 != a64 * -13635 + b64) {
202 FAILED();
203 }
204 // specifically check 64/32 divide
205 static uint64_t c64 = 0x13ffffffffull;
206 static uint32_t cd = 1;
207 a64 = c64 / cd;
208 b64 = c64 % cd;
209 if (c64 != a64 * cd + b64) {
210 FAILED();
211 }
212 cd++;
213 static float zf = 1.f;
214 float ff = zf / -13635.f;
215 if (fabsf(zf - ff * -13635.f) > 1e-2f) {
216 FAILED();
217 }
218 zf += 0.0331f;
219 z += (int)ff;
220 static double zd = 1.0;
221 double dd = zd / -13635.0;
222 if (fabs(zd - dd * -13635.0) > 1e-6) {
223 FAILED();
224 }
225 zd += 0.331;
226 z += (int)dd;
227
228 }
229 // todo this still seems broken on RP2350
230#if PICO_RP2040
231 // these use the divider
232 for(uint i=0;i<=100;i+=20) {
233 // both in and out bootrom range (we perform mod in wrapper code if necessarry)
234 f0t = tanf(i * 50);
235 f0c = cosf(i * 50);
236 f0s = sinf(i * 50);
237 d0t = tan(i * 1000);
238 d0c = cos(i * 1000);
239 d0s = sin(i * 1000);
240 }
241#endif
242 count_local++;
243 }
244 done = true;
246 printf("%d: %d %d %d\n", count_local, (int)count[0], (int)count[1], (int)count[2]);
247 printf("%d\n", z);
248 // make sure all the IRQs ran
249 if (!(count_local && count[0] && count[1] && count[2])) {
250 printf("DID NOT RUN\n");
251 exit(1);
252 }
253 if (failed) {
254 printf("FAILED\n");
255 exit(1);
256 }
257}
258
259int main() {
260#ifndef uart_default
261#warning test/pico_divider requires a default uart
262#else
263 stdio_init_all();
264#endif
265 test_nesting();
266 printf("PASSED\n");
267 return 0;
268}
void uint32_t
Definition bootrom.h:36
#define assert(expr)
Definition debug.h:68
float float
Definition call_apsr.h:35
int t
Definition ctypes.h:77
#define NULL
Definition oi_stddefs.h:55
int main()
getting-started Application entry point.
void irq_set_enabled(uint num, bool enabled)
Enable or disable a specific interrupt on the executing core.
Definition irq.c:25
void irq_set_exclusive_handler(uint num, irq_handler_t handler)
Set an exclusive interrupt handler for an interrupt on the executing core.
Definition irq.c:60
@ DMA_IRQ_0
Select DMA's IRQ 0 output.
Definition intctrl.h:65
@ DMA_IRQ_1
Select DMA's IRQ 1 output.
Definition intctrl.h:66
bool cancel_repeating_timer(repeating_timer_t *timer)
Cancel a repeating timer.
Definition time.c:511
uint64_t absolute_time_t
An opaque 64 bit timestamp in microseconds.
Definition types.h:43
bool time_reached(absolute_time_t t)
Definition timer.c:62
btstack_timer_source_t timer
volatile uint32_t aa
Definition ll_sx1280.c:276
#define fabsf
Definition math.h:30
float32x2_t float32x2_t c
Definition neon.h:216
int16x4_t a
Definition neon.h:62
r e[0]
Definition neon.h:74
void exit(int status)
volatile bool failed
volatile uint32_t count[3]
#define DREQ_DMA_TIMER0
#define FAILED()
void test_nesting()
void test_irq_handler0()
void test_irq_handler1()
bool timer_callback(repeating_timer_t *t)
void do_dma_start(uint ch)
double bb
int16x2_t b
Definition simd32.h:38
int i
Definition sqrt_test.cpp:12
unsigned int uint
Definition types.h:18
struct repeating_timer repeating_timer_t
Definition time.h:721
#define dma_hw
Definition dma.h:235
#define printf(format,...)
Definition sx1280-hal.c:23
tu_fifo_t * ff
Definition test_fifo.c:37