Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: scmRTOS. Вопросы и ответы.
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы
Страницы: 1, 2
bus16
С 1 - понятно, хотел просто уточнить.
Цитата(jorikdima @ Dec 27 2007, 12:32) *
2. За блокировкой идет то, что вы напишете, а не захват ресурса. И если вы проверите результат TMutex::LockSoftly() на правду/ложь и будете захватывать ресурс только в случае true, то все будет в порядке.

Mutex-ом как-раз блокируют используемый ресурс, просто-так блокировку вызывать бессмысленно, так-что за блокировкой всегда идёт именно работа с ресурсом.
TMutex::LockSoftly() - не возвращает значение, она "мягко" блокирует. Вот как именно "мягко" я и хочу понять
dxp
Цитата(bus16 @ Dec 27 2007, 15:45) *
Mutex-ом как-раз блокируют используемый ресурс, просто-так блокировку вызывать бессмысленно, так-что за блокировкой всегда идёт именно работа с ресурсом.
TMutex::LockSoftly() - не возвращает значение, она "мягко" блокирует. Вот как именно "мягко" я и хочу понять

Код
INLINE bool LockSoftly()     { TCritSect cs; if(ValueTag) return false; else Lock(); return true; }


как видно, функция возврящает bool. Если вернула true, то семафор захвачен, можно работать с ресурсом, если false, то семафор уже был захвачен другим процессом, тут его захватить не удалось, работать с ресурсом нельзя - можно заняться чем-то другим.
jorikdima
В том изаключается мягкость, что если ресурс уже заблокирован, то программисту дается возможность не ждать в спячке разблокировки, а поделоть что либо другое, естественно без использования упомянутого ресурса, ибо он занят. Чтобы дать разработчику понять захватился ли мютекс мягко или нет и придумано возвращения значения функции LockSoftly(). Если правда, то все хорошо, ресурс залочен - пользуйтесь. А если ложь, то сообщается, что ресурс занят можешь делать что либо другое. Если вам не нужна такая функциональность, то пользуйтесь Lock(). За блокировкой действительно всегда идет работа с ресурсом. Но я имел в виду, что по проверки условия возвращаемого значения можно и не идти на работу с ресурсом, а пойти по другим делам, если таковые имеются.
LessNik
Возник вопрос по обработке прерываний от системной периферии под ARM7 (AT91SAM7x256):

Как известно прерывания от DBGU и PIT совмещены. PIT- системный таймер. По DBGU приходят данные со скоростью 9600 почти без перерыва. Полученные данные записываются в к-либо буфер и обрабатываются.

Как лучше это сделать?
Может лучше в качестве системного таймера использовать TC0?

Код
void OS::SystemTimerUserHook()
{
if(AT91C_BASE_DBGU->DBGU_CSR&(AT91C_US_RXRDY|AT91C_US_OVRE))
  {                                                                  
     volatile unsigned int dummy = AT91C_BASE_DBGU->DBGU_CSR;      
     AT91C_BASE_DBGU->DBGU_CR=AT91C_US_RSTSTA;
     Buf=(AT91C_BASE_DBGU->DBGU_RHR);
     If (Buf==...)     FDbguDataReceived.SignalISR();
     AT91C_BASE_AIC->AIC_IVR = 1;   // ?
     AT91C_BASE_AIC->AIC_EOICR = 1; // ?
  }
}


Перестаёт срабатывать прерывание системного таймера OS::SystemTimer_ISR при активности DBGU, причём даже в условие не заходит ниразу.

P.S. В пошаговом режиме заходит в условие.
Сергей Борщ
Цитата(LessNik @ Jan 17 2008, 09:35) *
Перестаёт срабатывать прерывание системного таймера OS::SystemTimer_ISR при активности DBGU, причём даже в условие не заходит ниразу.
Что-то сразу не соображу, где может быть засада. Делал обмен по DBGU, правда, короткими пакетами. 115200.
Код
void OS::SystemTimerUserHook()
{
    pUpLink->Handler();
}
template<uint8_t rx_size, uint8_t tx_size>
void uart_t<rx_size, tx_size>::Handler()
{
    uint32_t Flags = pUART->US_CSR;
    Flags &= pUART->US_IMR;

    if(Flags & AT91C_US_TXRDY)
    {
        if(TxBuffer.get_count())
        {
            uint8_t Data;
            TxBuffer.pop(Data, 1);
            pUART->US_THR = Data;
        }
        else
            pUART->US_IDR = AT91C_US_TXRDY;
    }

    if(Flags & AT91C_US_RXRDY)
    {
        uint8_t Data = pUART->US_RHR;       // read anyway
        pUART->US_CR = AT91C_US_RSTSTA;     // clear errors if any
        if(RxBuffer.get_free_size())
            RxBuffer.push(Data);

    }
}
Посмотрел, как в OS_Target_cpp.cpp сделан обработчик прерывания - там баг, который я исправил в своем проекте, но не перенес исправление в репозиторий. В вашем коде SystemTimerUserHook(); вызывается только если прерывание пришло от таймера. Надо сделать такое изменнение:
Код
inline __arm void OS::SystemTimer_Handler()
{
    Kernel.SystemTimer();
}

OS_INTERRUPT void OS::SystemTimer_ISR()
{
    scmRTOS_ISRW_TYPE ISR;

    SYSTEM_TIMER_HANDLER();

#if scmRTOS_SYSTIMER_HOOK_ENABLE == 1
    SystemTimerUserHook();
#endif

    IRQ_DONE();
}
Спасибо, что нашли эту багу - сейсчас поправлю.

Посмотрел внимательнее ваш код - запись AT91C_BASE_AIC->AIC_EOICR = 1; // ? не нужна, это делается в самом обработчике, в макросе IRQ_DONE. А что вы хотели получить записью AT91C_BASE_AIC->AIC_IVR = 1; // ? мне совсем непонятно.
LessNik
a14.gif

Всё заработало. Пока ещё не смог сломать smile.gif

Цитата(Сергей Борщ @ Jan 17 2008, 11:59) *
А что вы хотели получить записью AT91C_BASE_AIC->AIC_IVR = 1; // ? мне совсем непонятно.


Это скопировал из другого проекта.
Использовал при отладке. Предварительно перешел в Protect Mode.

Но в этом проекте не использую Protect Mode. Надо удалить будет
LessNik
Цитата
Посмотрел, как в OS_Target_cpp.cpp сделан обработчик прерывания - там баг, который я исправил в своем проекте, но не перенес исправление в репозиторий. В вашем коде SystemTimerUserHook(); вызывается только если прерывание пришло от таймера. Надо сделать такое изменнение:
...


Может там ещё нужно где-то поправить? У меня периодически отваливаются прерывания от системного таймера при большой активности DBGU. Программа постоянно сидит в void OS::IdleProcessUserHook() {}

Если не трудно, можно выложить обновление здесь?
Сергей Борщ
Цитата(LessNik @ Jan 18 2008, 09:07) *
Может там ещё нужно где-то поправить? У меня периодически отваливаются прерывания от системного таймера при большой активности DBGU.
DBGU при этом продолжает работать?Стека для прерываний достаточно выделено?
Цитата(LessNik @ Jan 18 2008, 09:07) *
Программа постоянно сидит в void OS::IdleProcessUserHook() {}
Это нормально, если ей больше нечего делать.
Цитата(LessNik @ Jan 18 2008, 09:07) *
Если не трудно, можно выложить обновление здесь?
Да там только приведенные выше две функции OS::SystemTimer_Handler() и OS::SystemTimer_ISR() изменились. http://scmrtos.svn.sourceforge.net/viewvc/...1=71&r2=105
LessNik
Цитата(Сергей Борщ @ Jan 18 2008, 12:19) *
DBGU при этом продолжает работать?Стека для прерываний достаточно выделено?Это нормально, если ей больше нечего делать.Да там только приведенные выше две функции OS::SystemTimer_Handler() и OS::SystemTimer_ISR() изменились. http://scmrtos.svn.sourceforge.net/viewvc/...1=71&r2=105


GBGU перестаёт работать и перестаёт вызываться системное прерывание вообще OS_INTERRUPT void OS::SystemTimer_ISR() и Программа постоянно сидит в void OS::IdleProcessUserHook() {}, периодически реагируя на прерывание от другого таймера TC0.

Для верности объявил:
typedef OS::process<OS::pr0, 1000> TDBGUProc;
всё равно не работает.
Сергей Борщ
Цитата(LessNik @ Jan 18 2008, 16:36) *
GBGU перестаёт работать и перестаёт вызываться системное прерывание вообще OS_INTERRUPT void OS::SystemTimer_ISR() и Программа постоянно сидит в void OS::IdleProcessUserHook() {}, периодически реагируя на прерывание от другого таймера TC0.
Очень похоже, что ваша программа некорректно (без записи в AIC_EOICR) завершает какое-то из прерываний. При этом перестают вызываться прерывания с таким же и более низкими приоритетами. На это косвенно указывет и то, что программа крутится в Idle,т.е. не вызывается и переключатель контекста. Возможно, в каком-то из прерываний вы забыли завести объект OS:TISRW, в деструкторе которого и выпоняется эта запись. Если какое-либо ваше прерывание не использет никакие сервисы ОС, то можно не заводить в нем объект OS:TISRW, но тогда вы должны сами в конце этого прерывания вручную прописать AIC_EOICR.

Вот такая версия. Надеюсь, что ОС в данном случае не виновата. Но если вы все же найдете в ней недоработку-обязательно сообщите. И даже если не в ОС дело-все равно отпишитесь здесь, интересно же wink.gif

Цитата(prottoss @ Dec 13 2007, 14:18) *
кстати, в ассемблер на IAR тоже можно включать C-шные хедеры, так что я думаю, что можно побороть эту проблему.
Увы, насколько я понял рассматривая заголовочные файлы компилятора, __HAS_RAMPZ__ определяется не в заголовочном файле (который подключен к OS_Target_asm.s90), а самим компилятором на основе указанного ему типа процессора. А вот в ассемблере аналогичное определение они почем-то не сделали sad.gif Выход есть - написать в начале файла свой большой #if defined (__ATMEGA128__) и определить в нем __HAS_RAMPZ__ для всех процессоров, в которых он есть.

Надо занести это в трекер, чтобы не забыть сделать к ближайшему релизу
LessNik
Цитата(Сергей Борщ @ Jan 19 2008, 03:47) *
Очень похоже, что ваша программа некорректно (без записи в AIC_EOICR) завершает какое-то из прерываний. При этом перестают вызываться прерывания с таким же и более низкими приоритетами. На это косвенно указывет и то, что программа крутится в Idle,т.е. не вызывается и переключатель контекста. Возможно, в каком-то из прерываний вы забыли завести объект OS:TISRW, в деструкторе которого и выпоняется эта запись. Если какое-либо ваше прерывание не использет никакие сервисы ОС, то можно не заводить в нем объект OS:TISRW, но тогда вы должны сами в конце этого прерывания вручную прописать AIC_EOICR.


Получается, если я завожу объект OS:TISRW, то мне не нужно прописывать AIC_EOICR?
Я не нашел в деструкторе этого объекта записи в AIC_EOICR. Я обычно прописывал AT91C_BASE_AIC->AIC_EOICR = 0; И в примере тоже вручную прописывали:
Код
OS_INTERRUPT void Timer_ISR()
{
    OS::TISRW ISRW;
    volatile dword Tmp = AT91C_BASE_TCB->TCB_TC0.TC_SR;   // read to clear int flag

    AT91C_BASE_PIOA->PIO_SODR = (1 << 0);
    Timer_Ovf.SignalISR();

    AT91C_BASE_AIC->AIC_EOICR = 0;
}


Если не дописывать, то прерывание больше не вызывается

Попробовал так:
Код
OS_INTERRUPT void TimerCounter0Interrupt(void)
{
  OS::TISRW ISRW;
  volatile dword Tmp = AT91C_BASE_TCB->TCB_TC0.TC_SR;   // read to clear int flag

//    AT91C_BASE_AIC->AIC_EOICR = 0; без этой строчки не работает

}
Сергей Борщ
Цитата(LessNik @ Jan 22 2008, 08:40) *
Получается, если я завожу объект OS:TISRW, то мне не нужно прописывать AIC_EOICR?
Я не нашел в деструкторе этого объекта записи в AIC_EOICR.
Да, ошибся. Извините. Это в схеме 0 прописывать не надо - там это делается в ассемблерной "обертке". Надо будет и в схеме 1 ввести эту запись в деструктор, для однообразия
LessNik
Цитата(Сергей Борщ @ Jan 19 2008, 03:47) *
Надеюсь, что ОС в данном случае не виновата. Но если вы все же найдете в ней недоработку-обязательно сообщите. И даже если не в ОС дело-все равно отпишитесь здесь, интересно же wink.gif


Нашёл!

При настройке AIC, нужно использовать не AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, как было в примере, а AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL. Тогда всё работает стабильно:

Код
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL/*AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE*/ | AT91C_AIC_PRIOR_LOWEST + 1;
Сергей Борщ
Цитата(LessNik @ Jan 31 2008, 12:24) *
При настройке AIC, нужно использовать не AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, как было в примере, а AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL. Тогда всё работает стабильно:
Угу. Действительно. В моем проекте, где используется DBGU тоже стоит AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL. Внесу изменения в примеры ОСи. Спасибо!
Интересно, кто-нибудь знает, зачем я там делал EDGE?

P.S. гляньте вот сюда: ветка на сахаре. Обнаружился баг в TEeventFlag, там идет обсуждение путей его ликвидации.
spf
Цитата(Сергей Борщ @ Jan 31 2008, 18:02) *
P.S. гляньте вот сюда: ветка на сахаре. Обнаружился баг в TEeventFlag, там идет обсуждение путей его ликвидации.

И туда: [АНОНС] Для централизованного общения по теме scmRTOS создана "группа Google"
IgorKossak
Цитата(spf @ Feb 2 2008, 05:25) *

Ошибка!
Невозможно найти удаленный сервер
zltigo
Цитата(IgorKossak @ Feb 3 2008, 13:33) *
Невозможно найти удаленный сервер

Вчера еще дышал, я даже письмишко написал.
Сергей Борщ
Цитата(IgorKossak @ Feb 3 2008, 12:33) *
Ошибка!
Невозможно найти удаленный сервер
У меня провайдер в целях борьбы с порнухой режет и некоторые безобидные сайты (в том числе и groops.google.com). Вместо требуемой показывает страницу от IE "The page cannot be displayed". Возможно многие и верят, но я хожу из-под Оперы. Пойду к ним в понедельник пообщаюсь.
spf
Цитата(IgorKossak @ Feb 3 2008, 15:33) *
Невозможно найти удаленный сервер

Все работает, народ подтягивается.
IgorKossak
Цитата(spf @ Feb 4 2008, 17:21) *
Все работает, народ подтягивается.

По данной ссылке http://index.php/?showtopic=42800&hl= так и не могу зайти.
Ссылка правильная?

PS Нашёл правильную ссылку в соседней ветке.
spf
Цитата(IgorKossak @ Feb 5 2008, 11:11) *
По данной ссылке http://index.php/?showtopic=42800&hl= так и не могу зайти.
Ссылка правильная?

ну... видимо что-то потерялось:
http://electronix.ru/forum/index.php?s=&am...st&p=359121
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.