<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>LeafLabs Garden &#187; Topic: DMA Enhancements</title>
		<link>http://forums.leaflabs.com/topic.php?id=918</link>
		<description>A place to share, learn, and grow...</description>
		<language>en-US</language>
		<pubDate>Fri, 22 Jan 2016 00:08:16 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://forums.leaflabs.com/search.php</link>
		</textInput>
		<atom:link href="http://forums.leaflabs.com/rss.php?topic=918" rel="self" type="application/rss+xml" />

		<item>
			<title>kernelcode on "DMA Enhancements"</title>
			<link>http://forums.leaflabs.com/topic.php?id=918&amp;page=2#post-7853</link>
			<pubDate>Mon, 23 Jan 2012 19:38:07 +0000</pubDate>
			<dc:creator>kernelcode</dc:creator>
			<guid isPermaLink="false">7853@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Hi, I'm finding it tricky to jump into all of this development talk, having never used an Arduino and having got a Maple for a University project, but hopefully you can bear with me.&#60;/p&#62;
&#60;p&#62;Anyhow, my project involves grabbing samples from an ADC, doing some crunching and spitting them out on [some serial interface]. The requirements are such that I will almost certainly need to use DMA (and I'd like to anyway - it's so neat!) so I've started implementing some C++ wrappers for the dma.h libmaple functions, and have also implemented a (scruffy) DMA USART driver based off that. Hopefully this week I will get a DMA ADC driver going too.&#60;/p&#62;
&#60;p&#62;So my question is, how much is already implemented? I don't want to re-invent the wheel, and conversely I would really like to contribute my work back to the community (pending approval from my supervisor) if it would be useful.&#60;/p&#62;
&#60;p&#62;For an idea of where I'm at, here is my DMA class declaration:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;#include &#38;quot;dma.h&#38;quot;

class dma_object {

    private:
        dma_object( void );             ///&#38;lt; Device and Channel are req&#38;#39;d
        dma_dev *_dev;                  ///&#38;lt; DMA Device (DMA1 or DMA2)
        dma_channel _channel;           ///&#38;lt; DMA Channel to use
        uint32 _mode;                   ///&#38;lt; DMA Mode, ORed dma_mode_flags
        __io void * _m_address;         ///&#38;lt; Address in memory
        __io void * _p_address;         ///&#38;lt; Address in peripheral
        uint16 _transfers;              ///&#38;lt; Number of transfers
        dma_xfer_size _p_width;         ///&#38;lt; Data width (peripheral)
        dma_xfer_size _m_width;         ///&#38;lt; Data width (memory)
        dma_priority _priority;         ///&#38;lt; Priority (defaults to DMA_PRIORITY_LOW)
        void (*_handler)();             ///&#38;lt; irq handler
        void setup_xfer();              ///&#38;lt; Calls dma_set_... and dma_attach_interrupt

    public:
        /// Initialises DMA channel, sets some defaults
        dma_object(dma_dev * dev, dma_channel channel); 

        /// Full configuration information
        void configure( __io void * m_address, __io void * p_address,
                        dma_xfer_size m_width, dma_xfer_size p_width,
                        uint32 mode, uint16 transfers);

        inline void setMode     ( uint32 mode)
                                { _mode = mode; };
        inline void setMAddr    ( __io void* m_address )
                                { _m_address = m_address; };
        inline void setPAddr    ( __io void* p_address )
                                { _p_address = p_address; };
        inline void setTransfers( uint16 transfers )
                                { _transfers = transfers; };
        inline void setWidths   ( dma_xfer_size m_width,
                                  dma_xfer_size p_width )
                                { _m_width = m_width; _p_width = p_width; };
        inline void setPriority ( dma_priority priority)
                                { _priority = priority; };

        void enable ( void );
        void disable( void );

        void attachInterrupt( void (*handler)(void));
        void detachInterrupt( void );

};&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;This is in no way complete, or 'Wirish', and doesn't fit the coding conventions (yet) but hopefully someone can give me some input and maybe I can help out :-)&#60;/p&#62;
&#60;p&#62;-Brian
&#60;/p&#62;</description>
		</item>
		<item>
			<title>mbolivar on "DMA Enhancements"</title>
			<link>http://forums.leaflabs.com/topic.php?id=918#post-6038</link>
			<pubDate>Mon, 22 Aug 2011 15:30:03 +0000</pubDate>
			<dc:creator>mbolivar</dc:creator>
			<guid isPermaLink="false">6038@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Cool!  Sounds good; looking forward to using your code.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>robodude666 on "DMA Enhancements"</title>
			<link>http://forums.leaflabs.com/topic.php?id=918#post-6036</link>
			<pubDate>Mon, 22 Aug 2011 15:00:13 +0000</pubDate>
			<dc:creator>robodude666</dc:creator>
			<guid isPermaLink="false">6036@http://forums.leaflabs.com/</guid>
			<description>&#60;blockquote&#62;&#60;p&#62;
I personally really hate Wirish paradigms. They're so silly!
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;Sorry. I meant to say Arduino's and Wiring's paradigms are silly; not LeafLab's Wirish. I know that LeafLab's Wirish only follow those paradigms.&#60;/p&#62;
&#60;p&#62;Now.. Putting the irq cause into the wirish handlers while keeping the libmaple ones as lean as possible would probably be the best approach to it.&#60;/p&#62;
&#60;p&#62;That is also true. While ST's library does makes some sense, I did find myself referring to the RM0008 documentation to understand what EXACTLY was going on with the registers. An average arduino user would go insane from using ST's library, not that the average arduino user would be using structs, singletons, factory methods, etc. in the first place... So, point taken: KISS.&#60;/p&#62;
&#60;p&#62;Well, you've given me a lot of things to think about, and settled many of my concerns. I've started working on another project at the moment (gasp! I'm actually finishing this one.) but will start work on this class very soon.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>mbolivar on "DMA Enhancements"</title>
			<link>http://forums.leaflabs.com/topic.php?id=918#post-6031</link>
			<pubDate>Mon, 22 Aug 2011 14:25:26 +0000</pubDate>
			<dc:creator>mbolivar</dc:creator>
			<guid isPermaLink="false">6031@http://forums.leaflabs.com/</guid>
			<description>&#60;blockquote&#62;&#60;p&#62;
Would a ~100 nanosecond delay for turning off an ADC, SPI, USART, etc. really make a difference? I'd understand for people who have a task being completed very frequently that a ~100ns delay would cause very large delays cumulatively. I don't expect to receive a DMA error often, unless you're doing it wrong.
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;The error case was just a random example that I can't really back up with use cases, so I'll drop it.&#60;/p&#62;
&#60;p&#62;What I do know is that we've gotten a fair amount of feedback about IRQ handlers being slow, for instance, timer CC interrupt overhead has bitten people in the past.  Because of that, I'm wary of introducing mandatory overhead into IRQ handlers.&#60;/p&#62;
&#60;p&#62;I may well be being needlessly conservative.  If you want to do it this way, go ahead; we'll see how it plays out in practice and proceed from there.&#60;/p&#62;
&#60;p&#62;As another random devil's-advocate type suggestion, how about the Wirish DMA class automatically passing the dma_irq_cause to the user's attached handlers?  That way, using libmaple proper wouldn't incur extra ovehead unless it's wanted, but using Wirish (as usual) gets you more convenience at the cost of some performance.&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;
I got the idea of a struct/factory from the way STM has their official library. They use a struct to hold all configuration options that is passed along. It ends up being very useful and requires almost no documentation to understand what's going on.
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;We've read some of the ST code as well, and honestly, we don't like it.&#60;/p&#62;
&#60;p&#62;Using ST's struct-style libs requires an intimate knowledge of the register map in order to get anything done, so saying it &#34;requires almost no documentation to understand what's going on&#34; is only true if you don't count RM0008 as documentation.  libmaple might be close to the metal, but it's not _that_ close; if we don't provide some nicer abstractions, we might as well just use the ST libs.&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;
If you have, for example, a few SPI devices connected to SPI1 and you're using the DMA controller to communicate to it, but each device has its own set of configurations (memory address, # bytes, interrupt options, priority, etc.) you would need to set all of those over and over when repurposing the controller. Why not simply have all those settings stored in a struct that you can pass along to reconfigure the controller? Sure, you'd still have all the other wirish methods for all the knobs you want to twist, but when having to change multiple options at once you'll have an easier time doing it.
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;This is definitely desirable, but see above for why we avoid the ST style.&#60;/p&#62;
&#60;p&#62;And I don't think that having knob-twisting methods precludes initializing your peripherals with mostly-default values.  libmaple proper uses xxx_foreach() routines to get this done in C, e.g. setupTimers() in boards.cpp:&#60;/p&#62;
&#60;p&#62;&#60;a href=&#34;https://github.com/leaflabs/libmaple/blob/0.0.11/wirish/boards.cpp#L115&#34; rel=&#34;nofollow&#34;&#62;https://github.com/leaflabs/libmaple/blob/0.0.11/wirish/boards.cpp#L115&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;In C++, you can use default parameter values to get things done.  So e.g. you might have begin() call out to the knob-twisters:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;void DMAClass::begin(uint32 enabled_interrupts=(DMA_TRNS_ERR &#124; DMA_TRNS_CMPLT),
                      dma_priority priority=DMA_PRIORITY_LOW,
                      ...)
{
    this-&#38;gt;enableInterrupts(enabled_interrupts);
    this-&#38;gt;setPriority(priority);
    // .. etc.
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Users with different preferences could wrap DMAClass::begin() with a helper function of their own that reset the defaults they didn't like.&#60;/p&#62;
&#60;p&#62;It also comes down to a question of consistency.  For better or worse, the Wirish interfaces are modeled after Arduino's, with some of the bad parts removed.  Changing that makes me nervous; as time passes, we could get more and more different styles creeping in to Wirish, with the result being a library that's hard for beginners to make a mental model of.&#60;/p&#62;
&#60;p&#62;What do you think about that?&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;
The problem I was having about letting the user allocate the memory was that: what if they allocate the wrong amount? Or even worse, too little and the DMA controller starts writing into space that's not part of the allocated block? Also, would you then depend on the programmer being good to prevent any dangling pointers? (They free the allocated memory but forget to first NULL out the pointer passed to the DMA class, eep!)
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;If they allocate the wrong amount, they've got a bug.  C and C++ don't do bounds checking; c'est la vie.&#60;/p&#62;
&#60;p&#62;As far as dangling pointers go, following Wiring, we encourage a programming model where buffers are fixed-size and allocated statically.  This prevents the usual memory management issues.&#60;/p&#62;
&#60;p&#62;If someone wants to manage their memory dynamically, then, as usual in C and C++, it's up to them to do it correctly.&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;
I think things that are going to be common practices: reading ADC, SPI, USART, writing to ADC, SPI, USART, etc. should get their own subclasses (at least on a peripheral level) with these connivence methods instead of clogging up the main DMA interface with methods that may not apply to that particular object.
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;That seems like a good idea.  It'll also help partition up the documentation so people can laser in on the parts they care about.
&#60;/p&#62;