2015-10-06 61 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,编译器可能会为您执行此操作。检查生成的二进制文件是否确定。