4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 simavr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with simavr. If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/in.h>
23 #include <netinet/tcp.h>
24 #include <arpa/inet.h>
25 #include <sys/socket.h>
35 #include "avr_eeprom.h"
37 typedef struct avr_gdb_t {
39 int listen; // listen socket
40 int s; // current gdb connection
55 // decode line text hex to binary
56 int read_hex_string(const char * src, uint8_t * buffer, int maxlen)
58 uint8_t * dst = buffer;
61 while (*src && maxlen--) {
64 case 'a' ... 'f': b = (b << 4) | (c - 'a' + 0xa); break;
65 case 'A' ... 'F': b = (b << 4) | (c - 'A' + 0xa); break;
66 case '0' ... '9': b = (b << 4) | (c - '0'); break;
69 fprintf(stderr, "%s: huh '%c' (%s)\n", __FUNCTION__, c, src);
83 static void gdb_send_reply(avr_gdb_t * g, char * cmd)
86 uint8_t * dst = reply;
93 sprintf((char*)dst, "#%02x", check);
94 printf("%s '%s'\n", __FUNCTION__, reply);
95 send(g->s, reply, dst - reply + 3, 0);
98 static void gdb_send_quick_status(avr_gdb_t * g, uint8_t signal)
102 sprintf(cmd, "T%02x20:%02x;21:%02x%02x;22:%02x%02x%02x00;",
103 signal, g->avr->data[R_SREG],
104 g->avr->data[R_SPL], g->avr->data[R_SPH],
105 g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
106 gdb_send_reply(g, cmd);
109 static int gdb_change_breakpoint(avr_gdb_t * g, int set, int kind, uint32_t addr, uint32_t len)
111 printf("set %d kind %d addr %08x len %d (map %08x)\n", set, kind, addr, len, g->watchmap);
113 if (g->watchmap == 0xffffffff)
114 return -1; // map full
116 // check to see if it exists
117 for (int i = 0; i < 32; i++)
118 if ((g->watchmap & (1 << i)) && g->watch[i].pc == addr) {
119 g->watch[i].len = len;
122 for (int i = 0; i < 32; i++)
123 if (!(g->watchmap & (1 << i))) {
124 g->watchmap |= (1 << i);
125 g->watch[i].len = len;
126 g->watch[i].pc = addr;
127 g->watch[i].kind = kind;
131 for (int i = 0; i < 32; i++)
132 if ((g->watchmap & (1 << i)) && g->watch[i].pc == addr) {
133 g->watchmap &= ~(1 << i);
136 g->watch[i].kind = 0;
143 static void gdb_handle_command(avr_gdb_t * g)
145 avr_t * avr = g->avr;
146 char * cmd = g->query;
148 uint8_t command = *cmd++;
151 gdb_send_reply(g, "S00");
154 unsigned int regi = 0;
155 sscanf(cmd, "%x", ®i);
158 sprintf(rep, "%02x", g->avr->data[regi]);
161 sprintf(rep, "%02x", g->avr->data[R_SREG]);
164 sprintf(rep, "%02x%02x", g->avr->data[R_SPL], g->avr->data[R_SPH]);
167 sprintf(rep, "%02x%02x%02x00",
168 g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
171 gdb_send_reply(g, rep);
175 sscanf(cmd, "%x,%x", &addr, &len);
176 printf("read memory %08x, %08x\n", addr, len);
177 uint8_t * src = NULL;
179 src = avr->flash + addr;
180 } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) {
181 src = avr->data + addr - 0x800000;
182 } else if (addr >= 0x810000 && (addr - 0x810000) <= (16*1024)) {
183 avr_eeprom_desc_t ee = {.offset = (addr - 0x810000)};
184 avr_ioctl(avr, AVR_IOCTL_EEPROM_GET, &ee);
188 gdb_send_reply(g, "E01");
190 gdb_send_reply(g, "E01");
195 sprintf(dst, "%02x", *src++);
199 gdb_send_reply(g, rep);
203 sscanf(cmd, "%x,%x", &addr, &len);
204 printf("write memory %08x, %08x\n", addr, len);
205 char * start = strchr(cmd, ':');
207 gdb_send_reply(g, "E01");
211 read_hex_string(start + 1, avr->flash + addr, strlen(start+1));
212 gdb_send_reply(g, "OK");
213 } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) {
214 read_hex_string(start + 1, avr->data + addr - 0x800000, strlen(start+1));
215 gdb_send_reply(g, "OK");
217 gdb_send_reply(g, "E01");
220 avr->state = cpu_Running;
223 avr->state = cpu_Step;
227 uint32_t kind, addr, len;
228 sscanf(cmd, "%d,%x,%x", &kind, &addr, &len);
229 printf("breakbpoint %d, %08x, %08x\n", kind, addr, len);
231 case 0: // software breakpoint
232 case 1: // hardware breakpoint
233 if (addr <= avr->flashend) {
234 if (gdb_change_breakpoint(g, command == 'Z', kind, addr, len))
235 gdb_send_reply(g, "E01");
237 gdb_send_reply(g, "OK");
239 gdb_send_reply(g, "E01"); // out of flash address
241 case 2: // write watchpoint
242 case 3: // read watchpoint
243 case 4: // access watchpoint
245 gdb_send_reply(g, "");
249 gdb_send_reply(g, "");
253 void avr_gdb_processor(avr_t * avr)
255 if (!avr || !avr->gdb)
257 avr_gdb_t * g = avr->gdb;
259 if (g->watchmap && avr->state == cpu_Running) {
260 for (int i = 0; i < 32; i++)
261 if ((g->watchmap & (1 << i)) && g->watch[i].pc == avr->pc) {
262 printf("avr_gdb_processor hit breakpoint at %08x\n", avr->pc);
263 gdb_send_quick_status(g, 0);
264 avr->state = cpu_Stopped;
267 if (avr->state == cpu_StepDone) {
268 gdb_send_quick_status(g, 0);
269 avr->state = cpu_Stopped;
271 if (avr->gdb->query_len) {
274 // printf("avr_gdb_handle_query got a query '%s'\n", g->query);
275 gdb_handle_command(g);
280 static void * gdb_network_handler(void * param)
282 avr_gdb_t * g = (avr_gdb_t*)param;
285 if (listen(g->listen, 1)) {
286 perror("gdb_network_handler listen");
291 struct sockaddr_in address = { 0 };
292 socklen_t ad_len = sizeof(address);
294 g->s = accept(g->listen, (struct sockaddr*)&address, &ad_len);
297 perror("gdb_network_handler accept");
301 // should make that thread safe...
302 g->avr->state = cpu_Stopped;
307 FD_SET(g->s, &read_set);
309 struct timeval timo = { 1, 0000 }; // short, but not too short interval
310 /*int ret =*/ select(g->s + 1, &read_set, NULL, NULL, &timo);
312 if (FD_ISSET(g->s, &read_set)) {
313 uint8_t buffer[1024];
315 ssize_t r = recv(g->s, buffer, sizeof(buffer)-1, 0);
318 printf("%s connection closed\n", __FUNCTION__);
322 perror("gdb_network_handler recv");
326 // printf("%s: received %d bytes\n'%s'\n", __FUNCTION__, r, buffer);
327 // hdump("gdb", buffer, r);
329 uint8_t * src = buffer;
330 while (*src == '+' || *src == '-')
335 g->query_len = 1; // pass it on ?
339 uint8_t * end = buffer + r - 1;
340 while (end > src && *end != '#')
344 printf("GDB command = '%s'\n", src);
346 send(g->s, "+", 1, 0);
348 strcpy(g->query, (char*)src);
349 g->query_len = strlen((char*)src);
362 int avr_gdb_init(avr_t * avr)
364 avr_gdb_t * g = malloc(sizeof(avr_gdb_t));
365 memset(g, 0, sizeof(avr_gdb_t));
369 if ((g->listen = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
370 fprintf(stderr, "Can't create socket: %s", strerror(errno));
375 setsockopt(g->listen, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
377 struct sockaddr_in address = { 0 };
378 address.sin_family = AF_INET;
379 address.sin_port = htons (1234);
381 if (bind(g->listen, (struct sockaddr *) &address, sizeof(address))) {
382 fprintf(stderr, "Can not bind socket: %s", strerror(errno));
385 printf("avr_gdb_init listening on port %d\n", 1234);
389 pthread_create(&g->thread, NULL, gdb_network_handler, g);