DMA memcpy

244 views
Skip to first unread message

g3gg0

unread,
Nov 27, 2011, 4:31:36 AM11/27/11
to Magic Lantern firmware development
Hi there,

i stumbled around in the original firmware and came across the DMA
channels.
There seems to be a pair of dma channels reserved for graphics usage.

600D v1.0.1
0xF075CB8 int __cdecl dma_memcpy(unsigned __int8 *dest, unsigned
__int8 *src, int length, void *callback);

From task context you can call this function to copy specified data
around and after it is done, your callback function gets called.
I tried it with bmp_idle_copy and it works fine. It should be slightly
better than LDR/STR memcpy.
The big advantage is that you can do your memcpy asynchronously.

But beware not to start another dma_memcpy within the callback
handler.
When testing, it conflicted with liveview after some time. I guess the
reason is the semaphore at dword_89A8 that
gets locked by liveview (sub_FF278B18) and only is released in its
callback handler (sub_FF27818C).
If we are locking DMA all the time and block the dma again during
interrupt (i guess), it never gets unlocked.

Is there some reason why DMA is not used yet?

BR,
g3gg0

arm.indy

unread,
Nov 27, 2011, 7:55:14 AM11/27/11
to Magic Lantern firmware development
Hi g3gg0,

I suppose the reason is that we do not know how it works...
If you can explain more on this, maybe it can be used within Magic
Lantern.

what are those DMA channels and how does it work ?

Kind regards,

Indy

g3gg0

unread,
Nov 27, 2011, 8:46:00 AM11/27/11
to Magic Lantern firmware development
Hi,

DMA channels are hardware blocks that do not more than loading data
from a memory bus and writing it again.
E.g. you set up "copy 8192 byte from address a to b".
The DMA controller does that copy operation without any CPU
interaction.

This means you have a copy operation that is a) expensive to set up
but b) is very fast and c) causes no CPU load.
When doing memcpy, you are faster than DMA memcpy if you copy maybe up
to 100 byte.

For graphics copy operation i would prefer using the DMA controller.
We paint the menu in some backbuffer and when done, fire the DMA
memcpy and return to the next task.
Now the menu gets displayed (written into VRAM) while the CPU alreay
executes the next tasks.

Less flickering and less CPU load.

Just give it a try, its not much more complicated than memcpy ;)

example: (bmp.c)

volatile int bmp_dma_done = 0;
void bmp_dma_cb() { bmp_dma_done = 1; }

void bmp_idle_copy(int direction)
{
uint8_t* real = bmp_vram_real();
uint8_t* idle = bmp_vram_idle();

bmp_dma_done = 0;
if(direction)
dma_memcpy(real, idle, BMP_HEIGHT * BMPPITCH, bmp_dma_cb);
else
dma_memcpy(idle, real, BMP_HEIGHT * BMPPITCH, bmp_dma_cb);

/* actively wait for DMA being finished, the other code needs to
be touched to run asynchronously */
while(bmp_dma_done == 0);
}

This code just uses DMA memcpy for transferring the idle buffer into
vram buffer.
I think it should already be a speedup, although we are waiting
actively for DMA to finish.
On modern CPUs (not our CPU) have seen that using DMA speeds up memcpy
by factor ~2.5.

BR,
g3gg0

arm.indy

unread,
Nov 27, 2011, 9:43:22 AM11/27/11
to Magic Lantern firmware development
Thanks g3gg0 !

Which DMA channels are reserved for graphics ?
do you see any other usage of DMA ?

Indy

arm.indy

unread,
Nov 27, 2011, 10:29:39 AM11/27/11
to Magic Lantern firmware development
and what are the roles of registers
0xC0A10004 (base address?), 0xC0A10008 (status?), 0xC0A1000c,
0xC0A10010 (in interrupt handler) ?

I have started a wiki page: http://magiclantern.wikia.com/wiki/DMA

Indy

g3gg0

unread,
Nov 27, 2011, 11:05:04 AM11/27/11
to Magic Lantern firmware development
Well, I am not aware of the register details on this system.

But when looking at the code, yes 0xC0A10000 seems to be the DMA
controller base address.

0xC0A10000 DMA channel 0
+ 0x04 [32] unknown, written with 0x00 on DMA setup
+ 0x08 [32] control bits
--------------1----------------1 written when
---------------1---------------- gets set when (delta(source,dest)
& 0x1F) != 0
maybe some cache line issues
+ 0x10 [32] unknown, written with 0x00 on DMA setup
+ 0x14 [32] unknown, written with 0x07 on DMA setup (data
width?)
+ 0x18 [32] source address
+ 0x1C [32] destination address
+ 0x20 [32] transfer count (ignoring 2 LSB)


0xC0A11000 DMA channel 1 (see above)

g3gg0

unread,
Nov 27, 2011, 11:07:06 AM11/27/11
to Magic Lantern firmware development
I added the reversing results to the wiki site you posted

BR,
g3gg0

g3gg0

unread,
Nov 27, 2011, 11:28:07 AM11/27/11
to Magic Lantern firmware development

Out of the DMA context we maybe should also have a look at

int irq_register(char *name, unsigned int id, void *handler, void
*ctx)
which is at 0xFF1F5828 on 600D v1.0.1

its used to set up an interrupt handler like the DMA handler (ID =
0xA2 + channel#)


here a (auto generated) .idc for v1.0.1 on 600D for marking all calls
to irq_register.
there might be some interesting stuff to do with :)

#include <idc.idc>
static main()
{
MakeStr ( 0xFF01BFBC, BADADDR );
MakeRptCmt ( 0xFF01BDB0, "R1: 0x0056 - R0: VIDEODET - R2:
0xFF01BFA0 - R3: 0x0000 - " );
MakeStr ( 0xFF01BFCC, BADADDR );
MakeRptCmt ( 0xFF01BDC4, "R1: 0x0044 - R0: USBDET - R2: 0xFF01BFA0
- R3: 0x0000 - " );
MakeStr ( 0xFF01BFD8, BADADDR );
MakeRptCmt ( 0xFF01BDD8, "R1: 0x0054 - R0: HDMIDET - R2:
0xFF01BFA0 - R3: 0x0000 - " );
MakeStr ( 0xFF01BFE0, BADADDR );
MakeRptCmt ( 0xFF01BDEC, "R1: 0x0047 - R0: MICDET - R2: 0xFF01B428
- R3: 0x0000 - " );
MakeStr ( 0xFF01BFEC, BADADDR );
MakeRptCmt ( 0xFF01BE00, "R1: 0x0057 - R0: VARISW3 - R2:
0xFF01B428 - R3: 0x0000 - " );
MakeStr ( 0xFF0353F8, BADADDR );
MakeRptCmt ( 0xFF035268, "R1: 0x00C9 - R0: Fencing_A - R2: 0x0001
- R3: 0x0000 - " );
MakeStr ( 0xFF035780, BADADDR );
MakeRptCmt ( 0xFF0355D0, "R1: 0x00D0 - R0: Fencing_B - R2: 0x0000
- R3: 0x0000 - " );
MakeFunction ( 0xFF035798, BADADDR );
MakeStr ( 0xFF0359AC, BADADDR );
MakeRptCmt ( 0xFF03582C, "R1: 0x00D1 - R0: Fencing_C - R2:
0xFF034A18 - R3: 0x0000 - " );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF05564C, "R1: 0x002C - R0: - R2: 0xFF055284 - R3:
0x0000 - " );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF055660, "R1: 0x002D - R0: - R2: 0xFF055284 - R3:
0x0000 - " );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF055674, "R1: 0x0042 - R0: - R2: 0xFF055284 - R3:
0x0000 - " );
MakeFunction ( 0xFF0560EC, BADADDR );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF056160, "R1: 0x0000 - R0: - R2: 0xFF0560C0 - R3:
0xFFFFFFFF - " );
MakeFunction ( 0xFF066930, BADADDR );
MakeFunction ( 0xFF066908, BADADDR );
MakeFunction ( 0xFF0668D8, BADADDR );
MakeStr ( 0xFF066B8C, BADADDR );
MakeRptCmt ( 0xFF066970, "R1: 0x0068 - R0: - R2: 0xFF066B90 - R3:
0x0000 - " );
MakeFunction ( 0xFF066930, BADADDR );
MakeFunction ( 0xFF066908, BADADDR );
MakeStr ( 0xFF066BAC, BADADDR );
MakeRptCmt ( 0xFF066984, "R1: 0x0069 - R0: Pb error - R2:
0xFF066B90 - R3: 0x0000 - " );
MakeFunction ( 0xFF06C358, BADADDR );
MakeStr ( 0xFF06C458, BADADDR );
MakeRptCmt ( 0xFF06C3B4, "R1: 0x0055 - R0: REMIN_ISR - R2:
0xFF06C1EC - R3: 0x0000 - " );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF06D3C4, "R1: 0x0040 - R0: - R2: 0xFFFFFFFF - R3:
0x0000 - " );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF06D3D8, "R1: 0x0002 - R0: - R2: 0xFF06D0AC - R3:
0x0000 - " );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF06D3EC, "R1: 0x0001 - R0: - R2: 0xFF06D190 - R3:
0x0000 - " );
MakeStr ( 0xFF070644, BADADDR );
MakeRptCmt ( 0xFF070450, "R1: 0x0000 - R0: OCH_SPx - R2:
0xFF070288 - R3: 0xFFFFFFFF - " );
MakeStr ( 0xFF07064C, BADADDR );
MakeRptCmt ( 0xFF070464, "R1: 0x0000 - R0: OCHxEPx - R2:
0xFF0702EC - R3: 0xFFFFFFFF - " );
MakeStr ( 0xFF070654, BADADDR );
MakeRptCmt ( 0xFF070484, "R1: 0x0010 - R0: OC4_14 - R2: 0xFF0700A4
- R3: 0x0000 - " );
MakeStr ( 0xFF07065C, BADADDR );
MakeRptCmt ( 0xFF07049C, "R1: 0x0010 - R0: ICAPCHx - R2:
0xFF070350 - R3: 0x0000 - " );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF074DCC, "R1: 0xFFFFFFFF - R0: - R2: 0xFF074C64 -
R3: 0xFFFFFFFF - " );
MakeStr ( 0xFF075AB0, BADADDR );
MakeRptCmt ( 0xFF0759EC, "R1: 0x002F - R0: BLTDMA - R2: 0xFF075908
- R3: 0xFFFFFFFF - " );
MakeStr ( 0xFF075AB0, BADADDR );
MakeRptCmt ( 0xFF075BA4, "R1: 0x002F - R0: BLTDMA - R2: 0xFF075908
- R3: 0xFFFFFFFF - " );
MakeStr ( 0xFF075AB0, BADADDR );
MakeRptCmt ( 0xFF075D8C, "R1: 0x002F - R0: BLTDMA - R2: 0xFF075C3C
- R3: 0xFFFFFFFF - " );
MakeStr ( 0xFF075AB0, BADADDR );
MakeRptCmt ( 0xFF075F1C, "R1: 0x002F - R0: BLTDMA - R2: 0xFF075C3C
- R3: 0xFFFFFFFF - " );
MakeStr ( 0x00000007, BADADDR );
MakeRptCmt ( 0xFF0760D0, "R1: 0x002F - R0: - R2: 0xFF075F90 - R3:
0xFFFFFFFF - " );
MakeStr ( 0xFF079F04, BADADDR );
MakeRptCmt ( 0xFF079DA8, "R1: 0x009C - R0: SEQ - R2: 0xFF079C44 -
R3: 0x0000 - " );
MakeStr ( 0xFF1C3078, BADADDR );
MakeRptCmt ( 0xFF1C2DB0, "R1: 0x0052 - R0: IMGPOWDET - R2:
0xFF1C2D00 - R3: 0x0000 - " );
MakeStr ( 0xFF1D248C, BADADDR );
MakeRptCmt ( 0xFF1D229C, "R1: 0x007B - R0: DiUSB20Hal - R2:
0xFF1D1F58 - R3: 0x0000 - " );
MakeFunction ( 0xFF1DB44C, BADADDR );
MakeStr ( 0xFF1DB70C, BADADDR );
MakeRptCmt ( 0xFF1DB4E0, "R1: 0x0014 - R0: MREQ_ISR - R2:
0xFF1DB324 - R3: 0x0000 - " );
MakeStr ( 0xFF1DB718, BADADDR );
MakeRptCmt ( 0xFF1DB4F4, "R1: 0x0036 - R0: SIO3_ISR - R2:
0xFF1DB3B4 - R3: 0x0000 - " );
MakeFunction ( 0xFF1E033C, BADADDR );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF1E03A8, "R1: 0x0000 - R0: - R2: 0xFFFFFFFF - R3:
0xFF1DFF84 - " );
MakeFunction ( 0xFF1E246C, BADADDR );
MakeStr ( 0xFF1E2684, BADADDR );
MakeRptCmt ( 0xFF1E24E8, "R1: 0x0064 - R0: JpCoreIntrHandler - R2:
0xFF1E2140 - R3: 0x0000 - " );
MakeFunction ( 0xFF1E2EF8, BADADDR );
MakeStr ( 0xFF1E3170, BADADDR );
MakeRptCmt ( 0xFF1E2F90, "R1: 0x00A3 - R0: JpCore2IntrHandler -
R2: 0xFF1E2CD8 - R3: 0x0000 - " );
MakeFunction ( 0xFF2DCBC0, BADADDR );
MakeFunction ( 0xFF2DCB8C, BADADDR );
MakeFunction ( 0xFF2DCB64, BADADDR );
MakeStr ( 0xFF2DCD48, BADADDR );
MakeRptCmt ( 0xFF2DCC00, "R1: 0x0051 - R0: CAPREADY - R2:
0xFF2DCB8C - R3: 0x0000 - " );
MakeFunction ( 0xFF2DE790, BADADDR );
MakeStr ( 0xFF2DE8B4, BADADDR );
MakeRptCmt ( 0xFF2DE7F0, "R1: 0x006A - R0: HEAD1 - R2: 0xFF2DE790
- R3: 0x0000 - " );
MakeFunction ( 0xFF2DEB74, BADADDR );
MakeStr ( 0xFF2DEC54, BADADDR );
MakeRptCmt ( 0xFF2DEB90, "R1: 0x006C - R0: HEADERROR - R2:
0xFF2DE8E4 - R3: 0x0000 - " );
MakeStr ( 0xFF2FE9A8, BADADDR );
MakeRptCmt ( 0xFF2FE780, "R1: 0x00D1 - R0: Fencing_C - R2:
0xFF2FE52C - R3: 0x0000 - " );
MakeStr ( 0xFF2FEBCC, BADADDR );
MakeRptCmt ( 0xFF2FEB60, "R1: 0x00D0 - R0: Fencing_B - R2:
0xFF2FEBA8 - R3: 0x0000 - " );
MakeStr ( 0x00000001, BADADDR );
MakeRptCmt ( 0xFF34C28C, "R1: 0x004F - R0: - R2: 0xFF34C218 - R3:
0x0000 - " );
MakeStr ( 0x00000001, BADADDR );
MakeRptCmt ( 0xFF34C2A0, "R1: 0x004F - R0: - R2: 0xFF34C1C8 - R3:
0x0000 - " );
MakeFunction ( 0xFF34C740, BADADDR );
MakeStr ( 0x00000001, BADADDR );
MakeRptCmt ( 0xFF34C798, "R1: 0x004F - R0: - R2: 0xFF34C4A8 - R3:
0x0000 - " );
MakeFunction ( 0xFF3B9464, BADADDR );
MakeStr ( 0x00000037, BADADDR );
MakeRptCmt ( 0xFF3B94E0, "R1: 0x0006 - R0: - R2: 0xFF3B9594 - R3:
0x0000 - " );
MakeFunction ( 0xFF3D08A4, BADADDR );
MakeFunction ( 0xFF3D087C, BADADDR );
MakeFunction ( 0xFF3D0824, BADADDR );
MakeStr ( 0xFF3D0A08, BADADDR );
MakeRptCmt ( 0xFF3D08C0, "R1: 0x0065 - R0: ADKIZDET - R2:
0xFF3D087C - R3: 0x0000 - " );
MakeFunction ( 0xFF3D17CC, BADADDR );
MakeFunction ( 0xFF3D17AC, BADADDR );
MakeStr ( 0xFF3D19CC, BADADDR );
MakeRptCmt ( 0xFF3D1810, "R1: 0x0052 - R0: IMGPOWDET - R2:
0xFF3D19B0 - R3: 0x0000 - " );
MakeFunction ( 0xFF3D2880, BADADDR );
MakeStr ( 0xFF3D29B0, BADADDR );
MakeRptCmt ( 0xFF3D28CC, "R1: 0x006A - R0: HEAD1 - R2: 0xFF3D2880
- R3: 0x0000 - " );
MakeFunction ( 0xFF3D29C0, BADADDR );
MakeStr ( 0xFF3D2BF0, BADADDR );
MakeRptCmt ( 0xFF3D2A0C, "R1: 0x006B - R0: HEAD2 - R2: 0xFF3D29C0
- R3: 0x0000 - " );
MakeFunction ( 0xFF3D2A78, BADADDR );
MakeFunction ( 0xFF3D2A54, BADADDR );
MakeStr ( 0xFF3D2C08, BADADDR );
MakeRptCmt ( 0xFF3D2AC4, "R1: 0x00D9 - R0: HEAD3 - R2: 0xFF3D2A78
- R3: 0x0000 - " );
MakeFunction ( 0xFF3D2B30, BADADDR );
MakeFunction ( 0xFF3D2B0C, BADADDR );
MakeStr ( 0xFF3D2C20, BADADDR );
MakeRptCmt ( 0xFF3D2B7C, "R1: 0x00E0 - R0: HEAD4 - R2: 0xFF3D2B30
- R3: 0x0000 - " );
MakeFunction ( 0xFF3D2E64, BADADDR );
MakeStr ( 0xFF3D2F44, BADADDR );
MakeRptCmt ( 0xFF3D2E80, "R1: 0x006C - R0: HEADERROR - R2:
0xFF3D2C30 - R3: 0x0000 - " );
MakeFunction ( 0xFF3DCCA8, BADADDR );
MakeStr ( 0xFF3DCE34, BADADDR );
MakeRptCmt ( 0xFF3DCD34, "R1: 0x00D8 - R0: Kaiser - R2: 0xFF3DCC78
- R3: 0x0000 - " );
MakeFunction ( 0xFF42705C, BADADDR );
MakeFunction ( 0xFF427038, BADADDR );
MakeFunction ( 0xFF42701C, BADADDR );
MakeStr ( 0xFF42726C, BADADDR );
MakeRptCmt ( 0xFF427098, "R1: 0x0060 - R0: CompleteReadOperation -
R2: 0xFF42701C - R3: 0x0000 - " );
MakeFunction ( 0xFF429DCC, BADADDR );
MakeStr ( 0x00000010, BADADDR );
MakeRptCmt ( 0xFF429DE8, "R1: 0x0065 - R0: - R2: 0xFF42A0CC - R3:
0x0000 - " );
MakeFunction ( 0xFF42A358, BADADDR );
MakeFunction ( 0xFF42A2F4, BADADDR );
MakeStr ( 0xFF42A444, BADADDR );
MakeRptCmt ( 0xFF42A374, "R1: 0x0065 - R0: ADMERG - R2: 0xFF42A2F4
- R3: 0x0000 - " );
MakeFunction ( 0xFF43B778, BADADDR );
MakeStr ( 0xFF43B9A8, BADADDR );
MakeRptCmt ( 0xFF43B7EC, "R1: 0x0003 - R0: WDTInterrupt - R2:
0xFF43B740 - R3: 0x0000 - " );
MakeFunction ( 0xFF4E0B9C, BADADDR );
MakeStr ( 0x00000002, BADADDR );
MakeRptCmt ( 0xFF4E0BBC, "R1: 0xFFFFFFFF - R0: - R2: 0xFFFFFFFF -
R3: 0x0000 - " );
MakeFunction ( 0xFF4E0B9C, BADADDR );
MakeStr ( 0x00000002, BADADDR );
MakeRptCmt ( 0xFF4E0BE4, "R1: 0xFFFFFFFF - R0: - R2: 0xFFFFFFFF -
R3: 0x0000 - " );
MakeFunction ( 0xFF4ED84C, BADADDR );
MakeFunction ( 0xFF4ED81C, BADADDR );
MakeFunction ( 0xFF4ED7F4, BADADDR );
MakeStr ( 0xFF4EDC50, BADADDR );
MakeRptCmt ( 0xFF4ED874, "R1: 0x0066 - R0: WbInteg - R2:
0xFF4ED7F4 - R3: 0x0000 - " );
MakeFunction ( 0xFF4EFF84, BADADDR );
MakeFunction ( 0xFF4EFF58, BADADDR );
MakeStr ( 0xFF4F0104, BADADDR );
MakeRptCmt ( 0xFF4EFFCC, "R1: 0x0061 - R0: AfComplete - R2:
0xFF4EFDD4 - R3: 0x0000 - " );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF4F2A08, "R1: 0x0001 - R0: - R2: 0xFFFFFFFF - R3:
0x0000 - " );
MakeStr ( 0x00000001, BADADDR );
MakeRptCmt ( 0xFF4F8770, "R1: 0x0001 - R0: - R2: 0xFF4F7DD0 - R3:
0x0000 - " );
MakeFunction ( 0xFF52AF18, BADADDR );
MakeStr ( 0x00000000, BADADDR );
MakeRptCmt ( 0xFF52AF7C, "R1: 0x0000 - R0: - R2: 0xFF52AEB4 - R3:
0x0000 - " );
MakeFunction ( 0xFF52BEF8, BADADDR );
MakeFunction ( 0xFF52BEC4, BADADDR );
MakeStr ( 0x00000001, BADADDR );
MakeRptCmt ( 0xFF52BF2C, "R1: 0x0000 - R0: - R2: 0xFF52BEC4 - R3:
0x0000 - " );
}

arm.indy

unread,
Nov 27, 2011, 1:18:55 PM11/27/11
to Magic Lantern firmware development
FYI, AJ and Alex already worked on this,
http://groups.google.com/group/ml-devel/browse_frm/thread/5dc5f73a2be922d4/89e2cef9a36aacf7
and even hijacked some of them
to listen answer from Tx19 MPU about AF micro ajustment
http://groups.google.com/group/ml-devel/browse_frm/thread/dba2ba70e99f64ab/43009e5196efce2b?lnk=gst&q=sio3#43009e5196efce2b

about Tx19: http://magiclantern.wikia.com/wiki/Tx19a

Indy

>     MakeRptCmt ( 0xFF4ED874, "R1: 0x0066 - R0:...
>
> read more »

arm.indy

unread,
Nov 27, 2011, 4:42:54 PM11/27/11
to Magic Lantern firmware development
great! thanks!

these are the very first lines of the DIGIC programming manual ;-)

Indy

g3gg0

unread,
Nov 27, 2011, 7:01:58 PM11/27/11
to Magic Lantern firmware development
does magic lantern already support memory R/W via PTP?
this will help a lot.

arm.indy

unread,
Nov 28, 2011, 1:41:35 AM11/28/11
to Magic Lantern firmware development

Alex

unread,
Nov 28, 2011, 4:25:23 AM11/28/11
to ml-d...@googlegroups.com
See also:
http://magiclantern.wikia.com/wiki/PTP-CHDK

and in ML source code: ptp.c and ptp-chdk.h.

Reading memory and file uploading/downloading already works. Writing
memory is commented out (I didn't try it, but should work).

> --
> http://magiclantern.wikia.com/
>
> To post to this group, send email to ml-d...@googlegroups.com
> To unsubscribe from this group, send email to ml-devel+u...@googlegroups.com
> For more options, visit this group at http://groups.google.com/group/ml-devel?hl=en

Reply all
Reply to author
Forward
0 new messages