Merge branch 'master' into from_upstream

Conflicts:
      .gitmodules
      .travis.yml
      jimtcl
      src/jtag/core.c
      src/jtag/drivers/ftdi.c
      src/jtag/drivers/libjaylink
      src/jtag/drivers/mpsse.c
      src/jtag/drivers/stlink_usb.c
      src/rtos/hwthread.c
      src/target/riscv/riscv-013.c
      src/target/riscv/riscv.c
      tcl/board/sifive-hifive1-revb.cfg

Change-Id: I2d26ebeffb4c1374730d2e20e6e2a7710403657c
This commit is contained in:
Tim Newsome
2020-06-23 13:05:43 -07:00
766 changed files with 21771 additions and 5946 deletions
+24 -7
View File
@@ -263,6 +263,7 @@ int nand_read_status(struct nand_device *nand, uint8_t *status)
return ERROR_NAND_DEVICE_NOT_PROBED;
/* Send read status command */
/* FIXME: errors returned from nand->controller are mostly ignored! */
nand->controller->command(nand, NAND_CMD_STATUS);
alive_sleep(1);
@@ -301,7 +302,8 @@ static int nand_poll_ready(struct nand_device *nand, int timeout)
int nand_probe(struct nand_device *nand)
{
uint8_t manufacturer_id, device_id;
uint8_t id_buff[6];
uint8_t id_buff[6] = { 0 }; /* zero buff to silence false warning
* from clang static analyzer */
int retval;
int i;
@@ -392,19 +394,34 @@ int nand_probe(struct nand_device *nand)
if (nand->device->page_size == 0 ||
nand->device->erase_size == 0) {
if (nand->bus_width == 8) {
nand->controller->read_data(nand, id_buff + 3);
nand->controller->read_data(nand, id_buff + 4);
nand->controller->read_data(nand, id_buff + 5);
retval = nand->controller->read_data(nand, id_buff + 3);
if (retval != ERROR_OK)
return retval;
retval = nand->controller->read_data(nand, id_buff + 4);
if (retval != ERROR_OK)
return retval;
retval = nand->controller->read_data(nand, id_buff + 5);
if (retval != ERROR_OK)
return retval;
} else {
uint16_t data_buf;
nand->controller->read_data(nand, &data_buf);
retval = nand->controller->read_data(nand, &data_buf);
if (retval != ERROR_OK)
return retval;
id_buff[3] = data_buf;
nand->controller->read_data(nand, &data_buf);
retval = nand->controller->read_data(nand, &data_buf);
if (retval != ERROR_OK)
return retval;
id_buff[4] = data_buf;
nand->controller->read_data(nand, &data_buf);
retval = nand->controller->read_data(nand, &data_buf);
if (retval != ERROR_OK)
return retval;
id_buff[5] = data_buf >> 8;
}
}
+1 -1
View File
@@ -730,7 +730,7 @@ NAND_DEVICE_COMMAND_HANDLER(davinci_nand_device_command)
goto fail;
}
info = calloc(1, sizeof *info);
info = calloc(1, sizeof(*info));
if (info == NULL)
goto fail;
-2
View File
@@ -685,7 +685,6 @@ static int do_data_output(struct nand_device *nand)
case 2 << 2:
LOG_DEBUG("main area readed with more than 1 (incorrectable) error");
return ERROR_NAND_OPERATION_FAILED;
break;
}
switch (ecc_status & 0x0003) {
case 1:
@@ -694,7 +693,6 @@ static int do_data_output(struct nand_device *nand)
case 2:
LOG_DEBUG("main area readed with more than 1 (incorrectable) error");
return ERROR_NAND_OPERATION_FAILED;
break;
}
}
break;
-2
View File
@@ -874,7 +874,6 @@ int ecc_status_v1(struct nand_device *nand)
case 2 << 2:
LOG_INFO("main area read with more than 1 (incorrectable) error");
return ERROR_NAND_OPERATION_FAILED;
break;
}
switch (ecc_status & 0x0003) {
case 1:
@@ -883,7 +882,6 @@ int ecc_status_v1(struct nand_device *nand)
case 2:
LOG_INFO("main area read with more than 1 (incorrectable) error");
return ERROR_NAND_OPERATION_FAILED;
break;
}
return ERROR_OK;
}
+4
View File
@@ -51,6 +51,8 @@ NOR_DRIVERS = \
%D%/psoc4.c \
%D%/psoc5lp.c \
%D%/psoc6.c \
%D%/renesas_rpchf.c \
%D%/sh_qspi.c \
%D%/sim3x.c \
%D%/spi.c \
%D%/stmsmi.c \
@@ -74,6 +76,7 @@ NOR_DRIVERS = \
NORHEADERS = \
%D%/core.h \
%D%/cc3220sf.h \
%D%/bluenrg-x.h \
%D%/cc26xx.h \
%D%/cfi.h \
%D%/driver.h \
@@ -81,4 +84,5 @@ NORHEADERS = \
%D%/non_cfi.h \
%D%/ocl.h \
%D%/spi.h \
%D%/stm32l4x.h \
%D%/msp432.h
-2
View File
@@ -434,10 +434,8 @@ static int aducm360_write_block(struct flash_bank *bank,
switch (choice) {
case 0:
return aducm360_write_block_sync(bank, buffer, offset, count);
break;
case 1:
return aducm360_write_block_async(bank, buffer, offset, count);
break;
default:
LOG_ERROR("aducm360_write_block was cancelled (no writing method was chosen)!");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+1 -2
View File
@@ -253,8 +253,7 @@ static int ambiqmicro_read_part_info(struct flash_bank *bank)
}
if (ambiqmicro_info->target_class <
(sizeof(ambiqmicroParts)/sizeof(ambiqmicroParts[0])))
if (ambiqmicro_info->target_class < ARRAY_SIZE(ambiqmicroParts))
ambiqmicro_info->target_name =
ambiqmicroParts[ambiqmicro_info->target_class].partname;
else
+3 -6
View File
@@ -3068,7 +3068,6 @@ FLASH_BANK_COMMAND_HANDLER(sam3_flash_bank_command)
((unsigned int)(FLASH_BANK1_BASE_256K_AX)),
((unsigned int)(FLASH_BANK1_BASE_512K_AX)));
return ERROR_FAIL;
break;
/* at91sam3s and at91sam3n series only has bank 0*/
/* at91sam3u and at91sam3ax series has the same address for bank 0*/
@@ -3621,10 +3620,8 @@ COMMAND_HANDLER(sam3_handle_gpnvm_command)
switch (CMD_ARGC) {
default:
return ERROR_COMMAND_SYNTAX_ERROR;
break;
case 0:
goto showall;
break;
case 1:
who = -1;
break;
@@ -3653,7 +3650,8 @@ showall:
}
if ((who >= 0) && (((unsigned)(who)) < pChip->details.n_gpnvms)) {
r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), who, &v);
command_print(CMD, "sam3-gpnvm%u: %u", who, v);
if (r == ERROR_OK)
command_print(CMD, "sam3-gpnvm%u: %u", who, v);
return r;
} else {
command_print(CMD, "sam3-gpnvm invalid GPNVM: %u", who);
@@ -3707,7 +3705,6 @@ COMMAND_HANDLER(sam3_handle_slowclk_command)
/* error */
command_print(CMD, "Too many parameters");
return ERROR_COMMAND_SYNTAX_ERROR;
break;
}
command_print(CMD, "Slowclk freq: %d.%03dkhz",
(int)(pChip->cfg.slow_freq / 1000),
@@ -3729,7 +3726,7 @@ static const struct command_registration at91sam3_exec_command_handlers[] = {
.name = "info",
.handler = sam3_handle_info_command,
.mode = COMMAND_EXEC,
.help = "Print information about the current at91sam3 chip"
.help = "Print information about the current at91sam3 chip "
"and its flash configuration.",
.usage = "",
},
+1 -5
View File
@@ -2482,7 +2482,6 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command)
((unsigned int)(bank->base)),
((unsigned int)(FLASH_BANK_BASE_S)));
return ERROR_FAIL;
break;
/* at91sam4s series only has bank 0*/
/* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/
@@ -3101,10 +3100,8 @@ COMMAND_HANDLER(sam4_handle_gpnvm_command)
switch (CMD_ARGC) {
default:
return ERROR_COMMAND_SYNTAX_ERROR;
break;
case 0:
goto showall;
break;
case 1:
who = -1;
break;
@@ -3188,7 +3185,6 @@ COMMAND_HANDLER(sam4_handle_slowclk_command)
/* error */
command_print(CMD, "Too many parameters");
return ERROR_COMMAND_SYNTAX_ERROR;
break;
}
command_print(CMD, "Slowclk freq: %d.%03dkhz",
(int)(pChip->cfg.slow_freq / 1000),
@@ -3210,7 +3206,7 @@ static const struct command_registration at91sam4_exec_command_handlers[] = {
.name = "info",
.handler = sam4_handle_info_command,
.mode = COMMAND_EXEC,
.help = "Print information about the current at91sam4 chip"
.help = "Print information about the current at91sam4 chip "
"and its flash configuration.",
.usage = "",
},
+1
View File
@@ -601,6 +601,7 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer,
/* There's at least one aligned page to write out. */
if (count >= chip->page_size) {
assert(chip->page_size > 0);
int np = count / chip->page_size + ((count % chip->page_size) ? 1 : 0);
for (int i = 0; i < np; i++) {
+1 -6
View File
@@ -711,8 +711,6 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
uint16_t page_size;
uint16_t num_nvmbits;
char *target_name_t;
int bnk, sec;
at91sam7_info = malloc(sizeof(struct at91sam7_flash_bank));
@@ -753,9 +751,6 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
return ERROR_OK;
}
target_name_t = calloc(strlen(CMD_ARGV[7]) + 1, sizeof(char));
strcpy(target_name_t, CMD_ARGV[7]);
/* calculate bank size */
bank_size = num_sectors * pages_per_sector * page_size;
@@ -794,7 +789,7 @@ FLASH_BANK_COMMAND_HANDLER(at91sam7_flash_bank_command)
at91sam7_info = t_bank->driver_priv;
at91sam7_info->target_name = target_name_t;
at91sam7_info->target_name = strdup(CMD_ARGV[7]);
at91sam7_info->flashmode = 0;
at91sam7_info->ext_freq = ext_freq;
at91sam7_info->num_nvmbits = num_nvmbits;
+17
View File
@@ -181,6 +181,23 @@ static const struct samd_part samd21_parts[] = {
{ 0x26, "SAMD21E16B", 64, 8 },
{ 0x27, "SAMD21E15B", 32, 4 },
/* SAMD21 D and L Variants (from Errata)
http://ww1.microchip.com/downloads/en/DeviceDoc/
SAM-D21-Family-Silicon-Errata-and-DataSheet-Clarification-DS80000760D.pdf */
{ 0x55, "SAMD21E16BU", 64, 8 },
{ 0x56, "SAMD21E15BU", 32, 4 },
{ 0x57, "SAMD21G16L", 64, 8 },
{ 0x3E, "SAMD21E16L", 64, 8 },
{ 0x3F, "SAMD21E15L", 32, 4 },
{ 0x62, "SAMD21E16CU", 64, 8 },
{ 0x63, "SAMD21E15CU", 32, 4 },
{ 0x92, "SAMD21J17D", 128, 16 },
{ 0x93, "SAMD21G17D", 128, 16 },
{ 0x94, "SAMD21E17D", 128, 16 },
{ 0x95, "SAMD21E17DU", 128, 16 },
{ 0x96, "SAMD21G17L", 128, 16 },
{ 0x97, "SAMD21E17L", 128, 16 },
/* Known SAMDA1 parts.
SAMD-A1 series uses the same series identifier like the SAMD21
taken from http://ww1.microchip.com/downloads/en/DeviceDoc/40001895A.pdf (pages 14-17) */
-3
View File
@@ -375,7 +375,6 @@ static int samv_probe(struct flash_bank *bank)
default:
LOG_ERROR("unrecognized flash size code: %d", nvm_size_code);
return ERROR_FAIL;
break;
}
struct samv_flash_bank *samv_info = bank->driver_priv;
@@ -645,7 +644,6 @@ COMMAND_HANDLER(samv_handle_gpnvm_command)
switch (CMD_ARGC) {
case 0:
goto showall;
break;
case 1:
who = -1;
break;
@@ -660,7 +658,6 @@ COMMAND_HANDLER(samv_handle_gpnvm_command)
break;
default:
return ERROR_COMMAND_SYNTAX_ERROR;
break;
}
uint32_t v;
+27 -15
View File
@@ -58,7 +58,7 @@ struct avrf_type {
struct avrf_flash_bank {
int ppage_size;
int probed;
bool probed;
};
static const struct avrf_type avft_chips_info[] = {
@@ -67,6 +67,7 @@ static const struct avrf_type avft_chips_info[] = {
*/
{"atmega128", 0x9702, 256, 512, 8, 512},
{"atmega128rfa1", 0xa701, 128, 512, 8, 512},
{"atmega256rfr2", 0xa802, 256, 1024, 8, 1024},
{"at90can128", 0x9781, 256, 512, 8, 512},
{"at90usb128", 0x9782, 256, 512, 8, 512},
{"atmega164p", 0x940a, 128, 128, 4, 128},
@@ -142,16 +143,24 @@ static int avr_jtagprg_chiperase(struct avr_common *avr)
}
static int avr_jtagprg_writeflashpage(struct avr_common *avr,
const bool ext_addressing,
const uint8_t *page_buf,
uint32_t buf_size,
uint32_t addr,
uint32_t page_size)
{
uint32_t i, poll_value;
uint32_t poll_value;
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_COMMANDS);
avr_jtag_senddat(avr->jtag_info.tap, NULL, 0x2310, AVR_JTAG_REG_ProgrammingCommand_Len);
/* load extended high byte */
if (ext_addressing)
avr_jtag_senddat(avr->jtag_info.tap,
NULL,
0x0b00 | ((addr >> 17) & 0xFF),
AVR_JTAG_REG_ProgrammingCommand_Len);
/* load addr high byte */
avr_jtag_senddat(avr->jtag_info.tap,
NULL,
@@ -166,7 +175,7 @@ static int avr_jtagprg_writeflashpage(struct avr_common *avr,
avr_jtag_sendinstr(avr->jtag_info.tap, NULL, AVR_JTAG_INS_PROG_PAGELOAD);
for (i = 0; i < page_size; i++) {
for (uint32_t i = 0; i < page_size; i++) {
if (i < buf_size)
avr_jtag_senddat(avr->jtag_info.tap, NULL, page_buf[i], 8);
else
@@ -204,7 +213,7 @@ FLASH_BANK_COMMAND_HANDLER(avrf_flash_bank_command)
avrf_info = malloc(sizeof(struct avrf_flash_bank));
bank->driver_priv = avrf_info;
avrf_info->probed = 0;
avrf_info->probed = false;
return ERROR_OK;
}
@@ -238,6 +247,7 @@ static int avrf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t o
struct target *target = bank->target;
struct avr_common *avr = target->arch_info;
uint32_t cur_size, cur_buffer_size, page_size;
bool ext_addressing;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
@@ -258,6 +268,11 @@ static int avrf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t o
if (ERROR_OK != avr_jtagprg_enterprogmode(avr))
return ERROR_FAIL;
if (bank->size > 0x20000)
ext_addressing = true;
else
ext_addressing = false;
cur_size = 0;
while (count > 0) {
if (count > page_size)
@@ -265,6 +280,7 @@ static int avrf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t o
else
cur_buffer_size = count;
avr_jtagprg_writeflashpage(avr,
ext_addressing,
buffer + cur_size,
cur_buffer_size,
offset + cur_size,
@@ -288,7 +304,6 @@ static int avrf_probe(struct flash_bank *bank)
struct avrf_flash_bank *avrf_info = bank->driver_priv;
struct avr_common *avr = target->arch_info;
const struct avrf_type *avr_info = NULL;
int i;
uint32_t device_id;
if (bank->target->state != TARGET_HALTED) {
@@ -296,7 +311,7 @@ static int avrf_probe(struct flash_bank *bank)
return ERROR_TARGET_NOT_HALTED;
}
avrf_info->probed = 0;
avrf_info->probed = false;
avr_jtag_read_jtagid(avr, &device_id);
if (ERROR_OK != mcu_execute_queue())
@@ -308,7 +323,7 @@ static int avrf_probe(struct flash_bank *bank)
EXTRACT_MFG(device_id),
0x1F);
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
for (size_t i = 0; i < ARRAY_SIZE(avft_chips_info); i++) {
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
avr_info = &avft_chips_info[i];
LOG_INFO("target device is %s", avr_info->name);
@@ -328,20 +343,20 @@ static int avrf_probe(struct flash_bank *bank)
bank->num_sectors = avr_info->flash_page_num;
bank->sectors = malloc(sizeof(struct flash_sector) * avr_info->flash_page_num);
for (i = 0; i < avr_info->flash_page_num; i++) {
for (int i = 0; i < avr_info->flash_page_num; i++) {
bank->sectors[i].offset = i * avr_info->flash_page_size;
bank->sectors[i].size = avr_info->flash_page_size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = -1;
}
avrf_info->probed = 1;
avrf_info->probed = true;
return ERROR_OK;
} else {
/* chip not supported */
LOG_ERROR("0x%" PRIx32 " is not support for avr", EXTRACT_PART(device_id));
avrf_info->probed = 1;
avrf_info->probed = true;
return ERROR_FAIL;
}
}
@@ -359,7 +374,6 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
struct target *target = bank->target;
struct avr_common *avr = target->arch_info;
const struct avrf_type *avr_info = NULL;
int i;
uint32_t device_id;
if (bank->target->state != TARGET_HALTED) {
@@ -377,7 +391,7 @@ static int avrf_info(struct flash_bank *bank, char *buf, int buf_size)
EXTRACT_MFG(device_id),
0x1F);
for (i = 0; i < (int)ARRAY_SIZE(avft_chips_info); i++) {
for (size_t i = 0; i < ARRAY_SIZE(avft_chips_info); i++) {
if (avft_chips_info[i].chip_id == EXTRACT_PART(device_id)) {
avr_info = &avft_chips_info[i];
LOG_INFO("target device is %s", avr_info->name);
@@ -418,8 +432,6 @@ static int avrf_mass_erase(struct flash_bank *bank)
COMMAND_HANDLER(avrf_handle_mass_erase_command)
{
int i;
if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -430,7 +442,7 @@ COMMAND_HANDLER(avrf_handle_mass_erase_command)
if (avrf_mass_erase(bank) == ERROR_OK) {
/* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++)
for (int i = 0; i < bank->num_sectors; i++)
bank->sectors[i].is_erased = 1;
command_print(CMD, "avr mass erase complete");
+209 -303
View File
@@ -24,35 +24,62 @@
#include <target/armv7m.h>
#include <target/cortex_m.h>
#include "imp.h"
#include "bluenrg-x.h"
#define FLASH_SIZE_REG (0x40100014)
#define DIE_ID_REG (0x4090001C)
#define JTAG_IDCODE_REG (0x40900028)
#define BLUENRG2_IDCODE (0x0200A041)
#define FLASH_BASE (0x10040000)
#define FLASH_PAGE_SIZE (2048)
#define FLASH_REG_COMMAND (0x40100000)
#define FLASH_REG_IRQRAW (0x40100010)
#define FLASH_REG_ADDRESS (0x40100018)
#define FLASH_REG_DATA (0x40100040)
#define FLASH_CMD_ERASE_PAGE 0x11
#define FLASH_CMD_MASSERASE 0x22
#define FLASH_CMD_WRITE 0x33
#define FLASH_CMD_BURSTWRITE 0xCC
#define FLASH_INT_CMDDONE 0x01
#define FLASH_WORD_LEN 4
#define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
#define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
struct bluenrgx_flash_bank {
int probed;
uint32_t idcode;
uint32_t die_id;
#define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
#define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
#define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
struct flash_ctrl_priv_data {
uint32_t die_id_reg;
uint32_t jtag_idcode_reg;
uint32_t flash_base;
uint32_t flash_regs_base;
uint32_t flash_page_size;
uint32_t jtag_idcode;
char *part_name;
};
static int bluenrgx_protect_check(struct flash_bank *bank)
{
/* Nothing to do. Protection is only handled in SW. */
return ERROR_OK;
}
const struct flash_ctrl_priv_data flash_priv_data_1 = {
.die_id_reg = 0x4090001C,
.jtag_idcode_reg = 0x40900028,
.flash_base = 0x10040000,
.flash_regs_base = 0x40100000,
.flash_page_size = 2048,
.jtag_idcode = 0x00000000,
.part_name = "BLUENRG-1",
};
const struct flash_ctrl_priv_data flash_priv_data_2 = {
.die_id_reg = 0x4090001C,
.jtag_idcode_reg = 0x40900028,
.flash_base = 0x10040000,
.flash_regs_base = 0x40100000,
.flash_page_size = 2048,
.jtag_idcode = 0x0200A041,
.part_name = "BLUENRG-2",
};
const struct flash_ctrl_priv_data flash_priv_data_lp = {
.die_id_reg = 0x40000000,
.jtag_idcode_reg = 0x40000004,
.flash_base = 0x10040000,
.flash_regs_base = 0x40001000,
.flash_page_size = 2048,
.jtag_idcode = 0x0201E041,
.part_name = "BLUENRG-LP",
};
struct bluenrgx_flash_bank {
bool probed;
uint32_t die_id;
const struct flash_ctrl_priv_data *flash_ptr;
};
const struct flash_ctrl_priv_data *flash_ctrl[] = {&flash_priv_data_1, &flash_priv_data_2, &flash_priv_data_lp};
/* flash_bank bluenrg-x 0 0 0 0 <target#> */
FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
@@ -67,9 +94,12 @@ FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
return ERROR_FAIL;
}
bank->write_start_alignment = 16;
bank->write_end_alignment = 16;
bank->driver_priv = bluenrgx_info;
bluenrgx_info->probed = 0;
bluenrgx_info->probed = false;
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -77,6 +107,22 @@ FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
return ERROR_OK;
}
static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset)
{
struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
return bluenrgx_info->flash_ptr->flash_regs_base + reg_offset;
}
static inline int bluenrgx_read_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t *value)
{
return target_read_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
}
static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t value)
{
return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
}
static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
{
int retval = ERROR_OK;
@@ -87,7 +133,7 @@ static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
uint32_t address, command;
/* check preconditions */
if (bluenrgx_info->probed == 0)
if (!bluenrgx_info->probed)
return ERROR_FLASH_BANK_NOT_PROBED;
if (bank->target->state != TARGET_HALTED) {
@@ -103,24 +149,25 @@ static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
if (mass_erase) {
command = FLASH_CMD_MASSERASE;
address = bank->base;
if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
LOG_ERROR("Register write failed");
return ERROR_FAIL;
}
if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) != ERROR_OK) {
if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
(address - bank->base) >> 2) != ERROR_OK) {
LOG_ERROR("Register write failed");
return ERROR_FAIL;
}
if (target_write_u32(target, FLASH_REG_COMMAND, command) != ERROR_OK) {
if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
LOG_ERROR("Register write failed");
return ERROR_FAIL;
}
for (int i = 0; i < 100; i++) {
for (unsigned int i = 0; i < 100; i++) {
uint32_t value;
if (target_read_u32(target, FLASH_REG_IRQRAW, &value)) {
if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
LOG_ERROR("Register write failed");
return ERROR_FAIL;
}
@@ -135,26 +182,28 @@ static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
} else {
command = FLASH_CMD_ERASE_PAGE;
for (int i = first; i <= last; i++) {
address = bank->base+i*FLASH_PAGE_SIZE;
address = bank->base+i*FLASH_PAGE_SIZE(bluenrgx_info);
LOG_DEBUG("address = %08x, index = %d", address, i);
if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
LOG_ERROR("Register write failed");
return ERROR_FAIL;
}
if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) != ERROR_OK) {
if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
(address - bank->base) >> 2) != ERROR_OK) {
LOG_ERROR("Register write failed");
return ERROR_FAIL;
}
if (target_write_u32(target, FLASH_REG_COMMAND, command) != ERROR_OK) {
if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
LOG_ERROR("Failed");
return ERROR_FAIL;
}
for (int j = 0; j < 100; j++) {
for (unsigned int j = 0; j < 100; j++) {
uint32_t value;
if (target_read_u32(target, FLASH_REG_IRQRAW, &value)) {
if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
LOG_ERROR("Register write failed");
return ERROR_FAIL;
}
@@ -172,140 +221,10 @@ static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
}
static int bluenrgx_protect(struct flash_bank *bank, int set, int first, int last)
{
/* Protection is only handled in software: no hardware write protection
available in BlueNRG-x devices */
int sector;
for (sector = first; sector <= last; sector++)
bank->sectors[sector].is_protected = set;
return ERROR_OK;
}
static int bluenrgx_write_word(struct target *target, uint32_t address_base, uint8_t *values, uint32_t count)
{
int retval = ERROR_OK;
retval = target_write_u32(target, FLASH_REG_IRQRAW, 0x3f);
if (retval != ERROR_OK) {
LOG_ERROR("Register write failed, error code: %d", retval);
return retval;
}
for (uint32_t i = 0; i < count; i++) {
uint32_t address = address_base + i * FLASH_WORD_LEN;
retval = target_write_u32(target, FLASH_REG_ADDRESS, address >> 2);
if (retval != ERROR_OK) {
LOG_ERROR("Register write failed, error code: %d", retval);
return retval;
}
retval = target_write_buffer(target, FLASH_REG_DATA, FLASH_WORD_LEN, values + i * FLASH_WORD_LEN);
if (retval != ERROR_OK) {
LOG_ERROR("Register write failed, error code: %d", retval);
return retval;
}
retval = target_write_u32(target, FLASH_REG_COMMAND, FLASH_CMD_WRITE);
if (retval != ERROR_OK) {
LOG_ERROR("Register write failed, error code: %d", retval);
return retval;
}
for (int j = 0; j < 100; j++) {
uint32_t reg_value;
retval = target_read_u32(target, FLASH_REG_IRQRAW, &reg_value);
if (retval != ERROR_OK) {
LOG_ERROR("Register read failed, error code: %d", retval);
return retval;
}
if (reg_value & FLASH_INT_CMDDONE)
break;
if (j == 99) {
LOG_ERROR("Write command failed (timeout)");
return ERROR_FAIL;
}
}
}
return retval;
}
static int bluenrgx_write_bytes(struct target *target, uint32_t address_base, uint8_t *buffer, uint32_t count)
{
int retval = ERROR_OK;
uint8_t *new_buffer = NULL;
uint32_t pre_bytes = 0, post_bytes = 0, pre_word, post_word, pre_address, post_address;
if (count == 0) {
/* Just return if there are no bytes to write */
return retval;
}
if (address_base & 3) {
pre_bytes = address_base & 3;
pre_address = address_base - pre_bytes;
}
if ((count + pre_bytes) & 3) {
post_bytes = ((count + pre_bytes + 3) & ~3) - (count + pre_bytes);
post_address = (address_base + count) & ~3;
}
if (pre_bytes || post_bytes) {
uint32_t old_count = count;
count = old_count + pre_bytes + post_bytes;
new_buffer = malloc(count);
if (new_buffer == NULL) {
LOG_ERROR("odd number of bytes to write and no memory "
"for padding buffer");
return ERROR_FAIL;
}
LOG_INFO("Requested number of bytes to write and/or address not word aligned (%" PRIu32 "), extending to %"
PRIu32 " ", old_count, count);
if (pre_bytes) {
if (target_read_u32(target, pre_address, &pre_word)) {
LOG_ERROR("Memory read failed");
free(new_buffer);
return ERROR_FAIL;
}
}
if (post_bytes) {
if (target_read_u32(target, post_address, &post_word)) {
LOG_ERROR("Memory read failed");
free(new_buffer);
return ERROR_FAIL;
}
}
memcpy(new_buffer, &pre_word, pre_bytes);
memcpy((new_buffer+((pre_bytes+old_count) & ~3)), &post_word, 4);
memcpy(new_buffer+pre_bytes, buffer, old_count);
buffer = new_buffer;
}
retval = bluenrgx_write_word(target, address_base - pre_bytes, buffer, count/4);
if (new_buffer)
free(new_buffer);
return retval;
}
static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
struct target *target = bank->target;
uint32_t buffer_size = 16384 + 8;
struct working_area *write_algorithm;
@@ -313,10 +232,9 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
struct working_area *source;
uint32_t address = bank->base + offset;
struct reg_param reg_params[5];
struct mem_param mem_params[1];
struct armv7m_algorithm armv7m_info;
int retval = ERROR_OK;
uint32_t pre_size = 0, fast_size = 0, post_size = 0;
uint32_t pre_offset = 0, fast_offset = 0, post_offset = 0;
/* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
* hints how to generate the data!
@@ -325,6 +243,10 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
#include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
};
/* check preconditions */
if (!bluenrgx_info->probed)
return ERROR_FLASH_BANK_NOT_PROBED;
if ((offset + count) > bank->size) {
LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
(offset + count),
@@ -337,132 +259,105 @@ static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
return ERROR_TARGET_NOT_HALTED;
}
/* We are good here and we need to compute pre_size, fast_size, post_size */
pre_size = MIN(count, ((offset+0xF) & ~0xF) - offset);
pre_offset = offset;
fast_size = 16*((count - pre_size) / 16);
fast_offset = offset + pre_size;
post_size = (count-pre_size-fast_size) % 16;
post_offset = fast_offset + fast_size;
LOG_DEBUG("pre_size = %08x, pre_offset=%08x", pre_size, pre_offset);
LOG_DEBUG("fast_size = %08x, fast_offset=%08x", fast_size, fast_offset);
LOG_DEBUG("post_size = %08x, post_offset=%08x", post_size, post_offset);
/* Program initial chunk not 16 bytes aligned */
retval = bluenrgx_write_bytes(target, bank->base+pre_offset, (uint8_t *) buffer, pre_size);
if (retval) {
LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
return ERROR_FAIL;
if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
&write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* Program chunk 16 bytes aligned in fast mode */
if (fast_size) {
retval = target_write_buffer(target, write_algorithm->address,
sizeof(bluenrgx_flash_write_code),
bluenrgx_flash_write_code);
if (retval != ERROR_OK)
return retval;
if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
&write_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* memory buffer */
if (target_alloc_working_area(target, buffer_size, &source)) {
LOG_WARNING("no large enough working area available");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
retval = target_write_buffer(target, write_algorithm->address,
sizeof(bluenrgx_flash_write_code),
bluenrgx_flash_write_code);
if (retval != ERROR_OK)
return retval;
/* Stack pointer area */
if (target_alloc_working_area(target, 128,
&write_algorithm_sp) != ERROR_OK) {
LOG_DEBUG("no working area for write code stack pointer");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
/* memory buffer */
if (target_alloc_working_area(target, buffer_size, &source)) {
LOG_WARNING("no large enough working area available");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
/* Stack pointer area */
if (target_alloc_working_area(target, 64,
&write_algorithm_sp) != ERROR_OK) {
LOG_DEBUG("no working area for write code stack pointer");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
/* Put the parameter at the first available stack location */
init_mem_param(&mem_params[0], write_algorithm_sp->address + 80, 32, PARAM_OUT);
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
/* FIFO start address (first two words used for write and read pointers) */
buf_set_u32(reg_params[0].value, 0, 32, source->address);
/* FIFO end address (first two words used for write and read pointers) */
buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
/* Flash memory address */
buf_set_u32(reg_params[2].value, 0, 32, address);
/* Number of bytes */
buf_set_u32(reg_params[3].value, 0, 32, count);
/* Stack pointer for program working area */
buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
/* Flash register base address */
buf_set_u32(mem_params[0].value, 0, 32, bluenrgx_info->flash_ptr->flash_regs_base);
init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address);
LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size);
LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT, write_algorithm_sp->address);
LOG_DEBUG("address = %08x", address);
LOG_DEBUG("count = %08x", count);
/* FIFO start address (first two words used for write and read pointers) */
buf_set_u32(reg_params[0].value, 0, 32, source->address);
/* FIFO end address (first two words used for write and read pointers) */
buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
/* Flash memory address */
buf_set_u32(reg_params[2].value, 0, 32, address+pre_size);
/* Number of bytes */
buf_set_u32(reg_params[3].value, 0, 32, fast_size);
/* Stack pointer for program working area */
buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
retval = target_run_flash_async_algorithm(target,
buffer,
count/16,
16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
1,
mem_params,
5,
reg_params,
source->address,
source->size,
write_algorithm->address,
0,
&armv7m_info);
LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address);
LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size);
LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT, write_algorithm_sp->address);
LOG_DEBUG("address = %08x", address+pre_size);
LOG_DEBUG("count = %08x", count);
if (retval == ERROR_FLASH_OPERATION_FAILED) {
LOG_ERROR("error executing bluenrg-x flash write algorithm");
retval = target_run_flash_async_algorithm(target,
buffer+pre_size,
fast_size/16,
16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
0,
NULL,
5,
reg_params,
source->address,
source->size,
write_algorithm->address,
0,
&armv7m_info);
uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
if (retval == ERROR_FLASH_OPERATION_FAILED) {
LOG_ERROR("error executing bluenrg-x flash write algorithm");
uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
if (error != 0)
LOG_ERROR("flash write failed = %08" PRIx32, error);
}
if (error != 0)
LOG_ERROR("flash write failed = %08" PRIx32, error);
}
if (retval == ERROR_OK) {
uint32_t rp;
/* Read back rp and check that is valid */
retval = target_read_u32(target, source->address+4, &rp);
if (retval == ERROR_OK) {
uint32_t rp;
/* Read back rp and check that is valid */
retval = target_read_u32(target, source->address+4, &rp);
if (retval == ERROR_OK) {
if ((rp < source->address+8) || (rp > (source->address + source->size))) {
LOG_ERROR("flash write failed = %08" PRIx32, rp);
retval = ERROR_FLASH_OPERATION_FAILED;
}
if ((rp < source->address+8) || (rp > (source->address + source->size))) {
LOG_ERROR("flash write failed = %08" PRIx32, rp);
retval = ERROR_FLASH_OPERATION_FAILED;
}
}
target_free_working_area(target, source);
target_free_working_area(target, write_algorithm);
target_free_working_area(target, write_algorithm_sp);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);
destroy_reg_param(&reg_params[4]);
if (retval != ERROR_OK)
return retval;
}
target_free_working_area(target, source);
target_free_working_area(target, write_algorithm);
target_free_working_area(target, write_algorithm_sp);
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);
destroy_reg_param(&reg_params[4]);
destroy_mem_param(&mem_params[0]);
/* Program chunk at end, not addressable by fast burst write algorithm */
retval = bluenrgx_write_bytes(target, bank->base+post_offset, (uint8_t *) (buffer+pre_size+fast_size), post_size);
if (retval) {
LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
return ERROR_FAIL;
}
return retval;
}
@@ -470,33 +365,50 @@ static int bluenrgx_probe(struct flash_bank *bank)
{
struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
uint32_t idcode, size_info, die_id;
int i;
int retval = target_read_u32(bank->target, JTAG_IDCODE_REG, &idcode);
if (retval != ERROR_OK)
return retval;
retval = target_read_u32(bank->target, FLASH_SIZE_REG, &size_info);
int retval = target_read_u32(bank->target, BLUENRGLP_JTAG_REG, &idcode);
if (retval != ERROR_OK)
return retval;
retval = target_read_u32(bank->target, DIE_ID_REG, &die_id);
if (idcode != flash_priv_data_lp.jtag_idcode) {
retval = target_read_u32(bank->target, BLUENRG2_JTAG_REG, &idcode);
if (retval != ERROR_OK)
return retval;
}
/* Default device is BlueNRG-1 */
bluenrgx_info->flash_ptr = &flash_priv_data_1;
bank->base = flash_priv_data_1.flash_base;
for (size_t i = 0; i < ARRAY_SIZE(flash_ctrl); i++) {
if (idcode == (*flash_ctrl[i]).jtag_idcode) {
bluenrgx_info->flash_ptr = flash_ctrl[i];
bank->base = (*flash_ctrl[i]).flash_base;
break;
}
}
retval = bluenrgx_read_flash_reg(bank, FLASH_SIZE_REG, &size_info);
if (retval != ERROR_OK)
return retval;
bank->size = (size_info + 1) * 4;
bank->base = FLASH_BASE;
bank->num_sectors = bank->size/FLASH_PAGE_SIZE;
retval = target_read_u32(bank->target, DIE_ID_REG(bluenrgx_info), &die_id);
if (retval != ERROR_OK)
return retval;
bank->size = (size_info + 1) * FLASH_WORD_LEN;
bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info);
bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
for (i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = i * FLASH_PAGE_SIZE;
bank->sectors[i].size = FLASH_PAGE_SIZE;
for (int i = 0; i < bank->num_sectors; i++) {
bank->sectors[i].offset = i * FLASH_PAGE_SIZE(bluenrgx_info);
bank->sectors[i].size = FLASH_PAGE_SIZE(bluenrgx_info);
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 0;
}
bluenrgx_info->probed = 1;
bluenrgx_info->probed = true;
bluenrgx_info->die_id = die_id;
bluenrgx_info->idcode = idcode;
return ERROR_OK;
}
@@ -515,7 +427,6 @@ static int bluenrgx_get_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
int mask_number, cut_number;
char *part_name;
if (!bluenrgx_info->probed) {
int retval = bluenrgx_probe(bank);
@@ -526,16 +437,11 @@ static int bluenrgx_get_info(struct flash_bank *bank, char *buf, int buf_size)
}
}
if (bluenrgx_info->idcode == BLUENRG2_IDCODE)
part_name = "BLUENRG-2";
else
part_name = "BLUENRG-1";
mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
cut_number = bluenrgx_info->die_id & 0xF;
snprintf(buf, buf_size,
"%s - Rev: %d.%d", part_name, mask_number, cut_number);
"%s - Rev: %d.%d", bluenrgx_info->flash_ptr->part_name, mask_number, cut_number);
return ERROR_OK;
}
@@ -543,12 +449,12 @@ const struct flash_driver bluenrgx_flash = {
.name = "bluenrg-x",
.flash_bank_command = bluenrgx_flash_bank_command,
.erase = bluenrgx_erase,
.protect = bluenrgx_protect,
.protect = NULL,
.write = bluenrgx_write,
.read = default_flash_read,
.probe = bluenrgx_probe,
.erase_check = default_flash_blank_check,
.protect_check = bluenrgx_protect_check,
.protect_check = NULL,
.auto_probe = bluenrgx_auto_probe,
.info = bluenrgx_get_info,
};
@@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
* Copyright (C) 2019 by STMicroelectronics. *
* *
* 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 *
@@ -15,13 +15,31 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H
#define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H
#ifndef OPENOCD_FLASH_NOR_BLUENRGX_H
#define OPENOCD_FLASH_NOR_BLUENRGX_H
#ifdef HAVE_LIBUSB1
#include "libusb1_common.h"
#else
#include "libusb0_common.h"
#endif
/* Flash Controller registers offsets */
#define FLASH_REG_COMMAND 0x00
#define FLASH_REG_CONFIG 0x04
#define FLASH_REG_IRQSTAT 0x08
#define FLASH_REG_IRQMASK 0x0C
#define FLASH_REG_IRQRAW 0x10
#define FLASH_REG_ADDRESS 0x18
#define FLASH_REG_UNLOCKM 0x1C
#define FLASH_REG_UNLOCKL 0x20
#define FLASH_REG_DATA0 0x40
#define FLASH_REG_DATA1 0x44
#define FLASH_REG_DATA2 0x48
#define FLASH_REG_DATA3 0x4C
#define FLASH_SIZE_REG 0x14
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */
/* Flash Controller commands */
#define FLASH_CMD_ERASE_PAGE 0x11
#define FLASH_CMD_MASSERASE 0x22
#define FLASH_CMD_WRITE 0x33
#define FLASH_CMD_BURSTWRITE 0xCC
#define FLASH_INT_CMDDONE 0x01
#define FLASH_WORD_LEN 4
#endif /* OPENOCD_FLASH_NOR_BLUENRGX_H */
+2
View File
@@ -363,6 +363,8 @@ static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer,
LOG_ERROR("cc3220sf: Flash operation failed");
break;
}
keep_alive();
}
/* Do one word write for any final bytes less than a full word */
+169 -184
View File
File diff suppressed because it is too large Load Diff
+27
View File
@@ -73,6 +73,12 @@ struct cfi_flash_bank {
unsigned buf_write_timeout;
unsigned block_erase_timeout;
unsigned chip_erase_timeout;
/* memory accessors */
int (*write_mem)(struct flash_bank *bank, target_addr_t addr,
uint32_t count, const uint8_t *buffer);
int (*read_mem)(struct flash_bank *bank, target_addr_t addr,
uint32_t count, uint8_t *buffer);
};
/* Intel primary extended query table
@@ -148,6 +154,24 @@ struct cfi_fixup {
const void *param;
};
int cfi_erase(struct flash_bank *bank, int first, int last);
int cfi_protect(struct flash_bank *bank, int set, int first, int last);
int cfi_probe(struct flash_bank *bank);
int cfi_auto_probe(struct flash_bank *bank);
int cfi_protect_check(struct flash_bank *bank);
int cfi_get_info(struct flash_bank *bank, char *buf, int buf_size);
int cfi_flash_bank_cmd(struct flash_bank *bank, unsigned int argc, const char **argv);
uint32_t cfi_flash_address(struct flash_bank *bank, int sector, uint32_t offset);
int cfi_spansion_unlock_seq(struct flash_bank *bank);
int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t address);
int cfi_write_word(struct flash_bank *bank, uint8_t *word, uint32_t address);
int cfi_spansion_wait_status_busy(struct flash_bank *bank, int timeout);
int cfi_reset(struct flash_bank *bank);
int cfi_target_read_memory(struct flash_bank *bank, target_addr_t addr,
uint32_t count, uint8_t *buffer);
#define CFI_MFR_AMD 0x0001
#define CFI_MFR_FUJITSU 0x0004
#define CFI_MFR_ATMEL 0x001F
@@ -160,4 +184,7 @@ struct cfi_fixup {
#define CFI_MFR_ANY 0xffff
#define CFI_ID_ANY 0xffff
#define CFI_MAX_BUS_WIDTH 4
#define CFI_MAX_CHIP_WIDTH 4
#endif /* OPENOCD_FLASH_NOR_CFI_H */
+4
View File
@@ -66,6 +66,8 @@ extern const struct flash_driver psoc5lp_flash;
extern const struct flash_driver psoc5lp_eeprom_flash;
extern const struct flash_driver psoc5lp_nvl_flash;
extern const struct flash_driver psoc6_flash;
extern const struct flash_driver renesas_rpchf_flash;
extern const struct flash_driver sh_qspi_flash;
extern const struct flash_driver sim3x_flash;
extern const struct flash_driver stellaris_flash;
extern const struct flash_driver stm32f1x_flash;
@@ -136,6 +138,8 @@ static const struct flash_driver * const flash_drivers[] = {
&psoc5lp_eeprom_flash,
&psoc5lp_nvl_flash,
&psoc6_flash,
&renesas_rpchf_flash,
&sh_qspi_flash,
&sim3x_flash,
&stellaris_flash,
&stm32f1x_flash,
+1 -1
View File
@@ -154,7 +154,7 @@ static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first,
*
* @return
*/
static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t* buffer,
static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
int retval;
+13 -15
View File
@@ -99,7 +99,7 @@ struct efm32_family_data {
};
struct efm32x_flash_bank {
int probed;
bool probed;
uint32_t lb_page[LOCKBITS_PAGE_SZ/4];
uint32_t reg_base;
uint32_t reg_lock;
@@ -140,6 +140,7 @@ static const struct efm32_family_data efm32_families[] = {
{ 43, "EFR32BG13P Blue", .series = 1 },
{ 44, "EFR32BG13B Blue", .series = 1 },
{ 45, "EFR32BG13V Blue", .series = 1 },
{ 46, "EFR32ZG13P Zen", .series = 1 },
{ 49, "EFR32FG13P Flex", .series = 1 },
{ 50, "EFR32FG13B Flex", .series = 1 },
{ 51, "EFR32FG13V Flex", .series = 1 },
@@ -149,6 +150,7 @@ static const struct efm32_family_data efm32_families[] = {
{ 55, "EFR32BG14P Blue", .series = 1 },
{ 56, "EFR32BG14B Blue", .series = 1 },
{ 57, "EFR32BG14V Blue", .series = 1 },
{ 58, "EFR32ZG14P Zen", .series = 1 },
{ 61, "EFR32FG14P Flex", .series = 1 },
{ 62, "EFR32FG14B Flex", .series = 1 },
{ 63, "EFR32FG14V Flex", .series = 1 },
@@ -166,7 +168,8 @@ static const struct efm32_family_data efm32_families[] = {
{ 89, "EFM32PG13B Pearl", .series = 1 },
{ 91, "EFM32JG13B Jade", .series = 1 },
{ 100, "EFM32GG11B Giant", .series = 1, .msc_regbase = 0x40000000 },
{ 103, "EFM32TG11B Tiny", .series = 1 },
{ 103, "EFM32TG11B Tiny", .series = 1, .msc_regbase = 0x40000000 },
{ 106, "EFM32GG12B Giant", .series = 1, .msc_regbase = 0x40000000 },
{ 120, "EZR32WG Wonder", .series = 0 },
{ 121, "EZR32LG Leopard", .series = 0 },
{ 122, "EZR32HG Happy", .series = 0, .page_size = 1024 },
@@ -348,7 +351,7 @@ FLASH_BANK_COMMAND_HANDLER(efm32x_flash_bank_command)
efm32x_info = malloc(sizeof(struct efm32x_flash_bank));
bank->driver_priv = efm32x_info;
efm32x_info->probed = 0;
efm32x_info->probed = false;
memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
return ERROR_OK;
@@ -467,7 +470,6 @@ static int efm32x_erase_page(struct flash_bank *bank, uint32_t addr)
static int efm32x_erase(struct flash_bank *bank, int first, int last)
{
struct target *target = bank->target;
int i = 0;
int ret = 0;
if (TARGET_HALTED != target->state) {
@@ -482,7 +484,7 @@ static int efm32x_erase(struct flash_bank *bank, int first, int last)
return ret;
}
for (i = first; i <= last; i++) {
for (int i = first; i <= last; i++) {
ret = efm32x_erase_page(bank, bank->sectors[i].offset);
if (ERROR_OK != ret)
LOG_ERROR("Failed to erase page %d", i);
@@ -498,7 +500,6 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
{
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
struct target *target = bank->target;
int i = 0;
int data_size = 0;
uint32_t *ptr = NULL;
int ret = 0;
@@ -510,7 +511,7 @@ static int efm32x_read_lock_data(struct flash_bank *bank)
ptr = efm32x_info->lb_page;
for (i = 0; i < data_size; i++, ptr++) {
for (int i = 0; i < data_size; i++, ptr++) {
ret = target_read_u32(target, EFM32_MSC_LOCK_BITS+i*4, ptr);
if (ERROR_OK != ret) {
LOG_ERROR("Failed to read PLW %d", i);
@@ -616,7 +617,6 @@ static int efm32x_set_page_lock(struct flash_bank *bank, size_t page, int set)
static int efm32x_protect(struct flash_bank *bank, int set, int first, int last)
{
struct target *target = bank->target;
int i = 0;
int ret = 0;
if (!set) {
@@ -629,7 +629,7 @@ static int efm32x_protect(struct flash_bank *bank, int set, int first, int last)
return ERROR_TARGET_NOT_HALTED;
}
for (i = first; i <= last; i++) {
for (int i = first; i <= last; i++) {
ret = efm32x_set_page_lock(bank, i, set);
if (ERROR_OK != ret) {
LOG_ERROR("Failed to set lock on page %d", i);
@@ -960,11 +960,10 @@ static int efm32x_probe(struct flash_bank *bank)
struct efm32x_flash_bank *efm32x_info = bank->driver_priv;
struct efm32_info efm32_mcu_info;
int ret;
int i;
uint32_t base_address = 0x00000000;
char buf[256];
efm32x_info->probed = 0;
efm32x_info->probed = false;
memset(efm32x_info->lb_page, 0xff, LOCKBITS_PAGE_SZ);
ret = efm32x_read_info(bank, &efm32_mcu_info);
@@ -1003,14 +1002,14 @@ static int efm32x_probe(struct flash_bank *bank)
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
for (i = 0; i < num_pages; i++) {
for (int i = 0; i < num_pages; i++) {
bank->sectors[i].offset = i * efm32_mcu_info.page_size;
bank->sectors[i].size = efm32_mcu_info.page_size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
efm32x_info->probed = 1;
efm32x_info->probed = true;
return ERROR_OK;
}
@@ -1027,7 +1026,6 @@ static int efm32x_protect_check(struct flash_bank *bank)
{
struct target *target = bank->target;
int ret = 0;
int i = 0;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
@@ -1042,7 +1040,7 @@ static int efm32x_protect_check(struct flash_bank *bank)
assert(NULL != bank->sectors);
for (i = 0; i < bank->num_sectors; i++)
for (int i = 0; i < bank->num_sectors; i++)
bank->sectors[i].is_protected = efm32x_get_page_lock(bank, i);
return ERROR_OK;
+1 -1
View File
@@ -183,7 +183,7 @@ static int fespi_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_
}
static int fespi_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value)
{ \
{
struct target *target = bank->target;
struct fespi_flash_bank *fespi_info = bank->driver_priv;
+5 -3
View File
@@ -207,7 +207,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t halfword_count = DIV_ROUND_UP(byte_count, 2);
uint32_t result;
unsigned i;
int retval;
int retval, retval2 = ERROR_OK;
const uint8_t write_block_code[] = {
#include "../../../contrib/loaders/flash/fm4/write.inc"
};
@@ -327,7 +327,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer,
err_run_ret:
err_run:
err_write_data:
retval = fm4_enter_flash_cpu_rom_mode(target);
retval2 = fm4_enter_flash_cpu_rom_mode(target);
err_flash_mode:
for (i = 0; i < ARRAY_SIZE(reg_params); i++)
@@ -338,7 +338,9 @@ err_alloc_data:
err_write_code:
target_free_working_area(target, code_workarea);
return retval;
if (retval != ERROR_OK)
return retval;
return retval2;
}
static int mb9bf_probe(struct flash_bank *bank)
+18 -7
View File
@@ -59,7 +59,7 @@ static void jtagspi_set_ir(struct flash_bank *bank)
{
struct jtagspi_flash_bank *info = bank->driver_priv;
struct scan_field field;
uint8_t buf[4];
uint8_t buf[4] = { 0 };
LOG_DEBUG("loading jtagspi ir");
buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
@@ -153,12 +153,12 @@ static int jtagspi_cmd(struct flash_bank *bank, uint8_t cmd,
jtagspi_set_ir(bank);
/* passing from an IR scan to SHIFT-DR clears BYPASS registers */
jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
jtag_execute_queue();
int retval = jtag_execute_queue();
if (is_read)
flip_u8(data_buf, data, lenb);
free(data_buf);
return ERROR_OK;
return retval;
}
static int jtagspi_probe(struct flash_bank *bank)
@@ -228,13 +228,16 @@ static int jtagspi_probe(struct flash_bank *bank)
return ERROR_OK;
}
static void jtagspi_read_status(struct flash_bank *bank, uint32_t *status)
static int jtagspi_read_status(struct flash_bank *bank, uint32_t *status)
{
uint8_t buf;
if (jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8) == ERROR_OK) {
int err = jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8);
if (err == ERROR_OK) {
*status = buf;
/* LOG_DEBUG("status=0x%08" PRIx32, *status); */
}
return err;
}
static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
@@ -245,7 +248,11 @@ static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
do {
dt = timeval_ms() - t0;
jtagspi_read_status(bank, &status);
int retval = jtagspi_read_status(bank, &status);
if (retval != ERROR_OK)
return retval;
if ((status & SPIFLASH_BSY_BIT) == 0) {
LOG_DEBUG("waited %" PRId64 " ms", dt);
return ERROR_OK;
@@ -262,7 +269,11 @@ static int jtagspi_write_enable(struct flash_bank *bank)
uint32_t status;
jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0);
jtagspi_read_status(bank, &status);
int retval = jtagspi_read_status(bank, &status);
if (retval != ERROR_OK)
return retval;
if ((status & SPIFLASH_WE_BIT) == 0) {
LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
return ERROR_FAIL;
+36 -35
View File
@@ -787,9 +787,8 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
if ((val & (MDM_STAT_SYSSEC | MDM_STAT_FREADY)) != MDM_STAT_FREADY) {
uint32_t stats[32];
int i;
for (i = 0; i < 32; i++) {
for (unsigned int i = 0; i < 32; i++) {
stats[i] = MDM_STAT_FREADY;
dap_queue_ap_read(dap_ap(dap, MDM_AP), MDM_REG_STAT, &stats[i]);
}
@@ -798,7 +797,7 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
LOG_DEBUG("MDM: dap_run failed when validating secured state");
return ERROR_OK;
}
for (i = 0; i < 32; i++) {
for (unsigned int i = 0; i < 32; i++) {
if (stats[i] & MDM_STAT_SYSSEC)
secured_score++;
if (!(stats[i] & MDM_STAT_FREADY))
@@ -860,8 +859,7 @@ static struct kinetis_chip *kinetis_get_chip(struct target *target)
static int kinetis_chip_options(struct kinetis_chip *k_chip, int argc, const char *argv[])
{
int i;
for (i = 0; i < argc; i++) {
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "-sim-base") == 0) {
if (i + 1 < argc)
k_chip->sim_base = strtoul(argv[++i], NULL, 0);
@@ -933,7 +931,6 @@ static void kinetis_free_driver_priv(struct flash_bank *bank)
static int kinetis_create_missing_banks(struct kinetis_chip *k_chip)
{
unsigned bank_idx;
unsigned num_blocks;
struct kinetis_flash_bank *k_bank;
struct flash_bank *bank;
@@ -968,7 +965,7 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip)
*p = '\0';
}
for (bank_idx = 1; bank_idx < num_blocks; bank_idx++) {
for (unsigned int bank_idx = 1; bank_idx < num_blocks; bank_idx++) {
k_bank = &(k_chip->banks[bank_idx]);
bank = k_bank->bank;
@@ -1219,11 +1216,11 @@ static int kinetis_ftfx_clear_error(struct target *target)
static int kinetis_ftfx_prepare(struct target *target)
{
int result, i;
int result;
uint8_t fstat;
/* wait until busy */
for (i = 0; i < 50; i++) {
for (unsigned int i = 0; i < 50; i++) {
result = target_read_u8(target, FTFx_FSTAT, &fstat);
if (result != ERROR_OK)
return result;
@@ -1343,8 +1340,6 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer,
static int kinetis_protect(struct flash_bank *bank, int set, int first, int last)
{
int i;
if (allow_fcf_writes) {
LOG_ERROR("Protection setting is possible with 'kinetis fcf_source protection' only!");
return ERROR_FAIL;
@@ -1355,7 +1350,7 @@ static int kinetis_protect(struct flash_bank *bank, int set, int first, int last
return ERROR_FLASH_BANK_INVALID;
}
for (i = first; i < bank->num_prot_blocks && i <= last; i++)
for (int i = first; i < bank->num_prot_blocks && i <= last; i++)
bank->prot_blocks[i].is_protected = set;
LOG_INFO("Protection bits will be written at the next FCF sector erase or write.");
@@ -1369,7 +1364,7 @@ static int kinetis_protect_check(struct flash_bank *bank)
{
struct kinetis_flash_bank *k_bank = bank->driver_priv;
int result;
int i, b;
int b;
uint32_t fprot;
if (k_bank->flash_class == FC_PFLASH) {
@@ -1397,7 +1392,7 @@ static int kinetis_protect_check(struct flash_bank *bank)
}
b = k_bank->protection_block;
for (i = 0; i < bank->num_prot_blocks; i++) {
for (int i = 0; i < bank->num_prot_blocks; i++) {
if ((fprot >> b) & 1)
bank->prot_blocks[i].is_protected = 0;
else
@@ -1415,8 +1410,6 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf)
uint32_t fprot = 0xffffffff;
uint8_t fsec = 0xfe; /* set MCU unsecure */
uint8_t fdprot = 0xff;
int i;
unsigned bank_idx;
unsigned num_blocks;
uint32_t pflash_bit;
uint8_t dflash_bit;
@@ -1432,7 +1425,7 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf)
/* iterate over all kinetis banks */
/* current bank is bank 0, it contains FCF */
num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks;
for (bank_idx = 0; bank_idx < num_blocks; bank_idx++) {
for (unsigned int bank_idx = 0; bank_idx < num_blocks; bank_idx++) {
k_bank = &(k_chip->banks[bank_idx]);
bank_iter = k_bank->bank;
@@ -1443,8 +1436,10 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf)
kinetis_auto_probe(bank_iter);
assert(bank_iter->prot_blocks);
if (k_bank->flash_class == FC_PFLASH) {
for (i = 0; i < bank_iter->num_prot_blocks; i++) {
for (int i = 0; i < bank_iter->num_prot_blocks; i++) {
if (bank_iter->prot_blocks[i].is_protected == 1)
fprot &= ~pflash_bit;
@@ -1452,7 +1447,7 @@ static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf)
}
} else if (k_bank->flash_class == FC_FLEX_NVM) {
for (i = 0; i < bank_iter->num_prot_blocks; i++) {
for (int i = 0; i < bank_iter->num_prot_blocks; i++) {
if (bank_iter->prot_blocks[i].is_protected == 1)
fdprot &= ~dflash_bit;
@@ -1540,7 +1535,7 @@ static int kinetis_read_pmstat(struct kinetis_chip *k_chip, uint8_t *pmstat)
static int kinetis_check_run_mode(struct kinetis_chip *k_chip)
{
int result, i;
int result;
uint8_t pmstat;
struct target *target;
@@ -1578,7 +1573,7 @@ static int kinetis_check_run_mode(struct kinetis_chip *k_chip)
if (result != ERROR_OK)
return result;
for (i = 100; i; i--) {
for (unsigned int i = 100; i > 0; i--) {
result = kinetis_read_pmstat(k_chip, &pmstat);
if (result != ERROR_OK)
return result;
@@ -1623,7 +1618,7 @@ static void kinetis_invalidate_flash_cache(struct kinetis_chip *k_chip)
static int kinetis_erase(struct flash_bank *bank, int first, int last)
{
int result, i;
int result;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
struct kinetis_chip *k_chip = k_bank->k_chip;
@@ -1644,7 +1639,7 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last)
* requested erase is PFlash or NVM and encompasses the entire
* block. Should be quicker.
*/
for (i = first; i <= last; i++) {
for (int i = first; i <= last; i++) {
/* set command and sector address */
result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTERASE, k_bank->prog_base + bank->sectors[i].offset,
0, 0, 0, 0, 0, 0, 0, 0, NULL);
@@ -1798,6 +1793,8 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer
buffer += size;
offset += size;
count -= size;
keep_alive();
}
free(buffer_aligned);
@@ -1808,25 +1805,26 @@ static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer
static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
int result, fallback = 0;
int result;
bool fallback = false;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
struct kinetis_chip *k_chip = k_bank->k_chip;
if (!(k_chip->flash_support & FS_PROGRAM_SECTOR)) {
/* fallback to longword write */
fallback = 1;
fallback = true;
LOG_INFO("This device supports Program Longword execution only.");
} else {
result = kinetis_make_ram_ready(bank->target);
if (result != ERROR_OK) {
fallback = 1;
fallback = true;
LOG_WARNING("FlexRAM not ready, fallback to slow longword write.");
}
}
LOG_DEBUG("flash write @ " TARGET_ADDR_FMT, bank->base + offset);
if (fallback == 0) {
if (!fallback) {
/* program section command */
kinetis_write_sections(bank, buffer, offset, count);
} else if (k_chip->flash_support & FS_PROGRAM_LONGWORD) {
@@ -1889,6 +1887,8 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer,
buffer += 4;
offset += 4;
words_remaining--;
keep_alive();
}
}
free(new_buffer);
@@ -2018,7 +2018,6 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
unsigned familyid = 0, subfamid = 0;
unsigned cpu_mhz = 120;
unsigned idx;
bool use_nvm_marking = false;
char flash_marking[12], nvm_marking[2];
char name[40];
@@ -2113,7 +2112,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
LOG_ERROR("Unsupported K-family FAMID");
}
for (idx = 0; idx < ARRAY_SIZE(kinetis_types_old); idx++) {
for (size_t idx = 0; idx < ARRAY_SIZE(kinetis_types_old); idx++) {
if (kinetis_types_old[idx].sdid == mcu_type) {
strcpy(name, kinetis_types_old[idx].name);
use_nvm_marking = true;
@@ -2619,12 +2618,15 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip)
static int kinetis_probe(struct flash_bank *bank)
{
int result, i;
int result;
uint8_t fcfg2_maxaddr0, fcfg2_pflsh, fcfg2_maxaddr1;
unsigned num_blocks, first_nvm_bank;
uint32_t size_k;
struct kinetis_flash_bank *k_bank = bank->driver_priv;
struct kinetis_chip *k_chip = k_bank->k_chip;
struct kinetis_chip *k_chip;
assert(k_bank);
k_chip = k_bank->k_chip;
k_bank->probed = false;
@@ -2668,6 +2670,7 @@ static int kinetis_probe(struct flash_bank *bank)
if (k_chip->dflash_size == 0) {
k_bank->protection_size = 0;
} else {
int i;
for (i = k_chip->dflash_size; ~i & 1; i >>= 1)
;
if (i == 1)
@@ -2824,8 +2827,7 @@ static int kinetis_blank_check(struct flash_bank *bank)
if (block_dirty) {
/* the whole bank is not erased, check sector-by-sector */
int i;
for (i = 0; i < bank->num_sectors; i++) {
for (int i = 0; i < bank->num_sectors; i++) {
/* normal margin */
result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTSTAT,
k_bank->prog_base + bank->sectors[i].offset,
@@ -2841,8 +2843,7 @@ static int kinetis_blank_check(struct flash_bank *bank)
}
} else {
/* the whole bank is erased, update all sectors */
int i;
for (i = 0; i < bank->num_sectors; i++)
for (int i = 0; i < bank->num_sectors; i++)
bank->sectors[i].is_erased = 1;
}
} else {
+1 -1
View File
@@ -814,7 +814,7 @@ static int kinetis_ke_protect_check(struct flash_bank *bank)
kinfo->protection_size = 0;
} else {
LOG_WARNING("Flash protected. FPOPEN=%i FPLDIS=%i FPHDIS=%i FPLS=%i FPHS=%i", \
LOG_WARNING("Flash protected. FPOPEN=%i FPLDIS=%i FPHDIS=%i FPLS=%i FPHS=%i",
fpopen ? 1 : 0, fpldis ? 1 : 0, fphdis ? 1 : 0, fpls, fphs);
/* Retrieve which region is protected and how much */
+8 -8
View File
@@ -177,8 +177,8 @@ static int lpcspifi_set_hw_mode(struct flash_bank *bank)
retval = target_alloc_working_area(target, sizeof(spifi_init_code)
+ SPIFI_INIT_STACK_SIZE, &spifi_init_algorithm);
if (retval != ERROR_OK) {
LOG_ERROR("Insufficient working area to initialize SPIFI "\
"module. You must allocate at least %zdB of working "\
LOG_ERROR("Insufficient working area to initialize SPIFI "
"module. You must allocate at least %zdB of working "
"area in order to use this driver.",
sizeof(spifi_init_code) + SPIFI_INIT_STACK_SIZE
);
@@ -452,7 +452,7 @@ static int lpcspifi_erase(struct flash_bank *bank, int first, int last)
* it, use a bulk erase instead of going sector-by-sector. */
if (first == 0 && last == (bank->num_sectors - 1)
&& lpcspifi_info->dev->chip_erase_cmd != lpcspifi_info->dev->erase_cmd) {
LOG_DEBUG("Chip supports the bulk erase command."\
LOG_DEBUG("Chip supports the bulk erase command."
" Will use bulk erase instead of sector-by-sector erase.");
retval = lpcspifi_bulk_erase(bank);
@@ -525,7 +525,7 @@ static int lpcspifi_erase(struct flash_bank *bank, int first, int last)
retval = target_alloc_working_area(target, sizeof(lpcspifi_flash_erase_code),
&erase_algorithm);
if (retval != ERROR_OK) {
LOG_ERROR("Insufficient working area. You must configure a working"\
LOG_ERROR("Insufficient working area. You must configure a working"
" area of at least %zdB in order to erase SPIFI flash.",
sizeof(lpcspifi_flash_erase_code));
return retval;
@@ -685,7 +685,7 @@ static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer,
if (target_alloc_working_area(target, sizeof(lpcspifi_flash_write_code),
&write_algorithm) != ERROR_OK) {
LOG_ERROR("Insufficient working area. You must configure"\
LOG_ERROR("Insufficient working area. You must configure"
" a working area > %zdB in order to write to SPIFI flash.",
sizeof(lpcspifi_flash_write_code));
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@@ -707,15 +707,15 @@ static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer,
* space, free the algorithm */
target_free_working_area(target, write_algorithm);
LOG_ERROR("Insufficient working area. Please allocate at least"\
LOG_ERROR("Insufficient working area. Please allocate at least"
" %zdB of working area to enable flash writes.",
sizeof(lpcspifi_flash_write_code) + 1
);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} else if (fifo_size < page_size)
LOG_WARNING("Working area size is limited; flash writes may be"\
" slow. Increase working area size to at least %zdB"\
LOG_WARNING("Working area size is limited; flash writes may be"
" slow. Increase working area size to at least %zdB"
" to reduce write times.",
(size_t)(sizeof(lpcspifi_flash_write_code) + page_size)
);
+5 -5
View File
@@ -563,7 +563,7 @@ static int mrvlqspi_flash_erase(struct flash_bank *bank, int first, int last)
if (first == 0 && last == (bank->num_sectors - 1)
&& mrvlqspi_info->dev->chip_erase_cmd !=
mrvlqspi_info->dev->erase_cmd) {
LOG_DEBUG("Chip supports the bulk erase command."\
LOG_DEBUG("Chip supports the bulk erase command."
" Will use bulk erase instead of sector-by-sector erase.");
retval = mrvlqspi_bulk_erase(bank);
if (retval == ERROR_OK) {
@@ -681,7 +681,7 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer,
if (target_alloc_working_area(target, sizeof(mrvlqspi_flash_write_code),
&write_algorithm) != ERROR_OK) {
LOG_ERROR("Insufficient working area. You must configure"\
LOG_ERROR("Insufficient working area. You must configure"
" a working area > %zdB in order to write to SPIFI flash.",
sizeof(mrvlqspi_flash_write_code));
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@@ -703,15 +703,15 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer,
* space, free the algorithm */
target_free_working_area(target, write_algorithm);
LOG_ERROR("Insufficient working area. Please allocate at least"\
LOG_ERROR("Insufficient working area. Please allocate at least"
" %zdB of working area to enable flash writes.",
sizeof(mrvlqspi_flash_write_code) + 1
);
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
} else if (fifo_size < page_size)
LOG_WARNING("Working area size is limited; flash writes may be"\
" slow. Increase working area size to at least %zdB"\
LOG_WARNING("Working area size is limited; flash writes may be"
" slow. Increase working area size to at least %zdB"
" to reduce write times.",
(size_t)(sizeof(mrvlqspi_flash_write_code) + page_size)
);
+118 -111
View File
@@ -49,7 +49,8 @@ struct msp432_bank {
int family_type;
int device_type;
uint32_t sector_length;
bool probed[2];
bool probed_main;
bool probed_info;
bool unlock_bsl;
struct working_area *working_area;
struct armv7m_algorithm armv7m_info;
@@ -194,8 +195,7 @@ static int msp432_exec_cmd(struct target *target, struct msp432_algo_params
return retval;
/* Write out command to target memory */
retval = target_write_buffer(target, ALGO_FLASH_COMMAND_ADDR,
sizeof(command), (uint8_t *)&command);
retval = target_write_u32(target, ALGO_FLASH_COMMAND_ADDR, command);
return retval;
}
@@ -210,8 +210,7 @@ static int msp432_wait_return_code(struct target *target)
start_ms = timeval_ms();
while ((0 == return_code) || (FLASH_BUSY == return_code)) {
retval = target_read_buffer(target, ALGO_RETURN_CODE_ADDR,
sizeof(return_code), (uint8_t *)&return_code);
retval = target_read_u32(target, ALGO_RETURN_CODE_ADDR, &return_code);
if (ERROR_OK != retval)
return retval;
@@ -253,8 +252,7 @@ static int msp432_wait_inactive(struct target *target, uint32_t buffer)
start_ms = timeval_ms();
while (BUFFER_INACTIVE != status_code) {
retval = target_read_buffer(target, status_addr, sizeof(status_code),
(uint8_t *)&status_code);
retval = target_read_u32(target, status_addr, &status_code);
if (ERROR_OK != retval)
return retval;
@@ -477,15 +475,23 @@ COMMAND_HANDLER(msp432_mass_erase_command)
struct flash_bank *bank;
struct msp432_bank *msp432_bank;
bool all;
int retval;
if (0 == CMD_ARGC) {
if (1 > CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (retval != ERROR_OK)
return retval;
if (1 == CMD_ARGC) {
all = false;
} else if (1 == CMD_ARGC) {
} else if (2 == CMD_ARGC) {
/* Check argument for how much to erase */
if (0 == strcmp(CMD_ARGV[0], "main"))
if (0 == strcmp(CMD_ARGV[1], "main"))
all = false;
else if (0 == strcmp(CMD_ARGV[0], "all"))
else if (0 == strcmp(CMD_ARGV[1], "all"))
all = true;
else
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -493,10 +499,6 @@ COMMAND_HANDLER(msp432_mass_erase_command)
return ERROR_COMMAND_SYNTAX_ERROR;
}
retval = get_flash_bank_by_num(0, &bank);
if (ERROR_OK != retval)
return retval;
msp432_bank = bank->driver_priv;
if (MSP432E4 == msp432_bank->family_type) {
@@ -513,7 +515,7 @@ COMMAND_HANDLER(msp432_mass_erase_command)
LOG_INFO("msp432: Mass erase of flash is complete");
} else {
LOG_INFO("msp432: Mass erase of %s is complete",
all ? "main + info flash" : "main flash");
all ? "main + information flash" : "main flash");
}
return ERROR_OK;
@@ -523,13 +525,14 @@ COMMAND_HANDLER(msp432_bsl_command)
{
struct flash_bank *bank;
struct msp432_bank *msp432_bank;
int retval;
if (1 < CMD_ARGC)
if (1 > CMD_ARGC)
return ERROR_COMMAND_SYNTAX_ERROR;
retval = get_flash_bank_by_num(0, &bank);
if (ERROR_OK != retval)
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
if (retval != ERROR_OK)
return retval;
msp432_bank = bank->driver_priv;
@@ -539,13 +542,16 @@ COMMAND_HANDLER(msp432_bsl_command)
return ERROR_OK;
}
if (1 == CMD_ARGC) {
if (0 == strcmp(CMD_ARGV[0], "lock"))
if (2 == CMD_ARGC) {
if (0 == strcmp(CMD_ARGV[1], "lock"))
msp432_bank->unlock_bsl = false;
else if (0 == strcmp(CMD_ARGV[0], "unlock"))
else if (0 == strcmp(CMD_ARGV[1], "unlock"))
msp432_bank->unlock_bsl = true;
else
return ERROR_COMMAND_SYNTAX_ERROR;
} else if (1 != CMD_ARGC) {
/* Extra, unknown argument passed in */
return ERROR_COMMAND_SYNTAX_ERROR;
}
LOG_INFO("msp432: BSL flash region is currently %slocked",
@@ -561,6 +567,7 @@ FLASH_BANK_COMMAND_HANDLER(msp432_flash_bank_command)
if (CMD_ARGC < 6)
return ERROR_COMMAND_SYNTAX_ERROR;
/* Create shared private struct for flash banks */
msp432_bank = malloc(sizeof(struct msp432_bank));
if (NULL == msp432_bank)
return ERROR_FAIL;
@@ -571,14 +578,14 @@ FLASH_BANK_COMMAND_HANDLER(msp432_flash_bank_command)
msp432_bank->family_type = MSP432_NO_FAMILY;
msp432_bank->device_type = MSP432_NO_TYPE;
msp432_bank->sector_length = 0x1000;
msp432_bank->probed[0] = false;
msp432_bank->probed[1] = false;
msp432_bank->probed_main = false;
msp432_bank->probed_info = false;
msp432_bank->unlock_bsl = false;
msp432_bank->working_area = NULL;
/* Finish initialization of bank 0 (main flash) */
/* Finish up initial settings here */
bank->driver_priv = msp432_bank;
bank->next = NULL;
bank->base = FLASH_BASE;
return ERROR_OK;
}
@@ -589,6 +596,9 @@ static int msp432_erase(struct flash_bank *bank, int first, int last)
struct msp432_bank *msp432_bank = bank->driver_priv;
struct msp432_algo_params algo_params;
bool is_main = FLASH_BASE == bank->base;
bool is_info = P4_FLASH_INFO_BASE == bank->base;
int retval;
if (TARGET_HALTED != target->state) {
@@ -597,8 +607,7 @@ static int msp432_erase(struct flash_bank *bank, int first, int last)
}
/* Do a mass erase if user requested all sectors of main flash */
if ((0 == bank->bank_number) && (first == 0) &&
(last == (bank->num_sectors - 1))) {
if (is_main && (first == 0) && (last == (bank->num_sectors - 1))) {
/* Request mass erase of main flash */
return msp432_mass_erase(bank, false);
}
@@ -611,7 +620,7 @@ static int msp432_erase(struct flash_bank *bank, int first, int last)
msp432_init_params(&algo_params);
/* Adjust params if this is the info bank */
if (1 == bank->bank_number) {
if (is_info) {
buf_set_u32(algo_params.erase_param, 0, 32, FLASH_ERASE_INFO);
/* And flag if BSL is unlocked */
if (msp432_bank->unlock_bsl)
@@ -622,11 +631,11 @@ static int msp432_erase(struct flash_bank *bank, int first, int last)
for (int i = first; i <= last; i++) {
/* Skip TVL (read-only) sector of the info bank */
if (1 == bank->bank_number && 1 == i)
if (is_info && 1 == i)
continue;
/* Skip BSL sectors of info bank if locked */
if (1 == bank->bank_number && (2 == i || 3 == i) &&
if (is_info && (2 == i || 3 == i) &&
!msp432_bank->unlock_bsl)
continue;
@@ -666,6 +675,8 @@ static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
long long start_ms;
long long elapsed_ms;
bool is_info = P4_FLASH_INFO_BASE == bank->base;
int retval;
if (TARGET_HALTED != target->state) {
@@ -679,7 +690,7 @@ static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
* The BSL region in sectors 2 and 3 of the info flash may be unlocked
* The helper algorithm will hang on attempts to write to TVL
*/
if (1 == bank->bank_number) {
if (is_info) {
/* Set read-only start to TVL sector */
uint32_t start = 0x1000;
/* Set read-only end after BSL region if locked */
@@ -722,7 +733,7 @@ static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
buf_set_u32(algo_params.length, 0, 32, count);
/* Check if this is the info bank */
if (1 == bank->bank_number) {
if (is_info) {
/* And flag if BSL is unlocked */
if (msp432_bank->unlock_bsl)
buf_set_u32(algo_params.unlock_bsl, 0, 32, FLASH_UNLOCK_BSL);
@@ -753,8 +764,8 @@ static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
}
/* Signal the flash helper algorithm that data is ready to flash */
retval = target_write_buffer(target, ALGO_BUFFER1_STATUS_ADDR,
sizeof(data_ready), (uint8_t *)&data_ready);
retval = target_write_u32(target, ALGO_BUFFER1_STATUS_ADDR,
data_ready);
if (ERROR_OK != retval) {
(void)msp432_quit(bank);
return ERROR_FLASH_OPERATION_FAILED;
@@ -793,20 +804,23 @@ static int msp432_probe(struct flash_bank *bank)
struct target *target = bank->target;
struct msp432_bank *msp432_bank = bank->driver_priv;
char *name;
uint32_t device_id;
uint32_t hardware_rev;
uint32_t base;
uint32_t sector_length;
uint32_t size;
int num_sectors;
int bank_id;
bool is_main = FLASH_BASE == bank->base;
bool is_info = P4_FLASH_INFO_BASE == bank->base;
int retval;
bank_id = bank->bank_number;
/* Check if this bank has already been successfully probed */
if (is_main && msp432_bank->probed_main)
return ERROR_OK;
if (is_info && msp432_bank->probed_info)
return ERROR_OK;
/* Read the flash size register to determine this is a P4 or not */
/* MSP432P4s will return the size of flash. MSP432E4s will return zero */
@@ -849,63 +863,16 @@ static int msp432_probe(struct flash_bank *bank)
msp432_bank->device_type = msp432_device_type(msp432_bank->family_type,
msp432_bank->device_id, msp432_bank->hardware_rev);
/* If not already allocated, create the info bank for MSP432P4 */
/* We could not determine it was needed until device was probed */
if (MSP432P4 == msp432_bank->family_type) {
/* If we've been given bank 1, then this was already done */
if (0 == bank_id) {
/* And only allocate it if it doesn't exist yet */
if (NULL == bank->next) {
struct flash_bank *info_bank;
info_bank = malloc(sizeof(struct flash_bank));
if (NULL == info_bank)
return ERROR_FAIL;
name = malloc(strlen(bank->name)+1);
if (NULL == name) {
free(info_bank);
return ERROR_FAIL;
}
strcpy(name, bank->name);
/* Initialize bank 1 (info region) */
info_bank->name = name;
info_bank->target = bank->target;
info_bank->driver = bank->driver;
info_bank->driver_priv = bank->driver_priv;
info_bank->bank_number = 1;
info_bank->base = 0x00200000;
info_bank->size = 0;
info_bank->chip_width = 0;
info_bank->bus_width = 0;
info_bank->erased_value = 0xff;
info_bank->default_padded_value = 0xff;
info_bank->write_start_alignment = 0;
info_bank->write_end_alignment = 0;
info_bank->minimal_write_gap = FLASH_WRITE_GAP_SECTOR;
info_bank->num_sectors = 0;
info_bank->sectors = NULL;
info_bank->num_prot_blocks = 0;
info_bank->prot_blocks = NULL;
info_bank->next = NULL;
/* Enable the new bank */
bank->next = info_bank;
}
}
}
if (MSP432P4 == msp432_bank->family_type) {
/* Set up MSP432P4 specific flash parameters */
if (0 == bank_id) {
if (is_main) {
retval = target_read_u32(target, P4_FLASH_MAIN_SIZE_REG, &size);
if (ERROR_OK != retval)
return retval;
base = P4_FLASH_MAIN_BASE;
sector_length = P4_SECTOR_LENGTH;
num_sectors = size / sector_length;
} else if (1 == bank_id) {
} else if (is_info) {
if (msp432_bank->device_type == MSP432P411X ||
msp432_bank->device_type == MSP432P411X_GUESS) {
/* MSP432P411x has an info size register, use that for size */
@@ -916,19 +883,22 @@ static int msp432_probe(struct flash_bank *bank)
/* All other MSP432P401x devices have fixed info region size */
size = 0x4000; /* 16 KB info region */
}
base = P4_FLASH_INFO_BASE;
sector_length = P4_SECTOR_LENGTH;
num_sectors = size / sector_length;
} else {
/* Invalid bank number somehow */
/* Invalid bank somehow */
return ERROR_FAIL;
}
} else {
/* Set up MSP432E4 specific flash parameters */
base = E4_FLASH_BASE;
size = E4_FLASH_SIZE;
sector_length = E4_SECTOR_LENGTH;
num_sectors = size / sector_length;
if (is_main) {
size = E4_FLASH_SIZE;
sector_length = E4_SECTOR_LENGTH;
num_sectors = size / sector_length;
} else {
/* Invalid bank somehow */
return ERROR_FAIL;
}
}
if (NULL != bank->sectors) {
@@ -936,11 +906,12 @@ static int msp432_probe(struct flash_bank *bank)
bank->sectors = NULL;
}
bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
if (NULL == bank->sectors)
return ERROR_FAIL;
if (num_sectors > 0) {
bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
if (NULL == bank->sectors)
return ERROR_FAIL;
}
bank->base = base;
bank->size = size;
bank->write_start_alignment = 0;
bank->write_end_alignment = 0;
@@ -955,7 +926,31 @@ static int msp432_probe(struct flash_bank *bank)
}
/* We've successfully determined the stats on this flash bank */
msp432_bank->probed[bank_id] = true;
if (is_main)
msp432_bank->probed_main = true;
if (is_info)
msp432_bank->probed_info = true;
if (is_main && MSP432P4 == msp432_bank->family_type) {
/* Create the info flash bank needed by MSP432P4 variants */
struct flash_bank *info = calloc(sizeof(struct flash_bank), 1);
if (NULL == info)
return ERROR_FAIL;
/* Create a name for the info bank, append "_1" to main name */
char *name = malloc(strlen(bank->name) + 3);
strcpy(name, bank->name);
strcat(name, "_1");
/* Initialize info bank */
info->name = name;
info->target = bank->target;
info->driver = bank->driver;
info->driver_priv = msp432_bank;
info->base = P4_FLASH_INFO_BASE;
flash_bank_add(info);
}
/* If we fall through to here, then all went well */
@@ -966,15 +961,17 @@ static int msp432_auto_probe(struct flash_bank *bank)
{
struct msp432_bank *msp432_bank = bank->driver_priv;
bool is_main = FLASH_BASE == bank->base;
bool is_info = P4_FLASH_INFO_BASE == bank->base;
int retval = ERROR_OK;
if (bank->bank_number < 0 || bank->bank_number > 1) {
/* Invalid bank number somehow */
return ERROR_FAIL;
}
if (!msp432_bank->probed[bank->bank_number])
retval = msp432_probe(bank);
if (is_main)
if (!msp432_bank->probed_main)
retval = msp432_probe(bank);
if (is_info)
if (!msp432_bank->probed_info)
retval = msp432_probe(bank);
return retval;
}
@@ -1036,12 +1033,21 @@ static int msp432_info(struct flash_bank *bank, char *buf, int buf_size)
return ERROR_OK;
}
static int msp432_protect_check(struct flash_bank *bank)
{
/* Added to suppress warning, not needed for MSP432 flash */
return ERROR_OK;
}
static void msp432_flash_free_driver_priv(struct flash_bank *bank)
{
bool is_main = FLASH_BASE == bank->base;
/* A single private struct is shared between main and info banks */
/* Only free it on the call for main bank (#0) */
if ((0 == bank->bank_number) && (NULL != bank->driver_priv))
/* Only free it on the call for main bank */
if (is_main && (NULL != bank->driver_priv))
free(bank->driver_priv);
/* Forget about the private struct on both main and info banks */
bank->driver_priv = NULL;
}
@@ -1052,14 +1058,14 @@ static const struct command_registration msp432_exec_command_handlers[] = {
.handler = msp432_mass_erase_command,
.mode = COMMAND_EXEC,
.help = "Erase entire flash memory on device.",
.usage = "['main' | 'all']",
.usage = "bank_id ['main' | 'all']",
},
{
.name = "bsl",
.handler = msp432_bsl_command,
.mode = COMMAND_EXEC,
.help = "Allow BSL to be erased or written by flash commands.",
.usage = "['unlock' | 'lock']",
.usage = "bank_id ['unlock' | 'lock']",
},
COMMAND_REGISTRATION_DONE
};
@@ -1085,6 +1091,7 @@ const struct flash_driver msp432_flash = {
.probe = msp432_probe,
.auto_probe = msp432_auto_probe,
.erase_check = default_flash_blank_check,
.protect_check = msp432_protect_check,
.info = msp432_info,
.free_driver_priv = msp432_flash_free_driver_priv,
};
+5 -2
View File
@@ -34,14 +34,17 @@
#define MSP432E411Y 7 /* MSP432E401Y device */
#define MSP432E4X_GUESS 8 /* Assuming it's an MSP432E4x device */
/* Common MSP432 flash parameters */
#define FLASH_BASE 0x00000000
/* MSP432P4 flash parameters */
#define P4_FLASH_MAIN_BASE 0x00000000
#define P4_FLASH_MAIN_BASE FLASH_BASE
#define P4_FLASH_INFO_BASE 0x00200000
#define P4_SECTOR_LENGTH 0x1000
#define P4_ALGO_ENTRY_ADDR 0x01000110
/* MSP432E4 flash paramters */
#define E4_FLASH_BASE 0x00000000
#define E4_FLASH_BASE FLASH_BASE
#define E4_FLASH_SIZE 0x100000
#define E4_SECTOR_LENGTH 0x4000
#define E4_ALGO_ENTRY_ADDR 0x20000110
+562 -359
View File
File diff suppressed because it is too large Load Diff
+7 -22
View File
@@ -1216,7 +1216,7 @@ static int numicro_init_isp(struct target *target)
return ERROR_OK;
}
static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_t* rdata)
static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_t *rdata)
{
uint32_t timeout, status;
int retval = ERROR_OK;
@@ -1548,7 +1548,6 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
{
struct target *target = bank->target;
uint32_t timeout, status;
uint8_t *new_buffer = NULL;
int retval = ERROR_OK;
if (target->state != TARGET_HALTED) {
@@ -1566,20 +1565,8 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
if (retval != ERROR_OK)
return retval;
if (count & 0x3) {
uint32_t old_count = count;
count = (old_count | 3) + 1;
new_buffer = malloc(count);
if (new_buffer == NULL) {
LOG_ERROR("odd number of bytes to write and no memory "
"for padding buffer");
return ERROR_FAIL;
}
LOG_INFO("odd number of bytes to write (%d), extending to %d "
"and padding with 0xff", old_count, count);
memset(new_buffer, 0xff, count);
buffer = memcpy(new_buffer, buffer, old_count);
}
assert(offset % 4 == 0);
assert(count % 4 == 0);
uint32_t words_remaining = count / 4;
@@ -1597,13 +1584,10 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
LOG_DEBUG("write longword @ %08X", offset + i);
uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
memcpy(padding, buffer + i, MIN(4, count-i));
retval = target_write_u32(target, NUMICRO_FLASH_ISPADR, bank->base + offset + i);
if (retval != ERROR_OK)
return retval;
retval = target_write_memory(target, NUMICRO_FLASH_ISPDAT, 4, 1, padding);
retval = target_write_memory(target, NUMICRO_FLASH_ISPDAT, 4, 1, buffer + i);
if (retval != ERROR_OK)
return retval;
retval = target_write_u32(target, NUMICRO_FLASH_ISPTRG, ISPTRG_ISPGO);
@@ -1649,7 +1633,7 @@ static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
return ERROR_OK;
}
static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type** cpu)
static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type **cpu)
{
uint32_t part_id;
int retval = ERROR_OK;
@@ -1663,7 +1647,7 @@ static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_
LOG_INFO("Device ID: 0x%08" PRIx32 "", part_id);
/* search part numbers */
for (size_t i = 0; i < sizeof(NuMicroParts)/sizeof(NuMicroParts[0]); i++) {
for (size_t i = 0; i < ARRAY_SIZE(NuMicroParts); i++) {
if (part_id == NuMicroParts[i].partid) {
*cpu = &NuMicroParts[i];
LOG_INFO("Device Name: %s", (*cpu)->partname);
@@ -1754,6 +1738,7 @@ FLASH_BANK_COMMAND_HANDLER(numicro_flash_bank_command)
memset(bank_info, 0, sizeof(struct numicro_flash_bank));
bank->driver_priv = bank_info;
bank->write_start_alignment = bank->write_end_alignment = 4;
return ERROR_OK;
+1 -6
View File
@@ -108,7 +108,7 @@ static const struct row_region safe_sflash_regions[] = {
{0x16007C00, 0x400}, /* SFLASH: TOC2 */
};
#define SFLASH_NUM_REGIONS (sizeof(safe_sflash_regions) / sizeof(safe_sflash_regions[0]))
#define SFLASH_NUM_REGIONS ARRAY_SIZE(safe_sflash_regions)
static struct working_area *g_stack_area;
static struct armv7m_algorithm g_armv7m_info;
@@ -481,20 +481,15 @@ static const char *protection_to_str(uint8_t protection)
switch (protection) {
case PROTECTION_VIRGIN:
return "VIRGIN";
break;
case PROTECTION_NORMAL:
return "NORMAL";
break;
case PROTECTION_SECURE:
return "SECURE";
break;
case PROTECTION_DEAD:
return "DEAD";
break;
case PROTECTION_UNKNOWN:
default:
return "UNKNOWN";
break;
}
}
+648
View File
@@ -0,0 +1,648 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Renesas RCar Gen3 RPC Hyperflash driver
* Based on U-Boot RPC Hyperflash driver
*
* Copyright (C) 2016 Renesas Electronics Corporation
* Copyright (C) 2016 Cogent Embedded, Inc.
* Copyright (C) 2017-2019 Marek Vasut <marek.vasut@gmail.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include "cfi.h"
#include "non_cfi.h"
#include <helper/binarybuffer.h>
#include <helper/bits.h>
#include <helper/time_support.h>
#define RPC_CMNCR 0x0000 /* R/W */
#define RPC_CMNCR_MD BIT(31)
#define RPC_CMNCR_MOIIO0(val) (((val) & 0x3) << 16)
#define RPC_CMNCR_MOIIO1(val) (((val) & 0x3) << 18)
#define RPC_CMNCR_MOIIO2(val) (((val) & 0x3) << 20)
#define RPC_CMNCR_MOIIO3(val) (((val) & 0x3) << 22)
#define RPC_CMNCR_MOIIO_HIZ (RPC_CMNCR_MOIIO0(3) | RPC_CMNCR_MOIIO1(3) | \
RPC_CMNCR_MOIIO2(3) | RPC_CMNCR_MOIIO3(3))
#define RPC_CMNCR_IO0FV(val) (((val) & 0x3) << 8)
#define RPC_CMNCR_IO2FV(val) (((val) & 0x3) << 12)
#define RPC_CMNCR_IO3FV(val) (((val) & 0x3) << 14)
#define RPC_CMNCR_IOFV_HIZ (RPC_CMNCR_IO0FV(3) | RPC_CMNCR_IO2FV(3) | \
RPC_CMNCR_IO3FV(3))
#define RPC_CMNCR_BSZ(val) (((val) & 0x3) << 0)
#define RPC_SSLDR 0x0004 /* R/W */
#define RPC_SSLDR_SPNDL(d) (((d) & 0x7) << 16)
#define RPC_SSLDR_SLNDL(d) (((d) & 0x7) << 8)
#define RPC_SSLDR_SCKDL(d) (((d) & 0x7) << 0)
#define RPC_DRCR 0x000C /* R/W */
#define RPC_DRCR_SSLN BIT(24)
#define RPC_DRCR_RBURST(v) (((v) & 0x1F) << 16)
#define RPC_DRCR_RCF BIT(9)
#define RPC_DRCR_RBE BIT(8)
#define RPC_DRCR_SSLE BIT(0)
#define RPC_DRCMR 0x0010 /* R/W */
#define RPC_DRCMR_CMD(c) (((c) & 0xFF) << 16)
#define RPC_DRCMR_OCMD(c) (((c) & 0xFF) << 0)
#define RPC_DREAR 0x0014 /* R/W */
#define RPC_DREAR_EAV(v) (((v) & 0xFF) << 16)
#define RPC_DREAR_EAC(v) (((v) & 0x7) << 0)
#define RPC_DROPR 0x0018 /* R/W */
#define RPC_DROPR_OPD3(o) (((o) & 0xFF) << 24)
#define RPC_DROPR_OPD2(o) (((o) & 0xFF) << 16)
#define RPC_DROPR_OPD1(o) (((o) & 0xFF) << 8)
#define RPC_DROPR_OPD0(o) (((o) & 0xFF) << 0)
#define RPC_DRENR 0x001C /* R/W */
#define RPC_DRENR_CDB(o) (uint32_t)((((o) & 0x3) << 30))
#define RPC_DRENR_OCDB(o) (((o) & 0x3) << 28)
#define RPC_DRENR_ADB(o) (((o) & 0x3) << 24)
#define RPC_DRENR_OPDB(o) (((o) & 0x3) << 20)
#define RPC_DRENR_SPIDB(o) (((o) & 0x3) << 16)
#define RPC_DRENR_DME BIT(15)
#define RPC_DRENR_CDE BIT(14)
#define RPC_DRENR_OCDE BIT(12)
#define RPC_DRENR_ADE(v) (((v) & 0xF) << 8)
#define RPC_DRENR_OPDE(v) (((v) & 0xF) << 4)
#define RPC_SMCR 0x0020 /* R/W */
#define RPC_SMCR_SSLKP BIT(8)
#define RPC_SMCR_SPIRE BIT(2)
#define RPC_SMCR_SPIWE BIT(1)
#define RPC_SMCR_SPIE BIT(0)
#define RPC_SMCMR 0x0024 /* R/W */
#define RPC_SMCMR_CMD(c) (((c) & 0xFF) << 16)
#define RPC_SMCMR_OCMD(c) (((c) & 0xFF) << 0)
#define RPC_SMADR 0x0028 /* R/W */
#define RPC_SMOPR 0x002C /* R/W */
#define RPC_SMOPR_OPD0(o) (((o) & 0xFF) << 0)
#define RPC_SMOPR_OPD1(o) (((o) & 0xFF) << 8)
#define RPC_SMOPR_OPD2(o) (((o) & 0xFF) << 16)
#define RPC_SMOPR_OPD3(o) (((o) & 0xFF) << 24)
#define RPC_SMENR 0x0030 /* R/W */
#define RPC_SMENR_CDB(o) (((o) & 0x3) << 30)
#define RPC_SMENR_OCDB(o) (((o) & 0x3) << 28)
#define RPC_SMENR_ADB(o) (((o) & 0x3) << 24)
#define RPC_SMENR_OPDB(o) (((o) & 0x3) << 20)
#define RPC_SMENR_SPIDB(o) (((o) & 0x3) << 16)
#define RPC_SMENR_DME BIT(15)
#define RPC_SMENR_CDE BIT(14)
#define RPC_SMENR_OCDE BIT(12)
#define RPC_SMENR_ADE(v) (((v) & 0xF) << 8)
#define RPC_SMENR_OPDE(v) (((v) & 0xF) << 4)
#define RPC_SMENR_SPIDE(v) (((v) & 0xF) << 0)
#define RPC_SMRDR0 0x0038 /* R */
#define RPC_SMRDR1 0x003C /* R */
#define RPC_SMWDR0 0x0040 /* R/W */
#define RPC_SMWDR1 0x0044 /* R/W */
#define RPC_CMNSR 0x0048 /* R */
#define RPC_CMNSR_SSLF BIT(1)
#define RPC_CMNSR_TEND BIT(0)
#define RPC_DRDMCR 0x0058 /* R/W */
#define RPC_DRDMCR_DMCYC(v) (((v) & 0xF) << 0)
#define RPC_DRDRENR 0x005C /* R/W */
#define RPC_DRDRENR_HYPE (0x5 << 12)
#define RPC_DRDRENR_ADDRE BIT(8)
#define RPC_DRDRENR_OPDRE BIT(4)
#define RPC_DRDRENR_DRDRE BIT(0)
#define RPC_SMDMCR 0x0060 /* R/W */
#define RPC_SMDMCR_DMCYC(v) (((v) & 0xF) << 0)
#define RPC_SMDRENR 0x0064 /* R/W */
#define RPC_SMDRENR_HYPE (0x5 << 12)
#define RPC_SMDRENR_ADDRE BIT(8)
#define RPC_SMDRENR_OPDRE BIT(4)
#define RPC_SMDRENR_SPIDRE BIT(0)
#define RPC_PHYCNT 0x007C /* R/W */
#define RPC_PHYCNT_CAL BIT(31)
#define PRC_PHYCNT_OCTA_AA BIT(22)
#define PRC_PHYCNT_OCTA_SA BIT(23)
#define PRC_PHYCNT_EXDS BIT(21)
#define RPC_PHYCNT_OCT BIT(20)
#define RPC_PHYCNT_WBUF2 BIT(4)
#define RPC_PHYCNT_WBUF BIT(2)
#define RPC_PHYCNT_MEM(v) (((v) & 0x3) << 0)
#define RPC_PHYINT 0x0088 /* R/W */
#define RPC_PHYINT_RSTEN BIT(18)
#define RPC_PHYINT_WPEN BIT(17)
#define RPC_PHYINT_INTEN BIT(16)
#define RPC_PHYINT_RST BIT(2)
#define RPC_PHYINT_WP BIT(1)
#define RPC_PHYINT_INT BIT(0)
#define RPC_WBUF 0x8000 /* R/W size=4/8/16/32/64Bytes */
#define RPC_WBUF_SIZE 0x100
static uint32_t rpc_base = 0xee200000;
static uint32_t mem_base = 0x08000000;
enum rpc_hf_size {
RPC_HF_SIZE_16BIT = RPC_SMENR_SPIDE(0x8),
RPC_HF_SIZE_32BIT = RPC_SMENR_SPIDE(0xC),
RPC_HF_SIZE_64BIT = RPC_SMENR_SPIDE(0xF),
};
static int rpc_hf_wait_tend(struct target *target)
{
uint32_t reg = rpc_base + RPC_CMNSR;
uint32_t val;
unsigned long timeout = 1000;
long long endtime;
int ret;
endtime = timeval_ms() + timeout;
do {
ret = target_read_u32(target, reg, &val);
if (ret != ERROR_OK)
return ERROR_FAIL;
if (val & RPC_CMNSR_TEND)
return ERROR_OK;
alive_sleep(1);
} while (timeval_ms() < endtime);
LOG_ERROR("timeout");
return ERROR_TIMEOUT_REACHED;
}
static int clrsetbits_u32(struct target *target, uint32_t reg,
uint32_t clr, uint32_t set)
{
uint32_t val;
int ret;
ret = target_read_u32(target, reg, &val);
if (ret != ERROR_OK)
return ret;
val &= ~clr;
val |= set;
return target_write_u32(target, reg, val);
}
static int rpc_hf_mode(struct target *target, bool manual)
{
uint32_t val;
int ret;
ret = rpc_hf_wait_tend(target);
if (ret != ERROR_OK) {
LOG_ERROR("Mode TEND timeout");
return ret;
}
ret = clrsetbits_u32(target, rpc_base + RPC_PHYCNT,
RPC_PHYCNT_WBUF | RPC_PHYCNT_WBUF2 |
RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3),
RPC_PHYCNT_CAL | RPC_PHYCNT_MEM(3));
if (ret != ERROR_OK)
return ret;
ret = clrsetbits_u32(target, rpc_base + RPC_CMNCR,
RPC_CMNCR_MD | RPC_CMNCR_BSZ(3),
RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
(manual ? RPC_CMNCR_MD : 0) | RPC_CMNCR_BSZ(1));
if (ret != ERROR_OK)
return ret;
if (manual)
return ERROR_OK;
ret = target_write_u32(target, rpc_base + RPC_DRCR,
RPC_DRCR_RBURST(0x1F) | RPC_DRCR_RCF |
RPC_DRCR_RBE);
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_DRCMR,
RPC_DRCMR_CMD(0xA0));
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_DRENR,
RPC_DRENR_CDB(2) | RPC_DRENR_OCDB(2) |
RPC_DRENR_ADB(2) | RPC_DRENR_SPIDB(2) |
RPC_DRENR_CDE | RPC_DRENR_OCDE |
RPC_DRENR_ADE(4));
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_DRDMCR,
RPC_DRDMCR_DMCYC(0xE));
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_DRDRENR,
RPC_DRDRENR_HYPE | RPC_DRDRENR_ADDRE |
RPC_DRDRENR_DRDRE);
if (ret != ERROR_OK)
return ret;
/* Dummy read */
return target_read_u32(target, rpc_base + RPC_DRCR, &val);
}
static int rpc_hf_xfer(struct target *target, target_addr_t addr,
uint32_t wdata, uint32_t *rdata, enum rpc_hf_size size,
bool write, const uint8_t *wbuf, unsigned int wbuf_size)
{
int ret;
uint32_t val;
if (wbuf_size != 0) {
ret = rpc_hf_wait_tend(target);
if (ret != ERROR_OK) {
LOG_ERROR("Xfer TEND timeout");
return ret;
}
/* Write calibration magic */
ret = target_write_u32(target, rpc_base + RPC_DRCR, 0x01FF0301);
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_PHYCNT, 0x80030277);
if (ret != ERROR_OK)
return ret;
ret = target_write_memory(target, rpc_base | RPC_WBUF, 4,
wbuf_size / 4, wbuf);
if (ret != ERROR_OK)
return ret;
ret = clrsetbits_u32(target, rpc_base + RPC_CMNCR,
RPC_CMNCR_MD | RPC_CMNCR_BSZ(3),
RPC_CMNCR_MOIIO_HIZ | RPC_CMNCR_IOFV_HIZ |
RPC_CMNCR_MD | RPC_CMNCR_BSZ(1));
if (ret != ERROR_OK)
return ret;
} else {
ret = rpc_hf_mode(target, 1);
if (ret != ERROR_OK)
return ret;
}
/* Submit HF address, SMCMR CMD[7] ~= CA Bit# 47 (R/nW) */
ret = target_write_u32(target, rpc_base + RPC_SMCMR,
write ? 0 : RPC_SMCMR_CMD(0x80));
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_SMADR,
addr >> 1);
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_SMOPR, 0x0);
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_SMDRENR,
RPC_SMDRENR_HYPE | RPC_SMDRENR_ADDRE |
RPC_SMDRENR_SPIDRE);
if (ret != ERROR_OK)
return ret;
val = RPC_SMENR_CDB(2) | RPC_SMENR_OCDB(2) |
RPC_SMENR_ADB(2) | RPC_SMENR_SPIDB(2) |
(wbuf_size ? RPC_SMENR_OPDB(2) : 0) |
RPC_SMENR_CDE | RPC_SMENR_OCDE | RPC_SMENR_ADE(4) | size;
if (write) {
ret = target_write_u32(target, rpc_base + RPC_SMENR, val);
if (ret != ERROR_OK)
return ret;
if (wbuf_size == 0) {
buf_bswap32((uint8_t *)&wdata, (uint8_t *)&wdata, 4);
ret = target_write_u32(target, rpc_base + RPC_SMWDR0,
wdata);
if (ret != ERROR_OK)
return ret;
}
ret = target_write_u32(target, rpc_base + RPC_SMCR,
RPC_SMCR_SPIWE | RPC_SMCR_SPIE);
if (ret != ERROR_OK)
return ret;
} else {
val |= RPC_SMENR_DME;
ret = target_write_u32(target, rpc_base + RPC_SMDMCR,
RPC_SMDMCR_DMCYC(0xE));
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_SMENR, val);
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, rpc_base + RPC_SMCR,
RPC_SMCR_SPIRE | RPC_SMCR_SPIE);
if (ret != ERROR_OK)
return ret;
ret = rpc_hf_wait_tend(target);
if (ret != ERROR_OK)
return ret;
uint32_t val32;
ret = target_read_u32(target, rpc_base + RPC_SMRDR0, &val32);
if (ret != ERROR_OK)
return ret;
buf_bswap32((uint8_t *)&val32, (uint8_t *)&val32, 4);
*rdata = val32;
}
ret = rpc_hf_mode(target, 0);
if (ret != ERROR_OK)
LOG_ERROR("Xfer done TEND timeout");
return ret;
}
static int rpchf_target_write_memory(struct flash_bank *bank, target_addr_t addr,
uint32_t count, const uint8_t *buffer)
{
struct target *target = bank->target;
uint32_t wdata;
if (count != 2)
return ERROR_FAIL;
wdata = buffer[0] | (buffer[1] << 8);
return rpc_hf_xfer(target, addr, wdata, NULL, RPC_HF_SIZE_16BIT,
true, NULL, 0);
}
static int rpchf_target_read_memory(struct flash_bank *bank, target_addr_t addr,
uint32_t count, uint8_t *buffer)
{
struct target *target = bank->target;
uint32_t i, rdata;
int ret;
for (i = 0; i < count; i++) {
ret = rpc_hf_xfer(target, addr + (2 * i), 0, &rdata,
RPC_HF_SIZE_16BIT, false, NULL, 0);
if (ret != ERROR_OK)
return ret;
buffer[(2 * i) + 0] = rdata & 0xff;
buffer[(2 * i) + 1] = (rdata >> 8) & 0xff;
}
return ERROR_OK;
}
FLASH_BANK_COMMAND_HANDLER(rpchf_flash_bank_command)
{
struct cfi_flash_bank *cfi_info;
int ret;
ret = cfi_flash_bank_cmd(bank, CMD_ARGC, CMD_ARGV);
if (ret != ERROR_OK)
return ret;
cfi_info = bank->driver_priv;
cfi_info->read_mem = rpchf_target_read_memory;
cfi_info->write_mem = rpchf_target_write_memory;
return ERROR_OK;
}
static int rpchf_spansion_write_words(struct flash_bank *bank, const uint8_t *word,
uint32_t wordcount, uint32_t address)
{
int retval;
struct cfi_flash_bank *cfi_info = bank->driver_priv;
struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext;
/* Calculate buffer size and boundary mask
* buffersize is (buffer size per chip) * (number of chips)
* bufferwsize is buffersize in words */
uint32_t buffersize = RPC_WBUF_SIZE;
uint32_t buffermask = buffersize - 1;
uint32_t bufferwsize = buffersize / 2;
/* Check for valid range */
if (address & buffermask) {
LOG_ERROR("Write address at base " TARGET_ADDR_FMT
", address 0x%" PRIx32 " not aligned to 2^%d boundary",
bank->base, address, cfi_info->max_buf_write_size);
return ERROR_FLASH_OPERATION_FAILED;
}
/* Check for valid size */
if (wordcount > bufferwsize) {
LOG_ERROR("Number of data words %" PRId32 " exceeds available buffersize %"
PRId32, wordcount, buffersize);
return ERROR_FLASH_OPERATION_FAILED;
}
/* Unlock */
retval = cfi_spansion_unlock_seq(bank);
if (retval != ERROR_OK)
return retval;
retval = cfi_send_command(bank, 0xa0, cfi_flash_address(bank, 0, pri_ext->_unlock1));
if (retval != ERROR_OK)
return retval;
retval = rpc_hf_xfer(bank->target, address, 0, NULL, RPC_HF_SIZE_64BIT, true, word, wordcount * 2);
if (retval != ERROR_OK)
return retval;
if (cfi_spansion_wait_status_busy(bank, cfi_info->word_write_timeout) != ERROR_OK) {
retval = cfi_send_command(bank, 0xf0, cfi_flash_address(bank, 0, 0x0));
if (retval != ERROR_OK)
return retval;
LOG_ERROR("couldn't write block at base " TARGET_ADDR_FMT
", address 0x%" PRIx32 ", size 0x%" PRIx32, bank->base, address,
bufferwsize);
return ERROR_FLASH_OPERATION_FAILED;
}
return ERROR_OK;
}
static int rpchf_write_words(struct flash_bank *bank, const uint8_t *word,
uint32_t wordcount, uint32_t address)
{
return rpchf_spansion_write_words(bank, word, wordcount, address);
}
static int rpchf_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct cfi_flash_bank *cfi_info = bank->driver_priv;
uint32_t address = bank->base + offset; /* address of first byte to be programmed */
uint32_t write_p;
int align; /* number of unaligned bytes */
uint8_t current_word[CFI_MAX_BUS_WIDTH * 4]; /* word (bus_width size) currently being
*programmed */
int i;
int retval;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size)
return ERROR_FLASH_DST_OUT_OF_BANK;
if (cfi_info->qry[0] != 'Q')
return ERROR_FLASH_BANK_NOT_PROBED;
/* start at the first byte of the first word (bus_width size) */
write_p = address & ~(bank->bus_width - 1);
align = address - write_p;
if (align != 0) {
LOG_INFO("Fixup %d unaligned head bytes", align);
/* read a complete word from flash */
retval = cfi_target_read_memory(bank, write_p, 1, current_word);
if (retval != ERROR_OK)
return retval;
/* replace only bytes that must be written */
for (i = align;
(i < bank->bus_width) && (count > 0);
i++, count--)
if (cfi_info->data_swap)
/* data bytes are swapped (reverse endianness) */
current_word[bank->bus_width - i] = *buffer++;
else
current_word[i] = *buffer++;
retval = cfi_write_word(bank, current_word, write_p);
if (retval != ERROR_OK)
return retval;
write_p += bank->bus_width;
}
/* Calculate buffer size and boundary mask
* buffersize is (buffer size per chip) * (number of chips)
* bufferwsize is buffersize in words */
uint32_t buffersize = RPC_WBUF_SIZE;
uint32_t buffermask = buffersize-1;
uint32_t bufferwsize = buffersize / bank->bus_width;
/* fall back to memory writes */
while (count >= (uint32_t)bank->bus_width) {
int fallback;
if ((write_p & 0xff) == 0) {
LOG_INFO("Programming at 0x%08" PRIx32 ", count 0x%08"
PRIx32 " bytes remaining", write_p, count);
}
fallback = 1;
if ((bufferwsize > 0) && (count >= buffersize) &&
!(write_p & buffermask)) {
retval = rpchf_write_words(bank, buffer, bufferwsize, write_p);
if (retval == ERROR_OK) {
buffer += buffersize;
write_p += buffersize;
count -= buffersize;
fallback = 0;
} else if (retval != ERROR_FLASH_OPER_UNSUPPORTED)
return retval;
}
/* try the slow way? */
if (fallback) {
for (i = 0; i < bank->bus_width; i++)
current_word[i] = *buffer++;
retval = cfi_write_word(bank, current_word, write_p);
if (retval != ERROR_OK)
return retval;
write_p += bank->bus_width;
count -= bank->bus_width;
}
}
/* return to read array mode, so we can read from flash again for padding */
retval = cfi_reset(bank);
if (retval != ERROR_OK)
return retval;
/* handle unaligned tail bytes */
if (count > 0) {
LOG_INFO("Fixup %" PRId32 " unaligned tail bytes", count);
/* read a complete word from flash */
retval = cfi_target_read_memory(bank, write_p, 1, current_word);
if (retval != ERROR_OK)
return retval;
/* replace only bytes that must be written */
for (i = 0; (i < bank->bus_width) && (count > 0); i++, count--)
if (cfi_info->data_swap)
/* data bytes are swapped (reverse endianness) */
current_word[bank->bus_width - i] = *buffer++;
else
current_word[i] = *buffer++;
retval = cfi_write_word(bank, current_word, write_p);
if (retval != ERROR_OK)
return retval;
}
/* return to read array mode */
return cfi_reset(bank);
}
static int rpchf_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct cfi_flash_bank *cfi_info = bank->driver_priv;
struct target *target = bank->target;
LOG_DEBUG("reading buffer of %" PRIi32 " byte at 0x%8.8" PRIx32,
count, offset);
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size)
return ERROR_FLASH_DST_OUT_OF_BANK;
if (cfi_info->qry[0] != 'Q')
return ERROR_FLASH_BANK_NOT_PROBED;
return target_read_memory(target, offset | mem_base,
4, count / 4, buffer);
}
const struct flash_driver renesas_rpchf_flash = {
.name = "rpchf",
.flash_bank_command = rpchf_flash_bank_command,
.erase = cfi_erase,
.protect = cfi_protect,
.write = rpchf_write,
.read = rpchf_read,
.probe = cfi_probe,
.auto_probe = cfi_auto_probe,
.erase_check = default_flash_blank_check,
.protect_check = cfi_protect_check,
.info = cfi_get_info,
.free_driver_priv = default_flash_free_driver_priv,
};
+912
View File
@@ -0,0 +1,912 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* SH QSPI (Quad SPI) driver
* Copyright (C) 2019 Marek Vasut <marek.vasut@gmail.com>
*
* Based on U-Boot SH QSPI driver
* Copyright (C) 2013 Renesas Electronics Corporation
* Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "imp.h"
#include "spi.h"
#include <helper/binarybuffer.h>
#include <helper/bits.h>
#include <helper/time_support.h>
#include <helper/types.h>
#include <jtag/jtag.h>
#include <target/algorithm.h>
#include <target/arm.h>
#include <target/arm_opcodes.h>
#include <target/target.h>
/* SH QSPI register bit masks <REG>_<BIT> */
#define SPCR_MSTR 0x08
#define SPCR_SPE 0x40
#define SPSR_SPRFF 0x80
#define SPSR_SPTEF 0x20
#define SPPCR_IO3FV 0x04
#define SPPCR_IO2FV 0x02
#define SPPCR_IO1FV 0x01
#define SPBDCR_RXBC0 BIT(0)
#define SPCMD_SCKDEN BIT(15)
#define SPCMD_SLNDEN BIT(14)
#define SPCMD_SPNDEN BIT(13)
#define SPCMD_SSLKP BIT(7)
#define SPCMD_BRDV0 BIT(2)
#define SPCMD_INIT1 (SPCMD_SCKDEN | SPCMD_SLNDEN | \
SPCMD_SPNDEN | SPCMD_SSLKP | \
SPCMD_BRDV0)
#define SPCMD_INIT2 (SPCMD_SPNDEN | SPCMD_SSLKP | \
SPCMD_BRDV0)
#define SPBFCR_TXRST BIT(7)
#define SPBFCR_RXRST BIT(6)
#define SPBFCR_TXTRG 0x30
#define SPBFCR_RXTRG 0x07
/* SH QSPI register set */
#define SH_QSPI_SPCR 0x00
#define SH_QSPI_SSLP 0x01
#define SH_QSPI_SPPCR 0x02
#define SH_QSPI_SPSR 0x03
#define SH_QSPI_SPDR 0x04
#define SH_QSPI_SPSCR 0x08
#define SH_QSPI_SPSSR 0x09
#define SH_QSPI_SPBR 0x0a
#define SH_QSPI_SPDCR 0x0b
#define SH_QSPI_SPCKD 0x0c
#define SH_QSPI_SSLND 0x0d
#define SH_QSPI_SPND 0x0e
#define SH_QSPI_DUMMY0 0x0f
#define SH_QSPI_SPCMD0 0x10
#define SH_QSPI_SPCMD1 0x12
#define SH_QSPI_SPCMD2 0x14
#define SH_QSPI_SPCMD3 0x16
#define SH_QSPI_SPBFCR 0x18
#define SH_QSPI_DUMMY1 0x19
#define SH_QSPI_SPBDCR 0x1a
#define SH_QSPI_SPBMUL0 0x1c
#define SH_QSPI_SPBMUL1 0x20
#define SH_QSPI_SPBMUL2 0x24
#define SH_QSPI_SPBMUL3 0x28
struct sh_qspi_flash_bank {
const struct flash_device *dev;
uint32_t io_base;
int probed;
struct working_area *io_algorithm;
struct working_area *source;
unsigned int buffer_size;
};
struct sh_qspi_target {
char *name;
uint32_t tap_idcode;
uint32_t io_base;
};
static const struct sh_qspi_target target_devices[] = {
/* name, tap_idcode, io_base */
{ "SH QSPI", 0x4ba00477, 0xe6b10000 },
{ NULL, 0, 0 }
};
static int sh_qspi_init(struct flash_bank *bank)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
uint8_t val;
int ret;
/* QSPI initialize */
/* Set master mode only */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPCR, SPCR_MSTR);
if (ret != ERROR_OK)
return ret;
/* Set SSL signal level */
ret = target_write_u8(target, info->io_base + SH_QSPI_SSLP, 0x00);
if (ret != ERROR_OK)
return ret;
/* Set MOSI signal value when transfer is in idle state */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPPCR,
SPPCR_IO3FV | SPPCR_IO2FV);
if (ret != ERROR_OK)
return ret;
/* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPBR, 0x01);
if (ret != ERROR_OK)
return ret;
/* Disable Dummy Data Transmission */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPDCR, 0x00);
if (ret != ERROR_OK)
return ret;
/* Set clock delay value */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPCKD, 0x00);
if (ret != ERROR_OK)
return ret;
/* Set SSL negation delay value */
ret = target_write_u8(target, info->io_base + SH_QSPI_SSLND, 0x00);
if (ret != ERROR_OK)
return ret;
/* Set next-access delay value */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPND, 0x00);
if (ret != ERROR_OK)
return ret;
/* Set equence command */
ret = target_write_u16(target, info->io_base + SH_QSPI_SPCMD0,
SPCMD_INIT2);
if (ret != ERROR_OK)
return ret;
/* Reset transfer and receive Buffer */
ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val);
if (ret != ERROR_OK)
return ret;
val |= SPBFCR_TXRST | SPBFCR_RXRST;
ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val);
if (ret != ERROR_OK)
return ret;
/* Clear transfer and receive Buffer control bit */
ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val);
if (ret != ERROR_OK)
return ret;
val &= ~(SPBFCR_TXRST | SPBFCR_RXRST);
ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val);
if (ret != ERROR_OK)
return ret;
/* Set equence control method. Use equence0 only */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPSCR, 0x00);
if (ret != ERROR_OK)
return ret;
/* Enable SPI function */
ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val);
if (ret != ERROR_OK)
return ret;
val |= SPCR_SPE;
return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val);
}
static int sh_qspi_cs_activate(struct flash_bank *bank)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
uint8_t val;
int ret;
/* Set master mode only */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPCR, SPCR_MSTR);
if (ret != ERROR_OK)
return ret;
/* Set command */
ret = target_write_u16(target, info->io_base + SH_QSPI_SPCMD0,
SPCMD_INIT1);
if (ret != ERROR_OK)
return ret;
/* Reset transfer and receive Buffer */
ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val);
if (ret != ERROR_OK)
return ret;
val |= SPBFCR_TXRST | SPBFCR_RXRST;
ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val);
if (ret != ERROR_OK)
return ret;
/* Clear transfer and receive Buffer control bit */
ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR, &val);
if (ret != ERROR_OK)
return ret;
val &= ~(SPBFCR_TXRST | SPBFCR_RXRST);
ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR, val);
if (ret != ERROR_OK)
return ret;
/* Set equence control method. Use equence0 only */
ret = target_write_u8(target, info->io_base + SH_QSPI_SPSCR, 0x00);
if (ret != ERROR_OK)
return ret;
/* Enable SPI function */
ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val);
if (ret != ERROR_OK)
return ret;
val |= SPCR_SPE;
return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val);
}
static int sh_qspi_cs_deactivate(struct flash_bank *bank)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
uint8_t val;
int ret;
/* Disable SPI Function */
ret = target_read_u8(target, info->io_base + SH_QSPI_SPCR, &val);
if (ret != ERROR_OK)
return ret;
val &= ~SPCR_SPE;
return target_write_u8(target, info->io_base + SH_QSPI_SPCR, val);
}
static int sh_qspi_wait_for_bit(struct flash_bank *bank, uint8_t reg,
uint32_t mask, bool set,
unsigned long timeout)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
long long endtime;
uint8_t val;
int ret;
endtime = timeval_ms() + timeout;
do {
ret = target_read_u8(target, info->io_base + reg, &val);
if (ret != ERROR_OK)
return ret;
if (!set)
val = ~val;
if ((val & mask) == mask)
return ERROR_OK;
alive_sleep(1);
} while (timeval_ms() < endtime);
LOG_ERROR("timeout");
return ERROR_TIMEOUT_REACHED;
}
static int sh_qspi_xfer_common(struct flash_bank *bank,
const uint8_t *dout, unsigned int outlen,
uint8_t *din, unsigned int inlen,
bool xfer_start, bool xfer_end)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
uint8_t tdata, rdata;
uint8_t val;
unsigned int nbyte = outlen + inlen;
int ret = 0;
if (xfer_start) {
ret = sh_qspi_cs_activate(bank);
if (ret != ERROR_OK)
return ret;
ret = target_write_u32(target, info->io_base + SH_QSPI_SPBMUL0,
nbyte);
if (ret != ERROR_OK)
return ret;
ret = target_read_u8(target, info->io_base + SH_QSPI_SPBFCR,
&val);
if (ret != ERROR_OK)
return ret;
val &= ~(SPBFCR_TXTRG | SPBFCR_RXTRG);
ret = target_write_u8(target, info->io_base + SH_QSPI_SPBFCR,
val);
if (ret != ERROR_OK)
return ret;
}
while (nbyte > 0) {
ret = sh_qspi_wait_for_bit(bank, SH_QSPI_SPSR, SPSR_SPTEF,
true, 1000);
if (ret != ERROR_OK)
return ret;
tdata = outlen ? *dout++ : 0;
ret = target_write_u8(target, info->io_base + SH_QSPI_SPDR,
tdata);
if (ret != ERROR_OK)
return ret;
ret = sh_qspi_wait_for_bit(bank, SH_QSPI_SPSR, SPSR_SPRFF,
true, 1000);
if (ret != ERROR_OK)
return ret;
ret = target_read_u8(target, info->io_base + SH_QSPI_SPDR,
&rdata);
if (ret != ERROR_OK)
return ret;
if (!outlen && inlen) {
*din++ = rdata;
inlen--;
}
if (outlen)
outlen--;
nbyte--;
}
if (xfer_end)
return sh_qspi_cs_deactivate(bank);
else
return ERROR_OK;
}
/* Send "write enable" command to SPI flash chip. */
static int sh_qspi_write_enable(struct flash_bank *bank)
{
uint8_t dout = SPIFLASH_WRITE_ENABLE;
return sh_qspi_xfer_common(bank, &dout, 1, NULL, 0, 1, 1);
}
/* Read the status register of the external SPI flash chip. */
static int read_status_reg(struct flash_bank *bank, uint32_t *status)
{
uint8_t dout = SPIFLASH_READ_STATUS;
uint8_t din;
int ret;
ret = sh_qspi_xfer_common(bank, &dout, 1, &din, 1, 1, 1);
if (ret != ERROR_OK)
return ret;
*status = din & 0xff;
return ERROR_OK;
}
/* check for WIP (write in progress) bit in status register */
/* timeout in ms */
static int wait_till_ready(struct flash_bank *bank, int timeout)
{
long long endtime;
uint32_t status;
int ret;
endtime = timeval_ms() + timeout;
do {
/* read flash status register */
ret = read_status_reg(bank, &status);
if (ret != ERROR_OK)
return ret;
if ((status & SPIFLASH_BSY_BIT) == 0)
return ERROR_OK;
alive_sleep(1);
} while (timeval_ms() < endtime);
LOG_ERROR("timeout");
return ERROR_TIMEOUT_REACHED;
}
static int sh_qspi_erase_sector(struct flash_bank *bank, int sector)
{
struct sh_qspi_flash_bank *info = bank->driver_priv;
bool addr4b = info->dev->size_in_bytes > (1UL << 24);
uint32_t address = (sector * info->dev->sectorsize) <<
(addr4b ? 0 : 8);
uint8_t dout[5] = {
info->dev->erase_cmd,
(address >> 24) & 0xff, (address >> 16) & 0xff,
(address >> 8) & 0xff, (address >> 0) & 0xff
};
unsigned int doutlen = addr4b ? 5 : 4;
int ret;
/* Write Enable */
ret = sh_qspi_write_enable(bank);
if (ret != ERROR_OK)
return ret;
/* Erase */
ret = sh_qspi_xfer_common(bank, dout, doutlen, NULL, 0, 1, 1);
if (ret != ERROR_OK)
return ret;
/* Poll status register */
return wait_till_ready(bank, 3000);
}
static int sh_qspi_erase(struct flash_bank *bank, int first, int last)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
int retval = ERROR_OK;
int sector;
LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last);
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
LOG_ERROR("Flash sector invalid");
return ERROR_FLASH_SECTOR_INVALID;
}
if (!info->probed) {
LOG_ERROR("Flash bank not probed");
return ERROR_FLASH_BANK_NOT_PROBED;
}
if (info->dev->erase_cmd == 0x00)
return ERROR_FLASH_OPER_UNSUPPORTED;
for (sector = first; sector <= last; sector++) {
if (bank->sectors[sector].is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL;
}
}
for (sector = first; sector <= last; sector++) {
retval = sh_qspi_erase_sector(bank, sector);
if (retval != ERROR_OK)
break;
keep_alive();
}
return retval;
}
static int sh_qspi_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
struct reg_param reg_params[4];
struct arm_algorithm arm_algo;
uint32_t io_base = (uint32_t)(info->io_base);
uint32_t src_base = (uint32_t)(info->source->address);
uint32_t chunk;
bool addr4b = !!(info->dev->size_in_bytes > (1UL << 24));
int ret = ERROR_OK;
int sector;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size) {
LOG_WARNING("Write pasts end of flash. Extra data discarded.");
count = bank->size - offset;
}
if (offset & 0xff) {
LOG_ERROR("sh_qspi_write_page: unaligned write address: %08x",
offset);
return ERROR_FAIL;
}
/* Check sector protection */
for (sector = 0; sector < bank->num_sectors; sector++) {
/* Start offset in or before this sector? */
/* End offset in or behind this sector? */
struct flash_sector *bs = &bank->sectors[sector];
if ((offset < (bs->offset + bs->size)) &&
((offset + count - 1) >= bs->offset) &&
bs->is_protected) {
LOG_ERROR("Flash sector %d protected", sector);
return ERROR_FAIL;
}
}
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size) {
LOG_WARNING("Reads past end of flash. Extra data discarded.");
count = bank->size - offset;
}
arm_algo.common_magic = ARM_COMMON_MAGIC;
arm_algo.core_mode = ARM_MODE_SVC;
arm_algo.core_state = ARM_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
while (count > 0) {
chunk = (count > info->buffer_size) ?
info->buffer_size : count;
target_write_buffer(target, info->source->address,
chunk, buffer);
buf_set_u32(reg_params[0].value, 0, 32, io_base);
buf_set_u32(reg_params[1].value, 0, 32, src_base);
buf_set_u32(reg_params[2].value, 0, 32,
(1 << 31) | (addr4b << 30) |
(info->dev->pprog_cmd << 20) | chunk);
buf_set_u32(reg_params[3].value, 0, 32, offset);
ret = target_run_algorithm(target, 0, NULL, 4, reg_params,
info->io_algorithm->address,
0, 10000, &arm_algo);
if (ret != ERROR_OK) {
LOG_ERROR("error executing SH QSPI flash IO algorithm");
ret = ERROR_FLASH_OPERATION_FAILED;
break;
}
buffer += chunk;
offset += chunk;
count -= chunk;
}
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);
return ret;
}
static int sh_qspi_read(struct flash_bank *bank, uint8_t *buffer,
uint32_t offset, uint32_t count)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
struct reg_param reg_params[4];
struct arm_algorithm arm_algo;
uint32_t io_base = (uint32_t)(info->io_base);
uint32_t src_base = (uint32_t)(info->source->address);
uint32_t chunk;
bool addr4b = !!(info->dev->size_in_bytes > (1UL << 24));
int ret = ERROR_OK;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
__func__, offset, count);
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
if (offset + count > bank->size) {
LOG_WARNING("Reads past end of flash. Extra data discarded.");
count = bank->size - offset;
}
arm_algo.common_magic = ARM_COMMON_MAGIC;
arm_algo.core_mode = ARM_MODE_SVC;
arm_algo.core_state = ARM_STATE_ARM;
init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
while (count > 0) {
chunk = (count > info->buffer_size) ?
info->buffer_size : count;
buf_set_u32(reg_params[0].value, 0, 32, io_base);
buf_set_u32(reg_params[1].value, 0, 32, src_base);
buf_set_u32(reg_params[2].value, 0, 32,
(addr4b << 30) | (info->dev->read_cmd << 20) |
chunk);
buf_set_u32(reg_params[3].value, 0, 32, offset);
ret = target_run_algorithm(target, 0, NULL, 4, reg_params,
info->io_algorithm->address,
0, 10000, &arm_algo);
if (ret != ERROR_OK) {
LOG_ERROR("error executing SH QSPI flash IO algorithm");
ret = ERROR_FLASH_OPERATION_FAILED;
break;
}
target_read_buffer(target, info->source->address,
chunk, buffer);
buffer += chunk;
offset += chunk;
count -= chunk;
}
destroy_reg_param(&reg_params[0]);
destroy_reg_param(&reg_params[1]);
destroy_reg_param(&reg_params[2]);
destroy_reg_param(&reg_params[3]);
return ret;
}
/* Return ID of flash device */
static int read_flash_id(struct flash_bank *bank, uint32_t *id)
{
struct target *target = bank->target;
uint8_t dout = SPIFLASH_READ_ID;
uint8_t din[3] = { 0, 0, 0 };
int ret;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
ret = sh_qspi_xfer_common(bank, &dout, 1, din, 3, 1, 1);
if (ret != ERROR_OK)
return ret;
*id = (din[0] << 0) | (din[1] << 8) | (din[2] << 16);
if (*id == 0xffffff) {
LOG_ERROR("No SPI flash found");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int sh_qspi_protect(struct flash_bank *bank, int set,
int first, int last)
{
int sector;
for (sector = first; sector <= last; sector++)
bank->sectors[sector].is_protected = set;
return ERROR_OK;
}
static int sh_qspi_upload_helper(struct flash_bank *bank)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
/* see contrib/loaders/flash/sh_qspi.s for src */
static const uint8_t sh_qspi_io_code[] = {
#include "../../../contrib/loaders/flash/sh_qspi/sh_qspi.inc"
};
int ret;
if (info->source)
target_free_working_area(target, info->source);
if (info->io_algorithm)
target_free_working_area(target, info->io_algorithm);
/* flash write code */
if (target_alloc_working_area(target, sizeof(sh_qspi_io_code),
&info->io_algorithm) != ERROR_OK) {
LOG_WARNING("no working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
target_write_buffer(target, info->io_algorithm->address,
sizeof(sh_qspi_io_code), sh_qspi_io_code);
/*
* Try to allocate as big work area buffer as possible, start
* with 32 kiB and count down. If there is less than 256 Bytes
* of work area available, abort.
*/
info->buffer_size = 32768;
while (true) {
ret = target_alloc_working_area_try(target, info->buffer_size,
&info->source);
if (ret == ERROR_OK)
return ret;
info->buffer_size /= 2;
if (info->buffer_size <= 256) {
target_free_working_area(target, info->io_algorithm);
LOG_WARNING("no large enough working area available, can't do block memory writes");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
}
return ERROR_OK;
}
static int sh_qspi_probe(struct flash_bank *bank)
{
struct target *target = bank->target;
struct sh_qspi_flash_bank *info = bank->driver_priv;
struct flash_sector *sectors;
uint32_t id = 0; /* silence uninitialized warning */
uint32_t sectorsize;
const struct sh_qspi_target *target_device;
int ret;
if (info->probed)
free(bank->sectors);
info->probed = 0;
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",
target->tap->idcode);
return ERROR_FAIL;
}
info->io_base = target_device->io_base;
LOG_DEBUG("Found device %s at address " TARGET_ADDR_FMT,
target_device->name, bank->base);
ret = sh_qspi_upload_helper(bank);
if (ret != ERROR_OK)
return ret;
ret = sh_qspi_init(bank);
if (ret != ERROR_OK)
return ret;
ret = read_flash_id(bank, &id);
if (ret != ERROR_OK)
return ret;
info->dev = NULL;
for (const struct flash_device *p = flash_devices; p->name; p++)
if (p->device_id == id) {
info->dev = p;
break;
}
if (!info->dev) {
LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id);
return ERROR_FAIL;
}
LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")",
info->dev->name, info->dev->device_id);
/* Set correct size value */
bank->size = info->dev->size_in_bytes;
if (bank->size <= (1UL << 16))
LOG_WARNING("device needs 2-byte addresses - not implemented");
/* if no sectors, treat whole bank as single sector */
sectorsize = info->dev->sectorsize ?
info->dev->sectorsize :
info->dev->size_in_bytes;
/* create and fill sectors array */
bank->num_sectors = info->dev->size_in_bytes / sectorsize;
sectors = calloc(1, sizeof(*sectors) * bank->num_sectors);
if (!sectors) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
for (int sector = 0; sector < bank->num_sectors; sector++) {
sectors[sector].offset = sector * sectorsize;
sectors[sector].size = sectorsize;
sectors[sector].is_erased = 0;
sectors[sector].is_protected = 0;
}
bank->sectors = sectors;
info->probed = 1;
return ERROR_OK;
}
static int sh_qspi_auto_probe(struct flash_bank *bank)
{
struct sh_qspi_flash_bank *info = bank->driver_priv;
if (info->probed)
return ERROR_OK;
return sh_qspi_probe(bank);
}
static int sh_qspi_flash_blank_check(struct flash_bank *bank)
{
/* Not implemented */
return ERROR_OK;
}
static int sh_qspi_protect_check(struct flash_bank *bank)
{
/* Not implemented */
return ERROR_OK;
}
static int sh_qspi_get_info(struct flash_bank *bank, char *buf, int buf_size)
{
struct sh_qspi_flash_bank *info = bank->driver_priv;
if (!info->probed) {
snprintf(buf, buf_size,
"\nSH QSPI flash bank not probed yet\n");
return ERROR_OK;
}
snprintf(buf, buf_size, "\nSH QSPI flash information:\n"
" Device \'%s\' (ID 0x%08" PRIx32 ")\n",
info->dev->name, info->dev->device_id);
return ERROR_OK;
}
FLASH_BANK_COMMAND_HANDLER(sh_qspi_flash_bank_command)
{
struct sh_qspi_flash_bank *info;
LOG_DEBUG("%s", __func__);
if (CMD_ARGC < 6 || CMD_ARGC > 7)
return ERROR_COMMAND_SYNTAX_ERROR;
if ((CMD_ARGC == 7) && strcmp(CMD_ARGV[6], "cs0")) {
LOG_ERROR("Unknown arg: %s", CMD_ARGV[6]);
return ERROR_COMMAND_SYNTAX_ERROR;
}
info = calloc(1, sizeof(struct sh_qspi_flash_bank));
if (!info) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
bank->driver_priv = info;
return ERROR_OK;
}
const struct flash_driver sh_qspi_flash = {
.name = "sh_qspi",
.flash_bank_command = sh_qspi_flash_bank_command,
.erase = sh_qspi_erase,
.protect = sh_qspi_protect,
.write = sh_qspi_write,
.read = sh_qspi_read,
.probe = sh_qspi_probe,
.auto_probe = sh_qspi_auto_probe,
.erase_check = sh_qspi_flash_blank_check,
.protect_check = sh_qspi_protect_check,
.info = sh_qspi_get_info,
.free_driver_priv = default_flash_free_driver_priv,
};
+1 -1
View File
@@ -471,7 +471,7 @@ static int sim3x_write_block(struct flash_bank *bank, const uint8_t *buf,
return ret;
}
static int sim3x_flash_write(struct flash_bank *bank, const uint8_t * buffer, uint32_t offset, uint32_t count)
static int sim3x_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
{
int ret;
struct target *target;
+66 -68
View File
@@ -116,7 +116,7 @@ struct stm32x_options {
struct stm32x_flash_bank {
struct stm32x_options option_bytes;
int ppage_size;
int probed;
bool probed;
bool has_dual_banks;
/* used to access dual flash bank stm32xl */
@@ -145,7 +145,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32x_flash_bank_command)
stm32x_info = malloc(sizeof(struct stm32x_flash_bank));
bank->driver_priv = stm32x_info;
stm32x_info->probed = 0;
stm32x_info->probed = false;
stm32x_info->has_dual_banks = false;
stm32x_info->can_load_options = false;
stm32x_info->register_base = FLASH_REG_BASE_B0;
@@ -229,34 +229,20 @@ static int stm32x_read_options(struct flash_bank *bank)
uint32_t option_bytes;
int retval;
/* read user and read protection option bytes */
retval = target_read_u32(target, STM32_OB_RDP, &option_bytes);
/* read user and read protection option bytes, user data option bytes */
retval = target_read_u32(target, STM32_FLASH_OBR_B0, &option_bytes);
if (retval != ERROR_OK)
return retval;
stm32x_info->option_bytes.rdp = option_bytes & 0xFF;
stm32x_info->option_bytes.user = (option_bytes >> 16) & 0xFF;
/* read user data option bytes */
retval = target_read_u32(target, STM32_OB_DATA0, &option_bytes);
if (retval != ERROR_OK)
return retval;
stm32x_info->option_bytes.data = ((option_bytes >> 8) & 0xFF00) | (option_bytes & 0xFF);
stm32x_info->option_bytes.rdp = (option_bytes & (1 << OPT_READOUT)) ? 0 : stm32x_info->default_rdp;
stm32x_info->option_bytes.user = (option_bytes >> stm32x_info->option_offset >> 2) & 0xff;
stm32x_info->option_bytes.data = (option_bytes >> stm32x_info->user_data_offset) & 0xffff;
/* read write protection option bytes */
retval = target_read_u32(target, STM32_OB_WRP0, &option_bytes);
retval = target_read_u32(target, STM32_FLASH_WRPR_B0, &stm32x_info->option_bytes.protection);
if (retval != ERROR_OK)
return retval;
stm32x_info->option_bytes.protection = ((option_bytes >> 8) & 0xFF00) | (option_bytes & 0xFF);
retval = target_read_u32(target, STM32_OB_WRP2, &option_bytes);
if (retval != ERROR_OK)
return retval;
stm32x_info->option_bytes.protection |= (((option_bytes >> 8) & 0xFF00) | (option_bytes & 0xFF)) << 16;
return ERROR_OK;
}
@@ -382,7 +368,6 @@ static int stm32x_protect_check(struct flash_bank *bank)
static int stm32x_erase(struct flash_bank *bank, int first, int last)
{
struct target *target = bank->target;
int i;
if (bank->target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
@@ -400,7 +385,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
if (retval != ERROR_OK)
return retval;
for (i = first; i <= last; i++) {
for (int i = first; i <= last; i++) {
retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
if (retval != ERROR_OK)
return retval;
@@ -711,7 +696,7 @@ static int stm32x_probe(struct flash_bank *bank)
int page_size;
uint32_t base_address = 0x08000000;
stm32x_info->probed = 0;
stm32x_info->probed = false;
stm32x_info->register_base = FLASH_REG_BASE_B0;
stm32x_info->user_data_offset = 10;
stm32x_info->option_offset = 0;
@@ -728,31 +713,79 @@ static int stm32x_probe(struct flash_bank *bank)
/* set page size, protection granularity and max flash size depending on family */
switch (device_id & 0xfff) {
case 0x410: /* medium density */
case 0x440: /* stm32f05x */
page_size = 1024;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 64;
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
case 0x444: /* stm32f03x */
case 0x445: /* stm32f04x */
page_size = 1024;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 32;
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
case 0x448: /* stm32f07x */
page_size = 2048;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 128;
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
case 0x442: /* stm32f09x */
page_size = 2048;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 256;
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
case 0x410: /* stm32f1x medium-density */
page_size = 1024;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 128;
break;
case 0x412: /* low density */
case 0x412: /* stm32f1x low-density */
page_size = 1024;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 32;
break;
case 0x414: /* high density */
case 0x414: /* stm32f1x high-density */
page_size = 2048;
stm32x_info->ppage_size = 2;
max_flash_size_in_kb = 512;
break;
case 0x418: /* connectivity line density */
case 0x418: /* stm32f1x connectivity */
page_size = 2048;
stm32x_info->ppage_size = 2;
max_flash_size_in_kb = 256;
break;
case 0x420: /* value line density */
case 0x430: /* stm32f1 XL-density (dual flash banks) */
page_size = 2048;
stm32x_info->ppage_size = 2;
max_flash_size_in_kb = 1024;
stm32x_info->has_dual_banks = true;
break;
case 0x420: /* stm32f100xx low- and medium-density value line */
page_size = 1024;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 128;
break;
case 0x428: /* stm32f100xx high-density value line */
page_size = 2048;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 512;
break;
case 0x422: /* stm32f302/3xb/c */
page_size = 2048;
stm32x_info->ppage_size = 2;
@@ -771,17 +804,6 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
case 0x428: /* value line High density */
page_size = 2048;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 128;
break;
case 0x430: /* xl line density (dual flash banks) */
page_size = 2048;
stm32x_info->ppage_size = 2;
max_flash_size_in_kb = 1024;
stm32x_info->has_dual_banks = true;
break;
case 0x432: /* stm32f37x */
page_size = 2048;
stm32x_info->ppage_size = 2;
@@ -801,27 +823,6 @@ static int stm32x_probe(struct flash_bank *bank)
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
case 0x440: /* stm32f05x */
case 0x444: /* stm32f03x */
case 0x445: /* stm32f04x */
page_size = 1024;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 64;
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
case 0x448: /* stm32f07x */
case 0x442: /* stm32f09x */
page_size = 2048;
stm32x_info->ppage_size = 4;
max_flash_size_in_kb = 256;
stm32x_info->user_data_offset = 16;
stm32x_info->option_offset = 6;
stm32x_info->default_rdp = 0xAA;
stm32x_info->can_load_options = true;
break;
default:
LOG_WARNING("Cannot identify target as a STM32 family.");
return ERROR_FAIL;
@@ -900,7 +901,7 @@ static int stm32x_probe(struct flash_bank *bank)
if (num_prot_blocks == 32)
bank->prot_blocks[31].size = (num_pages - (31 * stm32x_info->ppage_size)) * page_size;
stm32x_info->probed = 1;
stm32x_info->probed = true;
return ERROR_OK;
}
@@ -1368,8 +1369,7 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], useropt);
CMD_ARGC--;
CMD_ARGV++;
}
else if (stm32x_info->has_dual_banks) {
} else if (stm32x_info->has_dual_banks) {
if (strcmp("BOOT0", CMD_ARGV[0]) == 0)
optionbyte |= (1 << 3);
else if (strcmp("BOOT1", CMD_ARGV[0]) == 0)
@@ -1488,8 +1488,6 @@ static int stm32x_mass_erase(struct flash_bank *bank)
COMMAND_HANDLER(stm32x_handle_mass_erase_command)
{
int i;
if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1501,7 +1499,7 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
retval = stm32x_mass_erase(bank);
if (retval == ERROR_OK) {
/* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++)
for (int i = 0; i < bank->num_sectors; i++)
bank->sectors[i].is_erased = 1;
command_print(CMD, "stm32x mass erase complete");
+57 -20
View File
@@ -634,7 +634,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last)
*/
for (i = first; i <= last; i++) {
int snb;
unsigned int snb;
if (stm32x_info->has_large_mem && i >= 12)
snb = (i - 12) | 0x10;
else
@@ -894,31 +894,68 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer,
return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK);
}
static int setup_sector(struct flash_bank *bank, int start, int num, int size)
static void setup_sector(struct flash_bank *bank, int i, int size)
{
assert(i < bank->num_sectors);
bank->sectors[i].offset = bank->size;
bank->sectors[i].size = size;
bank->size += bank->sectors[i].size;
LOG_DEBUG("sector %d: %dkBytes", i, size >> 10);
}
for (int i = start; i < (start + num) ; i++) {
assert(i < bank->num_sectors);
bank->sectors[i].offset = bank->size;
bank->sectors[i].size = size;
bank->size += bank->sectors[i].size;
LOG_DEBUG("sector %d: %d kBytes", i, size >> 10);
static uint16_t sector_size_in_kb(int i, uint16_t max_sector_size_in_kb)
{
assert(i >= 0);
if (i < 4)
return max_sector_size_in_kb / 8;
if (i == 4)
return max_sector_size_in_kb / 2;
return max_sector_size_in_kb;
}
static int calculate_number_of_sectors(struct flash_bank *bank,
uint16_t flash_size_in_kb,
uint16_t max_sector_size_in_kb)
{
struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
uint16_t remaining_flash_size_in_kb = flash_size_in_kb;
int nr_sectors;
/* Dual Bank Flash has two identically-arranged banks of sectors. */
if (stm32x_info->has_large_mem)
remaining_flash_size_in_kb /= 2;
for (nr_sectors = 0; remaining_flash_size_in_kb > 0; nr_sectors++) {
uint16_t size_in_kb = sector_size_in_kb(nr_sectors, max_sector_size_in_kb);
if (size_in_kb > remaining_flash_size_in_kb) {
LOG_INFO("%s Bank %" PRIu16 " kiB final sector clipped to %" PRIu16 " kiB",
stm32x_info->has_large_mem ? "Dual" : "Single",
flash_size_in_kb, remaining_flash_size_in_kb);
remaining_flash_size_in_kb = 0;
} else {
remaining_flash_size_in_kb -= size_in_kb;
}
}
return start + num;
return stm32x_info->has_large_mem ? nr_sectors*2 : nr_sectors;
}
static void setup_bank(struct flash_bank *bank, int start,
uint16_t flash_size_in_kb, uint16_t max_sector_size_in_kb)
{
int remain;
start = setup_sector(bank, start, 4, (max_sector_size_in_kb / 8) * 1024);
start = setup_sector(bank, start, 1, (max_sector_size_in_kb / 2) * 1024);
/* remaining sectors all of size max_sector_size_in_kb */
remain = (flash_size_in_kb / max_sector_size_in_kb) - 1;
start = setup_sector(bank, start, remain, max_sector_size_in_kb * 1024);
uint16_t remaining_flash_size_in_kb = flash_size_in_kb;
int sector_index = 0;
while (remaining_flash_size_in_kb > 0) {
uint16_t size_in_kb = sector_size_in_kb(sector_index, max_sector_size_in_kb);
if (size_in_kb > remaining_flash_size_in_kb) {
/* Clip last sector. Already warned in
* calculate_number_of_sectors. */
size_in_kb = remaining_flash_size_in_kb;
}
setup_sector(bank, start + sector_index, size_in_kb * 1024);
remaining_flash_size_in_kb -= size_in_kb;
sector_index++;
}
}
static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id)
@@ -1150,12 +1187,12 @@ static int stm32x_probe(struct flash_bank *bank)
}
/* calculate numbers of pages */
int num_pages = flash_size_in_kb / max_sector_size_in_kb
+ (stm32x_info->has_large_mem ? 8 : 4);
int num_pages = calculate_number_of_sectors(
bank, flash_size_in_kb, max_sector_size_in_kb);
bank->base = base_address;
bank->num_sectors = num_pages;
bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
bank->sectors = calloc(num_pages, sizeof(struct flash_sector));
for (i = 0; i < num_pages; i++) {
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 0;
+438 -376
View File
File diff suppressed because it is too large Load Diff
+719 -390
View File
File diff suppressed because it is too large Load Diff
+82
View File
@@ -0,0 +1,82 @@
/***************************************************************************
* Copyright (C) 2015 by Uwe Bonnes *
* bon@elektron.ikp.physik.tu-darmstadt.de *
*
* 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 *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_FLASH_NOR_STM32L4X
#define OPENOCD_FLASH_NOR_STM32L4X
/* Flash registers offsets */
#define STM32_FLASH_ACR 0x00
#define STM32_FLASH_KEYR 0x08
#define STM32_FLASH_OPTKEYR 0x0c
#define STM32_FLASH_SR 0x10
#define STM32_FLASH_CR 0x14
#define STM32_FLASH_OPTR 0x20
#define STM32_FLASH_WRP1AR 0x2c
#define STM32_FLASH_WRP1BR 0x30
#define STM32_FLASH_WRP2AR 0x4c
#define STM32_FLASH_WRP2BR 0x50
/* FLASH_CR register bits */
#define FLASH_PG (1 << 0)
#define FLASH_PER (1 << 1)
#define FLASH_MER1 (1 << 2)
#define FLASH_PAGE_SHIFT 3
#define FLASH_CR_BKER (1 << 11)
#define FLASH_MER2 (1 << 15)
#define FLASH_STRT (1 << 16)
#define FLASH_OPTSTRT (1 << 17)
#define FLASH_EOPIE (1 << 24)
#define FLASH_ERRIE (1 << 25)
#define FLASH_OBL_LAUNCH (1 << 27)
#define FLASH_OPTLOCK (1 << 30)
#define FLASH_LOCK (1 << 31)
/* FLASH_SR register bits */
#define FLASH_BSY (1 << 16)
/* Fast programming not used => related errors not used*/
#define FLASH_PGSERR (1 << 7) /* Programming sequence error */
#define FLASH_SIZERR (1 << 6) /* Size error */
#define FLASH_PGAERR (1 << 5) /* Programming alignment error */
#define FLASH_WRPERR (1 << 4) /* Write protection error */
#define FLASH_PROGERR (1 << 3) /* Programming error */
#define FLASH_OPERR (1 << 1) /* Operation error */
#define FLASH_EOP (1 << 0) /* End of operation */
#define FLASH_ERROR (FLASH_PGSERR | FLASH_SIZERR | FLASH_PGAERR | \
FLASH_WRPERR | FLASH_PROGERR | FLASH_OPERR)
/* register unlock keys */
#define KEY1 0x45670123
#define KEY2 0xCDEF89AB
/* option register unlock key */
#define OPTKEY1 0x08192A3B
#define OPTKEY2 0x4C5D6E7F
#define RDP_LEVEL_0 0xAA
#define RDP_LEVEL_1 0xBB
#define RDP_LEVEL_2 0xCC
/* other registers */
#define DBGMCU_IDCODE_G0 0x40015800
#define DBGMCU_IDCODE_L4_G4 0xE0042000
#define DBGMCU_IDCODE_L5 0xE0044000
#define STM32_FLASH_BANK_BASE 0x08000000
#endif
+7 -10
View File
@@ -128,7 +128,7 @@ struct stm32lx_part_info {
};
struct stm32lx_flash_bank {
int probed;
bool probed;
uint32_t idcode;
uint32_t user_bank_size;
uint32_t flash_base;
@@ -297,7 +297,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
bank->driver_priv = stm32lx_info;
stm32lx_info->probed = 0;
stm32lx_info->probed = false;
stm32lx_info->user_bank_size = bank->size;
/* the stm32l erased value is 0x00 */
@@ -308,8 +308,6 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command)
COMMAND_HANDLER(stm32lx_handle_mass_erase_command)
{
int i;
if (CMD_ARGC < 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -321,7 +319,7 @@ COMMAND_HANDLER(stm32lx_handle_mass_erase_command)
retval = stm32lx_mass_erase(bank);
if (retval == ERROR_OK) {
/* set all sectors as erased */
for (i = 0; i < bank->num_sectors; i++)
for (int i = 0; i < bank->num_sectors; i++)
bank->sectors[i].is_erased = 1;
command_print(CMD, "stm32lx mass erase complete");
@@ -731,14 +729,13 @@ static int stm32lx_probe(struct flash_bank *bank)
{
struct target *target = bank->target;
struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv;
int i;
uint16_t flash_size_in_kb;
uint32_t device_id;
uint32_t base_address = FLASH_BANK0_ADDRESS;
uint32_t second_bank_base;
unsigned int n;
stm32lx_info->probed = 0;
stm32lx_info->probed = false;
int retval = stm32lx_read_id_code(bank->target, &device_id);
if (retval != ERROR_OK)
@@ -756,7 +753,7 @@ static int stm32lx_probe(struct flash_bank *bank)
}
if (n == ARRAY_SIZE(stm32lx_parts)) {
LOG_WARNING("Cannot identify target as a STM32L family.");
LOG_ERROR("Cannot identify target as an STM32 L0 or L1 family device.");
return ERROR_FAIL;
} else {
LOG_INFO("Device: %s", stm32lx_info->part_info.device_str);
@@ -852,14 +849,14 @@ static int stm32lx_probe(struct flash_bank *bank)
return ERROR_FAIL;
}
for (i = 0; i < num_sectors; i++) {
for (int i = 0; i < num_sectors; i++) {
bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
bank->sectors[i].size = FLASH_SECTOR_SIZE;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = -1;
}
stm32lx_info->probed = 1;
stm32lx_info->probed = true;
return ERROR_OK;
}
+111 -6
View File
@@ -109,7 +109,7 @@ COMMAND_HANDLER(handle_flash_info_command)
return retval;
}
if (retval == ERROR_FLASH_OPER_UNSUPPORTED)
LOG_WARNING("Flash protection check is not implemented.");
LOG_INFO("Flash protection check is not implemented.");
command_print(CMD,
"#%d : %s at " TARGET_ADDR_FMT ", size 0x%8.8" PRIx32
@@ -476,7 +476,7 @@ COMMAND_HANDLER(handle_flash_write_image_command)
COMMAND_HANDLER(handle_flash_fill_command)
{
target_addr_t address;
uint32_t pattern;
uint64_t pattern;
uint32_t count;
struct target *target = get_current_target(CMD_CTX);
unsigned i;
@@ -487,7 +487,7 @@ COMMAND_HANDLER(handle_flash_fill_command)
return ERROR_COMMAND_SYNTAX_ERROR;
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[1], pattern);
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
struct flash_bank *bank;
@@ -496,6 +496,9 @@ COMMAND_HANDLER(handle_flash_fill_command)
return retval;
switch (CMD_NAME[4]) {
case 'd':
wordsize = 8;
break;
case 'w':
wordsize = 4;
break;
@@ -509,6 +512,11 @@ COMMAND_HANDLER(handle_flash_fill_command)
return ERROR_COMMAND_SYNTAX_ERROR;
}
if ((wordsize < sizeof(pattern)) && (pattern >> (8 * wordsize) != 0)) {
command_print(CMD, "Fill pattern 0x%" PRIx64 " does not fit within %" PRIu32 "-byte word", pattern, wordsize);
return ERROR_FAIL;
}
if (count == 0)
return ERROR_OK;
@@ -541,6 +549,10 @@ COMMAND_HANDLER(handle_flash_fill_command)
uint8_t *ptr = buffer + padding_at_start;
switch (wordsize) {
case 8:
for (i = 0; i < count; i++, ptr += wordsize)
target_buffer_set_u64(target, ptr, pattern);
break;
case 4:
for (i = 0; i < count; i++, ptr += wordsize)
target_buffer_set_u32(target, ptr, pattern);
@@ -577,9 +589,12 @@ COMMAND_HANDLER(handle_flash_fill_command)
goto done;
for (i = 0, ptr = buffer; i < count; i++) {
uint32_t readback = 0;
uint64_t readback = 0;
switch (wordsize) {
case 8:
readback = target_buffer_get_u64(target, ptr);
break;
case 4:
readback = target_buffer_get_u32(target, ptr);
break;
@@ -593,7 +608,7 @@ COMMAND_HANDLER(handle_flash_fill_command)
if (readback != pattern) {
LOG_ERROR(
"Verification error address " TARGET_ADDR_FMT
", read back 0x%02" PRIx32 ", expected 0x%02" PRIx32,
", read back 0x%02" PRIx64 ", expected 0x%02" PRIx64,
address + i * wordsize, readback, pattern);
retval = ERROR_FAIL;
goto done;
@@ -613,6 +628,67 @@ done:
return retval;
}
COMMAND_HANDLER(handle_flash_md_command)
{
int retval;
if (CMD_ARGC < 1 || CMD_ARGC > 2)
return ERROR_COMMAND_SYNTAX_ERROR;
target_addr_t address;
COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
uint32_t count = 1;
if (CMD_ARGC == 2)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], count);
unsigned int wordsize;
switch (CMD_NAME[2]) {
case 'w':
wordsize = 4;
break;
case 'h':
wordsize = 2;
break;
case 'b':
wordsize = 1;
break;
default:
return ERROR_COMMAND_SYNTAX_ERROR;
}
if (count == 0)
return ERROR_OK;
struct target *target = get_current_target(CMD_CTX);
struct flash_bank *bank;
retval = get_flash_bank_by_addr(target, address, true, &bank);
if (retval != ERROR_OK)
return retval;
uint32_t offset = address - bank->base;
uint32_t sizebytes = count * wordsize;
if (offset + sizebytes > bank->size) {
command_print(CMD, "Cannot cross flash bank borders");
return ERROR_FAIL;
}
uint8_t *buffer = calloc(count, wordsize);
if (buffer == NULL) {
command_print(CMD, "No memory for flash read buffer");
return ERROR_FAIL;
}
retval = flash_driver_read(bank, buffer, offset, sizebytes);
if (retval == ERROR_OK)
target_handle_md_output(CMD, target, address, wordsize, count, buffer);
free(buffer);
return retval;
}
COMMAND_HANDLER(handle_flash_write_bank_command)
{
uint32_t offset;
@@ -952,7 +1028,7 @@ COMMAND_HANDLER(handle_flash_padded_value_command)
COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], p->default_padded_value);
command_print(CMD, "Default padded value set to 0x%" PRIx8 " for flash bank %u", \
command_print(CMD, "Default padded value set to 0x%" PRIx8 " for flash bank %u",
p->default_padded_value, p->bank_number);
return retval;
@@ -1002,6 +1078,14 @@ static const struct command_registration flash_exec_command_handlers[] = {
"before erasing.",
},
{
.name = "filld",
.handler = handle_flash_fill_command,
.mode = COMMAND_EXEC,
.usage = "address value n",
.help = "Fill n double-words with 64-bit value, starting at "
"word address. (No autoerase.)",
},
{
.name = "fillw",
.handler = handle_flash_fill_command,
@@ -1026,6 +1110,27 @@ static const struct command_registration flash_exec_command_handlers[] = {
.help = "Fill n bytes with 8-bit value, starting at "
"word address. (No autoerase.)",
},
{
.name = "mdb",
.handler = handle_flash_md_command,
.mode = COMMAND_EXEC,
.usage = "address [count]",
.help = "Display bytes from flash.",
},
{
.name = "mdh",
.handler = handle_flash_md_command,
.mode = COMMAND_EXEC,
.usage = "address [count]",
.help = "Display half-words from flash.",
},
{
.name = "mdw",
.handler = handle_flash_md_command,
.mode = COMMAND_EXEC,
.usage = "address [count]",
.help = "Display words from flash.",
},
{
.name = "write_bank",
.handler = handle_flash_write_bank_command,
+1
View File
@@ -709,6 +709,7 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
* Select one or more bits in FMBSEA or FMBSEB to disable Level 1
* protection for the particular sector to be erased/written.
*/
assert(sector >= 0);
if (sector < 16) {
target_read_u32(target, 0xFFE88008, &fmbsea);
target_write_u32(target, 0xFFE88008, fmbsea | (1 << sector));
-1
View File
@@ -625,7 +625,6 @@ static int xcf_probe(struct flash_bank *bank)
default:
LOG_ERROR("Unknown flash device ID 0x%X", id);
return ERROR_FAIL;
break;
}
bank->sectors = malloc(bank->num_sectors * sizeof(struct flash_sector));
+63 -45
View File
@@ -17,9 +17,12 @@ proc program_error {description exit} {
proc program {filename args} {
set exit 0
set needsflash 1
foreach arg $args {
if {[string equal $arg "verify"]} {
if {[string equal $arg "preverify"]} {
set preverify 1
} elseif {[string equal $arg "verify"]} {
set verify 1
} elseif {[string equal $arg "reset"]} {
set reset 1
@@ -30,6 +33,15 @@ proc program {filename args} {
}
}
# Set variables
set filename \{$filename\}
if {[info exists address]} {
set flash_args "$filename $address"
} else {
set flash_args "$filename"
}
# make sure init is called
if {[catch {init}] != 0} {
program_error "** OpenOCD init failed **" 1
@@ -40,40 +52,46 @@ proc program {filename args} {
program_error "** Unable to reset target **" $exit
}
# Check whether programming is needed
if {[info exists preverify]} {
echo "**pre-verifying**"
if {[catch {eval verify_image $flash_args}] == 0} {
echo "**Verified OK - No flashing**"
set needsflash 0
}
}
# start programming phase
echo "** Programming Started **"
set filename \{$filename\}
if {[info exists address]} {
set flash_args "$filename $address"
} else {
set flash_args "$filename"
if {$needsflash == 1} {
echo "** Programming Started **"
if {[catch {eval flash write_image erase $flash_args}] == 0} {
echo "** Programming Finished **"
if {[info exists verify]} {
# verify phase
echo "** Verify Started **"
if {[catch {eval verify_image $flash_args}] == 0} {
echo "** Verified OK **"
} else {
program_error "** Verify Failed **" $exit
}
}
} else {
program_error "** Programming Failed **" $exit
}
}
if {[catch {eval flash write_image erase $flash_args}] == 0} {
echo "** Programming Finished **"
if {[info exists verify]} {
# verify phase
echo "** Verify Started **"
if {[catch {eval verify_image $flash_args}] == 0} {
echo "** Verified OK **"
} else {
program_error "** Verify Failed **" $exit
}
if {[info exists reset]} {
# reset target if requested
if {$exit == 1} {
# also disable target polling, we are shutting down anyway
poll off
}
if {[info exists reset]} {
# reset target if requested
if {$exit == 1} {
# also disable target polling, we are shutting down anyway
poll off
}
echo "** Resetting Target **"
reset run
}
} else {
program_error "** Programming Failed **" $exit
echo "** Resetting Target **"
reset run
}
if {$exit == 1} {
shutdown
}
@@ -81,25 +99,25 @@ proc program {filename args} {
}
add_help_text program "write an image to flash, address is only required for binary images. verify, reset, exit are optional"
add_usage_text program "<filename> \[address\] \[verify\] \[reset\] \[exit\]"
add_usage_text program "<filename> \[address\] \[pre-verify\] \[verify\] \[reset\] \[exit\]"
# stm32f0x uses the same flash driver as the stm32f1x
# this alias enables the use of either name.
proc stm32f0x args {
eval stm32f1x $args
}
# stm32[f0x|f3x] uses the same flash driver as the stm32f1x
proc stm32f0x args { eval stm32f1x $args }
proc stm32f3x args { eval stm32f1x $args }
# stm32f3x uses the same flash driver as the stm32f1x
# this alias enables the use of either name.
proc stm32f3x args {
eval stm32f1x $args
}
# stm32[f4x|f7x] uses the same flash driver as the stm32f2x
proc stm32f4x args { eval stm32f2x $args }
proc stm32f7x args { eval stm32f2x $args }
# stm32f4x uses the same flash driver as the stm32f2x
# this alias enables the use of either name.
proc stm32f4x args {
eval stm32f2x $args
}
# stm32lx driver supports both STM32 L0 and L1 devices
proc stm32l0x args { eval stm32lx $args }
proc stm32l1x args { eval stm32lx $args }
# stm32[g0|g4|wb|wl] uses the same flash driver as the stm32l4x
proc stm32g0x args { eval stm32l4x $args }
proc stm32g4x args { eval stm32l4x $args }
proc stm32wbx args { eval stm32l4x $args }
proc stm32wlx args { eval stm32l4x $args }
# ease migration to updated flash driver
proc stm32x args {
+2
View File
@@ -33,6 +33,7 @@
* using the bits in @c value. This routine fast-paths writes
* of little-endian, byte-aligned, 32-bit words.
* @param _buffer The buffer whose bits will be set.
* Do not use uninitialized buffer or clang static analyzer emits a warning.
* @param first The bit offset in @c _buffer to start writing (0-31).
* @param num The number of bits from @c value to copy (1-32).
* @param value Up to 32 bits that will be copied to _buffer.
@@ -62,6 +63,7 @@ static inline void buf_set_u32(uint8_t *_buffer,
* using the bits in @c value. This routine fast-paths writes
* of little-endian, byte-aligned, 64-bit words.
* @param _buffer The buffer whose bits will be set.
* Do not use uninitialized buffer or clang static analyzer emits a warning.
* @param first The bit offset in @c _buffer to start writing (0-63).
* @param num The number of bits from @c value to copy (1-64).
* @param value Up to 64 bits that will be copied to _buffer.
+32 -24
View File
@@ -52,6 +52,10 @@ struct log_capture_state {
Jim_Obj *output;
};
static int unregister_command(struct command_context *context,
struct command *parent, const char *name);
static char *command_name(struct command *c, char delim);
static void tcl_output(void *privData, const char *file, unsigned line,
const char *function, const char *string)
{
@@ -126,13 +130,12 @@ extern struct command_context *global_cmd_ctx;
/* dump a single line to the log for the command.
* Do nothing in case we are not at debug level 3 */
void script_debug(Jim_Interp *interp, const char *name,
unsigned argc, Jim_Obj * const *argv)
void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const *argv)
{
if (debug_level < LOG_LVL_DEBUG)
return;
char *dbg = alloc_printf("command - %s", name);
char *dbg = alloc_printf("command -");
for (unsigned i = 0; i < argc; i++) {
int len;
const char *w = Jim_GetString(argv[i], &len);
@@ -213,7 +216,7 @@ static int script_command(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
struct command *c = interp->cmdPrivData;
assert(c);
script_debug(interp, c->name, argc, argv);
script_debug(interp, argc, argv);
return script_command_run(interp, argc, argv, c);
}
@@ -243,11 +246,6 @@ struct command *command_find_in_context(struct command_context *cmd_ctx,
{
return command_find(cmd_ctx->commands, name);
}
struct command *command_find_in_parent(struct command *parent,
const char *name)
{
return command_find(parent->children, name);
}
/**
* Add the command into the linked list, sorted by name.
@@ -333,7 +331,6 @@ static struct command *command_new(struct command_context *cmd_ctx,
c->parent = parent;
c->handler = cr->handler;
c->jim_handler = cr->jim_handler;
c->jim_handler_data = cr->jim_handler_data;
c->mode = cr->mode;
command_add_child(command_list_for_parent(cmd_ctx, parent), c);
@@ -360,7 +357,7 @@ static int register_command_handler(struct command_context *cmd_ctx,
return retval;
}
struct command *register_command(struct command_context *context,
static struct command *register_command(struct command_context *context,
struct command *parent, const struct command_registration *cr)
{
if (!context || !cr->name)
@@ -382,14 +379,14 @@ struct command *register_command(struct command_context *context,
if (NULL == c)
return NULL;
int retval = ERROR_OK;
int retval = JIM_OK;
if (NULL != cr->jim_handler && NULL == parent) {
retval = Jim_CreateCommand(context->interp, cr->name,
cr->jim_handler, cr->jim_handler_data, NULL);
cr->jim_handler, NULL, NULL);
} else if (NULL != cr->handler || NULL != parent)
retval = register_command_handler(context, command_root(c));
if (ERROR_OK != retval) {
if (retval != JIM_OK) {
unregister_command(context, parent, name);
c = NULL;
}
@@ -442,7 +439,7 @@ int unregister_all_commands(struct command_context *context,
return ERROR_OK;
}
int unregister_command(struct command_context *context,
static int unregister_command(struct command_context *context,
struct command *parent, const char *name)
{
if ((!context) || (!name))
@@ -550,7 +547,7 @@ static char *__command_name(struct command *c, char delim, unsigned extra)
return name;
}
char *command_name(struct command *c, char delim)
static char *command_name(struct command *c, char delim)
{
return __command_name(c, delim, 0);
}
@@ -1033,8 +1030,7 @@ static int run_usage(Jim_Interp *interp, int argc_valid, int argc, Jim_Obj * con
static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
const char *cmd_name = Jim_GetString(argv[0], NULL);
script_debug(interp, cmd_name, argc, argv);
script_debug(interp, argc, argv);
struct command_context *cmd_ctx = current_command_context(interp);
struct command *c = cmd_ctx->commands;
@@ -1220,9 +1216,9 @@ static const struct command_registration command_subcommand_handlers[] = {
.mode = COMMAND_ANY,
.jim_handler = jim_command_mode,
.usage = "[command_name ...]",
.help = "Returns the command modes allowed by a command:"
"'any', 'config', or 'exec'. If no command is"
"specified, returns the current command mode. "
.help = "Returns the command modes allowed by a command: "
"'any', 'config', or 'exec'. If no command is "
"specified, returns the current command mode. "
"Returns 'unknown' if an unknown command is given. "
"Command can be multiple tokens.",
},
@@ -1230,6 +1226,21 @@ static const struct command_registration command_subcommand_handlers[] = {
};
static const struct command_registration command_builtin_handlers[] = {
{
.name = "ocd_find",
.mode = COMMAND_ANY,
.jim_handler = jim_find,
.help = "find full path to file",
.usage = "file",
},
{
.name = "capture",
.mode = COMMAND_ANY,
.jim_handler = jim_capture,
.help = "Capture progress output and return as tcl return value. If the "
"progress output was empty, return tcl return value.",
.usage = "command",
},
{
.name = "echo",
.handler = jim_echo,
@@ -1340,9 +1351,6 @@ struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp
Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",
Jim_NewStringObj(interp, HostOs, strlen(HostOs)));
Jim_CreateCommand(interp, "ocd_find", jim_find, NULL, NULL);
Jim_CreateCommand(interp, "capture", jim_capture, NULL, NULL);
register_commands(context, NULL, command_builtin_handlers);
Jim_SetAssocData(interp, "context", NULL, context);
+2 -44
View File
@@ -195,19 +195,9 @@ struct command {
struct command *next;
};
/**
* @param c The command to be named.
* @param delim The character to place between command names.
* @returns A malloc'd string containing the full command name,
* which may include one or more ancestor components. Multiple names
* are separated by single spaces. The caller must free() the string
* when done with it.
*/
char *command_name(struct command *c, char delim);
/*
* Commands should be registered by filling in one or more of these
* structures and passing them to register_command().
* structures and passing them to [un]register_commands().
*
* A conventioal format should be used for help strings, to provide both
* usage and basic information:
@@ -226,7 +216,6 @@ struct command_registration {
const char *name;
command_handler_t handler;
Jim_CmdProc *jim_handler;
void *jim_handler_data;
enum command_mode mode;
const char *help;
/** a string listing the options and arguments, required or optional */
@@ -244,24 +233,6 @@ struct command_registration {
/** Use this as the last entry in an array of command_registration records. */
#define COMMAND_REGISTRATION_DONE { .name = NULL, .chain = NULL }
/**
* Register a command @c handler that can be called from scripts during
* the execution @c mode specified.
*
* If @c parent is non-NULL, the new command will be registered as a
* sub-command under it; otherwise, it will be available as a top-level
* command.
*
* @param cmd_ctx The command_context in which to register the command.
* @param parent Register this command as a child of this, or NULL to
* register a top-level command.
* @param rec A command_registration record that contains the desired
* command parameters.
* @returns The new command, if successful; otherwise, NULL.
*/
struct command *register_command(struct command_context *cmd_ctx,
struct command *parent, const struct command_registration *rec);
/**
* Register one or more commands in the specified context, as children
* of @c parent (or top-level commends, if NULL). In a registration's
@@ -280,16 +251,6 @@ struct command *register_command(struct command_context *cmd_ctx,
int register_commands(struct command_context *cmd_ctx, struct command *parent,
const struct command_registration *cmds);
/**
* Unregisters command @c name from the given context, @c cmd_ctx.
* @param cmd_ctx The context of the registered command.
* @param parent The parent of the given command, or NULL.
* @param name The name of the command to unregister.
* @returns ERROR_OK on success, or an error code.
*/
int unregister_command(struct command_context *cmd_ctx,
struct command *parent, const char *name);
/**
* Unregisters all commands from the specfied context.
* @param cmd_ctx The context that will be cleared of registered commands.
@@ -301,8 +262,6 @@ int unregister_all_commands(struct command_context *cmd_ctx,
struct command *command_find_in_context(struct command_context *cmd_ctx,
const char *name);
struct command *command_find_in_parent(struct command *parent,
const char *name);
/**
* Update the private command data field for a command and all descendents.
@@ -449,7 +408,6 @@ COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label);
#define COMMAND_PARSE_ENABLE(in, out) \
COMMAND_PARSE_BOOL(in, out, "enable", "disable")
void script_debug(Jim_Interp *interp, const char *cmd,
unsigned argc, Jim_Obj * const *argv);
void script_debug(Jim_Interp *interp, unsigned int argc, Jim_Obj * const *argv);
#endif /* OPENOCD_HELPER_COMMAND_H */
+1 -1
View File
@@ -403,7 +403,7 @@ static int ioutil_Jim_Command_mac(Jim_Interp *interp, int argc,
{
if (strcmp("eth0", ifr->ifr_name) != 0)
continue;
strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name) - 1);
if (ioctl(SockFD, SIOCGIFHWADDR, &ifreq) < 0) {
close(SockFD);
return JIM_ERR;
+78 -20
View File
@@ -220,6 +220,15 @@ COMMAND_HANDLER(handle_debug_level_command)
COMMAND_HANDLER(handle_log_output_command)
{
if (CMD_ARGC == 0 || (CMD_ARGC == 1 && strcmp(CMD_ARGV[0], "default") == 0)) {
if (log_output != stderr && log_output != NULL) {
/* Close previous log file, if it was open and wasn't stderr. */
fclose(log_output);
}
log_output = stderr;
LOG_DEBUG("set log_output to default");
return ERROR_OK;
}
if (CMD_ARGC == 1) {
FILE *file = fopen(CMD_ARGV[0], "w");
if (file == NULL) {
@@ -231,9 +240,11 @@ COMMAND_HANDLER(handle_log_output_command)
fclose(log_output);
}
log_output = file;
LOG_DEBUG("set log_output to \"%s\"", CMD_ARGV[0]);
return ERROR_OK;
}
return ERROR_OK;
return ERROR_COMMAND_SYNTAX_ERROR;
}
static const struct command_registration log_command_handlers[] = {
@@ -242,7 +253,7 @@ static const struct command_registration log_command_handlers[] = {
.handler = handle_log_output_command,
.mode = COMMAND_ANY,
.help = "redirect logging to a file (default: stderr)",
.usage = "file_name",
.usage = "[file_name | \"default\"]",
},
{
.name = "debug_level",
@@ -390,25 +401,43 @@ char *alloc_printf(const char *format, ...)
* fast when invoked more often than every 500ms.
*
*/
void keep_alive()
#define KEEP_ALIVE_KICK_TIME_MS 500
#define KEEP_ALIVE_TIMEOUT_MS 1000
static void gdb_timeout_warning(int64_t delta_time)
{
extern int gdb_actual_connections;
if (gdb_actual_connections)
LOG_WARNING("keep_alive() was not invoked in the "
"%d ms timelimit. GDB alive packet not "
"sent! (%" PRId64 " ms). Workaround: increase "
"\"set remotetimeout\" in GDB",
KEEP_ALIVE_TIMEOUT_MS,
delta_time);
else
LOG_DEBUG("keep_alive() was not invoked in the "
"%d ms timelimit (%" PRId64 " ms). This may cause "
"trouble with GDB connections.",
KEEP_ALIVE_TIMEOUT_MS,
delta_time);
}
void keep_alive(void)
{
current_time = timeval_ms();
if (current_time-last_time > 1000) {
extern int gdb_actual_connections;
if (gdb_actual_connections)
LOG_WARNING("keep_alive() was not invoked in the "
"1000ms timelimit. GDB alive packet not "
"sent! (%" PRId64 "). Workaround: increase "
"\"set remotetimeout\" in GDB",
current_time-last_time);
else
LOG_DEBUG("keep_alive() was not invoked in the "
"1000ms timelimit (%" PRId64 "). This may cause "
"trouble with GDB connections.",
current_time-last_time);
int64_t delta_time = current_time - last_time;
if (delta_time > KEEP_ALIVE_TIMEOUT_MS) {
last_time = current_time;
gdb_timeout_warning(delta_time);
}
if (current_time-last_time > 500) {
if (delta_time > KEEP_ALIVE_KICK_TIME_MS) {
last_time = current_time;
/* this will keep the GDB connection alive */
LOG_USER_N("%s", "");
@@ -419,16 +448,20 @@ void keep_alive()
*
* These functions should be invoked at a well defined spot in server.c
*/
last_time = current_time;
}
}
/* reset keep alive timer without sending message */
void kept_alive()
void kept_alive(void)
{
current_time = timeval_ms();
int64_t delta_time = current_time - last_time;
last_time = current_time;
if (delta_time > KEEP_ALIVE_TIMEOUT_MS)
gdb_timeout_warning(delta_time);
}
/* if we sleep for extended periods of time, we must invoke keep_alive() intermittantly */
@@ -454,3 +487,28 @@ void busy_sleep(uint64_t ms)
*/
}
}
/* Maximum size of socket error message retreived from operation system */
#define MAX_SOCKET_ERR_MSG_LENGTH 256
/* Provide log message for the last socket error.
Uses errno on *nix and WSAGetLastError() on Windows */
void log_socket_error(const char *socket_desc)
{
int error_code;
#ifdef _WIN32
error_code = WSAGetLastError();
char error_message[MAX_SOCKET_ERR_MSG_LENGTH];
error_message[0] = '\0';
DWORD retval = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, 0,
error_message, MAX_SOCKET_ERR_MSG_LENGTH, NULL);
error_message[MAX_SOCKET_ERR_MSG_LENGTH - 1] = '\0';
const bool have_message = (retval != 0) && (error_message[0] != '\0');
LOG_ERROR("Error on socket '%s': WSAGetLastError==%d%s%s.", socket_desc, error_code,
(have_message ? ", message: " : ""),
(have_message ? error_message : ""));
#else
error_code = errno;
LOG_ERROR("Error on socket '%s': errno==%d, message: %s.", socket_desc, error_code, strerror(error_code));
#endif
}
+4 -1
View File
@@ -82,6 +82,8 @@ void kept_alive(void);
void alive_sleep(uint64_t ms);
void busy_sleep(uint64_t ms);
void log_socket_error(const char *socket_desc);
typedef void (*log_callback_fn)(void *priv, const char *file, unsigned line,
const char *function, const char *string);
@@ -95,7 +97,8 @@ int log_add_callback(log_callback_fn fn, void *priv);
int log_remove_callback(log_callback_fn fn, void *priv);
char *alloc_vprintf(const char *fmt, va_list ap);
char *alloc_printf(const char *fmt, ...);
char *alloc_printf(const char *fmt, ...)
__attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 1, 2)));
extern int debug_level;
-1
View File
@@ -29,4 +29,3 @@ add_help_text script "filename of OpenOCD script (tcl) to run"
add_usage_text script "<file>"
#########
+12 -22
View File
@@ -126,17 +126,17 @@ static inline uint64_t le_to_h_u64(const uint8_t *buf)
(uint64_t)buf[7] << 56);
}
static inline uint32_t le_to_h_u32(const uint8_t* buf)
static inline uint32_t le_to_h_u32(const uint8_t *buf)
{
return (uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24);
}
static inline uint32_t le_to_h_u24(const uint8_t* buf)
static inline uint32_t le_to_h_u24(const uint8_t *buf)
{
return (uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16);
}
static inline uint16_t le_to_h_u16(const uint8_t* buf)
static inline uint16_t le_to_h_u16(const uint8_t *buf)
{
return (uint16_t)((uint16_t)buf[0] | (uint16_t)buf[1] << 8);
}
@@ -153,17 +153,17 @@ static inline uint64_t be_to_h_u64(const uint8_t *buf)
(uint64_t)buf[0] << 56);
}
static inline uint32_t be_to_h_u32(const uint8_t* buf)
static inline uint32_t be_to_h_u32(const uint8_t *buf)
{
return (uint32_t)((uint32_t)buf[3] | (uint32_t)buf[2] << 8 | (uint32_t)buf[1] << 16 | (uint32_t)buf[0] << 24);
}
static inline uint32_t be_to_h_u24(const uint8_t* buf)
static inline uint32_t be_to_h_u24(const uint8_t *buf)
{
return (uint32_t)((uint32_t)buf[2] | (uint32_t)buf[1] << 8 | (uint32_t)buf[0] << 16);
}
static inline uint16_t be_to_h_u16(const uint8_t* buf)
static inline uint16_t be_to_h_u16(const uint8_t *buf)
{
return (uint16_t)((uint16_t)buf[1] | (uint16_t)buf[0] << 8);
}
@@ -192,7 +192,7 @@ static inline void h_u64_to_be(uint8_t *buf, int64_t val)
buf[7] = (uint8_t) (val >> 0);
}
static inline void h_u32_to_le(uint8_t* buf, int val)
static inline void h_u32_to_le(uint8_t *buf, int val)
{
buf[3] = (uint8_t) (val >> 24);
buf[2] = (uint8_t) (val >> 16);
@@ -200,7 +200,7 @@ static inline void h_u32_to_le(uint8_t* buf, int val)
buf[0] = (uint8_t) (val >> 0);
}
static inline void h_u32_to_be(uint8_t* buf, int val)
static inline void h_u32_to_be(uint8_t *buf, int val)
{
buf[0] = (uint8_t) (val >> 24);
buf[1] = (uint8_t) (val >> 16);
@@ -208,27 +208,27 @@ static inline void h_u32_to_be(uint8_t* buf, int val)
buf[3] = (uint8_t) (val >> 0);
}
static inline void h_u24_to_le(uint8_t* buf, int val)
static inline void h_u24_to_le(uint8_t *buf, int val)
{
buf[2] = (uint8_t) (val >> 16);
buf[1] = (uint8_t) (val >> 8);
buf[0] = (uint8_t) (val >> 0);
}
static inline void h_u24_to_be(uint8_t* buf, int val)
static inline void h_u24_to_be(uint8_t *buf, int val)
{
buf[0] = (uint8_t) (val >> 16);
buf[1] = (uint8_t) (val >> 8);
buf[2] = (uint8_t) (val >> 0);
}
static inline void h_u16_to_le(uint8_t* buf, int val)
static inline void h_u16_to_le(uint8_t *buf, int val)
{
buf[1] = (uint8_t) (val >> 8);
buf[0] = (uint8_t) (val >> 0);
}
static inline void h_u16_to_be(uint8_t* buf, int val)
static inline void h_u16_to_be(uint8_t *buf, int val)
{
buf[0] = (uint8_t) (val >> 8);
buf[1] = (uint8_t) (val >> 0);
@@ -349,7 +349,6 @@ typedef uint64_t uintmax_t;
#endif
#if BUILD_TARGET64
typedef uint64_t target_addr_t;
#define TARGET_ADDR_MAX UINT64_MAX
#define TARGET_PRIdADDR PRId64
@@ -357,15 +356,6 @@ typedef uint64_t target_addr_t;
#define TARGET_PRIoADDR PRIo64
#define TARGET_PRIxADDR PRIx64
#define TARGET_PRIXADDR PRIX64
#else
typedef uint32_t target_addr_t;
#define TARGET_ADDR_MAX UINT32_MAX
#define TARGET_PRIdADDR PRId32
#define TARGET_PRIuADDR PRIu32
#define TARGET_PRIoADDR PRIo32
#define TARGET_PRIxADDR PRIx32
#define TARGET_PRIXADDR PRIX32
#endif
#define TARGET_ADDR_FMT "0x%8.8" TARGET_PRIxADDR
#endif /* OPENOCD_HELPER_TYPES_H */
+2
View File
@@ -56,6 +56,7 @@ endif
%D%/interface.c \
%D%/interfaces.c \
%D%/tcl.c \
%D%/swim.c \
%D%/commands.h \
%D%/driver.h \
%D%/interface.h \
@@ -65,6 +66,7 @@ endif
%D%/minidriver/minidriver_imp.h \
%D%/minidummy/jtag_minidriver.h \
%D%/swd.h \
%D%/swim.h \
%D%/tcl.h \
$(JTAG_SRCS)
+185 -74
View File
@@ -46,7 +46,7 @@
* Holds support for configuring debug adapters from TCl scripts.
*/
extern struct jtag_interface *jtag_interface;
struct adapter_driver *adapter_driver;
const char * const jtag_only[] = { "jtag", NULL };
static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
@@ -61,12 +61,12 @@ static int jim_adapter_name(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
Jim_WrongNumArgs(goi.interp, 1, goi.argv-1, "(no params)");
return JIM_ERR;
}
const char *name = jtag_interface ? jtag_interface->name : NULL;
const char *name = adapter_driver ? adapter_driver->name : NULL;
Jim_SetResultString(goi.interp, name ? : "undefined", -1);
return JIM_OK;
}
COMMAND_HANDLER(interface_transport_command)
COMMAND_HANDLER(adapter_transports_command)
{
char **transports;
int retval;
@@ -85,26 +85,26 @@ COMMAND_HANDLER(interface_transport_command)
return retval;
}
COMMAND_HANDLER(handle_interface_list_command)
COMMAND_HANDLER(handle_adapter_list_command)
{
if (strcmp(CMD_NAME, "interface_list") == 0 && CMD_ARGC > 0)
if (strcmp(CMD_NAME, "list") == 0 && CMD_ARGC > 0)
return ERROR_COMMAND_SYNTAX_ERROR;
command_print(CMD, "The following debug interfaces are available:");
for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) {
const char *name = jtag_interfaces[i]->name;
command_print(CMD, "The following debug adapters are available:");
for (unsigned i = 0; NULL != adapter_drivers[i]; i++) {
const char *name = adapter_drivers[i]->name;
command_print(CMD, "%u: %s", i + 1, name);
}
return ERROR_OK;
}
COMMAND_HANDLER(handle_interface_command)
COMMAND_HANDLER(handle_adapter_driver_command)
{
int retval;
/* check whether the interface is already configured */
if (jtag_interface) {
if (adapter_driver) {
LOG_WARNING("Interface already configured, ignoring");
return ERROR_OK;
}
@@ -113,20 +113,20 @@ COMMAND_HANDLER(handle_interface_command)
if (CMD_ARGC != 1 || CMD_ARGV[0][0] == '\0')
return ERROR_COMMAND_SYNTAX_ERROR;
for (unsigned i = 0; NULL != jtag_interfaces[i]; i++) {
if (strcmp(CMD_ARGV[0], jtag_interfaces[i]->name) != 0)
for (unsigned i = 0; NULL != adapter_drivers[i]; i++) {
if (strcmp(CMD_ARGV[0], adapter_drivers[i]->name) != 0)
continue;
if (NULL != jtag_interfaces[i]->commands) {
if (NULL != adapter_drivers[i]->commands) {
retval = register_commands(CMD_CTX, NULL,
jtag_interfaces[i]->commands);
adapter_drivers[i]->commands);
if (ERROR_OK != retval)
return retval;
}
jtag_interface = jtag_interfaces[i];
adapter_driver = adapter_drivers[i];
return allow_transports(CMD_CTX, jtag_interface->transports);
return allow_transports(CMD_CTX, adapter_driver->transports);
}
/* no valid interface was found (i.e. the configuration option,
@@ -134,7 +134,7 @@ COMMAND_HANDLER(handle_interface_command)
*/
LOG_ERROR("The specified debug interface was not found (%s)",
CMD_ARGV[0]);
CALL_COMMAND_HANDLER(handle_interface_list_command);
CALL_COMMAND_HANDLER(handle_adapter_list_command);
return ERROR_JTAG_INVALID_INTERFACE;
}
@@ -355,7 +355,7 @@ next:
return ERROR_OK;
}
COMMAND_HANDLER(handle_adapter_nsrst_delay_command)
COMMAND_HANDLER(handle_adapter_srst_delay_command)
{
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -365,11 +365,11 @@ COMMAND_HANDLER(handle_adapter_nsrst_delay_command)
jtag_set_nsrst_delay(delay);
}
command_print(CMD, "adapter_nsrst_delay: %u", jtag_get_nsrst_delay());
command_print(CMD, "adapter srst delay: %u", jtag_get_nsrst_delay());
return ERROR_OK;
}
COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command)
COMMAND_HANDLER(handle_adapter_srst_pulse_width_command)
{
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -379,11 +379,11 @@ COMMAND_HANDLER(handle_adapter_nsrst_assert_width_command)
jtag_set_nsrst_assert_width(width);
}
command_print(CMD, "adapter_nsrst_assert_width: %u", jtag_get_nsrst_assert_width());
command_print(CMD, "adapter srst pulse_width: %u", jtag_get_nsrst_assert_width());
return ERROR_OK;
}
COMMAND_HANDLER(handle_adapter_khz_command)
COMMAND_HANDLER(handle_adapter_speed_command)
{
if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -411,6 +411,92 @@ COMMAND_HANDLER(handle_adapter_khz_command)
return retval;
}
COMMAND_HANDLER(handle_adapter_reset_de_assert)
{
enum values {
VALUE_UNDEFINED = -1,
VALUE_DEASSERT = 0,
VALUE_ASSERT = 1,
};
enum values value;
enum values srst = VALUE_UNDEFINED;
enum values trst = VALUE_UNDEFINED;
enum reset_types jtag_reset_config = jtag_get_reset_config();
char *signal;
if (CMD_ARGC == 0) {
if (transport_is_jtag()) {
if (jtag_reset_config & RESET_HAS_TRST)
signal = jtag_get_trst() ? "asserted" : "deasserted";
else
signal = "not present";
command_print(CMD, "trst %s", signal);
}
if (jtag_reset_config & RESET_HAS_SRST)
signal = jtag_get_srst() ? "asserted" : "deasserted";
else
signal = "not present";
command_print(CMD, "srst %s", signal);
return ERROR_OK;
}
if (CMD_ARGC != 1 && CMD_ARGC != 3)
return ERROR_COMMAND_SYNTAX_ERROR;
value = (strcmp(CMD_NAME, "assert") == 0) ? VALUE_ASSERT : VALUE_DEASSERT;
if (strcmp(CMD_ARGV[0], "srst") == 0)
srst = value;
else if (strcmp(CMD_ARGV[0], "trst") == 0)
trst = value;
else
return ERROR_COMMAND_SYNTAX_ERROR;
if (CMD_ARGC == 3) {
if (strcmp(CMD_ARGV[1], "assert") == 0)
value = VALUE_ASSERT;
else if (strcmp(CMD_ARGV[1], "deassert") == 0)
value = VALUE_DEASSERT;
else
return ERROR_COMMAND_SYNTAX_ERROR;
if (strcmp(CMD_ARGV[2], "srst") == 0 && srst == VALUE_UNDEFINED)
srst = value;
else if (strcmp(CMD_ARGV[2], "trst") == 0 && trst == VALUE_UNDEFINED)
trst = value;
else
return ERROR_COMMAND_SYNTAX_ERROR;
}
if (trst == VALUE_UNDEFINED) {
if (transport_is_jtag())
trst = jtag_get_trst() ? VALUE_ASSERT : VALUE_DEASSERT;
else
trst = VALUE_DEASSERT; /* unused, safe value */
}
if (srst == VALUE_UNDEFINED) {
if (jtag_reset_config & RESET_HAS_SRST)
srst = jtag_get_srst() ? VALUE_ASSERT : VALUE_DEASSERT;
else
srst = VALUE_DEASSERT; /* unused, safe value */
}
if (trst == VALUE_ASSERT && !transport_is_jtag()) {
LOG_ERROR("transport has no trst signal");
return ERROR_FAIL;
}
if (srst == VALUE_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
LOG_ERROR("adapter has no srst signal");
return ERROR_FAIL;
}
return adapter_resets((trst == VALUE_DEASSERT) ? TRST_DEASSERT : TRST_ASSERT,
(srst == VALUE_DEASSERT) ? SRST_DEASSERT : SRST_ASSERT);
}
#ifndef HAVE_JTAG_MINIDRIVER_H
#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
COMMAND_HANDLER(handle_usb_location_command)
@@ -438,7 +524,70 @@ static const struct command_registration adapter_usb_command_handlers[] = {
};
#endif /* MINIDRIVER */
static const struct command_registration adapter_srst_command_handlers[] = {
{
.name = "delay",
.handler = handle_adapter_srst_delay_command,
.mode = COMMAND_ANY,
.help = "delay after deasserting SRST in ms",
.usage = "[milliseconds]",
},
{
.name = "pulse_width",
.handler = handle_adapter_srst_pulse_width_command,
.mode = COMMAND_ANY,
.help = "SRST assertion pulse width in ms",
.usage = "[milliseconds]",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration adapter_command_handlers[] = {
{
.name = "driver",
.handler = handle_adapter_driver_command,
.mode = COMMAND_CONFIG,
.help = "Select a debug adapter driver",
.usage = "driver_name",
},
{
.name = "speed",
.handler = handle_adapter_speed_command,
.mode = COMMAND_ANY,
.help = "With an argument, change to the specified maximum "
"jtag speed. For JTAG, 0 KHz signifies adaptive "
"clocking. "
"With or without argument, display current setting.",
.usage = "[khz]",
},
{
.name = "list",
.handler = handle_adapter_list_command,
.mode = COMMAND_ANY,
.help = "List all built-in debug adapter drivers",
.usage = "",
},
{
.name = "name",
.mode = COMMAND_ANY,
.jim_handler = jim_adapter_name,
.help = "Returns the name of the currently "
"selected adapter (driver)",
},
{
.name = "srst",
.mode = COMMAND_ANY,
.help = "srst adapter command group",
.usage = "",
.chain = adapter_srst_command_handlers,
},
{
.name = "transports",
.handler = adapter_transports_command,
.mode = COMMAND_CONFIG,
.help = "Declare transports the adapter supports.",
.usage = "transport ... ",
},
#ifndef HAVE_JTAG_MINIDRIVER_H
{
.name = "usb",
@@ -448,6 +597,20 @@ static const struct command_registration adapter_command_handlers[] = {
.chain = adapter_usb_command_handlers,
},
#endif /* MINIDRIVER */
{
.name = "assert",
.handler = handle_adapter_reset_de_assert,
.mode = COMMAND_EXEC,
.help = "Controls SRST and TRST lines.",
.usage = "|deassert [srst|trst [assert|deassert srst|trst]]",
},
{
.name = "deassert",
.handler = handle_adapter_reset_de_assert,
.mode = COMMAND_EXEC,
.help = "Controls SRST and TRST lines.",
.usage = "|assert [srst|trst [deassert|assert srst|trst]]",
},
COMMAND_REGISTRATION_DONE
};
@@ -459,58 +622,6 @@ static const struct command_registration interface_command_handlers[] = {
.usage = "",
.chain = adapter_command_handlers,
},
{
.name = "adapter_khz",
.handler = handle_adapter_khz_command,
.mode = COMMAND_ANY,
.help = "With an argument, change to the specified maximum "
"jtag speed. For JTAG, 0 KHz signifies adaptive "
" clocking. "
"With or without argument, display current setting.",
.usage = "[khz]",
},
{
.name = "adapter_name",
.mode = COMMAND_ANY,
.jim_handler = jim_adapter_name,
.help = "Returns the name of the currently "
"selected adapter (driver)",
},
{
.name = "adapter_nsrst_delay",
.handler = handle_adapter_nsrst_delay_command,
.mode = COMMAND_ANY,
.help = "delay after deasserting SRST in ms",
.usage = "[milliseconds]",
},
{
.name = "adapter_nsrst_assert_width",
.handler = handle_adapter_nsrst_assert_width_command,
.mode = COMMAND_ANY,
.help = "delay after asserting SRST in ms",
.usage = "[milliseconds]",
},
{
.name = "interface",
.handler = handle_interface_command,
.mode = COMMAND_CONFIG,
.help = "Select a debug adapter interface (driver)",
.usage = "driver_name",
},
{
.name = "interface_transports",
.handler = interface_transport_command,
.mode = COMMAND_CONFIG,
.help = "Declare transports the interface supports.",
.usage = "transport ... ",
},
{
.name = "interface_list",
.handler = handle_interface_list_command,
.mode = COMMAND_ANY,
.help = "List all built-in debug adapter interfaces (drivers)",
.usage = "",
},
{
.name = "reset_config",
.handler = handle_reset_config_command,
+10 -5
View File
@@ -25,7 +25,6 @@
#include <transport/transport.h>
#include <target/target.h>
#include <jtag/aice/aice_transport.h>
#include <jtag/drivers/libusb_common.h>
#include "aice_usb.h"
#define AICE_KHZ_TO_SPEED_MAP_SIZE 16
@@ -518,14 +517,20 @@ static const struct command_registration aice_command_handlers[] = {
/***************************************************************************/
/* End of Command handlers */
struct jtag_interface aice_interface = {
static struct jtag_interface aice_interface = {
.execute_queue = aice_execute_queue,
};
struct adapter_driver aice_adapter_driver = {
.name = "aice",
.commands = aice_command_handlers,
.transports = aice_transports,
.commands = aice_command_handlers,
.init = aice_init,
.quit = aice_quit,
.execute_queue = aice_execute_queue,
.speed = aice_speed, /* set interface speed */
.speed_div = aice_speed_div, /* return readable value */
.khz = aice_khz, /* convert khz to interface speed value */
.speed_div = aice_speed_div, /* return readable value */
.jtag_ops = &aice_interface,
};
+3 -3
View File
@@ -47,6 +47,7 @@ static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
return JIM_ERR;
}
assert(pTap->expected_ids);
memcpy(new_expected_ids, pTap->expected_ids, expected_len);
new_expected_ids[pTap->expected_ids_cnt] = w;
@@ -173,7 +174,7 @@ COMMAND_HANDLER(handle_scan_chain_command)
while (tap) {
uint32_t expected, expected_mask, ii;
snprintf(expected_id, sizeof expected_id, "0x%08x",
snprintf(expected_id, sizeof(expected_id), "0x%08x",
(unsigned)((tap->expected_ids_cnt > 0)
? tap->expected_ids[0]
: 0));
@@ -195,7 +196,7 @@ COMMAND_HANDLER(handle_scan_chain_command)
(unsigned int)(expected_mask));
for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
snprintf(expected_id, sizeof expected_id, "0x%08x",
snprintf(expected_id, sizeof(expected_id), "0x%08x",
(unsigned) tap->expected_ids[ii]);
if (tap->ignore_version)
expected_id[2] = '*';
@@ -442,4 +443,3 @@ static void aice_constructor(void)
{
transport_register(&aice_jtag_transport);
}
+50 -36
View File
@@ -19,7 +19,7 @@
#include "config.h"
#endif
#include <jtag/drivers/libusb_common.h>
#include <jtag/drivers/libusb_helper.h>
#include <helper/log.h>
#include <helper/time_support.h>
#include <target/target.h>
@@ -349,41 +349,53 @@ static void aice_unpack_dthmb(uint8_t *cmd_ack_code, uint8_t *target_id,
/* calls the given usb_bulk_* function, allowing for the data to
* trickle in with some timeouts */
static int usb_bulk_with_retries(
int (*f)(jtag_libusb_device_handle *, int, char *, int, int),
jtag_libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout)
int (*f)(libusb_device_handle *, int, char *, int, int, int *),
libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout, int *transferred)
{
int tries = 3, count = 0;
while (tries && (count < size)) {
int result = f(dev, ep, bytes + count, size - count, timeout);
if (result > 0)
int result, ret;
ret = f(dev, ep, bytes + count, size - count, timeout, &result);
if (ERROR_OK == ret)
count += result;
else if ((-ETIMEDOUT != result) || !--tries)
return result;
else if ((ERROR_TIMEOUT_REACHED != ret) || !--tries)
return ret;
}
return count;
*transferred = count;
return ERROR_OK;
}
static int wrap_usb_bulk_write(jtag_libusb_device_handle *dev, int ep,
char *buff, int size, int timeout)
static int wrap_usb_bulk_write(libusb_device_handle *dev, int ep,
char *buff, int size, int timeout, int *transferred)
{
/* usb_bulk_write() takes const char *buff */
return jtag_libusb_bulk_write(dev, ep, buff, size, timeout);
jtag_libusb_bulk_write(dev, ep, buff, size, timeout, transferred);
return 0;
}
static inline int usb_bulk_write_ex(jtag_libusb_device_handle *dev, int ep,
static inline int usb_bulk_write_ex(libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout)
{
return usb_bulk_with_retries(&wrap_usb_bulk_write,
dev, ep, bytes, size, timeout);
int tr = 0;
usb_bulk_with_retries(&wrap_usb_bulk_write,
dev, ep, bytes, size, timeout, &tr);
return tr;
}
static inline int usb_bulk_read_ex(jtag_libusb_device_handle *dev, int ep,
static inline int usb_bulk_read_ex(struct libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout)
{
return usb_bulk_with_retries(&jtag_libusb_bulk_read,
dev, ep, bytes, size, timeout);
int tr = 0;
usb_bulk_with_retries(&jtag_libusb_bulk_read,
dev, ep, bytes, size, timeout, &tr);
return tr;
}
/* Write data from out_buffer to USB. */
@@ -472,7 +484,9 @@ static int aice_usb_packet_flush(void)
i = 0;
while (1) {
aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
int retval = aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
if (retval != ERROR_OK)
return retval;
if (batch_status & 0x1)
return ERROR_OK;
@@ -1785,8 +1799,8 @@ static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val);
static int check_suppressed_exception(uint32_t coreid, uint32_t dbger_value)
{
uint32_t ir4_value;
uint32_t ir6_value;
uint32_t ir4_value = 0;
uint32_t ir6_value = 0;
/* the default value of handling_suppressed_exception is false */
static bool handling_suppressed_exception;
@@ -1840,7 +1854,7 @@ static int check_privilege(uint32_t coreid, uint32_t dbger_value)
static int aice_check_dbger(uint32_t coreid, uint32_t expect_status)
{
uint32_t i = 0;
uint32_t value_dbger;
uint32_t value_dbger = 0;
while (1) {
aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &value_dbger);
@@ -1961,7 +1975,7 @@ static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
aice_execute_dim(coreid, instructions, 4);
uint32_t value_edmsw;
uint32_t value_edmsw = 0;
aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
if (value_edmsw & NDS_EDMSW_WDV)
aice_read_dtr(coreid, val);
@@ -2006,7 +2020,7 @@ static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
LOG_DEBUG("aice_write_reg, reg_no: 0x%08" PRIx32 ", value: 0x%08" PRIx32, num, val);
uint32_t instructions[4]; /** execute instructions in DIM */
uint32_t value_edmsw;
uint32_t value_edmsw = 0;
aice_write_dtr(coreid, val);
aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
@@ -2095,9 +2109,9 @@ static int aice_usb_open(struct aice_port_param_s *param)
{
const uint16_t vids[] = { param->vid, 0 };
const uint16_t pids[] = { param->pid, 0 };
struct jtag_libusb_device_handle *devh;
struct libusb_device_handle *devh;
if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &devh, NULL) != ERROR_OK)
return ERROR_FAIL;
/* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
@@ -2113,7 +2127,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
#if IS_WIN32 == 0
jtag_libusb_reset_device(devh);
libusb_reset_device(devh);
#if IS_DARWIN == 0
@@ -2121,7 +2135,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
/* reopen jlink after usb_reset
* on win32 this may take a second or two to re-enumerate */
int retval;
while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
while ((retval = jtag_libusb_open(vids, pids, NULL, &devh, NULL)) != ERROR_OK) {
usleep(1000);
timeout--;
if (!timeout)
@@ -2134,8 +2148,8 @@ static int aice_usb_open(struct aice_port_param_s *param)
#endif
/* usb_set_configuration required under win32 */
jtag_libusb_set_configuration(devh, 0);
jtag_libusb_claim_interface(devh, 0);
libusb_set_configuration(devh, 0);
libusb_claim_interface(devh, 0);
unsigned int aice_read_ep;
unsigned int aice_write_ep;
@@ -2435,7 +2449,7 @@ static int aice_backup_tmp_registers(uint32_t coreid)
LOG_DEBUG("backup_tmp_registers -");
/* backup target DTR first(if the target DTR is valid) */
uint32_t value_edmsw;
uint32_t value_edmsw = 0;
aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
core_info[coreid].edmsw_backup = value_edmsw;
if (value_edmsw & 0x1) { /* EDMSW.WDV == 1 */
@@ -2602,13 +2616,13 @@ static int aice_usb_halt(uint32_t coreid)
aice_init_edm_registers(coreid, false);
/** Clear EDM_CTL.DBGIM & EDM_CTL.DBGACKM */
uint32_t edm_ctl_value;
uint32_t edm_ctl_value = 0;
aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
if (edm_ctl_value & 0x3)
aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value & ~(0x3));
uint32_t dbger;
uint32_t acc_ctl_value;
uint32_t dbger = 0;
uint32_t acc_ctl_value = 0;
core_info[coreid].debug_under_dex_on = false;
aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger);
@@ -2649,7 +2663,7 @@ static int aice_usb_halt(uint32_t coreid)
* it is only for debugging 'debug exception handler' purpose.
* after openocd detaches from target, target behavior is
* undefined. */
uint32_t ir0_value;
uint32_t ir0_value = 0;
uint32_t debug_mode_ir0_value;
aice_read_reg(coreid, IR0, &ir0_value);
debug_mode_ir0_value = ir0_value | 0x408; /* turn on DEX, set POM = 1 */
@@ -4017,7 +4031,7 @@ static int aice_usb_profiling(uint32_t coreid, uint32_t interval, uint32_t itera
/* check status */
uint32_t i;
uint32_t batch_status;
uint32_t batch_status = 0;
i = 0;
while (1) {
+1 -1
View File
@@ -93,7 +93,7 @@
struct aice_usb_handler_s {
unsigned int usb_read_ep;
unsigned int usb_write_ep;
struct jtag_libusb_device_handle *usb_handle;
struct libusb_device_handle *usb_handle;
};
struct cache_info {
+14
View File
@@ -31,6 +31,7 @@
#endif
#include <jtag/jtag.h>
#include <transport/transport.h>
#include "commands.h"
struct cmd_queue_page {
@@ -48,6 +49,19 @@ static struct jtag_command **next_command_pointer = &jtag_command_queue;
void jtag_queue_command(struct jtag_command *cmd)
{
if (!transport_is_jtag()) {
/*
* FIXME: This should not happen!
* There could be old code that queues jtag commands with non jtag interfaces so, for
* the moment simply highlight it by log an error.
* We should fix it quitting with assert(0) because it is an internal error, or returning
* an error after call to jtag_command_queue_reset() to free the jtag queue and avoid
* memory leaks.
* The fix can be applied immediately after next release (v0.11.0 ?)
*/
LOG_ERROR("JTAG API jtag_queue_command() called on non JTAG interface");
}
/* this command goes on the end, so ensure the queue terminates */
cmd->next = NULL;
+301 -59
View File
@@ -126,10 +126,10 @@ static int rclk_fallback_speed_khz;
static enum {CLOCK_MODE_UNSELECTED, CLOCK_MODE_KHZ, CLOCK_MODE_RCLK} clock_mode;
static int jtag_speed;
static struct jtag_interface *jtag;
/* FIXME: change name to this variable, it is not anymore JTAG only */
static struct adapter_driver *jtag;
/* configuration */
struct jtag_interface *jtag_interface;
extern struct adapter_driver *adapter_driver;
void jtag_set_flush_queue_sleep(int ms)
{
@@ -503,7 +503,7 @@ int jtag_add_tms_seq(unsigned nbits, const uint8_t *seq, enum tap_state state)
{
int retval;
if (!(jtag->supported & DEBUG_CAP_TMS_SEQ))
if (!(jtag->jtag_ops->supported & DEBUG_CAP_TMS_SEQ))
return ERROR_JTAG_NOT_IMPLEMENTED;
jtag_checks();
@@ -611,53 +611,42 @@ void jtag_add_clocks(int num_cycles)
}
}
void swd_add_reset(int req_srst)
static int adapter_system_reset(int req_srst)
{
int retval;
if (req_srst) {
if (!(jtag_reset_config & RESET_HAS_SRST)) {
LOG_ERROR("BUG: can't assert SRST");
jtag_set_error(ERROR_FAIL);
return;
return ERROR_FAIL;
}
req_srst = 1;
}
/* Maybe change SRST signal state */
if (jtag_srst != req_srst) {
int retval;
retval = interface_jtag_add_reset(0, req_srst);
if (retval != ERROR_OK)
jtag_set_error(retval);
else
retval = jtag_execute_queue();
retval = jtag->reset(0, req_srst);
if (retval != ERROR_OK) {
LOG_ERROR("TRST/SRST error");
return;
LOG_ERROR("SRST error");
return ERROR_FAIL;
}
/* SRST resets everything hooked up to that signal */
jtag_srst = req_srst;
if (jtag_srst) {
if (req_srst) {
LOG_DEBUG("SRST line asserted");
if (adapter_nsrst_assert_width)
jtag_add_sleep(adapter_nsrst_assert_width * 1000);
jtag_sleep(adapter_nsrst_assert_width * 1000);
} else {
LOG_DEBUG("SRST line released");
if (adapter_nsrst_delay)
jtag_add_sleep(adapter_nsrst_delay * 1000);
}
retval = jtag_execute_queue();
if (retval != ERROR_OK) {
LOG_ERROR("SRST timings error");
return;
jtag_sleep(adapter_nsrst_delay * 1000);
}
}
return ERROR_OK;
}
void jtag_add_reset(int req_tlr_or_trst, int req_srst)
static void legacy_jtag_add_reset(int req_tlr_or_trst, int req_srst)
{
int trst_with_tlr = 0;
int new_srst = 0;
@@ -765,6 +754,119 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
}
}
/* FIXME: name is misleading; we do not plan to "add" reset into jtag queue */
void jtag_add_reset(int req_tlr_or_trst, int req_srst)
{
int retval;
int trst_with_tlr = 0;
int new_srst = 0;
int new_trst = 0;
if (!jtag->reset) {
legacy_jtag_add_reset(req_tlr_or_trst, req_srst);
return;
}
/* Without SRST, we must use target-specific JTAG operations
* on each target; callers should not be requesting SRST when
* that signal doesn't exist.
*
* RESET_SRST_PULLS_TRST is a board or chip level quirk, which
* can kick in even if the JTAG adapter can't drive TRST.
*/
if (req_srst) {
if (!(jtag_reset_config & RESET_HAS_SRST)) {
LOG_ERROR("BUG: can't assert SRST");
jtag_set_error(ERROR_FAIL);
return;
}
if ((jtag_reset_config & RESET_SRST_PULLS_TRST) != 0
&& !req_tlr_or_trst) {
LOG_ERROR("BUG: can't assert only SRST");
jtag_set_error(ERROR_FAIL);
return;
}
new_srst = 1;
}
/* JTAG reset (entry to TAP_RESET state) can always be achieved
* using TCK and TMS; that may go through a TAP_{IR,DR}UPDATE
* state first. TRST accelerates it, and bypasses those states.
*
* RESET_TRST_PULLS_SRST is a board or chip level quirk, which
* can kick in even if the JTAG adapter can't drive SRST.
*/
if (req_tlr_or_trst) {
if (!(jtag_reset_config & RESET_HAS_TRST))
trst_with_tlr = 1;
else if ((jtag_reset_config & RESET_TRST_PULLS_SRST) != 0
&& !req_srst)
trst_with_tlr = 1;
else
new_trst = 1;
}
/* Maybe change TRST and/or SRST signal state */
if (jtag_srst != new_srst || jtag_trst != new_trst) {
/* guarantee jtag queue empty before changing reset status */
jtag_execute_queue();
retval = jtag->reset(new_trst, new_srst);
if (retval != ERROR_OK) {
jtag_set_error(retval);
LOG_ERROR("TRST/SRST error");
return;
}
}
/* SRST resets everything hooked up to that signal */
if (jtag_srst != new_srst) {
jtag_srst = new_srst;
if (jtag_srst) {
LOG_DEBUG("SRST line asserted");
if (adapter_nsrst_assert_width)
jtag_add_sleep(adapter_nsrst_assert_width * 1000);
} else {
LOG_DEBUG("SRST line released");
if (adapter_nsrst_delay)
jtag_add_sleep(adapter_nsrst_delay * 1000);
}
}
/* Maybe enter the JTAG TAP_RESET state ...
* - using only TMS, TCK, and the JTAG state machine
* - or else more directly, using TRST
*
* TAP_RESET should be invisible to non-debug parts of the system.
*/
if (trst_with_tlr) {
LOG_DEBUG("JTAG reset with TLR instead of TRST");
jtag_add_tlr();
jtag_execute_queue();
} else if (jtag_trst != new_trst) {
jtag_trst = new_trst;
if (jtag_trst) {
LOG_DEBUG("TRST line asserted");
tap_set_state(TAP_RESET);
if (jtag_ntrst_assert_width)
jtag_add_sleep(jtag_ntrst_assert_width * 1000);
} else {
LOG_DEBUG("TRST line released");
if (jtag_ntrst_delay)
jtag_add_sleep(jtag_ntrst_delay * 1000);
/* We just asserted nTRST, so we're now in TAP_RESET.
* Inform possible listeners about this, now that
* JTAG instructions and data can be shifted. This
* sequence must match jtag_add_tlr().
*/
jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
jtag_notify_event(JTAG_TRST_ASSERTED);
}
}
}
void jtag_add_sleep(uint32_t us)
{
/** @todo Here, keep_alive() appears to be a layering violation!!! */
@@ -836,7 +938,88 @@ int default_interface_jtag_execute_queue(void)
return ERROR_FAIL;
}
return jtag->execute_queue();
if (!transport_is_jtag()) {
/*
* FIXME: This should not happen!
* There could be old code that queues jtag commands with non jtag interfaces so, for
* the moment simply highlight it by log an error and return on empty execute_queue.
* We should fix it quitting with assert(0) because it is an internal error.
* The fix can be applied immediately after next release (v0.11.0 ?)
*/
LOG_ERROR("JTAG API jtag_execute_queue() called on non JTAG interface");
if (!jtag->jtag_ops || !jtag->jtag_ops->execute_queue)
return ERROR_OK;
}
int result = jtag->jtag_ops->execute_queue();
#if !BUILD_ZY1000
/* Only build this if we use a regular driver with a command queue.
* Otherwise jtag_command_queue won't be found at compile/link time. Its
* definition is in jtag/commands.c, which is only built/linked by
* jtag/Makefile.am if MINIDRIVER_DUMMY || !MINIDRIVER, but those variables
* aren't accessible here. */
struct jtag_command *cmd = jtag_command_queue;
while (debug_level >= LOG_LVL_DEBUG && cmd) {
switch (cmd->type) {
case JTAG_SCAN:
LOG_DEBUG_IO("JTAG %s SCAN to %s",
cmd->cmd.scan->ir_scan ? "IR" : "DR",
tap_state_name(cmd->cmd.scan->end_state));
for (int i = 0; i < cmd->cmd.scan->num_fields; i++) {
struct scan_field *field = cmd->cmd.scan->fields + i;
if (field->out_value) {
char *str = buf_to_str(field->out_value, field->num_bits, 16);
LOG_DEBUG_IO(" %db out: %s", field->num_bits, str);
free(str);
}
if (field->in_value) {
char *str = buf_to_str(field->in_value, field->num_bits, 16);
LOG_DEBUG_IO(" %db in: %s", field->num_bits, str);
free(str);
}
}
break;
case JTAG_TLR_RESET:
LOG_DEBUG_IO("JTAG TLR RESET to %s",
tap_state_name(cmd->cmd.statemove->end_state));
break;
case JTAG_RUNTEST:
LOG_DEBUG_IO("JTAG RUNTEST %d cycles to %s",
cmd->cmd.runtest->num_cycles,
tap_state_name(cmd->cmd.runtest->end_state));
break;
case JTAG_RESET:
{
const char *reset_str[3] = {
"leave", "deassert", "assert"
};
LOG_DEBUG_IO("JTAG RESET %s TRST, %s SRST",
reset_str[cmd->cmd.reset->trst + 1],
reset_str[cmd->cmd.reset->srst + 1]);
}
break;
case JTAG_PATHMOVE:
LOG_DEBUG_IO("JTAG PATHMOVE (TODO)");
break;
case JTAG_SLEEP:
LOG_DEBUG_IO("JTAG SLEEP (TODO)");
break;
case JTAG_STABLECLOCKS:
LOG_DEBUG_IO("JTAG STABLECLOCKS (TODO)");
break;
case JTAG_TMS:
LOG_DEBUG_IO("JTAG TMS (TODO)");
break;
default:
LOG_ERROR("Unknown JTAG command: %d", cmd->type);
break;
}
cmd = cmd->next;
}
#endif
return result;
}
void jtag_execute_queue_noclear(void)
@@ -1050,7 +1233,7 @@ static int jtag_examine_chain(void)
/* Add room for end-of-chain marker. */
max_taps++;
uint8_t *idcode_buffer = malloc(max_taps * 4);
uint8_t *idcode_buffer = calloc(4, max_taps);
if (idcode_buffer == NULL)
return ERROR_JTAG_INIT_FAILED;
@@ -1086,7 +1269,7 @@ static int jtag_examine_chain(void)
* REVISIT create a jtag_alloc(chip, tap) routine, and
* share it with jim_newtap_cmd().
*/
tap = calloc(1, sizeof *tap);
tap = calloc(1, sizeof(*tap));
if (!tap) {
retval = ERROR_FAIL;
goto out;
@@ -1107,7 +1290,8 @@ static int jtag_examine_chain(void)
if ((idcode & 1) == 0) {
/* Zero for LSB indicates a device in bypass */
LOG_INFO("TAP %s has invalid IDCODE (0x%x)", tap->dotted_name, idcode);
LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%x)",
tap->dotted_name, idcode);
tap->hasidcode = false;
tap->idcode = 0;
@@ -1222,7 +1406,7 @@ static int jtag_validate_ircapture(void)
&& tap->ir_length < JTAG_IRLEN_MAX) {
tap->ir_length++;
}
LOG_WARNING("AUTO %s - use \"jtag newtap " "%s %s -irlen %d "
LOG_WARNING("AUTO %s - use \"jtag newtap %s %s -irlen %d "
"-expected-id 0x%08" PRIx32 "\"",
tap->dotted_name, tap->chip, tap->tapname, tap->ir_length, tap->idcode);
}
@@ -1335,18 +1519,18 @@ int adapter_init(struct command_context *cmd_ctx)
if (jtag)
return ERROR_OK;
if (!jtag_interface) {
/* nothing was previously specified by "interface" command */
if (!adapter_driver) {
/* nothing was previously specified by "adapter driver" command */
LOG_ERROR("Debug Adapter has to be specified, "
"see \"interface\" command");
"see \"adapter driver\" command");
return ERROR_JTAG_INVALID_INTERFACE;
}
int retval;
retval = jtag_interface->init();
retval = adapter_driver->init();
if (retval != ERROR_OK)
return retval;
jtag = jtag_interface;
jtag = adapter_driver;
if (jtag->speed == NULL) {
LOG_INFO("This adapter doesn't support configurable speed");
@@ -1355,7 +1539,7 @@ int adapter_init(struct command_context *cmd_ctx)
if (CLOCK_MODE_UNSELECTED == clock_mode) {
LOG_ERROR("An adapter speed is not selected in the init script."
" Insert a call to adapter_khz or jtag_rclk to proceed.");
" Insert a call to \"adapter speed\" or \"jtag_rclk\" to proceed.");
return ERROR_JTAG_INIT_FAILED;
}
@@ -1486,17 +1670,19 @@ int adapter_quit(void)
int swd_init_reset(struct command_context *cmd_ctx)
{
int retval = adapter_init(cmd_ctx);
int retval, retval1;
retval = adapter_init(cmd_ctx);
if (retval != ERROR_OK)
return retval;
LOG_DEBUG("Initializing with hard SRST reset");
if (jtag_reset_config & RESET_HAS_SRST)
swd_add_reset(1);
swd_add_reset(0);
retval = jtag_execute_queue();
return retval;
retval = adapter_system_reset(1);
retval1 = adapter_system_reset(0);
return (retval == ERROR_OK) ? retval1 : retval;
}
int jtag_init_reset(struct command_context *cmd_ctx)
@@ -1686,7 +1872,7 @@ void jtag_set_verify(bool enable)
jtag_verify = enable;
}
bool jtag_will_verify()
bool jtag_will_verify(void)
{
return jtag_verify;
}
@@ -1696,7 +1882,7 @@ void jtag_set_verify_capture_ir(bool enable)
jtag_verify_capture_ir = enable;
}
bool jtag_will_verify_capture_ir()
bool jtag_will_verify_capture_ir(void)
{
return jtag_verify_capture_ir;
}
@@ -1819,42 +2005,98 @@ bool transport_is_jtag(void)
return get_current_transport() == &jtag_transport;
}
void adapter_assert_reset(void)
int adapter_resets(int trst, int srst)
{
if (get_current_transport() == NULL) {
LOG_ERROR("transport is not selected");
return ERROR_FAIL;
}
if (transport_is_jtag()) {
if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
LOG_ERROR("adapter has no srst signal");
return ERROR_FAIL;
}
/* adapters without trst signal will eventually use tlr sequence */
jtag_add_reset(trst, srst);
/*
* The jtag queue is still used for reset by some adapter. Flush it!
* FIXME: To be removed when all adapter drivers will be updated!
*/
jtag_execute_queue();
return ERROR_OK;
} else if (transport_is_swd() || transport_is_hla() ||
transport_is_dapdirect_swd() || transport_is_dapdirect_jtag() ||
transport_is_swim()) {
if (trst == TRST_ASSERT) {
LOG_ERROR("transport %s has no trst signal",
get_current_transport()->name);
return ERROR_FAIL;
}
if (srst == SRST_ASSERT && !(jtag_reset_config & RESET_HAS_SRST)) {
LOG_ERROR("adapter has no srst signal");
return ERROR_FAIL;
}
adapter_system_reset(srst);
return ERROR_OK;
}
if (trst == TRST_DEASSERT && srst == SRST_DEASSERT)
return ERROR_OK;
LOG_ERROR("reset is not supported on transport %s",
get_current_transport()->name);
return ERROR_FAIL;
}
int adapter_assert_reset(void)
{
if (transport_is_jtag()) {
if (jtag_reset_config & RESET_SRST_PULLS_TRST)
jtag_add_reset(1, 1);
else
jtag_add_reset(0, 1);
} else if (transport_is_swd())
swd_add_reset(1);
return ERROR_OK;
} else if (transport_is_swd() || transport_is_hla() ||
transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
transport_is_swim())
return adapter_system_reset(1);
else if (get_current_transport() != NULL)
LOG_ERROR("reset is not supported on %s",
get_current_transport()->name);
else
LOG_ERROR("transport is not selected");
return ERROR_FAIL;
}
void adapter_deassert_reset(void)
int adapter_deassert_reset(void)
{
if (transport_is_jtag())
if (transport_is_jtag()) {
jtag_add_reset(0, 0);
else if (transport_is_swd())
swd_add_reset(0);
return ERROR_OK;
} else if (transport_is_swd() || transport_is_hla() ||
transport_is_dapdirect_jtag() || transport_is_dapdirect_swd() ||
transport_is_swim())
return adapter_system_reset(0);
else if (get_current_transport() != NULL)
LOG_ERROR("reset is not supported on %s",
get_current_transport()->name);
else
LOG_ERROR("transport is not selected");
return ERROR_FAIL;
}
int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
uint32_t port_size, unsigned int *trace_freq)
uint32_t port_size, unsigned int *trace_freq,
unsigned int traceclkin_freq, uint16_t *prescaler)
{
if (jtag->config_trace)
return jtag->config_trace(enabled, pin_protocol, port_size,
trace_freq);
else if (enabled) {
if (jtag->config_trace) {
return jtag->config_trace(enabled, pin_protocol, port_size, trace_freq,
traceclkin_freq, prescaler);
} else if (enabled) {
LOG_ERROR("The selected interface does not support tracing");
return ERROR_FAIL;
}
+8 -8
View File
@@ -22,7 +22,7 @@ DRIVERFILES += %D%/driver.c
DRIVERFILES += %D%/jtag_usb_common.c
if USE_LIBUSB1
DRIVERFILES += %D%/libusb1_common.c
DRIVERFILES += %D%/libusb_helper.c
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB1_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS)
endif
@@ -31,9 +31,6 @@ if USE_LIBUSB0
DRIVERFILES += %D%/usb_common.c
%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB0_CFLAGS)
%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB0_LIBS)
if !USE_LIBUSB1
DRIVERFILES += %D%/libusb0_common.c
endif
endif
if USE_LIBFTDI
@@ -136,6 +133,9 @@ if HLADAPTER
DRIVERFILES += %D%/stlink_usb.c
DRIVERFILES += %D%/ti_icdi_usb.c
endif
if RSHIM
DRIVERFILES += %D%/rshim.c
endif
if OSBDM
DRIVERFILES += %D%/osbdm.c
endif
@@ -145,6 +145,9 @@ endif
if SYSFSGPIO
DRIVERFILES += %D%/sysfsgpio.c
endif
if XLNX_PCIE_XVC
DRIVERFILES += %D%/xlnx-pcie-xvc.c
endif
if BCM2835GPIO
DRIVERFILES += %D%/bcm2835gpio.c
endif
@@ -168,9 +171,7 @@ DRIVERHEADERS = \
%D%/bitbang.h \
%D%/bitq.h \
%D%/jtag_usb_common.h \
%D%/libusb0_common.h \
%D%/libusb1_common.h \
%D%/libusb_common.h \
%D%/libusb_helper.h \
%D%/minidriver_imp.h \
%D%/mpsse.h \
%D%/rlink.h \
@@ -183,4 +184,3 @@ DRIVERHEADERS = \
%D%/versaloon/versaloon.h \
%D%/versaloon/versaloon_include.h \
%D%/versaloon/versaloon_internal.h
+8 -3
View File
@@ -393,7 +393,7 @@ int amt_jtagaccel_get_giveio_access(void)
HANDLE h;
OSVERSIONINFO version;
version.dwOSVersionInfoSize = sizeof version;
version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) {
errno = EINVAL;
return -1;
@@ -584,7 +584,11 @@ static const struct command_registration amtjtagaccel_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct jtag_interface amt_jtagaccel_interface = {
static struct jtag_interface amt_jtagaccel_interface = {
.execute_queue = amt_jtagaccel_execute_queue,
};
struct adapter_driver amt_jtagaccel_adapter_driver = {
.name = "amt_jtagaccel",
.transports = jtag_only,
.commands = amtjtagaccel_command_handlers,
@@ -592,5 +596,6 @@ struct jtag_interface amt_jtagaccel_interface = {
.init = amt_jtagaccel_init,
.quit = amt_jtagaccel_quit,
.speed = amt_jtagaccel_speed,
.execute_queue = amt_jtagaccel_execute_queue,
.jtag_ops = &amt_jtagaccel_interface,
};
+22 -16
View File
@@ -107,7 +107,7 @@ static int armjtagew_execute_queue(void)
switch (cmd->type) {
case JTAG_RUNTEST:
LOG_DEBUG_IO("runtest %i cycles, end in %i",
cmd->cmd.runtest->num_cycles, \
cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
armjtagew_end_state(cmd->cmd.runtest->end_state);
@@ -122,8 +122,8 @@ static int armjtagew_execute_queue(void)
break;
case JTAG_PATHMOVE:
LOG_DEBUG_IO("pathmove: %i states, end in %i", \
cmd->cmd.pathmove->num_states, \
LOG_DEBUG_IO("pathmove: %i states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
armjtagew_path_move(cmd->cmd.pathmove->num_states,
@@ -459,10 +459,10 @@ static int armjtagew_get_version_info(void)
auxinfo[256] = '\0';
LOG_INFO(
"ARM-JTAG-EW firmware version %d.%d, hardware revision %c, SN=%s, Additional info: %s", \
"ARM-JTAG-EW firmware version %d.%d, hardware revision %c, SN=%s, Additional info: %s",
usb_in_buffer[1],
usb_in_buffer[0], \
isgraph(usb_in_buffer[2]) ? usb_in_buffer[2] : 'X', \
usb_in_buffer[0],
isgraph(usb_in_buffer[2]) ? usb_in_buffer[2] : 'X',
sn,
auxinfo);
@@ -495,16 +495,22 @@ static const struct command_registration armjtagew_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct jtag_interface armjtagew_interface = {
.name = "arm-jtag-ew",
.commands = armjtagew_command_handlers,
.transports = jtag_only,
static struct jtag_interface armjtagew_interface = {
.execute_queue = armjtagew_execute_queue,
.speed = armjtagew_speed,
.speed_div = armjtagew_speed_div,
.khz = armjtagew_khz,
};
struct adapter_driver armjtagew_adapter_driver = {
.name = "arm-jtag-ew",
.transports = jtag_only,
.commands = armjtagew_command_handlers,
.init = armjtagew_init,
.quit = armjtagew_quit,
.speed = armjtagew_speed,
.khz = armjtagew_khz,
.speed_div = armjtagew_speed_div,
.jtag_ops = &armjtagew_interface,
};
/**************************************************************************
@@ -677,7 +683,7 @@ static int armjtagew_tap_execute(void)
/****************************************************************************
* JLink USB low-level functions */
static struct armjtagew *armjtagew_usb_open()
static struct armjtagew *armjtagew_usb_open(void)
{
usb_init();
@@ -744,7 +750,7 @@ static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
return -1;
}
result = usb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT, \
result = usb_bulk_write(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_OUT,
(char *)usb_out_buffer, out_length, ARMJTAGEW_USB_TIMEOUT);
LOG_DEBUG_IO("armjtagew_usb_write, out_length = %d, result = %d", out_length, result);
@@ -758,7 +764,7 @@ static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
/* Read data from USB into in_buffer. */
static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length)
{
int result = usb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN, \
int result = usb_bulk_read(armjtagew->usb_handle, ARMJTAGEW_EPT_BULK_IN,
(char *)usb_in_buffer, exp_in_length, ARMJTAGEW_USB_TIMEOUT);
LOG_DEBUG_IO("armjtagew_usb_read, result = %d", result);
+9 -4
View File
@@ -111,7 +111,6 @@ static uint32_t *pio_base;
*/
static bb_value_t at91rm9200_read(void);
static int at91rm9200_write(int tck, int tms, int tdi);
static int at91rm9200_reset(int trst, int srst);
static int at91rm9200_init(void);
static int at91rm9200_quit(void);
@@ -119,7 +118,6 @@ static int at91rm9200_quit(void);
static struct bitbang_interface at91rm9200_bitbang = {
.read = at91rm9200_read,
.write = at91rm9200_write,
.reset = at91rm9200_reset,
.blink = 0
};
@@ -189,13 +187,20 @@ static const struct command_registration at91rm9200_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct jtag_interface at91rm9200_interface = {
.name = "at91rm9200",
static struct jtag_interface at91rm9200_interface = {
.execute_queue = bitbang_execute_queue,
};
struct adapter_driver at91rm9200_adapter_driver = {
.name = "at91rm9200",
.transports = jtag_only,
.commands = at91rm9200_command_handlers,
.init = at91rm9200_init,
.quit = at91rm9200_quit,
.reset = at91rm9200_reset,
.jtag_ops = &at91rm9200_interface,
};
static int at91rm9200_init(void)
+18 -9
View File
@@ -51,7 +51,6 @@ static volatile uint32_t *pio_base;
static bb_value_t bcm2835gpio_read(void);
static int bcm2835gpio_write(int tck, int tms, int tdi);
static int bcm2835gpio_reset(int trst, int srst);
static int bcm2835_swdio_read(void);
static void bcm2835_swdio_drive(bool is_output);
@@ -62,7 +61,6 @@ static int bcm2835gpio_quit(void);
static struct bitbang_interface bcm2835gpio_bitbang = {
.read = bcm2835gpio_read,
.write = bcm2835gpio_write,
.reset = bcm2835gpio_reset,
.swdio_read = bcm2835_swdio_read,
.swdio_drive = bcm2835_swdio_drive,
.blink = NULL
@@ -407,18 +405,25 @@ static const struct command_registration bcm2835gpio_command_handlers[] = {
static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
struct jtag_interface bcm2835gpio_interface = {
.name = "bcm2835gpio",
static struct jtag_interface bcm2835gpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
};
struct adapter_driver bcm2835gpio_adapter_driver = {
.name = "bcm2835gpio",
.transports = bcm2835_transports,
.swd = &bitbang_swd,
.commands = bcm2835gpio_command_handlers,
.init = bcm2835gpio_init,
.quit = bcm2835gpio_quit,
.reset = bcm2835gpio_reset,
.speed = bcm2835gpio_speed,
.khz = bcm2835gpio_khz,
.speed_div = bcm2835gpio_speed_div,
.commands = bcm2835gpio_command_handlers,
.init = bcm2835gpio_init,
.quit = bcm2835gpio_quit,
.jtag_ops = &bcm2835gpio_interface,
.swd_ops = &bitbang_swd,
};
static bool bcm2835gpio_jtag_mode_possible(void)
@@ -461,7 +466,11 @@ static int bcm2835gpio_init(void)
return ERROR_JTAG_INIT_FAILED;
}
dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
if (dev_mem_fd < 0) {
LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
}
if (dev_mem_fd < 0) {
perror("open");
return ERROR_JTAG_INIT_FAILED;
-11
View File
@@ -314,17 +314,6 @@ int bitbang_execute_queue(void)
while (cmd) {
switch (cmd->type) {
case JTAG_RESET:
LOG_DEBUG_IO("reset trst: %i srst %i",
cmd->cmd.reset->trst,
cmd->cmd.reset->srst);
if ((cmd->cmd.reset->trst == 1) ||
(cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
tap_set_state(TAP_RESET);
if (bitbang_interface->reset(cmd->cmd.reset->trst,
cmd->cmd.reset->srst) != ERROR_OK)
return ERROR_FAIL;
break;
case JTAG_RUNTEST:
LOG_DEBUG_IO("runtest %i cycles, end in %s",
cmd->cmd.runtest->num_cycles,
+1 -2
View File
@@ -51,13 +51,12 @@ struct bitbang_interface {
/** Set TCK, TMS, and TDI to the given values. */
int (*write)(int tck, int tms, int tdi);
int (*reset)(int trst, int srst);
int (*blink)(int on);
int (*swdio_read)(void);
void (*swdio_drive)(bool on);
};
const struct swd_driver bitbang_swd;
extern const struct swd_driver bitbang_swd;
extern bool swd_mode;
+16 -19
View File
@@ -34,6 +34,7 @@
static int buspirate_execute_queue(void);
static int buspirate_init(void);
static int buspirate_quit(void);
static int buspirate_reset(int trst, int srst);
static void buspirate_end_state(tap_state_t state);
static void buspirate_state_move(void);
@@ -133,7 +134,6 @@ static void buspirate_tap_append_scan(int length, uint8_t *buffer,
struct scan_command *command);
static void buspirate_tap_make_space(int scan, int bits);
static void buspirate_reset(int trst, int srst);
static void buspirate_set_feature(int, char, char);
static void buspirate_set_mode(int, char);
static void buspirate_set_speed(int, char);
@@ -213,18 +213,6 @@ static int buspirate_execute_queue(void)
buffer, scan_size, cmd->cmd.scan);
break;
case JTAG_RESET:
LOG_DEBUG_IO("reset trst: %i srst %i",
cmd->cmd.reset->trst, cmd->cmd.reset->srst);
/* flush buffers, so we can reset */
buspirate_tap_execute();
if (cmd->cmd.reset->trst == 1)
tap_set_state(TAP_RESET);
buspirate_reset(cmd->cmd.reset->trst,
cmd->cmd.reset->srst);
break;
case JTAG_SLEEP:
LOG_DEBUG_IO("sleep %i", cmd->cmd.sleep->us);
buspirate_tap_execute();
@@ -548,14 +536,21 @@ static const struct swd_driver buspirate_swd = {
static const char * const buspirate_transports[] = { "jtag", "swd", NULL };
struct jtag_interface buspirate_interface = {
.name = "buspirate",
static struct jtag_interface buspirate_interface = {
.execute_queue = buspirate_execute_queue,
.commands = buspirate_command_handlers,
};
struct adapter_driver buspirate_adapter_driver = {
.name = "buspirate",
.transports = buspirate_transports,
.swd = &buspirate_swd,
.commands = buspirate_command_handlers,
.init = buspirate_init,
.quit = buspirate_quit
.quit = buspirate_quit,
.reset = buspirate_reset,
.jtag_ops = &buspirate_interface,
.swd_ops = &buspirate_swd,
};
/*************** jtag execute commands **********************/
@@ -860,7 +855,7 @@ static void buspirate_tap_append_scan(int length, uint8_t *buffer,
/*************** wrapper functions *********************/
/* (1) assert or (0) deassert reset lines */
static void buspirate_reset(int trst, int srst)
static int buspirate_reset(int trst, int srst)
{
LOG_DEBUG("trst: %i, srst: %i", trst, srst);
@@ -873,6 +868,8 @@ static void buspirate_reset(int trst, int srst)
buspirate_set_feature(buspirate_fd, FEATURE_SRST, ACTION_DISABLE);
else
buspirate_set_feature(buspirate_fd, FEATURE_SRST, ACTION_ENABLE);
return ERROR_OK;
}
static void buspirate_set_feature(int fd, char feat, char action)
+32 -28
View File
@@ -364,8 +364,6 @@ static void cmsis_dap_usb_close(struct cmsis_dap *dap)
free(pending_fifo[i].transfers);
pending_fifo[i].transfers = NULL;
}
return;
}
static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen)
@@ -509,15 +507,15 @@ static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data)
return ERROR_OK;
}
static int cmsis_dap_cmd_DAP_LED(uint8_t leds)
static int cmsis_dap_cmd_DAP_LED(uint8_t led, uint8_t state)
{
int retval;
uint8_t *buffer = cmsis_dap_handle->packet_buffer;
buffer[0] = 0; /* report number */
buffer[1] = CMD_DAP_LED;
buffer[2] = 0x00;
buffer[3] = leds;
buffer[2] = led;
buffer[3] = state;
retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4);
if (retval != ERROR_OK || buffer[1] != 0x00) {
@@ -1086,8 +1084,12 @@ static int cmsis_dap_init(void)
if (retval != ERROR_OK)
return ERROR_FAIL;
}
/* Both LEDs on */
retval = cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_ON);
if (retval != ERROR_OK)
return ERROR_FAIL;
retval = cmsis_dap_cmd_DAP_LED(0x03); /* Both LEDs on */
retval = cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_ON);
if (retval != ERROR_OK)
return ERROR_FAIL;
@@ -1102,9 +1104,6 @@ static int cmsis_dap_init(void)
LOG_INFO("Connecting under reset");
}
}
cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */
LOG_INFO("CMSIS-DAP: Interface ready");
return ERROR_OK;
@@ -1119,28 +1118,31 @@ static int cmsis_dap_swd_init(void)
static int cmsis_dap_quit(void)
{
cmsis_dap_cmd_DAP_Disconnect();
cmsis_dap_cmd_DAP_LED(0x00); /* Both LEDs off */
/* Both LEDs off */
cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_OFF);
cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_OFF);
cmsis_dap_usb_close(cmsis_dap_handle);
return ERROR_OK;
}
static void cmsis_dap_execute_reset(struct jtag_command *cmd)
static int cmsis_dap_reset(int trst, int srst)
{
/* Set both TRST and SRST even if they're not enabled as
* there's no way to tristate them */
output_pins = 0;
if (!cmd->cmd.reset->srst)
if (!srst)
output_pins |= SWJ_PIN_SRST;
if (!cmd->cmd.reset->trst)
if (!trst)
output_pins |= SWJ_PIN_TRST;
int retval = cmsis_dap_cmd_DAP_SWJ_Pins(output_pins,
SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL);
if (retval != ERROR_OK)
LOG_ERROR("CMSIS-DAP: Interface reset failed");
return retval;
}
static void cmsis_dap_execute_sleep(struct jtag_command *cmd)
@@ -1581,10 +1583,6 @@ static void cmsis_dap_execute_tms(struct jtag_command *cmd)
static void cmsis_dap_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
case JTAG_RESET:
cmsis_dap_flush();
cmsis_dap_execute_reset(cmd);
break;
case JTAG_SLEEP:
cmsis_dap_flush();
cmsis_dap_execute_sleep(cmd);
@@ -1631,10 +1629,10 @@ static int cmsis_dap_execute_queue(void)
static int cmsis_dap_speed(int speed)
{
if (speed > DAP_MAX_CLOCK)
LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed);
LOG_INFO("High speed (adapter speed %d) may be limited by adapter firmware.", speed);
if (speed == 0) {
LOG_ERROR("RTCK not supported. Set nonzero adapter_khz.");
LOG_ERROR("RTCK not supported. Set nonzero \"adapter speed\".");
return ERROR_JTAG_NOT_IMPLEMENTED;
}
@@ -1789,17 +1787,23 @@ static const struct swd_driver cmsis_dap_swd_driver = {
static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL };
struct jtag_interface cmsis_dap_interface = {
.name = "cmsis-dap",
static struct jtag_interface cmsis_dap_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.commands = cmsis_dap_command_handlers,
.swd = &cmsis_dap_swd_driver,
.transports = cmsis_dap_transport,
.execute_queue = cmsis_dap_execute_queue,
.speed = cmsis_dap_speed,
.speed_div = cmsis_dap_speed_div,
.khz = cmsis_dap_khz,
};
struct adapter_driver cmsis_dap_adapter_driver = {
.name = "cmsis-dap",
.transports = cmsis_dap_transport,
.commands = cmsis_dap_command_handlers,
.init = cmsis_dap_init,
.quit = cmsis_dap_quit,
.reset = cmsis_dap_reset,
.speed = cmsis_dap_speed,
.khz = cmsis_dap_khz,
.speed_div = cmsis_dap_speed_div,
.jtag_ops = &cmsis_dap_interface,
.swd_ops = &cmsis_dap_swd_driver,
};
+16 -14
View File
@@ -91,7 +91,6 @@ static int dummy_led(int on)
static struct bitbang_interface dummy_bitbang = {
.read = &dummy_read,
.write = &dummy_write,
.reset = &dummy_reset,
.blink = &dummy_led,
};
@@ -145,19 +144,22 @@ static const struct command_registration dummy_command_handlers[] = {
/* The dummy driver is used to easily check the code path
* where the target is unresponsive.
*/
struct jtag_interface dummy_interface = {
.name = "dummy",
static struct jtag_interface dummy_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = &bitbang_execute_queue,
};
.supported = DEBUG_CAP_TMS_SEQ,
.commands = dummy_command_handlers,
.transports = jtag_only,
struct adapter_driver dummy_adapter_driver = {
.name = "dummy",
.transports = jtag_only,
.commands = dummy_command_handlers,
.execute_queue = &bitbang_execute_queue,
.init = &dummy_init,
.quit = &dummy_quit,
.reset = &dummy_reset,
.speed = &dummy_speed,
.khz = &dummy_khz,
.speed_div = &dummy_speed_div,
.speed = &dummy_speed,
.khz = &dummy_khz,
.speed_div = &dummy_speed_div,
.init = &dummy_init,
.quit = &dummy_quit,
};
.jtag_ops = &dummy_interface,
};
+8 -4
View File
@@ -50,21 +50,25 @@ static int ep93xx_quit(void);
struct timespec ep93xx_zzzz;
struct jtag_interface ep93xx_interface = {
.name = "ep93xx",
static struct jtag_interface ep93xx_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
};
struct adapter_driver ep93xx_adapter_driver = {
.name = "ep93xx",
.transports = jtag_only,
.init = ep93xx_init,
.quit = ep93xx_quit,
.reset = ep93xx_reset,
.jtag_ops = &ep93xx_interface,
};
static struct bitbang_interface ep93xx_bitbang = {
.read = ep93xx_read,
.write = ep93xx_write,
.reset = ep93xx_reset,
.blink = 0,
};
+23 -21
View File
@@ -29,7 +29,7 @@
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <helper/time_support.h>
#include "libusb1_common.h"
#include "libusb_helper.h"
/* system includes */
#include <string.h>
@@ -71,7 +71,7 @@
static char *ft232r_serial_desc;
static uint16_t ft232r_vid = 0x0403; /* FTDI */
static uint16_t ft232r_pid = 0x6001; /* FT232R */
static jtag_libusb_device_handle *adapter;
static struct libusb_device_handle *adapter;
static uint8_t *ft232r_output;
static size_t ft232r_output_len;
@@ -132,11 +132,11 @@ static int ft232r_send_recv(void)
bytes_to_write = rxfifo_free;
if (bytes_to_write) {
int n = jtag_libusb_bulk_write(adapter, IN_EP,
(char *) ft232r_output + total_written,
bytes_to_write, 1000);
int n;
if (n == 0) {
if (jtag_libusb_bulk_write(adapter, IN_EP,
(char *) ft232r_output + total_written,
bytes_to_write, 1000, &n) != ERROR_OK) {
LOG_ERROR("usb bulk write failed");
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -147,12 +147,10 @@ static int ft232r_send_recv(void)
/* Read */
uint8_t reply[64];
int n;
int n = jtag_libusb_bulk_read(adapter, OUT_EP,
(char *) reply,
sizeof(reply), 1000);
if (n == 0) {
if (jtag_libusb_bulk_read(adapter, OUT_EP, (char *) reply,
sizeof(reply), 1000, &n) != ERROR_OK) {
LOG_ERROR("usb bulk read failed");
return ERROR_JTAG_DEVICE_ERROR;
}
@@ -259,7 +257,7 @@ static int ft232r_init(void)
{
uint16_t avids[] = {ft232r_vid, 0};
uint16_t apids[] = {ft232r_pid, 0};
if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter)) {
if (jtag_libusb_open(avids, apids, ft232r_serial_desc, &adapter, NULL)) {
LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n",
ft232r_vid, ft232r_pid, (ft232r_serial_desc == NULL) ? "[any]" : ft232r_serial_desc);
return ERROR_JTAG_INIT_FAILED;
@@ -270,7 +268,7 @@ static int ft232r_init(void)
else /* serial port will be restored after jtag: */
libusb_set_auto_detach_kernel_driver(adapter, 1); /* 1: DONT_DETACH_SIO_MODULE */
if (jtag_libusb_claim_interface(adapter, 0)) {
if (libusb_claim_interface(adapter, 0)) {
LOG_ERROR("unable to claim interface");
return ERROR_JTAG_INIT_FAILED;
}
@@ -332,7 +330,7 @@ static int ft232r_quit(void)
}
}
if (jtag_libusb_release_interface(adapter, 0) != 0)
if (libusb_release_interface(adapter, 0) != 0)
LOG_ERROR("usb release interface failed");
jtag_libusb_close(adapter);
@@ -914,17 +912,21 @@ static int syncbb_execute_queue(void)
return retval;
}
struct jtag_interface ft232r_interface = {
.name = "ft232r",
.commands = ft232r_command_handlers,
.transports = jtag_only,
static struct jtag_interface ft232r_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = syncbb_execute_queue,
};
struct adapter_driver ft232r_adapter_driver = {
.name = "ft232r",
.transports = jtag_only,
.commands = ft232r_command_handlers,
.speed = ft232r_speed,
.init = ft232r_init,
.quit = ft232r_quit,
.speed_div = ft232r_speed_div,
.speed = ft232r_speed,
.khz = ft232r_khz,
.speed_div = ft232r_speed_div,
.jtag_ops = &ft232r_interface,
};
+37 -32
View File
@@ -249,7 +249,7 @@ static int ftdi_set_signal(const struct signal *s, char value)
return ERROR_OK;
}
static int ftdi_get_signal(const struct signal *s, uint16_t * value_out)
static int ftdi_get_signal(const struct signal *s, uint16_t *value_out)
{
uint8_t data_low = 0;
uint8_t data_high = 0;
@@ -582,46 +582,40 @@ static void ftdi_execute_scan(struct jtag_command *cmd)
tap_state_name(tap_get_end_state()));
}
static void ftdi_execute_reset(struct jtag_command *cmd)
static int ftdi_reset(int trst, int srst)
{
LOG_DEBUG_IO("reset trst: %i srst %i",
cmd->cmd.reset->trst, cmd->cmd.reset->srst);
struct signal *sig_ntrst = find_signal_by_name("nTRST");
struct signal *sig_nsrst = find_signal_by_name("nSRST");
if (cmd->cmd.reset->trst == 1
|| (cmd->cmd.reset->srst
&& (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
tap_set_state(TAP_RESET);
LOG_DEBUG_IO("reset trst: %i srst %i", trst, srst);
struct signal *trst = find_signal_by_name("nTRST");
if (cmd->cmd.reset->trst == 1) {
if (trst)
ftdi_set_signal(trst, '0');
if (trst == 1) {
if (sig_ntrst)
ftdi_set_signal(sig_ntrst, '0');
else
LOG_ERROR("Can't assert TRST: nTRST signal is not defined");
} else if (trst && jtag_get_reset_config() & RESET_HAS_TRST &&
cmd->cmd.reset->trst == 0) {
} else if (sig_ntrst && jtag_get_reset_config() & RESET_HAS_TRST &&
trst == 0) {
if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN)
ftdi_set_signal(trst, 'z');
ftdi_set_signal(sig_ntrst, 'z');
else
ftdi_set_signal(trst, '1');
ftdi_set_signal(sig_ntrst, '1');
}
struct signal *srst = find_signal_by_name("nSRST");
if (cmd->cmd.reset->srst == 1) {
if (srst)
ftdi_set_signal(srst, '0');
if (srst == 1) {
if (sig_nsrst)
ftdi_set_signal(sig_nsrst, '0');
else
LOG_ERROR("Can't assert SRST: nSRST signal is not defined");
} else if (srst && jtag_get_reset_config() & RESET_HAS_SRST &&
cmd->cmd.reset->srst == 0) {
} else if (sig_nsrst && jtag_get_reset_config() & RESET_HAS_SRST &&
srst == 0) {
if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL)
ftdi_set_signal(srst, '1');
ftdi_set_signal(sig_nsrst, '1');
else
ftdi_set_signal(srst, 'z');
ftdi_set_signal(sig_nsrst, 'z');
}
LOG_DEBUG_IO("trst: %i, srst: %i",
cmd->cmd.reset->trst, cmd->cmd.reset->srst);
return mpsse_flush(mpsse_ctx);
}
static void ftdi_execute_sleep(struct jtag_command *cmd)
@@ -727,6 +721,11 @@ static int ftdi_initialize(void)
else
LOG_DEBUG("ftdi interface using shortest path jtag state transitions");
if (!ftdi_vid[0] && !ftdi_pid[0]) {
LOG_ERROR("Please specify ftdi_vid_pid");
return ERROR_JTAG_INIT_FAILED;
}
for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) {
mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc,
ftdi_serial, jtag_usb_get_location(), ftdi_channel);
@@ -1592,17 +1591,23 @@ static const struct swd_driver ftdi_swd = {
static const char * const ftdi_transports[] = { "jtag", "swd", NULL };
struct jtag_interface ftdi_interface = {
.name = "ftdi",
static struct jtag_interface ftdi_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.commands = ftdi_command_handlers,
.execute_queue = ftdi_execute_queue,
};
struct adapter_driver ftdi_adapter_driver = {
.name = "ftdi",
.transports = ftdi_transports,
.swd = &ftdi_swd,
.commands = ftdi_command_handlers,
.init = ftdi_initialize,
.quit = ftdi_quit,
.reset = ftdi_reset,
.speed = ftdi_speed,
.speed_div = ftdi_speed_div,
.khz = ftdi_khz,
.execute_queue = ftdi_execute_queue,
.speed_div = ftdi_speed_div,
.jtag_ops = &ftdi_interface,
.swd_ops = &ftdi_swd,
};
+9 -4
View File
@@ -350,7 +350,7 @@ static int gw16012_get_giveio_access(void)
HANDLE h;
OSVERSIONINFO version;
version.dwOSVersionInfoSize = sizeof version;
version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) {
errno = EINVAL;
return -1;
@@ -448,7 +448,7 @@ static int gw16012_init_device(void)
LOG_WARNING("No gw16012 port specified, using default '0x378' (LPT1)");
}
LOG_DEBUG("requesting privileges for parallel port 0x%lx...", (long unsigned)(gw16012_port));
LOG_DEBUG("requesting privileges for parallel port 0x%" PRIx16 "...", gw16012_port);
#if PARPORT_USE_GIVEIO == 1
if (gw16012_get_giveio_access() != 0) {
#else /* PARPORT_USE_GIVEIO */
@@ -521,12 +521,17 @@ static const struct command_registration gw16012_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct jtag_interface gw16012_interface = {
static struct jtag_interface gw16012_interface = {
.execute_queue = gw16012_execute_queue,
};
struct adapter_driver gw16012_adapter_driver = {
.name = "gw16012",
.transports = jtag_only,
.commands = gw16012_command_handlers,
.init = gw16012_init,
.quit = gw16012_quit,
.execute_queue = gw16012_execute_queue,
.jtag_ops = &gw16012_interface,
};
+13 -8
View File
@@ -84,7 +84,6 @@ static inline bool gpio_level(int g)
static bb_value_t imx_gpio_read(void);
static int imx_gpio_write(int tck, int tms, int tdi);
static int imx_gpio_reset(int trst, int srst);
static int imx_gpio_swdio_read(void);
static void imx_gpio_swdio_drive(bool is_output);
@@ -95,7 +94,6 @@ static int imx_gpio_quit(void);
static struct bitbang_interface imx_gpio_bitbang = {
.read = imx_gpio_read,
.write = imx_gpio_write,
.reset = imx_gpio_reset,
.swdio_read = imx_gpio_swdio_read,
.swdio_drive = imx_gpio_swdio_drive,
.blink = NULL
@@ -429,18 +427,25 @@ static const struct command_registration imx_gpio_command_handlers[] = {
static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL };
struct jtag_interface imx_gpio_interface = {
.name = "imx_gpio",
static struct jtag_interface imx_gpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
};
struct adapter_driver imx_gpio_adapter_driver = {
.name = "imx_gpio",
.transports = imx_gpio_transports,
.swd = &bitbang_swd,
.commands = imx_gpio_command_handlers,
.init = imx_gpio_init,
.quit = imx_gpio_quit,
.reset = imx_gpio_reset,
.speed = imx_gpio_speed,
.khz = imx_gpio_khz,
.speed_div = imx_gpio_speed_div,
.commands = imx_gpio_command_handlers,
.init = imx_gpio_init,
.quit = imx_gpio_quit,
.jtag_ops = &imx_gpio_interface,
.swd_ops = &bitbang_swd,
};
static bool imx_gpio_jtag_mode_possible(void)
+117 -52
View File
@@ -39,6 +39,7 @@
#include <jtag/swd.h>
#include <jtag/commands.h>
#include <jtag/drivers/jtag_usb_common.h>
#include <target/cortex_m.h>
#include <libjaylink/libjaylink.h>
@@ -62,6 +63,9 @@ static bool trace_enabled;
static unsigned int swd_buffer_size = JLINK_TAP_BUFFER_SIZE;
/* Maximum SWO frequency deviation. */
#define SWO_MAX_FREQ_DEV 0.03
/* 256 byte non-volatile memory */
struct device_config {
uint8_t usb_address;
@@ -90,6 +94,7 @@ static void jlink_path_move(int num_states, tap_state_t *path);
static void jlink_stableclocks(int num_cycles);
static void jlink_runtest(int num_cycles);
static void jlink_reset(int trst, int srst);
static int jlink_reset_safe(int trst, int srst);
static int jlink_swd_run_queue(void);
static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk);
static int jlink_swd_switch_seq(enum swd_special_seq seq);
@@ -247,16 +252,6 @@ static void jlink_execute_scan(struct jtag_command *cmd)
tap_state_name(tap_get_end_state()));
}
static void jlink_execute_reset(struct jtag_command *cmd)
{
LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst,
cmd->cmd.reset->srst);
jlink_flush();
jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
jlink_flush();
}
static void jlink_execute_sleep(struct jtag_command *cmd)
{
LOG_DEBUG_IO("sleep %" PRIi32 "", cmd->cmd.sleep->us);
@@ -282,9 +277,6 @@ static int jlink_execute_command(struct jtag_command *cmd)
case JTAG_SCAN:
jlink_execute_scan(cmd);
break;
case JTAG_RESET:
jlink_execute_reset(cmd);
break;
case JTAG_SLEEP:
jlink_execute_sleep(cmd);
break;
@@ -952,6 +944,13 @@ static void jlink_reset(int trst, int srst)
jaylink_jtag_set_trst(devh);
}
static int jlink_reset_safe(int trst, int srst)
{
jlink_flush();
jlink_reset(trst, srst);
return jlink_flush();
}
COMMAND_HANDLER(jlink_usb_command)
{
int tmp;
@@ -1267,55 +1266,74 @@ static uint32_t calculate_trace_buffer_size(void)
return tmp & 0xffffff00;
}
static bool check_trace_freq(struct jaylink_swo_speed speed,
uint32_t trace_freq)
static bool calculate_swo_prescaler(unsigned int traceclkin_freq,
uint32_t trace_freq, uint16_t *prescaler)
{
double min;
unsigned int presc;
double deviation;
presc = ((1.0 - SWO_MAX_FREQ_DEV) * traceclkin_freq) / trace_freq + 1;
if (presc > TPIU_ACPR_MAX_SWOSCALER)
return false;
deviation = fabs(1.0 - ((double)trace_freq * presc / traceclkin_freq));
if (deviation > SWO_MAX_FREQ_DEV)
return false;
*prescaler = presc;
return true;
}
static bool detect_swo_freq_and_prescaler(struct jaylink_swo_speed speed,
unsigned int traceclkin_freq, uint32_t *trace_freq,
uint16_t *prescaler)
{
uint32_t divider;
unsigned int presc;
double deviation;
min = fabs(1.0 - (speed.freq / ((double)trace_freq * speed.min_div)));
for (divider = speed.min_div; divider <= speed.max_div; divider++) {
*trace_freq = speed.freq / divider;
presc = ((1.0 - SWO_MAX_FREQ_DEV) * traceclkin_freq) / *trace_freq + 1;
for (divider = speed.min_div; divider < speed.max_div; divider++) {
deviation = fabs(1.0 - (speed.freq / ((double)trace_freq * divider)));
if (presc > TPIU_ACPR_MAX_SWOSCALER)
break;
if (deviation < 0.03) {
LOG_DEBUG("Found suitable frequency divider %u with deviation of "
"%.02f %%.", divider, deviation);
deviation = fabs(1.0 - ((double)*trace_freq * presc / traceclkin_freq));
if (deviation <= SWO_MAX_FREQ_DEV) {
*prescaler = presc;
return true;
}
if (deviation < min)
min = deviation;
}
LOG_ERROR("Selected trace frequency is not supported by the device. "
"Please choose a different trace frequency.");
LOG_ERROR("Maximum permitted deviation is 3.00 %%, but only %.02f %% "
"could be achieved.", min * 100);
return false;
}
static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
uint32_t port_size, unsigned int *trace_freq)
uint32_t port_size, unsigned int *trace_freq,
unsigned int traceclkin_freq, uint16_t *prescaler)
{
int ret;
uint32_t buffer_size;
struct jaylink_swo_speed speed;
uint32_t divider;
uint32_t min_freq;
uint32_t max_freq;
trace_enabled = enabled;
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SWO)) {
if (!enabled)
return ERROR_OK;
LOG_ERROR("Trace capturing is not supported by the device.");
return ERROR_FAIL;
}
if (pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART) {
LOG_ERROR("Selected pin protocol is not supported.");
return ERROR_FAIL;
}
trace_enabled = enabled;
ret = jaylink_swo_stop(devh);
if (ret != JAYLINK_OK) {
@@ -1334,6 +1352,11 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
return ERROR_OK;
}
if (pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART) {
LOG_ERROR("Selected pin protocol is not supported.");
return ERROR_FAIL;
}
buffer_size = calculate_trace_buffer_size();
if (!buffer_size) {
@@ -1349,13 +1372,45 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
return ERROR_FAIL;
}
if (!*trace_freq)
*trace_freq = speed.freq / speed.min_div;
if (*trace_freq > 0) {
divider = speed.freq / *trace_freq;
min_freq = speed.freq / speed.max_div;
max_freq = speed.freq / speed.min_div;
if (!check_trace_freq(speed, *trace_freq))
return ERROR_FAIL;
if (*trace_freq > max_freq) {
LOG_INFO("Given SWO frequency too high, using %u Hz instead.",
max_freq);
*trace_freq = max_freq;
} else if (*trace_freq < min_freq) {
LOG_INFO("Given SWO frequency too low, using %u Hz instead.",
min_freq);
*trace_freq = min_freq;
} else if (*trace_freq != speed.freq / divider) {
*trace_freq = speed.freq / divider;
LOG_DEBUG("Using %u bytes device memory for trace capturing.", buffer_size);
LOG_INFO("Given SWO frequency is not supported by the device, "
"using %u Hz instead.", *trace_freq);
}
if (!calculate_swo_prescaler(traceclkin_freq, *trace_freq,
prescaler)) {
LOG_ERROR("SWO frequency is not suitable. Please choose a "
"different frequency or use auto-detection.");
return ERROR_FAIL;
}
} else {
LOG_INFO("Trying to auto-detect SWO frequency.");
if (!detect_swo_freq_and_prescaler(speed, traceclkin_freq, trace_freq,
prescaler)) {
LOG_ERROR("Maximum permitted frequency deviation of %.02f %% "
"could not be achieved.", SWO_MAX_FREQ_DEV);
LOG_ERROR("Auto-detection of SWO frequency failed.");
return ERROR_FAIL;
}
LOG_INFO("Using SWO frequency of %u Hz.", *trace_freq);
}
ret = jaylink_swo_start(devh, JAYLINK_SWO_MODE_UART, *trace_freq,
buffer_size);
@@ -1365,6 +1420,9 @@ static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol,
return ERROR_FAIL;
}
LOG_DEBUG("Using %u bytes device memory for trace capturing.",
buffer_size);
/*
* Adjust the SWD transaction buffer size as starting SWO capturing
* allocates device internal memory.
@@ -1470,7 +1528,7 @@ COMMAND_HANDLER(jlink_handle_config_mac_address_command)
} else if (CMD_ARGC == 1) {
str = CMD_ARGV[0];
if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' || \
if ((strlen(str) != 17) || (str[2] != ':' || str[5] != ':' ||
str[8] != ':' || str[11] != ':' || str[14] != ':')) {
command_print(CMD, "Invalid MAC address format.");
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -2212,17 +2270,24 @@ static const struct swd_driver jlink_swd = {
static const char * const jlink_transports[] = { "jtag", "swd", NULL };
struct jtag_interface jlink_interface = {
.name = "jlink",
.commands = jlink_command_handlers,
.transports = jlink_transports,
.swd = &jlink_swd,
static struct jtag_interface jlink_interface = {
.execute_queue = &jlink_execute_queue,
.speed = &jlink_speed,
.speed_div = &jlink_speed_div,
.khz = &jlink_khz,
};
struct adapter_driver jlink_adapter_driver = {
.name = "jlink",
.transports = jlink_transports,
.commands = jlink_command_handlers,
.init = &jlink_init,
.quit = &jlink_quit,
.reset = &jlink_reset_safe,
.speed = &jlink_speed,
.khz = &jlink_khz,
.speed_div = &jlink_speed_div,
.config_trace = &config_trace,
.poll_trace = &poll_trace,
.jtag_ops = &jlink_interface,
.swd_ops = &jlink_swd,
};
+209 -20
View File
@@ -33,6 +33,8 @@
#include <netinet/tcp.h>
#endif
#include <string.h>
#define NO_TAP_SHIFT 0
#define TAP_SHIFT 1
@@ -47,34 +49,160 @@
#define CMD_SCAN_CHAIN_FLIP_TMS 3
#define CMD_STOP_SIMU 4
int server_port = SERVER_PORT;
char *server_address;
/* jtag_vpi server port and address to connect to */
static int server_port = SERVER_PORT;
static char *server_address;
int sockfd;
struct sockaddr_in serv_addr;
/* Send CMD_STOP_SIMU to server when OpenOCD exits? */
static bool stop_sim_on_exit;
static int sockfd;
static struct sockaddr_in serv_addr;
/* One jtag_vpi "packet" as sent over a TCP channel. */
struct vpi_cmd {
int cmd;
union {
uint32_t cmd;
unsigned char cmd_buf[4];
};
unsigned char buffer_out[XFERT_MAX_SIZE];
unsigned char buffer_in[XFERT_MAX_SIZE];
int length;
int nb_bits;
union {
uint32_t length;
unsigned char length_buf[4];
};
union {
uint32_t nb_bits;
unsigned char nb_bits_buf[4];
};
};
static char *jtag_vpi_cmd_to_str(int cmd_num)
{
switch (cmd_num) {
case CMD_RESET:
return "CMD_RESET";
case CMD_TMS_SEQ:
return "CMD_TMS_SEQ";
case CMD_SCAN_CHAIN:
return "CMD_SCAN_CHAIN";
case CMD_SCAN_CHAIN_FLIP_TMS:
return "CMD_SCAN_CHAIN_FLIP_TMS";
case CMD_STOP_SIMU:
return "CMD_STOP_SIMU";
default:
return "<unknown>";
}
}
static int jtag_vpi_send_cmd(struct vpi_cmd *vpi)
{
int retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
if (retval <= 0)
return ERROR_FAIL;
int retval;
/* Optional low-level JTAG debug */
if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
if (vpi->nb_bits > 0) {
/* command with a non-empty data payload */
char *char_buf = buf_to_str(vpi->buffer_out,
(vpi->nb_bits > DEBUG_JTAG_IOZ)
? DEBUG_JTAG_IOZ
: vpi->nb_bits,
16);
LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
"length=%" PRIu32 ", "
"nb_bits=%" PRIu32 ", "
"buf_out=0x%s%s",
jtag_vpi_cmd_to_str(vpi->cmd),
vpi->length,
vpi->nb_bits,
char_buf,
(vpi->nb_bits > DEBUG_JTAG_IOZ) ? "(...)" : "");
free(char_buf);
} else {
/* command without data payload */
LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
"length=%" PRIu32 ", "
"nb_bits=%" PRIu32,
jtag_vpi_cmd_to_str(vpi->cmd),
vpi->length,
vpi->nb_bits);
}
}
/* Use little endian when transmitting/receiving jtag_vpi cmds.
The choice of little endian goes against usual networking conventions
but is intentional to remain compatible with most older OpenOCD builds
(i.e. builds on little-endian platforms). */
h_u32_to_le(vpi->cmd_buf, vpi->cmd);
h_u32_to_le(vpi->length_buf, vpi->length);
h_u32_to_le(vpi->nb_bits_buf, vpi->nb_bits);
retry_write:
retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
if (retval < 0) {
/* Account for the case when socket write is interrupted. */
#ifdef _WIN32
int wsa_err = WSAGetLastError();
if (wsa_err == WSAEINTR)
goto retry_write;
#else
if (errno == EINTR)
goto retry_write;
#endif
/* Otherwise this is an error using the socket, most likely fatal
for the connection. B*/
log_socket_error("jtag_vpi xmit");
/* TODO: Clean way how adapter drivers can report fatal errors
to upper layers of OpenOCD and let it perform an orderly shutdown? */
exit(-1);
} else if (retval < (int)sizeof(struct vpi_cmd)) {
/* This means we could not send all data, which is most likely fatal
for the jtag_vpi connection (the underlying TCP connection likely not
usable anymore) */
LOG_ERROR("Could not send all data through jtag_vpi connection.");
exit(-1);
}
/* Otherwise the packet has been sent successfully. */
return ERROR_OK;
}
static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi)
{
int retval = read_socket(sockfd, vpi, sizeof(struct vpi_cmd));
if (retval < (int)sizeof(struct vpi_cmd))
return ERROR_FAIL;
unsigned bytes_buffered = 0;
while (bytes_buffered < sizeof(struct vpi_cmd)) {
int bytes_to_receive = sizeof(struct vpi_cmd) - bytes_buffered;
int retval = read_socket(sockfd, ((char *)vpi) + bytes_buffered, bytes_to_receive);
if (retval < 0) {
#ifdef _WIN32
int wsa_err = WSAGetLastError();
if (wsa_err == WSAEINTR) {
/* socket read interrupted by WSACancelBlockingCall() */
continue;
}
#else
if (errno == EINTR) {
/* socket read interrupted by a signal */
continue;
}
#endif
/* Otherwise, this is an error when accessing the socket. */
log_socket_error("jtag_vpi recv");
exit(-1);
} else if (retval == 0) {
/* Connection closed by the other side */
LOG_ERROR("Connection prematurely closed by jtag_vpi server.");
exit(-1);
}
/* Otherwise, we have successfully received some data */
bytes_buffered += retval;
}
/* Use little endian when transmitting/receiving jtag_vpi cmds. */
vpi->cmd = le_to_h_u32(vpi->cmd_buf);
vpi->length = le_to_h_u32(vpi->length_buf);
vpi->nb_bits = le_to_h_u32(vpi->nb_bits_buf);
return ERROR_OK;
}
@@ -87,6 +215,7 @@ static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi)
static int jtag_vpi_reset(int trst, int srst)
{
struct vpi_cmd vpi;
memset(&vpi, 0, sizeof(struct vpi_cmd));
vpi.cmd = CMD_RESET;
vpi.length = 0;
@@ -109,6 +238,7 @@ static int jtag_vpi_tms_seq(const uint8_t *bits, int nb_bits)
struct vpi_cmd vpi;
int nb_bytes;
memset(&vpi, 0, sizeof(struct vpi_cmd));
nb_bytes = DIV_ROUND_UP(nb_bits, 8);
vpi.cmd = CMD_TMS_SEQ;
@@ -176,6 +306,8 @@ static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift)
struct vpi_cmd vpi;
int nb_bytes = DIV_ROUND_UP(nb_bits, 8);
memset(&vpi, 0, sizeof(struct vpi_cmd));
vpi.cmd = tap_shift ? CMD_SCAN_CHAIN_FLIP_TMS : CMD_SCAN_CHAIN;
if (bits)
@@ -194,6 +326,16 @@ static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift)
if (retval != ERROR_OK)
return retval;
/* Optional low-level JTAG debug */
if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
char *char_buf = buf_to_str(vpi.buffer_in,
(nb_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : nb_bits,
16);
LOG_DEBUG_IO("recvd JTAG VPI data: nb_bits=%d, buf_in=0x%s%s",
nb_bits, char_buf, (nb_bits > DEBUG_JTAG_IOZ) ? "(...)" : "");
free(char_buf);
}
if (bits)
memcpy(bits, vpi.buffer_in, nb_bytes);
@@ -384,6 +526,11 @@ static int jtag_vpi_execute_queue(void)
case JTAG_SCAN:
retval = jtag_vpi_scan(cmd->cmd.scan);
break;
default:
LOG_ERROR("BUG: unknown JTAG command type 0x%X",
cmd->type);
retval = ERROR_FAIL;
break;
}
}
@@ -433,10 +580,28 @@ static int jtag_vpi_init(void)
return ERROR_OK;
}
static int jtag_vpi_stop_simulation(void)
{
struct vpi_cmd cmd;
memset(&cmd, 0, sizeof(struct vpi_cmd));
cmd.length = 0;
cmd.nb_bits = 0;
cmd.cmd = CMD_STOP_SIMU;
return jtag_vpi_send_cmd(&cmd);
}
static int jtag_vpi_quit(void)
{
if (stop_sim_on_exit) {
if (jtag_vpi_stop_simulation() != ERROR_OK)
LOG_WARNING("jtag_vpi: failed to send \"stop simulation\" command");
}
if (close_socket(sockfd) != 0) {
LOG_WARNING("jtag_vpi: could not close jtag_vpi client socket");
log_socket_error("jtag_vpi");
}
free(server_address);
return close(sockfd);
return ERROR_OK;
}
COMMAND_HANDLER(jtag_vpi_set_port)
@@ -466,31 +631,55 @@ COMMAND_HANDLER(jtag_vpi_set_address)
return ERROR_OK;
}
COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler)
{
if (CMD_ARGC != 1) {
LOG_ERROR("jtag_vpi_stop_sim_on_exit expects 1 argument (on|off)");
return ERROR_COMMAND_SYNTAX_ERROR;
} else {
COMMAND_PARSE_ON_OFF(CMD_ARGV[0], stop_sim_on_exit);
}
return ERROR_OK;
}
static const struct command_registration jtag_vpi_command_handlers[] = {
{
.name = "jtag_vpi_set_port",
.handler = &jtag_vpi_set_port,
.mode = COMMAND_CONFIG,
.help = "set the port of the VPI server",
.usage = "description_string",
.usage = "tcp_port_num",
},
{
.name = "jtag_vpi_set_address",
.handler = &jtag_vpi_set_address,
.mode = COMMAND_CONFIG,
.help = "set the address of the VPI server",
.usage = "description_string",
.usage = "ipv4_addr",
},
{
.name = "jtag_vpi_stop_sim_on_exit",
.handler = &jtag_vpi_stop_sim_on_exit_handler,
.mode = COMMAND_CONFIG,
.help = "Configure if simulation stop command shall be sent "
"before OpenOCD exits (default: off)",
.usage = "<on|off>",
},
COMMAND_REGISTRATION_DONE
};
struct jtag_interface jtag_vpi_interface = {
.name = "jtag_vpi",
static struct jtag_interface jtag_vpi_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.commands = jtag_vpi_command_handlers,
.execute_queue = jtag_vpi_execute_queue,
};
struct adapter_driver jtag_vpi_adapter_driver = {
.name = "jtag_vpi",
.transports = jtag_only,
.commands = jtag_vpi_command_handlers,
.init = jtag_vpi_init,
.quit = jtag_vpi_quit,
.execute_queue = jtag_vpi_execute_queue,
.jtag_ops = &jtag_vpi_interface,
};
+33 -58
View File
@@ -43,7 +43,7 @@
#include <jtag/swd.h>
#include <jtag/commands.h>
#include "libusb_common.h"
#include "libusb_helper.h"
#define VID 0x04b4
#define PID 0xf139
@@ -95,7 +95,7 @@
struct kitprog {
hid_device *hid_handle;
struct jtag_libusb_device_handle *usb_handle;
struct libusb_device_handle *usb_handle;
uint16_t packet_size;
uint16_t packet_index;
uint8_t *packet_buffer;
@@ -280,7 +280,7 @@ static int kitprog_usb_open(void)
const uint16_t pids[] = { PID, 0 };
if (jtag_libusb_open(vids, pids, kitprog_serial,
&kitprog_handle->usb_handle) != ERROR_OK) {
&kitprog_handle->usb_handle, NULL) != ERROR_OK) {
LOG_ERROR("Failed to open or find the device");
return ERROR_FAIL;
}
@@ -311,7 +311,7 @@ static int kitprog_usb_open(void)
}
/* Claim the KitProg Programmer (bulk transfer) interface */
if (jtag_libusb_claim_interface(kitprog_handle->usb_handle, 1) != ERROR_OK) {
if (libusb_claim_interface(kitprog_handle->usb_handle, 1) != ERROR_OK) {
LOG_ERROR("Failed to claim KitProg Programmer (bulk transfer) interface");
return ERROR_FAIL;
}
@@ -358,7 +358,7 @@ static int kitprog_get_version(void)
unsigned char command[3] = {HID_TYPE_START | HID_TYPE_WRITE, 0x00, HID_COMMAND_VERSION};
unsigned char data[64];
ret = kitprog_hid_command(command, sizeof command, data, sizeof data);
ret = kitprog_hid_command(command, sizeof(command), data, sizeof(data));
if (ret != ERROR_OK)
return ret;
@@ -376,7 +376,7 @@ static int kitprog_get_millivolts(void)
unsigned char command[3] = {HID_TYPE_START | HID_TYPE_READ, 0x00, HID_COMMAND_POWER};
unsigned char data[64];
ret = kitprog_hid_command(command, sizeof command, data, sizeof data);
ret = kitprog_hid_command(command, sizeof(command), data, sizeof(data));
if (ret != ERROR_OK)
return ret;
@@ -603,7 +603,7 @@ static int kitprog_generic_acquire(void)
* will take the Cortex-M3 out of reset and enable debugging.
*/
for (int i = 0; i < 2; i++) {
for (uint8_t j = 0; j < sizeof devices && acquire_count == i; j++) {
for (uint8_t j = 0; j < sizeof(devices) && acquire_count == i; j++) {
retval = kitprog_acquire_psoc(devices[j], ACQUIRE_MODE_RESET, 3);
if (retval != ERROR_OK) {
LOG_DEBUG("Aquisition function failed for device 0x%02x.", devices[j]);
@@ -731,14 +731,14 @@ static int kitprog_swd_run_queue(void)
}
}
ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle,
BULK_EP_OUT, (char *)buffer, write_count, 0);
if (ret > 0) {
queued_retval = ERROR_OK;
} else {
if (jtag_libusb_bulk_write(kitprog_handle->usb_handle,
BULK_EP_OUT, (char *)buffer,
write_count, 0, &ret)) {
LOG_ERROR("Bulk write failed");
queued_retval = ERROR_FAIL;
break;
} else {
queued_retval = ERROR_OK;
}
/* KitProg firmware does not send a zero length packet
@@ -754,18 +754,17 @@ static int kitprog_swd_run_queue(void)
if (read_count % 64 == 0)
read_count_workaround = read_count;
ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle,
if (jtag_libusb_bulk_read(kitprog_handle->usb_handle,
BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer,
read_count_workaround, 1000);
if (ret > 0) {
read_count_workaround, 1000, &ret)) {
LOG_ERROR("Bulk read failed");
queued_retval = ERROR_FAIL;
break;
} else {
/* Handle garbage data by offsetting the initial read index */
if ((unsigned int)ret > read_count)
read_index = ret - read_count;
queued_retval = ERROR_OK;
} else {
LOG_ERROR("Bulk read failed");
queued_retval = ERROR_FAIL;
break;
}
for (int i = 0; i < pending_transfer_count; i++) {
@@ -819,11 +818,16 @@ static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data)
/*************** jtag lowlevel functions ********************/
static void kitprog_execute_reset(struct jtag_command *cmd)
static int kitprog_reset(int trst, int srst)
{
int retval = ERROR_OK;
if (cmd->cmd.reset->srst == 1) {
if (trst == 1) {
LOG_ERROR("KitProg: Interface has no TRST");
return ERROR_FAIL;
}
if (srst == 1) {
retval = kitprog_reset_target();
/* Since the previous command also disables SWCLK output, we need to send an
* SWD bus reset command to re-enable it. For some reason, running
@@ -836,38 +840,7 @@ static void kitprog_execute_reset(struct jtag_command *cmd)
if (retval != ERROR_OK)
LOG_ERROR("KitProg: Interface reset failed");
}
static void kitprog_execute_sleep(struct jtag_command *cmd)
{
jtag_sleep(cmd->cmd.sleep->us);
}
static void kitprog_execute_command(struct jtag_command *cmd)
{
switch (cmd->type) {
case JTAG_RESET:
kitprog_execute_reset(cmd);
break;
case JTAG_SLEEP:
kitprog_execute_sleep(cmd);
break;
default:
LOG_ERROR("BUG: unknown JTAG command type encountered");
exit(-1);
}
}
static int kitprog_execute_queue(void)
{
struct jtag_command *cmd = jtag_command_queue;
while (cmd != NULL) {
kitprog_execute_command(cmd);
cmd = cmd->next;
}
return ERROR_OK;
return retval;
}
COMMAND_HANDLER(kitprog_handle_info_command)
@@ -961,12 +934,14 @@ static const struct swd_driver kitprog_swd = {
static const char * const kitprog_transports[] = { "swd", NULL };
struct jtag_interface kitprog_interface = {
struct adapter_driver kitprog_adapter_driver = {
.name = "kitprog",
.commands = kitprog_command_handlers,
.transports = kitprog_transports,
.swd = &kitprog_swd,
.execute_queue = kitprog_execute_queue,
.commands = kitprog_command_handlers,
.init = kitprog_init,
.quit = kitprog_quit
.quit = kitprog_quit,
.reset = kitprog_reset,
.swd_ops = &kitprog_swd,
};
-196
View File
@@ -1,196 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
* *
* Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
* *
* 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 *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "log.h"
#include "libusb0_common.h"
static bool jtag_libusb_match(struct jtag_libusb_device *dev,
const uint16_t vids[], const uint16_t pids[])
{
for (unsigned i = 0; vids[i]; i++) {
if (dev->descriptor.idVendor == vids[i] &&
dev->descriptor.idProduct == pids[i]) {
return true;
}
}
return false;
}
/* Returns true if the string descriptor indexed by str_index in device matches string */
static bool string_descriptor_equal(usb_dev_handle *device, uint8_t str_index,
const char *string)
{
int retval;
bool matched;
char desc_string[256+1]; /* Max size of string descriptor */
if (str_index == 0)
return false;
retval = usb_get_string_simple(device, str_index,
desc_string, sizeof(desc_string)-1);
if (retval < 0) {
LOG_ERROR("usb_get_string_simple() failed with %d", retval);
return false;
}
/* Null terminate descriptor string in case it needs to be logged. */
desc_string[sizeof(desc_string)-1] = '\0';
matched = strncmp(string, desc_string, sizeof(desc_string)) == 0;
if (!matched)
LOG_DEBUG("Device serial number '%s' doesn't match requested serial '%s'",
desc_string, string);
return matched;
}
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
const char *serial,
struct jtag_libusb_device_handle **out)
{
int retval = ERROR_FAIL;
bool serial_mismatch = false;
struct jtag_libusb_device_handle *libusb_handle;
usb_init();
usb_find_busses();
usb_find_devices();
struct usb_bus *busses = usb_get_busses();
for (struct usb_bus *bus = busses; bus; bus = bus->next) {
for (struct usb_device *dev = bus->devices;
dev; dev = dev->next) {
if (!jtag_libusb_match(dev, vids, pids))
continue;
libusb_handle = usb_open(dev);
if (NULL == libusb_handle) {
LOG_ERROR("usb_open() failed with %s", usb_strerror());
continue;
}
/* Device must be open to use libusb_get_string_descriptor_ascii. */
if (serial != NULL &&
!string_descriptor_equal(libusb_handle, dev->descriptor.iSerialNumber, serial)) {
serial_mismatch = true;
usb_close(libusb_handle);
continue;
}
*out = libusb_handle;
retval = ERROR_OK;
serial_mismatch = false;
break;
}
}
if (serial_mismatch)
LOG_INFO("No device matches the serial string");
return retval;
}
void jtag_libusb_close(jtag_libusb_device_handle *dev)
{
/* Close device */
usb_close(dev);
}
int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType,
uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes,
uint16_t size, unsigned int timeout)
{
int transferred = 0;
transferred = usb_control_msg(dev, requestType, request, wValue, wIndex,
bytes, size, timeout);
if (transferred < 0)
transferred = 0;
return transferred;
}
int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes,
int size, int timeout)
{
return usb_bulk_write(dev, ep, bytes, size, timeout);
}
int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes,
int size, int timeout)
{
return usb_bulk_read(dev, ep, bytes, size, timeout);
}
int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
int configuration)
{
struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
return usb_set_configuration(devh,
udev->config[configuration].bConfigurationValue);
}
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
unsigned int *usb_read_ep,
unsigned int *usb_write_ep,
int bclass, int subclass, int protocol, int trans_type)
{
struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
struct usb_interface *iface = udev->config->interface;
struct usb_interface_descriptor *desc = iface->altsetting;
*usb_read_ep = *usb_write_ep = 0;
for (int i = 0; i < desc->bNumEndpoints; i++) {
if ((bclass > 0 && desc->bInterfaceClass != bclass) ||
(subclass > 0 && desc->bInterfaceSubClass != subclass) ||
(protocol > 0 && desc->bInterfaceProtocol != protocol) ||
(trans_type > 0 && (desc->endpoint[i].bmAttributes & 0x3) != trans_type))
continue;
uint8_t epnum = desc->endpoint[i].bEndpointAddress;
bool is_input = epnum & 0x80;
LOG_DEBUG("usb ep %s %02x", is_input ? "in" : "out", epnum);
if (is_input)
*usb_read_ep = epnum;
else
*usb_write_ep = epnum;
if (*usb_read_ep && *usb_write_ep) {
LOG_DEBUG("Claiming interface %d", (int)desc->bInterfaceNumber);
usb_claim_interface(devh, (int)desc->bInterfaceNumber);
return ERROR_OK;
}
}
return ERROR_FAIL;
}
int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid)
{
if (!dev)
return ERROR_FAIL;
*pid = dev->descriptor.idProduct;
return ERROR_OK;
}
-74
View File
@@ -1,74 +0,0 @@
/***************************************************************************
* Copyright (C) 2009 by Zachary T Welch <zw@superlucidity.net> *
* *
* Copyright (C) 2011 by Mauro Gamba <maurillo71@gmail.com> *
* *
* 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 *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H
#define OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H
#include <usb.h>
#define jtag_libusb_device usb_device
#define jtag_libusb_device_handle usb_dev_handle
#define jtag_libusb_device_descriptor usb_device_descriptor
#define jtag_libusb_interface usb_interface
#define jtag_libusb_interface_descriptor usb_interface_descriptor
#define jtag_libusb_endpoint_descriptor usb_endpoint_descriptor
#define jtag_libusb_config_descriptor usb_config_descriptor
#define jtag_libusb_reset_device(dev) usb_reset(dev)
#define jtag_libusb_get_device(devh) usb_device(devh)
/* make some defines compatible to libusb1 */
#define LIBUSB_REQUEST_TYPE_VENDOR USB_TYPE_VENDOR
#define LIBUSB_RECIPIENT_DEVICE USB_RECIP_DEVICE
#define LIBUSB_ENDPOINT_OUT USB_ENDPOINT_OUT
#define LIBUSB_ENDPOINT_IN USB_ENDPOINT_IN
#define LIBUSB_TRANSFER_TYPE_BULK USB_ENDPOINT_TYPE_BULK
static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh,
int iface)
{
return usb_claim_interface(devh, iface);
};
static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
int iface)
{
return usb_release_interface(devh, iface);
}
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
const char *serial,
struct jtag_libusb_device_handle **out);
void jtag_libusb_close(jtag_libusb_device_handle *dev);
int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
uint8_t requestType, uint8_t request, uint16_t wValue,
uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout);
int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout);
int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout);
int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
int configuration);
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
unsigned int *usb_read_ep,
unsigned int *usb_write_ep,
int bclass, int subclass, int protocol, int trans_type);
int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */
@@ -21,7 +21,7 @@
#include "config.h"
#endif
#include <jtag/drivers/jtag_usb_common.h>
#include "libusb1_common.h"
#include "libusb_helper.h"
#include "log.h"
/*
@@ -33,7 +33,32 @@
static struct libusb_context *jtag_libusb_context; /**< Libusb context **/
static libusb_device **devs; /**< The usb device list **/
static bool jtag_libusb_match(struct libusb_device_descriptor *dev_desc,
static int jtag_libusb_error(int err)
{
switch (err) {
case LIBUSB_SUCCESS:
return ERROR_OK;
case LIBUSB_ERROR_TIMEOUT:
return ERROR_TIMEOUT_REACHED;
case LIBUSB_ERROR_IO:
case LIBUSB_ERROR_INVALID_PARAM:
case LIBUSB_ERROR_ACCESS:
case LIBUSB_ERROR_NO_DEVICE:
case LIBUSB_ERROR_NOT_FOUND:
case LIBUSB_ERROR_BUSY:
case LIBUSB_ERROR_OVERFLOW:
case LIBUSB_ERROR_PIPE:
case LIBUSB_ERROR_INTERRUPTED:
case LIBUSB_ERROR_NO_MEM:
case LIBUSB_ERROR_NOT_SUPPORTED:
case LIBUSB_ERROR_OTHER:
return ERROR_FAIL;
default:
return ERROR_FAIL;
}
}
static bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
const uint16_t vids[], const uint16_t pids[])
{
for (unsigned i = 0; vids[i]; i++) {
@@ -98,14 +123,45 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in
return matched;
}
static bool jtag_libusb_match_serial(libusb_device_handle *device,
struct libusb_device_descriptor *dev_desc, const char *serial,
adapter_get_alternate_serial_fn adapter_get_alternate_serial)
{
if (string_descriptor_equal(device, dev_desc->iSerialNumber, serial))
return true;
/* check the alternate serial helper */
if (!adapter_get_alternate_serial)
return false;
/* get the alternate serial */
char *alternate_serial = adapter_get_alternate_serial(device, dev_desc);
/* check possible failures */
if (alternate_serial == NULL)
return false;
/* then compare and free the alternate serial */
bool match = false;
if (strcmp(serial, alternate_serial) == 0)
match = true;
else
LOG_DEBUG("Device alternate serial number '%s' doesn't match requested serial '%s'",
alternate_serial, serial);
free(alternate_serial);
return match;
}
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
const char *serial,
struct jtag_libusb_device_handle **out)
struct libusb_device_handle **out,
adapter_get_alternate_serial_fn adapter_get_alternate_serial)
{
int cnt, idx, errCode;
int retval = ERROR_FAIL;
bool serial_mismatch = false;
struct jtag_libusb_device_handle *libusb_handle = NULL;
struct libusb_device_handle *libusb_handle = NULL;
if (libusb_init(&jtag_libusb_context) < 0)
return ERROR_FAIL;
@@ -118,7 +174,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
if (libusb_get_device_descriptor(devs[idx], &dev_desc) != 0)
continue;
if (!jtag_libusb_match(&dev_desc, vids, pids))
if (!jtag_libusb_match_ids(&dev_desc, vids, pids))
continue;
if (jtag_usb_get_location() && !jtag_libusb_location_equal(devs[idx]))
@@ -134,7 +190,7 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
/* Device must be open to use libusb_get_string_descriptor_ascii. */
if (serial != NULL &&
!string_descriptor_equal(libusb_handle, dev_desc.iSerialNumber, serial)) {
!jtag_libusb_match_serial(libusb_handle, &dev_desc, serial, adapter_get_alternate_serial)) {
serial_mismatch = true;
libusb_close(libusb_handle);
continue;
@@ -152,10 +208,13 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
if (serial_mismatch)
LOG_INFO("No device matches the serial string");
if (retval != ERROR_OK)
libusb_exit(jtag_libusb_context);
return retval;
}
void jtag_libusb_close(jtag_libusb_device_handle *dev)
void jtag_libusb_close(struct libusb_device_handle *dev)
{
/* Close device */
libusb_close(dev);
@@ -163,7 +222,7 @@ void jtag_libusb_close(jtag_libusb_device_handle *dev)
libusb_exit(jtag_libusb_context);
}
int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t requestType,
int jtag_libusb_control_transfer(struct libusb_device_handle *dev, uint8_t requestType,
uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes,
uint16_t size, unsigned int timeout)
{
@@ -178,30 +237,44 @@ int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev, uint8_t request
return transferred;
}
int jtag_libusb_bulk_write(jtag_libusb_device_handle *dev, int ep, char *bytes,
int size, int timeout)
int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep, char *bytes,
int size, int timeout, int *transferred)
{
int transferred = 0;
int ret;
libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
&transferred, timeout);
return transferred;
*transferred = 0;
ret = libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
transferred, timeout);
if (ret != LIBUSB_SUCCESS) {
LOG_ERROR("libusb_bulk_write error: %s", libusb_error_name(ret));
return jtag_libusb_error(ret);
}
return ERROR_OK;
}
int jtag_libusb_bulk_read(jtag_libusb_device_handle *dev, int ep, char *bytes,
int size, int timeout)
int jtag_libusb_bulk_read(struct libusb_device_handle *dev, int ep, char *bytes,
int size, int timeout, int *transferred)
{
int transferred = 0;
int ret;
libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
&transferred, timeout);
return transferred;
*transferred = 0;
ret = libusb_bulk_transfer(dev, ep, (unsigned char *)bytes, size,
transferred, timeout);
if (ret != LIBUSB_SUCCESS) {
LOG_ERROR("libusb_bulk_read error: %s", libusb_error_name(ret));
return jtag_libusb_error(ret);
}
return ERROR_OK;
}
int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
int jtag_libusb_set_configuration(struct libusb_device_handle *devh,
int configuration)
{
struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
struct libusb_device *udev = libusb_get_device(devh);
int retCode = -99;
struct libusb_config_descriptor *config = NULL;
@@ -226,12 +299,12 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
return retCode;
}
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
int jtag_libusb_choose_interface(struct libusb_device_handle *devh,
unsigned int *usb_read_ep,
unsigned int *usb_write_ep,
int bclass, int subclass, int protocol, int trans_type)
{
struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
struct libusb_device *udev = libusb_get_device(devh);
const struct libusb_interface *inter;
const struct libusb_interface_descriptor *interdesc;
const struct libusb_endpoint_descriptor *epdesc;
@@ -278,7 +351,7 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
return ERROR_FAIL;
}
int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid)
int jtag_libusb_get_pid(struct libusb_device *dev, uint16_t *pid)
{
struct libusb_device_descriptor dev_desc;
@@ -17,46 +17,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H
#define OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H
#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H
#define OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H
#include <libusb.h>
#define jtag_libusb_device libusb_device
#define jtag_libusb_device_handle libusb_device_handle
#define jtag_libusb_device_descriptor libusb_device_descriptor
#define jtag_libusb_interface libusb_interface
#define jtag_libusb_interface_descriptor libusb_interface_descriptor
#define jtag_libusb_endpoint_descriptor libusb_endpoint_descriptor
#define jtag_libusb_config_descriptor libusb_config_descriptor
#define jtag_libusb_reset_device(dev) libusb_reset_device(dev)
#define jtag_libusb_get_device(devh) libusb_get_device(devh)
static inline int jtag_libusb_claim_interface(jtag_libusb_device_handle *devh,
int iface)
{
return libusb_claim_interface(devh, iface);
};
static inline int jtag_libusb_release_interface(jtag_libusb_device_handle *devh,
int iface)
{
return libusb_release_interface(devh, iface);
}
/* this callback should return a non NULL value only when the serial could not
* be retrieved by the standard 'libusb_get_string_descriptor_ascii' */
typedef char * (*adapter_get_alternate_serial_fn)(libusb_device_handle *device,
struct libusb_device_descriptor *dev_desc);
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
const char *serial,
struct jtag_libusb_device_handle **out);
void jtag_libusb_close(jtag_libusb_device_handle *dev);
int jtag_libusb_control_transfer(jtag_libusb_device_handle *dev,
struct libusb_device_handle **out,
adapter_get_alternate_serial_fn adapter_get_alternate_serial);
void jtag_libusb_close(struct libusb_device_handle *dev);
int jtag_libusb_control_transfer(struct libusb_device_handle *dev,
uint8_t requestType, uint8_t request, uint16_t wValue,
uint16_t wIndex, char *bytes, uint16_t size, unsigned int timeout);
int jtag_libusb_bulk_write(struct jtag_libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout);
int jtag_libusb_bulk_read(struct jtag_libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout);
int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout, int *transferred);
int jtag_libusb_bulk_read(struct libusb_device_handle *dev, int ep,
char *bytes, int size, int timeout, int *transferred);
int jtag_libusb_set_configuration(struct libusb_device_handle *devh,
int configuration);
/**
* Find the first interface optionally matching class, subclass and
@@ -72,10 +55,10 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh,
* @param trans_type `bmAttributes Bits 0..1 Transfer type` to match, or -1 to ignore this field.
* @returns Returns ERROR_OK on success, ERROR_FAIL otherwise.
*/
int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh,
int jtag_libusb_choose_interface(struct libusb_device_handle *devh,
unsigned int *usb_read_ep,
unsigned int *usb_write_ep,
int bclass, int subclass, int protocol, int trans_type);
int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid);
int jtag_libusb_get_pid(struct libusb_device *dev, uint16_t *pid);
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H */
+6 -3
View File
@@ -890,6 +890,7 @@ int mpsse_flush(struct mpsse_ctx *ctx)
/* Polling loop, more or less taken from libftdi */
int64_t start = timeval_ms();
int64_t warn_after = 2000;
while (!write_result.done || !read_result.done) {
struct timeval timeout_usb;
@@ -913,9 +914,11 @@ int mpsse_flush(struct mpsse_ctx *ctx)
}
}
if (timeval_ms() - start > 2000) {
LOG_ERROR("Timed out handling USB events in mpsse_flush().");
break;
int64_t now = timeval_ms();
if (now - start > warn_after) {
LOG_WARNING("Haven't made progress in mpsse_flush() for %" PRId64
"ms.", now - start);
warn_after *= 2;
}
}
+20 -14
View File
@@ -32,7 +32,7 @@
#include <jtag/interface.h>
#include <jtag/commands.h>
#include "libusb_common.h"
#include "libusb_helper.h"
#include <string.h>
#include <time.h>
@@ -134,7 +134,7 @@ static void opendous_tap_append_scan(int length, uint8_t *buffer, struct scan_co
/* opendous lowlevel functions */
struct opendous_jtag {
struct jtag_libusb_device_handle *usb_handle;
struct libusb_device_handle *usb_handle;
};
static struct opendous_jtag *opendous_usb_open(void);
@@ -234,13 +234,19 @@ static const struct command_registration opendous_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct jtag_interface opendous_interface = {
static struct jtag_interface opendous_interface = {
.execute_queue = opendous_execute_queue,
};
struct adapter_driver opendous_adapter_driver = {
.name = "opendous",
.transports = jtag_only,
.commands = opendous_command_handlers,
.execute_queue = opendous_execute_queue,
.init = opendous_init,
.quit = opendous_quit,
.jtag_ops = &opendous_interface,
};
static int opendous_execute_queue(void)
@@ -253,7 +259,7 @@ static int opendous_execute_queue(void)
while (cmd != NULL) {
switch (cmd->type) {
case JTAG_RUNTEST:
LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, \
LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles,
cmd->cmd.runtest->end_state);
if (cmd->cmd.runtest->end_state != -1)
@@ -270,8 +276,8 @@ static int opendous_execute_queue(void)
break;
case JTAG_PATHMOVE:
LOG_DEBUG_IO("pathmove: %i states, end in %i", \
cmd->cmd.pathmove->num_states, \
LOG_DEBUG_IO("pathmove: %i states, end in %i",
cmd->cmd.pathmove->num_states,
cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
opendous_path_move(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path);
@@ -708,12 +714,12 @@ struct opendous_jtag *opendous_usb_open(void)
{
struct opendous_jtag *result;
struct jtag_libusb_device_handle *devh;
if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh) != ERROR_OK)
struct libusb_device_handle *devh;
if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh, NULL) != ERROR_OK)
return NULL;
jtag_libusb_set_configuration(devh, 0);
jtag_libusb_claim_interface(devh, 0);
libusb_claim_interface(devh, 0);
result = malloc(sizeof(*result));
result->usb_handle = devh;
@@ -764,8 +770,8 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
FUNC_WRITE_DATA, 0, 0, (char *) usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
} else {
result = jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT, \
(char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT);
jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT,
(char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT, &result);
}
#ifdef _DEBUG_USB_COMMS_
LOG_DEBUG("USB write end: %d bytes", result);
@@ -791,8 +797,8 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag)
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
FUNC_READ_DATA, 0, 0, (char *) usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
} else {
result = jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
(char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT);
jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
(char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT, &result);
}
#ifdef _DEBUG_USB_COMMS_
LOG_DEBUG("USB read end: %d bytes", result);
+21 -21
View File
@@ -45,7 +45,7 @@
#include <jtag/interface.h>
#include <jtag/commands.h>
#include "libusb_common.h"
#include "libusb_helper.h"
static enum {
OPENJTAG_VARIANT_STANDARD,
@@ -111,7 +111,7 @@ static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE];
static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS];
static int openjtag_scan_result_count;
static jtag_libusb_device_handle *usbh;
static struct libusb_device_handle *usbh;
/* CY7C65215 model only */
#define CY7C65215_JTAG_REQUEST 0x40 /* bmRequestType: vendor host-to-device */
@@ -229,7 +229,7 @@ static int openjtag_buf_write_standard(
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written += retval;
*bytes_written = retval;
return ERROR_OK;
}
@@ -256,10 +256,9 @@ static int openjtag_buf_write_cy7c65215(
return ERROR_JTAG_DEVICE_ERROR;
}
ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("bulk write failed, error %d", ret);
if (jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size,
CY7C65215_USB_TIMEOUT, &ret)) {
LOG_ERROR("bulk write failed, error");
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written = ret;
@@ -324,10 +323,9 @@ static int openjtag_buf_read_cy7c65215(
return ERROR_JTAG_DEVICE_ERROR;
}
ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
CY7C65215_USB_TIMEOUT);
if (ret < 0) {
LOG_ERROR("bulk read failed, error %d", ret);
if (jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty,
CY7C65215_USB_TIMEOUT, &ret)) {
LOG_ERROR("bulk read failed, error");
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_read = ret;
@@ -451,7 +449,7 @@ static int openjtag_init_cy7c65215(void)
int ret;
usbh = NULL;
ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh);
ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh, NULL);
if (ret != ERROR_OK) {
LOG_ERROR("unable to open cy7c65215 device");
goto err;
@@ -654,7 +652,6 @@ static void openjtag_add_scan(uint8_t *buffer, int length, struct scan_command *
/* whole byte */
/* bits to transfer */
bits = 7;
command |= (7 << 5);
length -= 8;
}
@@ -692,7 +689,7 @@ static void openjtag_execute_sleep(struct jtag_command *cmd)
static void openjtag_set_state(uint8_t openocd_state)
{
int8_t state = openjtag_get_tap_state(openocd_state);
uint8_t state = openjtag_get_tap_state(openocd_state);
uint8_t buf = 0;
buf = 0x01;
@@ -892,17 +889,20 @@ static const struct command_registration openjtag_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct jtag_interface openjtag_interface = {
static struct jtag_interface openjtag_interface = {
.execute_queue = openjtag_execute_queue,
};
struct adapter_driver openjtag_adapter_driver = {
.name = "openjtag",
.transports = jtag_only,
.commands = openjtag_command_handlers,
.execute_queue = openjtag_execute_queue,
.speed = openjtag_speed,
.speed_div = openjtag_speed_div,
.khz = openjtag_khz,
.init = openjtag_init,
.quit = openjtag_quit,
.speed = openjtag_speed,
.khz = openjtag_khz,
.speed_div = openjtag_speed_div,
.jtag_ops = &openjtag_interface,
};
+23 -18
View File
@@ -23,7 +23,7 @@
#include <helper/binarybuffer.h>
#include <helper/command.h>
#include <jtag/interface.h>
#include "libusb_common.h"
#include "libusb_helper.h"
struct sequence {
int len;
@@ -132,7 +132,7 @@ static const uint16_t osbdm_vid[] = { 0x15a2, 0x15a2, 0x15a2, 0 };
static const uint16_t osbdm_pid[] = { 0x0042, 0x0058, 0x005e, 0 };
struct osbdm {
struct jtag_libusb_device_handle *devh; /* USB handle */
struct libusb_device_handle *devh; /* USB handle */
uint8_t buffer[OSBDM_USB_BUFSIZE]; /* Data to send and receive */
int count; /* Count data to send and to read */
};
@@ -144,10 +144,12 @@ static struct osbdm osbdm_context;
static int osbdm_send_and_recv(struct osbdm *osbdm)
{
/* Send request */
int count = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
(char *)osbdm->buffer, osbdm->count, OSBDM_USB_TIMEOUT);
int count, ret;
if (count != osbdm->count) {
ret = jtag_libusb_bulk_write(osbdm->devh, OSBDM_USB_EP_WRITE,
(char *)osbdm->buffer, osbdm->count,
OSBDM_USB_TIMEOUT, &count);
if (ret || count != osbdm->count) {
LOG_ERROR("OSBDM communication error: can't write");
return ERROR_FAIL;
}
@@ -156,13 +158,12 @@ static int osbdm_send_and_recv(struct osbdm *osbdm)
uint8_t cmd_saved = osbdm->buffer[0];
/* Reading answer */
osbdm->count = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
(char *)osbdm->buffer, OSBDM_USB_BUFSIZE, OSBDM_USB_TIMEOUT);
ret = jtag_libusb_bulk_read(osbdm->devh, OSBDM_USB_EP_READ,
(char *)osbdm->buffer, OSBDM_USB_BUFSIZE,
OSBDM_USB_TIMEOUT, &osbdm->count);
/* Now perform basic checks for data sent by BDM device
*/
if (osbdm->count < 0) {
if (ret) {
LOG_ERROR("OSBDM communication error: can't read");
return ERROR_FAIL;
}
@@ -296,7 +297,7 @@ static int osbdm_swap(struct osbdm *osbdm, void *tms, void *tdi,
return ERROR_OK;
}
static int osbdm_flush(struct osbdm *osbdm, struct queue* queue)
static int osbdm_flush(struct osbdm *osbdm, struct queue *queue)
{
uint8_t tms[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
uint8_t tdi[DIV_ROUND_UP(OSBDM_SWAP_MAX, 8)];
@@ -373,10 +374,10 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue* queue)
static int osbdm_open(struct osbdm *osbdm)
{
(void)memset(osbdm, 0, sizeof(*osbdm));
if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh) != ERROR_OK)
if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh, NULL) != ERROR_OK)
return ERROR_FAIL;
if (jtag_libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)
return ERROR_FAIL;
return ERROR_OK;
@@ -688,12 +689,16 @@ static int osbdm_init(void)
return ERROR_OK;
}
struct jtag_interface osbdm_interface = {
.name = "osbdm",
.transports = jtag_only,
static struct jtag_interface osbdm_interface = {
.execute_queue = osbdm_execute_queue,
};
struct adapter_driver osbdm_adapter_driver = {
.name = "osbdm",
.transports = jtag_only,
.init = osbdm_init,
.quit = osbdm_quit
.quit = osbdm_quit,
.jtag_ops = &osbdm_interface,
};
+11 -6
View File
@@ -237,7 +237,7 @@ static int parport_get_giveio_access(void)
HANDLE h;
OSVERSIONINFO version;
version.dwOSVersionInfoSize = sizeof version;
version.dwOSVersionInfoSize = sizeof(version);
if (!GetVersionEx(&version)) {
errno = EINVAL;
return -1;
@@ -260,7 +260,6 @@ static int parport_get_giveio_access(void)
static struct bitbang_interface parport_bitbang = {
.read = &parport_read,
.write = &parport_write,
.reset = &parport_reset,
.blink = &parport_led,
};
@@ -514,16 +513,22 @@ static const struct command_registration parport_command_handlers[] = {
COMMAND_REGISTRATION_DONE
};
struct jtag_interface parport_interface = {
.name = "parport",
static struct jtag_interface parport_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
};
struct adapter_driver parport_adapter_driver = {
.name = "parport",
.transports = jtag_only,
.commands = parport_command_handlers,
.init = parport_init,
.quit = parport_quit,
.reset = parport_reset,
.speed = parport_speed,
.khz = parport_khz,
.speed_div = parport_speed_div,
.speed = parport_speed,
.execute_queue = bitbang_execute_queue,
.jtag_ops = &parport_interface,
};
+9 -4
View File
@@ -561,15 +561,20 @@ static int presto_jtag_quit(void)
return ERROR_OK;
}
struct jtag_interface presto_interface = {
static struct jtag_interface presto_interface = {
.execute_queue = bitq_execute_queue,
};
struct adapter_driver presto_adapter_driver = {
.name = "presto",
.transports = jtag_only,
.commands = presto_command_handlers,
.execute_queue = bitq_execute_queue,
.init = presto_jtag_init,
.quit = presto_jtag_quit,
.speed = presto_jtag_speed,
.khz = presto_adapter_khz,
.speed_div = presto_jtag_speed_div,
.init = presto_jtag_init,
.quit = presto_jtag_quit,
.jtag_ops = &presto_interface,
};
+9 -3
View File
@@ -199,7 +199,6 @@ static struct bitbang_interface remote_bitbang_bitbang = {
.sample = &remote_bitbang_sample,
.read_sample = &remote_bitbang_read_sample,
.write = &remote_bitbang_write,
.reset = &remote_bitbang_reset,
.blink = &remote_bitbang_blink,
};
@@ -342,11 +341,18 @@ static const struct command_registration remote_bitbang_command_handlers[] = {
COMMAND_REGISTRATION_DONE,
};
struct jtag_interface remote_bitbang_interface = {
.name = "remote_bitbang",
static struct jtag_interface remote_bitbang_interface = {
.execute_queue = &bitbang_execute_queue,
};
struct adapter_driver remote_bitbang_adapter_driver = {
.name = "remote_bitbang",
.transports = jtag_only,
.commands = remote_bitbang_command_handlers,
.init = &remote_bitbang_init,
.quit = &remote_bitbang_quit,
.reset = &remote_bitbang_reset,
.jtag_ops = &remote_bitbang_interface,
};
+9 -3
View File
@@ -1660,13 +1660,19 @@ static int rlink_quit(void)
return ERROR_OK;
}
struct jtag_interface rlink_interface = {
static struct jtag_interface rlink_interface = {
.execute_queue = rlink_execute_queue,
};
struct adapter_driver rlink_adapter_driver = {
.name = "rlink",
.transports = jtag_only,
.init = rlink_init,
.quit = rlink_quit,
.speed = rlink_speed,
.speed_div = rlink_speed_div,
.khz = rlink_khz,
.execute_queue = rlink_execute_queue,
.speed_div = rlink_speed_div,
.jtag_ops = &rlink_interface,
};
-2
View File
@@ -479,5 +479,3 @@ m4_delay(HOLD_DELAY_CYCLES - 10)
A = X
DR_MPEG = A ; return TCK low, as str912 reset halt seems to require it
BRANCH
-1
View File
@@ -98,4 +98,3 @@ const struct rlink_speed_table rlink_speed_table[] = {{
} };
const size_t rlink_speed_table_size = ARRAY_SIZE(rlink_speed_table);
+523
View File
@@ -0,0 +1,523 @@
/*
* Copyright (c) 2020, Mellanox Technologies Ltd. - All Rights Reserved
* Liming Sun <lsun@mellanox.com>
*
* 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
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <helper/types.h>
#include <helper/system.h>
#include <helper/time_support.h>
#include <helper/list.h>
#include <jtag/interface.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include <target/arm_adi_v5.h>
#include <transport/transport.h>
/* Rshim channel where the CoreSight register resides. */
#define RSH_MMIO_CHANNEL_RSHIM 0x1
/* APB and tile address translation. */
#define RSH_CS_ROM_BASE 0x80000000
#define RSH_CS_TILE_BASE 0x44000000
#define RSH_CS_TILE_SIZE 0x04000000
/*
* APB-AP Identification Register
* The default value is defined in "CoreSight on-chip trace and debug
* (Revision: r1p0)", Section 3.16.5 APB-AP register summary.
*/
#define APB_AP_IDR 0x44770002
/* CoreSight register definition. */
#define RSH_CORESIGHT_CTL 0x0e00
#define RSH_CORESIGHT_CTL_GO_SHIFT 0
#define RSH_CORESIGHT_CTL_GO_MASK 0x1ULL
#define RSH_CORESIGHT_CTL_ACTION_SHIFT 1
#define RSH_CORESIGHT_CTL_ACTION_MASK 0x2ULL
#define RSH_CORESIGHT_CTL_ADDR_SHIFT 2
#define RSH_CORESIGHT_CTL_ADDR_MASK 0x7ffffffcULL
#define RSH_CORESIGHT_CTL_ERR_SHIFT 31
#define RSH_CORESIGHT_CTL_ERR_MASK 0x80000000ULL
#define RSH_CORESIGHT_CTL_DATA_SHIFT 32
#define RSH_CORESIGHT_CTL_DATA_MASK 0xffffffff00000000ULL
/* Util macros to access the CoreSight register. */
#define RSH_CS_GET_FIELD(reg, field) \
(((uint64_t)(reg) & RSH_CORESIGHT_CTL_##field##_MASK) >> \
RSH_CORESIGHT_CTL_##field##_SHIFT)
#define RSH_CS_SET_FIELD(reg, field, value) \
(reg) = (((reg) & ~RSH_CORESIGHT_CTL_##field##_MASK) | \
(((uint64_t)(value) << RSH_CORESIGHT_CTL_##field##_SHIFT) & \
RSH_CORESIGHT_CTL_##field##_MASK))
#ifdef HAVE_SYS_IOCTL_H
/* Message used to program rshim via ioctl(). */
typedef struct {
uint32_t addr;
uint64_t data;
} __attribute__((packed)) rshim_ioctl_msg;
enum {
RSH_IOC_READ = _IOWR('R', 0, rshim_ioctl_msg),
RSH_IOC_WRITE = _IOWR('R', 1, rshim_ioctl_msg),
};
#endif
/* Use local variable stub for DP/AP registers. */
static uint32_t dp_ctrl_stat;
static uint32_t dp_id_code;
static uint32_t ap_sel, ap_bank;
static uint32_t ap_csw;
static uint32_t ap_drw;
static uint32_t ap_tar, ap_tar_inc;
/* Static functions to read/write via rshim/coresight. */
static int (*rshim_read)(int chan, int addr, uint64_t *value);
static int (*rshim_write)(int chan, int addr, uint64_t value);
static int coresight_write(uint32_t tile, uint32_t addr, uint32_t wdata);
static int coresight_read(uint32_t tile, uint32_t addr, uint32_t *value);
/* RShim file handler. */
static int rshim_fd = -1;
/* DAP error code. */
static int rshim_dap_retval = ERROR_OK;
/* Default rshim device. */
#define RSHIM_DEV_PATH_DEFAULT "/dev/rshim0/rshim"
static char *rshim_dev_path;
static int rshim_dev_read(int chan, int addr, uint64_t *value)
{
int rc;
addr = (addr & 0xFFFF) | (1 << 16);
rc = pread(rshim_fd, value, sizeof(*value), addr);
#ifdef HAVE_SYS_IOCTL_H
if (rc < 0 && errno == ENOSYS) {
rshim_ioctl_msg msg;
msg.addr = addr;
msg.data = 0;
rc = ioctl(rshim_fd, RSH_IOC_READ, &msg);
if (!rc)
*value = msg.data;
}
#endif
return rc;
}
static int rshim_dev_write(int chan, int addr, uint64_t value)
{
int rc;
addr = (addr & 0xFFFF) | (1 << 16);
rc = pwrite(rshim_fd, &value, sizeof(value), addr);
#ifdef HAVE_SYS_IOCTL_H
if (rc < 0 && errno == ENOSYS) {
rshim_ioctl_msg msg;
msg.addr = addr;
msg.data = value;
rc = ioctl(rshim_fd, RSH_IOC_WRITE, &msg);
}
#endif
return rc;
}
/* Convert AP address to tile local address. */
static void ap_addr_2_tile(int *tile, uint32_t *addr)
{
*addr -= RSH_CS_ROM_BASE;
if (*addr < RSH_CS_TILE_BASE) {
*tile = 0;
} else {
*addr -= RSH_CS_TILE_BASE;
*tile = *addr / RSH_CS_TILE_SIZE + 1;
*addr = *addr % RSH_CS_TILE_SIZE;
}
}
/*
* Write 4 bytes on the APB bus.
* tile = 0: access the root CS_ROM table
* > 0: access the ROM table of cluster (tile - 1)
*/
static int coresight_write(uint32_t tile, uint32_t addr, uint32_t wdata)
{
uint64_t ctl = 0;
int rc;
if (!rshim_read || !rshim_write)
return ERROR_FAIL;
/*
* ADDR[28] - must be set to 1 due to coresight ip.
* ADDR[27:24] - linear tile id
*/
addr = (addr >> 2) | (tile << 24);
if (tile)
addr |= (1 << 28);
RSH_CS_SET_FIELD(ctl, ADDR, addr);
RSH_CS_SET_FIELD(ctl, ACTION, 0); /* write */
RSH_CS_SET_FIELD(ctl, DATA, wdata);
RSH_CS_SET_FIELD(ctl, GO, 1); /* start */
rshim_write(RSH_MMIO_CHANNEL_RSHIM, RSH_CORESIGHT_CTL, ctl);
do {
rc = rshim_read(RSH_MMIO_CHANNEL_RSHIM,
RSH_CORESIGHT_CTL, &ctl);
if (rc < 0) {
LOG_ERROR("Failed to read rshim.\n");
return rc;
}
} while (RSH_CS_GET_FIELD(ctl, GO));
return ERROR_OK;
}
static int coresight_read(uint32_t tile, uint32_t addr, uint32_t *value)
{
uint64_t ctl = 0;
int rc;
if (!rshim_read || !rshim_write)
return ERROR_FAIL;
/*
* ADDR[28] - must be set to 1 due to coresight ip.
* ADDR[27:24] - linear tile id
*/
addr = (addr >> 2) | (tile << 24);
if (tile)
addr |= (1 << 28);
RSH_CS_SET_FIELD(ctl, ADDR, addr);
RSH_CS_SET_FIELD(ctl, ACTION, 1); /* read */
RSH_CS_SET_FIELD(ctl, GO, 1); /* start */
rshim_write(RSH_MMIO_CHANNEL_RSHIM, RSH_CORESIGHT_CTL, ctl);
do {
rc = rshim_read(RSH_MMIO_CHANNEL_RSHIM,
RSH_CORESIGHT_CTL, &ctl);
if (rc < 0) {
LOG_ERROR("Failed to write rshim.\n");
return rc;
}
} while (RSH_CS_GET_FIELD(ctl, GO));
*value = RSH_CS_GET_FIELD(ctl, DATA);
return ERROR_OK;
}
static int rshim_dp_q_read(struct adiv5_dap *dap, unsigned int reg,
uint32_t *data)
{
if (!data)
return ERROR_OK;
switch (reg) {
case DP_DPIDR:
*data = dp_id_code;
break;
case DP_CTRL_STAT:
*data = CDBGPWRUPACK | CSYSPWRUPACK;
break;
default:
break;
}
return ERROR_OK;
}
static int rshim_dp_q_write(struct adiv5_dap *dap, unsigned int reg,
uint32_t data)
{
switch (reg) {
case DP_CTRL_STAT:
dp_ctrl_stat = data;
break;
case DP_SELECT:
ap_sel = (data & DP_SELECT_APSEL) >> 24;
ap_bank = (data & DP_SELECT_APBANK) >> 4;
break;
default:
LOG_INFO("Unknown command");
break;
}
return ERROR_OK;
}
static int rshim_ap_q_read(struct adiv5_ap *ap, unsigned int reg,
uint32_t *data)
{
uint32_t addr;
int rc = ERROR_OK, tile;
switch (reg) {
case MEM_AP_REG_CSW:
*data = ap_csw;
break;
case MEM_AP_REG_CFG:
*data = 0;
break;
case MEM_AP_REG_BASE:
*data = RSH_CS_ROM_BASE;
break;
case AP_REG_IDR:
if (ap->ap_num == 0)
*data = APB_AP_IDR;
else
*data = 0;
break;
case MEM_AP_REG_BD0:
case MEM_AP_REG_BD1:
case MEM_AP_REG_BD2:
case MEM_AP_REG_BD3:
addr = (ap_tar & ~0xf) + (reg & 0x0C);
ap_addr_2_tile(&tile, &addr);
rc = coresight_read(tile, addr, data);
break;
case MEM_AP_REG_DRW:
addr = (ap_tar & ~0x3) + ap_tar_inc;
ap_addr_2_tile(&tile, &addr);
rc = coresight_read(tile, addr, data);
if (!rc && (ap_csw & CSW_ADDRINC_MASK))
ap_tar_inc += (ap_csw & 0x03) * 2;
break;
default:
LOG_INFO("Unknown command");
rc = ERROR_FAIL;
break;
}
/* Track the last error code. */
if (rc != ERROR_OK)
rshim_dap_retval = rc;
return rc;
}
static int rshim_ap_q_write(struct adiv5_ap *ap, unsigned int reg,
uint32_t data)
{
int rc = ERROR_OK, tile;
uint32_t addr;
if (ap_bank != 0) {
rshim_dap_retval = ERROR_FAIL;
return ERROR_FAIL;
}
switch (reg) {
case MEM_AP_REG_CSW:
ap_csw = data;
break;
case MEM_AP_REG_TAR:
ap_tar = data;
ap_tar_inc = 0;
break;
case MEM_AP_REG_BD0:
case MEM_AP_REG_BD1:
case MEM_AP_REG_BD2:
case MEM_AP_REG_BD3:
addr = (ap_tar & ~0xf) + (reg & 0x0C);
ap_addr_2_tile(&tile, &addr);
rc = coresight_write(tile, addr, data);
break;
case MEM_AP_REG_DRW:
ap_drw = data;
addr = (ap_tar & ~0x3) + ap_tar_inc;
ap_addr_2_tile(&tile, &addr);
rc = coresight_write(tile, addr, data);
if (!rc && (ap_csw & CSW_ADDRINC_MASK))
ap_tar_inc += (ap_csw & 0x03) * 2;
break;
default:
rc = EINVAL;
break;
}
/* Track the last error code. */
if (rc != ERROR_OK)
rshim_dap_retval = rc;
return rc;
}
static int rshim_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack)
{
return ERROR_OK;
}
static int rshim_dp_run(struct adiv5_dap *dap)
{
int retval = rshim_dap_retval;
/* Clear the error code. */
rshim_dap_retval = ERROR_OK;
return retval;
}
static int rshim_connect(struct adiv5_dap *dap)
{
char *path = rshim_dev_path ? rshim_dev_path : RSHIM_DEV_PATH_DEFAULT;
rshim_fd = open(path, O_RDWR | O_SYNC);
if (rshim_fd == -1) {
LOG_ERROR("Unable to open %s\n", path);
return ERROR_FAIL;
}
/*
* Set read/write operation via the device file. Funtion pointers
* are used here so more ways like remote accessing via socket could
* be added later.
*/
rshim_read = rshim_dev_read;
rshim_write = rshim_dev_write;
return ERROR_OK;
}
static void rshim_disconnect(struct adiv5_dap *dap)
{
if (rshim_fd != -1) {
close(rshim_fd);
rshim_fd = -1;
}
}
COMMAND_HANDLER(rshim_dap_device_command)
{
if (CMD_ARGC != 1) {
command_print(CMD, "Too many arguments");
return ERROR_COMMAND_SYNTAX_ERROR;
}
free(rshim_dev_path);
rshim_dev_path = strdup(CMD_ARGV[0]);
return ERROR_OK;
}
static const struct command_registration rshim_dap_subcommand_handlers[] = {
{
.name = "device",
.handler = rshim_dap_device_command,
.mode = COMMAND_CONFIG,
.help = "set the rshim device",
.usage = "</dev/rshim<N>/rshim>",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration rshim_dap_command_handlers[] = {
{
.name = "rshim",
.mode = COMMAND_ANY,
.help = "perform rshim management",
.chain = rshim_dap_subcommand_handlers,
.usage = "",
},
COMMAND_REGISTRATION_DONE
};
static int rshim_dap_init(void)
{
return ERROR_OK;
}
static int rshim_dap_quit(void)
{
return ERROR_OK;
}
static int rshim_dap_reset(int req_trst, int req_srst)
{
return ERROR_OK;
}
static int rshim_dap_speed(int speed)
{
return ERROR_OK;
}
static int rshim_dap_khz(int khz, int *jtag_speed)
{
*jtag_speed = khz;
return ERROR_OK;
}
static int rshim_dap_speed_div(int speed, int *khz)
{
*khz = speed;
return ERROR_OK;
}
/* DAP operations. */
static const struct dap_ops rshim_dap_ops = {
.connect = rshim_connect,
.queue_dp_read = rshim_dp_q_read,
.queue_dp_write = rshim_dp_q_write,
.queue_ap_read = rshim_ap_q_read,
.queue_ap_write = rshim_ap_q_write,
.queue_ap_abort = rshim_ap_q_abort,
.run = rshim_dp_run,
.quit = rshim_disconnect,
};
static const char *const rshim_dap_transport[] = { "dapdirect_swd", NULL };
struct adapter_driver rshim_dap_adapter_driver = {
.name = "rshim",
.transports = rshim_dap_transport,
.commands = rshim_dap_command_handlers,
.init = rshim_dap_init,
.quit = rshim_dap_quit,
.reset = rshim_dap_reset,
.speed = rshim_dap_speed,
.khz = rshim_dap_khz,
.speed_div = rshim_dap_speed_div,
.dap_swd_ops = &rshim_dap_ops,
};
File diff suppressed because it is too large Load Diff
+42 -18
View File
@@ -52,6 +52,7 @@
#include "config.h"
#endif
#include <helper/time_support.h>
#include <jtag/interface.h>
#include "bitbang.h"
@@ -60,7 +61,7 @@
*
* Assume here that there will be less than 10000 gpios on a system
*/
static int is_gpio_valid(int gpio)
static bool is_gpio_valid(int gpio)
{
return gpio >= 0 && gpio < 10000;
}
@@ -97,8 +98,6 @@ static void unexport_sysfs_gpio(int gpio)
snprintf(gpiostr, sizeof(gpiostr), "%d", gpio);
if (open_write_close("/sys/class/gpio/unexport", gpiostr) < 0)
LOG_ERROR("Couldn't unexport gpio %d", gpio);
return;
}
/*
@@ -112,6 +111,7 @@ static void unexport_sysfs_gpio(int gpio)
*/
static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
{
struct timeval timeout, now;
char buf[40];
char gpiostr[5];
int ret;
@@ -131,8 +131,19 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
}
}
gettimeofday(&timeout, NULL);
timeval_add_time(&timeout, 0, 500000);
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
for (;;) {
ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
if (ret >= 0 || errno != EACCES)
break;
gettimeofday(&now, NULL);
if (timeval_compare(&now, &timeout) >= 0)
break;
jtag_sleep(10000);
}
if (ret < 0) {
LOG_ERROR("Couldn't set direction for gpio %d", gpio);
perror("sysfsgpio: ");
@@ -141,7 +152,15 @@ static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
}
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);
ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
for (;;) {
ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
if (ret >= 0 || errno != EACCES)
break;
gettimeofday(&now, NULL);
if (timeval_compare(&now, &timeout) >= 0)
break;
jtag_sleep(10000);
}
if (ret < 0) {
LOG_ERROR("Couldn't open value for gpio %d", gpio);
perror("sysfsgpio: ");
@@ -530,21 +549,27 @@ static int sysfsgpio_quit(void);
static const char * const sysfsgpio_transports[] = { "jtag", "swd", NULL };
struct jtag_interface sysfsgpio_interface = {
.name = "sysfsgpio",
static struct jtag_interface sysfsgpio_interface = {
.supported = DEBUG_CAP_TMS_SEQ,
.execute_queue = bitbang_execute_queue,
};
struct adapter_driver sysfsgpio_adapter_driver = {
.name = "sysfsgpio",
.transports = sysfsgpio_transports,
.swd = &bitbang_swd,
.commands = sysfsgpio_command_handlers,
.init = sysfsgpio_init,
.quit = sysfsgpio_quit,
.reset = sysfsgpio_reset,
.jtag_ops = &sysfsgpio_interface,
.swd_ops = &bitbang_swd,
};
static struct bitbang_interface sysfsgpio_bitbang = {
.read = sysfsgpio_read,
.write = sysfsgpio_write,
.reset = sysfsgpio_reset,
.swdio_read = sysfsgpio_swdio_read,
.swdio_drive = sysfsgpio_swdio_drive,
.blink = 0
@@ -576,23 +601,23 @@ static void cleanup_all_fds(void)
static bool sysfsgpio_jtag_mode_possible(void)
{
if (!is_gpio_valid(tck_gpio))
return 0;
return false;
if (!is_gpio_valid(tms_gpio))
return 0;
return false;
if (!is_gpio_valid(tdi_gpio))
return 0;
return false;
if (!is_gpio_valid(tdo_gpio))
return 0;
return 1;
return false;
return true;
}
static bool sysfsgpio_swd_mode_possible(void)
{
if (!is_gpio_valid(swclk_gpio))
return 0;
return false;
if (!is_gpio_valid(swdio_gpio))
return 0;
return 1;
return false;
return true;
}
static int sysfsgpio_init(void)
@@ -688,4 +713,3 @@ static int sysfsgpio_quit(void)
cleanup_all_fds();
return ERROR_OK;
}
+33 -43
View File
@@ -235,7 +235,7 @@ int ulink_queue_stableclocks(struct ulink *device, struct jtag_command *cmd);
int ulink_post_process_scan(struct ulink_cmd *ulink_cmd);
int ulink_post_process_queue(struct ulink *device);
/* JTAG driver functions (registered in struct jtag_interface) */
/* adapter driver functions */
static int ulink_execute_queue(void);
static int ulink_khz(int khz, int *jtag_speed);
static int ulink_speed(int speed);
@@ -650,7 +650,7 @@ void ulink_clear_queue(struct ulink *device)
int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd)
{
int newsize_out, newsize_in;
int ret;
int ret = ERROR_OK;
newsize_out = ulink_get_queue_size(device, PAYLOAD_DIRECTION_OUT) + 1
+ ulink_cmd->payload_out_size;
@@ -663,14 +663,12 @@ int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd)
/* New command does not fit. Execute all commands in queue before starting
* new queue with the current command as first entry. */
ret = ulink_execute_queued_commands(device, USB_TIMEOUT);
if (ret != ERROR_OK)
return ret;
ret = ulink_post_process_queue(device);
if (ret != ERROR_OK)
return ret;
if (ret == ERROR_OK)
ret = ulink_post_process_queue(device);
ulink_clear_queue(device);
if (ret == ERROR_OK)
ulink_clear_queue(device);
}
if (device->queue_start == NULL) {
@@ -687,7 +685,10 @@ int ulink_append_queue(struct ulink *device, struct ulink_cmd *ulink_cmd)
device->queue_end = ulink_cmd;
}
return ERROR_OK;
if (ret != ERROR_OK)
ulink_clear_queue(device);
return ret;
}
/**
@@ -764,58 +765,40 @@ static const char *ulink_cmd_id_string(uint8_t id)
switch (id) {
case CMD_SCAN_IN:
return "CMD_SCAN_IN";
break;
case CMD_SLOW_SCAN_IN:
return "CMD_SLOW_SCAN_IN";
break;
case CMD_SCAN_OUT:
return "CMD_SCAN_OUT";
break;
case CMD_SLOW_SCAN_OUT:
return "CMD_SLOW_SCAN_OUT";
break;
case CMD_SCAN_IO:
return "CMD_SCAN_IO";
break;
case CMD_SLOW_SCAN_IO:
return "CMD_SLOW_SCAN_IO";
break;
case CMD_CLOCK_TMS:
return "CMD_CLOCK_TMS";
break;
case CMD_SLOW_CLOCK_TMS:
return "CMD_SLOW_CLOCK_TMS";
break;
case CMD_CLOCK_TCK:
return "CMD_CLOCK_TCK";
break;
case CMD_SLOW_CLOCK_TCK:
return "CMD_SLOW_CLOCK_TCK";
break;
case CMD_SLEEP_US:
return "CMD_SLEEP_US";
break;
case CMD_SLEEP_MS:
return "CMD_SLEEP_MS";
break;
case CMD_GET_SIGNALS:
return "CMD_GET_SIGNALS";
break;
case CMD_SET_SIGNALS:
return "CMD_SET_SIGNALS";
break;
case CMD_CONFIGURE_TCK_FREQ:
return "CMD_CONFIGURE_TCK_FREQ";
break;
case CMD_SET_LEDS:
return "CMD_SET_LEDS";
break;
case CMD_TEST:
return "CMD_TEST";
break;
default:
return "CMD_UNKNOWN";
break;
}
}
@@ -1627,6 +1610,7 @@ int ulink_queue_scan(struct ulink *device, struct jtag_command *cmd)
if (ret != ERROR_OK) {
free(tdi_buffer_start);
free(tdo_buffer_start);
return ret;
}
}
@@ -2209,14 +2193,17 @@ static int ulink_init(void)
}
ulink_clear_queue(ulink_handle);
ulink_append_get_signals_cmd(ulink_handle);
ulink_execute_queued_commands(ulink_handle, 200);
ret = ulink_append_get_signals_cmd(ulink_handle);
if (ret == ERROR_OK)
ret = ulink_execute_queued_commands(ulink_handle, 200);
/* Post-process the single CMD_GET_SIGNALS command */
input_signals = ulink_handle->queue_start->payload_in[0];
output_signals = ulink_handle->queue_start->payload_in[1];
if (ret == ERROR_OK) {
/* Post-process the single CMD_GET_SIGNALS command */
input_signals = ulink_handle->queue_start->payload_in[0];
output_signals = ulink_handle->queue_start->payload_in[1];
ulink_print_signal_states(input_signals, output_signals);
ulink_print_signal_states(input_signals, output_signals);
}
ulink_clear_queue(ulink_handle);
@@ -2272,17 +2259,20 @@ static const struct command_registration ulink_command_handlers[] = {
COMMAND_REGISTRATION_DONE,
};
struct jtag_interface ulink_interface = {
.name = "ulink",
.commands = ulink_command_handlers,
.transports = jtag_only,
static struct jtag_interface ulink_interface = {
.execute_queue = ulink_execute_queue,
.khz = ulink_khz,
.speed = ulink_speed,
.speed_div = ulink_speed_div,
};
struct adapter_driver ulink_adapter_driver = {
.name = "ulink",
.transports = jtag_only,
.commands = ulink_command_handlers,
.init = ulink_init,
.quit = ulink_quit
.quit = ulink_quit,
.speed = ulink_speed,
.khz = ulink_khz,
.speed_div = ulink_speed_div,
.jtag_ops = &ulink_interface,
};
@@ -23,7 +23,7 @@
#endif
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <libusb_common.h>
#include <libusb_helper.h>
#include <target/image.h>
#include "ublast_access.h"
@@ -42,28 +42,37 @@
static int ublast2_libusb_read(struct ublast_lowlevel *low, uint8_t *buf,
unsigned size, uint32_t *bytes_read)
{
*bytes_read = jtag_libusb_bulk_read(low->libusb_dev,
USBBLASTER_EPIN | \
int ret, tmp = 0;
ret = jtag_libusb_bulk_read(low->libusb_dev,
USBBLASTER_EPIN |
LIBUSB_ENDPOINT_IN,
(char *)buf,
size,
100);
return ERROR_OK;
100, &tmp);
*bytes_read = tmp;
return ret;
}
static int ublast2_libusb_write(struct ublast_lowlevel *low, uint8_t *buf,
int size, uint32_t *bytes_written)
{
*bytes_written = jtag_libusb_bulk_write(low->libusb_dev,
USBBLASTER_EPOUT | \
int ret, tmp = 0;
ret = jtag_libusb_bulk_write(low->libusb_dev,
USBBLASTER_EPOUT |
LIBUSB_ENDPOINT_OUT,
(char *)buf,
size,
100);
return ERROR_OK;
100, &tmp);
*bytes_written = tmp;
return ret;
}
static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libusb_dev,
static int ublast2_write_firmware_section(struct libusb_device_handle *libusb_dev,
struct image *firmware_image, int section_index)
{
uint16_t chunk_size;
@@ -97,7 +106,7 @@ static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libu
chunk_size = bytes_remaining;
jtag_libusb_control_transfer(libusb_dev,
LIBUSB_REQUEST_TYPE_VENDOR | \
LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT,
USBBLASTER_CTRL_LOAD_FIRM,
addr,
@@ -114,7 +123,7 @@ static int ublast2_write_firmware_section(struct jtag_libusb_device_handle *libu
return ERROR_OK;
}
static int load_usb_blaster_firmware(struct jtag_libusb_device_handle *libusb_dev,
static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev,
struct ublast_lowlevel *low)
{
struct image ublast2_firmware_image;
@@ -143,7 +152,7 @@ static int load_usb_blaster_firmware(struct jtag_libusb_device_handle *libusb_de
char value = CPU_RESET;
jtag_libusb_control_transfer(libusb_dev,
LIBUSB_REQUEST_TYPE_VENDOR | \
LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT,
USBBLASTER_CTRL_LOAD_FIRM,
EZUSB_CPUCS,
@@ -164,7 +173,7 @@ static int load_usb_blaster_firmware(struct jtag_libusb_device_handle *libusb_de
value = !CPU_RESET;
jtag_libusb_control_transfer(libusb_dev,
LIBUSB_REQUEST_TYPE_VENDOR | \
LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_OUT,
USBBLASTER_CTRL_LOAD_FIRM,
EZUSB_CPUCS,
@@ -182,11 +191,11 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
{
const uint16_t vids[] = { low->ublast_vid_uninit, 0 };
const uint16_t pids[] = { low->ublast_pid_uninit, 0 };
struct jtag_libusb_device_handle *temp;
struct libusb_device_handle *temp;
bool renumeration = false;
int ret;
if (jtag_libusb_open(vids, pids, NULL, &temp) == ERROR_OK) {
if (jtag_libusb_open(vids, pids, NULL, &temp, NULL) == ERROR_OK) {
LOG_INFO("Altera USB-Blaster II (uninitialized) found");
LOG_INFO("Loading firmware...");
ret = load_usb_blaster_firmware(temp, low);
@@ -200,13 +209,15 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
const uint16_t pids_renum[] = { low->ublast_pid, 0 };
if (renumeration == false) {
if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK) {
if (jtag_libusb_open(vids_renum, pids_renum, NULL,
&low->libusb_dev, NULL) != ERROR_OK) {
LOG_ERROR("Altera USB-Blaster II not found");
return ERROR_FAIL;
}
} else {
int retry = 10;
while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev) != ERROR_OK && retry--) {
while (jtag_libusb_open(vids_renum, pids_renum, NULL,
&low->libusb_dev, NULL) != ERROR_OK && retry--) {
usleep(1000000);
LOG_INFO("Waiting for renumerate...");
}
@@ -219,7 +230,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
char buffer[5];
jtag_libusb_control_transfer(low->libusb_dev,
LIBUSB_REQUEST_TYPE_VENDOR | \
LIBUSB_REQUEST_TYPE_VENDOR |
LIBUSB_ENDPOINT_IN,
USBBLASTER_CTRL_READ_REV,
0,

Some files were not shown because too many files have changed in this diff Show More