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.

[参考译文] MSP430FR5994:命令"MOVA R15、0x000c (SP)"不能在所有条件下工作

Guru**** 2391195 points
Other Parts Discussed in Thread: MSP430FR5994, MSP430FR5949, MSP-FET

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1037747/msp430fr5994-the-command-mova-r15-0x000c-sp-does-not-work-under-all-conditions

器件型号:MSP430FR5994
主题中讨论的其他器件: MSP430FR5949MSP-FET

您好、CPU 专家、

在 C 程序中、将使用8k RAM 的上部。
我在 lnk_msp430fr5994.cmd 文件中使用 Allen Gao 的线程进行了建议的设置。 结果是链接器在 RAM 中使用了高位地址范围。 这可以在堆栈指针和寄存器12、13和14的显示值中看到。 然而、寄存器12、13、14和15的值有时只被写入 RAM。

为什么只将寄存器的 HI 部分写入 RAM 中?
为什么这种情况只会发生、而不是在同一个 C 代码行中执行每个写入操作?

注意:每次执行 c 代码行时都会发生错误。 区别在于、寄存器12、13、14和15的不同寄存器未完全写入栈。

这是发生问题的 c 代码行的汇编代码以及分步处理的结果:

1:  966    void savePosAndVelInSensors(float *lon, float *lat, unsigned int *alt, unsigned char *vel){
        savePosAndVelInSensors():   // this is the head of the function
2: 042864:   00B1 0010           SUBA    #0x00010,SP   // SP: 0x003BD0
3: 042868:   0F71 000C           MOVA    R15,0x000c(SP)   // SP: 0x003BC0, R15: 0x002A60
4: 04286c:   0E71 0008           MOVA    R14,0x0008(SP)   // R14: 0x003BDE
5: 042870:   0D71 0004           MOVA    R13,0x0004(SP)   // R13: 0x003BDA
6: 042874:   0C71 0000           MOVA    R12,0x0000(SP)   // R12: 0x003BD6
7:  968        itoha((uint8_t*)lon,(uint8_t*)&sensors.lon[1],4);   // this is the first line inner the function...
8: 042878:   008D 5383           MOVA    #0x05383,R13

在调试器的单步操作过程中、连接的 GPS 接收器会不断向 UART 提供数据。

执行第2行后、我通过调试器手动写入存储器、以查看 CPU 的写入操作:

0x003BC0:11   11      11 11       11   11   11   11       11   11   11   11       11.
存储器(堆栈)的变化如下:
第3行之后:
0x003BC0:11   11      11 11       11   11   11   11       11   11   11   11   00  00

第4行之后:
0x003BC0:11   11      11 11       11   11   11   11   11   00    11      11 00  00 00

第5行之后:
0x003BC0:11      11      11 DA  3B  00    11      00      11 00 11      00  00

第6行之后:
0x003BC0:11      00    00 DA  3B  00    11      00      11 00 11   00 11   00  00 00

可以看出、在这种尝试中、寄存器15、14和12的内容没有完全到达堆栈。 只有寄存器13的内容被完全写入到堆栈中、在执行这个 C 语言行的其他尝试中、其它寄存器被写入、其它寄存器不被写入。

LEACNF0的内容为0x00000001。 程序段不会被中断(GIE = 0)中断。

注意:DMA1通道会影响堆栈内容。
此 DMA 通道由 UART (9600波特)的接收触发。 CPU 以8MHz 的频率运行。 接收到的字节被写入 RAM 中的一个数组(不同的地址范围)。 此写入操作正常。 DMAC 将每个接收到的字节写入接收缓冲区。 接收到的 NEMA 数据的校验和计算结果为"正确"。 DMAC 写入的数据不会超过此范围。 如果在第3行被处理前将0x0000写入通道的 DMA1CTL 寄存器、CPU (第3行-第6行)对堆栈的所有写入操作将被完全执行。

最重要的问题是:这是芯片问题还是外部电路问题? 如何避免这个问题? 是在未使用 RAM 的上部4K 或未使用与堆栈相关的 MOVA 指令或未使用与 DMA 相关的 MOVA 指令或未使用 RAM 的 DMA 功能时完全执行的写入操作 还是不同的背景?

此致
哈迪

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="198290" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1037747/msp430fr5994-the-command-mova-r15-0x000c-sp-does-not-work-under-all-conditions ]LEACNF0的内容为0x00000001。 [/报价]

    这意味着 LEA 不会访问 RAM。  虽然《MSP430FR58xx、MSP430FR59xx 和 MSP430FR6xx 系列用户指南》(修订版 P) 未介绍 LEA 寄存器、但在 CCS 文件 C 中找到以下内容:\ti\ccs1040\ccs\ccs_base\con\targetdb\Modules\MSP430\LEA_367.0.xml:

        <register id="LEACNF0" width="32" offset="0x4" internal="0" description="Configuration Register 0">
            <bitfield id="LEASWRST" description="LEA module software restart. Setting this bit to one restarts the LEA module. As long this bit remains set to one the LEA is held in Restart. (The LEA accessible memory behaves as system RAM)" begin="0" end="0" width="1" rwaccess="R/W">
            </bitfield>
    

    [引用 userid="198290" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1037747/msp430fr5994-the-command-mova-r15-0x000c-sp-does-not-work-under-all-conditions 中最重要的问题是:这是芯片问题还是外部电路问题? [/报价]

    您是否可以发布演示问题的自包含项目?

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

    切斯特、您好!

    现在,我成功地创建了一个小型程序,模拟状态并显示问题。

    我已关闭项目设置中的代码优化。

    为了使程序正常工作、芯片需要 P2.1上的串行信号。 它应该大约为9600位/秒 只应将任何字符连续发送到 MSP430。 不会对它们进行评估。 由于波特率未精确设置、因此可能也会错误地接收到这些波特率。 只有 UART 持续触发 DMAC 才很重要。 请在第49行中设置一个早餐点。 此时停止后、请执行以下步骤:
    -启用 Disassember 视图
    -进入(F5)
    -装配体步进(Ctrl+Shift+F5)
    -激活内存浏览器视图
    -显示 SP
    -输入一个模式、例如从 SP 的当前地址开始的16x 0x11
    -现在4个汇编步骤进入并将寄存器15、14、13、12的内容与每个步骤的堆栈进行比较。

    您可以看到、有时只写入 Hight 部分(0x0000)。 在这些情况下、寄存器的低电平部分(C 中的指针)会丢失。 此示例程序不使用指针执行任何操作。 在我的计划中、他们指向要处理的重要信息。

    您可以看到、是否禁用 LEA 并不重要。 在较低的4K RAM 中也会出现此问题。

    您能否重现问题?

    #include <msp430fr5994.h>
    
    unsigned char rxBuf[100];
    
    void initTimerB(void){
        TB0CCR0 = 10;
        TB0CCR6 = 9;
        TB0CCTL6 = CCIE;                        // start test
        TB0CTL = CNTL__8 | TBSSEL__ACLK | ID__2 | MC__UP | TBCLR | TBIE;   // 8-Bit, ACLK, up mode, clear TBR, overflowInterrupt
    }
    
    void initDma1ForUca0(void){
        DMA1CTL = 0x0000;
        DMACTL0 = 0x0000;
        DMA1SA = (__SFR_FARPTR)&UCA0RXBUF;
        DMA1DA = (__SFR_FARPTR)(&rxBuf[0]);
        DMA1SZ = sizeof(rxBuf);
        DMA1CTL = DMADT_0 | DMASRCINCR_0 | DMADSTINCR_3 | DMADSTBYTE | DMASRCBYTE | DMAEN;
        DMACTL0 = DMA1TSEL__UCA0RXIFG;
    }
    
    void initUartGnss(void){
        P2SEL0 |=  BIT1 |  BIT0;
        P2SEL1 &= ~BIT1 & ~BIT0;
        UCA0CTLW0  = UCSWRST;
        UCA0CTLW0 |= UCSSEL__SMCLK;
        UCA0BR0 = 52;
        UCA0BR1 = 0x00;
        UCA0CTLW0 &= ~UCSWRST;                  // Initialize eUSCI
        UCA0IFG = 0x00;                         // clear interrupt flags
        initDma1ForUca0();
    }
    
    void savePosAndVelInMemory(float *lon, float *lat, unsigned int *alt, unsigned char *vel){
        // the important steps are the correct pointer values in the head of the function
        // in most cases the low part of the pointers are not written to the stack
    
        //
        // There is a lot to do with the pointers here.
        //
    }
    
    void movaTest(){
        float lon = 12.456;
        float lat = 51.567;
        unsigned int alt = 54;
        unsigned char vel = 5;
        // please set a break point to the next line
        savePosAndVelInMemory(&lon, (float*)&lat, (unsigned int*)&alt, (unsigned char*)&vel);
    
    }
    
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;
        PM5CTL0 &= ~LOCKLPM5;
    //    gnssOn;                   // depend of hardware
    //    gnssOnOut;                // depend of hardware
        initUartGnss();
        initTimerB();
        __bis_SR_register(LPM3_bits + GIE);       // Enter LPM3, enable interrupts
        __no_operation();
    
    	return 0;
    }
    
    // TimerB Interrupt Vector (TBIV) handler
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER0_B1_VECTOR
    __interrupt void TIMER0_B1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_B1_VECTOR))) TIMER0_B1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      if(TB0IV){
            movaTest();
      }
    }
    

    此致
    哈迪

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

    您使用的编译器版本和选项是什么?

    为 TI v21.6.0.LTS 编译器创建了一个具有默认选项的新项目、并收到可能影响结果的警告:

    "/home/mr_halfword/ti/ccs1040/ccs/tools/compiler/ti-cgt-msp430_21.6.0.LTS/bin/cl430" -vmspx --data_model=restricted --use_hw_mpy=F5 --include_path="/home/mr_halfword/ti/ccs1040/ccs/ccs_base/msp430/include" --include_path="/home/mr_halfword/workspace_v10/MSP430FR5994_mova_issue" --include_path="/home/mr_halfword/ti/ccs1040/ccs/tools/compiler/ti-cgt-msp430_21.6.0.LTS/include" --advice:power=all --advice:hw_config=all --define=__MSP430FR5994__ --define=_MPU_ENABLE -g --printf_support=minimal --diag_warning=225 --diag_wrap=off --display_error_number --verbose_diagnostics --silicon_errata=CPU21 --silicon_errata=CPU22 --silicon_errata=CPU40 --preproc_with_compile --preproc_dependency="main.d_raw"  "../main.c"
    "../main.c", line 15: warning #173-D: invalid type conversion
          DMA1SA = (__SFR_FARPTR)&UCA0RXBUF;
                   ^
     
    "../main.c", line 16: warning #173-D: invalid type conversion
          DMA1DA = (__SFR_FARPTR)(&rxBuf[0]);
                   ^
    

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

    编译器为 TI v18.1.0.LTS

    以下是选项:
    -vmspx --data_model=large -off --opt_for_speed=2 --use_hw_mpy=F5 --include_path="C:/ti/ccsv8/ccs_base/msp430/include --include_path="/RAM_8K_test"--include_path="C:/ti/ccsv8/tools/compiler/ti-cgt-msp430_18.1.8.LTS/include --advice:power_path="call"--advice:atisi="cus_erratiag=/us_support=us_atiag=us_support/capsility=us_display_cp24=us_ature-f_cp_off-us_us_erratination=us_cp_us_atination=-us_display_us_support=us_us_erratination=-us_us_us_atination=-us_off-us_us_erranag_us_atination=us_us_us_display_

    这在本例中是否相关? 它涉及机器命令的处理。

    这些警告一直困扰着我很长时间。 但生成的命令可以正常工作。 如果您有有关忽略警告的提示、这也是很好的。

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

    您似乎忽略了本剧中的另一个角色:调试器。

    EEM 具有时钟控制选项、因此在不知道这些选项的情况下不清楚将运行什么。 可能 UART 时钟正在运行、或者在暂停执行时无法接收字符。

    但是、当你单步执行时会发生什么情况、具体取决于这些时钟控制选项。

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

    我在时钟选项中只能看到一个相关选项。 这是 UART 的时钟。 在调试模式下、它不会停止。 当我停止它时、MOVA 命令在单步模式下工作。 所有定时器、RTC 和 AES128的时钟被停止。 超低功耗模式选项没有影响。

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

    是否有人知道如何解决该问题?

    同时、我使用完全不同的硬件进行了测试。 它是采用 MSP430FR5949的不同 PCB。 这是一个类似的控制器。 也不起作用。 这4个寄存器不会被写入堆栈。

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

    未使用调试器时是否会发生此故障?

    我认为您可以更直接地执行它、而不是依赖于传入的串行数据来触发 DMA:

    void stacky1(void)
    {
      /* Setting up known values in registers
         These are caller saved so they can be trashed.
      */
      asm(" mova #0x10203,r12\n  mova #0x40506,r13\n \
            mova #0x70809,r14\n  mova #0xa0b0c,r15\n");
    
      // Test!
      asm(" nop\n");
      asm(" bis #2,&UCA0IFG\n");   // trigger DMA cycle by setting UCTXIFG
      asm(" pushm.a #4,r15\n");
    
      
      asm(" nop\n nop\n"); // breakpoint here to see results
      asm(" popm.a #4,r15\n"); //clean up stack
    }
    
    

    这将使您更好地控制时序、并允许测试除 MOVA 以外的其他指令、例如等效但较长的 movx.a.

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

    David 的建议有助于测试。 我以这种方式修改了测试程序:

      asm(" bis #1,&UCA0IFG\n");   // trigger DMA cycle by setting UCRXIFG
      asm(" SUBA    #0x00010,SP\n");
      asm(" MOVA    R15,0x000c(SP)\n");
      asm(" MOVA    R14,0x0008(SP)\n");
      asm(" MOVA    R13,0x0004(SP)\n");
      asm(" MOVA    R12,0x0000(SP)\n");
      asm(" ADDA    #0x00010,SP\n");
      asm(" pushm.a #4,r15\n");
    

    在测试第一个单元时、问题发生在实际操作(不带调试器)中。 有时这些值不正确。 如果没有调试器、现在很难重现、因为 UART 必须在"正确"的时刻接收字符。

    如果 UART 未接收到信号、您可以看到堆栈内容在最后一行之前已经正确。 然后、我向 UART 施加了大约2kHz 的方波信号。 现在问题再次出现。 在执行最后一行代码(pushm.a)之前、栈上寄存器的 lo 部分缺失。 执行 pushm.a 命令后、四个寄存器的完整内容将出现在堆栈上。 如果我关闭 UART 的时钟(UCA0CTLW0 = 0)、MOVA 命令将再次运行。 则外部条件(时钟和端口配置)仍然相同。
    这看起来问题与 DMAC 无关。 但也可以使用 UART。 现在需要回答以下问题:
    -它是 MOVA 命令吗?
    是 UART 还是其配置?
    -为什么 UART 会影响 MOVA 命令的执行?
    -是否有任何其他的关联?
    当然、最重要的是:我们如何防止编译器以后在任意位置将发现的问题插入代码中?

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

    直接设置 RXIFG 的目的是控制 DMA 周期的时序。 我测试了在我的 PET fr5969 eFORTH 系统上设置 RXIFG、并生成了预期的中断。

    您的描述中缺少的是调试器正在执行的操作。 如果在将数据移动到堆栈后设置断点、会发生什么情况? (不要单步执行代码!) 验证 DMA 传输当然首先发生。 如果调试器未被妨碍、堆栈是否正确? 如果是、则问题是由 DMA 和 EEM 之间的交互引起的。 解决方法当然是为了避免发生这种情况。

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

    我已经做了更多的测试。 他们似乎证实了这一点。 如果调试器不干预、则堆栈正确。 程序中有很多 DMA 操作。 能否通过 MSP-FET 中的固件更新解决该问题、还是在芯片设计中解决该问题? 是否有使用调试器的规则来确保结果正确?