[En-Nut-Discussion] Designing Interfaces, e.g. DMA

Ulrich Prinz ulrich.prinz at googlemail.com
Mon Jul 2 22:00:46 CEST 2012

Hi Uwe,

Not only the DMA_Init is a difference, the setup is different too.

So for general compatibility and probably without any loss of memory it 
sould be possible to generalize int DMA_Init( int dmaCid).
gcc should use R0 for parameter and for return code. With CPUs only 
supporting a single controller, R0 is used for return code only.

If you add a check
if (dmaCid > DMA_MAX_CID)
   return -1;

there will be no unsused compiler warning.

The second things is with the handling of a DMA transfer.

There is no general solution without getting more and more software 
overhead or writing extremely nifty #define things.

I love the idea of a OSI handling of anything that runs in packets.
So register / reserve a packet, fill in what you know, do a function 
call with the packet and get back what you need ( or an error :) )

So doing a
   dma_call_t *dmapack;
   dmapack = NutHeapAllocClear( sizeof(...

   dmapack->cmd = DMA_CMD_INIT;
   dmapack->cid = 0;
   dmapack->src = source_address;
   dmapack->dst = my_peripheral;
   dmapack->mode = DMA_M_RAM2PER | DMA_M_AUTOREP | DMA_M_....

   DMA_Command( dmapack);

   dmapack->cmd = DMA_CMD_RUN;

   DMA_Command( dmapack);


This is a pretty thing as the handling functions can live without almost 
any local RAM or stack. This keeps the threads stacks flat.

On the other hand, I see that it is more newbie safe to to write 
functions in the way call( where, what, how) and up we go. But with 
respect to the fact, that DMA is nothing for newbies...

I did not check why LPC and STM code is different in that DMA thing. I 
tried to automate a lot of things, i.E. you do not have to tell the 
system if source or targets are periphery or memory and so on.

But it is always difficult. It might work in a unified way for STM and 
LPC today but a new CPU will break it up tomorrow.

I think the OSI way is more efficient, as you keep the functions for all 
chips identical but add or remove only features and commands in the 
struct. Like the USART where some support BLOCK_MODE and some others don't.

Ah, for CAN:
I did only a very simple setup interface for it as we have a commercial 
stack on top. Sorry.

Best regards

Am 29.06.2012 11:20, schrieb Uwe Bonnes:
> Hello,
> how is the ethernut strategy to implement functionality like DMA? While
> there is some common functionality in the families that have DMA, a lot is
> different too. E.g. for setup with NXP, Ole has :
> void Lpc17xxGPDMA_Init(void);
> int  Lpc17xxGPDMA_Setup(gpdma_channel_cfg_t *ch_config);
> int  Lpc17xxGPDMA_IntGetStatus(gpdma_status_t type, uint8_t ch);
> void Lpc17xxGPDMA_ClearIntPending(gpdma_state_clear_t type, uint8_t ch);
> void Lpc17xxGPDMA_ChannelCmd(uint8_t ch, int enabled);
> while Ulrich for STM did:
> void DMA_Setup( uint8_t ch, void* dst, void* src, uint16_t length, uint32_t flags);
> void DMA_Enable(uint8_t ch);
> void DMA_Disable(uint8_t ch);
> void DMA_Init(void);
> void DMA_IrqMask( uint8_t ch, uint32_t mask, uint8_t ena);
> void DMA_ClearFlag( uint8_t ch, uint32_t flags);
> uint32_t DMA_GetFlag( uint8_t ch);
> For STM void DMA_Init(void) should perhaps be DMA_Init(uint8_t ch), as
> otherwise in parts with two independant DMA controllers, both would be
> switched on and consume current, even when only one is needed.
> Should every architecture implement it's own incarnation or should we tailor
> a common feature set?
> Same holds for the ADC/CAN etc.
> Bye

More information about the En-Nut-Discussion mailing list