| Микроконтролери и електроника http://mcu-bg.com/mcu_site/ |
|
| Извикване на функция http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=4730 |
Страница 1 от 1 |
| Автор: | Ки4о [ Чет Авг 30, 2007 5:17 pm ] |
| Заглавие: | Извикване на функция |
Нещо ми са мътни нещата - по-точно как се използва една функция едновременно и в главна програма и в прекъсване.Ситуацията е следната:Програмката за опресняване на ЛСД-то я ползвам и в главната програма - при първоначална инициализация и в програмата по прекъсване - когато трябва да изведа някой данни.Компилатора (Хай-тековски) не ревеше но изведнъж ревна - грешка 472. Описанието на тази грешка е: (472) non-reentrant function "*" appears in multiple call graphs: rooted at "*" and "*" (Linker) This function can be called from both main-line code and interrupt code. Use the reentrant keyword, if this compiler supports it, or recode to avoid using local variables or parameters, or duplicate the function, e.g.: void interrupt my_isr(void) { scan(6); /* scan is called from an interrupt function */ } void process(int a) { scan(a); /* scan is also called from main-line code */ } До колкото схващам това не е позволено.Единия път трябва да я ползвам с предаване на параметър, или да си напиша същата функция ама с друго име.Има ли друго спасение?На асемблер-няма проблеми ама на С явно има.Някой ще може ли да хвърли светлина по въпроса като разясни? |
|
| Автор: | ¶ [ Чет Авг 30, 2007 5:37 pm ] |
| Заглавие: | |
На C има проблем, но зависи от компилатора. Примерно по-старите версии на CCS C не ревяха, което беше добре, но по-новите ревят. Нямат и опция за забрана на тази проверка. Логическия проблем го има и при асемблера, но той не прави тези проверки. Реентратна функция означава функция, която може да се извиква по всяко време от различни асинхронни процеси, в случая от прекъсване и главна програма. Затова променливите на такава функция трябва да са auto, т.е. да се пазят в стека. Ако са глобални, трябва да вземеш мерки да ги синхронизираш, т.е. да добавиш флагове, които да ти показват, дали можеш да пипаш променливата или не. Причината е, че не знаеш кой асинхронен процес кога ще иска услуга от твоята функция. Може да стане така, че тя да обслужва един процес, същевременно втори процес се обръща към нея, докато не е завършила изпълнението на услугата за първия. Съответно глобалните ти променливи ще се брактисат, както първия, така и втория процес няма да са доволни от работата й. По принцип аз съм против това да се индикира като грешка от компилаторите за микроконтролери, защото се връзват ръцете на програмиста. Би трябвало да има избор програмиста, да го задава да се тълкува от компилатора като грешка, или да се тълкува като предупреждение. Виж при многозадачните и многопотребителските системи без това е на практика невъзможно да се синхронизират нишките на процесите. |
|
| Автор: | Yanek [ Чет Авг 30, 2007 8:05 pm ] |
| Заглавие: | |
Ако става дума за ПИК, то тогава проблема би могъл да бъде следния. Ако използваш овърлей модел на компилатора, тогава локалните променливи са просто клетки от РАМ-а които компилатора адресира директно т.е. когато извикаш във фоновата програма тази ф-ия тя използва променливи А и Б. Ако през това време дойде прекъсване, в което викаш същата ф-ия, отново ще се използват същите А и Б, така че би могло да промениш съдържанието им за фоновата. Но когато ползваш стеков модел тогава променливите се разполагат в стека по стандартния начин и са уникални за всяко извикване на тази ф-ия. Може и да не съм прав за твоя компилатор, но е твърде вероятна причина. Едит: Не знаех, че става дума за глобални променливи, но е интересно, компилатора не би трябвало да се обажда за глобалните. |
|
| Автор: | Ки4о [ Чет Авг 30, 2007 8:45 pm ] |
| Заглавие: | |
Май трябва да разясня още.ЛЦД-то се ползва при началната инициализация на променливите в контролера,като след инициализация се рзарешава прекъсвания.През останалото времме се върти един цикъл за сканиране на клавиатура и всичко се прави при прекъсване (извеждане на данни и др). При сработване на клавиатурата се забранява прекъсваненията и се свършват задачите зададени от бутоните след което отново се разрешават прекъсванията и процеса продължава.Явно се получава прекъсване в прекъсването и за това компилатора пищи.Ще пробвам да си сменя алгоритъма на програмата. |
|
| Автор: | Dimitar [ Чет Авг 30, 2007 8:56 pm ] |
| Заглавие: | |
Прекъсване в прекъсването на ПИК-а малко трудно ще се получи. А по принцип трябва да се пазиш да правиш доста неща в прекъсването. По-добре вдигай някакъв флаг, който да проверяваш в основната програма и тогава да викаш функциите. Нито клавиатурата, нито LCD-то са критични процеси, че чак да трябва вътре в прекъсването да ги правиш. А така като се замисля - в целия регулатор, без значение какъв е - не би трябвало да има такъв процес. Та сложи си едни флагчета да ти е мирна главата и да не изпадаш в такива философски размисли кое от кое се вика и кое е първичното |
|
| Автор: | ¶ [ Чет Авг 30, 2007 9:38 pm ] | |||||||||
| Заглавие: | ||||||||||
По принцип е така, но принципите са за това, за да се нарушават |
||||||||||
| Автор: | Dimitar [ Чет Авг 30, 2007 10:00 pm ] |
| Заглавие: | |
Серийния канал и аз така го правя |
|
| Автор: | ToHu [ Пет Авг 31, 2007 12:54 am ] |
| Заглавие: | |
И аз съм против викане на функции в прекъсване, каквито и да са те, особенно пък при пикове ... така лесно без да се усетиш може да препълниш стека. Ако прекъсването се появи в момент когато на вече в втора или трета извикана функция, самото прекъсване глта стек, и вътре ако извикаш функция ленсо може да го препълниш, особенно ако не мсилиш за него, или ако предполагаш разни неща като при РС-то. Аза неотложните процеси винаги има и решения които не изискват сложна обработка в прекъсване. Серийниа и при мен отчасти е така реализиран, но аз си пиша в по длъчък буфер, и си обработвам в основната .. .. е ако рам е кът .. то е ясно ... |
|
| Страница 1 от 1 | Часовете са според зоната UTC + 2 часа [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|