Understanding the Tiva DMA

In this tutorial i will explain the TM4C1294NCPDT DMA transfer modes, channels, triggers, etc. For even more detail on the DMA remember to consult the datasheet. I will skip over the transfer mode "Scatter-Gather". This is to use with TivaWare so registers will barely be referred

I don't have a script to jump to the topics but i have them by color to help to easily tell them apart and here are the names so it's easy to find them with CTRL+F.

Topics:

What is DMA and what does it do?

The channels and triggers

Arbitration Size and Transfer size

Let's see what transfer modes we have

What is DMA and what does it do?

DMA stands for Direct Memory Access. It allows peripherals to access the memory without having to go through the processor.

Normally for you to receive something like receive UART burst information, you need the processor to interrupt every time data is received or the receive FIFO is half full and then save that data in the memory for later use. It's a burst receive so you can receive allot of data and keep doing this over an over again before you have all the data and then use it.

Well the DMA helps with just that. The DMA allows the UART to trigger the DMA to empty the receive FIFO when it's half full and save the data in the memory. This without the processor not having to do anything besides configuring in the beginning the DMA and UART to work like that. Then in the end you have all the data ready to use, all that while the processor was busy doing something more interesting that simply being a bus driver for the data bus for alot of cycles.

Well this is what the DMA is for. Transferring data from the memory to peripheral but i can also:

  • Transfer data from memory region to memory region.

  • Transfer data from memory to peripheral

Now let's see the specs of the Tiva DMA.

Like most ARM-M4, the Tiva has a pretty good DMA. It has the folowing features:

  • ARM® PrimeCell® 32-channel configurable μDMA controller

  • Support for memory-to-memory, memory-to-peripheral, and peripheral-to-memory in multiple transfer modes

    • Basic for simple transfer scenarios

    • Ping-pong for continuous data flow

    • Scatter-gather for a programmable list of up to 256 arbitrary transfers initiated from a single request

  • Highly flexible and configurable channel operation

    • Independently configured and operated channels

    • Dedicated channels for supported on-chip modules

    • Flexible channel assignments

    • One channel each for receive and transmit path for bidirectional modules

    • Dedicated channel for software-initiated transfers

    • Per-channel configurable priority scheme

    • Optional software-initiated requests for any channel

  • Two levels of priority

  • Design optimizations for improved bus access performance between μDMA controller and the processor core

    • μDMA controller access is subordinate to core access

    • RAM striping

    • Peripheral bus segmentation

  • Data sizes of 8, 16, and 32 bits

  • Transfer size is programmable in binary steps from 1 to 1024

  • Source and destination address increment size of byte, half-word, word, or no increment

  • Maskable peripheral requests

  • Interrupt on transfer completion, with a separate interrupt per channel

Pretty cool specs, although i'm a bit disappointed with the 1024 total transfer limit

Let's get a bit into more detail now

The channels and triggers

The DMA has 32 channels but what is that? Each channel can have a different configuration from each other at the same time allowing for example the channel 0 can transfer data out of the UART receive FIFO while the channel 1 transfer data out of the SSI receive FIFO. Don't worry they won't confuse each other if they are clogging the bus trying to access the RAM. The channels have order of priority depending on it's number, channel 0 has the highest priority. You can also set a channel to be a High Priority channel.

Each channel has also specific DMA triggers that cause a DMA transfer to happen, Ex: the UART receive FIFO being half full triggers the DMA to take data out of it.

Now we have triggers? What are those?

Triggers are events that can cause a DMA transfer to happen. You configure a DMA channel to transfer data from point A to point B 1 item, 1024 times and wait for a trigger to do that 1 item transfer, up to 1024 times. The triggers can be various events each peripheral has it's own types of triggers but each peripheral only has 1 channel specific channel that it can use. You can also generate a trigger through software, but that is more useful for the Auto transfer mode, we will get more into transfer modes later.

μDMA Channel Assignments (table 9.1 and respective continuation from the datasheet)

In the table above you can see which channels can be triggered by which peripheral. Note that a channel can only be configured to be triggered by 1 peripheral at once.

Types of request by trigger

You maybe notice in the table above (9.1) a column called "Type" and that it can be B, SB or both. Well what is that?

That is the type of request that peripheral can make to the DMA. B stands for Burst and SB stands for Single Burst.

  • Single Burst means that the peripheral is ready to transfer just 1 item. The DMA will transfer that 1 item and then stop and wait for other request

  • Burst means that the peripheral is ready to transfer multiple items. The DMA will transfer the number set in the Arbitration Size wich can be from 1 to 1024, take note i will talk about that later.

Types of request by trigger table (table 9.2 and continuation from the datasheet)

Arbitration Size, Transfer size and other transfer options.

I already referred it and now i'll explain it since it's necessary to understand the transfer modes.

The Arbitration size is the number of transfers the DMA does per trigger unless if the channel is configured to Auto transfer mode

The Transfer size is the total number of transfer that you can configure a DMA channel to make, up to 1024 due to having a 10bit counter.

The Arbitration size is the number of items transferred per trigger. It decrements the Transfer size until it reaches 0, when it does it stops the DMA transfer. Some modes will ignore the Arbitration size.

The DMA also has the option to chose the items size. It can be 8bits, 16bits or 32 bits.

It also has the option to increment the source and destination address after each transfer and it can be 8bits, 16bits or 32bits and it doesn't matter the item size yo chosed. You can have 8bit items and chose a incrementation of 32 bits.

More preparations for the transfer modes,

The Channel Configuration

Well normally you configure everything in a peripheral operation in the registers right? Well in the DMA you also need a control table. You can check which registers the DMA has in the "Table 9-13. μDMA Register Map" in the datasheet under "μDMA Registers", but here i will talk about the control table.

The control table needs to contiguous and aligned on a 1024-byte boundary (so an array of 1024 uint8_t) and contains the source and destination pointers, transfer size, and transfer mode for each channel. Here is how the channel data is organized in the table:(taken from the datasheet)

You can see that there is a reference to Primary and Alternate. That is because you can have 2 configurations setup at the same time. That will be explained why in the transfer modes.

If you use a transfer mode that doesn't use the Alternate Control Structure then you can have the control table to just be 512 in size but usualy you won't need so much RAM that you need to make the control table smaller (Maybe in scatter-gather you would need that but this tutorial won't get into that). You can also make the table smaller if for example you only use channel 6, then you can not have the part of channel 7 and above.

Now let's get into each channel configuration space. Each has a 16-byte boundary, containing 4 long words (32bits) which are the source end pointer, the destination end

pointer, the control word, and an unused entry. The end pointers point to the ending address of the transfer and are inclusive. If the source or destination is non-incrementing (as for a peripheral register), then the pointer should point to the transfer address.

The control word has various fields:

    • Source and destination data sizes

    • Source and destination address increment size

    • Number of transfers before bus arbitration

    • Total number of items to transfer

    • Useburst flag

    • Transfer mode

Let's see what transfer modes we have

Wich ones do we have?

  • Stop Mode

  • Basic Mode

  • Auto Mode (remember this in "The channels and triggers?)

  • Ping-Pong

  • Scatter-Gather, more specifically, (this won't be explained here, please consult the datasheet for more info)

    • Memory Scatter-Gather

    • Peripheral Scatter-Gather

Stop Mode

Stop mode doesn't actually do a transfer. When the mode field has the value to stop then it doesn't do a transfer and disables the DMA. At the end of a transfer the mode field automatically changes to that and disables the DMA

Basic Mode

In Basic mode the DMA transfers items while there are more items to transfer and the transfer request is present. In this mode a transfer is only started when the configured trigger happens and the transfer size per trigger depends on the Arbitration size. This type of mode is better to be used with peripheral triggers, this is because it only transfers a set number of items (Arbitration size) when the peripheral says he's ready (the trigger).

Now let's see a case where the DMA channel is configured with a Transfer size of 1024 and a Arbitration size of 1, while on Basic Mode. This loads a value into the transfer counter of 1023. Each time a trigger happens the DMA transfers 1 item and decreases the counter by 1. This until the counter reaches 0 or the processor stops it. When it reaches 0 the DMA stops by setting the transfer mode to Stop mode.

Auto Mode

Auto mode is very similar to the basic mode but istead it transfers all the number of items set in Transfer size, ignoring Arbitration size and then stops by setting the transfer mode to Stop mode. This also ignores if the request is removed. This is better for software triggers where you just want to transfer all the items with 1 request.

Ping-Pong

Now Ping-Pong mode. Ping-Pong is similar to the Basic Mode. It transfers a number of items set in Arbitration size when a trigger happens. But this mode is for continuous data flow. Sometimes 1024 transfers is just not enough like in my RGB Matrix project with the WS2812. This is better than having Basic mode and setting it up again because that would leave a dead time between stopping and restarting.

How does it work?

Well remember in the Control Structure that there was a Primary and Alternate control structure for each channel? The Ping-Pong mode uses those 2 structures.

You set up the Primary like you would in Basic mode but now you set it up has Ping-Pong. Then you do the same but with the Alternate control structure. When the primary control structure transfer stops it generates a interrupt (you have to enable it of course) and starts the Alternate control structure transfer. In the interrupt you can setup again the Primary control structure so when the Alternate ends, it goes back to the primary. You can do this over and over again if you want to keep data flowing without limit.

Example of Ping-Pong μDMA Transaction (from datasheet)

Well that is pretty much it. I hope this helped you with the understanding of the DMA channel.

Maybe next time i will create a tutorial about more complex features like the Scatter-Gather.