I've tried following the documentation to make an SVC instruction work. From the Arm documentation here my SVC_Handler function is as they specify:
void SVC_Handler(void)
{
__asm(
".global SVC_Handler_Main\n"
"TST lr, #4\n"
"ITE EQ\n"
"MRSEQ r0, MSP\n"
"MRSNE r0, PSP\n"
"B SVC_Handler_Main\n"
) ;
}
My SVC_Handler_Main's first few lines is again just like they specify:
void SVC_Handler_Main( unsigned int *svc_args )
{
unsigned int svc_number;
/*
* Stack contains:
* r0, r1, r2, r3, r12, r14, the return address and xPSR
* First argument (r0) is svc_args[0]
*/
svc_number = ( ( char * )svc_args[ 6 ] )[ -2 ] ;
switch( svc_number )
{...
When I run the following code:
__asm("SVC #17"); //17 is an example number
No matter what, the variable svc_number
is always 255. The SVC actually triggers just fine and I can do whatever I want inside of it...as long as the svc_number of 255 is used. Any other number just gets set to 255. Did I miss something?
This is an STM32F401RE chip on a Nucleo board.
I have searched far and wide and have figured out the issue. I'm not entirely sure why, but the code provided by ARM didn't work as written, despite using the STM32CubeIDE. I had to re-write the SVC_Handler function so that both volatile and naked attributes were used. It looks like this now and works just fine:
__attribute__ ((naked)) void SVC_Handler(void) {
__asm volatile(".global SVC_Handler_Main");
__asm volatile("TST LR, 4"); // check LR to know which stack is used
__asm volatile("ITE EQ"); // 2 next instructions are conditional
__asm volatile("MRSEQ R0, MSP"); // save MSP if bit 2 is 0
__asm volatile("MRSNE R0, PSP"); // save PSP if bit 2 is 1
__asm volatile("B SVC_Handler_Main"); // pass R0 as the argument
}