| Микроконтролери и електроника http://mcu-bg.com/mcu_site/ |
|
| Защитени променливи в ембедед програмирането http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=3613 |
Страница 1 от 3 |
| Автор: | Реконструктор [ Пон Яну 22, 2007 10:36 am ] |
| Заглавие: | Защитени променливи в ембедед програмирането |
Възниква следният проблем: основния цикъл на програмата и някакво прекъсване трябва да споделят обща съставна променлива, т.е. такава, която е по-голяма от разредността на ядрото. Например, 32 битова променлива тип long в 8 битов процесор. Задачата за решаване е следната: Основния цикъл започва да работи с тази променлива, например да я копира на друго място, стига до 2-рия байт и в това време се генерира прекъсването, което записва съвсем друга стойност и когато управлението се върне обратно в цикъла, копирането на последните 2 байта създава неприятна боза. Най-простото нещо, което ползвам (друго не се сетих), е просто да правя полу-семафор и да заключвам променливата, преди да започна да я обработвам. Прекъсването проверява дали е заключена, и ако е, не я пипа. Да, но тук възникват 2 основни момента, за които нямам решение. 1. При неприятно стечение на обстоятелствата, прекъсването може да изпадне в резонанс с основния цикъл и моментът на възникването му да съвпада винаги с момента, в който променливата се обработва и, съответно, е заключена. По този начин променливата никога няма да се опреснява. 2. Ако опресняването е критично, т.е. не можем да пропускаме обработката в прекъсването, то, очевидно заключващия механизъм няма смисъл. Ще ви бъда благодарен, ако пуснете някакви линкове по въпроса, или споделите нещо, което сте измислили сами. |
|
| Автор: | evc [ Пон Яну 22, 2007 11:07 am ] | |||||||||
| Заглавие: | Re: Защитени променливи в ембедед програмирането | |||||||||
Отложи (забрани) си прекъсването до края на операцията с тази променлива в основния цикъл. В началото на копирането забраняваш всички прекъсвания, в края на копирането - разрешаваш. Ако по време на обработката възникне irq, веднага след разрешаване на прекъсванията, ще влезеш в обработка. Ако пък е критично прекъсването да се обработи веднага след постъпване на irq, направи си дублираща променлива и в комбинация с флага, който ползваш за "заключване", ще ползваш или едната или другата променлива, в зависимост от състоянието на флага, т.е. нещо като стек. |
||||||||||
| Автор: | mndsl [ Пон Яну 22, 2007 11:13 am ] |
| Заглавие: | |
Може да направиш обратното. Когато прекъсването опресни променливата да дигне един флаг. В главната програма преди копирането на всеки байт ще проверяваш този флаг и ако установиш, че се е промени по време на копиране връщаш цикъла отначало за да прочете отново всички байтове, като преди това естествено нулираш флага. |
|
| Автор: | Реконструктор [ Пон Яну 22, 2007 11:32 am ] | |||||||||
| Заглавие: | Re: Защитени променливи в ембедед програмирането | |||||||||
Ами отлагането чисто хардуерно не знам дали е взъможно. В смисъл, в доста от системите, особено тия, дето са само с 1 вектор на прекъсване, май събитието се губи, ако в този момент са ти забранени прекъсванията. Другото е добро, наистина ще работи, но трябва да има 2 флага - коя променлива е заключена и коя е последно обновена. Ще се усложни обработката, но ще работи (направо ще си трябва библиотека). Мерси! |
||||||||||
| Автор: | Реконструктор [ Пон Яну 22, 2007 11:36 am ] | |||||||||
| Заглавие: | ||||||||||
Ами това си го мислех, но трябва да си пиша цялата ф-я по прехвърлянето на асм (не съм фен). |
||||||||||
| Автор: | Цецо [ Пон Яну 22, 2007 11:57 am ] |
| Заглавие: | |
Едва ли ще намериш процесор, на който прекъсването да не се "запомня". Това си е стандарт, флага за прекъсване се вдига, даже и прекъсването да е забранено и когато го разрешиш, то се активира "моментало", ако междувременно не си нулирал флага насила. То това му е и идеята на тоя механизъм, да се "запомнят" прекъсванията и да се обработят, било то и с малко закъснение. |
|
| Автор: | Nikola Kirov [ Пон Яну 22, 2007 1:12 pm ] | |||||||||
| Заглавие: | ||||||||||
Точно с забраняване на прекъсванията е начина. Не съм имал случай когато забавянето на прекъсването с 4-5 такта да е проблем. Погледни ако искаш как е в ембедед OS-ите. там забраняването на прекъсванията е доста често. Много операции се правят точно в такъв режим. Там механизнма обикновенно е следния
Това са функциите на freeRtos за забраняване и разрешаване на прекъсванията. |
||||||||||
| Автор: | bkulev [ Пон Яну 22, 2007 1:14 pm ] |
| Заглавие: | |
Рек има и трети начин - променливата я пипаш само на едно място (ти си реши къде, дали irq или другаде), а в местата където сега я модифицират само даваш заявка(вдигаш флаг). Ама и това е според зависи... |
|
| Автор: | Реконструктор [ Пон Яну 22, 2007 1:48 pm ] | |||||||||
| Заглавие: | ||||||||||
Да, това си е класически семафор/критична секция. Аз поради няква причина останах с впечатлението, че доста системи не си "помнят" прекъсванията, за това възникна въпроса. |
||||||||||
| Автор: | plameniv [ Пон Яну 22, 2007 1:53 pm ] | ||||||||||||||||||
| Заглавие: | Hm | ||||||||||||||||||
Какъв е проблема важния ти цикъл да си работи с 2 променливи негова и друга идваща от прекъсване , просто проверяваш в основния цикъл дали има имат разлика и ако има нужда основния цикъл я променя с новата . Просто прекъсването винаги ще си пише на 1 място което си е негова променлива а не обща. |
|||||||||||||||||||
| Автор: | miro_atc [ Пон Яну 22, 2007 2:22 pm ] |
| Заглавие: | |
Комбинации има много на тая тема... Въпреки че повечето се споменаха ще се пробвам да ги обобщя: 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 може да нямаш и тогава семафорите стават една красива работа.... |
|
| Автор: | Ки4о [ Пон Яну 22, 2007 4:01 pm ] |
| Заглавие: | |
Рек това което казваш ти но използваш приоритетни прекъсвания - прекъсването с по-голям приоритет заменя стойността,а това с по-нисък- не я пипа. |
|
| Автор: | trm_only_for_work [ Пон Яну 22, 2007 5:24 pm ] | ||||||||||||||||||
| Заглавие: | |||||||||||||||||||
Цецо и Никола добре го казаха, отделн оче го пише и в 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 --- в твоя случей да опзлваш софтуерни флагове , за да следиш къде ти е програмата хич не е това, което искаш , но пак е вариант, макар и не добър. |
|||||||||||||||||||
| Автор: | Nikola Kirov [ Пон Яну 22, 2007 5:55 pm ] |
| Заглавие: | |
маниак,пооправил си си наистина съобщенията но още малко ще трябва. След едно прочитане не разбрах какво искаш да кажеш. Не смятам да го чета пак и да гадая. Още малко по смислено и си ОК |
|
| Автор: | Ки4о [ Пон Яну 22, 2007 10:13 pm ] |
| Заглавие: | |
Маниак,идеята на приоритетните прекъсвания е че ти сам задаваш приоритета,демек знаеш къде кво правиш При прекъсвания в прекъсването се запазват статуси,работни регистри,програмни броячи,.....но явно още не си стигнал до тези неща или кат си ги чел си ги попрескочил. |
|
| Страница 1 от 3 | Часовете са според зоната UTC + 2 часа [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|