|
Виж темите без отговор | Виж активните теми
Дата и час: Вто Юли 28, 2026 1:41 am
|
Страница 1 от 1
|
[ 8 мнения ] |
|
| Автор |
Съобщение |
|
Ки4о
Ранг: Форумен бог
Регистриран на: Съб Юли 22, 2006 9:50 pm Мнения: 1638
|
 Извикване на функция
Нещо ми са мътни нещата - по-точно как се използва една функция едновременно и в главна програма и в прекъсване.Ситуацията е следната:Програмката за опресняване на ЛСД-то я ползвам и в главната програма - при първоначална инициализация и в програмата по прекъсване - когато трябва да изведа някой данни.Компилатора (Хай-тековски) не ревеше но изведнъж ревна - грешка 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:17 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
На C има проблем, но зависи от компилатора. Примерно по-старите версии на CCS C не ревяха, което беше добре, но по-новите ревят. Нямат и опция за забрана на тази проверка. Логическия проблем го има и при асемблера, но той не прави тези проверки.
Реентратна функция означава функция, която може да се извиква по всяко време от различни асинхронни процеси, в случая от прекъсване и главна програма. Затова променливите на такава функция трябва да са auto, т.е. да се пазят в стека. Ако са глобални, трябва да вземеш мерки да ги синхронизираш, т.е. да добавиш флагове, които да ти показват, дали можеш да пипаш променливата или не. Причината е, че не знаеш кой асинхронен процес кога ще иска услуга от твоята функция. Може да стане така, че тя да обслужва един процес, същевременно втори процес се обръща към нея, докато не е завършила изпълнението на услугата за първия. Съответно глобалните ти променливи ще се брактисат, както първия, така и втория процес няма да са доволни от работата й.
По принцип аз съм против това да се индикира като грешка от компилаторите за микроконтролери, защото се връзват ръцете на програмиста. Би трябвало да има избор програмиста, да го задава да се тълкува от компилатора като грешка, или да се тълкува като предупреждение. Виж при многозадачните и многопотребителските системи без това е на практика невъзможно да се синхронизират нишките на процесите.
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Чет Авг 30, 2007 5:37 pm |
|
 |
|
Yanek
Ранг: Новодошъл
Регистриран на: Пет Юни 29, 2007 10:59 pm Мнения: 113
|
Ако става дума за ПИК, то тогава проблема би могъл да бъде следния. Ако използваш овърлей модел на компилатора, тогава локалните променливи са просто клетки от РАМ-а които компилатора адресира директно т.е. когато извикаш във фоновата програма тази ф-ия тя използва променливи А и Б. Ако през това време дойде прекъсване, в което викаш същата ф-ия, отново ще се използват същите А и Б, така че би могло да промениш съдържанието им за фоновата. Но когато ползваш стеков модел тогава променливите се разполагат в стека по стандартния начин и са уникални за всяко извикване на тази ф-ия. Може и да не съм прав за твоя компилатор, но е твърде вероятна причина.
Едит: Не знаех, че става дума за глобални променливи, но е интересно, компилатора не би трябвало да се обажда за глобалните.
|
| Чет Авг 30, 2007 8:05 pm |
|
 |
|
Ки4о
Ранг: Форумен бог
Регистриран на: Съб Юли 22, 2006 9:50 pm Мнения: 1638
|
Май трябва да разясня още.ЛЦД-то се ползва при началната инициализация на променливите в контролера,като след инициализация се рзарешава прекъсвания.През останалото времме се върти един цикъл за сканиране на клавиатура и всичко се прави при прекъсване (извеждане на данни и др).
При сработване на клавиатурата се забранява прекъсваненията и се свършват задачите зададени от бутоните след което отново се разрешават прекъсванията и процеса продължава.Явно се получава прекъсване в прекъсването и за това компилатора пищи.Ще пробвам да си сменя алгоритъма на програмата.
|
| Чет Авг 30, 2007 8:45 pm |
|
 |
|
Dimitar
Ранг: Форумен бог
Регистриран на: Пет Ное 12, 2004 3:38 pm Мнения: 9103 Местоположение: Chicago, IL
|
Прекъсване в прекъсването на ПИК-а малко трудно ще се получи. А по принцип трябва да се пазиш да правиш доста неща в прекъсването. По-добре вдигай някакъв флаг, който да проверяваш в основната програма и тогава да викаш функциите. Нито клавиатурата, нито LCD-то са критични процеси, че чак да трябва вътре в прекъсването да ги правиш. А така като се замисля - в целия регулатор, без значение какъв е - не би трябвало да има такъв процес. Та сложи си едни флагчета да ти е мирна главата и да не изпадаш в такива философски размисли кое от кое се вика и кое е първичното  .
|
| Чет Авг 30, 2007 8:56 pm |
|
 |
|
¶
Ранг: Форумен бог
Регистриран на: Пет Фев 25, 2005 1:58 pm Мнения: 4585 Местоположение: US
|
По принцип е така, но принципите са за това, за да се нарушават  Има процеси, които не търпят отлагане на обработката, примерно приемане на данни от сериен канал. Ако процесора е натоварен в главната програма, практически на десетки места ще се наложи да проверяваш флаговете, за да видиш има ли пристигнали данни от серийния канал, за да вземеш мерки да ги обработиш/съхраниш. Докато плясвайки кода за обработка/съхранение на данните от серийния канал в прекъсване се освобождаваш от тези досадни проверки. Получаваш данни, обработваш ги в прекъсването, като се получи валиден пакет, вдигаш един флаг и чак тогава главната програма се намесва. Аз предпочитам така да си правя програмите  А най-гот е без главна програма, всичко се изпълнява асинхронно 
_________________ Ето аз дишам, работя, живея и програми пиша тъй както умея, с проца под вежди се гледаме строго и боря се с него доколкото мога....
|
| Чет Авг 30, 2007 9:38 pm |
|
 |
|
Dimitar
Ранг: Форумен бог
Регистриран на: Пет Ное 12, 2004 3:38 pm Мнения: 9103 Местоположение: Chicago, IL
|
Серийния канал и аз така го правя  . Имах предвид да не вика разни функции из прекъсванията.
|
| Чет Авг 30, 2007 10:00 pm |
|
 |
|
ToHu
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 9:21 pm Мнения: 30686 Местоположение: София
|
И аз съм против викане на функции в прекъсване, каквито и да са те, особенно пък при пикове ... така лесно без да се усетиш може да препълниш стека. Ако прекъсването се появи в момент когато на вече в втора или трета извикана функция, самото прекъсване глта стек, и вътре ако извикаш функция ленсо може да го препълниш, особенно ако не мсилиш за него, или ако предполагаш разни неща като при РС-то.
Аза неотложните процеси винаги има и решения които не изискват сложна обработка в прекъсване. Серийниа и при мен отчасти е така реализиран, но аз си пиша в по длъчък буфер, и си обработвам в основната .. .. е ако рам е кът .. то е ясно ...
|
| Пет Авг 31, 2007 12:54 am |
|
|
|
Страница 1 от 1
|
[ 8 мнения ] |
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 3 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|