| Микроконтролери и електроника http://mcu-bg.com/mcu_site/ |
|
| Глобални променливи и прекъсвания http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=7374 |
Страница 1 от 3 |
| Автор: | i_dachev [ Сря Дек 09, 2009 10:58 am ] |
| Заглавие: | Глобални променливи и прекъсвания |
Чудя се ако декларирам глобална променлива която е 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 11:26 am ] |
| Заглавие: | |
Не. Ако ползваш едни и същи обекти които не са атомични (бит и байт при PIC18) в прекъсване и основната програма - твоя е грижата да синхронизираш достъпа до тях. Най просто е да забраниш прекъсванията при достъп до променливата в основната програма. Но не винаги е универсално решение. |
|
| Автор: | i_dachev [ Сря Дек 09, 2009 11:55 am ] |
| Заглавие: | |
Хм и аз така предложих, но немога да измисля нещо по-добро от това с кратко забраняване на прекъсванията някой да има идеи? |
|
| Автор: | zaphod [ Сря Дек 09, 2009 11:57 am ] |
| Заглавие: | |
както каза цецо, забраната за прекъсване в общия случай не е решение. става когато времето на защитената операция е некритично като закъснение за прекъсването, но ако е по-голямо от критичното, не става. тогава си трябва синхронизиращ примитив, нямам идея в 18ките има ли такива. но само за четене на един инт, става си и със забрана на прекъсването. |
|
| Автор: | i_dachev [ Сря Дек 09, 2009 12:21 pm ] |
| Заглавие: | |
Аз имам идея да ползвам допълнително един байт за синхронизация. Ако е вдигнат тоя байт/бит няма да пипам стойността от прекъсването. Ако не е променям. Слагам флага преди да прочета глобалната променлива и го свалям след края. |
|
| Автор: | Цецо [ Сря Дек 09, 2009 1:09 pm ] |
| Заглавие: | |
Специално в случая който излагаш, забраната на прекъсванията е най-оптималния вариант. Пускане/спиране на прекъсване в ПИК е манипулация на един бит - т.е. един клок. Няма как да направиш нещо по бързо. Т.е. и да сложиш специален бит (семафор) който да ти "защитава" променливата - нищо съществено няма да постигнеш като бързодействие или памет, напротив ще се забавиш. Виж ако защитената секция е по голяма по размер и се налага преоритет (или последователност) при обработката и т.н.... тогава вече трябва да мислиш за нещо по сложно... Всъщност тогава вече е време да почнеш да четеш "що е то RTOS" |
|
| Автор: | Реконструктор [ Сря Дек 09, 2009 9:37 pm ] | ||
| Заглавие: | |||
Ето ви едно извращение - C++ за микроконтролери.
|
|||
| Автор: | i_dachev [ Чет Дек 10, 2009 10:13 am ] |
| Заглавие: | |
къде им е трябвало това чудо на програмирането |
|
| Автор: | smtp [ Чет Дек 10, 2009 10:34 am ] | |||||||||
| Заглавие: | ||||||||||
кода си е напълно смислен (за теб е явно прекалено сложен) ! някой ден (след 10г примерно), когато почне да пишеш мнооого по-сложни/големи неща ще схванеш идеята която е: четене на коректни данни които не са в процес на модифициране! PS: това че е c++ няма никакво значение - само е по удобно! |
||||||||||
| Автор: | zaphod [ Чет Дек 10, 2009 10:34 am ] | |||||||||
| Заглавие: | ||||||||||
ще изтърваш семпли така. може да не ти пука конкретно в тая ситуация, но пък какво ти пука и да забраниш прекъсването? в случая е уместно, операцията е къса, няма да опескаш нищо, а няма да изтърваш семпли. |
||||||||||
| Автор: | Zdrav [ Чет Дек 10, 2009 10:53 am ] | ||||||||||||||||||
| Заглавие: | |||||||||||||||||||
Добре, а какво ще стане ако при рефрешването на m_Shadow(между байтовете, нали то също не е атомик), дойде прекъсване,в което се ползва CShadowVar::Get(). Ето тук:
Или този код е само за случаите в които Get() се ползва само от основната нишка, а Set() асинхронно в прекъсване... |
|||||||||||||||||||
| Автор: | tolstolob [ Чет Дек 10, 2009 11:16 am ] |
| Заглавие: | |
Най-добре си забрани прекъсванията и си копирай променливата. За 16-битова променлива копирането би трябвало да отнеме 4 цикъла + евентуално 1 за превключване на банката, което не е болка за умиране. |
|
| Автор: | Реконструктор [ Чет Дек 10, 2009 1:14 pm ] | |||||||||||||||||||||||||||
| Заглавие: | ||||||||||||||||||||||||||||
Ще се дигне m_bRefreshing и цикъла ще се повтори. Това е целия смисъл. |
||||||||||||||||||||||||||||
| Автор: | Zdrav [ Чет Дек 10, 2009 1:48 pm ] | |||||||||
| Заглавие: | ||||||||||
Реконструктор погледни сорса който си приложил. При викане на Get() не се вдига m_bRefreshing!!! Аз предлагам ето така:
Разбира се ако латентноста на прекъсванията е толкова критична. Ако не е и аз съм за варианта със забраняване/разрешаване на прекъсванията. |
||||||||||
| Автор: | perlsite [ Чет Дек 10, 2009 4:54 pm ] |
| Заглавие: | |
Винаги може да се омаже кода и не мисля, че по този начин може да се реши проблема точно защото и след като излезне от while цикъла, преди да върне метода, респективно да се ползва стойността може да бъде променена. Само решение с някаква опашка и dispatcher може да помогне, където всяка операция се поставя в опашка и винаги се изпълнява серийно. |
|
| Страница 1 от 3 | Часовете са според зоната UTC + 2 часа [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|