Skip to content

Commit c8dde81

Browse files
mwaskodeb-intel
authored andcommitted
arch: fw: asynchronous messaging service
Introduction of service to exchange events between firmware components Signed-off-by: Michal Wasko <[email protected]>
1 parent 074ea66 commit c8dde81

File tree

4 files changed

+279
-0
lines changed

4 files changed

+279
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
.. _async_msg:
2+
3+
Asynchronous Messaging Service
4+
##############################
5+
6+
Asynchronous Messaging Service (AMS) is designed to exchange sporadic /
7+
asynchronous events between firmware components, such as key phrase detection.
8+
It can also be optionally selected in the firmware build configuration. The
9+
service exposes an external interface to the host and is API accessible from
10+
firmware components.
11+
12+
**NOTE:** The AMS integration is currently a work in progress; it might not be
13+
fully functional in SOF main branch.
14+
15+
Asynchronous messages are one-way from producer to all consumers and allows to:
16+
17+
- direct asynchronous communication between components (1:1)
18+
- sending one asynchronous message to many components (1:N)
19+
- producing asynchronous messages by many modules where 1 is receiving (M:1)
20+
- producing asynchronous messages by many modules where many are receiving (M:N)
21+
22+
Messages are exchanged over IDC protocol and shared memory with multi-core
23+
support. Message producers and consumers can be run on different cores.
24+
25+
.. TODO: Add link to AMS interface generated from code
26+
27+
Asynchronous Messaging Flows
28+
****************************
29+
30+
Producer and consumer on the same core
31+
======================================
32+
33+
.. uml:: images/async_messaging/flow_prod_cons_same_core.pu
34+
:caption: Asynchronous Messaging example with WoV producer and custom module consumer running on single core
35+
36+
Producer on primary core, consumer on secondary core
37+
====================================================
38+
39+
.. uml:: images/async_messaging/flow_prod_primary_cons_secondary_core.pu
40+
:caption: Asynchronous Messaging example with WoV producer on primary core and custom module consumer running on secondary core
41+
42+
.. TODO: Port additional async messaging uml flows from internal FAS documentation
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
@startuml
2+
3+
box "DSP #0 (primary)" #LightBlue
4+
participant "DSP #0: AMS" as ams
5+
participant "DSP #0: KR" as kr
6+
participant "DSP #0: Custom module" as custom_module
7+
end box
8+
9+
box "Shared SRAM"
10+
participant "AMS database" as ams_db
11+
end box
12+
13+
...
14+
15+
group Register KEY_PHRASE_DETECTED producer
16+
group Get Message ID
17+
kr -> ams: am_service_get_message_type_id(KEY_PHRASE_DETECTED UUID)
18+
activate ams
19+
ams -> ams_db: Find ID for KEY_PHRASE_DETECTED message
20+
activate ams_db
21+
alt If no KEY_PHRASE_DETECTED is found
22+
ams -> ams_db: Assign ID to KEY_PHRASE_DETECTED message
23+
return
24+
end
25+
return
26+
end
27+
28+
kr -> ams: am_service_register_producer(message_id)
29+
activate ams
30+
return
31+
end
32+
33+
...
34+
35+
group Register KEY_PHRASE_DETECTED consumer
36+
group Get Message ID
37+
custom_module-> custom_module
38+
end
39+
40+
custom_module -> ams: am_service_register_consumer(message_id, callback)
41+
activate ams
42+
ams -> ams_db: Add KEY_PHRASE_DETECTED message consumer
43+
return
44+
end
45+
46+
...
47+
48+
group Send Async Message
49+
kr -> ams: am_service_send_message(lp_kpd_id, message)
50+
activate ams
51+
52+
ams -> ams_db: Get KEY_PHRASE_DETECTED consumers
53+
loop Until all consumer are called
54+
ams -> ams_db: Get AMS consumer Processor ID
55+
56+
alt AMS Consumer Processor ID != Current Processor ID
57+
ams -> ams: Forward AMS message to the consumer's core
58+
else AMS Consumer Processor ID == Current Processor ID
59+
ams -> ams_db: Get AMS consumer callback
60+
ams -> ams: Call consumer AMS callback
61+
end
62+
end
63+
return
64+
end
65+
66+
...
67+
68+
group Unregister KEY_PHRASE_DETECTED consumer
69+
custom_module -> ams: am_service_unregister_consumer(message_id, callback)
70+
activate ams
71+
ams -> ams_db: Remove KEY_PHRASE_DETECTED message consumer
72+
return
73+
end
74+
75+
...
76+
77+
group Unregister KEY_PHRASE_DETECTED producer
78+
kr -> ams: am_service_unregister_producer(message_id)
79+
activate ams
80+
return
81+
end
82+
83+
@enduml
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
@startuml
2+
3+
scale max 1280 width
4+
5+
box "DSP #0 (primary)" #LightBlue
6+
participant "DSP #0: IXC Service" as ixc_service_dsp_0
7+
participant "DSP #0: IDC" as idc_dsp_0
8+
participant "DSP #0: AMS" as ams_dsp_0
9+
participant "DSP #0: KR" as kr_dsp_0
10+
end box
11+
12+
box "DSP #1 (secondary)" #LightGreen
13+
participant "DSP #1: IDC" as idc_dsp_1
14+
participant "DSP #1: Scheduler" as scheduler_dsp_1
15+
participant "DSP #1: IDC Task" as idc_dsp_1
16+
participant "DSP #1: IXC Service" as ixc_service_dsp_1
17+
participant "DSP #1: AMS" as ams_dsp_1
18+
participant "DSP #1: Custom module" as custom_module_dsp_1
19+
end box
20+
21+
box "Shared SRAM"
22+
participant "AMS database" as ams_db
23+
end box
24+
25+
...
26+
27+
group Register KEY_PHRASE_DETECTED producer
28+
group Get Message ID
29+
kr_dsp_0 -> ams_dsp_0: am_service_get_message_type_id(KEY_PHRASE_DETECTED UUID)
30+
activate ams_dsp_0
31+
ams_dsp_0 -> ams_db: Find ID for KEY_PHRASE_DETECTED message
32+
activate ams_db
33+
alt If no KEY_PHRASE_DETECTED is found
34+
ams_dsp_0 -> ams_db: Assign ID to KEY_PHRASE_DETECTED message
35+
end
36+
return
37+
return
38+
end
39+
40+
kr_dsp_0 -> ams_dsp_0: am_service_register_producer(message_id)
41+
activate ams_dsp_0
42+
return
43+
end
44+
45+
...
46+
47+
group Register KEY_PHRASE_DETECTED consumer
48+
group Get Message ID
49+
custom_module_dsp_1 -> ams_dsp_1: am_service_get_message_type_id(KEY_PHRASE_DETECTED UUID)
50+
activate ams_dsp_1
51+
52+
ams_dsp_0 -> ams_db: Find ID for KEY_PHRASE_DETECTED message
53+
activate ams_db
54+
alt If no KEY_PHRASE_DETECTED is found
55+
ams_dsp_0 -> ams_db: Assign ID to KEY_PHRASE_DETECTED message
56+
end
57+
return
58+
end
59+
60+
custom_module_dsp_1 -> ams_dsp_1: am_service_register_consumer(message_id)
61+
activate ams_dsp_1
62+
ams_dsp_1 -> ams_db: Add KEY_PHRASE_DETECTED message consumer
63+
return
64+
end
65+
66+
...
67+
68+
group Send Async Message
69+
kr_dsp_0 -> ams_dsp_0: am_service_send_message(message_id, message)
70+
activate ams_dsp_0
71+
ams_dsp_0 -> ams_db: Get KEY_PHRASE_DETECTED consumers
72+
73+
note left of ams_db
74+
"External" means the consumers located on the other DSP cores.
75+
"Internal" means the consumers located on the same DSP core.
76+
end note
77+
78+
loop Until all consumer are called
79+
ams_dsp_0 -> ams_db: Get AMS consumer Processor ID
80+
81+
alt AMS Consumer Processor ID != Current Processor ID
82+
alt If a first time AMS consumer on this DSP core
83+
alt If it is a first external AMS consumer
84+
loop Until AMS message slot is reserved or limit of tries is reached
85+
ams_dsp_0 -> ams_db: Reserve AMS message slot
86+
end
87+
88+
ams_dsp_0 -> ams_db: Increment a 'core use count' for AMS slot
89+
ams_dsp_0 -> ams_db: Set MOVEMENT_REPORT message
90+
ams_dsp_0 -> ams_dsp_0: Flush/Invalidate L1 cache
91+
end
92+
93+
ams_dsp_0 -> ixc_service_dsp_0: Send FORWARD_AMS_MESSAGE(ams_message_slot_id) IDC to the consumer's core
94+
activate ixc_service_dsp_0
95+
ixc_service_dsp_0 -> idc_dsp_0: IDC Interrupt
96+
activate idc_dsp_0
97+
idc_dsp_1 -> scheduler_dsp_1: Add/unblock IDC task
98+
return
99+
return
100+
end
101+
else AMS Consumer Processor ID == Current Processor ID
102+
ams_dsp_0 -> ams_db: Get AMS consumer callback
103+
ams_dsp_0 -> ams_dsp_0: Call consumer AMS callback
104+
end
105+
end
106+
return
107+
108+
...
109+
110+
scheduler_dsp_1 -> idc_dsp_1: Execute task
111+
activate idc_dsp_1
112+
idc_dsp_1 -> ixc_service_dsp_1: Process IDC message
113+
activate ixc_service_dsp_1
114+
ixc_service_dsp_1 -> ams_dsp_1: FORWARD_AMS_MESSAGE(ams_message_slot_id)
115+
activate ams_dsp_1
116+
ams_dsp_1 -> ams_db: Get KEY_PHRASE_DETECTED consumers
117+
loop Until all consumer are called
118+
ams_dsp_1 -> ams_db: Get AMS consumer Processor ID
119+
120+
alt AMS Consumer Processor ID == Current Processor ID
121+
ams_dsp_1 -> ams_db: Get AMS consumer callback
122+
alt If Custom module consumer
123+
ams_dsp_1 -> custom_module_dsp_1: Call AMS Custom module callback
124+
activate custom_module_dsp_1
125+
return
126+
else
127+
ams_dsp_1 -> ams_dsp_0: Call consumer AMS callback
128+
end
129+
end
130+
end
131+
return
132+
return
133+
return
134+
end
135+
136+
...
137+
138+
group Unregister KEY_PHRASE_DETECTED produce
139+
kr_dsp_0 -> ams_dsp_0: am_service_unregister_producer(message_id)
140+
activate ams_dsp_0
141+
return
142+
end
143+
144+
...
145+
146+
group Unregister KEY_PHRASE_DETECTED consumer
147+
custom_module_dsp_1 -> ams_dsp_1: am_service_unregister_consumer(message_id)
148+
activate ams_dsp_1
149+
ams_dsp_1 -> ams_db: Remove KEY_PHRASE_DETECTED message consumer
150+
return
151+
end
152+
153+
@enduml

architectures/firmware/sof-zephyr/mpp_layer/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ to the Application layer.
1212

1313
mpp_overview
1414
mpp_scheduling
15+
async_messaging

0 commit comments

Comments
 (0)