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