Пример #1
0
Файл: main.c Проект: jeez/qmsi
int main(void)
{
	/*
	 * All interrupts to wake up from LPSS state need
	 * to be registered to transition again to LPSS.
	 *
	 * The only wake events for LPSS are RTC, AON GPIO,
	 * AON Counter and AON Comparator.
	 *
	 * All interrupts below will wake up the Sensor Subsystem.
	 */
	qm_irq_request(QM_IRQ_RTC_0_INT, dummy_isr);
	qm_irq_request(QM_IRQ_COMPARATOR_0_INT, dummy_isr);
	qm_irq_request(QM_IRQ_AONPT_0_INT, dummy_isr);
	qm_irq_request(QM_IRQ_AON_GPIO_0_INT, dummy_isr);

	/* Unmask comparator interrupts for the Sensor Subsystenm */
	QM_INTERRUPT_ROUTER->comparator_0_ss_halt_int_mask &=
	    ~QM_AC_COMPARATORS_MASK;

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

	/* Loop on SS2 to be ready for LPSS even after wake-up. */
	while (1) {
		ss_power_cpu_ss2();
	}

	return 0;
}
Пример #2
0
Файл: main.c Проект: jeez/qmsi
int main(void)
{
	qm_gpio_port_config_t cfg;

	QM_PUTS("Starting: AON GPIO");

	/* Request IRQ and write GPIO port config. */
	cfg.direction = 0;		   /* Set all pins as inputs. */
	cfg.int_en = BIT(PIN_INTR);	/* Interrupt enabled. */
	cfg.int_type = BIT(PIN_INTR);      /* Edge sensitive interrupt. */
	cfg.int_polarity = ~BIT(PIN_INTR); /* Falling edge. */
	cfg.int_debounce = BIT(PIN_INTR);  /* Debounce enabled. */
	cfg.int_bothedge = 0;		   /* Both edge disabled. */
	cfg.callback = aon_gpio_example_callback;
	cfg.callback_data = NULL;

	qm_irq_request(QM_IRQ_AON_GPIO_0_INT, qm_aon_gpio_0_isr);

	qm_gpio_set_config(QM_AON_GPIO_0, &cfg);

	QM_PUTS("AON GPIO set up, press 'PB0' to trigger the interrupt");

	/* Wait for the AON GPIO callback to be invoked and print the status. */
	while (!callback_invoked)
		;

	QM_PRINTF("Status of AON GPIO callback = 0x%u \n", callback_status);

	QM_PUTS("Finished: AON GPIO");

	return 0;
}
Пример #3
0
int main(void)
{
	/* Comparator example app
	 *
	 * This app sets up comparator 0 to fire an interrupt when the input
	 * voltage is greater than the reference voltage (0.95V)
	 *
	 * On the Intel(R) Quark(TM) Microcontroller D2000 Development Platform
	 * the pin used is marked "SSO 10"
	 */

	qm_ac_config_t ac_cfg;

	QM_PUTS("Analog Comparators example app start\n");

	/* Set up pin muxing and request IRQ*/
	qm_pmux_select(QM_PIN_ID_0, QM_PMUX_FN_1);
	qm_pmux_input_en(QM_PIN_ID_0, true);

	qm_irq_request(QM_IRQ_AC, qm_ac_isr);

	/* Write configs */
	ac_cfg.reference = BIT(0); /* Ref internal voltage */
	ac_cfg.polarity = 0x0;     /* Fire if greater than ref (high level) */
	ac_cfg.power = BIT(0);     /* Normal operation mode */
	ac_cfg.int_en = BIT(0);    /* AIN0 enable */
	ac_cfg.callback = ac_example_callback;

	qm_ac_set_config(&ac_cfg);

	QM_PUTS("Analog Comparators example app complete\n");

	return 0;
}
Пример #4
0
Файл: main.c Проект: jeez/qmsi
static void deep_sleep_test(void)
{
	/*
	 * Setup the RTC to get out of sleep mode. deep sleep will require an
	 * analog comparator interrupt to wake up the system.
	 */
	uint32_t pmux_sel_save[2], pmux_in_en_save, pmux_pullup_save;

	qm_ac_config_t ac_cfg;

	/*
	 * Physical step at this stage to raise the V on the comparator
	 * pin.
	 *
	 * Go to deep sleep, a comparator should wake me up.
	 */
	ac_cfg.reference =
	    BIT(WAKEUP_COMPARATOR_PIN); /* Ref internal voltage. */
	ac_cfg.polarity = 0x0; /* Fire if greater than ref (high level). */
	ac_cfg.power = BIT(WAKEUP_COMPARATOR_PIN);  /* Normal operation mode. */
	ac_cfg.int_en = BIT(WAKEUP_COMPARATOR_PIN); /* Enable comparator. */
	ac_cfg.callback = ac_example_callback;
	qm_ac_set_config(&ac_cfg);

	qm_irq_request(QM_IRQ_COMPARATOR_0_INT, qm_comparator_0_isr);

	/*
	 * Comparator pin will fire an interrupt when the input voltage
	 * is greater than the reference voltage (0.95V).
	 */

	/*
	 * In order to minimise power, pmux_sel must be set to 0, input
	 * enable must be cleared for any pins not expecting to be
	 * used to wake the SoC from deep sleep mode, in this example
	 * we are using AC 6.
	 */
	pmux_sel_save[0] = QM_SCSS_PMUX->pmux_sel[0];
	pmux_sel_save[1] = QM_SCSS_PMUX->pmux_sel[1];
	pmux_in_en_save = QM_SCSS_PMUX->pmux_in_en[0];

	pmux_pullup_save = QM_SCSS_PMUX->pmux_pullup[0];

	QM_SCSS_PMUX->pmux_sel[0] = QM_SCSS_PMUX->pmux_sel[1] = 0;
	QM_SCSS_PMUX->pmux_in_en[0] = BIT(WAKEUP_COMPARATOR_PIN);
	QM_SCSS_PMUX->pmux_pullup[0] = 0;

	/* Mux out comparator. */
	qm_pmux_select(QM_PIN_ID_6, QM_PMUX_FN_1);
	qm_pmux_input_en(QM_PIN_ID_6, true);

	ENTER_C2LP();

	/* Restore previous pinmuxing settings. */
	QM_SCSS_PMUX->pmux_sel[0] = pmux_sel_save[0];
	QM_SCSS_PMUX->pmux_sel[1] = pmux_sel_save[1];
	QM_SCSS_PMUX->pmux_in_en[0] = pmux_in_en_save;
	QM_SCSS_PMUX->pmux_pullup[0] = pmux_pullup_save;
}
Пример #5
0
int main(void)
{
    qm_gpio_port_config_t cfg;

    sensor_activation();

    QM_PUTS("Starting: Power LPSS");

    /* Set GPIO pin muxing. */
    qm_pmux_select(PIN_OUT, QM_PMUX_FN_0);
    qm_pmux_select(PIN_INTR, QM_PMUX_FN_0);

    /* Request IRQ and write GPIO port config. */
    cfg.direction = BIT(PIN_OUT);     /* Set PIN_OUT as output. */
    cfg.int_en = BIT(PIN_INTR);       /* Interrupt enabled. */
    cfg.int_type = BIT(PIN_INTR);     /* Edge sensitive interrupt. */
    cfg.int_polarity = BIT(PIN_INTR); /* Rising edge. */
    cfg.int_debounce = BIT(PIN_INTR); /* Debounce enabled. */
    cfg.int_bothedge = 0x0;		  /* Both edge disabled. */
    cfg.callback = NULL;
    cfg.callback_data = NULL;

    qm_irq_request(QM_IRQ_GPIO_0_INT, qm_gpio_0_isr);

    qm_gpio_set_config(QM_GPIO_0, &cfg);

    QM_PUTS("Go to LPSS with x86 core in C2.");

    /* Wait for the Sensor Subsystem to be ready to transition to LPSS. */
    while (!(QM_SCSS_GP->gps2 & QM_SCSS_GP_SENSOR_READY))
        ;

    /*
     * Go to C2. Sensor Subsystem will perform the transition to LPSS.
     * Once woken up, SS will wake up the x86 core with the GPIO interrupt.
     */
    power_cpu_c2();

    QM_PUTS("Wake up from LPSS.");

    QM_PUTS("Go to LPSS with x86 core in C2LP.");

    /* Wait for the Sensor Subsystem to be ready to transition to LPSS. */
    while (!(QM_SCSS_GP->gps2 & QM_SCSS_GP_SENSOR_READY))
        ;

    /*
     * Go to C2LP. Sensor Subsystem will perform the transition to LPSS.
     * Once woken up, SS will wake up the x86 core with the GPIO interrupt.
     */
    power_cpu_c2lp();

    QM_PUTS("Wake up from LPSS.");

    QM_PUTS("Finished: Power LPSS");

    return 0;
}
Пример #6
0
Файл: main.c Проект: jeez/qmsi
int main(void)
{
	qm_mpr_config_t cfg;
	uint8_t lower_bound;
	uint32_t heap_offset, mpr_base;

	QM_PUTS("Starting: MPR");

	/*
	 * The MPR is located in the heap in order to ensure it doesn't clash
	 * with anything so it is necessary to calculate the page number that
	 * corresponds to the start of the heap.
	 */
	heap_offset = (uint32_t)&__heap;
	lower_bound = (uint8_t)((heap_offset - SRAM_BASE) / MPR_PAGE_SIZE) + 1;

	/* Calculate the physical address of the start of the MPR. */
	mpr_base = SRAM_BASE + (lower_bound * MPR_PAGE_SIZE);

	/* Request the IRQ. */
	qm_irq_request(QM_IRQ_SRAM_MPR_0_INT, qm_sram_mpr_0_isr);

	/* Set the violation policy to trigger an interrupt. */
	qm_mpr_set_violation_policy(MPR_VIOL_MODE_INTERRUPT,
				    mpr_example_callback, NULL);

	/* Configure MPR to allow R/W from DMA agent only. */
	cfg.en_lock_mask = QM_SRAM_MPR_EN_MASK_ENABLE;
	cfg.agent_read_en_mask = QM_SRAM_MPR_AGENT_MASK_DMA;
	cfg.agent_write_en_mask = QM_SRAM_MPR_AGENT_MASK_DMA;
	cfg.up_bound = lower_bound;
	cfg.low_bound = lower_bound;

	qm_mpr_set_config(QM_MPR_0, &cfg);

	/* Trigger a violation event by attempting a write inside the MPR. */
	REG_VAL(mpr_base + 1) = 0xff;

	/* Wait for the callback to be invoked. */
	while (false == callback_invoked)
		;

	QM_PUTS("MPR Violation!");

	QM_PUTS("Finished: MPR");

	return 0;
}
Пример #7
0
Файл: main.c Проект: 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;
}
Пример #8
0
Файл: main.c Проект: jeez/qmsi
int main(void)
{
	uint32_t c_val = 0, pt_val = 0;
	qm_aonpt_config_t cfg;

	QM_PUTS("Starting: Always-on Counter");

	/* Always-on Counter enable and read value. */
	qm_aonc_enable(QM_AONC_0);

	if (qm_aonc_get_value(QM_AONC_0, &c_val) == 0) {
		QM_PRINTF("Always-on Counter value: %u\n", c_val);
	} else {
		QM_PUTS("Error: Could not read aonc value.");
	}

	/* Request an IRQ and write the Always-on Periodic Timer config. */
	cfg.count = 0x1000; /* 0.125 seconds. */
	cfg.int_en = true;  /* Interrupts enabled. */
	cfg.callback = aonpt_example_callback;

	qm_irq_request(QM_IRQ_AONPT_0_INT, qm_aonpt_0_isr);

	qm_aonpt_set_config(QM_AONC_0, &cfg);

	/* Wait for the defined number of callbacks be invoked. */
	while (NUM_CALLBACKS > callback_count)
		;

	QM_PRINTF("Periodic Timer callback fired %d times.\n", callback_count);

	/* Get the value of the Always-on Periodic Timer. */
	if (qm_aonpt_get_value(QM_AONC_0, &c_val) == 0) {
		QM_PRINTF("Always-on Periodic Timer value: %u\n", pt_val);
	} else {
		QM_PUTS("Error: Could not read Periodic timer value");
	}

	/* Disable the always-on periodic timer interrupt. */
	cfg.int_en = false;
	qm_aonpt_set_config(QM_AONC_0, &cfg);

	QM_PUTS("Finished: Always-on counter");

	return 0;
}
Пример #9
0
Файл: main.c Проект: jeez/qmsi
int main(void)
{
	qm_rtc_config_t rtc_cfg;
	unsigned int count = 0;
	/* Maximum number of 3-second iterations. */
	const unsigned int loop_max = 5;
	gpio_init();
	gpio_set_out(BOARD_LED_PIN, 0); /* Configure the onboard LED pin. */

	/* Clear Screen. */
	QM_PUTS("Starting: Power Profiler");
	QM_PUTS("Low power mode example.");
	QM_PRINTF("Increment = %d\n", QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1));

	clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);

	/* Initialise RTC configuration: Run, but don't interrupt. */
	rtc_cfg.init_val = 0;
	rtc_cfg.alarm_en = 0;
	rtc_cfg.alarm_val = QM_RTC_ALARM_SECOND(CLK_RTC_DIV_1);
	rtc_cfg.callback = rtc_example_callback;
	rtc_cfg.prescaler = CLK_RTC_DIV_1;
	qm_rtc_set_config(QM_RTC_0, &rtc_cfg);

	qm_irq_request(QM_IRQ_RTC_0_INT, qm_rtc_0_isr);

	test_clock_rates();

	/* Enable the RTC Interrupt. */
	rtc_cfg.alarm_en = 1;
	qm_rtc_set_config(QM_RTC_0, &rtc_cfg);

	count = 0;
	while (++count < loop_max) {
		QM_PRINTF("\nC:%d R:%d => ", count, rtc_tick);

		slow_mode_test();
		halt_test();
		sleep_test();
#if DEEP_SLEEP
		deep_sleep_test();
#endif
	}
	QM_PUTS("Finished: Power Profiler");
	return 0;
}
Пример #10
0
int main(void)
{
	volatile uint32_t delay;
	uint32_t c_val = 0, pt_val = 0;
	qm_aonpt_config_t cfg;

	QM_PUTS("\nAlways-on Counter example app\n");

	/* Always-on Counter enable, disable and read value */
	qm_aonc_disable(QM_SCSS_AON_0);
	qm_aonc_enable(QM_SCSS_AON_0);

	c_val = qm_aonc_get_value(QM_SCSS_AON_0);
	if (c_val) {
		QM_PRINTF("Always-on Counter value: %lu\n", c_val);
	} else {
		QM_PRINTF("ERROR: Could not read aonc value\n");
	}

	/* Request an IRQ and write the Always-on Periodic Timer config */
	cfg.count = 0x10000;
	cfg.int_en = true;
	cfg.callback = aonpt_example_callback;

	qm_irq_request(QM_IRQ_AONPT_0, qm_aonpt_isr_0);

	qm_aonpt_set_config(QM_SCSS_AON_0, &cfg);

	/* The AON Periodic Timer runs from the RTC clock at 32KHz (rather than
	 * the system clock which is 32MHz) so we need to spin for a few cycles
	 * allow the register change to propagate */
	for (delay = 500; delay--;) {
	}

	/* Get the value of the Always-on Periodic Timer */
	pt_val = qm_aonpt_get_value(QM_SCSS_AON_0);
	if (pt_val) {
		QM_PRINTF("Always-on Periodic Timer value: %lu\n", pt_val);
	} else {
		QM_PRINTF("ERROR: Could not read Periodic timer value\n\n");
	}

	QM_PUTS("Always-on counter example app complete\n");
	return 0;
}
Пример #11
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;
}
Пример #12
0
/* QMSI MPR sample application: this example uses an MPR to pretect a 1kB page
   of SRAM, and then triggers an MPR violation interrupt. */
int main(void)
{
	qm_mpr_config_t cfg;
	uint8_t lower_bound;
	uint32_t heap_offset, sram_base, mpr_base;

	QM_PUTS("\nMPR example app start");

	/* we're going to put this MPR in the heap, to ensure it doesn't clash
	 * with anything else, so we need to figure out the page number that
	 * corresponds to the start of the heap */
	heap_offset = (uint32_t)&__heap;

	/* the IDT lives at the start of SRAM, so __idt_start gives us the SRAM
	 * base address in the Lakemont memory map */
	sram_base = (uint32_t)&__idt_start;
	lower_bound = (uint8_t)((heap_offset - sram_base) / MPR_PAGE_SIZE) + 1;

	/* get the Lakemont physical address of the start of the MPR */
	mpr_base = sram_base + (lower_bound * MPR_PAGE_SIZE);

	/* Set the violation policy to trigger an interrupt */
	qm_irq_request(QM_IRQ_SRAM, qm_mpr_isr);
	qm_mpr_set_violation_policy(MPR_VIOL_MODE_INTERRUPT,
				    mpr_example_callback);

	/* Configure MPR to allow R/W from DMA agent */
	cfg.en_lock_mask = QM_SRAM_MPR_EN_MASK_ENABLE;
	cfg.agent_read_en_mask = QM_SRAM_MPR_AGENT_MASK_DMA;
	cfg.agent_write_en_mask = QM_SRAM_MPR_AGENT_MASK_DMA;
	cfg.up_bound = lower_bound;
	cfg.low_bound = lower_bound;

	qm_mpr_set_config(QM_MPR_0, &cfg);

	/* trigger a violation event by attempting a write inside the MPR */
	REG_VAL(mpr_base + 1) = 0xff;

	QM_PUTS("MPR example app complete");
	return 0;
}
Пример #13
0
/*-------------------------------------------------------------------------*/
void xmodem_io_uart_init()
{
	/* Pinmux for UART_x */
	qm_pmux_select(DM_COMM_UART_PIN_TX_ID, DM_COMM_UART_PIN_TX_FN);
	qm_pmux_select(DM_COMM_UART_PIN_RX_ID, DM_COMM_UART_PIN_RX_FN);
	qm_pmux_input_en(DM_COMM_UART_PIN_RX_ID, true);

	/* Enable UART and RTC clocks */
	clk_periph_enable(DM_COMM_UART_CLK | CLK_PERIPH_RTC_REGISTER |
			  CLK_PERIPH_CLK);

	/* Setup UART */
	qm_uart_set_config(DM_CONFIG_UART, &uart_config);

	/* Request IRQ for UART */
	dm_comm_irq_request();

	/* Set up timeout timer (RTC) */
	qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);
	qm_rtc_set_config(QM_RTC_0, &rtc_cfg);
}
Пример #14
0
int main(void)
{
	qm_gpio_port_config_t cfg;

	QM_PUTS("AON GPIO example\n");

	/* Request IRQ and write GPIO port config */
	cfg.direction = 0;		   /* All pins are input */
	cfg.int_en = BIT(PIN_INTR);	/* Interrupt enabled */
	cfg.int_type = BIT(PIN_INTR);      /* Edge sensitive interrupt */
	cfg.int_polarity = ~BIT(PIN_INTR); /* Falling edge */
	cfg.int_debounce = BIT(PIN_INTR);  /* Debounce enabled */
	cfg.int_bothedge = 0x0;		   /* Both edge disabled */
	cfg.callback = aon_gpio_example_callback;

	qm_irq_request(QM_IRQ_AONGPIO_0, qm_aon_gpio_isr_0);

	qm_gpio_set_config(QM_AON_GPIO_0, &cfg);
	QM_PUTS("AON GPIO set up, press the Push Button 0 to trigger the "
		"interrupt\n");
	return 0;
}
Пример #15
0
Файл: main.c Проект: 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");
}
Пример #16
0
Файл: main.c Проект: Hlotfy/qmsi
/* QMSI wdt app example */
int main(void)
{
	qm_wdt_config_t wr_cfg;

	QM_PRINTF("Starting: WDT\n");

	wr_cfg.timeout = QM_WDT_2_POW_17_CYCLES;
	wr_cfg.mode = QM_WDT_MODE_INTERRUPT_RESET;
	wr_cfg.callback = wdt_example_callback;

	wdt_fired = 0;

	qm_wdt_set_config(QM_WDT_0, &wr_cfg);
	qm_irq_request(QM_IRQ_WDT_0, qm_wdt_isr_0);

	qm_wdt_start(QM_WDT_0);

	/* Wait for WDT to fire 10 times and then finish. */
	while (wdt_fired < MAX_WDT_FIRINGS) {
	}
	QM_PRINTF("Watchdog fired %d times\n", MAX_WDT_FIRINGS);
	QM_PRINTF("Finished: WDT\n");
	return 0;
}
Пример #17
0
int main(void)
{
	qm_rtc_config_t rtc;

	QM_PUTS("Accelerometer example app\n");

	rtc.init_val = 0;
	rtc.alarm_en = true;
	rtc.alarm_val = ALARM;
	rtc.callback = print_accel_callback;

	qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);

	clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);

	bmc150_init(BMC150_J14_POS_0);

	bmc150_set_accel_mode(BMC150_MODE_2G);
	bmc150_set_bandwidth(BMC150_BANDWIDTH_64MS);

	qm_rtc_set_config(QM_RTC_0, &rtc);

	return 0;
}
Пример #18
0
SOL_API struct sol_i2c *
sol_i2c_open_raw(uint8_t bus, enum sol_i2c_speed speed)
{
    struct sol_i2c *i2c;
    qm_i2c_config_t cfg;
    qm_i2c_speed_t bus_speed;
    qm_rc_t ret;

    if (bus >= QM_I2C_NUM) {
        SOL_WRN("I2C bus #%" PRIu8 " doesn't exist.", bus);
        return NULL;
    }

    if ((i2c = buses[bus]) != NULL)
        return i2c;

    switch (speed) {
    case SOL_I2C_SPEED_10KBIT:
    case SOL_I2C_SPEED_100KBIT:
        bus_speed = QM_I2C_SPEED_STD;
        break;
    case SOL_I2C_SPEED_400KBIT:
        bus_speed = QM_I2C_SPEED_FAST;
        break;
    case SOL_I2C_SPEED_1MBIT:
    case SOL_I2C_SPEED_3MBIT_400KBIT:
        bus_speed = QM_I2C_SPEED_FAST_PLUS;
        break;
    default:
        SOL_WRN("Unsupported speed value: %d", speed);
        return NULL;
    };

    switch (bus) {
    case QM_I2C_0:
        qm_irq_request(QM_IRQ_I2C_0, qm_i2c_0_isr);
        clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_I2C_M0_REGISTER);
        break;
#if QUARK_SE
    case QM_I2C_1:
        qm_irq_request(QM_IRQ_I2C_1, qm_i2c_1_isr);
        clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_I2C_M1_REGISTER);
        break;
#endif
    case QM_I2C_NUM:
        /* We checked if we were passed the limit before, so we should never
         * hit this point. Using all the enum values and no default, however,
         * allows us to rely on the compiler to know if there are values
         * we are not considering (depending on warning levels) */
        break;
    }

    i2c = calloc(1, sizeof(*i2c));
    SOL_NULL_CHECK(i2c, NULL);

    i2c->bus = bus;

    ret = qm_i2c_get_config(i2c->bus, &cfg);
    SOL_EXP_CHECK_GOTO(ret != QM_RC_OK, error);

    cfg.speed = bus_speed;
    cfg.address_mode = QM_I2C_7_BIT;
    cfg.mode = QM_I2C_MASTER;
    cfg.slave_addr = 0;

    ret = qm_i2c_set_config(i2c->bus, &cfg);
    SOL_EXP_CHECK_GOTO(ret != QM_RC_OK, error);

    if (!i2c_irq_event) {
        bool r;

        i2c_irq_event = process_alloc_event();
        r = sol_mainloop_contiki_event_handler_add(&i2c_irq_event, NULL,
            i2c_cb_dispatch, NULL);
        SOL_EXP_CHECK_GOTO(!r, error);
    }

    buses[i2c->bus] = i2c;

    return i2c;

error:
    free(i2c);
    return NULL;
}
Пример #19
0
int main(void)
{
#if (QUARK_D2000)
	int i;
	qm_adc_config_t cfg;
	qm_adc_xfer_t xfer;
	qm_adc_channel_t channels[] = {QM_ADC_CH_8, QM_ADC_CH_9};
	uint32_t samples_polled[NUM_SAMPLES_POLLED] = {0};
	uint32_t samples_interrupt[NUM_SAMPLES_INTERRUPT] = {0};

	QM_PUTS("\nADC example app start");

	/* Enable the ADC and set the clock divisor */
	clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_ADC |
			  CLK_PERIPH_ADC_REGISTER);
	clk_adc_set_div(100); /* ADC clock is 320KHz @ 32MHz */

	/* Set up pinmux */
	qm_pmux_select(QM_PIN_ID_8, QM_PMUX_FN_1);
	qm_pmux_select(QM_PIN_ID_9, QM_PMUX_FN_1);
	qm_pmux_input_en(QM_PIN_ID_8, true);
	qm_pmux_input_en(QM_PIN_ID_9, true);

	/* Set the mode and calibrate */
	qm_adc_set_mode(QM_ADC_0, QM_ADC_MODE_NORM_CAL);
	qm_adc_calibrate(QM_ADC_0);

	/* Set up config */
	cfg.window = 20; /* Clock cycles between the start of each sample */
	cfg.resolution = QM_ADC_RES_12_BITS;
	qm_adc_set_config(QM_ADC_0, &cfg);

	/*******************************
	 * ADC polled mode example
	 ******************************/
	QM_PUTS("ADC polled mode");

	/* Set up xfer */
	xfer.ch = channels;
	xfer.ch_len = NUM_CHANNELS;
	xfer.samples = samples_polled;
	xfer.samples_len = NUM_SAMPLES_POLLED;

	/* Run the conversion */
	if (qm_adc_convert(QM_ADC_0, &xfer)) {
		QM_PUTS("ERROR: qm_adc_convert failed");
		return 1;
	}

	/* Print the values of the samples */
	for (i = 0; i < NUM_SAMPLES_POLLED; i++) {
		QM_PRINTF("%d:%x ", i, (unsigned int)samples_polled[i]);
	}

	/*******************************
	 * ADC interrupt mode example
	 ******************************/
	QM_PUTS("\nADC interrupt mode");

	qm_irq_request(QM_IRQ_ADC_0, qm_adc_0_isr);

	/* Set up xfer */
	xfer.ch = channels;
	xfer.ch_len = NUM_CHANNELS;
	xfer.samples = samples_interrupt;
	xfer.samples_len = NUM_SAMPLES_INTERRUPT;
	xfer.complete_callback = complete_callback;
	xfer.error_callback = error_callback;

	if (qm_adc_irq_convert(QM_ADC_0, &xfer)) {
		QM_PUTS("ERROR: qm_adc_irq_convert failed");
		return 1;
	}

	/* Wait for the callback */
	while (false == complete)
		;

	for (i = 0; i < NUM_SAMPLES_INTERRUPT; i++) {
		QM_PRINTF("%d:%x ", i, (unsigned int)samples_interrupt[i]);
	}

	QM_PUTS("\nADC example app complete");

#endif /* QUARK_D2000 */
	return 0;
}
Пример #20
0
Файл: main.c Проект: jeez/qmsi
int main(void)
{
	qm_dma_channel_config_t cfg = {0};
	static dma_channel_desc_t chan_desc;
	int return_code, i;

	QM_PUTS("Starting: DMA");

	/*
	 * Request the required interrupts. Depending on the channel used a
	 * different isr is set:
	 *     qm_irq_request(QM_IRQ_DMA_0_INT_<channel>,
	 * qm_dma_0_isr_<channel>)
	 */
	qm_irq_request(QM_IRQ_DMA_0_INT_0, qm_dma_0_isr_0);
	qm_irq_request(QM_IRQ_DMA_0_ERROR_INT, qm_dma_0_error_isr);

	/* Set the controller and channel IDs. */
	chan_desc.controller_id = QM_DMA_0;
	chan_desc.channel_id = QM_DMA_CHANNEL_0;

	return_code = qm_dma_init(chan_desc.controller_id);
	if (return_code) {
		QM_PUTS("ERROR: qm_dma_init");
	}

	/* Configure DMA channel. */
	cfg.channel_direction = QM_DMA_MEMORY_TO_MEMORY;
	cfg.source_transfer_width = QM_DMA_TRANS_WIDTH_8;
	cfg.destination_transfer_width = QM_DMA_TRANS_WIDTH_8;
	cfg.source_burst_length = QM_DMA_BURST_TRANS_LENGTH_1;
	cfg.destination_burst_length = QM_DMA_BURST_TRANS_LENGTH_1;
	cfg.client_callback = transfer_callback;
	cfg.transfer_type = QM_DMA_TYPE_SINGLE;

	/*
	 * Set the context as the channel descriptor. This will allow the
	 * descriptor to be available in the callback.
	 * The callback context is not actually used in this app. It is
	 * provided as an example.
	 */
	cfg.callback_context = (void *)&chan_desc;

	return_code = qm_dma_channel_set_config(chan_desc.controller_id,
						chan_desc.channel_id, &cfg);
	if (return_code) {
		QM_PUTS("ERROR: qm_dma_channel_set_config");
	}

	/* Do the transfers. */
	do_transfer(&chan_desc);

	QM_PUTS("Each RX buffer should contain the full TX buffer string.");
	QM_PRINTF("TX data: %s\n", tx_data);

	/* Print copied data. */
	for (i = 0; i < NUM_TRANSFERS; i++) {
		QM_PRINTF("RX data Loop %d: %s\n", i, rx_data[i]);
	}

	/* Configure DMA channel for multiblock usage. */
	cfg.transfer_type = QM_DMA_TYPE_MULTI_LL;
	return_code = qm_dma_channel_set_config(chan_desc.controller_id,
						chan_desc.channel_id, &cfg);
	if (return_code) {
		QM_PUTS("ERROR: qm_dma_channel_set_config");
	}

	/* Do the multiblock transfer. */
	do_transfer_multi(&chan_desc);

	QM_PRINTF("RX data (multiblock transfer):\n");
	rx_data[1][0] = '\0';
	printf("%s\n", (char *)&rx_data[0][0]);

	QM_PUTS("Finished: DMA");

	return 0;
}
Пример #21
0
/* Low power app example */
int main(void)
{
	/* Setup the RTC to get out of sleep mode. deep sleep will require an */
	/* analog comparator interrupt to wake up the system. */
	/*  Variables */
	uint32_t pmux_sel_save[2], pmux_in_en_save, pmux_pullup_save;
	qm_ac_config_t ac_cfg;
	qm_rtc_config_t rtc_cfg;

	QM_PUTS("Low power mode example.");

	clk_periph_enable(CLK_PERIPH_RTC_REGISTER | CLK_PERIPH_CLK);

	/*  Initialise RTC configuration. */
	rtc_cfg.init_val = 0;
	rtc_cfg.alarm_en = 1;
	rtc_cfg.alarm_val = QM_RTC_ALARM_SECOND;
	rtc_cfg.callback = rtc_example_callback;
	qm_rtc_set_config(QM_RTC_0, &rtc_cfg);

	qm_irq_request(QM_IRQ_RTC_0, qm_rtc_isr_0);

	QM_PUTS("CPU Halt.");
	/* Halt the CPU, RTC alarm will wake me up. */
	cpu_halt();
	QM_PUTS("CPU Halt wakeup.");

	/* Set another alarm one minute from now. */
	qm_rtc_set_alarm(QM_RTC_0,
			 QM_RTC[QM_RTC_0].rtc_ccvr + QM_RTC_ALARM_SECOND);
	QM_PUTS("Go to sleep.");
	/* Go to sleep, RTC will wake me up. */
	soc_sleep();
	QM_PUTS("Wake up from sleep.");

	/* Physical step at this stage to raise the V on the comparator pin. */
	/* Go to deep sleep, a comparator should wake me up. */
	QM_PUTS("Go to deep sleep.");

	ac_cfg.reference =
	    BIT(WAKEUP_COMPARATOR_PIN); /* Ref internal voltage */
	ac_cfg.polarity = 0x0; /* Fire if greater than ref (high level) */
	ac_cfg.power = BIT(WAKEUP_COMPARATOR_PIN);  /* Normal operation mode */
	ac_cfg.int_en = BIT(WAKEUP_COMPARATOR_PIN); /* Enable comparator */
	ac_cfg.callback = ac_example_callback;
	qm_ac_set_config(&ac_cfg);

	qm_irq_request(QM_IRQ_AC, qm_ac_isr);

	/*
	 * Comparator pin will fire an interrupt when the input voltage is
	 * greater than the reference voltage (0.95V).
	 */

	/*
	 * In order to minimise power, pmux_sel must be set to 0, input enable
	 * must be cleared for any pins not expecting to be used to wake the
	 * SoC from deep sleep mode, in this example we are using AC 6.
	 */
	pmux_sel_save[0] = QM_SCSS_PMUX->pmux_sel[0];
	pmux_sel_save[1] = QM_SCSS_PMUX->pmux_sel[1];
	pmux_in_en_save = QM_SCSS_PMUX->pmux_in_en[0];

	pmux_pullup_save = QM_SCSS_PMUX->pmux_pullup[0];

	QM_SCSS_PMUX->pmux_sel[0] = QM_SCSS_PMUX->pmux_sel[1] = 0;
	QM_SCSS_PMUX->pmux_in_en[0] = BIT(WAKEUP_COMPARATOR_PIN);
	QM_SCSS_PMUX->pmux_pullup[0] = 0;

	/* Mux out comparator */
	qm_pmux_select(QM_PIN_ID_6, QM_PMUX_FN_1);
	qm_pmux_input_en(QM_PIN_ID_6, true);

	soc_deep_sleep();

	/* Restore previous pinmuxing settings. */
	QM_SCSS_PMUX->pmux_sel[0] = pmux_sel_save[0];
	QM_SCSS_PMUX->pmux_sel[1] = pmux_sel_save[1];
	QM_SCSS_PMUX->pmux_in_en[0] = pmux_in_en_save;
	QM_SCSS_PMUX->pmux_pullup[0] = pmux_pullup_save;

	QM_PUTS("Wake up from deep sleep.");
	return 0;
}
Пример #22
0
SOL_API struct sol_spi *
sol_spi_open(unsigned int bus, const struct sol_spi_config *config)
{
    struct sol_spi *spi;
    qm_spi_t max_bus_available;
    int ret;

    SOL_LOG_INTERNAL_INIT_ONCE;

    /* QM_SPI_NUM is always considering that both master and the slave
     * exist, so we can't use it to check the valid buses to use */
#if QUARK_SE
    max_bus_available = QM_SPI_MST_1;
#else
    max_bus_available = QM_SPI_MST_0;
#endif

    SOL_EXP_CHECK(bus >= max_bus_available, NULL);
    SOL_NULL_CHECK(config, NULL);

#ifndef SOL_NO_API_VERSION
    if (unlikely(config->api_version != SOL_SPI_CONFIG_API_VERSION)) {
        SOL_WRN("Couldn't open SPI that has unsupported version '%u', "
            "expected version is '%u'",
            config->api_version, SOL_SPI_CONFIG_API_VERSION);
        return NULL;
    }
#endif

    if (config->chip_select > 3) {
        SOL_WRN("Invalid chip_select value '%u'. Value must be between 0 and 3.",
            config->chip_select);
        return NULL;
    }

    if ((config->bits_per_word < 4) || (config->bits_per_word > 32)) {
        SOL_WRN("Invalid bits_per_word value '%" PRIu8 "'. Value must be "
            "between 4 and 32.", config->bits_per_word);
        return NULL;
    }

    spi = calloc(1, sizeof(*spi));
    SOL_NULL_CHECK(spi, NULL);

    if (!spi_irq_event) {
        bool r;

        spi_irq_event = process_alloc_event();
        r = sol_mainloop_contiki_event_handler_add(&spi_irq_event, NULL,
            spi_cb_dispatch, NULL);
        SOL_EXP_CHECK_GOTO(!r, error);
    }

    spi->bus = bus;
    spi->slave = BIT(config->chip_select);
    spi->config.frame_size = config->bits_per_word - 1;
    spi->config.transfer_mode = QM_SPI_TMOD_TX_RX;
    spi->config.bus_mode = config->mode;
    spi->config.clk_divider = 32000000 / config->frequency;

    switch (spi->bus) {
    case QM_SPI_MST_0:
        clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_SPI_M0_REGISTER);
        qm_irq_request(QM_IRQ_SPI_MASTER_0, qm_spi_master_0_isr);
        break;
#if QUARK_SE
    case QM_SPI_MST_1:
        qm_irq_request(QM_IRQ_SPI_MASTER_1, qm_spi_master_1_isr);
        break;
#endif
    case QM_SPI_SLV_0:
    case QM_SPI_NUM:
        /* We checked if we were passed the limit before, so we should never
         * hit this point. Using all the enum values and no default, however,
         * allows us to rely on the compiler to know if there are values
         * we are not considering (depending on warning levels) */
        break;
    }

    ret = spi_set_gpio_ss(spi);
    SOL_INT_CHECK_GOTO(ret, < 0, error);

    return spi;

error:
    free(spi);
    return NULL;
}
Пример #23
0
/*  QMSI SPI app example */
int main(void)
{
	/*  Variables */
	qm_spi_config_t cfg;
	qm_spi_transfer_t polled_xfer_desc;
	qm_spi_async_transfer_t irq_xfer_desc;
	unsigned int i;

	for (i = 0; i < BUFFERSIZE; i++) {
		tx_buff[i] = i;
	}

/* Mux out SPI tx/rx pins and enable input for rx. */
#if (QUARK_SE)
	qm_pmux_select(QM_PIN_ID_55, QM_PMUX_FN_1); /* SPI0_M SCK */
	qm_pmux_select(QM_PIN_ID_56, QM_PMUX_FN_1); /* SPI0_M MISO */
	qm_pmux_select(QM_PIN_ID_57, QM_PMUX_FN_1); /* SPI0_M MOSI */
	qm_pmux_select(QM_PIN_ID_58, QM_PMUX_FN_1); /* SPI0_M SS0 */
	qm_pmux_select(QM_PIN_ID_59, QM_PMUX_FN_1); /* SPI0_M SS1 */
	qm_pmux_select(QM_PIN_ID_60, QM_PMUX_FN_1); /* SPI0_M SS2 */
	qm_pmux_select(QM_PIN_ID_61, QM_PMUX_FN_1); /* SPI0_M SS3 */
	qm_pmux_input_en(QM_PIN_ID_56, true);

#elif(QUARK_D2000)
	qm_pmux_select(QM_PIN_ID_0, QM_PMUX_FN_2);  /* SS0 */
	qm_pmux_select(QM_PIN_ID_1, QM_PMUX_FN_2);  /* SS1 */
	qm_pmux_select(QM_PIN_ID_2, QM_PMUX_FN_2);  /* SS2 */
	qm_pmux_select(QM_PIN_ID_3, QM_PMUX_FN_2);  /* SS3 */
	qm_pmux_select(QM_PIN_ID_16, QM_PMUX_FN_2); /* SCK */
	qm_pmux_select(QM_PIN_ID_17, QM_PMUX_FN_2); /* TXD */
	qm_pmux_select(QM_PIN_ID_18, QM_PMUX_FN_2); /* RXD */
	qm_pmux_input_en(QM_PIN_ID_18, true);       /* RXD input */
#else
#error("Unsupported / unspecified processor detected.")
#endif

	/* Enable the clock to the controller. */
	clk_periph_enable(CLK_PERIPH_CLK | CLK_PERIPH_SPI_M0_REGISTER);

	/*  Initialise SPI configuration */
	cfg.frame_size = QM_SPI_FRAME_SIZE_8_BIT;
	cfg.transfer_mode = QM_SPI_TMOD_TX_RX;
	cfg.bus_mode = QM_SPI_BMODE_0;
	cfg.clk_divider = SPI_CLOCK_DIV;

	qm_spi_set_config(QM_SPI_MST_0, &cfg);

	/* Set up loopback mode by RMW directly to the ctrlr0 register. */
	QM_SPI[QM_SPI_MST_0]->ctrlr0 |= BIT(11);

	qm_spi_slave_select(QM_SPI_MST_0, QM_SPI_SS_0);

	QM_PRINTF("\nStatus = 0x%08x", qm_spi_get_status(QM_SPI_MST_0));

	/* Set up the sync transfer struct and call a polled transfer. */
	polled_xfer_desc.tx = tx_buff;
	polled_xfer_desc.rx = rx_buff;
	polled_xfer_desc.tx_len = BUFFERSIZE;
	polled_xfer_desc.rx_len = BUFFERSIZE;

	qm_spi_transfer(QM_SPI_MST_0, &polled_xfer_desc);

	/* Compare RX and TX buffers */
	/* Also reset the buffers for the IRQ example */
	for (i = 0; i < BUFFERSIZE; i++) {
		QM_CHECK(tx_buff[i] == rx_buff[i], QM_RC_EINVAL);
		tx_buff[i] = i;
		rx_buff[i] = 0;
	}

	/* Set up the async transfer struct. */
	irq_xfer_desc.tx = tx_buff;
	irq_xfer_desc.rx = rx_buff;
	irq_xfer_desc.tx_len = BUFFERSIZE;
	irq_xfer_desc.rx_len = BUFFERSIZE;
	irq_xfer_desc.id = SPI_EXAMPLE_IRQ_ID;
	irq_xfer_desc.rx_callback = spi_rx_example_cb;
	irq_xfer_desc.tx_callback = spi_tx_example_cb;
	irq_xfer_desc.err_callback = spi_err_example_cb;

	/* Register driver IRQ. */
	qm_irq_request(QM_IRQ_SPI_MASTER_0, qm_spi_master_0_isr);

	/* Start the async (irq-based) transfer. */
	qm_spi_irq_transfer(QM_SPI_MST_0, &irq_xfer_desc);

	while (1)
		;

	return 0;
}
Пример #24
0
Файл: main.c Проект: Hlotfy/qmsi
int main(void)
{
	uint32_t flash_base;
	uint32_t fpr_flash;
	uint32_t value;
	uint32_t app_end;
	uint32_t address;
	uint8_t low_bound;
	qm_fpr_config_t cfg = {0};

#if (QUARK_D2000)
	flash_base = QM_FLASH_REGION_SYS_0_BASE;
	fpr_flash = QM_FLASH_0;
#elif(QUARK_SE)
	flash_base = QM_FLASH_REGION_SYS_1_BASE;
	fpr_flash = QM_FLASH_1;
#endif

	QM_PRINTF("Starting: FPR\n");

	/* Calculate how much space the application code occupies, so we can
	 * ensure our FPR does not overlap with it */
	app_end = (uint32_t)__data_lma + (uint32_t)__data_size;

	if ((app_end + FPR_SIZE + 1) > FLASH_END) {
		QM_PRINTF("No free pages. Quitting.\n");
		return 0;
	}

	/* Calculate 1k-aligned physical flash address for FPR start */
	low_bound = ((app_end - flash_base) / FPR_SIZE) + 1;

	/* Calculate MMIO address of a location inside the FPR */
	address = (flash_base + (FPR_SIZE * low_bound)) + 4;

/* Set the violation policy to trigger an interrupt */
#if (QUARK_D2000)
	qm_irq_request(QM_IRQ_FLASH_0, qm_fpr_isr_0);
#elif(QUARK_SE)
	qm_irq_request(QM_IRQ_FLASH_1, qm_fpr_isr_1);
#endif

	qm_fpr_set_violation_policy(FPR_VIOL_MODE_INTERRUPT, fpr_flash,
				    fpr_example_cb, NULL);

	/* Configure MPR to allow R/W from DMA agent only */
	cfg.en_mask = QM_FPR_ENABLE;
	cfg.allow_agents = QM_FPR_DMA;
	cfg.up_bound = low_bound + 1;
	cfg.low_bound = low_bound;

	qm_fpr_set_config(fpr_flash, QM_FPR_0, &cfg, QM_MAIN_FLASH_SYSTEM);

	/* Trigger a violation event by attempting to read in the FLASH */
	value = REG_VAL(address);

	while (false == callback_invoked) {
	}
	QM_PRINTF("Finished: FPR\n");
	value = value;
	return 0;
}
Пример #25
0
Файл: main.c Проект: Hlotfy/qmsi
/* 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;
}