OpenCores
URL https://opencores.org/ocsvn/adv_debug_sys/adv_debug_sys/trunk

Subversion Repositories adv_debug_sys

[/] [adv_debug_sys/] [trunk/] [Software/] [AdvancedWatchpointControl/] [src/] [advancedWatchpointControl/] [rspCoder.java] - Blame information for rev 54

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 54 nyawn
////////////////////////////////////////////////////////////////
2
//
3
// rspCoder.java
4
//
5
// Copyright (C) 2010 Nathan Yawn 
6
//                    (nyawn@opencores.org)
7
//
8
// This class handles formatting, escaping, and checksumming
9
// for packets sent to and received from the network layer.
10
//
11
////////////////////////////////////////////////////////////////
12
//
13
// This source file may be used and distributed without
14
// restriction provided that this copyright statement is not
15
// removed from the file and that any derivative work contains
16
// the original copyright notice and the associated disclaimer.
17
// 
18
// This source file is free software; you can redistribute it
19
// and/or modify it under the terms of the GNU General
20
// Public License as published by the Free Software Foundation;
21
// either version 3.0 of the License, or (at your option) any
22
// later version.
23
//
24
// This source is distributed in the hope that it will be
25
// useful, but WITHOUT ANY WARRANTY; without even the implied 
26
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
27
// PURPOSE.  See the GNU Lesser General Public License for more
28
// details.
29
// 
30
// You should have received a copy of the GNU General
31
// Public License along with this source; if not, download it 
32
// from http://www.gnu.org/licenses/gpl.html
33
//
34
////////////////////////////////////////////////////////////////
35 51 nyawn
package advancedWatchpointControl;
36
 
37
import java.io.IOException;
38
 
39
 
40
public class rspCoder {
41
 
42
 
43
 
44
        public enum rcvStateType { WAITING_FOR_START, RECEIVING_DATA, RECEIVING_CSUM1,
45
                RECEIVING_CSUM2, FINISHED }
46
 
47
        private networkSystem netSys = null;
48
        private rcvStateType rcvState = rcvStateType.WAITING_FOR_START;
49
        private StringBuilder rcvPacketStringBuilder = null;
50
 
51
        public rspCoder(networkSystem ns) {
52
                rcvPacketStringBuilder = new StringBuilder();
53
                netSys = ns;
54
        }
55
 
56
        public void Transact(TargetTransaction t) throws IOException {
57
                int retries_remaining = 3;
58
                int rcvchar;
59
                boolean ret = false;
60
 
61
                // Send the packet and look for an RSP ack ("+")
62
                do {
63
                        escapePacketAndSend(t.getDataToSend());
64
                        rcvchar = netSys.getChar(); // Get +/-
65
                        // If -, retry up to 3 times
66
                } while((rcvchar != '+') && ((retries_remaining--) >= 0));
67
 
68
                if(retries_remaining < 0) {
69
                        throw new IOException("Retries exceeded sending data");
70
                }
71
 
72
                retries_remaining = 3;
73
 
74
                do {
75
                        ret = false;
76
                        // Get one complete packet
77
                        String dataPacket = getDataPacket();
78
                        // Unescape, un-RLE, and test the checksum.  Returns null if bad checksum
79
                        String decodedPacket = decodeRSPPacket(dataPacket);
80
                        if(decodedPacket != null) {
81
                                // Let the transaction object parse the specific packet type
82
                                ret = t.receivePacket(decodedPacket);
83
                        }
84
                        if(!ret) {
85
                                sendNak();
86
                        }
87
 
88
                } while ((!ret)&& ((retries_remaining--) >= 0));
89
 
90
                if(retries_remaining < 0) {
91
                        throw new IOException("Retries exceeded parsing data");
92
                }
93
 
94
                sendAck();
95
 
96
        }  // Transact()
97
 
98
 
99
        private boolean escapePacketAndSend(String packetString) {
100
                //System.out.println("Sending packet: \"" + packetString + "\"");
101
                String protocolString = new String("$");
102
 
103
                // Escape the packet data.  '}' is 0x7d, the escape char.
104
                // Escaped char must be XOR'd with 0x20.
105
                packetString.replace("}", "}"+('}'^0x20));  // This must be escaped first!
106
                packetString.replace("#", "}"+('#'^0x20));  // '#' is 0x23
107
                packetString.replace("$", "}"+('$'^0x20));  // '$' is 0x24
108
 
109
                // Add the packet data
110
                protocolString += packetString;
111
 
112
                // Add the separator
113
                protocolString += "#";
114
 
115
                // Create the checksum (from packetString, not protocolString)
116
                int checksum = getChecksum(packetString);
117
 
118
                // Add the checksum
119
                if(checksum < 0x10)
120
                        protocolString += "0";
121
                protocolString += Integer.toHexString(checksum);
122
 
123
                // Send it.
124
                return netSys.sendData(protocolString);
125
        }
126
 
127
 
128
        // This reads one complete data packet from the network, including checksum
129
        public String getDataPacket() throws IOException {
130
                int rcvChar;
131
                rcvState = rcvStateType.WAITING_FOR_START;
132
 
133
                do {
134
                        rcvChar = netSys.getChar();
135
                        //System.out.println("parseData: " + rcvChar);
136
                        switch(rcvState) {
137
                                case WAITING_FOR_START:
138
                                        if(rcvChar == '$') {
139
                                                // discard the '$' character
140
                                                rcvState = rcvStateType.RECEIVING_DATA;
141
                                                rcvPacketStringBuilder = new StringBuilder();
142
                                        }
143
                                        break;
144
                                case RECEIVING_DATA:
145
                                        if(rcvChar == '#') {
146
                                                rcvState = rcvStateType.RECEIVING_CSUM1;
147
                                        }
148
                                        rcvPacketStringBuilder.append((char)rcvChar);
149
                                        break;
150
                                case RECEIVING_CSUM1:
151
                                        rcvPacketStringBuilder.append((char)rcvChar);
152
                                        rcvState = rcvStateType.RECEIVING_CSUM2;
153
                                        break;
154
                                case RECEIVING_CSUM2:
155
                                        rcvPacketStringBuilder.append((char)rcvChar);
156
                                        rcvState = rcvStateType.FINISHED;
157
                                        break;
158
                        }
159
                } while(rcvState != rcvStateType.FINISHED);
160
 
161
                return rcvPacketStringBuilder.toString();
162
        }  // parseData()
163
 
164
 
165
        // This looks like it modifies the input String.  But since a String
166
        // is actually constant, a new String object should be created each
167
        // time we "modify" the String, so the original input parameter
168
        // should remain intact.
169
        private String decodeRSPPacket(String packet) {
170
 
171
                //System.out.println("Parsing packet: \"" + packet + "\"\n");
172
 
173
                // Test the checksum
174
                int checksum = 0;
175
                try {
176
                        //System.out.println("Checksum substring: " + packet.substring(packet.length()-2));
177
                        checksum = Integer.parseInt(packet.substring(packet.length()-2), 16);
178
                } catch (NumberFormatException e) {
179
                        // TODO Log the error
180
                        sendNak();
181
                        System.out.println("Got bad checksum: calculated " + getChecksum(packet) + ", read " + checksum);
182
                        return null;
183
                }
184
                // Cut off the '#' and checksum
185
                packet = packet.substring(0, packet.length()-3);
186
 
187
                if(checksum != getChecksum(packet)) {
188
                        // TODO Log the error
189
                        sendNak();
190
                        System.out.println("Got bad checksum: calculated " + getChecksum(packet) + ", read " + checksum);
191
                        return null;
192
                }
193
 
194
                // Un-escape
195
                packet.replace("}"+('#'^0x20), "#");
196
                packet.replace("}"+('$'^0x20), "$");
197
                packet.replace("}"+('}'^0x20), "}");
198
 
199
                // Undo any run-length encoding.  This code is so ugly.
200
                if(packet.indexOf("*") != -1) {
201
                        StringBuffer sb = new StringBuffer(packet);
202
                        int thisIndex = 0;
203
                        int lastIndex = 0;
204
 
205
                        while(-1 != (thisIndex = sb.indexOf("*", lastIndex))) {
206
                                int runlength = sb.charAt(thisIndex+1) - 28;
207
                                sb.deleteCharAt(thisIndex+1);
208
                                sb.deleteCharAt(thisIndex);
209
                                char c = sb.charAt(thisIndex-1);
210
                                for(int i = 0; i < runlength; i++) {
211
                                        sb.insert(thisIndex, c);
212
                                }
213
                                lastIndex = thisIndex;
214
                        }
215
 
216
                        packet = sb.toString();
217
                }
218
 
219
                return packet;
220
        }  // handleRSPPacket()
221
 
222
 
223
        public void sendAck() {
224
                netSys.sendData("+");
225
        }
226
 
227
        public void sendNak() {
228
                netSys.sendData("-");
229
        }
230
 
231
 
232
        private int getChecksum(String packet) {
233
                int csum = 0;
234
                for(int i = 0; i < packet.length(); i++) {
235
                        csum += packet.charAt(i);
236
                        //System.out.println("checksum adding char: " + packet.charAt(i) + ", checksum " + csum);
237
                }
238
                csum = csum & 0xFF;
239
                //System.out.println("Final checksum: " + csum);
240
                return csum;
241
        }
242
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.