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.

[参考译文] TMS570LS1224:具有 DMA 的 ADC (spna227)

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1443070/tms570ls1224-adc-with-dma-spna227

器件型号:TMS570LS1224
主题中讨论的其他器件:HALCOGEN

工具与软件:

您好(Jagadish)、

我一直在按照 span227的指示实施具有 DMA 的 ADC。 我需要从特定(单)通道获取20个样本并将其存储到 RAM 中。 为了简化操作、我首先通过单个样本触发 DMA 请求。

Fullscreen
1
2
3
4
5
6
7
8
9
//
// Inside void main()
//
adcInit();
adcREG1->ADG1CHNSELMODECTRL = 0x0A; // enable enhanced channel selection mode for group1
adcREG1->ADG1MAXCOUNT = 1; // 1 conversion total
adcREG1->ADG1CURRCOUNT = 0; // clear group1 current_count counter
adcREG1->G1DMACR = 0x09; // DMA request on group1 conversion end
adcEnableNotification(adcREG1, adcGROUP1);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//
// Inside void main()
//
dmaEnable();
dmaReqAssign(1, 10);
dmaConfigCtrlPacket( ADG1_ptr, // control packet for group1
(uint32)(&adcREG1->GxBUF[1]), // group1 results FIFO
(uint32)(&adc1_G1_results), // group1 results in CPU data RAM
1, // number of frames to be transferred
1, // number of elements per frame
0, // next channel to be chained, 0 = disable chaining
2, // read element size (32 bits)
2, // write element size (32 bits)
1, // transfer type = 1 ==> block transfer
0, // read addressing mode = 0 ==> fixed
1, // write addressing mode = 1 ==> post-incremented
1, // autoinit enabled
0, // read address element index offset = 0
0, // write address element index offset = 0
0, // read address frame index offset = 0
0 // write address frame index offset = 0
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

并在具有足够堆栈分配的任务中打印结果:

Fullscreen
1
2
3
4
5
6
7
8
9
10
//
// Inside task
//
while (1)
{
adcStartConversion(adcREG1, adcGROUP1);
printf("ADC: %u\n", adc1_G1_results[0]);
vTaskDelay(xDelay);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

在处理 每帧不同数量的元素(1、5、20)后、我能够通过调试器看到 DMA 引擎将请求的计数转移到目标 RAM 缓冲区中。 我不使用连续转换-在  以下主题中读取 Sunil Oak 的响应后: e2e.ti.com/.../tms570lc4357-dma-with-adc-in-continuous-mode

遗憾的是、在不改变照明水平的情况下、我从 Launchpad 套件通道6上的光电晶体管得到了非常奇怪的结果。 我知道它会打印整个 uint32 、包括标志和通道 ID、但读数差异仍然很大(在单个恒定通道的上下文中)。 其内容如下所示:

Fullscreen
1
2
3
4
5
6
7
8
9
10
ADC: 0
ADC: 68347
ADC: 68347
ADC: 68347
ADC: 68348
ADC: 2812
ADC: 2811
ADC: 68347
ADC: 2812
ADC: 2811
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

我也很难理解以下内容:

1. ADC 和 DMA 中断通知都不会被触发。 我不仅尝试使用 HALCoGen 功能(如上述代码片段中所示)、还通过在 INT 使能寄存器中分配适当的位字段值进行了尝试。

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel)
{
sciSendByte(scilinREG, 'D');
return;
}
void adcNotification(adcBASE_t *adc, uint32 group)
{
sciSendByte(scilinREG, 'A');
return;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

我的 GIO 和 SCI 中断(FIQ/IRQ)能够正常工作(在 FreeRTOS 环境中)。

2. API 中提及的 ADC 存储对象与 TRM 之间的关系是什么:

  • (API)  GxBUF[...] -数组(8 *(uint32_t))=(8 * 4字节)=每组32字节
  • (TRM) ADC FIFO RAM -"转换结果存储在 a. 64字存储器 (SRAM)。" 这意味着总共64 * 4 = 256个字节、每个组~85个字节
  • (TRM)"ADBNDEND 包含一个名为 BNDEND 的3位字段、用于配置可用总存储器。 满量程
    模块最多可支持1024个缓冲器。 该器件最多支持对两个 ADC 使用64个缓冲器
    供电"。

3.基于上述情况, DMA 传输应该考虑哪些因素? 如何配置 ADC FIFO 以实现最佳的 DMA 传输效率?

我希望我的帖子不是那么压倒性,但我真的花了大约一个星期的研究,我是无处可去。

非常感谢使用任何其它最新的示例代码。。。

感谢您的理解和诚挚的问候、

Varban

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

    您好、Varban、

    我的建议是尝试在 ADC DMA 中使用以下重点方法。

    您每次正确地需要20个样本、所以将块大小配置为 20个、这样 DMA 将在20次转换后获得 ADC 触发。 一旦 DMA 从 ADC 获得触发信号、我们应配置 DMA、使其元素数量为1、帧数为20、一旦我们执行此操作、DMA 将把所有这20个转换结果从 ADC 存储器传输到 RAM。 一旦 DMA 完成20个转换结果的传输、它将触发您一个块传输完成中断。

    一旦您获得 DMA 块传输中断、您就可以在由 DMA 移位的 RAM 中对 ADC 数据执行所需的操作。

    我没有任何直接的例子、但我会尝试在您的终端上实现、如果您在实现过程中遇到任何困难、我会尝试进一步为您提供帮助。

    ——
    谢谢、此致、
    Jagadish。

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

    已编辑

    尊敬的 Jagadish:

    感谢您的指导、并对我的延迟响应表示抱歉。

    以上就是我对建议方法的理解。 基于以下 HALCoGen 配置:

    我写了以下内容:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    xTaskHandle xUserTaskHandle;
    void vUserTask(void *pvParameters)
    {
    const TickType_t xDelay = 500 / portTICK_PERIOD_MS;
    uint16_t n = 0;
    while (1)
    {
    adcStartConversion(adcREG1, adcGROUP1);
    for (n = 0; n < ADC_SAMPLE_COUNT; n++)
    {
    printf("[%u] Ch: %u, ADC: %u\n", n,
    (uint32)((adc1_G1_results[n] >> 16U) & 0x1FU), // Channel ID
    (uint16)(adc1_G1_results[n] & 0xFFFU)); // Value
    }
    printf("----------------\n");
    vTaskDelay(xDelay);
    }
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    和 ADC DMA 配置寄存器的"缩放":

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #define ADC_SAMPLE_COUNT 32U // Equal to the configured FIFO size in HALCoGen
    ...
    adcREG1->G1DMACR = (1U << 0U) | // G1_DMA_EN - ADC module generates a DMA transfer when the ADC has written to the Group1 memory. G1_BLK_XFER bit must be cleared to ‘0’ for this DMA request to be generated.
    (1U << 2U) | // G1_BLK_XFER - ADC module generates a DMA request when the ADC has written G1_BLOCKS number of buffers into the Group1 memory.
    (1U << 3U) | // DMA_G1_END - ADC module generates a DMA request when the ADC has completed the conversions for all channels selected for conversion in the group1.
    (ADC_SAMPLE_COUNT << 16U); // G1_BLOCKS - One DMA request is generated if the G1_BLK_XFER is set to ‘1’ and the specified number of Group1 conversion results have been accumulated
    // ADC_SAMPLE_COUNT = 32U, equal to the configured FIFO size inside HALCoGen
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    尽管我最后遇到了 DMA 传输、但我仍然有以下问题和观察结果。

    1.缓冲区内容

    在我最初的错误之后、在循环中使用硬编码索引0进行了编辑(抱歉、混淆了)。

    结果如下:仅对一个值进行采样、缓冲器中的所有其他值都是0。

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ----------------
    [0] Ch: 6, ADC: 420
    [1] Ch: 8, ADC: 0
    [2] Ch: 8, ADC: 0
    [3] Ch: 8, ADC: 0
    [4] Ch: 8, ADC: 0
    [5] Ch: 8, ADC: 0
    [6] Ch: 8, ADC: 0
    [7] Ch: 8, ADC: 0
    [8] Ch: 8, ADC: 0
    [9] Ch: 8, ADC: 0
    [10] Ch: 8, ADC: 0
    [11] Ch: 8, ADC: 0
    [12] Ch: 8, ADC: 0
    [13] Ch: 8, ADC: 0
    [14] Ch: 8, ADC: 0
    [15] Ch: 8, ADC: 0
    [16] Ch: 8, ADC: 0
    [17] Ch: 8, ADC: 0
    [18] Ch: 8, ADC: 0
    [19] Ch: 8, ADC: 0
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    我还尝试了 adcResetFiFo()在 adcStartConversion()之前和之后-行为(缓冲区内容)是完全相同的。

    2. G1_Blocks 的值

    我注意到 adcStartConversion()将 G1_Blocks 从32U 更改为31U。 然后、寄存器"自动"恢复到32U:

    这是否正常?

    3. G1_DMA_EN 位

    当 G1_DMA_EN 位为0或1时、我在程序行为上没有观察到任何差异。 此场景的推荐配置应该是什么?

    谢谢。此致、

    Varban  

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

    您好!

    我最终通过激活 adcREG1、adcGROUP1中的所有通道并将 FIFO 大小设置为等于通道数量(在本例中为- 24)来运行 DMA。

    然后,在 非连续模式下调用 adcStartConversion()后, ADC 一次性获取 FIFO 中的所有通道读数,并向 RAM 触发一个 DMA -传输所有24个 uint32_t 值。

    这看起来我最初要寻找的(读取单个通道 N 次、填充队列并在 FIFO 满事件时触发 DMA)根据设计是不可能的、如果我错了、请纠正。

    谢谢。此致、

    Varban

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

    您好、Varban、

    您能否参考以下示例配置和代码:

    e2e.ti.com/.../ADC_5F00_with_5F00_DMA_5F00_RM46.zip

    在上面的工程中、我能够使用 DMA 将通道6的20个样本成功传输到另一个 RAM 缓冲区。

     

    我认为与您项目的主要区别在于、我在这里启用了连续转换模式、而不是单次转换模式。

    我启用此功能是因为如果不启用这种连续转换模式、每当我们发出开始转换命令时、通道6数据始终存储在 ADC RAM 存储器的单个位置。

    我想这只是预期、我的意思是单次模式只会对所有已启用的通道执行一次转换、并会将数据存储在 ADC RAM 中。 如果我们启用第6个通道、则每次仅在 RAM 的第一个位置存储其数据。

    ——

    谢谢、此致、
    Jagadish。

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

    尊敬的 Jagadish:

    感谢您的答复!

    在连续模式下的观察结果是完全相同的。

    然而、仍然不建议将 DMA 与 连续 模式一起使用、如 在本主题中所述: e2e.ti.com/.../tms570lc4357-dma-with-adc-in-continuous-mode?

    此致、

    Varban

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

    您好、Varban、

    [报价 userid="208956" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1443070/tms570ls1224-adc-with-dma-spna227/5545796 #5545796"]然而、是否仍然不建议将 DMA 与 连续 模式配合使用、正如 在本主题中所说的那样: e2e.ti.com/.../tms570lc4357-dma-with-adc-in-continuous-mode?

    我 认为这是正确的。

    即使您也验证我的转换结果、您也可以看到、对于最后4次转换、已设置空标志:

    正如他们所说的、 在连续模式与 DMA 之间似乎存在一些时序问题。

    此外、当我们为此转换模式选择单通道时、转换将很快发生。

    正如您看到的、一个通道的转换时间仅为1.6us、这意味着我们将以每1.6uS 速率获取样本。 我想我们不需要具有如此低间隔的样本。

    因此、他们倾向于使用计时器或 PWM 来生成样片。

    ——
    谢谢、此致、
    Jagadish。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您可以看到一个通道的转换时间仅为1.6us、这意味着我们将每1.6uS 获取一次样片。 我想我们不需要具有如此低间隔的样本。[/报价]

    从我所观察到的情况来看、在 DMA 情况下、可能需要一些基于中断的状态机(以指示新的传输完成)、而中断(即使具有非常简单和快速的处理)也可能会使 RTOS 流受阻。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [报价 userid="208956" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1443070/tms570ls1224-adc-with-dma-spna227/5548403 #5548403"]并且从我观察到的内容来看-如果是 DMA、可能需要基于中断的某种状态机(用于指示新的传输完成)、而中断(即使是非常简单和快速的处理)也可能会阻塞 RTOS 流程。[/QUET]

    也许你是对的、但我从未在 RTOS 环境中测试过 DMA。