Beispiel #1
0
/* Write byte at address */
static int arc_mem_write_block8(struct target *target, uint32_t addr,
	uint32_t count, void *buf)
{
	struct arc32_common *arc32 = target_to_arc32(target);
	uint32_t i;

	LOG_DEBUG("Write 1-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32,
			addr, count);

	/* We will read data from memory, so we need to flush D$. */
	CHECK_RETVAL(arc32_dcache_flush(target));

	uint32_t buffer_he;
	uint8_t buffer_te[sizeof(uint32_t)];
	/* non-word writes are less common, than 4-byte writes, so I suppose we can
	 * allowe ourselves to write this in a cycle, instead of calling arc_jtag
	 * with count > 1. */
	for(i = 0; i < count; i++) {
		/* See comment in arc_mem_write_block16 for details. Since it is a byte
		 * there is not need to convert write buffer to target endianness, but
		 * we still have to convert read buffer. */
		CHECK_RETVAL(arc_jtag_read_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he,
			    arc_mem_is_slow_memory(arc32, (addr + i) & ~3, 4, 1)));
		target_buffer_set_u32(target, buffer_te, buffer_he);
		memcpy(buffer_te  + ((addr + i) & 3), (uint8_t*)buf + i, 1);
		buffer_he = target_buffer_get_u32(target, buffer_te);
		CHECK_RETVAL(arc_jtag_write_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he));
	}

	/* Invalidate caches. */
	CHECK_RETVAL(arc32_cache_invalidate(target));

	return ERROR_OK;
}
Beispiel #2
0
/* Write half-word at half-word-aligned address */
static int arc_mem_write_block16(struct target *target, uint32_t addr, int count,
	void *buf)
{
	struct arc32_common *arc32 = target_to_arc32(target);
	int retval = ERROR_OK;
	int i;

	LOG_DEBUG("Write memory (16bit): addr=0x%" PRIx32 ", count=%i", addr, count);

	/* Check arguments */
	if (addr & 1u)
		return ERROR_TARGET_UNALIGNED_ACCESS;

	/* We will read data from memory, so we need to flush D$. */
	retval = arc32_dcache_flush(target);
	if (ERROR_OK != retval)
		return retval;

	uint32_t buffer_he;
	uint8_t buffer_te[sizeof(uint32_t)];
	uint8_t halfword_te[sizeof(uint16_t)];
	/* non-word writes are less common, than 4-byte writes, so I suppose we can
	 * allowe ourselves to write this in a cycle, instead of calling arc_jtag
	 * with count > 1. */
	for(i = 0; i < count; i++) {
		/* We can read only word at word-aligned address. Also *jtag_read_memory
		 * functions return data in host endianness, so host endianness !=
		 * target endianness we have to convert data back to target endianness,
		 * or bytes will be at the wrong places.So:
		 *   1) read word
		 *   2) convert to target endianness
		 *   3) make changes
		 *   4) convert back to host endianness
		 *   5) write word back to target.
		 */
		retval = arc_jtag_read_memory(&arc32->jtag_info,
				(addr + i * sizeof(uint16_t)) & ~3u, 1, &buffer_he);
		target_buffer_set_u32(target, buffer_te, buffer_he);
		/* buf is in host endianness, convert to target */
		target_buffer_set_u16(target, halfword_te, ((uint16_t *)buf)[i]);
		memcpy(buffer_te  + ((addr + i * sizeof(uint16_t)) & 3u),
                        halfword_te, sizeof(uint16_t));
		buffer_he = target_buffer_get_u32(target, buffer_te);
		retval = arc_jtag_write_memory(&arc32->jtag_info,
                        (addr + i * sizeof(uint16_t)) & ~3u, 1, &buffer_he);

		if (ERROR_OK != retval)
			return retval;
	}

	/* Invalidate caches. */
	retval = arc32_cache_invalidate(target);

	return retval;
}
Beispiel #3
0
/* Write word at word-aligned address */
static int arc_mem_write_block32(struct target *target, uint32_t addr,
	uint32_t count, void *buf)
{
	struct arc32_common *arc32 = target_to_arc32(target);

	LOG_DEBUG("Write 4-byte memory block: addr=0x%08" PRIx32 ", count=%" PRIu32,
			addr, count);

	/* Check arguments */
	assert(!(addr & 3));

	/* No need to flush cache, because we don't read values from memory. */
	CHECK_RETVAL(arc_jtag_write_memory( &arc32->jtag_info, addr, count,
				(uint32_t *)buf));
	/* Invalidate caches. */
	CHECK_RETVAL(arc32_cache_invalidate(target));

	return ERROR_OK;
}
Beispiel #4
0
/* Write word at word-aligned address */
static int arc_mem_write_block32(struct target *target, uint32_t addr, int count,
	void *buf)
{
	struct arc32_common *arc32 = target_to_arc32(target);
	int retval = ERROR_OK;

	/* Check arguments */
	if (addr & 0x3u)
		return ERROR_TARGET_UNALIGNED_ACCESS;

	/* No need to flush cache, because we don't read values from memory. */
	retval = arc_jtag_write_memory( &arc32->jtag_info, addr, count, (uint32_t *)buf);
	if (ERROR_OK != retval)
		return retval;

	/* Invalidate caches. */
	retval = arc32_cache_invalidate(target);

	return retval;
}
Beispiel #5
0
/* Write byte at address */
static int arc_mem_write_block8(struct target *target, uint32_t addr, int count,
	void *buf)
{
	struct arc32_common *arc32 = target_to_arc32(target);
	int retval = ERROR_OK;
	int i;

	/* We will read data from memory, so we need to flush D$. */
	retval = arc32_dcache_flush(target);
	if (ERROR_OK != retval)
		return retval;

	uint32_t buffer_he;
	uint8_t buffer_te[sizeof(uint32_t)];
	/* non-word writes are less common, than 4-byte writes, so I suppose we can
	 * allowe ourselves to write this in a cycle, instead of calling arc_jtag
	 * with count > 1. */
	for(i = 0; i < count; i++) {
		/* See comment in arc_mem_write_block16 for details. Since it is a byte
		 * there is not need to convert write buffer to target endianness, but
		 * we still have to convert read buffer. */
		retval = arc_jtag_read_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he);
		target_buffer_set_u32(target, buffer_te, buffer_he);
		memcpy(buffer_te  + ((addr + i) & 3), (uint8_t*)buf + i, 1);
		buffer_he = target_buffer_get_u32(target, buffer_te);
		retval = arc_jtag_write_memory(&arc32->jtag_info, (addr + i) & ~3, 1, &buffer_he);

		if (ERROR_OK != retval)
			return retval;
	}

	/* Invalidate caches. */
	retval = arc32_cache_invalidate(target);

	return retval;
}