Cコードの実行時間をミリ秒単位で取得したいのですが、msp430f16
.
どんな助けでも大歓迎です。
ありがとうございました。
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) 文字を送信する時間を測定します。上記のように、除数を調整して、タイマーの 1 サイクル以上をカウントしないようにします (タイマーはロールオーバーできます。例、問題ない、0xF000、問題である 0xF100 に 1 回程度)。可能な場合は、完全にロールオーバーしないように除算を大幅に超過し、最高の精度が得られるまで除数を縮小します。
はい、割り込みを使用してロールオーバーを処理できますが、それは測定しようとしているものを台無しにします。それをしたくありません(割り込みのオーバーヘッドまたはタイマーのロールオーバーを監視するために使用するメカニズムを除きます(必要はありません)このための割り込み) は、測定に許容されます)。
#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 バックエンドは本当に実験的なものです。読んでください。naken430asm アセンブラは非常に使いやすく、このプロセッサの asm も非常にシンプルで、優れたアーキテクチャです...
一部の MSP430 デバイスにはオンボードのサイクル カウンターがあり、デバッガーの使用時に使用できます。コード シーケンスを比較すると、これは非常に正確であることがわかりました。
お使いのデバイスに搭載されているかどうかはわかりません。実際、MSP430f16 という名前のものは見つかりませんでした。通常、「f」の後に 3 桁または 4 桁の数字があります。
これを行う一般的な方法はありません。利用可能なハードウェア タイマー リソースを使用して、適切なタイムベースを提供するように構成することができます。コード実行のタイミングを計るには、ミリ秒のタイマーが多少適切かもしれません。マイクロ秒の方が適切かもしれません。
オーバーヘッドや追加のコード (またはハードウェア) がなく、おそらくより正確な方法は、シミュレーターでコードを実行してプロファイリングすることです。Code Composer Studio にはプロファイリング ツールとシミュレーション ツールが含まれていると思います。他のツールチェーンにもそれらが含まれている可能性があります。テスト対象のコードにハードウェアのタイミング/レイテンシの依存関係がある場合、このアプローチは適切ではない可能性があります。
もう 1 つの簡単な方法は、実行前と実行後に利用可能な GPIO を切り替え、オシロスコープまたは外部タイマー/カウンターでピンを監視することです。このアプローチには、ハードウェアのレイテンシ/ジッターと、テスト対象のコードの実行中に発生する可能性のある割り込みに関連するオーバーヘッドも含まれます。利用可能なハードウェア タイマー リソースがない場合にも実装できます。
既存のソフトウェアを変更せずに迅速なものを探しているが、超正確ではない場合。プロファイリングするコードの前後にロギング ブレークポイントを使用できます。
IAR を使用している場合、このオプションは少し隠されています。ブレークポイントを追加する行を右クリックし、ロギング ブレークポイントを選択する必要があります。
もちろん、ログをトリガーするのにいくらかの遅延があります。この遅延は一定である必要があります。