【问题标题】:How to get execution time using msp430?如何使用 msp430 获取执行时间?
【发布时间】:2011-12-28 15:28:54
【问题描述】:

我想以毫秒为单位获取 C 代码的执行时间,我使用 msp430f16

任何帮助将不胜感激。

谢谢。

【问题讨论】:

    标签: c timer embedded msp430


    【解决方案1】:

    http://github.com/dwelch67/msp430_samples

    示例显示使用计时器测量时间段,对计时器之前和之后进行采样并减去差值,即您的执行时间。

    编辑:

    此示例使用计时器和除数,而不是监视翻转标志读取 计时器计数器寄存器并假设您计数的时间超过计时器的滴答数,请从另一个中减去一个以获得时间。调整除数以避免翻转,并尝试获得您所追求的准确性。

        ;This version is written for naken430asm.
        ;http://www.mikekohn.net/micro/naken430asm_msp430_assembler.php
        ;naken430asm -o filename.hex filename.s
        ;mspdebug takes hex files as well as elfs.
    
    WDTCTL equ 0x0120
    
    
    CALBC1_1MHZ equ 0x10FF
    CALDCO_1MHZ equ 0x10FE
    
    DCOCTL  equ 0x56
    BCSCTL1 equ 0x57
    BCSCTL2 equ 0x58
    
    TACTL   equ 0x0160
    TAR     equ 0x0170
    TACCR0  equ 0x0172
    TACCTL0 equ 0x0162
    
    P1OUT   equ 0x0021
    P1DIR   equ 0x0022
    
    
        org 0xFC00
    
    reset:
        mov #0x0280,r1
    
        mov #0x5A80,&WDTCTL ; 0x5A00|WDTHOLD
    
        ; use calibrated clock
        clr.b &DCOCTL
        mov.b &CALBC1_1MHZ,&BCSCTL1
        mov.b &CALDCO_1MHZ,&DCOCTL
    
        ; make p1.0 and p1.6 outputs
        bis.b #0x41,&P1DIR
        bic.b #0x41,&P1OUT
        bis.b #0x40,&P1OUT
    
        ; 1MHz is 1000000 clocks per second
        ; 1000000 = 0xF4240
        ; The timers are 16 bit
        ; Using a divide by 8 in BCSCTL2 gives
        ; 125000 (0x1E848) clocks in a second
        ; Using a divide by 8 in the timer gives
        ; 15625 (0x3D09) timer ticks per second.
    
        ; If both divisors are by 8, and we set
        ; TACCR0 to 0x3D08 and set for count up mode
        ; then, theory, we can measure seconds.
    
        bis.b #0x06,&BCSCTL2
        mov #0x02C4,&TACTL
        mov #0x3D08,&TACCR0
        mov #0x02D0,&TACTL
        ;mov #0x02D0,&TACTL ; use this instead to blink faster
    
    loop:
        xor.b #0x41,&P1OUT
    loop0:
        bit.w #0x0001,&TACCTL0
        jz loop0
        bic.w #0x0001,&TACCTL0
    
        jmp loop
    
    
    hang:
        jmp hang
    
        org 0xFFE0
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw hang
        dw reset
    

    此示例使用计时器测量传输串行(rs232)字符的时间段,如上所述调整除数以确保您不会计数超过一个计时器周期(计时器可以翻转,很好 0xF000例如到 0x3000,没有问题,0xF000,大约一次到 0xF100 是有问题的)。如果可能会严重超过除数以便您绝对不会滚动,缩小除数直到获得最佳精度。

    是的,您可以使用中断来处理翻转,但这会弄乱您要测量的东西,您不想这样做(除非中断的开销或您用来监视计时器翻转的任何机制(您不需要为此中断)是您的测量可接受的)。

    #define WDTCTL     (*((volatile unsigned short *)0x0120))
    
    #define CALBC1_1MHZ (*((volatile unsigned char *)0x10FF))
    #define CALDCO_1MHZ (*((volatile unsigned char *)0x10FE))
    #define CALBC1_8MHZ (*((volatile unsigned char *)0x10FD))
    #define CALDCO_8MHZ (*((volatile unsigned char *)0x10FC))
    #define CALBC1_12MHZ (*((volatile unsigned char *)0x10FB))
    #define CALDCO_12MHZ (*((volatile unsigned char *)0x10FA))
    #define CALBC1_16MHZ (*((volatile unsigned char *)0x10F9))
    #define CALDCO_16MHZ (*((volatile unsigned char *)0x10F8))
    
    #define DCOCTL  (*((volatile unsigned char *)0x56))
    #define BCSCTL1 (*((volatile unsigned char *)0x57))
    #define BCSCTL2 (*((volatile unsigned char *)0x58))
    
    #define TACTL   (*((volatile unsigned short *)0x0160))
    #define TAR     (*((volatile unsigned short *)0x0170))
    #define TACCR0  (*((volatile unsigned short *)0x0172))
    #define TACCTL0 (*((volatile unsigned short *)0x0162))
    
    
    #define P1IN  (*((volatile unsigned char *)0x0020))
    #define P1OUT (*((volatile unsigned char *)0x0021))
    #define P1DIR (*((volatile unsigned char *)0x0022))
    
    // 16MHz clock
    // The timer is 16 bit
    // set to divide by 1
    // 16,000,000 / 155200 = 138.88889
    #define TACCR0_VALUE 138
    
    //-------------------------------------------------------------------
    void uart_putc ( unsigned short c )
    {
        unsigned short sa;
        unsigned short sb;
        unsigned short then,now;
    
        sa=c<<1;
        sa|=1<<9;
        sb=10;
        then=TAR;
        while(sb--)
        {
            if(sa&1) P1OUT|=1; else P1OUT&=(~1);
            sa>>=1;
            while(1)
            {
                now=TAR-then;
                if(now>TACCR0_VALUE) break;
            }
            then+=TACCR0_VALUE;
        }
    }
    //-------------------------------------------------------------------
    void hexstring ( unsigned short d, unsigned short cr )
    {
        //unsigned short ra;
        unsigned short rb;
        unsigned short rc;
    
        rb=16;
        while(1)
        {
            rb-=4;
            rc=(d>>rb)&0xF;
            if(rc>9) rc+=0x37; else rc+=0x30;
            uart_putc(rc);
            if(rb==0) break;
        }
        if(cr)
        {
            uart_putc(0x0D);
            uart_putc(0x0A);
        }
        else
        {
            uart_putc(0x20);
        }
    }
    //-------------------------------------------------------------------
    void notmain ( void )
    {
        unsigned short /*sa,*/sb;
        //unsigned short start;
        unsigned short then; //,now;
        unsigned short bitin;
        //unsigned short log[32];
    
        WDTCTL = 0x5A80;
    
        // use calibrated clock
        DCOCTL = 0x00;
        BCSCTL1 = CALBC1_16MHZ;
        DCOCTL = CALDCO_16MHZ;
    
        // make p1.0 an output
        P1DIR |= 0x01;
        P1OUT |= 0x01;
    
        P1DIR &= ~0x02;
    
    
        BCSCTL2&=~0x06;
        TACTL = 0x0204;
        TACTL = 0x0220;
    
        hexstring(0x1234,1);
        hexstring(0x5678,1);
    
        while(1)
        {
            //sa=0;
            bitin=0;
            while(1) if((P1IN&2)==0) break;
            then=TAR;
            while(1)
            {
                if((TAR-then)>=(TACCR0_VALUE>>1)) break;
            }
            if(P1IN&2)
            {
                bitin>>=1;
                bitin|=1<<9;
            }
            else
            {
                bitin>>=1;
            }
            then+=(TACCR0_VALUE>>1);
                for(sb=0;sb<9;sb++)
            {
                while(1)
                {
                    if((TAR-then)>=TACCR0_VALUE) break;
                }
                if(P1IN&2)
                {
                    bitin>>=1;
                    bitin|=1<<9;
                }
                else
                {
                    bitin>>=1;
                }
                then+=TACCR0_VALUE;
            }
            hexstring(bitin,0);  hexstring(bitin>>1,1);
        }
    }
    //-------------------------------------------------------------------
    //-------------------------------------------------------------------
    

    llvm 的 msp430 后端是真正的实验性,阅读:坏了,不要依赖它,而不仅仅是玩它,gcc 编译器不是微不足道的,但构建起来也不是太痛苦。 naken430asm 汇编器非常易于使用,并且该处理器的 asm 也非常简单,良好的架构...

    【讨论】:

    • 根据标准 StackOverflow 政策,最好提供实际答案,而不仅仅是指向答案的指针(将来可能会移动或消失)。
    • 同时堆栈溢出会丢失在链接上所做的改进。不过,在答案中添加了示例代码。
    • 是的,我同意添加链接也很有用。无论如何,您在代码中添加的解释比我在链接中找到的要好得多!很高兴投票。
    【解决方案2】:

    没有通用的方法可以做到这一点,您可以使用可用的硬件计时器资源并将其配置为提供适当的时基。我建议对于计时代码执行,毫秒计时器可能有点理所当然;微秒可能更合适。

    没有开销或额外代码(甚至硬件)并且可能更准确的更简单方法是在模拟器中执行和分析代码。我相信 Code Composer Studio 包括分析和模拟工具。其他工具链也可以包含它们。如果正在测试的代码具有硬件时序/延迟依赖性,则此方法可能不适合。

    另一种简单的方法是在执行前后切换可用的 GPIO,并使用示波器或外部定时器/计数器监控引脚。这种方法将包括硬件延迟/抖动以及与在执行被测代码期间可能发生的中断相关的任何开销。也可以在没有可用的硬件定时器资源时实现。

    【讨论】:

    • 对于“以毫秒为单位”,我希望 GPIO + 示波器时序非常好。
    • @XTL:考虑到具体问题,公平点,但对于许多“硬”实时应用程序来说,开销可能很关键。
    【解决方案3】:

    某些 MSP430 器件具有板载循环计数器,在使用调试器时可用。我发现这在比较代码序列时非常准确。

    我不知道你的设备是否有一个。其实我还没有找到一个叫MSP430f16的,一般都是f后面有三四位数字。

    【讨论】:

      【解决方案4】:

      如果您想在不更改现有软件的情况下快速找到一些东西,但不是超级准确。您可以在要分析的代码之前和之后使用日志记录断点。

      如果您使用的是 IAR,则此选项有点隐藏。您必须右键单击要添加断点的行并选择记录断点。

      当然,触发日志会有一些延迟,这个延迟应该是恒定的。

      【讨论】:

        猜你喜欢
        • 2012-09-25
        • 2014-08-08
        • 2019-04-12
        • 1970-01-01
        • 1970-01-01
        • 2012-08-26
        • 2017-12-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多