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); }
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; }
/// 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); } }
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); }
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); }
/* 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; }
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); }
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; }
/* 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); }
/*--------------------------------------------------------------------*/ 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); }
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; }
/// 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); } }
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); }
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; }
/** * 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); }
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); }
/** * 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); }
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; }