The distributed programmable peripheral interconnect (DPPI) enables peripherals to interact autonomously with each other by using tasks and events, without any intervention from the CPU. DPPI allows precise synchronization between peripherals when real-time application constraints exist and eliminates the need for CPU involvement to implement behavior which can be predefined using the DPPI.
The DPPI has the following features:
- Peripheral tasks can subscribe to channels
- Peripheral events can be published on channels
- Publish/subscribe pattern enabling multiple connection options that include the following:
- One-to-one
- One-to-many
- Many-to-one
- Many-to-many
The DPPI consists of several PPIBus modules, which are connected to a fixed number of DPPI channels and a DPPI configuration (DPPIC).
Subscribing to and publishing on channels
The PPIBus can route peripheral events onto the channels (publishing), or route events from the channels into peripheral tasks (subscribing).
All peripherals include the following:
- One subscribe register per task
- One publish register per event
Publish and subscribe registers use a channel index field to determine the channel to which the event is published or tasks subscribed. In addition, there is an enable bit for the subscribe and publish registers that needs to be enabled before the subscription or publishing takes effect.
Writing non-existing channel index (CHIDX) numbers into a peripheral's publish or subscribe registers will yield unexpected results.
One event can trigger multiple tasks by subscribing different tasks to the same channel. Similarly, one task can be triggered by multiple events by publishing different events to the same channel. For advanced use cases, multiple events and multiple tasks can connect to the same channel forming a many-to-many connection. If multiple events are published on the same channel at the same time, the events are merged and only one event is routed through the DPPI.
How peripheral events are routed onto different channels based on publish registers is illustrated in the following figure.
The following figure illustrates how peripheral tasks are triggered from different channels based on subscribe registers.
DPPI configuration (DPPIC)
Enabling and disabling of channels globally is handled through the DPPI configuration (DPPIC). Connection (connect/disconnect) between a channel and a peripheral is handled locally by the PPIBus.
There are two ways of enabling and disabling global channels using the DPPI configuration:
- Enable or disable channels individually using registers CHEN, CHENSET, and CHENCLR.
- Enable or disable channels in channel groups using the groups' tasks ENABLE and DISABLE. It needs to be defined which channels belong to which channel groups before these tasks are triggered.
The DPPI configuration tasks (for example CHG[0].EN) can be triggered through DPPI like any other task, which means they can be linked to a DPPI channel through the subscribe registers.
In order to write to CHG[x], the corresponding CHG[x].EN and CHG[x].DIS subscribe registers must be disabled. Writes to CHG[x] are ignored if any of the two subscribe registers are enabled.
Connection examples
DPPI offers several connection options. Examples are given for how to create one-to-one and many-to-many connections.
One-to-one connection
This example shows how to create a one-to-one connection between TIMER compare register and SAADC start task.
The channel configuration is set up first. TIMER0 will publish its COMPARE0 event on channel 0, and SAADC will subscribe its START task to events on the same channel. After that, the channel is enabled through the DPPIC.
NRF_TIMER0->PUBLISH_COMPARE0 = (DPPI_PUB_CHIDX_Ch0) |
(DPPI_PUB_EN_Msk);
NRF_SAADC->SUBSCRIBE_START = (DPPI_SUB_CHIDX_Ch0) |
(DPPI_SUB_EN_Msk);
NRF_DPPIC->CHENSET = (DPPI_CHENSET_CH0_Set << DPPI_CHENSET_CH0_Pos);
Many-to-many connection
The example shows how to create a many-to-many connection, showcasing the DPPIC's channel group functionality.
NRF_DPPIC->CHG[0] = (DPPI_CHG_CH0_Included << PPI_CHG_CH0_Pos);
NRF_GPIOTE->PUBLISH_IN0 = (DPPI_PUB_CHIDX_Ch0) |
(DPPI_PUB_EN_Msk);
NRF_TIMER0->PUBLISH_COMPARE0 = (DPPI_PUB_CHIDX_Ch0) |
(DPPI_PUB_EN_Msk);
NRF_SAADC->SUBSCRIBE_START = (DPPI_SUB_CHIDX_Ch0) |
(DPPI_SUB_EN_Msk);
NRF_DPPIC->SUBSCRIBE_CHG[0].DIS = (DPPI_SUB_CHIDX_Ch0) |
(DPPI_SUB_EN_Msk);
NRF_DPPIC->TASK_CHG[0].EN = 1;
Special considerations for a system implementing TrustZone for Cortex-M processors
DPPI is implemented with split security, meaning it handles both secure and non-secure accesses. In a system implementing the TrustZone® for Cortex®-M technology, DPPI channels can be defined as secure or non-secure using the SPU.
A peripheral configured as non-secure will only be able to subscribe to or publish on non-secure DPPI channels. A peripheral configured as secure will be able to access all DPPI channels. DPPI handles both secure and non-secure accesses, but behaves differently depending on the access type:
- A non-secure peripheral access can only configure and control the DPPI channels defined as non-secure in the SPU.DPPI.PERM[] register(s)
- A secure peripheral access can control all the DPPI channels, independently of the SPU.DPPI.PERM[] register(s)
A group of channels can be created, making it possible to simultaneously enable or disable all channels within the group. The security attribute of a group of channels (secure or non-secure) is defined as follows:
- If all channels (enabled or not) within a group are non-secure, then the group is considered non-secure
- If at least one of the channels (enabled or not) within the group is secure, then the group is considered secure
A non-secure access to a DPPI register, or a bit field, controlling a channel marked as secure in SPU.DPPI[].PERM register(s) will be ignored. Write accesses will have no effect, and read accesses will always return a zero value.
No exceptions are triggered when non-secure accesses target a register or a bit field
controlling a secure channel. For example, if the bit i is set in the
SPU.DPPI[0].PERM register (declaring DPPI channel i as secure), then:
- Non-secure write accesses to registers CHEN, CHENSET, and CHENCLR cannot write bit
iof these registers - Non-secure write accesses to TASK_CHG[j].EN and TASK_CHG[j].DIS registers are
ignored if the channel group
jcontains at least one channel defined as secure (it can be the channel i itself or any channel declared as secure) - Non-secure read accesses to registers CHEN, CHENSET, and CHENCLR always read 0 for
the bit at position
i
For the channel configuration registers (CHG[]), access from non-secure code is only
possible if the included channels are all non-secure, whether the channels are enabled
or not. If a CHG[g] register included one or more secure channel(s), then the group
g is considered as secure, and only secure transfers can read to or
write from CHG[g]. A non-secure write access is ignored, and a non-secure read access
returns 0.
The DPPI can subscribe to secure and non-secure channels through the SUBSCRIBE_CHG[] registers, in order to trigger the task for enabling or disabling groups of channels. An event from a secure channel will be ignored if the group subscribing to this channel is non-secure. A secure group can subscribe to a non-secure channel or a secure channel.
Registers
Instances
| Instance | Base address | TrustZone | Split access | Description | ||
|---|---|---|---|---|---|---|
| Map | Att | DMA | ||||
|
DPPIC : S |
0x50017000 |
HF | NS | NA | Yes |
DPPI configuration |
Register overview
| Register | Offset | TZ | Description |
|---|---|---|---|
| TASKS_CHG[n].EN | 0x000 |
Enable channel group n |
|
| TASKS_CHG[n].DIS | 0x004 |
Disable channel group n |
|
| SUBSCRIBE_CHG[n].EN | 0x080 |
Subscribe configuration for task CHG[n].EN |
|
| SUBSCRIBE_CHG[n].DIS | 0x084 |
Subscribe configuration for task CHG[n].DIS |
|
| CHEN | 0x500 |
Channel enable register |
|
| CHENSET | 0x504 |
Channel enable set register |
|
| CHENCLR | 0x508 |
Channel enable clear register |
|
| CHG[n] | 0x800 |
Channel group n Note: Writes to this register are ignored if either SUBSCRIBE_CHG[n].EN or SUBSCRIBE_CHG[n].DIS is enabled |
TASKS_CHG[n] (n=0..5)
Channel group tasks
TASKS_CHG[n].EN (n=0..5)
Address offset: 0x000 + (n × 0x8)
Enable channel group n
| Bit number | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | A | ||||||||||||||||||||||||||||||||||
| Reset 0x00000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
| ID | R/W | Field | Value ID | Value | Description | ||||||||||||||||||||||||||||||
| A |
W |
EN |
Enable channel group n |
||||||||||||||||||||||||||||||||
|
Trigger |
1 |
Trigger task |
|||||||||||||||||||||||||||||||||
TASKS_CHG[n].DIS (n=0..5)
Address offset: 0x004 + (n × 0x8)
Disable channel group n
| Bit number | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | A | ||||||||||||||||||||||||||||||||||
| Reset 0x00000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
| ID | R/W | Field | Value ID | Value | Description | ||||||||||||||||||||||||||||||
| A |
W |
DIS |
Disable channel group n |
||||||||||||||||||||||||||||||||
|
Trigger |
1 |
Trigger task |
|||||||||||||||||||||||||||||||||
SUBSCRIBE_CHG[n] (n=0..5)
Subscribe configuration for tasks
SUBSCRIBE_CHG[n].EN (n=0..5)
Address offset: 0x080 + (n × 0x8)
Subscribe configuration for task CHG[n].EN
| Bit number | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | B | A | A | A | A | A | A | A | A | ||||||||||||||||||||||||||
| Reset 0x00000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
| ID | R/W | Field | Value ID | Value | Description | ||||||||||||||||||||||||||||||
| A |
RW |
CHIDX |
[0..255] |
DPPI channel that task CHG[n].EN will subscribe to |
|||||||||||||||||||||||||||||||
| B |
RW |
EN |
|||||||||||||||||||||||||||||||||
|
Disabled |
0 |
Disable subscription |
|||||||||||||||||||||||||||||||||
|
Enabled |
1 |
Enable subscription |
|||||||||||||||||||||||||||||||||
SUBSCRIBE_CHG[n].DIS (n=0..5)
Address offset: 0x084 + (n × 0x8)
Subscribe configuration for task CHG[n].DIS
| Bit number | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | B | A | A | A | A | A | A | A | A | ||||||||||||||||||||||||||
| Reset 0x00000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
| ID | R/W | Field | Value ID | Value | Description | ||||||||||||||||||||||||||||||
| A |
RW |
CHIDX |
[0..255] |
DPPI channel that task CHG[n].DIS will subscribe to |
|||||||||||||||||||||||||||||||
| B |
RW |
EN |
|||||||||||||||||||||||||||||||||
|
Disabled |
0 |
Disable subscription |
|||||||||||||||||||||||||||||||||
|
Enabled |
1 |
Enable subscription |
|||||||||||||||||||||||||||||||||
CHEN
Address offset: 0x500
Channel enable register
| Bit number | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | P | O | N | M | L | K | J | I | H | G | F | E | D | C | B | A | |||||||||||||||||||
| Reset 0x00000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
| ID | R/W | Field | Value ID | Value | Description | ||||||||||||||||||||||||||||||
| A-P |
RW |
CH[i] (i=0..15) |
Enable or disable channel i |
||||||||||||||||||||||||||||||||
|
Disabled |
0 |
Disable channel |
|||||||||||||||||||||||||||||||||
|
Enabled |
1 |
Enable channel |
|||||||||||||||||||||||||||||||||
CHENSET
Address offset: 0x504
Channel enable set register
| Bit number | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | P | O | N | M | L | K | J | I | H | G | F | E | D | C | B | A | |||||||||||||||||||
| Reset 0x00000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
| ID | R/W | Field | Value ID | Value | Description | ||||||||||||||||||||||||||||||
| A-P |
RW |
CH[i] (i=0..15) |
Channel i enable set register. Writing 0 has no effect. |
||||||||||||||||||||||||||||||||
|
Disabled |
0 |
Read: Channel disabled |
|||||||||||||||||||||||||||||||||
|
Enabled |
1 |
Read: Channel enabled |
|||||||||||||||||||||||||||||||||
|
Set |
1 |
Write: Enable channel |
|||||||||||||||||||||||||||||||||
CHENCLR
Address offset: 0x508
Channel enable clear register
| Bit number | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | P | O | N | M | L | K | J | I | H | G | F | E | D | C | B | A | |||||||||||||||||||
| Reset 0x00000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
| ID | R/W | Field | Value ID | Value | Description | ||||||||||||||||||||||||||||||
| A-P |
RW |
CH[i] (i=0..15) |
Channel i enable clear register. Writing 0 has no effect. |
||||||||||||||||||||||||||||||||
|
Disabled |
0 |
Read: Channel disabled |
|||||||||||||||||||||||||||||||||
|
Enabled |
1 |
Read: Channel enabled |
|||||||||||||||||||||||||||||||||
|
Clear |
1 |
Write: Disable channel |
|||||||||||||||||||||||||||||||||
CHG[n] (n=0..5)
Address offset: 0x800 + (n × 0x4)
Channel group n
Note: Writes to this register are ignored if either SUBSCRIBE_CHG[n].EN or SUBSCRIBE_CHG[n].DIS is enabled
| Bit number | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ID | P | O | N | M | L | K | J | I | H | G | F | E | D | C | B | A | |||||||||||||||||||
| Reset 0x00000000 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |||
| ID | R/W | Field | Value ID | Value | Description | ||||||||||||||||||||||||||||||
| A-P |
RW |
CH[i] (i=0..15) |
Include or exclude channel i |
||||||||||||||||||||||||||||||||
|
Excluded |
0 |
Exclude |
|||||||||||||||||||||||||||||||||
|
Included |
1 |
Include |
|||||||||||||||||||||||||||||||||