2015-10-06 105 views
1

我希望我的中斷服務程序使用不同的堆棧(可能是它自己的)&不使用調用者線程的堆棧。如何創建中斷堆棧?

thread_entry(){ 
    do_something(); 
    --> Interrupt occurs 
    do_otherstuff();  

} 

void interrupt_routine() 
{ 
    uint8_t read_byte;  // I don't want this to be part of caller thread's stack 
    read_byte= hw_read(); 
} 

難道可能&如何做到這一點?

+0

這是什麼編程語言? – JJJ

+0

真實代碼在C.我只是在這裏放了一種僞代碼。對於那個很抱歉。 – sniper

+0

如何讓變量'static'(取決於你有多少ram)? – vlp

回答

0

Linux的GNU C庫有控制信號執行的堆棧的方法。有關完整的詳細信息,請參閱documentation

的基本想法是,你棧和呼叫的功能

sigstack() 

指定該堆棧可用於的信號處理分配內存。然後,使用

sigaction() 

函數註冊一個處理一個特定的信號,並指定標誌值

SA_ONSTACK 

,這種處理器的特殊的堆疊

這裏上運行是顯示的代碼片段該模式是從Linux Programming Interface「借來的」示例

sigstack.ss_sp = malloc(SIGSTKSZ); 
if (sigstack.ss_sp == NULL) 
    errExit("malloc"); 

sigstack.ss_size = SIGSTKSZ; 
sigstack.ss_flags = 0; 
if (sigaltstack(&sigstack, NULL) == -1) 
    errExit("sigaltstack"); 
printf("Alternate stack is at   %10p-%p\n", 
     sigstack.ss_sp, (char *) sbrk(0) - 1); 

sa.sa_handler = sigsegvHandler;  /* Establish handler for SIGSEGV */ 
sigemptyset(&sa.sa_mask); 
sa.sa_flags = SA_ONSTACK;   /* Handler uses alternate stack */ 
if (sigaction(SIGSEGV, &sa, NULL) == -1) 
    errExit("sigaction"); 
+0

謝謝,這似乎是一個可行的解決方案。 – sniper

1

OS和中斷處理程序所需的堆棧在初始化時自行設置。這又是體系結構特定的代碼。對於ARM處理器的情況,當處理器處於中斷模式時,它具有獨特的R13。這個寄存器再次在啓動時初始化。你想用這個設計解決什麼問題。

0

這是一個簡單的x86內聯彙編實現。你有一個包裝函數來改變堆棧,並調用你的真實例程。

const uint32_t interrupt_stack_size = 4096; 
uint8_t interrupt_stack[interrupt_stack_size]; 

void interrupt_routine_wrap() 
{ 
    static int thread_esp; 
    // Stack grows towards lower addresses, so start at the bottom 
    static int irq_esp = (int) interrupt_stack + interrupt_stack_size; 

    // Store the old esp 
    asm mov dword ptr thread_esp, esp; 

    // Set the new esp 
    asm mov esp, dword ptr irq_esp; 

    // Execute the real interrupt routine 
    interrupt_routine(); 

    // Restore old esp 
    asm mov esp, dword ptr thread_esp; 
} 

我完全無視這裏的段寄存器(ss),但不同的內存模型可能需要存儲,隨着sp

您可以通過使用setjmp/longjmp來讀取/寫入所有寄存器來擺脫內聯彙編。這是一個更便攜的方式來做到這一點。

另請注意,我在這裏不保存任何寄存器,並且內聯彙編可能會混淆編譯器。也許值得在包裝程序周圍添加一對pusha/popa。如果將函數指定爲interrupt,編譯器可能會爲您執行此操作。檢查生成的二進制文件是否確定。