OSDN Git Service

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