예제 #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);
}
예제 #2
0
static void dma_restart()
{
    dma_set_memory_address(DMA1, DMA_CHANNEL5,
            (uint32_t) buf + 12);
    dma_set_number_of_data(DMA1, DMA_CHANNEL5, 83);
    dma_set_memory_address(DMA1, DMA_CHANNEL6,
            (uint32_t) buf + 12 + 83 * 4);
    dma_set_number_of_data(DMA1, DMA_CHANNEL6, 83);

    dma_enable_channel(DMA1, DMA_CHANNEL5);
    dma_enable_channel(DMA1, DMA_CHANNEL6);

    state = ADC_WORKING;
}
예제 #3
0
/// Processing done after rx completes.
void process_rx_dma_interrupt(struct spi_periph *periph) {
  struct spi_periph_dma *dma = periph->init_struct;
  struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];

  /* Disable DMA Channel */
  dma_disable_transfer_complete_interrupt(dma->dma, dma->rx_chan);

  /* Disable SPI Rx request */
  spi_disable_rx_dma((uint32_t)periph->reg_addr);

  /* Disable DMA rx channel */
  dma_disable_channel(dma->dma, dma->rx_chan);


  if (dma->rx_extra_dummy_dma) {
    /*
     * We are finished the first part of the receive with real data,
     * but still need to run the dummy to get a transfer complete interrupt
     * after the complete transaction is done.
     */

    /* Reset the flag so this only happens once in a transaction */
    dma->rx_extra_dummy_dma = FALSE;

    /* Use the difference in length between rx and tx */
    uint16_t len_remaining = trans->output_length - trans->input_length;

    spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
                      (uint32_t)&(dma->rx_dummy_buf), len_remaining, trans->dss, FALSE);
    dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
    dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_HIGH);

    /* Enable DMA transfer complete interrupts. */
    dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
    /* Enable DMA channels */
    dma_enable_channel(dma->dma, dma->rx_chan);
    /* Enable SPI transfers via DMA */
    spi_enable_rx_dma((uint32_t)periph->reg_addr);
  }
  else {
    /*
     * Since the receive DMA is always run until the very end
     * and this interrupt is triggered after the last data word was read,
     * we now know that this transaction is finished.
     */

    /* Run the callback */
    trans->status = SPITransSuccess;
    if (trans->after_cb != 0) {
      trans->after_cb(trans);
    }

    /* AFTER the callback, then unselect the slave if required */
    if (trans->select == SPISelectUnselect || trans->select == SPIUnselect) {
      SpiSlaveUnselect(trans->slave_idx);
    }

    spi_next_transaction(periph);
  }
}
예제 #4
0
파일: main.c 프로젝트: Mechelix/btstack
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);
}
void dma_transmit(const void* buffer, const int datasize)
{
    dma_set_memory_address(DMA1, DMA_CHANNEL4, (uint32_t) buffer);
    dma_set_number_of_data(DMA1, DMA_CHANNEL4, datasize);

    dma_enable_channel(DMA1, DMA_CHANNEL4);
    usart_enable_tx_dma(USART2);
}
void dma_request(void* buffer, const int datasize)
{
    dma_set_memory_address(DMA1, DMA_CHANNEL5, (uint32_t) buffer);
    dma_set_number_of_data(DMA1, DMA_CHANNEL5, datasize);

    dma_enable_channel(DMA1, DMA_CHANNEL5);
    signal_host();
    usart_enable_rx_dma(USART2);
}
예제 #7
0
파일: acq.c 프로젝트: atalax/spectrometer
void acq_start()
{
	spi_enable(SPI_C1);

	spi_enable_rx_dma(SPI_C1);
	dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL2);
	dma_enable_half_transfer_interrupt(DMA1, DMA_CHANNEL2);
	dma_enable_channel(DMA1, DMA_CHANNEL2);
	nvic_enable_irq(NVIC_DMA1_CHANNEL2_IRQ);
}
예제 #8
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;
}
예제 #9
0
void tim4_isr()
{
    timer_clear_flag(TIM4, TIM_SR_UIF);

    cm3_assert(state == IDLE);
    state = READING;

    select_slave();

    dma_clear_interrupt_flags(DMA1, DMA_CHANNEL1, 0xf);
    dma_clear_interrupt_flags(DMA1, DMA_CHANNEL2, 0xf);

    dma_set_memory_address(DMA1, DMA_CHANNEL1, (uint32_t) txstr);
    dma_set_number_of_data(DMA1, DMA_CHANNEL1, 10);
    dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t) rxbuf);
    dma_set_number_of_data(DMA1, DMA_CHANNEL2, 10);

    spi_enable_tx_dma(SPI2);
    spi_enable_rx_dma(SPI2);

    dma_enable_channel(DMA1, DMA_CHANNEL1);
    dma_enable_channel(DMA1, DMA_CHANNEL2);
}
예제 #10
0
void ws2812_send( void )
{
	/* init the DMA data transfer */

	dma_clear_interrupt_flags( DMA1, DMA_CHANNEL2, DMA_TEIF | DMA_HTIF | DMA_TCIF | DMA_GIF);
	dma_clear_interrupt_flags( DMA1, DMA_CHANNEL3, DMA_TEIF | DMA_HTIF | DMA_TCIF | DMA_GIF);
	dma_clear_interrupt_flags( DMA1, DMA_CHANNEL4, DMA_TEIF | DMA_HTIF | DMA_TCIF | DMA_GIF);

	dma_set_memory_address( DMA1, DMA_CHANNEL4, (uint32_t)actual_bitframe);

	dma_set_number_of_data( DMA1, DMA_CHANNEL2, WS2812_BUFFERSIZE);
	dma_set_number_of_data( DMA1, DMA_CHANNEL3, WS2812_BUFFERSIZE);
	dma_set_number_of_data( DMA1, DMA_CHANNEL4, WS2812_BUFFERSIZE);

	TIM3_SR = 0;

	dma_enable_channel( DMA1, DMA_CHANNEL2);
	dma_enable_channel( DMA1, DMA_CHANNEL3);
	dma_enable_channel( DMA1, DMA_CHANNEL4);

	//timer_enable_irq( TIM3, TIM_DIER_TDE);
	timer_enable_irq( TIM3, TIM_DIER_CC1DE);
	timer_enable_irq( TIM3, TIM_DIER_CC3DE);
	timer_enable_irq( TIM3, TIM_DIER_UDE);

	timer_set_counter(TIM3, 60);


	timer_enable_counter(TIM3);


	SCB_ICSR |= SCB_ICSR_PENDSVSET;



}
예제 #11
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;
}
예제 #12
0
/* 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);
}
/*--------------------------------------------------------------------*/
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);
}
예제 #14
0
파일: uart.c 프로젝트: F-D-R/deviation
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;
}
예제 #15
0
/// Processing done after tx completes
void process_tx_dma_interrupt(struct spi_periph *periph) {
  struct spi_periph_dma *dma = periph->init_struct;
  struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];

  /* Disable DMA Channel */
  dma_disable_transfer_complete_interrupt(dma->dma, dma->tx_chan);

  /* Disable SPI TX request */
  spi_disable_tx_dma((uint32_t)periph->reg_addr);

  /* Disable DMA tx channel */
  dma_disable_channel(dma->dma, dma->tx_chan);

  if (dma->tx_extra_dummy_dma) {
    /*
     * We are finished the first part of the transmit with real data,
     * but still need to clock in the rest of the receive data.
     * Set up a dummy dma transmit transfer to accomplish this.
     */

    /* Reset the flag so this only happens once in a transaction */
    dma->tx_extra_dummy_dma = FALSE;

    /* Use the difference in length between tx and rx */
    uint16_t len_remaining = trans->input_length - trans->output_length;

    spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
                      (uint32_t)&(dma->tx_dummy_buf), len_remaining, trans->dss, FALSE);
    dma_set_read_from_memory(dma->dma, dma->tx_chan);
    dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);

    /* Enable DMA transfer complete interrupts. */
    dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
    /* Enable DMA channels */
    dma_enable_channel(dma->dma, dma->tx_chan);
    /* Enable SPI transfers via DMA */
    spi_enable_tx_dma((uint32_t)periph->reg_addr);

  }
}
예제 #16
0
파일: main.c 프로젝트: Mechelix/btstack
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);
}
예제 #17
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;
}
예제 #18
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);
}
예제 #19
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;
}
static void ResetDMA()
{
   dma_disable_channel(DMA1, TERM_USART_DMACHAN);
   dma_set_number_of_data(DMA1, TERM_USART_DMACHAN, TERM_BUFSIZE);
   dma_enable_channel(DMA1, TERM_USART_DMACHAN);
}
예제 #21
0
/**
 * Start a new transaction with DMA.
 */
static void spi_start_dma_transaction(struct spi_periph* periph, struct spi_transaction* trans)
{
  struct spi_periph_dma *dma;
  uint8_t sig = 0x00;

  /* Store local copy to notify of the results */
  trans->status = SPITransRunning;
  periph->status = SPIRunning;

  dma = periph->init_struct;

  /*
   * Check if we need to reconfigure the spi peripheral for this transaction
   */
  sig = get_transaction_signature(trans);
  if (sig != dma->comm_sig) {
    /* A different config is required in this transaction... */
    set_comm_from_transaction(&(dma->comm), trans);

    /* remember the new conf signature */
    dma->comm_sig = sig;

    /* apply the new configuration */
    spi_disable((uint32_t)periph->reg_addr);
    spi_init_master((uint32_t)periph->reg_addr, dma->comm.br, dma->comm.cpol,
                    dma->comm.cpha, dma->comm.dff, dma->comm.lsbfirst);
    spi_enable_software_slave_management((uint32_t)periph->reg_addr);
    spi_set_nss_high((uint32_t)periph->reg_addr);
    spi_enable((uint32_t)periph->reg_addr);
  }

  /*
   * Select the slave after reconfiguration of the peripheral
   */
  if (trans->select == SPISelectUnselect || trans->select == SPISelect) {
    SpiSlaveSelect(trans->slave_idx);
  }

  /* Run the callback AFTER selecting the slave */
  if (trans->before_cb != 0) {
    trans->before_cb(trans);
  }

  /*
   * Receive DMA channel configuration ----------------------------------------
   *
   * We always run the receive DMA until the very end!
   * This is done so we can use the transfer complete interrupt
   * of the RX DMA to signal the end of the transaction.
   *
   * If we want to receive less than we transmit, a dummy buffer
   * for the rx DMA is used after for the remaining data.
   *
   * In the transmit only case (input_length == 0),
   * the dummy is used right from the start.
   */
  if (trans->input_length == 0) {
    /* run the dummy rx dma for the complete transaction length */
    spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
                      (uint32_t)&(dma->rx_dummy_buf), trans->output_length, trans->dss, FALSE);
  } else {
    /* run the real rx dma for input_length */
    spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
                      (uint32_t)trans->input_buf, trans->input_length, trans->dss, TRUE);
    /* use dummy rx dma for the rest */
    if (trans->output_length > trans->input_length) {
      /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
      dma->rx_extra_dummy_dma = TRUE;
    }
  }
  dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_VERY_HIGH);


  /*
   * Transmit DMA channel configuration ---------------------------------------
   *
   * We always run the transmit DMA!
   * To receive data, the clock must run, so something has to be transmitted.
   * If needed, use a dummy DMA transmitting zeros for the remaining length.
   *
   * In the reveive only case (output_length == 0),
   * the dummy is used right from the start.
   */
  if (trans->output_length == 0) {
    spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
                      (uint32_t)&(dma->tx_dummy_buf), trans->input_length, trans->dss, FALSE);
  } else {
    spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
                      (uint32_t)trans->output_buf, trans->output_length, trans->dss, TRUE);
    if (trans->input_length > trans->output_length) {
      /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
      dma->tx_extra_dummy_dma = TRUE;
    }
  }
  dma_set_read_from_memory(dma->dma, dma->tx_chan);
  dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);


  /* Enable DMA transfer complete interrupts. */
  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);

  /* Enable DMA channels */
  dma_enable_channel(dma->dma, dma->rx_chan);
  dma_enable_channel(dma->dma, dma->tx_chan);

  /* Enable SPI transfers via DMA */
  spi_enable_rx_dma((uint32_t)periph->reg_addr);
  spi_enable_tx_dma((uint32_t)periph->reg_addr);
}
예제 #22
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;
}
예제 #23
0
파일: dma.c 프로젝트: doceme/libopencm3
int main(void)
{
	/* Exactly 20 bytes including '0' at the end.
	   We want to transfer 32bit * 5 so it should fit */
	char s1[20] = "Hello STM MEM2MEM\r\n";
	char s2[20];

        rcc_clock_setup_in_hse_16mhz_out_72mhz();
	gpio_setup();
	usart_setup();

	gpio_clear(GPIOB, GPIO7);	/* LED1 on */
	gpio_set(GPIOB, GPIO6);		/* LED2 off */

	my_usart_print_string(USART1, "s1 ");
	my_usart_print_string(USART1, s1);

	rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN);

	/* MEM2MEM mode for channel 1. */
	dma_enable_mem2mem_mode(DMA1, DMA_CHANNEL1);

	/* Highest priority. */
	dma_set_priority(DMA1, DMA_CHANNEL1, DMA_CCR1_PL_VERY_HIGH);

	/* 32Bit wide transfer for source and destination. */
	dma_set_memory_size(DMA1, DMA_CHANNEL1, DMA_CCR1_MSIZE_32BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL1, DMA_CCR1_PSIZE_32BIT);

	/* After each 32Bit we have to increase the addres because we use RAM. */
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL1);
	dma_enable_peripheral_increment_mode(DMA1, DMA_CHANNEL1);

	/* We define the source as peripheral. */
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL1);

	/* We want to transfer string s1. */
	dma_set_peripheral_address(DMA1, DMA_CHANNEL1, (u32) &s1);

	/* Destination should be string s2. */
	dma_set_memory_address(DMA1, DMA_CHANNEL1, (u32) &s2);

	/* Set number of DATA to transfer.
	   Remember that this means not necessary bytes but MSIZE or PSIZE
	   depending from your source device. */
	dma_set_number_of_data(DMA1, DMA_CHANNEL1, 5); 

	/* Start DMA transfer. */
	dma_enable_channel(DMA1, DMA_CHANNEL1);

	/* TODO: write a function to get the interrupt flags. */
	while(!(DMA_ISR(DMA1) & 0x0000001))
	{
	}

	dma_disable_channel(DMA1, DMA_CHANNEL1);

	/* String s1 should now already be transferred to s2. */
	my_usart_print_string(USART1, "s2 ");
	my_usart_print_string(USART1, s2);

	gpio_clear(GPIOB, GPIO6);	/* LED2 on */
	while(1); /* Halt. */

	return 0;
}
예제 #24
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_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;
}