Datasheet
Table Of Contents
- RP2040 Datasheet
- Colophon
- Chapter 1. Introduction
- Chapter 2. System Description
- 2.1. Bus Fabric
- 2.2. Address Map
- 2.3. Processor subsystem
- 2.4. Cortex-M0+
- 2.5. DMA
- 2.6. Memory
- 2.7. Boot Sequence
- 2.8. Bootrom
- 2.9. Power Supplies
- 2.10. Core Supply Regulator
- 2.11. Power Control
- 2.12. Chip-Level Reset
- 2.13. Power-On State Machine
- 2.14. Subsystem Resets
- 2.15. Clocks
- 2.16. Crystal Oscillator (XOSC)
- 2.17. Ring Oscillator (ROSC)
- 2.18. PLL
- 2.19. GPIO
- 2.20. Sysinfo
- 2.21. Syscfg
- 2.22. TBMAN
- Chapter 3. PIO
- Chapter 4. Peripherals
- 4.1. USB
- 4.2. UART
- 4.3. I2C
- 4.3.1. Features
- 4.3.2. IP Configuration
- 4.3.3. I2C Overview
- 4.3.4. I2C Terminology
- 4.3.5. I2C Behaviour
- 4.3.6. I2C Protocols
- 4.3.7. Tx FIFO Management and START, STOP and RESTART Generation
- 4.3.8. Multiple Master Arbitration
- 4.3.9. Clock Synchronization
- 4.3.10. Operation Modes
- 4.3.11. Spike Suppression
- 4.3.12. Fast Mode Plus Operation
- 4.3.13. Bus Clear Feature
- 4.3.14. IC_CLK Frequency Configuration
- 4.3.15. DMA Controller Interface
- 4.3.16. Operation of Interrupt Registers
- 4.3.17. List of Registers
- 4.4. SPI
- 4.5. PWM
- 4.6. Timer
- 4.7. Watchdog
- 4.8. RTC
- 4.9. ADC and Temperature Sensor
- 4.10. SSI
- 4.10.1. Overview
- 4.10.2. Features
- 4.10.3. IP Modifications
- 4.10.4. Clock Ratios
- 4.10.5. Transmit and Receive FIFO Buffers
- 4.10.6. 32-Bit Frame Size Support
- 4.10.7. SSI Interrupts
- 4.10.8. Transfer Modes
- 4.10.9. Operation Modes
- 4.10.10. Partner Connection Interfaces
- 4.10.11. DMA Controller Interface
- 4.10.12. APB Interface
- 4.10.13. List of Registers
- Chapter 5. Electrical and Mechanical
- Appendix A: Register Field Types
- Appendix B: Errata
- Appendix C: Documentation Release History
79 // Tell the DMA to raise IRQ line 0 when the channel finishes a block
80 dma_channel_set_irq0_enabled(dma_chan, true);
81
82 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
83 irq_set_exclusive_handler(DMA_IRQ_0, dma_handler);
84 irq_set_enabled(DMA_IRQ_0, true);
85
86 // Manually call the handler once, to trigger the first transfer
87 dma_handler();
88
89 // Everything else from this point is interrupt-driven. The processor has
90 // time to sit and think about its early retirement -- maybe open a bakery?
91 while (true)
92 tight_loop_contents();
93 #endif
94 }
One disadvantage of this technique is that we don’t start to reconfigure the channel until some time after the channel
makes its last transfer. If there is heavy interrupt activity on the processor, this may be quite a long time, and therefore
quite a large gap in transfers, which is problematic if we need to sustain a high data throughput.
This is solved by using two channels, with their CHAIN_TO fields crossed over, so that channel A triggers channel B when it
completes, and vice versa. At any point in time, one of the channels is transferring data, and the other is either already
configured to start the next transfer immediately when the current one finishes, or it is in the process of being
reconfigured. When channel A completes, it immediately starts the cued-up transfer on channel B. At the same time, the
interrupt is fired, and the handler reconfigures channel A so that it is ready for when channel B completes.
2.5.6.2. DMA Control Blocks
Frequently, multiple smaller buffers must be gathered together and sent to the same peripheral. To address this use
case, the RP2040 DMA can execute a long and complex sequence of transfers without processor control. One channel
repeatedly reconfigures a second channel, and the second channel restarts the first each time it completes block of
transfers.
Because the first DMA channel is transferring data directly from memory to the second channel’s control registers, the
format of the control blocks in memory must match those registers. The last register written to, each time, will be one of
the trigger registers (Section 2.5.2.1) which will start the second channel on its programmed block of transfers. The
register aliases (Section 2.5.2.1) give some flexibility for the block layout, and more importantly allow some registers to
be omitted from the blocks, so they occupy less memory and can be loaded more quickly.
This example shows how multiple buffers can be gathered and transferred to the UART, by reprogramming TRANS_COUNT
and READ_ADDR_TRIG:
Pico Examples: https://github.com/raspberrypi/pico-examples/tree/master/dma/control_blocks/control_blocks.c Lines 1 - 115
ÊÊ1 /**
ÊÊ2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
ÊÊ3 *
ÊÊ4 * SPDX-License-Identifier: BSD-3-Clause
ÊÊ5 */
ÊÊ6
ÊÊ7 // Use two DMA channels to make a programmed sequence of data transfers to the
ÊÊ8 // UART (a data gather operation). One channel is responsible for transferring
ÊÊ9 // the actual data, the other repeatedly reprograms that channel.
Ê10
Ê11 #include <stdio.h>
Ê12 #include "pico/stdlib.h"
Ê13 #include "hardware/dma.h"
Ê14 #include "hardware/structs/uart.h"
Ê15
RP2040 Datasheet
2.5. DMA 100