реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Cortex M3, PendSV и переключение контекста
alt3857
сообщение Jun 8 2011, 11:13
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 94
Регистрация: 21-04-10
Пользователь №: 56 794



Привет!
В Cortex-M3 есть прерывание PendSV, в чем его основная цель? В доках нашел "PendSV is an interrupt-driven request for system-level service. In an OS environment, use PendSV for context switching when no other exception is active". Т.е. как я понял оно нужно (рекомендовано ARM-ом) для выполнения переключения контекста операционной системой. Но в операционке все равно задействован SysTick Timer и его прерывание для проверки необходимости переключения на каждый тик, почему контекст нельзя переключать в нем, зачем дополнительно нужно PendSV?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 8 2011, 11:17
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(alt3857 @ Jun 8 2011, 15:13) *
Но в операционке все равно задействован SysTick Timer и его прерывание для проверки необходимости переключения на каждый тик, почему контекст нельзя переключать в нем, зачем дополнительно нужно PendSV?

Необходимость переключения контекста в операционной системе может возникать далеко не только по тику таймера. Поэтому данная возможность должна быть доступна в произвольный момент времени.
Go to the top of the page
 
+Quote Post
gladov
сообщение Jun 9 2011, 04:34
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 169
Регистрация: 10-11-05
Из: Воронеж
Пользователь №: 10 687



Цитата(aaarrr @ Jun 8 2011, 15:17) *
Необходимость переключения контекста в операционной системе может возникать далеко не только по тику таймера. Поэтому данная возможность должна быть доступна в произвольный момент времени.


Именно поэтому таймер лишь генерирует запрос на переключение. Аналогичный запрос может быть сгенерирован и "изнутри" ОС, например, при освобождении какого-то ресурса, ожидаемого процессом. А вот обработка запроса переключения производится из PendSV. Операция вынесена в прерывание чтобы была возможность обеспечить атомарность действий.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 9 2011, 09:33
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Весь сок PendSV,SVC и Systick (pendSTset) поймете, когда захотите lock-free ось написать sm.gif
штука крутая, мне понравилось
Go to the top of the page
 
+Quote Post
KRS
сообщение Jun 9 2011, 21:34
Сообщение #5


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(gladov @ Jun 9 2011, 08:34) *
Операция вынесена в прерывание чтобы была возможность обеспечить атомарность действий.

Дело не в атомарности!
Это запрос на переключение контекста, который будет выполнен после выхода из критического участка (где прерывания запрещены) или после выхода из прерывания от устройства где получены данные для приоритетной задачи и т.п.
Очень удобная вещь! А учитывая методы входа/выхода кортекса в прерывания позволяет быстро и удобно переключить задачу после обработки прерываний!
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 10 2011, 22:44
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Цитата
Это запрос на переключение контекста, который будет выполнен после выхода из критического участка

Весь смысл этих операций, чтобы НЕ блокировать прерывания. а на pendsv можно навешать не только переключение контекста, у меня там висит обработчик очереди запросов от хардварных прерываний(у которых приоритет всегда выше,чем у pendsv,systick) на выполнения системных функций. В итоге локов нету, система всегда совершает прогресс и оверхед минимальный(ну так инструкций 20-30)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jun 11 2011, 01:39
Сообщение #7


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(brag @ Jun 11 2011, 03:44) *
... у меня там висит обработчик очереди запросов от хардварных прерываний(у которых приоритет всегда выше,чем у pendsv,systick) на выполнения системных функций.

А можно поинтересоваться в общих чертах, что за прерывания и какие системные функции?
Кроме того, если приоритет выше, значит они должны прерывать pendsv,systick, так?


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 11 2011, 19:54
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Цитата(GetSmart @ Jun 11 2011, 04:39) *
А можно поинтересоваться в общих чертах, что за прерывания

ну там от DMA, SPI, UART, USB итд.

Цитата
и какие системные функции?

ну там SignalSemaphore, SetSemaphore, CloseMutex итд

Цитата
Кроме того, если приоритет выше, значит они должны прерывать pendsv,systick, так?

да, совершенно верно. И их могут прервать прерывания с еще вышим припритетом.
Go to the top of the page
 
+Quote Post
KRS
сообщение Jun 11 2011, 20:14
Сообщение #9


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(brag @ Jun 11 2011, 23:54) *
ну там SignalSemaphore, SetSemaphore, CloseMutex итд

А смысл использовать для этих целей PendSV?
Для этого есть SVCall.
А PendSV это асинхронный запрос, который или из прерывания запрашивается или из критической секции. т.е. из участка кода с более высоким приоритетом чем PendSV иначе PendSV будет себя вести как SVCall.

В System Level Programmers’ Model есть глава
SVCall, PendSV and critical region code avoidance
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 12 2011, 13:43
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Цитата
А смысл использовать для этих целей PendSV?
Для этого есть SVCall.
А PendSV это асинхронный запрос, который или из прерывания запрашивается

так речь и шла о прерываниях:
Цитата(brag)
у меня там висит обработчик очереди запросов от хардварных прерываний(у которых приоритет всегда выше,чем у pendsv,systick) на выполнения системных функций

доступ к системным функциям из обычных тредов ессно через SVC
а критических секций нет, они на cortex-m3 просто не нужны.
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jun 12 2011, 18:06
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Вы код для семафоров, в таком случае, свой используете? Там же по умолчанию критические секции расставлены.
Очередь запросов у вас не переполняется? В чем вообще плюсы от использования lock free оси? Не проще ли использовать QP Framework - там имхо тоже lock free, но честнее.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 13 2011, 10:43
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Цитата(andrewlekar @ Jun 12 2011, 21:06) *
Вы код для семафоров, в таком случае, свой используете?
конечно свой. ось вообще вся своя.
Цитата
Там же по умолчанию критические секции расставлены.
у меня по умолчанию ничего не расставлено, по умолчанию у меня пустая папка, где со временем вырастают файлики с кодом sm.gif
Цитата
Очередь запросов у вас не переполняется?
нет. во первых ошибка переполняния обрабатывается и выводится сообщение. во вторых размер очереди выбирается так, чтобы хватило в самом худшем случаи. контроллеры с меньше,чем 64кб оперативки не беру.
Цитата
В чем вообще плюсы от использования lock free оси?
Если есть хоть какая-то работа с внешним потоком данных, то это прямой прирост производительности, во первых. прерывание выполняется сразу, а не ждет хз сколько, пока система отработает какую-то ерунду, часто вообще не мешающую выполнятся тому же прерыванию. прерывание далеко не всегда обращается к системной функции,а блокируем мы его(их всех) всегда,ибо не знаем,будет ли оно обращатся или нет.
Потом гораздо меньше лажи с приоритетами... вернее если код не lock-free, то и приоритеты прерываний можно засунуть по-дальше, толку от них мало.
Потом lock-free у меня только запись в очередь, а чтение и остальные функции wait-free.
Вообще про плюсы и минусы lock-free/wait-free можно почитать в инете, но все зависит от конкретной платформы. на armv7 мне показалось, что это круто, и я не ошибся (касается конкретно только моих проектов).
Цитата
Не проще ли использовать QP Framework - там имхо тоже lock free, но честнее.
мне сложнее, это надо вьезжать в этот фреймворк,материть его,если что-то мне там не нра итп..
Написать ось, которая будет соответствовать моим требованием займет не более недели времени, что гораздо проще и интереснее, чем драконится с каким-то фреймворком недельку-вторую
Go to the top of the page
 
+Quote Post
alt3857
сообщение Jun 14 2011, 17:59
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 94
Регистрация: 21-04-10
Пользователь №: 56 794



brag, можете коротенький пример последовательности переключения контекста привести, на примере 2 функций (из одной в другую)?
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 14 2011, 21:16
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



конкретный пример вотъ. код вроде простой и понятный...

собственно переключение. приоритет самый низкий
Код
F_NAKED void ePendSV(void){
    register U32 rpsp asm("r3");
    asm volatile(" mrs %0,PSP; stmdb %0!,{r4-r11,lr}" :"=r"(rpsp));
    pRunTcb->psp=rpsp;
    pRunTcb=pReadyTcb;
    rpsp=pRunTcb->psp;
    asm volatile(" ldmia %0!,{r4-r11,lr}; msr PSP,%0; bx lr" :"+r"(rpsp));
}

naked и асм.вставки тк gcc тупой не умеет юзать ldm/stm. а кусок сишного кода тк леньки мне и синтакс gas - бей головой дуба :D писать не удобно
также тут исключен код, перегружающий MPU регионы, нету у STM32F1 MPU. на NXP моя ось еще и защищенная wink.gif

постановка задачи,готовой к выполнению в очередь. используется внутри практически всех системных функций (CreateThread,OpenMutex итд). приоритет этих функций всегда выше или равен PendSV.
Код
void tcbEnqueueReady(t_bragOsTcb *tcb){
    U32 prio;
    prio=tcb->priority;
    cdllEnqueue(&readyQueue[prio],&tcb->queueNode);
    readyPrioMsk|=1<<(31-prio);
    if(prio<pReadyTcb->priority){
        pReadyTcb=tcb;
        PendSVset();
    }
}


Системные функции могут вызыватся только:
1. из SVC, в данном случаи приоритет выше, чем у PendSV. сделаете иначе - попадете на оооочень неприятные грабли! лень расписывать(много невсемпонятного текста) почему, но скажу пару ключевых слов: Приоритет, Стек, Tail-chainning. Если интересно - порисуйте диаграмки последовательности выполнения и все станет понятно.
2. из Systick. приоритет равен PendSV
Ессно выше приведенный код получается автоматически защищен от race-conditions.

Удаление задачи из очереди. Здесь PendSVset выполняется всегда, тк так сложилось, что у меня эта функция удаляет из очереди только ту задачу, которая в данный момент выполняется. но с ее помощью можно удалить любую задачу из очереди, при этом можно сделать проверку, чтобы даром не выполнять пустое переключение контекста,не влияющее на ход работы системы.
Код
void tcbDequeueReady(t_bragOsTcb *tcb){
    U32 prio;
    cdllRemove(&tcb->queueNode);
    prio=tcb->priority;
    if(cdllIsEmpty(&readyQueue[prio]))readyPrioMsk&=~(1<<(31-prio));
    pReadyTcb=getNextReadyTcb();
    PendSVset();
}


cdllХххх - работа с обычным двусвязным списком.
getNextReadyTcb - достает из головы этого самого списка(у меня их 32,на каждый тредовый приоритет свой список,выбирается не пустой список самого высокого приоритета) адрес tcb
PendSVset используется только в этих двух функциях, ну и еще при инициализации системы, чтобы переключится на первый тред.

ну и самый сок, добавление запроса в lock-free очередь. может использоватся любым прерыванием с любым приоритетом.
Код
int SrqEnqueue(U32 a0,U32 a1,U32 svc){
    register U32 r0 asm("r0");
    register U32 r1 asm("r1");
    U32 tail,newtail;
    
   // lockless enqueue
    do{
        asm volatile("ldrex %0,%1" :"=r"(tail) :"m"(srqQueue.tail));
        newtail=(tail+1)%MAX_SRQ_QUEUE_ITEMS;
        if(newtail==srqQueue.head)return ERR_QUEUE_FULL;
        asm volatile("strex %0,%2,%1" :"=&r"(r),"=m"(srqQueue.tail) :"r"(newtail));
    }while(r);
    
   // write data
    r0=a0;r1=a1;
    asm volatile("stmia %3,{%0,%1,%2}" : :"r"(r0),"r"(r1),"r"(svc),"r"(&srqQueue.buf[tail]) :"memory");
    PendSTset();
    return 0;
}

MAX_SRQ_QUEUE_ITEMS кратно степени двойки - % заменяется компиллером на обычный AND.
PendSTset - гыгы sm.gif там выгрузка этой очереди, и системный таймер там же. не хотелось нагружать маленький красивенький pendsv всякой ерундой, пусть pendsv будет именно pendsv и не более wink.gif
Код
void eSystick(void){
.....    блаблалбла-декларация....

    SrqDequeueRun();
    if(!IsSystick())return;

.....      блаблабла--системный таймер........

IsSystick - это действительно таймер тикнул?

выгрузка из очереди. wait-free. выполняется только из eSystick. здесь все просто,никаких хитростей.
Код
void SrqDequeueRun(void){
    register U32 r0 asm("r0");
    register U32 r1 asm("r1");
    U32 a0,a1,svc;
    t_srqItem *data;
    U32 head;
    
    head=srqQueue.head;
    if(head==srqQueue.tail)return;
    
    while(head!=srqQueue.tail){
        data=&srqQueue.buf[head];
        head=(head+1)%MAX_SRQ_QUEUE_ITEMS;
        asm volatile("ldmia %3,{%0,%1,%2}" :"=r"(r0),"=r"(r1),"=r"(svc) :"r"(data));
        a0=r0;a1=r1;
        /*if(svc>=sizeof(svcTable)/sizeof(t_Callback))*/
        a0=((int(*)(U32,U32))svcTable[svc])(a0,a1);
    }
    srqQueue.head=head;
}


на RVCT все обходится почти без асма с тем же результатом, он ldm/stm нормально генерит. Только алгоритмический код у него немного тормознее выходит (базового кода моей оси это не касается), или это я просто привык писать под gcc,выработалось чутье его алгоритмов оптимизации sm.gif)

Мютексы простые, без наследования приоритетов. Мне это не нужно. и производительность в +
Семафоры есть простые и с таймаутом - примитивы только set,signal,wait,wait+timeout
тред можно только создать и убить с другого треда. сам тред может себя остановить на некоторое время или выгрузится. также его могут убить обработчики fault-ов через ту же lock-free srq.
Ну и в принципе все.
Никаких критических секций, никаких циклов поиска итп.
KIS - keep it simple wink.gif
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 16th July 2025 - 17:13
Рейтинг@Mail.ru


Страница сгенерированна за 0.01472 секунд с 7
ELECTRONIX ©2004-2016