Duane Ellis: fix warnings
[fw/openocd] / src / server / gdb_server.c
index 6018cd44e3e9c2f9b8f27a4be566523354ca55be..629995388f7119386f1ec1825beb93b9bcfce384 100644 (file)
@@ -2,6 +2,9 @@
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
+ *   Copyright (C) 2007,2008 Ã˜yvind Harboe                                      *
+ *   oyvind.harboe@zylin.com                                               *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
@@ -287,7 +290,6 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
         * however sometimes '-' is sent even though we've already received
         * an ACK (+) for everything we've sent off.
         */
-#ifndef _WIN32
        int gotdata;
        for (;;)
        {
@@ -299,7 +301,6 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
                        return retval;
                LOG_WARNING("Discard unexpected char %c", reply);
        }
-#endif
 #endif
 
        while (1)
@@ -413,6 +414,8 @@ int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
                                case '$':
                                        break;
                                case '+':
+                                       /* gdb sends a dummy ack '+' at every remote connect - see remote_start_remote (remote.c)
+                                        * incase anyone tries to debug why they receive this warning every time */
                                        LOG_WARNING("acknowledgment received, but no packet pending");
                                        break;
                                case '-':
@@ -568,7 +571,7 @@ int gdb_output_con(connection_t *connection, const char* line)
        return ERROR_OK;
 }
 
-int gdb_output(struct command_context_s *context, char* line)
+int gdb_output(struct command_context_s *context, const char* line)
 {
        /* this will be dumped to the log and also sent as an O packet if possible */
        LOG_USER_N("%s", line);
@@ -577,24 +580,10 @@ int gdb_output(struct command_context_s *context, char* line)
 
 int gdb_program_handler(struct target_s *target, enum target_event event, void *priv)
 {
-       FILE *script;
        struct command_context_s *cmd_ctx = priv;
 
-       if (target->gdb_program_script)
-       {
-               script = open_file_from_path(target->gdb_program_script, "r");
-               if (!script)
-               {
-                       LOG_ERROR("couldn't open script file %s", target->gdb_program_script);
-                               return ERROR_OK;
-               }
-
-               LOG_INFO("executing gdb_program script '%s'", target->gdb_program_script);
-               command_run_file(cmd_ctx, script, COMMAND_EXEC);
-               fclose(script);
-
-               jtag_execute_queue();
-       }
+       target_invoke_script(cmd_ctx, target, "gdb_program");
+       jtag_execute_queue();
 
        return ERROR_OK;
 }
@@ -693,6 +682,12 @@ int gdb_new_connection(connection_t *connection)
         * connect. 
         */
        target_halt(gdb_service->target);
+       /* FIX!!!! could extended-remote work better here?
+        * 
+        *  wait a tiny bit for halted state or we just continue. The
+        * GDB register packet will then contain garbage 
+        */
+       target_wait_state(gdb_service->target, TARGET_HALTED, 500);
        
        /* remove the initial ACK from the incoming buffer */
        if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK)
@@ -1233,6 +1228,7 @@ void gdb_step_continue_packet(connection_t *connection, target_t *target, char *
        if (packet[0] == 'c')
        {
                LOG_DEBUG("continue");
+               target_invoke_script(connection->cmd_ctx, target, "pre_resume");
                target_resume(target, current, address, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
        }
        else if (packet[0] == 's')
@@ -1419,6 +1415,24 @@ int gdb_calc_blocksize(flash_bank_t *bank)
        return block_size;
 }
 
+static int compare_bank (const void * a, const void * b)
+{
+       flash_bank_t *b1, *b2;
+       b1=*((flash_bank_t **)a);
+       b2=*((flash_bank_t **)b);
+       
+       if (b1->base==b2->base)
+       {
+               return 0;
+       } else if (b1->base>b2->base)
+       {
+               return 1;
+       } else
+       {
+               return -1;
+       }
+}
+
 int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
 {
        command_context_t *cmd_ctx = connection->cmd_ctx;
@@ -1500,7 +1514,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
 
                xml_printf(&retval, &buffer, &pos, &size,
                                "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-",
-                               (GDB_BUFFER_SIZE - 1), gdb_use_memory_map == 1 ? '+' : '-');
+                               (GDB_BUFFER_SIZE - 1), ((gdb_use_memory_map == 1)&&(flash_get_bank_count()>0)) ? '+' : '-');
 
                if (retval != ERROR_OK)
                {
@@ -1513,7 +1527,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
 
                return ERROR_OK;
        }
-       else if (strstr(packet, "qXfer:memory-map:read::"))
+       else if (strstr(packet, "qXfer:memory-map:read::")&&(flash_get_bank_count()>0))
        {
                /* We get away with only specifying flash here. Regions that are not
                 * specified are treated as if we provided no memory map(if not we
@@ -1539,23 +1553,63 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                length = strtoul(separator + 1, &separator, 16);
 
                xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
-
+       
+               /* 
+               sort banks in ascending order, we need to make non-flash memory be ram(or rather
+               read/write) by default for GDB.
+               GDB does not have a concept of non-cacheable read/write memory.
+                */
+               flash_bank_t **banks=malloc(sizeof(flash_bank_t *)*flash_get_bank_count());
                int i;
+               
                for (i=0; i<flash_get_bank_count(); i++)
                {
                        p = get_flash_bank_by_num(i);
                        if (p == NULL)
-                               break;
-
+                       {
+                               free(banks);
+                               retval = ERROR_FAIL;
+                               gdb_send_error(connection, retval);
+                               return retval;
+                       }
+                       banks[i]=p;
+               }
+               
+               qsort(banks, flash_get_bank_count(), sizeof(flash_bank_t *), compare_bank);
+               
+               u32 ram_start=0;
+               for (i=0; i<flash_get_bank_count(); i++)
+               {
+                       p = banks[i];
+                       
+                       if (ram_start<p->base)
+                       {
+                               xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
+                                       ram_start, p->base-ram_start);
+                       }
+                       
                        /* if device has uneven sector sizes, eg. str7, lpc
                         * we pass the smallest sector size to gdb memory map */
                        blocksize = gdb_calc_blocksize(p);
-
+       
                        xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
                                "<property name=\"blocksize\">0x%x</property>\n" \
                                "</memory>\n", \
                                p->base, p->size, blocksize);
+                       ram_start=p->base+p->size;                      
                }
+               if (ram_start!=0)
+               {
+                       xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
+                               ram_start, 0-ram_start);
+               } else
+               {
+                       /* a flash chip could be at the very end of the 32 bit address space, in which case
+                       ram_start will be precisely 0 */
+               }
+               
+               free(banks);
+               banks = NULL;
 
                xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
 
@@ -1757,11 +1811,13 @@ int gdb_detach(connection_t *connection, target_t *target)
        switch( detach_mode )
        {
                case GDB_DETACH_RESUME:
+                       target_invoke_script(connection->cmd_ctx, target, "pre_resume");
                        target_resume(target, 1, 0, 1, 0);
                        break;
 
                case GDB_DETACH_RESET:
-                       target_process_reset(connection->cmd_ctx);
+                       /* FIX?? make this configurable?? */
+                       target_process_reset(connection->cmd_ctx, RESET_HALT);
                        break;
 
                case GDB_DETACH_HALT:
@@ -1792,11 +1848,14 @@ static void gdb_log_callback(void *priv, const char *file, int line,
        gdb_output_con(connection, string);
 }
 
+/* Do not allocate this on the stack */
+char gdb_packet_buffer[GDB_BUFFER_SIZE];
+
 int gdb_input_inner(connection_t *connection)
 {
        gdb_service_t *gdb_service = connection->service->priv;
        target_t *target = gdb_service->target;
-       char packet[GDB_BUFFER_SIZE];
+       char *packet=gdb_packet_buffer;
        int packet_size;
        int retval;
        gdb_connection_t *gdb_con = connection->priv;
@@ -1900,7 +1959,7 @@ int gdb_input_inner(connection_t *connection)
                                        break;
                                case 'R':
                                        /* handle extended restart packet */
-                                       target_process_reset(connection->cmd_ctx);
+                                       command_run_linef(connection->cmd_ctx, "ocd_gdb_restart %d", get_num_by_target(target));
                                        break;
                                default:
                                        /* ignore unkown packets */
@@ -1943,7 +2002,7 @@ int gdb_input(connection_t *connection)
        return ERROR_OK;
 }
 
-int gdb_init()
+int gdb_init(void)
 {
        gdb_service_t *gdb_service;
        target_t *target = targets;