YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
multicore_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#include <array>
15#include <cassert>
16#include <cstdlib>
17
18#include "multicore_rp2350.h"
19#include "task.h"
20#include "RP2350.h"
21using namespace _SIO_;
22using namespace _PPB_;
23using namespace _PSM_;
24
25// Static members
26std::function<void(void)> multicore_rp2350::_f;
27
28void multicore_rp2350::fifo_push_blocking(uint32_t val) {
29 while(SIO.FIFO_ST.RDY != 1) ;
30 SIO.FIFO_WR = val;
31 __SEV();
32}
33
34uint32_t multicore_rp2350::fifo_pop_blocking() {
35 while(SIO.FIFO_ST.VLD != 1) ;
36 return SIO.FIFO_RD;
37}
38
39uint32_t multicore_rp2350::fifo_drain() {
40 uint32_t val {0};
41 while(SIO.FIFO_ST.VLD) val = SIO.FIFO_RD;
42 return val;
43}
44
45void multicore_rp2350::start_on_core1(
46 std::function<void(void)> func,
47 uint8_t * stack,
48 uint32_t * vec_table) {
49 // Store the method to execute
50 _f = func;
51 // When no stack if given, use SCRATCH_Y
52 if (stack == nullptr) {
53 extern uint32_t __StackYTop;
54 stack = (uint8_t *)&__StackYTop;
55 }
56 // When no vector table is given, use the current one
57 if (vec_table == nullptr) {
58 vec_table = (uint32_t *)PPB.VTOR.value;
59 }
60 // Set up the command array
61 std::array<uint32_t, 6> cmd_sequence = {
62 0, 0, 1,
63 (uint32_t)vec_table,
64 (uint32_t)stack,
65 (uint32_t)_run
66 };
67
68 uint32_t seq = 0;
69 // Start the communication with core 1, using a
70 // simple state machine, which will transfer all
71 // necessary information to run the code
72 do {
73 uint32_t cmd = cmd_sequence[seq];
74 // Always drain the READ FIFO (from core 1) before sending a 0
75 if (!cmd) {
76 fifo_drain();
77 // Execute a SEV as core 1 may be waiting for FIFO space via WFE
78 __SEV();
79 }
80 fifo_push_blocking(cmd);
81 uint32_t response = fifo_pop_blocking();
82 // Move to next state on correct response
83 // (echo-d value), otherwise start over
84 seq = cmd == response ? seq + 1 : 0;
85 } while (seq < 6);
86}
87
88//void __attribute__ ((naked)) task_trampoline() {
89// asm("pop {r0-r7}");
90// asm("mov r12, r4");
91// asm("mov lr, r5");
92// asm("bx r6 ");
93//}
94//
95//void multicore_rp2040::start_on_core1(const task & t) {
96// //assert(!t.isLinkedIn());
97// start_on_core1(task_trampoline, t.getSavedSP()+sizeof(callee_saved_registers));
98//}
99
100void multicore_rp2350::reset_core1() {
101 task::sleep_ms(10);
102 // Reset core 1
103 PSM_SET.FRCE_OFF.PROC1 = 1;
104 // Wait until reset has been performed
105 while (!PSM.FRCE_OFF.PROC1) ;
106 // Bring core 1 back out of reset.
107 PSM_CLR.FRCE_OFF.PROC1 = 1;
108 // Wait for core 1 to send us a 0 via the FIFO
109 uint32_t value = fifo_pop_blocking();
110 // check the pushed value
111 assert(value == 0);
112 (void) value; // silence warning
113 task::sleep_ms(10);
114}
115
116// Helper method
117void multicore_rp2350::_run() {
118 _f();
119 exit(0);
120}
#define __SEV
Send Event.