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.

[参考译文] MSP432E401Y:是否快速重新启用已配置的 DMA 操作?

Guru**** 2582405 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/777848/msp432e401y-fast-re-enable-of-already-configured-dma-operation

器件型号:MSP432E401Y
主题中讨论的其他器件:MSP432P401R

我设置了一个 PWM 中断(PWM 刚刚用于计时) 来执行虚拟 SSI 写入、该写入会执行整个 SSI 事务、从而使我从 FIFO 中的从器件进行的读取可用。  我正在尝试使它尽可能快。

我正在尝试尽可能缩短这段总 ISR 时间(中断延迟+ SSI 写入+ SSI 等待+ SSI 读取)、并且尝试使用 DMA 完全删除 SSI 等待和 SSI 读取、只是在下一个 ISR 开始时抓取之前的读取。  我使用 HWREG 读取/写入简化了 ISR 处理代码和 SSI 处理代码、以避免开销调用驱动程序函数、但似乎找不到与 DMA 等效的代码。

如果我执行以下操作、它将起作用:

MAP_uDMAChannelTransferSet (UDMA_CH12_SSI2RX | UDMA_PRI_SELECT、
UDMA_MODE_BASIC、
(void *)(&SSI2->DR)、
Receive_data、3);

MAP_uDMAChannelEnable (UDMA_CH12_SSI2RX); 

但我似乎找不到 HWREG 等效运算。  我看到 ChannelTransferSet 和 ChannelEnable make 的唯一更改是控制表中的单字节、因此是 UDMA_ENASET。  如果我尝试将单字节写入控制表并设置使能位、它将不会继续运行。

DMA 中是否缺少其他内容?  可能是对控制表的完全写入、还是对 DMA 本身进行某种控制表传输?  我在这两个驱动程序调用中看不到任何暗示这一点的东西。

谢谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    或者、如果有一种方法可以禁用 DMA 复位以在一个3字节传输后停止(并且只等待下一个 SSI DMA 请求)、这将是理想情况。 此事务需要无限期地发生、因此除了手动启动或停止它之外、实际上无需代码干预。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 James、

    [引用 USER="James McLaughlin ]但我似乎找不到 HWREG 等效运算。  我看到 ChannelTransferSet 和 ChannelEnable make 的唯一更改是控制表中的单字节、因此是 UDMA_ENASET。  如果我尝试将单字节写入控制表并设置使能位、它将不会继续运行。

    您是否在文件夹/source/ti/devices/msp432e4/driverlib?中查看了 uDMAChannelTransferSet API 的实现  它更新了源地址末指针、目标地址末指针和通道控制字;换句话说、控制表中的整个通道控制结构体。

    我不建议对这样复杂的 API 进行直接存储器存取。 您可以尝试将代码复制到您自己的函数(如 myUDMAChannelTransferSet)中、并将其内联以查看这是否适用于您的用例。

    谢谢、

    SAI

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

    您好、Sai、

    我尝试仅使用 API 的必要部分、是的、这就是我询问重新启用 DMA 的最低写入量是多少。

    我确实看到了该源文件、并且监控了通道控制结构体中的所有3个项目。  只有一个字节发生了变化、但仅仅写入该字节并重新启用 UDMA 似乎不起作用。

    DMA 是否确实需要写入全部3个项目?  或者、我可以做一些更小的结构值子集吗?

    重点是缩短处理时间、因此我不必执行的任何写入都很有用、即使它只有1个字与3个字或1个字节与4个字。  似乎我每次都不需要再写大部分内容。

    此外、我是否应该假定没有办法配置 DMA、使其保持在 UDMA_MODE_BASIC 状态、而不是复位到 UDMA_MODE_STOP?

    谢谢!

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

    MSP432P401R 和 MSP432E4111共用 ARM UDMA、因此以下代码段可能会有所帮助。

    /* ADC14 MEM0的完成中断*/
    __attribute__((ramfunc)//需要编译器 TI v15.12.1.LTS
    void DMA_INT1_IRQHandler (void)
    {
    uint32_t* controlPtr =(uint32_t*)&controlTable[0];
    
    /*使用 DMA 的交替模式在主缓冲器和备用缓冲器之间切换*/
    IF (DMA_getChannelAttribute (7)& UDMA_ATTR_ALTSELECT)
    {
    // DMA_setChannelControl (UDMA_PRI_SELECT | DMA_CH7_ADC14、
    // UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    // DMA_setChannelTransfer (UDMA_PRI_SELECT | DMA_CH7_ADC14、
    // UDMA_MODE_pingpong、(void*)&ADC14->MEM[0]、
    // data_array1、sample_length);
    controlPtr +=2;
    *controlPtr =(*controlPtr & 0x000000 )|((( sample_length)-1)<<4)|0x03;
    switch_data = 1;
    }
    其他
    {
    // DMA_setChannelControl (UDMA_ALT_SELECT | DMA_CH7_ADC14、
    // UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1);
    // DMA_setChannelTransfer (UDMA_ALT_SELECT | DMA_CH7_ADC14、
    // UDMA_MODE_pingpong、(void*)&ADC14->MEM[0]、
    // data_array2、sample_length);
    controlPtr +=34;
    *controlPtr =(*controlPtr & 0x000000 )|((( sample_length)-1)<<4)|0x03;
    switch_data = 0;
    }
    } 

    我不确定我是否完全遵循了最后一个发言。  DMA 将状态更改为在发送最后一个字节时停止。  如果您看一下对 controlPtr 的写入、逻辑 OR 为0x03表示传输模式、3表示乒乓模式、1表示基本模式。

    此致、
    Chris

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

    感谢您深入了解 Chris。  我认为这或多或少是我最终所做的:

    //为下一个事务重置 DMA
    pui8ControlTable[216]= 0x29;// TX
    pui8ControlTable[200]= 0x29;// RX
    HWREG (UDMA_ENASET)= 0x3000;//重新启用这两个 

    我初始写入0x29的尝试不起作用、因此我不确定是否必须写入所有字节。  我相信、事实证明我只是写入了错误的字节(顺序相反)。

    对于最后一个问题、我只是想弄清楚是否有办法在没有代码干预的情况下重新设置该传输模式。  或者可能阻止它在最后一个字节被发送后进入停止状态。  我知道每个发送/接收将是3个字节、但理想情况下、我可以继续从同一个源定期重新触发它、甚至不必反复写入相同的控制字节。  这些传输的周期为1us、因此我们可以节省的每一小段时间都有所帮助。

    或者、我想知道是否有办法在每个计时器周期中发送3个字节、然后使用 RX 持续填充缓冲区(假设每次发送10万个字节、3个字节)、并且仅在缓冲区已满时中断?  似乎应该有某种机制来实现这一点,我还找不到。

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

    我知道在没有代码干预的情况下复位 DMA 的唯一方法是使用散聚模式、最后一项任务是复位/重新配置 DMA。  其外观如下所示:

    DMA_ControlTable spiTXDmaSEQ[TX_TASKs]=
    {
    //任务1、清除芯片选择
    DMA_TaskStructEntry (1、UDMA_SIZE_8、
    UDMA_SRC_INC_NONE、&outputLow、
    UDMA_DST_INC_NONE、 &P6->OUT、
    //uDMA_dst_INC_NONE、(void *)(0x42000000 +(0x40004C00 + 0x043)- 0x40000000)*(0x20)+ 0*(0x04)、//端口6位0
    UDMA_ADC_1、UDMA_MODE_MEM_ME_DST_NOT_UDAB2*
    
    
    、UDMA_DST_DCM_DCM_SD_EVM_DCM_SD_2、UtDA_DCM_NOT_EVM_DCM_SD_SD_EVM_2、UARTEST_ST_NOT_EVM_D20_EVM_SD_SD_EVM_ADCM_NOT_SD_EM_EM_EM_EM_EM_EM_SD_EM_EM_EM_EM
    &EUSCI_B0_SPI->TXBUF、
    UDMA_ARB_2、UDMA_MODE_MEM_SP散 射_收集)、
    //任务3、将配置重置回启动
    DMA_TaskStructEntry (4、UDMA_SIZE 32、
    UDMA_SRC_INC_32、(void *)& ReInitTask0_dst
    、UDMA_INC_32、UDMA_INC_INC (void *)&MSP_EXP432P401RLP_DMAControlTable[0]、
    UDMA_ARB_4、UDMA_MODE_PER_散 射收集) 

    DMA 的大小限制为1024 (因此、要处理1024个任务)、因此、如果要同时移动到 TX 和 RX、我认为您无法达到所需的大小。

    此致、

    Chris

     

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

    哦、如果我理解您的建议是正确的、那么这种做法可能会很好。

    我的当前设置如下所示:

    MAP_uDMAChannelControlSet (UDMA_CH12_SSI2RX | UDMA_PRI_SELECT、
    UDMA_SIZE 8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 |
    UDMA_ARB_1 | UDMA_NEL_USEBURST;
    
    MAP_uDMAChannelTransferSet
    
    (UDMA_INC_RETURN)、UDMA_DIAT_UDMA_RE_DIAT_DIAT_UDR_INC_RETURN (USSDIAT_DIAT_DIAT_12)
    3);
    
    MAP_uDMAChannelControlSet (UDMA_CH13_SSI2TX | UDMA_PRI_SELECT、
    UDMA_SIZE 8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE |
    UDMA_ARB_1 | UDMA_NEL_USEBURST);
    
    MAP_uDMA_SEND_UDMA_SEND_UDR_13 (UDMA_SEND_UDMA_SEND、UDMA_SEND
    
    
    、UDMA_SEND、UDMA_SEND_BUDA_DCR_DCR_D_ UDMA_D_ UDA_D (UDMA_DIC_NEUDMA_SEND) 3); 

    是否可以:
    -设置 satter_cet 而不是 basic
    -使 RX 缓冲区为10k、在结束时中断、每次递增3个字节(4个字节也没关系)
    -通过您建议的这种方法只重置 TX
    -在 RX ISR 中、当接收到10k 满时、然后通过代码干预复位

    有时我可以这么做、只需每1us 中断一次就可以花费大量的处理时间来处理中断延迟。  我真正需要做的就是减少这种情况、但保证每1us 发生一次3字节 TX。

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

    我想、这需要的不仅仅是可用的主通道和备用通道。

    至少我可以执行100次甚至500次交替的 TX RX 任务、最后一个任务是重新启动的?  这似乎是合理的吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    就这一建议的解决方案而言、这是我的理解(如果有任何错误、请告知我):
    -这个 DMA_ControlTable 将被用作 uDMAControlBaseSet 的参数
    -一次只能有一个 DMA_ControlTable
    -表中最多可以有1024个任务

    任务是否按顺序运行? 还是仲裁级别?
    启动每个任务的源是什么、或者每次启动表本身是什么?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!

    是的、DMA_ControlTable 将用作 uDMAControlBaseSet 的参数。
    是的。 您可以有效地告诉 UDMA 在哪里获取任务定义。
    1024数字是一个任务的大小限制。 例如、在分散集中、您可以配置主任务以加载备用任务256次(任务定义中包含4个32位字、因此为1024/4)。 然后、每个备用任务可以执行1024次任务。

    任务按顺序运行。 您可以将传输配置为自动或从外设触发。 (外设与存储器散聚)。 您可以在数据表中找到 DMA 通道增压。

    www.ti.com/.../msp432e401y.pdf

    有关通道定义、请参阅 udma.h。


    此致、
    Chris
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    非常好、感谢 Chris 的所有帮助。 您帮助我了解了某些器件的限制以及其他可能实现我所需的功能的方法。