Отговори на тема  [ 33 мнения ]  Отиди на страница 1, 2, 3  Следваща
Защитени променливи в ембедед програмирането 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение Защитени променливи в ембедед програмирането
Възниква следният проблем: основния цикъл на програмата и някакво прекъсване трябва да споделят обща съставна променлива, т.е. такава, която е по-голяма от разредността на ядрото. Например, 32 битова променлива тип long в 8 битов процесор. Задачата за решаване е следната: Основния цикъл започва да работи с тази променлива, например да я копира на друго място, стига до 2-рия байт и в това време се генерира прекъсването, което записва съвсем друга стойност и когато управлението се върне обратно в цикъла, копирането на последните 2 байта създава неприятна боза.
Най-простото нещо, което ползвам (друго не се сетих), е просто да правя полу-семафор и да заключвам променливата, преди да започна да я обработвам. Прекъсването проверява дали е заключена, и ако е, не я пипа. Да, но тук възникват 2 основни момента, за които нямам решение.
1. При неприятно стечение на обстоятелствата, прекъсването може да изпадне в резонанс с основния цикъл и моментът на възникването му да съвпада винаги с момента, в който променливата се обработва и, съответно, е заключена. По този начин променливата никога няма да се опреснява.
2. Ако опресняването е критично, т.е. не можем да пропускаме обработката в прекъсването, то, очевидно заключващия механизъм няма смисъл.
Ще ви бъда благодарен, ако пуснете някакви линкове по въпроса, или споделите нещо, което сте измислили сами. :)


Пон Яну 22, 2007 10:36 am
Профил
Ранг: Напреднал
Ранг: Напреднал
Аватар

Регистриран на: Пет Окт 21, 2005 8:45 am
Мнения: 499
Мнение Re: Защитени променливи в ембедед програмирането
Реконструктор написа:
...Основния цикъл започва да работи с тази променлива, например да я копира на друго място, стига до 2-рия байт и в това време се генерира прекъсването, което записва съвсем друга стойност и когато управлението се върне обратно в цикъла, копирането на последните 2 байта създава неприятна боза...

Отложи (забрани) си прекъсването до края на операцията с тази променлива в основния цикъл. В началото на копирането забраняваш всички прекъсвания, в края на копирането - разрешаваш. Ако по време на обработката възникне irq, веднага след разрешаване на прекъсванията, ще влезеш в обработка. Ако пък е критично прекъсването да се обработи веднага след постъпване на irq, направи си дублираща променлива и в комбинация с флага, който ползваш за "заключване", ще ползваш или едната или другата променлива, в зависимост от състоянието на флага, т.е. нещо като стек.

_________________
Простотията е Божи дар, но човек не бива да парадира с подаръците си!


Пон Яну 22, 2007 11:07 am
Профил ICQ
Ранг: Новодошъл
Ранг: Новодошъл

Регистриран на: Вто Май 23, 2006 4:56 pm
Мнения: 113
Местоположение: Варна
Мнение 
Може да направиш обратното. Когато прекъсването опресни променливата да дигне един флаг. В главната програма преди копирането на всеки байт ще проверяваш този флаг и ако установиш, че се е промени по време на копиране връщаш цикъла отначало за да прочете отново всички байтове, като преди това естествено нулираш флага.


Пон Яну 22, 2007 11:13 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение Re: Защитени променливи в ембедед програмирането
evc написа:
Отложи (забрани) си прекъсването до края на операцията с тази променлива в основния цикъл. В началото на копирането забраняваш всички прекъсвания, в края на копирането - разрешаваш. Ако по време на обработката възникне irq, веднага след разрешаване на прекъсванията, ще влезеш в обработка. Ако пък е критично прекъсването да се обработи веднага след постъпване на irq, направи си дублираща променлива и в комбинация с флага, който ползваш за "заключване", ще ползваш или едната или другата променлива, в зависимост от състоянието на флага, т.е. нещо като стек.


Ами отлагането чисто хардуерно не знам дали е взъможно. В смисъл, в доста от системите, особено тия, дето са само с 1 вектор на прекъсване, май събитието се губи, ако в този момент са ти забранени прекъсванията.
Другото е добро, наистина ще работи, но трябва да има 2 флага - коя променлива е заключена и коя е последно обновена. Ще се усложни обработката, но ще работи (направо ще си трябва библиотека). Мерси! :)


Пон Яну 22, 2007 11:32 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение 
mndsl написа:
Може да направиш обратното. Когато прекъсването опресни променливата да дигне един флаг. В главната програма преди копирането на всеки байт ще проверяваш този флаг и ако установиш, че се е промени по време на копиране връщаш цикъла отначало за да прочете отново всички байтове, като преди това естествено нулираш флага.


Ами това си го мислех, но трябва да си пиша цялата ф-я по прехвърлянето на асм (не съм фен). :)


Пон Яну 22, 2007 11:36 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Едва ли ще намериш процесор, на който прекъсването да не се "запомня". Това си е стандарт, флага за прекъсване се вдига, даже и прекъсването да е забранено и когато го разрешиш, то се активира "моментало", ако междувременно не си нулирал флага насила.

То това му е и идеята на тоя механизъм, да се "запомнят" прекъсванията и да се обработят, било то и с малко закъснение.

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Пон Яну 22, 2007 11:57 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
Точно с забраняване на прекъсванията е начина. Не съм имал случай когато забавянето на прекъсването с 4-5 такта да е проблем.

Погледни ако искаш как е в ембедед OS-ите.

там забраняването на прекъсванията е доста често. Много операции се правят точно в такъв режим.

Там механизнма обикновенно е следния

Код:
void vPortEnterCritical( void )
{
   __disable_interrupt();

   /* Now interrupts are disabled ulCriticalNesting can be accessed
   directly.  Increment ulCriticalNesting to keep a count of how many times
   portENTER_CRITICAL() has been called. */
   ulCriticalNesting++;
}

void vPortExitCritical( void )
{
   if( ulCriticalNesting > portNO_CRITICAL_NESTING )
   {
      /* Decrement the nesting count as we are leaving a critical section. */
      ulCriticalNesting--;

      /* If the nesting level has reached zero then interrupts should be
      re-enabled. */
      if( ulCriticalNesting == portNO_CRITICAL_NESTING )
      {
         __enable_interrupt();
      }
   }
}


Това са функциите на freeRtos за забраняване и разрешаване на прекъсванията.


Пон Яну 22, 2007 1:12 pm
Профил
Ранг: Популярен
Ранг: Популярен

Регистриран на: Сря Яну 25, 2006 12:47 pm
Мнения: 305
Местоположение: Varna
Мнение 
Рек има и трети начин - променливата я пипаш само на едно място (ти си реши къде, дали irq или другаде), а в местата където сега я модифицират само даваш заявка(вдигаш флаг).
Ама и това е според зависи... :)


Пон Яну 22, 2007 1:14 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Сеп 25, 2004 12:32 pm
Мнения: 8382
Местоположение: София
Мнение 
Nikola Kirov написа:
Там механизнма обикновенно е следния


Да, това си е класически семафор/критична секция. :)
Аз поради няква причина останах с впечатлението, че доста системи не си "помнят" прекъсванията, за това възникна въпроса.


Пон Яну 22, 2007 1:48 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Окт 10, 2004 9:55 am
Мнения: 1718
Мнение Hm
Реконструктор написа:
Nikola Kirov написа:
Там механизнма обикновенно е следния


Да, това си е класически семафор/критична секция. :)
Аз поради няква причина останах с впечатлението, че доста системи не си "помнят" прекъсванията, за това възникна въпроса.

Какъв е проблема важния ти цикъл да си работи с 2 променливи негова и друга идваща от прекъсване , просто проверяваш в основния цикъл дали има имат разлика и ако има нужда основния цикъл я променя с новата .
Просто прекъсването винаги ще си пише на 1 място което си е негова променлива а не обща.


Пон Яну 22, 2007 1:53 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение 
Комбинации има много на тая тема... Въпреки че повечето се споменаха ще се пробвам да ги обобщя:

1) Ако бачкаш на С компилатор, повечето имат __monitor опции за функции. Правиш си функциите които четат/пишат защитената променлива с тая опция и оставаш на компилатора да му мисли...

2) Ако нямаш вложени извиквания на критични секции, може просто:

__disable_interrupt();
// бачкаш си защитената променлива
__enable_interrupt();

3) Ако имаш вложени критични секции и битови операции на процесора с достъп до флага за прекъсвания, може по следния начин:

bit old_flag;
old_flag = int_flag;
int_enable_flag = DISABLE;
// бачкаш си защитената променлива
int_enable_flag = old_flag;

4) Друг вариант е да броиш колко пъти си искал да забраниш прекъсванията - както е показал Никола...

5) Когато прекъсването само чете защитената променлива, а отдолу се променя, можеш да направиш две копия на променливата и един флаг който показва кое е валидното копие. В основната програма променяш "невалидното копие" и сменяш флага (с атомична операция). Така никога не забраняваш прекъсванията.

6) Когато само прекъсването пипа променливата, ти трябва едно копие на променливата и един флаг. Просто прекъсването винаги като пипне променливата вдига и флага. Отдолу, за да изчетеше променливата правиш цикъл в който първо сваляш флага, правиш си копие и проверяваш дали междувременно не се е вдигнал флага. Ако се е вдигнал зацикляш, докато успееш да прочетеш без да е имало прекъсване...


7) Ако променливата се променя от много места и не искаш да забраняваш прекъсванията може и по-сложен алгоритъм да се направи. Тук зависи дали имаш атомични операции, примерно на ARM може да нямаш и тогава семафорите стават една красива работа....


Пон Яну 22, 2007 2:22 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Юли 22, 2006 9:50 pm
Мнения: 1638
Мнение 
Рек това което казваш ти но използваш приоритетни прекъсвания - прекъсването с по-голям приоритет заменя стойността,а това с по-нисък- не я пипа.


Пон Яну 22, 2007 4:01 pm
Профил
Ранг: Минаващ
Ранг: Минаващ
Аватар

Регистриран на: Пон Яну 15, 2007 8:47 pm
Мнения: 59
Мнение 
Nikola Kirov написа:
Точно с забраняване на прекъсванията е начина. Не съм имал случай когато забавянето на прекъсването с 4-5 такта да е проблем.

Погледни ако искаш как е в ембедед OS-ите.

там забраняването на прекъсванията е доста често. Много операции се правят точно в такъв режим.

Там механизнма обикновенно е следния

Код:
void vPortEnterCritical( void )
{
   __disable_interrupt();

   /* Now interrupts are disabled ulCriticalNesting can be accessed
   directly.  Increment ulCriticalNesting to keep a count of how many times
   portENTER_CRITICAL() has been called. */
   ulCriticalNesting++;
}

void vPortExitCritical( void )
{
   if( ulCriticalNesting > portNO_CRITICAL_NESTING )
   {
      /* Decrement the nesting count as we are leaving a critical section. */
      ulCriticalNesting--;

      /* If the nesting level has reached zero then interrupts should be
      re-enabled. */
      if( ulCriticalNesting == portNO_CRITICAL_NESTING )
      {
         __enable_interrupt();
      }
   }
}


Това са функциите на freeRtos за забраняване и разрешаване на прекъсванията.


Цецо и Никола добре го казаха, отделн оче го пише и в datasheet на PIC,ARM , значи и в док. на AVR трябва да го пише.

Проблема не е дори, когато имаш някокло прекъсваня (а ако имаш и приоритети на прекъсванята хептен).
Пробелма е, когато може едно прекъсване да бъде задействано от две или повече неща/ситуации.

Примерно вързал си 4,8пина с int_on_statechange и става страшно , ако го забавиш.
Ако ползваш един външен int за няколко събития (примерно IC подава int_out към главното mcu< но това е знак само за събитие, но не и кое точно събтие).
И ако възникнат две събития в IC-то ,дали IC-то така ще е у-но , че да "помни" предишното състояние или препокривя ~"STATUS" регистъра (применро).

Може и със флагове , но софтуерно. Въпреки че в твоят случей ще е дървено така:

т.е

critical_point:

bsf MYSTATUS,CP ; critical point execution flag set
do
do
do
do
____int_ ->>>
do
do
do
bsf MYSTATUS,CP ; critical point execution done
return ; to main or whatever is in STACK

...

int:

btfsc MYSTATUS,CP
goto ... Или нещо друго

do_int

--- в твоя случей да опзлваш софтуерни флагове , за да следиш къде ти е програмата хич не е това, което искаш , но пак е вариант, макар и не добър.

_________________
@HCL: "Авторьт не поема отговорност в случай на некоректна или непьлна информация. "
(1)всеки има право на мнение, но това не означава че всеки е прав
(3)не сте длъжен да сте съгласен с неговото мнение.
Защо трябва да Ви се напомня ?


Пон Яну 22, 2007 5:24 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Нед Окт 31, 2004 9:19 pm
Мнения: 4464
Местоположение: Stara Zagora
Мнение 
маниак,пооправил си си наистина съобщенията но още малко ще трябва. След едно прочитане не разбрах какво искаш да кажеш. Не смятам да го чета пак и да гадая.
Още малко по смислено и си ОК :)


Пон Яну 22, 2007 5:55 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Съб Юли 22, 2006 9:50 pm
Мнения: 1638
Мнение 
Маниак,идеята на приоритетните прекъсвания е че ти сам задаваш приоритета,демек знаеш къде кво правиш :wink:
При прекъсвания в прекъсването се запазват статуси,работни регистри,програмни броячи,.....но явно още не си стигнал до тези неща или кат си ги чел си ги попрескочил.


Пон Яну 22, 2007 10:13 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 33 мнения ]  Отиди на страница 1, 2, 3  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни