پروتکل ARP (Address Resolution Protocol) با استفاده از آدرس IP مقصد یا گیرنده پیام؛ آدرس فیزیکی یا همون مک آدرس گيرنده رو به دست میاره تا بتونيم فریمهای لایه 2 رو ارسال کنيم. فرض كنيد شمارهتلفن شخصي رو نداريد؛ چطور ميتونيد بهش تلفن كنيد؟ ما ممكنه از سرویسهایی مثل 118 یا کتابچههای تلفن استفاده كنيم؛ اما در مبحث شبكه؛ سعي ميشه با استفاده از قابلیتهای خود شبكه، مشكلات حل بشه.
کار پروتکل ARP چیه؟ هر وقت نیاز میشه یه بسته با استفاده از پروتکل IP رو بفرستيم، قبلش چک میکنیم که آیا مک آدرس گیرنده رو داریم یا نه؟ اگر مك آدرس رو نداشته باشيم، اول بايد اون رو به دست بياريم؛ پس هر هاست، نیاز داره جدولی داشته باشه به اسم جدول ARP که توش مشخص شده هر آیپی متعلق به كدام مک آدرس است.
این عملیات در داخل میکروکنترلر پیادهسازی (Implementation) میشه، از طرفی چون ممکنه هر قطعهای از شبکه خارج بشه (خاموش بشه؛ کابلش جدا بشه یا حتی هنگ و ریست شده باشه) معمول اینه که جدول ARP به طور مرتب چک و بروز میشه، به همین دلیل اگر با نرمافزاری مثل wireshark شبکه رو شنود کنید، میبینید که هرازگاهی بستههای ARP دوباره ارسال میشه.
تا اینجا تراشه ENC28J60 رو راه انداختیم و دو تابع نوشتیم که توسط اونها، فریمهای رسیده از شبکه رو دریافت و پردازش میکنیم یا فریمهایی رو روی شبکه ارسال میکنیم. شاکله برنامه رو هم گفتیم كه میخوایم اینطور پیادهسازی کنیم که یه پکت رو میگیریم، پردازش میکنیم و اگه نیاز بود جوابش رو همونجا بوجود میاریم (داخل همون حافظهای که داخل میکروکنترلر برای دریافت فریمها در نظر گرفتیم).
وقتي یه فریم رو میگیریم، مک آدرس ها بالطبع سرجاشون هستند (در 12 بایت ابتدایی فریم) دو بایت بعدی در فریم بنام Ether type رو برمیداریم، در حالتی که این فریم متعلق به پروتکل ARP باشه، عدد داخل این دو بایت 0x0806 هست. پس بایت های داده ی داخل فریم متعلق به این پروتکل هستند. گفتیم هر پروتکلی، هدر مخصوص به خودش رو در ابتدای داده ها اضافه میکنه؛ پس در ابتدای بخش داده ها در یک فریم، باید بخش هدر مربوط به ARP رو تفکیک و بررسی کنیم. اگر بخواهیم ترکیب بایت های درون فریم در لایه دوم رو به صورت شکل نشون بدیم، یه همچین چیزی هست (از چپ به راست) :
6 octet Destination MAC Address | 6 octet Source MAC Address | 2 octet Ether Type 0x0806 | Payload in frame | 4 octet CRC | |
28 octet ARP Header | 18 octet Padding 0x00 |
12 بایت ابتدایی مک آدرس ها هستند. 2 بایت با مقدار 0x0806 نوع پروتکل لایه سوم رو مشخص میکنه که در این حالت، ARP هست. در بخش داده های فریم (payload)؛ فقط بخش هدر در پروتکل ARP وجود داره که تعداد 28 بایت، فضا اشغال میکنه. داده ی دیگری توسط این پروتکل ارسال نمی شود و از آنجاییکه اندازه کل فریم 46 بایت (کمتر از 64 بایت برای حداقل طول فریم) است لذا در ادامه فریم؛ بسته به پیاده سازی لایه دوم؛ ممکن است شما 18 بایت با مقدار 0x00 برای padding داشته باشید. در انتهای فریم هم طبق معمول CRC خواهیم داشت. فرمت هدر، در پروتکل ARP در جدول زیر نشان داده شده است:
Octet Offset | 0 | 1 |
0 | HType (Hardware Type) | |
2 | PType (Protocol Type) | |
4 | HLen (Hardware Address Length) | PLen (Protocol Address Length) |
6 | OPER (Operation) | |
8 | SHA (Sender Hardware Address) first 2 Bytes | |
10 | SHA next 2 Bytes | |
12 | SHA Last 2 Bytes | |
14 | SPA (Sender Protocol Address) first 2 Bytes | |
16 | SPA last 2 Bytes | |
18 | THA (Target Hardware Address) first 2 Bytes | |
20 | THA next 2 Bytes | |
22 | THA Last 2 Bytes | |
24 | TPA (Target Protocol Address) first 2 Bytes | |
26 | TPA last 2 Bytes |
HTYPE : دو بایت با نام Htype، نوع سختافزار رو مشخص میکنه. برای برد ما که از اترنت 10Mb استفاده میکنه؛ داخل این دو بایت عدد 0x0001 بايد باشه.
PTYPE : یا Protocol Type؛ شامل دو بایت که اگه یادتون باشه برای پروتکل IP عدد 0x0800 بود. در واقع در این بخش نشون میدیم آدرس منطقی ما، آدرس مورد استفاده در پروتکل IP خواهد بود.
HLEN : در این قسمت که یک بایتی هست، تعداد بایتهای آدرس فیزیکی یا سختافزاری ما مشخص میشه و از اونجایی که مک آدرسها، 6 بايتی هستند؛ در این جا عدد 0x06 نوشته میشه.
PLEN : در این بخش كه يك بايت رو اشغال كرده؛ تعداد بایتهای آدرس منطقی نوشته میشه، آدرس منطقی ما از نوع IP Address هست؛ پس در اینجا عدد 0x04 نوشته میشه.
OPER : نوع عملیات رو مشخص میکنه. کلاً دو نوع پیام روی ARP مورد استفاده ما هست، درخواست (Request) و پاسخ (Reply) که جهت درخواست عدد 0x01 و برای پاسخ عدد 0x02 استفاده میشه. سمتی که نیاز داره IP یه دستگاه دیگه رو پیدا کنه، درخواست (0x01) میفرسته و سمت مقابل پاسخ (0x02) میده.
SHA : یا آدرس سختافزاری فرستنده. در این 6 بایت، مک آدرس فرستنده این پکت قرار میگیره.
SPA : در اینجا 4 بایت آدرس IP فرستنده نوشته میشه.
در ادامه و در بخشهای THA و TPA هم مک آدرس و IP آدرس طرف مقابل نوشته میشه.
در ابتدا درخواستی از طرف درخواستکننده ارسال میشه. از اونجاییکه در این مرحله، هنوز مک آدرس طرف مقابل رو نمیدونه، پس به جای مک آدرس عدد FF:FF:FF:FF:FF:FF ارسال میشه. اگه یادتون باشه این آدرس رو بهش میگفتیم Broadcast Address در نتیجه تمامی دستگاههای متصل به شبکه داخلی، این پیام رو دریافت میکنند. در جواب این پیام (درخواست)؛ دستگاهی که IP آدرسش در پیام قبلی اومده؛ پیامی ارسال میکنه اما دیگه اینجا هم مک آدرس و هم IP آدرس طرف مقابل رو میدونه. مک آدرس خودش رو هم اضافه میکنه و نوع پیام رو در قسمت OPER عدد 0x02 میذاره و ارسال میکنه. در نتيجه این پیام دیگه broadcast نیست. به این فرایند اصطلاحاً Who has? میگن، درخواستکننده پیامش رو اینجور میفرسته:
Who has IP=aa-aa-aa-aa ? tell me IP=yy-yy-yy-yy at mac=zz:zz:zz:zz:zz:zz
در جواب هم سمت مقابل میگه
I am at IP=xx-xx-xx-xx ,mac=bb:bb:bb:bb:bb:bb
در شکلهای زیر درخواست و پاسخ ARP ثبت شده توسط نرمافزار wireshark رو میبینیم:
درخواست ARP
پاسخ ARP
تصاویر مربوط به درخواست ARP از طرف کامپیوتر با سیستمعامل ویندوز و چیپ ASUS و پاسخ از طرف برد ما با تراشه ENC هست (بخش OUI مک آدرس رو مقدار 0x00,0x17,0x22 گذاشتيم؛ درنتيجه، در گزارش، wireshark سازنده چیپ رو شركت ديگه اي به جز ميكروچيپ تشخیص داده)؛
اگه بخوایم نسبت این پروتکل و فریم Ethenet ii رو بهصورت تصویری نشون بدیم؛ چیزی مثل جدول زیر میشه:
(Network Layer) لایه 3 | IP (packet) | ARP (packet) |
(Data Link Layer) لایه 2 | Ethernet ii (frame) | |
(Physical Layer) لایه 1 | ‘0’ , ‘1’ (Stream) |
بهتره بریم سر وقت نرمافزار میکروكنترلرمون تا کار رو ادامه بدیم و پاسخ به درخواستهای ARP رو توش پیادهسازی کنیم. اگه یادتون باشه ما یه ساختار به اسم ENC28J60_Frame داشتیم و يك تابع که توسط اون فریمهای Ethernet ii رو دریافت و در متغیری از این ساختار (struct) ذخیره میکردیم.
از اونجایی که کار ما با تراشه ENC تموم شده و جهت اینکه احتمالاً بعداً، بهراحتی بتونیم از تراشه دیگه ای استفاده بکنیم؛ برای اضافهکردن مابقی کدها (که پردازش پروتکلها رو انجام خواهند داد) یک زوج فایل جدید بهصورت .c, .h به برنامه اضافه میکنیم و اسمشون رو Ethernet.c , Ethernet.h میذاریم.
در فایل اصلی برنامه (main.c) و در تابع main؛ متغیری عمومی بهصورت زیر تعریف میکنیم:
1 | ENC28J60_Frame frame; |
برای اینکه مجبور نباشید برگردید عقب، مجددن اعلان ساختار ENC28J60_Frame رو اینجا براتون میذاریم
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | typedef struct ENC28J60_Frame { uint16_t nextPtr; uint16_t length; uint16_t status; uint8_t data[ENC28J60_FRAME_DATA_MAX]; uint32_t checksum; } ENC28J60_Frame; |
در فایل جدید تابعی به فرمت
1 | void ETH_Process (ENC28J60_Frame* encFrame); |
تعریف میکنیم، این تابع آدرس متغیری از نوع ساختار ENC28J60_Frame رو میگیره و دادههای داخل اون رو پردازش میکنه. روال کار اینطوریه که در حلقه اصلی برنامه (while(1)) ما به طور متوالی این تابع رو فراخوانی میکنیم. این تابع با استفاده از تابعی که قبلاً تعریف کردیم (ENC28J60_ReceiveFrame) فریم های دریافت شده رو پردازش میکنه و در صورت لزوم پاسخ میده (با استفاده از تابع ENC28J60_TransmitFrame)
داخل تابع ETH_Process اولین کاری که باید انجام بدیم اینه که ببینیم فریم جدیدی داریم یا نه:
1 | uint16_t requestSize = ENC28J60_ReceiveFrame(encFrame); |
اگر فریمی موجود باشه: if (requestSize > 0)
بخش داده از فریم جدید رو جدا کرده و نوع اون رو هم به ساختار جدیدی بنام ETH_Frame اصطلاحاً typecast میکنیم:
1 2 3 4 5 | ETH_Frame* ethFrame = (ETH_Frame*)encFrame->data; uint16_t etherType = ntohs(ethFrame->etherType); uint16_t ethDataLen = requestSize – sizeof(ETH_Frame); |
همینجا اعلان ساختار ETH_Frame رو هم نشون بدیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 | typedef struct ETH_Frame { uint8_t destMacAddr[MAC_ADDRESS_BYTES_NUM]; uint8_t srcMacAddr[MAC_ADDRESS_BYTES_NUM]; uint16_t etherType; uint8_t data[]; } ETH_Frame; |
همونطور که میبینید؛ این ساختار به فرمت یک فریم Ethernet ii هست؛ یعنی دو آرایه 6 بایتی برای مک آدرسها، 2 بایت برای Ether Type و یک آرایه با اندازه نامشخص از دادههای فریم براش در نظر گرفتیم.
خب برگردیم سراغ کد قبلی، در خط اول قسمت encFrame->data رو اصطلاحا typecast کردیم و آدرس اون رو در اشارهگری بنام ethFrame ذخیره کردیم.
در خط بعدی نوع اترنت (etherType) رو هم از داخل ساختار کشیدیم بیرون و بهصورت جداگانه در متغیری ذخیره کردیم. در خط سوم هم از اندازه تعداد بایتهای فریم اصلی، اندازه ساختار ETH_Frame رو کم کردیم؛ بهاینترتیب اندازه دادههای درون فریم رو به دست آوردیم.
اگه دقت کرده باشید؛ در خط دوم از چیزی به اسم ntohs استفاده شده که ظاهرش مثل توابع C هست؛ اما در واقع تنها یک define با آرگومان هست، قبل از پیادهسازیاش باید بگیم چی هست و چی کاری میکنه!
تابع ntohs در واقع تفاوت اول رو حلوفصل میکنه. همونطور که گفتیم دادهها در شبکه بهصورت Big Endian ارسال میشن، مثلاً در ارسال دو بایت Ether Type که در پروتکل ARP برابر با 0x0806 بود؛ ابتدا بایت 0x08 ارسال میشه و بعد 0x06، خب ما اینها رو داخل یک آرایه ریختیم؛ از اونجایی که این اطلاعات به ترتیب ورود، درون این آرایه ذخیرهشدن؛ لذا اگه بخوایم اونها رو پردازش کنیم، چیزی که میبینیم (میکروکنترلر میبینه) در واقع عدد 0x0608 هست.
برای همین میایم و با استفاده از ntohs جای بایتها رو هنگام انتقال به متغیر etherType عوض میکنیم.
همونطور که گفتیم بهجای تعریف تابعی برای این کار؛ از defineهای آرگومان دار استفاده کردیم. یه نکته دیگه هم اینکه، دو تا define تعریف میکنیم؛ یکی برای دادههای دو بایتی و ديگری براي چهار بایتیها.
پس در ابتداي فايل Ethernet.c همچنین چیزی اضافه میشه:
1 2 3 4 5 6 7 8 9 10 | #define htons(val) ((val << 8) & 0xFF00) | ((val >> 8) & 0xFF) #define htonl(val) ((val << 8) & 0xFF0000) | ((val >> 8) & 0xFF00) | ((val << 24) & 0xFF000000) | ((val >> 24) & 0xFF) #define ntohs(val) htons(val) #define ntohl(val) htonl(val) |
h بهجای host و n بهجای network، s برای short و l برای long بکار رفته. همونطور که دیده میشه کار ntohs و htons همینطور کار ntohl و htonl یکسانه و فقط به جهت تشخيص جهت ارتباط چهار تا شدهاند وگرنه همون دوتای اول کفایت میکرد. كار اين كد هم فقط جابهجاکردن (swap) بایتهای داخل متغير هست.
خب برگردیم به ادامه تفسير کد:
1 2 3 4 5 6 7 8 9 | // ARP protocol if (etherType == ETH_FRAME_TYPE_ARP) //0x0806 { responseSize = ARP_Process((ARP_Frame*)ethFrame->data, ethDataLen); } |
نوع فریم رو چک میکنیم که اگر از نوع ARP باشه، جوابش رو تهیه کنیم. برای بار چندم یادآوری میکنیم که جوابها در همون حافظهای که برای اطلاعات دریافتی اختصاص دادیم، قرار میگیرند، لذا چنانچه نیاز به ارسال پاسخ باشه (مثل همینجا در ARP) کافیه جای مک آدرسها رو داخل فریم اصلی عوض کنیم (در واقع جای فرستنده و گیرنده عوض میشه) و بقیه اطلاعات رو هم باتوجهبه پروتکل دریافتی تنظیم کنیم؛ مثلاً اینجا باید در قسمت OPER عدد 0x02 رو بنویسیم.
و در انتها هم چنانچه جواب لازم باشه اون رو ارسال میکنیم
1 2 3 4 5 6 7 | if (responseSize > 0) { ETH_Response(ethFrame, responseSize); } |
در نهایت تابع ETH_Process همچین چیزی میشه:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | void ETH_Process(ENC28J60_Frame* encFrame) { uint16_t responseSize = 0; uint16_t requestSize = ENC28J60_ReceiveFrame(encFrame); if (requestSize > 0) { ETH_Frame* ethFrame = (ETH_Frame*)encFrame->data; uint16_t etherType = ntohs(ethFrame->etherType); uint16_t ethDataLen = requestSize – sizeof(ETH_Frame); // ARP protocol if (etherType == ETH_FRAME_TYPE_ARP) //0x0806 { responseSize = ARP_Process((ARP_Frame*)ethFrame->data, ethDataLen); } if (responseSize > 0) ////////////// Reply { ETH_Response(ethFrame, responseSize); } } } |
در کد بالا دو تابع، هنوز برای ما ناشناخته است. تابع ETH_Response؛ تنها جای مک آدرس گیرنده و فرستنده رو تغییر میده و فریم رو ارسال میکنه:
1 2 3 4 5 6 7 8 9 10 11 | static void ETH_Response(ETH_Frame* ethFrame, uint16_t len) { memcpy(ethFrame->destMacAddr, ethFrame->srcMacAddr, MAC_ADDRESS_BYTES_NUM); memcpy(ethFrame->srcMacAddr, macAddr, MAC_ADDRESS_BYTES_NUM); ENC28J60_TransmitFrame((uint8_t*)ethFrame, len + sizeof(ETH_Frame)); } |
تابع memcpy از توابع داخلی KEIL و اصلی زبان C هست و محتویات یک قسمت از حافظه رو با اندازه معلوم بهجای دیگهای از حافظه کپی میکنه.
تابع ARP_Process هم در ادامه اومده و کار سادهای داره. ابتدا بررسي ميكنه كه آدرس IP ما در بخش آدرس IP درخواست اومده باشه (يادمون هست كه اين پيام يك پيام عمومي هست و لذا تمام پیغامهای ARP رو ميكروكنترلر ما دريافت و پردازش خواهد كرد؛ اما تنها به اون هايی بايد جواب بده كه مقصدشون ما هستيم) و بعد براي تنظيم پيام پاسخ؛ در قسمت OPER عدد 0x0002 رو مینویسه و مک آدرس و IP آدرس رو داخل هدر ARP تنظیم میکنه!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | uint16_t ARP_Process(ARP_Frame* arpFrame, uint16_t frameLen) { uint16_t newFrameLen = 0; if (memcmp(arpFrame->destIpAddr, ipAddr, IP_ADDRESS_BYTES_NUM) == 0) { if ((arpFrame->opCode) == ( ntohs(ARP_OP_CODE_REQUEST) ) ) //==0x0001 { memcpy(arpFrame->destMacAddr, arpFrame->srcMacAddr, 6); memcpy(arpFrame->srcMacAddr, macAddr, 6); memcpy(arpFrame->destIpAddr, arpFrame->srcIpAddr, 4); memcpy(arpFrame->srcIpAddr, ipAddr, 4); arpFrame->opCode = htons(ARP_OP_CODE_RESPONSE);//0x0002 newFrameLen = frameLen; } } return newFrameLen; } |
حلقه اصلی برنامه داخل فایل main.c هم این شکلی میشه:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ ETH_Process(&frame); } |
دو متغیر اصلی برنامه يعني مك آدرس و IP آدرس خودمون رو هم یادمون نره که در ابتداي فايل enc28j60.c تعریف کنیم:
1 2 3 | uint8_t macAddr[MAC_ADDRESS_BYTES_NUM] = {0x00, 0x17, 0x22, 0xED, 0xA5, 0x01}; uint8_t ipAddr[IP_ADDRESS_BYTES_NUM] = {192, 168, 0, 22}; |
فرض میکنیم که کد بدون خطا، کامپایل و پروگرم شده؛ حالا چجوری میشه برنامه رو تست کنیم؟
اولین کار اینه که محدوده (range) آیپی کامپیوتر و بردمون رو یکی کنیم؛ بهطوریکه این دو در یک زیر شبکه قرار بگیرند، شما هر آیپی برای بردتون در نظر گرفتید، آیپی کامپیوتر رو هم در همون محدوده قرار بدید و فقط عدد اول (از سمت راست) رو تغییر بدید؛ مثلاً اگر آیپی دستگاه 192.168.0.22 هست، شما میتونید آیپی کامپیوترتون رو 192.168.0.1 بذارید یا هر آیپی دیگه ای به فرم بالا بهجز اینکه عدد آخرش 22 یا صفر باشه.
نحوه تنظیم آدرس IP در ویندوز
نحوه تنظیم آدرس IP در ویندوز
پنجره cmd.exe يا همون كامند پرامپت ويندوز رو باز کنید. برای این کار در قسمت استارت ویندوز، تایپ کنید cmd و داخل پنجره باز شده تایپ کنید:
Ping 192.168.0.22
و Enter رو بزنید. همزمان میتوانید با استفاده از قابلیت دیباگ میکروکنترلرتون (اگه داشته باشه) و یا نرمافزار wireshark پیامها رو رصد کنید.
قبل از اینکه بریم سر وقت پروتکل بعدی یعنی IP یا همون Internet Protocol با چنتا از قابلیتهای تراشه ENC آشنا بشیم و همینطور چند اصطلاح جدید یاد بگیریم. اگه توجه کرده باشید روال کارمون تا اینجا اینطور بود که مفاهیم رو کمکم ارائه میدیم تا خواننده خیلی آشفته نشه در مقابل حجم اطلاعات وارده!
در دیتاشیت تراشه ENC چند قابلیت نوشته شده که شاید نیاز به توضیح داشته باشند. اولین قابلیت، تشخیص خودکار قطبیت (AutoPolarity detection) هست. در یک ارتباط دیفرانسیلی، اگه جای پینهای مثبت و منفی رو اشتباه متصل کنیم؛ طبیعیه که ارتباط برقرار نشه ولی AutoPolarioty این قابلیت رو داره که حتی در صورت اتصال اشتباه پینهای مثبت و منفی TX+,TX- به گیرنده هم بیتها رو درست بخونه. در ابتدای برقراری یک ارتباط؛ تراشه منتظر الگوی خاصی از بیتها هست. چنانچه سطح بیتها در این روال متقارن باشه؛ تراشه متوجه میشه که پینها اشتباه متصل شده ن و در داخل تراشه، جای پینها تعویض میشه.
دومین قابلیت Auto MDI-X هست. از اسم هم مشخصه که مربوط به بخش MDI هست، حالا چی هست؟ در یک ارتباط بایست بخش TX فرستنده به RX گیرنده متصل بشه. در تراشههای اولیه، هر دو دستگاه دارای بخش MDI بودند؛ لذا لازم بود که حتماً از کابلهای معروف به کابل کراس (cross) یا متقاطع استفاده بشه که جای پینهای TX و RX روی کابل تغییر میکرد. بعدها، تراشههایی به وجود اومد که این تقاطع، داخل خود تراشه انجام میشد که بهش MDI-X میگفتن (اون X آخر، علامت تقاطع هست) لذا نیاز نبود که از کابل کراس استفاده بشه و اتصالات روی کابل یکبهیک بود، به این کابلها، کابل مستقیم یا straghit میگفتن.
پس برای اتصال قطعات قدیمی و جدید در شبکه؛ 4 حالت برای کابل داشتیم:
MDI-X | MDI |
|
Straight | Cross | MDI |
Cross | Straight | MDI-X |
تراشههای با قابلیت Auto MDI-X با اجرای یک فرایند، متوجه میشن که آیا ارتباط TX به Rx درست هست یا نه! و اگر این ارتباط به دستی برقرار نشده باشه؛ درون تراشه، ارتباط رو به شکل درست برقرار میکنن. در نتیجه در این حالت، از هر دو نوع کابل میتونید استفاده کنید. پیشنهاد میکنم فرایند بررسی و تغییر اتصال در حالت Auto MDI-X رو در نت جستجو و مطالعه کنید، روش ساده اما جالبی برای انجام این کار داره!
یک اصطلاح و یک نکته دیگه هم Auto Negotiation یا مذاکره خودکار هست. هنگام روشنشدن یا هنگام اتصال کابل به سوکت؛ دو طرف کابل، برای بررسی قابلیتهای همدیگه مثل سرعت، نوع ارتباط (نیم دوطرفه یا تمام دوطرفه) و… یک فرایندی رو طی میکنند تا حالت بهینه رو تنظیم کنند. به این فرایند مذاکره خودکار گفته میشود.
این تنظیمات رو میتوان بهصورت دستی هم انجام داد؛ اما پیشنهاد نمیشود.
از طرفی ممکنه با اصطلاحی به نام Jabber Condition یا Jabber detection هم برخورد کنید. اگر فریم دریافتی، دادهای بیش از مقدار تعریف شده (1500 در اترنت پایه؛ 1504در Tag frame یا 1982 در Envelope frame) داشته باشه؛ اصطلاحا شرایط Jabber اتفاق افتاده و بررسی اون جزو وظایف قسمت PHY هست. از اونجاییکه این وضعیت ممکنه در حالت هنگ فرستنده اتفاق افتاده باشه (لذا باعث سرریز حافظه دریافت بشه)؛ میشه تراشه PHY رو طوری تنظیم کنیم که این فریم ها رو دریافت نکنه.
یک نکته کاربردی هم اینجا بگیم و بحث رو تموم کنیم. در حین ارتباط و به طور مرتب؛ برقراری ارتباط (متصل بودن کابل و روشن بودن سمت دیگر) با ارسال پالسهای همزمانی که به نام LTP(Link Test Pulse) یا NLP(Normal Link Pulse) شناخته میشوند؛ چک خواهد شد.
در سرعت 10Mb این پالسها در حالت توقف (Idle) و تقریباً در هر 16ms ارسال میشوند. در سرعت 100Mb نوع بررسی برقراری ارتباط؛ همچنین نوع کدینگ preamble و دادهها متفاوت هست. خوشبختانه این امور توسط سختافزار PHY انجام و از طریق ثباتهای وضعیت داخلی به اطلاع کاربر رسانده میشود. ما نیاز ضروری به دانستن آنها نداریم.
برای اطلاع بیشتر میتونید به سند کاربردی AN1120 از شرکت میکروچیپ یا اسناد شرکتهای دیگه در این مورد مراجعه کنید.
نویسنده شو !
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.