Hello.
I am working on a project that requires reading from an external ADC via SPI. To save on computing cost, I would like to go down the DMA route. I've looked at several examples on interfacing DMA with SPI. However, I haven't had any success implementing my own code. I am experiencing a problem where the DMA channel is always busy. Not only that, but I do not see any clock signals out of the SCK pin. My main function looks a lot like the code below...minus the commented out section which I excluded for this post.
Where: Basically what I want to do is have the DMA fill out a 9 element data array. I managed to get a similar code working for the internal ADC, but that doesn't involve SPI. Does anyone have any ideas as to what could be the issue?
Thank you.
I am working on a project that requires reading from an external ADC via SPI. To save on computing cost, I would like to go down the DMA route. I've looked at several examples on interfacing DMA with SPI. However, I haven't had any success implementing my own code. I am experiencing a problem where the DMA channel is always busy. Not only that, but I do not see any clock signals out of the SCK pin. My main function looks a lot like the code below...minus the commented out section which I excluded for this post.
Code:
// Setup Inits stdio_init_all(); // Initialize SPI spi_init(SPI_PORT, 1000000); // Set channel and baud rate spi_set_format(SPI_PORT, 16, SPI_CPOL_0, SPI_CPHA_0, SPI_LSB_FIRST); // Format channel gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); // Map GPIO gpio_set_function(PIN_SCK, GPIO_FUNC_SPI); gpio_init(PIN_CS); bi_decl(bi_2pins_with_func(PIN_MISO, PIN_SCK, GPIO_FUNC_SPI)); gpio_set_dir(PIN_CS, GPIO_OUT); gpio_put(PIN_CS, 1); bi_decl(bi_1pin_with_name(PIN_CS, "SPI CS")); // Channel Configs dma_channel_config c_rx = dma_channel_get_default_config(sample_chan); dma_channel_config c_ctrl = dma_channel_get_default_config(ctrl_chan); // Set up ADC sample channel channel_config_set_transfer_data_size( &c_rx, DMA_SIZE_16); // SPI ADC data transfer is 16 bits. channel_config_set_read_increment( &c_rx, false); // We are always reading from SPI receive buffer. channel_config_set_write_increment( &c_rx, true); // Increment write address as we are writing to a buffer. channel_config_set_dreq( &c_rx, spi_get_dreq(SPI_PORT, false)); // Pull data when its ready from the ADC. channel_config_set_chain_to(&c_rx, ctrl_chan); // Chain to sample chan dma_channel_configure(sample_chan, &c_rx, sample_data, &spi_get_hw(SPI_PORT)->dr, NUM_SAMPLES, false); // Set up control channel channel_config_set_transfer_data_size(&c_ctrl, DMA_SIZE_32); // DMA comm bits is 32 channel_config_set_read_increment( &c_ctrl, false); // Always read from the same register channel_config_set_write_increment( &c_ctrl, false); // Always write to the same register channel_config_set_chain_to(&c_ctrl, sample_chan); // Chain to sample chan dma_channel_configure(ctrl_chan, &c_ctrl, &dma_hw->ch[sample_chan].write_addr, &sample_address_pointer, 1, false); dma_start_channel_mask(1u << ctrl_chan); while (dma_channel_is_busy(ctrl_chan)) { __breakpoint(); } while (dma_channel_is_busy(sample_chan)) { __breakpoint(); }
Code:
// SPI/DMA definitions#define PIN_MISO 20#define PIN_CS 1#define PIN_SCK 18#define SPI_PORT spi0#define NUM_SAMPLES 9const uint16_t sample_chan = 0;const uint16_t ctrl_chan = 1;uint16_t sample_data[9];uint16_t *sample_address_pointer = &sample_data[0];uint16_t n = sizeof(sample_data) / sizeof(sample_data[0]);
Thank you.
Statistics: Posted by Tominator-LMG — Thu Nov 14, 2024 12:49 am — Replies 0 — Views 36