Как получить время выполнения, используя msp430? - PullRequest
5 голосов
/ 28 декабря 2011

Я бы хотел, чтобы время выполнения кода C было в миллисекундах, и я использую msp430f16.

. Любая помощь будет принята.

Спасибо.

Ответы [ 4 ]

4 голосов
/ 28 декабря 2011

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);
    }
}
//-------------------------------------------------------------------
//-------------------------------------------------------------------

Msp430 бэкенда llvm действительно экспериментален, читай: сломан, не полагайтесь на него больше, чем просто поиграть с ним,компилятор gcc не тривиален, но и не слишком болезнен для сборки.Ассемблер naken430asm очень прост в использовании, а ассемблер для этого процессора достаточно прост, хорошая архитектура ...

1 голос
/ 31 декабря 2011

Некоторые устройства MSP430 имеют встроенный счетчик циклов, который доступен при использовании отладчика.Я обнаружил, что это очень точно при сравнении кодовых последовательностей.

Хотя я не знаю, есть ли у вашего устройства такая.На самом деле я не нашел ни одного по имени MSP430f16, у него обычно есть три или четыре цифры после "f".

1 голос
/ 31 декабря 2011

Не существует общего способа сделать это, вы можете использовать доступный ресурс аппаратного таймера и настроить его для предоставления соответствующей временной базы.Я хотел бы предположить, что для выполнения кода таймера, миллисекундный таймер может быть несколько естественным;микросекунды могут быть более подходящими.

Более простой метод без дополнительных затрат или дополнительного кода (или даже аппаратного обеспечения) и, возможно, большей точности, заключается в выполнении и профилировании кода в симуляторе.Я считаю, что Code Composer Studio включает в себя инструменты профилирования и моделирования.Другие цепочки инструментов также могут включать их.Если тестируемый код имеет аппаратные временные / латентные зависимости, этот подход может оказаться неприемлемым.

Другой простой способ - переключать доступный GPIO до и после выполнения и отслеживать вывод с помощью осциллографа или внешнего таймера / счетчика,Этот подход будет включать аппаратные задержки / дрожание, а также любые издержки, связанные с прерываниями, которые могут возникнуть во время выполнения тестируемого кода.Это также может быть реализовано при отсутствии доступного ресурса аппаратного таймера.

0 голосов
/ 27 июня 2012

Если вы ищете что-то быстрое, не меняя существующее программное обеспечение, но не супер точное. Вы можете использовать контрольные точки регистрации до и после кода, который вы хотите профилировать.

Если вы используете IAR, эта опция немного скрыта. Вы должны щелкнуть правой кнопкой мыши на строке, которую вы хотите добавить точку останова, и выбрать точку останова регистрации.

Конечно, будет некоторая задержка для запуска журнала, эта задержка должна быть постоянной.

...