Comments (6)
I'm implementing exactly this in a ringbuffer in https://github.com/biemster/pico-I2S, but it is not working yet.
from pico-examples.
@jonathangjertsen , could you provide a little more detail on what you'd like to see in an example? For example, where does the data come from that's being scattered to the two buffers? Does completion of the processing trigger the next DMA transfer?
from pico-examples.
A typical example is continuously capturing ADC data at very high speed without any gaps. There is an example of using the DMA and ADC together, but it's just a one-shot.
I like this figure from TI's various processor datasheets (in this case taken from the TM4C1294NCPDT). I think it uses some generic ARM component for the DMA which may or may not be similar to the one used by the Pico
from pico-examples.
Thanks.
One approach to alternating between the two ping
and pong
buffers is to reconfigure the DMA channel from the IRQ handler once one buffer is full. For example, modifying the example in dma/channel_irq/channel_irq.c, we can can demonstrate ping-ponging between two buffers, allowing the on chip temperature to be oversampled and averaged. N.b. I've not dug into the RP2040 datasheet to determine whether this oversampling and averaging would have the desired effect of improving the resolution in the temperature reading, but it's a useful backdrop for the problem.
#include <stdio.h>
#include <stdint.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#include "hardware/dma.h"
#include "hardware/irq.h"
#include "hardware/timer.h"
#define CAPTURE_DEPTH 256
// Replace capture_buf[CAPTURE_DEPTH] with a ping and pong register
uint16_t ping[CAPTURE_DEPTH];
uint16_t pong[CAPTURE_DEPTH];
bool write_ping = true;
int dma_chan;
// Written to in the IRQ context, read from the main loop.
volatile uint32_t sum = 0;
void dma_handler() {
// Clear the interrupt request.
dma_hw->ints0 = 1u << dma_chan;
void *write_addr;
uint16_t *read_addr;
if (write_ping) {
// Ping was being written to, and has completed. Now read from ping, and write to pong.
write_ping = false;
read_addr = ping;
write_addr = pong;
} else {
write_ping = true;
read_addr = pong;
write_addr = ping;
}
// Kick off the next transfer.
dma_channel_set_write_addr(dma_chan, write_addr, true);
// Process what's in the read buffer.
uint32_t temp = 0;
for (size_t i = 0; i < CAPTURE_DEPTH; i++) {
// Mask the bottom 12 bits.
temp += read_addr[i] & 0xFFF;
}
// Oversampled, so divide down.
temp /= CAPTURE_DEPTH;
// Update.
sum = temp;
}
int main()
{
stdio_init_all();
#ifdef PICO_DEFAULT_LED_PIN
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
#endif
/* Initialize hardware AD converter, enable onboard temperature sensor and
* select its channel (do this once for efficiency, but beware that this
* is a global operation). */
adc_init();
adc_set_temp_sensor_enabled(true);
adc_select_input(4);
adc_fifo_setup(
true, // Write each completed conversion to the sample FIFO
true, // Enable DMA data request (DREQ)
1, // DREQ (and IRQ) asserted when at least 1 sample present
false,
false // Don't shift, masking values is handled in dma_handler()'s processing of the read buffer.
);
adc_set_clkdiv(0);
sleep_ms(1000);
printf("Arming DMA\n");
// Set up the DMA to start transferring data as soon as it appears in FIFO
dma_chan = dma_claim_unused_channel(true);
dma_channel_config cfg = dma_channel_get_default_config(dma_chan);
// Reading from constant address, writing to incrementing byte addresses
channel_config_set_transfer_data_size(&cfg, DMA_SIZE_16);
channel_config_set_read_increment(&cfg, false);
channel_config_set_write_increment(&cfg, true);
// Pace transfers based on availability of ADC samples
channel_config_set_dreq(&cfg, DREQ_ADC);
dma_channel_configure(dma_chan, &cfg,
ping, // dst
&adc_hw->fifo, // src
CAPTURE_DEPTH, // transfer count
false // do not start, wait for dma_handler() to be called
);
printf("Starting capture\n");
adc_run(true);
// Tell the DMA to raise IRQ line 0 when the channel finishes a block
dma_channel_set_irq0_enabled(dma_chan, true);
// Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
irq_set_exclusive_handler(DMA_IRQ_0, dma_handler);
irq_set_enabled(DMA_IRQ_0, true);
// Manually call the handler once, to trigger the first transfer
dma_handler();
float old_temp = 0;
while (true) {
/* 12-bit conversion, assume max value == ADC_VREF == 3.3 V */
const float conversionFactor = 3.3f / (1 << 12);
float adc = (float) sum * conversionFactor;
float tempC = 27.0f - (adc - 0.706f) / 0.001721f;
if (old_temp != tempC) {
printf("Onboard temperature = %.03f %c\n", tempC, TEMPERATURE_UNITS);
}
old_temp = tempC;
#ifdef PICO_DEFAULT_LED_PIN
gpio_put(PICO_DEFAULT_LED_PIN, 1);
sleep_ms(10);
gpio_put(PICO_DEFAULT_LED_PIN, 0);
#endif
sleep_ms(490);
}
return 0;
}
Some example output (yup, reading the first uninitialized data gives a nonsense value):
Arming DMA
Starting capture
Onboard temperature = 437.227 C
Onboard temperature = 14.499 C
Onboard temperature = 14.967 C
Onboard temperature = 15.435 C
from pico-examples.
There's a good example of DMA ping-pong writing to two buffers from ADC in https://github.com/zapta/simple_stepper_motor_analyzer/blob/main/platformio/src/acquisition/adc_dma.cpp
There's a messier examlple in https://github.com/kevinjwalters/galactic-bluetooth-audio/blob/spectrogram-tuner-dmaadc/uad/audiosourcedmaadc.cpp
from pico-examples.
Here is an other example without interrupt handler in python: https://github.com/wodr/Pico/blob/main/DmaRingBuffer/DmaRingBufferDoubleDma.py
from pico-examples.
Related Issues (20)
- Flashing pico fails HOT 4
- Add example of using TinyUSB CDC with extra stdio_usb iface
- Modify the pio uart examples to use DMA HOT 1
- ping examples hardcode an IP address
- Recommended launch.json is slow to connect due to no "adapter speed" setting
- No key press detected for pending in [iperf server] example HOT 1
- stdio_usb input available callback can't call other stdio functions, and pico-examples iperf assumes it can. HOT 4
- UART RX Garbage data recived HOT 5
- Pico-W to Pico-W STALL while sending UDP HOT 2
- Bug in BME280 SPI example when reading compensation parameters for humidity HOT 3
- Out-of-Memory Errors When Publishing MQTT Messages HOT 1
- host_cdc_msc_hid: incorrect len parameter in tuh_hid_report_received_cb HOT 1
- Bug in pio/uart_rx /uart_rx_intr.c HOT 6
- ir_nec variable length commands HOT 8
- How to do multiple TLS requests with changing request string HOT 2
- Example of starting and stopping btstack needed
- What does example iperf.c HOT 11
- Why MEMP_NUM_ARP_QUEUE lwIP options is set in lwipopts_examples_common.h if ARP_QUEUEING default value is 0? HOT 1
- Modbus TCP client over Wifi for Raspberry Pi Pico W (RP2040) HOT 1
- Issue in flash_program.c example
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pico-examples.