示例#1
0
/******************************************************************************
    rn42_init
*//**
    @brief Initializes RN42 driver.

    @brief usart    Pointer to the USART hardware structure the RN42 is on.
    @brief irq      IRQ number to process interrupts on.
    @brief gpio_pin Pin connected to the RN42's status output.
******************************************************************************/
void
rn42_init(
    volatile avr32_usart_t *usart,
    uint32_t irq,
    uint32_t gpio_pin)
{ 
    static usart_options_t usart_options =
    {
        .baudrate     = 115200,
        .charlength   = 8,
        .paritytype   = USART_NO_PARITY,
        .stopbits     = USART_1_STOPBIT,
        .channelmode  = USART_NORMAL_CHMODE
    };

    static pdca_channel_options_t pdca_rx_options =
    {
        .pid = AVR32_PDCA_PID_USART3_RX,
        .addr = NULL,
        .size = 0,
        .r_addr = NULL,
        .r_size = 0,
        .transfer_size = PDCA_TRANSFER_SIZE_BYTE
    };

    static pdca_channel_options_t pdca_tx_options =
    {
        .pid = AVR32_PDCA_PID_USART3_TX,
        .addr = NULL,
        .size = 0,
        .r_addr = NULL,
        .r_size = 0,
        .transfer_size = PDCA_TRANSFER_SIZE_BYTE
    };

    /* Initialize the USART to use hardware handshaking. Without the
       handshaking, the RN42 has trouble keeping up when continuosly sending
       fairly small amounts of data. Note that when hardware handshaking is
       enabled, the PDCA must be used for receiving data.
     */
    rn42_usart = usart;
    usart_serial_init(rn42_usart, &usart_options);
    rn42_usart->mr = (rn42_usart->mr & ~0xf) | 0x02;

    /* Register the ISR for USART's DMA completion IRQs. */
    pdca_init_channel(PDCA_CHANNEL_RX, &pdca_rx_options);
    pdca_init_channel(PDCA_CHANNEL_TX, &pdca_tx_options);
    irq_register_handler(usart_isr, PDCA_IRQ, 0);

    setup_usart_rx_dma(bt_buf, sizeof(command_t));
    usart_irq_enable();
    pdca_enable(PDCA_CHANNEL_RX);
    pdca_enable(PDCA_CHANNEL_TX);

    /* Configure RN42 status GPIO. */
    gpio_configure_pin(gpio_pin, GPIO_DIR_INPUT | GPIO_PULL_DOWN);
    gpio_disable_pin_pull_up(gpio_pin);

    rn42_status_pin = gpio_pin;
}


/******************************************************************************
    rn42_connected
*//**
    @brief Returns whether the RN42 is connected by examining the status GPIO.

    The RN42's status line appears to bounce, so this function takes care of
    debouncing it.
******************************************************************************/
static bool
rn42_connected(void)
{
    bool connected1;
    bool connected2;

    do {
        connected1 = gpio_pin_is_high(rn42_status_pin);
        delay_ms(50);
        connected2 = gpio_pin_is_high(rn42_status_pin);
    } while (connected1 != connected2);

    return connected1 & connected2;
}


/******************************************************************************
    rn42_send_data
*//**
    @brief Transmits data to a Bluetooth peer over the RN42 module.

    @param[in] buf  Pointer to the data that should be sent.
    @param[in] size Number of bytes to send.
******************************************************************************/
void
rn42_send_data(uint8_t *buf, uint32_t size)
{
    uint32_t status;

    setup_usart_tx_dma(buf, size);

    while (true)
    {
        status = pdca_get_transfer_status(PDCA_CHANNEL_TX);

        if (status & PDCA_TRANSFER_COMPLETE)
        {
            break;
        }
    }
}


/******************************************************************************
    send_response
*//**
    @brief Sends a response packet to the host.

    @param[in] cmd_id       The command ID we're responding to.
    @param[in] status       The status code.
    @param[in] data         Pointer to data to send to the PC.
    @param[in] data_length  Number of bytes to send.
******************************************************************************/
static void
send_response(
    uint8_t cmd_id,
    uint8_t status,
    uint8_t *data,
    uint32_t data_length)
{
    response_t response = {
        {'C', 'C', 'M', 'D'},
        cmd_id,
        status,
    };
    storeBigU32(&response.data_length, data_length);

    rn42_send_data((uint8_t*) &response, sizeof(response));
    rn42_send_data(data, data_length);
}
/**
 * \brief Initializes the ACIFB module with trigger
 * - Start the GCLK for ACIFB
 * - Initialize the trigger mode & compare interrupts for ACIFB
 *
 * \retval STATUS_OK   Configuration OK
 * \retval ERR_TIMEOUT Timeout on configuring ACIFB module
 * \retval ERR_BUSY    ACIFB module unable to configure the trigger
 */
static status_code_t ac_init()
{
	/* struct genclk_config gcfg; */
	uint32_t div = sysclk_get_pba_hz() / AC_GCLK_FREQUENCY;

	scif_gc_setup(AC_GCLK_ID, AC_GCLK_SRC, AVR32_GC_DIV_CLOCK, div);

	/* Now enable the generic clock */
	scif_gc_enable(AC_GCLK_ID);

	/* GPIO pin/acifb - function map. */
	static const gpio_map_t ACIFB_GPIO_MAP = {
		{EXAMPLE_ACIFBP_PIN, EXAMPLE_ACIFBP_FUNCTION},
		{EXAMPLE_ACIFBN_PIN, EXAMPLE_ACIFBN_FUNCTION},
	};

	/* ACIFB Configuration */
	const acifb_t acifb_opt = {
		.sut = 6, /* Resolution mode */
		.actest = TESTMODE_OFF,
		.eventen = true
	};
	/* ACIFB Channel Configuration */
	const acifb_channel_t acifb_channel_opt = {
		/* Filter length */
		.filter_len = 0,
		/* Hysteresis value */
		.hysteresis_value = 0,
		/* Output event when ACOUT is zero? */
		.event_negative = false,
		/* Output event when ACOUT is one? */
		.event_positive = false,
		/* Set the positive input */
		.positive_input = PI_ACP,
		/* Set the negative input */
		.negative_input = NI_ACN,
		/* Set the comparator mode */
		.mode = MODE_EVENT_TRIGGERED,
		/* Interrupt settings */
		.interrupt_settings = IS_VINP_LT_VINN,
		/* Analog comparator channel number */
		.ac_n = EXAMPLE_ACIFB_CHANNEL
	};

	/* Enable Analog Comparator clock */
	sysclk_enable_pba_module(SYSCLK_ACIFB);
	/* Disable pullup on ACIFB channel input pins */
	gpio_disable_pin_pull_up(EXAMPLE_ACIFBP_PIN);
	gpio_disable_pin_pull_up(EXAMPLE_ACIFBN_PIN);
	/* Enable the ACIFB pins */
	gpio_enable_module(ACIFB_GPIO_MAP,
			sizeof(ACIFB_GPIO_MAP) / sizeof(ACIFB_GPIO_MAP[0]));
	/* Configure the ACIFB peripheral */
	acifb_setup_and_enable(acifb, &acifb_opt);
	/* Configure the ACIFB channel with interrupt & trigger */
	acifb_channels_setup(acifb, &acifb_channel_opt, AC_NB_CHANNELS);

	/* Disable global interrupts */
	cpu_irq_disable();

	/*
	 * Initialize the interrupt vectors
	 * Note: This function adds nothing for IAR as the interrupts are
	 * handled by the IAR compiler itself. It provides an abstraction
	 * between GCC & IAR compiler to use interrupts.
	 * Refer function implementation in interrupt_avr32.h
	 */
	irq_initialize_vectors();

	/*
	 * Register the ACIFB interrupt handler
	 * Note: This function adds nothing for IAR as the interrupts are
	 * handled by the IAR compiler itself. It provides an abstraction
	 * between GCC & IAR compiler to use interrupts.
	 * Refer function implementation in interrupt_avr32.h
	 */
	irq_register_handler(&ACIFB_interrupt_handler, AVR32_ACIFB_IRQ,
			AC_INTERRUPT_PRIORITY);
	/* Enable Analog Comparator Channel interrupt */
	acifb_enable_comparison_interrupt(acifb, EXAMPLE_ACIFB_CHANNEL);
	/* Enable global interrupts */
	cpu_irq_enable();

	return STATUS_OK;
} /* End of ac_init() */

/**
 * \brief  Asynchronous Timer Initialization
 * - Start the 32KHz Oscillator
 * - Initializes the AST module with periodic trigger events
 *
 * \retval STATUS_OK   Configuration OK
 * \retval ERR_BUSY    Error in configuring the AST module
 */
static status_code_t ast_init()
{
	/* Initial Count value to write in AST */
	unsigned long ast_counter = 0;
	/* Set the prescaler to set a periodic trigger from AST */
	avr32_ast_pir0_t pir = {
		.insel = AST_TRIGGER_PRESCALER
	};

	/* Set the OSC32 parameters */
	scif_osc32_opt_t osc32_opt = {
		.mode = SCIF_OSC_MODE_2PIN_CRYSTAL_HICUR,
		.startup = OSC32_STARTUP_8192,
		.pinsel = BOARD_OSC32_PINSEL,
		.en1k = false,
		.en32k = true
	};

	/* Enable the 32KHz Oscillator */
	scif_start_osc32(&osc32_opt, true);
	/* Enable the Peripheral Event System Clock */
	sysclk_enable_hsb_module(SYSCLK_EVENT);
	/* Enable PBA clock for AST clock to switch its source */
	sysclk_enable_pba_module(SYSCLK_AST);
	/* Initialize the AST in counter mode */
	if (!ast_init_counter(&AVR32_AST, AST_CLOCK_SOURCE, AST_PRESCALER,
			ast_counter)) {
		return ERR_BUSY;
	}

	/* Initialize the periodic value register with the prescaler */
	ast_set_periodic0_value(&AVR32_AST, pir);
	/* Enable the AST periodic event */
	ast_enable_periodic0(&AVR32_AST);

	/* Clear All AST Interrupt request and clear SR */
	ast_clear_all_status_flags(&AVR32_AST);

	/* Enable the AST */
	ast_enable(&AVR32_AST);
	
	/* Disable PBA clock for AST after switching its source to OSC32 */
	sysclk_disable_pba_module(SYSCLK_AST);

	return STATUS_OK;
} /* End of ast_init() */

/**
 * \brief  Low Power Configuration
 * Initializes the power saving measures to reduce power consumption
 * - Enable pull-ups on GPIO pins
 * - Disable the clocks to unwanted modules
 * - Disable internal voltage regulator when in 1.8V supply mode
 */
static void power_save_measures_init()
{
	uint8_t i;
	uint32_t gpio_mask[AVR32_GPIO_PORT_LENGTH] = {0};

	/*
	 * Enable internal pull-ups on all unused GPIO pins
	 * Note: Pull-ups on Oscillator or JTAG pins can be enabled only if they
	 * are not used as an oscillator or JTAG pin respectively.
	 */
	for (i = 0; i < (sizeof(gpio_used_pins) / sizeof(uint32_t)); i++) {
		gpio_mask[gpio_used_pins[i] >>
		5] |= 1 << (gpio_used_pins[i] & 0x1F);
	}
	for (i = 0; i < AVR32_GPIO_PORT_LENGTH; i++) {
		gpio_configure_group(i, ~(gpio_mask[i]),
				GPIO_PULL_UP | GPIO_DIR_INPUT);
	}
	/* Disable OCD clock which is not disabled by sysclk service */
	sysclk_disable_cpu_module(SYSCLK_OCD);
#if POWER_SUPPLY_MODE_1_8V

	/*
	 * When using 1.8V Single supply mode, the Voltage Regulator can be
	 * shut-down using the code below, in-order to save power.
	 * See Voltage Regulator Calibration Register in datasheet for more
	 *info.
	 * CAUTION: When using 3.3V Single supply mode, the Voltage Regulator
	 * cannot be shut-down and the application will hang in this loop.
	 */
	uint32_t tmp = (AVR32_SCIF.vregcr);
	tmp &= (~(1 << 5 | 1 << 18));
	AVR32_SCIF.unlock = 0xAA000000 | AVR32_SCIF_VREGCR;
	AVR32_SCIF.vregcr = tmp;
	/* Wait until internal voltage regulator is disabled. */
	while ((AVR32_SCIF.vregcr & 0x00040020)) {
	}
#endif
} /* End of power_save_measures_init() */
示例#3
0
/**
 * \brief Initializes the ADCIFB module with trigger
 * - Initialize the trigger mode & compare interrupts for ADCIFB
 *
 * \retval STATUS_OK   Configuration OK
 * \retval ERR_TIMEOUT Timeout on configuring ADCIFB module
 * \retval ERR_BUSY    ADCIFB module unable to configure the trigger
 */
static status_code_t adc_init()
{
	/* GPIO pin/adc - function map. */
	static const gpio_map_t ADCIFB_GPIO_MAP = {
		{EXAMPLE_ADCIFB_PIN, EXAMPLE_ADCIFB_FUNCTION}
	};

	/* ADCIFB Configuration */
	adcifb_opt_t adcifb_opt = {
		/* Resolution mode */
		.resolution = AVR32_ADCIFB_ACR_RES_10BIT,
		/* Channels Sample & Hold Time in [0,15] */
		.shtim  = ADC_SAMPLE_HOLD_TIME,
		/* ADC Clock Prescaler */
		.ratio_clkadcifb_clkadc = (sysclk_get_pba_hz()) / ADC_FREQUENCY,
		.startup = ADC_STARTUP_TIME,
		/* ADCIFB Sleep Mode enabled */
		.sleep_mode_enable = true
	};

	/* Disable pull up on ADCIFB channel input pin */
	gpio_disable_pin_pull_up(EXAMPLE_ADCIFB_PIN);
	/* Enable the ADC pins */
	gpio_enable_module(ADCIFB_GPIO_MAP,
			sizeof(ADCIFB_GPIO_MAP) / sizeof(ADCIFB_GPIO_MAP[0]));
	/* Enable ADCIFB clock */
	sysclk_enable_pba_module(SYSCLK_ADCIFB);
	/* Configure the ADCIFB peripheral */
	if (adcifb_configure(adcifb, &adcifb_opt)) {
		/* Error configuring the ADCIFB */
		return ERR_TIMEOUT;
	}

	/* Configure the trigger for ADCIFB peripheral */
	if (adcifb_configure_trigger(adcifb, AVR32_ADCIFB_TRGR_TRGMOD_EVT, 0)) {
		/* Error configuring the trigger for ADCIFB */
		return ERR_BUSY;
	}

	/* Enable ADCIFB Channel 0 */
	adcifb_channels_enable(adcifb, EXAMPLE_ADCIFB_CHANNEL);

	/* Disable global interrupts */
	cpu_irq_disable();

	/*
	 * Initialize the interrupt vectors
	 * Note: This function adds nothing for IAR as the interrupts are
	 * handled by the IAR compiler itself. It provides an abstraction
	 * between GCC & IAR compiler to use interrupts.
	 * Refer function implementation in interrupt_avr32.h
	 */
	irq_initialize_vectors();

	/*
	 * Register the ADCIFB interrupt handler
	 * Note: This function adds nothing for IAR as the interrupts are
	 * handled by the IAR compiler itself. It provides an abstraction
	 * between GCC & IAR compiler to use interrupts.
	 * Refer function implementation in interrupt_avr32.h
	 */
	irq_register_handler(&ADCIFB_interrupt_handler, AVR32_ADCIFB_IRQ,
			ADC_INTERRUPT_PRIORITY);

	/*
	 * Set the threshold value in CVR.LV register to generate interrupt
	 * when the value detected is above the threshold.
	 * 1.500 V with 10-bit resolution
	 */
	adcifb_set_high_compare_value(adcifb, ADC_COMPARE_VALUE);

	/* Enable the Analog Compare option in ADCIFB */
	adcifb_enable_analog_compare_mode(adcifb);

	/* Enable the data ready interrupt for ADCIFB */
	adcifb_enable_compare_gt_interrupt(adcifb);

	return STATUS_OK;
} /* End of adc_init() */

/**
 * \brief  Asynchronous Timer Initialization
 * - Start the 32KHz Oscillator
 * - Initializes the AST module with periodic trigger events
 *
 * \retval STATUS_OK      Configuration OK
 * \retval ERR_TIMEOUT    Error in configuring the AST module
 */
static status_code_t ast_init()
{
	/* Initial Count value to write in AST */
	unsigned long ast_counter = 0;
	/* Set the prescaler to set a periodic trigger from AST */
	avr32_ast_pir0_t pir = {
		.insel = AST_TRIGGER_PRESCALER
	};

	/* Set the OSC32 parameters */
	scif_osc32_opt_t osc32_opt = {
		.mode = SCIF_OSC_MODE_2PIN_CRYSTAL_HICUR,
		.startup = OSC32_STARTUP_8192,
		.pinsel = BOARD_OSC32_PINSEL,
		.en1k = false,
		.en32k = true
	};

	/* Enable the 32KHz Oscillator */
	scif_start_osc32(&osc32_opt, true);
	/* Enable the Peripheral Event System Clock */
	sysclk_enable_hsb_module(SYSCLK_EVENT);
	/* Enable PBA clock for AST clock to switch its source */
	sysclk_enable_pba_module(SYSCLK_AST);
	/* Initialize the AST in counter mode */
	if (!ast_init_counter(&AVR32_AST, AST_CLOCK_SOURCE, AST_PRESCALER,
			ast_counter)) {
		return ERR_TIMEOUT;
	}

	/* Initialize the periodic value register with the prescaler */
	ast_set_periodic0_value(&AVR32_AST, pir);
	/* Enable the AST periodic event */
	ast_enable_periodic0(&AVR32_AST);

	/* Clear All AST Interrupt request and clear SR */
	ast_clear_all_status_flags(&AVR32_AST);

	/* Enable the AST */
	ast_enable(&AVR32_AST);

	/* Disable PBA clock for AST after switching its source to OSC32 */
	sysclk_disable_pba_module(SYSCLK_AST);

	return STATUS_OK;
} /* End of ast_init() */

/**
 * \brief  Low Power Configuration
 * Initializes the power saving measures to reduce power consumption
 * - Enable pullups on GPIO pins
 * - Disable the clocks to unused modules
 * - Disable internal voltage regulator when in 1.8V supply mode
 */
static void power_save_measures_init()
{
	uint8_t i;
	uint32_t gpio_mask[AVR32_GPIO_PORT_LENGTH] = {0};

	/*
	 * Enable internal pull-ups on all unused GPIO pins
	 * Note: Pull-ups on Oscillator or JTAG pins can be enabled only if they
	 * are not used as an oscillator or JTAG pin respectively.
	 */
	for (i = 0; i < (sizeof(gpio_used_pins) / sizeof(uint32_t)); i++) {
		gpio_mask[gpio_used_pins[i] >>
		5] |= 1 << (gpio_used_pins[i] & 0x1F);
	}
	for (i = 0; i < AVR32_GPIO_PORT_LENGTH; i++) {
		gpio_configure_group(i, ~(gpio_mask[i]),
				GPIO_PULL_UP | GPIO_DIR_INPUT);
	}
	/* Disable OCD clock which is not disabled by sysclk service */
	sysclk_disable_cpu_module(SYSCLK_OCD);
#if POWER_SUPPLY_MODE_1_8V

	/*
	 * When using 1.8V Single supply mode, the Voltage Regulator can be
	 * shut-down using the code below, in-order to save power.
	 * See Voltage Regulator Calibration Register in datasheet for more
	 *info.
	 * CAUTION: When using 3.3V Single supply mode, the Voltage Regulator
	 * cannot be shut-down and the application will hang in this loop.
	 */
	uint32_t tmp = (AVR32_SCIF.vregcr);
	tmp &= (~(1 << 5 | 1 << 18));
	AVR32_SCIF.unlock = 0xAA000000 | AVR32_SCIF_VREGCR;
	AVR32_SCIF.vregcr = tmp;
	/* Wait until internal voltage regulator is disabled. */
	while ((AVR32_SCIF.vregcr & 0x00040020)) {
	}
#endif
} /* End of power_save_measures_init() */