blob: 2d3c0205d63f8818d8962eced57a31da10256080 [file] [log] [blame]
Brian Silverman3240e102019-02-16 18:24:24 -08001#include "aos/time/time.h"
2#include "motors/core/kinetis.h"
3#include "motors/core/time.h"
4#include "motors/peripheral/configuration.h"
5#include "motors/peripheral/uart.h"
6#include "motors/print/print.h"
7#include "motors/util.h"
8
9namespace frc971 {
10namespace jevois {
11namespace {
12
13struct Uarts {
14 Uarts() {
15 DisableInterrupts disable_interrupts;
16 instance = this;
17 }
18 ~Uarts() {
19 DisableInterrupts disable_interrupts;
20 instance = nullptr;
21 }
22
23 void Initialize(int baud_rate) {
24 cam0.Initialize(baud_rate);
25 cam1.Initialize(baud_rate);
26 cam2.Initialize(baud_rate);
27 cam3.Initialize(baud_rate);
28 cam4.Initialize(baud_rate);
29 }
30
31 frc971::teensy::InterruptBufferedUart cam0{&UART1, F_CPU};
32 frc971::teensy::InterruptBufferedUart cam1{&UART0, F_CPU};
33 frc971::teensy::InterruptBufferedUart cam2{&UART2, BUS_CLOCK_FREQUENCY};
34 frc971::teensy::InterruptBufferedUart cam3{&UART3, BUS_CLOCK_FREQUENCY};
35 frc971::teensy::InterruptBufferedUart cam4{&UART4, BUS_CLOCK_FREQUENCY};
36
37 static Uarts *instance;
38};
39
40Uarts *Uarts::instance = nullptr;
41
42extern "C" {
43
44void *__stack_chk_guard = (void *)0x67111971;
45void __stack_chk_fail(void) {
46 while (true) {
47 GPIOC_PSOR = (1 << 5);
48 printf("Stack corruption detected\n");
49 delay(1000);
50 GPIOC_PCOR = (1 << 5);
51 delay(1000);
52 }
53}
54
55extern char *__brkval;
56extern uint32_t __bss_ram_start__[];
57extern uint32_t __heap_start__[];
58extern uint32_t __stack_end__[];
59
60void uart0_status_isr(void) {
61 DisableInterrupts disable_interrupts;
62 Uarts::instance->cam1.HandleInterrupt(disable_interrupts);
63}
64
65void uart1_status_isr(void) {
66 DisableInterrupts disable_interrupts;
67 Uarts::instance->cam0.HandleInterrupt(disable_interrupts);
68}
69
70void uart2_status_isr(void) {
71 DisableInterrupts disable_interrupts;
72 Uarts::instance->cam2.HandleInterrupt(disable_interrupts);
73}
74
75void uart3_status_isr(void) {
76 DisableInterrupts disable_interrupts;
77 Uarts::instance->cam3.HandleInterrupt(disable_interrupts);
78}
79
80void uart4_status_isr(void) {
81 DisableInterrupts disable_interrupts;
82 Uarts::instance->cam4.HandleInterrupt(disable_interrupts);
83}
84
85} // extern "C"
86
87// A test program which echos characters back after adding a per-UART offset to
88// them (CAM0 adds 1, CAM1 adds 2, etc).
89__attribute__((unused)) void TestUarts() {
90 Uarts *const uarts = Uarts::instance;
91 while (true) {
92 {
93 std::array<char, 10> buffer;
94 const auto data = uarts->cam0.Read(buffer);
95 for (int i = 0; i < data.size(); ++i) {
96 data[i] += 1;
97 }
98 uarts->cam0.Write(data);
99 }
100 {
101 std::array<char, 10> buffer;
102 const auto data = uarts->cam1.Read(buffer);
103 for (int i = 0; i < data.size(); ++i) {
104 data[i] += 2;
105 }
106 uarts->cam1.Write(data);
107 }
108 {
109 std::array<char, 10> buffer;
110 const auto data = uarts->cam2.Read(buffer);
111 for (int i = 0; i < data.size(); ++i) {
112 data[i] += 3;
113 }
114 uarts->cam2.Write(data);
115 }
116 {
117 std::array<char, 10> buffer;
118 const auto data = uarts->cam3.Read(buffer);
119 for (int i = 0; i < data.size(); ++i) {
120 data[i] += 4;
121 }
122 uarts->cam3.Write(data);
123 }
124 {
125 std::array<char, 10> buffer;
126 const auto data = uarts->cam4.Read(buffer);
127 for (int i = 0; i < data.size(); ++i) {
128 data[i] += 5;
129 }
130 uarts->cam4.Write(data);
131 }
132 }
133}
134
135// Tests all the I/O pins. Cycles through each one for 1 second. While active,
136// each output is turned on, and each input has its value printed.
137__attribute__((unused)) void TestIo() {
138 // Set SPI0 pins to GPIO.
139 // SPI_OUT
140 PERIPHERAL_BITBAND(GPIOC_PDDR, 6) = 1;
141 PORTC_PCR6 = PORT_PCR_DSE | PORT_PCR_MUX(1);
142 // SPI_CS
143 PERIPHERAL_BITBAND(GPIOD_PDDR, 0) = 0;
144 PORTD_PCR0 = PORT_PCR_DSE | PORT_PCR_MUX(1);
145 // SPI_IN
146 PERIPHERAL_BITBAND(GPIOC_PDDR, 7) = 0;
147 PORTC_PCR7 = PORT_PCR_DSE | PORT_PCR_MUX(1);
148 // SPI_SCK
149 PERIPHERAL_BITBAND(GPIOD_PDDR, 1) = 0;
150 PORTD_PCR1 = PORT_PCR_DSE | PORT_PCR_MUX(1);
151
152 // Set LED pins to GPIO.
153 PERIPHERAL_BITBAND(GPIOC_PDDR, 11) = 1;
154 PORTC_PCR11 = PORT_PCR_DSE | PORT_PCR_MUX(1);
155 PERIPHERAL_BITBAND(GPIOC_PDDR, 10) = 1;
156 PORTC_PCR10 = PORT_PCR_DSE | PORT_PCR_MUX(1);
157 PERIPHERAL_BITBAND(GPIOC_PDDR, 8) = 1;
158 PORTC_PCR8 = PORT_PCR_DSE | PORT_PCR_MUX(1);
159 PERIPHERAL_BITBAND(GPIOC_PDDR, 9) = 1;
160 PORTC_PCR9 = PORT_PCR_DSE | PORT_PCR_MUX(1);
161 PERIPHERAL_BITBAND(GPIOB_PDDR, 18) = 1;
162 PORTB_PCR18 = PORT_PCR_DSE | PORT_PCR_MUX(1);
163 PERIPHERAL_BITBAND(GPIOC_PDDR, 2) = 1;
164 PORTC_PCR2 = PORT_PCR_DSE | PORT_PCR_MUX(1);
165 PERIPHERAL_BITBAND(GPIOD_PDDR, 7) = 1;
166 PORTD_PCR7 = PORT_PCR_DSE | PORT_PCR_MUX(1);
167 PERIPHERAL_BITBAND(GPIOC_PDDR, 1) = 1;
168 PORTC_PCR1 = PORT_PCR_DSE | PORT_PCR_MUX(1);
169 PERIPHERAL_BITBAND(GPIOB_PDDR, 19) = 1;
170 PORTB_PCR19 = PORT_PCR_DSE | PORT_PCR_MUX(1);
171 PERIPHERAL_BITBAND(GPIOD_PDDR, 5) = 1;
172 PORTD_PCR5 = PORT_PCR_DSE | PORT_PCR_MUX(1);
173
174 auto next = aos::monotonic_clock::now();
175 static constexpr auto kTick = std::chrono::seconds(1);
176 while (true) {
177 printf("SPI_MISO\n");
178 PERIPHERAL_BITBAND(GPIOC_PDOR, 6) = 1;
179 while (aos::monotonic_clock::now() < next + kTick) {
180 }
181 PERIPHERAL_BITBAND(GPIOC_PDOR, 6) = 0;
182 next += kTick;
183
184 while (aos::monotonic_clock::now() < next + kTick) {
185 printf("SPI_CS %d\n", (int)PERIPHERAL_BITBAND(GPIOD_PDIR, 0));
186 }
187 next += kTick;
188
189 while (aos::monotonic_clock::now() < next + kTick) {
190 printf("SPI_MOSI %d\n", (int)PERIPHERAL_BITBAND(GPIOC_PDIR, 7));
191 }
192 next += kTick;
193
194 while (aos::monotonic_clock::now() < next + kTick) {
195 printf("SPI_CLK %d\n", (int)PERIPHERAL_BITBAND(GPIOD_PDIR, 1));
196 }
197 next += kTick;
198
199 printf("CAM0\n");
200 PERIPHERAL_BITBAND(GPIOC_PDOR, 11) = 1;
201 while (aos::monotonic_clock::now() < next + kTick) {
202 }
203 PERIPHERAL_BITBAND(GPIOC_PDOR, 11) = 0;
204 next += kTick;
205
206 printf("CAM1\n");
207 PERIPHERAL_BITBAND(GPIOC_PDOR, 10) = 1;
208 while (aos::monotonic_clock::now() < next + kTick) {
209 }
210 PERIPHERAL_BITBAND(GPIOC_PDOR, 10) = 0;
211 next += kTick;
212
213 printf("CAM2\n");
214 PERIPHERAL_BITBAND(GPIOC_PDOR, 8) = 1;
215 while (aos::monotonic_clock::now() < next + kTick) {
216 }
217 PERIPHERAL_BITBAND(GPIOC_PDOR, 8) = 0;
218 next += kTick;
219
220 printf("CAM3\n");
221 PERIPHERAL_BITBAND(GPIOC_PDOR, 9) = 1;
222 while (aos::monotonic_clock::now() < next + kTick) {
223 }
224 PERIPHERAL_BITBAND(GPIOC_PDOR, 9) = 0;
225 next += kTick;
226
227 printf("CAM4\n");
228 PERIPHERAL_BITBAND(GPIOB_PDOR, 18) = 1;
229 while (aos::monotonic_clock::now() < next + kTick) {
230 }
231 PERIPHERAL_BITBAND(GPIOB_PDOR, 18) = 0;
232 next += kTick;
233
234 printf("CAM5\n");
235 PERIPHERAL_BITBAND(GPIOC_PDOR, 2) = 1;
236 while (aos::monotonic_clock::now() < next + kTick) {
237 }
238 PERIPHERAL_BITBAND(GPIOC_PDOR, 2) = 0;
239 next += kTick;
240
241 printf("CAM6\n");
242 PERIPHERAL_BITBAND(GPIOD_PDOR, 7) = 1;
243 while (aos::monotonic_clock::now() < next + kTick) {
244 }
245 PERIPHERAL_BITBAND(GPIOD_PDOR, 7) = 0;
246 next += kTick;
247
248 printf("CAM7\n");
249 PERIPHERAL_BITBAND(GPIOC_PDOR, 1) = 1;
250 while (aos::monotonic_clock::now() < next + kTick) {
251 }
252 PERIPHERAL_BITBAND(GPIOC_PDOR, 1) = 0;
253 next += kTick;
254
255 printf("CAM8\n");
256 PERIPHERAL_BITBAND(GPIOB_PDOR, 19) = 1;
257 while (aos::monotonic_clock::now() < next + kTick) {
258 }
259 PERIPHERAL_BITBAND(GPIOB_PDOR, 19) = 0;
260 next += kTick;
261
262 printf("CAM9\n");
263 PERIPHERAL_BITBAND(GPIOD_PDOR, 5) = 1;
264 while (aos::monotonic_clock::now() < next + kTick) {
265 }
266 PERIPHERAL_BITBAND(GPIOD_PDOR, 5) = 0;
267 next += kTick;
268 }
269}
270
271int Main() {
272 // for background about this startup delay, please see these conversations
273 // https://forum.pjrc.com/threads/36606-startup-time-(400ms)?p=113980&viewfull=1#post113980
274 // https://forum.pjrc.com/threads/31290-Teensey-3-2-Teensey-Loader-1-24-Issues?p=87273&viewfull=1#post87273
275 delay(400);
276
277 // Set all interrupts to the second-lowest priority to start with.
278 for (int i = 0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_SANE_PRIORITY(i, 0xD);
279
280 // Now set priorities for all the ones we care about. They only have meaning
281 // relative to each other, which means centralizing them here makes it a lot
282 // more manageable.
283 NVIC_SET_SANE_PRIORITY(IRQ_FTM0, 0x3);
284 NVIC_SET_SANE_PRIORITY(IRQ_UART0_STATUS, 0xE);
285
286 // Set the LED's pin to output mode.
287 PERIPHERAL_BITBAND(GPIOC_PDDR, 5) = 1;
288 PORTC_PCR5 = PORT_PCR_DSE | PORT_PCR_MUX(1);
289
290 frc971::motors::PrintingParameters printing_parameters;
291 printing_parameters.dedicated_usb = true;
292 const ::std::unique_ptr<frc971::motors::PrintingImplementation> printing =
293 CreatePrinting(printing_parameters);
294 printing->Initialize();
295
296 DMA.CR = M_DMA_EMLM;
297
298 SIM_SCGC4 |=
299 SIM_SCGC4_UART0 | SIM_SCGC4_UART1 | SIM_SCGC4_UART2 | SIM_SCGC4_UART3;
300 SIM_SCGC1 |= SIM_SCGC1_UART4;
301
302 // SPI0 goes to the roboRIO.
303 // SPI0_PCS0 is SPI_CS.
304 PORTD_PCR0 = PORT_PCR_DSE | PORT_PCR_MUX(2);
305 // SPI0_SOUT is SPI_MISO.
306 PORTC_PCR6 = PORT_PCR_DSE | PORT_PCR_MUX(2);
307 // SPI0_SIN is SPI_MOSI.
308 PORTC_PCR7 = PORT_PCR_DSE | PORT_PCR_MUX(2);
309 // SPI0_SCK is SPI_CLK.
310 PORTD_PCR1 = PORT_PCR_DSE | PORT_PCR_MUX(2);
311
312 // FTM0_CH0 is LED0 (7 in silkscreen, a beacon channel).
313 PORTC_PCR1 = PORT_PCR_DSE | PORT_PCR_MUX(4);
314 // FTM0_CH1 is LED1 (5 in silkscreen, a beacon channel).
315 PORTC_PCR2 = PORT_PCR_DSE | PORT_PCR_MUX(4);
316 // FTM0_CH7 is LED2 (6 in silkscreen, a beacon channel).
317 PORTD_PCR7 = PORT_PCR_DSE | PORT_PCR_MUX(4);
318 // FTM0_CH5 is LED3 (9 in silkscreen, a vision camera).
319 PORTD_PCR5 = PORT_PCR_DSE | PORT_PCR_MUX(4);
320
321 // FTM2_CH1 is LED4 (8 in silkscreen, a vision camera).
322 PORTB_PCR19 = PORT_PCR_DSE | PORT_PCR_MUX(3);
323 // FTM2_CH0 is LED5 (for CAM4).
324 PORTB_PCR18 = PORT_PCR_DSE | PORT_PCR_MUX(3);
325
326 // FTM3_CH4 is LED6 (for CAM2).
327 PORTC_PCR8 = PORT_PCR_DSE | PORT_PCR_MUX(3);
328 // FTM3_CH5 is LED7 (for CAM3).
329 PORTC_PCR9 = PORT_PCR_DSE | PORT_PCR_MUX(3);
330 // FTM3_CH6 is LED8 (for CAM1).
331 PORTC_PCR10 = PORT_PCR_DSE | PORT_PCR_MUX(3);
332 // FTM3_CH7 is LED9 (for CAM0).
333 PORTC_PCR11 = PORT_PCR_DSE | PORT_PCR_MUX(3);
334
335 // This hardware has been deactivated, but keep this comment for now to
336 // document which pins it is on.
337#if 0
338 // This is ODROID_EN.
339 PERIPHERAL_BITBAND(GPIOC_PDDR, 0) = 1;
340 PERIPHERAL_BITBAND(GPIOC_PDOR, 0) = 0;
341 PORTC_PCR0 = PORT_PCR_DSE | PORT_PCR_MUX(1);
342 // This is CAM_EN.
343 PERIPHERAL_BITBAND(GPIOB_PDDR, 0) = 1;
344 PERIPHERAL_BITBAND(GPIOB_PDOR, 0) = 0;
345 PORTB_PCR0 = PORT_PCR_DSE | PORT_PCR_MUX(1);
346#endif
347 // This is 5V_PGOOD.
348 PERIPHERAL_BITBAND(GPIOD_PDDR, 6) = 0;
349 PORTD_PCR6 = PORT_PCR_MUX(1);
350
351 // These go to CAM1.
352 // UART0_RX (peripheral) is UART1_RX (schematic).
353 PORTA_PCR15 = PORT_PCR_DSE | PORT_PCR_MUX(3);
354 // UART0_TX (peripheral) is UART1_TX (schematic).
355 PORTA_PCR14 = PORT_PCR_DSE | PORT_PCR_MUX(3);
356
357 // These go to CAM0.
358 // UART1_RX (peripheral) is UART0_RX (schematic).
359 PORTC_PCR3 = PORT_PCR_DSE | PORT_PCR_MUX(3);
360 // UART1_TX (peripheral) is UART0_TX (schematic).
361 PORTC_PCR4 = PORT_PCR_DSE | PORT_PCR_MUX(3);
362
363 // These go to CAM2.
364 // UART2_RX
365 PORTD_PCR2 = PORT_PCR_DSE | PORT_PCR_MUX(3);
366 // UART2_TX
367 PORTD_PCR3 = PORT_PCR_DSE | PORT_PCR_MUX(3);
368
369 // These go to CAM3.
370 // UART3_RX
371 PORTB_PCR10 = PORT_PCR_DSE | PORT_PCR_MUX(3);
372 // UART3_TX
373 PORTB_PCR11 = PORT_PCR_DSE | PORT_PCR_MUX(3);
374
375 // These go to CAM4.
376 // UART4_RX
377 PORTE_PCR25 = PORT_PCR_DSE | PORT_PCR_MUX(3);
378 // UART4_TX
379 PORTE_PCR24 = PORT_PCR_DSE | PORT_PCR_MUX(3);
380
381 Uarts uarts;
382
383 // Give everything a chance to get going.
384 delay(100);
385
386 printf("Ram start: %p\n", __bss_ram_start__);
387 printf("Heap start: %p\n", __heap_start__);
388 printf("Heap end: %p\n", __brkval);
389 printf("Stack start: %p\n", __stack_end__);
390
391 uarts.Initialize(115200);
392 NVIC_ENABLE_IRQ(IRQ_UART0_STATUS);
393 NVIC_ENABLE_IRQ(IRQ_UART1_STATUS);
394 NVIC_ENABLE_IRQ(IRQ_UART2_STATUS);
395 NVIC_ENABLE_IRQ(IRQ_UART3_STATUS);
396 NVIC_ENABLE_IRQ(IRQ_UART4_STATUS);
397
398 while (true) {
399 }
400}
401
402extern "C" {
403
404int main(void) {
405 return Main();
406}
407
408} // extern "C"
409
410} // namespace
411} // namespace jevois
412} // namespace frc971