ARM11: added mrc/mcr support to arm11 code.
[fw/openocd] / src / target / target.c
index 2b7d7e2c6394855510e12790fe09c8bbbba8462e..d4662f71176b09b8368a23b970a48ff8496a40f8 100644 (file)
@@ -69,6 +69,7 @@ static int handle_fast_load_image_command(struct command_context_s *cmd_ctx, cha
 static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
 static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
 static int jim_target(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
 
@@ -495,7 +496,13 @@ static int default_virt2phys(struct target_s *target, uint32_t virtual, uint32_t
 
 static int default_mmu(struct target_s *target, int *enabled)
 {
-       *enabled = 0;
+       LOG_ERROR("Not implemented.");
+       return ERROR_FAIL;
+}
+
+static int default_has_mmu(struct target_s *target, bool *has_mmu)
+{
+       *has_mmu = true;
        return ERROR_OK;
 }
 
@@ -601,11 +608,24 @@ int target_read_memory(struct target_s *target,
        return target->type->read_memory(target, address, size, count, buffer);
 }
 
+int target_read_phys_memory(struct target_s *target,
+               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       return target->type->read_phys_memory(target, address, size, count, buffer);
+}
+
 int target_write_memory(struct target_s *target,
                uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
        return target->type->write_memory(target, address, size, count, buffer);
 }
+
+int target_write_phys_memory(struct target_s *target,
+               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       return target->type->write_phys_memory(target, address, size, count, buffer);
+}
+
 int target_bulk_write_memory(struct target_s *target,
                uint32_t address, uint32_t count, uint8_t *buffer)
 {
@@ -674,6 +694,90 @@ void target_reset_examined(struct target_s *target)
 }
 
 
+
+static int default_mrc(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
+{
+       LOG_ERROR("Not implemented");
+       return ERROR_FAIL;
+}
+
+static int default_mcr(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
+{
+       LOG_ERROR("Not implemented");
+       return ERROR_FAIL;
+}
+
+static int arm_cp_check(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm)
+{
+       /* basic check */
+       if (!target_was_examined(target))
+       {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
+       if ((cpnum <0) || (cpnum > 15))
+       {
+               LOG_ERROR("Illegal co-processor %d", cpnum);
+               return ERROR_FAIL;
+       }
+
+       return ERROR_OK;
+}
+
+int target_mrc(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
+{
+       int retval;
+
+       retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return target->type->mrc(target, cpnum, op1, op2, CRn, CRm, value);
+}
+
+int target_mcr(struct target_s *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
+{
+       int retval;
+
+       retval = arm_cp_check(target, cpnum, op1, op2, CRn, CRm);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return target->type->mcr(target, cpnum, op1, op2, CRn, CRm, value);
+}
+
+static int default_read_phys_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       int retval;
+       bool mmu;
+       retval = target->type->has_mmu(target, &mmu);
+       if (retval != ERROR_OK)
+               return retval;
+       if (mmu)
+       {
+               LOG_ERROR("Not implemented");
+               return ERROR_FAIL;
+       }
+       return target_read_memory(target, address, size, count, buffer);
+}
+
+static int default_write_phys_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       int retval;
+       bool mmu;
+       retval = target->type->has_mmu(target, &mmu);
+       if (retval != ERROR_OK)
+               return retval;
+       if (mmu)
+       {
+               LOG_ERROR("Not implemented");
+               return ERROR_FAIL;
+       }
+       return target_write_memory(target, address, size, count, buffer);
+}
+
+
 int target_init(struct command_context_s *cmd_ctx)
 {
        target_t *target = all_targets;
@@ -698,7 +802,39 @@ int target_init(struct command_context_s *cmd_ctx)
                {
                        target->type->virt2phys = default_virt2phys;
                }
-               target->type->virt2phys = default_virt2phys;
+
+               if (target->type->read_phys_memory == NULL)
+               {
+                       target->type->read_phys_memory = default_read_phys_memory;
+               }
+
+               if (target->type->write_phys_memory == NULL)
+               {
+                       target->type->write_phys_memory = default_write_phys_memory;
+               }
+
+               if (target->type->mcr == NULL)
+               {
+                       target->type->mcr = default_mcr;
+               } else
+               {
+                       /* FIX! multiple targets will generally register global commands
+                        * multiple times. Only register this one if *one* of the
+                        * targets need the command. Hmm... make it a command on the
+                        * Jim Tcl target object?
+                        */
+                       register_jim(cmd_ctx, "mcr", jim_mcrmrc, "write coprocessor <cpnum> <op1> <op2> <CRn> <CRm> <value>");
+               }
+
+               if (target->type->mrc == NULL)
+               {
+                       target->type->mrc = default_mrc;
+               } else
+               {
+                       register_jim(cmd_ctx, "mrc", jim_mcrmrc, "read coprocessor <cpnum> <op1> <op2> <CRn> <CRm>");
+               }
+
+
                /* a non-invasive way(in terms of patches) to add some code that
                 * runs before the type->write/read_memory implementation
                 */
@@ -715,6 +851,10 @@ int target_init(struct command_context_s *cmd_ctx)
                {
                        target->type->mmu = default_mmu;
                }
+               if (target->type->has_mmu == NULL)
+               {
+                       target->type->has_mmu = default_has_mmu;
+               }
                target = target->next;
        }
 
@@ -956,13 +1096,29 @@ int target_alloc_working_area(struct target_s *target, uint32_t size, working_ar
                {
                        return retval;
                }
+
                if (enabled)
                {
-                       target->working_area = target->working_area_virt;
-               }
-               else
+                       if (target->working_area_phys_spec)
+                       {
+                               LOG_DEBUG("MMU disabled, using physical address for working memory 0x%08x", (unsigned)target->working_area_phys);
+                               target->working_area = target->working_area_phys;
+                       } else
+                       {
+                               LOG_ERROR("No working memory available. Specify -work-area-phys to target.");
+                               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+                       }
+               } else
                {
-                       target->working_area = target->working_area_phys;
+                       if (target->working_area_virt_spec)
+                       {
+                               LOG_DEBUG("MMU enabled, using virtual address for working memory 0x%08x", (unsigned)target->working_area_virt);
+                               target->working_area = target->working_area_virt;
+                       } else
+                       {
+                               LOG_ERROR("No working memory available. Specify -work-area-virt to target.");
+                               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+                       }
                }
        }
 
@@ -991,8 +1147,6 @@ int target_alloc_working_area(struct target_s *target, uint32_t size, working_ar
                uint32_t first_free = target->working_area;
                uint32_t free_size = target->working_area_size;
 
-               LOG_DEBUG("allocating new working area");
-
                c = target->working_areas;
                while (c)
                {
@@ -1009,6 +1163,8 @@ int target_alloc_working_area(struct target_s *target, uint32_t size, working_ar
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
 
+               LOG_DEBUG("allocated new working area at address 0x%08x", (unsigned)first_free);
+
                new_wa = malloc(sizeof(working_area_t));
                new_wa->next = NULL;
                new_wa->size = size;
@@ -1532,13 +1688,13 @@ int target_register_user_commands(struct command_context_s *cmd_ctx)
        register_command(cmd_ctx,  NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run | halt | init] - default is run");
        register_command(cmd_ctx,  NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
 
-       register_command(cmd_ctx,  NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");
-       register_command(cmd_ctx,  NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words <addr> [count]");
-       register_command(cmd_ctx,  NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes <addr> [count]");
+       register_command(cmd_ctx,  NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words [phys] <addr> [count]");
+       register_command(cmd_ctx,  NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words [phys] <addr> [count]");
+       register_command(cmd_ctx,  NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes [phys] <addr> [count]");
 
-       register_command(cmd_ctx,  NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word <addr> <value> [count]");
-       register_command(cmd_ctx,  NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value> [count]");
-       register_command(cmd_ctx,  NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value> [count]");
+       register_command(cmd_ctx,  NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word [phys]  <addr> <value> [count]");
+       register_command(cmd_ctx,  NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word [phys]  <addr> <value> [count]");
+       register_command(cmd_ctx,  NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte [phys] <addr> <value> [count]");
 
        register_command(cmd_ctx,  NULL, "bp",
                        handle_bp_command, COMMAND_EXEC,
@@ -1800,6 +1956,8 @@ static int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char
                {
                        int i;
 
+                       command_print(cmd_ctx, "===== %s", cache->name);
+
                        for (i = 0, reg = cache->reg_list;
                                        i < cache->num_regs;
                                        i++, reg++, count++)
@@ -2184,6 +2342,22 @@ static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char
        default: return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
+       bool physical=strcmp(args[0], "phys")==0;
+       int (*fn)(struct target_s *target,
+                       uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
+       if (physical)
+       {
+               argc--;
+               args++;
+               fn=target_read_phys_memory;
+       } else
+       {
+               fn=target_read_memory;
+       }
+       if ((argc < 1) || (argc > 2))
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
        uint32_t address;
        int retval = parse_u32(args[0], &address);
        if (ERROR_OK != retval)
@@ -2200,8 +2374,7 @@ static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char
        uint8_t *buffer = calloc(count, size);
 
        target_t *target = get_current_target(cmd_ctx);
-       retval = target_read_memory(target,
-                               address, size, count, buffer);
+       retval = fn(target, address, size, count, buffer);
        if (ERROR_OK == retval)
                handle_md_output(cmd_ctx, target, address, size, count, buffer);
 
@@ -2212,7 +2385,23 @@ static int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char
 
 static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
 {
-        if ((argc < 2) || (argc > 3))
+       if (argc < 2)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       bool physical=strcmp(args[0], "phys")==0;
+       int (*fn)(struct target_s *target,
+                       uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
+       if (physical)
+       {
+               argc--;
+               args++;
+               fn=target_write_phys_memory;
+       } else
+       {
+               fn=target_write_memory;
+       }
+       if ((argc < 2) || (argc > 3))
                return ERROR_COMMAND_SYNTAX_ERROR;
 
        uint32_t address;
@@ -2255,7 +2444,7 @@ static int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char
        }
        for (unsigned i = 0; i < count; i++)
        {
-               retval = target_write_memory(target,
+               retval = fn(target,
                                address + i * wordsize, wordsize, 1, value_buf);
                if (ERROR_OK != retval)
                        return retval;
@@ -2807,7 +2996,8 @@ static int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char
                break;
 
        default:
-               command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
+               command_print(cmd_ctx, "usage: wp [address length "
+                               "[(r|w|a) [value [mask]]]]");
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
@@ -3299,7 +3489,6 @@ static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 
        return target_array2mem(interp,target, argc-1, argv + 1);
 }
-
 static int target_array2mem(Jim_Interp *interp, target_t *target, int argc, Jim_Obj *const *argv)
 {
        long l;
@@ -3639,6 +3828,7 @@ static int target_configure(Jim_GetOptInfo *goi, target_t *target)
                                        return e;
                                }
                                target->working_area_virt = w;
+                               target->working_area_virt_spec = true;
                        } else {
                                if (goi->argc != 0) {
                                        goto no_params;
@@ -3656,6 +3846,7 @@ static int target_configure(Jim_GetOptInfo *goi, target_t *target)
                                        return e;
                                }
                                target->working_area_phys = w;
+                               target->working_area_phys_spec = true;
                        } else {
                                if (goi->argc != 0) {
                                        goto no_params;
@@ -4637,10 +4828,88 @@ static int handle_fast_load_command(struct command_context_s *cmd_ctx, char *cmd
        return retval;
 }
 
+static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       command_context_t *context;
+       target_t *target;
+       int retval;
 
-/*
- * Local Variables:
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+       context = Jim_GetAssocData(interp, "context");
+       if (context == NULL) {
+               LOG_ERROR("array2mem: no command context");
+               return JIM_ERR;
+       }
+       target = get_current_target(context);
+       if (target == NULL) {
+               LOG_ERROR("array2mem: no current target");
+               return JIM_ERR;
+       }
+
+       if ((argc < 6) || (argc > 7))
+       {
+               return JIM_ERR;
+       }
+
+       int cpnum;
+       uint32_t op1;
+       uint32_t op2;
+       uint32_t CRn;
+       uint32_t CRm;
+       uint32_t value;
+
+       int e;
+       long l;
+       e = Jim_GetLong(interp, argv[1], &l);
+       if (e != JIM_OK) {
+               return e;
+       }
+       cpnum = l;
+
+       e = Jim_GetLong(interp, argv[2], &l);
+       if (e != JIM_OK) {
+               return e;
+       }
+       op1 = l;
+
+       e = Jim_GetLong(interp, argv[3], &l);
+       if (e != JIM_OK) {
+               return e;
+       }
+       op2 = l;
+
+       e = Jim_GetLong(interp, argv[4], &l);
+       if (e != JIM_OK) {
+               return e;
+       }
+       CRn = l;
+
+       e = Jim_GetLong(interp, argv[5], &l);
+       if (e != JIM_OK) {
+               return e;
+       }
+       CRm = l;
+
+       value = 0;
+
+       if (argc == 7)
+       {
+               e = Jim_GetLong(interp, argv[6], &l);
+               if (e != JIM_OK) {
+                       return e;
+               }
+               value = l;
+
+               retval = target_mcr(target, cpnum, op1, op2, CRn, CRm, value);
+               if (retval != ERROR_OK)
+                       return JIM_ERR;
+       } else
+       {
+               retval = target_mrc(target, cpnum, op1, op2, CRn, CRm, &value);
+               if (retval != ERROR_OK)
+                       return JIM_ERR;
+
+               Jim_SetResult(interp, Jim_NewIntObj(interp, value));
+       }
+
+       return JIM_OK;
+}