This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C129ENCPDT:TM4C129ENCPDT UDMA 连续传输

Guru**** 2032800 points
Other Parts Discussed in Thread: TM4C129ENCPDT, EK-TM4C1294XL
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1158122/tm4c129encpdt-tm4c129encpdt-udma-continuous-transfer

器件型号:TM4C129ENCPDT
Thread 中讨论的其他器件: EK-TM4C1294XL

您好!

我需要配置 TM4C129ENCPDT 微控制器、以便通过 UDMA 将16位字从 RAM 缓冲器传输到 EPI。 每个字传输都必须在通用定时器(GPTM)以周期模式运行的情况下触发(定时器 DMA 超时事件)。 使用的通用定时器将持续产生超时事件、并且 uDMA 通道还必须将字连续移动到 EPI、当字传输计数达到最大值时、源地址必须自动回绕到 RAM 缓冲区、并持续重复缓冲区。 我知道 C2000系列微控制器 DMA 具有这种操作模式、但我不知道是否可以使用 Tiva C UDMA 实现它。

我已经通过设置 DMA 控制表任务列表、使用散聚模式实施并测试了持续的 uDMA 传输、其中第二个任务是重新加载用于缓冲区传输的 uDMA 通道配置:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define EPI_PORTA_PINS (GPIO_PIN_7 | GPIO_PIN_6)
#define EPI_PORTB_PINS (GPIO_PIN_3)
#define EPI_PORTC_PINS (GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4)
#define EPI_PORTG_PINS (GPIO_PIN_1 | GPIO_PIN_0)
#define EPI_PORTK_PINS (GPIO_PIN_5 | GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0)
#define EPI_PORTL_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0)
#define EPI_PORTM_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0)
#define EPI_PORTQ_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0)
#define EPI_PORTP_PINS (GPIO_PIN_3 | GPIO_PIN_2)
uint32_t sys_clk;
static uint16_t src_buf[1024];
#pragma DATA_ALIGN(udma_control_table, 1024)
tDMAControlTable udma_control_table[1024];
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

这种配置似乎可以正常工作、但问题在于、在散聚模式下、配置重新加载事件会增加一个额外的暂停来继续向 EPI 传输数据流、尤其是当我需要尽快将数据流式传输到 EPI 而不暂停时。 同时、字传输周期必须由通用定时器控制。 那么、我需要知道是否有任何其他 UDMA 配置可启用持续数据传输、其中原子源地址自动换行和传输计数复位发生在 DMA 硬件中?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Mark、您好!

    我不确定传输计数、但地址换行似乎可以这样处理:

    μ μDMA 控制器在主控制结构体从列表中拷贝下一个传输指令、然后执行新的传输指令之间交替切换。 通过将最后一个条目的控制字编程为使用自动传输模式来标记列表的末尾。 在自动模式下完成最后一个传输后、μ μDMA 控制器将停止。 只有在最后一次传输结束后才会产生一个完成中断。 可以通过将最后一个条目复制到主控制结构体以指向列表的开头(或指向新列表)来循环列表。

    您是否尝试过这种方法? 我以前没有亲自测试过该功能、但对我来说、它看起来就像您在尝试在那里执行的操作一样。

    另一种可能是您可以使用乒乓模式。 我不确定这是否适合您的用例、但我想强调一下、以防万一。

    在乒乓模式下、通常会有两个缓冲区、DMA 会在它们之间无缝跳转、在缓冲区从一个缓冲区弹出到另一个缓冲区后、您会收到一个中断、指示您需要加载未随下一批处理数据一起传输的缓冲区。 这将导致数据流的无限期、一致。 在这种情况下、如果您从 RAM 读取数据、我认为这可能仍然有效、因为您不提供缓冲区地址、而是只提供一个 RAM 地址、该地址会随每个周期更新。 此外、您还可以保留传输计数、因为当您将下一个通道交换到新的 RAM 地址时、每个中断都会标记一定数量的传输已完成。

    请告诉我您对这些可能解决方案的可行性有何看法。

    此致、

    Ralph Jacobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="189615" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1158122/tm4c129encpdt-tm4c129encpdt-udma-continuous-transfer/4355308 #4355308"]通过将最后一个条目复制到主控制结构体中以指向列表的开头(或指向新列表),可以循环显示列表。


    是的、我已经尝试过此解决方案、它可以正常工作、但我的问题是 DMA 配置重新加载会导致额外的暂停。 也许您可以提供示例代码、说明如何初始化 tDMAControlTable 的任务列表、其中 最后一个条目复制主控制结构体指向该列表的开头。 可能是我的代码中的任务列表不是最佳的?
    我还尝试了乒乓模式、但每次主缓冲器或辅助缓冲器传输完成时、DMA 通道都会停止、并进行 ISR 调用、在此期间我应该为下一次传输重新配置 DMA (请参阅 M4C1294NCPDT 微控制器数据表中第686页的图9-2、并参考 TivaWare 示例 UDMA_DEMON.c 中的示例代码)。 我未能让 DMA 通道在主缓冲器和备用缓冲器之间连续交替工作-每次缓冲器传输完成 DMA 都会停止。 您能给我 一个乒乓模式示例吗  ?我应该如何配置 DMA 通道、以便它能够在两个缓冲器之间持续交替?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Mark、您好!

    我不相信我有一个现成的示例用于存储器散聚放循环、所以如果你可以发布你到目前为止所做的事情、这实际上会让我有一个头头开始。 我之前没有使用这种环路执行存储器散聚示例。

    尽管我在再次阅读描述时说过这一点、但我不确定循环列表实际上会导致它循环而不停止。 明天我也会深入探讨这一点。

    对于乒乓示例、您应该能够参考以下示例: [INSTALL Path]\TivaWare_C_Series-2.2.0.295\examples\boards\ek-tm4c1294xl\adc_udma_pingpong

    此示例设置主和副传输通道。 然后、ADC 启动后、它开始填充主通道。 一旦缓冲区已满、就会触发一个中断-当主缓冲区处于停止模式时、副缓冲区会在该时间开始填充。 当副填充时、缓冲区数据被处理、然后缓冲区被再次视为空。 此时、主器件的下一个传输被配置。 然后、当替代项填充时、主项现在已重新启用、因此它开始将数据流化、而相同的数据处理随后会与该备用项发生。

    这至少会导致您在乒乓模式下寻找的连续流。

    此致、

    Ralph Jacobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Ralph、

    从 TivaWare Expa ADC UDMA Ping-Pong 中可以看出、在一次侧或二次侧传输完成后、必须在主循环中重新启用 UDMA 通道。 所以对我来说,如果 CPU 通过 调用 uDMAChannelTransferSet()和 uDMAChannelEnable()来重新启用下一个传输,那么 UDMA 似乎不能在缓冲区之间持续交替。

    我还尝试 过 UDMA 乒乓模式、但主要问题是、如果其中一个主传输或备用传输完成、UDMA 通道总是停止-如果 UDMA 通道可以自动切换到硬件中的 alt/主传输、那么它就能完美工作。

    我在 初 始帖子提供的示例中实现了采用循环方法的存储器散聚、您可以尝试使用该方法。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Mark、您好!

    [引用 userid="539342" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1158122/tm4c129encpdt-tm4c129encpdt-udma-continuous-transfer/4358227 #4358227"]Form TivaWare Expple ADC UDMA Ping-Pong 我看到在主次传输完成后、必须在主循环中重新启用 UDMA 通道。 因此、对于我来说、UDMA 似乎无法在缓冲区之间持续交替、除非 CPU 通过调用 uDMAChannelTransferSet()和 uDMAChannelEnable()?[/quot]来重新启用下一个传输

    因此、我将尝试并详细解释该示例所做的工作。

    首先、我们配置 UDMA、使主 控制结构体和副控制结构体 都分配了一个缓冲区、并将其设置为从 ADC0采样序列0 FIFO 接收数据。 然后启用 UDMA 和 ADC。

    当 ADC 采样并填充 FIFO 时、它会在 FIFO 填充时标记 UDMA 以传输数据。 UDMA 会一直运行、直到其中一个缓冲区已满。

    此时、会发生三件事情:

    1. 主控制结构体指示其上存在 UDMA_STOP 条件
    2. 会触发一个中断以警告 MCU UDMA 已填充缓冲区、并且没有用于更多数据的可用空间
    3. 由于替代控制结构体已经被初始化并准备好进行传输、因此 UDMA 控制器自动切换到替代控制结构体以继续填充 ADC 数据

    现在、在应用中、当替代结构被填充时、中断可被处理并且主应用循环被告知主控制结构体已充满 ADC 数据。

    应用程序处理该数据、然后将主控制结构配置为准备接收更多数据并重新启用。

    只要在副缓冲器已满之前完成此操作、那么当副控制结构体填满缓冲器时、将会发生相同的三个步骤、但对于副控制结构体、 UDMA 将看到主设备已准备好进行传输、因此它会自动切换到该主设备。

    因此、当您确实必须在缓冲区已满后重新启用通道时、除非您的缓冲区已满、否则切换始终会自动完成、否则您没有机会重新启用下一个 UDMA 传输。

    此致、

    Ralph Jacobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Mark、您好!

    为了在散聚器件上回圈、在与我的同事查看数据表后、我们 共同评估 了 UDMA 控制器的设计是始终在散聚模式下停止、而不管回路是否正确。 这是因为没有任何方法可以向 UDMA 控制器指示、因为结束地址与起始地址相同、所以它可以不停地继续。 因此、微控制器需要告诉它可以继续传输数据。

    希望乒乓方法最终能够为您提供支持、否则、我相信 uDMA 将无法满足您的具体需求。

    此致、

    Ralph Jacobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     您好、Ralph、

    感谢 您的解释。 我尝试 根据示例 ADC_UDMA_pingpong 修改我的示例、但注意到我必须使用外设 ISR 而不是 UDMA ISR。 我 的目的是使用周期性计时器触发从 RAM 到 EPI 的 UDMA 数据字复制(当前使用 UDMA_CHANNEL TMR0B DMA 通道)-您能不能建议在乒乓模式下实现这一目标的最佳解决方案是什么?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Mark、您好!

    我希望 ADC 乒乓示例所采用的方法与单个 tweak 相同。

    EPI 接口具有用于 UDMA 写入/读取传输的中断功能、因此应启用该功能并将其用于标志控制结构体需要重新启用。 同时、计时器可以独立运行以触发数据副本。

    我们提供的 ADC 示例的工作原理与此类似。 ADC 设置为触发中断、我们实际上为 ADC 采样序列0中断提供服务、以处理 UDMA 已填充缓冲区、因此没有运行专用的 UDMA ISR。 同时、计时器配置为以设置的频率对 ADC 进行持续采样。

     您的用例的不同 之处在于、ADC 用例中的计时器作为外设配置的一部分直接进入 ADC 外设。 在您的情况下、计时器不会自动插入 UDMA 以仅在后台运行、而是需要计时器 ISR、它会触发 UDMA 字复制。 触发后、EPI 中断将在一个包含一个缓冲区的副本完成后触发、您可以确定需要重新启用哪个控制结构来保持连续传输、直到完成这组传输。

    此致、

    Ralph Jacobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

     您好、Ralph、

    我根据您的建议实施了该代码,并使其在连续交替模式下工作,Timer0B 将触发频率为125kHz 的 ISR,其中为 EPI0 DMA 通道发出 uDMAChannelRequest()。 然后在64个字被传输后 、EPI0IntHandler() ISR 被调用、其中重新启用下一个 pri/alt 传输:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #define EPI_PORTA_PINS (GPIO_PIN_7 | GPIO_PIN_6)
    #define EPI_PORTB_PINS (GPIO_PIN_3)
    #define EPI_PORTC_PINS (GPIO_PIN_7 | GPIO_PIN_6 | GPIO_PIN_5 | GPIO_PIN_4)
    #define EPI_PORTG_PINS (GPIO_PIN_1 | GPIO_PIN_0)
    #define EPI_PORTK_PINS (GPIO_PIN_5 | GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0)
    #define EPI_PORTL_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0)
    #define EPI_PORTM_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0)
    #define EPI_PORTQ_PINS (GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 | GPIO_PIN_0)
    #define EPI_PORTP_PINS (GPIO_PIN_3 | GPIO_PIN_2)
    uint32_t sys_clk;
    static volatile uint16_t *g_par_port_ptr = (uint16_t *)0xA0000000;
    static uint16_t src_buf[1024];
    #pragma DATA_ALIGN(udma_control_table, 1024)
    tDMAControlTable udma_control_table[1024];
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
     

    在此实施方案中、我有几个问题:

    1) 1) UDMA 传输 通过 Timer0B ISR 触发、当我需要将计时器频率从125kHz 提高到2MHz 时、CPU 必须为太多的计时器 ISR 提供服务、这将限制 DMA 字的传输 速度。 是否还有其他选项可以在没有 ISR 的情况下将 Timer0B 周期性中断传递给该 DMA 通道、例如使用 GPIO UDMA 触发  器、其中计时器输出从外部连接到触发 UDMA 传输的 GPIO 输入?
    2) 2)发生 pri / alt 传输 切换时、字传输在事件周围不会定期一致、您可以看到、在最后一个字传输之后 、在第一个字传输开始时 、句点不同。

    在图像上、第一个图是数据(16位)、地址(8位)、EP-CLK、CS、RD、 WR

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Mark、您好!

    [引用 userid="539342" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1158122/tm4c129encpdt-tm4c129encpdt-udma-continuous-transfer/4364698 #43646989"]2)发生 pri / alt 传输 切换时、字传输在事件周围不会定期保持一致、您可以看到、在最后一个字传输 之后、在开始的第一个字传输 时、句点不同。

    这并不奇怪、因为 DMA 控制器既发出中断、又进行交换、这需要几个时钟周期、因此没有办法解决这个问题。

    1~) uDMA 传输 通过 Timer0B ISR 触发、当我需要将计时器频率从125kHz 提高到2MHz 时、CPU 必须为太多的计时器 ISR 提供服务、这将限制 DMA 字的传输 速度/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1158122/tm4c129encpdt-tm4c129encpdt-udma-continuous-transfer/4364698。 是否有任何其他选项可以在没有 ISR 的情况下将 Timer0B 周期性中断传递到此 DMA 通道、例如使用 GPIO uDMA 触发器、其中计时器输出从外部连接到触发 UDMA 传输的 GPIO 输入?[/QUERPLET]

    我不确定您获得的传输速度是多少、但2MHz 似乎非常快、能够通过 DMA 传输数据、具体取决于您发送的数据量。 该器件以120MHz 运行、因此您会在该点每60个时钟周期中断一次。 可能有一个用例我不理解、但我想您要发送一个缓冲区、例如 256 字节缓冲区、该缓冲区现在拆分为128字节用于主/备用通道、并提示传输根据需要进行。 因此、您将以可以触发下一次传输的速度运行计时器。 我看不到这样的情况会如何在2MHz 计时器速率下进行升级。

    这偏离了一些基本答案、但想表达我对用例的理解。

    答案本身就是、在乒乓模式下、我看不到一种实现您所描述的方式。 DMA 传输实际上是三种类型中的一种: 存储器到存储器、存储器到外设和外设到存储器。 这对于理解它可能无法正常工作的原因非常重要

    在散聚模式下、您可以在多个外设到存储器的情况下执行某种操作、这正是该模式的关键所在、但即使如此、我也不确定散聚模式是否支持定时器--> DMA -->触发猝发写入缓冲器--> DMA --> EPI。 我没有听说过这样的工作、但我没有尝试证明它不工作。 通常情况下、它类似于 ADC0到缓冲器[0]、ADC1到缓冲器[1]、... ADCx 到缓冲器[X]、并且不使用一个外设触发从存储器到另一个外设的数据发送。 但是、如已建立的那样、此时您将丢失持续的数据传输。

    对于乒乓模式,这是不可能的,因为您正在对内存执行单个外设操作,或者对 单个外设执行 memory*操作。 由于您要求 将两个外设和一个存储器缓冲器绑定在一起、因此无法支持这三个外设的乒乓模式。  图9-2也说明了这一点。 乒乓式 μ μDMA 传输的示例、它侧重于单个外设控制结构体、因此无需包含其他支持定时器和 EPI 的控制结构体。

    此致、

    Ralph Jacobi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你(们)好  

    感谢你的帮助。

    我正在寻找一种解决 方案、在该解决方案中、我可以通过 EPI 接口定期将数据写入并行 DAC、这需要以统一的周期进行更新。 我使用 DMA+EXTIF+DAC 在 C2000系列微控制器中也成功实现了类似的应用
    由于我现在已经针对持续 DMA 传输测试了两种 DMA 模式、我认为我们可以关闭这个线程。