Exemple #1
0
static void ss_gpio_interrupt_example(void)
{
	uint32_t i;

	QM_PUTS("Starting: SS GPIO interrupt");

	/* Enable clock to interrupt controller. */
	__builtin_arc_sr(BIT(31) + BIT(0),
			 QM_SS_GPIO_0_BASE + QM_SS_GPIO_LS_SYNC);

	/* Set SS GPIO pin 2 as OUTPUT. */
	__builtin_arc_sr(BIT(2), QM_SS_GPIO_0_BASE + QM_SS_GPIO_SWPORTA_DDR);

	/* Register the SS GPIO interrupt. */
	QM_IR_UNMASK_INTERRUPTS(QM_INTERRUPT_ROUTER->ss_gpio_0_int_mask);
	qm_ss_irq_request(QM_SS_IRQ_GPIO_0_INT, ss_gpio_interrupt_isr);

	/* Set the bit 3 to rising edge-sensitive. */
	__builtin_arc_sr(BIT(3), QM_SS_GPIO_0_BASE + QM_SS_GPIO_INTTYPE_LEVEL);
	/* Unmask SS GPIO pin 3 interrupt only. */
	__builtin_arc_sr(~BIT(3), QM_SS_GPIO_0_BASE + QM_SS_GPIO_INTMASK);
	/* Clear SS GPIO interrupt requests. */
	__builtin_arc_sr(BIT(3), QM_SS_GPIO_0_BASE + QM_SS_GPIO_PORTA_EOI);
	/* Enable SS GPIO interrupt. */
	__builtin_arc_sr(BIT(3), QM_SS_GPIO_0_BASE + QM_SS_GPIO_INTEN);

	for (i = 0; i < NUM_LOOPS; i++) {
		/*
		 * Toggle the SS GPIO 2, will trigger the interrupt on SS
		 * GPIO 3.
		 */
		clk_sys_udelay(DELAY);
		__builtin_arc_sr(BIT(2),
				 QM_SS_GPIO_0_BASE + QM_SS_GPIO_SWPORTA_DR);
		QM_GPIO[0]->gpio_swporta_dr |= BIT(LED_BIT);
		clk_sys_udelay(DELAY);
		__builtin_arc_sr(0, QM_SS_GPIO_0_BASE + QM_SS_GPIO_SWPORTA_DR);
		QM_GPIO[0]->gpio_swporta_dr &= ~BIT(LED_BIT);
	}
	/* Unmask all SS GPIO interrupts. */
	__builtin_arc_sr(0xff, QM_SS_GPIO_0_BASE + QM_SS_GPIO_INTMASK);
	if (counter == NUM_LOOPS) {
		QM_PUTS("Success");
	} else {
		QM_PUTS("Error: Check are pins 14 and 16 on J14 connector "
			"short connected?");
	}

	QM_PUTS("Finished: SS GPIO interrupt");
}
Exemple #2
0
/* Writes a page to the EEPROM using IRQ I2C transfer. */
void i2c_irq_write_example()
{
	QM_PUTS("IRQ write");

	async_irq_write_xfer.tx = eeprom_irq_write_data;
	async_irq_write_xfer.tx_len =
	    EEPROM_PAGE_SIZE_BYTES + EEPROM_ADDR_SIZE_BYTES;
	async_irq_write_xfer.callback = i2c_0_irq_callback;
	async_irq_write_xfer.callback_data = &id_write;
	async_irq_write_xfer.rx = NULL;
	async_irq_write_xfer.rx_len = 0;
	async_irq_write_xfer.stop = true;

	if (qm_i2c_master_irq_transfer(QM_I2C_0, &async_irq_write_xfer,
				       EEPROM_SLAVE_ADDR)) {
		QM_PUTS("Error: IRQ write failed");
	}

	/* Wait until complete flag is set in callback. */
	while (!i2c_0_irq_complete)
		;

	if (i2c_0_irq_rc_error) {
		QM_PUTS("Error: I2C IRQ Transfer failed");
	} else {
		QM_PUTS("I2C IRQ Transfer complete");
	}
	/* Wait for EEPROM to complete the write operation. */
	clk_sys_udelay(EEPROM_WRITE_WAIT_TIME_US);
}
Exemple #3
0
/*
 * Returns the start and end RTC times for this busy loop.
 * Ideally, by examining the TSC and RTC times, we should be able to
 * identify their correlation.
 */
static uint64_t rtc_tsc_correlate(unsigned int *rtc_start,
				  unsigned int *rtc_end)
{
#if (!QM_SENSOR)
	uint64_t start_tsc;
	uint64_t end_tsc;
#else
	uint32_t start_tsc;
	uint32_t end_tsc;
#endif

retry:
	*rtc_start = QM_RTC[QM_RTC_0]->rtc_ccvr;
	start_tsc = get_ticks();
	clk_sys_udelay(400);
	*rtc_end = QM_RTC[QM_RTC_0]->rtc_ccvr;

	/* To prevent int_32 bit overflow while computing the rtc difference. */
	if ((*rtc_end < *rtc_start) &&
	    (!((*rtc_start & 0xF0000000) == 0xF0000000))) {
		goto retry;
	}
	end_tsc = get_ticks();
	return end_tsc - start_tsc;
}
Exemple #4
0
static void wait_rx_callback_timeout(uint32_t timeout)
{
	while (!rx_callback_invoked && timeout) {
		clk_sys_udelay(WAIT_READ_CB_PERIOD_1MS);
		timeout--;
	};
}
Exemple #5
0
/* QMSI timer app example */
int main(void)
{
	/* Variables */
	qm_pwm_config_t wr_cfg, rd_cfg;
	uint32_t lo_cnt, hi_cnt;

	/* Initialise timer configuration */
	wr_cfg.lo_count = 0x100000;
	wr_cfg.hi_count = 0;
	wr_cfg.mode = QM_PWM_MODE_TIMER_COUNT;
	wr_cfg.mask_interrupt = false;
	wr_cfg.callback = timer_example_callback;

	/* Enable clocking for the PWM block */
	clk_periph_enable(CLK_PERIPH_PWM_REGISTER | CLK_PERIPH_CLK);

	/* Set the configuration of the Timer */
	qm_pwm_set_config(QM_PWM_0, QM_PWM_ID_1, &wr_cfg);
	/* Register the ISR with the SoC */
	qm_irq_request(QM_IRQ_PWM_0, qm_pwm_isr_0);

	/* Optionally, get config back to see the settings */
	qm_pwm_get_config(QM_PWM_0, QM_PWM_ID_1, &rd_cfg);

	/* Start Timer 2 */
	qm_pwm_start(QM_PWM_0, QM_PWM_ID_1);

	/* Optionally, get the current count values */
	qm_pwm_get(QM_PWM_0, QM_PWM_ID_1, &lo_cnt, &hi_cnt);

	clk_sys_udelay(UDELAY);
	/* Optionally, reload new values into the Timer */
	lo_cnt = 0x40000;
	hi_cnt = 0;
	qm_pwm_set(QM_PWM_0, QM_PWM_ID_1, lo_cnt, hi_cnt);

	clk_sys_udelay(UDELAY);

	/* Stop the Timer from running */
	qm_pwm_stop(QM_PWM_0, QM_PWM_ID_1);
	/* Disable clocking for the PWM block */
	clk_periph_disable(CLK_PERIPH_PWM_REGISTER);

	return 0;
}
Exemple #6
0
Fichier : main.c Projet : jeez/qmsi
static void ss_sw_triggered_interrupt_example(void)
{
	uint32_t i;
	QM_PUTS("Starting: SW triggered interrupt");

	qm_irq_request(QM_IRQ_I2C_1_INT, sw_interrupt_isr);

	QM_GPIO[0]->gpio_swporta_ddr |= BIT(LED_BIT);
	for (i = 0; i < NUM_LOOPS; i++) {
		QM_GPIO[0]->gpio_swporta_dr |= BIT(LED_BIT);
		clk_sys_udelay(DELAY);
		QM_GPIO[0]->gpio_swporta_dr &= ~BIT(LED_BIT);
		clk_sys_udelay(DELAY);
		/* SW mainpulated interrupt trigger, triggers I2C_1. */
		__builtin_arc_sr(QM_IRQ_I2C_1_INT_VECTOR, QM_SS_AUX_IRQ_HINT);
	}
	if (counter == NUM_LOOPS) {
		QM_PUTS("Success");
	} else {
		QM_PUTS("Error: SW interrupt didn't fire correctly");
	}
	QM_PUTS("Finished: SW triggered interrupt");
}
Exemple #7
0
/* Writes a page to the EEPROM using PIO I2C transfer. */
void i2c_pio_write_example()
{
	qm_i2c_status_t status;

	QM_PUTS("PIO write");

	/* Write EEPROM page address then the data. */
	if (qm_i2c_master_write(QM_I2C_0, EEPROM_SLAVE_ADDR,
				eeprom_pio_write_data,
				sizeof(eeprom_pio_write_data), true, &status)) {
		QM_PUTS("Error: PIO write failed");
	} else {
		QM_PUTS("I2C PIO TX Transfer complete");
	}
	clk_sys_udelay(EEPROM_WRITE_WAIT_TIME_US);
}
Exemple #8
0
int main()
{
	uint8_t payload[3];

	QM_PRINTF("Simple nRF24L01 receive example\r\n");

#if defined(RF24_SPI_MULTIBYTE)
	QM_PRINTF("Using multibyte SPI transfers\r\n");
#else
	QM_PRINTF("Using single byte SPI transfers\r\n");
#endif

	if (rf24_init()) {
		QM_PRINTF("Failed to initialize nRF24L01\r\n");
	} else {
		QM_PRINTF("Initialized nRF24L01 radio. ");
		if (rf24_is_plus()) {
			QM_PRINTF("Detected nRF24L01+\r\n");
		} else {
			QM_PRINTF("Detected nRF24L01\r\n");
		}
	}


    rf24_set_retries(15,15);

    rf24_open_reading_pipe_uint64(0, 0xAA55AA55AA);

    rf24_start_listening();

    clk_sys_udelay(1000);

    while(1) {

    	if (rf24_available()) {
    		rf24_read(payload, 3);

    		QM_PRINTF("Received data ... %d,%d,%d\r\n",payload[0],payload[1],payload[2]);

#if !defined (RF24_MINIMAL)
    		rf24_print_details();
#endif
    	}
    }

    return 0;
}
Exemple #9
0
Fichier : main.c Projet : jeez/qmsi
int main(void)
{
	uint32_t baudrate, dtr = 0;
	int bytes_read;

	QM_PUTS("Starting: USB CDC ACM Example");

	qm_irq_request(QM_IRQ_USB_0_INT, qm_usb_0_isr);

	/* Enable the USB VBUS on Quark SE DevBoard. */
	enable_usb_vbus();

	/* Init USB CDC ACM. */
	cdc_acm_init();

	QM_PUTS("CDC ACM Initialized. Waiting for DTR.");
	do {
		cdc_acm_line_ctrl_get(LINE_CTRL_DTR, &dtr);
	} while (!dtr);

	QM_PUTS("DTR set, start test.");

	/* Wait 1 sec for the host to do all settings. */
	clk_sys_udelay(ONE_SEC_UDELAY);

	if (cdc_acm_line_ctrl_get(LINE_CTRL_BAUD_RATE, &baudrate)) {
		QM_PUTS("Failed to get baudrate, ret code.");
	} else {
		QM_PRINTF("Baudrate detected: %d\n", baudrate);
	}

	QM_PUTS("USB CDC ACM set. Switch to the USB Serial Console.");
	cdc_acm_irq_callback_set(interrupt_handler);
	write_data(banner1, strlen(banner1));
	write_data(banner2, strlen(banner2));

	/* Enable RX interrupts. */
	cdc_acm_irq_rx_enable();

	/* Echo the received data. */
	while (1) {
		read_and_echo_data(&bytes_read);
	}

	return 0;
}
Exemple #10
0
Fichier : main.c Projet : jeez/qmsi
/*
 * Returns the start and end RTC times for this busy loop.
 * Ideally, by examining the TSC and RTC times, we should be able to
 * identify their correlation.
 */
static uint64_t spin_loop(unsigned int count, unsigned int *rtc_start,
			  unsigned int *rtc_end)
{
	uint64_t start_tsc;

retry:
	*rtc_start = QM_RTC[QM_RTC_0].rtc_ccvr;
	start_tsc = _rdtsc();
	clk_sys_udelay(400);
	*rtc_end = QM_RTC[QM_RTC_0].rtc_ccvr;

	if ((*rtc_end < *rtc_start) &&
	    (!((*rtc_start & 0xF0000000) == 0xF0000000))) {
		goto retry;
	}
	return _rdtsc() - start_tsc;
}
Exemple #11
0
int main(void)
{
	bool do_soc_sleep, sleep_ready;
	int current_state = 0;
	QM_PRINTF("Starting: Sleep multicore %s\n", MYNAME);

#if !QM_SENSOR
	sensor_activation();
#endif
	init_mailbox();

	while (current_state < 5) {
		clk_sys_udelay(DELAY_1_SECOND);
		state_machine(current_state, &sleep_ready, &do_soc_sleep);

		/*
		 * In that order, we can force the race condition when both
		 * request sleep.
		 */
		if (do_soc_sleep) {
			request_soc_sleep();
			current_state++;
		} else if (mbox_cb_fired) {
			mbox_cb_fired = false;

			qm_mbox_ch_read(mbox_rx, &rx_data);
			if (rx_data.ctrl == SLEEP_REQ) {
				soc_sleep_requested(sleep_ready);
				current_state++;
			}
		}
	}

	QM_PRINTF("Finished: Sleep multicore %s\n", MYNAME);
	return 0;
}
Exemple #12
0
int main(void)
{
	qm_rtc_config_t rtc_cfg;
	uint32_t aonc_start;
	uint32_t rtc_trigger;

	/*  Initialise RTC configuration. */
	rtc_cfg.init_val = 0; /* Set initial value to 0. */
	rtc_cfg.alarm_en = 1; /* Enable alarm. */
	rtc_cfg.alarm_val = QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1); /* 1s alarm. */
	rtc_cfg.callback = NULL;
	rtc_cfg.callback_data = NULL;
	rtc_cfg.prescaler = CLK_RTC_DIV_1;
	qm_rtc_set_config(QM_RTC_0, &rtc_cfg);

	/*
	 * The RTC clock resides in a different clock domain
	 * to the system clock.
	 * It takes 3-4 RTC ticks for a system clock write to propagate
	 * to the RTC domain.
	 * If an entry to sleep is initiated without waiting for the
	 * transaction to complete the SOC will not wake from sleep.
	 */
	aonc_start = QM_AONC[QM_AONC_0]->aonc_cnt;
	while (QM_AONC[QM_AONC_0]->aonc_cnt - aonc_start < RTC_SYNC_CLK_COUNT) {
	}

	QM_IR_UNMASK_INT(QM_IRQ_RTC_0_INT);
	QM_IRQ_REQUEST(QM_IRQ_RTC_0_INT, qm_rtc_0_isr);

	/*
	 * Enable LPSS by the Sensor Subsystem.
	 * This will clock gate sensor peripherals.
	 */
	qm_ss_power_soc_lpss_enable();

	/*
	 * Signal to the x86 core that the Sensor Subsystem
	 * is ready to enter LPSS mode.
	 */
	QM_SCSS_GP->gps2 |= QM_SCSS_GP_SENSOR_READY;

	rtc_trigger = switch_rtc_to_level();

	/* Go to LPSS, RTC will wake the Sensor Subsystem up. */
	qm_ss_power_cpu_ss2();

	/* Log the interrupt event in soc_watch. */
	SOC_WATCH_LOG_EVENT(SOCW_EVENT_INTERRUPT, QM_IRQ_RTC_0_INT_VECTOR);

	restore_rtc_trigger(rtc_trigger);

	/* Clear the SENSOR_READY flag in General Purpose Sticky Register 2. */
	QM_SCSS_GP->gps2 &= ~QM_SCSS_GP_SENSOR_READY;

	/*
	 * Disable LPSS.
	 * This will restore clock gating of sensor peripherals.
	 */
	qm_ss_power_soc_lpss_disable();

	/* Core still in C2 mode. */
	qm_gpio_clear_pin(QM_GPIO_0, PIN_OUT);
	clk_sys_udelay(GPIO_TOGGLE_DELAY);
	qm_gpio_set_pin(QM_GPIO_0, PIN_OUT);
	clk_sys_udelay(GPIO_TOGGLE_DELAY);
	qm_gpio_clear_pin(QM_GPIO_0, PIN_OUT);

	/* Set another alarm 1 second from now. */
	qm_rtc_set_alarm(QM_RTC_0, QM_RTC[QM_RTC_0]->rtc_ccvr +
				       (QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1)));
	/*
	 * The RTC clock resides in a different clock domain
	 * to the system clock.
	 * It takes 3-4 RTC ticks for a system clock write to propagate
	 * to the RTC domain.
	 * If an entry to sleep is initiated without waiting for the
	 * transaction to complete the SOC will not wake from sleep.
	 */
	aonc_start = QM_AONC[QM_AONC_0]->aonc_cnt;
	while (QM_AONC[QM_AONC_0]->aonc_cnt - aonc_start < RTC_SYNC_CLK_COUNT) {
	}

	/*
	 * Enable LPSS by the Sensor Subsystem.
	 * This will clock gate sensor peripherals.
	 */
	qm_ss_power_soc_lpss_enable();

	/*
	 * Signal to the x86 core that the Sensor Subsystem
	 * is ready to enter LPSS mode.
	 */
	QM_SCSS_GP->gps2 |= QM_SCSS_GP_SENSOR_READY;

	rtc_trigger = switch_rtc_to_level();

	/* Go to LPSS, RTC will wake the Sensor Subsystem up. */
	qm_ss_power_cpu_ss2();

	/* Log the interrupt event in soc_watch. */
	SOC_WATCH_LOG_EVENT(SOCW_EVENT_INTERRUPT, QM_IRQ_RTC_0_INT_VECTOR);
	restore_rtc_trigger(rtc_trigger);

	/* Clear the SENSOR_READY flag in General Purpose Sticky Register 2. */
	QM_SCSS_GP->gps2 &= ~QM_SCSS_GP_SENSOR_READY;

	/*
	 * Disable LPSS.
	 * This will restore clock gating of sensor peripherals.
	 */
	qm_ss_power_soc_lpss_disable();

	/* Core still in C2LP mode. */
	qm_gpio_clear_pin(QM_GPIO_0, PIN_OUT);
	clk_sys_udelay(GPIO_TOGGLE_DELAY);
	qm_gpio_set_pin(QM_GPIO_0, PIN_OUT);
	clk_sys_udelay(GPIO_TOGGLE_DELAY);
	qm_gpio_clear_pin(QM_GPIO_0, PIN_OUT);

	/* Trigger soc_watch flush. */
	SOC_WATCH_TRIGGER_FLUSH();

	return 0;
}
Exemple #13
0
/* Sample UART0 QMSI application. */
int main(void)
{
	qm_uart_config_t cfg = {0};
	qm_uart_status_t uart_status __attribute__((unused)) = 0;
	int ret __attribute__((unused));
	const uint32_t xfer_irq_data = BANNER_IRQ_ID;
	const uint32_t xfer_dma_data = BANNER_DMA_ID;

	/* Set divisors to yield 115200bps baud rate. */
	/* Sysclk is set by boot ROM to hybrid osc in crystal mode (32MHz),
	 * peripheral clock divisor set to 1.
	 */
	cfg.baud_divisor = QM_UART_CFG_BAUD_DL_PACK(0, 17, 6);

	cfg.line_control = QM_UART_LC_8N1;
	cfg.hw_fc = false;

/* Mux out STDOUT_UART tx/rx pins and enable input for rx. */
#if (QUARK_SE)
	if (STDOUT_UART == QM_UART_0) {
		qm_pmux_select(QM_PIN_ID_18, QM_PMUX_FN_0);
		qm_pmux_select(QM_PIN_ID_19, QM_PMUX_FN_0);
		qm_pmux_input_en(QM_PIN_ID_18, true);
	} else {
		qm_pmux_select(QM_PIN_ID_16, QM_PMUX_FN_2);
		qm_pmux_select(QM_PIN_ID_17, QM_PMUX_FN_2);
		qm_pmux_input_en(QM_PIN_ID_17, true);
	}

#elif(QUARK_D2000)
	if (STDOUT_UART == QM_UART_0) {
		qm_pmux_select(QM_PIN_ID_12, QM_PMUX_FN_2);
		qm_pmux_select(QM_PIN_ID_13, QM_PMUX_FN_2);
		qm_pmux_input_en(QM_PIN_ID_13, true);
	} else {
		qm_pmux_select(QM_PIN_ID_20, QM_PMUX_FN_2);
		qm_pmux_select(QM_PIN_ID_21, QM_PMUX_FN_2);
		qm_pmux_input_en(QM_PIN_ID_21, true);
	}

#else
#error("Unsupported / unspecified processor detected.")
#endif

	clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_UARTA_REGISTER);
	qm_uart_set_config(STDOUT_UART, &cfg);

	QM_PRINTF("Starting: UART\n");

	/* Synchronous TX. */
	ret = qm_uart_write_buffer(STDOUT_UART, (uint8_t *)BANNER_STR,
				   sizeof(BANNER_STR));
	QM_ASSERT(0 == ret);

/* Register the UART interrupts. */
#if (STDOUT_UART_0)
	qm_irq_request(QM_IRQ_UART_0, qm_uart_0_isr);
#elif(STDOUT_UART_1)
	qm_irq_request(QM_IRQ_UART_1, qm_uart_1_isr);
#endif

	/* Used on both TX and RX. */
	async_xfer_desc.callback_data = (void *)&xfer_irq_data;

	/* IRQ based TX. */
	async_xfer_desc.data = (uint8_t *)BANNER_IRQ;
	async_xfer_desc.data_len = sizeof(BANNER_IRQ);
	async_xfer_desc.callback = uart_example_tx_callback;
	ret = qm_uart_irq_write(STDOUT_UART, &async_xfer_desc);
	QM_ASSERT(0 == ret);

	clk_sys_udelay(WAIT_1SEC);

	/* IRQ based RX. */
	rx_callback_invoked = false;

	async_xfer_desc.data = rx_buffer;
	async_xfer_desc.data_len = BIG_NUMBER_RX;
	async_xfer_desc.callback = uart_example_rx_callback;
	ret = qm_uart_irq_read(STDOUT_UART, &async_xfer_desc);
	QM_ASSERT(0 == ret);
	QM_PRINTF("\nWaiting for you to type %d characters... ?\n",
		  BIG_NUMBER_RX);

	wait_rx_callback_timeout(TIMEOUT_10SEC);

	if (!rx_callback_invoked) {
		/* RX complete callback was not invoked, we need to terminate
		 * the transfer in order to grab whatever is available in the RX
		 * buffer. */
		ret = qm_uart_irq_read_terminate(STDOUT_UART);
		QM_ASSERT(0 == ret);
	} else {
		/* RX complete callback was invoked and RX buffer was read, we
		 * wait in case the user does not stop typing after entering the
		 * exact amount of data that fits the RX buffer, i.e. there may
		 * be additional bytes in the RX FIFO that need to be read
		 * before continuing. */
		clk_sys_udelay(WAIT_5SEC);

		qm_uart_get_status(STDOUT_UART, &uart_status);
		if (QM_UART_RX_BUSY & uart_status) {
			/* There is some data in the RX FIFO, let's fetch it. */
			ret = qm_uart_irq_read(STDOUT_UART, &async_xfer_desc);
			QM_ASSERT(0 == ret);

			ret = qm_uart_irq_read_terminate(STDOUT_UART);
			QM_ASSERT(0 == ret);
		}
	}

	/* Register the DMA interrupts. */
	qm_irq_request(QM_IRQ_DMA_0, qm_dma_0_isr_0);
	qm_irq_request(QM_IRQ_DMA_ERR, qm_dma_0_isr_err);

	/* DMA controller initialization. */
	ret = qm_dma_init(QM_DMA_0);
	QM_ASSERT(0 == ret);

	/* Used on both TX and RX. */
	async_xfer_desc.callback_data = (void *)&xfer_dma_data;

	/* DMA based TX. */
	ret =
	    qm_uart_dma_channel_config(STDOUT_UART, QM_DMA_0, QM_DMA_CHANNEL_0,
				       QM_DMA_MEMORY_TO_PERIPHERAL);
	QM_ASSERT(0 == ret);

	async_xfer_desc.data = (uint8_t *)BANNER_DMA;
	async_xfer_desc.data_len = sizeof(BANNER_DMA);
	async_xfer_desc.callback = uart_example_tx_callback;
	ret = qm_uart_dma_write(STDOUT_UART, &async_xfer_desc);
	QM_ASSERT(0 == ret);

	clk_sys_udelay(WAIT_1SEC);

	/* DMA based RX. */
	rx_callback_invoked = false;

	ret =
	    qm_uart_dma_channel_config(STDOUT_UART, QM_DMA_0, QM_DMA_CHANNEL_0,
				       QM_DMA_PERIPHERAL_TO_MEMORY);
	QM_ASSERT(0 == ret);

	QM_PUTS("Waiting for data on STDOUT_UART (DMA mode) ...");
	async_xfer_desc.data = (uint8_t *)rx_buffer;
	async_xfer_desc.data_len = BIG_NUMBER_RX;
	async_xfer_desc.callback = uart_example_rx_callback;
	ret = qm_uart_dma_read(STDOUT_UART, &async_xfer_desc);
	QM_ASSERT(0 == ret);

	wait_rx_callback_timeout(TIMEOUT_10SEC);

	if (!rx_callback_invoked) {
		/* RX complete callback was not invoked, we need to terminate
		 * the transfer in order to grab whatever was written in the RX
		 * buffer. */
		ret = qm_uart_dma_read_terminate(STDOUT_UART);
		QM_ASSERT(0 == ret);
	}

	QM_PRINTF("\nFinished: UART\n");
	return 0;
}