9

私は、cortex m4 でクロック サイクル カウントを測定してきましたが、今度は cortex m7 で測定したいと考えています。私が使用するボードは STM32F746ZG です。

m4の場合、すべてが機能しました:

volatile unsigned int *DWT_CYCCNT;
volatile unsigned int *DWT_CONTROL;
volatile unsigned int *SCB_DEMCR;

void reset_cnt(){
    DWT_CYCCNT   = (volatile unsigned int *)0xE0001004; //address of the register
    DWT_CONTROL  = (volatile unsigned int *)0xE0001000; //address of the register
    SCB_DEMCR    = (volatile unsigned int *)0xE000EDFC; //address of the register
    *SCB_DEMCR   = *SCB_DEMCR | 0x01000000;
    *DWT_CYCCNT  = 0; // reset the counter
    *DWT_CONTROL = 0; 
}

void start_cnt(){
    *DWT_CONTROL = *DWT_CONTROL | 0x00000001 ; // enable the counter
}

void stop_cnt(){
     *DWT_CONTROL = *DWT_CONTROL & 0xFFFFFFFE ; // disable the counter    
}

unsigned int getCycles(){
    return *DWT_CYCCNT;
}

問題は、m7 で実行したときに DWT_CTRL レジスタが変更されず、0x40000001 に変更される代わりに 0x40000000 のままであるため、サイクル カウントが常にゼロになることです。私が他の投稿で読んだことから、DWT_CTRL を変更できるようにするには、FP_LAR レジスタを 0xC5ACCE55 に設定する必要があるようです。

これらの定義を追加しました (以下の両方の FP_LAR_PTR アドレスを試しました):

#define FP_LAR_PTR ((volatile unsigned int *) 0xe0000fb0) //according to reference
//#define FP_LAR_PTR ((volatile unsigned int *) 0xe0002fb0) //according to guy on the internet
// Lock Status Register lock status bit
#define DWT_LSR_SLK_Pos                1
#define DWT_LSR_SLK_Msk                (1UL << DWT_LSR_SLK_Pos)
// Lock Status Register lock availability bit
#define DWT_LSR_SLI_Pos                0
#define DWT_LSR_SLI_Msk                (1UL << DWT_LSR_SLI_Pos)
// Lock Access key, common for all
#define DWT_LAR_KEY                    0xC5ACCE55

そしてこの機能:

void dwt_access_enable(unsigned int ena){
    volatile unsigned int *LSR;
    LSR = (volatile unsigned int *) 0xe0000fb4;
    uint32_t lsr = *LSR;;
    //printf("LSR: %.8X - SLI MASK: %.8X\n", lsr, DWT_LSR_SLI_Msk);

    if ((lsr & DWT_LSR_SLI_Msk) != 0) {
        if (ena) {
            //printf("LSR: %.8X - SLKMASK: %.8X\n", lsr, DWT_LSR_SLK_Msk);
            if ((lsr & DWT_LSR_SLK_Msk) != 0) {    //locked: access need unlock
                *FP_LAR_PTR = DWT_LAR_KEY;
                printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR);
            }
        } else {
            if ((lsr & DWT_LSR_SLK_Msk) == 0) {   //unlocked
                *FP_LAR_PTR = 0;
                 //printf("FP_LAR directly after change: 0x%.8X\n", *FP_LAR_PTR);
            }
        }
    }
}

コメント解除された print を呼び出すと 0xC5ACCE55 が返されますが、関数が返された後にそれを出力すると 0x00000000 が返され、その理由がわかりません。私は正しい軌道に乗っていますか、それとも完全に間違っていますか?

編集:関数に余分なコードをすべて入れずに試し、LARレジスタのみを変更しようとしたことにも言及するのは良いことだと思います。

BR グスタフ

4

2 に答える 2

4

ドキュメントをもう一度見てみると、ARM TRM のタイプミスまたはコピー アンド ペースト エラーが非常に疑わしいと思います。0xe0000fb0 は、ITM_LAR、DWT_LAR 、およびFP_LSR (および *_LSR と同等) のアドレスとして指定されます。他のすべての ITM レジスタページ 0xe0000000 にあるため、Cortex-M7 ドキュメントのその部分の責任者が Cortex-M4 レジスタ定義を取得し、新しい LAR と LSR を ITM ページに追加してコピーしたように非常によく似ています。それらを DWT および FPB ページに移動して、名前を更新しますが、アドレスの更新を見落とします。

あなたが無意識のうちに ITM_LAR (または実際の FP_LAR) のロックを解除していて、DWT_LAR が実際には 0xe000 1 fb0 にあることは間違いありません。

ドウェルチによる編集

誰かが誰かに夕食の借りがある。

hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));

PUT32(0xE000EDFC,0x01000000);

hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));

PUT32(0xE0001000,0x40000001);

hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));

PUT32(0xE0001FB0,0xC5ACCE55);
PUT32(0xE0001000,0x40000001);

hexstring(GET32(0xE0001FB4));
hexstring(GET32(0xE0001000));
hexstring(GET32(0xE0001004));
hexstring(GET32(0xE0001004));

出力

00000000
00000000
00000000
00000000
00000003
40000000
00000000
00000000
00000003
40000000
00000000
00000000
00000001
40000001
0000774F
0000B311

TRM の表は変な見た目で、他のドキュメントに示されているように、ベースに 0xFB0 と 0xFB4 を追加すると、Cortex-M7 の残りの DWT は 0xE0001xxx であり、実際には LAR と LSR が 0xE0001FB0 と 0xE0001FB4 になっているように見えます。 .

于 2016-07-13T19:59:22.900 に答える
2

CMSIS の一部として定義されている場合は、独自のレジスタ定義を作成しないことをお勧めします。そのためには、ドキュメントとその解釈の両方が正しいことが必要です。この場合、ドキュメントは確かに間違っているように見えますが、CMSIS ヘッダーは正しいようです。ドキュメントが正しいことを確認するよりも、CMSIS ヘッダーを自動的に検証する方がはるかに簡単なので、毎回 CMSIS を信頼します。

どのレジスタFP_LARが参照されているかはわかりませんが、アドレス割り当ては を参照していますが、どの Cortex-M4 が欠けてITM_LARいるかを意図していた可能性が高いようです。DWT_LAR

信頼するようにという私のアドバイスにもかかわらず、CMSIS 4.00 はDWT_LSR/SWT_LARのマスクを定義することを省略していますが、それらは対応する ITM マスクと同一であると私は信じています。

LARまた、レジスタは書き込み専用であることにも注意してください。読み取ろうとしても意味がありません。

CMSIS を使用したコードは次のようになります。

#include "core_cm7.h"  // Applies to all Cortex-M7

void reset_cnt()
{
    CoreDebug->DEMCR |= 0x01000000;
    DWT->CYCCNT = 0; // reset the counter
    DWT->CTRL = 0; 
}

void start_cnt()
{
    DWT->CTRL |= 0x00000001 ; // enable the counter
}

void stop_cnt()
{
     DWT->CTRL &= 0xFFFFFFFE ; // disable the counter    
}

unsigned int getCycles()
{
    return DWT->CYCCNT ;
}

// Not defined in CMSIS 4.00 headers - check if defined
// to allow for possible correction in later versions
#if !defined DWT_LSR_Present_Msk 
    #define DWT_LSR_Present_Msk ITM_LSR_Present_Msk
#endif
#if !defined DWT_LSR_Access_Msk 
    #define DWT_LSR_Access_Msk ITM_LSR_Access_Msk
#endif
#define DWT_LAR_KEY 0xC5ACCE55

void dwt_access_enable( unsigned ena )
{
    uint32_t lsr = DWT->LSR;;

    if( (lsr & DWT_LSR_Present_Msk) != 0 ) 
    {
        if( ena ) 
        {
            if ((lsr & DWT_LSR_Access_Msk) != 0) //locked: access need unlock
            {    
                DWT->LAR = DWT_LAR_KEY;
            }
        } 
        else 
        {
            if ((lsr & DWT_LSR_Access_Msk) == 0) //unlocked
            {   
                DWT->LAR = 0;
            }
        }
    }
}
于 2016-07-14T08:26:21.460 に答える