cortex_a hybrid & context breakpoints
[openocd.git] / src / target / cortex_a.c
old mode 100644 (file)
new mode 100755 (executable)
index 86706cc..39f1b9e
@@ -14,6 +14,9 @@
  *   Copyright (C) 2010 Ã˜yvind Harboe                                      *
  *   oyvind.harboe@zylin.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     *
@@ -50,6 +53,10 @@ static int cortex_a8_debug_entry(struct target *target);
 static int cortex_a8_restore_context(struct target *target, bool bpwp);
 static int cortex_a8_set_breakpoint(struct target *target,
                struct breakpoint *breakpoint, uint8_t matchmode);
+static int cortex_a8_set_context_breakpoint(struct target *target,
+               struct breakpoint *breakpoint, uint8_t matchmode);
+static int cortex_a8_set_hybrid_breakpoint(struct target *target,
+               struct breakpoint *breakpoint);
 static int cortex_a8_unset_breakpoint(struct target *target,
                struct breakpoint *breakpoint);
 static int cortex_a8_dap_read_coreregister_u32(struct target *target,
@@ -671,7 +678,54 @@ static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
 
        return retval;
 }
+static struct target *get_cortex_a8(struct target *target, int32_t coreid)
+{
+struct target_list *head;
+struct target *curr;
 
+       head = target->head;
+       while(head != (struct target_list*)NULL)
+       {
+               curr = head->target;
+               if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED))
+               {
+        return curr;
+               }
+               head = head->next;
+       }
+   return target;
+}
+static int cortex_a8_halt(struct target *target);
+
+static int cortex_a8_halt_smp(struct target *target)
+{
+       int retval = 0;
+       struct target_list *head;
+       struct target *curr;
+       head = target->head;
+       while(head != (struct target_list*)NULL)
+       {
+               curr = head->target;
+               if ((curr != target) && (curr->state!= TARGET_HALTED))
+               {
+                       retval += cortex_a8_halt(curr);
+               }
+               head = head->next;
+       }
+       return retval;
+}
+
+static int update_halt_gdb(struct target *target)
+{
+       int retval = 0;
+       if (target->gdb_service->core[0]==-1)
+       {
+               target->gdb_service->target = target;
+               target->gdb_service->core[0] = target->coreid;
+               retval += cortex_a8_halt_smp(target);
+       }
+       return retval;
+}
 
 /*
  * Cortex-A8 Run control
@@ -685,7 +739,20 @@ static int cortex_a8_poll(struct target *target)
        struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
        struct adiv5_dap *swjdp = armv7a->armv4_5_common.dap;
        enum target_state prev_target_state = target->state;
-
+       //  toggle to another core is done by gdb as follow
+       //  maint packet J core_id
+       //  continue
+       //  the next polling trigger an halt event sent to gdb
+       if ((target->state == TARGET_HALTED) && (target->smp) &&
+                       (target->gdb_service) &&
+                       (target->gdb_service->target==NULL) )
+       {
+               target->gdb_service->target =
+                       get_cortex_a8(target, target->gdb_service->core[1]);
+               target_call_event_callbacks(target,
+                               TARGET_EVENT_HALTED);
+               return retval;
+       }
        retval = mem_ap_sel_read_atomic_u32(swjdp, swjdp_debugap,
                        armv7a->debug_base + CPUDBG_DSCR, &dscr);
        if (retval != ERROR_OK)
@@ -707,7 +774,12 @@ static int cortex_a8_poll(struct target *target)
                                retval = cortex_a8_debug_entry(target);
                                if (retval != ERROR_OK)
                                        return retval;
-
+                               if (target->smp)
+                               {
+                                       retval = update_halt_gdb(target);
+                                       if (retval != ERROR_OK)
+                                               return retval;
+                               }
                                target_call_event_callbacks(target,
                                                TARGET_EVENT_HALTED);
                        }
@@ -718,6 +790,12 @@ static int cortex_a8_poll(struct target *target)
                                retval = cortex_a8_debug_entry(target);
                                if (retval != ERROR_OK)
                                        return retval;
+                               if (target->smp)
+                               {
+                                       retval = update_halt_gdb(target);
+                                       if (retval != ERROR_OK)
+                                               return retval;
+                               }
 
                                target_call_event_callbacks(target,
                                                TARGET_EVENT_DEBUG_HALTED);
@@ -789,16 +867,13 @@ static int cortex_a8_halt(struct target *target)
        return ERROR_OK;
 }
 
-static int cortex_a8_resume(struct target *target, int current,
-               uint32_t address, int handle_breakpoints, int debug_execution)
+static int cortex_a8_internal_restore(struct target *target, int current,
+               uint32_t *address, int handle_breakpoints, int debug_execution)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *armv4_5 = &armv7a->armv4_5_common;
-       struct adiv5_dap *swjdp = armv7a->armv4_5_common.dap;
        int retval;
-
-//     struct breakpoint *breakpoint = NULL;
-       uint32_t resume_pc, dscr;
+       uint32_t resume_pc;
 
        if (!debug_execution)
                target_free_all_working_areas(target);
@@ -827,7 +902,9 @@ static int cortex_a8_resume(struct target *target, int current,
        /* current = 1: continue on current pc, otherwise continue at <address> */
        resume_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
        if (!current)
-               resume_pc = address;
+               resume_pc = *address;
+       else
+               *address = resume_pc;
 
        /* Make sure that the Armv7 gdb thumb fixups does not
         * kill the return address
@@ -856,6 +933,11 @@ static int cortex_a8_resume(struct target *target, int current,
        retval = cortex_a8_restore_context(target, handle_breakpoints);
        if (retval != ERROR_OK)
                return retval;
+    target->debug_reason = DBG_REASON_NOTHALTED;
+       target->state = TARGET_RUNNING;
+
+       /* registers are now invalid */
+       register_cache_invalidate(armv4_5->core_cache);
 
 #if 0
        /* the front-end may request us not to handle breakpoints */
@@ -872,8 +954,17 @@ static int cortex_a8_resume(struct target *target, int current,
        }
 
 #endif
+       return retval;
+}
 
-       /*
+static int cortex_a8_internal_restart(struct target *target)
+{
+       struct armv7a_common *armv7a = target_to_armv7a(target);
+       struct arm *armv4_5 = &armv7a->armv4_5_common;
+       struct adiv5_dap *swjdp = armv4_5->dap;
+       int retval;
+       uint32_t dscr;
+/*
         * Restart core and wait for it to be started.  Clear ITRen and sticky
         * exception flags: see ARMv7 ARM, C5.9.
         *
@@ -895,7 +986,8 @@ static int cortex_a8_resume(struct target *target, int current,
                return retval;
 
        retval = mem_ap_sel_write_atomic_u32(swjdp, swjdp_debugap,
-                       armv7a->debug_base + CPUDBG_DRCR, DRCR_RESTART | DRCR_CLEAR_EXCEPTIONS);
+                       armv7a->debug_base + CPUDBG_DRCR, DRCR_RESTART |
+                       DRCR_CLEAR_EXCEPTIONS);
        if (retval != ERROR_OK)
                return retval;
 
@@ -921,17 +1013,64 @@ static int cortex_a8_resume(struct target *target, int current,
        /* registers are now invalid */
        register_cache_invalidate(armv4_5->core_cache);
 
+       return ERROR_OK;
+}
+
+static int cortex_a8_restore_smp(struct target *target,int handle_breakpoints)
+{
+       int retval = 0;
+       struct target_list *head;
+       struct target *curr;
+    uint32_t address;
+       head = target->head;
+       while(head != (struct target_list*)NULL)
+       {
+               curr = head->target;
+               if ((curr != target) && (curr->state != TARGET_RUNNING))
+               {
+               /*  resume current address , not in step mode */
+               retval += cortex_a8_internal_restore(curr, 1, &address,
+                               handle_breakpoints, 0);
+                 retval += cortex_a8_internal_restart(curr);
+               }
+               head = head->next;
+
+       }
+       return retval;
+}
+
+static int cortex_a8_resume(struct target *target, int current,
+               uint32_t address, int handle_breakpoints, int debug_execution)
+{
+       int retval = 0;
+       /*   dummy resume for smp toggle in order to reduce gdb impact  */
+       if ((target->smp) && (target->gdb_service->core[1]!=-1))
+       {
+               /*   simulate a start and halt of target */
+               target->gdb_service->target = NULL;
+               target->gdb_service->core[0] = target->gdb_service->core[1];
+               /*  fake resume at next poll we play the  target core[1], see poll*/
+               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+               return 0;
+       }
+       cortex_a8_internal_restore(target, current, &address, handle_breakpoints, debug_execution);
+       if (target->smp)
+       {   target->gdb_service->core[0] = -1;
+               retval += cortex_a8_restore_smp(target, handle_breakpoints);
+       }
+       cortex_a8_internal_restart(target);
+
        if (!debug_execution)
        {
                target->state = TARGET_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-               LOG_DEBUG("target resumed at 0x%" PRIx32, resume_pc);
+               LOG_DEBUG("target resumed at 0x%" PRIx32, address);
        }
        else
        {
                target->state = TARGET_DEBUG_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
-               LOG_DEBUG("target debug resumed at 0x%" PRIx32, resume_pc);
+               LOG_DEBUG("target debug resumed at 0x%" PRIx32, address);
        }
 
        return ERROR_OK;
@@ -1287,6 +1426,141 @@ static int cortex_a8_set_breakpoint(struct target *target,
        return ERROR_OK;
 }
 
+static int cortex_a8_set_context_breakpoint(struct target *target,
+               struct breakpoint *breakpoint, uint8_t matchmode)
+{
+       int retval = ERROR_FAIL;
+       int brp_i=0;
+       uint32_t control;
+       uint8_t byte_addr_select = 0x0F;
+       struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+       struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
+       struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
+       
+       if (breakpoint->set)
+       {
+               LOG_WARNING("breakpoint already set");
+               return retval ;
+       }
+       /*check available context BRPs*/
+       while ((brp_list[brp_i].used || (brp_list[brp_i].type!=BRP_CONTEXT)) && (brp_i < cortex_a8->brp_num))
+                       brp_i++ ;
+       
+       if (brp_i >= cortex_a8->brp_num)
+       {
+               LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
+               return ERROR_FAIL;
+       }
+
+       breakpoint->set = brp_i + 1;
+       control = ((matchmode & 0x7) << 20)
+                               | (byte_addr_select << 5)
+                               | (3 << 1) | 1;
+       brp_list[brp_i].used = 1;
+       brp_list[brp_i].value = (breakpoint->asid);
+       brp_list[brp_i].control = control;
+       retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, 
+                       brp_list[brp_i].value);
+       if(retval != ERROR_OK)
+               return retval;
+       retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                       brp_list[brp_i].control);
+       if(retval != ERROR_OK)
+               return retval;
+       LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
+       brp_list[brp_i].control,
+       brp_list[brp_i].value);
+       return ERROR_OK;
+               
+}
+
+static int cortex_a8_set_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint)
+{
+       int retval = ERROR_FAIL;
+       int brp_1=0; //holds the contextID pair
+       int brp_2=0; // holds the IVA pair
+       uint32_t control_CTX, control_IVA;
+       uint8_t CTX_byte_addr_select = 0x0F;
+       uint8_t IVA_byte_addr_select = 0x0F;
+       uint8_t CTX_machmode = 0x03;
+       uint8_t IVA_machmode = 0x01;
+       struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+       struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
+       struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
+       
+       
+       
+       if (breakpoint->set)
+       {
+               LOG_WARNING("breakpoint already set");
+               return retval ;
+       }
+       /*check available context BRPs*/
+       while ((brp_list[brp_1].used || (brp_list[brp_1].type!=BRP_CONTEXT)) && (brp_1 < cortex_a8->brp_num))
+                       brp_1++ ;
+       
+       printf("brp(CTX) found num: %d \n",brp_1);
+       if (brp_1 >= cortex_a8->brp_num)
+       {
+               LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
+               return ERROR_FAIL;
+       }
+
+       while ((brp_list[brp_2].used || (brp_list[brp_2].type!=BRP_NORMAL)) && (brp_2 < cortex_a8->brp_num))
+                       brp_2++ ;
+       
+       printf("brp(IVA) found num: %d \n",brp_2);
+       if (brp_2 >= cortex_a8->brp_num)
+       {
+               LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
+               return ERROR_FAIL;
+       }
+
+       breakpoint->set = brp_1 + 1;
+       breakpoint->linked_BRP= brp_2;
+       control_CTX = ((CTX_machmode & 0x7) << 20)
+                               | (brp_2 << 16)
+                               | (0 << 14)
+                               | (CTX_byte_addr_select << 5)
+                               | (3 << 1) | 1;
+               brp_list[brp_1].used = 1;
+               brp_list[brp_1].value = (breakpoint->asid);
+               brp_list[brp_1].control = control_CTX;
+               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                               + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].BRPn, 
+                               brp_list[brp_1].value);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                               + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].BRPn,
+                               brp_list[brp_1].control);
+               if( retval != ERROR_OK )
+                       return retval;
+
+               control_IVA = ((IVA_machmode & 0x7) << 20)
+                               | (brp_1 << 16)
+                               | (IVA_byte_addr_select << 5)
+                               | (3 << 1) | 1;
+               brp_list[brp_2].used = 1;
+               brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC);
+               brp_list[brp_2].control = control_IVA;
+               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                               + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].BRPn, 
+                               brp_list[brp_2].value);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                               + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].BRPn,
+                               brp_list[brp_2].control);
+               if (retval != ERROR_OK )
+                       return retval;
+
+       return ERROR_OK;
+}
+
+
 static int cortex_a8_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
        int retval;
@@ -1302,27 +1576,81 @@ static int cortex_a8_unset_breakpoint(struct target *target, struct breakpoint *
 
        if (breakpoint->type == BKPT_HARD)
        {
-               int brp_i = breakpoint->set - 1;
-               if ((brp_i < 0) || (brp_i >= cortex_a8->brp_num))
+               if ((breakpoint->address != 0) && (breakpoint->asid != 0))
                {
-                       LOG_DEBUG("Invalid BRP number in breakpoint");
+                       int brp_i = breakpoint->set - 1;
+                       int brp_j = breakpoint->linked_BRP;
+                       if ((brp_i < 0) || (brp_i >= cortex_a8->brp_num))
+                       {
+                               LOG_DEBUG("Invalid BRP number in breakpoint");
+                               return ERROR_OK;
+                       }
+                       LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
+                                       brp_list[brp_i].control, brp_list[brp_i].value);
+                       brp_list[brp_i].used = 0;
+                       brp_list[brp_i].value = 0;
+                       brp_list[brp_i].control = 0;
+                       retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       brp_list[brp_i].control);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       brp_list[brp_i].value);
+                       if (retval != ERROR_OK)
+                               return retval;                                          
+                       if ((brp_j < 0) || (brp_j >= cortex_a8->brp_num))
+                       {
+                               LOG_DEBUG("Invalid BRP number in breakpoint");
+                               return ERROR_OK;
+                       }
+                       LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_j,
+                                       brp_list[brp_j].control, brp_list[brp_j].value);
+                       brp_list[brp_j].used = 0;
+                       brp_list[brp_j].value = 0;
+                       brp_list[brp_j].control = 0;
+                       retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_j].BRPn,
+                                       brp_list[brp_j].control);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_j].BRPn,
+                                       brp_list[brp_j].value);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       breakpoint->linked_BRP = 0;
+                       breakpoint->set = 0;
                        return ERROR_OK;
+                       
                }
-               LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
-                               brp_list[brp_i].control, brp_list[brp_i].value);
-               brp_list[brp_i].used = 0;
-               brp_list[brp_i].value = 0;
-               brp_list[brp_i].control = 0;
-               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
-                               + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
-                               brp_list[brp_i].control);
-               if (retval != ERROR_OK)
-                       return retval;
-               retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
-                               + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
-                               brp_list[brp_i].value);
-               if (retval != ERROR_OK)
-                       return retval;
+               else
+               {
+                       int brp_i = breakpoint->set - 1;
+                       if ((brp_i < 0) || (brp_i >= cortex_a8->brp_num))
+                       {
+                               LOG_DEBUG("Invalid BRP number in breakpoint");
+                               return ERROR_OK;
+                       }
+                       LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
+                                       brp_list[brp_i].control, brp_list[brp_i].value);
+                       brp_list[brp_i].used = 0;
+                       brp_list[brp_i].value = 0;
+                       brp_list[brp_i].control = 0;
+                       retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                                       + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       brp_list[brp_i].control);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       retval = cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
+                                       + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
+                                       brp_list[brp_i].value);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       breakpoint->set = 0;
+                       return ERROR_OK;
+               }                                       
        }
        else
        {
@@ -1366,6 +1694,41 @@ static int cortex_a8_add_breakpoint(struct target *target,
        return cortex_a8_set_breakpoint(target, breakpoint, 0x00); /* Exact match */
 }
 
+static int cortex_a8_add_context_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
+{
+       struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+
+       if ((breakpoint->type == BKPT_HARD) && (cortex_a8->brp_num_available < 1))
+       {
+               LOG_INFO("no hardware breakpoint available");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       if (breakpoint->type == BKPT_HARD)
+               cortex_a8->brp_num_available--;
+
+       return cortex_a8_set_context_breakpoint(target, breakpoint, 0x02); /* asid match */
+}
+
+static int cortex_a8_add_hybrid_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
+{
+       struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
+
+       if ((breakpoint->type == BKPT_HARD) && (cortex_a8->brp_num_available < 1))
+       {
+               LOG_INFO("no hardware breakpoint available");
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+
+       if (breakpoint->type == BKPT_HARD)
+               cortex_a8->brp_num_available--;
+
+       return cortex_a8_set_hybrid_breakpoint(target, breakpoint); /* ??? */
+}
+
+
 static int cortex_a8_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
        struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
@@ -1450,42 +1813,76 @@ static int cortex_a8_deassert_reset(struct target *target)
        return ERROR_OK;
 }
 
+
 static int cortex_a8_write_apb_ab_memory(struct target *target,
                 uint32_t address, uint32_t size,
                 uint32_t count, const uint8_t *buffer)
 {
+
+       /* write memory through APB-AP */
+
        int retval = ERROR_INVALID_ARGUMENTS;
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *armv4_5 = &armv7a->armv4_5_common;
-       int nbytes = count * size;
-       uint32_t data;
+       int total_bytes = count * size;
+       int start_byte, nbytes_to_write, i;
        struct reg *reg;
+       union _data {
+               uint8_t uc_a[4];
+               uint32_t ui;
+       } data;
 
        if (target->state != TARGET_HALTED)
        {
                LOG_WARNING("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
+
        reg = arm_reg_current(armv4_5, 0);
        reg->dirty = 1;
        reg = arm_reg_current(armv4_5, 1);
        reg->dirty = 1;
-       retval = cortex_a8_dap_write_coreregister_u32(target, address, 0);
+
+       retval = cortex_a8_dap_write_coreregister_u32(target, address & 0xFFFFFFFC, 0);
        if (retval != ERROR_OK)
                return retval;
 
-       while (nbytes > 0) {
-               data = *buffer++;
-               retval = cortex_a8_dap_write_coreregister_u32(target, data, 1);
+       start_byte = address & 0x3;
+
+       while (total_bytes > 0) {
+
+               nbytes_to_write = 4 - start_byte;
+               if (total_bytes < nbytes_to_write)
+                       nbytes_to_write = total_bytes; 
+                       
+               if ( nbytes_to_write != 4 ) {
+               
+                       /* execute instruction LDR r1, [r0] */
+                       retval = cortex_a8_exec_opcode(target,  ARMV4_5_LDR(1, 0), NULL);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       retval = cortex_a8_dap_read_coreregister_u32(target, &data.ui, 1);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+       
+               for (i = 0; i < nbytes_to_write; ++i)
+                       data.uc_a[i + start_byte] = *buffer++;
+
+               retval = cortex_a8_dap_write_coreregister_u32(target, data.ui, 1);
                if (retval != ERROR_OK)
                        return retval;
 
-               /* execute instruction STRB r1, [r0], 1 (0xe4c01001) */
-               retval = cortex_a8_exec_opcode(target, ARMV4_5_STRB_IP(1, 0) , NULL);
+               /* execute instruction STRW r1, [r0], 1 (0xe4801004) */
+               retval = cortex_a8_exec_opcode(target, ARMV4_5_STRW_IP(1, 0) , NULL);
                if (retval != ERROR_OK)
-                       return retval;
-               --nbytes;
+                               return retval;
+
+               total_bytes -= nbytes_to_write;
+               start_byte = 0;
        }
+
        return retval;
 }
 
@@ -1494,13 +1891,19 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
                 uint32_t address, uint32_t size,
                 uint32_t count, uint8_t *buffer)
 {
+
+       /* read memory through APB-AP */
+
        int retval = ERROR_INVALID_ARGUMENTS;
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct arm *armv4_5 = &armv7a->armv4_5_common;
-       /* read memory through APB-AP */
-       int nbytes = count * size;
-       uint32_t data;
+       int total_bytes = count * size;
+       int start_byte, nbytes_to_read, i;
        struct reg *reg;
+       union _data {
+               uint8_t uc_a[4];
+               uint32_t ui;
+       } data;
 
        if (target->state != TARGET_HALTED)
        {
@@ -1513,26 +1916,34 @@ static int cortex_a8_read_apb_ab_memory(struct target *target,
        reg = arm_reg_current(armv4_5, 1);
        reg->dirty = 1;
 
-       retval = cortex_a8_dap_write_coreregister_u32(target, address, 0);
+       retval = cortex_a8_dap_write_coreregister_u32(target, address & 0xFFFFFFFC, 0);
        if (retval != ERROR_OK)
                return retval;
 
-       while (nbytes > 0) {
+       start_byte = address & 0x3;
 
+       while (total_bytes > 0) {
 
-               /* execute instruction LDRB r1, [r0], 1 (0xe4d01001) */
-               retval = cortex_a8_exec_opcode(target, ARMV4_5_LDRB_IP(1, 0) , NULL);
+               /* execute instruction LDRW r1, [r0], 4 (0xe4901004)  */
+               retval = cortex_a8_exec_opcode(target,  ARMV4_5_LDRW_IP(1, 0), NULL);
                if (retval != ERROR_OK)
                        return retval;
 
-               retval = cortex_a8_dap_read_coreregister_u32(target, &data, 1);
+               retval = cortex_a8_dap_read_coreregister_u32(target, &data.ui, 1);
                if (retval != ERROR_OK)
                        return retval;
 
-               *buffer++ = data;
-               --nbytes;
-
+               nbytes_to_read = 4 - start_byte;
+               if (total_bytes < nbytes_to_read)
+                       nbytes_to_read = total_bytes; 
+       
+               for (i = 0; i < nbytes_to_read; ++i)
+                       *buffer++ = data.uc_a[i + start_byte];
+                       
+               total_bytes -= nbytes_to_read;
+               start_byte = 0;
        }
+
        return retval;
 }
 
@@ -1576,7 +1987,6 @@ static int cortex_a8_read_phys_memory(struct target *target,
                                                buffer, count, address);
                                break;
                        }
-
                } else {
 
                        /* read memory through APB-AP */
@@ -1616,6 +2026,7 @@ static int cortex_a8_read_memory(struct target *target, uint32_t address,
                if (retval != ERROR_OK)
                        return retval;
 
+
                if(enabled)
                {
                        virt = address;
@@ -1984,7 +2395,6 @@ static int cortex_a8_init_arch_info(struct target *target,
 
        /* Leave (only) generic DAP stuff for debugport_init() */
        dap->jtag_info = &cortex_a8->jtag_info;
-       dap->memaccess_tck = 80;
 
        /* Number of bits for tar autoincrement, impl. dep. at least 10 */
        dap->tar_autoincr_block = (1 << 10);
@@ -2222,6 +2632,68 @@ COMMAND_HANDLER(cortex_a8_handle_dbginit_command)
 
        return cortex_a8_init_debug_access(target);
 }
+COMMAND_HANDLER(cortex_a8_handle_smp_off_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+    /* check target is an smp target */
+    struct target_list *head;
+       struct target *curr;
+       head = target->head;
+       target->smp = 0;
+       if (head != (struct target_list*)NULL)
+       {
+               while (head != (struct target_list*)NULL)
+               {
+                       curr = head->target;
+                       curr->smp = 0;
+                       head = head->next;
+               }
+               /*  fixes the target display to the debugger */
+               target->gdb_service->target = target;
+       }
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(cortex_a8_handle_smp_on_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct target_list *head;
+       struct target *curr;
+       head = target->head;
+       if (head != (struct target_list*)NULL)
+       {   target->smp=1;
+               while (head != (struct target_list*)NULL)
+               {
+                       curr = head->target;
+                       curr->smp = 1;
+                       head = head->next;
+               }
+       }
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(cortex_a8_handle_smp_gdb_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       int retval = ERROR_OK;
+       struct target_list *head;
+       head = target->head;
+       if (head != (struct target_list*)NULL)
+       {
+               if (CMD_ARGC == 1)
+               {
+                       int coreid = 0;
+                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid);
+                       if (ERROR_OK != retval)
+                               return retval;
+                       target->gdb_service->core[1]=coreid;
+
+               }
+               command_print(CMD_CTX, "gdb coreid  %d -> %d", target->gdb_service->core[0]
+                               , target->gdb_service->core[1]);
+       }
+       return ERROR_OK;
+}
 
 static const struct command_registration cortex_a8_exec_command_handlers[] = {
        {
@@ -2236,6 +2708,25 @@ static const struct command_registration cortex_a8_exec_command_handlers[] = {
                .mode = COMMAND_EXEC,
                .help = "Initialize core debug",
        },
+       {   .name ="smp_off",
+           .handler = cortex_a8_handle_smp_off_command,
+               .mode = COMMAND_EXEC,
+               .help = "Stop smp handling",
+       },
+       {
+        .name ="smp_on",
+        .handler = cortex_a8_handle_smp_on_command,
+               .mode = COMMAND_EXEC,
+               .help = "Restart smp handling",
+       },
+       {
+        .name ="smp_gdb",
+        .handler = cortex_a8_handle_smp_gdb_command,
+               .mode = COMMAND_EXEC,
+               .help = "display/fix current core played to gdb",
+       },
+
+
        COMMAND_REGISTRATION_DONE
 };
 static const struct command_registration cortex_a8_command_handlers[] = {
@@ -2283,6 +2774,8 @@ struct target_type cortexa8_target = {
        .run_algorithm = armv4_5_run_algorithm,
 
        .add_breakpoint = cortex_a8_add_breakpoint,
+       .add_context_breakpoint = cortex_a8_add_context_breakpoint,
+       .add_hybrid_breakpoint = cortex_a8_add_hybrid_breakpoint,
        .remove_breakpoint = cortex_a8_remove_breakpoint,
        .add_watchpoint = NULL,
        .remove_watchpoint = NULL,

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)