Conform to OpenOCD style guide.

Change-Id: I2b23ac79639ed40e9d59db5c52ea2196df0349bc
This commit is contained in:
Tim Newsome 2017-12-22 14:35:38 -08:00
parent 19d9e3e32a
commit d942bce996
16 changed files with 848 additions and 735 deletions

View File

@ -28,7 +28,7 @@ matrix:
- os: linux - os: linux
env: env:
- BUILD=i686-linux-gnu - BUILD=i686-linux-gnu
- CFLAGS=-m32 - CFLAGS=-m32
- EXECUTABLE=openocd - EXECUTABLE=openocd
compiler: clang compiler: clang
@ -38,7 +38,7 @@ matrix:
- gcc-multilib - gcc-multilib
- os: linux - os: linux
env: env:
- BUILD=i686-w64-mingw - BUILD=i686-w64-mingw
- CONFIGURE_ARGS="--build=i686-unknown-linux-gnu --host=i686-w64-mingw32" - CONFIGURE_ARGS="--build=i686-unknown-linux-gnu --host=i686-w64-mingw32"
- EXECUTABLE=openocd.exe - EXECUTABLE=openocd.exe

View File

@ -1,7 +1,7 @@
/*************************************************************************** /***************************************************************************
* Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> * * Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
* Modified by Megan Wachs <megan@sifive.com> from the original stmsmi.c * * Modified by Megan Wachs <megan@sifive.com> from the original stmsmi.c *
* * * *
* This program is free software; you can redistribute it and/or modify * * 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 * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
@ -18,7 +18,7 @@
/* The Freedom E SPI controller is a SPI bus controller /* The Freedom E SPI controller is a SPI bus controller
* specifically designed for SPI Flash Memories on Freedom E platforms. * specifically designed for SPI Flash Memories on Freedom E platforms.
* *
* Two working modes are available: * Two working modes are available:
* - SW mode: the SPI is controlled by SW. Any custom commands can be sent * - SW mode: the SPI is controlled by SW. Any custom commands can be sent
* on the bus. Writes are only possible in this mode. * on the bus. Writes are only possible in this mode.
@ -127,7 +127,7 @@
int __a; \ int __a; \
uint32_t __v; \ uint32_t __v; \
\ \
__a = target_read_u32(target, ctrl_base + (a), &__v); \ __a = target_read_u32(target, ctrl_base + (a), &__v); \
if (__a != ERROR_OK) { \ if (__a != ERROR_OK) { \
LOG_ERROR("FESPI_READ_REG error"); \ LOG_ERROR("FESPI_READ_REG error"); \
return __a; \ return __a; \
@ -139,7 +139,7 @@
{ \ { \
int __r; \ int __r; \
\ \
__r = target_write_u32(target, ctrl_base + (a), (v)); \ __r = target_write_u32(target, ctrl_base + (a), (v)); \
if (__r != ERROR_OK) { \ if (__r != ERROR_OK) { \
LOG_ERROR("FESPI_WRITE_REG error"); \ LOG_ERROR("FESPI_WRITE_REG error"); \
return __r; \ return __r; \
@ -163,7 +163,7 @@ struct fespi_target {
uint32_t ctrl_base; uint32_t ctrl_base;
}; };
//TODO !!! What is the right naming convention here? /* TODO !!! What is the right naming convention here? */
static const struct fespi_target target_devices[] = { static const struct fespi_target target_devices[] = {
/* name, tap_idcode, ctrl_base */ /* name, tap_idcode, ctrl_base */
{ "Freedom E300 SPI Flash", 0x10e31913 , 0x10014000 }, { "Freedom E300 SPI Flash", 0x10e31913 , 0x10014000 },
@ -189,16 +189,17 @@ FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command)
fespi_info->probed = 0; fespi_info->probed = 0;
fespi_info->ctrl_base = 0; fespi_info->ctrl_base = 0;
if (CMD_ARGC >= 7) { if (CMD_ARGC >= 7) {
int temp; int temp;
COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], temp); COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], temp);
fespi_info->ctrl_base = (uint32_t) temp; fespi_info->ctrl_base = (uint32_t) temp;
LOG_DEBUG("ASSUMING FESPI device at ctrl_base = 0x%x", fespi_info->ctrl_base); LOG_DEBUG("ASSUMING FESPI device at ctrl_base = 0x%x", fespi_info->ctrl_base);
} }
return ERROR_OK; return ERROR_OK;
} }
static int fespi_set_dir (struct flash_bank * bank, bool dir) { static int fespi_set_dir(struct flash_bank *bank, bool dir)
{
struct target *target = bank->target; struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv; struct fespi_flash_bank *fespi_info = bank->driver_priv;
uint32_t ctrl_base = fespi_info->ctrl_base; uint32_t ctrl_base = fespi_info->ctrl_base;
@ -211,7 +212,8 @@ static int fespi_set_dir (struct flash_bank * bank, bool dir) {
} }
static int fespi_txwm_wait(struct flash_bank *bank) { static int fespi_txwm_wait(struct flash_bank *bank)
{
struct target *target = bank->target; struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv; struct fespi_flash_bank *fespi_info = bank->driver_priv;
uint32_t ctrl_base = fespi_info->ctrl_base; uint32_t ctrl_base = fespi_info->ctrl_base;
@ -219,9 +221,8 @@ static int fespi_txwm_wait(struct flash_bank *bank) {
int64_t start = timeval_ms(); int64_t start = timeval_ms();
while (1) { while (1) {
if (FESPI_READ_REG(FESPI_REG_IP) & FESPI_IP_TXWM) { if (FESPI_READ_REG(FESPI_REG_IP) & FESPI_IP_TXWM)
break; break;
}
int64_t now = timeval_ms(); int64_t now = timeval_ms();
if (now - start > 1000) { if (now - start > 1000) {
LOG_ERROR("ip.txwm didn't get set."); LOG_ERROR("ip.txwm didn't get set.");
@ -233,7 +234,8 @@ static int fespi_txwm_wait(struct flash_bank *bank) {
} }
static int fespi_tx(struct flash_bank *bank, uint8_t in){ static int fespi_tx(struct flash_bank *bank, uint8_t in)
{
struct target *target = bank->target; struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv; struct fespi_flash_bank *fespi_info = bank->driver_priv;
uint32_t ctrl_base = fespi_info->ctrl_base; uint32_t ctrl_base = fespi_info->ctrl_base;
@ -241,9 +243,8 @@ static int fespi_tx(struct flash_bank *bank, uint8_t in){
int64_t start = timeval_ms(); int64_t start = timeval_ms();
while (1) { while (1) {
if ((int32_t) FESPI_READ_REG(FESPI_REG_TXFIFO) >= 0) { if ((int32_t) FESPI_READ_REG(FESPI_REG_TXFIFO) >= 0)
break; break;
}
int64_t now = timeval_ms(); int64_t now = timeval_ms();
if (now - start > 1000) { if (now - start > 1000) {
LOG_ERROR("txfifo stayed negative."); LOG_ERROR("txfifo stayed negative.");
@ -276,14 +277,14 @@ static int fespi_rx(struct flash_bank *bank, uint8_t *out)
} }
} }
if (out) { if (out)
*out = value & 0xff; *out = value & 0xff;
}
return ERROR_OK; return ERROR_OK;
} }
//TODO!!! Why don't we need to call this after writing? /* TODO!!! Why don't we need to call this after writing? */
static int fespi_wip (struct flash_bank * bank, int timeout) static int fespi_wip(struct flash_bank *bank, int timeout)
{ {
struct target *target = bank->target; struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv; struct fespi_flash_bank *fespi_info = bank->driver_priv;
@ -326,26 +327,34 @@ static int fespi_erase_sector(struct flash_bank *bank, int sector)
int retval; int retval;
retval = fespi_tx(bank, SPIFLASH_WRITE_ENABLE); retval = fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
if (retval != ERROR_OK) {return retval;} if (retval != ERROR_OK)
return retval;
retval = fespi_txwm_wait(bank); retval = fespi_txwm_wait(bank);
if (retval != ERROR_OK) {return retval;} if (retval != ERROR_OK)
return retval;
FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_HOLD); FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
retval = fespi_tx(bank, fespi_info->dev->erase_cmd); retval = fespi_tx(bank, fespi_info->dev->erase_cmd);
if (retval != ERROR_OK) {return retval;} if (retval != ERROR_OK)
return retval;
sector = bank->sectors[sector].offset; sector = bank->sectors[sector].offset;
retval = fespi_tx(bank, sector >> 16); retval = fespi_tx(bank, sector >> 16);
if (retval != ERROR_OK) {return retval;} if (retval != ERROR_OK)
return retval;
retval = fespi_tx(bank, sector >> 8); retval = fespi_tx(bank, sector >> 8);
if (retval != ERROR_OK) {return retval;} if (retval != ERROR_OK)
return retval;
retval = fespi_tx(bank, sector); retval = fespi_tx(bank, sector);
if (retval != ERROR_OK) {return retval;} if (retval != ERROR_OK)
return retval;
retval = fespi_txwm_wait(bank); retval = fespi_txwm_wait(bank);
if (retval != ERROR_OK) {return retval;} if (retval != ERROR_OK)
return retval;
FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_AUTO); FESPI_WRITE_REG(FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
retval = fespi_wip(bank, FESPI_MAX_TIMEOUT); retval = fespi_wip(bank, FESPI_MAX_TIMEOUT);
if (retval != ERROR_OK){return retval;} if (retval != ERROR_OK)
return retval;
return ERROR_OK; return ERROR_OK;
} }
@ -384,9 +393,9 @@ static int fespi_erase(struct flash_bank *bank, int first, int last)
FESPI_WRITE_REG(FESPI_REG_TXCTRL, FESPI_TXWM(1)); FESPI_WRITE_REG(FESPI_REG_TXCTRL, FESPI_TXWM(1));
retval = fespi_txwm_wait(bank); retval = fespi_txwm_wait(bank);
if (retval != ERROR_OK){ if (retval != ERROR_OK) {
LOG_ERROR("WM Didn't go high before attempting."); LOG_ERROR("WM Didn't go high before attempting.");
return retval; return retval;
} }
/* Disable Hardware accesses*/ /* Disable Hardware accesses*/
@ -394,7 +403,7 @@ static int fespi_erase(struct flash_bank *bank, int first, int last)
/* poll WIP */ /* poll WIP */
retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT); retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
for (sector = first; sector <= last; sector++) { for (sector = first; sector <= last; sector++) {
@ -427,7 +436,7 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
uint32_t ctrl_base = fespi_info->ctrl_base; uint32_t ctrl_base = fespi_info->ctrl_base;
uint32_t ii; uint32_t ii;
//TODO!!! assert that len < page size /* TODO!!! assert that len < page size */
fespi_tx(bank, SPIFLASH_WRITE_ENABLE); fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
fespi_txwm_wait(bank); fespi_txwm_wait(bank);
@ -440,9 +449,8 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
fespi_tx(bank, offset >> 8); fespi_tx(bank, offset >> 8);
fespi_tx(bank, offset); fespi_tx(bank, offset);
for (ii = 0; ii < len; ii++) { for (ii = 0; ii < len; ii++)
fespi_tx(bank, buffer[ii]); fespi_tx(bank, buffer[ii]);
}
fespi_txwm_wait(bank); fespi_txwm_wait(bank);
@ -487,67 +495,67 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
.global _start .global _start
_start: _start:
command_table: command_table:
j main // 0 j main // 0
ebreak // 4 ebreak // 4
j tx // 8 j tx // 8
j txwm_wait // 12 j txwm_wait // 12
j write_reg // 16 j write_reg // 16
j wip_wait // 20 j wip_wait // 20
j set_dir // 24 j set_dir // 24
// Execute the program. // Execute the program.
main: main:
lbu t0, 0(a1) lbu t0, 0(a1)
addi a1, a1, 1 addi a1, a1, 1
la t1, command_table la t1, command_table
add t0, t0, t1 add t0, t0, t1
jr t0 jr t0
// Read 1 byte the contains the number of bytes to transmit. Then read those // Read 1 byte the contains the number of bytes to transmit. Then read those
// bytes from the program and transmit them one by one. // bytes from the program and transmit them one by one.
tx: tx:
lbu t1, 0(a1) // read number of bytes to transmit lbu t1, 0(a1) // read number of bytes to transmit
addi a1, a1, 1 addi a1, a1, 1
1: lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear 1: lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
bltz t0, 1b bltz t0, 1b
lbu t0, 0(a1) // Load byte to write lbu t0, 0(a1) // Load byte to write
sw t0, FESPI_REG_TXFIFO(a0) sw t0, FESPI_REG_TXFIFO(a0)
addi a1, a1, 1 addi a1, a1, 1
addi t1, t1, -1 addi t1, t1, -1
bgtz t1, 1b bgtz t1, 1b
j main j main
// Wait until TXWM is set. // Wait until TXWM is set.
txwm_wait: txwm_wait:
1: lw t0, FESPI_REG_IP(a0) 1: lw t0, FESPI_REG_IP(a0)
andi t0, t0, FESPI_IP_TXWM andi t0, t0, FESPI_IP_TXWM
beqz t0, 1b beqz t0, 1b
j main j main
// Read 1 byte that contains the offset of the register to write, and 1 byte // Read 1 byte that contains the offset of the register to write, and 1 byte
// that contains the data to write. // that contains the data to write.
write_reg: write_reg:
lbu t0, 0(a1) // read register to write lbu t0, 0(a1) // read register to write
add t0, t0, a0 add t0, t0, a0
lbu t1, 1(a1) // read value to write lbu t1, 1(a1) // read value to write
addi a1, a1, 2 addi a1, a1, 2
sw t1, 0(t0) sw t1, 0(t0)
j main j main
wip_wait: wip_wait:
li a2, SPIFLASH_READ_STATUS li a2, SPIFLASH_READ_STATUS
jal txrx_byte jal txrx_byte
// discard first result // discard first result
1: li a2, 0 1: li a2, 0
jal txrx_byte jal txrx_byte
andi t0, a2, SPIFLASH_BSY_BIT andi t0, a2, SPIFLASH_BSY_BIT
bnez t0, 1b bnez t0, 1b
j main j main
txrx_byte: // transmit the byte in a2, receive a bit into a2 txrx_byte: // transmit the byte in a2, receive a bit into a2
lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
bltz t0, txrx_byte bltz t0, txrx_byte
sw a2, FESPI_REG_TXFIFO(a0) sw a2, FESPI_REG_TXFIFO(a0)
1: lw a2, FESPI_REG_RXFIFO(a0) 1: lw a2, FESPI_REG_RXFIFO(a0)
bltz a2, 1b bltz a2, 1b
ret ret
@ -556,8 +564,8 @@ set_dir:
lw t0, FESPI_REG_FMT(a0) lw t0, FESPI_REG_FMT(a0)
li t1, ~(FESPI_FMT_DIR(0xFFFFFFFF)) li t1, ~(FESPI_FMT_DIR(0xFFFFFFFF))
and t0, t0, t1 and t0, t0, t1
lbu t1, 0(a1) // read value to OR in lbu t1, 0(a1) // read value to OR in
addi a1, a1, 1 addi a1, a1, 1
or t0, t0, t1 or t0, t0, t1
sw t0, FESPI_REG_FMT(a0) sw t0, FESPI_REG_FMT(a0)
j main j main
@ -565,24 +573,24 @@ set_dir:
// ALGO_END // ALGO_END
*/ */
static const uint8_t algorithm_bin[] = { static const uint8_t algorithm_bin[] = {
0x6f, 0x00, 0xc0, 0x01, 0x73, 0x00, 0x10, 0x00, 0x6f, 0x00, 0xc0, 0x02, 0x6f, 0x00, 0xc0, 0x01, 0x73, 0x00, 0x10, 0x00, 0x6f, 0x00, 0xc0, 0x02,
0x6f, 0x00, 0x00, 0x05, 0x6f, 0x00, 0xc0, 0x05, 0x6f, 0x00, 0x00, 0x07, 0x6f, 0x00, 0x00, 0x05, 0x6f, 0x00, 0xc0, 0x05, 0x6f, 0x00, 0x00, 0x07,
0x6f, 0x00, 0x00, 0x0a, 0x83, 0xc2, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00, 0x6f, 0x00, 0x00, 0x0a, 0x83, 0xc2, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0x17, 0x03, 0x00, 0x00, 0x13, 0x03, 0xc3, 0xfd, 0xb3, 0x82, 0x62, 0x00, 0x17, 0x03, 0x00, 0x00, 0x13, 0x03, 0xc3, 0xfd, 0xb3, 0x82, 0x62, 0x00,
0x67, 0x80, 0x02, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00, 0x67, 0x80, 0x02, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe, 0x83, 0xc2, 0x05, 0x00, 0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe, 0x83, 0xc2, 0x05, 0x00,
0x23, 0x24, 0x55, 0x04, 0x93, 0x85, 0x15, 0x00, 0x13, 0x03, 0xf3, 0xff, 0x23, 0x24, 0x55, 0x04, 0x93, 0x85, 0x15, 0x00, 0x13, 0x03, 0xf3, 0xff,
0xe3, 0x44, 0x60, 0xfe, 0x6f, 0xf0, 0x5f, 0xfc, 0x83, 0x22, 0x45, 0x07, 0xe3, 0x44, 0x60, 0xfe, 0x6f, 0xf0, 0x5f, 0xfc, 0x83, 0x22, 0x45, 0x07,
0x93, 0xf2, 0x12, 0x00, 0xe3, 0x8c, 0x02, 0xfe, 0x6f, 0xf0, 0x5f, 0xfb, 0x93, 0xf2, 0x12, 0x00, 0xe3, 0x8c, 0x02, 0xfe, 0x6f, 0xf0, 0x5f, 0xfb,
0x83, 0xc2, 0x05, 0x00, 0xb3, 0x82, 0xa2, 0x00, 0x03, 0xc3, 0x15, 0x00, 0x83, 0xc2, 0x05, 0x00, 0xb3, 0x82, 0xa2, 0x00, 0x03, 0xc3, 0x15, 0x00,
0x93, 0x85, 0x25, 0x00, 0x23, 0xa0, 0x62, 0x00, 0x6f, 0xf0, 0xdf, 0xf9, 0x93, 0x85, 0x25, 0x00, 0x23, 0xa0, 0x62, 0x00, 0x6f, 0xf0, 0xdf, 0xf9,
0x13, 0x06, 0x50, 0x00, 0xef, 0x00, 0x80, 0x01, 0x13, 0x06, 0x00, 0x00, 0x13, 0x06, 0x50, 0x00, 0xef, 0x00, 0x80, 0x01, 0x13, 0x06, 0x00, 0x00,
0xef, 0x00, 0x00, 0x01, 0x93, 0x72, 0x16, 0x00, 0xe3, 0x9a, 0x02, 0xfe, 0xef, 0x00, 0x00, 0x01, 0x93, 0x72, 0x16, 0x00, 0xe3, 0x9a, 0x02, 0xfe,
0x6f, 0xf0, 0x1f, 0xf8, 0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe, 0x6f, 0xf0, 0x1f, 0xf8, 0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe,
0x23, 0x24, 0xc5, 0x04, 0x03, 0x26, 0xc5, 0x04, 0xe3, 0x4e, 0x06, 0xfe, 0x23, 0x24, 0xc5, 0x04, 0x03, 0x26, 0xc5, 0x04, 0xe3, 0x4e, 0x06, 0xfe,
0x67, 0x80, 0x00, 0x00, 0x83, 0x22, 0x05, 0x04, 0x13, 0x03, 0x70, 0xff, 0x67, 0x80, 0x00, 0x00, 0x83, 0x22, 0x05, 0x04, 0x13, 0x03, 0x70, 0xff,
0xb3, 0xf2, 0x62, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00, 0xb3, 0xf2, 0x62, 0x00, 0x03, 0xc3, 0x05, 0x00, 0x93, 0x85, 0x15, 0x00,
0xb3, 0xe2, 0x62, 0x00, 0x23, 0x20, 0x55, 0x04, 0x6f, 0xf0, 0x9f, 0xf4 0xb3, 0xe2, 0x62, 0x00, 0x23, 0x20, 0x55, 0x04, 0x6f, 0xf0, 0x9f, 0xf4
}; };
#define STEP_EXIT 4 #define STEP_EXIT 4
#define STEP_TX 8 #define STEP_TX 8
@ -625,7 +633,7 @@ static int as_empty(struct algorithm_steps *as)
return 1; return 1;
} }
// Return size of compiled program. /* Return size of compiled program. */
static unsigned as_compile(struct algorithm_steps *as, uint8_t *target, static unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
unsigned target_size) unsigned target_size)
{ {
@ -684,9 +692,8 @@ static unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
LOG_DEBUG("%d-byte program:", offset); LOG_DEBUG("%d-byte program:", offset);
for (unsigned i = 0; i < offset;) { for (unsigned i = 0; i < offset;) {
char buf[80]; char buf[80];
for (unsigned x = 0; i < offset && x < 16; x++, i++) { for (unsigned x = 0; i < offset && x < 16; x++, i++)
sprintf(buf + x*3, "%02x ", target[i]); sprintf(buf + x*3, "%02x ", target[i]);
}
LOG_DEBUG("%s", buf); LOG_DEBUG("%s", buf);
} }
@ -771,7 +778,7 @@ static int steps_add_buffer_write(struct algorithm_steps *as,
as_add_txwm_wait(as); as_add_txwm_wait(as);
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO); as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
// fespi_wip() /* fespi_wip() */
as_add_set_dir(as, FESPI_DIR_RX); as_add_set_dir(as, FESPI_DIR_RX);
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD); as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
as_add_wip_wait(as); as_add_wip_wait(as);
@ -908,11 +915,10 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
cur_count = 4 - (offset & 3); cur_count = 4 - (offset & 3);
if (cur_count > count) if (cur_count > count)
cur_count = count; cur_count = count;
if (algorithm_wa) { if (algorithm_wa)
retval = steps_add_buffer_write(as, buffer, offset, cur_count); retval = steps_add_buffer_write(as, buffer, offset, cur_count);
} else { else
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count); retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
}
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto err; goto err;
offset += cur_count; offset += cur_count;
@ -929,11 +935,10 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
else else
cur_count = count & ~3; cur_count = count & ~3;
if (algorithm_wa) { if (algorithm_wa)
retval = steps_add_buffer_write(as, buffer, offset, cur_count); retval = steps_add_buffer_write(as, buffer, offset, cur_count);
} else { else
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count); retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
}
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto err; goto err;
@ -945,18 +950,16 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
/* buffer tail */ /* buffer tail */
if (count > 0) { if (count > 0) {
if (algorithm_wa) { if (algorithm_wa)
retval = steps_add_buffer_write(as, buffer, offset, count); retval = steps_add_buffer_write(as, buffer, offset, count);
} else { else
retval = slow_fespi_write_buffer(bank, buffer, offset, count); retval = slow_fespi_write_buffer(bank, buffer, offset, count);
}
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto err; goto err;
} }
if (algorithm_wa) { if (algorithm_wa)
retval = steps_execute(as, bank, algorithm_wa, data_wa); retval = steps_execute(as, bank, algorithm_wa, data_wa);
}
err: err:
if (algorithm_wa) { if (algorithm_wa) {
@ -1043,27 +1046,27 @@ static int fespi_probe(struct flash_bank *bank)
fespi_info->probed = 0; fespi_info->probed = 0;
if (fespi_info->ctrl_base == 0) { if (fespi_info->ctrl_base == 0) {
for (target_device = target_devices ; target_device->name ; ++target_device) for (target_device = target_devices ; target_device->name ; ++target_device)
if (target_device->tap_idcode == target->tap->idcode) if (target_device->tap_idcode == target->tap->idcode)
break; break;
if (!target_device->name) { if (!target_device->name) {
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable", LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
target->tap->idcode); target->tap->idcode);
return ERROR_FAIL; return ERROR_FAIL;
} }
fespi_info->ctrl_base = target_device->ctrl_base; fespi_info->ctrl_base = target_device->ctrl_base;
LOG_DEBUG("Valid FESPI on device %s at address 0x%" PRIx32, LOG_DEBUG("Valid FESPI on device %s at address 0x%" PRIx32,
target_device->name, bank->base); target_device->name, bank->base);
} else { } else {
LOG_DEBUG("Assuming FESPI as specified at address 0x%x with ctrl at 0x%x", LOG_DEBUG("Assuming FESPI as specified at address 0x%x with ctrl at 0x%x",
fespi_info->ctrl_base, fespi_info->ctrl_base,
bank->base); bank->base);
} }
ctrl_base = fespi_info->ctrl_base; ctrl_base = fespi_info->ctrl_base;
/* read and decode flash ID; returns in SW mode */ /* read and decode flash ID; returns in SW mode */
FESPI_WRITE_REG(FESPI_REG_TXCTRL, FESPI_TXWM(1)); FESPI_WRITE_REG(FESPI_REG_TXCTRL, FESPI_TXWM(1));

View File

@ -76,10 +76,8 @@ static void remote_bitbang_fill_buf(void)
contiguous_available_space); contiguous_available_space);
if (count > 0) { if (count > 0) {
remote_bitbang_end += count; remote_bitbang_end += count;
// TODO: check for overflow. if (remote_bitbang_end == sizeof(remote_bitbang_buf))
if (remote_bitbang_end == sizeof(remote_bitbang_buf)) {
remote_bitbang_end = 0; remote_bitbang_end = 0;
}
} else if (count == 0) { } else if (count == 0) {
return; return;
} else if (count < 0) { } else if (count < 0) {
@ -171,7 +169,7 @@ static int remote_bitbang_read_sample(void)
{ {
if (remote_bitbang_start != remote_bitbang_end) { if (remote_bitbang_start != remote_bitbang_end) {
int c = remote_bitbang_buf[remote_bitbang_start]; int c = remote_bitbang_buf[remote_bitbang_start];
remote_bitbang_start = remote_bitbang_start =
(remote_bitbang_start + 1) % sizeof(remote_bitbang_buf); (remote_bitbang_start + 1) % sizeof(remote_bitbang_buf);
return char_to_int(c); return char_to_int(c);
} }

View File

@ -79,7 +79,7 @@ static int riscv_gdb_thread_packet(struct connection *connection, const char *pa
if (strncmp(packet, "qfThreadInfo", 12) == 0) { if (strncmp(packet, "qfThreadInfo", 12) == 0) {
riscv_update_threads(target->rtos); riscv_update_threads(target->rtos);
r->qs_thread_info_offset = 1; r->qs_thread_info_offset = 1;
char m[16]; char m[16];
snprintf(m, 16, "m%08x", (int)rtos->thread_details[0].threadid); snprintf(m, 16, "m%08x", (int)rtos->thread_details[0].threadid);
gdb_put_packet(connection, m, strlen(m)); gdb_put_packet(connection, m, strlen(m));
@ -305,8 +305,7 @@ static int riscv_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[])
return JIM_OK; return JIM_OK;
} }
const struct rtos_type riscv_rtos = const struct rtos_type riscv_rtos = {
{
.name = "riscv", .name = "riscv",
.detect_rtos = riscv_detect_rtos, .detect_rtos = riscv_detect_rtos,
.create = riscv_create_rtos, .create = riscv_create_rtos,

View File

@ -1286,10 +1286,10 @@ static int gdb_get_register_packet(struct connection *connection,
} }
if (!reg_list[reg_num]->valid) { if (!reg_list[reg_num]->valid) {
retval = reg_list[reg_num]->type->get(reg_list[reg_num]); retval = reg_list[reg_num]->type->get(reg_list[reg_num]);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name); LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name);
free (reg_list); free(reg_list);
return gdb_error(connection, retval); return gdb_error(connection, retval);
} }
} }
@ -1347,7 +1347,7 @@ static int gdb_set_register_packet(struct connection *connection,
gdb_target_to_reg(target, separator + 1, chars, bin_buf); gdb_target_to_reg(target, separator + 1, chars, bin_buf);
retval = reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf); retval = reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf);
if (retval != ERROR_OK){ if (retval != ERROR_OK) {
LOG_DEBUG("Couldn't set register %s.", reg_list[reg_num]->name); LOG_DEBUG("Couldn't set register %s.", reg_list[reg_num]->name);
free(bin_buf); free(bin_buf);
free(reg_list); free(reg_list);

View File

@ -17,7 +17,7 @@ static uint32_t load(const struct target *target, unsigned int rd,
return ld(rd, base, offset); return ld(rd, base, offset);
} }
assert(0); assert(0);
return 0; // Silence -Werror=return-type return 0; /* Silence -Werror=return-type */
} }
static uint32_t store(const struct target *target, unsigned int src, static uint32_t store(const struct target *target, unsigned int src,
@ -32,7 +32,7 @@ static uint32_t store(const struct target *target, unsigned int src,
return sd(src, base, offset); return sd(src, base, offset);
} }
assert(0); assert(0);
return 0; // Silence -Werror=return-type return 0; /* Silence -Werror=return-type */
} }
#endif #endif

View File

@ -138,8 +138,8 @@ void riscv_batch_add_nop(struct riscv_batch *batch)
void dump_field(const struct scan_field *field) void dump_field(const struct scan_field *field)
{ {
static const char *op_string[] = {"-", "r", "w", "?"}; static const char * const op_string[] = {"-", "r", "w", "?"};
static const char *status_string[] = {"+", "?", "F", "b"}; static const char * const status_string[] = {"+", "?", "F", "b"};
if (debug_level < LOG_LVL_DEBUG) if (debug_level < LOG_LVL_DEBUG)
return; return;

View File

@ -295,7 +295,7 @@
* *
* Other values are reserved for future use. * Other values are reserved for future use.
*/ */
#define CSR_TDATA1_TYPE_OFFSET XLEN-4 #define CSR_TDATA1_TYPE_OFFSET (XLEN-4)
#define CSR_TDATA1_TYPE_LENGTH 4 #define CSR_TDATA1_TYPE_LENGTH 4
#define CSR_TDATA1_TYPE (0xfULL << CSR_TDATA1_TYPE_OFFSET) #define CSR_TDATA1_TYPE (0xfULL << CSR_TDATA1_TYPE_OFFSET)
/* /*
@ -307,14 +307,14 @@
* *
* This bit is only writable from Debug Mode. * This bit is only writable from Debug Mode.
*/ */
#define CSR_TDATA1_DMODE_OFFSET XLEN-5 #define CSR_TDATA1_DMODE_OFFSET (XLEN-5)
#define CSR_TDATA1_DMODE_LENGTH 1 #define CSR_TDATA1_DMODE_LENGTH 1
#define CSR_TDATA1_DMODE (0x1ULL << CSR_TDATA1_DMODE_OFFSET) #define CSR_TDATA1_DMODE (0x1ULL << CSR_TDATA1_DMODE_OFFSET)
/* /*
* Trigger-specific data. * Trigger-specific data.
*/ */
#define CSR_TDATA1_DATA_OFFSET 0 #define CSR_TDATA1_DATA_OFFSET 0
#define CSR_TDATA1_DATA_LENGTH XLEN - 5 #define CSR_TDATA1_DATA_LENGTH (XLEN - 5)
#define CSR_TDATA1_DATA (((1L<<XLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET) #define CSR_TDATA1_DATA (((1L<<XLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET)
#define CSR_TDATA2 0x7a2 #define CSR_TDATA2 0x7a2
#define CSR_TDATA2_DATA_OFFSET 0 #define CSR_TDATA2_DATA_OFFSET 0
@ -325,10 +325,10 @@
#define CSR_TDATA3_DATA_LENGTH XLEN #define CSR_TDATA3_DATA_LENGTH XLEN
#define CSR_TDATA3_DATA (((1L<<XLEN)-1) << CSR_TDATA3_DATA_OFFSET) #define CSR_TDATA3_DATA (((1L<<XLEN)-1) << CSR_TDATA3_DATA_OFFSET)
#define CSR_MCONTROL 0x7a1 #define CSR_MCONTROL 0x7a1
#define CSR_MCONTROL_TYPE_OFFSET XLEN-4 #define CSR_MCONTROL_TYPE_OFFSET (XLEN-4)
#define CSR_MCONTROL_TYPE_LENGTH 4 #define CSR_MCONTROL_TYPE_LENGTH 4
#define CSR_MCONTROL_TYPE (0xfULL << CSR_MCONTROL_TYPE_OFFSET) #define CSR_MCONTROL_TYPE (0xfULL << CSR_MCONTROL_TYPE_OFFSET)
#define CSR_MCONTROL_DMODE_OFFSET XLEN-5 #define CSR_MCONTROL_DMODE_OFFSET (XLEN-5)
#define CSR_MCONTROL_DMODE_LENGTH 1 #define CSR_MCONTROL_DMODE_LENGTH 1
#define CSR_MCONTROL_DMODE (0x1ULL << CSR_MCONTROL_DMODE_OFFSET) #define CSR_MCONTROL_DMODE (0x1ULL << CSR_MCONTROL_DMODE_OFFSET)
/* /*
@ -339,7 +339,7 @@
* corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in * corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in
* size. * size.
*/ */
#define CSR_MCONTROL_MASKMAX_OFFSET XLEN-11 #define CSR_MCONTROL_MASKMAX_OFFSET (XLEN-11)
#define CSR_MCONTROL_MASKMAX_LENGTH 6 #define CSR_MCONTROL_MASKMAX_LENGTH 6
#define CSR_MCONTROL_MASKMAX (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET) #define CSR_MCONTROL_MASKMAX (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET)
/* /*
@ -478,10 +478,10 @@
#define CSR_MCONTROL_LOAD_LENGTH 1 #define CSR_MCONTROL_LOAD_LENGTH 1
#define CSR_MCONTROL_LOAD (0x1ULL << CSR_MCONTROL_LOAD_OFFSET) #define CSR_MCONTROL_LOAD (0x1ULL << CSR_MCONTROL_LOAD_OFFSET)
#define CSR_ICOUNT 0x7a1 #define CSR_ICOUNT 0x7a1
#define CSR_ICOUNT_TYPE_OFFSET XLEN-4 #define CSR_ICOUNT_TYPE_OFFSET (XLEN-4)
#define CSR_ICOUNT_TYPE_LENGTH 4 #define CSR_ICOUNT_TYPE_LENGTH 4
#define CSR_ICOUNT_TYPE (0xfULL << CSR_ICOUNT_TYPE_OFFSET) #define CSR_ICOUNT_TYPE (0xfULL << CSR_ICOUNT_TYPE_OFFSET)
#define CSR_ICOUNT_DMODE_OFFSET XLEN-5 #define CSR_ICOUNT_DMODE_OFFSET (XLEN-5)
#define CSR_ICOUNT_DMODE_LENGTH 1 #define CSR_ICOUNT_DMODE_LENGTH 1
#define CSR_ICOUNT_DMODE (0x1ULL << CSR_ICOUNT_DMODE_OFFSET) #define CSR_ICOUNT_DMODE (0x1ULL << CSR_ICOUNT_DMODE_OFFSET)
/* /*

View File

@ -1,8 +1,8 @@
#ifndef TARGET__RISCV__GDB_REGS_H #ifndef TARGET__RISCV__GDB_REGS_H
#define TARGET__RISCV__GDB_REGS_H #define TARGET__RISCV__GDB_REGS_H
// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in /* gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in
// its source tree. We must interpret the numbers the same here. * its source tree. We must interpret the numbers the same here. */
enum gdb_regno { enum gdb_regno {
GDB_REGNO_ZERO = 0, /* Read-only register, always 0. */ GDB_REGNO_ZERO = 0, /* Read-only register, always 0. */
GDB_REGNO_RA = 1, /* Return Address. */ GDB_REGNO_RA = 1, /* Return Address. */

View File

@ -5,16 +5,19 @@
#define S0 8 #define S0 8
#define S1 9 #define S1 9
static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) { static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo)
{
return (value >> lo) & ((1 << (hi+1-lo)) - 1); return (value >> lo) & ((1 << (hi+1-lo)) - 1);
} }
static uint32_t bit(uint32_t value, unsigned int b) { static uint32_t bit(uint32_t value, unsigned int b)
{
return (value >> b) & 1; return (value >> b) & 1;
} }
static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused)); static uint32_t jal(unsigned int rd, uint32_t imm) __attribute__ ((unused));
static uint32_t jal(unsigned int rd, uint32_t imm) { static uint32_t jal(unsigned int rd, uint32_t imm)
{
return (bit(imm, 20) << 31) | return (bit(imm, 20) << 31) |
(bits(imm, 10, 1) << 21) | (bits(imm, 10, 1) << 21) |
(bit(imm, 11) << 20) | (bit(imm, 11) << 20) |
@ -24,7 +27,8 @@ static uint32_t jal(unsigned int rd, uint32_t imm) {
} }
static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused)); static uint32_t csrsi(unsigned int csr, uint16_t imm) __attribute__ ((unused));
static uint32_t csrsi(unsigned int csr, uint16_t imm) { static uint32_t csrsi(unsigned int csr, uint16_t imm)
{
return (csr << 20) | return (csr << 20) |
(bits(imm, 4, 0) << 15) | (bits(imm, 4, 0) << 15) |
MATCH_CSRRSI; MATCH_CSRRSI;
@ -107,7 +111,8 @@ static uint32_t lb(unsigned int rd, unsigned int base, uint16_t offset)
} }
static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused)); static uint32_t csrw(unsigned int source, unsigned int csr) __attribute__ ((unused));
static uint32_t csrw(unsigned int source, unsigned int csr) { static uint32_t csrw(unsigned int source, unsigned int csr)
{
return (csr << 20) | (source << 15) | MATCH_CSRRW; return (csr << 20) | (source << 15) | MATCH_CSRRW;
} }
@ -121,17 +126,20 @@ static uint32_t addi(unsigned int dest, unsigned int src, uint16_t imm)
} }
static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused)); static uint32_t csrr(unsigned int rd, unsigned int csr) __attribute__ ((unused));
static uint32_t csrr(unsigned int rd, unsigned int csr) { static uint32_t csrr(unsigned int rd, unsigned int csr)
{
return (csr << 20) | (rd << 7) | MATCH_CSRRS; return (csr << 20) | (rd << 7) | MATCH_CSRRS;
} }
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused)); static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr) { static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr)
{
return (csr << 20) | (rs << 15) | (rd << 7) | MATCH_CSRRS; return (csr << 20) | (rs << 15) | (rd << 7) | MATCH_CSRRS;
} }
static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused)); static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) __attribute__ ((unused));
static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr) { static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr)
{
return (csr << 20) | (rs << 15) | (rd << 7) | MATCH_CSRRW; return (csr << 20) | (rs << 15) | (rd << 7) | MATCH_CSRRW;
} }
@ -206,9 +214,15 @@ static uint32_t fmv_d_x(unsigned dest, unsigned src)
} }
static uint32_t ebreak(void) __attribute__ ((unused)); static uint32_t ebreak(void) __attribute__ ((unused));
static uint32_t ebreak(void) { return MATCH_EBREAK; } static uint32_t ebreak(void)
{
return MATCH_EBREAK;
}
static uint32_t ebreak_c(void) __attribute__ ((unused)); static uint32_t ebreak_c(void) __attribute__ ((unused));
static uint32_t ebreak_c(void) { return MATCH_C_EBREAK; } static uint32_t ebreak_c(void)
{
return MATCH_C_EBREAK;
}
static uint32_t fence_i(void) __attribute__ ((unused)); static uint32_t fence_i(void) __attribute__ ((unused));
static uint32_t fence_i(void) static uint32_t fence_i(void)
@ -226,7 +240,8 @@ static uint32_t lui(unsigned int dest, uint32_t imm)
/* /*
static uint32_t csrci(unsigned int csr, uint16_t imm) __attribute__ ((unused)); static uint32_t csrci(unsigned int csr, uint16_t imm) __attribute__ ((unused));
static uint32_t csrci(unsigned int csr, uint16_t imm) { static uint32_t csrci(unsigned int csr, uint16_t imm)
{
return (csr << 20) | return (csr << 20) |
(bits(imm, 4, 0) << 15) | (bits(imm, 4, 0) << 15) |
MATCH_CSRRCI; MATCH_CSRRCI;

View File

@ -18,11 +18,10 @@ int riscv_program_init(struct riscv_program *p, struct target *target)
p->target = target; p->target = target;
p->instruction_count = 0; p->instruction_count = 0;
p->target_xlen = riscv_xlen(target); p->target_xlen = riscv_xlen(target);
for (size_t i = 0; i < RISCV_REGISTER_COUNT; ++i) { for (size_t i = 0; i < RISCV_REGISTER_COUNT; ++i)
p->writes_xreg[i] = 0; p->writes_xreg[i] = 0;
}
for(size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i) for (size_t i = 0; i < RISCV_MAX_DEBUG_BUFFER_SIZE; ++i)
p->debug_buffer[i] = -1; p->debug_buffer[i] = -1;
return ERROR_OK; return ERROR_OK;
@ -54,7 +53,7 @@ int riscv_program_exec(struct riscv_program *p, struct target *t)
if (riscv_program_ebreak(p) != ERROR_OK) { if (riscv_program_ebreak(p) != ERROR_OK) {
LOG_ERROR("Unable to write ebreak"); LOG_ERROR("Unable to write ebreak");
for(size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i) for (size_t i = 0; i < riscv_debug_buffer_size(p->target); ++i)
LOG_ERROR("ram[%02x]: DASM(0x%08lx) [0x%08lx]", (int)i, (long)p->debug_buffer[i], (long)p->debug_buffer[i]); LOG_ERROR("ram[%02x]: DASM(0x%08lx) [0x%08lx]", (int)i, (long)p->debug_buffer[i], (long)p->debug_buffer[i]);
abort(); abort();
return ERROR_FAIL; return ERROR_FAIL;

File diff suppressed because it is too large Load Diff

View File

@ -150,20 +150,20 @@ typedef struct {
/* We only need the address so that we know the alignment of the buffer. */ /* We only need the address so that we know the alignment of the buffer. */
riscv_addr_t progbuf_address; riscv_addr_t progbuf_address;
// Number of run-test/idle cycles the target requests we do after each dbus /* Number of run-test/idle cycles the target requests we do after each dbus
// access. * access. */
unsigned int dtmcontrol_idle; unsigned int dtmcontrol_idle;
// This value is incremented every time a dbus access comes back as "busy". /* This value is incremented every time a dbus access comes back as "busy".
// It's used to determine how many run-test/idle cycles to feed the target * It's used to determine how many run-test/idle cycles to feed the target
// in between accesses. * in between accesses. */
unsigned int dmi_busy_delay; unsigned int dmi_busy_delay;
// This value is increased every time we tried to execute two commands /* This value is increased every time we tried to execute two commands
// consecutively, and the second one failed because the previous hadn't * consecutively, and the second one failed because the previous hadn't
// completed yet. It's used to add extra run-test/idle cycles after * completed yet. It's used to add extra run-test/idle cycles after
// starting a command, so we don't have to waste time checking for busy to * starting a command, so we don't have to waste time checking for busy to
// go low. * go low. */
unsigned int ac_busy_delay; unsigned int ac_busy_delay;
bool need_strict_step; bool need_strict_step;
@ -173,12 +173,12 @@ typedef struct {
bool abstract_read_fpr_supported; bool abstract_read_fpr_supported;
bool abstract_write_fpr_supported; bool abstract_write_fpr_supported;
// When a function returns some error due to a failure indicated by the /* When a function returns some error due to a failure indicated by the
// target in cmderr, the caller can look here to see what that error was. * target in cmderr, the caller can look here to see what that error was.
// (Compare with errno.) * (Compare with errno.) */
uint8_t cmderr; uint8_t cmderr;
// Some fields from hartinfo. /* Some fields from hartinfo. */
uint8_t datasize; uint8_t datasize;
uint8_t dataaccess; uint8_t dataaccess;
int16_t dataaddr; int16_t dataaddr;
@ -232,7 +232,7 @@ static void decode_dmi(char *text, unsigned address, unsigned data)
if (i > 0) if (i > 0)
*(text++) = ' '; *(text++) = ' ';
if (mask & (mask >> 1)) { if (mask & (mask >> 1)) {
// If the field is more than 1 bit wide. /* If the field is more than 1 bit wide. */
sprintf(text, "%s=%d", description[i].name, value); sprintf(text, "%s=%d", description[i].name, value);
} else { } else {
strcpy(text, description[i].name); strcpy(text, description[i].name);
@ -245,8 +245,8 @@ static void decode_dmi(char *text, unsigned address, unsigned data)
static void dump_field(const struct scan_field *field) static void dump_field(const struct scan_field *field)
{ {
static const char *op_string[] = {"-", "r", "w", "?"}; static const char * const op_string[] = {"-", "r", "w", "?"};
static const char *status_string[] = {"+", "?", "F", "b"}; static const char * const status_string[] = {"+", "?", "F", "b"};
if (debug_level < LOG_LVL_DEBUG) if (debug_level < LOG_LVL_DEBUG)
return; return;
@ -371,9 +371,8 @@ static dmi_status_t dmi_scan(struct target *target, uint16_t *address_in,
if (exec) if (exec)
idle_count += info->ac_busy_delay; idle_count += info->ac_busy_delay;
if (idle_count) { if (idle_count)
jtag_add_runtest(idle_count, TAP_IDLE); jtag_add_runtest(idle_count, TAP_IDLE);
}
int retval = jtag_execute_queue(); int retval = jtag_execute_queue();
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
@ -381,13 +380,11 @@ static dmi_status_t dmi_scan(struct target *target, uint16_t *address_in,
return DMI_STATUS_FAILED; return DMI_STATUS_FAILED;
} }
if (data_in) { if (data_in)
*data_in = buf_get_u64(in, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH); *data_in = buf_get_u64(in, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH);
}
if (address_in) { if (address_in)
*address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits); *address_in = buf_get_u32(in, DTM_DMI_ADDRESS_OFFSET, info->abits);
}
dump_field(&field); dump_field(&field);
@ -403,9 +400,9 @@ static uint64_t dmi_read(struct target *target, uint16_t address)
unsigned i = 0; unsigned i = 0;
// This first loop ensures that the read request was actually sent /* This first loop ensures that the read request was actually sent
// to the target. Note that if for some reason this stays busy, * to the target. Note that if for some reason this stays busy,
// it is actually due to the previous dmi_read or dmi_write. * it is actually due to the previous dmi_read or dmi_write. */
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
status = dmi_scan(target, NULL, NULL, DMI_OP_READ, address, 0, status = dmi_scan(target, NULL, NULL, DMI_OP_READ, address, 0,
false); false);
@ -424,9 +421,9 @@ static uint64_t dmi_read(struct target *target, uint16_t address)
abort(); abort();
} }
// This second loop ensures that we got the read /* This second loop ensures that we got the read
// data back. Note that NOP can result in a 'busy' result as well, but * data back. Note that NOP can result in a 'busy' result as well, but
// that would be noticed on the next DMI access we do. * that would be noticed on the next DMI access we do. */
uint64_t value; uint64_t value;
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
status = dmi_scan(target, &address_in, &value, DMI_OP_NOP, address, 0, status = dmi_scan(target, &address_in, &value, DMI_OP_NOP, address, 0,
@ -456,7 +453,7 @@ static void dmi_write(struct target *target, uint16_t address, uint64_t value)
dmi_status_t status = DMI_STATUS_BUSY; dmi_status_t status = DMI_STATUS_BUSY;
unsigned i = 0; unsigned i = 0;
// The first loop ensures that we successfully sent the write request. /* The first loop ensures that we successfully sent the write request. */
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
status = dmi_scan(target, NULL, NULL, DMI_OP_WRITE, address, value, status = dmi_scan(target, NULL, NULL, DMI_OP_WRITE, address, value,
address == DMI_COMMAND); address == DMI_COMMAND);
@ -476,8 +473,9 @@ static void dmi_write(struct target *target, uint16_t address, uint64_t value)
abort(); abort();
} }
// The second loop isn't strictly necessary, but would ensure that /* The second loop isn't strictly necessary, but would ensure that the
// the write is complete/ has no non-busy errors before returning from this function. * write is complete/ has no non-busy errors before returning from this
* function. */
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
status = dmi_scan(target, NULL, NULL, DMI_OP_NOP, address, 0, status = dmi_scan(target, NULL, NULL, DMI_OP_NOP, address, 0,
false); false);
@ -529,9 +527,8 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
while (1) { while (1) {
*abstractcs = dmi_read(target, DMI_ABSTRACTCS); *abstractcs = dmi_read(target, DMI_ABSTRACTCS);
if (get_field(*abstractcs, DMI_ABSTRACTCS_BUSY) == 0) { if (get_field(*abstractcs, DMI_ABSTRACTCS_BUSY) == 0)
return ERROR_OK; return ERROR_OK;
}
if (time(NULL) - start > riscv_command_timeout_sec) { if (time(NULL) - start > riscv_command_timeout_sec) {
info->cmderr = get_field(*abstractcs, DMI_ABSTRACTCS_CMDERR); info->cmderr = get_field(*abstractcs, DMI_ABSTRACTCS_CMDERR);
@ -551,9 +548,9 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
} }
LOG_ERROR("Timed out after %ds waiting for busy to go low (abstractcs=0x%x). " LOG_ERROR("Timed out after %ds waiting for busy to go low (abstractcs=0x%x). "
"Increase the timeout with riscv set_command_timeout_sec.", "Increase the timeout with riscv set_command_timeout_sec.",
riscv_command_timeout_sec, riscv_command_timeout_sec,
*abstractcs); *abstractcs);
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
@ -574,7 +571,7 @@ static int execute_abstract_command(struct target *target, uint32_t command)
info->cmderr = get_field(cs, DMI_ABSTRACTCS_CMDERR); info->cmderr = get_field(cs, DMI_ABSTRACTCS_CMDERR);
if (info->cmderr != 0) { if (info->cmderr != 0) {
LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, cs); LOG_DEBUG("command 0x%x failed; abstractcs=0x%x", command, cs);
// Clear the error. /* Clear the error. */
dmi_write(target, DMI_ABSTRACTCS, set_field(0, DMI_ABSTRACTCS_CMDERR, dmi_write(target, DMI_ABSTRACTCS, set_field(0, DMI_ABSTRACTCS_CMDERR,
info->cmderr)); info->cmderr));
return ERROR_FAIL; return ERROR_FAIL;
@ -704,9 +701,8 @@ static int register_write_abstract(struct target *target, uint32_t number,
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE); AC_ACCESS_REGISTER_WRITE);
if (write_abstract_arg(target, 0, value) != ERROR_OK) { if (write_abstract_arg(target, 0, value) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
int result = execute_abstract_command(target, command); int result = execute_abstract_command(target, command);
if (result != ERROR_OK) { if (result != ERROR_OK) {
@ -732,7 +728,7 @@ static int examine_progbuf(struct target *target)
if (info->progbuf_writable != YNM_MAYBE) if (info->progbuf_writable != YNM_MAYBE)
return ERROR_OK; return ERROR_OK;
// Figure out if progbuf is writable. /* Figure out if progbuf is writable. */
if (info->progbufsize < 1) { if (info->progbufsize < 1) {
info->progbuf_writable = YNM_NO; info->progbuf_writable = YNM_NO;
@ -761,8 +757,8 @@ static int examine_progbuf(struct target *target)
return ERROR_FAIL; return ERROR_FAIL;
if (result != ERROR_OK) { if (result != ERROR_OK) {
// This program might have failed if the program buffer is not /* This program might have failed if the program buffer is not
// writable. * writable. */
info->progbuf_writable = YNM_NO; info->progbuf_writable = YNM_NO;
return ERROR_OK; return ERROR_OK;
} }
@ -789,11 +785,11 @@ typedef enum {
} memory_space_t; } memory_space_t;
typedef struct { typedef struct {
// How can the debugger access this memory? /* How can the debugger access this memory? */
memory_space_t memory_space; memory_space_t memory_space;
// Memory address to access the scratch memory from the hart. /* Memory address to access the scratch memory from the hart. */
riscv_addr_t hart_address; riscv_addr_t hart_address;
// Memory address to access the scratch memory from the debugger. /* Memory address to access the scratch memory from the debugger. */
riscv_addr_t debug_address; riscv_addr_t debug_address;
} scratch_mem_t; } scratch_mem_t;
@ -812,12 +808,11 @@ static int scratch_find(struct target *target,
alignment *= 2; alignment *= 2;
if (info->dataaccess == 1) { if (info->dataaccess == 1) {
// Sign extend dataaddr. /* Sign extend dataaddr. */
scratch->hart_address = info->dataaddr; scratch->hart_address = info->dataaddr;
if (info->dataaddr & (1<<11)) { if (info->dataaddr & (1<<11))
scratch->hart_address |= 0xfffffffffffff000ULL; scratch->hart_address |= 0xfffffffffffff000ULL;
} /* Align. */
// Align.
scratch->hart_address = (scratch->hart_address + alignment - 1) & ~(alignment - 1); scratch->hart_address = (scratch->hart_address + alignment - 1) & ~(alignment - 1);
if ((size_bytes + scratch->hart_address - info->dataaddr + 3) / 4 >= if ((size_bytes + scratch->hart_address - info->dataaddr + 3) / 4 >=
@ -831,8 +826,8 @@ static int scratch_find(struct target *target,
if (examine_progbuf(target) != ERROR_OK) if (examine_progbuf(target) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
// Allow for ebreak at the end of the program. /* Allow for ebreak at the end of the program. */
unsigned program_size = (program->instruction_count + 1 ) * 4; unsigned program_size = (program->instruction_count + 1) * 4;
scratch->hart_address = (info->progbuf_address + program_size + alignment - 1) & scratch->hart_address = (info->progbuf_address + program_size + alignment - 1) &
~(alignment - 1); ~(alignment - 1);
if ((size_bytes + scratch->hart_address - info->progbuf_address + 3) / 4 >= if ((size_bytes + scratch->hart_address - info->progbuf_address + 3) / 4 >=
@ -961,11 +956,10 @@ static int register_write_direct(struct target *target, unsigned number,
return ERROR_FAIL; return ERROR_FAIL;
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
if (riscv_supports_extension(target, 'D')) { if (riscv_supports_extension(target, 'D'))
riscv_program_insert(&program, fmv_d_x(number - GDB_REGNO_FPR0, S0)); riscv_program_insert(&program, fmv_d_x(number - GDB_REGNO_FPR0, S0));
} else { else
riscv_program_insert(&program, fmv_w_x(number - GDB_REGNO_FPR0, S0)); riscv_program_insert(&program, fmv_w_x(number - GDB_REGNO_FPR0, S0));
}
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
riscv_program_csrw(&program, S0, number); riscv_program_csrw(&program, S0, number);
} else { } else {
@ -976,7 +970,7 @@ static int register_write_direct(struct target *target, unsigned number,
int exec_out = riscv_program_exec(&program, target); int exec_out = riscv_program_exec(&program, target);
// Restore S0. /* Restore S0. */
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
@ -1004,10 +998,10 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK) if (register_read_direct(target, &s0, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
// Write program to move data into s0. /* Write program to move data into s0. */
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) {
// TODO: Possibly set F in mstatus. /* TODO: Possibly set F in mstatus. */
if (riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) { if (riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) {
/* There are no instructions to move all the bits from a /* There are no instructions to move all the bits from a
* register, so we need to use some scratch RAM. */ * register, so we need to use some scratch RAM. */
@ -1033,19 +1027,19 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
abort(); abort();
} }
// Execute program. /* Execute program. */
result = riscv_program_exec(&program, target); result = riscv_program_exec(&program, target);
if (use_scratch) { if (use_scratch) {
if (scratch_read64(target, &scratch, value) != ERROR_OK) if (scratch_read64(target, &scratch, value) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
} else { } else {
// Read S0 /* Read S0 */
if (register_read_direct(target, value, GDB_REGNO_S0) != ERROR_OK) if (register_read_direct(target, value, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
} }
// Restore S0. /* Restore S0. */
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -1094,11 +1088,11 @@ static int init_target(struct command_context *cmd_ctx,
info->dmi_busy_delay = 0; info->dmi_busy_delay = 0;
info->ac_busy_delay = 0; info->ac_busy_delay = 0;
// Assume all these abstract commands are supported until we learn /* Assume all these abstract commands are supported until we learn
// otherwise. * otherwise.
// TODO: The spec allows eg. one CSR to be able to be accessed abstractly * TODO: The spec allows eg. one CSR to be able to be accessed abstractly
// while another one isn't. We don't track that this closely here, but in * while another one isn't. We don't track that this closely here, but in
// the future we probably should. * the future we probably should. */
info->abstract_read_csr_supported = true; info->abstract_read_csr_supported = true;
info->abstract_write_csr_supported = true; info->abstract_write_csr_supported = true;
info->abstract_read_fpr_supported = true; info->abstract_read_fpr_supported = true;
@ -1117,7 +1111,7 @@ static void deinit_target(struct target *target)
static int examine(struct target *target) static int examine(struct target *target)
{ {
// Don't need to select dbus, since the first thing we do is read dtmcontrol. /* Don't need to select dbus, since the first thing we do is read dtmcontrol. */
uint32_t dtmcontrol = dtmcontrol_scan(target, 0); uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol); LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol);
@ -1147,7 +1141,7 @@ static int examine(struct target *target)
return ERROR_FAIL; return ERROR_FAIL;
} }
// Reset the Debug Module. /* Reset the Debug Module. */
dmi_write(target, DMI_DMCONTROL, 0); dmi_write(target, DMI_DMCONTROL, 0);
dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE); dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL); uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
@ -1184,7 +1178,7 @@ static int examine(struct target *target)
return ERROR_FAIL; return ERROR_FAIL;
} }
// Check that abstract data registers are accessible. /* Check that abstract data registers are accessible. */
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT); info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
info->progbufsize = get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE); info->progbufsize = get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE);
@ -1193,8 +1187,8 @@ static int examine(struct target *target)
RISCV_INFO(r); RISCV_INFO(r);
r->impebreak = get_field(dmstatus, DMI_DMSTATUS_IMPEBREAK); r->impebreak = get_field(dmstatus, DMI_DMSTATUS_IMPEBREAK);
// Don't call any riscv_* functions until after we've counted the number of /* Don't call any riscv_* functions until after we've counted the number of
// cores and initialized registers. * cores and initialized registers. */
for (int i = 0; i < RISCV_MAX_HARTS; ++i) { for (int i = 0; i < RISCV_MAX_HARTS; ++i) {
if (!riscv_rtos_enabled(target) && i != target->coreid) if (!riscv_rtos_enabled(target) && i != target->coreid)
continue; continue;
@ -1203,29 +1197,26 @@ static int examine(struct target *target)
riscv013_select_current_hart(target); riscv013_select_current_hart(target);
uint32_t s = dmi_read(target, DMI_DMSTATUS); uint32_t s = dmi_read(target, DMI_DMSTATUS);
if (get_field(s, DMI_DMSTATUS_ANYNONEXISTENT)) { if (get_field(s, DMI_DMSTATUS_ANYNONEXISTENT))
break; break;
}
r->hart_count = i + 1; r->hart_count = i + 1;
if (!riscv_is_halted(target)) { if (!riscv_is_halted(target))
riscv013_halt_current_hart(target); riscv013_halt_current_hart(target);
}
/* Without knowing anything else we can at least mess with the /* Without knowing anything else we can at least mess with the
* program buffer. */ * program buffer. */
r->debug_buffer_size[i] = info->progbufsize; r->debug_buffer_size[i] = info->progbufsize;
int result = register_read_abstract(target, NULL, GDB_REGNO_S0, 64); int result = register_read_abstract(target, NULL, GDB_REGNO_S0, 64);
if (result == ERROR_OK) { if (result == ERROR_OK)
r->xlen[i] = 64; r->xlen[i] = 64;
} else { else
r->xlen[i] = 32; r->xlen[i] = 32;
}
register_read_direct(target, &r->misa, GDB_REGNO_MISA); register_read_direct(target, &r->misa, GDB_REGNO_MISA);
// Now init registers based on what we discovered. /* Now init registers based on what we discovered. */
if (riscv_init_registers(target) != ERROR_OK) if (riscv_init_registers(target) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
@ -1241,19 +1232,18 @@ static int examine(struct target *target)
riscv_enumerate_triggers(target); riscv_enumerate_triggers(target);
/* Resumes all the harts, so the debugger can later pause them. */ /* Resumes all the harts, so the debugger can later pause them. */
// TODO: Only do this if the harts were halted to start with. /* TODO: Only do this if the harts were halted to start with. */
riscv_resume_all_harts(target); riscv_resume_all_harts(target);
target->state = TARGET_RUNNING; target->state = TARGET_RUNNING;
target_set_examined(target); target_set_examined(target);
if (target->rtos) { if (target->rtos)
riscv_update_threads(target->rtos); riscv_update_threads(target->rtos);
}
// Some regression suites rely on seeing 'Examined RISC-V core' to know /* Some regression suites rely on seeing 'Examined RISC-V core' to know
// when they can connect with gdb/telnet. * when they can connect with gdb/telnet.
// We will need to update those suites if we want to change that text. * We will need to update those suites if we want to change that text. */
LOG_INFO("Examined RISC-V core; found %d harts", LOG_INFO("Examined RISC-V core; found %d harts",
riscv_count_harts(target)); riscv_count_harts(target));
for (int i = 0; i < riscv_count_harts(target); ++i) { for (int i = 0; i < riscv_count_harts(target); ++i) {
@ -1276,12 +1266,12 @@ static int assert_reset(struct target *target)
uint32_t control_base = set_field(0, DMI_DMCONTROL_DMACTIVE, 1); uint32_t control_base = set_field(0, DMI_DMCONTROL_DMACTIVE, 1);
if (target->rtos) { if (target->rtos) {
// There's only one target, and OpenOCD thinks each hart is a thread. /* There's only one target, and OpenOCD thinks each hart is a thread.
// We must reset them all. * We must reset them all. */
// TODO: Try to use hasel in dmcontrol /* TODO: Try to use hasel in dmcontrol */
// Set haltreq/resumereq for each hart. /* Set haltreq/resumereq for each hart. */
uint32_t control = control_base; uint32_t control = control_base;
for (int i = 0; i < riscv_count_harts(target); ++i) { for (int i = 0; i < riscv_count_harts(target); ++i) {
if (!riscv_hart_enabled(target, i)) if (!riscv_hart_enabled(target, i))
@ -1292,12 +1282,12 @@ static int assert_reset(struct target *target)
target->reset_halt ? 1 : 0); target->reset_halt ? 1 : 0);
dmi_write(target, DMI_DMCONTROL, control); dmi_write(target, DMI_DMCONTROL, control);
} }
// Assert ndmreset /* Assert ndmreset */
control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
dmi_write(target, DMI_DMCONTROL, control); dmi_write(target, DMI_DMCONTROL, control);
} else { } else {
// Reset just this hart. /* Reset just this hart. */
uint32_t control = set_field(control_base, DMI_DMCONTROL_HARTSEL, uint32_t control = set_field(control_base, DMI_DMCONTROL_HARTSEL,
r->current_hartid); r->current_hartid);
control = set_field(control, DMI_DMCONTROL_HALTREQ, control = set_field(control, DMI_DMCONTROL_HALTREQ,
@ -1305,11 +1295,11 @@ static int assert_reset(struct target *target)
control = set_field(control, DMI_DMCONTROL_HARTRESET, 1); control = set_field(control, DMI_DMCONTROL_HARTRESET, 1);
dmi_write(target, DMI_DMCONTROL, control); dmi_write(target, DMI_DMCONTROL, control);
// Read back to check if hartreset is supported. /* Read back to check if hartreset is supported. */
uint32_t rb = dmi_read(target, DMI_DMCONTROL); uint32_t rb = dmi_read(target, DMI_DMCONTROL);
if (!get_field(rb, DMI_DMCONTROL_HARTRESET)) { if (!get_field(rb, DMI_DMCONTROL_HARTRESET)) {
// Use ndmreset instead. That will reset the entire device, but /* Use ndmreset instead. That will reset the entire device, but
// that's probably what OpenOCD wants anyway. * that's probably what OpenOCD wants anyway. */
control = set_field(control, DMI_DMCONTROL_HARTRESET, 0); control = set_field(control, DMI_DMCONTROL_HARTRESET, 0);
control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
dmi_write(target, DMI_DMCONTROL, control); dmi_write(target, DMI_DMCONTROL, control);
@ -1329,7 +1319,7 @@ static int deassert_reset(struct target *target)
LOG_DEBUG("%d", r->current_hartid); LOG_DEBUG("%d", r->current_hartid);
// Clear the reset, but make sure haltreq is still set /* Clear the reset, but make sure haltreq is still set */
uint32_t control = 0; uint32_t control = 0;
control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0);
control = set_field(control, DMI_DMCONTROL_HARTSEL, r->current_hartid); control = set_field(control, DMI_DMCONTROL_HARTSEL, r->current_hartid);
@ -1405,7 +1395,8 @@ static void write_to_buf(uint8_t *buffer, uint64_t value, unsigned size)
} }
} }
static int execute_fence(struct target *target) { static int execute_fence(struct target *target)
{
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
riscv_program_fence(&program); riscv_program_fence(&program);
@ -1441,7 +1432,7 @@ static int read_memory(struct target *target, target_addr_t address,
if (execute_fence(target) != ERROR_OK) if (execute_fence(target) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
// Write the program (load, increment) /* Write the program (load, increment) */
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
switch (size) { switch (size) {
@ -1464,7 +1455,7 @@ static int read_memory(struct target *target, target_addr_t address,
return ERROR_FAIL; return ERROR_FAIL;
riscv_program_write(&program); riscv_program_write(&program);
// Write address to S0, and execute buffer. /* Write address to S0, and execute buffer. */
if (register_write_direct(target, GDB_REGNO_S0, address) != ERROR_OK) if (register_write_direct(target, GDB_REGNO_S0, address) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
uint32_t command = access_register_command(GDB_REGNO_S1, riscv_xlen(target), uint32_t command = access_register_command(GDB_REGNO_S1, riscv_xlen(target),
@ -1473,27 +1464,27 @@ static int read_memory(struct target *target, target_addr_t address,
if (execute_abstract_command(target, command) != ERROR_OK) if (execute_abstract_command(target, command) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
// First read has just triggered. Result is in s1. /* First read has just triggered. Result is in s1. */
dmi_write(target, DMI_ABSTRACTAUTO, dmi_write(target, DMI_ABSTRACTAUTO,
1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
// read_addr is the next address that the hart will read from, which is the /* read_addr is the next address that the hart will read from, which is the
// value in s0. * value in s0. */
riscv_addr_t read_addr = address + size; riscv_addr_t read_addr = address + size;
// The next address that we need to receive data for. /* The next address that we need to receive data for. */
riscv_addr_t receive_addr = address; riscv_addr_t receive_addr = address;
riscv_addr_t fin_addr = address + (count * size); riscv_addr_t fin_addr = address + (count * size);
unsigned skip = 1; unsigned skip = 1;
while (read_addr < fin_addr) { while (read_addr < fin_addr) {
LOG_DEBUG("read_addr=0x%" PRIx64 ", receive_addr=0x%" PRIx64 LOG_DEBUG("read_addr=0x%" PRIx64 ", receive_addr=0x%" PRIx64
", fin_addr=0x%" PRIx64, read_addr, receive_addr, fin_addr); ", fin_addr=0x%" PRIx64, read_addr, receive_addr, fin_addr);
// The pipeline looks like this: /* The pipeline looks like this:
// memory -> s1 -> dm_data0 -> debugger * memory -> s1 -> dm_data0 -> debugger
// It advances every time the debugger reads dmdata0. * It advances every time the debugger reads dmdata0.
// So at any time the debugger has just read mem[s0 - 3*size], * So at any time the debugger has just read mem[s0 - 3*size],
// dm_data0 contains mem[s0 - 2*size] * dm_data0 contains mem[s0 - 2*size]
// s1 contains mem[s0-size] * s1 contains mem[s0-size] */
LOG_DEBUG("creating burst to read from 0x%" TARGET_PRIxADDR LOG_DEBUG("creating burst to read from 0x%" TARGET_PRIxADDR
" up to 0x%" TARGET_PRIxADDR, read_addr, fin_addr); " up to 0x%" TARGET_PRIxADDR, read_addr, fin_addr);
@ -1512,8 +1503,8 @@ static int read_memory(struct target *target, target_addr_t address,
riscv_batch_run(batch); riscv_batch_run(batch);
// Wait for the target to finish performing the last abstract command, /* Wait for the target to finish performing the last abstract command,
// and update our copy of cmderr. * and update our copy of cmderr. */
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
abstractcs = dmi_read(target, DMI_ABSTRACTCS); abstractcs = dmi_read(target, DMI_ABSTRACTCS);
@ -1538,7 +1529,7 @@ static int read_memory(struct target *target, target_addr_t address,
+#include <unistd.h> +#include <unistd.h>
+ +
#include <cassert> #include <cassert>
#include "debug_module.h" #include "debug_module.h"
@@ -398,6 +400,15 @@ bool debug_module_t::perform_abstract_command() @@ -398,6 +400,15 @@ bool debug_module_t::perform_abstract_command()
// Since the next instruction is what we will use, just use nother NOP // Since the next instruction is what we will use, just use nother NOP
@ -1562,17 +1553,17 @@ static int read_memory(struct target *target, target_addr_t address,
dmi_write(target, DMI_ABSTRACTAUTO, 0); dmi_write(target, DMI_ABSTRACTAUTO, 0);
// This is definitely a good version of the value that we /* This is definitely a good version of the value that we
// attempted to read when we discovered that the target was * attempted to read when we discovered that the target was
// busy. * busy. */
dmi_data0 = dmi_read(target, DMI_DATA0); dmi_data0 = dmi_read(target, DMI_DATA0);
// Clobbers DMI_DATA0. /* Clobbers DMI_DATA0. */
if (register_read_direct(target, &next_read_addr, GDB_REGNO_S0) != ERROR_OK) if (register_read_direct(target, &next_read_addr, GDB_REGNO_S0) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
// Restore the command, and execute it. /* Restore the command, and execute it.
// Now DMI_DATA0 contains the next value just as it would if no * Now DMI_DATA0 contains the next value just as it would if no
// error had occurred. * error had occurred. */
dmi_write(target, DMI_COMMAND, command); dmi_write(target, DMI_COMMAND, command);
dmi_write(target, DMI_ABSTRACTAUTO, dmi_write(target, DMI_ABSTRACTAUTO,
@ -1588,11 +1579,10 @@ static int read_memory(struct target *target, target_addr_t address,
return ERROR_FAIL; return ERROR_FAIL;
} }
// Now read whatever we got out of the batch. /* Now read whatever we got out of the batch. */
for (size_t i = 0; i < reads; i++) { for (size_t i = 0; i < reads; i++) {
if (read_addr >= next_read_addr) { if (read_addr >= next_read_addr)
break; break;
}
read_addr += size; read_addr += size;
@ -1625,14 +1615,14 @@ static int read_memory(struct target *target, target_addr_t address,
dmi_write(target, DMI_ABSTRACTAUTO, 0); dmi_write(target, DMI_ABSTRACTAUTO, 0);
if (count > 1) { if (count > 1) {
// Read the penultimate word. /* Read the penultimate word. */
uint64_t value = dmi_read(target, DMI_DATA0); uint64_t value = dmi_read(target, DMI_DATA0);
write_to_buf(buffer + receive_addr - address, value, size); write_to_buf(buffer + receive_addr - address, value, size);
LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%" PRIx64, receive_addr, value); LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%" PRIx64, receive_addr, value);
receive_addr += size; receive_addr += size;
} }
// Read the last word. /* Read the last word. */
uint64_t value; uint64_t value;
if (register_read_direct(target, &value, GDB_REGNO_S1) != ERROR_OK) if (register_read_direct(target, &value, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
@ -1664,7 +1654,7 @@ static int write_memory(struct target *target, target_addr_t address,
if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK) if (register_read_direct(target, &s1, GDB_REGNO_S1) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
// Write the program (store, increment) /* Write the program (store, increment) */
struct riscv_program program; struct riscv_program program;
riscv_program_init(&program, target); riscv_program_init(&program, target);
@ -1736,12 +1726,12 @@ static int write_memory(struct target *target, target_addr_t address,
address + offset) != ERROR_OK) address + offset) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
// Write value. /* Write value. */
dmi_write(target, DMI_DATA0, value); dmi_write(target, DMI_DATA0, value);
// Write and execute command that moves value into S1 and /* Write and execute command that moves value into S1 and
// executes program buffer. * executes program buffer. */
uint32_t command = access_register_command(GDB_REGNO_S1, 32, uint32_t command = access_register_command(GDB_REGNO_S1, 32,
AC_ACCESS_REGISTER_POSTEXEC | AC_ACCESS_REGISTER_POSTEXEC |
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_TRANSFER |
AC_ACCESS_REGISTER_WRITE); AC_ACCESS_REGISTER_WRITE);
@ -1749,7 +1739,7 @@ static int write_memory(struct target *target, target_addr_t address,
if (result != ERROR_OK) if (result != ERROR_OK)
return result; return result;
// Turn on autoexec /* Turn on autoexec */
dmi_write(target, DMI_ABSTRACTAUTO, dmi_write(target, DMI_ABSTRACTAUTO,
1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
@ -1764,9 +1754,9 @@ static int write_memory(struct target *target, target_addr_t address,
riscv_batch_run(batch); riscv_batch_run(batch);
riscv_batch_free(batch); riscv_batch_free(batch);
// Note that if the scan resulted in a Busy DMI response, it /* Note that if the scan resulted in a Busy DMI response, it
// is this read to abstractcs that will cause the dmi_busy_delay * is this read to abstractcs that will cause the dmi_busy_delay
// to be incremented if necessary. * to be incremented if necessary. */
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
@ -1815,8 +1805,7 @@ static int arch_state(struct target *target)
return ERROR_OK; return ERROR_OK;
} }
struct target_type riscv013_target = struct target_type riscv013_target = {
{
.name = "riscv", .name = "riscv",
.init_target = init_target, .init_target = init_target,
@ -2102,7 +2091,7 @@ static void riscv013_step_or_resume_current_hart(struct target *target, bool ste
void riscv013_clear_abstract_error(struct target *target) void riscv013_clear_abstract_error(struct target *target)
{ {
// Wait for busy to go away. /* Wait for busy to go away. */
time_t start = time(NULL); time_t start = time(NULL);
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS); uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) { while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) {
@ -2117,6 +2106,6 @@ void riscv013_clear_abstract_error(struct target *target)
break; break;
} }
} }
// Clear the error status. /* Clear the error status. */
dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR); dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR);
} }

View File

@ -65,7 +65,7 @@
#define DIM(x) (sizeof(x)/sizeof(*x)) #define DIM(x) (sizeof(x)/sizeof(*x))
// Constants for legacy SiFive hardware breakpoints. /* Constants for legacy SiFive hardware breakpoints. */
#define CSR_BPCONTROL_X (1<<0) #define CSR_BPCONTROL_X (1<<0)
#define CSR_BPCONTROL_W (1<<1) #define CSR_BPCONTROL_W (1<<1)
#define CSR_BPCONTROL_R (1<<2) #define CSR_BPCONTROL_R (1<<2)
@ -185,8 +185,8 @@ int riscv_command_timeout_sec = DEFAULT_COMMAND_TIMEOUT_SEC;
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/ /* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC; int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
bool riscv_use_scratch_ram = false; bool riscv_use_scratch_ram;
uint64_t riscv_scratch_ram_address = 0; uint64_t riscv_scratch_ram_address;
/* In addition to the ones in the standard spec, we'll also expose additional /* In addition to the ones in the standard spec, we'll also expose additional
* CSRs in this list. * CSRs in this list.
@ -284,7 +284,7 @@ static void trigger_from_breakpoint(struct trigger *trigger,
trigger->read = false; trigger->read = false;
trigger->write = false; trigger->write = false;
trigger->execute = true; trigger->execute = true;
// unique_id is unique across both breakpoints and watchpoints. /* unique_id is unique across both breakpoints and watchpoints. */
trigger->unique_id = breakpoint->unique_id; trigger->unique_id = breakpoint->unique_id;
} }
@ -304,7 +304,7 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid,
const uint32_t bpcontrol_bpaction = 0xff << 11; const uint32_t bpcontrol_bpaction = 0xff << 11;
if (tdata1 & (bpcontrol_r | bpcontrol_w | bpcontrol_x)) { if (tdata1 & (bpcontrol_r | bpcontrol_w | bpcontrol_x)) {
// Trigger is already in use, presumably by user code. /* Trigger is already in use, presumably by user code. */
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
@ -315,8 +315,8 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid,
tdata1 = set_field(tdata1, bpcontrol_s, !!(r->misa & (1 << ('S' - 'A')))); tdata1 = set_field(tdata1, bpcontrol_s, !!(r->misa & (1 << ('S' - 'A'))));
tdata1 = set_field(tdata1, bpcontrol_h, !!(r->misa & (1 << ('H' - 'A')))); tdata1 = set_field(tdata1, bpcontrol_h, !!(r->misa & (1 << ('H' - 'A'))));
tdata1 |= bpcontrol_m; tdata1 |= bpcontrol_m;
tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); // exact match tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); /* exact match */
tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); // cause bp exception tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); /* cause bp exception */
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, tdata1); riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, tdata1);
@ -342,13 +342,13 @@ static int maybe_add_trigger_t2(struct target *target, unsigned hartid,
{ {
RISCV_INFO(r); RISCV_INFO(r);
// tselect is already set /* tselect is already set */
if (tdata1 & (MCONTROL_EXECUTE | MCONTROL_STORE | MCONTROL_LOAD)) { if (tdata1 & (MCONTROL_EXECUTE | MCONTROL_STORE | MCONTROL_LOAD)) {
// Trigger is already in use, presumably by user code. /* Trigger is already in use, presumably by user code. */
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} }
// address/data match trigger /* address/data match trigger */
tdata1 |= MCONTROL_DMODE(riscv_xlen(target)); tdata1 |= MCONTROL_DMODE(riscv_xlen(target));
tdata1 = set_field(tdata1, MCONTROL_ACTION, tdata1 = set_field(tdata1, MCONTROL_ACTION,
MCONTROL_ACTION_DEBUG_MODE); MCONTROL_ACTION_DEBUG_MODE);
@ -390,12 +390,12 @@ static int add_trigger(struct target *target, struct trigger *trigger)
{ {
RISCV_INFO(r); RISCV_INFO(r);
// In RTOS mode, we need to set the same trigger in the same slot on every /* In RTOS mode, we need to set the same trigger in the same slot on every
// hart, to keep up the illusion that each hart is a thread running on the * hart, to keep up the illusion that each hart is a thread running on the
// same core. * same core. */
// Otherwise, we just set the trigger on the one hart this target deals /* Otherwise, we just set the trigger on the one hart this target deals
// with. * with. */
riscv_reg_t tselect[RISCV_MAX_HARTS]; riscv_reg_t tselect[RISCV_MAX_HARTS];
@ -412,9 +412,8 @@ static int add_trigger(struct target *target, struct trigger *trigger)
unsigned int i; unsigned int i;
for (i = 0; i < r->trigger_count[first_hart]; i++) { for (i = 0; i < r->trigger_count[first_hart]; i++) {
if (r->trigger_unique_id[i] != -1) { if (r->trigger_unique_id[i] != -1)
continue; continue;
}
riscv_set_register_on_hart(target, first_hart, GDB_REGNO_TSELECT, i); riscv_set_register_on_hart(target, first_hart, GDB_REGNO_TSELECT, i);
@ -425,9 +424,8 @@ static int add_trigger(struct target *target, struct trigger *trigger)
for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) { for (int hartid = first_hart; hartid < riscv_count_harts(target); ++hartid) {
if (!riscv_hart_enabled(target, hartid)) if (!riscv_hart_enabled(target, hartid))
continue; continue;
if (hartid > first_hart) { if (hartid > first_hart)
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i); riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i);
}
switch (type) { switch (type) {
case 1: case 1:
result = maybe_add_trigger_t1(target, hartid, trigger, tdata1); result = maybe_add_trigger_t1(target, hartid, trigger, tdata1);
@ -440,14 +438,12 @@ static int add_trigger(struct target *target, struct trigger *trigger)
continue; continue;
} }
if (result != ERROR_OK) { if (result != ERROR_OK)
continue; continue;
}
} }
if (result != ERROR_OK) { if (result != ERROR_OK)
continue; continue;
}
LOG_DEBUG("Using trigger %d (type %d) for bp %d", i, type, LOG_DEBUG("Using trigger %d (type %d) for bp %d", i, type,
trigger->unique_id); trigger->unique_id);
@ -481,11 +477,10 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
} }
int retval; int retval;
if (breakpoint->length == 4) { if (breakpoint->length == 4)
retval = target_write_u32(target, breakpoint->address, ebreak()); retval = target_write_u32(target, breakpoint->address, ebreak());
} else { else
retval = target_write_u16(target, breakpoint->address, ebreak_c()); retval = target_write_u16(target, breakpoint->address, ebreak_c());
}
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%" LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%"
TARGET_PRIxADDR, breakpoint->length, breakpoint->address); TARGET_PRIxADDR, breakpoint->length, breakpoint->address);
@ -496,9 +491,8 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
struct trigger trigger; struct trigger trigger;
trigger_from_breakpoint(&trigger, breakpoint); trigger_from_breakpoint(&trigger, breakpoint);
int result = add_trigger(target, &trigger); int result = add_trigger(target, &trigger);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
} else { } else {
LOG_INFO("OpenOCD only supports hardware and software breakpoints."); LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
@ -527,9 +521,8 @@ static int remove_trigger(struct target *target, struct trigger *trigger)
unsigned int i; unsigned int i;
for (i = 0; i < r->trigger_count[first_hart]; i++) { for (i = 0; i < r->trigger_count[first_hart]; i++) {
if (r->trigger_unique_id[i] == trigger->unique_id) { if (r->trigger_unique_id[i] == trigger->unique_id)
break; break;
}
} }
if (i >= r->trigger_count[first_hart]) { if (i >= r->trigger_count[first_hart]) {
LOG_ERROR("Couldn't find the hardware resources used by hardware " LOG_ERROR("Couldn't find the hardware resources used by hardware "
@ -565,9 +558,8 @@ int riscv_remove_breakpoint(struct target *target,
struct trigger trigger; struct trigger trigger;
trigger_from_breakpoint(&trigger, breakpoint); trigger_from_breakpoint(&trigger, breakpoint);
int result = remove_trigger(target, &trigger); int result = remove_trigger(target, &trigger);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
} else { } else {
LOG_INFO("OpenOCD only supports hardware and software breakpoints."); LOG_INFO("OpenOCD only supports hardware and software breakpoints.");
@ -589,7 +581,7 @@ static void trigger_from_watchpoint(struct trigger *trigger,
trigger->read = (watchpoint->rw == WPT_READ || watchpoint->rw == WPT_ACCESS); trigger->read = (watchpoint->rw == WPT_READ || watchpoint->rw == WPT_ACCESS);
trigger->write = (watchpoint->rw == WPT_WRITE || watchpoint->rw == WPT_ACCESS); trigger->write = (watchpoint->rw == WPT_WRITE || watchpoint->rw == WPT_ACCESS);
trigger->execute = false; trigger->execute = false;
// unique_id is unique across both breakpoints and watchpoints. /* unique_id is unique across both breakpoints and watchpoints. */
trigger->unique_id = watchpoint->unique_id; trigger->unique_id = watchpoint->unique_id;
} }
@ -599,9 +591,8 @@ int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
trigger_from_watchpoint(&trigger, watchpoint); trigger_from_watchpoint(&trigger, watchpoint);
int result = add_trigger(target, &trigger); int result = add_trigger(target, &trigger);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
watchpoint->set = true; watchpoint->set = true;
return ERROR_OK; return ERROR_OK;
@ -614,9 +605,8 @@ int riscv_remove_watchpoint(struct target *target,
trigger_from_watchpoint(&trigger, watchpoint); trigger_from_watchpoint(&trigger, watchpoint);
int result = remove_trigger(target, &trigger); int result = remove_trigger(target, &trigger);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
watchpoint->set = false; watchpoint->set = false;
return ERROR_OK; return ERROR_OK;
@ -651,7 +641,7 @@ static int riscv_examine(struct target *target)
return ERROR_OK; return ERROR_OK;
} }
// Don't need to select dbus, since the first thing we do is read dtmcontrol. /* Don't need to select dbus, since the first thing we do is read dtmcontrol. */
riscv_info_t *info = (riscv_info_t *) target->arch_info; riscv_info_t *info = (riscv_info_t *) target->arch_info;
uint32_t dtmcontrol = dtmcontrol_scan(target, 0); uint32_t dtmcontrol = dtmcontrol_scan(target, 0);
@ -775,9 +765,8 @@ static int riscv_get_gdb_reg_list(struct target *target,
} }
*reg_list = calloc(*reg_list_size, sizeof(struct reg *)); *reg_list = calloc(*reg_list_size, sizeof(struct reg *));
if (!*reg_list) { if (!*reg_list)
return ERROR_FAIL; return ERROR_FAIL;
}
for (int i = 0; i < *reg_list_size; i++) { for (int i = 0; i < *reg_list_size; i++) {
assert(!target->reg_cache->reg_list[i].valid || assert(!target->reg_cache->reg_list[i].valid ||
@ -794,7 +783,7 @@ static int riscv_arch_state(struct target *target)
return tt->arch_state(target); return tt->arch_state(target);
} }
// Algorithm must end with a software breakpoint instruction. /* Algorithm must end with a software breakpoint instruction. */
static int riscv_run_algorithm(struct target *target, int num_mem_params, static int riscv_run_algorithm(struct target *target, int num_mem_params,
struct mem_param *mem_params, int num_reg_params, struct mem_param *mem_params, int num_reg_params,
struct reg_param *reg_params, target_addr_t entry_point, struct reg_param *reg_params, target_addr_t entry_point,
@ -812,11 +801,10 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
/// Save registers /* Save registers */
struct reg *reg_pc = register_get_by_name(target->reg_cache, "pc", 1); struct reg *reg_pc = register_get_by_name(target->reg_cache, "pc", 1);
if (!reg_pc || reg_pc->type->get(reg_pc) != ERROR_OK) { if (!reg_pc || reg_pc->type->get(reg_pc) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
uint64_t saved_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size); uint64_t saved_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size);
uint64_t saved_regs[32]; uint64_t saved_regs[32];
@ -839,17 +827,15 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
return ERROR_FAIL; return ERROR_FAIL;
} }
if (r->type->get(r) != ERROR_OK) { if (r->type->get(r) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
saved_regs[r->number] = buf_get_u64(r->value, 0, r->size); saved_regs[r->number] = buf_get_u64(r->value, 0, r->size);
if (r->type->set(r, reg_params[i].value) != ERROR_OK) { if (r->type->set(r, reg_params[i].value) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
} }
// Disable Interrupts before attempting to run the algorithm. /* Disable Interrupts before attempting to run the algorithm. */
uint64_t current_mstatus; uint64_t current_mstatus;
uint8_t mstatus_bytes[8]; uint8_t mstatus_bytes[8];
@ -869,11 +855,10 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
reg_mstatus->type->set(reg_mstatus, mstatus_bytes); reg_mstatus->type->set(reg_mstatus, mstatus_bytes);
/// Run algorithm /* Run algorithm */
LOG_DEBUG("resume at 0x%" TARGET_PRIxADDR, entry_point); LOG_DEBUG("resume at 0x%" TARGET_PRIxADDR, entry_point);
if (oldriscv_resume(target, 0, entry_point, 0, 0) != ERROR_OK) { if (oldriscv_resume(target, 0, entry_point, 0, 0) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
int64_t start = timeval_ms(); int64_t start = timeval_ms();
while (target->state != TARGET_HALTED) { while (target->state != TARGET_HALTED) {
@ -889,14 +874,12 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
} }
int result = old_or_new_riscv_poll(target); int result = old_or_new_riscv_poll(target);
if (result != ERROR_OK) { if (result != ERROR_OK)
return result; return result;
}
} }
if (reg_pc->type->get(reg_pc) != ERROR_OK) { if (reg_pc->type->get(reg_pc) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
uint64_t final_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size); uint64_t final_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size);
if (final_pc != exit_point) { if (final_pc != exit_point) {
LOG_ERROR("PC ended up at 0x%" PRIx64 " instead of 0x%" LOG_ERROR("PC ended up at 0x%" PRIx64 " instead of 0x%"
@ -904,37 +887,35 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
return ERROR_FAIL; return ERROR_FAIL;
} }
// Restore Interrupts /* Restore Interrupts */
LOG_DEBUG("Restoring Interrupts"); LOG_DEBUG("Restoring Interrupts");
buf_set_u64(mstatus_bytes, 0, info->xlen[0], current_mstatus); buf_set_u64(mstatus_bytes, 0, info->xlen[0], current_mstatus);
reg_mstatus->type->set(reg_mstatus, mstatus_bytes); reg_mstatus->type->set(reg_mstatus, mstatus_bytes);
/// Restore registers /* Restore registers */
uint8_t buf[8]; uint8_t buf[8];
buf_set_u64(buf, 0, info->xlen[0], saved_pc); buf_set_u64(buf, 0, info->xlen[0], saved_pc);
if (reg_pc->type->set(reg_pc, buf) != ERROR_OK) { if (reg_pc->type->set(reg_pc, buf) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
for (int i = 0; i < num_reg_params; i++) { for (int i = 0; i < num_reg_params; i++) {
LOG_DEBUG("restore %s", reg_params[i].reg_name); LOG_DEBUG("restore %s", reg_params[i].reg_name);
struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0); struct reg *r = register_get_by_name(target->reg_cache, reg_params[i].reg_name, 0);
buf_set_u64(buf, 0, info->xlen[0], saved_regs[r->number]); buf_set_u64(buf, 0, info->xlen[0], saved_regs[r->number]);
if (r->type->set(r, buf) != ERROR_OK) { if (r->type->set(r, buf) != ERROR_OK)
return ERROR_FAIL; return ERROR_FAIL;
}
} }
return ERROR_OK; return ERROR_OK;
} }
/* Should run code on the target to perform CRC of /* Should run code on the target to perform CRC of
memory. Not yet implemented. memory. Not yet implemented.
*/ */
static int riscv_checksum_memory(struct target *target, static int riscv_checksum_memory(struct target *target,
target_addr_t address, uint32_t count, target_addr_t address, uint32_t count,
uint32_t* checksum) uint32_t *checksum)
{ {
*checksum = 0xFFFFFFFF; *checksum = 0xFFFFFFFF;
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@ -945,10 +926,10 @@ block holds all-ones (because this is generally called on
NOR flash which is 1 when "blank") NOR flash which is 1 when "blank")
Not yet implemented. Not yet implemented.
*/ */
int riscv_blank_check_memory(struct target * target, int riscv_blank_check_memory(struct target *target,
target_addr_t address, target_addr_t address,
uint32_t count, uint32_t count,
uint32_t * blank, uint32_t *blank,
uint8_t erased_value) uint8_t erased_value)
{ {
*blank = 0; *blank = 0;
@ -1031,7 +1012,7 @@ int riscv_openocd_poll(struct target *target)
target->debug_reason = DBG_REASON_SINGLESTEP; target->debug_reason = DBG_REASON_SINGLESTEP;
break; break;
} }
if (riscv_rtos_enabled(target)) { if (riscv_rtos_enabled(target)) {
target->rtos->current_threadid = triggered_hart + 1; target->rtos->current_threadid = triggered_hart + 1;
target->rtos->current_thread = triggered_hart + 1; target->rtos->current_thread = triggered_hart + 1;
@ -1075,9 +1056,8 @@ int riscv_openocd_resume(
) { ) {
LOG_DEBUG("resuming all harts"); LOG_DEBUG("resuming all harts");
if (!current) { if (!current)
riscv_set_register(target, GDB_REGNO_PC, address); riscv_set_register(target, GDB_REGNO_PC, address);
}
int out = riscv_resume_all_harts(target); int out = riscv_resume_all_harts(target);
if (out != ERROR_OK) { if (out != ERROR_OK) {
@ -1099,9 +1079,8 @@ int riscv_openocd_step(
) { ) {
LOG_DEBUG("stepping rtos hart"); LOG_DEBUG("stepping rtos hart");
if (!current) { if (!current)
riscv_set_register(target, GDB_REGNO_PC, address); riscv_set_register(target, GDB_REGNO_PC, address);
}
int out = riscv_step_rtos_hart(target); int out = riscv_step_rtos_hart(target);
if (out != ERROR_OK) { if (out != ERROR_OK) {
@ -1126,7 +1105,7 @@ COMMAND_HANDLER(riscv_set_command_timeout_sec)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
int timeout = atoi(CMD_ARGV[0]); int timeout = atoi(CMD_ARGV[0]);
if (timeout <= 0){ if (timeout <= 0) {
LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]); LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -1143,7 +1122,7 @@ COMMAND_HANDLER(riscv_set_reset_timeout_sec)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
} }
int timeout = atoi(CMD_ARGV[0]); int timeout = atoi(CMD_ARGV[0]);
if (timeout <= 0){ if (timeout <= 0) {
LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]); LOG_ERROR("%s is not a valid integer argument for command.", CMD_ARGV[0]);
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -1204,7 +1183,7 @@ COMMAND_HANDLER(riscv_set_expose_csrs)
for (unsigned i = 0; i == 0 || CMD_ARGV[0][i-1]; i++) { for (unsigned i = 0; i == 0 || CMD_ARGV[0][i-1]; i++) {
char c = CMD_ARGV[0][i]; char c = CMD_ARGV[0][i];
if (isspace(c)) { if (isspace(c)) {
// Ignore whitespace. /* Ignore whitespace. */
continue; continue;
} }
@ -1303,8 +1282,7 @@ const struct command_registration riscv_command_handlers[] = {
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
struct target_type riscv_target = struct target_type riscv_target = {
{
.name = "riscv", .name = "riscv",
.init_target = riscv_init_target, .init_target = riscv_init_target,
@ -1443,13 +1421,12 @@ bool riscv_supports_extension(struct target *target, char letter)
{ {
RISCV_INFO(r); RISCV_INFO(r);
unsigned num; unsigned num;
if (letter >= 'a' && letter <= 'z') { if (letter >= 'a' && letter <= 'z')
num = letter - 'a'; num = letter - 'a';
} else if (letter >= 'A' && letter <= 'Z') { else if (letter >= 'A' && letter <= 'Z')
num = letter - 'A'; num = letter - 'A';
} else { else
return false; return false;
}
return r->misa & (1 << num); return r->misa & (1 << num);
} }
@ -1533,9 +1510,11 @@ void riscv_set_rtos_hartid(struct target *target, int hartid)
int riscv_count_harts(struct target *target) int riscv_count_harts(struct target *target)
{ {
if (target == NULL) return 1; if (target == NULL)
return 1;
RISCV_INFO(r); RISCV_INFO(r);
if (r == NULL) return 1; if (r == NULL)
return 1;
return r->hart_count; return r->hart_count;
} }
@ -1546,7 +1525,7 @@ bool riscv_has_register(struct target *target, int hartid, int regid)
void riscv_set_register(struct target *target, enum gdb_regno r, riscv_reg_t v) void riscv_set_register(struct target *target, enum gdb_regno r, riscv_reg_t v)
{ {
// TODO: propagate errors /* TODO: propagate errors */
return riscv_set_register_on_hart(target, riscv_current_hartid(target), r, v); return riscv_set_register_on_hart(target, riscv_current_hartid(target), r, v);
} }
@ -1697,8 +1676,8 @@ int riscv_enumerate_triggers(struct target *target)
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, t); riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, t);
uint64_t tselect_rb = riscv_get_register_on_hart(target, hartid, uint64_t tselect_rb = riscv_get_register_on_hart(target, hartid,
GDB_REGNO_TSELECT); GDB_REGNO_TSELECT);
// Mask off the top bit, which is used as tdrmode in old /* Mask off the top bit, which is used as tdrmode in old
// implementations. * implementations. */
tselect_rb &= ~(1ULL << (riscv_xlen(target)-1)); tselect_rb &= ~(1ULL << (riscv_xlen(target)-1));
if (tselect_rb != t) if (tselect_rb != t)
break; break;
@ -1707,14 +1686,13 @@ int riscv_enumerate_triggers(struct target *target)
int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target))); int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
switch (type) { switch (type) {
case 1: case 1:
// On these older cores we don't support software using /* On these older cores we don't support software using
// triggers. * triggers. */
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0); riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0);
break; break;
case 2: case 2:
if (tdata1 & MCONTROL_DMODE(riscv_xlen(target))) { if (tdata1 & MCONTROL_DMODE(riscv_xlen(target)))
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0); riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0);
}
break; break;
} }
} }
@ -1765,15 +1743,14 @@ const char *gdb_regno_name(enum gdb_regno regno)
case GDB_REGNO_PRIV: case GDB_REGNO_PRIV:
return "priv"; return "priv";
default: default:
if (regno <= GDB_REGNO_XPR31) { if (regno <= GDB_REGNO_XPR31)
sprintf(buf, "x%d", regno - GDB_REGNO_ZERO); sprintf(buf, "x%d", regno - GDB_REGNO_ZERO);
} else if (regno >= GDB_REGNO_CSR0 && regno <= GDB_REGNO_CSR4095) { else if (regno >= GDB_REGNO_CSR0 && regno <= GDB_REGNO_CSR4095)
sprintf(buf, "csr%d", regno - GDB_REGNO_CSR0); sprintf(buf, "csr%d", regno - GDB_REGNO_CSR0);
} else if (regno >= GDB_REGNO_FPR0 && regno <= GDB_REGNO_FPR31) { else if (regno >= GDB_REGNO_FPR0 && regno <= GDB_REGNO_FPR31)
sprintf(buf, "f%d", regno - GDB_REGNO_FPR0); sprintf(buf, "f%d", regno - GDB_REGNO_FPR0);
} else { else
sprintf(buf, "gdb_regno_%d", regno); sprintf(buf, "gdb_regno_%d", regno);
}
return buf; return buf;
} }
} }
@ -1864,15 +1841,15 @@ int riscv_init_registers(struct target *target)
#include "encoding.h" #include "encoding.h"
#undef DECLARE_CSR #undef DECLARE_CSR
}; };
// encoding.h does not contain the registers in sorted order. /* encoding.h does not contain the registers in sorted order. */
qsort(csr_info, DIM(csr_info), sizeof(*csr_info), cmp_csr_info); qsort(csr_info, DIM(csr_info), sizeof(*csr_info), cmp_csr_info);
unsigned csr_info_index = 0; unsigned csr_info_index = 0;
// When gdb request register N, gdb_get_register_packet() assumes that this /* When gdb request register N, gdb_get_register_packet() assumes that this
// is register at index N in reg_list. So if there are certain registers * is register at index N in reg_list. So if there are certain registers
// that don't exist, we need to leave holes in the list (or renumber, but * that don't exist, we need to leave holes in the list (or renumber, but
// it would be nice not to have yet another set of numbers to translate * it would be nice not to have yet another set of numbers to translate
// between). * between). */
for (uint32_t number = 0; number < GDB_REGNO_COUNT; number++) { for (uint32_t number = 0; number < GDB_REGNO_COUNT; number++) {
struct reg *r = &target->reg_cache->reg_list[number]; struct reg *r = &target->reg_cache->reg_list[number];
r->caller_save = true; r->caller_save = true;
@ -1883,43 +1860,107 @@ int riscv_init_registers(struct target *target)
r->arch_info = target; r->arch_info = target;
r->number = number; r->number = number;
r->size = riscv_xlen(target); r->size = riscv_xlen(target);
// r->size is set in riscv_invalidate_register_cache, maybe because the /* r->size is set in riscv_invalidate_register_cache, maybe because the
// target is in theory allowed to change XLEN on us. But I expect a lot * target is in theory allowed to change XLEN on us. But I expect a lot
// of other things to break in that case as well. * of other things to break in that case as well. */
if (number <= GDB_REGNO_XPR31) { if (number <= GDB_REGNO_XPR31) {
switch (number) { switch (number) {
case GDB_REGNO_ZERO: r->name = "zero"; break; case GDB_REGNO_ZERO:
case GDB_REGNO_RA: r->name = "ra"; break; r->name = "zero";
case GDB_REGNO_SP: r->name = "sp"; break; break;
case GDB_REGNO_GP: r->name = "gp"; break; case GDB_REGNO_RA:
case GDB_REGNO_TP: r->name = "tp"; break; r->name = "ra";
case GDB_REGNO_T0: r->name = "t0"; break; break;
case GDB_REGNO_T1: r->name = "t1"; break; case GDB_REGNO_SP:
case GDB_REGNO_T2: r->name = "t2"; break; r->name = "sp";
case GDB_REGNO_FP: r->name = "fp"; break; break;
case GDB_REGNO_S1: r->name = "s1"; break; case GDB_REGNO_GP:
case GDB_REGNO_A0: r->name = "a0"; break; r->name = "gp";
case GDB_REGNO_A1: r->name = "a1"; break; break;
case GDB_REGNO_A2: r->name = "a2"; break; case GDB_REGNO_TP:
case GDB_REGNO_A3: r->name = "a3"; break; r->name = "tp";
case GDB_REGNO_A4: r->name = "a4"; break; break;
case GDB_REGNO_A5: r->name = "a5"; break; case GDB_REGNO_T0:
case GDB_REGNO_A6: r->name = "a6"; break; r->name = "t0";
case GDB_REGNO_A7: r->name = "a7"; break; break;
case GDB_REGNO_S2: r->name = "s2"; break; case GDB_REGNO_T1:
case GDB_REGNO_S3: r->name = "s3"; break; r->name = "t1";
case GDB_REGNO_S4: r->name = "s4"; break; break;
case GDB_REGNO_S5: r->name = "s5"; break; case GDB_REGNO_T2:
case GDB_REGNO_S6: r->name = "s6"; break; r->name = "t2";
case GDB_REGNO_S7: r->name = "s7"; break; break;
case GDB_REGNO_S8: r->name = "s8"; break; case GDB_REGNO_FP:
case GDB_REGNO_S9: r->name = "s9"; break; r->name = "fp";
case GDB_REGNO_S10: r->name = "s10"; break; break;
case GDB_REGNO_S11: r->name = "s11"; break; case GDB_REGNO_S1:
case GDB_REGNO_T3: r->name = "t3"; break; r->name = "s1";
case GDB_REGNO_T4: r->name = "t4"; break; break;
case GDB_REGNO_T5: r->name = "t5"; break; case GDB_REGNO_A0:
case GDB_REGNO_T6: r->name = "t6"; break; r->name = "a0";
break;
case GDB_REGNO_A1:
r->name = "a1";
break;
case GDB_REGNO_A2:
r->name = "a2";
break;
case GDB_REGNO_A3:
r->name = "a3";
break;
case GDB_REGNO_A4:
r->name = "a4";
break;
case GDB_REGNO_A5:
r->name = "a5";
break;
case GDB_REGNO_A6:
r->name = "a6";
break;
case GDB_REGNO_A7:
r->name = "a7";
break;
case GDB_REGNO_S2:
r->name = "s2";
break;
case GDB_REGNO_S3:
r->name = "s3";
break;
case GDB_REGNO_S4:
r->name = "s4";
break;
case GDB_REGNO_S5:
r->name = "s5";
break;
case GDB_REGNO_S6:
r->name = "s6";
break;
case GDB_REGNO_S7:
r->name = "s7";
break;
case GDB_REGNO_S8:
r->name = "s8";
break;
case GDB_REGNO_S9:
r->name = "s9";
break;
case GDB_REGNO_S10:
r->name = "s10";
break;
case GDB_REGNO_S11:
r->name = "s11";
break;
case GDB_REGNO_T3:
r->name = "t3";
break;
case GDB_REGNO_T4:
r->name = "t4";
break;
case GDB_REGNO_T5:
r->name = "t5";
break;
case GDB_REGNO_T6:
r->name = "t6";
break;
} }
r->group = "general"; r->group = "general";
r->feature = &feature_cpu; r->feature = &feature_cpu;
@ -1938,38 +1979,102 @@ int riscv_init_registers(struct target *target)
r->exist = false; r->exist = false;
} }
switch (number) { switch (number) {
case GDB_REGNO_FT0: r->name = "ft0"; break; case GDB_REGNO_FT0:
case GDB_REGNO_FT1: r->name = "ft1"; break; r->name = "ft0";
case GDB_REGNO_FT2: r->name = "ft2"; break; break;
case GDB_REGNO_FT3: r->name = "ft3"; break; case GDB_REGNO_FT1:
case GDB_REGNO_FT4: r->name = "ft4"; break; r->name = "ft1";
case GDB_REGNO_FT5: r->name = "ft5"; break; break;
case GDB_REGNO_FT6: r->name = "ft6"; break; case GDB_REGNO_FT2:
case GDB_REGNO_FT7: r->name = "ft7"; break; r->name = "ft2";
case GDB_REGNO_FS0: r->name = "fs0"; break; break;
case GDB_REGNO_FS1: r->name = "fs1"; break; case GDB_REGNO_FT3:
case GDB_REGNO_FA0: r->name = "fa0"; break; r->name = "ft3";
case GDB_REGNO_FA1: r->name = "fa1"; break; break;
case GDB_REGNO_FA2: r->name = "fa2"; break; case GDB_REGNO_FT4:
case GDB_REGNO_FA3: r->name = "fa3"; break; r->name = "ft4";
case GDB_REGNO_FA4: r->name = "fa4"; break; break;
case GDB_REGNO_FA5: r->name = "fa5"; break; case GDB_REGNO_FT5:
case GDB_REGNO_FA6: r->name = "fa6"; break; r->name = "ft5";
case GDB_REGNO_FA7: r->name = "fa7"; break; break;
case GDB_REGNO_FS2: r->name = "fs2"; break; case GDB_REGNO_FT6:
case GDB_REGNO_FS3: r->name = "fs3"; break; r->name = "ft6";
case GDB_REGNO_FS4: r->name = "fs4"; break; break;
case GDB_REGNO_FS5: r->name = "fs5"; break; case GDB_REGNO_FT7:
case GDB_REGNO_FS6: r->name = "fs6"; break; r->name = "ft7";
case GDB_REGNO_FS7: r->name = "fs7"; break; break;
case GDB_REGNO_FS8: r->name = "fs8"; break; case GDB_REGNO_FS0:
case GDB_REGNO_FS9: r->name = "fs9"; break; r->name = "fs0";
case GDB_REGNO_FS10: r->name = "fs10"; break; break;
case GDB_REGNO_FS11: r->name = "fs11"; break; case GDB_REGNO_FS1:
case GDB_REGNO_FT8: r->name = "ft8"; break; r->name = "fs1";
case GDB_REGNO_FT9: r->name = "ft9"; break; break;
case GDB_REGNO_FT10: r->name = "ft10"; break; case GDB_REGNO_FA0:
case GDB_REGNO_FT11: r->name = "ft11"; break; r->name = "fa0";
break;
case GDB_REGNO_FA1:
r->name = "fa1";
break;
case GDB_REGNO_FA2:
r->name = "fa2";
break;
case GDB_REGNO_FA3:
r->name = "fa3";
break;
case GDB_REGNO_FA4:
r->name = "fa4";
break;
case GDB_REGNO_FA5:
r->name = "fa5";
break;
case GDB_REGNO_FA6:
r->name = "fa6";
break;
case GDB_REGNO_FA7:
r->name = "fa7";
break;
case GDB_REGNO_FS2:
r->name = "fs2";
break;
case GDB_REGNO_FS3:
r->name = "fs3";
break;
case GDB_REGNO_FS4:
r->name = "fs4";
break;
case GDB_REGNO_FS5:
r->name = "fs5";
break;
case GDB_REGNO_FS6:
r->name = "fs6";
break;
case GDB_REGNO_FS7:
r->name = "fs7";
break;
case GDB_REGNO_FS8:
r->name = "fs8";
break;
case GDB_REGNO_FS9:
r->name = "fs9";
break;
case GDB_REGNO_FS10:
r->name = "fs10";
break;
case GDB_REGNO_FS11:
r->name = "fs11";
break;
case GDB_REGNO_FT8:
r->name = "ft8";
break;
case GDB_REGNO_FT9:
r->name = "ft9";
break;
case GDB_REGNO_FT10:
r->name = "ft10";
break;
case GDB_REGNO_FT11:
r->name = "ft11";
break;
} }
r->group = "float"; r->group = "float";
r->feature = &feature_fpu; r->feature = &feature_fpu;
@ -1986,11 +2091,11 @@ int riscv_init_registers(struct target *target)
r->name = csr_info[csr_info_index].name; r->name = csr_info[csr_info_index].name;
} else { } else {
sprintf(reg_name, "csr%d", csr_number); sprintf(reg_name, "csr%d", csr_number);
// Assume unnamed registers don't exist, unless we have some /* Assume unnamed registers don't exist, unless we have some
// configuration that tells us otherwise. That's important * configuration that tells us otherwise. That's important
// because eg. Eclipse crashes if a target has too many * because eg. Eclipse crashes if a target has too many
// registers, and apparently has no way of only showing a * registers, and apparently has no way of only showing a
// subset of registers in any case. * subset of registers in any case. */
r->exist = false; r->exist = false;
} }
@ -2032,9 +2137,8 @@ int riscv_init_registers(struct target *target)
r->feature = &feature_virtual; r->feature = &feature_virtual;
r->size = 8; r->size = 8;
} }
if (reg_name[0]) { if (reg_name[0])
r->name = reg_name; r->name = reg_name;
}
reg_name += strlen(reg_name) + 1; reg_name += strlen(reg_name) + 1;
assert(reg_name < info->reg_names + GDB_REGNO_COUNT * max_reg_name_len); assert(reg_name < info->reg_names + GDB_REGNO_COUNT * max_reg_name_len);
r->value = &info->reg_cache_values[number]; r->value = &info->reg_cache_values[number];

View File

@ -141,7 +141,7 @@ int riscv_openocd_resume(
struct target *target, struct target *target,
int current, int current,
target_addr_t address, target_addr_t address,
int handle_breakpoints, int handle_breakpoints,
int debug_execution int debug_execution
); );

View File

@ -2830,8 +2830,8 @@ COMMAND_HANDLER(handle_reg_command)
retval = reg->type->set(reg, buf); retval = reg->type->set(reg, buf);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
LOG_DEBUG("Couldn't set register %s.", reg->name); LOG_DEBUG("Couldn't set register %s.", reg->name);
free (buf); free(buf);
return retval; return retval;
} }