All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] PPC405: DMA-Problem with OCM (interrupt-example)
@ 2007-01-17 22:33 Niklaus Giger
  2007-01-18  0:26 ` Jan Kiszka
  2007-01-18  8:31 ` Wolfgang Grandegger
  0 siblings, 2 replies; 8+ messages in thread
From: Niklaus Giger @ 2007-01-17 22:33 UTC (permalink / raw)
  To: xenomai

[-- Attachment #1: Type: text/plain, Size: 1608 bytes --]

Hi

I tried to simply an example program how to use interrupts
with Xenomai (see attached Makefile & dma_4xx_int_module.c).

The interrupt part of the example works, but the DMA transfer (memory to
memory) using the OnChipMemory fails. I think I must somewhere specify that 
the src/dst adressed should not be cached, but I do not know how to do it.
(I tried to use virt_to_phys and virt_to_bus but failed miserably.)
The OCM is initialised in my board specific __init by calling:
>         io_block_mapping(mfdcr(DCRN_OCMDSARC), mfdcr(DCRN_OCMDSARC),
> 4*1024, _PAGE_IO);

A simple insmod/rmmod cycle gives me the following output:

>                      init_module: SRC f4000000 DST f4000103
>                      init_module: residue 111 status 0xa00f100
>              xenomai_irq_handler: IRQ  8 uipr 0xffffff87 uier 0x003f0000
> uisr 0xc0809807 xenomai_irq_handler: residue 0 status 0x1a00f000
> src at f4000000 is Could we use a DMA + interrupt to copy a string?
> dst at f4000103 is Should be overwritten.
>                   cleanup_module: dma_ch.control 0x0 0
>                   cleanup_module: IRQ  8 uipr 0xffffff87 uier 0x003f0000
> uisr 0xc0009807 cleanup_module: residue 0 status 0x1a00f000
> src at f4000000 is Could we use a DMA + interrupt to copy a string?
> dst at f4000103 is Should be overwritten.

Does anybody have a clue?

If this question is off topic, which mailing list would you reccomend?
(http://ozlabs.org/pipermail/linuxppc-embedded/ ??)

Is the example code otherwise good enough to be accepted as an example how to 
attach a interrupt?

Best regards
-- 
Niklaus Giger

[-- Attachment #2: Makefile.zip --]
[-- Type: application/x-zip, Size: 799 bytes --]

PK\x03\x04\x14\0\0\0\b\0!º16&\x01&p¤\x02\0\0Ô\x04\0\0\b\0\0\0Makefile}Sao›0\x10ý\ÿŠ[šJ!
°nÕ¤Qñ\x12Úe!¡‚T«4Mˆ€)^ŒM1l©¦ý÷Ù„,‰¦\x0e	°ÏwïÞÝ=ŸŸ«\aÜ`y;»{\bÕ,XBg;Ge›­¨MQ§æº%4Ó‹´}¯¿3>\x18—\x1fK4õ¢Õt\x16ÚfÁKlÊ3³æ¼É…ÉȆ&­ˆwžh\x1e…î\x11\x14%¬Ý\x1eP\x13ºŸ,»ªRä†A\x14Ån°¸Ÿù^gН¶[\x1dÝ;+é±KëÆÄ4Û˜WñÛ\x0erM˜Õ-(O\x13zØv\vùA\vË\x1eŽD)…êg¦!¤
ö‰h€çT\x15%iÒ\x10Î\x044\x1cÖ\x18ºRÑ£·\fd\_£ÖAn1ãeB:€%o°¥"ø\x0f\×$ÃÐ\x14\x18\x04Nê´€*i
ÈyÝÙT”žr–“'\x10iMªf\x02­À0(“\r\x06•g×}Û0Œ\x01:¥Wò¬¥ø”Ù"˜>ø^\x046de¢\x1a\x14\x13ÖÄ;Oô\x1fn^[\3LAð¶NqGñ˜‡\x1aRÏ`7~˜{áÒóa—\x0en\x1efþ\x14FŒCZ$ì	CŸ[Rã\f\x18¯Ë„Ò\x17m¯^[’3ü\f£á¨gªMdÓƒ›Ï\x11¨Ç²aøKf\x17íZÖx1\vƒOààü^[¹¾ç,åö_Wãb|êzÿe
\x7fQû!“\x1c¾Â`8”g\x03xcÃ`\0ß®U\a\x18à´àН\\x03¦²v)ˆkÈI/Šù®CRšˆ¯¿ë%À\x11¸*@CÞã*tb÷Öwî"i×gÑêœf\x12–Ò6Ã{À«'fÅ\x05ÙJ@g:ídzYÒ™KÑwÃ8¹\bR…'{\r@]\x19iV?\r”L\x03\rt\x17úŒ°–…\x06êÚÈ•úi¯óA¨\x17™…κÖ*\x1eÚ^y\b\x11&\x1a9^ëlo9öš-£•ãû±4Ä}ºýÙ#Ä=\0B
å\0ƒRŠ\x13fuYCÉVVÙÏ]ƒ±‘–™ürùnÔG\x06\x19),ºÐ±!^J)l±ÔC0š²\x1a#„YFrô\aPK\x01\x02\x14\x03\x14\0\0\0\b\0!º16&\x01&p¤\x02\0\0Ô\x04\0\0\b\0	\0\0\0\0\0\0\0\0\0¤\0\0\0\0MakefileUT\x05\0\a^ ®EPK\x05\x06\0\0\0\0\x01\0\x01\0?\0\0\0Ê\x02\0\0\0\0

[-- Attachment #3: dma_4xx_int_module.c.zip --]
[-- Type: application/x-zip, Size: 1915 bytes --]

PK\x03\x04\x14\0\0\0\b\0\x03¼16—¿»Hè\x06\0\02\x11\0\0\x14\0\0\0dma_4xx_int_module.cÅVmsÚH\x12þŒ~E\x1f[N	¯‚±ÙÔå–}#\x18;TÙ˜\x13P¾ÜfK%K\x03ÌFÌèF#c6åÿ¾Ý3\x12 àœ|تÅ/HÓïÝOwÏÙ)œÂ½âZ3\x01\x0fk\x18òOI˜gpÍçLÁ\x0f¾6çôúË’-\x1f˜jβYSªùO\x0eœâ/L\x16<ƒTɹ
—€3Å\x18dr¦W¡b\x1dXË\x1c¢P€b1Ï´â\x0f¹fÀ5„">“Š\x14,eÌgk:ËEŒVõ‚fj™œ™—ëá\x14®™`*L`”?$<‚^[\x1e1‘1\b3ҐÒa¶`1…@\x12Wäøð\x01®$*\x0e5—¢\x03Œ#]Á#S\x19¾ÃEaƒ´\x14:=
ÜP“ç
dJr\rtw\rI¨·¢Íÿ\x13þ6Ê\x18¸0Þ,dŠ\x11-P%ƸâI\x02\x0f\fòŒÍòÄ#\x15È\f÷ƒÉû»é\x04ºÃ\x0fpßõýîpò¡ƒÌz!‘Ê\x1e™UÅ—iÂQ3Æ¥B¡×è>i¸íû½÷(Ò}7¸\x19L>P\x04WƒÉ°?\x1eÃ՝\x0f]\x18uýÉ 7½éú0šú£»q¿	0f¬Œý…\x14ÏPÙRb\x1ac¦Cždeà\x1f°°\x19z—İ\b\x1f\x19\x168bü\x11}\v!’éúËÅ#%a"ÅÜ„‰ÌÛDv€Ï@HíÁ
±‰^Êò’ø¶²\x1e\fDÔôàÍ¿`Â0I\fFI\x181x\rãœ4´Û-\x0fÞÉL\x13ëm\x17Z\x17ççç¯ÏÛ­\x7fz0\x1dw‹ þÂÏ.<ð\x17;€=…Ʊ…\a<6°\x10þÄ\†\x1c>1%XB͐#ÏjÁ£\x05æUÄ	CaÒôþ\x1eñ„\0Tyª›p'`4ê}÷ô\x04Ù:Ó\f›eÅLŸ!®L®¤ˆ\x16<…KŒ\x15µ\0ö®Tk
\x13î\rø\f%B\vdµm\bï\x18åõ\x1fè3+ݱð/M‘È2Ï4á7Œ4\x7f\f	å\x04\x10S<Í2mcf›`\v„¬¤ú„.™6"e­7ð\x10fÔ°2T±\af\x0e„kÒ›d\x12
“ß=‹(€5ÓF9‹^[E¡Î\x1cç^[.¢$\x19üp‘?qÁusñÓÁ¹Íh•\x12f˳40¦ ^†Uš@<=2T§ÕQ‚æKf(ÎíÝåô¦\x1f\öÇ=\x7f0š\fî†n}›©ö¶\Ø:KYotJ‰î\x14›Ýwë/×\x1dö›A¯?\x1c÷Ýúõ膎L£+\x11ø“`0œødG\x05òá÷ŽóMÌf\˜Ú\x06C\x1fÚ\x0e’€«ÿÁð¶\x03g§Dx½ëXBÜeº[o®GÊæ¶Ð3é'Áxâ\x0f†×\0õž-¥…OhÐðíŽ.\x04µiü\x10h\x02ŠùÏõcz. >¶˜ÀbK\x1c¦+»}š[nË\x18Œ\aÿíÃùÅ[ÇA˜¢_c¿×)\x1e/Ç“m\x1a°TÅ Z\x04\x1aÒ€pÐÙ†€\0\\x05˜\x02\x17ÿ\x1aPû\3ŸN-E\x1fõ'·~ҾȾ‡ÿo8¹ˆ!ç©‚ÖÓIëí\x13>³ç¬|þ(ê\x1e)¨\x05ÁÕtØ£º\aGiö T^[ÎâH¹—=\x7f\x18L\a½`仸Õj4<Ø£ô7”crã’Úè\x1cu[±ŒÇ9ƒ“\x18(^[¸¹ÑGãaÅ9ëSø9Ó&_…¬kÁ‚ökGÙ¬^÷ЃLE€;í$¥ùv’}\x141N†ÊAÝ\x03×\x16¬Å³\x01Ò\x03¼Â\x02þÚúmóÐèÀ³ã8’Ç@6±\x15\x02-éË5g§hË\x03ûˆV<¼)d|.ÌŠE\x1031×\v\x0f•×*ç\bÓ`\x03φóÙ©Ñ)†íÐê85TŸ1í–.¾²Øñ ã\x7f09sí+V¬…=W³oÍT&!\x02v]¨(OW<Æ\x15\x06x:º\x0fÞv\x1c¨Y3E.‰©À¨\x19¸EÎ1þÂ\bªÂç¢P\x03>S\r*UÞ“Æ\x10t®\x04\x15ý„®<8\x1aqÂd”yÊ9å¡
MTë•Y\x02Ì\x1f™{vª.F‰Ú-w\x01ŠŠ_pàØQYtÊ”þÀ‡Âl!”\x15øÂùÌ6ù oœzýàöÖ$}ËŠ\b\bÂ8V^[V<ØcÁȪ,E¨{\x06#¼4è\rMË\x0e^[\x13áCˆs/	U8™2U2¸\x15ܲí¨x\x06–àÜ<\x10Ã\vãËr/—€‰³£\x1a\b\x1a[œ¤8ÉlY\x0eæV%¬\x02+Õ)€Â<]Ð\r.08/³Þ=o\x061uד½ÎÐÄ\rìõE¹¸\x0eò\bI‚\x16\x15œÒ\x7fӍ‡	Ø	û+³S\x19ï\x1d´	¹X\x01^Š/oú—\x1dòÒìBj%{#píD ÔêÀ¬ÐH1¼Ð¸¯Ê}êA\x1dͶ\x03ô£^Ì÷#áá| \x11±×·Ù÷'\x19ô•’
‡tE?Ìð\x16ÍÊZÔ¨M\x06¸äƒjÃP,e0ç\x16\x0589\x115å´ÚY\x14w½ÛËq×ï‘\fÎÓ/0áξ8Ý]±ßB›\x12©•ˆÒµkæóξö`w\x1f7v8ÑT…óÂÛç¬"•üÇÝ@\x1eÚAµ7!Œe¤Ò\r§VæÌ6Õ¶&¤voC”r\x15ó\x1eœ—}ûòÚ;ÚT_¹V¿¼S_Z§Å\f6%¦]‚?ÏÅ\x0eŒ\x12\x16Š<-
nÙ.Û{Ž}øÚ\bÿÆ\0w¨ÅúÂ\x01,f|¾Ý6–CÀØó&²k%\x13ãa1ĪÀ©ò‘Kʼn]Ëf,\x14p*ÆI\x15O^["K˜Þ£íÍ—gçOPK\x01\x02\x14\x03\x14\0\0\0\b\0\x03¼16—¿»Hè\x06\0\02\x11\0\0\x14\0	\0\0\0\0\0\0\0\0\0¤\0\0\0\0dma_4xx_int_module.cUT\x05\0\a磮EPK\x05\x06\0\0\0\0\x01\0\x01\0K\0\0\0\x1a\a\0\0\0\0

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Xenomai-core] PPC405: DMA-Problem with OCM (interrupt-example)
  2007-01-17 22:33 [Xenomai-core] PPC405: DMA-Problem with OCM (interrupt-example) Niklaus Giger
@ 2007-01-18  0:26 ` Jan Kiszka
  2007-01-18  8:31 ` Wolfgang Grandegger
  1 sibling, 0 replies; 8+ messages in thread
From: Jan Kiszka @ 2007-01-18  0:26 UTC (permalink / raw)
  To: niklaus.giger; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 552 bytes --]

Niklaus Giger wrote:
> ...
> Is the example code otherwise good enough to be accepted as an example how to 
> attach a interrupt?

Can't help with your core issue, but I can comment on the IRQ code:

Please use RTDM for in-kernel demos like this. Unless you embed the IRQ
handling into an application directly, RTDM is the preferred way to go -
as you are then designing a driver.

When porting to RTDM, watch out for the latest change I just checked in:
there is now no need to enable an IRQ line explicitly after requesting it.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 249 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Xenomai-core] PPC405: DMA-Problem with OCM (interrupt-example)
  2007-01-17 22:33 [Xenomai-core] PPC405: DMA-Problem with OCM (interrupt-example) Niklaus Giger
  2007-01-18  0:26 ` Jan Kiszka
@ 2007-01-18  8:31 ` Wolfgang Grandegger
  2007-01-19 23:06   ` [Xenomai-core] PPC405: DMA-problem solved! Niklaus Giger
  1 sibling, 1 reply; 8+ messages in thread
From: Wolfgang Grandegger @ 2007-01-18  8:31 UTC (permalink / raw)
  To: niklaus.giger; +Cc: xenomai

Niklaus Giger wrote:
> Hi
> 
> I tried to simply an example program how to use interrupts
> with Xenomai (see attached Makefile & dma_4xx_int_module.c).
> 
> The interrupt part of the example works, but the DMA transfer (memory to
> memory) using the OnChipMemory fails. I think I must somewhere specify that 
> the src/dst adressed should not be cached, but I do not know how to do it.

consistant_alloc() should help. It's used in the kernel in various 
places, e.g. in "drivers/net/ibm_emac".

> (I tried to use virt_to_phys and virt_to_bus but failed miserably.)
> The OCM is initialised in my board specific __init by calling:
>>         io_block_mapping(mfdcr(DCRN_OCMDSARC), mfdcr(DCRN_OCMDSARC),
>> 4*1024, _PAGE_IO);
> 
> A simple insmod/rmmod cycle gives me the following output:
> 
>>                      init_module: SRC f4000000 DST f4000103
>>                      init_module: residue 111 status 0xa00f100
>>              xenomai_irq_handler: IRQ  8 uipr 0xffffff87 uier 0x003f0000
>> uisr 0xc0809807 xenomai_irq_handler: residue 0 status 0x1a00f000
>> src at f4000000 is Could we use a DMA + interrupt to copy a string?
>> dst at f4000103 is Should be overwritten.
>>                   cleanup_module: dma_ch.control 0x0 0
>>                   cleanup_module: IRQ  8 uipr 0xffffff87 uier 0x003f0000
>> uisr 0xc0009807 cleanup_module: residue 0 status 0x1a00f000
>> src at f4000000 is Could we use a DMA + interrupt to copy a string?
>> dst at f4000103 is Should be overwritten.
> 
> Does anybody have a clue?
> 
> If this question is off topic, which mailing list would you reccomend?
> (http://ozlabs.org/pipermail/linuxppc-embedded/ ??)

linuxppc-embedded is OK.

> Is the example code otherwise good enough to be accepted as an example how to 
> attach a interrupt?

Wolfgang.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Xenomai-core] PPC405: DMA-problem solved!
  2007-01-18  8:31 ` Wolfgang Grandegger
@ 2007-01-19 23:06   ` Niklaus Giger
  2007-01-20  8:04     ` Jan Kiszka
  0 siblings, 1 reply; 8+ messages in thread
From: Niklaus Giger @ 2007-01-19 23:06 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1006 bytes --]

Am Donnerstag, 18. Januar 2007 09:31 schrieb Wolfgang Grandegger:
> Niklaus Giger wrote:
> > Hi
> >
> > I tried to simply an example program how to use interrupts
> > with Xenomai (see attached Makefile & dma_4xx_int_module.c).
> >
> > The interrupt part of the example works, but the DMA transfer (memory to
> > memory) using the OnChipMemory fails. I think I must somewhere specify
> > that the src/dst adressed should not be cached, but I do not know how to
> > do it.
>
> consistant_alloc() should help. It's used in the kernel in various
> places, e.g. in "drivers/net/ibm_emac".

Thank you for your tips.

After fixing two bugs in arch/ppc/syslib/ppc4xx_dma.c. See  
 * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025697.html
 * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025700.html
my example code worked (tested with DMA channel 0 and DMA channel 3).
<..>

Interrupt code is ported to RTDM.

@Jan: Can the attached patch be applied?

Best regards

-- 
Niklaus Giger

[-- Attachment #2: ppc4xx_int.patch --]
[-- Type: text/x-diff, Size: 8791 bytes --]

Index: examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c
===================================================================
--- examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c	(Revision 0)
+++ examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c	(Revision 0)
@@ -0,0 +1,167 @@
+/* * Written by Niklaus Giger <niklaus.giger@domain.hid>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ****************************************************************************
+ *
+ * This is an example howto write a Xenomai kernel module which handles a
+ * HW interrupt. The example is PPC4xx specific (testd on a PPC405 board)
+ * Probably also works on a PPC44x (not yet tested, needs a different irq?).
+ *
+ * Beware!
+ * The following patches must be applied to your kernel to fix bugs
+ * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025697.html
+ * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025700.html
+ *
+ * Beware!
+ * The kernel option PPC4xx DMA must be activated for this test.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <asm/ppc4xx_dma.h>
+
+#include <rtdm/rtdm_driver.h>
+#include <rtdm/rtdm.h>
+rtdm_irq_t irq_handle;
+
+MODULE_DESCRIPTION("PPC4xx DMA3 interrupt demo");
+MODULE_AUTHOR("niklaus.giger@domain.hid");
+MODULE_LICENSE("GPL");
+
+#define DMA_NR 3
+int irq = DMA_NR + 5; /* DMA-x interrupt line  on PPC405GPr */
+
+#define TEST_STRING  "Could we use a DMA + interrupt to copy a string?"
+#define TEST_STRING2 "Should be overwritten."
+#define STRING_SIZE 128
+
+char *SRC;
+char *DST;
+
+static ppc_dma_ch_t p_init;
+
+#define show_irq(irq) 	{						\
+	printk("%32s: IRQ %2d uipr 0x%08x uier 0x%08x uisr 0x%08x\n",	\
+		__FUNCTION__, irq, 					\
+		mfdcr(DCRN_UIC_PR(UIC0)), mfdcr(DCRN_UIC_ER(UIC0)),	\
+		mfdcr(DCRN_UIC_SR(UIC0)));				\
+	printk("%32s: residue %d status 0x08%x cntrl 0x%08x\n",__FUNCTION__,\
+		ppc4xx_get_dma_residue(DMA_NR),				\
+		ppc4xx_get_dma_status(),				\
+		mfdcr(DCRN_DMACR0 + (DMA_NR * 0x8)));			\
+	printk("src at %p is %s\ndst at %p is %s\n", (char *)SRC,	\
+		SRC, &DST[0], &DST[0]); }
+
+void dma_mem_to_mem(void *src, void *dst, unsigned int length,
+			unsigned int use_interrupt)
+{
+#warning Do not use dma_mem_to_mem for OnChipMemory! It will not work.
+	int res = 0;
+	memset((char *)&p_init, sizeof(p_init), 0);
+	p_init.polarity = 0;
+	p_init.pwidth   = PW_8;
+ 	res = ppc4xx_init_dma_channel(DMA_NR, &p_init);
+	if (res) {
+		printk("%32s: nit_dma_channel return %d %d bytes dest %p\n",
+			__FUNCTION__, res, length, dst);
+	}
+	res = ppc4xx_clr_dma_status(DMA_NR);
+	if (res) { 
+		printk("%32s: ppc4xx_clr_dma_status %d\n", __FUNCTION__, res);
+	}
+#warning flush_dcache_all is a performance killer, but I do not know at the 
+#warning moment how to flush only the parts needed
+	flush_dcache_all(); /* from arch/ppc/kernel/misc.S */
+
+	ppc4xx_set_dma_mode(DMA_NR, DMA_MODE_MM);
+	ppc4xx_set_src_addr(DMA_NR, virt_to_bus(src));
+	ppc4xx_set_dst_addr(DMA_NR, virt_to_bus(dst));
+	ppc4xx_set_dma_count(DMA_NR, length);
+	ppc4xx_enable_dma(DMA_NR);
+	if (use_interrupt) {
+		res = ppc4xx_enable_dma_interrupt(DMA_NR);
+	} else {
+		res = ppc4xx_disable_dma_interrupt(DMA_NR);
+	}
+	if (res) { 
+		printk("%32s: en/disable_dma_interrupt %d return %d per %d\n",
+		__FUNCTION__, use_interrupt, res, 
+		ppc4xx_get_peripheral_width(DMA_NR));
+	}
+}
+
+int dma_irq_handler(rtdm_irq_t *irq_handle)
+{
+	ppc4xx_disable_dma(DMA_NR);
+	ppc4xx_disable_dma_interrupt(DMA_NR);
+	show_irq(irq);
+	return RTDM_IRQ_HANDLED;
+}
+
+int init_module()
+{
+	if (rtdm_irq_request(&irq_handle, irq,  dma_irq_handler, 0, "dma3_4xx", 0)) {
+		printk("%s:%s Error: rtdm_irq_request failed\n",
+			 __FILE__, __FUNCTION__);
+		return 1;
+	}
+	show_irq(irq);
+	if (rtdm_irq_enable (&irq_handle)) {
+		printk("%s:%s Error: rtdm_irq_enable failed\n",
+			 __FILE__, __FUNCTION__);
+		return 1;
+	}
+
+	SRC = (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, get_order(STRING_SIZE));
+	DST = (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, get_order(STRING_SIZE));
+
+	strncpy(SRC, TEST_STRING,  STRING_SIZE);
+	strncpy(DST, TEST_STRING2, STRING_SIZE);
+
+	flush_dcache_all(); /* from arch/ppc/kernel/misc.S */
+	dma_mem_to_mem(SRC, DST, STRING_SIZE, 1);
+	if (ppc4xx_get_dma_residue(DMA_NR)) { 
+		printk("%32s: residue %d status 0x%x\n",__FUNCTION__,
+		ppc4xx_get_dma_residue(DMA_NR),
+		ppc4xx_get_dma_status());
+	}
+	return 0;
+	
+	
+}
+
+void cleanup_module ()
+{
+	ppc_dma_ch_t dma_ch;
+	if (ppc4xx_get_dma_residue(DMA_NR)) {
+		printk("%32s: residue %d status 0x%x\n",__FUNCTION__,
+		ppc4xx_get_dma_residue(DMA_NR),
+		ppc4xx_get_dma_status());
+	}
+	ppc4xx_get_channel_config(DMA_NR, &dma_ch);
+	printk("%32s: dma_ch.control 0x%x %d SRC %p %s\n",__FUNCTION__, dma_ch.control,
+		dma_ch.pwidth, SRC,__TIME__);
+
+	if (rtdm_irq_disable (&irq_handle)) {
+		printk("%32s: rtdm_irq_disable failed\n",__FUNCTION__);
+	}
+	if (rtdm_irq_free (&irq_handle)) {
+		printk("%32s: rtdm_irq_free failed\n",__FUNCTION__);
+	}
+	show_irq(irq);
+}
Index: examples/rtdm/pp4xx_interrupt/Makefile
===================================================================
--- examples/rtdm/pp4xx_interrupt/Makefile	(Revision 0)
+++ examples/rtdm/pp4xx_interrupt/Makefile	(Revision 0)
@@ -0,0 +1,47 @@
+###### CONFIGURATION ######
+###### Please adapt it to your needs
+O:=/usr/src/build-hcu3-2.6.19.1
+DESTDIR:=/home/hcu/rootfs/niklaus_2.6.19
+KSRC:=/usr/src/linux-2.6.19.1
+
+ARCH:=ppc
+CROSS_COMPILE:=ppc_4xx-
+PATH:=/home/opt/eldk/4_0/usr/bin:/usr/local/bin:/usr/bin:/bin
+M:=$(shell pwd)
+
+### List of applications to be build
+XENO=$(DESTDIR)/usr/xenomai
+### Note: to override the search path for the xeno-config script, use "make XENOCONFIG=..."
+
+
+### List of modules to be build
+MODULES = dma_4xx_int_module
+
+### Note: to override the kernel source path, use "make KSRC=..."
+
+###### KERNEL MODULE BUILD (no change required normally) ######
+ifneq ($(MODULES),)
+
+OBJS     := ${patsubst %, %.o, $(MODULES)}
+CLEANMOD := ${patsubst %, .%*, $(MODULES)}
+PWD      := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
+
+### Kernel 2.6
+obj-m        := $(OBJS)
+EXTRA_CFLAGS :=-I$(KSRC)/include/xenomai -I$(KSRC)/include/xenomai/posix $(ADD_CFLAGS)
+
+MODMAKE:=make CROSS_COMPILE=$(CROSS_COMPILE)  ARCH=$(ARCH) O=$(O) -C $(KSRC) M=$(M) PATH=$(PATH) -I$(KSRC)/include/xenomai
+
+modules:
+	$(MODMAKE) modules
+
+install:	modules
+	$(MODMAKE) INSTALL_MOD_PATH=$(DESTDIR) modules_install
+
+all::	modules
+
+clean::
+	$(RM) $(CLEANMOD) *.cmd *.o *.ko *.mod.c Module*.symvers
+	$(RM) -R .tmp*
+
+endif
Index: examples/common/Makefile
===================================================================
--- examples/common/Makefile	(Revision 2079)
+++ examples/common/Makefile	(Arbeitskopie)
@@ -3,9 +3,9 @@
 ### List of applications to be build
 APPLICATIONS = hw_direct_io
 
-### Note: to override the search path for the xeno-config script, use "make XENO=..."
+### Note: to override the search path for the xeno-config script, use "make XENOCONFIG=..."
+### Note: if you installed it into a non standard place add DESTDIR=/path/to/installed/xenomai"
 
-
 ### List of modules to be build
 MODULES =
 
@@ -14,6 +14,8 @@
 
 ### Note: to override the kernel source path, use "make KSRC=..."
 
+# default place to install the resulting binaries
+EXEC_PREFIX := $(DESTDIR)/usr/xenomai/bin
 
 
 ###### USER SPACE BUILD (no change required normally) ######
@@ -24,7 +26,9 @@
 ### Sanity check
 ifeq ($(XENOCONFIG),)
 all::
-	@echo ">>> Invoke make like this: \"make XENO=/path/to/xeno-config\" <<<"
+	@echo ">>> Invoke make like this: \"make XENOCONFIG=/path/to/xeno-config\" <<<"
+	@echo ">>> add KSRC=.. to override the default kernel source at /lib/modules/$(shell uname -r)/build <<<"
+	@echo ">>> add DESTDIR=/path/to/installed/xenomai if you installed it into a non standard place <<<"
 	@echo
 endif
 
@@ -40,6 +44,9 @@
 clean::
 	$(RM) $(APPLICATIONS) *.o
 
+install::   $(APPLICATIONS)
+	cp $(APPLICATIONS) $(EXEC_PREFIX)/
+
 endif
 
 
@@ -80,3 +87,4 @@
 	$(RM) -R .tmp*
 
 endif
+

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Xenomai-core] PPC405: DMA-problem solved!
  2007-01-19 23:06   ` [Xenomai-core] PPC405: DMA-problem solved! Niklaus Giger
@ 2007-01-20  8:04     ` Jan Kiszka
  2007-01-21 21:37       ` Wolfgang Grandegger
  2007-01-22  7:22       ` Niklaus Giger
  0 siblings, 2 replies; 8+ messages in thread
From: Jan Kiszka @ 2007-01-20  8:04 UTC (permalink / raw)
  To: niklaus.giger; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 12257 bytes --]

Niklaus Giger wrote:
> Am Donnerstag, 18. Januar 2007 09:31 schrieb Wolfgang Grandegger:
>> Niklaus Giger wrote:
>>> Hi
>>>
>>> I tried to simply an example program how to use interrupts
>>> with Xenomai (see attached Makefile & dma_4xx_int_module.c).
>>>
>>> The interrupt part of the example works, but the DMA transfer (memory to
>>> memory) using the OnChipMemory fails. I think I must somewhere specify
>>> that the src/dst adressed should not be cached, but I do not know how to
>>> do it.
>> consistant_alloc() should help. It's used in the kernel in various
>> places, e.g. in "drivers/net/ibm_emac".
> 
> Thank you for your tips.
> 
> After fixing two bugs in arch/ppc/syslib/ppc4xx_dma.c. See  
>  * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025697.html
>  * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025700.html
> my example code worked (tested with DMA channel 0 and DMA channel 3).
> <..>
> 
> Interrupt code is ported to RTDM.
> 
> @Jan: Can the attached patch be applied?

Almost, just the usual nitpicking comments below. :)

> 
> Best regards
> 
> 
> 
> ------------------------------------------------------------------------
> 
> Index: examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c
> ===================================================================
> --- examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c	(Revision 0)
> +++ examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c	(Revision 0)

This demo is about how to use the driver API (/wrt interrupts) + how to
do PPC4xx-specific DMA. So my suggestion:

examples/rtdm/driver-api/dma-ppc4xx.c

In any case, we need to resolve the arch dependency somehow. I guess
it will  currently not fly when I kick the full build in examples/ for a
non-PPC platform. Any *simple* way to catch this? Would also be
applicable to the heartbeat-x86 example then, though this will not cause
build troubles.

> @@ -0,0 +1,167 @@
> +/* * Written by Niklaus Giger <niklaus.giger@domain.hid>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of the
> + * License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + *
> + ****************************************************************************
> + *
> + * This is an example howto write a Xenomai kernel module which handles a
> + * HW interrupt. The example is PPC4xx specific (testd on a PPC405 board)
> + * Probably also works on a PPC44x (not yet tested, needs a different irq?).
> + *
> + * Beware!
> + * The following patches must be applied to your kernel to fix bugs

Which kernel? I guess this issue will not persist forever.

> + * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025697.html
> + * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025700.html
> + *
> + * Beware!
> + * The kernel option PPC4xx DMA must be activated for this test.

Please provide the full CONFIG_OPTION_NAME here.

> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/io.h>
> +#include <asm/ppc4xx_dma.h>
> +
> +#include <rtdm/rtdm_driver.h>
> +#include <rtdm/rtdm.h>
> +rtdm_irq_t irq_handle;
> +
> +MODULE_DESCRIPTION("PPC4xx DMA3 interrupt demo");
> +MODULE_AUTHOR("niklaus.giger@domain.hid");
> +MODULE_LICENSE("GPL");
> +
> +#define DMA_NR 3
> +int irq = DMA_NR + 5; /* DMA-x interrupt line  on PPC405GPr */
> +
> +#define TEST_STRING  "Could we use a DMA + interrupt to copy a string?"
> +#define TEST_STRING2 "Should be overwritten."
> +#define STRING_SIZE 128
> +
> +char *SRC;
> +char *DST;
> +
> +static ppc_dma_ch_t p_init;
> +
> +#define show_irq(irq) 	{						\
> +	printk("%32s: IRQ %2d uipr 0x%08x uier 0x%08x uisr 0x%08x\n",	\
> +		__FUNCTION__, irq, 					\
> +		mfdcr(DCRN_UIC_PR(UIC0)), mfdcr(DCRN_UIC_ER(UIC0)),	\
> +		mfdcr(DCRN_UIC_SR(UIC0)));				\
> +	printk("%32s: residue %d status 0x08%x cntrl 0x%08x\n",__FUNCTION__,\
> +		ppc4xx_get_dma_residue(DMA_NR),				\
> +		ppc4xx_get_dma_status(),				\
> +		mfdcr(DCRN_DMACR0 + (DMA_NR * 0x8)));			\
> +	printk("src at %p is %s\ndst at %p is %s\n", (char *)SRC,	\
> +		SRC, &DST[0], &DST[0]); }
> +
> +void dma_mem_to_mem(void *src, void *dst, unsigned int length,
> +			unsigned int use_interrupt)
> +{
> +#warning Do not use dma_mem_to_mem for OnChipMemory! It will not work.

Why do we have a compiler warning here, why not a comment?

> +	int res = 0;
> +	memset((char *)&p_init, sizeof(p_init), 0);
> +	p_init.polarity = 0;
> +	p_init.pwidth   = PW_8;
> + 	res = ppc4xx_init_dma_channel(DMA_NR, &p_init);
> +	if (res) {
> +		printk("%32s: nit_dma_channel return %d %d bytes dest %p\n",
> +			__FUNCTION__, res, length, dst);
> +	}
> +	res = ppc4xx_clr_dma_status(DMA_NR);
> +	if (res) { 
> +		printk("%32s: ppc4xx_clr_dma_status %d\n", __FUNCTION__, res);
> +	}
> +#warning flush_dcache_all is a performance killer, but I do not know at the 
> +#warning moment how to flush only the parts needed

Can we resolve this? Wolfgang?

> +	flush_dcache_all(); /* from arch/ppc/kernel/misc.S */
> +
> +	ppc4xx_set_dma_mode(DMA_NR, DMA_MODE_MM);
> +	ppc4xx_set_src_addr(DMA_NR, virt_to_bus(src));
> +	ppc4xx_set_dst_addr(DMA_NR, virt_to_bus(dst));
> +	ppc4xx_set_dma_count(DMA_NR, length);
> +	ppc4xx_enable_dma(DMA_NR);
> +	if (use_interrupt) {
> +		res = ppc4xx_enable_dma_interrupt(DMA_NR);
> +	} else {
> +		res = ppc4xx_disable_dma_interrupt(DMA_NR);
> +	}
> +	if (res) { 
> +		printk("%32s: en/disable_dma_interrupt %d return %d per %d\n",
> +		__FUNCTION__, use_interrupt, res, 
> +		ppc4xx_get_peripheral_width(DMA_NR));
> +	}
> +}
> +
> +int dma_irq_handler(rtdm_irq_t *irq_handle)
> +{
> +	ppc4xx_disable_dma(DMA_NR);
> +	ppc4xx_disable_dma_interrupt(DMA_NR);
> +	show_irq(irq);
> +	return RTDM_IRQ_HANDLED;
> +}
> +
> +int init_module()
> +{
> +	if (rtdm_irq_request(&irq_handle, irq,  dma_irq_handler, 0, "dma3_4xx", 0)) {
> +		printk("%s:%s Error: rtdm_irq_request failed\n",
> +			 __FILE__, __FUNCTION__);
> +		return 1;
> +	}
> +	show_irq(irq);
> +	if (rtdm_irq_enable (&irq_handle)) {
> +		printk("%s:%s Error: rtdm_irq_enable failed\n",
> +			 __FILE__, __FUNCTION__);
> +		return 1;
> +	}

This demo will go to trunk, thus rtdm_irq_enable is no longer needed.

> +
> +	SRC = (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, get_order(STRING_SIZE));
> +	DST = (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, get_order(STRING_SIZE));
> +
> +	strncpy(SRC, TEST_STRING,  STRING_SIZE);
> +	strncpy(DST, TEST_STRING2, STRING_SIZE);
> +
> +	flush_dcache_all(); /* from arch/ppc/kernel/misc.S */
> +	dma_mem_to_mem(SRC, DST, STRING_SIZE, 1);
> +	if (ppc4xx_get_dma_residue(DMA_NR)) { 
> +		printk("%32s: residue %d status 0x%x\n",__FUNCTION__,
> +		ppc4xx_get_dma_residue(DMA_NR),
> +		ppc4xx_get_dma_status());
> +	}
> +	return 0;
> +	
> +	
> +}
> +
> +void cleanup_module ()
> +{
> +	ppc_dma_ch_t dma_ch;
> +	if (ppc4xx_get_dma_residue(DMA_NR)) {
> +		printk("%32s: residue %d status 0x%x\n",__FUNCTION__,
> +		ppc4xx_get_dma_residue(DMA_NR),
> +		ppc4xx_get_dma_status());
> +	}
> +	ppc4xx_get_channel_config(DMA_NR, &dma_ch);
> +	printk("%32s: dma_ch.control 0x%x %d SRC %p %s\n",__FUNCTION__, dma_ch.control,
> +		dma_ch.pwidth, SRC,__TIME__);
> +
> +	if (rtdm_irq_disable (&irq_handle)) {
> +		printk("%32s: rtdm_irq_disable failed\n",__FUNCTION__);
> +	}

Disabling is typically not needed, unless it is the only way to silence
the IRQ source. Keep in mind that this disabling would be fatal if the
IRQ happened to be shared (though unusual on PPC, AFAIK).

> +	if (rtdm_irq_free (&irq_handle)) {
> +		printk("%32s: rtdm_irq_free failed\n",__FUNCTION__);
> +	}
> +	show_irq(irq);
> +}
> Index: examples/rtdm/pp4xx_interrupt/Makefile
> ===================================================================
> --- examples/rtdm/pp4xx_interrupt/Makefile	(Revision 0)
> +++ examples/rtdm/pp4xx_interrupt/Makefile	(Revision 0)
> @@ -0,0 +1,47 @@
> +###### CONFIGURATION ######
> +###### Please adapt it to your needs
> +O:=/usr/src/build-hcu3-2.6.19.1
> +DESTDIR:=/home/hcu/rootfs/niklaus_2.6.19
> +KSRC:=/usr/src/linux-2.6.19.1
> +
> +ARCH:=ppc
> +CROSS_COMPILE:=ppc_4xx-
> +PATH:=/home/opt/eldk/4_0/usr/bin:/usr/local/bin:/usr/bin:/bin
> +M:=$(shell pwd)
> +
> +### List of applications to be build
> +XENO=$(DESTDIR)/usr/xenomai
> +### Note: to override the search path for the xeno-config script, use "make XENOCONFIG=..."
> +
> +
> +### List of modules to be build
> +MODULES = dma_4xx_int_module
> +
> +### Note: to override the kernel source path, use "make KSRC=..."
> +
> +###### KERNEL MODULE BUILD (no change required normally) ######
> +ifneq ($(MODULES),)
> +
> +OBJS     := ${patsubst %, %.o, $(MODULES)}
> +CLEANMOD := ${patsubst %, .%*, $(MODULES)}
> +PWD      := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
> +
> +### Kernel 2.6
> +obj-m        := $(OBJS)
> +EXTRA_CFLAGS :=-I$(KSRC)/include/xenomai -I$(KSRC)/include/xenomai/posix $(ADD_CFLAGS)
> +
> +MODMAKE:=make CROSS_COMPILE=$(CROSS_COMPILE)  ARCH=$(ARCH) O=$(O) -C $(KSRC) M=$(M) PATH=$(PATH) -I$(KSRC)/include/xenomai
> +
> +modules:
> +	$(MODMAKE) modules
> +
> +install:	modules
> +	$(MODMAKE) INSTALL_MOD_PATH=$(DESTDIR) modules_install
> +
> +all::	modules
> +
> +clean::
> +	$(RM) $(CLEANMOD) *.cmd *.o *.ko *.mod.c Module*.symvers
> +	$(RM) -R .tmp*
> +
> +endif
> Index: examples/common/Makefile
> ===================================================================
> --- examples/common/Makefile	(Revision 2079)
> +++ examples/common/Makefile	(Arbeitskopie)
> @@ -3,9 +3,9 @@
>  ### List of applications to be build
>  APPLICATIONS = hw_direct_io
>  
> -### Note: to override the search path for the xeno-config script, use "make XENO=..."
> +### Note: to override the search path for the xeno-config script, use "make XENOCONFIG=..."

If you prefer XENOCONFIG, please provide patches for the whole examples
repos. :)

> +### Note: if you installed it into a non standard place add DESTDIR=/path/to/installed/xenomai"

The hint to DESTDIR is useful, but the explanation should be more like
"if Xenomai was installed with DESTDIR set, the same must be provided here".

>  
> -
>  ### List of modules to be build
>  MODULES =
>  
> @@ -14,6 +14,8 @@
>  
>  ### Note: to override the kernel source path, use "make KSRC=..."
>  
> +# default place to install the resulting binaries
> +EXEC_PREFIX := $(DESTDIR)/usr/xenomai/bin
>  
>  
>  ###### USER SPACE BUILD (no change required normally) ######
> @@ -24,7 +26,9 @@
>  ### Sanity check
>  ifeq ($(XENOCONFIG),)
>  all::
> -	@echo ">>> Invoke make like this: \"make XENO=/path/to/xeno-config\" <<<"
> +	@echo ">>> Invoke make like this: \"make XENOCONFIG=/path/to/xeno-config\" <<<"
> +	@echo ">>> add KSRC=.. to override the default kernel source at /lib/modules/$(shell uname -r)/build <<<"

KSRC is unrelated here (user space part of the makefile).

> +	@echo ">>> add DESTDIR=/path/to/installed/xenomai if you installed it into a non standard place <<<"

See earlier comment.

>  	@echo
>  endif
>  
> @@ -40,6 +44,9 @@
>  clean::
>  	$(RM) $(APPLICATIONS) *.o
>  
> +install::   $(APPLICATIONS)
> +	cp $(APPLICATIONS) $(EXEC_PREFIX)/
> +

NACK. I'd rather like to keep the makefile focused (the next step would
be to add uninstall, then ...).

>  endif
>  
>  
> @@ -80,3 +87,4 @@
>  	$(RM) -R .tmp*
>  
>  endif
> +
> 
> 

Jan



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Xenomai-core] PPC405: DMA-problem solved!
  2007-01-20  8:04     ` Jan Kiszka
@ 2007-01-21 21:37       ` Wolfgang Grandegger
  2007-01-22 14:06         ` Jan Kiszka
  2007-01-22  7:22       ` Niklaus Giger
  1 sibling, 1 reply; 8+ messages in thread
From: Wolfgang Grandegger @ 2007-01-21 21:37 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Jan Kiszka wrote:
> Niklaus Giger wrote:
>> Am Donnerstag, 18. Januar 2007 09:31 schrieb Wolfgang Grandegger:
>>> Niklaus Giger wrote:
>>>> Hi
>>>>
>>>> I tried to simply an example program how to use interrupts
>>>> with Xenomai (see attached Makefile & dma_4xx_int_module.c).
>>>>
>>>> The interrupt part of the example works, but the DMA transfer (memory to
>>>> memory) using the OnChipMemory fails. I think I must somewhere specify
>>>> that the src/dst adressed should not be cached, but I do not know how to
>>>> do it.
>>> consistant_alloc() should help. It's used in the kernel in various
>>> places, e.g. in "drivers/net/ibm_emac".
>> Thank you for your tips.
>>
>> After fixing two bugs in arch/ppc/syslib/ppc4xx_dma.c. See  
>>  * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025697.html
>>  * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025700.html
>> my example code worked (tested with DMA channel 0 and DMA channel 3).
>> <..>
>>
>> Interrupt code is ported to RTDM.
>>
>> @Jan: Can the attached patch be applied?
> 
> Almost, just the usual nitpicking comments below. :)
> 
>> Best regards
>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> Index: examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c
>> ===================================================================
>> --- examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c	(Revision 0)
>> +++ examples/rtdm/pp4xx_interrupt/dma_4xx_int_module.c	(Revision 0)
> 
> This demo is about how to use the driver API (/wrt interrupts) + how to
> do PPC4xx-specific DMA. So my suggestion:
> 
> examples/rtdm/driver-api/dma-ppc4xx.c
> 
> In any case, we need to resolve the arch dependency somehow. I guess
> it will  currently not fly when I kick the full build in examples/ for a
> non-PPC platform. Any *simple* way to catch this? Would also be
> applicable to the heartbeat-x86 example then, though this will not cause
> build troubles.

The only simple way I see is referencing the configured kernel tree.

>> @@ -0,0 +1,167 @@
>> +/* * Written by Niklaus Giger <niklaus.giger@domain.hid>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License as
>> + * published by the Free Software Foundation; either version 2 of the
>> + * License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
>> + *
>> + ****************************************************************************
>> + *
>> + * This is an example howto write a Xenomai kernel module which handles a
>> + * HW interrupt. The example is PPC4xx specific (testd on a PPC405 board)
>> + * Probably also works on a PPC44x (not yet tested, needs a different irq?).
>> + *
>> + * Beware!
>> + * The following patches must be applied to your kernel to fix bugs
> 
> Which kernel? I guess this issue will not persist forever.

Hopefully not.

> 
>> + * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025697.html
>> + * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025700.html
>> + *
>> + * Beware!
>> + * The kernel option PPC4xx DMA must be activated for this test.
> 
> Please provide the full CONFIG_OPTION_NAME here.
> 
>> + *
>> + */
>> +
>> +#include <linux/init.h>
>> +#include <linux/module.h>
>> +#include <linux/io.h>
>> +#include <asm/ppc4xx_dma.h>
>> +
>> +#include <rtdm/rtdm_driver.h>
>> +#include <rtdm/rtdm.h>
>> +rtdm_irq_t irq_handle;
>> +
>> +MODULE_DESCRIPTION("PPC4xx DMA3 interrupt demo");
>> +MODULE_AUTHOR("niklaus.giger@domain.hid");
>> +MODULE_LICENSE("GPL");
>> +
>> +#define DMA_NR 3
>> +int irq = DMA_NR + 5; /* DMA-x interrupt line  on PPC405GPr */
>> +
>> +#define TEST_STRING  "Could we use a DMA + interrupt to copy a string?"
>> +#define TEST_STRING2 "Should be overwritten."
>> +#define STRING_SIZE 128
>> +
>> +char *SRC;
>> +char *DST;
>> +
>> +static ppc_dma_ch_t p_init;
>> +
>> +#define show_irq(irq) 	{						\
>> +	printk("%32s: IRQ %2d uipr 0x%08x uier 0x%08x uisr 0x%08x\n",	\
>> +		__FUNCTION__, irq, 					\
>> +		mfdcr(DCRN_UIC_PR(UIC0)), mfdcr(DCRN_UIC_ER(UIC0)),	\
>> +		mfdcr(DCRN_UIC_SR(UIC0)));				\
>> +	printk("%32s: residue %d status 0x08%x cntrl 0x%08x\n",__FUNCTION__,\
>> +		ppc4xx_get_dma_residue(DMA_NR),				\
>> +		ppc4xx_get_dma_status(),				\
>> +		mfdcr(DCRN_DMACR0 + (DMA_NR * 0x8)));			\
>> +	printk("src at %p is %s\ndst at %p is %s\n", (char *)SRC,	\
>> +		SRC, &DST[0], &DST[0]); }
>> +
>> +void dma_mem_to_mem(void *src, void *dst, unsigned int length,
>> +			unsigned int use_interrupt)
>> +{
>> +#warning Do not use dma_mem_to_mem for OnChipMemory! It will not work.
> 
> Why do we have a compiler warning here, why not a comment?
> 
>> +	int res = 0;
>> +	memset((char *)&p_init, sizeof(p_init), 0);
>> +	p_init.polarity = 0;
>> +	p_init.pwidth   = PW_8;
>> + 	res = ppc4xx_init_dma_channel(DMA_NR, &p_init);
>> +	if (res) {
>> +		printk("%32s: nit_dma_channel return %d %d bytes dest %p\n",
>> +			__FUNCTION__, res, length, dst);
>> +	}
>> +	res = ppc4xx_clr_dma_status(DMA_NR);
>> +	if (res) { 
>> +		printk("%32s: ppc4xx_clr_dma_status %d\n", __FUNCTION__, res);
>> +	}
>> +#warning flush_dcache_all is a performance killer, but I do not know at the 
>> +#warning moment how to flush only the parts needed
> 
> Can we resolve this? Wolfgang?

flush_dcache_range should do the job. Or even better use the DMA-API 
described in Documentation/DMA-API.txt to get DMA'able memory (as 
pointed out recently on the linuxppc-emmbedded ML).

>> +	flush_dcache_all(); /* from arch/ppc/kernel/misc.S */
>> +
>> +	ppc4xx_set_dma_mode(DMA_NR, DMA_MODE_MM);
>> +	ppc4xx_set_src_addr(DMA_NR, virt_to_bus(src));
>> +	ppc4xx_set_dst_addr(DMA_NR, virt_to_bus(dst));
>> +	ppc4xx_set_dma_count(DMA_NR, length);
>> +	ppc4xx_enable_dma(DMA_NR);
>> +	if (use_interrupt) {
>> +		res = ppc4xx_enable_dma_interrupt(DMA_NR);
>> +	} else {
>> +		res = ppc4xx_disable_dma_interrupt(DMA_NR);
>> +	}
>> +	if (res) { 
>> +		printk("%32s: en/disable_dma_interrupt %d return %d per %d\n",
>> +		__FUNCTION__, use_interrupt, res, 
>> +		ppc4xx_get_peripheral_width(DMA_NR));
>> +	}
>> +}
>> +
>> +int dma_irq_handler(rtdm_irq_t *irq_handle)
>> +{
>> +	ppc4xx_disable_dma(DMA_NR);
>> +	ppc4xx_disable_dma_interrupt(DMA_NR);
>> +	show_irq(irq);
>> +	return RTDM_IRQ_HANDLED;
>> +}
>> +
>> +int init_module()
>> +{
>> +	if (rtdm_irq_request(&irq_handle, irq,  dma_irq_handler, 0, "dma3_4xx", 0)) {
>> +		printk("%s:%s Error: rtdm_irq_request failed\n",
>> +			 __FILE__, __FUNCTION__);
>> +		return 1;
>> +	}
>> +	show_irq(irq);
>> +	if (rtdm_irq_enable (&irq_handle)) {
>> +		printk("%s:%s Error: rtdm_irq_enable failed\n",
>> +			 __FILE__, __FUNCTION__);
>> +		return 1;
>> +	}
> 
> This demo will go to trunk, thus rtdm_irq_enable is no longer needed.
> 
>> +
>> +	SRC = (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, get_order(STRING_SIZE));
>> +	DST = (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, get_order(STRING_SIZE));
>> +
>> +	strncpy(SRC, TEST_STRING,  STRING_SIZE);
>> +	strncpy(DST, TEST_STRING2, STRING_SIZE);
>> +
>> +	flush_dcache_all(); /* from arch/ppc/kernel/misc.S */
>> +	dma_mem_to_mem(SRC, DST, STRING_SIZE, 1);
>> +	if (ppc4xx_get_dma_residue(DMA_NR)) { 
>> +		printk("%32s: residue %d status 0x%x\n",__FUNCTION__,
>> +		ppc4xx_get_dma_residue(DMA_NR),
>> +		ppc4xx_get_dma_status());
>> +	}
>> +	return 0;
>> +	
>> +	
>> +}
>> +
>> +void cleanup_module ()
>> +{
>> +	ppc_dma_ch_t dma_ch;
>> +	if (ppc4xx_get_dma_residue(DMA_NR)) {
>> +		printk("%32s: residue %d status 0x%x\n",__FUNCTION__,
>> +		ppc4xx_get_dma_residue(DMA_NR),
>> +		ppc4xx_get_dma_status());
>> +	}
>> +	ppc4xx_get_channel_config(DMA_NR, &dma_ch);
>> +	printk("%32s: dma_ch.control 0x%x %d SRC %p %s\n",__FUNCTION__, dma_ch.control,
>> +		dma_ch.pwidth, SRC,__TIME__);
>> +
>> +	if (rtdm_irq_disable (&irq_handle)) {
>> +		printk("%32s: rtdm_irq_disable failed\n",__FUNCTION__);
>> +	}
> 
> Disabling is typically not needed, unless it is the only way to silence
> the IRQ source. Keep in mind that this disabling would be fatal if the
> IRQ happened to be shared (though unusual on PPC, AFAIK).
> 
>> +	if (rtdm_irq_free (&irq_handle)) {
>> +		printk("%32s: rtdm_irq_free failed\n",__FUNCTION__);
>> +	}
>> +	show_irq(irq);
>> +}

And should we not also use rtdm_prinkt()?

>> Index: examples/rtdm/pp4xx_interrupt/Makefile
>> ===================================================================
>> --- examples/rtdm/pp4xx_interrupt/Makefile	(Revision 0)
>> +++ examples/rtdm/pp4xx_interrupt/Makefile	(Revision 0)
>> @@ -0,0 +1,47 @@
>> +###### CONFIGURATION ######
>> +###### Please adapt it to your needs
>> +O:=/usr/src/build-hcu3-2.6.19.1
>> +DESTDIR:=/home/hcu/rootfs/niklaus_2.6.19
>> +KSRC:=/usr/src/linux-2.6.19.1
>> +
>> +ARCH:=ppc
>> +CROSS_COMPILE:=ppc_4xx-
>> +PATH:=/home/opt/eldk/4_0/usr/bin:/usr/local/bin:/usr/bin:/bin
>> +M:=$(shell pwd)

This is your private stuff and should be removed.

>> +### List of applications to be build
>> +XENO=$(DESTDIR)/usr/xenomai
>> +### Note: to override the search path for the xeno-config script, use "make XENOCONFIG=..."
>> +
>> +
>> +### List of modules to be build
>> +MODULES = dma_4xx_int_module
>> +
>> +### Note: to override the kernel source path, use "make KSRC=..."
>> +
>> +###### KERNEL MODULE BUILD (no change required normally) ######
>> +ifneq ($(MODULES),)
>> +
>> +OBJS     := ${patsubst %, %.o, $(MODULES)}
>> +CLEANMOD := ${patsubst %, .%*, $(MODULES)}
>> +PWD      := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
>> +
>> +### Kernel 2.6
>> +obj-m        := $(OBJS)
>> +EXTRA_CFLAGS :=-I$(KSRC)/include/xenomai -I$(KSRC)/include/xenomai/posix $(ADD_CFLAGS)
>> +
>> +MODMAKE:=make CROSS_COMPILE=$(CROSS_COMPILE)  ARCH=$(ARCH) O=$(O) -C $(KSRC) M=$(M) PATH=$(PATH) -I$(KSRC)/include/xenomai
>> +
>> +modules:
>> +	$(MODMAKE) modules
>> +
>> +install:	modules
>> +	$(MODMAKE) INSTALL_MOD_PATH=$(DESTDIR) modules_install
>> +
>> +all::	modules
>> +
>> +clean::
>> +	$(RM) $(CLEANMOD) *.cmd *.o *.ko *.mod.c Module*.symvers
>> +	$(RM) -R .tmp*
>> +
>> +endif

Anyway, the Makefile /examples/rtdm/driver-api/Makefile should work fine 
for this example as well.

>> Index: examples/common/Makefile
>> ===================================================================
>> --- examples/common/Makefile	(Revision 2079)
>> +++ examples/common/Makefile	(Arbeitskopie)
>> @@ -3,9 +3,9 @@
>>  ### List of applications to be build
>>  APPLICATIONS = hw_direct_io
>>  
>> -### Note: to override the search path for the xeno-config script, use "make XENO=..."
>> +### Note: to override the search path for the xeno-config script, use "make XENOCONFIG=..."
> 
> If you prefer XENOCONFIG, please provide patches for the whole examples
> repos. :)
> 
>> +### Note: if you installed it into a non standard place add DESTDIR=/path/to/installed/xenomai"
> 
> The hint to DESTDIR is useful, but the explanation should be more like
> "if Xenomai was installed with DESTDIR set, the same must be provided here".
> 
>>  
>> -
>>  ### List of modules to be build
>>  MODULES =
>>  
>> @@ -14,6 +14,8 @@
>>  
>>  ### Note: to override the kernel source path, use "make KSRC=..."
>>  
>> +# default place to install the resulting binaries
>> +EXEC_PREFIX := $(DESTDIR)/usr/xenomai/bin
>>  
>>  
>>  ###### USER SPACE BUILD (no change required normally) ######
>> @@ -24,7 +26,9 @@
>>  ### Sanity check
>>  ifeq ($(XENOCONFIG),)
>>  all::
>> -	@echo ">>> Invoke make like this: \"make XENO=/path/to/xeno-config\" <<<"
>> +	@echo ">>> Invoke make like this: \"make XENOCONFIG=/path/to/xeno-config\" <<<"
>> +	@echo ">>> add KSRC=.. to override the default kernel source at /lib/modules/$(shell uname -r)/build <<<"
> 
> KSRC is unrelated here (user space part of the makefile).
> 
>> +	@echo ">>> add DESTDIR=/path/to/installed/xenomai if you installed it into a non standard place <<<"
> 
> See earlier comment.
> 
>>  	@echo
>>  endif
>>  
>> @@ -40,6 +44,9 @@
>>  clean::
>>  	$(RM) $(APPLICATIONS) *.o
>>  
>> +install::   $(APPLICATIONS)
>> +	cp $(APPLICATIONS) $(EXEC_PREFIX)/
>> +
> 
> NACK. I'd rather like to keep the makefile focused (the next step would
> be to add uninstall, then ...).
> 
>>  endif
>>  
>>  
>> @@ -80,3 +87,4 @@
>>  	$(RM) -R .tmp*
>>  
>>  endif
>> +
>>
>>

What does the hw_direct_io example do? As I see it, it's not related to 
Xenomai.

Wolfgang.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Xenomai-core] PPC405: DMA-problem solved!
  2007-01-20  8:04     ` Jan Kiszka
  2007-01-21 21:37       ` Wolfgang Grandegger
@ 2007-01-22  7:22       ` Niklaus Giger
  1 sibling, 0 replies; 8+ messages in thread
From: Niklaus Giger @ 2007-01-22  7:22 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 3583 bytes --]

(Forgot to cc @xenomai-core this e-mail sent yesterday to Jan)
Am Samstag, 20. Januar 2007 09:04 schrieben Sie:
> Niklaus Giger wrote:
<..>
> This demo is about how to use the driver API (/wrt interrupts) + how to
> do PPC4xx-specific DMA. So my suggestion:
>
> examples/rtdm/driver-api/dma-ppc4xx.c
Agreed. See new version in the attached patch.
>
> In any case, we need to resolve the arch dependency somehow. I guess
> it will  currently not fly when I kick the full build in examples/ for a
> non-PPC platform. Any *simple* way to catch this? Would also be
> applicable to the heartbeat-x86 example then, though this will not cause
> build troubles.
Is my proposed solution in the Makefile okay for you?
How do you kick your full build? Does it still work now?

<..>
> > + * The following patches must be applied to your kernel to fix bugs
>
> Which kernel? I guess this issue will not persist forever.
> > + *
> > http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025697.html +
> > * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025700.html
> > + *
> > + * Beware!
> > + * The kernel option PPC4xx DMA must be activated for this test.
>
> Please provide the full CONFIG_OPTION_NAME here.
Fixed.
<..>
> Why do we have a compiler warning here, why not a comment?
Fixed.
> > +#warning flush_dcache_all is a performance killer, but I do not know at
> > the +#warning moment how to flush only the parts needed
>
> Can we resolve this? Wolfgang?
> > +   flush_dcache_all(); /* from arch/ppc/kernel/misc.S */
I think we cannot fix this, as it is probably a weakness of the port to
PPC4xx. I tried various procedures *dcache* procedure which all lead to kernel 
oops. I changed the comment a little to reflect the change.

I looked also at dma_alloc_coherent, but this need a driver structure which I 
do not have in this example. I have no time at this moment to really dig 
deeper into the 4xx-DMA problems. But I might be forced to do it later once I 
get hands on our new PPC440EPx based board later (around March/April this 
year). I remember spending quite a few hours on this problem years ago on our 
first PPC403GA board (but running vxWorks).

<..>
>
> This demo will go to trunk, thus rtdm_irq_enable is no longer needed.
>
Didn't know. Fixed.
<..>
> Disabling is typically not needed, unless it is the only way to silence
> the IRQ source. Keep in mind that this disabling would be fatal if the
> IRQ happened to be shared (though unusual on PPC, AFAIK).
>
Thanks for catching this error. Fixed.
<..>
> > +install::   $(APPLICATIONS)
> > +   cp $(APPLICATIONS) $(EXEC_PREFIX)/
> > +
>
> NACK. I'd rather like to keep the makefile focused (the next step would
> be to add uninstall, then ...).
Added a comment on top of the Makefile about how to call it for cross 
compiling.

I changed the target to modules_install, but still think that this is useful 
for my use, eg. without it I have no direct way to access the kernel module 
from my NFS-mounted rootfs when I want to run a test on my target board.
Another solution would be to add an example script to cross compile like the 
following (tested) snippet
> make \
> -C   /usr/src/linux-2.6.19.1 \
> KSRC=/usr/src/linux-2.6.19.1 \
> ARCH=ppc \
> O=/usr/src/build-hcu3-2.6.19.1 \
> INSTALL_MOD_PATH=/home/hcu/rootfs/niklaus_2.6.19 \
> CROSS_COMPILE=ppc_4xx-  \
> PATH=/opt/eldk/4_0/usr/bin:$PATH \
> SUBDIRS=`pwd` \
> modules modules_install

Thanks for your careful review.

Best regards
---
Niklaus Giger

[-- Attachment #2: dma-ppc4xx.patch --]
[-- Type: text/x-diff, Size: 8378 bytes --]

Index: examples/rtdm/driver-api/dma-ppc4xx.c
===================================================================
--- examples/rtdm/driver-api/dma-ppc4xx.c	(Revision 0)
+++ examples/rtdm/driver-api/dma-ppc4xx.c	(Revision 0)
@@ -0,0 +1,169 @@
+/* * Written by Niklaus Giger <niklaus.giger@domain.hid>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ****************************************************************************
+ *
+ * This is an example howto write a Xenomai kernel module which handles a
+ * HW interrupt. The example is PPC4xx specific (testd on a PPC405 board)
+ * Probably also works on a PPC44x (not yet tested, needs a different irq?).
+ *
+ * Beware!
+ * The following patches had to be applied against the 2.6.19.2 linux kernel
+ * to fix bugs in arch/ppc/syslib/ppc4xx_dma.c
+ * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025697.html
+ * http://ozlabs.org/pipermail/linuxppc-embedded/2007-January/025700.html
+ *
+ * Beware!
+ * The kernel option CONFIG_PPC4xx_DMA must be activated for this test.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <asm/ppc4xx_dma.h>
+
+#include <rtdm/rtdm_driver.h>
+#include <rtdm/rtdm.h>
+rtdm_irq_t irq_handle;
+
+MODULE_DESCRIPTION("PPC4xx DMA3 interrupt demo");
+MODULE_AUTHOR("niklaus.giger@domain.hid");
+MODULE_LICENSE("GPL");
+
+#define DMA_NR 3
+int irq = DMA_NR + 5; /* DMA-x interrupt line  on PPC405GPr */
+
+#define TEST_STRING  "Could we use a DMA + interrupt to copy a string?"
+#define TEST_STRING2 "Should be overwritten."
+#define STRING_SIZE 128
+
+char *SRC;
+char *DST;
+
+static ppc_dma_ch_t p_init;
+
+#define show_irq(irq) 	{						\
+	printk("%32s: IRQ %2d uipr 0x%08x uier 0x%08x uisr 0x%08x\n",	\
+		__FUNCTION__, irq, 					\
+		mfdcr(DCRN_UIC_PR(UIC0)), mfdcr(DCRN_UIC_ER(UIC0)),	\
+		mfdcr(DCRN_UIC_SR(UIC0)));				\
+	printk("%32s: residue %d status 0x08%x cntrl 0x%08x\n",__FUNCTION__,\
+		ppc4xx_get_dma_residue(DMA_NR),				\
+		ppc4xx_get_dma_status(),				\
+		mfdcr(DCRN_DMACR0 + (DMA_NR * 0x8)));			\
+	printk("src at %p is %s\ndst at %p is %s\n", (char *)SRC,	\
+		SRC, &DST[0], &DST[0]); }
+
+void dma_mem_to_mem(void *src, void *dst, unsigned int length,
+			unsigned int use_interrupt)
+{
+	/* Do not use dma_mem_to_mem for OnChipMemory! It will not work. */
+	int res = 0;
+	memset((char *)&p_init, sizeof(p_init), 0);
+	p_init.polarity = 0;
+	p_init.pwidth   = PW_8;
+ 	res = ppc4xx_init_dma_channel(DMA_NR, &p_init);
+	if (res) {
+		printk("%32s: nit_dma_channel return %d %d bytes dest %p\n",
+			__FUNCTION__, res, length, dst);
+	}
+	res = ppc4xx_clr_dma_status(DMA_NR);
+	if (res) { 
+		printk("%32s: ppc4xx_clr_dma_status %d\n", __FUNCTION__, res);
+	}
+	/*
+	 * flush_dcache_all is a performance killer, but is does work on a
+	 * PPC405GPr as it does not use any of the DCU instructions like dcbf.
+	 * Procedures like flush_dcache_range produce:
+	 * Oops: kernel access of bad area, sig: 11 [#1]
+	 * Probably all these procedure should be fixe for PPC40x
+	*/
+	flush_dcache_all(); /* from arch/ppc/kernel/misc.S */
+	ppc4xx_set_dma_mode(DMA_NR, DMA_MODE_MM);
+	ppc4xx_set_src_addr(DMA_NR, virt_to_bus(src));
+	ppc4xx_set_dst_addr(DMA_NR, virt_to_bus(dst));
+	ppc4xx_set_dma_count(DMA_NR, length);
+	ppc4xx_enable_dma(DMA_NR);
+	if (use_interrupt) {
+		res = ppc4xx_enable_dma_interrupt(DMA_NR);
+	} else {
+		res = ppc4xx_disable_dma_interrupt(DMA_NR);
+	}
+	if (res) { 
+		printk("%32s: en/disable_dma_interrupt %d return %d per %d\n",
+		__FUNCTION__, use_interrupt, res, 
+		ppc4xx_get_peripheral_width(DMA_NR));
+	}
+}
+
+int dma_irq_handler(rtdm_irq_t *irq_handle)
+{
+	ppc4xx_disable_dma(DMA_NR);
+	ppc4xx_disable_dma_interrupt(DMA_NR);
+	show_irq(irq);
+	return RTDM_IRQ_HANDLED;
+}
+
+int init_module()
+{
+	if (rtdm_irq_request(&irq_handle, irq,  
+			dma_irq_handler, 0, "dma3_4xx", 0)) {
+		printk("%s:%s Error: rtdm_irq_request failed\n",
+			 __FILE__, __FUNCTION__);
+		return 1;
+	}
+	SRC = (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, 
+				get_order(STRING_SIZE));
+	DST = (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, 
+				get_order(STRING_SIZE));
+
+	strncpy(SRC, TEST_STRING,  STRING_SIZE);
+	strncpy(DST, TEST_STRING2, STRING_SIZE);
+
+	dma_mem_to_mem(SRC, DST, STRING_SIZE, 1);
+	if (ppc4xx_get_dma_residue(DMA_NR)) { 
+		printk("%32s: residue %d status 0x%x\n",__FUNCTION__,
+		ppc4xx_get_dma_residue(DMA_NR),
+		ppc4xx_get_dma_status());
+	}
+	return 0;
+	
+	
+}
+
+void cleanup_module ()
+{
+	ppc_dma_ch_t dma_ch;
+	if (ppc4xx_get_dma_residue(DMA_NR)) {
+		printk("%32s: residue %d status 0x%x\n",__FUNCTION__,
+		ppc4xx_get_dma_residue(DMA_NR),
+		ppc4xx_get_dma_status());
+	}
+	ppc4xx_get_channel_config(DMA_NR, &dma_ch);
+	printk("%32s: dma_ch.control 0x%x %d SRC %p %s\n",__FUNCTION__,
+		dma_ch.control,	dma_ch.pwidth, SRC,__TIME__);
+
+	if (rtdm_irq_free (&irq_handle)) {
+		printk("%32s: rtdm_irq_free failed\n",__FUNCTION__);
+	}
+	show_irq(irq);
+	if (strncmp(DST, TEST_STRING, STRING_SIZE) == 0) {
+		printk("%32s: DMA transfer succedded\n",__FUNCTION__);
+	} else {
+		printk("%32s: DMA transfer failed !!!!!\n",__FUNCTION__);
+	}
+}
Index: examples/rtdm/driver-api/Makefile
===================================================================
--- examples/rtdm/driver-api/Makefile	(Revision 2079)
+++ examples/rtdm/driver-api/Makefile	(Arbeitskopie)
@@ -1,14 +1,45 @@
 ###### CONFIGURATION ######
+# If Xenomai was installed with DESTDIR set, the same must be provided here.
+# To cross-compile you might call make with something like:
+# make 	ARCH=ppc \
+#	DESTDIR=/home/hcu/rootfs/linux_2.6.19 \
+#	O=/usr/src/build-hcu3-2.6.19.1 \
+#	KSRC=/usr/src/linux-2.6.19.1  \
+#	CROSS_COMPILE=ppc_4xx-  \
+#	PATH=/opt/eldk/4_0/usr/bin:$PATH \
+#	all
 
 ### List of applications to be build
-APPLICATIONS =
 
+PPC_APPLICATIONS =
+X86_APPLICATIONS =
+
 ### Note: to override the search path for the xeno-config script, use "make XENO=..."
 
-
 ### List of modules to be build
-MODULES = heartbeat-x86
+PPC_MODULES = dma-ppc4xx
+X86_MODULES = heartbeat-x86
 
+### Set modules to build depending on ARCH, defaults to currently running machine
+ifdef ARCH
+ifeq ($(ARCH), ppc)
+MODULES      ?= $(PPC_MODULES)
+APPLICATIONS ?= $(PPC_APPLICATIONS)
+else ifeq ($(ARCH), x86)
+MODULES      ?= $(X86_MODULES)
+APPLICATIONS ?= $(X86_APPLICATIONS)
+endif
+else	# ARCH not defined
+ifeq ($(shell uname -m), ppc)
+MODULES      ?= $(PPC_MODULES)
+APPLICATIONS ?= $(PPC_APPLICATIONS)
+endif
+ifeq (86,$(findstring 86,$(shell (uname -m))))
+MODULES      ?= $(X86_MODULES)
+APPLICATIONS ?= $(X86_APPLICATIONS)
+endif
+endif	# ARCH not defined
+
 ### Default to sources of currently running kernel
 KSRC ?= /lib/modules/$(shell uname -r)/build
 
@@ -57,9 +88,15 @@
 obj-m        := $(OBJS)
 EXTRA_CFLAGS := -I$(KSRC)/include/xenomai -I$(KSRC)/include/xenomai/posix $(ADD_CFLAGS)
 
-all::
+modules:
 	$(MAKE) -C $(KSRC) SUBDIRS=$(PWD) modules
 
+modules_install: modules
+	$(MAKE) -C $(KSRC) SUBDIRS=$(PWD) INSTALL_MOD_PATH=$(DESTDIR) modules modules_install
+
+all::	modules
+	$(MAKE) -C $(KSRC) SUBDIRS=$(PWD) modules
+
 ### Kernel 2.4
 else
 
@@ -67,16 +104,17 @@
 INCLUDE := -I$(KSRC)/include/xenomai -I$(KSRC)/include/xenomai/compat -I$(KSRC)/include/xenomai/posix
 CFLAGS  += $(shell $(MAKE) -s -C $(KSRC) CC=$(CC) ARCH=$(ARCH) SUBDIRS=$(PWD) modules) $(INCLUDE)
 
+## Target for capturing 2.4 module CFLAGS
+modules:
+	@echo "$(CFLAGS)"
+
 all:: $(OBJS)
 
 endif
 
-## Target for capturing 2.4 module CFLAGS
-modules:
-	@echo "$(CFLAGS)"
-
 clean::
-	$(RM) $(CLEANMOD) *.cmd *.o *.ko *.mod.c Module*.symvers
+	$(RM) $(CLEANMOD) .*.cmd *.o *.ko *.mod.c Module*.symvers
 	$(RM) -R .tmp*
 
 endif
+

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Xenomai-core] PPC405: DMA-problem solved!
  2007-01-21 21:37       ` Wolfgang Grandegger
@ 2007-01-22 14:06         ` Jan Kiszka
  0 siblings, 0 replies; 8+ messages in thread
From: Jan Kiszka @ 2007-01-22 14:06 UTC (permalink / raw)
  To: Wolfgang Grandegger; +Cc: xenomai

[-- Attachment #1: Type: text/plain, Size: 1887 bytes --]

Wolfgang Grandegger wrote:
>> In any case, we need to resolve the arch dependency somehow. I guess
>> it will  currently not fly when I kick the full build in examples/ for a
>> non-PPC platform. Any *simple* way to catch this? Would also be
>> applicable to the heartbeat-x86 example then, though this will not cause
>> build troubles.
> 
> The only simple way I see is referencing the configured kernel tree.

Sourcing $KSRC/.config into the makefile and evaluating the ARCH? Would
save us from passing ARCH on make invocation...

...
>>> +    int res = 0;
>>> +    memset((char *)&p_init, sizeof(p_init), 0);
>>> +    p_init.polarity = 0;
>>> +    p_init.pwidth   = PW_8;
>>> +     res = ppc4xx_init_dma_channel(DMA_NR, &p_init);
>>> +    if (res) {
>>> +        printk("%32s: nit_dma_channel return %d %d bytes dest %p\n",
>>> +            __FUNCTION__, res, length, dst);
>>> +    }
>>> +    res = ppc4xx_clr_dma_status(DMA_NR);
>>> +    if (res) { +        printk("%32s: ppc4xx_clr_dma_status %d\n",
>>> __FUNCTION__, res);
>>> +    }
>>> +#warning flush_dcache_all is a performance killer, but I do not know
>>> at the +#warning moment how to flush only the parts needed
>>
>> Can we resolve this? Wolfgang?
> 
> flush_dcache_range should do the job. Or even better use the DMA-API
> described in Documentation/DMA-API.txt to get DMA'able memory (as
> pointed out recently on the linuxppc-emmbedded ML).

I definitely prefer to have a tested variant here that is as little
invasive as possible. This is "educational" code, so we should not
spread suboptimal patterns.

>>> +    if (rtdm_irq_free (&irq_handle)) {
>>> +        printk("%32s: rtdm_irq_free failed\n",__FUNCTION__);
>>> +    }
>>> +    show_irq(irq);
>>> +}
> 
> And should we not also use rtdm_prinkt()?

Not strictly required here, we are in non-rt context.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 250 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2007-01-22 14:06 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-01-17 22:33 [Xenomai-core] PPC405: DMA-Problem with OCM (interrupt-example) Niklaus Giger
2007-01-18  0:26 ` Jan Kiszka
2007-01-18  8:31 ` Wolfgang Grandegger
2007-01-19 23:06   ` [Xenomai-core] PPC405: DMA-problem solved! Niklaus Giger
2007-01-20  8:04     ` Jan Kiszka
2007-01-21 21:37       ` Wolfgang Grandegger
2007-01-22 14:06         ` Jan Kiszka
2007-01-22  7:22       ` Niklaus Giger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.