/**
 * \brief Test the data integrity
 *
 * Tests the integrity of the entire SDRAM by filling it a sequence of
 * incrementing 32-bit values and then verifying its content.
 * This is done in two passes, with an inversion of the content after
 * the first pass of verification.
 *
 * \note This test does not give 100% coverage for possible faults in SDRAM.
 * For exhaustive testing of memory, you may refer to literature on MARCH test
 * algorithms.
 *
 * \param test Current test case.
 */
void run_data_integrity_test(const struct test_case *test)
{
	struct ebi_test_params *params;
	hugemem_ptr_t          base;
	uint32_t               size;
	uint32_t               offset;
	uint32_t               pattern;

	params = (struct ebi_test_params *)test_get_data();
	base = params->base;
	size = params->size;

	// Fill memory with a known pattern.
	for (pattern = 1, offset = 0; offset < size; pattern++,
			offset += sizeof(uint32_t)) {
		hugemem_ptr_t p;

		p = (hugemem_ptr_t)((uint32_t)base + offset);
		hugemem_write32(p, pattern);
	}

	// Check each location and invert it for the second pass.
	for (pattern = 1, offset = 0; offset < size; pattern++,
			offset += sizeof(uint32_t)) {
		hugemem_ptr_t p;
		uint32_t      actual;
		uint32_t      expected;

		p = (hugemem_ptr_t)((uint32_t)base + offset);

		actual = hugemem_read32(p);
		test_assert_true(test, actual == pattern,
				"Read 0x%08lx @ 0x%08lx, expected 0x%08lx",
				actual, (uint32_t)p, pattern);

		expected = ~pattern;
		hugemem_write32(p, expected);
	}

	// Check each location for the inverted pattern and zero it.
	for (pattern = 1, offset = 0; offset < size; pattern++,
			offset += sizeof(uint32_t)) {
		hugemem_ptr_t p;
		uint32_t      actual;
		uint32_t      expected;

		p = (hugemem_ptr_t)((uint32_t)base + offset);

		expected = ~pattern;
		actual = hugemem_read32(p);
		test_assert_true(test, actual == expected,
				"Read 0x%08lx @ 0x%08lx, expected 0x%08lx",
				actual, (uint32_t)p, expected);
	}
}
Example #2
0
/**
 * \brief Perform a SDRAM data integrity test
 *
 * This function will perform a SDRAM data integrity test by writing 0s and 1s
 * to the entire external device.
 *
 * \param base Base address of the external memory device
 * \param size Size of the external memory device
 *
 * \retval STATUS_OK on success, and \ref status_code_t error code on failure
 */
static status_code_t ebi_test_data_integrity(hugemem_ptr_t base, uint32_t size)
{
	uint32_t        offset;
	uint32_t        pattern;

	/* Fill memory with a known pattern. */
	for (pattern = 1, offset = 0; offset < size; pattern++,
			offset += sizeof(uint32_t)) {
		hugemem_ptr_t   p;

		p = (hugemem_ptr_t)((uint32_t)base + offset);
		hugemem_write32(p, pattern);
	}

	/* Check each location and invert it for the second pass. */
	for (pattern = 1, offset = 0; offset < size; pattern++,
			offset += sizeof(uint32_t)) {
		hugemem_ptr_t   p;
		uint32_t        actual;
		uint32_t        expected;

		p = (hugemem_ptr_t)((uint32_t)base + offset);

		actual = hugemem_read32(p);
		if (actual != pattern) {
			return ERR_IO_ERROR;
		}

		expected = ~pattern;
		hugemem_write32(p, expected);
	}

	/* Check each location for the inverted pattern and zero it. */
	for (pattern = 1, offset = 0; offset < size; pattern++,
			offset += sizeof(uint32_t)) {
		hugemem_ptr_t   p;
		uint32_t        actual;
		uint32_t        expected;

		p = (hugemem_ptr_t)((uint32_t)base + offset);

		expected = ~pattern;
		actual = hugemem_read32(p);
		if (actual != expected) {
			return ERR_IO_ERROR;
		}
	}

	return STATUS_OK;
}
/**
 * \brief Test the data bus
 *
 * Tests the data bus for stuck and coupled lines by writing and verifying bit
 * patterns in RAM.
 *
 * First, unique 32-bit patterns with a single set bit are written to successive
 * locations in memory. These patterns are referred to as a walking 1 since the
 * bit pattern is shifted by 1 position for each new memory location.
 *
 * The patterns are then read back for verification, inverted and written back
 * to the memory location -- the memory locations now contain a walking 0. These
 * patterns are read back again for verification.
 *
 * \param test Current test case.
 */
void run_data_bus_test(const struct test_case *test)
{
	struct ebi_test_params *params;
	hugemem_ptr_t          base;
	hugemem_ptr_t          p;
	uint_fast8_t           i;

	params = (struct ebi_test_params *)test_get_data();
	base = params->base;

	// Write walking 1s
	for (p = base, i = 0; i < 32; i++) {
		hugemem_write32(p, 1UL << i);
		p = (hugemem_ptr_t)((uint32_t)p + sizeof(uint32_t));
	}

	// Read walking 1s, write walking 0s
	for (p = base, i = 0; i < 32; i++) {
		uint32_t expected = 1UL << i;
		uint32_t actual;

		actual = hugemem_read32(p);
		test_assert_true(test, actual == expected,
				"Read 0x%04x, expected 0x%04x (walking 1)",
				actual, expected);

		hugemem_write32(p, ~expected);
		p = (hugemem_ptr_t)((uint32_t)p + sizeof(uint32_t));
	}

	// Read walking 0s
	for (p = base, i = 0; i < 32; i++) {
		uint32_t actual;
		uint32_t expected = ~(1UL << i);

		actual = hugemem_read32(p);
		test_assert_true(test, actual == expected,
				"Read 0x%04x, expected 0x%04x (walking 0)",
				actual, expected);

		p = (hugemem_ptr_t)((uint32_t)p + sizeof(uint32_t));
	}
}
Example #4
0
/**
 * \brief Test the EBI data bus wired to the SDRAM
 *
 * This function will perform a walking 1s to locate any shorts or open leads
 * to the SDRAM device.
 *
 * \param base Base address of the external memory device
 *
 * \retval STATUS_OK on success, and \ref status_code_t error code on failure
 */
static status_code_t ebi_test_data_bus(hugemem_ptr_t base)
{
	hugemem_ptr_t   p;
	uint_fast8_t    i;

	/* Write walking 1s */
	for (p = base, i = 0; i < 32; i++) {
		hugemem_write32(p, 1UL << i);
		p = (hugemem_ptr_t)((uint32_t)p + sizeof(uint32_t));
	}

	/* Read walking 1s, write walking 0s */
	for (p = base, i = 0; i < 32; i++) {
		uint32_t        expected = 1UL << i;
		uint32_t        actual;

		actual = hugemem_read32(p);
		if (actual != expected) {
			return ERR_IO_ERROR;
		}

		hugemem_write32(p, ~expected);
		p = (hugemem_ptr_t)((uint32_t)p + sizeof(uint32_t));
	}

	/* Read walking 0s */
	for (p = base, i = 0; i < 32; i++) {
		uint32_t        actual;
		uint32_t        expected = ~(1UL << i);

		actual = hugemem_read32(p);
		if (actual != expected) {
			return ERR_IO_ERROR;
		}

		p = (hugemem_ptr_t)((uint32_t)p + sizeof(uint32_t));
	}

	return STATUS_OK;
}
Example #5
0
/**
 *
 * \brief Set DMA configuration, and read it back
 *
 * \note This function writes a configuration to the DMA
 * controller, and reads it back to verify settings have
 * been correctly set.
 *
 * \param test   Current test case
 */
static void run_dma_config_interface_test(const struct test_case *test)
{
	struct dma_channel_config config_params;
	struct dma_channel_config read_config;

	const uint16_t transfer_count = 1024;
	const uint8_t repeats         = 64;
	uint8_t channel_index;

#ifdef CONFIG_HAVE_HUGEMEM
	hugemem_ptr_t dest_huge_addr  = HUGEMEM_NULL;
	hugemem_ptr_t src_huge_addr   = HUGEMEM_NULL;

	hugemem_write32(dest_huge_addr, 0xABCD1234);
	hugemem_write32(src_huge_addr, 0xAAAABBBB);
#else
	const uint16_t dest_addr      = 0xBEEF;
	const uint16_t src_addr       = 0xABCD;
#endif

	memset(&config_params, 0, sizeof(config_params));

	dma_enable();

	/* Apply some parameters */
	dma_channel_set_burst_length(&config_params,
			DMA_CH_BURSTLEN_4BYTE_gc);
	dma_channel_set_single_shot(&config_params);
	dma_channel_set_interrupt_level(&config_params,
			PMIC_LVL_HIGH);
	dma_channel_set_src_reload_mode(&config_params,
			DMA_CH_SRCRELOAD_BLOCK_gc);
	dma_channel_set_dest_reload_mode(&config_params,
			DMA_CH_DESTRELOAD_BURST_gc);
	dma_channel_set_src_dir_mode(&config_params,
			DMA_CH_SRCDIR_DEC_gc);
	dma_channel_set_dest_dir_mode(&config_params,
			DMA_CH_DESTDIR_DEC_gc);
	dma_channel_set_trigger_source(&config_params,
			DMA_CH_TRIGSRC_TCC0_CCA_gc);
	dma_channel_set_transfer_count(&config_params,
			transfer_count);
	dma_channel_set_repeats(&config_params,
			repeats);

#ifdef CONFIG_HAVE_HUGEMEM
	dma_channel_set_destination_hugemem(&config_params, dest_huge_addr);
	dma_channel_set_source_hugemem(&config_params, src_huge_addr);
#else
	dma_channel_set_destination_address(&config_params, dest_addr);
	dma_channel_set_source_address(&config_params, src_addr);
#endif

	/* Loop through all channels, read back config from them, and verify */
	for (channel_index = 0; channel_index < DMA_NUMBER_OF_CHANNELS; channel_index++) {
		dma_channel_write_config(channel_index, &config_params);

		/* Null out the read_config struct */
		memset(&read_config, 0, sizeof(read_config));

		/* Read the config back from the module */
		dma_channel_read_config(channel_index, &read_config);

		test_assert_true(test,
				read_config.addrctrl == config_params.addrctrl,
				"CH %d: Address control register does not match configuration",
				channel_index);

		test_assert_true(test, read_config.ctrla == config_params.ctrla,
				"CH %d: Control register A does not match configuration",
				channel_index);

		test_assert_true(test,
				read_config.repcnt == config_params.repcnt,
				"CH %d: Repeat counter register does not match configuration",
				channel_index);

		test_assert_true(test,
				read_config.trfcnt == config_params.trfcnt,
				"CH %d: Transfer counter register does not"
				" match configuration", channel_index);

		test_assert_true(test,
				read_config.trigsrc == config_params.trigsrc,
				"CH %d: Trigger source register does not match configuration",
				channel_index);

#ifdef CONFIG_HAVE_HUGEMEM
		test_assert_true(test,
				read_config.destaddr == config_params.destaddr,
				"CH %d: Destination address register does not"
				" match configuration", channel_index);

		test_assert_true(test,
				read_config.srcaddr == config_params.srcaddr,
				"CH %d: Source address register does not match configuration",
				channel_index);
#else
		test_assert_true(test,
				read_config.destaddr16 == config_params.destaddr16,
				"CH %d: DESTADDR16 does not match configuration",
				channel_index);

		test_assert_true(test,
				read_config.srcaddr16 == config_params.srcaddr16,
				"CH %d: SRCADDR16 does not match configuration");
#endif
	}

	/* Reset the channel */
	dma_channel_reset(DMA_CHANNEL_0);

	/* Check set and unset single shot */
	memset(&config_params, 0, sizeof(config_params));
	memset(&read_config, 0, sizeof(read_config));

	dma_channel_set_single_shot(&config_params);

	dma_channel_write_config(DMA_CHANNEL_0, &config_params);
	dma_channel_read_config(DMA_CHANNEL_0, &read_config);

	test_assert_true(test, read_config.ctrla == config_params.ctrla,
			"Single shot mode not set correctly");

	memset(&config_params, 0, sizeof(config_params));
	dma_channel_unset_single_shot(&config_params);

	dma_channel_write_config(DMA_CHANNEL_0, &config_params);
	dma_channel_read_config(DMA_CHANNEL_0, &read_config);

	test_assert_true(test, read_config.ctrla == config_params.ctrla,
			"Single shot mode not unset correctly");

	/* Reset it again, and test the direct configuration functions */
	memset(&read_config, 0, sizeof(read_config));

	dma_channel_write_burst_length(DMA_CHANNEL_0, DMA_CH_BURSTLEN_4BYTE_gc);
	dma_channel_write_transfer_count(DMA_CHANNEL_0, transfer_count);
	dma_channel_write_repeats(DMA_CHANNEL_0, repeats);

#ifdef CONFIG_HAVE_HUGEMEM
	dma_channel_write_source_hugemem(DMA_CHANNEL_0, src_huge_addr);
	dma_channel_write_destination_hugemem(DMA_CHANNEL_0, dest_huge_addr);
#else
	dma_channel_write_source(DMA_CHANNEL_0, src_addr);
	dma_channel_write_destination(DMA_CHANNEL_0, dest_addr);
#endif

	/* Verify that settings have been set correctly */
	dma_channel_read_config(DMA_CHANNEL_0, &read_config);

	test_assert_true(test,
			(read_config.ctrla & DMA_CH_BURSTLEN_gm)
			== DMA_CH_BURSTLEN_4BYTE_gc,
			"Read burst length does not match configuration");

	test_assert_true(test, read_config.trfcnt == transfer_count,
			"Read transfer count does not match configuration");

	test_assert_true(test, read_config.repcnt == repeats,
			"Read repeat value does not match configuration");

#ifdef CONFIG_HAVE_HUGEMEM
	test_assert_true(test, read_config.srcaddr == src_huge_addr,
			"Read source address does not match configuration");

	test_assert_true(test, read_config.destaddr == dest_huge_addr,
			"Read destination address does not match configuration");
#else
	test_assert_true(test, read_config.srcaddr16 == src_addr,
			"Read source address does not match configuration");

	test_assert_true(test, read_config.destaddr16 == dest_addr,
			"Read destination address does not match configuration");
#endif

	dma_disable();
}