mips32: Added CP0 coprocessor R/W routines
[fw/openocd] / src / target / target.c
index 93efa762f14d5327797a6ba64c0d9eefd93c56e4..03431560f57cd89724937794aa749a93ffef17a6 100644 (file)
  *   Copyright (C) 2008 by Rick Altherr                                    *
  *   kc8apf@kc8apf.net>                                                    *
  *                                                                         *
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   Copyright (C) ST-Ericsson SA 2011                                     *
+ *   michel.jaouen@stericsson.com : smp minimum support                    *
+ *                                                                         *
  *   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     *
 #include "register.h"
 #include "trace.h"
 #include "image.h"
+#include "rtos/rtos.h"
 
 
+static int target_read_buffer_default(struct target *target, uint32_t address,
+               uint32_t size, uint8_t *buffer);
+static int target_write_buffer_default(struct target *target, uint32_t address,
+               uint32_t size, const uint8_t *buffer);
 static int target_array2mem(Jim_Interp *interp, struct target *target,
                int argc, Jim_Obj *const *argv);
 static int target_mem2array(Jim_Interp *interp, struct target *target,
@@ -70,6 +81,7 @@ extern struct target_type arm11_target;
 extern struct target_type mips_m4k_target;
 extern struct target_type avr_target;
 extern struct target_type dsp563xx_target;
+extern struct target_type dsp5680xx_target;
 extern struct target_type testee_target;
 extern struct target_type avr32_ap7k_target;
 
@@ -92,6 +104,7 @@ static struct target_type *target_types[] =
        &mips_m4k_target,
        &avr_target,
        &dsp563xx_target,
+       &dsp5680xx_target,
        &testee_target,
        &avr32_ap7k_target,
        NULL,
@@ -278,6 +291,15 @@ uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer)
                return be_to_h_u32(buffer);
 }
 
+/* read a uint24_t from a buffer in target memory endianness */
+uint32_t target_buffer_get_u24(struct target *target, const uint8_t *buffer)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               return le_to_h_u24(buffer);
+       else
+               return be_to_h_u24(buffer);
+}
+
 /* read a uint16_t from a buffer in target memory endianness */
 uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer)
 {
@@ -302,6 +324,15 @@ void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t valu
                h_u32_to_be(buffer, value);
 }
 
+/* write a uint24_t to a buffer in target memory endianness */
+void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t value)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               h_u24_to_le(buffer, value);
+       else
+               h_u24_to_be(buffer, value);
+}
+
 /* write a uint16_t to a buffer in target memory endianness */
 void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value)
 {
@@ -593,7 +624,7 @@ const char *target_type_name(struct target *target)
        return target->type->name;
 }
 
-static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        if (!target_was_examined(target))
        {
@@ -683,19 +714,19 @@ static int target_read_phys_memory(struct target *target,
 }
 
 int target_write_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        return target->type->write_memory(target, address, size, count, buffer);
 }
 
 static int target_write_phys_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        return target->type->write_phys_memory(target, address, size, count, buffer);
 }
 
 int target_bulk_write_memory(struct target *target,
-               uint32_t address, uint32_t count, uint8_t *buffer)
+               uint32_t address, uint32_t count, const uint8_t *buffer)
 {
        return target->type->bulk_write_memory(target, address, count, buffer);
 }
@@ -703,7 +734,7 @@ int target_bulk_write_memory(struct target *target,
 int target_add_breakpoint(struct target *target,
                struct breakpoint *breakpoint)
 {
-       if (target->state != TARGET_HALTED) {
+       if ((target->state != TARGET_HALTED)&&(breakpoint->type!=BKPT_HARD)) {
                LOG_WARNING("target %s is not halted", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
@@ -761,7 +792,7 @@ err_read_phys_memory(struct target *target, uint32_t address,
 
 static int
 err_write_phys_memory(struct target *target, uint32_t address,
-               uint32_t size, uint32_t count, uint8_t *buffer)
+               uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        LOG_ERROR("Not implemented: %s", __func__);
        return ERROR_FAIL;
@@ -845,6 +876,13 @@ static int target_init_one(struct command_context *cmd_ctx,
                type->read_phys_memory = type->read_memory;
                type->virt2phys = identity_virt2phys;
        }
+
+       if (target->type->read_buffer == NULL)
+               target->type->read_buffer = target_read_buffer_default;
+
+       if (target->type->write_buffer == NULL)
+               target->type->write_buffer = target_write_buffer_default;
+
        return ERROR_OK;
 }
 
@@ -1213,7 +1251,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w
        }
 
        /* mark as used, and return the new (reused) area */
-       new_wa->free = 0;
+       new_wa->free = false;
        *area = new_wa;
 
        /* user pointer */
@@ -1247,7 +1285,7 @@ static int target_free_working_area_restore(struct target *target, struct workin
                        return retval;
        }
 
-       area->free = 1;
+       area->free = true;
 
        /* mark user pointer invalid */
        *area->user = NULL;
@@ -1311,9 +1349,8 @@ int target_arch_state(struct target *target)
  * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_write_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
+int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer)
 {
-       int retval;
        LOG_DEBUG("writing buffer of %i byte at 0x%8.8x",
                  (int)size, (unsigned)address);
 
@@ -1336,6 +1373,13 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
                return ERROR_FAIL;
        }
 
+       return target->type->write_buffer(target, address, size, buffer);
+}
+
+static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer)
+{
+       int retval = ERROR_OK;
+
        if (((address % 2) == 0) && (size == 2))
        {
                return target_write_memory(target, address, 2, 1, buffer);
@@ -1386,7 +1430,7 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
                        return retval;
        }
 
-       return ERROR_OK;
+       return retval;
 }
 
 /* Single aligned words are guaranteed to use 16 or 32 bit access
@@ -1395,7 +1439,6 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
  */
 int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
 {
-       int retval;
        LOG_DEBUG("reading buffer of %i byte at 0x%8.8x",
                          (int)size, (unsigned)address);
 
@@ -1418,6 +1461,13 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u
                return ERROR_FAIL;
        }
 
+       return target->type->read_buffer(target, address, size, buffer);
+}
+
+static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
+{
+       int retval = ERROR_OK;
+
        if (((address % 2) == 0) && (size == 2))
        {
                return target_read_memory(target, address, 2, 1, buffer);
@@ -1502,7 +1552,7 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz
                        return retval;
                }
 
-               /* convert to target endianess */
+               /* convert to target endianness */
                for (i = 0; i < (size/sizeof(uint32_t)); i++)
                {
                        uint32_t target_data;
@@ -2314,7 +2364,7 @@ COMMAND_HANDLER(handle_md_command)
 
        bool physical=strcmp(CMD_ARGV[0], "phys")==0;
        int (*fn)(struct target *target,
-                       uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
+                       uint32_t address, uint32_t size_value, uint32_t count, uint8_t *buffer);
        if (physical)
        {
                CMD_ARGC--;
@@ -2349,10 +2399,10 @@ COMMAND_HANDLER(handle_md_command)
 }
 
 typedef int (*target_write_fn)(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
+               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
 
 static int target_write_memory_fast(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        return target_write_buffer(target, address, size * count, buffer);
 }
@@ -3077,7 +3127,7 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam
 
        int addressSpace = (max-min + 1);
 
-       static const uint32_t maxBuckets = 256 * 1024; /* maximum buckets. */
+       static const uint32_t maxBuckets = 16 * 1024; /* maximum buckets. */
        uint32_t length = addressSpace;
        if (length > maxBuckets)
        {
@@ -3104,7 +3154,7 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam
        writeLong(f, min);                      /* low_pc */
        writeLong(f, max);                      /* high_pc */
        writeLong(f, length);           /* # of samples */
-       writeLong(f, 64000000);         /* 64MHz */
+       writeLong(f, 100);                      /* KLUDGE! We lie, ca. 100Hz best case. */
        writeString(f, "seconds");
        for (i = 0; i < (15-strlen("seconds")); i++)
                writeData(f, &zero, 1);
@@ -3660,7 +3710,10 @@ enum target_cfg_param {
        TCFG_WORK_AREA_BACKUP,
        TCFG_ENDIAN,
        TCFG_VARIANT,
+       TCFG_COREID,
        TCFG_CHAIN_POSITION,
+       TCFG_DBGBASE,
+       TCFG_RTOS,
 };
 
 static Jim_Nvp nvp_config_opts[] = {
@@ -3672,8 +3725,10 @@ static Jim_Nvp nvp_config_opts[] = {
        { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP },
        { .name = "-endian" ,          .value = TCFG_ENDIAN },
        { .name = "-variant",          .value = TCFG_VARIANT },
+       { .name = "-coreid",           .value = TCFG_COREID },
        { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
-
+       { .name = "-dbgbase",          .value = TCFG_DBGBASE },
+       { .name = "-rtos",             .value = TCFG_RTOS },
        { .name = NULL, .value = -1 }
 };
 
@@ -3881,6 +3936,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        /* loop for more e*/
                        break;
 
+
                case TCFG_ENDIAN:
                        if (goi->isconfigure) {
                                e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n);
@@ -3924,6 +3980,23 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        Jim_SetResultString(goi->interp, target->variant,-1);
                        /* loop for more */
                        break;
+
+               case TCFG_COREID:
+                       if (goi->isconfigure) {
+                               e = Jim_GetOpt_Wide(goi, &w);
+                               if (e != JIM_OK) {
+                                       return e;
+                               }
+                               target->coreid = (int32_t)w;
+                       } else {
+                               if (goi->argc != 0) {
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size));
+                       /* loop for more */
+                       break;
+
                case TCFG_CHAIN_POSITION:
                        if (goi->isconfigure) {
                                Jim_Obj *o_t;
@@ -3947,6 +4020,34 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        Jim_SetResultString(goi->interp, target->tap->dotted_name, -1);
                        /* loop for more e*/
                        break;
+               case TCFG_DBGBASE:
+                       if (goi->isconfigure) {
+                               e = Jim_GetOpt_Wide(goi, &w);
+                               if (e != JIM_OK) {
+                                       return e;
+                               }
+                               target->dbgbase = (uint32_t)w;
+                               target->dbgbase_set = true;
+                       } else {
+                               if (goi->argc != 0) {
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
+                       /* loop for more */
+                       break;
+
+               case TCFG_RTOS:
+                       /* RTOS */
+                       {
+                               int result = rtos_create( goi, target );
+                               if ( result != JIM_OK )
+                               {
+                                       return result;
+                               }
+                       }
+                       /* loop for more */
+                       break;
                }
        } /* while (goi->argc) */
 
@@ -4221,9 +4322,6 @@ static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv
        int e = target->type->examine(target);
        if (e != ERROR_OK)
        {
-               Jim_Obj *eObj = Jim_NewIntObj(interp, e);
-               Jim_SetResultFormatted(interp, "examine-fails: %#s", eObj);
-               Jim_FreeNewObj(interp, eObj);
                return JIM_ERR;
        }
        return JIM_OK;
@@ -4263,9 +4361,6 @@ static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        }
        if (e != ERROR_OK)
        {
-               Jim_Obj *eObj = Jim_NewIntObj(interp, e);
-               Jim_SetResultFormatted(interp, "poll-fails: %#s", eObj);
-               Jim_FreeNewObj(interp, eObj);
                return JIM_ERR;
        }
        return JIM_OK;
@@ -4640,6 +4735,9 @@ static int target_create(Jim_GetOptInfo *goi)
        /* will be set by "-endian" */
        target->endianness = TARGET_ENDIAN_UNKNOWN;
 
+       /* default to first core, override with -coreid */
+       target->coreid = 0;
+
        target->working_area        = 0x0;
        target->working_area_size   = 0x0;
        target->working_areas       = NULL;
@@ -4672,6 +4770,9 @@ static int target_create(Jim_GetOptInfo *goi)
 
        target->endianness = TARGET_ENDIAN_UNKNOWN;
 
+       target->rtos = NULL;
+       target->rtos_auto_detect = false;
+
        /* Do the rest as "configure" options */
        goi->isconfigure = 1;
        e = target_configure(goi, target);
@@ -4798,6 +4899,61 @@ static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        return JIM_OK;
 }
 
+static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       int i;
+       const char *targetname;
+       int retval,len;
+       struct target *target;
+       struct target_list *head, *curr, *new;
+    curr = (struct target_list*) NULL;
+       head = (struct target_list*) NULL;
+       new = (struct target_list*) NULL;
+
+       retval = 0;
+       LOG_DEBUG("%d",argc);
+       /* argv[1] = target to associate in smp
+        * argv[2] = target to assoicate in smp 
+        * argv[3] ...
+        */
+
+       for(i=1;i<argc;i++)
+       {
+
+               targetname = Jim_GetString(argv[i], &len);
+               target = get_target(targetname);
+               LOG_DEBUG("%s ",targetname);
+               if (target)
+               {
+                       new=malloc(sizeof(struct target_list));
+                       new->target = target;
+                       new->next = (struct target_list*)NULL;
+                       if (head == (struct target_list*)NULL)
+                       {
+                               head = new;
+                               curr = head;
+                       }
+                       else
+                       {
+                               curr->next = new;
+                               curr = new;
+                       }
+               }
+       }
+    /*  now parse the list of cpu and put the target in smp mode*/
+       curr=head;
+
+    while(curr!=(struct target_list *)NULL)
+       {
+    target=curr->target;
+       target->smp = 1;
+       target->head = head;
+       curr=curr->next;
+       }
+       return retval; 
+}
+
+
 static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        Jim_GetOptInfo goi;
@@ -4913,6 +5069,14 @@ static const struct command_registration target_subcommand_handlers[] = {
                .help = "Returns the number of targets as an integer "
                        "(DEPRECATED)",
        },
+       {
+               .name = "smp",
+               .mode = COMMAND_ANY,
+               .jim_handler = jim_target_smp,
+               .usage = "targetname1 targetname2 ...",
+               .help = "gather several target in a smp list"
+       },
+
        COMMAND_REGISTRATION_DONE
 };