Пример #1
0
/** Checks whether a memory region is zeroed. */
int mips32_blank_check_memory(struct target *target,
		uint32_t address, uint32_t count, uint32_t *blank)
{
	struct working_area *erase_check_algorithm;
	struct reg_param reg_params[3];
	struct mips32_algorithm mips32_info;

	static const uint32_t erase_check_code[] = {
						/* nbyte: */
		0x80880000,		/* lb		$t0, ($a0) */
		0x00C83024,		/* and		$a2, $a2, $t0 */
		0x24A5FFFF,		/* addiu	$a1, $a1, -1 */
		0x14A0FFFC,		/* bne		$a1, $zero, nbyte */
		0x24840001,		/* addiu	$a0, $a0, 1 */
		0x7000003F		/* sdbbp */
	};

	/* make sure we have a working area */
	if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;

	/* convert erase check code into a buffer in target endianness */
	uint8_t erase_check_code_8[sizeof(erase_check_code)];
	target_buffer_set_u32_array(target, erase_check_code_8,
					ARRAY_SIZE(erase_check_code), erase_check_code);

	target_write_buffer(target, erase_check_algorithm->address, sizeof(erase_check_code), erase_check_code_8);

	mips32_info.common_magic = MIPS32_COMMON_MAGIC;
	mips32_info.isa_mode = MIPS32_ISA_MIPS32;

	init_reg_param(&reg_params[0], "r4", 32, PARAM_OUT);
	buf_set_u32(reg_params[0].value, 0, 32, address);

	init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
	buf_set_u32(reg_params[1].value, 0, 32, count);

	init_reg_param(&reg_params[2], "r6", 32, PARAM_IN_OUT);
	buf_set_u32(reg_params[2].value, 0, 32, 0xff);

	int retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
			erase_check_algorithm->address,
			erase_check_algorithm->address + (sizeof(erase_check_code) - 4),
			10000, &mips32_info);

	if (retval == ERROR_OK)
		*blank = buf_get_u32(reg_params[2].value, 0, 32);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);

	target_free_working_area(target, erase_check_algorithm);

	return retval;
}
Пример #2
0
/** Checks whether a memory region is zeroed. */
int xmc4xxx_blank_check_memory(struct target *target,
	uint32_t address, uint32_t count, uint32_t *blank)
{
	struct working_area *erase_check_algorithm;
	struct reg_param reg_params[3];
	struct armv7m_algorithm armv7m_info;
	int retval;

	static const uint8_t erase_check_code[] = {
#include "../../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
	};

	/* make sure we have a working area */
	if (target_alloc_working_area(target, sizeof(erase_check_code),
		&erase_check_algorithm) != ERROR_OK)
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;

	retval = target_write_buffer(target, erase_check_algorithm->address,
			sizeof(erase_check_code), (uint8_t *)erase_check_code);
	if (retval != ERROR_OK)
		return retval;

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
	buf_set_u32(reg_params[0].value, 0, 32, address);

	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
	buf_set_u32(reg_params[1].value, 0, 32, count);

	init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
	buf_set_u32(reg_params[2].value, 0, 32, 0x00);

	retval = target_run_algorithm(target,
				      0,
				      NULL,
				      3,
				      reg_params,
				      erase_check_algorithm->address,
				      erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
				      10000,
				      &armv7m_info);

	if (retval == ERROR_OK)
		*blank = buf_get_u32(reg_params[2].value, 0, 32);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);

	target_free_working_area(target, erase_check_algorithm);

	return retval;
}
Пример #3
0
static int msp432_exec_cmd(struct target *target, struct msp432_algo_params
			*algo_params, uint32_t command)
{
	int retval;

	/* Make sure the given params do not include the command */
	buf_set_u32(algo_params->flash_command, 0, 32, FLASH_NO_COMMAND);
	buf_set_u32(algo_params->return_code, 0, 32, 0);
	buf_set_u32(algo_params->buffer1_status, 0, 32, BUFFER_INACTIVE);
	buf_set_u32(algo_params->buffer2_status, 0, 32, BUFFER_INACTIVE);

	/* Write out parameters to target memory */
	retval = target_write_buffer(target, ALGO_PARAMS_BASE_ADDR,
				sizeof(struct msp432_algo_params), (uint8_t *)algo_params);
	if (ERROR_OK != retval)
		return retval;

	/* Write out command to target memory */
	retval = target_write_buffer(target, ALGO_FLASH_COMMAND_ADDR,
				sizeof(command), (uint8_t *)&command);

	return retval;
}
Пример #4
0
/** Generates a CRC32 checksum of a memory region. */
int armv7m_checksum_memory(struct target *target,
	target_addr_t address, uint32_t count, uint32_t *checksum)
{
	struct working_area *crc_algorithm;
	struct armv7m_algorithm armv7m_info;
	struct reg_param reg_params[2];
	int retval;

	static const uint8_t cortex_m_crc_code[] = {
#include "../../contrib/loaders/checksum/armv7m_crc.inc"
	};

	retval = target_alloc_working_area(target, sizeof(cortex_m_crc_code), &crc_algorithm);
	if (retval != ERROR_OK)
		return retval;

	retval = target_write_buffer(target, crc_algorithm->address,
			sizeof(cortex_m_crc_code), (uint8_t *)cortex_m_crc_code);
	if (retval != ERROR_OK)
		goto cleanup;

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);

	buf_set_u32(reg_params[0].value, 0, 32, address);
	buf_set_u32(reg_params[1].value, 0, 32, count);

	int timeout = 20000 * (1 + (count / (1024 * 1024)));

	retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
			crc_algorithm->address + (sizeof(cortex_m_crc_code) - 6),
			timeout, &armv7m_info);

	if (retval == ERROR_OK)
		*checksum = buf_get_u32(reg_params[0].value, 0, 32);
	else
		LOG_ERROR("error executing cortex_m crc algorithm");

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);

cleanup:
	target_free_working_area(target, crc_algorithm);

	return retval;
}
Пример #5
0
static int loadDriver(struct ecosflash_flash_bank *info)
{
    size_t buf_cnt;
    size_t image_size;
    struct image image;

    image.base_address_set = 0;
    image.start_address_set = 0;
    struct target *target = info->target;
    int retval;

    if ((retval = image_open(&image, info->driverPath, NULL)) != ERROR_OK)
    {
        return retval;
    }

    info->start_address = image.start_address;

    image_size = 0x0;
    int i;
    for (i = 0; i < image.num_sections; i++)
    {
        void *buffer = malloc(image.sections[i].size);
        if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
        {
            free(buffer);
            image_close(&image);
            return retval;
        }
        target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
        image_size += buf_cnt;
        LOG_DEBUG("%zu bytes written at address 0x%8.8" PRIx32 "",
                  buf_cnt, image.sections[i].base_address);

        free(buffer);
    }

    image_close(&image);

    return ERROR_OK;
}
Пример #6
0
static int smi_write_buffer(struct flash_bank *bank, uint8_t *buffer,
	uint32_t address, uint32_t len)
{
	struct target *target = bank->target;
	struct stmsmi_flash_bank *stmsmi_info = bank->driver_priv;
	uint32_t io_base = stmsmi_info->io_base;
	int retval;

	LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32,
		__FUNCTION__, address, len);

	retval = smi_write_enable(bank);
	if (retval != ERROR_OK)
		return retval;

	/* HW mode, write burst mode */
	SMI_SET_HWWB_MODE();

	retval = target_write_buffer(target, address, len, buffer);
	if (retval != ERROR_OK)
		return retval;

	return ERROR_OK;
}
Пример #7
0
/* Un-initialize the ssp module and initialize the SPIFI module */
static int lpcspifi_set_hw_mode(struct flash_bank *bank)
{
	struct target *target = bank->target;
	struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
	uint32_t ssp_base = lpcspifi_info->ssp_base;
	struct armv7m_algorithm armv7m_info;
	struct working_area *spifi_init_algorithm;
	struct reg_param reg_params[1];
	int retval = ERROR_OK;

	LOG_DEBUG("Uninitializing LPC43xx SSP");
	/* Turn off the SSP module */
	retval = ssp_write_reg(target, ssp_base, SSP_CR1, 0x00000000);
	if (retval != ERROR_OK)
		return retval;

	/* see contrib/loaders/flash/lpcspifi_init.S for src */
	static const uint8_t spifi_init_code[] = {
		0x4f, 0xea, 0x00, 0x08, 0xa1, 0xb0, 0x00, 0xaf,
		0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
		0x4f, 0xf0, 0xf3, 0x02, 0xc3, 0xf8, 0x8c, 0x21,
		0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
		0x4f, 0xf4, 0xc0, 0x42, 0xc4, 0xf2, 0x08, 0x02,
		0x4f, 0xf4, 0xc0, 0x41, 0xc4, 0xf2, 0x08, 0x01,
		0x4f, 0xf4, 0xc0, 0x40, 0xc4, 0xf2, 0x08, 0x00,
		0x4f, 0xf0, 0xd3, 0x04, 0xc0, 0xf8, 0x9c, 0x41,
		0x20, 0x46, 0xc1, 0xf8, 0x98, 0x01, 0x01, 0x46,
		0xc2, 0xf8, 0x94, 0x11, 0xc3, 0xf8, 0x90, 0x11,
		0x4f, 0xf4, 0xc0, 0x43, 0xc4, 0xf2, 0x08, 0x03,
		0x4f, 0xf0, 0x13, 0x02, 0xc3, 0xf8, 0xa0, 0x21,
		0x40, 0xf2, 0x18, 0x13, 0xc1, 0xf2, 0x40, 0x03,
		0x1b, 0x68, 0x1c, 0x68, 0x40, 0xf2, 0xb4, 0x30,
		0xc1, 0xf2, 0x00, 0x00, 0x4f, 0xf0, 0x03, 0x01,
		0x4f, 0xf0, 0xc0, 0x02, 0x4f, 0xea, 0x08, 0x03,
		0xa0, 0x47, 0x00, 0xf0, 0x00, 0xb8, 0x00, 0xbe
	};

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;


	LOG_DEBUG("Allocating working area for SPIFI init algorithm");
	/* Get memory for spifi initialization algorithm */
	retval = target_alloc_working_area(target, sizeof(spifi_init_code),
		&spifi_init_algorithm);
	if (retval != ERROR_OK) {
		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)
		);

		return retval;
	}

	LOG_DEBUG("Writing algorithm to working area at 0x%08" PRIx32,
		spifi_init_algorithm->address);
	/* Write algorithm to working area */
	retval = target_write_buffer(target,
		spifi_init_algorithm->address,
		sizeof(spifi_init_code),
		spifi_init_code
	);

	if (retval != ERROR_OK) {
		target_free_working_area(target, spifi_init_algorithm);
		return retval;
	}

	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);		/* spifi clk speed */

	/* For now, the algorithm will set up the SPIFI module
	 * @ the IRC clock speed. In the future, it could be made
	 * a bit smarter to use other clock sources if the user has
	 * already configured them in order to speed up memory-
	 * mapped reads. */
	buf_set_u32(reg_params[0].value, 0, 32, 12);

	/* Run the algorithm */
	LOG_DEBUG("Running SPIFI init algorithm");
	retval = target_run_algorithm(target, 0 , NULL, 1, reg_params,
		spifi_init_algorithm->address,
		spifi_init_algorithm->address + sizeof(spifi_init_code) - 2,
		1000, &armv7m_info);

	if (retval != ERROR_OK)
		LOG_ERROR("Error executing SPIFI init algorithm");

	target_free_working_area(target, spifi_init_algorithm);

	destroy_reg_param(&reg_params[0]);

	return retval;
}
Пример #8
0
static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer,
	uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
	int retval = ERROR_OK;
	uint32_t page_size, fifo_size;
	struct working_area *fifo;
	struct reg_param reg_params[6];
	struct armv7m_algorithm armv7m_info;
	struct working_area *write_algorithm;
	int sector;

	LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32,
		offset, count);

	if (target->state != TARGET_HALTED) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	if (offset + count > mrvlqspi_info->dev->size_in_bytes) {
		LOG_WARNING("Writes past end of flash. Extra data discarded.");
		count = mrvlqspi_info->dev->size_in_bytes - offset;
	}

	/* 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? */
		if ((offset <
			(bank->sectors[sector].offset + bank->sectors[sector].size))
			&& ((offset + count - 1) >= bank->sectors[sector].offset)
			&& bank->sectors[sector].is_protected) {
			LOG_ERROR("Flash sector %d protected", sector);
			return ERROR_FAIL;
		}
	}

	page_size = mrvlqspi_info->dev->pagesize;

	/* See contrib/loaders/flash/mrvlqspi.S for src */
	static const uint8_t mrvlqspi_flash_write_code[] = {
		0x4f, 0xf0, 0x00, 0x0a, 0xa2, 0x44, 0x92, 0x45,
		0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6b, 0xf8,
		0x5f, 0xf0, 0x01, 0x08, 0xc5, 0xf8, 0x1c, 0x80,
		0x5f, 0xf0, 0x06, 0x08, 0xc5, 0xf8, 0x10, 0x80,
		0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0, 0x6b, 0xf8,
		0x00, 0xf0, 0x7d, 0xf8, 0x5f, 0xf0, 0x31, 0x08,
		0xc5, 0xf8, 0x1c, 0x80, 0x90, 0x46, 0xc5, 0xf8,
		0x14, 0x80, 0x5f, 0xf0, 0x02, 0x08, 0xc5, 0xf8,
		0x10, 0x80, 0x5f, 0xf0, 0x01, 0x09, 0x00, 0xf0,
		0x5a, 0xf8, 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1,
		0x00, 0x0f, 0x00, 0xf0, 0x8b, 0x80, 0x47, 0x68,
		0x47, 0x45, 0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8,
		0x01, 0x9b, 0x00, 0xf0, 0x30, 0xf8, 0x8f, 0x42,
		0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60,
		0x01, 0x3b, 0x00, 0x2b, 0x00, 0xf0, 0x05, 0x80,
		0x02, 0xf1, 0x01, 0x02, 0x92, 0x45, 0x7f, 0xf4,
		0xe4, 0xaf, 0x00, 0xf0, 0x50, 0xf8, 0xa2, 0x44,
		0x00, 0xf0, 0x2d, 0xf8, 0x5f, 0xf0, 0x01, 0x08,
		0xc5, 0xf8, 0x1c, 0x80, 0x5f, 0xf0, 0x00, 0x08,
		0xc5, 0xf8, 0x20, 0x80, 0x5f, 0xf0, 0x05, 0x08,
		0xc5, 0xf8, 0x10, 0x80, 0x5f, 0xf0, 0x00, 0x09,
		0x00, 0xf0, 0x29, 0xf8, 0x00, 0xf0, 0x13, 0xf8,
		0x09, 0xf0, 0x01, 0x09, 0xb9, 0xf1, 0x00, 0x0f,
		0xf8, 0xd1, 0x00, 0xf0, 0x34, 0xf8, 0x00, 0x2b,
		0xa4, 0xd1, 0x00, 0xf0, 0x53, 0xb8, 0xd5, 0xf8,
		0x00, 0x80, 0x5f, 0xea, 0x08, 0x68, 0xfa, 0xd4,
		0xc5, 0xf8, 0x08, 0x90, 0x70, 0x47, 0xd5, 0xf8,
		0x00, 0x80, 0x5f, 0xea, 0xc8, 0x68, 0xfa, 0xd4,
		0xd5, 0xf8, 0x0c, 0x90, 0x70, 0x47, 0xd5, 0xf8,
		0x04, 0x80, 0x48, 0xf4, 0x00, 0x78, 0xc5, 0xf8,
		0x04, 0x80, 0xd5, 0xf8, 0x04, 0x80, 0x5f, 0xea,
		0x88, 0x58, 0xfa, 0xd4, 0x70, 0x47, 0xd5, 0xf8,
		0x00, 0x80, 0x48, 0xf0, 0x01, 0x08, 0xc5, 0xf8,
		0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea,
		0x88, 0x78, 0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80,
		0x69, 0xf3, 0x4d, 0x38, 0x48, 0xf4, 0x00, 0x48,
		0xc5, 0xf8, 0x04, 0x80, 0x70, 0x47, 0xd5, 0xf8,
		0x00, 0x80, 0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5,
		0xd5, 0xf8, 0x00, 0x80, 0x5f, 0xea, 0x48, 0x68,
		0xfa, 0xd5, 0xd5, 0xf8, 0x04, 0x80, 0x48, 0xf4,
		0x80, 0x48, 0xc5, 0xf8, 0x04, 0x80, 0xd5, 0xf8,
		0x04, 0x80, 0x5f, 0xea, 0x08, 0x48, 0xfa, 0xd4,
		0xd5, 0xf8, 0x00, 0x80, 0x28, 0xf0, 0x01, 0x08,
		0xc5, 0xf8, 0x00, 0x80, 0xd5, 0xf8, 0x00, 0x80,
		0x5f, 0xea, 0x88, 0x78, 0xfa, 0xd5, 0x70, 0x47,
		0x00, 0x20, 0x50, 0x60, 0x30, 0x46, 0x00, 0xbe
	};

	if (target_alloc_working_area(target, sizeof(mrvlqspi_flash_write_code),
			&write_algorithm) != ERROR_OK) {
		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;
	}

	retval = target_write_buffer(target, write_algorithm->address,
			sizeof(mrvlqspi_flash_write_code),
			mrvlqspi_flash_write_code);
	if (retval != ERROR_OK) {
		target_free_working_area(target, write_algorithm);
		return retval;
	}

	/* FIFO allocation */
	fifo_size = target_get_working_area_avail(target);

	if (fifo_size == 0) {
		/* if we already allocated the writing code but failed to get fifo
		 * space, free the algorithm */
		target_free_working_area(target, write_algorithm);

		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"\
			" to reduce write times.",
			(size_t)(sizeof(mrvlqspi_flash_write_code) + page_size)
		);

	if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) {
		target_free_working_area(target, write_algorithm);
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);	/* buffer start, status (out) */
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);	/* buffer end */
	init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);	/* target address */
	init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);	/* count (halfword-16bit) */
	init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);	/* page size */
	init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);	/* qspi base address */

	buf_set_u32(reg_params[0].value, 0, 32, fifo->address);
	buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size);
	buf_set_u32(reg_params[2].value, 0, 32, offset);
	buf_set_u32(reg_params[3].value, 0, 32, count);
	buf_set_u32(reg_params[4].value, 0, 32, page_size);
	buf_set_u32(reg_params[5].value, 0, 32, (uint32_t) mrvlqspi_info->reg_base);

	retval = target_run_flash_async_algorithm(target, buffer, count, 1,
			0, NULL,
			6, reg_params,
			fifo->address, fifo->size,
			write_algorithm->address, 0,
			&armv7m_info
	);

	if (retval != ERROR_OK)
		LOG_ERROR("Error executing flash write algorithm");

	target_free_working_area(target, fifo);
	target_free_working_area(target, write_algorithm);

	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_reg_param(&reg_params[5]);

	return retval;
}
Пример #9
0
int mips32_run_algorithm(struct target *target, int num_mem_params,
		struct mem_param *mem_params, int num_reg_params,
		struct reg_param *reg_params, uint32_t entry_point,
		uint32_t exit_point, int timeout_ms, void *arch_info)
{
	struct mips32_common *mips32 = target_to_mips32(target);
	struct mips32_algorithm *mips32_algorithm_info = arch_info;
	enum mips32_isa_mode isa_mode = mips32->isa_mode;

	uint32_t context[MIPS32NUMCOREREGS];
	int i;
	int retval = ERROR_OK;

	LOG_DEBUG("Running algorithm");

	/* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
	 * at the exit point */

	if (mips32->common_magic != MIPS32_COMMON_MAGIC)
	{
		LOG_ERROR("current target isn't a MIPS32 target");
		return ERROR_TARGET_INVALID;
	}

	if (target->state != TARGET_HALTED)
	{
		LOG_WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	/* refresh core register cache */
	for (i = 0; i < MIPS32NUMCOREREGS; i++)
	{
		if (!mips32->core_cache->reg_list[i].valid)
			mips32->read_core_reg(target, i);
		context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
	}

	for (i = 0; i < num_mem_params; i++)
	{
		if ((retval = target_write_buffer(target, mem_params[i].address,
				mem_params[i].size, mem_params[i].value)) != ERROR_OK)
		{
			return retval;
		}
	}

	for (i = 0; i < num_reg_params; i++)
	{
		struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);

		if (!reg)
		{
			LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
			return ERROR_COMMAND_SYNTAX_ERROR;
		}

		if (reg->size != reg_params[i].size)
		{
			LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
					reg_params[i].reg_name);
			return ERROR_COMMAND_SYNTAX_ERROR;
		}

		mips32_set_core_reg(reg, reg_params[i].value);
	}

	mips32->isa_mode = mips32_algorithm_info->isa_mode;

	retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32);

	if (retval != ERROR_OK)
		return retval;

	for (i = 0; i < num_mem_params; i++)
	{
		if (mem_params[i].direction != PARAM_OUT)
		{
			if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
					mem_params[i].value)) != ERROR_OK)
			{
				return retval;
			}
		}
	}

	for (i = 0; i < num_reg_params; i++)
	{
		if (reg_params[i].direction != PARAM_OUT)
		{
			struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
			if (!reg)
			{
				LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
				return ERROR_COMMAND_SYNTAX_ERROR;
			}

			if (reg->size != reg_params[i].size)
			{
				LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
						reg_params[i].reg_name);
				return ERROR_COMMAND_SYNTAX_ERROR;
			}

			buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
		}
	}

	/* restore everything we saved before */
	for (i = 0; i < MIPS32NUMCOREREGS; i++)
	{
		uint32_t regvalue;
		regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
		if (regvalue != context[i])
		{
			LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
				mips32->core_cache->reg_list[i].name, context[i]);
			buf_set_u32(mips32->core_cache->reg_list[i].value,
					0, 32, context[i]);
			mips32->core_cache->reg_list[i].valid = 1;
			mips32->core_cache->reg_list[i].dirty = 1;
		}
	}

	mips32->isa_mode = isa_mode;

	return ERROR_OK;
}
Пример #10
0
/** Generates a CRC32 checksum of a memory region. */
int armv7m_checksum_memory(struct target *target,
	uint32_t address, uint32_t count, uint32_t *checksum)
{
	struct working_area *crc_algorithm;
	struct armv7m_algorithm armv7m_info;
	struct reg_param reg_params[2];
	int retval;

	/* see contrib/loaders/checksum/armv7m_crc.s for src */

	static const uint8_t cortex_m3_crc_code[] = {
		/* main: */
		0x02, 0x46,			/* mov		r2, r0 */
		0x00, 0x20,			/* movs		r0, #0 */
		0xC0, 0x43,			/* mvns		r0, r0 */
		0x0A, 0x4E,			/* ldr		r6, CRC32XOR */
		0x0B, 0x46,			/* mov		r3, r1 */
		0x00, 0x24,			/* movs		r4, #0 */
		0x0D, 0xE0,			/* b		ncomp */
		/* nbyte: */
		0x11, 0x5D,			/* ldrb		r1, [r2, r4] */
		0x09, 0x06,			/* lsls		r1, r1, #24 */
		0x48, 0x40,			/* eors		r0, r0, r1 */
		0x00, 0x25,			/* movs		r5, #0 */
		/* loop: */
		0x00, 0x28,			/* cmp		r0, #0 */
		0x02, 0xDA,			/* bge		notset */
		0x40, 0x00,			/* lsls		r0, r0, #1 */
		0x70, 0x40,			/* eors		r0, r0, r6 */
		0x00, 0xE0,			/* b		cont */
		/* notset: */
		0x40, 0x00,			/* lsls		r0, r0, #1 */
		/* cont: */
		0x01, 0x35,			/* adds		r5, r5, #1 */
		0x08, 0x2D,			/* cmp		r5, #8 */
		0xF6, 0xD1,			/* bne		loop */
		0x01, 0x34,			/* adds		r4, r4, #1 */
		/* ncomp: */
		0x9C, 0x42,			/* cmp		r4, r3 */
		0xEF, 0xD1,			/* bne		nbyte */
		0x00, 0xBE,			/* bkpt		#0 */
		0xB7, 0x1D, 0xC1, 0x04	/* CRC32XOR:	.word	0x04c11db7 */
	};

	retval = target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm);
	if (retval != ERROR_OK)
		return retval;

	retval = target_write_buffer(target, crc_algorithm->address,
			sizeof(cortex_m3_crc_code), (uint8_t *)cortex_m3_crc_code);
	if (retval != ERROR_OK)
		goto cleanup;

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);

	buf_set_u32(reg_params[0].value, 0, 32, address);
	buf_set_u32(reg_params[1].value, 0, 32, count);

	int timeout = 20000 * (1 + (count / (1024 * 1024)));

	retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
			crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6),
			timeout, &armv7m_info);

	if (retval == ERROR_OK)
		*checksum = buf_get_u32(reg_params[0].value, 0, 32);
	else
		LOG_ERROR("error executing cortex_m crc algorithm");

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);

cleanup:
	target_free_working_area(target, crc_algorithm);

	return retval;
}
Пример #11
0
static int msp432_write(struct flash_bank *bank, const uint8_t *buffer,
	uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	struct msp432_bank *msp432_bank = bank->driver_priv;
	struct msp432_algo_params algo_params;
	uint32_t size;
	uint32_t data_ready = BUFFER_DATA_READY;
	long long start_ms;
	long long elapsed_ms;

	int retval;

	if (TARGET_HALTED != target->state) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	/*
	 * Block attempts to write to read-only sectors of flash
	 * The TVL region in sector 1 of the info flash is always read-only
	 * 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) {
		/* Set read-only start to TVL sector */
		uint32_t start = 0x1000;
		/* Set read-only end after BSL region if locked */
		uint32_t end = (msp432_bank->unlock_bsl) ? 0x2000 : 0x4000;
		/* Check if request includes anything in read-only sectors */
		if ((offset + count - 1) < start || offset >= end) {
			/* The request includes no bytes in read-only sectors */
			/* Fall out and process the request normally */
		} else {
			/* Send a request for anything before read-only sectors */
			if (offset < start) {
				uint32_t start_count = MIN(start - offset, count);
				retval = msp432_write(bank, buffer, offset, start_count);
				if (ERROR_OK != retval)
					return retval;
			}
			/* Send a request for anything after read-only sectors */
			if ((offset + count - 1) >= end) {
				uint32_t skip = end - offset;
				count -= skip;
				offset += skip;
				buffer += skip;
				return msp432_write(bank, buffer, offset, count);
			} else {
				/* Request is entirely in read-only sectors */
				return ERROR_OK;
			}
		}
	}

	retval = msp432_init(bank);
	if (ERROR_OK != retval)
		return retval;

	/* Initialize algorithm parameters to default values */
	msp432_init_params(&algo_params);

	/* Set up parameters for requested flash write operation */
	buf_set_u32(algo_params.address, 0, 32, bank->base + offset);
	buf_set_u32(algo_params.length, 0, 32, count);

	/* Check if this is the info bank */
	if (1 == bank->bank_number) {
		/* And flag if BSL is unlocked */
		if (msp432_bank->unlock_bsl)
			buf_set_u32(algo_params.unlock_bsl, 0, 32, FLASH_UNLOCK_BSL);
	}

	/* Set up flash helper algorithm to continuous flash mode */
	retval = msp432_exec_cmd(target, &algo_params, FLASH_CONTINUOUS);
	if (ERROR_OK != retval) {
		(void)msp432_quit(bank);
		return retval;
	}

	/* Write requested data, one buffer at a time */
	start_ms = timeval_ms();
	while (count > 0) {

		if (count > ALGO_BUFFER_SIZE)
			size = ALGO_BUFFER_SIZE;
		else
			size = count;

		/* Put next block of data to flash into buffer */
		retval = target_write_buffer(target, ALGO_BUFFER1_ADDR, size, buffer);
		if (ERROR_OK != retval) {
			LOG_ERROR("Unable to write data to target memory");
			(void)msp432_quit(bank);
			return ERROR_FLASH_OPERATION_FAILED;
		}

		/* 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);
		if (ERROR_OK != retval) {
			(void)msp432_quit(bank);
			return ERROR_FLASH_OPERATION_FAILED;
		}

		retval = msp432_wait_inactive(target, 1);
		if (ERROR_OK != retval) {
			(void)msp432_quit(bank);
			return retval;
		}

		count -= size;
		buffer += size;

		elapsed_ms = timeval_ms() - start_ms;
		if (elapsed_ms > 500)
			keep_alive();
	}

	/* Confirm that the flash helper algorithm is finished */
	retval = msp432_wait_return_code(target);
	if (ERROR_OK != retval) {
		(void)msp432_quit(bank);
		return retval;
	}

	retval = msp432_quit(bank);
	if (ERROR_OK != retval)
		return retval;

	return retval;
}
Пример #12
0
/** Checks whether a memory region is erased. */
int armv7m_blank_check_memory(struct target *target,
	target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
{
	struct working_area *erase_check_algorithm;
	struct reg_param reg_params[3];
	struct armv7m_algorithm armv7m_info;
	const uint8_t *code;
	uint32_t code_size;
	int retval;

	static const uint8_t erase_check_code[] = {
#include "../../contrib/loaders/erase_check/armv7m_erase_check.inc"
	};
	static const uint8_t zero_erase_check_code[] = {
#include "../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
	};

	switch (erased_value) {
	case 0x00:
		code = zero_erase_check_code;
		code_size = sizeof(zero_erase_check_code);
		break;
	case 0xff:
	default:
		code = erase_check_code;
		code_size = sizeof(erase_check_code);
	}

	/* make sure we have a working area */
	if (target_alloc_working_area(target, code_size,
		&erase_check_algorithm) != ERROR_OK)
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;

	retval = target_write_buffer(target, erase_check_algorithm->address,
			code_size, code);
	if (retval != ERROR_OK)
		goto cleanup;

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
	buf_set_u32(reg_params[0].value, 0, 32, address);

	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
	buf_set_u32(reg_params[1].value, 0, 32, count);

	init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
	buf_set_u32(reg_params[2].value, 0, 32, erased_value);

	retval = target_run_algorithm(target,
			0,
			NULL,
			3,
			reg_params,
			erase_check_algorithm->address,
			erase_check_algorithm->address + (code_size - 2),
			10000,
			&armv7m_info);

	if (retval == ERROR_OK)
		*blank = buf_get_u32(reg_params[2].value, 0, 32);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);

cleanup:
	target_free_working_area(target, erase_check_algorithm);

	return retval;
}
Пример #13
0
static int fm3_write_block(struct flash_bank *bank, uint8_t *buffer,
		uint32_t offset, uint32_t count)
{
	struct fm3_flash_bank *fm3_info = bank->driver_priv;
	struct target *target = bank->target;
	uint32_t buffer_size = 2048;		/* 8192 for MB9Bxx6! */
	struct working_area *source;
	uint32_t address = bank->base + offset;
	struct reg_param reg_params[6];
	struct armv7m_algorithm armv7m_info;
	int retval = ERROR_OK;
	uint32_t u32FlashType;
	uint32_t u32FlashSeqAddress1;
	uint32_t u32FlashSeqAddress2;

	u32FlashType = (uint32_t) fm3_info->flashtype;

	if (u32FlashType == fm3_flash_type1)
	{
		u32FlashSeqAddress1 = 0x00001550;
		u32FlashSeqAddress2 = 0x00000AA8;
	}
	else if (u32FlashType == fm3_flash_type2)
	{
		u32FlashSeqAddress1 = 0x00000AA8;
		u32FlashSeqAddress2 = 0x00000554;
	}
	else
	{
		LOG_ERROR("Flash/Device type unknown!");
		return ERROR_FLASH_OPERATION_FAILED;
	}

	/* RAMCODE used for fm3 Flash programming:                 */
	/* R0 keeps source start address         (u32Source)       */
	/* R1 keeps target start address         (u32Target)       */
	/* R2 keeps number of halfwords to write (u32Count)        */
	/* R3 keeps Flash Sequence address 1     (u32FlashSeq1)    */
	/* R4 keeps Flash Sequence address 2     (u32FlashSeq2)    */
	/* R5 returns result value               (u32FlashResult)  */

	const uint8_t fm3_flash_write_code[] = {
								/*    fm3_FLASH_IF->FASZ &= 0xFFFD;           */
	0x5F, 0xF0, 0x80, 0x45,		/*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
	0x2D, 0x68,					/*        LDR      R5, [R5]                   */
	0x4F, 0xF6, 0xFD, 0x76,		/*        MOVW     R6, #0xFFFD                */
	0x35, 0x40,					/*        ANDS     R5, R5, R6                 */
	0x5F, 0xF0, 0x80, 0x46,		/*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
	0x35, 0x60,					/*        STR      R5, [R6]                   */
								/*    fm3_FLASH_IF->FASZ |= 1;                */
	0x5F, 0xF0, 0x80, 0x45,		/*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
	0x2D, 0x68,					/*        LDR      R5, [R3]                   */
	0x55, 0xF0, 0x01, 0x05,		/*        ORRS.W   R5, R5, #1                 */
	0x5F, 0xF0, 0x80, 0x46,		/*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
	0x35, 0x60,					/*        STR      R5, [R6]                   */
								/*    u32DummyRead = fm3_FLASH_IF->FASZ;      */
	0x28, 0x4D,					/*        LDR.N    R5, ??u32DummyRead         */
	0x5F, 0xF0, 0x80, 0x46,		/*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
	0x36, 0x68,					/*        LDR      R6, [R6]                   */
	0x2E, 0x60,					/*        STR      R6, [R5]                   */
								/*    u32FlashResult = FLASH_WRITE_NO_RESULT  */
	0x26, 0x4D,					/*        LDR.N    R5, ??u32FlashResult       */
	0x00, 0x26,					/*        MOVS     R6, #0                     */
	0x2E, 0x60,					/*        STR      R6, [R5]                   */
								/*    while ((u32Count > 0 )                  */
								/*      && (u32FlashResult                    */
								/*          == FLASH_WRITE_NO_RESULT))        */
	0x01, 0x2A,					/* L0:    CMP      R2, #1                     */
	0x2C, 0xDB,					/*        BLT.N    L1                         */
	0x24, 0x4D,					/*        LDR.N    R5, ??u32FlashResult       */
	0x2D, 0x68,					/*        LDR      R5, [R5]                   */
	0x00, 0x2D,					/*        CMP      R5, #0                     */
	0x28, 0xD1,					/*        BNE.N    L1                         */
								/*    *u32FlashSeq1 = FLASH_WRITE_1;          */
	0xAA, 0x25,					/*        MOVS     R5, #0xAA                  */
	0x1D, 0x60,					/*        STR      R5, [R3]                   */
								/*    *u32FlashSeq2 = FLASH_WRITE_2;          */
	0x55, 0x25,					/*        MOVS     R5, #0x55                  */
	0x25, 0x60,					/*        STR      R5, [R4]                   */
								/*    *u32FlashSeq1 = FLASH_WRITE_3;          */
	0xA0, 0x25,					/*        MOVS     R5, #0xA0                  */
	0x1D, 0x60,					/*        STRH     R5, [R3]                   */
								/*    *(volatile uint16_t*)u32Target          */
								/*      = *(volatile uint16_t*)u32Source;     */
	0x05, 0x88,					/*        LDRH     R5, [R0]                   */
	0x0D, 0x80,					/*        STRH     R5, [R1]                   */
								/*    while (u32FlashResult                   */
								/*           == FLASH_WRITE_NO_RESTULT)       */
	0x1E, 0x4D,					/* L2:    LDR.N    R5, ??u32FlashResult       */
	0x2D, 0x68,					/*        LDR      R5, [R5]                   */
	0x00, 0x2D,					/*        CMP      R5, #0                     */
	0x11, 0xD1,					/*        BNE.N    L3                         */
								/*    if ((*(volatile uint16_t*)u32Target     */
								/*        & FLASH_DQ5) == FLASH_DQ5)          */
	0x0D, 0x88,					/*        LDRH     R5, [R1]                   */
	0xAD, 0x06,					/*        LSLS     R5, R5, #0x1A              */
	0x02, 0xD5,					/*        BPL.N    L4                         */
								/*    u32FlashResult = FLASH_WRITE_TIMEOUT    */
	0x1A, 0x4D,					/*        LDR.N    R5, ??u32FlashResult       */
	0x02, 0x26,					/*        MOVS     R6, #2                     */
	0x2E, 0x60,					/*        STR      R6, [R5]                   */
								/*    if ((*(volatile uint16_t *)u32Target    */
								/*         & FLASH_DQ7)                       */
								/*        == (*(volatile uint16_t*)u32Source  */
								/*            & FLASH_DQ7))                   */
	0x0D, 0x88,					/* L4:    LDRH     R5, [R1]                   */
	0x15, 0xF0, 0x80, 0x05,		/*        ANDS.W   R5, R5, #0x80              */
	0x06, 0x88,					/*        LDRH     R6, [R0]                   */
	0x16, 0xF0, 0x80, 0x06,		/*        ANDS.W   R6, R6, #0x80              */
	0xB5, 0x42,					/*        CMP      R5, R6                     */
	0xED, 0xD1,					/*        BNE.N    L2                         */
								/*    u32FlashResult = FLASH_WRITE_OKAY       */
	0x15, 0x4D,					/*        LDR.N    R5, ??u32FlashResult       */
	0x01, 0x26,					/*        MOVS     R6, #1                     */
	0x2E, 0x60,					/*        STR      R6, [R5]                   */
	0xE9, 0xE7,					/*        B.N      L2                         */
								/*    if (u32FlashResult                      */
								/*        != FLASH_WRITE_TIMEOUT)             */
	0x13, 0x4D,					/*        LDR.N    R5, ??u32FlashResult       */
	0x2D, 0x68,					/*        LDR      R5, [R5]                   */
	0x02, 0x2D,					/*        CMP      R5, #2                     */
	0x02, 0xD0,					/*        BEQ.N    L5                         */
								/*    u32FlashResult = FLASH_WRITE_NO_RESULT  */
	0x11, 0x4D,					/*        LDR.N    R5, ??u32FlashResult       */
	0x00, 0x26,					/*        MOVS     R6, #0                     */
	0x2E, 0x60,					/*        STR      R6, [R5]                   */
								/*    u32Count--;                             */
	0x52, 0x1E,					/* L5:    SUBS     R2, R2, #1                 */
								/*    u32Source += 2;                         */
	0x80, 0x1C,					/*        ADDS     R0, R0, #2                 */
								/*    u32Target += 2;                         */
	0x89, 0x1C,					/*        ADDS     R1, R1, #2                 */
	0xD0, 0xE7,					/*        B.N      L0                         */
								/*    fm3_FLASH_IF->FASZ &= 0xFFFE;           */
	0x5F, 0xF0, 0x80, 0x45,		/* L1:    MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
	0x2D, 0x68,					/*        LDR      R5, [R5]                   */
	0x4F, 0xF6, 0xFE, 0x76,		/*        MOVW     R6, #0xFFFE                */
	0x35, 0x40,					/*        ANDS     R5, R5, R6                 */
	0x5F, 0xF0, 0x80, 0x46,		/*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
	0x35, 0x60,					/*        STR      R5, [R6]                   */
								/*    fm3_FLASH_IF->FASZ |= 2;                */
	0x5F, 0xF0, 0x80, 0x45,		/*        MOVS.W   R5, #(fm3_FLASH_IF->FASZ)  */
	0x2D, 0x68,					/*        LDR      R5, [R5]                   */
	0x55, 0xF0, 0x02, 0x05,		/*        ORRS.W   R5, R5, #2                 */
	0x5F, 0xF0, 0x80, 0x46,		/*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
	0x35, 0x60,					/*        STR      R5, [R6]                   */
								/*    u32DummyRead = fm3_FLASH_IF->FASZ;      */
	0x04, 0x4D,					/*        LDR.N    R5, ??u32DummyRead         */
	0x5F, 0xF0, 0x80, 0x46,		/*        MOVS.W   R6, #(fm3_FLASH_IF->FASZ)  */
	0x36, 0x68,					/*        LDR      R6, [R6]                   */
	0x2E, 0x60,					/*        STR      R6, [R5]                   */
								/*    copy u32FlashResult to R3 for return    */
								/*      value                                 */
	0xDF, 0xF8, 0x08, 0x50,		/*        LDR.W    R5, ??u32FlashResult       */
	0x2D, 0x68,					/*        LDR      R5, [R5]                   */
								/*    Breakpoint here                         */
	0x00, 0xBE,					/*        BKPT     #0                         */

	/* The following address pointers assume, that the code is running from   */
	/* address 0x1FFF8008. These address pointers will be patched, if a       */
	/* different start address in RAM is used (e.g. for Flash type 2)!        */
	0x00, 0x80, 0xFF, 0x1F,		/* u32DummyRead address in RAM (0x1FFF8000)   */
	0x04, 0x80, 0xFF, 0x1F		/* u32FlashResult address in RAM (0x1FFF8004) */
	};

	LOG_INFO("Fujitsu MB9B500: FLASH Write ...");

	/* disable HW watchdog */
	retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
	if (retval != ERROR_OK)
		return retval;

	retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
	if (retval != ERROR_OK)
		return retval;

	retval = target_write_u32(target, 0x40011008, 0x00000000);
	if (retval != ERROR_OK)
		return retval;

	count = count / 2;		/* number bytes -> number halfwords */

	/* check code alignment */
	if (offset & 0x1)
	{
		LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
	}

	/* allocate working area with flash programming code */
	if (target_alloc_working_area(target, sizeof(fm3_flash_write_code),
			&fm3_info->write_algorithm) != ERROR_OK)
	{
		LOG_WARNING("no working area available, can't do block memory writes");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

	retval = target_write_buffer(target, fm3_info->write_algorithm->address,
		sizeof(fm3_flash_write_code), fm3_flash_write_code);
	if (retval != ERROR_OK)
		return retval;

	/* memory buffer */
	while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
	{
		buffer_size /= 2;
		if (buffer_size <= 256)
		{
			/* free working area, if write algorithm already allocated */
			if (fm3_info->write_algorithm)
			{
				target_free_working_area(target, fm3_info->write_algorithm);
			}

			LOG_WARNING("No large enough working area available, can't do block memory writes");
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	}

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARMV7M_MODE_ANY;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* source start address */
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* target start address */
	init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of halfwords to program */
	init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* Flash Sequence address 1 */
	init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* Flash Sequence address 1 */
	init_reg_param(&reg_params[5], "r5", 32, PARAM_IN);  /* result */

	/* write code buffer and use Flash programming code within fm3 */
	/* Set breakpoint to 0 with time-out of 1000 ms */
	while (count > 0)
	{
		uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;

		retval = target_write_buffer(target, fm3_info->write_algorithm->address,
				8, fm3_flash_write_code);
		if (retval != ERROR_OK)
			break;

		/* Patching 'local variable address' for different RAM addresses */
		if (fm3_info->write_algorithm->address != 0x1FFF8008)
		{
			/* Algorithm: u32DummyRead: */
			retval = target_write_u32(target, (fm3_info->write_algorithm->address)
					+ sizeof(fm3_flash_write_code) - 8,
					(fm3_info->write_algorithm->address) - 8);
			if (retval != ERROR_OK)
				break;

			/* Algorithm: u32FlashResult: */
			retval = target_write_u32(target, (fm3_info->write_algorithm->address)
					+ sizeof(fm3_flash_write_code) - 4, (fm3_info->write_algorithm->address) - 4);
			if (retval != ERROR_OK)
				break;
		}

		retval = target_write_buffer(target, source->address, thisrun_count * 2,
				buffer);
		if (retval != ERROR_OK)
			break;

		buf_set_u32(reg_params[0].value, 0, 32, source->address);
		buf_set_u32(reg_params[1].value, 0, 32, address);
		buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
		buf_set_u32(reg_params[3].value, 0, 32, u32FlashSeqAddress1);
		buf_set_u32(reg_params[4].value, 0, 32, u32FlashSeqAddress2);

		retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
				fm3_info->write_algorithm->address, 0, 1000, &armv7m_info);
		if (retval != ERROR_OK)
		{
			LOG_ERROR("Error executing fm3 Flash programming algorithm");
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}

		if (buf_get_u32(reg_params[5].value, 0, 32) != ERROR_OK)
		{
			LOG_ERROR("Fujitsu MB9[A/B]FXXX: Flash programming ERROR (Timeout) \
					-> Reg R3: %x", buf_get_u32(reg_params[5].value, 0, 32));
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}

		buffer  += thisrun_count * 2;
		address += thisrun_count * 2;
		count   -= thisrun_count;
	}
Пример #14
0
int armv4_5_run_algorithm_inner(struct target *target,
	int num_mem_params, struct mem_param *mem_params,
	int num_reg_params, struct reg_param *reg_params,
	uint32_t entry_point, uint32_t exit_point,
	int timeout_ms, void *arch_info,
	int (*run_it)(struct target *target, uint32_t exit_point,
	int timeout_ms, void *arch_info))
{
	struct arm *arm = target_to_arm(target);
	struct arm_algorithm *arm_algorithm_info = arch_info;
	enum arm_state core_state = arm->core_state;
	uint32_t context[17];
	uint32_t cpsr;
	int exit_breakpoint_size = 0;
	int i;
	int retval = ERROR_OK;

	LOG_DEBUG("Running algorithm");

	if (arm_algorithm_info->common_magic != ARM_COMMON_MAGIC) {
		LOG_ERROR("current target isn't an ARMV4/5 target");
		return ERROR_TARGET_INVALID;
	}

	if (target->state != TARGET_HALTED) {
		LOG_WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	if (!is_arm_mode(arm->core_mode)) {
		LOG_ERROR("not a valid arm core mode - communication failure?");
		return ERROR_FAIL;
	}

	/* armv5 and later can terminate with BKPT instruction; less overhead */
	if (!exit_point && arm->is_armv4) {
		LOG_ERROR("ARMv4 target needs HW breakpoint location");
		return ERROR_FAIL;
	}

	/* save r0..pc, cpsr-or-spsr, and then cpsr-for-sure;
	 * they'll be restored later.
	 */
	for (i = 0; i <= 16; i++) {
		struct reg *r;

		r = &ARMV4_5_CORE_REG_MODE(arm->core_cache,
				arm_algorithm_info->core_mode, i);
		if (!r->valid)
			arm->read_core_reg(target, r, i,
				arm_algorithm_info->core_mode);
		context[i] = buf_get_u32(r->value, 0, 32);
	}
	cpsr = buf_get_u32(arm->cpsr->value, 0, 32);

	for (i = 0; i < num_mem_params; i++) {
		retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size,
				mem_params[i].value);
		if (retval != ERROR_OK)
			return retval;
	}

	for (i = 0; i < num_reg_params; i++) {
		struct reg *reg = register_get_by_name(arm->core_cache, reg_params[i].reg_name, 0);
		if (!reg) {
			LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
			return ERROR_COMMAND_SYNTAX_ERROR;
		}

		if (reg->size != reg_params[i].size) {
			LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
				reg_params[i].reg_name);
			return ERROR_COMMAND_SYNTAX_ERROR;
		}

		retval = armv4_5_set_core_reg(reg, reg_params[i].value);
		if (retval != ERROR_OK)
			return retval;
	}

	arm->core_state = arm_algorithm_info->core_state;
	if (arm->core_state == ARM_STATE_ARM)
		exit_breakpoint_size = 4;
	else if (arm->core_state == ARM_STATE_THUMB)
		exit_breakpoint_size = 2;
	else {
		LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
		return ERROR_COMMAND_SYNTAX_ERROR;
	}

	if (arm_algorithm_info->core_mode != ARM_MODE_ANY) {
		LOG_DEBUG("setting core_mode: 0x%2.2x",
			arm_algorithm_info->core_mode);
		buf_set_u32(arm->cpsr->value, 0, 5,
			arm_algorithm_info->core_mode);
		arm->cpsr->dirty = 1;
		arm->cpsr->valid = 1;
	}

	/* terminate using a hardware or (ARMv5+) software breakpoint */
	if (exit_point) {
		retval = breakpoint_add(target, exit_point,
				exit_breakpoint_size, BKPT_HARD);
		if (retval != ERROR_OK) {
			LOG_ERROR("can't add HW breakpoint to terminate algorithm");
			return ERROR_TARGET_FAILURE;
		}
	}

	retval = target_resume(target, 0, entry_point, 1, 1);
	if (retval != ERROR_OK)
		return retval;
	retval = run_it(target, exit_point, timeout_ms, arch_info);

	if (exit_point)
		breakpoint_remove(target, exit_point);

	if (retval != ERROR_OK)
		return retval;

	for (i = 0; i < num_mem_params; i++) {
		if (mem_params[i].direction != PARAM_OUT) {
			int retvaltemp = target_read_buffer(target, mem_params[i].address,
					mem_params[i].size,
					mem_params[i].value);
			if (retvaltemp != ERROR_OK)
				retval = retvaltemp;
		}
	}

	for (i = 0; i < num_reg_params; i++) {
		if (reg_params[i].direction != PARAM_OUT) {

			struct reg *reg = register_get_by_name(arm->core_cache,
					reg_params[i].reg_name,
					0);
			if (!reg) {
				LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
				retval = ERROR_COMMAND_SYNTAX_ERROR;
				continue;
			}

			if (reg->size != reg_params[i].size) {
				LOG_ERROR(
					"BUG: register '%s' size doesn't match reg_params[i].size",
					reg_params[i].reg_name);
				retval = ERROR_COMMAND_SYNTAX_ERROR;
				continue;
			}

			buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
		}
	}

	/* restore everything we saved before (17 or 18 registers) */
	for (i = 0; i <= 16; i++) {
		uint32_t regvalue;
		regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
				arm_algorithm_info->core_mode, i).value, 0, 32);
		if (regvalue != context[i]) {
			LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "",
				ARMV4_5_CORE_REG_MODE(arm->core_cache,
				arm_algorithm_info->core_mode, i).name, context[i]);
			buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
				arm_algorithm_info->core_mode, i).value, 0, 32, context[i]);
			ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
				i).valid = 1;
			ARMV4_5_CORE_REG_MODE(arm->core_cache, arm_algorithm_info->core_mode,
				i).dirty = 1;
		}
	}

	arm_set_cpsr(arm, cpsr);
	arm->cpsr->dirty = 1;

	arm->core_state = core_state;

	return retval;
}
Пример #15
0
/**
 * ARM-specific bulk write from buffer to address of 8-bit wide NAND.
 * For now this supports ARMv4,ARMv5 and ARMv7-M cores.
 *
 * Enhancements to target_run_algorithm() could enable:
 *   - ARMv6 and ARMv7 cores in ARM mode
 *
 * Different code fragments could handle:
 *   - 16-bit wide data (needs different setup)
 *
 * @param nand Pointer to the arm_nand_data struct that defines the I/O
 * @param data Pointer to the data to be copied to flash
 * @param size Size of the data being copied
 * @return Success or failure of the operation
 */
int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size)
{
	struct target *target = nand->target;
	struct arm_algorithm armv4_5_algo;
	struct armv7m_algorithm armv7m_algo;
	void *arm_algo;
	struct arm *arm = target->arch_info;
	struct reg_param reg_params[3];
	uint32_t target_buf;
	uint32_t exit_var = 0;
	int retval;

	/* Inputs:
	 *  r0	NAND data address (byte wide)
	 *  r1	buffer address
	 *  r2	buffer length
	 */
	static const uint32_t code_armv4_5[] = {
		0xe4d13001,	/* s: ldrb  r3, [r1], #1 */
		0xe5c03000,	/*    strb  r3, [r0]     */
		0xe2522001,	/*    subs  r2, r2, #1   */
		0x1afffffb,	/*    bne   s            */

		/* exit: ARMv4 needs hardware breakpoint */
		0xe1200070,	/* e: bkpt  #0           */
	};

	/* Inputs:
	 *  r0	NAND data address (byte wide)
	 *  r1	buffer address
	 *  r2	buffer length
	 *
	 * see contrib/loaders/flash/armv7m_io.s for src
	 */
	static const uint32_t code_armv7m[] = {
		0x3b01f811,
		0x3a017003,
		0xaffaf47f,
		0xbf00be00,
	};

	int target_code_size = 0;
	const uint32_t *target_code_src = NULL;

	/* set up algorithm */
	if (is_armv7m(target_to_armv7m(target))) {  /* armv7m target */
		armv7m_algo.common_magic = ARMV7M_COMMON_MAGIC;
		armv7m_algo.core_mode = ARM_MODE_THREAD;
		arm_algo = &armv7m_algo;
		target_code_size = sizeof(code_armv7m);
		target_code_src = code_armv7m;
	} else {
		armv4_5_algo.common_magic = ARM_COMMON_MAGIC;
		armv4_5_algo.core_mode = ARM_MODE_SVC;
		armv4_5_algo.core_state = ARM_STATE_ARM;
		arm_algo = &armv4_5_algo;
		target_code_size = sizeof(code_armv4_5);
		target_code_src = code_armv4_5;
	}

	if (nand->op != ARM_NAND_WRITE || !nand->copy_area) {
		retval = arm_code_to_working_area(target, target_code_src, target_code_size,
				nand->chunk_size, &nand->copy_area);
		if (retval != ERROR_OK)
			return retval;
	}

	nand->op = ARM_NAND_WRITE;

	/* copy data to work area */
	target_buf = nand->copy_area->address + target_code_size;
	retval = target_write_buffer(target, target_buf, size, data);
	if (retval != ERROR_OK)
		return retval;

	/* set up parameters */
	init_reg_param(&reg_params[0], "r0", 32, PARAM_IN);
	init_reg_param(&reg_params[1], "r1", 32, PARAM_IN);
	init_reg_param(&reg_params[2], "r2", 32, PARAM_IN);

	buf_set_u32(reg_params[0].value, 0, 32, nand->data);
	buf_set_u32(reg_params[1].value, 0, 32, target_buf);
	buf_set_u32(reg_params[2].value, 0, 32, size);

	/* armv4 must exit using a hardware breakpoint */
	if (arm->is_armv4)
		exit_var = nand->copy_area->address + target_code_size - 4;

	/* use alg to write data from work area to NAND chip */
	retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
			nand->copy_area->address, exit_var, 1000, arm_algo);
	if (retval != ERROR_OK)
		LOG_ERROR("error executing hosted NAND write");

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);

	return retval;
}
Пример #16
0
static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
{
	struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
	struct target *target = bank->target;
	uint32_t dst_min_alignment;
	uint32_t bytes_remaining = count;
	uint32_t bytes_written = 0;
	int first_sector = 0;
	int last_sector = 0;
	uint32_t param_table[5];
	uint32_t result_table[4];
	int status_code;
	int i;
	struct working_area *download_area;
	int retval = ERROR_OK;

	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;

	dst_min_alignment = lpc2000_info->cmd51_dst_boundary;

	if (offset % dst_min_alignment) {
		LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32,
			offset,
			dst_min_alignment);
		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
	}

	for (i = 0; i < bank->num_sectors; i++) {
		if (offset >= bank->sectors[i].offset)
			first_sector = i;
		if (offset + DIV_ROUND_UP(count, dst_min_alignment)
				* dst_min_alignment > bank->sectors[i].offset)
			last_sector = i;
	}

	LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);

	/* check if exception vectors should be flashed */
	if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum) {
		uint32_t checksum = 0;
		for (i = 0; i < 8; i++) {
			LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4,
				buf_get_u32(buffer + (i * 4), 0, 32));
			if (i != lpc2000_info->checksum_vector)
				checksum += buf_get_u32(buffer + (i * 4), 0, 32);
		}
		checksum = 0 - checksum;
		LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);

		uint32_t original_value = buf_get_u32(buffer +
				(lpc2000_info->checksum_vector * 4), 0, 32);
		if (original_value != checksum) {
			LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") "
					"to be written to flash is different from calculated vector "
					"checksum (0x%8.8" PRIx32 ").", original_value, checksum);
			LOG_WARNING("To remove this warning modify build tools on developer PC "
					"to inject correct LPC vector checksum.");
		}

		buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
	}

	/* allocate a working area */
	if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer,
			&download_area) != ERROR_OK) {
		LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
		return ERROR_FLASH_OPERATION_FAILED;
	}

	while (bytes_remaining > 0) {
		uint32_t thisrun_bytes;
		if (bytes_remaining >= lpc2000_info->cmd51_max_buffer)
			thisrun_bytes = lpc2000_info->cmd51_max_buffer;
		else if (bytes_remaining >= 1024)
			thisrun_bytes = 1024;
		else if ((bytes_remaining >= 512) || (!lpc2000_info->cmd51_can_256b))
			thisrun_bytes = 512;
		else
			thisrun_bytes = 256;

		/* Prepare sectors */
		param_table[0] = first_sector;
		param_table[1] = last_sector;
		status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
		switch (status_code) {
			case ERROR_FLASH_OPERATION_FAILED:
				retval = ERROR_FLASH_OPERATION_FAILED;
				break;
			case LPC2000_CMD_SUCCESS:
				break;
			case LPC2000_INVALID_SECTOR:
				retval = ERROR_FLASH_SECTOR_INVALID;
				break;
			default:
				LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
				retval = ERROR_FLASH_OPERATION_FAILED;
				break;
		}

		/* Exit if error occured */
		if (retval != ERROR_OK)
			break;

		if (bytes_remaining >= thisrun_bytes) {
			retval = target_write_buffer(bank->target, download_area->address,
					thisrun_bytes, buffer + bytes_written);
			if (retval != ERROR_OK) {
				retval = ERROR_FLASH_OPERATION_FAILED;
				break;
			}
		} else {
			uint8_t *last_buffer = malloc(thisrun_bytes);
			memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
			memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes -
				bytes_remaining);
			target_write_buffer(bank->target,
				download_area->address,
				thisrun_bytes,
				last_buffer);
			free(last_buffer);
		}

		LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32,
			thisrun_bytes,
			bank->base + offset + bytes_written);

		/* Write data */
		param_table[0] = bank->base + offset + bytes_written;
		param_table[1] = download_area->address;
		param_table[2] = thisrun_bytes;
		param_table[3] = lpc2000_info->cclk;
		status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
		switch (status_code) {
			case ERROR_FLASH_OPERATION_FAILED:
				retval = ERROR_FLASH_OPERATION_FAILED;
				break;
			case LPC2000_CMD_SUCCESS:
				break;
			case LPC2000_INVALID_SECTOR:
				retval = ERROR_FLASH_SECTOR_INVALID;
				break;
			default:
				LOG_WARNING("lpc2000 returned %i", status_code);
				retval = ERROR_FLASH_OPERATION_FAILED;
				break;
		}

		/* Exit if error occured */
		if (retval != ERROR_OK)
			break;

		if (bytes_remaining > thisrun_bytes)
			bytes_remaining -= thisrun_bytes;
		else
			bytes_remaining = 0;
		bytes_written += thisrun_bytes;
	}

	target_free_working_area(target, download_area);

	return retval;
}
Пример #17
0
static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer,
		uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;

	uint32_t halfpages_number;
	uint32_t bytes_remaining = 0;
	uint32_t address = bank->base + offset;
	uint32_t bytes_written = 0;
	int retval, retval2;

	if (bank->target->state != TARGET_HALTED) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	if (offset & 0x3) {
		LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
	}

	retval = stm32lx_unlock_program_memory(bank);
	if (retval != ERROR_OK)
		return retval;

	/* first we need to write any unaligned head bytes upto
	 * the next 128 byte page */

	if (offset % 128)
		bytes_remaining = MIN(count, 128 - (offset % 128));

	while (bytes_remaining > 0) {
		uint8_t value[4] = {0xff, 0xff, 0xff, 0xff};

		/* copy remaining bytes into the write buffer */
		uint32_t bytes_to_write = MIN(4, bytes_remaining);
		memcpy(value, buffer + bytes_written, bytes_to_write);

		retval = target_write_buffer(target, address, 4, value);
		if (retval != ERROR_OK)
			goto reset_pg_and_lock;

		bytes_written += bytes_to_write;
		bytes_remaining -= bytes_to_write;
		address += 4;

		retval = stm32lx_wait_until_bsy_clear(bank);
		if (retval != ERROR_OK)
			goto reset_pg_and_lock;
	}

	offset += bytes_written;
	count -= bytes_written;

	/* this should always pass this check here */
	assert((offset % 128) == 0);

	/* calculate half pages */
	halfpages_number = count / 128;

	if (halfpages_number) {
		retval = stm32lx_write_half_pages(bank, buffer + bytes_written, offset, 128 * halfpages_number);
		if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
			/* attempt slow memory writes */
			LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
			halfpages_number = 0;
		} else {
			if (retval != ERROR_OK)
				return ERROR_FAIL;
		}
	}

	/* write any remaining bytes */
	uint32_t page_bytes_written = 128 * halfpages_number;
	bytes_written += page_bytes_written;
	address += page_bytes_written;
	bytes_remaining = count - page_bytes_written;

	retval = stm32lx_unlock_program_memory(bank);
	if (retval != ERROR_OK)
		return retval;

	while (bytes_remaining > 0) {
		uint8_t value[4] = {0xff, 0xff, 0xff, 0xff};

		/* copy remaining bytes into the write buffer */
		uint32_t bytes_to_write = MIN(4, bytes_remaining);
		memcpy(value, buffer + bytes_written, bytes_to_write);

		retval = target_write_buffer(target, address, 4, value);
		if (retval != ERROR_OK)
			goto reset_pg_and_lock;

		bytes_written += bytes_to_write;
		bytes_remaining -= bytes_to_write;
		address += 4;

		retval = stm32lx_wait_until_bsy_clear(bank);
		if (retval != ERROR_OK)
			goto reset_pg_and_lock;
	}

reset_pg_and_lock:
	retval2 = stm32lx_lock_program_memory(bank);
	if (retval == ERROR_OK)
		retval = retval2;

	return retval;
}
Пример #18
0
static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer,
		uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	uint32_t buffer_size = 16384;
	struct working_area *write_algorithm;
	struct working_area *source;
	uint32_t address = bank->base + offset;

	struct reg_param reg_params[3];
	struct armv7m_algorithm armv7m_info;

	int retval = ERROR_OK;

	/* see contib/loaders/flash/stm32lx.S for src */

	static const uint8_t stm32lx_flash_write_code[] = {
		/* write_word: */
		0x00, 0x23,             /* movs r3, #0 */
		0x04, 0xe0,             /* b test_done */

		/* write_word: */
		0x51, 0xf8, 0x04, 0xcb, /* ldr ip, [r1], #4 */
		0x40, 0xf8, 0x04, 0xcb, /* str ip, [r0], #4 */
		0x01, 0x33,             /* adds r3, #1 */

		/* test_done: */
		0x93, 0x42,             /* cmp r3, r2 */
		0xf8, 0xd3,             /* bcc write_word */
		0x00, 0xbe,             /* bkpt 0 */
	};

	/* Check if there is an even number of half pages (128bytes) */
	if (count % 128) {
		LOG_ERROR("there should be an even number "
				"of half pages = 128 bytes (count = %" PRIi32 " bytes)", count);
		return ERROR_FAIL;
	}

	/* flash write code */
	if (target_alloc_working_area(target, sizeof(stm32lx_flash_write_code),
			&write_algorithm) != ERROR_OK) {
		LOG_DEBUG("no working area for block memory writes");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	};

	/* Write the flashing code */
	retval = target_write_buffer(target,
			write_algorithm->address,
			sizeof(stm32lx_flash_write_code),
			(uint8_t *)stm32lx_flash_write_code);
	if (retval != ERROR_OK) {
		target_free_working_area(target, write_algorithm);
		return retval;
	}

	/* Allocate half pages memory */
	while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
		if (buffer_size > 1024)
			buffer_size -= 1024;
		else
			buffer_size /= 2;

		if (buffer_size <= 256) {
			/* we already allocated the writing code, but failed to get a
			 * buffer, free the algorithm */
			target_free_working_area(target, write_algorithm);

			LOG_WARNING("no large enough working area available, can't do block memory writes");
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	}

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;
	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);

	/* Enable half-page write */
	retval = stm32lx_enable_write_half_page(bank);
	if (retval != ERROR_OK) {
		target_free_working_area(target, source);
		target_free_working_area(target, write_algorithm);

		destroy_reg_param(&reg_params[0]);
		destroy_reg_param(&reg_params[1]);
		destroy_reg_param(&reg_params[2]);
		return retval;
	}

	struct armv7m_common *armv7m = target_to_armv7m(target);
	if (armv7m == NULL) {

		/* something is very wrong if armv7m is NULL */
		LOG_ERROR("unable to get armv7m target");
		return retval;
	}

	/* save any DEMCR flags and configure target to catch any Hard Faults */
	uint32_t demcr_save = armv7m->demcr;
	armv7m->demcr = VC_HARDERR;

	/* Loop while there are bytes to write */
	while (count > 0) {
		uint32_t this_count;
		this_count = (count > buffer_size) ? buffer_size : count;

		/* Write the next half pages */
		retval = target_write_buffer(target, source->address, this_count, buffer);
		if (retval != ERROR_OK)
			break;

		/* 4: Store useful information in the registers */
		/* the destination address of the copy (R0) */
		buf_set_u32(reg_params[0].value, 0, 32, address);
		/* The source address of the copy (R1) */
		buf_set_u32(reg_params[1].value, 0, 32, source->address);
		/* The length of the copy (R2) */
		buf_set_u32(reg_params[2].value, 0, 32, this_count / 4);

		/* 5: Execute the bunch of code */
		retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params)
				/ sizeof(*reg_params), reg_params,
				write_algorithm->address, 0, 10000, &armv7m_info);
		if (retval != ERROR_OK)
			break;

		/* check for Hard Fault */
		if (armv7m->exception_number == 3)
			break;

		/* 6: Wait while busy */
		retval = stm32lx_wait_until_bsy_clear(bank);
		if (retval != ERROR_OK)
			break;

		buffer += this_count;
		address += this_count;
		count -= this_count;
	}

	/* restore previous flags */
	armv7m->demcr = demcr_save;

	if (armv7m->exception_number == 3) {

		/* the stm32l15x devices seem to have an issue when blank.
		 * if a ram loader is executed on a blank device it will
		 * Hard Fault, this issue does not happen for a already programmed device.
		 * A related issue is described in the stm32l151xx errata (Doc ID 17721 Rev 6 - 2.1.3).
		 * The workaround of handling the Hard Fault exception does work, but makes the
		 * loader more complicated, as a compromise we manually write the pages, programming time
		 * is reduced by 50% using this slower method.
		 */

		LOG_WARNING("couldn't use loader, falling back to page memory writes");

		while (count > 0) {
			uint32_t this_count;
			this_count = (count > 128) ? 128 : count;

			/* Write the next half pages */
			retval = target_write_buffer(target, address, this_count, buffer);
			if (retval != ERROR_OK)
				break;

			/* Wait while busy */
			retval = stm32lx_wait_until_bsy_clear(bank);
			if (retval != ERROR_OK)
				break;

			buffer += this_count;
			address += this_count;
			count -= this_count;
		}
	}

	if (retval == ERROR_OK)
		retval = stm32lx_lock_program_memory(bank);

	target_free_working_area(target, source);
	target_free_working_area(target, write_algorithm);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);

	return retval;
}
Пример #19
0
static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
{
	struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
	struct target *target = bank->target;
	uint32_t buffer_size = 16384;
	struct working_area *source;
	uint32_t address = bank->base + offset;
	struct reg_param reg_params[4];
	struct armv7m_algorithm armv7m_info;
	int retval = ERROR_OK;

	uint8_t stm32x_flash_write_code[] = {
									/* write: */
		0xDF, 0xF8, 0x24, 0x40,		/* ldr	r4, STM32_FLASH_CR */
		0x09, 0x4D,					/* ldr	r5, STM32_FLASH_SR */
		0x4F, 0xF0, 0x01, 0x03,		/* mov	r3, #1 */
		0x23, 0x60,					/* str	r3, [r4, #0] */
		0x30, 0xF8, 0x02, 0x3B,		/* ldrh r3, [r0], #2 */
		0x21, 0xF8, 0x02, 0x3B,		/* strh r3, [r1], #2 */
									/* busy: */
		0x2B, 0x68,					/* ldr 	r3, [r5, #0] */
		0x13, 0xF0, 0x01, 0x0F,		/* tst 	r3, #0x01 */
		0xFB, 0xD0,					/* beq 	busy */
		0x13, 0xF0, 0x14, 0x0F,		/* tst	r3, #0x14 */
		0x01, 0xD1,					/* bne	exit */
		0x01, 0x3A,					/* subs	r2, r2, #1 */
		0xED, 0xD1,					/* bne	write */
									/* exit: */
		0xFE, 0xE7,					/* b exit */
		0x10, 0x20, 0x02, 0x40,		/* STM32_FLASH_CR:	.word 0x40022010 */
		0x0C, 0x20, 0x02, 0x40		/* STM32_FLASH_SR:	.word 0x4002200C */
	};

	/* flash write code */
	if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code), &stm32x_info->write_algorithm) != ERROR_OK)
	{
		LOG_WARNING("no working area available, can't do block memory writes");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	};

	if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code)) != ERROR_OK)
		return retval;

	/* memory buffer */
	while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
	{
		buffer_size /= 2;
		if (buffer_size <= 256)
		{
			/* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
			if (stm32x_info->write_algorithm)
				target_free_working_area(target, stm32x_info->write_algorithm);

			LOG_WARNING("no large enough working area available, can't do block memory writes");
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	};

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARMV7M_MODE_ANY;

	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_IN);

	while (count > 0)
	{
		uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;

		if ((retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer)) != ERROR_OK)
			break;

		buf_set_u32(reg_params[0].value, 0, 32, source->address);
		buf_set_u32(reg_params[1].value, 0, 32, address);
		buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);

		if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, stm32x_info->write_algorithm->address, \
				stm32x_info->write_algorithm->address + (sizeof(stm32x_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK)
		{
			LOG_ERROR("error executing stm32x flash write algorithm");
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}

		if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR)
		{
			LOG_ERROR("flash memory not erased before writing");
			/* Clear but report errors */
			target_write_u32(target, STM32_FLASH_SR, FLASH_PGERR);
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}

		if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR)
		{
			LOG_ERROR("flash memory write protected");
			/* Clear but report errors */
			target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR);
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}

		buffer += thisrun_count * 2;
		address += thisrun_count * 2;
		count -= thisrun_count;
	}

	target_free_working_area(target, source);
	target_free_working_area(target, stm32x_info->write_algorithm);

	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 retval;
}
Пример #20
0
static int lpcspifi_erase(struct flash_bank *bank, int first, int last)
{
	struct target *target = bank->target;
	struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
	struct reg_param reg_params[4];
	struct armv7m_algorithm armv7m_info;
	struct working_area *erase_algorithm;
	int retval = ERROR_OK;
	int sector;

	LOG_DEBUG("erase from sector %d to sector %d", 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 (!(lpcspifi_info->probed)) {
		LOG_ERROR("Flash bank not probed");
		return ERROR_FLASH_BANK_NOT_PROBED;
	}

	for (sector = first; sector <= last; sector++) {
		if (bank->sectors[sector].is_protected) {
			LOG_ERROR("Flash sector %d protected", sector);
			return ERROR_FAIL;
		}
	}

	/* If we're erasing the entire chip and the flash supports
	 * 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."\
		" Will use bulk erase instead of sector-by-sector erase.");
		retval = lpcspifi_bulk_erase(bank);

		if (retval == ERROR_OK) {
			retval = lpcspifi_set_hw_mode(bank);
			return retval;
		} else
			LOG_WARNING("Bulk flash erase failed. Falling back to sector-by-sector erase.");
	}

	retval = lpcspifi_set_hw_mode(bank);
	if (retval != ERROR_OK)
		return retval;

	/* see contrib/loaders/flash/lpcspifi_erase.S for src */
	static const uint8_t lpcspifi_flash_erase_code[] = {
		0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
		0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
		0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
		0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
		0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
		0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
		0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
		0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
		0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
		0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
		0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
		0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
		0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
		0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
		0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
		0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
		0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
		0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
		0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
		0x00, 0xf0, 0x52, 0xf8, 0x4f, 0xf0, 0x06, 0x09,
		0x00, 0xf0, 0x3b, 0xf8, 0x00, 0xf0, 0x48, 0xf8,
		0x00, 0xf0, 0x4a, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
		0x00, 0xf0, 0x33, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
		0x00, 0xf0, 0x2f, 0xf8, 0x00, 0xf0, 0x3c, 0xf8,
		0x19, 0xf0, 0x02, 0x0f, 0x00, 0xf0, 0x45, 0x80,
		0x00, 0xf0, 0x3a, 0xf8, 0x4f, 0xea, 0x02, 0x09,
		0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xea, 0x10, 0x49,
		0x00, 0xf0, 0x1f, 0xf8, 0x4f, 0xea, 0x10, 0x29,
		0x00, 0xf0, 0x1b, 0xf8, 0x4f, 0xea, 0x00, 0x09,
		0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, 0x24, 0xf8,
		0x00, 0xf0, 0x26, 0xf8, 0x4f, 0xf0, 0x05, 0x09,
		0x00, 0xf0, 0x0f, 0xf8, 0x4f, 0xf0, 0x00, 0x09,
		0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, 0x18, 0xf8,
		0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4, 0xf0, 0xaf,
		0x01, 0x39, 0xf9, 0xb1, 0x18, 0x44, 0xff, 0xf7,
		0xbf, 0xbf, 0x4f, 0xf4, 0x40, 0x5a, 0xc4, 0xf2,
		0x08, 0x0a, 0xca, 0xf8, 0x08, 0x90, 0xda, 0xf8,
		0x0c, 0x90, 0x19, 0xf0, 0x10, 0x0f, 0x7f, 0xf4,
		0xfa, 0xaf, 0xda, 0xf8, 0x08, 0x90, 0x70, 0x47,
		0x4f, 0xf0, 0xff, 0x08, 0x00, 0xf0, 0x02, 0xb8,
		0x4f, 0xf0, 0x00, 0x08, 0x4f, 0xf4, 0x80, 0x4a,
		0xc4, 0xf2, 0x0f, 0x0a, 0xca, 0xf8, 0xab, 0x80,
		0x70, 0x47, 0x00, 0x20, 0x00, 0xbe, 0xff, 0xff
	};

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;


	/* Get memory for spifi initialization algorithm */
	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"\
			" area of at least %zdB in order to erase SPIFI flash.",
			sizeof(lpcspifi_flash_erase_code));
		return retval;
	}

	/* Write algorithm to working area */
	retval = target_write_buffer(target, erase_algorithm->address,
		sizeof(lpcspifi_flash_erase_code), lpcspifi_flash_erase_code);
	if (retval != ERROR_OK) {
		target_free_working_area(target, erase_algorithm);
		return retval;
	}

	init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);	/* Start address */
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);	/* Sector count */
	init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);	/* Erase command */
	init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);	/* Sector size */

	buf_set_u32(reg_params[0].value, 0, 32, bank->sectors[first].offset);
	buf_set_u32(reg_params[1].value, 0, 32, last - first + 1);
	buf_set_u32(reg_params[2].value, 0, 32, lpcspifi_info->dev->erase_cmd);
	buf_set_u32(reg_params[3].value, 0, 32, bank->sectors[first].size);

	/* Run the algorithm */
	retval = target_run_algorithm(target, 0 , NULL, 4, reg_params,
		erase_algorithm->address,
		erase_algorithm->address + sizeof(lpcspifi_flash_erase_code) - 4,
		3000*(last - first + 1), &armv7m_info);

	if (retval != ERROR_OK)
		LOG_ERROR("Error executing flash erase algorithm");

	target_free_working_area(target, erase_algorithm);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);
	destroy_reg_param(&reg_params[3]);

	retval = lpcspifi_set_hw_mode(bank);

	return retval;
}
Пример #21
0
static int lpcspifi_write(struct flash_bank *bank, uint8_t *buffer,
	uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv;
	uint32_t page_size, fifo_size;
	struct working_area *fifo;
	struct reg_param reg_params[5];
	struct armv7m_algorithm armv7m_info;
	struct working_area *write_algorithm;
	int sector;
	int retval = ERROR_OK;

	LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32,
		offset, count);

	if (target->state != TARGET_HALTED) {
		LOG_ERROR("Target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	if (offset + count > lpcspifi_info->dev->size_in_bytes) {
		LOG_WARNING("Writes past end of flash. Extra data discarded.");
		count = lpcspifi_info->dev->size_in_bytes - offset;
	}

	/* 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? */
		if ((offset <
				(bank->sectors[sector].offset + bank->sectors[sector].size))
			&& ((offset + count - 1) >= bank->sectors[sector].offset)
			&& bank->sectors[sector].is_protected) {
			LOG_ERROR("Flash sector %d protected", sector);
			return ERROR_FAIL;
		}
	}

	page_size = lpcspifi_info->dev->pagesize;

	retval = lpcspifi_set_hw_mode(bank);
	if (retval != ERROR_OK)
		return retval;

	/* see contrib/loaders/flash/lpcspifi_write.S for src */
	static const uint8_t lpcspifi_flash_write_code[] = {
		0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x08, 0x0a,
		0x4f, 0xf0, 0xea, 0x08, 0xca, 0xf8, 0x8c, 0x81,
		0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x90, 0x81,
		0x4f, 0xf0, 0x40, 0x08, 0xca, 0xf8, 0x94, 0x81,
		0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x98, 0x81,
		0x4f, 0xf0, 0xed, 0x08, 0xca, 0xf8, 0x9c, 0x81,
		0x4f, 0xf0, 0x44, 0x08, 0xca, 0xf8, 0xa0, 0x81,
		0x4f, 0xf4, 0xc0, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
		0x4f, 0xf4, 0x00, 0x68, 0xca, 0xf8, 0x14, 0x80,
		0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
		0x4f, 0xf0, 0xff, 0x08, 0xca, 0xf8, 0xab, 0x80,
		0x4f, 0xf0, 0x00, 0x0a, 0xc4, 0xf2, 0x05, 0x0a,
		0x4f, 0xf0, 0x00, 0x08, 0xc0, 0xf2, 0x00, 0x18,
		0xca, 0xf8, 0x94, 0x80, 0x4f, 0xf4, 0x00, 0x5a,
		0xc4, 0xf2, 0x05, 0x0a, 0x4f, 0xf0, 0x01, 0x08,
		0xca, 0xf8, 0x00, 0x87, 0x4f, 0xf4, 0x40, 0x5a,
		0xc4, 0xf2, 0x08, 0x0a, 0x4f, 0xf0, 0x07, 0x08,
		0xca, 0xf8, 0x00, 0x80, 0x4f, 0xf0, 0x02, 0x08,
		0xca, 0xf8, 0x10, 0x80, 0xca, 0xf8, 0x04, 0x80,
		0x4f, 0xf0, 0x00, 0x0b, 0xa3, 0x44, 0x93, 0x45,
		0x7f, 0xf6, 0xfc, 0xaf, 0x00, 0xf0, 0x6a, 0xf8,
		0x4f, 0xf0, 0x06, 0x09, 0x00, 0xf0, 0x53, 0xf8,
		0x00, 0xf0, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8,
		0x4f, 0xf0, 0x05, 0x09, 0x00, 0xf0, 0x4b, 0xf8,
		0x4f, 0xf0, 0x00, 0x09, 0x00, 0xf0, 0x47, 0xf8,
		0x00, 0xf0, 0x54, 0xf8, 0x19, 0xf0, 0x02, 0x0f,
		0x00, 0xf0, 0x5d, 0x80, 0x00, 0xf0, 0x52, 0xf8,
		0x4f, 0xf0, 0x02, 0x09, 0x00, 0xf0, 0x3b, 0xf8,
		0x4f, 0xea, 0x12, 0x49, 0x00, 0xf0, 0x37, 0xf8,
		0x4f, 0xea, 0x12, 0x29, 0x00, 0xf0, 0x33, 0xf8,
		0x4f, 0xea, 0x02, 0x09, 0x00, 0xf0, 0x2f, 0xf8,
		0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f,
		0x00, 0xf0, 0x47, 0x80, 0x47, 0x68, 0x47, 0x45,
		0x3f, 0xf4, 0xf6, 0xaf, 0x17, 0xf8, 0x01, 0x9b,
		0x00, 0xf0, 0x21, 0xf8, 0x8f, 0x42, 0x28, 0xbf,
		0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b,
		0xbb, 0xb3, 0x02, 0xf1, 0x01, 0x02, 0x93, 0x45,
		0x7f, 0xf4, 0xe6, 0xaf, 0x00, 0xf0, 0x22, 0xf8,
		0xa3, 0x44, 0x00, 0xf0, 0x23, 0xf8, 0x4f, 0xf0,
		0x05, 0x09, 0x00, 0xf0, 0x0c, 0xf8, 0x4f, 0xf0,
		0x00, 0x09, 0x00, 0xf0, 0x08, 0xf8, 0x00, 0xf0,
		0x15, 0xf8, 0x19, 0xf0, 0x01, 0x0f, 0x7f, 0xf4,
		0xf0, 0xaf, 0xff, 0xf7, 0xa7, 0xbf, 0x4f, 0xf4,
		0x40, 0x5a, 0xc4, 0xf2, 0x08, 0x0a, 0xca, 0xf8,
		0x08, 0x90, 0xda, 0xf8, 0x0c, 0x90, 0x19, 0xf0,
		0x10, 0x0f, 0x7f, 0xf4, 0xfa, 0xaf, 0xda, 0xf8,
		0x08, 0x90, 0x70, 0x47, 0x4f, 0xf0, 0xff, 0x08,
		0x00, 0xf0, 0x02, 0xb8, 0x4f, 0xf0, 0x00, 0x08,
		0x4f, 0xf4, 0x80, 0x4a, 0xc4, 0xf2, 0x0f, 0x0a,
		0xca, 0xf8, 0xab, 0x80, 0x70, 0x47, 0x00, 0x20,
		0x50, 0x60, 0x30, 0x46, 0x00, 0xbe, 0xff, 0xff
	};

	if (target_alloc_working_area(target, sizeof(lpcspifi_flash_write_code),
			&write_algorithm) != ERROR_OK) {
		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;
	};

	retval = target_write_buffer(target, write_algorithm->address,
			sizeof(lpcspifi_flash_write_code),
			lpcspifi_flash_write_code);
	if (retval != ERROR_OK) {
		target_free_working_area(target, write_algorithm);
		return retval;
	}

	/* FIFO allocation */
	fifo_size = target_get_working_area_avail(target);

	if (fifo_size == 0) {
		/* if we already allocated the writing code but failed to get fifo
		 * space, free the algorithm */
		target_free_working_area(target, write_algorithm);

		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"\
			" to reduce write times.",
			(size_t)(sizeof(lpcspifi_flash_write_code) + page_size)
		);
	else if (fifo_size > 0x2000) /* Beyond this point, we start to get diminishing returns */
		fifo_size = 0x2000;

	if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) {
		target_free_working_area(target, write_algorithm);
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	};

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);		/* buffer start, status (out) */
	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);		/* buffer end */
	init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);		/* target address */
	init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);		/* count (halfword-16bit) */
	init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);		/* page size */

	buf_set_u32(reg_params[0].value, 0, 32, fifo->address);
	buf_set_u32(reg_params[1].value, 0, 32, fifo->address + fifo->size);
	buf_set_u32(reg_params[2].value, 0, 32, offset);
	buf_set_u32(reg_params[3].value, 0, 32, count);
	buf_set_u32(reg_params[4].value, 0, 32, page_size);

	retval = target_run_flash_async_algorithm(target, buffer, count, 1,
			0, NULL,
			5, reg_params,
			fifo->address, fifo->size,
			write_algorithm->address, 0,
			&armv7m_info
	);

	if (retval != ERROR_OK)
		LOG_ERROR("Error executing flash write algorithm");

	target_free_working_area(target, fifo);
	target_free_working_area(target, write_algorithm);

	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]);

	/* Switch to HW mode before return to prompt */
	retval = lpcspifi_set_hw_mode(bank);
	return retval;
}
Пример #22
0
static int str7x_write_block(struct flash_bank *bank, const uint8_t *buffer,
		uint32_t offset, uint32_t count)
{
	struct str7x_flash_bank *str7x_info = bank->driver_priv;
	struct target *target = bank->target;
	uint32_t buffer_size = 32768;
	struct working_area *write_algorithm;
	struct working_area *source;
	uint32_t address = bank->base + offset;
	struct reg_param reg_params[6];
	struct arm_algorithm arm_algo;
	int retval = ERROR_OK;

	/* see contib/loaders/flash/str7x.s for src */

	static const uint32_t str7x_flash_write_code[] = {
					/* write:				*/
		0xe3a04201, /*	mov r4, #0x10000000	*/
		0xe5824000, /*	str r4, [r2, #0x0]	*/
		0xe5821010, /*	str r1, [r2, #0x10]	*/
		0xe4904004, /*	ldr r4, [r0], #4	*/
		0xe5824008, /*	str r4, [r2, #0x8]	*/
		0xe4904004, /*	ldr r4, [r0], #4	*/
		0xe582400c, /*	str r4, [r2, #0xc]	*/
		0xe3a04209, /*	mov r4, #0x90000000	*/
		0xe5824000, /*	str r4, [r2, #0x0]	*/
					/* busy:				*/
		0xe5924000, /*	ldr r4, [r2, #0x0]	*/
		0xe1140005,	/*	tst r4, r5			*/
		0x1afffffc, /*	bne busy			*/
		0xe5924014, /*	ldr r4, [r2, #0x14]	*/
		0xe31400ff, /*	tst r4, #0xff		*/
		0x03140c01, /*	tsteq r4, #0x100	*/
		0x1a000002, /*	bne exit			*/
		0xe2811008, /*	add r1, r1, #0x8	*/
		0xe2533001, /*	subs r3, r3, #1		*/
		0x1affffec, /*	bne write			*/
					/* exit:				*/
		0xeafffffe, /*	b exit				*/
	};

	/* flash write code */
	if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code),
			&write_algorithm) != ERROR_OK) {
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}

	uint8_t code[sizeof(str7x_flash_write_code)];
	target_buffer_set_u32_array(target, code, ARRAY_SIZE(str7x_flash_write_code),
			str7x_flash_write_code);
	target_write_buffer(target, write_algorithm->address, sizeof(code), code);

	/* memory buffer */
	while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
		buffer_size /= 2;
		if (buffer_size <= 256) {
			/* we already allocated the writing code, but failed to get a
			 * buffer, free the algorithm */
			target_free_working_area(target, write_algorithm);

			LOG_WARNING("no large enough working area available, can't do block memory writes");
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	}

	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);
	init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
	init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);

	while (count > 0) {
		uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;

		target_write_buffer(target, source->address, thisrun_count * 8, buffer);

		buf_set_u32(reg_params[0].value, 0, 32, source->address);
		buf_set_u32(reg_params[1].value, 0, 32, address);
		buf_set_u32(reg_params[2].value, 0, 32, str7x_get_flash_adr(bank, FLASH_CR0));
		buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
		buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits);

		retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
				write_algorithm->address,
				write_algorithm->address + (sizeof(str7x_flash_write_code) - 4),
				10000, &arm_algo);
		if (retval != ERROR_OK)
			break;

		if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00) {
			retval = str7x_result(bank);
			break;
		}

		buffer += thisrun_count * 8;
		address += thisrun_count * 8;
		count -= thisrun_count;
	}

	target_free_working_area(target, source);
	target_free_working_area(target, write_algorithm);

	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_reg_param(&reg_params[5]);

	return retval;
}
Пример #23
0
/** Checks whether a memory region is zeroed. */
int xmc4xxx_blank_check_memory(struct target *target,
	uint32_t address, uint32_t count, uint32_t *blank)
{
	struct working_area *erase_check_algorithm;
	struct reg_param reg_params[3];
	struct armv7m_algorithm armv7m_info;
	int retval;

	/* see contrib/loaders/erase_check/armv7m_0_erase_check.s for src */

	static const uint8_t erase_check_code[] = {
		/* loop: */
		0x03, 0x78,		/* ldrb	r3, [r0] */
		0x01, 0x30,		/* adds	r0, #1 */
		0x1A, 0x43,		/* orrs	r2, r2, r3 */
		0x01, 0x39,		/* subs	r1, r1, #1 */
		0xFA, 0xD1,		/* bne	loop */
		0x00, 0xBE		/* bkpt	#0 */
	};

	/* make sure we have a working area */
	if (target_alloc_working_area(target, sizeof(erase_check_code),
		&erase_check_algorithm) != ERROR_OK)
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;

	retval = target_write_buffer(target, erase_check_algorithm->address,
			sizeof(erase_check_code), (uint8_t *)erase_check_code);
	if (retval != ERROR_OK)
		return retval;

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARM_MODE_THREAD;

	init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
	buf_set_u32(reg_params[0].value, 0, 32, address);

	init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
	buf_set_u32(reg_params[1].value, 0, 32, count);

	init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
	buf_set_u32(reg_params[2].value, 0, 32, 0x00);

	retval = target_run_algorithm(target,
				      0,
				      NULL,
				      3,
				      reg_params,
				      erase_check_algorithm->address,
				      erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
				      10000,
				      &armv7m_info);

	if (retval == ERROR_OK)
		*blank = buf_get_u32(reg_params[2].value, 0, 32);

	destroy_reg_param(&reg_params[0]);
	destroy_reg_param(&reg_params[1]);
	destroy_reg_param(&reg_params[2]);

	target_free_working_area(target, erase_check_algorithm);

	return retval;
}
Пример #24
0
/** Starts a Thumb algorithm in the target. */
int armv7m_start_algorithm(struct target *target,
	int num_mem_params, struct mem_param *mem_params,
	int num_reg_params, struct reg_param *reg_params,
	target_addr_t entry_point, target_addr_t exit_point,
	void *arch_info)
{
	struct armv7m_common *armv7m = target_to_armv7m(target);
	struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
	enum arm_mode core_mode = armv7m->arm.core_mode;
	int retval = ERROR_OK;

	/* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
	 * at the exit point */

	if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
		LOG_ERROR("current target isn't an ARMV7M target");
		return ERROR_TARGET_INVALID;
	}

	if (target->state != TARGET_HALTED) {
		LOG_WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	/* refresh core register cache
	 * Not needed if core register cache is always consistent with target process state */
	for (unsigned i = 0; i < armv7m->arm.core_cache->num_regs; i++) {

		armv7m_algorithm_info->context[i] = buf_get_u32(
				armv7m->arm.core_cache->reg_list[i].value,
				0,
				32);
	}

	for (int i = 0; i < num_mem_params; i++) {
		/* TODO: Write only out params */
		retval = target_write_buffer(target, mem_params[i].address,
				mem_params[i].size,
				mem_params[i].value);
		if (retval != ERROR_OK)
			return retval;
	}

	for (int i = 0; i < num_reg_params; i++) {
		struct reg *reg =
			register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, 0);
/*		uint32_t regvalue; */

		if (!reg) {
			LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
			return ERROR_COMMAND_SYNTAX_ERROR;
		}

		if (reg->size != reg_params[i].size) {
			LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
				reg_params[i].reg_name);
			return ERROR_COMMAND_SYNTAX_ERROR;
		}

/*		regvalue = buf_get_u32(reg_params[i].value, 0, 32); */
		armv7m_set_core_reg(reg, reg_params[i].value);
	}

	if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY &&
			armv7m_algorithm_info->core_mode != core_mode) {

		/* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */
		if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) {
			armv7m_algorithm_info->core_mode = ARM_MODE_THREAD;
			LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead");
		}

		LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
		buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
			0, 1, armv7m_algorithm_info->core_mode);
		armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
		armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
	}

	/* save previous core mode */
	armv7m_algorithm_info->core_mode = core_mode;

	retval = target_resume(target, 0, entry_point, 1, 1);

	return retval;
}
Пример #25
0
/** Starts a Thumb algorithm in the target. */
int armv7m_start_algorithm(struct target *target,
	int num_mem_params, struct mem_param *mem_params,
	int num_reg_params, struct reg_param *reg_params,
	uint32_t entry_point, uint32_t exit_point,
	void *arch_info)
{
	struct armv7m_common *armv7m = target_to_armv7m(target);
	struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
	enum armv7m_mode core_mode = armv7m->core_mode;
	int retval = ERROR_OK;

	/* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
	 * at the exit point */

	if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
	{
		LOG_ERROR("current target isn't an ARMV7M target");
		return ERROR_TARGET_INVALID;
	}

	if (target->state != TARGET_HALTED)
	{
		LOG_WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	/* refresh core register cache */
	/* Not needed if core register cache is always consistent with target process state */
	for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++)
	{
		if (!armv7m->core_cache->reg_list[i].valid)
			armv7m->read_core_reg(target, i);
		armv7m_algorithm_info->context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
	}

	for (int i = 0; i < num_mem_params; i++)
	{
		// TODO: Write only out params
		if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
			return retval;
	}

	for (int i = 0; i < num_reg_params; i++)
	{
		struct reg *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
//		uint32_t regvalue;

		if (!reg)
		{
			LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
			return ERROR_INVALID_ARGUMENTS;
		}

		if (reg->size != reg_params[i].size)
		{
			LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
			return ERROR_INVALID_ARGUMENTS;
		}

//		regvalue = buf_get_u32(reg_params[i].value, 0, 32);
		armv7m_set_core_reg(reg, reg_params[i].value);
	}

	if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY)
	{
		LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value,
				0, 1, armv7m_algorithm_info->core_mode);
		armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
		armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
	}
	armv7m_algorithm_info->core_mode = core_mode;

	retval = target_resume(target, 0, entry_point, 1, 1);

	return retval;
}
Пример #26
0
static int stm32x_write_block(struct flash_bank *bank, uint8_t *buffer,
		uint32_t offset, uint32_t count)
{
	struct stm32x_flash_bank *stm32x_info = bank->driver_priv;
	struct target *target = bank->target;
	uint32_t buffer_size = 16384;
	struct working_area *source;
	uint32_t address = bank->base + offset;
	struct reg_param reg_params[4];
	struct armv7m_algorithm armv7m_info;
	int retval = ERROR_OK;

	/* see contib/loaders/flash/stm32x.s for src */

	static const uint8_t stm32x_flash_write_code[] = {
									/* #define STM32_FLASH_CR_OFFSET	0x10 */
									/* #define STM32_FLASH_SR_OFFSET	0x0C */
									/* write: */
		0x08, 0x4c,					/* ldr	r4, STM32_FLASH_BASE */
		0x1c, 0x44,					/* add	r4, r3 */
									/* write_half_word: */
		0x01, 0x23,					/* movs	r3, #0x01 */
		0x23, 0x61,					/* str	r3, [r4, #STM32_FLASH_CR_OFFSET] */
		0x30, 0xf8, 0x02, 0x3b,		/* ldrh	r3, [r0], #0x02 */
		0x21, 0xf8, 0x02, 0x3b,		/* strh	r3, [r1], #0x02 */
									/* busy: */
		0xe3, 0x68,					/* ldr	r3, [r4, #STM32_FLASH_SR_OFFSET] */
		0x13, 0xf0, 0x01, 0x0f,		/* tst	r3, #0x01 */
		0xfb, 0xd0,					/* beq	busy */
		0x13, 0xf0, 0x14, 0x0f,		/* tst	r3, #0x14 */
		0x01, 0xd1,					/* bne	exit */
		0x01, 0x3a,					/* subs	r2, r2, #0x01 */
		0xf0, 0xd1,					/* bne	write_half_word */
									/* exit: */
		0x00, 0xbe,					/* bkpt	#0x00 */
		0x00, 0x20, 0x02, 0x40,		/* STM32_FLASH_BASE: .word 0x40022000 */
	};

	/* flash write code */
	if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code),
			&stm32x_info->write_algorithm) != ERROR_OK)
	{
		LOG_WARNING("no working area available, can't do block memory writes");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	};

	if ((retval = target_write_buffer(target, stm32x_info->write_algorithm->address,
			sizeof(stm32x_flash_write_code),
			(uint8_t*)stm32x_flash_write_code)) != ERROR_OK)
		return retval;

	/* memory buffer */
	while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
	{
		buffer_size /= 2;
		if (buffer_size <= 256)
		{
			/* if we already allocated the writing code, but failed to get a
			 * buffer, free the algorithm */
			if (stm32x_info->write_algorithm)
				target_free_working_area(target, stm32x_info->write_algorithm);

			LOG_WARNING("no large enough working area available, can't do block memory writes");
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	};

	armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	armv7m_info.core_mode = ARMV7M_MODE_ANY;

	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_IN_OUT);

	while (count > 0)
	{
		uint32_t thisrun_count = (count > (buffer_size / 2)) ?
				(buffer_size / 2) : count;

		if ((retval = target_write_buffer(target, source->address,
				thisrun_count * 2, buffer)) != ERROR_OK)
			break;

		buf_set_u32(reg_params[0].value, 0, 32, source->address);
		buf_set_u32(reg_params[1].value, 0, 32, address);
		buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
		buf_set_u32(reg_params[3].value, 0, 32, stm32x_info->register_offset);

		if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
				stm32x_info->write_algorithm->address,
				0,
				10000, &armv7m_info)) != ERROR_OK)
		{
			LOG_ERROR("error executing stm32x flash write algorithm");
			break;
		}

		if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR)
		{
			LOG_ERROR("flash memory not erased before writing");
			/* Clear but report errors */
			target_write_u32(target, STM32_FLASH_SR, FLASH_PGERR);
			retval = ERROR_FAIL;
			break;
		}

		if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR)
		{
			LOG_ERROR("flash memory write protected");
			/* Clear but report errors */
			target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR);
			retval = ERROR_FAIL;
			break;
		}

		buffer += thisrun_count * 2;
		address += thisrun_count * 2;
		count -= thisrun_count;
	}

	target_free_working_area(target, source);
	target_free_working_area(target, stm32x_info->write_algorithm);

	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 retval;
}
Пример #27
0
/* If this fn returns ERROR_TARGET_RESOURCE_NOT_AVAILABLE, then the caller can fall
 * back to another mechanism that does not require onboard RAM
 *
 * Caller should not check for other return values specifically
 */
static int aduc702x_write_block(struct flash_bank *bank,
	const uint8_t *buffer,
	uint32_t offset,
	uint32_t count)
{
	struct target *target = bank->target;
	uint32_t buffer_size = 7000;
	struct working_area *write_algorithm;
	struct working_area *source;
	uint32_t address = bank->base + offset;
	struct reg_param reg_params[6];
	struct arm_algorithm arm_algo;
	int retval = ERROR_OK;

	if (((count%2) != 0) || ((offset%2) != 0)) {
		LOG_ERROR("write block must be multiple of two bytes in offset & length");
		return ERROR_FAIL;
	}

	/* parameters:

	r0 - address of source data (absolute)
	r1 - number of halfwords to be copied
	r2 - start address in flash (offset from beginning of flash memory)
	r3 - exit code
	r4 - base address of flash controller (0xFFFFF800)

	registers:

	r5 - scratch
	r6 - set to 2, used to write flash command

	*/
	static const uint32_t aduc702x_flash_write_code[] = {
		/* <_start>: */
		0xe3a05008,	/* mov	r5, #8	; 0x8 */
		0xe5845004,	/* str	r5, [r4, #4] */
		0xe3a06002,	/* mov	r6, #2	; 0x2 */
		/* <next>: */
		0xe1c421b0,	/* strh	r2, [r4, #16] */
		0xe0d050b2,	/* ldrh	r5, [r0], #2 */
		0xe1c450bc,	/* strh	r5, [r4, #12] */
		0xe5c46008,	/* strb	r6, [r4, #8] */
		/* <wait_complete>: */
		0xe1d430b0,	/* ldrh	r3, [r4] */
		0xe3130004,	/* tst	r3, #4	; 0x4 */
		0x1afffffc,	/* bne	1001c <wait_complete> */
		0xe2822002,	/* add	r2, r2, #2	; 0x2 */
		0xe2511001,	/* subs	r1, r1, #1	; 0x1 */
		0x0a000001,	/* beq	1003c <done> */
		0xe3130001,	/* tst	r3, #1	; 0x1 */
		0x1afffff3,	/* bne	1000c <next> */
		/* <done>: */
		0xeafffffe	/* b	1003c <done> */
	};

	/* flash write code */
	if (target_alloc_working_area(target, sizeof(aduc702x_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;
	}

	uint8_t code[sizeof(aduc702x_flash_write_code)];
	target_buffer_set_u32_array(target, code, ARRAY_SIZE(aduc702x_flash_write_code),
			aduc702x_flash_write_code);
	retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code);
	if (retval != ERROR_OK)
		return retval;

	/* memory buffer */
	while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
		buffer_size /= 2;
		if (buffer_size <= 256) {
			/* we already allocated the writing code, but failed to get a buffer,
			 *free the algorithm */
			target_free_working_area(target, write_algorithm);

			LOG_WARNING("no large enough working area available, can't do block memory writes");
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	}

	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_IN);
	init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT);

	while (count > 0) {
		uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count;

		retval = target_write_buffer(target, source->address, thisrun_count, buffer);
		if (retval != ERROR_OK)
			break;

		buf_set_u32(reg_params[0].value, 0, 32, source->address);
		buf_set_u32(reg_params[1].value, 0, 32, thisrun_count/2);
		buf_set_u32(reg_params[2].value, 0, 32, address);
		buf_set_u32(reg_params[4].value, 0, 32, 0xFFFFF800);

		retval = target_run_algorithm(target, 0, NULL, 5,
				reg_params, write_algorithm->address,
				write_algorithm->address +
				sizeof(aduc702x_flash_write_code) - 4,
				10000, &arm_algo);
		if (retval != ERROR_OK) {
			LOG_ERROR("error executing aduc702x flash write algorithm");
			break;
		}

		if ((buf_get_u32(reg_params[3].value, 0, 32) & 1) != 1) {
			/* FIX!!!! what does this mean??? replace w/sensible error message */
			LOG_ERROR("aduc702x detected error writing flash");
			retval = ERROR_FAIL;
			break;
		}

		buffer += thisrun_count;
		address += thisrun_count;
		count -= thisrun_count;
	}

	target_free_working_area(target, source);
	target_free_working_area(target, write_algorithm);

	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]);

	return retval;
}
Пример #28
0
static int msp432_init(struct flash_bank *bank)
{
	struct target *target = bank->target;
	struct msp432_bank *msp432_bank = bank->driver_priv;
	struct msp432_algo_params algo_params;
	struct reg_param reg_params[1];

	const uint8_t *loader_code;
	uint32_t loader_size;
	uint32_t algo_entry_addr;
	int retval;

	/* Make sure we've probed the flash to get the device and size */
	retval = msp432_auto_probe(bank);
	if (ERROR_OK != retval)
		return retval;

	/* Choose appropriate flash helper algorithm */
	switch (msp432_bank->device_type) {
		case MSP432P401X:
		case MSP432P401X_DEPR:
		case MSP432P401X_GUESS:
		default:
			loader_code = msp432p401x_algo;
			loader_size = sizeof(msp432p401x_algo);
			algo_entry_addr = P4_ALGO_ENTRY_ADDR;
			break;
		case MSP432P411X:
		case MSP432P411X_GUESS:
			loader_code = msp432p411x_algo;
			loader_size = sizeof(msp432p411x_algo);
			algo_entry_addr = P4_ALGO_ENTRY_ADDR;
			break;
		case MSP432E401Y:
		case MSP432E411Y:
		case MSP432E4X_GUESS:
			loader_code = msp432e4x_algo;
			loader_size = sizeof(msp432e4x_algo);
			algo_entry_addr = E4_ALGO_ENTRY_ADDR;
			break;
	}

	/* Issue warnings if this is a device we may not be able to flash */
	if (MSP432P401X_GUESS == msp432_bank->device_type ||
		MSP432P411X_GUESS == msp432_bank->device_type) {
		/* Explicit device type check failed. Report this. */
		LOG_WARNING(
			"msp432: Unrecognized MSP432P4 Device ID and Hardware "
			"Rev (%04X, %02X)", msp432_bank->device_id,
			msp432_bank->hardware_rev);
	} else if (MSP432P401X_DEPR == msp432_bank->device_type) {
		LOG_WARNING(
			"msp432: MSP432P401x pre-production device (deprecated "
			"silicon)\n" SUPPORT_MESSAGE);
	} else if (MSP432E4X_GUESS == msp432_bank->device_type) {
		/* Explicit device type check failed. Report this. */
		LOG_WARNING(
			"msp432: Unrecognized MSP432E4 DID0 and DID1 values "
			"(%08X, %08X)", msp432_bank->device_id,
			msp432_bank->hardware_rev);
	}

	/* Check for working area to use for flash helper algorithm */
	if (NULL != msp432_bank->working_area)
		target_free_working_area(target, msp432_bank->working_area);
	retval = target_alloc_working_area(target, ALGO_WORKING_SIZE,
				&msp432_bank->working_area);
	if (ERROR_OK != retval)
		return retval;

	/* Confirm the defined working address is the area we need to use */
	if (ALGO_BASE_ADDR != msp432_bank->working_area->address)
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;

	/* Write flash helper algorithm into target memory */
	retval = target_write_buffer(target, ALGO_BASE_ADDR, loader_size,
				loader_code);
	if (ERROR_OK != retval)
		return retval;

	/* Initialize the ARMv7 specific info to run the algorithm */
	msp432_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
	msp432_bank->armv7m_info.core_mode = ARM_MODE_THREAD;

	/* Initialize algorithm parameters to default values */
	msp432_init_params(&algo_params);

	/* Write out parameters to target memory */
	retval = target_write_buffer(target, ALGO_PARAMS_BASE_ADDR,
				sizeof(algo_params), (uint8_t *)&algo_params);
	if (ERROR_OK != retval)
		return retval;

	/* Initialize stack pointer for flash helper algorithm */
	init_reg_param(&reg_params[0], "sp", 32, PARAM_OUT);
	buf_set_u32(reg_params[0].value, 0, 32, ALGO_STACK_POINTER_ADDR);

	/* Begin executing the flash helper algorithm */
	retval = target_start_algorithm(target, 0, 0, 1, reg_params,
				algo_entry_addr, 0, &msp432_bank->armv7m_info);
	destroy_reg_param(&reg_params[0]);
	if (ERROR_OK != retval) {
		LOG_ERROR("msp432: Failed to start flash helper algorithm");
		return retval;
	}

	/*
	 * At this point, the algorithm is running on the target and
	 * ready to receive commands and data to flash the target
	 */

	/* Issue the init command to the flash helper algorithm */
	retval = msp432_exec_cmd(target, &algo_params, FLASH_INIT);
	if (ERROR_OK != retval)
		return retval;

	retval = msp432_wait_return_code(target);

	return retval;
}
Пример #29
0
static int str9x_write_block(struct flash_bank *bank,
		const uint8_t *buffer, uint32_t offset, uint32_t count)
{
	struct target *target = bank->target;
	uint32_t buffer_size = 32768;
	struct working_area *write_algorithm;
	struct working_area *source;
	uint32_t address = bank->base + offset;
	struct reg_param reg_params[4];
	struct arm_algorithm arm_algo;
	int retval = ERROR_OK;

	/* see contib/loaders/flash/str9x.s for src */

	static const uint32_t str9x_flash_write_code[] = {
					/* write:				*/
		0xe3c14003,	/*	bic	r4, r1, #3		*/
		0xe3a03040,	/*	mov	r3, #0x40		*/
		0xe1c430b0,	/*	strh r3, [r4, #0]	*/
		0xe0d030b2,	/*	ldrh r3, [r0], #2	*/
		0xe0c130b2,	/*	strh r3, [r1], #2	*/
		0xe3a03070,	/*	mov r3, #0x70		*/
		0xe1c430b0,	/*	strh r3, [r4, #0]	*/
					/* busy:				*/
		0xe5d43000,	/*	ldrb r3, [r4, #0]	*/
		0xe3130080,	/*	tst r3, #0x80		*/
		0x0afffffc,	/*	beq busy			*/
		0xe3a05050,	/*	mov	r5, #0x50		*/
		0xe1c450b0,	/*	strh r5, [r4, #0]	*/
		0xe3a050ff,	/*	mov	r5, #0xFF		*/
		0xe1c450b0,	/*	strh r5, [r4, #0]	*/
		0xe3130012,	/*	tst	r3, #0x12		*/
		0x1a000001,	/*	bne exit			*/
		0xe2522001,	/*	subs r2, r2, #1		*/
		0x1affffed,	/*	bne write			*/
					/* exit:				*/
		0xe1200070,	/*	bkpt #0				*/
	};

	/* flash write code */
	if (target_alloc_working_area(target, sizeof(str9x_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;
	};

	uint8_t code[sizeof(str9x_flash_write_code)];
	target_buffer_set_u32_array(target, code, ARRAY_SIZE(str9x_flash_write_code),
			str9x_flash_write_code);
	target_write_buffer(target, write_algorithm->address, sizeof(code), code);

	/* memory buffer */
	while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
		buffer_size /= 2;
		if (buffer_size <= 256) {
			/* we already allocated the writing code, but failed to get a
			 * buffer, free the algorithm */
			target_free_working_area(target, write_algorithm);

			LOG_WARNING("no large enough working area available, can't do block memory writes");
			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
		}
	}

	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_IN);

	while (count > 0) {
		uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;

		target_write_buffer(target, source->address, thisrun_count * 2, buffer);

		buf_set_u32(reg_params[0].value, 0, 32, source->address);
		buf_set_u32(reg_params[1].value, 0, 32, address);
		buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);

		retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
				write_algorithm->address,
				0, 10000, &arm_algo);
		if (retval != ERROR_OK) {
			LOG_ERROR("error executing str9x flash write algorithm");
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}

		if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80) {
			retval = ERROR_FLASH_OPERATION_FAILED;
			break;
		}

		buffer += thisrun_count * 2;
		address += thisrun_count * 2;
		count -= thisrun_count;
	}

	target_free_working_area(target, source);
	target_free_working_area(target, write_algorithm);

	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 retval;
}
Пример #30
0
static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
{
	uint8_t page_buffer[FLASH_PAGE_SIZE];
	uint32_t status, source_offset, dest_offset;
	struct target *target = bank->target;
	uint32_t bytes_remaining = count;
	uint32_t first_sector, last_sector, sector, page;
	int i;

	/* probed? halted? */
	status = lpc288x_system_ready(bank);
	if (status != ERROR_OK)
		return status;

	/* Initialise search indices */
	first_sector = last_sector = 0xffffffff;

	/* validate the write range... */
	for (i = 0; i < bank->num_sectors; i++) {
		if ((offset >= bank->sectors[i].offset) &&
				(offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
				(first_sector == 0xffffffff)) {
			first_sector = i;
			/* all writes must start on a sector boundary... */
			if (offset % bank->sectors[i].size) {
				LOG_INFO(
					"offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "",
					offset,
					bank->sectors[i].size);
				return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
			}
		}
		if (((offset + count) > bank->sectors[i].offset) &&
				((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
				(last_sector == 0xffffffff))
			last_sector = i;
	}

	/* Range check... */
	if (first_sector == 0xffffffff || last_sector == 0xffffffff) {
		LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
		return ERROR_FLASH_DST_OUT_OF_BANK;
	}

	/* Configure the flash controller timing */
	lpc288x_set_flash_clk(bank);

	/* initialise the offsets */
	source_offset = 0;
	dest_offset = 0;

	for (sector = first_sector; sector <= last_sector; sector++) {
		for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++) {
			if (bytes_remaining == 0) {
				count = 0;
				memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
			} else if (bytes_remaining < FLASH_PAGE_SIZE) {
				count = bytes_remaining;
				memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
				memcpy(page_buffer, &buffer[source_offset], count);
			} else {
				count = FLASH_PAGE_SIZE;
				memcpy(page_buffer, &buffer[source_offset], count);
			}

			/* Wait for flash to become ready */
			if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
				return ERROR_FLASH_OPERATION_FAILED;

			/* fill flash data latches with 1's */
			target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);

			target_write_u32(target, F_CTRL, FC_CS | FC_WEN | FC_FUNC);

			if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE,
					page_buffer) != ERROR_OK) {
				LOG_INFO("Write to flash buffer failed");
				return ERROR_FLASH_OPERATION_FAILED;
			}

			dest_offset += FLASH_PAGE_SIZE;
			source_offset += count;
			bytes_remaining -= count;

			lpc288x_load_timer(LOAD_TIMER_WRITE, target);

			target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC |
				FC_CS);
		}
	}

	return ERROR_OK;
}