Beispiel #1
0
/**
 * \brief Trigger and wait for a successful transfer
 *
 * \param channel_num             Channel number
 */
static void ut_edma_transfer_block(edma_channel_num_t channel_num)
{
	/* Trigger a EDMA copy */
	edma_channel_trigger_block_transfer(channel_num);

	/* Wait for it to finish */
	while (edma_get_channel_status(channel_num) !=
			EDMA_CH_TRANSFER_COMPLETED) {
		/* Intentionally left empty */
	}
}
Beispiel #2
0
/**
 * \internal
 * \brief Common EDMA channel interrupt handler
 *
 * Calls the channel callback with the channel status code. The following
 * status codes are possible:
 * - EDMA_CH_TRANSFER_COMPLETED: Transfer completed successfully
 * - EDMA_CH_TRANSFER_ERROR: Fault in transfer
 *
 * The optional callback used by the interrupt handler is set by the
 * edma_set_callback() function.
 *
 * \param num EDMA channel number to handle interrupt for
 */
static void edma_interrupt(const edma_channel_num_t num)
{
	edma_channel_status_t status;
	EDMA_CH_t *channel;

	channel = edma_get_channel_address_from_num(num);
	status  = edma_get_channel_status(num);

	/* Clear all interrupt flags to be sure */
	channel->CTRLB |= EDMA_CH_TRNIF_bm | EDMA_CH_ERRIF_bm;

	if (edma_data[num].callback) {
		edma_data[num].callback(status);
	}
}
Beispiel #3
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_edma_error_handling_test(const struct test_case *test)
{
	/* 
	 * Enable EDMA module, peripheral channels 0 and 1,
	 * standard channel 2
	 */
	edma_enable(EDMA_CHMODE_STD2_gc);

	/* Reset the channel */
	edma_channel_reset(EDMA_CH_2);

	/* Set up channel 0 to do some work, check that is it busy,
	 * change some settings and verify a transfer error */
	edma_channel_write_burst_length(EDMA_CH_2, EDMA_CH_BURSTLEN_1BYTE_gc);
	edma_channel_write_transfer_count16(EDMA_CH_2, MEMORY_BLOCK_SIZE);
	edma_channel_write_src_address(EDMA_CH_2,
			(uint16_t)(uintptr_t)memory_block_src);
	edma_channel_write_dest_address(EDMA_CH_2,
			(uint16_t)(uintptr_t)memory_block_dest);

	/* Enable the channel */
	edma_channel_enable(EDMA_CH_2);

	/* Start a block transfer */
	edma_channel_trigger_block_transfer(EDMA_CH_2);

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

	/* Disable the channel while it is busy */
	if (edma_channel_is_busy(EDMA_CH_2)) {
		edma_channel_disable(EDMA_CH_2);
	}

	/* Test whether the channel is in error */
	test_assert_true(test,
			edma_get_channel_status(
			EDMA_CH_2) == EDMA_CH_TRANSFER_ERROR,
			"EDMA channel not in ERROR after disabling during transfer write");

	edma_disable();
}
Beispiel #4
0
/**
 *
 * \brief Test search and double buffering (link) modes
 *
 * \note This function tests search and double buffering features of the EDMA
 * controller by configuring channel 2 searching data. In case of success, the
 * channel 0 is automatically (double buffering) enables (if it is
 * successfull) and copies a memory block. The copy is verified.
 *
 * \param test   Current test case
 */
static void run_edma_search_dbuf_test(const struct test_case *test)
{
	struct edma_channel_config ch0_config_params;
	struct edma_channel_config ch2_config_params;

	bool success;

	/* 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(&ch0_config_params, 0, sizeof(ch0_config_params));
	memset(&ch2_config_params, 0, sizeof(ch2_config_params));

	/* Enable EDMA module, Channels 0 and 2 in standard configuration */
	edma_enable(EDMA_CHMODE_STD02_gc);

	/* Enable double buffering mode on channel 0 and 1 */
	edma_set_double_buffer_mode(EDMA_DBUFMODE_BUF0123_gc);

	/* Set channel 2 to search data (last byte of memory_block_src[]) */
	edma_channel_set_src_reload_mode(&ch2_config_params,
			EDMA_CH_RELOAD_NONE_gc);
	edma_channel_set_src_dir_mode(&ch2_config_params, EDMA_CH_DIR_INC_gc);
	edma_channel_set_dest_reload_mode(&ch2_config_params,
			EDMA_CH_RELOAD_NONE_gc);
	edma_channel_set_search_mode(&ch2_config_params,
			EDMA_CH_DESTDIR_MP1_gc);
	edma_channel_set_burst_length(&ch2_config_params,
			EDMA_CH_BURSTLEN_1BYTE_gc);
	edma_channel_set_trigger_source(&ch2_config_params,
			EDMA_CH_TRIGSRC_OFF_gc);
	edma_channel_set_transfer_count16(&ch2_config_params,
			MEMORY_BLOCK_SIZE);
	edma_channel_set_source_address(&ch2_config_params,
			(uint16_t)(uintptr_t)memory_block_src);
	edma_channel_set_search_data(&ch2_config_params,
			memory_block_src[MEMORY_BLOCK_SIZE - 1], 0xFF);

	/* Write config channel 2 */
	edma_channel_write_config(EDMA_CH_2, &ch2_config_params);

	/*
	 * Set channel 0 to copy from memory_block_src[] to memory_block_dest[]
	 * once a match will occur on channel 2. There will be no transfer if no
	 * match occurs.
	 */
	edma_channel_set_repeat(&ch0_config_params);
	edma_channel_set_burst_length(&ch0_config_params,
			EDMA_CH_BURSTLEN_2BYTE_gc);
	edma_channel_set_src_reload_mode(&ch0_config_params,
			EDMA_CH_RELOAD_TRANSACTION_gc);
	edma_channel_set_dest_reload_mode(&ch0_config_params,
			EDMA_CH_RELOAD_TRANSACTION_gc);
	edma_channel_set_src_dir_mode(&ch0_config_params, EDMA_CH_DIR_INC_gc);
	edma_channel_set_dest_dir_mode(&ch0_config_params,
			EDMA_CH_DESTDIR_INC_gc);
	edma_channel_set_trigger_source(&ch0_config_params,
			EDMA_CH_TRIGSRC_OFF_gc);
	edma_channel_set_transfer_count16(&ch0_config_params,
			MEMORY_BLOCK_SIZE);
	edma_channel_set_source_address(&ch0_config_params,
			(uint16_t)(uintptr_t)memory_block_src);
	edma_channel_set_destination_address(&ch0_config_params,
			(uint16_t)(uintptr_t)memory_block_dest);

	/* Write config channel 0 */
	edma_channel_write_config(EDMA_CH_0, &ch0_config_params);

	/* Enable only channel 2 */
	edma_channel_enable(EDMA_CH_2);

	/* Transfer block and wait for it to finish */
	edma_channel_trigger_block_transfer(EDMA_CH_2);
	edma_channel_trigger_block_transfer(EDMA_CH_0);

	/* Wait for search completion */
	while (edma_get_channel_status(EDMA_CH_2) !=
			EDMA_CH_TRANSFER_COMPLETED) {
		/* Intentionally left empty */
	}

	/* Wait for transfer completion */
	while (edma_get_channel_status(EDMA_CH_0) !=
			EDMA_CH_TRANSFER_COMPLETED) {
		/* Intentionally left empty */
	}

	/* Disable EDMA */
	edma_disable();

	/* Verify that the search result is as expected */
	success = block_compare(
			edma_channel_get_search_pointer(EDMA_CH_2),
			&memory_block_src[MEMORY_BLOCK_SIZE - 1], 1);

	test_assert_true(test, success,
			"SEARCH mode did not function properly");

	/* Verify that the transfer result is as expected */
	success = block_compare(memory_block_src, memory_block_dest,
			MEMORY_BLOCK_SIZE);

	test_assert_true(test, success,
			"DOUBLE BUFFER mode did not function properly");
}