OSDN Git Service

9f3fc376eb1f1f9d52e5e5d7852f4b1e8a4e2206
[mimic/MiMicSDK.git] / lib / src / driver / ethernet / lpc17xx / EthDev_LPC17xx.c
1 /*\r
2  * EthDev_LPC1769.c\r
3  *\r
4  *  Created on: 2011/12/07\r
5  *      Author: nyatla\r
6  */\r
7 #include "NyLPC_config.h"\r
8 #if NyLPC_MCU==NyLPC_MCU_LPC17xx\r
9 #include "LPC17xx.h"\r
10 #include "EthDev_LPC17xx.h"\r
11 #include "NyLPC_os.h"\r
12 #include "LPC17xx.h"\r
13 /* If no buffers are available, then wait this long before looking again.... */\r
14 #define emacBUFFER_WAIT_DELAY_MS                 3\r
15 #define emacBUFFER_WAIT_EMPTY_DELAY_MS  10\r
16 #define emacSHORT_DELAY_MS                              10\r
17 //--------------------------------------------------\r
18 // common function.\r
19 //--------------------------------------------------\r
20 \r
21 \r
22 \r
23 /**\r
24  * 送信デスクリプタを準備します。\r
25  */\r
26 void EthDev_LPC17xx_prevTxDescriptor(void)\r
27 {\r
28         long x;\r
29         //デスクリプタの設定\r
30         for( x = 0; x < NUM_TX_FRAG; x++ )\r
31         {\r
32                 TX_DESC_PACKET( x ) = ( unsigned long ) NULL;\r
33                 TX_DESC_CTRL( x ) = 0;\r
34                 TX_STAT_INFO( x ) = 0;\r
35         }\r
36         /* Set LPC_EMAC Transmit Descriptor Registers. */\r
37         LPC_EMAC->TxDescriptor = TX_DESC_BASE;\r
38         LPC_EMAC->TxStatus = TX_STAT_BASE;\r
39         LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1;\r
40 }\r
41 \r
42 \r
43 /**\r
44  * 送信中のイーサフレームを処理する機会を与えて、送信キューが空くまで待ちます。\r
45  * LPC1769の場合は、非同期に更新したディスクリプタの内容から、送信メモリのフラグを更新します。\r
46  * @return\r
47  * 次に書き込むことが出来る送信キュー。\r
48  */\r
49 static NyLPC_TUInt32 waitForTxEthFrameEmpty(void)\r
50 {\r
51         NyLPC_TUInt32   IndexNext;\r
52         struct NyLPC_TTxBufferHeader *b;\r
53         void* p;\r
54         NyLPC_TUInt32 i;\r
55 \r
56         //送信キューの決定\r
57         IndexNext = (LPC_EMAC->TxProduceIndex + 1)%NUM_TX_FRAG;\r
58 \r
59         //送信キューフルが解除されるまで待ち\r
60         while(IndexNext == LPC_EMAC->TxConsumeIndex)\r
61         {\r
62                 //\r
63                 NyLPC_cThread_sleep(emacBUFFER_WAIT_EMPTY_DELAY_MS);\r
64         }\r
65 \r
66         //(TxProduceIndex+1)→TxConsumeIndexにあるデータのsentフラグを消去\r
67         for(i=IndexNext;i!=LPC_EMAC->TxConsumeIndex;i=(i+1)%NUM_TX_FRAG)\r
68         {\r
69                 p=(void*)TX_DESC_PACKET(i);\r
70                 if(p!=NULL){\r
71                         b=((struct NyLPC_TTxBufferHeader*)p)-1;\r
72                         b->is_lock=NyLPC_TUInt8_FALSE;\r
73                         TX_DESC_PACKET(i)=0;\r
74                 }\r
75         }\r
76         p=(void*)TX_DESC_PACKET(i);\r
77         if(p!=NULL){\r
78                 b=((struct NyLPC_TTxBufferHeader*)p)-1;\r
79                 b->is_lock=NyLPC_TUInt8_FALSE;\r
80                 TX_DESC_PACKET(i)=0;\r
81         }\r
82         return IndexNext;\r
83 }\r
84 \r
85 void EthDev_LPC17xx_processTx(void)\r
86 {\r
87         waitForTxEthFrameEmpty();\r
88 }\r
89 \r
90 /**\r
91  * Ethernetパケットを送信します。\r
92  * allocTxBufで得たバッファか、NyLPC_TTxBufferHeaderのペイロード部分を指定すること。\r
93  * <p>関数仕様</p>\r
94  * この関数は、i_bufが\r
95  * </div>\r
96  */\r
97 void EthDev_LPC17xx_sendTxEthFrame(struct NyLPC_TTxBufferHeader* i_buf,unsigned short i_size)\r
98 {\r
99         NyLPC_TUInt32   IndexNext,Index;\r
100 \r
101         //サイズ0なら送信の必要なし\r
102         if(i_size == 0)\r
103         {\r
104                 return;\r
105         }\r
106         //送信デスクリプタの反映\r
107         IndexNext =waitForTxEthFrameEmpty();\r
108 \r
109         //送信対象のメモリブロックを送信中に設定。\r
110 //      b=(i_buf+1);\r
111         //送信中のメモリブロックなら無視\r
112         if(i_buf->is_lock){\r
113                 return;\r
114         }\r
115         //送信中にセット\r
116         i_buf->is_lock=NyLPC_TUInt8_TRUE;\r
117 \r
118         //送信データのセット\r
119         Index = LPC_EMAC->TxProduceIndex;\r
120         if (i_size > ETH_FRAG_SIZE){\r
121                 i_size = ETH_FRAG_SIZE;\r
122         }\r
123 \r
124         //送信処理\r
125         TX_DESC_PACKET( Index ) = ( unsigned long )(i_buf+1);\r
126         //See UM10360.pdf Table 181. Transmit descriptor control word\r
127         TX_DESC_CTRL( Index ) = ((i_size-1) | TCTRL_LAST | TCTRL_INT );\r
128         LPC_EMAC->TxProduceIndex = IndexNext;\r
129         return;\r
130 }\r
131 \r
132 /***********************************************************************\r
133  * RXバッファ\r
134  ***********************************************************************/\r
135 \r
136 void EthDev_LPC17xx_prevRxDescriptor(void)\r
137 {\r
138         int x;\r
139         //デスクリプタの設定\r
140         for( x = 0; x < NUM_RX_FRAG; x++ )\r
141         {\r
142                 /* Allocate the next Ethernet buffer to this descriptor. */\r
143                 RX_DESC_PACKET(x) = ETH_BUF(x);\r
144                 RX_DESC_CTRL(x) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 );\r
145                 RX_STAT_INFO(x) = 0;\r
146                 RX_STAT_HASHCRC(x) = 0;\r
147         }\r
148 \r
149         /* Set LPC_EMAC Receive Descriptor Registers. */\r
150         LPC_EMAC->RxDescriptor = RX_DESC_BASE;\r
151         LPC_EMAC->RxStatus = RX_STAT_BASE;\r
152         LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1;\r
153 \r
154 }\r
155 \r
156 \r
157 /**\r
158  * 受信キューの先頭にあるRXフレームのポインタを返します。\r
159  * 関数は、受信キューのポインタを操作しません。続けて読み出したとしても、同じポインターを返します。\r
160  * 制限として、返却したポインタの内容は、一時的に書き換え可としてください。(この制限は将来削除します。)\r
161  * @return\r
162  * 成功した場合、受信データを格納したバッファポインターです。\r
163  * 次回nextRxEthFrameを呼び出すまで有効です。\r
164  */\r
165 void* EthDev_LPC17xx_getRxEthFrame(unsigned short* o_len_of_data)\r
166 {\r
167 \r
168         if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )\r
169         {\r
170                 //受信データを返却する。\r
171                 *o_len_of_data = (unsigned short)(( RX_STAT_INFO( LPC_EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3);\r
172                 return ( unsigned char * ) RX_DESC_PACKET( LPC_EMAC->RxConsumeIndex );\r
173         }\r
174         return NULL;\r
175 }\r
176 \r
177 \r
178 /**\r
179  * 受信キューを進行します。\r
180  */\r
181 void EthDev_LPC17xx_nextRxEthFrame(void)\r
182 {\r
183         long lIndex;\r
184         if( LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex )\r
185         {\r
186                 //キューすすめる。\r
187                 lIndex = LPC_EMAC->RxConsumeIndex;\r
188                 lIndex++;\r
189                 if( lIndex >= NUM_RX_FRAG )\r
190                 {\r
191                         lIndex = 0;\r
192                 }\r
193                 LPC_EMAC->RxConsumeIndex = lIndex;\r
194         }\r
195 }\r
196 \r
197 \r
198 /*-----------------------------------------------------------*/\r
199 \r
200 \r
201 /*-----------------------------------------------------------*/\r
202 #define ETHDEV_PHY_DEF_ADR              0x0100  /* Default PHY device address        */\r
203 \r
204 NyLPC_TBool EthDev_LPC17xx_prvWritePHY( long lPhyReg, long lValue )\r
205 {\r
206     const long lMaxTime = 10;\r
207     long x;\r
208 \r
209     LPC_EMAC->MCMD = 0;\r
210     LPC_EMAC->MADR = ETHDEV_PHY_DEF_ADR | lPhyReg;\r
211     LPC_EMAC->MWTD = lValue;\r
212 \r
213     for( x = 0; x < lMaxTime; x++ )\r
214     {\r
215         if( ( LPC_EMAC->MIND & MIND_BUSY ) == 0 )\r
216         {\r
217             /* Operation has finished. */\r
218             break;\r
219         }\r
220 \r
221         NyLPC_cThread_sleep( emacSHORT_DELAY_MS );\r
222     }\r
223 \r
224     if( x < lMaxTime )\r
225     {\r
226         return NyLPC_TBool_TRUE;\r
227     }\r
228     else\r
229     {\r
230         return NyLPC_TBool_FALSE;\r
231     }\r
232 }\r
233 /*-----------------------------------------------------------*/\r
234 \r
235 unsigned short EthDev_LPC17xx_prvReadPHY( unsigned int ucPhyReg, NyLPC_TBool* plStatus )\r
236 {\r
237     long x;\r
238     const long lMaxTime = 10;\r
239 \r
240     LPC_EMAC->MCMD = 1;\r
241     LPC_EMAC->MADR = ETHDEV_PHY_DEF_ADR | ucPhyReg;\r
242     LPC_EMAC->MCMD = MCMD_READ;\r
243 \r
244     for( x = 0; x < lMaxTime; x++ )\r
245     {\r
246         /* Operation has finished. */\r
247         if( ( LPC_EMAC->MIND & MIND_BUSY ) == 0 )\r
248         {\r
249             break;\r
250         }\r
251         NyLPC_cThread_sleep( emacSHORT_DELAY_MS );\r
252     }\r
253 \r
254     LPC_EMAC->MCMD = 0;\r
255 \r
256     if( x >= lMaxTime )\r
257     {\r
258         *plStatus = NyLPC_TBool_FALSE;\r
259     }\r
260 \r
261     return( LPC_EMAC->MRDD );\r
262 }\r
263 \r
264 \r
265 \r
266 \r
267 \r
268 \r
269 \r
270 \r
271 #endif\r
272 \r