Я пытаюсь создать простой обработчик SV C в GNU G CC (не ARM G CC). Если вызывается служба SV C, она правильно вводит SVC_Handler()
, но когда я пытаюсь найти номер SV C, используемый для вызова обработчика SV C (svc_number
), я получаю значение 248 вместо 1.
Я использую CubeMX IDE и плату Nucleo-F401RE.
Код:
void SVC_Handler(void)
{
asm volatile (
"TST lr, #4\t\n"
"ITE EQ\t\n"
"MRSEQ r0, msp\t\n"
"MRSNE r0, psp\t\n"
"B %[SVC_Handler_Main]\t\n"
:
: [SVC_Handler_Main] "i" (SVC_Handler_Main)
: "r0"
);
}
void SVC_Handler_Main(unsigned int* svc_args) {
uint8_t svc_number;
svc_number = ((char* )svc_args[6])[-2];
switch(svc_number) { // <- that's where I get 248 instead of 1
case SVC_ADD:
SVC_Add_Handler(svc_args[0], svc_args[1]);
break;
default:
break;
}
}
int __attribute__ ((noinline)) SVC_Service_Add(int x, int y) {
svc(SVC_ADD);
}
#define SVC_ADD 1
#define svc(code) asm volatile ("SVC %[immediate]"::[immediate] "I" (code))
Я использовал выражение выражения с точкой останова после svc_number
, и его значение равно 248 вместо 1 что должно быть.
Сервисные вызовы (SV C) используются главным образом в проекте ОСРВ для программного обеспечения для входа в привилегированный режим. ARM G CC имеет хорошую поддержку для вызовов SV, тогда как в GNU G CC вы должны делать все это самостоятельно. Теория выглядит следующим образом: Когда вызывается SV (в моем случае SVC_Service_Add ()), он вызывает SVC_Handler (). SVC_Handler () проверяет, какой стек используется (основной msp или процесс psp), чтобы найти эту информацию, прочитав бит 2 регистра регистра (LR). В зависимости от этого, MSP или PSP сохраняется в r0. После этого компилятор помещает r0, r1, r2, r3, r12, r14, адрес возврата и xPSR в svc_args, поэтому эти параметры можно использовать в SVC_Handler_Main. svc_args [0] = r0, svc_args [1] = r1, ... svc_args [6] = SP (тот, который нам интересен, тот, где хранится число SV C). Так как стек Cortex M4 является полностью нисходящим, нам нужно сделать [-2], чтобы получить интересующий нас байт svc_args [6]. Поскольку вызов SVC_Handler был выполнен макросом SVC_ADD (0x01), ((char * ) svc_args [6]) [- 2] должен быть равен SVC_ADD, поэтому из SVC_Handler_Main () можно вызывать правильную функцию. Я не получаю 1, я почему-то получаю 248.
Вопрос : почему svc_number
равно 248 , тогда как я ожидал 1