簡體   English   中英

ESP32 最高優先級中斷在匯編中獲取定時器值

[英]ESP32 Highest Priority Interrupt To Grab Timer Value In Assembly

我正在嘗試在 ESP32 上安裝一個 GPIO 中斷,以盡可能精確地記錄每秒一次的脈沖。 其他正在運行的進程(在兩個處理器上)延遲了我正常的基於 C 的中斷(ESP_INTR_FLAG_LEVEL3),使檢測變化最多半毫秒。

所以我的下一步是在匯編中調用中斷,這需要使用 ESP32 的更高優先級。 我只需要獲取硬件定時器值並將其存儲在全局變量中。

我對 ESP32 組裝沒有經驗,更不用說了。 這是我能夠想出的:

.global timer0_isr
.global timer0_value

timer0_isr:
    movi a10, 0x3FF5F00C    //Timer 0 Update address into a10
    s32i a0, a10, 0         //A write instruction copies the timer to the timer registers; doesn't matter what is written
    movi a11, timer0_value  //timer0_value address into a11
    movi a12, 0x3FF5F004    //Timer 0 lower 32 bits address into a12
    s32i a12, a11, 0        //Store lower 32 bits to timer0_value
    movi a13, 0x3FF5F008    //Timer 0 upper 32 bits address into a13
    s32i a13, a11, 4        //Store upper 32 bits to timer0_value + 4

在 C 中聲明了 function 和變量:

extern "C" {
  extern uint64_t timer0_value = 0;
  void timer0_isr();
}

這是調用 function 時的異常:

Let's get the address: 3FFD1420 <---This is my pulling the variable address in C. 它確實出現在 A11 中

Guru Meditation Error:核心 1 恐慌(IllegalInstruction)。 異常未處理。

Memory 在 0x400d4fc4 轉儲:eccbd10b 00001bd9 21004136

核心 1 寄存器轉儲:

PC:0x400d4fca PS:0x00060f30 A0:0x800d4db2 A1:0x3ffb2770
A2:0x3ffd2818 A3:0x3ffd1420 A4:0x3ffd2c2c A5:0x8814bd16
A6:0x00000000 A7:0x00000001 A8:0x800d3a99 A9:0x00000000
A10:0x3ff5f00c A11:0x3ffd1420 A12:0x3ff5f004 A13:0x3ff5f008
A14:0x0000000a A15:0x0000033c SAR:0x00000003 借口:0x00000000
EXCVADDR:0x00000000 LBEG:0x4008bea9 LEND:0x4008beb9 LCOUNT:0xfffffffd
回溯:0x400d4fc7:0x3ffb27700x400d4daf:0x3ffb27d0 0x400e44b2:0x3ffb2820

最奇怪的部分是我可以注釋掉程序集的不同部分並讓它運行。 我什至可以將 32 位復制到 timer0_value 中,盡管沒有更新計時器指令,該值不會改變。 如果變量寫入指令被注釋掉,更新定時器指令將運行

這是 ESP32 參考: https://www.mouser.com/pdfdocs/ESP32-Tech_Reference.pdf

這是 Xtensa 指令參考: https://www.cadence.com/content/dam/cadence-www/global/en_US/documents/tools/ip/tensilica-ip/isa-summary.pdf

另外值得一提的是,我正在使用 Arduino IDE 2.0

編輯:Xtensa 文檔有movi描述了“使用 12 位有符號常量加載寄存器”。 32 位地址是否有可能損壞 memory,如果是這樣,我如何為s32i指令引用 32 位 memory 地址?

中斷處理程序需要存儲在“IRAM”——“指令RAM”中。 否則無法保證中斷處理程序在需要時駐留在可執行文件 memory 中,並且調用它的結果將是未定義和不可預測的。

在 C 和 C++ 中,您可以使用IRAM_ATTR屬性來執行此操作:

void IRAM_ATTR void timer0_isr();

在匯編中,您需要使用.section來告訴 linker 代碼必須存儲在 IRAM 中:

.section        .iram1,"ax"

.global timer0_isr
.global timer0_value
.align      4

timer0_isr:
    movi a10, 0x3FF5F00C 
    ...

Espressif 在高級中斷中記錄了匯編代碼。 它們還包括.align ,我相信它會強制代碼在 32 位邊界上對齊。 我不是 100% 確信這是需要的,甚至不是它所做的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM