0

In an embedded ARM project using a STM32f1 controller, I started to use a coroutine framework (https://github.com/xhawk18/s_task). It works well and simplifies my application.

However, each coroutine has its own stack, and I need to size the stack so that it can accommodate potentially nested interrupt calls.

One of the interrupt routines handles USB communication and the USB stack is a bit of a stack hog. Alone this is not an issue, but it seems to be quite a RAM waste to size many coroutine stacks for the worst case. I therefore thought I would give this ISR a separate stack.

The solution I came up with is this:

#define stringify(s) xstringify(s)
#define xstringify(s) #s

extern "C" {
  
void USB_LP_CAN1_RX0_IRQHandler_impl(void);

#define USB_STACK_SIZE 128
void* _usb_old_sp;
void* _usb_stack[USB_STACK_SIZE];

__attribute__((naked)) void USB_LP_CAN1_RX0_IRQHandler(void) {
    __asm__ volatile(" push {r0, lr} ");
    __asm__ volatile(" ldr  r0, =_usb_old_sp  ");
    __asm__ volatile(" str  sp, [r0]");
    __asm__ volatile(" ldr  sp, =_usb_stack+" stringify(USB_STACK_SIZE) "*4  ");
    USB_LP_CAN1_RX0_IRQHandler_impl();
    __asm__ volatile(" ldr  r0, =_usb_old_sp  ");
    __asm__ volatile(" ldr  sp, [r0]");
    __asm__ volatile(" pop {r0, pc} ");
}

void USB_LP_CAN1_RX0_IRQHandler_impl(void) {
  // ...code here...
}

}

It seems to work.

However, I wonder whether there could be simpler solutions. In particular, I am interested whether I could avoid the extra nested function call. I have it there because in the C routine the code to save the necessary registers will automatically be generated by the compiler. I therefore cannot declare the actual C code in the ISR naked, which I need to switch stack.

The other thing is that I will have to do this for every ISRs separately, at least for the ones that are stack-hungry. In an ideal world, all ISRs would share a single stack that is separate from the one of the coroutines.

I know there is a Main and a Process Stack Pointer, and these maybe could be used for such a switch? On the other hand, I do shy away from re-writing/changing the coroutine framework I now use. But maybe there is a simple solution to this?

Any ideas and hints are appreciated!

user52366
  • 1,035
  • 1
  • 10
  • 21

1 Answers1

0

I think I will use another coroutine framework, either FreeRTOS where the IRQ is executed on the main stack, or this one: https://github.com/QuantumLeaps/.

user52366
  • 1,035
  • 1
  • 10
  • 21