debug protocol commands
authorMichael Walle <michael@walle.cc>
Mon, 18 Oct 2010 20:08:26 +0000 (22:08 +0200)
committerMichael Walle <michael@walle.cc>
Mon, 18 Oct 2010 20:08:26 +0000 (22:08 +0200)
src/target/lm32.c

index b752e45..9ed5683 100644 (file)
@@ -36,9 +36,9 @@
  *  shift in:                 shift out:
  *   1                         1
  *   0 9 8 7 6 5 4 3 2 1 0     0 9 8 7 6 5 4 3 2 1 0
- *  +-----+---------------+   +-----+---------------+
- *  | ADR |     DATA      |   |    RESERVED   |P|T|R|
- *  +-----+---------------+   +-----+---------------+
+ *  +---------------+-----+   +---------------+-+-+-+
+ *  |      DATA     | ADR |   |      DATA     |P|T|R|
+ *  +---------------+-----+   +---------------+-+-+-+
  *   ADR                       R = JTAG RX ready
  *    0 = debug protocol       T = JTAG TX full
  *    1 = JTAG uart TX         P = DP command in progress
@@ -219,38 +219,67 @@ lm32_jtag_datar(struct target *target, uint32_t data_in, uint32_t *data_out)
  */
 
 static int
-lm32_send_command(struct target *target, uint32_t cmd, int flush)
+lm32_dp_send_data(struct target *target, uint8_t data, int flush)
 {
-       if (lm32_jtag_datar(target, LM32_ADDR_DP | (cmd << 7), NULL) != ERROR_OK)
-               goto err;
+       if (lm32_jtag_datar(target, (data << 3) | LM32_ADDR_DP, NULL) != ERROR_OK)
+               return ERROR_FAIL;
 
        if (flush)
                if (jtag_execute_queue() != ERROR_OK)
-                       goto err;
+                       return ERROR_FAIL;
 
        return ERROR_OK;
-err:
-       LOG_ERROR("error sending JTAG command");
-       return ERROR_FAIL;
 }
 
 static int
-lm32_get_status(struct target *target, uint32_t *status)
+lm32_dp_receive_data(struct target *target, uint8_t *data)
 {
-       return lm32_jtag_datar(target, LM32_ADDR_DP | (LM32_DP_NOP << 7), status);
+       uint32_t tmp=0;
+       int ret;
+
+       ret = lm32_jtag_datar(target, (LM32_DP_NOP << 7) | LM32_ADDR_DP, &tmp);
+       if (ret != ERROR_OK)
+               return ret;
+
+       LOG_DEBUG("tmp=%03x", tmp);
+
+       *data = (tmp >> 3) & 0xff;
+
+       return ERROR_OK;
 }
 
 static int
-lm32_read_rx(struct target *target, uint8_t *data)
+lm32_dp_send_command(struct target *target, uint8_t cmd, int flush)
+{
+       return lm32_dp_send_data(target, cmd << 4, flush);
+}
+
+static int
+lm32_get_status(struct target *target, uint8_t *status)
+{
+       uint32_t tmp;
+       int ret;
+
+       ret = lm32_jtag_datar(target, LM32_ADDR_DP | (LM32_DP_NOP << 7), &tmp);
+       if (ret != ERROR_OK)
+               return ret;
+
+       *status = tmp & 0x7;
+
+       return ERROR_OK;
+}
+
+static int
+lm32_wait_for_status(struct target *target, uint8_t mask, uint8_t value)
 {
        struct timeval timeout, now;
-       uint32_t status;
-       uint32_t tmp_data;
+       uint8_t status;
        int ret;
 
-       gettimeofday(&timeout, NULL);
-       timeval_add_time(&timeout, 1, 0);
+#define DEFAULT_TIMEOUT 1
 
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, DEFAULT_TIMEOUT, 0);
        for (;;)
        {
                if ((ret = lm32_get_status(target, &status)) != ERROR_OK) {
@@ -258,19 +287,12 @@ lm32_read_rx(struct target *target, uint8_t *data)
                        return ret;
                }
 
-               if (status & LM32_STAT_RX_READY)
-               {
-                       lm32_jtag_datar(target, LM32_ADDR_RX, NULL);
-                       lm32_jtag_datar(target, LM32_ADDR_DP | (LM32_DP_NOP << 7), &tmp_data);
-                       goto done;
-               }
+               if ((status & mask) == value)
+                       break;
 
                gettimeofday(&now, NULL);
                if (timercmp(&now, &timeout, >))
-               {
-                       LOG_ERROR("timeout reading RX register");
                        return ERROR_TARGET_TIMEOUT;
-               }
 
                if (debug_level >= 3)
                {
@@ -280,18 +302,36 @@ lm32_read_rx(struct target *target, uint8_t *data)
                        keep_alive();
                }
        }
-done:
 
-       if ((ret = jtag_execute_queue()) != ERROR_OK) {
+       return ERROR_OK;
+}
+
+static int
+lm32_read_rx(struct target *target, uint8_t *data)
+{
+       int ret;
+       uint32_t tmp_data;
+
+       ret = lm32_wait_for_status(target, LM32_STAT_RX_READY, LM32_STAT_RX_READY);
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = lm32_jtag_datar(target, LM32_ADDR_RX, NULL);
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = lm32_jtag_datar(target, LM32_ADDR_DP | (LM32_DP_NOP << 7), &tmp_data);
+       if (ret != ERROR_OK)
+               return ret;
+
+       ret = jtag_execute_queue();
+       if (ret != ERROR_OK)
                return ret;
-       }
 
        *data = (tmp_data >> 3) & 0xff;
 
-#if 0
-       if (debug_level >= 2)
+       if (debug_level >= 4)
                LOG_DEBUG("read %02x", *data);
-#endif
 
        return ERROR_OK;
 }
@@ -299,47 +339,18 @@ done:
 static int
 lm32_write_tx(struct target *target, uint8_t data)
 {
-       struct timeval timeout, now;
-       uint32_t status;
        int ret;
 
-#if 0
-       if (debug_level >= 3)
+       if (debug_level >= 4)
                LOG_DEBUG("sending %02x", data);
-#endif
-
-       gettimeofday(&timeout, NULL);
-       timeval_add_time(&timeout, 1, 0);
 
-       for (;;)
-       {
-               if ((ret = lm32_get_status(target, &status)) != ERROR_OK) {
-                       LOG_ERROR("error reading jtag status");
-                       return ret;
-               }
-
-               if (!(status & LM32_STAT_TX_FULL))
-               {
-                       lm32_jtag_datar(target, (data << 3) | LM32_ADDR_TX, NULL);
-                       goto done;
-               }
-
-               gettimeofday(&now, NULL);
-               if (timercmp(&now, &timeout, >))
-               {
-                       LOG_ERROR("timeout writing TX register");
-                       return ERROR_TARGET_TIMEOUT;
-               }
+       ret = lm32_wait_for_status(target, LM32_STAT_TX_FULL, 0);
+       if (ret != ERROR_OK)
+               return ret;
 
-               if (debug_level >= 3)
-               {
-                       LOG_DEBUG("sleeping 100ms");
-                       alive_sleep(100);
-               } else {
-                       keep_alive();
-               }
-       }
-done:
+       ret = lm32_jtag_datar(target, (data << 3) | LM32_ADDR_TX, NULL);
+       if (ret != ERROR_OK)
+               return ret;
 
        return jtag_execute_queue();
 }
@@ -376,6 +387,95 @@ lm32_recv_u32(struct target *target, uint32_t *data)
        return ERROR_OK;
 }
 
+static int
+lm32_dp_read_memory(struct target *target, uint32_t address, uint8_t *data)
+{
+       int ret;
+       int i;
+
+       ret = lm32_dp_send_command(target, LM32_DP_READ_MEMORY, 0);
+       if (ret != ERROR_OK)
+               return ret;
+       
+       /* now send address */
+       for (i = 3; i >= 0; i--)
+       {
+               ret = lm32_dp_send_data(target, (address >> (8*i)) & 0xff, (i==0) ? 1 : 0);
+               if (ret != ERROR_OK)
+                       return ret;
+       }
+
+       /* wait for completion */
+       ret = lm32_wait_for_status(target, LM32_STAT_PROCESSING, 0);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* read byte */
+       return lm32_dp_receive_data(target, data);
+}
+
+static int
+lm32_dp_read_sequential(struct target *target, uint8_t *data)
+{
+       int ret;
+
+       ret = lm32_dp_send_command(target, LM32_DP_READ_SEQUENTIAL, 1);
+       if (ret != ERROR_OK)
+               return ret;
+       
+       /* wait for completion */
+       ret = lm32_wait_for_status(target, LM32_STAT_PROCESSING, 0);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* read byte */
+       return lm32_dp_receive_data(target, data);
+}
+
+static int
+lm32_dp_write_memory(struct target *target, uint32_t address, uint8_t data)
+{
+       int ret;
+       int i;
+
+       ret = lm32_dp_send_command(target, LM32_DP_WRITE_MEMORY, 0);
+       if (ret != ERROR_OK)
+               return ret;
+       
+       /* now send address */
+       for (i = 3; i >= 0; i--)
+       {
+               ret = lm32_dp_send_data(target, (address >> (8*i)) & 0xff, 0);
+               if (ret != ERROR_OK)
+                       return ret;
+       }
+
+       /* and the byte to write */
+       ret = lm32_dp_send_data(target, data, 1);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* wait for completion */
+       return lm32_wait_for_status(target, LM32_STAT_PROCESSING, 0);
+}
+
+static int
+lm32_dp_write_sequential(struct target *target, uint8_t data)
+{
+       int ret;
+
+       ret = lm32_dp_send_command(target, LM32_DP_WRITE_SEQUENTIAL, 0);
+       if (ret != ERROR_OK)
+               return ret;
+       
+       ret = lm32_dp_send_data(target, data, 1);
+       if (ret != ERROR_OK)
+               return ret;
+
+       /* wait for completion */
+       return lm32_wait_for_status(target, LM32_STAT_PROCESSING, 0);
+}
+
 static int
 lm32_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
 {
@@ -624,7 +724,7 @@ static int
 lm32_poll(struct target *target)
 {
        int ret = ERROR_OK;
-       uint32_t status;
+       uint8_t status;
 
        if (target->state == TARGET_RUNNING)
        {
@@ -679,7 +779,7 @@ lm32_halt(struct target *target)
                return ERROR_TARGET_INVALID;
        }
 
-       if ((ret = lm32_send_command(target, LM32_DP_BREAK, 1)) != ERROR_OK)
+       if ((ret = lm32_dp_send_command(target, LM32_DP_BREAK, 1)) != ERROR_OK)
        {
                LOG_ERROR("could not send BREAK command");
                return ret;
@@ -703,11 +803,11 @@ lm32_deassert_reset(struct target *target)
        int ret;
        uint8_t data;
 
-       ret = lm32_send_command(target, LM32_DP_RESET, 0);
+       ret = lm32_dp_send_command(target, LM32_DP_RESET, 0);
        if (ret != ERROR_OK)
                goto err;
 
-       ret = lm32_send_command(target, LM32_DP_BREAK, 0);
+       ret = lm32_dp_send_command(target, LM32_DP_BREAK, 0);
        if (ret != ERROR_OK)
                goto err;
 
@@ -741,7 +841,7 @@ lm32_deassert_reset(struct target *target)
        else
                ret = lm32_send_u32(target, 0x00000000);
 
-       lm32_send_command(target, LM32_DP_RESET, 1);
+       lm32_dp_send_command(target, LM32_DP_RESET, 1);
        target->state = TARGET_RUNNING;
 
        return ERROR_OK;
@@ -809,44 +909,6 @@ lm32_step(struct target *target, int current, uint32_t address, int handle_break
        return ERROR_OK;
 }
 
-#if 0
-static int
-lm32_soft_reset_halt(struct target *target)
-{
-       struct lm32 *lm32 = target->arch_info;
-       int i;
-       uint8_t data;
-
-       LOG_DEBUG("-");
-
-       lm32_send_command(target, LM32_DP_BREAK, 0);
-       lm32_read_rx(target, &data);
-       lm32_write_tx(target, LM32_MONITOR_CMD_WRITE_CSR);
-       lm32_write_tx(target, LM32_MONITOR_WRITE_CSR_DC);
-       /* Cn = disabled, RE = remap all exception, SS = single step disabled */
-       lm32_send_u32(target, 0x00000002);
-
-       /* clear registers */
-       for (i = 0; i < LM32_NUM_REGS; i++)
-       {
-               data = 0;
-               buf_set_u32(lm32->reg_cache->reg_list[i].value, 0, 32, 0);
-               lm32->reg_cache->reg_list[i].dirty = 1;
-       }
-       lm32_restore_context(target);
-
-       lm32_send_command(target, LM32_DP_RESET, 1);
-
-       target->state = TARGET_HALTED;
-       target->debug_reason = DBG_REASON_DBGRQ;
-       lm32_invalidate_regs(target);
-
-       lm32_debug_entry(target);
-       
-       return ERROR_OK;
-}
-#endif
-
 static int
 lm32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
 {
@@ -1263,7 +1325,7 @@ lm32_checksum_memory(struct target *target, uint32_t address, uint32_t size, uin
 COMMAND_HANDLER(lm32_handle_break_command)
 {
        struct target *target = get_current_target(CMD_CTX);
-       return lm32_send_command(target, LM32_DP_BREAK, 1);
+       return lm32_dp_send_command(target, LM32_DP_BREAK, 1);
 }
 
 COMMAND_HANDLER(lm32_handle_reset_command)
@@ -1271,15 +1333,18 @@ COMMAND_HANDLER(lm32_handle_reset_command)
        struct target *target = get_current_target(CMD_CTX);
        /* XXX */
        target->state = TARGET_RUNNING;
-       return lm32_send_command(target, LM32_DP_RESET, 1);
+       return lm32_dp_send_command(target, LM32_DP_RESET, 1);
 }
 
 COMMAND_HANDLER(lm32_handle_status_command)
 {
        struct target *target = get_current_target(CMD_CTX);
-       uint32_t status;
+       uint8_t status;
+       int ret;
 
-       lm32_get_status(target, &status);
+       ret = lm32_get_status(target, &status);
+       if (ret != ERROR_OK)
+               return ret;
 
        command_print(CMD_CTX, "rx_ready=%i tx_full=%i processing=%i",
                (status & LM32_STAT_RX_READY) ? 1 : 0,
@@ -1318,11 +1383,126 @@ COMMAND_HANDLER(lm32_handle_juart_write_command)
                return ERROR_OK;
        }
        
-       COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], byte);
+       COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], byte);
 
        return lm32_write_tx(target, byte);
 }
 
+COMMAND_HANDLER(lm32_handle_dp_read_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       uint32_t addr;
+       uint8_t data;
+       int ret;
+
+       if (CMD_ARGC < 1)
+       {
+               LOG_ERROR("'lm32 dp read <addr>' command takes one operand");
+               return ERROR_OK;
+       }
+       
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+
+       ret = lm32_dp_read_memory(target, addr, &data);
+       if (ret != ERROR_OK)
+               return ret;
+
+       command_print(CMD_CTX, "%08x=%02x", addr, data);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(lm32_handle_dp_read_sequential_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       uint8_t data;
+       int ret;
+
+       ret = lm32_dp_read_sequential(target, &data);
+       if (ret != ERROR_OK)
+               return ret;
+
+       command_print(CMD_CTX, "%02x", data);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(lm32_handle_dp_write_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       uint32_t addr;
+       uint8_t data;
+       int ret;
+
+       if (CMD_ARGC < 2)
+       {
+               LOG_ERROR("'lm32 dp write <addr> <byte>' command takes two operands");
+               return ERROR_OK;
+       }
+       
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr);
+       COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], data);
+
+       ret = lm32_dp_write_memory(target, addr, data);
+       if (ret != ERROR_OK)
+               return ret;
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(lm32_handle_dp_write_sequential_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       uint8_t data;
+       int ret;
+
+       if (CMD_ARGC < 1)
+       {
+               LOG_ERROR("'lm32 dp write_seq <byte>' command takes one operand");
+               return ERROR_OK;
+       }
+       
+       COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], data);
+
+       ret = lm32_dp_write_sequential(target, data);
+       if (ret != ERROR_OK)
+               return ret;
+
+       return ERROR_OK;
+}
+
+static const struct command_registration lm32_dp_command_handlers[] =
+{
+       {
+               .name = "read",
+               .handler = lm32_handle_dp_read_command,
+               .mode = COMMAND_EXEC,
+               .help = "Execute debug protocol read command",
+               .usage = "addr",
+       },
+       {
+               .name = "read_seq",
+               .handler = lm32_handle_dp_read_sequential_command,
+               .mode = COMMAND_EXEC,
+               .help = "Execute debug protocol read sequential command",
+               .usage = "",
+       },
+       {
+               .name = "write",
+               .handler = lm32_handle_dp_write_command,
+               .mode = COMMAND_EXEC,
+               .help = "Execute debug protocol write command",
+               .usage = "addr byte",
+       },
+       {
+               .name = "write_seq",
+               .handler = lm32_handle_dp_write_sequential_command,
+               .mode = COMMAND_EXEC,
+               .help = "Execute debug protocol write sequential command",
+               .usage = "byte",
+       },
+};
+
 static const struct command_registration lm32_juart_command_handlers[] =
 {
        {
@@ -1362,9 +1542,15 @@ static const struct command_registration lm32_any_command_handlers[] =
                .name = "status",
                .handler = lm32_handle_status_command,
                .mode = COMMAND_EXEC,
-               .help = "Shos status flags.",
+               .help = "Show status flags.",
                .usage = "",
        },
+       {
+               .name = "dp",
+               .mode = COMMAND_ANY,
+               .help = "JTAG debug protocol commands",
+               .chain = lm32_dp_command_handlers,
+       },
        {
                .name = "juart",
                .mode = COMMAND_ANY,