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