DMA on UART0
Hi all,
I've been trying to get DMA working on UART0. I've done memory to memory DMA, which seems to work.
However when I try to set up for UART0, I see one character appearing, and then it stops.
I have a callback set up for the interrupt on the DMA channel, and it does get called, and the END bit is set, however I only received the first character.
The DMA channel is set to 12 (UART_TX), I specify the UART0 DR register as the address (after converting the memory address space.
I tried setting the DMACR register on the UART to 0x07, but that also does nothing.
Any pointers?
I tried looking into the Circle code, but that only seems to implement DMA on SPI and I2S.
Regards,
Rene
I've been trying to get DMA working on UART0. I've done memory to memory DMA, which seems to work.
However when I try to set up for UART0, I see one character appearing, and then it stops.
I have a callback set up for the interrupt on the DMA channel, and it does get called, and the END bit is set, however I only received the first character.
The DMA channel is set to 12 (UART_TX), I specify the UART0 DR register as the address (after converting the memory address space.
I tried setting the DMACR register on the UART to 0x07, but that also does nothing.
Any pointers?
I tried looking into the Circle code, but that only seems to implement DMA on SPI and I2S.
Regards,
Rene
- cleverca22
- Posts: 9593
- Joined: Sat Aug 18, 2012 2:33 pm
Re: DMA on UART0
That was the right trigger, thanks. I also noticed you need to adapt for the fact that the data register is 32 bits but only holds a single character:
So here I use a stride of 1 to make sure we only advance one byte at a time.
Thanks for the help!
(mod edit for code tags)
Code: Select all
m_controlBlock->TransferInformation = (static_cast<uint32>(dreq) << RPI_DMA_TI_PERMAP_SHIFT) |
(RPI_DMA_DEFAULT_BURST_LENGTH << RPI_DMA_TI_BURST_LENGTH_SHIFT) |
RPI_DMA_TI_SRC_WIDTH | RPI_DMA_TI_SRC_INC | RPI_DMA_TI_DST_DREQ | RPI_DMA_TI_WAIT_RESP;
if (srcStride != 0)
{
// Writes are always a full 32 bit register, but we want to send a different width
// This is a.o. used for UART writes
m_controlBlock->TransferInformation |= RPI_DMA_TI_TDMODE;
m_controlBlock->TransferLength = length << RPI_DMA_TXFR_LEN_YLENGTH_SHIFT | 1 << RPI_DMA_TXFR_LEN_XLENGTH_SHIFT;
}
else
{
m_controlBlock->TransferLength = length;
}
m_controlBlock->ModeStride2D = 0;
m_controlBlock->SourceAddress = ARM_TO_GPU((uintptr)srcAddress);
m_controlBlock->DestinationAddress = dstIOAddress;
m_controlBlock->NextControlBlockAddress = 0;
Thanks for the help!
(mod edit for code tags)
- DougieLawson
- Posts: 43604
- Joined: Sun Jun 16, 2013 11:19 pm
Re: DMA on UART0
Code (any language) works so much better on here between [code]... your code here ...[/code] tags.renebarto wrote: ↑Sun Sep 14, 2025 11:46 pmThat was the right trigger, thanks. I also noticed you need to adapt for the fact that the data register is 32 bits but only holds a single character:So here I use a stride of 1 to make sure we only advance one byte at a time.Code: Select all
m_controlBlock->TransferInformation = (static_cast<uint32>(dreq) << RPI_DMA_TI_PERMAP_SHIFT) | (RPI_DMA_DEFAULT_BURST_LENGTH << RPI_DMA_TI_BURST_LENGTH_SHIFT) | RPI_DMA_TI_SRC_WIDTH | RPI_DMA_TI_SRC_INC | RPI_DMA_TI_DST_DREQ | RPI_DMA_TI_WAIT_RESP; if (srcStride != 0) { // Writes are always a full 32 bit register, but we want to send a different width // This is a.o. used for UART writes m_controlBlock->TransferInformation |= RPI_DMA_TI_TDMODE; m_controlBlock->TransferLength = length << RPI_DMA_TXFR_LEN_YLENGTH_SHIFT | 1 << RPI_DMA_TXFR_LEN_XLENGTH_SHIFT; } else { m_controlBlock->TransferLength = length; } m_controlBlock->ModeStride2D = 0; m_controlBlock->SourceAddress = ARM_TO_GPU((uintptr)srcAddress); m_controlBlock->DestinationAddress = dstIOAddress; m_controlBlock->NextControlBlockAddress = 0;
Thanks for the help!
Languages using left-hand whitespace for syntax are ridiculous
DMs sent on Bluesky or by LinkedIn will be answered next month.
Fake doctors - are all on my foes list.
The use of crystal balls and mind reading is prohibited.
DMs sent on Bluesky or by LinkedIn will be answered next month.
Fake doctors - are all on my foes list.
The use of crystal balls and mind reading is prohibited.
Return to "Bare metal, Assembly language"
Jump to
- Community
- General discussion
- Announcements
- Other languages
- Deutsch
- Español
- Français
- Italiano
- Nederlands
- 日本語
- Polski
- Português
- Русский
- Türkçe
- User groups and events
- Raspberry Pi Official Magazine
- Using the Raspberry Pi
- Beginners
- Troubleshooting
- Advanced users
- Assistive technology and accessibility
- Education
- Picademy
- Teaching and learning resources
- Staffroom, classroom and projects
- Astro Pi
- Mathematica
- High Altitude Balloon
- Weather station
- Programming
- C/C++
- Java
- Python
- Scratch
- Other programming languages
- Windows 10 for IoT
- Wolfram Language
- Bare metal, Assembly language
- Graphics programming
- OpenGLES
- OpenVG
- OpenMAX
- General programming discussion
- Projects
- Networking and servers
- Automation, sensing and robotics
- Graphics, sound and multimedia
- Other projects
- Media centres
- Gaming
- AIY Projects
- Hardware and peripherals
- Camera board
- Compute Module
- Official Display
- HATs and other add-ons
- Device Tree
- Interfacing (DSI, CSI, I2C, etc.)
- Keyboard computers (400, 500, 500+)
- Raspberry Pi Pico
- General
- SDK
- MicroPython
- Other RP2040 boards
- Zephyr
- Rust
- AI Accelerator
- AI Camera - IMX500
- Hailo
- Software
- Raspberry Pi OS
- Raspberry Pi Connect
- Raspberry Pi Desktop for PC and Mac
- Beta testing
- Other
- Android
- Debian
- FreeBSD
- Gentoo
- Linux Kernel
- NetBSD
- openSUSE
- Plan 9
- Puppy
- Arch
- Pidora / Fedora
- RISCOS
- Ubuntu
- Ye Olde Pi Shoppe
- For sale
- Wanted
- Off topic
- Off topic discussion