Пример #1
0
/**
 * \brief main function
 */
int main(void)
{
	struct dma_channel_config config;
	uint32_t                  checksum;

	pmic_init();
	board_init();
	sysclk_init();
	sleepmgr_init();

	// Randomly selected data
	source[0] = 0xAA;
	source[1] = 0xBB;
	source[2] = 0xCC;
	source[3] = 0xDD;
	source[4] = 0xEE;
	source[5] = 0xFF;

	// Calculate checksum for the data
	checksum = crc_io_checksum((void*)source, 6, CRC_16BIT);
	// Append the checksum to the data, big endian
	crc16_append_value(checksum, source+6);

	//Enable the CRC module for DMA
	crc_dma_checksum_start(DMA_CHANNEL, CRC_16BIT);

	// Enable DMA
	dma_enable();

	// Set callback function for DMA completion
	dma_set_callback(DMA_CHANNEL, example_crc_dma_transfer_done);

	// Make sure config is all zeroed out so we don't get any stray bits
	memset(&config, 0, sizeof(config));

	/**
	 * This example will configure a DMA channel with the following
	 * settings:
	 *  - Low interrupt priority
	 *  - 1 byte burst length
	 *  - DMA_BUFFER_SIZE bytes for each transfer
	 *  - Reload source and destination address at end of each transfer
	 *  - Increment source and destination address during transfer
	 *  - Source address is set to \ref source
	 *  - Destination address is set to \ref destination
	 */
	dma_channel_set_interrupt_level(&config, PMIC_LVL_LOW);
	dma_channel_set_burst_length(&config, DMA_CH_BURSTLEN_1BYTE_gc);
	dma_channel_set_transfer_count(&config, DMA_BUFFER_SIZE);
	dma_channel_set_src_reload_mode(&config,
			DMA_CH_SRCRELOAD_TRANSACTION_gc);
	dma_channel_set_dest_reload_mode(&config,
			DMA_CH_DESTRELOAD_TRANSACTION_gc);
	dma_channel_set_src_dir_mode(&config, DMA_CH_SRCDIR_INC_gc);
	dma_channel_set_dest_dir_mode(&config, DMA_CH_DESTDIR_INC_gc);
	dma_channel_set_source_address(&config, (uint16_t)(uintptr_t)source);
	dma_channel_set_destination_address(&config,
			(uint16_t)(uintptr_t)destination);
	dma_channel_write_config(DMA_CHANNEL, &config);

	// Use the configuration above by enabling the DMA channel in use.
	dma_channel_enable(DMA_CHANNEL);

	// Enable interrupts
	cpu_irq_enable();

	// Trigger the DMA transfer
	dma_channel_trigger_block_transfer(DMA_CHANNEL);

	// Light the first LED to indicate that the DMA has started.
	gpio_set_pin_low(LED0_GPIO);

	while (true) {
		/*
		 * Force a NOP instruction for an eventual placement of a debug
		 * session breakpoint.
		 */
		asm("nop\n");
	}
}
Пример #2
0
/**
 * \brief Test read from fixed location, trigger from timer and callback
 *
 * \note This test sets up a timer to trigger the DMA module,
 * which in turn reads the timer_overflow_counter variable and writes
 * it to memory sequentially. It then checks to see that the memory block
 * written is sequential according to the overflow count.
 *
 * \param test              Current test
 */
static void run_dma_triggered_with_callback(const struct test_case *test)
{
	struct dma_channel_config config_params;
	bool success;

	/* Null the buffer */
	set_buffer(dest_block_tc, 0x0000);

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

	/*
	 * Enable the timer, and set it to count up.
	 * When it overflows, it triggers the DMA to
	 * read timer_overflow_counter. */
	tc_enable(&TIMER);

	tc_set_direction(&TIMER, TC_UP);
	tc_write_period(&TIMER, TIMER_PERIOD);

	tc_set_resolution(&TIMER, TIMER_RESOLUTION);

	tc_set_overflow_interrupt_level(&TIMER, PMIC_LVL_LOW);
	tc_set_overflow_interrupt_callback(&TIMER, timer_overflow_callback);

	/* Enable the DMA module */
	dma_enable();

	/* Set callback for transfer done */
	dma_set_callback(DMA_CHANNEL_0, dma_transfer_is_complete);

	/* Set low interrupt level */
	dma_channel_set_interrupt_level(&config_params, PMIC_LVL_LOW);

	/* Set up the DMA to read the timer value
	 *
	 * - Single shot transfer mode
	 * - Two byte (16-bit) burst length
	 * - Increment on source and destination
	 * - Reload on burst for source
	 * - No reload for destination
	 */
	dma_channel_set_single_shot(&config_params);
	dma_channel_set_burst_length(&config_params,
			DMA_CH_BURSTLEN_1BYTE_gc);
	dma_channel_set_src_reload_mode(&config_params,
			DMA_CH_SRCRELOAD_BURST_gc);
	dma_channel_set_src_dir_mode(&config_params,
			DMA_CH_SRCDIR_FIXED_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);

	/* Set trigger source to TCC0's overflow */
	dma_channel_set_trigger_source(&config_params,
			DMA_CH_TRIGSRC_TCC0_OVF_gc);

	/* Transfer DEST_BLOCK_TC_SIZE bytes */
	dma_channel_set_transfer_count(&config_params,
			DEST_BLOCK_TC_SIZE);

	/* Set address */
	dma_channel_set_source_address(&config_params,
			(uint16_t)(uintptr_t)&timer_overflow_counter);
	dma_channel_set_destination_address(&config_params,
			(uint16_t)(uintptr_t)dest_block_tc);

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

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

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

	/* Wait for transfer to finish */
	while (!dma_has_completed) {
		/* Intentionally left empty */
	}

	/* Disable DMA */
	dma_disable();

	/* Verify that the result is as expected */
	success = block_compare(dest_block_tc,
			expected_result_tc, DEST_BLOCK_TC_SIZE);

	test_assert_true(test, success, "Result is not as expected");
}