PDA

View Full Version : مشکل در دسترسی تابع وقفه به متغییر های کلاس



md3848
دوشنبه 10 دی 1397, 13:21 عصر
سلام - کلاس من ( داخل فایل usb.h ) به صورت زیر هستش :
class USB {
public :
void isr();
private :
volatile uint8_t CCEMPTY_status = 1;
} static usb;

در فایل usb.cpp، تو تابع وقفه، اومدم یه تابع از کلاس فوق رو فراخوندم :
extern "C" {
void USB_IRQHandler() {
usb.isr();
}
}

داخل تابع isr از متغیر CCEMPTY_status استفاده کردم ولی تغییرات داخل این متغییر ثبت نمیشه ولی وقتی تعریف متغییر CCEMPTY_status رو، اول فایل usb.cpp قرار میدم مشکل حل میشه - چرا؟ :متفکر:

کد زیر داخل کلاس به صورت private باشه یا اول فایل usb.cpp باشه - چه فرقی داره - چرا باید تو یکیش تغییرات تو متغییر ثبت نشه؟
volatile uint8_t CCEMPTY_status = 1;

farhad_shiri_ex
سه شنبه 11 دی 1397, 08:33 صبح
سلام - کلاس من ( داخل فایل usb.h ) به صورت زیر هستش :
class USB {
public :
void isr();
private :
volatile uint8_t CCEMPTY_status = 1;
} static usb;

در فایل usb.cpp، تو تابع وقفه، اومدم یه تابع از کلاس فوق رو فراخوندم :
extern "C" {
void USB_IRQHandler() {
usb.isr();
}
}

داخل تابع isr از متغیر CCEMPTY_status استفاده کردم ولی تغییرات داخل این متغییر ثبت نمیشه ولی وقتی تعریف متغییر CCEMPTY_status رو، اول فایل usb.cpp قرار میدم مشکل حل میشه - چرا؟ :متفکر:

کد زیر داخل کلاس به صورت private باشه یا اول فایل usb.cpp باشه - چه فرقی داره - چرا باید تو یکیش تغییرات تو متغییر ثبت نشه؟
volatile uint8_t CCEMPTY_status = 1;

اگر متغییر را در ابتدای فایل usb.cpp تعریف کنید متغیر شما دیگه یک متغییر عضو نخواهد بود و global خواهد شد. به همین علت می تونید از همه توابع بهش دسترسی داشته باشید.
ولی کد شما که مشکلی نداره نوع unsigned char که تعریف شده متغییر عضو کلاس هست پس بنابراین بدون مشکل برای اعضای کلاس کار خواهد کرد.
البته دوتا نکته وجود داره یکی اینکه فرار تعریف شدن این متغییر در ناحیه های بحرانی برای شما کاربردی داره؟
دوم اینکه تابع مذکور را دارید داخل یک shared library / dynamic library استفاده میکنید؟ و چون که یک آبجکت استاتیک از کلاس تعریف کرده اید پس بنابراین در تمام لایبرری خودتون به یک شی واحد دسترسی خواهید داشت و این حوزه دسترسی در لایبرری خواهد بود پس بنابراین در خارج از این لایبرری دسترسی به این متغییر نخواهید داشت در صورت نیاز باید امکانی را فراهم کنید که در خارج از حوزه لایبرری هم به آن دسترسی داشته باشید با تعریف یک متد دسترسی در لایبرری هم به رفرنس و هم به اشاره گری ثابت وهم به مقدار متغییر می تونید دسترسی داشته باشید.
بنابراین همانطور که قبلا هم گفتم دسترسی و تغییر مقدار متغییر عضو در سطح لایبرری نمی تونه مشکلی داشته باشه!
به هرحال برای راهنمایی بهتر باید کدتون را کاملتر قرار بدید.
در آخر هم پیشنهاد میکنم بجای استفاده از نوع volatile از کلاسهای std::atomic و std::memory_order استفاده کنید تا بتونید از قفل های تعریف شده در این کلاسها در جهت همگام سازی داده ها در نخ های مختلف استفاده کرده باشید

md3848
سه شنبه 11 دی 1397, 09:37 صبح
این کدی که دارم میزنم برا میکرو کنترلر هستش، کدهام به صورت زیر هستش :

تو فایل main از کتابخونه usbSerial استفاده کردم؛
تو کتابخونه usbSerial از کتابخونه usb استفاده کردم.
تو کتابخونه cdc_class_request و standard_request هم نیاز دارم که از کتابخونه usb استفاده کنم.
لذا چون 3 جا نیاز دارم که از کلاس usb با یک شیء استفاده کنم، اومدم شیء رو به صورت static تعریف کردم.

خدمت شما : http://s9.picofile.com/file/8347540384/usb_lib.rar.html

farhad_shiri_ex
سه شنبه 11 دی 1397, 10:46 صبح
این کدی که دارم میزنم برا میکرو کنترلر هستش، کدهام به صورت زیر هستش :

بله حدس زدم! به این علت که معمولا برنامه نویس های غیر embedded از این روش تعریف شی استاتیک استفاده نمیکنن! اونهم به این علت که دیگه از تکنیک های dependency injection و... نمی تونن استفاده کنن!



تو فایل main از کتابخونه usbSerial استفاده کردم؛
تو کتابخونه usbSerial از کتابخونه usb استفاده کردم.
تو کتابخونه cdc_class_request و standard_request هم نیاز دارم که از کتابخونه usb استفاده کنم.
لذا چون 3 جا نیاز دارم که از کلاس usb با یک شیء استفاده کنم، اومدم شیء رو به صورت static تعریف کردم.

باشه مشکلی نداره هر چندبارهم که استفاده کنید بازهم به یک شی اشاره خواهد شد منتهی چون استاتیک هست پس هربار به آخرین داده های کلاس دسترسی خواهید داشت .!
این تابعی ()USB_IRQHandler هست که به صورت اتوماتیک تو وقفه call میشه؟ اگر اینطوره با چه میکروی کار میکنید؟ (احتمال داره که نحوه دسترسی به حافظه تو میکرو شما یک ملاحضه فنی داشته باشه که نمی تونید به پشته کلاس دسترسی داشته باشید)
همانطور که گفتم امکان نداره که این نوع دسترسی تو Memory model های pc مشکلی داشته باشه!

void USB_VIRTUAL_COM::init() {
// init hardware
usb.init();
...

الان اینجا دارید کلاس usb را init میکنید اگر متغیر هایی که گلوبال تعریف کردید را به عنوان متغیرهای عضو کلاس تعریف کنید باید بهشون دسترسی داشته باشید.!

md3848
سه شنبه 11 دی 1397, 13:15 عصر
USB_IRQHandler تابع وقفه هستش دیگه - خودکار خودش اجرا میشه تحت یه شرایطی
MICRO = LPC1768
arm compiler v6.9
c++ 11
IDE = KEIL V5.25.2.0

farhad_shiri_ex
سه شنبه 11 دی 1397, 14:45 عصر
USB_IRQHandler تابع وقفه هستش دیگه - خودکار خودش اجرا میشه تحت یه شرایطی

بله منهم که همین را گفتم ...
خوب الان وقتی از اون متغیر ها به صورت عضو استفاده میکنید مقداردهی نمیشه ؟ روی میکرو که آپلود میکنید خروجی چی هستش؟

md3848
چهارشنبه 12 دی 1397, 08:30 صبح
آره دیگه - گفتم قبلا که - عضو کلاس چه public و چه private که باشن مقدار دهی نمیشن و باید حتما در اول فایل usb.cpp تعریفشون کنم.:گریه:
این کدا برا راه اندازی پورت usb هستش - میکرو به pc وصل میشه و یه سری اطلاعات اولیه رد و بدل میشه که باعث رخ دادن وقفه میشه - که تو اون وقفه هه این متغییری که صحبتشو میکنیم - مشکل داره و مقدار دهی نمیشه.:متفکر:

pe32_64
پنج شنبه 13 دی 1397, 20:59 عصر
آره دیگه - گفتم قبلا که - عضو کلاس چه public و چه private که باشن مقدار دهی نمیشن و باید حتما در اول فایل usb.cpp تعریفشون کنم.:گریه:
این کدا برا راه اندازی پورت usb هستش - میکرو به pc وصل میشه و یه سری اطلاعات اولیه رد و بدل میشه که باعث رخ دادن وقفه میشه - که تو اون وقفه هه این متغییری که صحبتشو میکنیم - مشکل داره و مقدار دهی نمیشه.:متفکر:


سلام - کلاس من ( داخل فایل usb.h ) به صورت زیر هستش :
class USB {
public :
void isr();
private :
volatile uint8_t CCEMPTY_status = 1;
} static usb;

در فایل usb.cpp، تو تابع وقفه، اومدم یه تابع از کلاس فوق رو فراخوندم :
extern "C" {
void USB_IRQHandler() {
usb.isr();
}
}

داخل تابع isr از متغیر CCEMPTY_status استفاده کردم ولی تغییرات داخل این متغییر ثبت نمیشه ولی وقتی تعریف متغییر CCEMPTY_status رو، اول فایل usb.cpp قرار میدم مشکل حل میشه - چرا؟ :متفکر:

کد زیر داخل کلاس به صورت private باشه یا اول فایل usb.cpp باشه - چه فرقی داره - چرا باید تو یکیش تغییرات تو متغییر ثبت نشه؟
volatile uint8_t CCEMPTY_status = 1;


این کدی که دارم میزنم برا میکرو کنترلر هستش، کدهام به صورت زیر هستش :


تو فایل main از کتابخونه usbSerial استفاده کردم؛
تو کتابخونه usbSerial از کتابخونه usb استفاده کردم.
تو کتابخونه cdc_class_request و standard_request هم نیاز دارم که از کتابخونه usb استفاده کنم.
لذا چون 3 جا نیاز دارم که از کلاس usb با یک شیء استفاده کنم، اومدم شیء رو به صورت static تعریف کردم.


خدمت شما : http://s9.picofile.com/file/8347540384/usb_lib.rar.html



سلام
متغیر استاتیک در هر compilation unit (فایل cpp) ، از دیگری جدا به حساب میاد.
یعنی شما سه تا متغییر مختلف "usb" داری. باید از extern استفاده کرد.مثالش هم لینک دادم:
https://stackoverflow.com/questions/20716091/global-const-object-shared-between-compilation-units