Exemple #1
0
void TBlockingSpiDmaJob::Run()
{
    TaskId = TScheduler::GetCurrentTaskId();
    CurrentJob = this;

    const uint32_t spi = FLASH_SPI_CHANNEL;
    const uint32_t dma = DMA1;

    assert(SPI_SR(spi) & SPI_SR_TXE);
    assert(~SPI_SR(spi) & SPI_SR_BSY);
    assert(!(SPI_SR(spi) & SPI_SR_RXNE));

    {
        const uint32_t channel = FLASH_DMA_TX_CHANNEL;
        dma_channel_reset(dma, channel);
        dma_set_peripheral_address(dma, channel, reinterpret_cast<uint32_t>(&SPI_DR(spi)));
        dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(Out));
        dma_set_number_of_data(dma, channel, Len);
        dma_set_read_from_memory(dma, channel);
        dma_enable_memory_increment_mode(dma, channel);
        dma_set_peripheral_size(dma, channel, DMA_CCR_PSIZE_8BIT);
        dma_set_memory_size(dma, channel, DMA_CCR_MSIZE_8BIT);
        dma_set_priority(dma, channel, DMA_CCR_PL_LOW);
        // dma_enable_transfer_complete_interrupt(dma, channel);
        dma_enable_channel(dma, channel);
    }

    {
        const uint32_t channel = FLASH_DMA_RX_CHANNEL;
        dma_channel_reset(dma, channel);
        dma_set_peripheral_address(dma, channel, reinterpret_cast<uint32_t>(&SPI_DR(spi)));
        dma_set_number_of_data(dma, channel, Len);
        if (In != 0) {
            dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(In));
            dma_enable_memory_increment_mode(dma, channel);
        }
        else {
            dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(&DummyPosition));
        }
        dma_set_peripheral_size(dma, channel, DMA_CCR_PSIZE_8BIT);
        dma_set_memory_size(dma, channel, DMA_CCR_MSIZE_8BIT);
        dma_set_priority(dma, channel, DMA_CCR_PL_LOW);
        dma_enable_transfer_complete_interrupt(dma, channel);
        dma_enable_channel(dma, channel);
    }

    // Kick off the transfer
    spi_enable_rx_dma(spi);
    spi_enable_tx_dma(spi);

    // Wait for completion
    TScheduler::BlockUntil(&Finished);
}
Exemple #2
0
void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){

	// hal_uart_manual_rts_clear();
	gpio_clear(GPIOB, GPIO_DEBUG_1);

	/*
	 * USART3_RX is on DMA_CHANNEL3
	 */

	// printf("hal_uart_dma_receive_block req size %u\n", size);

	/* Reset DMA channel*/
	dma_channel_reset(DMA1, DMA_CHANNEL3);

	dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t)&USART3_DR);
	dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t)data);
	dma_set_number_of_data(DMA1, DMA_CHANNEL3, size);
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL3);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
	dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
	dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
	dma_enable_channel(DMA1, DMA_CHANNEL3);
    usart_enable_rx_dma(USART3);
}
Exemple #3
0
void init_adc_sensor(){
	// we will use ADC1 channel 0 for IR sensor & ADC1 channel 1 for laser's photoresistor
	uint8_t adc_channel_array[ADC_CHANNEL_NUMBER] = {0,1,6};
	// Make sure the ADC doesn't run during config
	adc_off(ADC1);
	// enable ADC & PA0/PA1 clocking
	rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN | RCC_APB2ENR_IOPAEN);
	rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV4);
	gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0 | GPIO1);
	rcc_periph_clock_enable(RCC_DMA1); // enable DMA for ADC values storing
	// Configure ADC as continuous scan mode with DMA
	ADC1_CR1 = ADC_CR1_SCAN; // enable scan mode
	// set sample time on channels 1&2: 239.5 cycles for better results
	ADC1_SMPR2 = 0x3f;
	dma_channel_reset(DMA1, DMA_CHANNEL1);
	DMA1_CPAR1 = (uint32_t) &(ADC_DR(ADC1));
	DMA1_CMAR1 = (uint32_t) ADC_value;
	DMA1_CNDTR1 = ADC_CHANNEL_NUMBER;
	DMA1_CCR1 = DMA_CCR_MINC | DMA_CCR_PSIZE_16BIT | DMA_CCR_MSIZE_16BIT
			| DMA_CCR_CIRC | DMA_CCR_PL_HIGH | DMA_CCR_EN;
	// continuous conv, enable ADC & DMA
	ADC1_CR2 = ADC_CR2_CONT | ADC_CR2_ADON | ADC_CR2_DMA;
	// set channels
	adc_set_regular_sequence(ADC1, ADC_CHANNEL_NUMBER, adc_channel_array);
	// reset calibration registers & start calibration
	ADC1_CR2 |= ADC_CR2_RSTCAL;
	while(ADC1_CR2 & ADC_CR2_RSTCAL); // wait for registers reset
	ADC1_CR2 |= ADC_CR2_CAL;
	while(ADC1_CR2 & ADC_CR2_CAL); // wait for calibration ends
	nvic_enable_irq(NVIC_ADC1_2_IRQ);
	ADC1_CR2 |= ADC_CR2_SWSTART;
	// turn on ADC - to do it we need set ADC_CR2_ADON again!
	ADC1_CR2 |= ADC_CR2_ADON;
}
Exemple #4
0
/* Receive data using DMA. */
void rx_spi(void *data, uint16_t size){
	if(DmaCleanupNeeded)cleanup_dma_spi();

	/* This byte is sent continuously when rx_spi() receives data. */
	static const uint8_t RxSpiDummyByte = 0x00;

	spi_enable_rx_dma(SPI3);
	
	dma_channel_reset(DMA1, DMA_CHANNEL2);
	dma_disable_channel(DMA1, DMA_CHANNEL2);
	dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t) &(SPI_DR(SPI3)));
	dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t) data);
	dma_set_number_of_data(DMA1, DMA_CHANNEL2, size);
	dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_HIGH);
	dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
	dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL2);
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
	dma_enable_channel(DMA1, DMA_CHANNEL2);

	/* The SPI peripheral is driven by transmitted bytes, so dummy bytes
	 * must be sent in order to receive data. This is accomplished with DMA
	 * by simply not incrementing the memory address. */
	dma_channel_reset(DMA1, DMA_CHANNEL3);
	dma_disable_channel(DMA1, DMA_CHANNEL3);
	dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t) &(SPI_DR(SPI3)));
	dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t) &RxSpiDummyByte);
	dma_set_number_of_data(DMA1, DMA_CHANNEL3, size);
	dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
	dma_disable_memory_increment_mode(DMA1, DMA_CHANNEL3);
	dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL3);
	dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
	dma_enable_channel(DMA1, DMA_CHANNEL3);
	
	spi_enable_tx_dma(SPI3);
	spi_enable(SPI3);
	DmaCleanupNeeded = true;
}
Exemple #5
0
/* Simultaneously transmit and receive data using DMA. */
void rxtx_spi(void *rxdata, const void *txdata, uint16_t size){
	if(DmaCleanupNeeded)cleanup_dma_spi();

	spi_enable_rx_dma(SPI3);
	
	dma_channel_reset(DMA1, DMA_CHANNEL2);
	dma_disable_channel(DMA1, DMA_CHANNEL2);
	dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t) &(SPI_DR(SPI3)));
	dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t) rxdata);
	dma_set_number_of_data(DMA1, DMA_CHANNEL2, size);
	dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_HIGH);
	dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
	dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL2);
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
	dma_enable_channel(DMA1, DMA_CHANNEL2);

	dma_channel_reset(DMA1, DMA_CHANNEL3);
	dma_disable_channel(DMA1, DMA_CHANNEL3);
	dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t) &(SPI_DR(SPI3)));
	dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t) txdata);
	dma_set_number_of_data(DMA1, DMA_CHANNEL3, size);
	dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
	dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL3);
	dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
	dma_enable_channel(DMA1, DMA_CHANNEL3);
	
	spi_enable_tx_dma(SPI3);
	spi_enable(SPI3);

	DmaCleanupNeeded = true;
}
/* SPI transmit completed with DMA */
void dma1_channel3_isr(void)
{
	gpio_set(GPIOB,GPIO1);
	if ((DMA1_ISR &DMA_ISR_TCIF3) != 0) {
		DMA1_IFCR |= DMA_IFCR_CTCIF3;
	}

	dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);

	spi_disable_tx_dma(SPI1);

	dma_disable_channel(DMA1, DMA_CHANNEL3);

	/* If tx_len < rx_len, create a dummy transfer to clock in the remaining
	 * rx data
	 */
	if (rx_buf_remainder > 0) {
		dma_channel_reset(DMA1, DMA_CHANNEL3);
		dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t)&SPI1_DR);
		dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t)(&dummy_tx_buf)); // Change here
		dma_set_number_of_data(DMA1, DMA_CHANNEL3, rx_buf_remainder); // Change here
		dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
		dma_disable_memory_increment_mode(DMA1, DMA_CHANNEL3); // Change here
#if USE_16BIT_TRANSFERS
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
		dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);

		rx_buf_remainder = 0; // Clear the buffer remainder to disable this section later

		dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
		dma_enable_channel(DMA1, DMA_CHANNEL3);
		spi_enable_tx_dma(SPI1);
	} else {
		/* Increment the status to indicate one of the transfers is complete */
		transceive_status++;
	}

	gpio_clear(GPIOB,GPIO1);
}
Exemple #7
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_dma_error_handling_test(const struct test_case *test)
{
	/* Enable DMA */
	dma_enable();

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

	/* Set up channel 0 to do some work, check that is it busy,
	 * change some settings and verify a transfer error */
	dma_channel_write_burst_length(DMA_CHANNEL_0,
			DMA_CH_BURSTLEN_1BYTE_gc);
	dma_channel_write_transfer_count(DMA_CHANNEL_0,
			MEMORY_BLOCK_SIZE);
	dma_channel_write_source(DMA_CHANNEL_0,
			(uint16_t)(uintptr_t)memory_block_src);
	dma_channel_write_destination(DMA_CHANNEL_0,
			(uint16_t)(uintptr_t)memory_block_dest);

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

	/* Start a block transfer */
	dma_channel_trigger_block_transfer(DMA_CHANNEL_0);

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

	/* Disable the channel while it is busy */
	if (dma_channel_is_busy(DMA_CHANNEL_0)) {
		dma_channel_disable(DMA_CHANNEL_0);
	}

	/* Test whether the channel is in error */
	test_assert_true(test,
			dma_get_channel_status(
			DMA_CHANNEL_0) == DMA_CH_TRANSFER_ERROR,
			"DMA channel not in error after disabling during transfer"
			" write");

	dma_disable();
}
Exemple #8
0
u8 UART_Send(u8 *data, u16 len) {
    if (busy) return 1;
    busy = 1;

    dma_channel_reset(_USART_DMA, _USART_DMA_CHANNEL);

    dma_set_peripheral_address(_USART_DMA, _USART_DMA_CHANNEL,(u32) &_USART_DR);  /* send data to the USART data register */
    dma_set_memory_address(_USART_DMA, _USART_DMA_CHANNEL, (u32) data);
    dma_set_number_of_data(_USART_DMA, _USART_DMA_CHANNEL, len);
    dma_set_read_from_memory(_USART_DMA, _USART_DMA_CHANNEL);                     /* direction is from memory to usart */
    dma_enable_memory_increment_mode(_USART_DMA, _USART_DMA_CHANNEL);             /* memory pointer increments, peripheral no */
    dma_set_peripheral_size(_USART_DMA, _USART_DMA_CHANNEL, DMA_CCR_PSIZE_8BIT);  /* USART_DR is 8bit wide in this mode */
    dma_set_memory_size(_USART_DMA, _USART_DMA_CHANNEL, DMA_CCR_MSIZE_8BIT);      /* destination memory is also 8 bit wide */
    dma_set_priority(_USART_DMA, _USART_DMA_CHANNEL, DMA_CCR_PL_LOW);
    dma_enable_transfer_complete_interrupt(_USART_DMA, _USART_DMA_CHANNEL);

    dma_enable_channel(_USART_DMA, _USART_DMA_CHANNEL);    /* dma ready to go */
    usart_enable_tx_dma(_USART);

    return 0;
}
/*--------------------------------------------------------------------*/
void dma_setup(void)
{
/* DAC channel 1 shares DMA controller 2 Channel 3. */
/* Enable DMA2 clock and IRQ */
	rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA2EN);
	nvic_enable_irq(NVIC_DMA2_CHANNEL3_IRQ);
	dma_channel_reset(DMA2,DMA_CHANNEL3);
	dma_set_priority(DMA2,DMA_CHANNEL3,DMA_CCR_PL_LOW);
	dma_set_memory_size(DMA2,DMA_CHANNEL3,DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA2,DMA_CHANNEL3,DMA_CCR_PSIZE_8BIT);
	dma_enable_memory_increment_mode(DMA2,DMA_CHANNEL3);
	dma_enable_circular_mode(DMA2,DMA_CHANNEL3);
	dma_set_read_from_memory(DMA2,DMA_CHANNEL3);
/* The register to target is the DAC1 8-bit right justified data register */
	dma_set_peripheral_address(DMA2,DMA_CHANNEL3,(uint32_t) &DAC_DHR8R1);
/* The array v[] is filled with the waveform data to be output */
	dma_set_memory_address(DMA2,DMA_CHANNEL3,(uint32_t) v);
	dma_set_number_of_data(DMA2,DMA_CHANNEL3,256);
	dma_enable_transfer_complete_interrupt(DMA2, DMA_CHANNEL3);
	dma_enable_channel(DMA2,DMA_CHANNEL3);
}
void dma_transmit_setup(void)
{
    dma_channel_reset(DMA1, DMA_CHANNEL4);

    nvic_enable_irq(NVIC_DMA1_CHANNEL4_5_IRQ);

    dma_set_peripheral_address(DMA1, DMA_CHANNEL4, (uint32_t) &USART2_TDR);
    dma_set_read_from_memory(DMA1, DMA_CHANNEL4);

    dma_set_peripheral_size(DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_8BIT);
    dma_set_memory_size(DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_8BIT);

    dma_set_priority(DMA1, DMA_CHANNEL4, DMA_CCR_PL_VERY_HIGH);

    dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL4);
    dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL4);

    dma_disable_transfer_error_interrupt(DMA1, DMA_CHANNEL4);
    dma_disable_half_transfer_interrupt(DMA1, DMA_CHANNEL4);
    dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL4);
}
Exemple #11
0
/******************************************************************************
 *
 * Helpers for SPI transactions with DMA
 *
 *****************************************************************************/
static void spi_configure_dma(uint32_t dma, uint8_t chan, uint32_t periph_addr, uint32_t buf_addr,
                              uint16_t len, enum SPIDataSizeSelect dss, bool_t increment)
{
  dma_channel_reset(dma, chan);
  dma_set_peripheral_address(dma, chan, periph_addr);
  dma_set_memory_address(dma, chan, buf_addr);
  dma_set_number_of_data(dma, chan, len);

  /* Set the dma transfer size based on SPI transaction DSS */
  if (dss == SPIDss8bit) {
    dma_set_peripheral_size(dma, chan, DMA_CCR_PSIZE_8BIT);
    dma_set_memory_size(dma, chan, DMA_CCR_MSIZE_8BIT);
  } else {
    dma_set_peripheral_size(dma, chan, DMA_CCR_PSIZE_16BIT);
    dma_set_memory_size(dma, chan, DMA_CCR_MSIZE_16BIT);
  }

  if (increment)
    dma_enable_memory_increment_mode(dma, chan);
  else
    dma_disable_memory_increment_mode(dma, chan);
}
Exemple #12
0
void acq_init()
{
	/* Initialize amplifier control GPIO */
	gpio_mode_setup(BANK_AMP, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_AMP);
	gpio_clear(BANK_AMP, GPIO_AMP);
	gpio_mode_setup(BANK_LED, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_LED);
	gpio_clear(BANK_LED, GPIO_LED);

	/* Initialize SPI GPIOs */
	gpio_mode_setup(BANK_CS, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_CS);
	gpio_mode_setup(BANK_SCLK, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_SCLK);
	gpio_mode_setup(BANK_DOUT, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_DOUT);

	gpio_set_af(BANK_CS, GPIO_AF6, GPIO_CS);
	gpio_set_af(BANK_SCLK, GPIO_AF6, GPIO_SCLK);
	gpio_set_af(BANK_DOUT, GPIO_AF6, GPIO_DOUT);

	rcc_periph_clock_enable(RCC_SPI3);

	acq_spi_init(SPI_C1);

	rcc_periph_clock_enable(RCC_DMA1);
	dma_channel_reset(DMA1, DMA_CHANNEL2);
	dma_disable_channel(DMA1, DMA_CHANNEL2);

	dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t)&SPI_DR(SPI_C1));
	dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t)&acq_channel.buff);
	dma_set_number_of_data(DMA1, DMA_CHANNEL2, BUFFER_SIZE);

	dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_MEDIUM);

	dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_16BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_16BIT);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
	dma_enable_circular_mode(DMA1, DMA_CHANNEL2);

	nvic_set_priority(NVIC_DMA1_CHANNEL2_IRQ, PRIO_ACQ);
}
Exemple #13
0
void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){

	// printf("hal_uart_dma_send_block size %u\n", size);
	/*
	 * USART3_TX Using DMA_CHANNEL2 
	 */

	/* Reset DMA channel*/
	dma_channel_reset(DMA1, DMA_CHANNEL2);

	dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t)&USART3_DR);
	dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t)data);
	dma_set_number_of_data(DMA1, DMA_CHANNEL2, size);
	dma_set_read_from_memory(DMA1, DMA_CHANNEL2);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
	dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
	dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_VERY_HIGH);
	dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL2);
	dma_enable_channel(DMA1, DMA_CHANNEL2);
    usart_enable_tx_dma(USART3);
}
Exemple #14
0
static int timer_dma(uint8_t *tx_buf, int tx_len)
{
	dma_int_enable();	

	/* Reset DMA channels*/
	dma_channel_reset(DMA1, DMA_CHANNEL3);

	/* Set up tx dma */
	dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t)&TIM_CCR2(TIM3));
	dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t)tx_buf);
	dma_set_number_of_data(DMA1, DMA_CHANNEL3, tx_len);
	dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_32BIT);
	dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
	dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);

	dma_enable_circular_mode(DMA1, DMA_CHANNEL3);
	dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);
	dma_enable_half_transfer_interrupt(DMA1, DMA_CHANNEL3);
	dma_enable_channel(DMA1, DMA_CHANNEL3);

	return 0;
}
Exemple #15
0
static int spi_dma_transceive(uint8_t *tx_buf, int tx_len, uint8_t *rx_buf, int rx_len)
#endif
{
/* Check for 0 length in both tx and rx */
    if ((rx_len < 1) && (tx_len < 1)) {
/* return -1 as error */
        return -1;
    }

/* Reset DMA channels*/
    dma_channel_reset(DMA1, DMA_CHANNEL4);
    dma_channel_reset(DMA1, DMA_CHANNEL5);

/* Reset SPI data and status registers.
 * Here we assume that the SPI peripheral is NOT
 * busy any longer, i.e. the last activity was verified
 * complete elsewhere in the program.
 */
    volatile uint8_t temp_data __attribute__ ((unused));
    while (SPI_SR(SPI2) & (SPI_SR_RXNE | SPI_SR_OVR)) {
        temp_data = SPI_DR(SPI2);
    }

/* Reset status flag appropriately (both 0 case caught above) */
    transceive_status = NONE;
    if (rx_len < 1) {
        transceive_status = ONE;
    }
    if (tx_len < 1) {
        transceive_status = ONE;
    }

/* Set up rx dma, note it has higher priority to avoid overrun */
    if (rx_len > 0) {
        dma_set_peripheral_address(DMA1, DMA_CHANNEL4, (uint32_t)&SPI2_DR);
        dma_set_memory_address(DMA1, DMA_CHANNEL4, (uint32_t)rx_buf);
        dma_set_number_of_data(DMA1, DMA_CHANNEL4, rx_len);
        dma_set_read_from_peripheral(DMA1, DMA_CHANNEL4);
        dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL4);
#if USE_16BIT_TRANSFERS
        dma_set_peripheral_size(DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_16BIT);
        dma_set_memory_size(DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_16BIT);
#else
        dma_set_peripheral_size(DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_8BIT);
        dma_set_memory_size(DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_8BIT);
#endif
        dma_set_priority(DMA1, DMA_CHANNEL4, DMA_CCR_PL_VERY_HIGH);
    }

/* Set up tx dma */
    if (tx_len > 0) {
        dma_set_peripheral_address(DMA1, DMA_CHANNEL5, (uint32_t)&SPI2_DR);
        dma_set_memory_address(DMA1, DMA_CHANNEL5, (uint32_t)tx_buf);
        dma_set_number_of_data(DMA1, DMA_CHANNEL5, tx_len);
        dma_set_read_from_memory(DMA1, DMA_CHANNEL5);
        dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL5);
#if USE_16BIT_TRANSFERS
        dma_set_peripheral_size(DMA1, DMA_CHANNEL5, DMA_CCR_PSIZE_16BIT);
        dma_set_memory_size(DMA1, DMA_CHANNEL5, DMA_CCR_MSIZE_16BIT);
#else
        dma_set_peripheral_size(DMA1, DMA_CHANNEL5, DMA_CCR_PSIZE_8BIT);
        dma_set_memory_size(DMA1, DMA_CHANNEL5, DMA_CCR_MSIZE_8BIT);
#endif
        dma_set_priority(DMA1, DMA_CHANNEL5, DMA_CCR_PL_HIGH);
    }

/* Enable dma transfer complete interrupts */
    if (rx_len > 0) {
        dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL4);
    }
    if (tx_len > 0) {
        dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL5);
    }

/* Activate dma channels */
    if (rx_len > 0) {
        dma_enable_channel(DMA1, DMA_CHANNEL4);
    }
    if (tx_len > 0) {
        dma_enable_channel(DMA1, DMA_CHANNEL5);
    }

/* Enable the spi transfer via dma
 * This will immediately start the transmission,
 * after which when the receive is complete, the
 * receive dma will activate
 */
    if (rx_len > 0) {
        spi_enable_rx_dma(SPI2);
    }
    if (tx_len > 0) {
        spi_enable_tx_dma(SPI2);
    }

    return 0;
}
Exemple #16
0
bool TSpiDmaQueue::TryStartJob()
{
    // Start the next DMA job in the queue if the SPI interface is
    // available (TXE=1 and BSY=0)
    // We treat both SPI busses (flash and display) as one, so no concurrent jobs
    // are allowed.

    const uint32_t spi = LCD_SPI_CHANNEL;
    if ((SPI_SR(spi) & SPI_SR_TXE) && (~SPI_SR(spi) & SPI_SR_BSY)) {

        if (Jobs.Empty()) {
            return false;
        }

        const TSpiDmaJob& job = Jobs.First();
        const TBuffer& buffer = job.GetBuffer();

        // SPI receive register should be empty here!
        assert(!(SPI_SR(spi) & SPI_SR_RXNE));

        const uint32_t dma = DMA1;
        {
            const uint32_t channel = (job.GetChip() == TSpiDmaJob::CS_LCD) ? LCD_DMA_TX_CHANNEL : FLASH_DMA_TX_CHANNEL;
            dma_channel_reset(dma, channel);
            dma_set_peripheral_address(dma, channel, reinterpret_cast<uint32_t>(&SPI_DR(spi)));
            dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(buffer.GetData()));
            dma_set_number_of_data(dma, channel, buffer.GetLength());
            dma_set_read_from_memory(dma, channel);
            dma_enable_memory_increment_mode(dma, channel);
            dma_set_peripheral_size(dma, channel, DMA_CCR_PSIZE_8BIT);
            dma_set_memory_size(dma, channel, DMA_CCR_MSIZE_8BIT);
            dma_set_priority(dma, channel, DMA_CCR_PL_LOW);
            //dma_enable_transfer_complete_interrupt(dma, channel);
            dma_enable_channel(dma, channel);
        }

        {
            const uint32_t channel =  (job.GetChip() == TSpiDmaJob::CS_LCD) ? LCD_DMA_RX_CHANNEL : FLASH_DMA_RX_CHANNEL;
            dma_channel_reset(dma, channel);
            dma_set_peripheral_address(dma, channel, reinterpret_cast<uint32_t>(&SPI_DR(spi)));
            dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(buffer.GetData()));
            dma_set_number_of_data(dma, channel, buffer.GetLength());
            dma_enable_memory_increment_mode(dma, channel);
            dma_set_peripheral_size(dma, channel, DMA_CCR_PSIZE_8BIT);
            dma_set_memory_size(dma, channel, DMA_CCR_MSIZE_8BIT);
            dma_set_priority(dma, channel, DMA_CCR_PL_LOW);
            dma_enable_transfer_complete_interrupt(dma, channel);
            dma_enable_channel(dma, channel);
        }

        // Set CS and LCD_A0 lines
        Pin_lcd_cs.Clear();
        if (job.GetLcdData()) {
            Pin_lcd_a0.Set();
        } else {
            Pin_lcd_a0.Clear();
        }

        // Kick off the transfer
        spi_enable_rx_dma(spi);
        spi_enable_tx_dma(spi);

        return true;
    }

    return false;
}
Exemple #17
0
static void setup_i2c_port(enum I2C_FREQ I2C_speed)
{
	// Disable I2C if it happens to be enabled
	i2c_peripheral_disable(I2C_PORT);
	dma_channel_reset(I2C_TX_DMA, I2C_TX_DMA_CHANNEL);
	i2c_disable_interrupt(I2C_PORT, (I2C_CR2_ITEVTEN | I2C_CR2_ITERREN));
	DISABLE_I2C_INTERRUPT();
	reset_i2c_pins();

	// set: Source, Destination, and Amount (DMA channel must be disabled)
	dma_set_peripheral_address(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, (uint32_t)&I2C_DR(I2C_PORT));
	dma_set_memory_address(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, 0);
	dma_set_number_of_data(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, 0);
	// set the DMA Configuration (DMA_CCRx)
	//			 (BIT 14) mem2mem_mode disabled
	dma_set_priority(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_PL_HIGH); // (BIT 12:13)
	dma_set_memory_size(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_MSIZE_8BIT); // (BIT 10:11)
	dma_set_peripheral_size(I2C_TX_DMA, I2C_TX_DMA_CHANNEL, DMA_CCR_PSIZE_8BIT); // (BIT 8:9)
	dma_enable_memory_increment_mode(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 7)
	dma_disable_peripheral_increment_mode(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 6)
	//			 (BIT 5) Circular mode is disabled
	dma_set_read_from_memory(I2C_TX_DMA, I2C_TX_DMA_CHANNEL);	// (BIT 4)
	dma_enable_transfer_error_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 3)
	dma_disable_half_transfer_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 2)
	dma_enable_transfer_complete_interrupt(I2C_TX_DMA, I2C_TX_DMA_CHANNEL); // (BIT 1)

	// This is the slave address when not transmitting data
	i2c_set_own_7bit_slave_address(I2C_PORT, 0x32);
	// do not respond to the specified slave address
	i2c_disable_ack(I2C_PORT);
	// Use DMA to send I2C data
	i2c_enable_dma(I2C_PORT);
	// set which interrupts I2C uses
	i2c_enable_interrupt(I2C_PORT, (I2C_CR2_ITEVTEN | I2C_CR2_ITERREN));
	// APB1 is running at 36MHz = T(PCLK1) = 1/36000000 sec.
	i2c_set_clock_frequency(I2C_PORT, I2C_CR2_FREQ_36MHZ);
	// Set up the hardware for the particular speed
	switch (I2C_speed) {
		// Values found on Internet for the I2C standard
		//   STANDARD : SCL max rise time = 1000ns = 1000/1000000000 sec
		//       FAST : SCL max rise time =  300ns =  300/1000000000 sec
		// 
		// DATASHEET Function:
		//   TRISE = (T(MAX_SCL_RISE) / T(PCLK1)) + 1
		// 
		// DATASHEET Functions:
		//   STANDARD :      
		//     T(high) =      CCR * T(PCLK1)
		//     T(low)  =      CCR * T(PCLK1)
		//   FAST (DUTY=I2C_CCR_DUTY_DIV2)
		//     T(high) =      CCR * T(PCLK1)
		//     T(low)  =  2 * CCR * T(PCLK1)
		//   FAST (DUTY=I2C_CCR_DUTY_16_DIV_9)   [To reach 400KHz]
		//     T(high) =  9 * CCR * T(PCLK1)
		//     T(low)  = 16 * CCR * T(PCLK1)
		// 
		// I2C PERIOD:
		//   STANDARD
		//     PERIOD = T(high) + T(low) = (2 * CCR * T(PCLK1))
		//   FAST (DUTY=I2C_CCR_DUTY_DIV2)
		//     PERIOD = T(high) + T(low) = (3 * CCR * T(PCLK1))
		//   FAST (DUTY=I2C_CCR_DUTY_16_DIV_9)
		//     PERIOD = T(high) + T(low) = (25 * CCR * T(PCLK1))
		case I2C_400KHz:
			// I2C PERIOD: 400KHz = 400000Hz = 1/400000 sec.
			i2c_set_fast_mode(I2C_PORT);
			// I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9
			i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_16_DIV_9);
			// CCR = PERIOD / (25 * T(PCLK1))
			// CCR = (1/400000) / (25/36000000) = 18/5 = 3.6
			// CCR = 4 => I2C PERIOD = 360kHz
			// CCR = 3 => I2C PERIOD = 480kHz
			i2c_set_ccr(I2C_PORT, 4);	// Only fast mode can have a value less than 0x04
			// TRISE = ( (300/1000000000) / (1/36000000) ) + 1 = 59/5 = 11.8
			// TRISE = 12 => SCL max rise time ~= 305.555ns
			// TRISE = 11 => SCL max rise time ~= 277.777ns
			i2c_set_trise(I2C_PORT, 11);
			break;
		case I2C_100KHz:
			// I2C PERIOD: 100KHz = 100000Hz = 1/100000 sec.
			i2c_set_standard_mode(I2C_PORT);
			// I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9
			i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_DIV2);
			// CCR = PERIOD / (2 * T(PCLK1))
			// CCR = (1/100000) / (2/36000000) = 180
			i2c_set_ccr(I2C_PORT, 180);
			// TRISE = ( (1000/1000000000) / (1/36000000) ) + 1 = 37
			i2c_set_trise(I2C_PORT, 37);
			break;
		case I2C_53KHz:
			// ~= 52.91kHz is the slowest I could get to work
			// CCR value of 341 works but not 342 or higher
		case I2C_50KHz:
		default:
			// I2C PERIOD: 50KHz = 50000Hz = 1/50000 sec.
			i2c_set_standard_mode(I2C_PORT);
			// I2C_CCR_DUTY_DIV2 or I2C_CCR_DUTY_16_DIV_9
			i2c_set_dutycycle(I2C_PORT, I2C_CCR_DUTY_DIV2);
			// CCR = PERIOD / (2 * T(PCLK1))
			// CCR = (1/50000) / (2/36000000) = 360
			//   (341 works but not 342 or higher)
			i2c_set_ccr(I2C_PORT, 341);
			// TRISE = ( (1000/1000000000) / (1/36000000) ) + 1 = 37
			i2c_set_trise(I2C_PORT, 37);
			break;
	}
	i2c_peripheral_enable(I2C_PORT);

	// set the priorities for the interrupts
	nvic_set_priority(I2C_EV_IRQ, IRQ_PRI_I2C);
	nvic_set_priority(I2C_ER_IRQ, IRQ_PRI_ER_I2C);
	nvic_set_priority(I2C_DMA_IRQ, IRQ_PRI_DMA_I2C);
}
Exemple #18
0
/**
 * \brief Test different directions on all channels
 *
 * \note This test copies the source memory block into the destination block
 * in different ways.
 *
 * \param test              Current test
 */
static void run_dma_direction_test(const struct test_case *test)
{
	struct dma_channel_config config_params;
	uint8_t channel_index;
	bool success = true; /* Assume everything goes well */

	/* Fill the source block with our known pattern */
	set_buffer(memory_block_src, 0x00);
	block_fill(memory_block_src, MEMORY_BLOCK_SIZE);

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

	/* Enable DMA */
	dma_enable();

	/* No reload on source and destination */
	dma_channel_set_src_reload_mode(&config_params,
			DMA_CH_SRCRELOAD_NONE_gc);
	dma_channel_set_dest_reload_mode(&config_params,
			DMA_CH_DESTRELOAD_NONE_gc);
	dma_channel_set_transfer_count(&config_params,
			MEMORY_BLOCK_SIZE);
	dma_channel_set_burst_length(&config_params,
			DMA_CH_BURSTLEN_1BYTE_gc);

	/* Test a memory transfer on all channels */
	for (channel_index = 0; channel_index < DMA_NUMBER_OF_CHANNELS;
			channel_index++) {
		/* Reset channel and write the configuration */
		dma_channel_reset(channel_index);
		/* Increment source, increment destination */
		dma_channel_set_src_dir_mode(&config_params,
				DMA_CH_SRCDIR_INC_gc);
		dma_channel_set_dest_dir_mode(&config_params,
				DMA_CH_DESTDIR_INC_gc);
		/* Data starts from the first byte */
		dma_channel_set_source_address(&config_params,
				(uint16_t)(uintptr_t)memory_block_src);
		dma_channel_set_destination_address(&config_params,
				(uint16_t)(uintptr_t)memory_block_dest);

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

		/* Clear destination */
		set_buffer(memory_block_dest, 0x00);

		/* Enable channel, transfer, and disable it */
		dma_channel_enable(channel_index);
		dma_transfer_block(channel_index);
		dma_channel_disable(channel_index);

		/* Check that source and destination are equal */
		success = block_compare(memory_block_src,
				memory_block_dest, MEMORY_BLOCK_SIZE);

		if (!success) {
			break;
		}

		/* Reset channel and write the configuration */
		dma_channel_reset(channel_index);
		/* Decrement source, increment destination */
		dma_channel_set_src_dir_mode(&config_params,
				DMA_CH_SRCDIR_DEC_gc);
		dma_channel_set_dest_dir_mode(&config_params,
				DMA_CH_DESTDIR_INC_gc);
		/* Data starts from the first byte */
		dma_channel_set_source_address(&config_params,
				(uint16_t)(uintptr_t)
				(memory_block_src + MEMORY_BLOCK_SIZE - 1));
		dma_channel_set_destination_address(&config_params,
				(uint16_t)(uintptr_t)memory_block_dest);

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

		/* Clear destination */
		set_buffer(memory_block_dest, 0x00);

		/* Enable channel, transfer, and disable it */
		dma_channel_enable(channel_index);
		dma_transfer_block(channel_index);
		dma_channel_disable(channel_index);

		/* Check that destination is the reverse of source */
		success = block_compare_reverse(memory_block_src,
				memory_block_dest, MEMORY_BLOCK_SIZE);

		if (!success) {
			break;
		}

		/* Reset channel and write the configuration */
		dma_channel_reset(channel_index);
		/* Decrement source, increment destination */
		dma_channel_set_src_dir_mode(&config_params,
				DMA_CH_SRCDIR_INC_gc);
		dma_channel_set_dest_dir_mode(&config_params,
				DMA_CH_DESTDIR_DEC_gc);
		/* Data starts from the first byte */
		dma_channel_set_source_address(&config_params,
				(uint16_t)(uintptr_t)memory_block_src);
		dma_channel_set_destination_address(&config_params,
				(uint16_t)(uintptr_t)
				(memory_block_dest + MEMORY_BLOCK_SIZE - 1));

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

		/* Clear destination */
		set_buffer(memory_block_dest, 0x00);

		/* Enable channel, transfer, and disable it */
		dma_channel_enable(channel_index);
		dma_transfer_block(channel_index);
		dma_channel_disable(channel_index);

		/* Check that destination is the reverse of source */
		success = block_compare_reverse(memory_block_src,
				memory_block_dest, MEMORY_BLOCK_SIZE);

		if (!success) {
			break;
		}

		/* Reset channel and write the configuration */
		dma_channel_reset(channel_index);
		/* Decrement source, Decrement destination */
		dma_channel_set_src_dir_mode(&config_params,
				DMA_CH_SRCDIR_DEC_gc);
		dma_channel_set_dest_dir_mode(&config_params,
				DMA_CH_DESTDIR_DEC_gc);
		/* Data starts from the first byte */
		dma_channel_set_source_address(&config_params,
				(uint16_t)(uintptr_t)
				(memory_block_src + MEMORY_BLOCK_SIZE - 1));
		dma_channel_set_destination_address(&config_params,
				(uint16_t)(uintptr_t)
				(memory_block_dest + MEMORY_BLOCK_SIZE - 1));

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

		/* Clear destination */
		set_buffer(memory_block_dest, 0x00);

		/* Enable channel, transfer, and disable it */
		dma_channel_enable(channel_index);
		dma_transfer_block(channel_index);
		dma_channel_disable(channel_index);

		/* Check that source and destination are equal */
		success = block_compare(memory_block_src,
				memory_block_dest, MEMORY_BLOCK_SIZE);

		if (!success) {
			break;
		}
	}

	/* Disable DMA */
	dma_disable();

	test_assert_true(test, success,
			"DMA direction copy test failed on channel %d",
			channel_index);
}
Exemple #19
0
void ws2812_init( void )
{
	uint32_t i,j;

	for( i = 0; i < WS2812_BUFFERSIZE; i++ )
	{
		bitframe_pattern[i] = 0;
		bitframe_pattern_draw[i] = 0;
	}

	for( i=0; i < (3*NR_OF_LEDS_PER_CH*NR_OF_ROWS); i++)
	{
		frame_pattern[i] = 0;

	}

	/* configure the GPIOs */
	/* Enable GPIOC clock  */
	rcc_periph_clock_enable(RCC_GPIOB);

	/* Setup GPIO pin GPIO8/9 on GPIO port C for LEDs. */
	gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, GPIO0);
	gpio_set_output_options( GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_HIGH, GPIO0);

	/* configure the DMA */
	rcc_periph_clock_enable(RCC_DMA);

	/* configure DMA for sending high constant pattern to port on begin of cycle
	 * send unrolled bitframe on Timer OC1 event
	 * send low on Timer OC3 event
	 */
	dma_channel_reset( DMA1, DMA_CHANNEL3);
	dma_set_peripheral_address( DMA1, DMA_CHANNEL3, (uint32_t)&GPIOB_ODR);
    dma_set_memory_address( DMA1, DMA_CHANNEL3, (uint32_t)&high_pattern);
    dma_set_peripheral_size( DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
    dma_set_memory_size( DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
    dma_disable_peripheral_increment_mode( DMA1, DMA_CHANNEL3 );
    dma_disable_memory_increment_mode( DMA1, DMA_CHANNEL3 );
    dma_set_priority( DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
    dma_set_read_from_memory(DMA1, DMA_CHANNEL3);

	dma_channel_reset( DMA1, DMA_CHANNEL4);
	dma_set_peripheral_address( DMA1, DMA_CHANNEL4, (uint32_t)&GPIOB_ODR);
    dma_set_memory_address( DMA1, DMA_CHANNEL4, (uint32_t)actual_bitframe);
    dma_set_peripheral_size( DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_8BIT);
    dma_set_memory_size( DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_8BIT);
    dma_disable_peripheral_increment_mode( DMA1, DMA_CHANNEL4 );
    dma_enable_memory_increment_mode( DMA1, DMA_CHANNEL4 );
    dma_set_priority( DMA1, DMA_CHANNEL4, DMA_CCR_PL_HIGH);
    dma_set_read_from_memory(DMA1, DMA_CHANNEL4);

	dma_channel_reset( DMA1, DMA_CHANNEL2);
	dma_set_peripheral_address( DMA1, DMA_CHANNEL2, (uint32_t)&GPIOB_ODR);
    dma_set_memory_address( DMA1, DMA_CHANNEL2, (uint32_t)&low_pattern);
    dma_set_peripheral_size( DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
    dma_set_memory_size( DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
    dma_disable_peripheral_increment_mode( DMA1, DMA_CHANNEL2 );
    dma_disable_memory_increment_mode( DMA1, DMA_CHANNEL2 );
    dma_set_priority( DMA1, DMA_CHANNEL2, DMA_CCR_PL_HIGH);
    dma_set_read_from_memory(DMA1, DMA_CHANNEL2);


    nvic_set_priority(NVIC_DMA1_CHANNEL2_3_IRQ, 0);
    nvic_enable_irq(NVIC_DMA1_CHANNEL2_3_IRQ);
    dma_enable_transfer_complete_interrupt( DMA1, DMA_CHANNEL2);


    /* configure timer */
    rcc_periph_clock_enable(RCC_TIM3);


    /* configure the timer for 800kHz overall frequency */
    timer_reset( TIM3 );
    timer_set_mode( TIM3, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    timer_set_period( TIM3, 60);
    timer_set_repetition_counter( TIM3, 0);
    timer_disable_preload( TIM3 );

    /* timer compare section 1 for low coding */
    timer_set_oc_mode( TIM3, TIM_OC1,TIM_OCM_FROZEN);
    timer_set_oc_value( TIM3, TIM_OC1, 19);
    timer_disable_oc_preload( TIM3, TIM_OC1);

    /* timer compare section 3 for high coding */
    timer_set_oc_mode( TIM3, TIM_OC3,TIM_OCM_FROZEN);
    timer_set_oc_value( TIM3, TIM_OC3, 41);
    timer_disable_oc_preload( TIM3, TIM_OC3);

    nvic_set_priority( NVIC_TIM3_IRQ,1);
    nvic_set_priority( NVIC_PENDSV_IRQ, 2);
    nvic_enable_irq(NVIC_TIM3_IRQ);
    nvic_enable_irq(NVIC_PENDSV_IRQ);

    /* start the sending process */
    ws2812_send();
}
Exemple #20
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");
}
Exemple #21
0
/**
 *
 * \brief Set DMA configuration, and read it back
 *
 * \note This function writes a configuration to the DMA
 * controller, and reads it back to verify settings have
 * been correctly set.
 *
 * \param test   Current test case
 */
static void run_dma_config_interface_test(const struct test_case *test)
{
	struct dma_channel_config config_params;
	struct dma_channel_config read_config;

	const uint16_t transfer_count = 1024;
	const uint8_t repeats         = 64;
	uint8_t channel_index;

#ifdef CONFIG_HAVE_HUGEMEM
	hugemem_ptr_t dest_huge_addr  = HUGEMEM_NULL;
	hugemem_ptr_t src_huge_addr   = HUGEMEM_NULL;

	hugemem_write32(dest_huge_addr, 0xABCD1234);
	hugemem_write32(src_huge_addr, 0xAAAABBBB);
#else
	const uint16_t dest_addr      = 0xBEEF;
	const uint16_t src_addr       = 0xABCD;
#endif

	memset(&config_params, 0, sizeof(config_params));

	dma_enable();

	/* Apply some parameters */
	dma_channel_set_burst_length(&config_params,
			DMA_CH_BURSTLEN_4BYTE_gc);
	dma_channel_set_single_shot(&config_params);
	dma_channel_set_interrupt_level(&config_params,
			PMIC_LVL_HIGH);
	dma_channel_set_src_reload_mode(&config_params,
			DMA_CH_SRCRELOAD_BLOCK_gc);
	dma_channel_set_dest_reload_mode(&config_params,
			DMA_CH_DESTRELOAD_BURST_gc);
	dma_channel_set_src_dir_mode(&config_params,
			DMA_CH_SRCDIR_DEC_gc);
	dma_channel_set_dest_dir_mode(&config_params,
			DMA_CH_DESTDIR_DEC_gc);
	dma_channel_set_trigger_source(&config_params,
			DMA_CH_TRIGSRC_TCC0_CCA_gc);
	dma_channel_set_transfer_count(&config_params,
			transfer_count);
	dma_channel_set_repeats(&config_params,
			repeats);

#ifdef CONFIG_HAVE_HUGEMEM
	dma_channel_set_destination_hugemem(&config_params, dest_huge_addr);
	dma_channel_set_source_hugemem(&config_params, src_huge_addr);
#else
	dma_channel_set_destination_address(&config_params, dest_addr);
	dma_channel_set_source_address(&config_params, src_addr);
#endif

	/* Loop through all channels, read back config from them, and verify */
	for (channel_index = 0; channel_index < DMA_NUMBER_OF_CHANNELS; channel_index++) {
		dma_channel_write_config(channel_index, &config_params);

		/* Null out the read_config struct */
		memset(&read_config, 0, sizeof(read_config));

		/* Read the config back from the module */
		dma_channel_read_config(channel_index, &read_config);

		test_assert_true(test,
				read_config.addrctrl == config_params.addrctrl,
				"CH %d: Address control register does not match configuration",
				channel_index);

		test_assert_true(test, read_config.ctrla == config_params.ctrla,
				"CH %d: Control register A does not match configuration",
				channel_index);

		test_assert_true(test,
				read_config.repcnt == config_params.repcnt,
				"CH %d: Repeat counter register does not match configuration",
				channel_index);

		test_assert_true(test,
				read_config.trfcnt == config_params.trfcnt,
				"CH %d: Transfer counter register does not"
				" match configuration", channel_index);

		test_assert_true(test,
				read_config.trigsrc == config_params.trigsrc,
				"CH %d: Trigger source register does not match configuration",
				channel_index);

#ifdef CONFIG_HAVE_HUGEMEM
		test_assert_true(test,
				read_config.destaddr == config_params.destaddr,
				"CH %d: Destination address register does not"
				" match configuration", channel_index);

		test_assert_true(test,
				read_config.srcaddr == config_params.srcaddr,
				"CH %d: Source address register does not match configuration",
				channel_index);
#else
		test_assert_true(test,
				read_config.destaddr16 == config_params.destaddr16,
				"CH %d: DESTADDR16 does not match configuration",
				channel_index);

		test_assert_true(test,
				read_config.srcaddr16 == config_params.srcaddr16,
				"CH %d: SRCADDR16 does not match configuration");
#endif
	}

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

	/* Check set and unset single shot */
	memset(&config_params, 0, sizeof(config_params));
	memset(&read_config, 0, sizeof(read_config));

	dma_channel_set_single_shot(&config_params);

	dma_channel_write_config(DMA_CHANNEL_0, &config_params);
	dma_channel_read_config(DMA_CHANNEL_0, &read_config);

	test_assert_true(test, read_config.ctrla == config_params.ctrla,
			"Single shot mode not set correctly");

	memset(&config_params, 0, sizeof(config_params));
	dma_channel_unset_single_shot(&config_params);

	dma_channel_write_config(DMA_CHANNEL_0, &config_params);
	dma_channel_read_config(DMA_CHANNEL_0, &read_config);

	test_assert_true(test, read_config.ctrla == config_params.ctrla,
			"Single shot mode not unset correctly");

	/* Reset it again, and test the direct configuration functions */
	memset(&read_config, 0, sizeof(read_config));

	dma_channel_write_burst_length(DMA_CHANNEL_0, DMA_CH_BURSTLEN_4BYTE_gc);
	dma_channel_write_transfer_count(DMA_CHANNEL_0, transfer_count);
	dma_channel_write_repeats(DMA_CHANNEL_0, repeats);

#ifdef CONFIG_HAVE_HUGEMEM
	dma_channel_write_source_hugemem(DMA_CHANNEL_0, src_huge_addr);
	dma_channel_write_destination_hugemem(DMA_CHANNEL_0, dest_huge_addr);
#else
	dma_channel_write_source(DMA_CHANNEL_0, src_addr);
	dma_channel_write_destination(DMA_CHANNEL_0, dest_addr);
#endif

	/* Verify that settings have been set correctly */
	dma_channel_read_config(DMA_CHANNEL_0, &read_config);

	test_assert_true(test,
			(read_config.ctrla & DMA_CH_BURSTLEN_gm)
			== DMA_CH_BURSTLEN_4BYTE_gc,
			"Read burst length does not match configuration");

	test_assert_true(test, read_config.trfcnt == transfer_count,
			"Read transfer count does not match configuration");

	test_assert_true(test, read_config.repcnt == repeats,
			"Read repeat value does not match configuration");

#ifdef CONFIG_HAVE_HUGEMEM
	test_assert_true(test, read_config.srcaddr == src_huge_addr,
			"Read source address does not match configuration");

	test_assert_true(test, read_config.destaddr == dest_huge_addr,
			"Read destination address does not match configuration");
#else
	test_assert_true(test, read_config.srcaddr16 == src_addr,
			"Read source address does not match configuration");

	test_assert_true(test, read_config.destaddr16 == dest_addr,
			"Read destination address does not match configuration");
#endif

	dma_disable();
}
static int spi_dma_transceive(uint8_t *tx_buf, int tx_len, uint8_t *rx_buf, int rx_len)
#endif
{	

	/* Check for 0 length in both tx and rx */
	if ((rx_len < 1) && (tx_len < 1)) {
		/* return -1 as error */
		return -1;
	}

	/* Reset DMA channels*/
	dma_channel_reset(DMA1, DMA_CHANNEL2);
	dma_channel_reset(DMA1, DMA_CHANNEL3);

	/* Reset SPI data and status registers.
	 * Here we assume that the SPI peripheral is NOT
	 * busy any longer, i.e. the last activity was verified
	 * complete elsewhere in the program.
	 */
	volatile uint8_t temp_data __attribute__ ((unused));
	while (SPI_SR(SPI1) & (SPI_SR_RXNE | SPI_SR_OVR)) {
		temp_data = SPI_DR(SPI1);
	}

	/* Reset status flag appropriately (both 0 case caught above) */
	transceive_status = NONE;
	if (rx_len < 1) {
		transceive_status = ONE;
	}

	/* Determine tx length case to change behaviour
	 * If tx_len >= rx_len, then normal case, run both DMAs with normal settings
	 * If rx_len == 0, just don't run the rx DMA at all
	 * If tx_len == 0, use a dummy buf and set the tx dma to transfer the same
	 *    amount as the rx_len, to ensure everything is clocked in
	 * If 0 < tx_len < rx_len, first do a normal case, then on the tx finished
	 *    interrupt, set up a new dummyy buf tx dma transfer for the remaining
	 *    required clock cycles (handled in tx dma complete interrupt)
	 */
	if ((tx_len > 0) && (tx_len < rx_len)) {
		rx_buf_remainder = rx_len - tx_len;
	}

	/* Set up rx dma, note it has higher priority to avoid overrun */
	if (rx_len > 0) {
		dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t)&SPI1_DR);
		dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t)rx_buf);
		dma_set_number_of_data(DMA1, DMA_CHANNEL2, rx_len);
		dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
		dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
#if USE_16BIT_TRANSFERS
		dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_16BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_16BIT);
#else
		dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
#endif
		dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_VERY_HIGH);
	}

	/* Set up tx dma (must always run tx to get clock signal) */
	if (tx_len > 0) {
		/* Here we have a regular tx transfer */
		dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t)&SPI1_DR);
		dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t)tx_buf);
		dma_set_number_of_data(DMA1, DMA_CHANNEL3, tx_len);
		dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
		dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
#if USE_16BIT_TRANSFERS
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
		dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	} else {
		/* Here we aren't transmitting any real data, use the dummy buffer
		 * and set the length to the rx_len to get all rx data in, while
		 * not incrementing the memory pointer
		 */
		dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t)&SPI1_DR);
		dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t)(&dummy_tx_buf)); // Change here
		dma_set_number_of_data(DMA1, DMA_CHANNEL3, rx_len); // Change here
		dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
		dma_disable_memory_increment_mode(DMA1, DMA_CHANNEL3); // Change here
#if USE_16BIT_TRANSFERS
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
		dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	}

	/* Enable dma transfer complete interrupts */
	if (rx_len > 0) {
		dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL2);
	}
	dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);

	/* Activate dma channels */
	if (rx_len > 0) {
		dma_enable_channel(DMA1, DMA_CHANNEL2);
	}
	dma_enable_channel(DMA1, DMA_CHANNEL3);

	/* Enable the spi transfer via dma
	 * This will immediately start the transmission,
	 * after which when the receive is complete, the
	 * receive dma will activate
	 */
	if (rx_len > 0) {
    	spi_enable_rx_dma(SPI1);
    }
    spi_enable_tx_dma(SPI1);

    return 0;
}
Exemple #23
0
/**
 * Initialize analog to digital converter
 */
void adc_init(adc_callback_t half_transfer_callback,
	      adc_callback_t transfer_complete_callback)
{
	/* Reset adc_state. */
	adc_state.dma_transfer_error_counter = 0;
	adc_state.half_transfer_callback = half_transfer_callback;
	adc_state.transfer_complete_callback = transfer_complete_callback;

	/* Initialize peripheral clocks. */
	rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN);
	rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
	rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN);
	rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC2EN);

	/* Initialize the ADC input GPIO. */
	/* WARNING: this code is written to work with strip. On the strip
	 * hardware we are lucky and all the ADC channels are on the same bank
	 * so we can initialize all of them in one go. This code will need to be
	 * changed/improved if we ever have to support hardware that has the
	 * ADC's spread over more then one bank.
	 */
	gpio_set_mode(ADC_BANK, GPIO_MODE_INPUT,
		      GPIO_CNF_INPUT_ANALOG, ADC_PORT_U_VOLTAGE |
		      ADC_PORT_V_VOLTAGE |
		      ADC_PORT_W_VOLTAGE |
		      ADC_PORT_V_BATT |
		      ADC_PORT_CURRENT);

	/* Configure DMA for data aquisition. */
	/* Channel 1 reacts to: ADC1, TIM2_CH3 and TIM4_CH1 */
	dma_channel_reset(DMA1, DMA_CHANNEL1);

	dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (uint32_t)&ADC1_DR);
	dma_set_memory_address(DMA1, DMA_CHANNEL1,
			       (uint32_t)adc_state.raw_data);
	dma_set_number_of_data(DMA1, DMA_CHANNEL1, ADC_RAW_SAMPLE_COUNT/2);
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL1);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1);
	dma_enable_circular_mode(DMA1, DMA_CHANNEL1);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR_PSIZE_32BIT);
	dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR_MSIZE_32BIT);
	dma_set_priority(DMA1, DMA_CHANNEL1, DMA_CCR_PL_VERY_HIGH);

	dma_enable_half_transfer_interrupt(DMA1, DMA_CHANNEL1);
	dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL1);
	dma_enable_transfer_error_interrupt(DMA1, DMA_CHANNEL1);

	dma_enable_channel(DMA1, DMA_CHANNEL1);

	/* Configure interrupts in NVIC. */
	nvic_set_priority(NVIC_DMA1_CHANNEL1_IRQ, 0);
	nvic_enable_irq(NVIC_DMA1_CHANNEL1_IRQ);

	/* Disable ADC's. */
	adc_off(ADC1);
	adc_off(ADC2);

	/* Enable dualmode. */
	adc_set_dual_mode(ADC_CR1_DUALMOD_RSM); /* Dualmode regular only. */

	/* Configure the adc channels. */
	adc_config(ADC1, adc1_channel_array);
	adc_config(ADC2, adc2_channel_array);

	/* Start converting. */
	adc_start_conversion_regular(ADC1);
}