예제 #1
0
파일: unit_tests.c 프로젝트: InSoonPark/asf
/**
 * \brief 32-bit checksum of DMA transfer data
 *
 * This test sets up DMA to do a data block transfer, and sets up
 * the CRC module to do a 32 bit checksum on the data. The checksum
 * will then be added to another buffer, the same procedure is setup
 * with this new buffer which should result in a checksum = 0.
 *
 * \param test    Current test case
 */
static void run_32bit_dma_test(const struct test_case *test)
{
	uint32_t checksum;
	bool success;
	uint8_t data_buf_8bit[LENGTH(data_8bit) + sizeof(uint32_t)];
	uint8_t data_8bit_cpy[LENGTH(data_8bit) + sizeof(uint32_t)];

	setup_dma_channel(LENGTH(data_8bit),
			(uint8_t *)data_8bit, data_buf_8bit);
	crc_dma_checksum_start(CONF_TEST_DMACH, CRC_32BIT);
	dma_channel_trigger_block_transfer(CONF_TEST_DMACH);

	success = wait_for_dma_transfer(test);

	dma_channel_disable(CONF_TEST_DMACH);
	dma_disable();

	checksum = crc_dma_checksum_stop();

	if (!success) {
		return;
	}

	test_assert_true(test, checksum == CRC_CHECKSUM_32BIT,
			"Checksum mismatch on DMA CRC-32 test");

	memcpy(data_8bit_cpy, data_8bit, LENGTH(data_8bit));
	crc32_append_value(checksum,
			&data_8bit_cpy[LENGTH(data_8bit_cpy) - sizeof(uint32_t)]);

	setup_dma_channel(LENGTH(data_8bit_cpy),
			(uint8_t *)data_8bit_cpy, data_buf_8bit);

	crc_dma_checksum_start(CONF_TEST_DMACH, CRC_32BIT);
	dma_channel_trigger_block_transfer(CONF_TEST_DMACH);

	success = wait_for_dma_transfer(test);

	dma_channel_disable(CONF_TEST_DMACH);
	dma_disable();

	checksum = crc_dma_checksum_stop();

	if (!success) {
		return;
	}

	test_assert_true(test, checksum == 0,
			"Checksum fail check failed on DMA CRC-16 test");
}
예제 #2
0
/**
 * \brief Test the error handling of the module
 *
 * \note Test error handling by disabling a channel which is in use
 *
 * \param test              Current test
 */
static void run_dma_error_handling_test(const struct test_case *test)
{
	/* Enable DMA */
	dma_enable();

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

	/* Set up channel 0 to do some work, check that is it busy,
	 * change some settings and verify a transfer error */
	dma_channel_write_burst_length(DMA_CHANNEL_0,
			DMA_CH_BURSTLEN_1BYTE_gc);
	dma_channel_write_transfer_count(DMA_CHANNEL_0,
			MEMORY_BLOCK_SIZE);
	dma_channel_write_source(DMA_CHANNEL_0,
			(uint16_t)(uintptr_t)memory_block_src);
	dma_channel_write_destination(DMA_CHANNEL_0,
			(uint16_t)(uintptr_t)memory_block_dest);

	/* Enable the channel */
	dma_channel_enable(DMA_CHANNEL_0);

	/* Start a block transfer */
	dma_channel_trigger_block_transfer(DMA_CHANNEL_0);

	/* Wait for the channel to become busy */
	while (!dma_channel_is_busy(DMA_CHANNEL_0)) {
		/* Intentionally left empty */
	}

	/* Disable the channel while it is busy */
	if (dma_channel_is_busy(DMA_CHANNEL_0)) {
		dma_channel_disable(DMA_CHANNEL_0);
	}

	/* Test whether the channel is in error */
	test_assert_true(test,
			dma_get_channel_status(
			DMA_CHANNEL_0) == DMA_CH_TRANSFER_ERROR,
			"DMA channel not in error after disabling during transfer"
			" write");

	dma_disable();
}
예제 #3
0
/**
 *
 * \brief Test double buffering mode
 *
 * \note This function tests the double buffering feature of the DMA
 * controller by configuring channel 0 and 1 to do the same copy,
 * and verify that the channels enable each other according to
 * the double buffering process.
 *
 * \param test   Current test case
 */
static void run_dma_double_buffering_test(const struct test_case *test)
{
	struct dma_channel_config config_params;
	bool success = true; /* Assume everything goes well */

	/* Fill source block with pattern data */
	set_buffer(memory_block_src, 0x00);
	block_fill(memory_block_src, MEMORY_BLOCK_SIZE);

	/* Null out the destination block */
	set_buffer(memory_block_dest, 0x00);

	/* Null out the config params */
	memset(&config_params, 0, sizeof(config_params));

	/* Enable DMA */
	dma_enable();

	/* Enable double buffering mode on channel 0 and 1 */
	dma_set_double_buffer_mode(DMA_DBUFMODE_CH01_gc);

	/* Set channel 1 to copy from memory_block_src to memory_block_dest */
	dma_channel_set_src_reload_mode(&config_params,
			DMA_CH_SRCRELOAD_NONE_gc);
	dma_channel_set_src_dir_mode(&config_params,
			DMA_CH_SRCDIR_INC_gc);
	dma_channel_set_dest_reload_mode(&config_params,
			DMA_CH_DESTRELOAD_NONE_gc);
	dma_channel_set_dest_dir_mode(&config_params,
			DMA_CH_DESTDIR_INC_gc);
	dma_channel_set_burst_length(&config_params,
			DMA_CH_BURSTLEN_1BYTE_gc);
	dma_channel_set_transfer_count(&config_params,
			MEMORY_BLOCK_SIZE);
	dma_channel_set_source_address(&config_params,
			(uint16_t)(uintptr_t)memory_block_src);
	dma_channel_set_destination_address(&config_params,
			(uint16_t)(uintptr_t)memory_block_dest);
	dma_channel_set_repeats(&config_params,
			DOUBLE_BUFFER_REPEATS);

	/* Write config and enable */
	dma_channel_write_config(DMA_CHANNEL_0, &config_params);
	dma_channel_write_config(DMA_CHANNEL_1, &config_params);

	/* Enable only channel 0 */
	dma_channel_enable(DMA_CHANNEL_0);

	/* Transfer block and wait for it to finish */
	dma_channel_trigger_block_transfer(DMA_CHANNEL_0);

	while (dma_get_channel_status(DMA_CHANNEL_0) !=
			DMA_CH_TRANSFER_COMPLETED) {
		/* Intentionally left empty */
	}

	/*
	 * If double buffering is working, channel 1
	 * will be enabled now by the controller
	 */
	if (!(dma_channel_is_enabled(DMA_CHANNEL_1))) {
		success = false;
	}

	/*
	 * Disable channel 0, transfer channel 1,
	 * and verify that channel 0 is enabled again by the controller
	 */
	dma_channel_disable(DMA_CHANNEL_0);

	/* Transfer block and wait for it to finish */
	dma_channel_trigger_block_transfer(DMA_CHANNEL_1);

	while (dma_get_channel_status(DMA_CHANNEL_1) !=
			DMA_CH_TRANSFER_COMPLETED) {
		/* Intentionally left empty */
	}

	/* Verify that channel 0 is enabled again */
	if (!(dma_channel_is_enabled(DMA_CHANNEL_0))) {
		success = false;
	}

	test_assert_true(test, success,
			"Double buffering mode did not function properly");
}
예제 #4
0
/**
 * \brief Test different directions on all channels
 *
 * \note This test copies the source memory block into the destination block
 * in different ways.
 *
 * \param test              Current test
 */
static void run_dma_direction_test(const struct test_case *test)
{
	struct dma_channel_config config_params;
	uint8_t channel_index;
	bool success = true; /* Assume everything goes well */

	/* Fill the source block with our known pattern */
	set_buffer(memory_block_src, 0x00);
	block_fill(memory_block_src, MEMORY_BLOCK_SIZE);

	/* Null out the config params */
	memset(&config_params, 0, sizeof(config_params));

	/* Enable DMA */
	dma_enable();

	/* No reload on source and destination */
	dma_channel_set_src_reload_mode(&config_params,
			DMA_CH_SRCRELOAD_NONE_gc);
	dma_channel_set_dest_reload_mode(&config_params,
			DMA_CH_DESTRELOAD_NONE_gc);
	dma_channel_set_transfer_count(&config_params,
			MEMORY_BLOCK_SIZE);
	dma_channel_set_burst_length(&config_params,
			DMA_CH_BURSTLEN_1BYTE_gc);

	/* Test a memory transfer on all channels */
	for (channel_index = 0; channel_index < DMA_NUMBER_OF_CHANNELS;
			channel_index++) {
		/* Reset channel and write the configuration */
		dma_channel_reset(channel_index);
		/* Increment source, increment destination */
		dma_channel_set_src_dir_mode(&config_params,
				DMA_CH_SRCDIR_INC_gc);
		dma_channel_set_dest_dir_mode(&config_params,
				DMA_CH_DESTDIR_INC_gc);
		/* Data starts from the first byte */
		dma_channel_set_source_address(&config_params,
				(uint16_t)(uintptr_t)memory_block_src);
		dma_channel_set_destination_address(&config_params,
				(uint16_t)(uintptr_t)memory_block_dest);

		/* Write the config */
		dma_channel_write_config(channel_index, &config_params);

		/* Clear destination */
		set_buffer(memory_block_dest, 0x00);

		/* Enable channel, transfer, and disable it */
		dma_channel_enable(channel_index);
		dma_transfer_block(channel_index);
		dma_channel_disable(channel_index);

		/* Check that source and destination are equal */
		success = block_compare(memory_block_src,
				memory_block_dest, MEMORY_BLOCK_SIZE);

		if (!success) {
			break;
		}

		/* Reset channel and write the configuration */
		dma_channel_reset(channel_index);
		/* Decrement source, increment destination */
		dma_channel_set_src_dir_mode(&config_params,
				DMA_CH_SRCDIR_DEC_gc);
		dma_channel_set_dest_dir_mode(&config_params,
				DMA_CH_DESTDIR_INC_gc);
		/* Data starts from the first byte */
		dma_channel_set_source_address(&config_params,
				(uint16_t)(uintptr_t)
				(memory_block_src + MEMORY_BLOCK_SIZE - 1));
		dma_channel_set_destination_address(&config_params,
				(uint16_t)(uintptr_t)memory_block_dest);

		/* Write the config */
		dma_channel_write_config(channel_index, &config_params);

		/* Clear destination */
		set_buffer(memory_block_dest, 0x00);

		/* Enable channel, transfer, and disable it */
		dma_channel_enable(channel_index);
		dma_transfer_block(channel_index);
		dma_channel_disable(channel_index);

		/* Check that destination is the reverse of source */
		success = block_compare_reverse(memory_block_src,
				memory_block_dest, MEMORY_BLOCK_SIZE);

		if (!success) {
			break;
		}

		/* Reset channel and write the configuration */
		dma_channel_reset(channel_index);
		/* Decrement source, increment destination */
		dma_channel_set_src_dir_mode(&config_params,
				DMA_CH_SRCDIR_INC_gc);
		dma_channel_set_dest_dir_mode(&config_params,
				DMA_CH_DESTDIR_DEC_gc);
		/* Data starts from the first byte */
		dma_channel_set_source_address(&config_params,
				(uint16_t)(uintptr_t)memory_block_src);
		dma_channel_set_destination_address(&config_params,
				(uint16_t)(uintptr_t)
				(memory_block_dest + MEMORY_BLOCK_SIZE - 1));

		/* Write the config */
		dma_channel_write_config(channel_index, &config_params);

		/* Clear destination */
		set_buffer(memory_block_dest, 0x00);

		/* Enable channel, transfer, and disable it */
		dma_channel_enable(channel_index);
		dma_transfer_block(channel_index);
		dma_channel_disable(channel_index);

		/* Check that destination is the reverse of source */
		success = block_compare_reverse(memory_block_src,
				memory_block_dest, MEMORY_BLOCK_SIZE);

		if (!success) {
			break;
		}

		/* Reset channel and write the configuration */
		dma_channel_reset(channel_index);
		/* Decrement source, Decrement destination */
		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);
		/* Data starts from the first byte */
		dma_channel_set_source_address(&config_params,
				(uint16_t)(uintptr_t)
				(memory_block_src + MEMORY_BLOCK_SIZE - 1));
		dma_channel_set_destination_address(&config_params,
				(uint16_t)(uintptr_t)
				(memory_block_dest + MEMORY_BLOCK_SIZE - 1));

		/* Write the config */
		dma_channel_write_config(channel_index, &config_params);

		/* Clear destination */
		set_buffer(memory_block_dest, 0x00);

		/* Enable channel, transfer, and disable it */
		dma_channel_enable(channel_index);
		dma_transfer_block(channel_index);
		dma_channel_disable(channel_index);

		/* Check that source and destination are equal */
		success = block_compare(memory_block_src,
				memory_block_dest, MEMORY_BLOCK_SIZE);

		if (!success) {
			break;
		}
	}

	/* Disable DMA */
	dma_disable();

	test_assert_true(test, success,
			"DMA direction copy test failed on channel %d",
			channel_index);
}