Ensure Cortex-M reset wakes device from sleep (wfi/wfe)
[fw/openocd] / src / target / mips32_pracc.c
index 267a4ffd94c89c24a263ffe17854263daf44a4e4..bae436784af3253a64c7520e2d3b800b6db3b2cf 100644 (file)
@@ -125,9 +125,9 @@ static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl)
 
        /* wait for the PrAcc to become "1" */
        mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL);
-       ejtag_ctrl = ejtag_info->ejtag_ctrl;
 
        while (1) {
+               ejtag_ctrl = ejtag_info->ejtag_ctrl;
                retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl);
                if (retval != ERROR_OK)
                        return retval;
@@ -153,18 +153,22 @@ static int mips32_pracc_exec_read(struct mips32_pracc_context *ctx, uint32_t add
        uint32_t ejtag_ctrl, data;
 
        if ((address >= MIPS32_PRACC_PARAM_IN)
-               && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
+               && (address < MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
                offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
                data = ctx->local_iparam[offset];
        } else if ((address >= MIPS32_PRACC_PARAM_OUT)
-               && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
+               && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
                offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
                data = ctx->local_oparam[offset];
        } else if ((address >= MIPS32_PRACC_TEXT)
-               && (address <= MIPS32_PRACC_TEXT + ctx->code_len * 4)) {
+               && (address < MIPS32_PRACC_TEXT + ctx->code_len * 4)) {
                offset = (address - MIPS32_PRACC_TEXT) / 4;
                data = ctx->code[offset];
        } else if (address == MIPS32_PRACC_STACK) {
+               if (ctx->stack_offset <= 0) {
+                       LOG_ERROR("Error: Pracc stack out of bounds");
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
                /* save to our debug stack */
                data = ctx->stack[--ctx->stack_offset];
        } else {
@@ -209,14 +213,18 @@ static int mips32_pracc_exec_write(struct mips32_pracc_context *ctx, uint32_t ad
                return retval;
 
        if ((address >= MIPS32_PRACC_PARAM_IN)
-               && (address <= MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
+               && (address < MIPS32_PRACC_PARAM_IN + ctx->num_iparam * 4)) {
                offset = (address - MIPS32_PRACC_PARAM_IN) / 4;
                ctx->local_iparam[offset] = data;
        } else if ((address >= MIPS32_PRACC_PARAM_OUT)
-               && (address <= MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
+               && (address < MIPS32_PRACC_PARAM_OUT + ctx->num_oparam * 4)) {
                offset = (address - MIPS32_PRACC_PARAM_OUT) / 4;
                ctx->local_oparam[offset] = data;
        } else if (address == MIPS32_PRACC_STACK) {
+               if (ctx->stack_offset >= 32) {
+                       LOG_ERROR("Error: Pracc stack out of bounds");
+                       return ERROR_JTAG_DEVICE_ERROR;
+               }
                /* save data onto our stack */
                ctx->stack[ctx->stack_offset++] = data;
        } else {
@@ -231,7 +239,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_
                int num_param_in, uint32_t *param_in, int num_param_out, uint32_t *param_out, int cycle)
 {
        uint32_t ejtag_ctrl;
-       uint32_t address, data;
+       uint32_t address;
        struct mips32_pracc_context ctx;
        int retval;
        int pass = 0;
@@ -250,7 +258,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, const uint32_
                if (retval != ERROR_OK)
                        return retval;
 
-               address = data = 0;
+               address = 0;
                mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS);
                retval = mips_ejtag_drscan_32(ejtag_info, &address);
                if (retval != ERROR_OK)
@@ -343,10 +351,10 @@ static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr,
 
        int retval = ERROR_OK;
        int blocksize;
-       int bytesread;
+       int wordsread;
        uint32_t param_in[2];
 
-       bytesread = 0;
+       wordsread = 0;
 
        while (count > 0) {
                blocksize = count;
@@ -357,13 +365,13 @@ static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr,
                param_in[1] = blocksize;
 
                retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                               ARRAY_SIZE(param_in), param_in, blocksize, &buf[bytesread], 1);
+                               ARRAY_SIZE(param_in), param_in, blocksize, &buf[wordsread], 1);
                if (retval != ERROR_OK)
                        return retval;
 
                count -= blocksize;
-               addr += blocksize;
-               bytesread += blocksize;
+               addr += blocksize*sizeof(uint32_t);
+               wordsread += blocksize;
        }
 
        return retval;
@@ -442,14 +450,17 @@ static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr,
 
        /* TODO remove array */
        uint32_t *param_out = malloc(count * sizeof(uint32_t));
-       int i;
+       if (param_out == NULL) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
 
        int retval = ERROR_OK;
        int blocksize;
+       int hwordsread = 0;
        uint32_t param_in[2];
 
-       /*while (count > 0) */
-       {
+       while (count > 0) {
                blocksize = count;
                if (count > 0x400)
                        blocksize = 0x400;
@@ -458,17 +469,21 @@ static int mips32_pracc_read_mem16(struct mips_ejtag *ejtag_info, uint32_t addr,
                param_in[1] = blocksize;
 
                retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                       ARRAY_SIZE(param_in), param_in, count, param_out, 1);
+                       ARRAY_SIZE(param_in), param_in, blocksize, &param_out[hwordsread], 1);
+
+               if (retval != ERROR_OK)
+                       return retval;
 
-/*             count -= blocksize; */
-/*             addr += blocksize; */
+               count -= blocksize;
+               addr += blocksize*sizeof(uint16_t);
+               hwordsread += blocksize;
        }
 
-       for (i = 0; i < count; i++)
+       int i;
+       for (i = 0; i < hwordsread; i++)
                buf[i] = param_out[i];
 
        free(param_out);
-
        return retval;
 }
 
@@ -513,14 +528,17 @@ static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr,
 
        /* TODO remove array */
        uint32_t *param_out = malloc(count * sizeof(uint32_t));
-       int i;
+       if (param_out == NULL) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
 
        int retval = ERROR_OK;
        int blocksize;
        uint32_t param_in[2];
+       int bytesread = 0;
 
-/*     while (count > 0) */
-       {
+       while (count > 0) {
                blocksize = count;
                if (count > 0x400)
                        blocksize = 0x400;
@@ -529,17 +547,20 @@ static int mips32_pracc_read_mem8(struct mips_ejtag *ejtag_info, uint32_t addr,
                param_in[1] = blocksize;
 
                retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code,
-                       ARRAY_SIZE(param_in), param_in, count, param_out, 1);
+                       ARRAY_SIZE(param_in), param_in, count, &param_out[bytesread], 1);
 
-/*             count -= blocksize; */
-/*             addr += blocksize; */
-       }
+               if (retval != ERROR_OK)
+                       return retval;
 
-       for (i = 0; i < count; i++)
+               count -= blocksize;
+               addr += blocksize;
+               bytesread += blocksize;
+       }
+       int i;
+       for (i = 0; i < bytesread; i++)
                buf[i] = param_out[i];
 
        free(param_out);
-
        return retval;
 }
 
@@ -816,6 +837,9 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
        uint32_t conf = 0;
        int cached = 0;
 
+       if ((KSEGX(addr) == KSEG1) || ((addr >= 0xff200000) && (addr <= 0xff3fffff)))
+               return retval; /*Nothing to do*/
+
        mips32_cp0_read(ejtag_info, &conf, 16, 0);
 
        switch (KSEGX(addr)) {
@@ -825,9 +849,6 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
                case KSEG0:
                        cached = (conf & MIPS32_CONFIG0_K0_MASK) >> MIPS32_CONFIG0_K0_SHIFT;
                        break;
-               case KSEG1:
-                       /* uncachable segment - nothing to do */
-                       break;
                case KSEG2:
                case KSEG3:
                        cached = (conf & MIPS32_CONFIG0_K23_MASK) >> MIPS32_CONFIG0_K23_SHIFT;