]> rtime.felk.cvut.cz Git - rpp-test-sw.git/blob - rpp-test-sw/commands/cmd_emac.c
Merge branch 'can' of rtime.felk.cvut.cz:rpp-test-sw
[rpp-test-sw.git] / rpp-test-sw / commands / cmd_emac.c
1 /*
2  * Copyright (C) 2012-2013 Czech Technical University in Prague
3  *
4  * Created on: 28.2.2013
5  *
6  * Authors:
7  *     - Rostislav LisovĂ˝
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * File : cmd_emac.c
23  *
24  * Abstract:
25  *              Test command for Ethernet PHY
26  *
27  */
28 #include "cmd_emac.h"
29
30 #ifndef DOCGEN
31
32 #include "rpp/rpp.h"
33 #include "sys/sys.h"
34 #include "sys/phy_dp83848h.h"
35
36 unsigned int emacCtrlBase       = EMAC_CTRL_BASE;
37 unsigned int emacBase           = EMAC_BASE;
38 unsigned int emacCtrlRamBase    = EMAC_CTRL_RAM_BASE;
39 unsigned int mdioBase           = MDIO_BASE;
40
41 int rx_irq_cnt; /* Interrupt counters */
42 int tx_irq_cnt;
43
44 unsigned int phyalive;
45 unsigned int phylink;
46
47 unsigned int intvect;
48 unsigned int intvectraw;
49
50 uint8_t emacAddress[6]  = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab};
51 uint32_t emacPhyAddress = 0x1;  /* Address of PHY on "MDIO bus"
52                                    (depends on PHY configuration) */
53 int channel = 0;        /* Emac has 8 RX and TX channels; we use only one */
54
55 EMAC_Desc fr1 __attribute__((aligned(4)));      /* Frame descriptor of Ethernet frame to be sent */
56
57 /* Frame descriptor used for receiving frames --
58    it might be placed in normal RAM or in CPPI ram of EMAC */
59 //EMAC_Desc rx_desc __attribute__((aligned(4)));
60 volatile EMAC_Desc *rx_desc = ((EMAC_Desc*) EMAC_CTRL_RAM_BASE);
61
62
63 #define BUFF_SIZE       2048
64 uint8_t rx_buff[BUFF_SIZE]; /* Buffer for data reception */
65
66 eth_frame_t efr1;       /* Buffer for TX -- Before sending some data we have to
67                            prepare it in "Ethernet frame" format */
68
69
70 void dummy_wait()
71 {
72         volatile int i;
73
74         for (i = 0; i < 65555; i ++)
75                 ;
76 }
77
78 int emac_test(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[])
79 {
80         int chan;
81         unsigned char input = 0;
82         volatile unsigned int delay = 0xfff;
83         unsigned short data;
84         int j;
85
86         /* Deactivate reset pin of PHY */
87         dmmREG->PC4 = (1 << DMM_CLK); /* Set to H */
88         dummy_wait();
89         dmmREG->PC5 = (1 << DMM_CLK); /* Set to L */
90         dummy_wait();
91         dmmREG->PC4 = (1 << DMM_CLK); /* Set to H */
92         dummy_wait();
93
94         /* Prepare RX Packet buffer descriptor */
95         rx_desc->pBuffer = rx_buff;
96         rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
97         rx_desc->pNext = NULL;
98         rx_desc->BufOffLen = BUFF_SIZE;
99
100
101         /* Fill some testing Ethernet frame with relevant data */
102         efr1.destination[0] = 0x00;
103         efr1.destination[1] = 0x21;
104         efr1.destination[2] = 0x70;
105         efr1.destination[3] = 0xb5;
106         efr1.destination[4] = 0x4b;
107         efr1.destination[5] = 0xea;
108         efr1.source[0]      = 0xff;
109         efr1.source[1]      = 0xff;
110         efr1.source[2]      = 0xff;
111         efr1.source[3]      = 0xff;
112         efr1.source[4]      = 0xff;
113         efr1.source[5]      = 0xff;
114
115         efr1.len = 46;
116         efr1.data[0] = 0xaa;
117
118         _enable_IRQ();
119         _enable_FIQ();
120
121
122         EMACInit(emacCtrlBase, emacBase);
123         MDIOInit(mdioBase, 0x0, 0x0);
124         dummy_wait();   // FIXME
125
126         EMACMACSrcAddrSet(emacBase, emacAddress);
127         /*  Be sure to program all eight MAC address registers -
128          *  whether the receive channel is to be enabled or not.
129          */
130         for (chan = 0; chan < 8; chan++)
131                 EMACMACAddrSet(emacBase, chan, emacAddress, EMAC_MACADDR_NO_MATCH_NO_FILTER);
132
133         phyalive = MDIOPhyAliveStatusGet(mdioBase);
134         if (!phyalive) {
135                 rpp_sci_printf("PHY not alive\r\n");
136                 return -1;
137         }
138
139         phylink = MDIOPhyLinkStatusGet(mdioBase);
140         if (!phylink)
141                 rpp_sci_printf("PHY link down\r\n");
142         else
143                 rpp_sci_printf("PHY link up\r\n");
144
145         rpp_sci_printf("Configuring PHY and EMAC...\r\n");
146         PHY_auto_negotiate(mdioBase, emacPhyAddress, PHY_100BASETXDUPL_m | PHY_100BASETX_m | PHY_10BASETDUPL_m | PHY_10BASET_m);
147
148         /* Set the EMAC with the negotiation results if it is successful */
149         PHY_partner_ability_get(mdioBase, emacPhyAddress, &data);
150         if (data & PHY_100BASETXDUPL_m) {
151                 EMACDuplexSet(emacBase, EMAC_DUPLEX_FULL);
152                 dummy_wait();
153         } else if (data & PHY_100BASETX_m) {
154                 EMACDuplexSet(emacBase, EMAC_DUPLEX_HALF);
155                 dummy_wait();
156         } else {
157                 while(1)
158                         ;
159         }
160
161         for (chan = 0; chan < 8; chan++) {
162                 EMACTxHdrDescPtrWrite(emacBase, 0, chan);
163                 EMACRxHdrDescPtrWrite(emacBase, 0, chan);
164         }
165
166         //EMACCoreIntAck(emacBase, EMAC_INT_CORE0_RX);
167         //EMACCoreIntAck(emacBase, EMAC_INT_CORE0_TX);
168
169         EMACRxBroadCastEnable(emacBase, channel);
170         EMACRxPromiscEnable(emacBase, channel);
171
172         EMACTxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
173         EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
174
175         EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
176
177         //EMACRxUnicastSet(emacBase, 0);
178         EMACTxEnable(emacBase);
179         EMACRxEnable(emacBase);
180
181         EMACMIIEnable(emacBase);
182
183         phylink = MDIOPhyLinkStatusGet(mdioBase);
184         if (!phylink)
185                 rpp_sci_printf("PHY link down\r\n");
186         else
187                 rpp_sci_printf("PHY link up\r\n");
188
189
190         /* TX */
191         for (j = 0; j < 8; j++) {
192                 fr1.pNext = NULL;
193                 fr1.pBuffer = (uint8_t*)&efr1;
194                 fr1.BufOffLen = 65;
195                 fr1.PktFlgLen = (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_EOP | EMAC_DSC_FLAG_OWNER | 65);
196
197                 EMACTxHdrDescPtrWrite(emacBase, (unsigned int)&fr1, channel);
198                 rpp_sci_printf("Packet sent\r\n");
199                 while(fr1.PktFlgLen == EMAC_DSC_FLAG_OWNER){
200                         if(rpp_sci_read_nb(1, &input) == SUCCESS){
201                                 return -1;
202                         }
203                 }
204                 dummy_wait();
205                 intvect = EMACIntVectorGet(emacBase);
206                 intvectraw = EMACIntVectorRawGet(emacBase);
207         }
208
209         /* Dummy RX */
210         {
211                 char rx_fr[10];
212                 int i;
213
214                 rpp_sci_printf("Trying to receive some data\r\n");
215                 EMACRxIntPulseEnable(emacBase, emacCtrlBase, 0, channel);
216
217                 for (j = 0; j < 8; j++) {
218                         while (!(rx_desc->PktFlgLen & EMAC_DSC_FLAG_SOP))
219                                 if(rpp_sci_read_nb(1, &input) == SUCCESS){
220                                         return -1;
221                                 }
222                                 ;
223
224                         rpp_sci_printf("Received packet:\r\n");
225                         rpp_sci_printf("Length: %d\r\n", rx_desc->PktFlgLen & 0xffff);
226
227                         for (i = 0; i < (rx_desc->PktFlgLen & 0xffff); i++) {
228                                 i2str(rx_fr, rx_desc->pBuffer[i], 0, 16);
229                                 rpp_sci_printf("%x ", rx_desc->pBuffer[i]);
230                                 if (((i+1) % 8) == 0)
231                                         rpp_sci_printf("\r\n");
232                         }
233
234                         /* Reinitialize RX buffer */
235                         rx_desc->pBuffer = rx_buff;
236                         rx_desc->PktFlgLen = EMAC_DSC_FLAG_OWNER;
237                         rx_desc->pNext = NULL;
238                         rx_desc->BufOffLen = BUFF_SIZE;
239                         EMACRxHdrDescPtrWrite(emacBase, (unsigned int)rx_desc, channel);
240                         rpp_sci_printf("\r\n-------------------------------------------\r\n");
241                 }
242
243                 EMACRxIntPulseDisable(emacBase, emacCtrlBase, 0, channel);
244         }
245
246
247
248         return 0;
249 }
250
251 #endif  /* DOCGEN */
252
253 cmd_des_t const cmd_des_test_ethernet={
254     0, 0,
255     "ethernet", "Temporary command to test Ethernet communication",
256     "=== Command syntax ===\n"
257     "\n"
258     "   ethernet\n"
259     "\n"
260     "=== Description ===\n"
261     "\n"
262     "Command tries to send a few ethernet frames. No real connection or\n"
263     "meaningful packets are sent. This only tests, if Ethernet is just\n"
264     "working.\n",
265     CMD_HANDLER(emac_test), (void *)&cmd_list_emac
266 };
267
268 cmd_des_t const *cmd_list_emac[]={
269   &cmd_des_test_ethernet,
270   NULL
271 };