| Автор |
Съобщение |
|
i_dachev
Ранг: Новодошъл
Регистриран на: Вто Ное 16, 2004 3:29 pm Мнения: 108 Местоположение: София
|
 Глобални променливи и прекъсвания
Чудя се ако декларирам глобална променлива която е 16 или повече бита за
PIC18 процесор и използвам C18 компилатор, то няма ли да има проблем
ако ползвам променливата в нормална функция и прекъсване.
За пример следния код:
volatile int g_p;
void main() {
int l_p;
...
l_p = g_p;
...
}
isr...
void isr() {
...
g_p = 0xFF40;
...
}
...
Проблема който виждам е че присвояването на l_p = g_p не е атомарно.
Дали има инструкции на PIC18, които могат да го направят атомарно от гледна
точка на прекъсването?
|
| Сря Дек 09, 2009 10:58 am |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Не. Ако ползваш едни и същи обекти които не са атомични (бит и байт при PIC18) в прекъсване и основната програма - твоя е грижата да синхронизираш достъпа до тях.
Най просто е да забраниш прекъсванията при достъп до променливата в основната програма. Но не винаги е универсално решение.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Дек 09, 2009 11:26 am |
|
 |
|
i_dachev
Ранг: Новодошъл
Регистриран на: Вто Ное 16, 2004 3:29 pm Мнения: 108 Местоположение: София
|
Хм и аз така предложих, но немога да измисля нещо по-добро
от това с кратко забраняване на прекъсванията някой да има идеи?
|
| Сря Дек 09, 2009 11:55 am |
|
 |
|
zaphod
Ранг: Форумен бог
Регистриран на: Нед Юли 24, 2005 10:28 am Мнения: 2658
|
както каза цецо, забраната за прекъсване в общия случай не е решение. става когато времето на защитената операция е некритично като закъснение за прекъсването, но ако е по-голямо от критичното, не става. тогава си трябва синхронизиращ примитив, нямам идея в 18ките има ли такива. но само за четене на един инт, става си и със забрана на прекъсването.
|
| Сря Дек 09, 2009 11:57 am |
|
 |
|
i_dachev
Ранг: Новодошъл
Регистриран на: Вто Ное 16, 2004 3:29 pm Мнения: 108 Местоположение: София
|
Аз имам идея да ползвам допълнително един байт за синхронизация.
Ако е вдигнат тоя байт/бит няма да пипам стойността от прекъсването.
Ако не е променям.
Слагам флага преди да прочета глобалната променлива и го свалям след края.
|
| Сря Дек 09, 2009 12:21 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Специално в случая който излагаш, забраната на прекъсванията е най-оптималния вариант.
Пускане/спиране на прекъсване в ПИК е манипулация на един бит - т.е. един клок. Няма как да направиш нещо по бързо. Т.е. и да сложиш специален бит (семафор) който да ти "защитава" променливата - нищо съществено няма да постигнеш като бързодействие или памет, напротив ще се забавиш.
Виж ако защитената секция е по голяма по размер и се налага преоритет (или последователност) при обработката и т.н.... тогава вече трябва да мислиш за нещо по сложно... Всъщност тогава вече е време да почнеш да четеш "що е то RTOS"  :):)
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Дек 09, 2009 1:09 pm |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Ето ви едно извращение - C++ за микроконтролери.  Това е защитена променлива, която не налага забраната на прекъсванията.
|
| Сря Дек 09, 2009 9:37 pm |
|
 |
|
i_dachev
Ранг: Новодошъл
Регистриран на: Вто Ное 16, 2004 3:29 pm Мнения: 108 Местоположение: София
|
 това е безсмислен код  или трябва да ти обяснят подробно,
къде им е трябвало това чудо на програмирането
|
| Чет Дек 10, 2009 10:13 am |
|
 |
|
smtp
Ранг: Новодошъл
Регистриран на: Нед Яну 18, 2009 1:28 pm Мнения: 110
|
кода си е напълно смислен (за теб е явно прекалено сложен) !
някой ден (след 10г примерно), когато почне да пишеш мнооого по-сложни/големи неща ще схванеш идеята която е: четене на коректни данни които не са в процес на модифициране!
PS: това че е c++ няма никакво значение - само е по удобно!
|
| Чет Дек 10, 2009 10:34 am |
|
 |
|
zaphod
Ранг: Форумен бог
Регистриран на: Нед Юли 24, 2005 10:28 am Мнения: 2658
|
ще изтърваш семпли така. може да не ти пука конкретно в тая ситуация, но пък какво ти пука и да забраниш прекъсването? в случая е уместно, операцията е къса, няма да опескаш нищо, а няма да изтърваш семпли.
|
| Чет Дек 10, 2009 10:34 am |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
Добре, а какво ще стане ако при рефрешването на m_Shadow(между байтовете, нали то също не е атомик), дойде прекъсване,в което се ползва CShadowVar::Get().
Ето тук:
Или този код е само за случаите в които Get() се ползва само от основната нишка, а Set() асинхронно в прекъсване...
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Чет Дек 10, 2009 10:53 am |
|
 |
|
tolstolob
Ранг: Ориентиран
Регистриран на: Вто Фев 06, 2007 2:45 am Мнения: 263
|
Най-добре си забрани прекъсванията и си копирай променливата. За 16-битова променлива копирането би трябвало да отнеме 4 цикъла + евентуално 1 за превключване на банката, което не е болка за умиране.
|
| Чет Дек 10, 2009 11:16 am |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Ще се дигне m_bRefreshing и цикъла ще се повтори. Това е целия смисъл.
|
| Чет Дек 10, 2009 1:14 pm |
|
 |
|
Zdrav
Ранг: Форумен бог
Регистриран на: Сря Яну 26, 2005 2:01 pm Мнения: 1952 Местоположение: Варна
|
Реконструктор погледни сорса който си приложил. При викане на Get() не се вдига m_bRefreshing!!!
Аз предлагам ето така:
Разбира се ако латентноста на прекъсванията е толкова критична. Ако не е и аз съм за варианта със забраняване/разрешаване на прекъсванията.
_________________ Най-опасният враг на истината и свободата е мнозинството.
|
| Чет Дек 10, 2009 1:48 pm |
|
 |
|
perlsite
Ранг: Ориентиран
Регистриран на: Пон Апр 17, 2006 1:44 pm Мнения: 291
|
Винаги може да се омаже кода и не мисля, че по този начин може да се реши проблема точно защото и след като излезне от while цикъла, преди да върне метода, респективно да се ползва стойността може да бъде променена.
Само решение с някаква опашка и dispatcher може да помогне, където всяка операция се поставя в опашка и винаги се изпълнява серийно.
|
| Чет Дек 10, 2009 4:54 pm |
|
|