xref: /aosp_15_r20/external/pigweed/pw_stream_shmem_mcuxpresso/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1.. _module-pw_stream_shmem_mcuxpresso:
2
3==========================
4pw_stream_shmem_mcuxpresso
5==========================
6``pw_stream_shmem_mcuxpresso`` implements the ``pw_stream`` interface for
7reading and writing between two different processor cores via shared memory
8using the NXP MCUXpresso SDK. It uses the messaging unit module (MU) to signal
9data readiness between cores.
10
11Setup
12=====
13This module requires a little setup:
14
151. Use ``pw_build_mcuxpresso`` to create a ``pw_source_set`` for an
16   MCUXpresso SDK.
172. Include the debug console component in this SDK definition.
183. Specify the ``pw_third_party_mcuxpresso_SDK`` GN global variable to specify
19   the name of this source set.
20
21The name of the SDK source set must be set in the
22"pw_third_party_mcuxpresso_SDK" GN arg
23
24Usage
25=====
26``ShmemMcuxpressoStream`` blocks on both reads and writes, as only one
27outstanding buffer can be transferred at a time in each direction. This means a
28dedicated thread should be used for both reading and writing. A typical use case
29for this class would be as the underlying transport for a pw_rpc network between
30cores. Use with the ``pw::rpc::StreamRpcFrameSender`` and
31``pw::rpc::StreamRpcDispatcher`` classes.
32
33Interrupt handlers and shared buffers on both cores must be setup before using
34this stream. The shared buffer must be mapped as uncacheable on both sides.
35
36As an example on the RT595, we connect the M33 core to the FusionF1 DSP. On the
37FusionF1 side, the MU interrupt must be explicitly routed.
38
39Initialization for the M33 Core:
40
41.. code-block:: cpp
42
43   // `kSharedBuffer` is a pointer to memory that is shared between the M33 and
44   // F1 cores, and it is at least `2 * kSharedBufferSize` in size.
45   ByteSpan read_buffer = ByteSpan{kSharedBuffer, kSharedBufferSize};
46   ByteSpan write_buffer = ByteSpan{kSharedBuffer + kSharedBufferSize, kSharedBufferSize};
47   ShmemMcuxpressoStream stream{MUA, read_buffer, write_buffer};
48
49   PW_EXTERN_C void MU_A_DriverIRQHandler() {
50     stream.HandleInterrupt();
51   }
52
53   void Init() {
54     return stream.Enable();
55   }
56
57Initialization for the FusionF1 Core:
58
59.. code-block:: cpp
60
61   ByteSpan write_buffer = ByteSpan{kSharedBuffer, kSharedBufferSize};
62   ByteSpan read_buffer = ByteSpan{kSharedBuffer + kSharedBufferSize, kSharedBufferSize};
63   ShmemMcuxpressoStream stream{MUB, read_buffer, write_buffer};
64
65   PW_EXTERN_C void MU_B_IrqHandler(void*) {
66     stream.HandleInterrupt();
67   }
68
69   void Init() {
70    // Enables the clock for the Input Mux
71    INPUTMUX_Init(INPUTMUX);
72    // MUB interrupt signal is selected for DSP interrupt input 1
73    INPUTMUX_AttachSignal(INPUTMUX, 1U, kINPUTMUX_MuBToDspInterrupt);
74    // Disables the clock for the Input Mux to save power
75    INPUTMUX_Deinit(INPUTMUX);
76
77    xt_set_interrupt_handler(kMuBIrqNum, MU_B_IrqHandler, NULL);
78    xt_interrupt_enable(kMuBIrqNum);
79    stream.Enable();
80   }
81
82Read/Write example where each core has threads for reading and writing.
83
84Core 0:
85
86.. code-block:: cpp
87
88   constexpr std::byte kCore0Value = std::byte{0xab};
89   constexpr std::byte kCore1Value = std::byte{0xcd};
90
91   void ReadThread() {
92     while(true) {
93       std::array<std::byte, 1> read = {};
94       auto status = stream.Read(read);
95       if (!status.ok() || status.size() != 1 || read[0] != kCore1Value) {
96         PW_LOG_WARN("Incorrect value read from core1");
97       }
98     }
99   }
100
101
102   void WriteThread() {
103     std::array<std::byte, 1> write = {kCore0Value};
104     while(true) {
105       stream.Write(write);
106     }
107   }
108
109Core 1:
110
111.. code-block:: cpp
112
113   void ReadThread() {
114    while(true) {
115      std::array<std::byte, 1> read = {};
116      auto status = stream.Read(read);
117      if (!status.ok() || status.size() != 1 || read[0] != kCore0Value) {
118        PW_LOG_WARN("Incorrect value read from core0");
119      }
120    }
121
122  }
123
124  void WriteThread() {
125    std::array<std::byte, 1> write = {kCore1Value};
126    while(true) {
127      stream.Write(write);
128    }
129  }
130