Conform to OpenOCD style guide.
Change-Id: I2b23ac79639ed40e9d59db5c52ea2196df0349bc
This commit is contained in:
parent
19d9e3e32a
commit
d942bce996
|
@ -28,7 +28,7 @@ matrix:
|
|||
|
||||
- os: linux
|
||||
env:
|
||||
- BUILD=i686-linux-gnu
|
||||
- BUILD=i686-linux-gnu
|
||||
- CFLAGS=-m32
|
||||
- EXECUTABLE=openocd
|
||||
compiler: clang
|
||||
|
@ -38,7 +38,7 @@ matrix:
|
|||
- gcc-multilib
|
||||
|
||||
- os: linux
|
||||
env:
|
||||
env:
|
||||
- BUILD=i686-w64-mingw
|
||||
- CONFIGURE_ARGS="--build=i686-unknown-linux-gnu --host=i686-w64-mingw32"
|
||||
- EXECUTABLE=openocd.exe
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2010 by Antonio Borneo <borneo.antonio@gmail.com> *
|
||||
* Modified by Megan Wachs <megan@sifive.com> from the original stmsmi.c *
|
||||
* *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
/* The Freedom E SPI controller is a SPI bus controller
|
||||
* specifically designed for SPI Flash Memories on Freedom E platforms.
|
||||
*
|
||||
*
|
||||
* Two working modes are available:
|
||||
* - SW mode: the SPI is controlled by SW. Any custom commands can be sent
|
||||
* on the bus. Writes are only possible in this mode.
|
||||
|
@ -127,7 +127,7 @@
|
|||
int __a; \
|
||||
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) { \
|
||||
LOG_ERROR("FESPI_READ_REG error"); \
|
||||
return __a; \
|
||||
|
@ -139,7 +139,7 @@
|
|||
{ \
|
||||
int __r; \
|
||||
\
|
||||
__r = target_write_u32(target, ctrl_base + (a), (v)); \
|
||||
__r = target_write_u32(target, ctrl_base + (a), (v)); \
|
||||
if (__r != ERROR_OK) { \
|
||||
LOG_ERROR("FESPI_WRITE_REG error"); \
|
||||
return __r; \
|
||||
|
@ -163,7 +163,7 @@ struct fespi_target {
|
|||
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[] = {
|
||||
/* name, tap_idcode, ctrl_base */
|
||||
{ "Freedom E300 SPI Flash", 0x10e31913 , 0x10014000 },
|
||||
|
@ -189,16 +189,17 @@ FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command)
|
|||
fespi_info->probed = 0;
|
||||
fespi_info->ctrl_base = 0;
|
||||
if (CMD_ARGC >= 7) {
|
||||
int temp;
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], temp);
|
||||
fespi_info->ctrl_base = (uint32_t) temp;
|
||||
LOG_DEBUG("ASSUMING FESPI device at ctrl_base = 0x%x", fespi_info->ctrl_base);
|
||||
int temp;
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], temp);
|
||||
fespi_info->ctrl_base = (uint32_t) temp;
|
||||
LOG_DEBUG("ASSUMING FESPI device at ctrl_base = 0x%x", fespi_info->ctrl_base);
|
||||
}
|
||||
|
||||
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 fespi_flash_bank *fespi_info = bank->driver_priv;
|
||||
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 fespi_flash_bank *fespi_info = bank->driver_priv;
|
||||
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();
|
||||
|
||||
while (1) {
|
||||
if (FESPI_READ_REG(FESPI_REG_IP) & FESPI_IP_TXWM) {
|
||||
if (FESPI_READ_REG(FESPI_REG_IP) & FESPI_IP_TXWM)
|
||||
break;
|
||||
}
|
||||
int64_t now = timeval_ms();
|
||||
if (now - start > 1000) {
|
||||
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 fespi_flash_bank *fespi_info = bank->driver_priv;
|
||||
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();
|
||||
|
||||
while (1) {
|
||||
if ((int32_t) FESPI_READ_REG(FESPI_REG_TXFIFO) >= 0) {
|
||||
if ((int32_t) FESPI_READ_REG(FESPI_REG_TXFIFO) >= 0)
|
||||
break;
|
||||
}
|
||||
int64_t now = timeval_ms();
|
||||
if (now - start > 1000) {
|
||||
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;
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
//TODO!!! Why don't we need to call this after writing?
|
||||
static int fespi_wip (struct flash_bank * bank, int timeout)
|
||||
/* TODO!!! Why don't we need to call this after writing? */
|
||||
static int fespi_wip(struct flash_bank *bank, int timeout)
|
||||
{
|
||||
struct target *target = bank->target;
|
||||
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;
|
||||
|
||||
retval = fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
|
||||
if (retval != ERROR_OK) {return retval;}
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
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);
|
||||
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;
|
||||
retval = fespi_tx(bank, sector >> 16);
|
||||
if (retval != ERROR_OK) {return retval;}
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
retval = fespi_tx(bank, sector >> 8);
|
||||
if (retval != ERROR_OK) {return retval;}
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
retval = fespi_tx(bank, sector);
|
||||
if (retval != ERROR_OK) {return retval;}
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
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);
|
||||
|
||||
retval = fespi_wip(bank, FESPI_MAX_TIMEOUT);
|
||||
if (retval != ERROR_OK){return retval;}
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
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));
|
||||
retval = fespi_txwm_wait(bank);
|
||||
if (retval != ERROR_OK){
|
||||
LOG_ERROR("WM Didn't go high before attempting.");
|
||||
return retval;
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("WM Didn't go high before attempting.");
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Disable Hardware accesses*/
|
||||
|
@ -394,7 +403,7 @@ static int fespi_erase(struct flash_bank *bank, int first, int last)
|
|||
|
||||
/* poll WIP */
|
||||
retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
|
||||
if (retval != ERROR_OK)
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
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 ii;
|
||||
|
||||
//TODO!!! assert that len < page size
|
||||
/* TODO!!! assert that len < page size */
|
||||
|
||||
fespi_tx(bank, SPIFLASH_WRITE_ENABLE);
|
||||
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);
|
||||
|
||||
for (ii = 0; ii < len; ii++) {
|
||||
for (ii = 0; ii < len; ii++)
|
||||
fespi_tx(bank, buffer[ii]);
|
||||
}
|
||||
|
||||
fespi_txwm_wait(bank);
|
||||
|
||||
|
@ -487,67 +495,67 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
|
|||
.global _start
|
||||
_start:
|
||||
command_table:
|
||||
j main // 0
|
||||
ebreak // 4
|
||||
j tx // 8
|
||||
j txwm_wait // 12
|
||||
j write_reg // 16
|
||||
j main // 0
|
||||
ebreak // 4
|
||||
j tx // 8
|
||||
j txwm_wait // 12
|
||||
j write_reg // 16
|
||||
j wip_wait // 20
|
||||
j set_dir // 24
|
||||
j set_dir // 24
|
||||
|
||||
// Execute the program.
|
||||
main:
|
||||
lbu t0, 0(a1)
|
||||
addi a1, a1, 1
|
||||
la t1, command_table
|
||||
add t0, t0, t1
|
||||
jr t0
|
||||
lbu t0, 0(a1)
|
||||
addi a1, a1, 1
|
||||
la t1, command_table
|
||||
add t0, t0, t1
|
||||
jr t0
|
||||
|
||||
// Read 1 byte the contains the number of bytes to transmit. Then read those
|
||||
// bytes from the program and transmit them one by one.
|
||||
tx:
|
||||
lbu t1, 0(a1) // read number of bytes to transmit
|
||||
addi a1, a1, 1
|
||||
lbu t1, 0(a1) // read number of bytes to transmit
|
||||
addi a1, a1, 1
|
||||
1: lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
|
||||
bltz t0, 1b
|
||||
lbu t0, 0(a1) // Load byte to write
|
||||
sw t0, FESPI_REG_TXFIFO(a0)
|
||||
addi a1, a1, 1
|
||||
addi t1, t1, -1
|
||||
bgtz t1, 1b
|
||||
j main
|
||||
bltz t0, 1b
|
||||
lbu t0, 0(a1) // Load byte to write
|
||||
sw t0, FESPI_REG_TXFIFO(a0)
|
||||
addi a1, a1, 1
|
||||
addi t1, t1, -1
|
||||
bgtz t1, 1b
|
||||
j main
|
||||
|
||||
// Wait until TXWM is set.
|
||||
txwm_wait:
|
||||
1: lw t0, FESPI_REG_IP(a0)
|
||||
andi t0, t0, FESPI_IP_TXWM
|
||||
beqz t0, 1b
|
||||
j main
|
||||
andi t0, t0, FESPI_IP_TXWM
|
||||
beqz t0, 1b
|
||||
j main
|
||||
|
||||
// Read 1 byte that contains the offset of the register to write, and 1 byte
|
||||
// that contains the data to write.
|
||||
write_reg:
|
||||
lbu t0, 0(a1) // read register to write
|
||||
add t0, t0, a0
|
||||
lbu t1, 1(a1) // read value to write
|
||||
addi a1, a1, 2
|
||||
sw t1, 0(t0)
|
||||
j main
|
||||
lbu t0, 0(a1) // read register to write
|
||||
add t0, t0, a0
|
||||
lbu t1, 1(a1) // read value to write
|
||||
addi a1, a1, 2
|
||||
sw t1, 0(t0)
|
||||
j main
|
||||
|
||||
wip_wait:
|
||||
li a2, SPIFLASH_READ_STATUS
|
||||
jal txrx_byte
|
||||
jal txrx_byte
|
||||
// discard first result
|
||||
1: li a2, 0
|
||||
jal txrx_byte
|
||||
jal txrx_byte
|
||||
andi t0, a2, SPIFLASH_BSY_BIT
|
||||
bnez t0, 1b
|
||||
j main
|
||||
|
||||
txrx_byte: // transmit the byte in a2, receive a bit into a2
|
||||
lw t0, FESPI_REG_TXFIFO(a0) // wait for FIFO clear
|
||||
bltz t0, txrx_byte
|
||||
sw a2, FESPI_REG_TXFIFO(a0)
|
||||
bltz t0, txrx_byte
|
||||
sw a2, FESPI_REG_TXFIFO(a0)
|
||||
1: lw a2, FESPI_REG_RXFIFO(a0)
|
||||
bltz a2, 1b
|
||||
ret
|
||||
|
@ -556,8 +564,8 @@ set_dir:
|
|||
lw t0, FESPI_REG_FMT(a0)
|
||||
li t1, ~(FESPI_FMT_DIR(0xFFFFFFFF))
|
||||
and t0, t0, t1
|
||||
lbu t1, 0(a1) // read value to OR in
|
||||
addi a1, a1, 1
|
||||
lbu t1, 0(a1) // read value to OR in
|
||||
addi a1, a1, 1
|
||||
or t0, t0, t1
|
||||
sw t0, FESPI_REG_FMT(a0)
|
||||
j main
|
||||
|
@ -565,24 +573,24 @@ set_dir:
|
|||
// ALGO_END
|
||||
*/
|
||||
static const uint8_t algorithm_bin[] = {
|
||||
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, 0x0a, 0x83, 0xc2, 0x05, 0x00, 0x93, 0x85, 0x15, 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,
|
||||
0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe, 0x83, 0xc2, 0x05, 0x00,
|
||||
0x23, 0x24, 0x55, 0x04, 0x93, 0x85, 0x15, 0x00, 0x13, 0x03, 0xf3, 0xff,
|
||||
0xe3, 0x44, 0x60, 0xfe, 0x6f, 0xf0, 0x5f, 0xfc, 0x83, 0x22, 0x45, 0x07,
|
||||
0x93, 0xf2, 0x12, 0x00, 0xe3, 0x8c, 0x02, 0xfe, 0x6f, 0xf0, 0x5f, 0xfb,
|
||||
0x83, 0xc2, 0x05, 0x00, 0xb3, 0x82, 0xa2, 0x00, 0x03, 0xc3, 0x15, 0x00,
|
||||
0x93, 0x85, 0x25, 0x00, 0x23, 0xa0, 0x62, 0x00, 0x6f, 0xf0, 0xdf, 0xf9,
|
||||
0x13, 0x06, 0x50, 0x00, 0xef, 0x00, 0x80, 0x01, 0x13, 0x06, 0x00, 0x00,
|
||||
0xef, 0x00, 0x00, 0x01, 0x93, 0x72, 0x16, 0x00, 0xe3, 0x9a, 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,
|
||||
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, 0xe2, 0x62, 0x00, 0x23, 0x20, 0x55, 0x04, 0x6f, 0xf0, 0x9f, 0xf4
|
||||
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, 0x0a, 0x83, 0xc2, 0x05, 0x00, 0x93, 0x85, 0x15, 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,
|
||||
0x83, 0x22, 0x85, 0x04, 0xe3, 0xce, 0x02, 0xfe, 0x83, 0xc2, 0x05, 0x00,
|
||||
0x23, 0x24, 0x55, 0x04, 0x93, 0x85, 0x15, 0x00, 0x13, 0x03, 0xf3, 0xff,
|
||||
0xe3, 0x44, 0x60, 0xfe, 0x6f, 0xf0, 0x5f, 0xfc, 0x83, 0x22, 0x45, 0x07,
|
||||
0x93, 0xf2, 0x12, 0x00, 0xe3, 0x8c, 0x02, 0xfe, 0x6f, 0xf0, 0x5f, 0xfb,
|
||||
0x83, 0xc2, 0x05, 0x00, 0xb3, 0x82, 0xa2, 0x00, 0x03, 0xc3, 0x15, 0x00,
|
||||
0x93, 0x85, 0x25, 0x00, 0x23, 0xa0, 0x62, 0x00, 0x6f, 0xf0, 0xdf, 0xf9,
|
||||
0x13, 0x06, 0x50, 0x00, 0xef, 0x00, 0x80, 0x01, 0x13, 0x06, 0x00, 0x00,
|
||||
0xef, 0x00, 0x00, 0x01, 0x93, 0x72, 0x16, 0x00, 0xe3, 0x9a, 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,
|
||||
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, 0xe2, 0x62, 0x00, 0x23, 0x20, 0x55, 0x04, 0x6f, 0xf0, 0x9f, 0xf4
|
||||
};
|
||||
#define STEP_EXIT 4
|
||||
#define STEP_TX 8
|
||||
|
@ -625,7 +633,7 @@ static int as_empty(struct algorithm_steps *as)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Return size of compiled program.
|
||||
/* Return size of compiled program. */
|
||||
static unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
|
||||
unsigned target_size)
|
||||
{
|
||||
|
@ -684,9 +692,8 @@ static unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
|
|||
LOG_DEBUG("%d-byte program:", offset);
|
||||
for (unsigned i = 0; i < offset;) {
|
||||
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]);
|
||||
}
|
||||
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_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
|
||||
|
||||
// fespi_wip()
|
||||
/* fespi_wip() */
|
||||
as_add_set_dir(as, FESPI_DIR_RX);
|
||||
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
|
||||
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);
|
||||
if (cur_count > count)
|
||||
cur_count = count;
|
||||
if (algorithm_wa) {
|
||||
if (algorithm_wa)
|
||||
retval = steps_add_buffer_write(as, buffer, offset, cur_count);
|
||||
} else {
|
||||
else
|
||||
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
|
||||
}
|
||||
if (retval != ERROR_OK)
|
||||
goto err;
|
||||
offset += cur_count;
|
||||
|
@ -929,11 +935,10 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
|
|||
else
|
||||
cur_count = count & ~3;
|
||||
|
||||
if (algorithm_wa) {
|
||||
if (algorithm_wa)
|
||||
retval = steps_add_buffer_write(as, buffer, offset, cur_count);
|
||||
} else {
|
||||
else
|
||||
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
|
||||
}
|
||||
if (retval != ERROR_OK)
|
||||
goto err;
|
||||
|
||||
|
@ -945,18 +950,16 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
|
|||
|
||||
/* buffer tail */
|
||||
if (count > 0) {
|
||||
if (algorithm_wa) {
|
||||
if (algorithm_wa)
|
||||
retval = steps_add_buffer_write(as, buffer, offset, count);
|
||||
} else {
|
||||
else
|
||||
retval = slow_fespi_write_buffer(bank, buffer, offset, count);
|
||||
}
|
||||
if (retval != ERROR_OK)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (algorithm_wa) {
|
||||
if (algorithm_wa)
|
||||
retval = steps_execute(as, bank, algorithm_wa, data_wa);
|
||||
}
|
||||
|
||||
err:
|
||||
if (algorithm_wa) {
|
||||
|
@ -1043,27 +1046,27 @@ static int fespi_probe(struct flash_bank *bank)
|
|||
fespi_info->probed = 0;
|
||||
|
||||
if (fespi_info->ctrl_base == 0) {
|
||||
for (target_device = target_devices ; target_device->name ; ++target_device)
|
||||
if (target_device->tap_idcode == target->tap->idcode)
|
||||
break;
|
||||
for (target_device = target_devices ; target_device->name ; ++target_device)
|
||||
if (target_device->tap_idcode == target->tap->idcode)
|
||||
break;
|
||||
|
||||
if (!target_device->name) {
|
||||
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
|
||||
target->tap->idcode);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
if (!target_device->name) {
|
||||
LOG_ERROR("Device ID 0x%" PRIx32 " is not known as FESPI capable",
|
||||
target->tap->idcode);
|
||||
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,
|
||||
target_device->name, bank->base);
|
||||
LOG_DEBUG("Valid FESPI on device %s at address 0x%" PRIx32,
|
||||
target_device->name, bank->base);
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("Assuming FESPI as specified at address 0x%x with ctrl at 0x%x",
|
||||
fespi_info->ctrl_base,
|
||||
bank->base);
|
||||
}
|
||||
ctrl_base = fespi_info->ctrl_base;
|
||||
ctrl_base = fespi_info->ctrl_base;
|
||||
|
||||
/* read and decode flash ID; returns in SW mode */
|
||||
FESPI_WRITE_REG(FESPI_REG_TXCTRL, FESPI_TXWM(1));
|
||||
|
|
|
@ -76,10 +76,8 @@ static void remote_bitbang_fill_buf(void)
|
|||
contiguous_available_space);
|
||||
if (count > 0) {
|
||||
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;
|
||||
}
|
||||
} else if (count == 0) {
|
||||
return;
|
||||
} else if (count < 0) {
|
||||
|
@ -171,7 +169,7 @@ static int remote_bitbang_read_sample(void)
|
|||
{
|
||||
if (remote_bitbang_start != remote_bitbang_end) {
|
||||
int c = remote_bitbang_buf[remote_bitbang_start];
|
||||
remote_bitbang_start =
|
||||
remote_bitbang_start =
|
||||
(remote_bitbang_start + 1) % sizeof(remote_bitbang_buf);
|
||||
return char_to_int(c);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ static int riscv_gdb_thread_packet(struct connection *connection, const char *pa
|
|||
if (strncmp(packet, "qfThreadInfo", 12) == 0) {
|
||||
riscv_update_threads(target->rtos);
|
||||
r->qs_thread_info_offset = 1;
|
||||
|
||||
|
||||
char m[16];
|
||||
snprintf(m, 16, "m%08x", (int)rtos->thread_details[0].threadid);
|
||||
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;
|
||||
}
|
||||
|
||||
const struct rtos_type riscv_rtos =
|
||||
{
|
||||
const struct rtos_type riscv_rtos = {
|
||||
.name = "riscv",
|
||||
.detect_rtos = riscv_detect_rtos,
|
||||
.create = riscv_create_rtos,
|
||||
|
|
|
@ -1286,10 +1286,10 @@ static int gdb_get_register_packet(struct connection *connection,
|
|||
}
|
||||
|
||||
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) {
|
||||
LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name);
|
||||
free (reg_list);
|
||||
free(reg_list);
|
||||
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);
|
||||
|
||||
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);
|
||||
free(bin_buf);
|
||||
free(reg_list);
|
||||
|
|
|
@ -17,7 +17,7 @@ static uint32_t load(const struct target *target, unsigned int rd,
|
|||
return ld(rd, base, offset);
|
||||
}
|
||||
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,
|
||||
|
@ -32,7 +32,7 @@ static uint32_t store(const struct target *target, unsigned int src,
|
|||
return sd(src, base, offset);
|
||||
}
|
||||
assert(0);
|
||||
return 0; // Silence -Werror=return-type
|
||||
return 0; /* Silence -Werror=return-type */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -138,8 +138,8 @@ void riscv_batch_add_nop(struct riscv_batch *batch)
|
|||
|
||||
void dump_field(const struct scan_field *field)
|
||||
{
|
||||
static const char *op_string[] = {"-", "r", "w", "?"};
|
||||
static const char *status_string[] = {"+", "?", "F", "b"};
|
||||
static const char * const op_string[] = {"-", "r", "w", "?"};
|
||||
static const char * const status_string[] = {"+", "?", "F", "b"};
|
||||
|
||||
if (debug_level < LOG_LVL_DEBUG)
|
||||
return;
|
||||
|
|
|
@ -295,7 +295,7 @@
|
|||
*
|
||||
* 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 (0xfULL << CSR_TDATA1_TYPE_OFFSET)
|
||||
/*
|
||||
|
@ -307,14 +307,14 @@
|
|||
*
|
||||
* 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 (0x1ULL << CSR_TDATA1_DMODE_OFFSET)
|
||||
/*
|
||||
* Trigger-specific data.
|
||||
*/
|
||||
#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_TDATA2 0x7a2
|
||||
#define CSR_TDATA2_DATA_OFFSET 0
|
||||
|
@ -325,10 +325,10 @@
|
|||
#define CSR_TDATA3_DATA_LENGTH XLEN
|
||||
#define CSR_TDATA3_DATA (((1L<<XLEN)-1) << CSR_TDATA3_DATA_OFFSET)
|
||||
#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 (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 (0x1ULL << CSR_MCONTROL_DMODE_OFFSET)
|
||||
/*
|
||||
|
@ -339,7 +339,7 @@
|
|||
* corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in
|
||||
* 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 (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET)
|
||||
/*
|
||||
|
@ -478,10 +478,10 @@
|
|||
#define CSR_MCONTROL_LOAD_LENGTH 1
|
||||
#define CSR_MCONTROL_LOAD (0x1ULL << CSR_MCONTROL_LOAD_OFFSET)
|
||||
#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 (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 (0x1ULL << CSR_ICOUNT_DMODE_OFFSET)
|
||||
/*
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef 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
|
||||
// its source tree. We must interpret the numbers the same here.
|
||||
/* 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. */
|
||||
enum gdb_regno {
|
||||
GDB_REGNO_ZERO = 0, /* Read-only register, always 0. */
|
||||
GDB_REGNO_RA = 1, /* Return Address. */
|
||||
|
|
|
@ -5,16 +5,19 @@
|
|||
#define S0 8
|
||||
#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);
|
||||
}
|
||||
|
||||
static uint32_t bit(uint32_t value, unsigned int b) {
|
||||
static uint32_t bit(uint32_t value, unsigned int b)
|
||||
{
|
||||
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) {
|
||||
static uint32_t jal(unsigned int rd, uint32_t imm)
|
||||
{
|
||||
return (bit(imm, 20) << 31) |
|
||||
(bits(imm, 10, 1) << 21) |
|
||||
(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) {
|
||||
static uint32_t csrsi(unsigned int csr, uint16_t imm)
|
||||
{
|
||||
return (csr << 20) |
|
||||
(bits(imm, 4, 0) << 15) |
|
||||
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) {
|
||||
static uint32_t csrw(unsigned int source, unsigned int csr)
|
||||
{
|
||||
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) {
|
||||
static uint32_t csrr(unsigned int rd, unsigned int csr)
|
||||
{
|
||||
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) {
|
||||
static uint32_t csrrs(unsigned int rd, unsigned int rs, unsigned int csr)
|
||||
{
|
||||
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) {
|
||||
static uint32_t csrrw(unsigned int rd, unsigned int rs, unsigned int csr)
|
||||
{
|
||||
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) { 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) { 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)
|
||||
|
@ -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) {
|
||||
static uint32_t csrci(unsigned int csr, uint16_t imm)
|
||||
{
|
||||
return (csr << 20) |
|
||||
(bits(imm, 4, 0) << 15) |
|
||||
MATCH_CSRRCI;
|
||||
|
|
|
@ -18,11 +18,10 @@ int riscv_program_init(struct riscv_program *p, struct target *target)
|
|||
p->target = target;
|
||||
p->instruction_count = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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) {
|
||||
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]);
|
||||
abort();
|
||||
return ERROR_FAIL;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -150,20 +150,20 @@ typedef struct {
|
|||
/* We only need the address so that we know the alignment of the buffer. */
|
||||
riscv_addr_t progbuf_address;
|
||||
|
||||
// Number of run-test/idle cycles the target requests we do after each dbus
|
||||
// access.
|
||||
/* Number of run-test/idle cycles the target requests we do after each dbus
|
||||
* access. */
|
||||
unsigned int dtmcontrol_idle;
|
||||
|
||||
// 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
|
||||
// in between accesses.
|
||||
/* 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
|
||||
* in between accesses. */
|
||||
unsigned int dmi_busy_delay;
|
||||
|
||||
// This value is increased every time we tried to execute two commands
|
||||
// consecutively, and the second one failed because the previous hadn't
|
||||
// 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
|
||||
// go low.
|
||||
/* This value is increased every time we tried to execute two commands
|
||||
* consecutively, and the second one failed because the previous hadn't
|
||||
* 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
|
||||
* go low. */
|
||||
unsigned int ac_busy_delay;
|
||||
|
||||
bool need_strict_step;
|
||||
|
@ -173,12 +173,12 @@ typedef struct {
|
|||
bool abstract_read_fpr_supported;
|
||||
bool abstract_write_fpr_supported;
|
||||
|
||||
// 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.
|
||||
// (Compare with errno.)
|
||||
/* 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.
|
||||
* (Compare with errno.) */
|
||||
uint8_t cmderr;
|
||||
|
||||
// Some fields from hartinfo.
|
||||
/* Some fields from hartinfo. */
|
||||
uint8_t datasize;
|
||||
uint8_t dataaccess;
|
||||
int16_t dataaddr;
|
||||
|
@ -232,7 +232,7 @@ static void decode_dmi(char *text, unsigned address, unsigned data)
|
|||
if (i > 0)
|
||||
*(text++) = ' ';
|
||||
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);
|
||||
} else {
|
||||
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 const char *op_string[] = {"-", "r", "w", "?"};
|
||||
static const char *status_string[] = {"+", "?", "F", "b"};
|
||||
static const char * const op_string[] = {"-", "r", "w", "?"};
|
||||
static const char * const status_string[] = {"+", "?", "F", "b"};
|
||||
|
||||
if (debug_level < LOG_LVL_DEBUG)
|
||||
return;
|
||||
|
@ -371,9 +371,8 @@ static dmi_status_t dmi_scan(struct target *target, uint16_t *address_in,
|
|||
if (exec)
|
||||
idle_count += info->ac_busy_delay;
|
||||
|
||||
if (idle_count) {
|
||||
if (idle_count)
|
||||
jtag_add_runtest(idle_count, TAP_IDLE);
|
||||
}
|
||||
|
||||
int retval = jtag_execute_queue();
|
||||
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;
|
||||
}
|
||||
|
||||
if (data_in) {
|
||||
if (data_in)
|
||||
*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);
|
||||
}
|
||||
|
||||
dump_field(&field);
|
||||
|
||||
|
@ -403,9 +400,9 @@ static uint64_t dmi_read(struct target *target, uint16_t address)
|
|||
|
||||
unsigned i = 0;
|
||||
|
||||
// This first loop ensures that the read request was actually sent
|
||||
// to the target. Note that if for some reason this stays busy,
|
||||
// it is actually due to the previous dmi_read or dmi_write.
|
||||
/* This first loop ensures that the read request was actually sent
|
||||
* to the target. Note that if for some reason this stays busy,
|
||||
* it is actually due to the previous dmi_read or dmi_write. */
|
||||
for (i = 0; i < 256; i++) {
|
||||
status = dmi_scan(target, NULL, NULL, DMI_OP_READ, address, 0,
|
||||
false);
|
||||
|
@ -424,9 +421,9 @@ static uint64_t dmi_read(struct target *target, uint16_t address)
|
|||
abort();
|
||||
}
|
||||
|
||||
// This second loop ensures that we got the read
|
||||
// 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.
|
||||
/* This second loop ensures that we got the read
|
||||
* 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. */
|
||||
uint64_t value;
|
||||
for (i = 0; i < 256; i++) {
|
||||
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;
|
||||
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++) {
|
||||
status = dmi_scan(target, NULL, NULL, DMI_OP_WRITE, address, value,
|
||||
address == DMI_COMMAND);
|
||||
|
@ -476,8 +473,9 @@ static void dmi_write(struct target *target, uint16_t address, uint64_t value)
|
|||
abort();
|
||||
}
|
||||
|
||||
// The second loop isn't strictly necessary, but would ensure that
|
||||
// the write is complete/ has no non-busy errors before returning from this function.
|
||||
/* The second loop isn't strictly necessary, but would ensure that the
|
||||
* write is complete/ has no non-busy errors before returning from this
|
||||
* function. */
|
||||
for (i = 0; i < 256; i++) {
|
||||
status = dmi_scan(target, NULL, NULL, DMI_OP_NOP, address, 0,
|
||||
false);
|
||||
|
@ -529,9 +527,8 @@ static int wait_for_idle(struct target *target, uint32_t *abstractcs)
|
|||
while (1) {
|
||||
*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;
|
||||
}
|
||||
|
||||
if (time(NULL) - start > riscv_command_timeout_sec) {
|
||||
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). "
|
||||
"Increase the timeout with riscv set_command_timeout_sec.",
|
||||
riscv_command_timeout_sec,
|
||||
*abstractcs);
|
||||
"Increase the timeout with riscv set_command_timeout_sec.",
|
||||
riscv_command_timeout_sec,
|
||||
*abstractcs);
|
||||
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);
|
||||
if (info->cmderr != 0) {
|
||||
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,
|
||||
info->cmderr));
|
||||
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_WRITE);
|
||||
|
||||
if (write_abstract_arg(target, 0, value) != ERROR_OK) {
|
||||
if (write_abstract_arg(target, 0, value) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
int result = execute_abstract_command(target, command);
|
||||
if (result != ERROR_OK) {
|
||||
|
@ -732,7 +728,7 @@ static int examine_progbuf(struct target *target)
|
|||
if (info->progbuf_writable != YNM_MAYBE)
|
||||
return ERROR_OK;
|
||||
|
||||
// Figure out if progbuf is writable.
|
||||
/* Figure out if progbuf is writable. */
|
||||
|
||||
if (info->progbufsize < 1) {
|
||||
info->progbuf_writable = YNM_NO;
|
||||
|
@ -761,8 +757,8 @@ static int examine_progbuf(struct target *target)
|
|||
return ERROR_FAIL;
|
||||
|
||||
if (result != ERROR_OK) {
|
||||
// This program might have failed if the program buffer is not
|
||||
// writable.
|
||||
/* This program might have failed if the program buffer is not
|
||||
* writable. */
|
||||
info->progbuf_writable = YNM_NO;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
@ -789,11 +785,11 @@ typedef enum {
|
|||
} memory_space_t;
|
||||
|
||||
typedef struct {
|
||||
// How can the debugger access this memory?
|
||||
/* How can the debugger access this memory? */
|
||||
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;
|
||||
// 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;
|
||||
} scratch_mem_t;
|
||||
|
||||
|
@ -812,12 +808,11 @@ static int scratch_find(struct target *target,
|
|||
alignment *= 2;
|
||||
|
||||
if (info->dataaccess == 1) {
|
||||
// Sign extend dataaddr.
|
||||
/* Sign extend dataaddr. */
|
||||
scratch->hart_address = info->dataaddr;
|
||||
if (info->dataaddr & (1<<11)) {
|
||||
if (info->dataaddr & (1<<11))
|
||||
scratch->hart_address |= 0xfffffffffffff000ULL;
|
||||
}
|
||||
// Align.
|
||||
/* Align. */
|
||||
scratch->hart_address = (scratch->hart_address + alignment - 1) & ~(alignment - 1);
|
||||
|
||||
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)
|
||||
return ERROR_FAIL;
|
||||
|
||||
// Allow for ebreak at the end of the program.
|
||||
unsigned program_size = (program->instruction_count + 1 ) * 4;
|
||||
/* Allow for ebreak at the end of the program. */
|
||||
unsigned program_size = (program->instruction_count + 1) * 4;
|
||||
scratch->hart_address = (info->progbuf_address + program_size + alignment - 1) &
|
||||
~(alignment - 1);
|
||||
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;
|
||||
|
||||
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));
|
||||
} else {
|
||||
else
|
||||
riscv_program_insert(&program, fmv_w_x(number - GDB_REGNO_FPR0, S0));
|
||||
}
|
||||
} else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) {
|
||||
riscv_program_csrw(&program, S0, number);
|
||||
} else {
|
||||
|
@ -976,7 +970,7 @@ static int register_write_direct(struct target *target, unsigned number,
|
|||
|
||||
int exec_out = riscv_program_exec(&program, target);
|
||||
|
||||
// Restore S0.
|
||||
/* Restore S0. */
|
||||
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
|
||||
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)
|
||||
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) {
|
||||
// TODO: Possibly set F in mstatus.
|
||||
/* TODO: Possibly set F in mstatus. */
|
||||
if (riscv_supports_extension(target, 'D') && riscv_xlen(target) < 64) {
|
||||
/* There are no instructions to move all the bits from a
|
||||
* 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();
|
||||
}
|
||||
|
||||
// Execute program.
|
||||
/* Execute program. */
|
||||
result = riscv_program_exec(&program, target);
|
||||
|
||||
if (use_scratch) {
|
||||
if (scratch_read64(target, &scratch, value) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
} else {
|
||||
// Read S0
|
||||
/* Read S0 */
|
||||
if (register_read_direct(target, value, GDB_REGNO_S0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
// Restore S0.
|
||||
/* Restore S0. */
|
||||
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -1094,11 +1088,11 @@ static int init_target(struct command_context *cmd_ctx,
|
|||
info->dmi_busy_delay = 0;
|
||||
info->ac_busy_delay = 0;
|
||||
|
||||
// Assume all these abstract commands are supported until we learn
|
||||
// otherwise.
|
||||
// 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
|
||||
// the future we probably should.
|
||||
/* Assume all these abstract commands are supported until we learn
|
||||
* otherwise.
|
||||
* 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
|
||||
* the future we probably should. */
|
||||
info->abstract_read_csr_supported = true;
|
||||
info->abstract_write_csr_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)
|
||||
{
|
||||
// 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);
|
||||
LOG_DEBUG("dtmcontrol=0x%x", dtmcontrol);
|
||||
|
@ -1147,7 +1141,7 @@ static int examine(struct target *target)
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
// Reset the Debug Module.
|
||||
/* Reset the Debug Module. */
|
||||
dmi_write(target, DMI_DMCONTROL, 0);
|
||||
dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
|
||||
uint32_t dmcontrol = dmi_read(target, DMI_DMCONTROL);
|
||||
|
@ -1184,7 +1178,7 @@ static int examine(struct target *target)
|
|||
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);
|
||||
info->datacount = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
|
||||
info->progbufsize = get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE);
|
||||
|
@ -1193,8 +1187,8 @@ static int examine(struct target *target)
|
|||
RISCV_INFO(r);
|
||||
r->impebreak = get_field(dmstatus, DMI_DMSTATUS_IMPEBREAK);
|
||||
|
||||
// Don't call any riscv_* functions until after we've counted the number of
|
||||
// cores and initialized registers.
|
||||
/* Don't call any riscv_* functions until after we've counted the number of
|
||||
* cores and initialized registers. */
|
||||
for (int i = 0; i < RISCV_MAX_HARTS; ++i) {
|
||||
if (!riscv_rtos_enabled(target) && i != target->coreid)
|
||||
continue;
|
||||
|
@ -1203,29 +1197,26 @@ static int examine(struct target *target)
|
|||
riscv013_select_current_hart(target);
|
||||
|
||||
uint32_t s = dmi_read(target, DMI_DMSTATUS);
|
||||
if (get_field(s, DMI_DMSTATUS_ANYNONEXISTENT)) {
|
||||
if (get_field(s, DMI_DMSTATUS_ANYNONEXISTENT))
|
||||
break;
|
||||
}
|
||||
r->hart_count = i + 1;
|
||||
|
||||
if (!riscv_is_halted(target)) {
|
||||
if (!riscv_is_halted(target))
|
||||
riscv013_halt_current_hart(target);
|
||||
}
|
||||
|
||||
/* Without knowing anything else we can at least mess with the
|
||||
* program buffer. */
|
||||
r->debug_buffer_size[i] = info->progbufsize;
|
||||
|
||||
int result = register_read_abstract(target, NULL, GDB_REGNO_S0, 64);
|
||||
if (result == ERROR_OK) {
|
||||
if (result == ERROR_OK)
|
||||
r->xlen[i] = 64;
|
||||
} else {
|
||||
else
|
||||
r->xlen[i] = 32;
|
||||
}
|
||||
|
||||
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)
|
||||
return ERROR_FAIL;
|
||||
|
||||
|
@ -1241,19 +1232,18 @@ static int examine(struct target *target)
|
|||
riscv_enumerate_triggers(target);
|
||||
|
||||
/* 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);
|
||||
target->state = TARGET_RUNNING;
|
||||
|
||||
target_set_examined(target);
|
||||
|
||||
if (target->rtos) {
|
||||
if (target->rtos)
|
||||
riscv_update_threads(target->rtos);
|
||||
}
|
||||
|
||||
// Some regression suites rely on seeing 'Examined RISC-V core' to know
|
||||
// when they can connect with gdb/telnet.
|
||||
// We will need to update those suites if we want to change that text.
|
||||
/* Some regression suites rely on seeing 'Examined RISC-V core' to know
|
||||
* when they can connect with gdb/telnet.
|
||||
* We will need to update those suites if we want to change that text. */
|
||||
LOG_INFO("Examined RISC-V core; found %d harts",
|
||||
riscv_count_harts(target));
|
||||
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);
|
||||
|
||||
if (target->rtos) {
|
||||
// There's only one target, and OpenOCD thinks each hart is a thread.
|
||||
// We must reset them all.
|
||||
/* There's only one target, and OpenOCD thinks each hart is a thread.
|
||||
* 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;
|
||||
for (int i = 0; i < riscv_count_harts(target); ++i) {
|
||||
if (!riscv_hart_enabled(target, i))
|
||||
|
@ -1292,12 +1282,12 @@ static int assert_reset(struct target *target)
|
|||
target->reset_halt ? 1 : 0);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
}
|
||||
// Assert ndmreset
|
||||
/* Assert ndmreset */
|
||||
control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
||||
} else {
|
||||
// Reset just this hart.
|
||||
/* Reset just this hart. */
|
||||
uint32_t control = set_field(control_base, DMI_DMCONTROL_HARTSEL,
|
||||
r->current_hartid);
|
||||
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);
|
||||
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);
|
||||
if (!get_field(rb, DMI_DMCONTROL_HARTRESET)) {
|
||||
// Use ndmreset instead. That will reset the entire device, but
|
||||
// that's probably what OpenOCD wants anyway.
|
||||
/* Use ndmreset instead. That will reset the entire device, but
|
||||
* that's probably what OpenOCD wants anyway. */
|
||||
control = set_field(control, DMI_DMCONTROL_HARTRESET, 0);
|
||||
control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, control);
|
||||
|
@ -1329,7 +1319,7 @@ static int deassert_reset(struct target *target)
|
|||
|
||||
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;
|
||||
control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0);
|
||||
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;
|
||||
riscv_program_init(&program, target);
|
||||
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)
|
||||
return ERROR_FAIL;
|
||||
|
||||
// Write the program (load, increment)
|
||||
/* Write the program (load, increment) */
|
||||
struct riscv_program program;
|
||||
riscv_program_init(&program, target);
|
||||
switch (size) {
|
||||
|
@ -1464,7 +1455,7 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
return ERROR_FAIL;
|
||||
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)
|
||||
return ERROR_FAIL;
|
||||
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)
|
||||
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,
|
||||
1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
|
||||
|
||||
// read_addr is the next address that the hart will read from, which is the
|
||||
// value in s0.
|
||||
/* read_addr is the next address that the hart will read from, which is the
|
||||
* value in s0. */
|
||||
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 fin_addr = address + (count * size);
|
||||
unsigned skip = 1;
|
||||
while (read_addr < fin_addr) {
|
||||
LOG_DEBUG("read_addr=0x%" PRIx64 ", receive_addr=0x%" PRIx64
|
||||
", fin_addr=0x%" PRIx64, read_addr, receive_addr, fin_addr);
|
||||
// The pipeline looks like this:
|
||||
// memory -> s1 -> dm_data0 -> debugger
|
||||
// It advances every time the debugger reads dmdata0.
|
||||
// So at any time the debugger has just read mem[s0 - 3*size],
|
||||
// dm_data0 contains mem[s0 - 2*size]
|
||||
// s1 contains mem[s0-size]
|
||||
/* The pipeline looks like this:
|
||||
* memory -> s1 -> dm_data0 -> debugger
|
||||
* It advances every time the debugger reads dmdata0.
|
||||
* So at any time the debugger has just read mem[s0 - 3*size],
|
||||
* dm_data0 contains mem[s0 - 2*size]
|
||||
* s1 contains mem[s0-size] */
|
||||
|
||||
LOG_DEBUG("creating burst to read from 0x%" TARGET_PRIxADDR
|
||||
" 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);
|
||||
|
||||
// Wait for the target to finish performing the last abstract command,
|
||||
// and update our copy of cmderr.
|
||||
/* Wait for the target to finish performing the last abstract command,
|
||||
* and update our copy of cmderr. */
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
||||
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 <cassert>
|
||||
|
||||
|
||||
#include "debug_module.h"
|
||||
@@ -398,6 +400,15 @@ bool debug_module_t::perform_abstract_command()
|
||||
// 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);
|
||||
|
||||
// This is definitely a good version of the value that we
|
||||
// attempted to read when we discovered that the target was
|
||||
// busy.
|
||||
/* This is definitely a good version of the value that we
|
||||
* attempted to read when we discovered that the target was
|
||||
* busy. */
|
||||
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)
|
||||
return ERROR_FAIL;
|
||||
// Restore the command, and execute it.
|
||||
// Now DMI_DATA0 contains the next value just as it would if no
|
||||
// error had occurred.
|
||||
/* Restore the command, and execute it.
|
||||
* Now DMI_DATA0 contains the next value just as it would if no
|
||||
* error had occurred. */
|
||||
dmi_write(target, DMI_COMMAND, command);
|
||||
|
||||
dmi_write(target, DMI_ABSTRACTAUTO,
|
||||
|
@ -1588,11 +1579,10 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
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++) {
|
||||
if (read_addr >= next_read_addr) {
|
||||
if (read_addr >= next_read_addr)
|
||||
break;
|
||||
}
|
||||
|
||||
read_addr += size;
|
||||
|
||||
|
@ -1625,14 +1615,14 @@ static int read_memory(struct target *target, target_addr_t address,
|
|||
dmi_write(target, DMI_ABSTRACTAUTO, 0);
|
||||
|
||||
if (count > 1) {
|
||||
// Read the penultimate word.
|
||||
/* Read the penultimate word. */
|
||||
uint64_t value = dmi_read(target, DMI_DATA0);
|
||||
write_to_buf(buffer + receive_addr - address, value, size);
|
||||
LOG_DEBUG("M[0x%" TARGET_PRIxADDR "] reads 0x%" PRIx64, receive_addr, value);
|
||||
receive_addr += size;
|
||||
}
|
||||
|
||||
// Read the last word.
|
||||
/* Read the last word. */
|
||||
uint64_t value;
|
||||
if (register_read_direct(target, &value, GDB_REGNO_S1) != ERROR_OK)
|
||||
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)
|
||||
return ERROR_FAIL;
|
||||
|
||||
// Write the program (store, increment)
|
||||
/* Write the program (store, increment) */
|
||||
struct riscv_program program;
|
||||
riscv_program_init(&program, target);
|
||||
|
||||
|
@ -1736,12 +1726,12 @@ static int write_memory(struct target *target, target_addr_t address,
|
|||
address + offset) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
// Write value.
|
||||
/* Write value. */
|
||||
dmi_write(target, DMI_DATA0, value);
|
||||
|
||||
// Write and execute command that moves value into S1 and
|
||||
// executes program buffer.
|
||||
uint32_t command = access_register_command(GDB_REGNO_S1, 32,
|
||||
/* Write and execute command that moves value into S1 and
|
||||
* executes program buffer. */
|
||||
uint32_t command = access_register_command(GDB_REGNO_S1, 32,
|
||||
AC_ACCESS_REGISTER_POSTEXEC |
|
||||
AC_ACCESS_REGISTER_TRANSFER |
|
||||
AC_ACCESS_REGISTER_WRITE);
|
||||
|
@ -1749,7 +1739,7 @@ static int write_memory(struct target *target, target_addr_t address,
|
|||
if (result != ERROR_OK)
|
||||
return result;
|
||||
|
||||
// Turn on autoexec
|
||||
/* Turn on autoexec */
|
||||
dmi_write(target, DMI_ABSTRACTAUTO,
|
||||
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_free(batch);
|
||||
|
||||
// Note that if the scan resulted in a Busy DMI response, it
|
||||
// is this read to abstractcs that will cause the dmi_busy_delay
|
||||
// to be incremented if necessary.
|
||||
/* Note that if the scan resulted in a Busy DMI response, it
|
||||
* is this read to abstractcs that will cause the dmi_busy_delay
|
||||
* to be incremented if necessary. */
|
||||
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
|
||||
|
@ -1815,8 +1805,7 @@ static int arch_state(struct target *target)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
struct target_type riscv013_target =
|
||||
{
|
||||
struct target_type riscv013_target = {
|
||||
.name = "riscv",
|
||||
|
||||
.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)
|
||||
{
|
||||
// Wait for busy to go away.
|
||||
/* Wait for busy to go away. */
|
||||
time_t start = time(NULL);
|
||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY)) {
|
||||
|
@ -2117,6 +2106,6 @@ void riscv013_clear_abstract_error(struct target *target)
|
|||
break;
|
||||
}
|
||||
}
|
||||
// Clear the error status.
|
||||
/* Clear the error status. */
|
||||
dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
#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_W (1<<1)
|
||||
#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.*/
|
||||
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
|
||||
|
||||
bool riscv_use_scratch_ram = false;
|
||||
uint64_t riscv_scratch_ram_address = 0;
|
||||
bool riscv_use_scratch_ram;
|
||||
uint64_t riscv_scratch_ram_address;
|
||||
|
||||
/* In addition to the ones in the standard spec, we'll also expose additional
|
||||
* CSRs in this list.
|
||||
|
@ -284,7 +284,7 @@ static void trigger_from_breakpoint(struct trigger *trigger,
|
|||
trigger->read = false;
|
||||
trigger->write = false;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -304,7 +304,7 @@ static int maybe_add_trigger_t1(struct target *target, unsigned hartid,
|
|||
const uint32_t bpcontrol_bpaction = 0xff << 11;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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_h, !!(r->misa & (1 << ('H' - 'A'))));
|
||||
tdata1 |= bpcontrol_m;
|
||||
tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); // exact match
|
||||
tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); // cause bp exception
|
||||
tdata1 = set_field(tdata1, bpcontrol_bpmatch, 0); /* exact match */
|
||||
tdata1 = set_field(tdata1, bpcontrol_bpaction, 0); /* cause bp exception */
|
||||
|
||||
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);
|
||||
|
||||
// tselect is already set
|
||||
/* tselect is already set */
|
||||
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;
|
||||
}
|
||||
|
||||
// address/data match trigger
|
||||
/* address/data match trigger */
|
||||
tdata1 |= MCONTROL_DMODE(riscv_xlen(target));
|
||||
tdata1 = set_field(tdata1, MCONTROL_ACTION,
|
||||
MCONTROL_ACTION_DEBUG_MODE);
|
||||
|
@ -390,12 +390,12 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
|||
{
|
||||
RISCV_INFO(r);
|
||||
|
||||
// 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
|
||||
// same core.
|
||||
/* 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
|
||||
* same core. */
|
||||
|
||||
// Otherwise, we just set the trigger on the one hart this target deals
|
||||
// with.
|
||||
/* Otherwise, we just set the trigger on the one hart this target deals
|
||||
* with. */
|
||||
|
||||
riscv_reg_t tselect[RISCV_MAX_HARTS];
|
||||
|
||||
|
@ -412,9 +412,8 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
|||
|
||||
unsigned int 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!riscv_hart_enabled(target, hartid))
|
||||
continue;
|
||||
if (hartid > first_hart) {
|
||||
if (hartid > first_hart)
|
||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TSELECT, i);
|
||||
}
|
||||
switch (type) {
|
||||
case 1:
|
||||
result = maybe_add_trigger_t1(target, hartid, trigger, tdata1);
|
||||
|
@ -440,14 +438,12 @@ static int add_trigger(struct target *target, struct trigger *trigger)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (result != ERROR_OK) {
|
||||
if (result != ERROR_OK)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (result != ERROR_OK) {
|
||||
if (result != ERROR_OK)
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Using trigger %d (type %d) for bp %d", i, type,
|
||||
trigger->unique_id);
|
||||
|
@ -481,11 +477,10 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
|
|||
}
|
||||
|
||||
int retval;
|
||||
if (breakpoint->length == 4) {
|
||||
if (breakpoint->length == 4)
|
||||
retval = target_write_u32(target, breakpoint->address, ebreak());
|
||||
} else {
|
||||
else
|
||||
retval = target_write_u16(target, breakpoint->address, ebreak_c());
|
||||
}
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_ERROR("Failed to write %d-byte breakpoint instruction at 0x%"
|
||||
TARGET_PRIxADDR, breakpoint->length, breakpoint->address);
|
||||
|
@ -496,9 +491,8 @@ int riscv_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
|
|||
struct trigger trigger;
|
||||
trigger_from_breakpoint(&trigger, breakpoint);
|
||||
int result = add_trigger(target, &trigger);
|
||||
if (result != ERROR_OK) {
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
} else {
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (i >= r->trigger_count[first_hart]) {
|
||||
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;
|
||||
trigger_from_breakpoint(&trigger, breakpoint);
|
||||
int result = remove_trigger(target, &trigger);
|
||||
if (result != ERROR_OK) {
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
} else {
|
||||
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->write = (watchpoint->rw == WPT_WRITE || watchpoint->rw == WPT_ACCESS);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -599,9 +591,8 @@ int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
|
|||
trigger_from_watchpoint(&trigger, watchpoint);
|
||||
|
||||
int result = add_trigger(target, &trigger);
|
||||
if (result != ERROR_OK) {
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
watchpoint->set = true;
|
||||
|
||||
return ERROR_OK;
|
||||
|
@ -614,9 +605,8 @@ int riscv_remove_watchpoint(struct target *target,
|
|||
trigger_from_watchpoint(&trigger, watchpoint);
|
||||
|
||||
int result = remove_trigger(target, &trigger);
|
||||
if (result != ERROR_OK) {
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
watchpoint->set = false;
|
||||
|
||||
return ERROR_OK;
|
||||
|
@ -651,7 +641,7 @@ static int riscv_examine(struct target *target)
|
|||
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;
|
||||
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 *));
|
||||
if (!*reg_list) {
|
||||
if (!*reg_list)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < *reg_list_size; i++) {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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,
|
||||
struct mem_param *mem_params, int num_reg_params,
|
||||
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;
|
||||
}
|
||||
|
||||
/// Save registers
|
||||
/* Save registers */
|
||||
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;
|
||||
}
|
||||
uint64_t saved_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size);
|
||||
|
||||
uint64_t saved_regs[32];
|
||||
|
@ -839,17 +827,15 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
|
|||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (r->type->get(r) != ERROR_OK) {
|
||||
if (r->type->get(r) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Disable Interrupts before attempting to run the algorithm.
|
||||
/* Disable Interrupts before attempting to run the algorithm. */
|
||||
uint64_t current_mstatus;
|
||||
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);
|
||||
|
||||
/// Run algorithm
|
||||
/* Run algorithm */
|
||||
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;
|
||||
}
|
||||
|
||||
int64_t start = timeval_ms();
|
||||
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);
|
||||
if (result != ERROR_OK) {
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (reg_pc->type->get(reg_pc) != ERROR_OK) {
|
||||
if (reg_pc->type->get(reg_pc) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
uint64_t final_pc = buf_get_u64(reg_pc->value, 0, reg_pc->size);
|
||||
if (final_pc != exit_point) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Restore Interrupts
|
||||
/* Restore Interrupts */
|
||||
LOG_DEBUG("Restoring Interrupts");
|
||||
buf_set_u64(mstatus_bytes, 0, info->xlen[0], current_mstatus);
|
||||
reg_mstatus->type->set(reg_mstatus, mstatus_bytes);
|
||||
|
||||
/// Restore registers
|
||||
/* Restore registers */
|
||||
uint8_t buf[8];
|
||||
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;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_reg_params; i++) {
|
||||
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);
|
||||
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_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.
|
||||
*/
|
||||
|
||||
static int riscv_checksum_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count,
|
||||
uint32_t* checksum)
|
||||
uint32_t *checksum)
|
||||
{
|
||||
*checksum = 0xFFFFFFFF;
|
||||
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")
|
||||
Not yet implemented.
|
||||
*/
|
||||
int riscv_blank_check_memory(struct target * target,
|
||||
int riscv_blank_check_memory(struct target *target,
|
||||
target_addr_t address,
|
||||
uint32_t count,
|
||||
uint32_t * blank,
|
||||
uint32_t *blank,
|
||||
uint8_t erased_value)
|
||||
{
|
||||
*blank = 0;
|
||||
|
@ -1031,7 +1012,7 @@ int riscv_openocd_poll(struct target *target)
|
|||
target->debug_reason = DBG_REASON_SINGLESTEP;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (riscv_rtos_enabled(target)) {
|
||||
target->rtos->current_threadid = triggered_hart + 1;
|
||||
target->rtos->current_thread = triggered_hart + 1;
|
||||
|
@ -1075,9 +1056,8 @@ int riscv_openocd_resume(
|
|||
) {
|
||||
LOG_DEBUG("resuming all harts");
|
||||
|
||||
if (!current) {
|
||||
if (!current)
|
||||
riscv_set_register(target, GDB_REGNO_PC, address);
|
||||
}
|
||||
|
||||
int out = riscv_resume_all_harts(target);
|
||||
if (out != ERROR_OK) {
|
||||
|
@ -1099,9 +1079,8 @@ int riscv_openocd_step(
|
|||
) {
|
||||
LOG_DEBUG("stepping rtos hart");
|
||||
|
||||
if (!current) {
|
||||
if (!current)
|
||||
riscv_set_register(target, GDB_REGNO_PC, address);
|
||||
}
|
||||
|
||||
int out = riscv_step_rtos_hart(target);
|
||||
if (out != ERROR_OK) {
|
||||
|
@ -1126,7 +1105,7 @@ COMMAND_HANDLER(riscv_set_command_timeout_sec)
|
|||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
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]);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
@ -1143,7 +1122,7 @@ COMMAND_HANDLER(riscv_set_reset_timeout_sec)
|
|||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
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]);
|
||||
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++) {
|
||||
char c = CMD_ARGV[0][i];
|
||||
if (isspace(c)) {
|
||||
// Ignore whitespace.
|
||||
/* Ignore whitespace. */
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1303,8 +1282,7 @@ const struct command_registration riscv_command_handlers[] = {
|
|||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
struct target_type riscv_target =
|
||||
{
|
||||
struct target_type riscv_target = {
|
||||
.name = "riscv",
|
||||
|
||||
.init_target = riscv_init_target,
|
||||
|
@ -1443,13 +1421,12 @@ bool riscv_supports_extension(struct target *target, char letter)
|
|||
{
|
||||
RISCV_INFO(r);
|
||||
unsigned num;
|
||||
if (letter >= 'a' && letter <= 'z') {
|
||||
if (letter >= 'a' && letter <= 'z')
|
||||
num = letter - 'a';
|
||||
} else if (letter >= 'A' && letter <= 'Z') {
|
||||
else if (letter >= 'A' && letter <= 'Z')
|
||||
num = letter - 'A';
|
||||
} else {
|
||||
else
|
||||
return false;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (target == NULL) return 1;
|
||||
if (target == NULL)
|
||||
return 1;
|
||||
RISCV_INFO(r);
|
||||
if (r == NULL) return 1;
|
||||
if (r == NULL)
|
||||
return 1;
|
||||
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)
|
||||
{
|
||||
// TODO: propagate errors
|
||||
/* TODO: propagate errors */
|
||||
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);
|
||||
uint64_t tselect_rb = riscv_get_register_on_hart(target, hartid,
|
||||
GDB_REGNO_TSELECT);
|
||||
// Mask off the top bit, which is used as tdrmode in old
|
||||
// implementations.
|
||||
/* Mask off the top bit, which is used as tdrmode in old
|
||||
* implementations. */
|
||||
tselect_rb &= ~(1ULL << (riscv_xlen(target)-1));
|
||||
if (tselect_rb != t)
|
||||
break;
|
||||
|
@ -1707,14 +1686,13 @@ int riscv_enumerate_triggers(struct target *target)
|
|||
int type = get_field(tdata1, MCONTROL_TYPE(riscv_xlen(target)));
|
||||
switch (type) {
|
||||
case 1:
|
||||
// On these older cores we don't support software using
|
||||
// triggers.
|
||||
/* On these older cores we don't support software using
|
||||
* triggers. */
|
||||
riscv_set_register_on_hart(target, hartid, GDB_REGNO_TDATA1, 0);
|
||||
break;
|
||||
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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1765,15 +1743,14 @@ const char *gdb_regno_name(enum gdb_regno regno)
|
|||
case GDB_REGNO_PRIV:
|
||||
return "priv";
|
||||
default:
|
||||
if (regno <= GDB_REGNO_XPR31) {
|
||||
if (regno <= GDB_REGNO_XPR31)
|
||||
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);
|
||||
} 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);
|
||||
} else {
|
||||
else
|
||||
sprintf(buf, "gdb_regno_%d", regno);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
@ -1864,15 +1841,15 @@ int riscv_init_registers(struct target *target)
|
|||
#include "encoding.h"
|
||||
#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);
|
||||
unsigned csr_info_index = 0;
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// between).
|
||||
/* 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
|
||||
* 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
|
||||
* between). */
|
||||
for (uint32_t number = 0; number < GDB_REGNO_COUNT; number++) {
|
||||
struct reg *r = &target->reg_cache->reg_list[number];
|
||||
r->caller_save = true;
|
||||
|
@ -1883,43 +1860,107 @@ int riscv_init_registers(struct target *target)
|
|||
r->arch_info = target;
|
||||
r->number = number;
|
||||
r->size = riscv_xlen(target);
|
||||
// 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
|
||||
// of other things to break in that case as well.
|
||||
/* 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
|
||||
* of other things to break in that case as well. */
|
||||
if (number <= GDB_REGNO_XPR31) {
|
||||
switch (number) {
|
||||
case GDB_REGNO_ZERO: r->name = "zero"; break;
|
||||
case GDB_REGNO_RA: r->name = "ra"; break;
|
||||
case GDB_REGNO_SP: r->name = "sp"; break;
|
||||
case GDB_REGNO_GP: r->name = "gp"; break;
|
||||
case GDB_REGNO_TP: r->name = "tp"; break;
|
||||
case GDB_REGNO_T0: r->name = "t0"; break;
|
||||
case GDB_REGNO_T1: r->name = "t1"; break;
|
||||
case GDB_REGNO_T2: r->name = "t2"; break;
|
||||
case GDB_REGNO_FP: r->name = "fp"; break;
|
||||
case GDB_REGNO_S1: r->name = "s1"; break;
|
||||
case GDB_REGNO_A0: 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;
|
||||
case GDB_REGNO_ZERO:
|
||||
r->name = "zero";
|
||||
break;
|
||||
case GDB_REGNO_RA:
|
||||
r->name = "ra";
|
||||
break;
|
||||
case GDB_REGNO_SP:
|
||||
r->name = "sp";
|
||||
break;
|
||||
case GDB_REGNO_GP:
|
||||
r->name = "gp";
|
||||
break;
|
||||
case GDB_REGNO_TP:
|
||||
r->name = "tp";
|
||||
break;
|
||||
case GDB_REGNO_T0:
|
||||
r->name = "t0";
|
||||
break;
|
||||
case GDB_REGNO_T1:
|
||||
r->name = "t1";
|
||||
break;
|
||||
case GDB_REGNO_T2:
|
||||
r->name = "t2";
|
||||
break;
|
||||
case GDB_REGNO_FP:
|
||||
r->name = "fp";
|
||||
break;
|
||||
case GDB_REGNO_S1:
|
||||
r->name = "s1";
|
||||
break;
|
||||
case GDB_REGNO_A0:
|
||||
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->feature = &feature_cpu;
|
||||
|
@ -1938,38 +1979,102 @@ int riscv_init_registers(struct target *target)
|
|||
r->exist = false;
|
||||
}
|
||||
switch (number) {
|
||||
case GDB_REGNO_FT0: r->name = "ft0"; break;
|
||||
case GDB_REGNO_FT1: r->name = "ft1"; break;
|
||||
case GDB_REGNO_FT2: r->name = "ft2"; break;
|
||||
case GDB_REGNO_FT3: r->name = "ft3"; break;
|
||||
case GDB_REGNO_FT4: r->name = "ft4"; break;
|
||||
case GDB_REGNO_FT5: r->name = "ft5"; break;
|
||||
case GDB_REGNO_FT6: r->name = "ft6"; break;
|
||||
case GDB_REGNO_FT7: r->name = "ft7"; break;
|
||||
case GDB_REGNO_FS0: r->name = "fs0"; break;
|
||||
case GDB_REGNO_FS1: r->name = "fs1"; break;
|
||||
case GDB_REGNO_FA0: 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;
|
||||
case GDB_REGNO_FT0:
|
||||
r->name = "ft0";
|
||||
break;
|
||||
case GDB_REGNO_FT1:
|
||||
r->name = "ft1";
|
||||
break;
|
||||
case GDB_REGNO_FT2:
|
||||
r->name = "ft2";
|
||||
break;
|
||||
case GDB_REGNO_FT3:
|
||||
r->name = "ft3";
|
||||
break;
|
||||
case GDB_REGNO_FT4:
|
||||
r->name = "ft4";
|
||||
break;
|
||||
case GDB_REGNO_FT5:
|
||||
r->name = "ft5";
|
||||
break;
|
||||
case GDB_REGNO_FT6:
|
||||
r->name = "ft6";
|
||||
break;
|
||||
case GDB_REGNO_FT7:
|
||||
r->name = "ft7";
|
||||
break;
|
||||
case GDB_REGNO_FS0:
|
||||
r->name = "fs0";
|
||||
break;
|
||||
case GDB_REGNO_FS1:
|
||||
r->name = "fs1";
|
||||
break;
|
||||
case GDB_REGNO_FA0:
|
||||
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->feature = &feature_fpu;
|
||||
|
@ -1986,11 +2091,11 @@ int riscv_init_registers(struct target *target)
|
|||
r->name = csr_info[csr_info_index].name;
|
||||
} else {
|
||||
sprintf(reg_name, "csr%d", csr_number);
|
||||
// Assume unnamed registers don't exist, unless we have some
|
||||
// configuration that tells us otherwise. That's important
|
||||
// because eg. Eclipse crashes if a target has too many
|
||||
// registers, and apparently has no way of only showing a
|
||||
// subset of registers in any case.
|
||||
/* Assume unnamed registers don't exist, unless we have some
|
||||
* configuration that tells us otherwise. That's important
|
||||
* because eg. Eclipse crashes if a target has too many
|
||||
* registers, and apparently has no way of only showing a
|
||||
* subset of registers in any case. */
|
||||
r->exist = false;
|
||||
}
|
||||
|
||||
|
@ -2032,9 +2137,8 @@ int riscv_init_registers(struct target *target)
|
|||
r->feature = &feature_virtual;
|
||||
r->size = 8;
|
||||
}
|
||||
if (reg_name[0]) {
|
||||
if (reg_name[0])
|
||||
r->name = reg_name;
|
||||
}
|
||||
reg_name += strlen(reg_name) + 1;
|
||||
assert(reg_name < info->reg_names + GDB_REGNO_COUNT * max_reg_name_len);
|
||||
r->value = &info->reg_cache_values[number];
|
||||
|
|
|
@ -141,7 +141,7 @@ int riscv_openocd_resume(
|
|||
struct target *target,
|
||||
int current,
|
||||
target_addr_t address,
|
||||
int handle_breakpoints,
|
||||
int handle_breakpoints,
|
||||
int debug_execution
|
||||
);
|
||||
|
||||
|
|
|
@ -2830,8 +2830,8 @@ COMMAND_HANDLER(handle_reg_command)
|
|||
|
||||
retval = reg->type->set(reg, buf);
|
||||
if (retval != ERROR_OK) {
|
||||
LOG_DEBUG("Couldn't set register %s.", reg->name);
|
||||
free (buf);
|
||||
LOG_DEBUG("Couldn't set register %s.", reg->name);
|
||||
free(buf);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue