محسن نوشته

نگاهی عمیق به پشته شبکه (بخش چهارم)
منتشر شده در: — Aug 15, 2020

تا حالا به درک روشنی از ENC28J60 بعنوان تراشه ارتباط با دنیای شبکه های کامپیوتری مبتنی بر پروتکل IEEE802.3 رسیدیم. توی این بخش میریم سراغ کار اصلی که با این تراشه داریم یعنی مبادله فریم های اترنت و پیکربندی ENC28J60 را برای دریافت و ارسال فریم بررسی میکنیم. حواسمون باشه نمونه کدهایی که توی این بخش آورده شده مبتنی بر میکروکنترلرهای AVR و خاصه ATMega128 هستش. خوب مقدمه کافیه بریم کارمونو شروع کنیم که کلی چیزهای خوشمزه قراره با هم یاد بگیریم.

نکته: لازمه یه تشکر ویژه از همسرم، ثریا داشته باشم. ثریا توی مسیر ریسرچ و مطالعه همیشه پشتیبان من بوده و هر کاری که از دستش میومده برای این هدف انجام داده. تصاویری که توی این مجموعه از پست ها میبینید را ثریا طراحی کرده و این زحمتش UX جذابی حین مطالعه برامون ایجاد میکنه. ثریا جان سپاس.

فریم اترنت:

میدونیم ENC28J60 از یک طرف به زوج سیم های بهم تابیده شده کابل شبکه وصل میشه و از طرف دیگه به باس SPI. بنابراین از یک طرف با پالس های الکتریکی و از طرف دیگه با جریانی از بیت ها سروکار دارد. علاوه بر این یاد گرفتم با چه دستورالعمل هایی میشه چه کارهایی با این تراشه دوست داشتنی کرد. کار اصلی که ما دوست داریم باهاش کنیم اینه که بهش فریم اترنت بدیم و اون فریم را برای ما تبدیل به پالس های الکتریکی مناسب کنه و اونارو روی زوج سیم ارسال کنه. علاوه بر این وقتی پالس های الکتریکی از زوج سیم دریافت میکنه فریم اترنت را ازشون استخراج و به ما تحویل بده. پس با یه عینک دیگه میتونیم بگیم ENC28J60 از یه طرف با پالس های الکتریکی و از طرف دیگه با فریم های اترنت سروکار دارد. ساختار فریم های اترنت توسط پروتکل IEEE802.3 تعریف شده و همه تراشه های شبکه، کارت های شبکه و دیوایس هایی که به شبکه اترنت متصل میشن باید این پروتکل را رعایت کنند. در واقع هدف اصلی این پروتکل تعریف یک زبان مکالمه واحد بین نودهای شبکه اترنت هستش. اصلی ترین بخش این زبان هم ساختاربندی داده هایی هست که روی شبکه اترنت مبادله میشود. داده ها باید در ساختار تعریف شده ای جایابی و سپس ارسال شوند. شکل زیر این ساختار مشخص که همون فریم اترنت هستش را نمایش میده.

ENC28J60

طول فریم اترنت بین 64 تا 1518 بایت میتونه متغیر باشه و از اجزای زیر تشکیل میشه: آدرس مقصد (dst addr)

آدرس مبدا (src addr)

نوع/اندازه (type)

داده (data)

کد کشف خطا (CRC)

از آنجایی که فریم های اترنت نهایتا تبدیل به یک دنباله از پالس های الکتریکی می شوند، گیرنده باید نقطه شروع پالس های الکتریکی مربوط به یک فریم را تشخیص دهد. بنابراین قبل از ارسال فریم اترنت7 بایت به عنوان Preamble جهت سینک شدن گیرنده فریم با فرستنده و یک بایت به عنوان StartOfFram یا SOF ارسال می‌شود. شکل زیر محل قرارگیری این دو را نمایش میدهد.

ENC28J60

حواسمون باشه که تزریق Preamble و SOF توسط ماژول PHY تراشه ENC28J60 انجام میشه و ما بعنوان واحد پردازشی لازم نیست برای این مورد کاری انجان بدیم. آدرس های مبدا و مقصد هم آدرس MAC تراشه یا کارت شبکه هایی هستن که فریم را ارسال و دریافت می کنن. فیلد Type یا Length یه فیلد مهمه! وقتی واحد پردازشی یک فریم اترنت دریافت میکنه میره سراغ پردازش داده هایی که توی فیلد Data فریم قرار داره. فیلد Type مشخص میکنه این دیتا چی هست. بعوان مثال توی فیلد Data یک بسته IPv4 قرار گرفته یا IPv6 و … . شکل زیر مقادیر مختلفی که فیلد Type میتونه داشته باشه را نمایش میده.

ENC28J60

تراشه ENC28J60 فریم‌هایی که طول بیشتر از 1518 بایت و یا کمتر از 64 بایت دارند را دور میریزه! اما ENC28J60 برای ما امکان اینکه این رفتار را کنترل کنیم فراهم آورده. در صورتی که میخواهیم فریم های با طول بزرگتر را دریافت کنیم بیت HFRMEN از ثبات MACON1 رو باید روشن کنیم. علاوه بر این اگه میخواهیم فریم های با طول کمتر از 64 بایت ارسال کنیم باید بیت های PADCFG از MACON3 را بدرستی روشن کنیم. شکل زیر بما نشون میده بیت های PADCFG را چطور باید تنظیم کنیم.

ENC28J60

وقتی پالس های الکتریکی فریم اترنت روی سیم ها حرکت می کنند ممکنه نویز، اعوجاج و … باعث تغییر این پالس ها بشه و متعاقبا بیت نظیر این پالس به اشتباه کدگشایی بشه. برای کشف این نوع خطاها پروتکل IEEE802.3 از مکانیزم کشف خطای CRC با طول 4 بایت برای فریم های اترنت استفاده می کنه. وقتی یک فریم دریافت میشه ابتدا کد کشف خطای اون محاسبه میشه. برای این محاسبه از فیلدهای: آدرس مبدا، آدرس مقصد، نوع، داده و padding استفاده میشه. اگه کد محاسبه شده با کد اعلام شده در فریم برابر بود یعنی خطایی در بیت های فریم رخ نداده است. در غیر این صورت حداقل مقدار یک بیت از فریم دچار خطا شده است. ما میتونیم بیت CRCEN از ثبات ERXFCON را روشن کنیم. وقتی این بیت روشنه محاسبه CRC و چک کردنشو خود ENC28J60 انجام میده.

نوع آدرس‌هایی که توی فریم های اترنت استفاده میشه آدرس های سخت افزاری یا MAC Address هستن. هر آدرس MAC از دو بخش اصلی ساخته میشه. شکل زیر ساختار آدرس MAC را نمایش میده.

ENC28J60

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

بخش OUI: که شناسه مختص تولید کننده تراشه های کارت شبکه هستش و توسط سازمان IEEE صادر میشه.

بخش AAU: که شناسه مختص تراشه کارت شبکه هستش و توسط تولید کننده کارت شبکه یا تراشه شبکه تخصیص داده میشه.

با این مدل میتونیم بگیم هر آدرس MAC توی کل زمین یکتا هستش. اما این موضوع اونقدر هم مهم نیست. چراکه ما میتونیم آدرس MAC یک تراشه یا کارت شبکه را تغییر بدیم و علاوه بر این از این آدرس‌های بعنوان آدرس های قابل مسیریابی در گستره دنیا استفاده نمیشه. البته این آدرس ها در مسیریابی بسته ها نقش دارن اما دامنه اثر این نقش خیلی خیلی کوچک و محدود هستش. آدرس MAC تراشه ENC28J60 توی ثبات های MAADR0 تا MAADR5 قرار داده میشه و میتونیم هر مقدار دلخواهی بهش بدیم. همین قابلیت میتونه بما کمک کنه تا کلی کارهای عجیب با این تراشه دوست داشتنی انجام بدیم!

پیکربندی ENC28J60 برای مبادله فریم اترنت:

پیکربندی ENC28j60 برای مبادله فریم روال مشخصی داره، ابتدا با هم با زبان شیرین فارسی این روال را بررسی میکنیم و بعد کد مربوطه را به زبان شیرین C یه نگاه میندازیم.

پیکربندی بافر

باید فضای بافر را به دو قسمت یکی برای فریم های دریافتی و یکی برای فریم های ارسالی تنظیم کنیم. نکته مهم اینکه وقتی هر فریم ارسال یا دریافت میشه ENC28J60 گزارش کاملی از شرح وقایع ارسال یا دریافت فریم را بترتیب توی 7 یا 6 بایت انتهای فریم تحت عنوان بردار حالت ارسال یا دریافت بما میده. بنابراین اگر بیشینه طول فریمی که توسط واحد پردازشی ارسال میشه 1518 بایت هست طول بافر ارسال باید 1 + 7 + 1518 بایت درنظر گرفته بشه. اون 1 هم مربوط به PPCB هست که یکم جلوتر باهاش آشنا میشیم.

تنظیم ثبات ERXFCON

این ثبات فیلترهای مختلف سخت افزاری که ENC28J60 ارائه میده را کنترل میکنه.

پیکربندی ماژول MAC

اگه ENC28J60 توی مد Full Duplex کار میکنه بیت های TXPAUS و RXPAUS را روشن میکنیم تا مکانیزم کنترل جریان فعال بشه. IEEE802.3 از فریم ویژه ای بنام Pause Control برای کنترل جریان استفاده میکنه. وقتی بیت RXPUSH روشن هست، ENC28J60 به محض دریافت فریم Pause Control ارسال فریم های اترنت را متوقف می کنه. وقتی بیت TXPAUS خاموش هست ENC28J60 فریم های Pause Control ارسال نمی کنه.

تنظیم ثبات MACON3: بیت های PADCFG برای اضافه کردن خودکار Padding به فریم، بیت TXCRCEN برای محاسبه خودکار CRC برای فریم های ارسالی و بیت FULDPX برای تنظیم مود عملکرد ENC28J60 در Half Duplex یا Full Duplex هستن. نکته مهم اینکه مود عملکرد ماژول PHY نیز باید با مود عملکرد ماژول MAC هماهنگ باشه. برای این کار از بیت PDPXMD از ثبات PHCON1 استفاده میکنیم.

تنظیم ثبات MACON4: مقادیر بعد از Reset شدن ENC28J60 برای بیشتر کاربردها کفایت میکنه.

تنظیم Inter Packet Gap: وقتی تراشه شبکه یک فریم اترنت دریافت میکنه مقدار مشخصی زمان لازم داره تا اونو پردازش کنه و توی بافر قرار بده. متاسفانه حین این زمان نمیتونه بسته جدیدی را دریافت کنه! (البته برای تراشه های با معماری قدیمی) بنابراین باید بین دو فریم متوالی یک GAP در نظر گرفته بشه. این گپ زمانی را IEEE802.3 به عنوان Inter Packet Gap نامگذاری کرده و دو نوع داره که عبارتند از: Back-to-Back و NON Back-to-Back. مقدار NON Back-to-Back Inter Packet Gap در ثبات MAIPGL در مودهای Half Duplex و Full Duplex مقدار 0x12 و در ثبات MAIPGH مقدار 0x0C هستش. مقدار Back-to-Back Inter Packe Gap در ثبات MABBIPG تنظیم میشه و برای Half Duplex مقدار 0x12 (معادل 9.6 میکروثانیه) و برای Full Duplex مقدار 0x15 (معادل 9.6 میکروثانیه) هست. حواسمون باشه مقادیری که ما برای BBIPG و IPG توی ثباتها میزاریم به زمان مشخصی بر حسب میکروثانیه نگاشت میشن. جدول این نگاشت توی مستندات IEEE802.3 ارائه شده.

تنظیم MACLCON1 و MACLCON2: این دو وظیفه کنترل ارسال مجدد فریم موقع تصادم و کنترل پنجره تصادم را به عهده دارن. مقادیر بعد از Reset شدن جواب اکثر کاربردها رو میده اما اگه طول کابل از مقادیر متعارف بیشتر شد یا کابل از محیط پر نویزی عبور میکرد مقادیر MACLCON2 باید افزایش پیدا کنه. حواسمون باشه که کاربرد این دو برای مود Half Duplex هستش.

تنظیم آدرس MAC: آدرس MAC تراشه ENC28J60 توی ثبات های MAADR0 تا MAADR5 قرار داده میشه.

پیکربندی ماژول PHY

تنظیم بیت PDPXMD متناسب با مود عملکرد تراشه. اگه روشن باشه ماژول PHY توی مود Full Duplex کار میکنه.

وقتی تراشه توی مود Half Duplex کار میکنه بیت HDLDIS از ثبات PHCON2 روشن میشه.

تنظیم مناسب وضعیت LED ها.

ثبات هایی که توی این بخش بهشون نیاز داشتیم در ادامه لیست شدن.

ENC28J60

ENC28J60

ENC28J60

ENC28J60

ENC28J60

توی قطعه کد زیر همه داستان بالا به زبان شیرین C با کامنت های افزوده! نمایش داده شده.

 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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//perform system reset
enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);

//check CLKRDY bit to see if reset is complete
while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));


//NextPacketPtr global variable
NextPacketPtr = RXSTART_INIT;

//initialize receive buffer
enc28j60Write(ERXSTL, RXSTART_INIT&0xFF);
enc28j60Write(ERXSTH, RXSTART_INIT>>8);

//set receive pointer address
enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF);
enc28j60Write(ERXRDPTH, RXSTART_INIT>>8);

//set receive buffer end
enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF);
enc28j60Write(ERXNDH, RXSTOP_INIT>>8);

//set transmit buffer start
enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);
enc28j60Write(ETXSTH, TXSTART_INIT>>8);

//bring MAC out of reset
enc28j60Write(MACON2, 0x00);

//enable MAC receive
enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);

//enable automatic padding and CRC operations
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3,      MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX);

//Set the maximum packet size which the controller will accept
enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF);	
enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8);

//set inter-frame gap (back-to-back)
enc28j60Write(MABBIPG, 0x15);

//set inter-frame gap (non-back-to-back)
enc28j60Write(MAIPGL, 0x12);
enc28j60Write(MAIPGH, 0x0C);

//write MAC address
enc28j60Write(MAADR5, ENC28J60_MAC0);
enc28j60Write(MAADR4, ENC28J60_MAC1);
enc28j60Write(MAADR3, ENC28J60_MAC2);
enc28j60Write(MAADR2, ENC28J60_MAC3);
enc28j60Write(MAADR1, ENC28J60_MAC4);
enc28j60Write(MAADR0, ENC28J60_MAC5);

//no loopback of transmitted frames
enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);

//switch to bank 0
enc28j60SetBank(ECON1);

//enable interrutps
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);

//enable packet reception
enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
}

ارسال فریم اترنت:

تا اینجا ENC28J60 پیکربندی شد و آماده مبادله فریم با شبکه اترنت هستش. توی این بخش می خواهیم ببینیم چه کارهایی باید برای ارسال فریم اترنت انجام بدیم. ماژول MAC میتونه برای ما خیلی از کارهایی که برای ارسال فریم اترنت لازم داریم را بصورت خودکار انجام بده. اون میتونه CRC رو محاسبه و به فریم اضافه کنه، Padding به اندازه مورد نیاز به فریم اضافه کنه با اینکه فریم های بزرگتر از 1518 بایت برای ما ارسال کنه. توی بخش قبل ثباتهای مرتبط با این قابلیت ها رو بررسی کردیم. اما گاهی ممکنه بخواهیم فریمی با ویژگی های متفاوت ارسال کنیم. برای این کار ENC28J60 یه قابلیت جالب به ما میده. بایت اولی که قبل از فریم اصلی توی بافر ارسال قرار میگیره اسمش PPCB یا Per Packet Control Block هست. واحد پردازشی میتونه توی این بایت کانفیگ اختصاصی برای فریم موجود در بافر ارسال را به ENC28J60 ارسال کنه. شکل زیر نقش بیت های این بایت را نمایش میده.

ENC28J60

اگه بیت POVERRIDE خاموش باشه یعنی ENC2860 مطابق محتوای ثبات MACON3 رفتار میکنه در غیر این صورت هرآنچه در PPCB اعلام شده به فریم ارسالی اعمال میشه. برای ارسال هم واحد پردازشی باید روال مشخصی رو اجرا کنه، ما ابتدا این روال رو با زبان شیرین فارسی و بعد با زبان شیرین C بررسی میکنیم: مقداردهی مناسب ثبات ETXST

نوشتن بایت PPCB و بایت های فریم در بافر ارسال با استفاده از دستور WBM (توی پست قبلی بررسی کردیم)

مقدار دهی مناسب ثبات ETXND. این ثبات به آدرس آخرین بایت فریم ارسالی در بافر ارسال اشاره میکنه.

اگه میخواهیم خاتمه ارسال فریم از طریق وقفه یا Interrupt اعلام بشه بیت TXIF از ثبات EIR را خاموش و بیت های TXIE و INTIE از ثبات EIE را روشن می کنیم.

برای شروع ارسال بیت TXRST از ثبات ECON1 را روشن می کنیم. بعد از خاتمه ارسال 7 بایت به انتهای فریم ارسالی در بافر ارسال اضافه می شود. این بایت ها بردار حالت ارسال یا Transmit Status Vector نام دارن و ENC28J60 شرح مفصلی از وقایع موقع ارسال را با اونها گزارش میده. شکل زیر محل قرار گیری TSV را نمایش میده.

ENC28J60

کد زیر هم داستان فوق را با زبان شیرین C و کامنت افزوده نمایش میده:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
void enc28j60PacketSend(unsigned int len, unsigned char* packet)
{
	//Set the ETXST pointer
	enc28j60Write(ETXSTL, TXSTART_INIT&0xFF);//TXSTART_INIT=0x1A0F 
	enc28j60Write(ETXSTH, TXSTART_INIT>>8);
	//Set the write pointer to start of transmit buffer area
	enc28j60Write(EWRPTL, TXSTART_INIT);//TXSTART_INIT=0x1A0F
	enc28j60Write(EWRPTH, TXSTART_INIT>>8);
	//write per-packet control byte
	enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);
	//copy the packet into the transmit buffer
	enc28j60WriteBuffer(len, packet);
	//Set the ETXND pointer 
	enc28j60Write(ETXNDL, (TXSTART_INIT+len));
	enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8);
	//send the contents of the transmit buffer onto the network
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);
}

شکل زیر بردار حالت ارسال رو با جزئیات بهمون نشون میده.

ENC28J60

ثباتهایی که برای ارسال فریم بهشون نیاز داریم توی شکل های زیر نمایش داده شده است.

ENC28J60

دریافت فریم اترنت:

برای فعال کردن دریافت فریم ها سه تا کار لازمه انجام بشه که عبارتند از:

آیا میخواهیم موقع دریافت فریم Interrupt تولید بشه؟ اگه بله توی پیکربندی اولیه ENC28J60 باید بیت های PKTIE و INTIE از ثبات EIE روشن شده باشن.

آیا میخواهیم وقتی ENC28J60 با محدودیت فضا برای ذخیره سازی فریم های دریافتی روبرو شد Interrupt تولید بشه؟ اگه بله توی پیکربندی اولیه ENC28J60 باید بیت RXERIF از ثبات EIR خاموش و بیت های RXERIE و INTIE از ثبات EIE روشن بشن.

بیت RXEN از ثبات ECON1 را روشن کنیم تا دریافت فریم های از روی زوج سیم شروع بشه.

نکته مهم: بعد از روشن شدن RXEN نباید پیکربندی فیلترها و اشاره گرهای بافر دریافت تغییر کنن.

وقتی فریم جدیدی دریافت و ذخیره میشه بیت PKTIF از ثبات EIR روشن میشه و اگه Interrupt درخواست شده بود، تولید میشه. به اعضای هر فریم ذخیره شده در بافر دریافت ثبات EPKTCNT یک واحد زیاد میشه. تا زمانی که بیت PKTIF روشنه یعنی یک یا چند فریم توی بافر دریافت وجود دارند. تعداد این فریم ها توی ثبات EPKTCNT نگهداری میشه.

شکل زیر ساختار یک فریم دریافت شده را نمایش میده.

ENC28J60

ابتدای هر فریم دریافت شده 6 بایت بعنوان بردار حالت دریافت اضافه میشه. دو بایت اول اشاره به ابتدای فریم بعدی در بافر دریافت می کنن و 4 بایت بعدی شرح کاملی از اتفاقاتی که موقع پذیرش و ذخیره فریم رخ داده اعلام میکنه. حواسمون باشه که ENC28J60 همیشه تلاش میکنه آدرس شروع فریم بعدی توی بافر دریافت، زوج باشه. بنابراین ممکنه یک بایت انتهای فریم دریافتی بصورت Padding اضافه بشه تا آدرس شروع فریم بعدی زوج بشه.

شکل زیر جزئیات بایت های مربوط به بردار حالت دریافت فریم را نمایش میده

ENC28J60

خوب بریم ببینیم برای واکشی فریم های دریافت شده MCU باید چیکار کنه. MCU اول از همه باید بردار حالت دریافت رو با استفاده از دستور RBM دریافت کنه (یا حداقل دو بایت اول بردار حالت دریافت که به ابتدای فریم بعدی اشاره میکنه را برای واکشی فریم بعدی ذخیره کنه). MCU میتونه بصورت پیوسته دستور RBM رو استفاده کنه و کل بایت های یک فریم را دریافت کنه. بعد از اینکه فریم رو دریافت میکنه باید مقداری از بافر دریافت که توسط این فریم اشغال شده بود را آزاد کنه. برای این کار مقدار اشاره گر ERXRDPT را با مقدار مناسب بروز کنه. این اشاره گر به ENC28J60 میفهمونه که MCU تا کجای بافر را دریافت کرده. بعد از این MCU باید بیت PKTDEC از ثبات ECON2 را روشن کنه. این کار باعث میشه از مقدار ثبات EPKTCNT یک واحد کم بشه (یادمون باشه این ثبات تعداد بسته های موجود در بافر دریافت فریم را اعلام میکنه). اگه بعد از بروزرسانی PKTDEC مقدار EPKTDEC صفر بشه یعنی هیچ فریم پردازش شده ای وجود نداره و فلگ PKTIF از ثبات EIE بصورت خودکار خاموش میشه. وقتی مقدار EPKTCNT به 255 رسید همه بسته های دریافتی دور ریخته خواهند شد. کد زیر داستان بالا رو به زبان شیرین C با کامنت افزوده نمایش میده.

 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
NextPacketPtr = RXSTART_INIT;//RXSTART_INIT= ERXST=0X0000

unsigned int enc28j60PacketReceive(unsigned int maxlen, unsigned char* packet) 
{
	u16 rxstat;
	u16 len;
	//check if a packet has been received and buffered
	if( !enc28j60Read(EPKTCNT) )	return 0;
	//Set the read pointer to the start of the received packet
	enc28j60Write(ERDPTL, (NextPacketPtr));
	enc28j60Write(ERDPTH, (NextPacketPtr)>>8);
	//read the next packet pointer
	NextPacketPtr  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
	NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
	//read the packet length
	len  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
	len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
	//read the receive status
	rxstat  = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);
	rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8;
	//limit retrieve length
	//(we reduce the MAC-reported length by 4 to remove the CRC)
	len = MIN(len, maxlen);
	//copy the packet from the receive buffer
	enc28j60ReadBuffer(len, packet);
	//Move the RX read pointer to the start of the next received packet
	//This frees the memory we just read out
	enc28j60Write(ERXRDPTL, (NextPacketPtr));
	enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8);
	//decrement the packet counter indicate we are done with this packet
	enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);
	return len;
}

لیست ثباتهایی که برای واکشی فریم از بافر دریافت لازم داریم در ادامه اورده شده.

ENC28J60

ENC28J60

جمع بندی:

خوب بلاخره تونستیم با ENC28J60 مبادله فریم داشته باشیم. حالا میشه این فریم ها رو برای پردازش فرستاد به پشته TCP/IP و یا فریم های خروجی از پشته را به ENC28J60 داد تا روی Wire ارسال بشه. قبل از اینکه بریم سراغ این پشته چنتا کار کوچیک با ENC28J60 داریم. لازمه درباره فیلترها و مودهای عملکردش یکم دانشمونو افزایش بدیم که این میشه موضوع پست بعدی.

پیروز باشید.