Which DMA microcontroller engines you like the most? - Page 1
Forum section: electronics / general

author: benSTmax
author_rank: Regular Contributor
timestamp: January 12, 2017, 03:59:31 pm
content: These days most of the popular 32-bits MCUs have an ARM core with maybe one exception which is Microchip (using MIPS cores in their PIC32s).In such a situation the differentiation comes from the peripheral themselves.The DMA engine within a micro can help a developer differentiate between a few products from different vendors.Throughout the years I have used parts from TI, ST, former-Freescale/NXP (and soon Qualcomm), Microchip, Cypress, former-Atmel (now Microchip).Till recently, my preferred DMA engine was the one used in the TI's Tiva TM4C12x series.Then came the one used in Freescale's Kinetis K6x series.Inspired bymikeselectricstuff's projectsusing PIC32hereandhere(A bigThank Youfor the materials on this topic posted on hisYoutube channel), I started exploring the DMA engine in the PIC32MX250 series from Microchip and I totally love it.Right now, my personal ranking would be:Microchip's PIC32MX250 DMA engine- My current favorite. Though a simple engine, it is incredibly powerful and versatile due to the clever DMA trigger selection. You can do amazing things with it due to the large number and flexibility (in choice) of DMA triggers. For me, this DMA engine required the smallest learning curveTI Tiva TM4C12x DMA engine- This was my personal favorite till PIC32. The scatter-gather capabilities are amazing and for me it required a medium learning curveFreescale's Kinetis K6x DMA engine- I have used this engine in a few projects and it has a lot of possibilities. However this isn't a simple engine and you have quite a few registers to program

author: mark03
author_rank: Frequent Contributor
timestamp: January 12, 2017, 05:02:09 pm
content: IMO, a proper DMA engine should support circular buffers in such a way that you can pause an in-progress DMA, add some data to the circular queue, and then restart the DMA, without a lot of hassle. The one Kinetis part I used (I think it was a KL26?) was wonderful. All of the STM32 parts fail on this metric, unfortunately. Their "circular" mode should be called auto-repeat instead; once you stop a DMA you cannot pick up where you left off. Too bad we can't mix and match our favorite peripherals from different vendors!

author: Howardlong
author_rank: Super Contributor
timestamp: January 12, 2017, 05:27:31 pm
content: Quote from: mark03 on January 12, 2017, 05:02:09 pmThe DMA in PIC32s allows circular buffers (it's called auto enable) and includes several buffer interrupts including at full and at half full so implementing continuous ping pong buffers in a single DMA channel is simple, or as simple as it can be with DMA. You can also do it with DMA channel chaining, but that's expensive in terms of burning up DMA channels.Getting stuff like cache coherency working is an irritation you can do without, as is Microchip's continual desire to rip up peripheral libraries and start again every three or four years, so I program the registers directly rather than pay the tax of having to learn another API.The only other processor I've done DMA on recently is the NXP LPC4370, which was OK but had limitations on maximum buffer size which was 4095 bytes IIRC. The PIC32 has no buffer size restriction, you can DMA the entire physical address space in one transaction if you want to.

author: hans
author_rank: Super Contributor
timestamp: January 12, 2017, 08:43:23 pm
content: I only used the SMT32F407 and PIC32MX795 DMA's so far.I think it's quite possibly one of the worst/frustrating and one of the best/elegant implementations right beside each other, in huge favour of the PIC32.The PIC32 is simple to understand & program, yet it functions very well. The shadow IRQ system is excellent, as it allows any channel to be used with any IRQ trigger for any DMA transfer.STM32 on the other hand probably has more options than the PIC32, but due to their channel selection it means youhave tocheck triggers for particular channels during hardware design phase. More problems arise when e.g. you have a complex DMA use case and have collisions in this table. Also the extra delays between DMA1 and DMA2 for APB1/2 are noticeable at high frequencies.Haven't tried Tm4C12x, but scatter/gather sounds like an excellent feature considering most large memory MCU's have broken up memory maps.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: January 13, 2017, 06:08:09 pm
content: I don't have any DMA experience ouside PIC32 but I like it's orthogonality, in that any IRQ can trigger a DMA from any address to any address, which came in handy recently when I used the DMA-complete int to load a constant into a timer-control register to stop an external clock precisely.I'm sure you could do some really crazy stuff by DMAing things between hardware registers. I wonder what happens if you DMA stuff into DMA registers...

author: retrolefty
author_rank: Super Contributor
timestamp: January 13, 2017, 08:49:45 pm
content: Quote from: mikeselectricstuff on January 13, 2017, 06:08:09 pmIt creates a Black Hole and we all perish.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: January 13, 2017, 10:37:17 pm
content: BTW here's another one on using DMA to get image data from a camera into a PIC32

author: hans
author_rank: Super Contributor
timestamp: January 13, 2017, 11:23:12 pm
content: Quote from: mikeselectricstuff on January 13, 2017, 06:08:09 pmUse DMA to transfer data between hardware/RAM, and then use a second channel to swap the RAM source or destination start pointers from the first DMA channel automatically via the DMA complete IRQ.Then if the DMA the complete ISR occurs from channel 2, all buffers are sent.If you need to send arbitrary size buffers, use a 3rd DMA channel to control the second in which the 2nd writes the source and size registers of 1st in bursts, and the 3rd resets the 2nd DMA channel destination address for the next burst.Hmm, now I wonder if that could really work... not sure how much the DMA controller likes it's pointers to be touched when it's activeI'm sure it will kill an electron somewhere in the chip by doing that though.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: January 13, 2017, 11:37:47 pm
content: You could do some seriously crazy code obfuscation .. throw in CRC and abort on pattern-match for good measure.

author: timb
author_rank: Super Contributor
timestamp: January 14, 2017, 06:20:39 am
content: I particularly like the DMA of the PSoC 5LP. They even make it easy to setup with a DMA wizard. Another neat thing is the DMA component has status pins, which makes it possible for the programmable logic to trigger DMA reads and writes completely outside of the software. (This allows you to do cool stuff like, say, move data from an I2C sensor to SPI flash when the sensor pulls an IRQ line, all with basically no CPU intervention.)

author: Karel
author_rank: Super Contributor
timestamp: January 14, 2017, 08:46:06 am
content: Microchip PIC32.Honestly, it was the first one where I used DMA and it was so easy to implement just by reading the datasheet andthe PIC32 family manuals, that I never felt the need to try something else.So, I can't compare with other brands (have done some stuff wit AVR in the past, no DMA though), but I'm quietsatisfied with PIC32's, also because they are easy to setup. Apart from the Harmony framework which I detest.Offtopic: Once, when I was visiting the company that does our series production, I asked them which MCU's are used moston the boards they produce for their clients. I expected it to be ARM but they said Microchip is used most.Their clients do automotive, aerospace and industrial.

author: Howardlong
author_rank: Super Contributor
timestamp: January 14, 2017, 03:38:16 pm
content: Quote from: Karel on January 14, 2017, 08:46:06 amI've given up with Harmony for anything other than USB and Ethernet. Everything else is hand rolled bare metal SFR access, including PIC32MZ.

author: Howardlong
author_rank: Super Contributor
timestamp: January 15, 2017, 06:30:39 pm
content: One feature I'd like with PIC32 DMA that's missing is a padding feature allowing you to interleave data without resorting to manipulation after the fact.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: January 15, 2017, 07:27:37 pm
content: Quote from: Howardlong on January 15, 2017, 06:30:39 pmSomething else that would be handy is the ability to configure a pin to output a pulse whenever a transfer occurs - debugging DMA can be a bit of a PITA as it;s hard to know when transfers occur.

author: Howardlong
author_rank: Super Contributor
timestamp: January 15, 2017, 11:12:07 pm
content: Quote from: mikeselectricstuff on January 15, 2017, 07:27:37 pmIndeed. I had a bug only two days ago on an MZ where after hundreds of thousands of transfers one or two of six DMA channels would stop issuing interrupts.I was using IFSybits.DMAxIF=0 (non-atomic read-modify-write) in the ISR rather than IFSySET=DMAxIFBIT (atomic). As other DMA channels hit the same IFSy register, coincidentally they would interfere with the CPU accessing the same word, and the ISR would fail to fire once in a blue moon despite the DMAxIF and DMAxIE bits being set. That took a few hours to figure out.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: January 16, 2017, 12:08:42 am
content: Yeah I've been bitten by that as well - after the first couple of incidents you start to recognise "once in a blue moon" behaviour & realise it's a tiny "window of fail" somewhere.

author: Howardlong
author_rank: Super Contributor
timestamp: January 16, 2017, 09:19:42 am
content: Quote from: mikeselectricstuff on January 16, 2017, 12:08:42 amThing is, it works on PIC24 and PIC16 because unlike MIPS those cores have atomic bit set/reset.Unfortunately, unlike the base registers themselves, the bit fields for the set/clear pseudo SFRs are not declared by the provided devices' header files, so either you declare them yourself or use the PLIB out of the dreaded Harmony, which then means your code has a dependency on Harmony working, and those declarations and functions not being deprecated or changed.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: January 16, 2017, 01:34:47 pm
content: Quote from: Howardlong on January 16, 2017, 09:19:42 amAre they hardcoded in the PLIB functions, or is the a header file you could steal from PLIB to do it yourself ?I generally avoid using manufacturer-provided libraries - a nasty I got caught by a while ago was that a very simple library call (IntDisableInterrupts on PIC24) which I assumed was implemented as a macro, as it should be a single instruction, was actually implemented as a subroutine call.Problem was I'd used in a bootloader, so you could only update firmware once

author: Howardlong
author_rank: Super Contributor
timestamp: January 16, 2017, 04:05:32 pm
content: These days I try to avoid peripheral libraries too.My process for this has changed since using the PIC32MZ which pretty much demands Harmony if you want to use anything from the peripheral libraries such as chip setup.For the basic projects, I don't use MHC or Harmony at all except for a few PLIB resources. Below is my typical boiler plate code for a new project.o Set up as non-Harmony Project;o Add "c:\microchip\harmony\v1_09\framework" to the project's include directories;o Add "c:\microchip\harmony\v1_09\bin\framework\peripheral\PIC32MZnnnnEFxnnn_peripherals.a" as a Library/Object file to the project;o Create a clean main.c file in the project, deleting all the machine generated shit;o Add the following example code in main.c;Code:// DEVCFG0#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)/*** DEVCFG1 ***/#pragma config FNOSC = 0 //FRCDIV, note that setting this to 7 instead of 0 causes a clock failure, and COSC set to BFRC#pragma config IESO = OFF#pragma config POSCMOD = EC#pragma config OSCIOFNC = OFF#pragma config FCKSM = CSECME#pragma config FWDTEN = OFF#pragma config FDMTEN = OFF#define PLIB_DISABLE_OPTIMIZATION_WARNING#include "peripheral/peripheral.h"#include <xc.h>#include <sys/attribs.h> // Interrupt macros#include <stdint.h>#include <stdbool.h>o Add the following functions and main() to main.c:Code:static void CPUInit(void){// Note that cache is already configured by startup code// C:\Program Files\Microchip\xc32\v1.42\pic32-libs\libpic32\stubs\pic32_init_cache.S// Set up wait statesPLIB_PCACHE_WaitStateSet(PCACHE_ID_0, 2); // Adjust as appropriate for memory and clock// Set up prefetchif (PLIB_PCACHE_ExistsPrefetchEnable(PCACHE_ID_0)){PLIB_PCACHE_PrefetchEnableSet(PCACHE_ID_0, PLIB_PCACHE_PREFETCH_ENABLE_ALL);}// Set up interrupt controllerPLIB_INT_MultiVectorSelect(INT_ID_0);PLIB_INT_Enable(INT_ID_0);}static void OSCInit(void){// Switch to 200MHz PLL sourced from 24MHz EC POSCPLIB_DEVCON_SystemUnlock ( DEVCON_ID_0 );PLIB_OSC_SysPLLInputDivisorSet(OSC_ID_0, OSC_SYSPLL_IN_DIV_3); // Generate 8MHz from 24MHz POSCPLIB_OSC_SysPLLFrequencyRangeSet(OSC_ID_0, OSC_SYSPLL_FREQ_RANGE_5M_TO_10M);PLIB_OSC_SysPLLInputClockSourceSet(OSC_ID_0, OSC_SYSPLL_IN_CLK_SOURCE_PRIMARY);PLIB_OSC_SysPLLMultiplierSelect(OSC_ID_0, 50);PLIB_OSC_SysPLLOutputDivisorSet(OSC_ID_0, OSC_SYSPLL_OUT_DIV_2);PLIB_OSC_SysClockSelect(OSC_ID_0, OSC_PRIMARY_WITH_PLL);while (!PLIB_OSC_ClockSwitchingIsComplete(OSC_ID_0)){Nop();}PLIB_DEVCON_SystemLock ( DEVCON_ID_0 );}void main(void){CPUInit();OSCInit();// Your code goes here}Setting up the CPU and oscillator is almost all I use the PLIBs for, I use bare metal SFR access for almost everything else. It's my intention to move to bare SFR access to set the oscillator in future, but this is a hangover from the time I did actually try to use PLIB but have since decided it's not worth the effort.If I could be sure the PLIBs were:(a) correct;(b) fit for purpose;(c) able to cover the complete set of peripheral use cases;(d) not going to be deprecated any time soon;(e) easy to use and learn;then I'd be more likely to use them. As it is, within a year or two of release the peripheral library APIs no longer fit the peripherals of newer devices.

author: Karel
author_rank: Super Contributor
timestamp: January 16, 2017, 04:53:32 pm
content: I still prefer the PIC32MX series and I use the following boilerplate code:Code:#include <xc.h>#include <sys/attribs.h>// #define CPU_HZ 30000000// #define CPU_HZ 38000000#define CPU_HZ 96000000#if CPU_HZ <= 40000000CHECON = 0; /* disable data caching, disable predictive prefetch, zero wait states */BMXCONCLR = 1 << 6; /* data RAM accesses from CPU have zero wait states for address setup */#else// CHECON = 0x00000312; /* enable data caching with a size of 4 lines *//* enable predictive prefetch for cacheable regions only *//* two waitstates for PFM */CHECON = 0x00000332; /* enable data caching with a size of 4 lines *//* enable predictive prefetch for both cacheable and non-cacheable regions *//* two waitstates for PFM */BMXCONCLR = 1 << 6; /* data RAM accesses from CPU have zero wait states for address setup */#endif#pragma config FSRSSEL = PRIORITY_7 /* Shadow Register Set Priority Select */#pragma config FPLLIDIV = DIV_2 /* System PLL input divider */#if CPU_HZ == 30000000#pragma config FPLLMUL = MUL_15 /* System PLL multiplier */#pragma config FPLLODIV = DIV_2 /* System PLL Output Clock Divider */#pragma config FPBDIV = DIV_1 /* Peripheral Clock Divisor */#endif#if CPU_HZ == 38000000#pragma config FPLLMUL = MUL_19 /* System PLL multiplier */#pragma config FPLLODIV = DIV_2 /* System PLL Output Clock Divider */#pragma config FPBDIV = DIV_1 /* Peripheral Clock Divisor */#endif#if CPU_HZ == 96000000#pragma config FPLLMUL = MUL_24 /* System PLL multiplier */#pragma config FPLLODIV = DIV_1 /* System PLL Output Clock Divider */#pragma config FPBDIV = DIV_2 /* Peripheral Clock Divisor */#endif#pragma config FNOSC = FRCPLL /* Fast RC Osc with PLL */#pragma config FSOSCEN = OFF /* Disable secondary oscillator */#pragma config IESO = OFF /* Disable internal/external switch-over */#pragma config POSCMOD = OFF /* Primary oscillator disabled */#pragma config OSCIOFNC = OFF /* CLKO Output Signal Active on the OSCO Pin disabled */#pragma config FCKSM = CSDCMD /* Clock switch disabled, FSCM disabled */#pragma config FWDTEN = OFF /* Disable watchdog timer */#pragma config JTAGEN = OFF /* Switch off JTAG */#pragma config ICESEL = ICS_PGx1 /* Use PGEC1/PGED1 for programming/debugging */#pragma config PWP = OFF /* Program Flash Write Protect disabled */#pragma config BWP = OFF /* Boot Flash Write Protect bit disabled */#pragma config CP = ON /* Code Protect bit enabled */// #pragma config DEBUG = OFF /* Background Debugger disabled */#pragma config DEBUG = 3INTEnableSystemMultiVectoredInt(); /* Enable multi vectored interrupts */INTEnableInterrupts(); /* Enable interrupts */The last two functions to enable the interrupts I copied from the Microchip libs.MZ is still too buggy, even the latest versions. For example, the uarts can't recover from a buffer overrun.

author: Howardlong
author_rank: Super Contributor
timestamp: January 16, 2017, 07:57:45 pm
content: There are two features on the MZ EF that make it tower over the MX, that of USB HS and the integrated multiple simultaneous sampling high speed ADCs.I agree though that the errata rap sheet is something that Microchip should be ashamed of. Even findamentals like I2C and the crystal oscillator have significant shortcomings. The oscillator has been broken since the MZ EC, an even more woeful disaster, where they didn't acknowledge that its HS ADC was almost completely broken until about a year after it was released.

author: hli
author_rank: Frequent Contributor
timestamp: January 16, 2017, 08:10:44 pm
content: Quote from: timb on January 14, 2017, 06:20:39 amSecond that. Being able to trigger DMA with any signal you can come in hardware (even being able to create new hardware signals in custom logic), and then getting a DMA transfer signal in hardware which you can use to do any other things in hardware is really powerful. And IMHO the API for it is easy to understand, and Cypress has some really good application notes. They even explain the tricky things (such as self-modifying DMA - having one of the DMA channels modifying another DMA channels registers is quite powerful, e.g. to be able to use multiple target buffers without any software intervention).

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: January 16, 2017, 08:13:18 pm
content: Quote from: Howardlong on January 16, 2017, 07:57:45 pmDo you happen to know if Microchip have a working solution for reading USB memory sticks at High Speed on the MZ ?

author: Howardlong
author_rank: Super Contributor
timestamp: January 16, 2017, 08:29:39 pm
content: Quote from: mikeselectricstuff on January 16, 2017, 08:13:18 pmNo. Not sure if this helps, but to implement and take advantage of higher speeds as an HS device (rather than a host) I had to implement multiple simultaneous endpoints. I don't have any experience of running the USB peripheral as host.

author: Howardlong
author_rank: Super Contributor
timestamp: January 16, 2017, 09:50:07 pm
content: Quote from: Howardlong on January 16, 2017, 08:29:39 pmUpdate: I received a couple of PIC32MZ EF Curiosity boards last week, so I thought I'd try them out as a USB host for a thumb drive. I just ran a modified "PIC32MZ EF Curiosity USB MSD Host" (msd_basic) fromhereMy modified version ishere.The modification was to change it to write a 256MB file, by writing 4096 bytes 65536 times.It managed this in 28 seconds, so 9.6MB/s, or 77Mb/s. So it's definitely HS, but not stunning.The drive I used was a Sandisk Extreme USB 3.0 thumb drive which was specifically chosen for its high R/W speeds. For comparison, from a Windows box on USB 3.0, the same file writes in about 3 seconds. From a PC's USB 2.0 connection it's 10 seconds.Update: I haveanother versionof that project that reads the file. For some reason, it's slower, taking 46s to read the 256MB file, 5.8MB/s or 46Mbps.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: January 17, 2017, 12:11:50 am
content: That's odd - write speed will probably be affected more by variations in memory devices, but I'm usually only interested in reads. that speed looks a bit disappointing, but if it's anything like the library for the older versions, there's probably a lot of scope for optimisation.The old SD card code was doing stupid stuff like checking for end of cluster on every single byte transferrred, and not using the SPI in 32 bit mode during sector reads, but easy to optimise without needing to understand much of their code. USB may take a bit more work however.

author: bktemp
author_rank: Super Contributor
timestamp: January 17, 2017, 06:46:58 am
content: I did some tests using an STM32F469 @ 180MHz for comparing HS-USB and 4bit SD card running at 24MHz:Code:SD read test...reading 1 bytes...1 bytes done in 0.000s ( 2.224kByte/s)reading 2 bytes...2 bytes done in 0.000s ( 5.710kByte/s)reading 4 bytes...4 bytes done in 0.000s (11.322kByte/s)reading 8 bytes...8 bytes done in 0.000s (22.843kByte/s)reading 16 bytes...16 bytes done in 0.000s (45.687kByte/s)reading 32 bytes...32 bytes done in 0.000s (91.374kByte/s)reading 64 bytes...64 bytes done in 0.000s (182.215kByte/s)reading 128 bytes...128 bytes done in 0.000s (363.372kByte/s)reading 256 bytes...256 bytes done in 0.000s (716.332kByte/s)reading 512 bytes...512 bytes done in 0.000s (1457.726kByte/s)reading 1024 bytes...1024 bytes done in 0.000s (2506.266kByte/s)reading 2048 bytes...2048 bytes done in 0.000s (4065.042kByte/s)reading 4096 bytes...4096 bytes done in 0.001s (5882.355kByte/s)reading 8192 bytes...8192 bytes done in 0.001s (7561.440kByte/s)reading 16384 bytes...16384 bytes done in 0.002s (8834.902kByte/s)reading 32768 bytes...32768 bytes done in 0.004s (7540.060kByte/s)reading 65536 bytes...65536 bytes done in 0.008s (8323.583kByte/s)reading 131072 bytes...131072 bytes done in 0.015s (8772.535kByte/s)reading 262144 bytes...262144 bytes done in 0.028s (9023.303kByte/s)reading 524288 bytes...524288 bytes done in 0.057s (9036.202kByte/s)reading 1048576 bytes...1048576 bytes done in 0.112s (9160.118kByte/s)reading 2097152 bytes...2097152 bytes done in 0.222s (9223.775kByte/s)reading 4194304 bytes...4194304 bytes done in 0.442s (9257.087kByte/s)reading 8388608 bytes...8388608 bytes done in 0.884s (9268.472kByte/s)reading 16777216 bytes...16777216 bytes done in 1.766s (9275.356kByte/s)USB read test...reading 1 bytes...1 bytes done in 0.001s ( 1.247kByte/s)reading 2 bytes...2 bytes done in 0.001s ( 2.488kByte/s)reading 4 bytes...4 bytes done in 0.001s ( 4.901kByte/s)reading 8 bytes...8 bytes done in 0.001s ( 9.990kByte/s)reading 16 bytes...16 bytes done in 0.001s (20.006kByte/s)reading 32 bytes...32 bytes done in 0.001s (40.064kByte/s)reading 64 bytes...64 bytes done in 0.001s (79.617kByte/s)reading 128 bytes...128 bytes done in 0.001s (159.235kByte/s)reading 256 bytes...256 bytes done in 0.001s (315.258kByte/s)reading 512 bytes...512 bytes done in 0.001s (636.132kByte/s)reading 1024 bytes...1024 bytes done in 0.001s (1269.036kByte/s)reading 2048 bytes...2048 bytes done in 0.001s (2395.210kByte/s)reading 4096 bytes...4096 bytes done in 0.001s (3960.398kByte/s)reading 8192 bytes...8192 bytes done in 0.001s (5869.408kByte/s)reading 16384 bytes...16384 bytes done in 0.002s (8815.431kByte/s)reading 32768 bytes...32768 bytes done in 0.003s (12061.822kByte/s)reading 65536 bytes...65536 bytes done in 0.006s (10555.835kByte/s)reading 131072 bytes...131072 bytes done in 0.011s (11769.038kByte/s)reading 262144 bytes...262144 bytes done in 0.021s (12391.100kByte/s)reading 524288 bytes...524288 bytes done in 0.040s (12781.792kByte/s)reading 1048576 bytes...1048576 bytes done in 0.079s (12970.898kByte/s)reading 2097152 bytes...2097152 bytes done in 0.157s (13033.883kByte/s)reading 4194304 bytes...4194304 bytes done in 0.312s (13107.332kByte/s)reading 8388608 bytes...8388608 bytes done in 0.624s (13121.314kByte/s)reading 16777216 bytes...16777216 bytes done in 1.248s (13131.705kByte/s)USB write test...writing 1 bytes...1 bytes done in 0.001s ( 1.856kByte/s)writing 2 bytes...2 bytes done in 0.001s ( 3.727kByte/s)writing 4 bytes...4 bytes done in 0.001s ( 7.440kByte/s)writing 8 bytes...8 bytes done in 0.001s (14.880kByte/s)writing 16 bytes...16 bytes done in 0.001s (30.339kByte/s)writing 32 bytes...32 bytes done in 0.001s (59.523kByte/s)writing 64 bytes...64 bytes done in 0.001s (119.047kByte/s)writing 128 bytes...128 bytes done in 0.001s (237.642kByte/s)writing 256 bytes...256 bytes done in 0.001s (472.590kByte/s)writing 512 bytes...512 bytes done in 0.001s (452.898kByte/s)writing 1024 bytes...1024 bytes done in 0.001s (903.342kByte/s)writing 2048 bytes...2048 bytes done in 0.001s (1792.115kByte/s)writing 4096 bytes...4096 bytes done in 0.001s (3246.754kByte/s)writing 8192 bytes...8192 bytes done in 0.001s (5449.594kByte/s)writing 16384 bytes...16384 bytes done in 0.004s (4539.009kByte/s)writing 32768 bytes...32768 bytes done in 0.004s (7191.014kByte/s)writing 65536 bytes...65536 bytes done in 0.015s (4258.152kByte/s)writing 131072 bytes...131072 bytes done in 0.016s (8192.004kByte/s)writing 262144 bytes...262144 bytes done in 0.030s (8404.745kByte/s)writing 524288 bytes...524288 bytes done in 0.060s (8464.493kByte/s)writing 1048576 bytes...1048576 bytes done in 0.120s (8547.369kByte/s)writing 2097152 bytes...2097152 bytes done in 0.241s (8502.092kByte/s)writing 4194304 bytes...4194304 bytes done in 0.509s (8052.676kByte/s)writing 8388608 bytes...8388608 bytes done in 0.995s (8235.363kByte/s)writing 16777216 bytes...16777216 bytes done in 1.991s (8229.559kByte/s)SD write test...writing 1 bytes...1 bytes done in 0.001s ( 1.547kByte/s)writing 2 bytes...2 bytes done in 0.001s ( 3.066kByte/s)writing 4 bytes...4 bytes done in 0.001s ( 6.132kByte/s)writing 8 bytes...8 bytes done in 0.001s (12.131kByte/s)writing 16 bytes...16 bytes done in 0.001s (24.801kByte/s)writing 32 bytes...32 bytes done in 0.001s (48.981kByte/s)writing 64 bytes...64 bytes done in 0.001s (97.809kByte/s)writing 128 bytes...128 bytes done in 0.001s (193.798kByte/s)writing 256 bytes...256 bytes done in 0.001s (393.700kByte/s)writing 512 bytes...512 bytes done in 0.190s ( 2.633kByte/s)writing 1024 bytes...1024 bytes done in 0.130s ( 7.706kByte/s)writing 2048 bytes...2048 bytes done in 0.006s (357.653kByte/s)writing 4096 bytes...4096 bytes done in 0.006s (699.423kByte/s)writing 8192 bytes...8192 bytes done in 0.007s (1175.261kByte/s)writing 16384 bytes...16384 bytes done in 0.014s (1158.497kByte/s)writing 32768 bytes...32768 bytes done in 0.007s (4348.419kByte/s)writing 65536 bytes...65536 bytes done in 0.013s (4863.963kByte/s)writing 131072 bytes...131072 bytes done in 0.069s (1859.141kByte/s)writing 262144 bytes...262144 bytes done in 0.047s (5484.737kByte/s)writing 524288 bytes...524288 bytes done in 0.284s (1800.256kByte/s)writing 1048576 bytes...1048576 bytes done in 0.187s (5467.634kByte/s)writing 2097152 bytes...2097152 bytes done in 0.372s (5505.334kByte/s)writing 4194304 bytes...4194304 bytes done in 0.999s (4101.966kByte/s)writing 8388608 bytes...8388608 bytes done in 1.779s (4605.802kByte/s)writing 16777216 bytes...16777216 bytes done in 3.090s (5302.262kByte/s)It was only a single measurement, but it was pretty constant when repeating the test. The irregularities during writing are probably wear leveling activities.The speed varies a lot between different SD cards and USB drives, but the most important parameter is the block size: You need to write many sectors at once, otherwise it will be really slow. Especially for modern flash devices with large write pages, you need to read/write at least 4-32kBytes at once to nearly reach the maximum speed possible.I haven't used the recent versions of Microchip's MSD code, but the older versions didn't make use of the read multiple sector commands efficiently.Another catch when using USB drives and writing data to them: You need to send the SYNCHRONIZE CACHE command before unplugging, otherwise the last written data may get lost, because they could be still in the write buffer of the thumb drive. Both the code provided by Microchip and ST hadn't implemented this correctly.If you need to write a continous stream of data to flash devices, don't use the newest, largest devices, but go for older, smaller ones. I had many issues with 8 and 16GB SD cards. They often paused writing for a couple of seconds (!) to do wear leveling. 1-4GB seem to be the best choice for embedded systems with limited amount of memory for write buffer.The separately selectable data width for DMA is a nice feature in STM32 for transferring unaligned data packets to a 32bit target. But otherwise I prefer PIC24/PIC32, because its DMA is much easier to understand but very powerful because of the many trigger sources.

author: Howardlong
author_rank: Super Contributor
timestamp: January 17, 2017, 08:18:44 am
content: Quote from: mikeselectricstuff on January 17, 2017, 12:11:50 amFWIW, when I was fiddling about with the device code (my application is a streaming device so I needed to optimise device to host performance), you could increase the speed fairly significantly by increasing the size of the buffer to quite large sizes, using much more than the 4096 bytes I used in this example.When I've used the LPC4370 as a streaming device in the past (204MHz Cortex M4F), their USB device library managed single endpoint speeds of ~250Mbps, and I could get it up to about 320Mbps by bonding endpoints.

author: Carl47D
author_rank: Newbie
timestamp: January 17, 2017, 05:31:07 pm
content: Quote from: hli on January 16, 2017, 08:10:44 pmI like more the PSoC4 DMA API than the 5LP, and DMA on PSoC4 works on sleep mode IIRC.

author: Lukas
author_rank: Frequent Contributor
timestamp: January 17, 2017, 06:18:48 pm
content: The ultimate question: Can you build a turing machine using just the DMA peripheral DMA'ing into its control registers?

author: rea5245
author_rank: Frequent Contributor
timestamp: August 29, 2020, 07:58:59 pm
content: Quote from: Lukas on January 17, 2017, 06:18:48 pmThese guys claim that the PIC32's DMA system is Turing-complete:http://people.ece.cornell.edu/land/courses/ece4760/PIC32/index_DMA_weird_machine.html

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 31, 2020, 08:07:38 pm
content: I second the greatness of the PIC32 DMA.

author: Karel
author_rank: Super Contributor
timestamp: September 01, 2020, 06:08:43 am
content: The problem is the tools. They use ancient GCC compilers (XC16/32) that are forked and aren't very well optimized.(As opposed to sending their modifications upstream and use newer versions.)

author: coppice
author_rank: Super Contributor
timestamp: September 01, 2020, 09:25:25 am
content: Quote from: Karel on September 01, 2020, 06:08:43 amRecent versions of GCC work well for complex cores, like x86-64 ones. However, GCC 10 often produces slower code than GCC 3.2 (a high spot for its simple core performance) with simpler cores. Maybe they have a good reason to stick with ancient versions of GCC.

author: Karel
author_rank: Super Contributor
timestamp: September 01, 2020, 10:09:04 am
content: Quote from: coppice on September 01, 2020, 09:25:25 amYes, the reason is, they (Microchip) crippled GCC (specifically the optimization settings) and they charge you for the non-crippled version.