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.

[参考译文] MSP430FR6007:crc_table 函数

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1576239/msp430fr6007-crc_table-function

器件型号: MSP430FR6007

工具/软件:

您好、

在我的 linke 命令文件中、我执行以下操作:

.text       :{} crc_table (crc_table_text, algorithm=CRC32_PRIME)>> FRAM2 | FRAM
文本在 FRAM 和 FRAM2 中。 中的 crc_table_text 是起始地址
结构如下所示:
typedef 结构 crc_table
  uint16_t     rec_size  /* 8 位可寻址单元*/
  uint16_t     num_recs
  CRC_RECORD    Recs[1]
} CRC_TABLE
Recs 数组中的此数字是否与我的截面数相关? 在本例中是 FRAM 和 FRAM2?
遗憾的是、我使用 DMA 进行计算、在这种情况下、不能使用调试器。 到目前为止、我计算泛化和字节数的例程正在运行。 这是经过测试的。 我在代码中执行此操作时、当前无法正常工作。
crc_table const *p_crc_table_text =&crc_table_text;
crc_table const *p_crc_table_isr_text =&crc_table_isr_text;

const uint32_t calculatedCrcText = crc_calculation_is3309 ((uint8_t *) p_crc_table_text->recs[0].addr
                              p_crc_table_text->recs[0].size0x00000000、false);
const uint32_t calculatedCrcIsrText = crc_calculation_is3309 ((uint8_t *) p_crc_table_isr_text->recs[0].addr
                                p_crc_table_isr_text->recs[0].size0x00000000、false);
DMA 是否也可在 FRAM2 中用于 CRC 计算?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    通常、不能假设.text 只有一个 crc_table 条目:

    1) 链接器能够生成对齐“空洞“、因此某些字节在加载后无法预测。 对于这种情况、链接器会生成多个条目。

    2).text 可以在 FLASH 和 FLASH2 之间拆分。 (如果优先使用 FLASH2,这是不可能的,因为它太大了,但这是可能的。)

    只需逐步检查 num_recs 条目次数。

    -----

    DMASA/DMADA 为 32 位、因此可容纳 FLASH2 中的地址。 若要确保编译器的指针大小正确、应使用内在函数“__data20_write_long",“,如、如示例 msp430fr60x7_DMA_01.c 中所示、此处为:

    https://dev.ti.com/tirex/explore/node?node=A__AJThw7eQLuzxGR4hTWjRfQ__msp430ware__IOGqZri__LATEST

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

    我目前在 DMA 源策略中使用 TI 驱动程序库中的 DMA_setSrcAddress。 据我所知、这种实现方式是错误的、可能会成为问题?

    void DMA_setSrcAddress(uint8_t channelSelect, uint32_t srcAddress, uint16_t directionSelect)
    {
      // Set the Source Address
      __data16_write_addr((unsigned short)(DMA_BASE + channelSelect + OFS_DMA0SA), srcAddress);
    
      // Reset bits before setting them
      HWREG16(DMA_BASE + channelSelect + OFS_DMA0CTL) &= ~(DMASRCINCR_3);
      HWREG16(DMA_BASE + channelSelect + OFS_DMA0CTL) |= directionSelect;
    }
    
    void DMA_setDstAddress(uint8_t channelSelect, uint32_t dstAddress, uint16_t directionSelect)
    {
      // Set the Destination Address
      __data16_write_addr((unsigned short)(DMA_BASE + channelSelect + OFS_DMA0DA), dstAddress);
    
      // Reset bits before setting them
      HWREG16(DMA_BASE + channelSelect + OFS_DMA0CTL) &= ~(DMADSTINCR_3);
      HWREG16(DMA_BASE + channelSelect + OFS_DMA0CTL) |= (directionSelect << 2);
    }

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

    根据 C 编译器用户指南 (SLAU132Y) 表 6-5、“16"与“与“20"表示“表示目标(寄存器)地址的宽度、而不是基准大小(两种情况下均为 32 位)。 在 FR6007 [Ref 数据表 (SLASEV3A) 表 9-64]上、这些寄存器从大约 0x0500 开始、即 16 位可寻址。

    因此、虽然 data20 变体可能是一个“好习惯“、但我预计 data16 变体可以正常工作。

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

    好的、尝试了一下。 不幸的是,这不是解决办法。 第二个问题我无法调试它、因为使用 DMA 调试器无法正常工作。  

    问题仍然是我的日常工作到目前为止。 我还在组件中添加了一个使用 crc_table 功能的测试、该测试也有效。  

    我看到的唯一区别是、在我的产品中填充了 FRAM(超过 64KB)、而在独立元件测试中未填充。

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

    “你怎么知道的?“ (结果不正确? DMA 在中间停止?)

    我不熟悉 IS3309 CRC。 您是通过字节还是字进行写入?

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

    从 TI 链接器脚本保存的校验和与我的计算校验和不同。 Im 按字节写入。 您可以忽略 CRC 的类型、它是一个普通的添加功能。 可能有所不同  

      CRC_TABLE const *p_crc_table_text = &crc_table_text;
      CRC_TABLE const *p_crc_table_isr_text = &crc_table_isr_text;
    
      const uint32_t calculatedCrcText = crc_calc((uint8_t *)p_crc_table_text->recs[0].addr,
                                                                p_crc_table_text->recs[0].size, 0x00000000, false);
     
      if (calculatedCrcText != p_crc_table_text->recs[0].crc_value)
      {
        // Error
      }

    我在隔离式 CRC 元件中进行了一些测试

    一些输入

    一般而言、如前所述、计算是有效的。 不幸的是、当我创建一个巨大的阵列来模拟一个已填充的 FRAM 时、链接器似乎没有放置它

    我创建了一个数组:

    __attribute__((section(".const"), used)) const std::array<uint8_t, 0x33000> fill_array{0x01}

    在链接器命令文件中、我放置了以下内容:

        .const            : {} crc_table (crc_table_const, algorithm=CRC32_PRIME)>> FRAM | FRAM2  /* Constant data                     */

    在映射文件中:

    它在那里和列表中

    您可以看到它位于较高的 FRAM 上、但在目标上、您可以看到它没有高器件和低器件两个条目。 我真的不明白、甚至不知道如何对其进行仿真以得到误差。 计算出的校验和拟合(可在下图中看到)、因此到目前为止计算是正确的。 在我看来,应该有一些与高和低内存区域有关的东西。

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

    crc_tables 的屏幕截图指示 num_recs=2、但(调试器看到它时)每个都只有一个元素。 这大概来自    crc_tbl.h 中的“crc_record recs[1];“声明 您可能必须使用 Memory Browser 来查看另一个条目。

    ------------------------

    我之前在 FR5994 上使用了高 FRAM 上的 DMA(我需要大型输入缓冲器)、并按预期工作。 也就是说、有零星的报告称 DMAxSA/DA 未获取所有位(存储器模型和勘误表的混合)、通常的建议(如 Lehman 先生在这里所说) 是始终使用 data20_write_long。 (我不知道为什么 DriverLib 人没有。)   在 DMA 操作之前和之后检查 DMA0 寄存器 (CTL/SA/DA/SZ) 可能会很有用。  

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

    因此、我假设至少看到此链接器命令行的 2 条记录是正确的吗?

    .text       :{} crc_table  (crc_table_text, algorithm=CRC32_PRIME)>> FRAM2   | FRAM

    我期望一个用于 FRAM、一个用于 FRAM2

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

    你会看到,在 FRAM2 填充的情况下,这在这种情况下不太可能(因为你填充了大部分 FRAM2 的阵列)。

    您的屏幕截图显示 num_recs=2(对于.text 和.const)、显然这就是所发生的情况。

    如果有任何函数声明为 ISR (#pragma vector=)、则将其放入名为“.text:_isr“的函数中、该函数放置在低 FRAM 中。  (我认为)该区域不包括在.text CRC 中。

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

    所以我的 CRC DMA 源方法看起来像这样,但这会杀死系统  

    我对本模块有很多问题、我非常沮丧。  

     static void feed(const uint8_t *src, size_t length, const uint8_t *dst)
      {
        // Add size validation (your original 0x5FF is fine)
        if (length > 0xFFFF || length == 0)
        {
          return; // Invalid size
        }
    
        DMA_initParam cfg = {
            DMA_CHANNEL_0,                // channelSelect
            DMA_TRANSFER_BLOCK, // transferModeSelect
            length,                       // transferSize
            DMA_TRIGGERSOURCE_0,          // triggerSourceSelect
            DMA_SIZE_SRCBYTE_DSTBYTE,     // transferUnitSelect
            DMA_TRIGGER_RISINGEDGE        // triggerTypeSelect
        };
    
        DMA_init(&cfg);
    
        // Set direction bits
        HWREG16(DMA_BASE + DMA_CHANNEL_0 + OFS_DMA0CTL) &= ~(DMASRCINCR | DMADSTINCR);
        HWREG16(DMA_BASE + DMA_CHANNEL_0 + OFS_DMA0CTL) |= DMASRCINCR_3;
    
        // Try without masking first
        __data20_write_long((uintptr_t)&DMA0SA, (uintptr_t)src);
        __data20_write_long((uintptr_t)&DMA0DA, (uintptr_t)dst);
    
        // Clear flag and enable
        DMA0CTL &= ~DMAIFG;
        DMA_enableTransfers(DMA_CHANNEL_0);
        DMA0CTL |= DMAREQ;
        
        // Add timeout to debug
        uint32_t timeout = 10000;
        while (!(DMA0CTL & DMAIFG) && --timeout)
        {
          __no_operation();
        }
    
        if (timeout == 0)
        {
          // Timeout occurred - add breakpoint here for debugging
          __no_operation();
        }
    
        DMA_disableTransfers(DMA_CHANNEL_0);
      }

    我想计算代码的 CRC。 软件太慢、因此应使用 DMA。

    从 CRC 驱动程序中、我为馈送函数提供一个存储器块(因为 DMA 长度限制为 16 位)。 根据我的设置、我将该存储器块逐字节传输到一个块中的 CRC 目标地址。 想象一下 dst 是 CRC 目标寄存器。 从设置点开始、DMA 只应递增 src 地址、而不是目标地址。 当我添加 DMA0CTL |= DMAREQ 行时、系统崩溃。 我不希望出现中断。 这条线是否是必需的? 但是当我删除这条线时,我得到了内存移动的超时。 您是否有一个结合使用 DMA 和 CRC 模块来计算 20 位存储器区域中的 CRC 的工作示例?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    添加 DMA0CTL |= DMAREQ 行时、系统崩溃。 我不希望出现中断。 是否需要此行?

    当然、这是必需的。 必须触发 DMA、否则不会发生任何情况。

    嗯。 我只是在查看 GCC 版本的__data20_write_long()、它有什么问题。

    #define _data20_write_long(addr,src) \
    ({ \
            unsigned int __tmp; \
            unsigned long __addr = addr; \
            __asm__ __volatile__ ( \
            "movx.a %1, %0 \n\t" \
            "mov.w  %L2, 0(%0) \n\t" \
            "mov.w  %H2, 2(%0)" \
            : "=&r"((unsigned int) __tmp) \
            : "m"((unsigned long) __addr), "ri"((long) src) \
            ); \
    })
    
    

    在预期的 movx.a 指令之后、有两个字写入。 当与 DMA 地址寄存器一起使用时、这会完全破坏意图并将高位字清零。 过去有一个__data20_write_addr() 没有这种冗余和错误的写入。

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

    哦、我怀疑系统崩溃是一种开机清除 (PUC) 功能、无法访问空的外围设备空间。

    有很多方法可以检查这个问题。 检查生成的代码是最简单的。

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

    e2e.ti.com/.../test_5F00_dma.zip

    我使用 driverlib 进行了一个微小的测试。 我可以看到-- data-model large 控制器在频率设置中挂起。 当包含 DMA 设置时、当我排除 DMA 设置时、它不会卡在晶体设置中。 它似乎适用于-data-mode 受限的情况。 但这只是一个直觉,我没有尝试所有的组合。

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

    其他问题。 目前、我使用 DMA 将块传输到 CRC 模块。 这种行为合适吗? CRC 是否能够处理此问题? 还是 DMA_TRANSFER_SINGLE?

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

    单通道模式要求每次传输都触发。 这会使响应速度慢于不使用 DMA。

    如果您需要在传输发生时滑入一些 CPU 活动、则突发块模式会更好。 由于阻塞机制直至其完成、则情况并非如此。

    哦、我在您包含的那堆代码中查看了 dma.obj。 我假设此代码来自 DriverLib。 我认为这应该适用于设置源和目标 DMA 地址。

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

    通常您提前清除 LOCKLPM5。 不要在配置 LFXT 引脚之后、希望有关 GPIO 配置的一般规则不适用于 LFXT。

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

    不是 driverlib 中的错误。 在较高地址区域中、没有将 DMA 与 CRC 模块结合使用的实际示例。 我的示例向您展示、当我运行示例时会发生一些奇怪的情况(即使使用  PM5CTL0 &=~LOCKLPM5;移到顶部(在 PJ 端口 INIT 下方),晶体从未初始化)。 如果我删除了 DMA 代码、它会运行到末尾

    不知道这里发生了什么。   

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

    我没有使用 CRC32 的器件、但我确实在 FR5969 上运行了此代码、没有遇到任何问题:

    int main(void)
    {
      DMA0CTL = DMASBDB | DMASRCINCR_3 | DMADT_1;
      DMA0DA = &CRCDIRB_H;
      __data16_write_addr(&DMA0SA, 0x10000L);
      DMA0SZ = 0xffff;
      DMA0CTL |= DMAEN;
      CRCINIRES = 0xffff;
      DMA0CTL |= DMAREQ;
      
      while (1);
    }
    

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

    它的 16 位地址范围也可以在我这边工作。 问题出在 20 位地址范围

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    它的 16 位地址范围也适用于我。 问题在于 20 位地址范围

    将其分成更小的部分。

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

    我必须跳转到更高的地址(20 位)、DMA 独立于块大小、 看起来这就是问题所在。

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

    它不应该是。 至少通过 GCC 我得到了合理的代码和预期的行为。

    $/usr/ti/gcc/bin/msp430-elf-objdump -S a.out

      __data16_write_addr(&DMA0SA, 0x10000L);
        4468:       81 43 00 00     mov     #0,     0(r1)   ;r3 As==00
        446c:       91 43 02 00     mov     #1,     2(r1)   ;r3 As==01
    
    00004470 <.Loc.17.1>:
        4470:       8c 00 12 05     mova    #1298,  r12     ;0x00512
        4474:       00 18 ec 41     movx.a  @r1,    0(r12)  ;
        4478:       00 00 
    
    

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

    很遗憾、这对我没有帮助。 第一个 I 使用 CGT、第二个 I 使用__data20_wirte。 我也得到了使用__data20_write 的正确汇编、但当我添加:DMA0CTL |= DMAREQ;(在时钟初始化后完成)时、代码仍然卡滞。 当此行未注释时。 无论出于何种原因、晶体设置在 while 循环中挂起。  

    uint16_t volatile resetReason = 0;
    int main()
    {
      resetReason = SYSRSTIV;
      resetReason = 0;
    
      WDTCTL = WDTPW | WDTHOLD; // Stop the watchdog timer
    
      // To enable LFXT, the PSEL bits associated with the crystal pins must be set.   - RM 3.2
      // Setting the PSEL bit causes the LFXIN and LFXOUT ports to be configured for LFXT operation.
      // LFXIN = PJ.4
      PJSEL0 |= BIT4 | BIT5;    // Set bits 4 and 5 in PJSEL0 to enable primary function
      PJSEL1 &= ~(BIT4 | BIT5); // Clear bits 4 and 5 in PJSEL1 to select primary function
    
    
      PM5CTL0 &= ~LOCKLPM5; // Clear the LOCKLPM5 bit to enable GPIO functionality
      // Unlock CS registers
      CSCTL0 = 0xA500; // Password to unlock clock system registers
      // Set DCO to 8 MHz
      CSCTL1 = 0x000C;
      // Configure clock sources
      CSCTL2 = SELM__DCOCLK | SELS__DCOCLK | SELA__LFXTCLK;
      // MCLK = DCOCLK, SMCLK = DCOCLK, ACLK = LFXTCLK
      // Set dividers for MCLK, SMCLK, and ACLK
      CSCTL3 = DIVM__1 | DIVS__1 | DIVA__1;
      // MCLK = DCO / 1, SMCLK = DCO / 1, ACLK = LFXT / 1
      // Enable LFXT with drive strength 3
      CSCTL4 &= ~LFXTOFF;    // Enable LFXT
      CSCTL4 |= LFXTDRIVE_3; // Set LFXT drive strength to 3
      // Clear fault flags and wait for LFXT to stabilize
      do
      {
        CSCTL5 &= ~LFXTOFFG; // Clear LFXT fault flag
        SFRIFG1 &= ~OFIFG;   // Clear oscillator fault flag
      } while (SFRIFG1 & OFIFG);
      // Lock CS registers
      CSCTL0_H = 0x01; // Lock clock system registers
    
      uint16_t length = 0xFFFF;
      DMA_initParam cfg = {
          DMA_CHANNEL_0,            // channelSelect
          DMA_TRANSFER_BLOCK,       // transferModeSelect
          length,                   // transferSize
          DMA_TRIGGERSOURCE_0,      // triggerSourceSelect
          DMA_SIZE_SRCBYTE_DSTBYTE, // transferUnitSelect
          DMA_TRIGGER_RISINGEDGE    // triggerTypeSelect
      };
    
      uintptr_t src = (uintptr_t)(0x10000);
      uintptr_t dst = (uintptr_t)(&CRC32DIRBB0);
    
      DMA_init(&cfg);
    
      HWREG16(DMA_BASE + DMA_CHANNEL_0 + OFS_DMA0CTL) &= ~(DMASRCINCR | DMADSTINCR);
      HWREG16(DMA_BASE + DMA_CHANNEL_0 + OFS_DMA0CTL) |= DMASRCINCR_3;
    
      __data20_write_long((uintptr_t)&DMA0SA, src);
      __data20_write_long((uintptr_t)&DMA0DA, dst);
    
      DMA0CTL &= ~DMAIFG;
      DMA_enableTransfers(DMA_CHANNEL_0);
    
      //DMA0CTL |= DMAREQ;
    
      uint32_t timeout = 10000;
      while (!(DMA0CTL & DMAIFG) && --timeout)
      {
        __no_operation();
      }
      /**/
    
      while (1)
      {
      };
    }

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

    因此、您说当添加代码来设置 DMAREQ 时、时钟初始化就会在执行之前很久失败。

    除非编译器以独特的方式错误运行、否则这是不可能的。

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

    当您逐步操作时、设备是否仍然挂起? 是否有环路等待晶体启动?

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

    您好 Luke、是的、您在上面的示例中看到了环路、我等待晶体。

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

    能否输出低频时钟? DMAREQ 线路在时钟检查之后、我不知道编译器为什么会在时钟检查之前调整 DMA 代码

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

    您好 Luke、  

    让我再次解锁该主题并发布客户的最新反馈:

    我刚刚注意到其他一些问题:在较低地址(16 位)中使用 DMA 功能时工作正常、但在使用较高的 FRAM 区域时、器件停止工作。  

    我还在数据表中找到了以下注释:  

    但让我来展示一下我在做什么:  

    template <size_t VMaxChunkSize = 0xFFFF>
    struct CRC32DataFeedMockWithDma
    {
      static constexpr auto maxChunkSize()
      {
        return VMaxChunkSize;
      }
    
      static struct Internals m_internals;
    
      static void feed(const uint8_t *src, size_t length, const uint8_t *dst)
      {
        // Safety check: DMA transfer size is uint16_t, max 65535
        if (length > 0xFFFF || length == 0)
        {
          return; // or assert/abort
        }
        
        DMA_initParam cfg = {
            DMA_CHANNEL_0,                 // channelSelect
            DMA_TRANSFER_BLOCK,            // transferModeSelect
            static_cast<uint16_t>(length), // transferSize
            DMA_TRIGGERSOURCE_0,           // triggerSourceSelect
            DMA_SIZE_SRCBYTE_DSTBYTE,      // transferUnitSelect
            DMA_TRIGGER_RISINGEDGE         // triggerTypeSelect
        };
    
        DMA_init(&cfg);
    
        // Use proper 20-bit address handling
        // Convert pointers to 32-bit first to avoid truncation
        uint32_t volatile src_addr = reinterpret_cast<uint32_t>(src);
        uint32_t volatile dst_addr = reinterpret_cast<uint32_t>(dst);
    
        // Set the Source Address (20-bit)
        __data20_write_long((uint32_t)&DMA0SA, src_addr & 0xFFFFF);
    
        // Reset bits before setting them
        HWREG16(DMA_BASE + DMA_CHANNEL_0 + OFS_DMA0CTL) &= ~(DMASRCINCR_3);
        HWREG16(DMA_BASE + DMA_CHANNEL_0 + OFS_DMA0CTL) |= DMA_DIRECTION_INCREMENT;
    
        // Set the Destination Address (20-bit)
        __data20_write_long((uint32_t)&DMA0DA, dst_addr & 0xFFFFF);
    
        HWREG16(DMA_BASE + DMA_CHANNEL_0 + OFS_DMA0CTL) &= ~(DMADSTINCR_3);
        HWREG16(DMA_BASE + DMA_CHANNEL_0 + OFS_DMA0CTL) |= (DMA_DIRECTION_UNCHANGED << 2);
    
        // Clear DMA interrupt flag and start transfer
        DMA0CTL &= ~DMAIFG;
        DMA_enableTransfers(DMA_CHANNEL_0);
        DMA_startTransfer(DMA_CHANNEL_0);
    
        // Poll for completion
        while (!(DMA0CTL & DMAIFG))
        {
          __no_operation();
        }
    
        DMA_disableTransfers(DMA_CHANNEL_0);
      }
    };
    
    

    你知道这里可能有什么问题吗?  

    谢谢!  

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

        // Set the Destination Address (20-bit)
        __data20_write_long((uint32_t)&DMA0DA, dst_addr & 0xFFFFF);

    这使用两次 16 位写入。 请参阅  SLAU132

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

    我们解决了这一主题中的问题。  

    MSP430FR6007:在 20 位地址空间中使用 DMA 失败 — MSP 低功耗微控制器论坛 — MSP 低功耗微控制器 — TI E2E 支持论坛