EK-RA8M1 で Performance Monitoring Unit (PMU) を使おうとしていますが、DWTとPMUのCCNTR(0xE000307C)のサイクルカウントは取得できているのですが、PMUイベントはサイクルカウントも含めて、全て 0 のままカウントアップされていません。
環境は e2studio 25.1.0 の Renesas RA C/C++ Project で、gcc / armclang, Flat / TrustZone Secure のどれも同じ結果でした。
CMSISのAPI経由でもレジスタ直叩きでも同じ結果でした。
PMUに関する設定、データ取得手順ですが、別のCortex-M55のSoC (Grove Vision AI Module V2) では同じ設定でPMUイベントが取れたので、ソフトウェアの手順がおかしいわけではないと思っております。
EK-RA8M1 は PMUイベントが取得可能なものでしょうか。
PMU関連のレジスタにはアクセスできていますので、PMUはあると思っているのですが、HWの設定が必要?使用には条件または制限がある?
J-Link RTT Viewerで、レジスタダンプしたところ、このようになっておりました。
00> [PMU] num_event_counters 800> PMU->CNTENSET 0x0000000000> PMU->CNTENCLR 0x0000000000> PMU->INTENSET 0x0000000000> PMU->INTENCLR 0x0000000000> PMU->OVSCLR 0x0000000000> PMU->SWINC 0x0000000000> PMU->OVSSET 0x0000000000> PMU->TYPE 0x00A05F0800> PMU->CTRL 0x0000000000> PMU->AUTHSTATUS 0x00FF00FF00> PMU->DEVARCH 0x47700A0600> PMU->DEVTYPE 0x00000016
ここまで設定直後
ここから、PMU->CTRL と PMU->CNTENSET をセットして、一定時間経過後のダンプがこうなりました。
00> PMU->CTRL 0x0000000100> PMU->CNTENSET 0x800000FF00> [DWT] Cycle Count Register 225826820600> [DWT] CPI Count Register 000> [DWT] Exception Overhead Count Register 000> [DWT] Sleep Count Register 000> [DWT] LSU Count Register 000> [DWT] Folded-instruction Count Register 000> [DWT] Program Counter Sample Register 3355558800> [PMU] Cycle count 225827600300> [PMU] Time 4704741 [us]00> PMU_EVTYPER[0] 0x0011, PMU_EVCNTR[0] 000> PMU_EVTYPER[1] 0x0001, PMU_EVCNTR[1] 000> PMU_EVTYPER[2] 0x0006, PMU_EVCNTR[2] 000> PMU_EVTYPER[3] 0x0007, PMU_EVCNTR[3] 000> PMU_EVTYPER[4] 0x0008, PMU_EVCNTR[4] 000> PMU_EVTYPER[5] 0x0023, PMU_EVCNTR[5] 000> PMU_EVTYPER[6] 0x0024, PMU_EVCNTR[6] 000> PMU_EVTYPER[7] 0x003C, PMU_EVCNTR[7] 0
このように、PMUイベントは取得できておりません。
みりんレモンさん、こんにちは。
RA8M1デバイスや周辺ソリューションの詳細な対応状況はルネサスの技術問い合わせ窓口に問い合わせされた方がよいかと思われます。特にCM85 PMUはArm CoreSight(デバッグ)の一部機能になるため、ツール・デバッガが使用する機能とバッティングしないように注意を払う必要があります。
一先ず私の環境(EK-RA8D1、FSPv5.8.0、e2studio2025-01)で動作することを確認できましたので、手順を共有します。※PMUレジスタ・CMSIS APIの使い方や実行手順が正しいかは分かりません。ご参考まで。
ステップ1. RAプロジェクトを作成 私のテストではBare Metal - Minimalテンプレート、Flatプロジェクトタイプ、GCCコンパイラ、J-Linkデバッガを選択ステップ2. Stacksタブでr_icuドライバを追加。インスタンス名は"g_external_irq0". これは例外呼び出しテスト用のダミーですので、その他のモジュール設定変更は不要ステップ3. Generate Project Contentボタンを押すステップ4. 以下に添付のユーザコードをhal_entry.cファイルに追加ステップ5. プロジェクトをビルドステップ6. デバッグ構成を開き、時間計測機能を無効化 (Debugger > デバッグ・ツール設定 > 時間計測)ステップ7. デバッグ接続開始ステップ8. プログラムを走らせ、hal_entry関数の末尾のブレイクポイントで停止するまで待つ 停止したらcycle_count変数とevent_count_n (n=0~3)変数の値をe2studioの式ビューなどで確認 event_count_0とevent_count_1の期待値は100、それ以外はクロック構成やL1キャッシュの動き次第で異なります。 (参考)
hal_entry.cファイルに実装するコード:
#include "hal_data.h" volatile unsigned int cycle_count = 0; volatile unsigned int event_count_0 = 0; volatile unsigned int event_count_1 = 0; volatile unsigned int event_count_2 = 0; volatile unsigned int event_count_3 = 0; void pmu_test(void); void R_BSP_WarmStart(bsp_warm_start_event_t event); void hal_entry(void) { R_ICU_ExternalIrqOpen(&g_external_irq0_ctrl, &g_external_irq0_cfg); R_ICU_ExternalIrqEnable(&g_external_irq0_ctrl); pmu_test(); __BKPT(0); } void pmu_test(void) { // Disable DWT CYCCNT DWT->CTRL &= 0xFFFFFFFE; // Enable the PMU // Note: Before using the PMU, software needs to ensure // that trace is enabled via the Debug Exception Monitor Control Register, DEMCR: CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; __ISB(); __DSB(); ARM_PMU_Enable(); // Configure Event Counter Registers ARM_PMU_Set_EVTYPER(0, ARM_PMU_SW_INCR); ARM_PMU_Set_EVTYPER(1, ARM_PMU_EXC_TAKEN); ARM_PMU_Set_EVTYPER(2, ARM_PMU_L1I_CACHE); ARM_PMU_Set_EVTYPER(3, ARM_PMU_L1I_CACHE_REFILL); // Reset Event Counters and Cycle Counter ARM_PMU_EVCNTR_ALL_Reset(); ARM_PMU_CYCCNT_Reset(); // Start incrementing Cycle Count Register and Event Counter Registers 0 ~ 3 ARM_PMU_CNTR_Enable(PMU_CNTENSET_CCNTR_ENABLE_Msk| PMU_CNTENSET_CNT0_ENABLE_Msk| PMU_CNTENSET_CNT1_ENABLE_Msk| PMU_CNTENSET_CNT2_ENABLE_Msk| PMU_CNTENSET_CNT3_ENABLE_Msk); // Code you want to measure here for(int i=0; i<100; i++) { // Software increment for CNT0 ARM_PMU_CNTR_Increment(PMU_CNTENSET_CNT0_ENABLE_Msk); // Dummy exception call NVIC_SetPendingIRQ(g_external_irq0_cfg.irq); __NOP(); } // Stop incrementing Cycle Count Register and Event Counter Registers 0 ~ 3 ARM_PMU_CNTR_Disable(PMU_CNTENCLR_CCNTR_ENABLE_Msk| PMU_CNTENCLR_CNT0_ENABLE_Msk| PMU_CNTENCLR_CNT1_ENABLE_Msk| PMU_CNTENSET_CNT2_ENABLE_Msk| PMU_CNTENSET_CNT3_ENABLE_Msk); // Get count data cycle_count = ARM_PMU_Get_CCNTR(); event_count_0 = ARM_PMU_Get_EVCNTR(0); event_count_1 = ARM_PMU_Get_EVCNTR(1); event_count_2 = ARM_PMU_Get_EVCNTR(2); event_count_3 = ARM_PMU_Get_EVCNTR(3); (void) cycle_count; (void) event_count_0; (void) event_count_1; (void) event_count_2; (void) event_count_3; } void R_BSP_WarmStart(bsp_warm_start_event_t event) { if (BSP_WARM_START_POST_C == event) { /* Configure pins. */ R_IOPORT_Open (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME); } }
ReKawashima さん、
ご対応ありがとうございます。
こちらの環境(EK-RA8M1、FSPv5.8.0、e2studio2025-01)でも、教えていただいた手順でPMU Eventがカウントされていることが確認できました。
元々作っていたプロジェクトで確認したところ、状況証拠から DWT->CTRL レジスタの CYCCNTENA ビットを落としていなかったことが原因だったようです。
> 特にCM85 PMUはArm CoreSight(デバッグ)の一部機能になるため、ツール・デバッガが使用する機能とバッティングしないように注意を払う必要があります。
Grove Vision AI Module V2では デバッガを接続せず確認したので、ご指摘の通りかと思います。
これで、CPUストール要因の分析を進めることができるようになります。
ありがとうございました。