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); }
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 mew_bluetooth_transmit(uint8_t* data, uint16_t size, uint8_t sync_mode) { mew_check_dma_memory((void*)data, "mew_bluetooth_transmit"); mew_wait_for_state(&_mew_dma_tx_state, 0); _mew_dma_tx_state = 1; dma_stream_reset(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX); dma_set_transfer_mode(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX, DMA_SxCR_DIR_MEM_TO_PERIPHERAL); dma_set_priority(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX, DMA_SxCR_PL_HIGH); dma_set_memory_size(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX, DMA_SxCR_MSIZE_8BIT); dma_set_peripheral_size(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX, DMA_SxCR_PSIZE_8BIT); dma_enable_memory_increment_mode(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX); dma_set_peripheral_address(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX, (uint32_t) &MEW_BLUETOOTH_DMA_DR); dma_channel_select(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX, MEW_BLUETOOTH_DMA_CHANNEL_TX); dma_set_memory_address(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX, (uint32_t) data); dma_set_number_of_data(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX, size); dma_disable_fifo_error_interrupt(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX); dma_disable_half_transfer_interrupt(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX); dma_enable_transfer_complete_interrupt(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX); dma_enable_transfer_error_interrupt(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX); dma_enable_transfer_complete_interrupt(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX); __mew_bluetooth_clear_buf(); dma_enable_stream(MEW_BLUETOOTH_DMA, MEW_BLUETOOTH_DMA_STREAM_TX); if (sync_mode == 1) { mew_wait_for_state(&_mew_dma_tx_state, 0); } }
void baro_init() { gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO13 | GPIO15); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); deselect_slave(); spi_init_master(SPI2, SPI_CR1_BAUDRATE_FPCLK_DIV_8, SPI_CR1_CPOL, SPI_CR1_CPHA, SPI_CR1_DFF_8BIT, SPI_CR1_MSBFIRST); spi_enable_ss_output(SPI2); spi_enable(SPI2); dma_set_peripheral_address(DMA1, DMA_CHANNEL3, SPI2_DR); 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_8BIT); dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT); dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH); dma_set_peripheral_address(DMA1, DMA_CHANNEL4, SPI2_DR); dma_set_read_from_peripheral(DMA1, DMA_CHANNEL4); dma_enable_memory_increment_mode(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_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL4); timer_reset(TIM4); timer_enable_irq(TIM4, TIM_DIER_UIE); timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); /* 3200 / 16 = 200 Hz */ timer_set_prescaler(TIM4, 32); timer_set_period(TIM4, 5625); nvic_set_priority(NVIC_TIM4_IRQ, 16 * 2); nvic_set_priority(NVIC_DMA1_CHANNEL4_IRQ, 16 * 2); nvic_enable_irq(NVIC_TIM4_IRQ); nvic_enable_irq(NVIC_DMA1_CHANNEL4_IRQ); read_calibration_data(); }
/* 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; }
static void __spi_dma_setup(uint32_t stream, uint32_t maddr, size_t n) { while ((DMA1_SCR(stream) & DMA_SxCR_EN) != 0) bl_dbg("Stream enabled"); /* Set peripheral address */ dma_set_peripheral_address(DMA1, stream, (uint32_t)&SPI2_DR); /* Set memory address */ dma_set_memory_address(DMA1, stream, maddr); /* Set total number of bytes to transfer */ dma_set_number_of_data(DMA1, stream, n); /* Select channel, it is 0 for both RX and TX */ dma_channel_select(DMA1, stream, DMA_SxCR_CHSEL_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; }
void usart_tx(char *buf, unsigned short len) { usart_enable_tx_dma(USART1); dma_stream_reset(DMA2, DMA_STREAM7); dma_set_priority(DMA2, DMA_STREAM7, DMA_SxCR_PL_LOW); dma_set_memory_size(DMA2, DMA_STREAM7, DMA_SxCR_MSIZE_8BIT); dma_set_peripheral_size(DMA2, DMA_STREAM7, DMA_SxCR_PSIZE_8BIT); dma_enable_memory_increment_mode(DMA2, DMA_STREAM7); dma_set_transfer_mode(DMA2, DMA_STREAM7, DMA_SxCR_DIR_MEM_TO_PERIPHERAL); dma_set_peripheral_address(DMA2, DMA_STREAM7, (uint32_t) &USART1_DR); dma_set_memory_address(DMA2, DMA_STREAM7, (uint32_t) buf); dma_set_number_of_data(DMA2, DMA_STREAM7, len); dma_enable_transfer_complete_interrupt(DMA2, DMA_STREAM7); dma_channel_select(DMA2, DMA_STREAM7, DMA_SxCR_CHSEL_4); dma_enable_stream(DMA2, DMA_STREAM7); }
/* 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); }
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_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); }
/*--------------------------------------------------------------------*/ 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); }
/****************************************************************************** * * 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); }
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); }
u8 UART_Send(u8 *data, u16 len) { if (busy) return 1; busy = 1; DMA_stream_reset(USART_DMA); dma_set_peripheral_address(USART_DMA.dma, USART_DMA.stream, (u32) &USART_DR(UART_CFG.uart)); /* send data to the USART data register */ dma_set_memory_address(USART_DMA.dma, USART_DMA.stream, (u32) data); dma_set_number_of_data(USART_DMA.dma, USART_DMA.stream, len); dma_set_read_from_memory(USART_DMA.dma, USART_DMA.stream); /* direction is from memory to usart */ dma_enable_memory_increment_mode(USART_DMA.dma, USART_DMA.stream); /* memory pointer increments, peripheral no */ dma_set_peripheral_size(USART_DMA.dma, USART_DMA.stream, DMA_SxCR_PSIZE_8BIT); /* USART_DR is 8bit wide in this mode */ dma_set_memory_size(USART_DMA.dma, USART_DMA.stream, DMA_SxCR_MSIZE_8BIT); /* destination memory is also 8 bit wide */ dma_set_priority(USART_DMA.dma, USART_DMA.stream, DMA_CCR_PL_LOW); dma_enable_transfer_complete_interrupt(USART_DMA.dma, USART_DMA.stream); DMA_channel_select(USART_DMA); DMA_enable_stream(USART_DMA); /* dma ready to go */ usart_enable_tx_dma(UART_CFG.uart); return 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); }
static void platform_init_adc() { /* Set up DMA for the ADC */ nvic_enable_irq(NVIC_DMA2_STREAM0_IRQ); nvic_set_priority(NVIC_DMA2_STREAM0_IRQ, 64); /* Set up ADC */ for (int i = 0; i < NUM_SENSORS; ++i) { if (config.sensors[i].method == SENSOR_ADC) { adc_pins[i] = config.sensors[i].pin; gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, (1<<adc_pins[i])); } } adc_off(ADC1); adc_enable_scan_mode(ADC1); adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_15CYC); adc_power_on(ADC1); adc_disable_dma(ADC1); adc_enable_dma(ADC1); adc_clear_overrun_flag(ADC1); adc_set_dma_continue(ADC1); dma_stream_reset(DMA2, DMA_STREAM0); dma_set_priority(DMA2, DMA_STREAM0, DMA_SxCR_PL_HIGH); dma_set_memory_size(DMA2, DMA_STREAM0, DMA_SxCR_MSIZE_16BIT); dma_set_peripheral_size(DMA2, DMA_STREAM0, DMA_SxCR_PSIZE_16BIT); dma_enable_memory_increment_mode(DMA2, DMA_STREAM0); dma_set_transfer_mode(DMA2, DMA_STREAM0, DMA_SxCR_DIR_PERIPHERAL_TO_MEM); dma_enable_circular_mode(DMA2, DMA_STREAM0); dma_set_peripheral_address(DMA2, DMA_STREAM0, (uint32_t) &ADC1_DR); dma_set_memory_address(DMA2, DMA_STREAM0, (uint32_t) adc_dma_buf); dma_set_number_of_data(DMA2, DMA_STREAM0, NUM_SENSORS); dma_enable_transfer_complete_interrupt(DMA2, DMA_STREAM0); dma_channel_select(DMA2, DMA_STREAM0, DMA_SxCR_CHSEL_0); dma_enable_stream(DMA2, DMA_STREAM0); adc_set_regular_sequence(ADC1, NUM_SENSORS, adc_pins); }
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; }
/*--------------------------------------------------------------------*/ void dma_setup(void) { rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_DMA2EN); /* ADC1 uses DMA controller 2 Stream 0 channel 0. */ /* Enable DMA2 clock and IRQ */ nvic_enable_irq(NVIC_DMA2_STREAM0_IRQ); dma_stream_reset(DMA2,DMA_STREAM0); dma_set_priority(DMA2,DMA_STREAM0,DMA_SxCR_PL_LOW); dma_set_peripheral_size(DMA2,DMA_STREAM0,DMA_SxCR_PSIZE_32BIT); /* The register to target is the ADC regular data register */ dma_set_peripheral_address(DMA2,DMA_STREAM0,(uint32_t) &ADC1_DR); /* The array v[] is filled with the waveform data to be output */ dma_set_memory_size(DMA2,DMA_STREAM0,DMA_SxCR_MSIZE_32BIT); dma_set_memory_address(DMA2,DMA_STREAM0,(uint32_t) v); dma_set_number_of_data(DMA2,DMA_STREAM0,64); dma_set_transfer_mode(DMA2,DMA_STREAM0, DMA_SxCR_DIR_PERIPHERAL_TO_MEM); dma_enable_memory_increment_mode(DMA2,DMA_STREAM0); dma_enable_circular_mode(DMA2,DMA_STREAM0); /* Don't use FIFO */ dma_enable_direct_mode(DMA2,DMA_STREAM0); dma_enable_transfer_complete_interrupt(DMA2, DMA_STREAM0); dma_channel_select(DMA2, DMA_STREAM0, DMA_SxCR_CHSEL_0); dma_enable_stream(DMA2,DMA_STREAM0); }
/*--------------------------------------------------------------------*/ static void dma_setup(void) { /* DAC channel 1 uses DMA controller 1 Stream 5 Channel 7. */ /* Enable DMA1 clock and IRQ */ rcc_periph_clock_enable(RCC_DMA1); nvic_enable_irq(NVIC_DMA1_STREAM5_IRQ); dma_stream_reset(DMA1, DMA_STREAM5); dma_set_priority(DMA1, DMA_STREAM5, DMA_SxCR_PL_LOW); dma_set_memory_size(DMA1, DMA_STREAM5, DMA_SxCR_MSIZE_8BIT); dma_set_peripheral_size(DMA1, DMA_STREAM5, DMA_SxCR_PSIZE_8BIT); dma_enable_memory_increment_mode(DMA1, DMA_STREAM5); dma_enable_circular_mode(DMA1, DMA_STREAM5); dma_set_transfer_mode(DMA1, DMA_STREAM5, DMA_SxCR_DIR_MEM_TO_PERIPHERAL); /* The register to target is the DAC1 8-bit right justified data register */ dma_set_peripheral_address(DMA1, DMA_STREAM5, (uint32_t) &DAC_DHR8R1); /* The array v[] is filled with the waveform data to be output */ dma_set_memory_address(DMA1, DMA_STREAM5, (uint32_t) waveform); dma_set_number_of_data(DMA1, DMA_STREAM5, 256); dma_enable_transfer_complete_interrupt(DMA1, DMA_STREAM5); dma_channel_select(DMA1, DMA_STREAM5, DMA_SxCR_CHSEL_7); dma_enable_stream(DMA1, DMA_STREAM5); }
/** * 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); }
void accel_highg_init() { uint8_t channel_array[16]; gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0 | GPIO1 | GPIO2); adc_set_dual_mode(ADC_CR1_DUALMOD_RSM); /* ADC1 + ADC2 dual mode */ adc_set_dual_mode(ADC_CR1_DUALMOD_ISM); adc_enable_external_trigger_injected(ADC1, ADC_CR2_JEXTSEL_TIM1_TRGO); adc_enable_external_trigger_injected(ADC3, ADC_CR2_JEXTSEL_TIM1_TRGO); adc_enable_dma(ADC1); adc_enable_dma(ADC3); adc_power_on(ADC1); adc_power_on(ADC2); adc_power_on(ADC3); adc_stab_sleep(); adc_reset_calibration(ADC1); adc_reset_calibration(ADC2); adc_reset_calibration(ADC3); adc_calibration(ADC1); adc_calibration(ADC2); adc_calibration(ADC3); memset(channel_array, 0, sizeof(channel_array)); channel_array[0] = 10; adc_set_injected_sequence(ADC1, 1, channel_array); channel_array[0] = 11; adc_set_injected_sequence(ADC2, 1, channel_array); channel_array[0] = 12; adc_set_injected_sequence(ADC3, 1, channel_array); timer_reset(TIM1); timer_enable_irq(TIM1, TIM_DIER_UIE); timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); /* 500Hz */ timer_set_prescaler(TIM1, 64); timer_set_period(TIM1, 2250); /* Generate TRGO */ timer_set_master_mode(TIM1, TIM_CR2_MMS_UPDATE); dma_set_peripheral_address(DMA1, DMA_CHANNEL5, (uint32_t) &ADC1_DR); dma_set_read_from_memory(DMA1, DMA_CHANNEL5); dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL5); dma_set_peripheral_size(DMA1, DMA_CHANNEL5, DMA_CCR_PSIZE_32BIT); dma_set_memory_size(DMA1, DMA_CHANNEL5, DMA_CCR_MSIZE_32BIT); dma_set_priority(DMA1, DMA_CHANNEL5, DMA_CCR_PL_HIGH); dma_set_peripheral_address(DMA1, DMA_CHANNEL6, (uint32_t) &ADC3_DR); dma_set_read_from_peripheral(DMA1, DMA_CHANNEL6); dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL6); dma_set_peripheral_size(DMA1, DMA_CHANNEL6, DMA_CCR_PSIZE_16BIT); dma_set_memory_size(DMA1, DMA_CHANNEL6, DMA_CCR_MSIZE_16BIT); dma_set_priority(DMA1, DMA_CHANNEL6, DMA_CCR_PL_HIGH); dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL5); dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL6); }
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(); }
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 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); }
void codecInit(void) { memset(adcBuffer, 0xaa, sizeof(adcBuffer)); // I2S2 alternate function mapping gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 | GPIO15); gpio_set_af(GPIOB, GPIO_AF5, GPIO12 | GPIO13 | GPIO15); gpio_set_af(GPIOB, GPIO_AF6, GPIO14); // I2S2ext_SD (I2S receive) gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6); gpio_set_af(GPIOC, GPIO_AF5, GPIO6); // MCLK gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO12 | GPIO13 | GPIO15); gpio_set_output_options(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO6); // Set up SPI1 spi_reset(SPI1); spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_256, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE, SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST); spi_set_nss_high(SPI1); spi_enable_software_slave_management(SPI1); spi_enable(SPI1); // SPI1 alternate function mapping, set CSB signal high output gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO5 | GPIO7); gpio_set_af(GPIOA, GPIO_AF5, GPIO5 | GPIO7); gpio_set(GPIOA, GPIO4); gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4); codecConfig(); // Set up I2S for 48kHz 16-bit stereo. // The input to the PLLI2S is 1MHz. Division factors are from // table 126 in the data sheet. // // This gives us 1.536MHz SCLK = 16 bits * 2 channels * 48000 Hz // and 12.288 MHz MCLK = 256 * 48000 Hz. // With this PLL configuration the actual sampling frequency // is nominally 47991 Hz. spi_reset(SPI2); RCC_PLLI2SCFGR = (3 << 28) | (258 << 6); RCC_CR |= RCC_CR_PLLI2SON; while (!(RCC_CR & RCC_CR_PLLI2SRDY)); const unsigned i2sdiv = 3; SPI_I2SPR(SPI2) = SPI_I2SPR_MCKOE | SPI_I2SPR_ODD | i2sdiv; SPI_I2SCFGR(SPI2) |= SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE | (SPI_I2SCFGR_I2SCFG_MASTER_TRANSMIT << SPI_I2SCFGR_I2SCFG_LSB); SPI_I2SCFGR(I2S2_EXT_BASE) = SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE | (SPI_I2SCFGR_I2SCFG_SLAVE_RECEIVE << SPI_I2SCFGR_I2SCFG_LSB); // Configure the DMA engine to stream data to the DAC. dma_stream_reset(DMA1, DAC_DMA_STREAM); dma_set_peripheral_address(DMA1, DAC_DMA_STREAM, (intptr_t)&SPI_DR(SPI2)); dma_set_memory_address(DMA1, DAC_DMA_STREAM, (intptr_t)dacBuffer[0]); dma_set_memory_address_1(DMA1, DAC_DMA_STREAM, (intptr_t)dacBuffer[1]); dma_set_number_of_data(DMA1, DAC_DMA_STREAM, BUFFER_SAMPLES); dma_channel_select(DMA1, DAC_DMA_STREAM, DAC_DMA_CHANNEL); dma_set_transfer_mode(DMA1, DAC_DMA_STREAM, DMA_SxCR_DIR_MEM_TO_PERIPHERAL); dma_set_memory_size(DMA1, DAC_DMA_STREAM, DMA_SxCR_MSIZE_16BIT); dma_set_peripheral_size(DMA1, DAC_DMA_STREAM, DMA_SxCR_PSIZE_16BIT); dma_enable_memory_increment_mode(DMA1, DAC_DMA_STREAM); dma_enable_double_buffer_mode(DMA1, DAC_DMA_STREAM); dma_enable_stream(DMA1, DAC_DMA_STREAM); // Configure the DMA engine to stream data from the ADC. dma_stream_reset(DMA1, ADC_DMA_STREAM); dma_set_peripheral_address(DMA1, ADC_DMA_STREAM, (intptr_t)&SPI_DR(I2S2_EXT_BASE)); dma_set_memory_address(DMA1, ADC_DMA_STREAM, (intptr_t)adcBuffer[0]); dma_set_memory_address_1(DMA1, ADC_DMA_STREAM, (intptr_t)adcBuffer[1]); dma_set_number_of_data(DMA1, ADC_DMA_STREAM, BUFFER_SAMPLES); dma_channel_select(DMA1, ADC_DMA_STREAM, ADC_DMA_CHANNEL); dma_set_transfer_mode(DMA1, ADC_DMA_STREAM, DMA_SxCR_DIR_PERIPHERAL_TO_MEM); dma_set_memory_size(DMA1, ADC_DMA_STREAM, DMA_SxCR_MSIZE_16BIT); dma_set_peripheral_size(DMA1, ADC_DMA_STREAM, DMA_SxCR_PSIZE_16BIT); dma_enable_memory_increment_mode(DMA1, ADC_DMA_STREAM); dma_enable_double_buffer_mode(DMA1, ADC_DMA_STREAM); dma_enable_stream(DMA1, ADC_DMA_STREAM); dma_enable_transfer_complete_interrupt(DMA1, ADC_DMA_STREAM); nvic_enable_irq(NVIC_DMA1_STREAM3_IRQ); nvic_set_priority(NVIC_DMA1_STREAM3_IRQ, 0x80); // 0 is most urgent // Start transmitting data spi_enable_rx_dma(I2S2_EXT_BASE); spi_enable_tx_dma(SPI2); }
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; }
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; }
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; }