Перейти к содержанию
    

вызов супервизора SVCall в STM32

В cortex M есть команда вызова системных функций, SVC

при исполнении этой команды процессор переходит в обработчик исключения супервизора.

 

что должно происходить в обработчике исключения супервизора, вызов системной функции прямо в обработчике?

как то странно это. логичнее на мой взгляд было бы выйти из обработчика передав управление вызываемой функции в привилегированном режиме. незнаю как только реализовать это попроще

 

как правильно должно это все работать по задумкам разработчиков?

Изменено пользователем FFFF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как правильно должно это все работать по задумкам разработчиков?

Если выйти из обработчика, то кончится и привилегированный режим.

Поэтому обработчик вызывает функцию, она возвращается в обработчик и обработчик закрывается, а если надо, то перед этим сделает переключение контекста.

Смотрите как сделано в Mbed OS.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

спасибо.

и как это сделано в любой rtos? системная функция вызывается прямо в обработчике исключения и возвращается в него?

 

я с Си плохо знаком, пробираться в дебрях rtos для меня мучение

Изменено пользователем FFFF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Там в основном ассемблер. Для изучения сильно помогает Source Insight.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

что должно происходить в обработчике исключения супервизора, вызов системной функции прямо в обработчике?

как то странно это. логичнее на мой взгляд было бы выйти из обработчика передав управление вызываемой функции в привилегированном режиме. незнаю как только реализовать это попроще

Как душе угодно: можно прям оттуда вызвать, можно оттуда только программно активировать другое прерывание или задачу, где всё и свершить.

 

Как это сделано в любой RTOS.

Видимо uCOS-II - не любая. Так как вообще никак не использует SVC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Видимо uCOS-II - не любая. Так как вообще никак не использует SVC.

А во FreeRTOS вообще плохо поступили - SVC используется один раз в жизни -только при запуске первой задачи :crying: Но это дело можно под себя перепилить, если что, как мне кажется.

Изменено пользователем Arlleex

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Открыл вот порт FreeRTOS на Cortex-M4.

В этой RTOS переключатель контекста построен по следующей модели:

1. Сохранить контекст прерванной задачи;

2. Переключить указатель на контекст новой задачи;

3. Восстановить регистры из этого контекста.

 

Все 3 пункта выполняются в обработчике исключения PendSV.

Для того, чтобы начать выполнение, нужно как-то запустить первую задачу.

FreeRTOS предлагает решение на исключении SVC

__asm void prvStartFirstTask( void )
{
    PRESERVE8

    /* Use the NVIC offset register to locate the stack. */
    ldr r0, =0xE000ED08
    ldr r0, [r0]
    ldr r0, [r0]
    /* Set the msp back to the start of the stack. */
    msr msp, r0
    /* Clear the bit that indicates the FPU is in use in case the FPU was used
    before the scheduler was started - which would otherwise result in the
    unnecessary leaving of space in the SVC stack for lazy saving of FPU
    registers. */
    mov r0, #0
    msr control, r0
    /* Globally enable interrupts. */
    cpsie i
    cpsie f
    dsb
    isb
    /* Call SVC to start the first task. */
    svc 0
    nop
    nop
}

Сам обработчик

__asm void vPortSVCHandler( void )
{
    PRESERVE8

    /* Get the location of the current TCB. */
    ldr    r3, =pxCurrentTCB
    ldr r1, [r3]
    ldr r0, [r1]
    /* Pop the core registers. */
    ldmia r0!, {r4-r11, r14}
    msr psp, r0
    isb
    mov r0, #0
    msr    basepri, r0
    bx r14
}

 

А меня жаба душит транжирить SVC на такое... Вообще не хочу, чтобы FreeRTOS использовала SVC.

Есть идея сделать почти все то же самое, что в обработчике, но вызовом функции: только вместо bx r14 перевести процессор на использование PSP + непривилегированный режим. Ну и регистры все восстановить, потому как не в прерывании находимся. И это будет возможно сделать, поскольку после сброса CPU находится в привилегированном режиме, соответственно все системные функции работы с регистрами специального назначения ему разрешены.

Нужно попробовать, но хотелось бы выслушать критику... Работать будет?

 

Итого, что-то типа

__asm void prvStartFirstTask( void )
{
    PRESERVE8

    /* Use the NVIC offset register to locate the stack. */
    ldr r0, =0xE000ED08
    ldr r0, [r0]
    ldr r0, [r0]
    /* Set the msp back to the start of the stack. */
    msr msp, r0
    /* Clear the bit that indicates the FPU is in use in case the FPU was used
    before the scheduler was started - which would otherwise result in the
    unnecessary leaving of space in the SVC stack for lazy saving of FPU
    registers. */
    mov r0, #0
    msr control, r0
    /* Globally enable interrupts. */
    cpsie i
    cpsie f
    dsb
    isb

        // Финт ушами

        /* Get the location of the current TCB. */
    ldr    r3, =pxCurrentTCB
    ldr r1, [r3]
    ldr r0, [r1]
    // восстановить контекст первой задачи в нужной последовательности
    ldmia r0!, {тут список регистров R0-R12, LR, XPSR в правильном порядке}
    msr psp, r0
    isb
    mov r0, #0
    msr    basepri, r0
        // а тут восстановить PC и поехали
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А меня жаба душит транжирить SVC на такое... Вообще не хочу, чтобы FreeRTOS использовала SVC.

 

а Вы как бы распорядились SVC?

Изменено пользователем FFFF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ldr r0, =0xE000ED08

ldr r0, [r0]

ldr r0, [r0]

msr msp, r0

Что-то у Вас мухи с котлетами намешаны ;)

Зачем ещё и указатель стека прерываний на начало стека из таблицы прерываний ставить?

Это вобщем-то не относится к данной задаче. Хотя конечно хозяин - барин.

 

mov r0, #0

msr control, r0

Опять мухи с котлетами. Тогда сюда ещё до кучи и инициализацию пинов впендюрить можно. :laughing:

Да и вроде - невозможно так записать что-то в CONTROL. Нужно юзать EXC_RETURN.

 

dsb

isb

Зачем?

 

ldmia r0!, {тут список регистров R0-R12, LR, XPSR в правильном порядке}

Ну вообще-то тут R0-R3,R12,LR,XPSR совершенно лишние.

Вроде как достаточно восстановить R4-R11, занести в LR нужное значение и сделать BX LR (сымитировать возврат из прерывания с переключением на нужный стек и в нужный режим).

 

msr psp, r0

isb

mov r0, #0

msr basepri, r0

// а тут восстановить PC и поехали

В результате режим процессора Вы не переключили и он остался в handler-режиме.

Для переключения нужно юзать BX LR с правильным значением в нём.

И опять же - ISB тут лишняя.

 

В uCOS вообще не заморачиваются: они изначально заносят в PSP=0, а потом просто программно возбуждают PendSV (как для любого программного переключения контекста), а в ISR PendSV делают проверку если PSP==0 (начальный старт первой задачи) - просто пропускают сохранение контекста сразу переходя к восстановлению контекста самой приоритетной задачи.

Конечно при этом в переключатель контекста добавляется одна лишняя команда, но имхо - это несущественно.

 

PS: Да и, как видно по приведённому Вами коду, FreeRTOS использует не всю SVC, а только SVC 0. Остальные 255 - свободны. Неужто Вам 255 не хватит? Для чего???

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если передавать номер функции в регистре перед вызовом SVC то можно и больше чем 256

 

еще и быстрее будет. надо лишь в регистр ввести значение необходимой функции. 2 команды если число больше 255, не придется доставать значение из SVC в обработчике

Изменено пользователем FFFF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

если передавать номер функции в регистре перед вызовом SVC то можно и больше чем 256

еще и быстрее будет. надо лишь в регистр ввести значение необходимой функции. 2 команды если число больше 255, не придется доставать значение из SVC в обработчике

Цитируя давайте ссылки на первоисточник:

ARM Mbed OS, файл rtx_ketnel.c, строка 516

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

собственно я сам до этого дошел, думаю это лежит на поверхности

 

я Си не знаю, 516 строка для меня темный лес

Изменено пользователем FFFF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А меня жаба душит транжирить SVC на такое... Вообще не хочу, чтобы FreeRTOS использовала SVC.

 

а Вы как бы распорядились SVC?

Сам факт того, что это прерывание используется только 1 раз... Ужас.

Даже если оно мне не нужно - у меня внутренний когнитивный диссонанс :biggrin:

 

Что-то у Вас мухи с котлетами намешаны ;)

Зачем ещё и указатель стека прерываний на начало стека из таблицы прерываний ставить?

Это вобщем-то не относится к данной задаче. Хотя конечно хозяин - барин.

 

...

 

Опять мухи с котлетами. Тогда сюда ещё до кучи и инициализацию пинов впендюрить можно. :laughing:

 

...

 

Зачем?

Не мое. Это я сейчас порт на Cortex-M4 открыл и сюда вставил :laughing: Нужно оно там или не нужно - это другой вопрос, конечно же.

 

Да и вроде - невозможно так записать что-то в CONTROL. Нужно юзать EXC_RETURN.

В привилегированном режиме можно. EXC_RETURN используется при входе в прерывание и выходе из него.

 

Ну вообще-то тут R0-R3,R12,LR,XPSR совершенно лишние.

Вроде как достаточно восстановить R4-R11, занести в LR нужное значение и сделать BX LR (сымитировать возврат из прерывания с переключением на нужный стек и в нужный режим).

В этом и фишка, что я хочу полностью избавиться от SVC, передать управление на первую задачу без использования прерывания. Поэтому я и предложил восстановить весь регистровый стек, потому как мы не в прерывании еще находимся, поэтому R0-R3, R12, LR, XPSR восстановить нужно будет.

Интересно вот, что будет если в привилегированном режиме потока записать EXC_RETURN в LR со значениями (PSP + Thread Mode) и сделать BX LR... Какой-нибудь Usage Fault, скорее всего.

 

В результате режим процессора Вы не переключили и он остался в handler-режиме.

Для переключения нужно юзать BX LR с правильным значением в нём.

И опять же - ISB тут лишняя.

Повторюсь, что режим процессора должен оставаться в Thread. Если бы прерывание было - как в исходном примере, то я не задался бы целью обойти использование SVC :(

ISB лишняя, да... Там весь порт кривущий, но работает. Вычищаю потихоньку, что нужно мне. Вот и решил заморочиться, избавившись от такого не очень, на мой взгляд, разумного использования SVC. Я еще понимаю, если бы оно вызывалось раз в день. Но тут только при старте приложения...

 

PS: Да и, как видно по приведённому Вами коду, FreeRTOS использует не всю SVC, а только SVC 0. Остальные 255 - свободны. Неужто Вам 255 не хватит? Для чего???

Мне-то хватит. Просто хочу свои SVC как можно короче сделать, без лишних телодвижений. А подход, предложенный индусами-портировщиками, мне не очень нравится. Поэтому и гадаю, как красиво сделать ;)

 

В uCOS вообще не заморачиваются: они изначально заносят в PSP=0, а потом просто программно возбуждают PendSV (как для любого программного переключения контекста), а в ISR PendSV делают проверку если PSP==0 (начальный старт первой задачи) - просто пропускают сохранение контекста сразу переходя к восстановлению контекста самой приоритетной задачи.

Конечно при этом в переключатель контекста добавляется одна лишняя команда, но имхо - это несущественно.

Воот. Вот это уже другое дело. Я тоже рассматривал такой вариант, но как раз лишние пару инструкций проверки травят душу перфекциониста :biggrin:

Вот и думаю, что это сделать, скорее всего, можно без прерываний и лишних телодвижений в переключателе контекста (я хотел бы, чтобы он был как можно короче и быстрее). Просто нужно исхитриться и восстановить весь контекст выполнения первой запускаемой задачи.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...