- 16 and 32 bit unaligned accesses supported
authorntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Tue, 11 Mar 2008 18:39:43 +0000 (18:39 +0000)
committerntfreak <ntfreak@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Tue, 11 Mar 2008 18:39:43 +0000 (18:39 +0000)
- uses packed transfers for 8/16bit read/writes greater than 4bytes
- 8/16bit transfers now use address auto increment

git-svn-id: svn://svn.berlios.de/openocd/trunk@495 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/target/armv7m.c
src/target/armv7m.h
src/target/cortex_m3.c
src/target/cortex_m3.h
src/target/cortex_swjdp.c
src/target/cortex_swjdp.h

index f1f0ac967a0d91f90f3c8cd0dbddd4e2a2f7428a..99d289ade613ac9d3e5792f0e5e3a6ccd5c19153 100644 (file)
@@ -111,10 +111,10 @@ armv7m_core_reg_t armv7m_core_reg_list_arch_info[] =
 
        /*  CORE_SP are accesible using MSR and MRS instructions */
 #if 0
-//     {0x00, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* APSR */
-//     {0x01, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* IAPSR */
-//     {0x05, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* IPSR */
-//     {0x06, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* EPSR */
+       {0x00, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* APSR */
+       {0x01, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* IAPSR */
+       {0x05, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* IPSR */
+       {0x06, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* EPSR */
 #endif
 
        {0x10, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* PRIMASK */
index e897fc4490e61b9853724baeeac149b35ce29189..a29593daad936031576873752a4348d2a4368dd4 100644 (file)
@@ -85,46 +85,17 @@ typedef struct armv7m_common_s
        enum armv7m_mode core_mode;
        enum armv7m_state core_state;
        int  exception_number;
-       int (*full_context)(struct target_s *target);
+       
        /* Direct processor core register read and writes */
        int (*load_core_reg_u32)(struct target_s *target, enum armv7m_regtype type, u32 num, u32 *value);
        int (*store_core_reg_u32)(struct target_s *target, enum armv7m_regtype type, u32 num, u32 value);
        /* register cache to processor synchronization */
        int (*read_core_reg)(struct target_s *target, int num);
        int (*write_core_reg)(struct target_s *target, int num);
-       /* get or set register through cache, return error if target is running and synchronisation is impossible */
-       int (*get_core_reg_32)(struct target_s *target, int num, u32* value);
-       int (*set_core_reg_32)(struct target_s *target, int num, u32 value);
-
+       
        arm_jtag_t jtag_info;
-       reg_cache_t *eice_cache;
-       reg_cache_t *etm_cache;
 
        int (*examine_debug_reason)(target_t *target);
-       
-       void (*change_to_arm)(target_t *target, u32 *r0, u32 *pc);
-       
-/*
-       void (*read_core_regs)(target_t *target, u32 mask, u32 *core_regs[16]);
-       void (*read_core_regs_target_buffer)(target_t *target, u32 mask, void *buffer, int size);
-       void (*write_core_regs)(target_t *target, u32 mask, u32 core_regs[16]);
-*/
-
-/*
-       void (*write_xpsr_im8)(target_t *target, u8 xpsr_im, int rot, int spsr);
-       
-       void (*load_word_regs)(target_t *target, u32 mask);
-       void (*load_hword_reg)(target_t *target, int num);
-       void (*load_byte_reg)(target_t *target, int num);
-
-       void (*store_word_regs)(target_t *target, u32 mask);
-       void (*store_hword_reg)(target_t *target, int num);
-       void (*store_byte_reg)(target_t *target, int num);
-       
-       void (*write_pc)(target_t *target, u32 pc);
-       void (*branch_resume)(target_t *target);
-*/     
-
        void (*pre_debug_entry)(target_t *target);
        void (*post_debug_entry)(target_t *target);
        
index 51ec52e0fa651152fb0288a9f02653b7bfe3b98b..ca629cc6ff9cdbb49048ab3f9084716e9f1d32cb 100644 (file)
@@ -144,6 +144,7 @@ int cortex_m3_exec_opcode(target_t *target,u32 opcode, int len /* MODE, r0_inval
        return retvalue;
 }
 
+#if 0
 /* Enable interrupts */
 int cortex_m3_cpsie(target_t *target, u32 IF)
 {
@@ -155,6 +156,7 @@ int cortex_m3_cpsid(target_t *target, u32 IF)
 {
        return cortex_m3_exec_opcode(target, ARMV7M_T_CPSID(IF), 2);
 }
+#endif
 
 int cortex_m3_endreset_event(target_t *target)
 {
@@ -325,7 +327,6 @@ int cortex_m3_debug_entry(target_t *target)
                cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff);
        }
 
-
        /* Now we can load SP core registers */ 
        for (i = ARMV7M_PRIMASK; i < ARMV7NUMCOREREGS; i++)
        {
@@ -1212,39 +1213,31 @@ int cortex_m3_read_memory(struct target_s *target, u32 address, u32 size, u32 co
        armv7m_common_t *armv7m = target->arch_info;
        cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
        swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       int retval;
        
        /* sanitize arguments */
        if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
                return ERROR_INVALID_ARGUMENTS;
-
-       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
-               return ERROR_TARGET_UNALIGNED_ACCESS;
        
-       /* Is not optimal, autoincrement of tar should be used (  ahbap_block_read and CSW_ADDRINC_SINGLE ) */
+       /* cortex_m3 handles unaligned memory access */
+               
        switch (size)
        {
                case 4:
-                       /* TODOLATER Check error return value ! */
-                       {
-                               ahbap_read_buf(swjdp, buffer, 4 * count, address);
-                       }
+                       retval = ahbap_read_buf_u32(swjdp, buffer, 4 * count, address);
                        break;
                case 2:
-                       {
-                               ahbap_read_buf_u16(swjdp, buffer, 2 * count, address);
-                       }       
+                       retval = ahbap_read_buf_u16(swjdp, buffer, 2 * count, address);
                        break;
                case 1:
-                       {
-                               ahbap_read_buf(swjdp, buffer, count, address);
-                       }       
+                       retval = ahbap_read_buf_u8(swjdp, buffer, count, address);
                        break;
                default:
                        ERROR("BUG: we shouldn't get here");
                        exit(-1);
        }
        
-       return ERROR_OK;
+       return retval;
 }
 
 int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
@@ -1253,45 +1246,34 @@ int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 c
        armv7m_common_t *armv7m = target->arch_info;
        cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
        swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       int retval;
        
        /* sanitize arguments */
        if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
                return ERROR_INVALID_ARGUMENTS;
-
-       if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
-               return ERROR_TARGET_UNALIGNED_ACCESS;
-               
+       
        switch (size)
        {
                case 4:
-                       /* TODOLATER Check error return value ! */
-                       {
-                               ahbap_write_buf(swjdp, buffer, 4 * count, address);
-                       }
+                       retval = ahbap_write_buf_u32(swjdp, buffer, 4 * count, address);
                        break;
                case 2:
-                       {
-                               ahbap_write_buf_u16(swjdp, buffer, 2 * count, address);
-                       }       
+                       retval = ahbap_write_buf_u16(swjdp, buffer, 2 * count, address);
                        break;
                case 1:
-                       {
-                               ahbap_write_buf(swjdp, buffer, count, address);
-                       }       
+                       retval = ahbap_write_buf_u8(swjdp, buffer, count, address);     
                        break;
                default:
                        ERROR("BUG: we shouldn't get here");
                        exit(-1);
        }
        
-       return ERROR_OK;
+       return retval;
 }
 
 int cortex_m3_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
 {
-       cortex_m3_write_memory(target, address, 4, count, buffer);
-       
-       return ERROR_OK;
+       return cortex_m3_write_memory(target, address, 4, count, buffer);
 }
 
 void cortex_m3_build_reg_cache(target_t *target)
index 236911f54e491e0f878eef50b77e280c19e67a8b..17c2b47ba126f059ef1089ecc87074e2aebc2c30 100644 (file)
@@ -134,8 +134,7 @@ typedef struct  cortex_m3_dwt_comparator_s
 typedef struct cortex_m3_common_s
 {
        int common_magic;
-       /* int (*full_context)(struct target_s *target); */
-
+       
        arm_jtag_t jtag_info;
        
        /* Context information */
@@ -159,32 +158,8 @@ typedef struct cortex_m3_common_s
        int intlinesnum;
        u32 *intsetenable;
        
-/*
-       u32 arm_bkpt;
-       u16 thumb_bkpt;
-       int sw_bkpts_use_wp;
-       int wp_available;
-       int wp0_used;
-       int wp1_used;
-       
-       int force_hw_bkpts;
-       int dbgreq_adjust_pc;
-       int use_dbgrq;
-       int has_etm;
-       
-       int reinit_embeddedice;
-       
-       struct working_area_s *dcc_working_area;
-       
-       int fast_memory_access;
-       int dcc_downloads;
-*/
-       /* breakpoint use map */
-       int sw_bkpts_enabled;
-
        armv7m_common_t armv7m;
        swjdp_common_t swjdp_info;
-       
        void *arch_info;
 } cortex_m3_common_t;
 
index 6f26790741e2f1d4efb62c77c9315a3375599bdf..cc61d4de5e1461f6654060d73a0ffaa411a63772 100644 (file)
@@ -21,8 +21,8 @@
  *                                                                         *
  * CoreSight (Light?) SerialWireJtagDebugPort                              *
  *                                                                         *
- * CoreSight™ DAP-Lite TRM, ARM DDI 0316A                                  *
- * Cortex-M3™ TRM, ARM DDI 0337C                                           *
+ * CoreSight™ DAP-Lite TRM, ARM DDI 0316A                                *
+ * Cortex-M3™ TRM, ARM DDI 0337C                                         *
  *                                                                         *
 ***************************************************************************/
 #ifdef HAVE_CONFIG_H
 #include <stdlib.h>
 
 /*
-
-Transaction Mode:
-swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-Uses Overrun checking mode and does not do actual JTAG send/receive or transaction 
-result checking until swjdp_end_transaction()
-This must be done before using or deallocating any return variables.
-
-swjdp->trans_mode == TRANS_MODE_ATOMIC
-All reads and writes to the AHB bus are checked for valid completion, and return values
-are immediatley available.
-
+ * Transaction Mode:
+ * swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+ * Uses Overrun checking mode and does not do actual JTAG send/receive or transaction 
+ * result checking until swjdp_end_transaction()
+ * This must be done before using or deallocating any return variables.
+ * swjdp->trans_mode == TRANS_MODE_ATOMIC
+ * All reads and writes to the AHB bus are checked for valid completion, and return values
+ * are immediatley available.
 */
 
 /***************************************************************************
@@ -143,7 +140,7 @@ int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *o
        swjdp_scan(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
        if ((RnW == DPAP_READ) && (invalue != NULL))
        {
-               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
+               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
        }
        
        /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */
@@ -157,11 +154,10 @@ int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *o
 
 int scan_inout_check_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue)
 {
-
        swjdp_scan_u32(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
        if ((RnW==DPAP_READ) && (invalue != NULL))
        {
-               swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
+               swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
        }
        
        /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and then check CTRL_STAT */
@@ -192,7 +188,6 @@ int swjdp_transaction_endcheck(swjdp_common_t *swjdp)
                        if (waitcount > 100)
                        {
                                WARNING("Timeout waiting for ACK = OK/FAULT in SWJDP transaction");
-
                                return ERROR_JTAG_DEVICE_ERROR;
                        }
                }
@@ -255,17 +250,12 @@ int swjdp_transaction_endcheck(swjdp_common_t *swjdp)
 
 int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr)
 {
-       u8 out_value_buf[4];
-       
-       buf_set_u32(out_value_buf, 0, 32, value);
-       return scan_inout_check(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+       return scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, value, NULL);
 }
 
 int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr)
 {
-       scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);
-
-    return ERROR_OK;
+       return scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);
 }
 
 int swjdp_bankselect_apacc(swjdp_common_t *swjdp,u32 reg_addr)
@@ -328,7 +318,7 @@ int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar)
        if (csw != swjdp->ap_csw_value)
        {
                /* DEBUG("swjdp : Set CSW %x",csw); */
-               ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw ); 
+               ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw );
                swjdp->ap_csw_value = csw;
        }
        if (tar != swjdp->ap_tar_value)
@@ -339,7 +329,7 @@ int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar)
        }
        if (csw & CSW_ADDRINC_MASK)
        {       
-               /* Do not cache TAR value when autoincrementing */      
+               /* Do not cache TAR value when autoincrementing */
                swjdp->ap_tar_value = -1;
        }
        return ERROR_OK;
@@ -401,35 +391,54 @@ int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value)
 * Write a buffer in target order (little endian)                             *
 *                                                                            *
 *****************************************************************************/
-int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+int ahbap_write_buf_u32(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
 {
        u32 outvalue;
        int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;
-
+       u32 adr = address;
+       u8* pBuffer = buffer;
+       
        swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
-       while ((address & 0x3) && (count > 0))
+       
+       count >>= 2;
+       wcount = count;
+       
+       /* if we have an unaligned access - reorder data */
+       if (adr & 0x3u)
        {
-               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-               outvalue = (*buffer++) << 8 * (address & 0x3);
-               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
-               swjdp_transaction_endcheck(swjdp);
-               count--;
-               address++;
+               for (writecount = 0; writecount < count; writecount++)
+               {
+                       int i;
+                       outvalue = *((u32*)pBuffer);
+                       
+                       for (i = 0; i < 4; i++ )
+                       {
+                               *((u8*)pBuffer + (adr & 0x3)) = outvalue;
+                               outvalue >>= 8;
+                               adr++;
+                       }
+                       pBuffer += 4;
+               }
        }
-       wcount = count >> 2;
-       count = count - 4 * wcount;
+       
        while (wcount > 0)
        {
                /* Adjust to write blocks within 4K aligned boundaries */
                blocksize = (0x1000 - (0xFFF & address)) >> 2;
                if (wcount < blocksize)
                        blocksize = wcount;
+               
+               /* handle unaligned data at 4k boundary */
+               if (blocksize == 0)
+                       blocksize = 1;
+                       
                ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
-               for (writecount=0; writecount<blocksize; writecount++)
+               
+               for (writecount = 0; writecount < blocksize; writecount++)
                {
                        ahbap_write_reg(swjdp, AHBAP_DRW, buffer + 4 * writecount );
                }
+               
                if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
                {
                        wcount = wcount - blocksize;
@@ -440,6 +449,7 @@ int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
                {
                        errorcount++;
                }
+               
                if (errorcount > 1)
                {
                        WARNING("Block write error address 0x%x, wcount 0x%x", address, wcount);
@@ -447,16 +457,77 @@ int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
                }
        }
        
-       while (count > 0)
+       return retval;
+}
+
+int ahbap_write_buf_packed_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 outvalue;
+       int retval = ERROR_OK;
+       int wcount, blocksize, writecount, i;
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+               
+       wcount = count >> 1;
+       
+       while (wcount > 0)
        {
-               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-               outvalue = (*buffer++) << 8 * (address & 0x3);
-               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
-               retval = swjdp_transaction_endcheck(swjdp);
-               count--;
-               address++;
+               int nbytes;
+               
+               /* Adjust to read within 4K block boundaries */
+               blocksize = (0x1000 - (0xFFF & address)) >> 1;
+               
+               if (wcount < blocksize)
+                       blocksize = wcount;
+               
+               /* handle unaligned data at 4k boundary */
+               if (blocksize == 0)
+                       blocksize = 1;
+               
+               ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_PACKED, address);
+               writecount = blocksize;
+               
+               do
+               {
+                       nbytes = MIN((writecount << 1), 4);
+                       
+                       if (nbytes < 4 )
+                       {
+                               if (ahbap_write_buf_u16(swjdp, buffer, nbytes, address) != ERROR_OK)
+                               {
+                                       WARNING("Block read error address 0x%x, count 0x%x", address, count);
+                                       return ERROR_JTAG_DEVICE_ERROR;
+                               }
+                               
+                               address += nbytes >> 1;
+                       }
+                       else
+                       {
+                               outvalue = *((u32*)buffer);
+                               
+                               for (i = 0; i < nbytes; i++ )
+                               {
+                                       *((u8*)buffer + (address & 0x3)) = outvalue;
+                                       outvalue >>= 8;
+                                       address++;
+                               }
+                               
+                               outvalue = *((u32*)buffer);
+                               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue);
+                               if (swjdp_transaction_endcheck(swjdp) != ERROR_OK)
+                               {
+                                       WARNING("Block read error address 0x%x, count 0x%x", address, count);
+                                       return ERROR_JTAG_DEVICE_ERROR;
+                               }
+                       }
+                       
+                       buffer += nbytes >> 1;
+                       writecount -= nbytes >> 1;
+                       
+               } while (writecount);
+               wcount -= blocksize;
        }
-
+       
        return retval;
 }
 
@@ -465,6 +536,9 @@ int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 addres
        u32 outvalue;
        int retval = ERROR_OK;
        
+       if (count >= 4)
+               return ahbap_write_buf_packed_u16(swjdp, buffer, count, address);
+               
        swjdp->trans_mode = TRANS_MODE_COMPOSITE;
        
        while (count > 0)
@@ -481,38 +555,128 @@ int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 addres
        return retval;
 }
 
-/*****************************************************************************
-*                                                                            *
-* ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)  *
-*                                                                            *
-* Read block fast in target order (little endian) into a buffer       *
-*                                                                            *
-*****************************************************************************/
-int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+int ahbap_write_buf_packed_u8(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
 {
-       u32 invalue;
-       int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
-
+       u32 outvalue;
+       int retval = ERROR_OK;
+       int wcount, blocksize, writecount, i;
+       
        swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       wcount = count;
+       
+       while (wcount > 0)
+       {
+               int nbytes;
+               
+               /* Adjust to read within 4K block boundaries */
+               blocksize = (0x1000 - (0xFFF & address));
+               
+               if (wcount < blocksize)
+                       blocksize = wcount;
+                               
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_PACKED, address);
+               writecount = blocksize;
+               
+               do
+               {
+                       nbytes = MIN(writecount, 4);
+                       
+                       if (nbytes < 4 )
+                       {
+                               if (ahbap_write_buf_u8(swjdp, buffer, nbytes, address) != ERROR_OK)
+                               {
+                                       WARNING("Block read error address 0x%x, count 0x%x", address, count);
+                                       return ERROR_JTAG_DEVICE_ERROR;
+                               }
+                               
+                               address += nbytes;
+                       }
+                       else
+                       {
+                               outvalue = *((u32*)buffer);
+                               
+                               for (i = 0; i < nbytes; i++ )
+                               {
+                                       *((u8*)buffer + (address & 0x3)) = outvalue;
+                                       outvalue >>= 8;
+                                       address++;
+                               }
+                               
+                               outvalue = *((u32*)buffer);
+                               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue);
+                               if (swjdp_transaction_endcheck(swjdp) != ERROR_OK)
+                               {
+                                       WARNING("Block read error address 0x%x, count 0x%x", address, count);
+                                       return ERROR_JTAG_DEVICE_ERROR;
+                               }
+                       }
+                       
+                       buffer += nbytes;
+                       writecount -= nbytes;
+                       
+               } while (writecount);
+               wcount -= blocksize;
+       }
+       
+       return retval;
+}
 
-       while ((address & 0x3) && (count > 0))
+int ahbap_write_buf_u8(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 outvalue;
+       int retval = ERROR_OK;
+       
+       if (count >= 4)
+               return ahbap_write_buf_packed_u8(swjdp, buffer, count, address);
+               
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       while (count > 0)
        {
                ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue);
-               swjdp_transaction_endcheck(swjdp);
-               *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;
+               outvalue = *((u8*)buffer) << 8 * (address & 0x3);
+               ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+               retval = swjdp_transaction_endcheck(swjdp);
                count--;
                address++;
+               buffer++;
        }
-       wcount = count >> 2;
-       count = count - 4 * wcount;
+       
+       return retval;
+}
+
+/*********************************************************************************
+*                                                                                *
+* ahbap_read_buf_u32(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)  *
+*                                                                                *
+* Read block fast in target order (little endian) into a buffer                  *
+*                                                                                *
+**********************************************************************************/
+int ahbap_read_buf_u32(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
+       u32 adr = address;
+       u8* pBuffer = buffer;
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       count >>= 2;
+       wcount = count;
+       
        while (wcount > 0)
        {
                /* Adjust to read within 4K block boundaries */
                blocksize = (0x1000 - (0xFFF & address)) >> 2;
                if (wcount < blocksize)
                        blocksize = wcount;
+               
+               /* handle unaligned data at 4k boundary */
+               if (blocksize == 0)
+                       blocksize = 1;
+               
                ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+               
                /* Scan out first read */
                swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, NULL, NULL);
                for (readcount = 0; readcount < blocksize - 1; readcount++)
@@ -520,8 +684,9 @@ int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
                        /* Scan out read instruction and scan in previous value */
                        swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
                }
+               
                /* Scan in last value */
-               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
+               swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
                if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
                {
                        wcount = wcount - blocksize;
@@ -532,31 +697,94 @@ int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
                {
                        errorcount++;
                }
+               
                if (errorcount > 1)
                {
                        WARNING("Block read error address 0x%x, count 0x%x", address, count);
                        return ERROR_JTAG_DEVICE_ERROR;
                }
        }
-
-       while (count > 0)
+       
+       /* if we have an unaligned access - reorder data */
+       if (adr & 0x3u)
        {
-               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
-               retval = swjdp_transaction_endcheck(swjdp);
-               *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;
-               count--;
-               address++;
+               for (readcount = 0; readcount < count; readcount++)
+               {
+                       int i;
+                       u32 data = *((u32*)pBuffer);
+                       
+                       for (i = 0; i < 4; i++ )
+                       {
+                               *((u8*)pBuffer) = (data >> 8 * (adr & 0x3));
+                               pBuffer++;
+                               adr++;
+                       }
+               }
        }
+       
+       return retval;
+}
 
+int ahbap_read_buf_packed_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 invalue;
+       int retval = ERROR_OK;
+       int wcount, blocksize, readcount, i;
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       wcount = count >> 1;
+       
+       while (wcount > 0)
+       {
+               int nbytes;
+               
+               /* Adjust to read within 4K block boundaries */
+               blocksize = (0x1000 - (0xFFF & address)) >> 1;
+               if (wcount < blocksize)
+                       blocksize = wcount;
+                               
+               ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_PACKED, address);
+               
+               /* handle unaligned data at 4k boundary */
+               if (blocksize == 0)
+                       blocksize = 1;
+               readcount = blocksize;
+               
+               do
+               {
+                       ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+                       if (swjdp_transaction_endcheck(swjdp) != ERROR_OK)
+                       {
+                               WARNING("Block read error address 0x%x, count 0x%x", address, count);
+                               return ERROR_JTAG_DEVICE_ERROR;
+                       }
+                       
+                       nbytes = MIN((readcount << 1), 4);
+                       
+                       for (i = 0; i < nbytes; i++ )
+                       {
+                               *((u8*)buffer) = (invalue >> 8 * (address & 0x3));
+                               buffer++;
+                               address++;
+                       }
+                       
+                       readcount -= (nbytes >> 1);
+               } while (readcount);
+               wcount -= blocksize;
+       }
+       
        return retval;
 }
 
 int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
 {
-       u32 invalue;
+       u32 invalue, i;
        int retval = ERROR_OK;
        
+       if (count >= 4)
+               return ahbap_read_buf_packed_u16(swjdp, buffer, count, address);
+       
        swjdp->trans_mode = TRANS_MODE_COMPOSITE;
        
        while (count > 0)
@@ -564,51 +792,98 @@ int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address
                ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
                ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
                retval = swjdp_transaction_endcheck(swjdp);
-               *((u16*)buffer) = (invalue >> 8 * (address & 0x3));
+               if (address & 0x1)
+               {
+                       for (i = 0; i < 2; i++ )
+                       {
+                               *((u8*)buffer) = (invalue >> 8 * (address & 0x3));
+                               buffer++;
+                               address++;
+                       }
+               }
+               else
+               {
+                       *((u16*)buffer) = (invalue >> 8 * (address & 0x3));
+                       address += 2;
+                       buffer += 2;
+               }
                count -= 2;
-               address += 2;
-               buffer += 2;
        }
 
        return retval;
 }
 
-int ahbap_block_read_u32(swjdp_common_t *swjdp, u32 *buffer, int count, u32 address)
+int ahbap_read_buf_packed_u8(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
 {
-       int readcount, errorcount = 0;
-       u32 blocksize;
+       u32 invalue;
+       int retval = ERROR_OK;
+       int wcount, blocksize, readcount, i;
        
        swjdp->trans_mode = TRANS_MODE_COMPOSITE;
        
-       while (count > 0)
+       wcount = count;
+       
+       while (wcount > 0)
        {
+               int nbytes;
+               
                /* Adjust to read within 4K block boundaries */
-               blocksize = (0x1000 - (0xFFF & address)) >> 2;
-               if (count < blocksize)
-                       blocksize = count;
-               ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
-               for (readcount = 0; readcount < blocksize; readcount++)
-               {
-                       ahbap_read_reg_u32(swjdp, AHBAP_DRW, buffer + readcount );
-               }
-               if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
-               {
-                       count = count - blocksize;
-                       address = address + 4 * blocksize;
-                       buffer = buffer + blocksize;
-               }
-               else
-               {
-                       errorcount++;
-               }
-               if (errorcount > 1)
+               blocksize = (0x1000 - (0xFFF & address));
+               
+               if (wcount < blocksize)
+                       blocksize = wcount;
+                               
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_PACKED, address);
+               readcount = blocksize;
+               
+               do
                {
-                       WARNING("Block read error address 0x%x, count 0x%x", address, count);
-                       return ERROR_JTAG_DEVICE_ERROR;
-               }
+                       ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+                       if (swjdp_transaction_endcheck(swjdp) != ERROR_OK)
+                       {
+                               WARNING("Block read error address 0x%x, count 0x%x", address, count);
+                               return ERROR_JTAG_DEVICE_ERROR;
+                       }
+                       
+                       nbytes = MIN(readcount, 4);
+                       
+                       for (i = 0; i < nbytes; i++ )
+                       {
+                               *((u8*)buffer) = (invalue >> 8 * (address & 0x3));
+                               buffer++;
+                               address++;
+                       }
+                       
+                       readcount -= nbytes;
+               } while (readcount);
+               wcount -= blocksize;
        }
+       
+       return retval;
+}
 
-       return ERROR_OK;
+int ahbap_read_buf_u8(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+       u32 invalue;
+       int retval = ERROR_OK;
+       
+       if (count >= 4)
+               return ahbap_read_buf_packed_u8(swjdp, buffer, count, address);
+       
+       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+       
+       while (count > 0)
+       {
+               ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+               ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+               retval = swjdp_transaction_endcheck(swjdp);
+               *((u8*)buffer) = (invalue >> 8 * (address & 0x3));
+               count--;
+               address++;
+               buffer++;
+       }
+
+       return retval;
 }
 
 int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum)
@@ -616,6 +891,9 @@ int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum)
        int retval;
        u32 dcrdr;
        
+       /* because the DCB_DCRDR is used for the emulated dcc channel
+        * we gave to save/restore the DCB_DCRDR when used */
+       
        ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);
        
        swjdp->trans_mode = TRANS_MODE_COMPOSITE;
@@ -638,6 +916,9 @@ int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum)
        int retval;
        u32 dcrdr;
        
+       /* because the DCB_DCRDR is used for the emulated dcc channel
+        * we gave to save/restore the DCB_DCRDR when used */
+        
        ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);
        
        swjdp->trans_mode = TRANS_MODE_COMPOSITE;
@@ -696,13 +977,13 @@ int ahbap_debugport_init(swjdp_common_t *swjdp)
        swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
        /* With debug power on we can activate OVERRUN checking */
        swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;
-       swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat , DP_CTRL_STAT);
+       swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT);
        swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
        
        ahbap_read_reg_u32(swjdp, 0xFC, &idreg);
        ahbap_read_reg_u32(swjdp, 0xF8, &romaddr);
        
-       DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x", idreg, romaddr);       
+       DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x", idreg, romaddr);
        
        return ERROR_OK;
 }
index 99dae691782fa917600b8c710297679183f407d4..524386d0bf847e664d4e6bf712cfb4e62753c8a5 100644 (file)
 #define DP_SELECT       0x8
 #define DP_RDBUFF       0xC
 
-#define CORUNDETECT    (1<<0)
-#define SSTICKYORUN    (1<<1)
-#define SSTICKYERR     (1<<5)
-#define CDBGRSTREQ     (1<<26)
-#define CDBGRSTACK     (1<<27)
+#define CORUNDETECT            (1<<0)
+#define SSTICKYORUN            (1<<1)
+#define SSTICKYERR             (1<<5)
+#define CDBGRSTREQ             (1<<26)
+#define CDBGRSTACK             (1<<27)
 #define CDBGPWRUPREQ   (1<<28)
 #define CDBGPWRUPACK   (1<<29)
 #define CSYSPWRUPREQ   (1<<30)
 #define CSYSPWRUPACK   (1<<31)
 
-#define        AHBAP_CSW       0x00
-#define AHBAP_TAR      0x04
-#define AHBAP_DRW      0x0C
-#define AHBAP_BD0      0x10
-#define AHBAP_BD1      0x14
-#define AHBAP_BD2      0x18
-#define AHBAP_BD3      0x1C
+#define        AHBAP_CSW               0x00
+#define AHBAP_TAR              0x04
+#define AHBAP_DRW              0x0C
+#define AHBAP_BD0              0x10
+#define AHBAP_BD1              0x14
+#define AHBAP_BD2              0x18
+#define AHBAP_BD3              0x1C
 #define AHBAP_DBGROMA  0xF8
-#define AHBAP_IDR      0xFC
+#define AHBAP_IDR              0xFC
 
 #define CSW_8BIT               0
 #define CSW_16BIT              1
@@ -67,9 +67,9 @@
 #define CSW_DBGSWENABLE                (1<<31)
 
 /* transaction mode */
-#define TRANS_MODE_NONE                0
+#define TRANS_MODE_NONE                        0
 /* Transaction waits for previous to complete */
-#define TRANS_MODE_ATOMIC      1
+#define TRANS_MODE_ATOMIC              1
 /* Freerunning transactions with delays and overrun checking */
 #define TRANS_MODE_COMPOSITE   2
 
@@ -88,12 +88,10 @@ typedef struct swjdp_common_s
        u32 dp_select_value;
        u32 ap_csw_value;
        u32 ap_tar_value;
-       u8  prev_ack;
        /* information about current pending SWjDP-AHBAP transaction */
        u8  trans_mode;
        u8  trans_rw;
        u8  ack;
-       u32 *trans_value;
 } swjdp_common_t;
 
 /* Internal functions used in the module, partial transactions, use with caution */
@@ -113,17 +111,18 @@ extern int swjdp_transaction_endcheck(swjdp_common_t *swjdp);
 /* Host endian word transfer of single memory and system registers */
 extern int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value);
 extern int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value);
-/* Target endian (u8*) buffer transfers of blocks of memory and system registers */
-extern int ahbap_read_block(swjdp_common_t *swjdp, u8 *buffer, int bytecount, u32 address);
-extern int ahbap_write_block(swjdp_common_t *swjdp, u8 *buffer, int bytecount, u32 address);
+
 /* Host endian word transfers of processor core registers */
 extern int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum);
 extern int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum);
 
-extern int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address);
+extern int ahbap_read_buf_u8(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address);
 extern int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address);
-extern int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address);
+extern int ahbap_read_buf_u32(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address);
+
+extern int ahbap_write_buf_u8(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address);
 extern int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address);
+extern int ahbap_write_buf_u32(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address);
 
 /* Initialisation of the debug system, power domains and registers */
 extern int ahbap_debugport_init(swjdp_common_t *swjdp);

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)