Reply by Mark Crow May 8, 20072007-05-08
Great info. I missed the "APB access" point. Thanks for the heads up. Now
I need to find out if disabling the DMA during a watchdog feed will disrupt
a DMA in progress. If so (my guess is it probably will), then disabling the
watchdog during DMA operations will be the only choice.

Thanks again

_____

From: l... [mailto:l...] On Behalf Of
Daniel Gelbgras
Sent: Tuesday, May 08, 2007 3:43 PM
To: l...
Subject: Re: [lpc2000] Re: DMA->SSP/SPI Mystery on LPC2468

Hi Mark,

just about Watchdog problems:
extract of the LPC2468 Erratsheet :

"WDT.1:Accessing non-Watchdog APB registers
in the middle of the feed sequence causes a reset
Problem:After writing 0xAA to WDFEED, any APB register access
other than writing 0x55 to WDFEED may cause an immediate reset.
...
Workaround:Avoid APB accesses in the middle of the feed sequence.
This implies that interrupts and the GPDMA should be disabled
while feeding the Watchdog"

regards
Daniel

----- Original Message -----
From: "markcrow" >
To: .com>
Sent: Tuesday, May 08, 2007 5:21 PM
Subject: [lpc2000] Re: DMA->SSP/SPI Mystery on LPC2468

Just a follow up; I looked at your code and discovered that mine was
the same...AND I'm still getting the watchdog reset.

As it turns out, if a watchdog feed is performed when DMA is enabled
(in the DMA config register) a watchdog feed will cause a watchdog
reset. I'm going to ask NXP to look into this.

RE: the code below; DMACC0Control_SBSize_BIT and
DMACC0Control_DBSize_BIT weren't defined so I don't know for sure
what the two related fields in the DMA Channel 0 control register
were set to. However, I have tried various combinations and only '1'
will work in both fields for some reason. DMA is transferring to
SSP0 which has an 8-byte FIFO and I'd like to set the dest burst size
to 8 (as well as the source burst size). Maybe I misunderstand what
a 'burst size' is???

--- In lpc2000@yahoogroups .com,
"arjanverheij"
wrote:
>
> Gents,
>
> Following is the code I used to get SPI going with DMA.
> A couple of notes:
> - the DMA controller can't access the normal RAM, so buffers and
LLI
> structures have to be in USB RAM or external RAM
> - I got weird things to happen (debugger lock up etc.) if I write
to
> DMACC1Configuration register BEFORE setting the enable bit in
> DMACConfiguration
>
> About the code:
> - I soldered SSP0 to SSP1 (4 physical wires)
> - I call SPIwithDMA_Init from Main, after enabling interrupts and
> starting the RTC
> - SPIwithDMA_Init does 3 tests, and on my Embedded Artists 2468
> board they all complete without errors
> - I use Rowley CrossWorks
> #include "platform.h"
> #include
> #include #define VICSourceDMA 25
>
> #define USB_RAM 0x7FD00000
> #define USB_RAM_SIZE 0x00004000 //16KB (8KB on LPC23xx)
> #define ETH_RAM 0x7FE00000
> #define ETH_RAM_SIZE 0x00004000 //16KB
> #define BAT_RAM 0xE0084000
> #define BAT_RAM_SIZE 0x00000800 //2KB
>
> byte* sendBuf = (byte*)0x7FD00000;
> byte* recvBuf = (byte*)0x7FD00100;
> int sendFrameSize = 50;
> int recvFrameSize = 50;
> typedef struct tagDMAControl
> {
> unsigned TransferSize : 12;
> unsigned SrcBurstSize : 3; //000=1, 001=4, 010=8,
> 011, 1002, 101d, 1108, 111%6
> unsigned DstBurstSize : 3;
> unsigned SrcWidth : 3; //000its,
> 001bits, 0102bits
> unsigned DstWidth : 3;
> unsigned reseved : 2;
> unsigned SrcIncrement : 1;
> unsigned DstIncrement : 1;
> unsigned Protection : 3;
> unsigned TCIntEnable : 1;
> } DMAControl;
>
> typedef struct tagDMA_LinkedListItem
> {
> void* Source;
> void* Destination;
> void* NextLLI;
> DMAControl Control;
> } DMA_LinkedListItem;
> //Init SSP0 for master mode, 6Mbits/s
> void SSP0_Init()
> {
> //set I/O pin config for LPC2468
> //available pins:
> //SCK0 P0.15 P1.20 P2.22
> //SSEL0 p0.16 P1.21 P2.23
> //MISO0 p0.17 P1.23 P2.26
> //MOSI0 p0.18 P1.24 P2.27
>
> PINSEL0 |= (2 << 30); //SCK0 on P0.15
> PINSEL1 |= (2 << 0); //SSEL0 on P0.16
> PINSEL1 |= (2 << 2); //MISO0 on P0.17
> PINSEL1 |= (2 << 4); //MOSI0 on P0.18
>
> // enable clock to SSP0 just to make sure. By default, it's
> enabled already
> PCONP |= PCONP_PCSSP0;
> //set PCLK divider for SSP0 to 1
> PCLKSEL1 = (PCLKSEL1 & ~PCLKSEL1_PCLK_SSP0_MASK) | (1 <<
> PCLKSEL1_PCLK_SSP0_BIT);
>
> //NOTE: in slave mode CPSR must be >
> SSP0CPSR = 12; //SCK = CCLK / PCLKdiv /
> CPSR / SCR = 72/1/12/1 = 6 MHz
> SSP0CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
> SSP0CR1 = SSP0CR1_SSE; //Master mode, SSP enabled
>
> }
>
> //init SSP1 for slave mode, 6Mbits/s
> void SSP1_Init()
> {
> //set I/O pin config for LPC2468
> //available pins:
> //SCK1 P0.7 P1.31 P4.20
> //SSEL1 p0.6 P0.14 P4.21
> //MISO1 p0.8 P0.12 P4.22
> //MOSI1 p0.9 P0.13 P2.23
>
> PINSEL0 |= (2 << 14); //SCK0 on P0.7
> PINSEL0 |= (2 << 12); //SSEL0 on P0.6
> PINSEL0 |= (2 << 16); //MISO0 on P0.8
> PINSEL0 |= (2 << 18); //MOSI0 on P0.9
>
> // enable clock to SSP0 just to make sure. By default, it's
> enabled already
> PCONP |= PCONP_PCSSP1;
> //set PCLK divider for SSP0 to 1
> PCLKSEL0 = (PCLKSEL0 & ~PCLKSEL0_PCLK_SSP1_MASK) | (1 <<
> PCLKSEL0_PCLK_SSP1_BIT);
>
> //NOTE: in slave mode CPSR must be >
> SSP1CPSR = 12; //SCK = CCLK / PCLKdiv /
> CPSR / SCR = 72/1/12/1 = 6 MHz
> SSP1CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
> SSP1CR1 = SSP1CR1_MS | SSP1CR1_SSE; //Slave mode, SSP
> enabled
> }
> //this method tests transfering bytes from SSP0 to SSP1 and vice
> versa
> //returns number of errors
> int SPIwithDMA_TestWithoutDMA(int n)
> {
> int errors = 0;
> int i;
> unsigned short s, r, s2, r2;
>
> for (i=0; i > {
> s = (unsigned short)(123 + (i << 5));
> s2 = (unsigned short)(567 + (i << 6));
>
> SSP1DR = s2;
> SSP0DR = s;
> while ( !(SSP1SR & SSP1SR_RNE) )
> ;
> r = SSP1DR;
> r2 = SSP0DR;
> if (r != s || r2 != s2)
> errors++;
> }
>
> return errors;
> }
> volatile uint PacketsReceived = 0;
> volatile uint DMAErrCount = 0;
> void DMAHandler( void )
> {
> uint regVal;
>
> regVal = DMACIntTCStatus;
> if ( regVal )
> {
> if (regVal & DMACIntTCStatus_IntTCStatus1) //then it
> was the receive channel
> PacketsReceived++;
> DMACIntTCClear |= regVal;
> }
>
> regVal = DMACIntErrorStatus;
> if ( regVal )
> {
> DMAErrCount++;
> DMACIntErrClr |= regVal;
> }
>
> #ifdef VECTORED_IRQ_INTERRUPTS
> VICVectAddr = 0; /* Acknowledge Interrupt */
> #endif //otherwise CrossWorks irq_handler will take care of
this
> }
> bool DMA_Init()
> {
> /* USB RAM is used for test.
> Please note, Ethernet has its own SRAM, but GPDMA can't
> access
> that. GPDMA can access USB SRAM and IRAM. Ethernet DMA
> controller can
> access both IRAM and Ethernet SRAM. */
> PCONP |= PCONP_PCGPDMA; /* Enable GPDMA clock */
>
> /* clear all interrupts on both channels */
> DMACIntTCClear = 0x03;
> DMACIntErrClr = 0x03;
>
> //install DMA interrupt handler
> ctl_set_isr(VICSourceDMA, 1, CTL_ISR_TRIGGER_FIXED,
> DMAHandler, 0);
> ctl_unmask_isr(VICSourceDMA);
>
> //NOTE: it seems the following needs to execute before
> accessing
> // DMACC1Configuration, otherwise the CPU locks up
> DMACConfiguration = 0x01; /* Enable DMA channels,
> little endian */
>
> return true;
> }
> //This function tries to transfer 1 packet from SSP0 to SSP1 with
DMA
> int SPIwithDMA_TestDMATransfer()
> {
> int i, wait=0, errors=0;
>
> //disable SSP from sending DMA requests
> SSP1DMACR = 0;
> SSP0DMACR = 0;
>
> /*Set up DMA channel 0 to stream data from memory to SSP0 */
> DMACC0SrcAddr = (int)sendBuf;
> DMACC0DestAddr = (int)&SSP0DR;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC0Control > (sendFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (1 << DMACC0Control_SI_BIT)
> //source increment
> | (0 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
>
> /*Set up DMA channel 1 to stream data from SSP1 to memory */
> DMACC1SrcAddr = (int)&SSP1DR;
> DMACC1DestAddr = (int)recvBuf;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC1Control > (recvFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (0 << DMACC0Control_SI_BIT)
> //source increment
> | (1 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
> //fill send packet with test pattern
> for(i=0; i<0x100; i++)
> {
> sendBuf[i] = i;
> recvBuf[i] = 0;
> }
>
> //src = n/a, dest = SSP0Tx, flow = M2P by P control,
> DMACC0Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (0 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (1 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (1 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> //src = SSP1Rx, dest = n/a, flow = P2M by P control,
> DMACC1Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (3 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (2 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> PacketsReceived = 0;
>
> //Enable the SSP DMA requests, receive first
> SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
> | (0 << SSP0DMACR_TXDMAE_BIT);
> SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
> | (1 << SSP0DMACR_TXDMAE_BIT);
>
> while(PacketsReceived < 1)
> wait++;
>
> //check received data
> for(i=0; i > {
> if (recvBuf[i] != i)
> errors++;
> }
>
> return errors;
> }
> //declare buffers and LLI structs in USB RAM
> byte* TxBuf1 = (byte*)(USB_RAM + 0x200);
> byte* TxBuf2 = (byte*)(USB_RAM + 0x300);
> byte* RxBuf1 = (byte*)(USB_RAM + 0x400);
> byte* RxBuf2 = (byte*)(USB_RAM + 0x500);
> DMA_LinkedListItem* LLI_Tx1 = (DMA_LinkedListItem*)(USB_RAM +
0x600);
> DMA_LinkedListItem* LLI_Tx2 = (DMA_LinkedListItem*)(USB_RAM +
0x610);
> DMA_LinkedListItem* LLI_Rx1 = (DMA_LinkedListItem*)(USB_RAM +
0x620);
> DMA_LinkedListItem* LLI_Rx2 = (DMA_LinkedListItem*)(USB_RAM +
0x630);
>
> int SPIwithDMA_TestLLI()
> {
> int i, wait=0, errors=0;
> unsigned long t0, t1;
>
> //disable both DMA channels while configuring
> // DMACC0Configuration &= ~DMACC0Configuration_E_BIT;
> // DMACC1Configuration &= ~DMACC1Configuration_E_BIT;
>
> //disable SSP from sending DMA requests
> SSP1DMACR = 0;
> SSP0DMACR = 0;
>
> //fill send packet with test pattern
> for(i=0; i<0x100; i++)
> {
> sendBuf[i] = i;
> recvBuf[i] = 0;
> }
>
> /*Set up DMA channel 0 to stream data from memory to SSP0 */
> DMACC0SrcAddr = (int)sendBuf;
> DMACC0DestAddr = (int)&SSP0DR;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC0Control > (sendFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (1 << DMACC0Control_SI_BIT)
> //source increment
> | (0 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
>
> /*Set up DMA channel 1 to stream data from SSP1 to memory */
> DMACC1SrcAddr = (int)&SSP1DR;
> DMACC1DestAddr = (int)recvBuf;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC1Control > (recvFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (0 << DMACC0Control_SI_BIT)
> //source increment
> | (1 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
> //src = n/a, dest = SSP0Tx, flow = M2P by P control,
> DMACC0Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (0 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (1 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> //src = SSP1Rx, dest = n/a, flow = P2M by P control,
> DMACC1Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (3 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (2 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> LLI_Tx1->Source = (void*)
> TxBuf1;
> LLI_Tx1->Destination = (void*)
> &SSP0DR;
> LLI_Tx1->NextLLI > (void*)LLI_Tx2;
> LLI_Tx1->Control.TransferSize = 50;
> LLI_Tx1->Control.SrcBurstSize = 1; //000=1, 001=4,
> 010=8, 011, 1002, 101d, 1108, 111%6
> LLI_Tx1->Control.DstBurstSize = 1;
> LLI_Tx1->Control.SrcWidth = 1; //000its,
> 001bits, 0102bits
> LLI_Tx1->Control.DstWidth = 1;
> LLI_Tx1->Control.SrcIncrement = 1;
> LLI_Tx1->Control.DstIncrement = 0;
> LLI_Tx1->Control.Protection = 0;
> LLI_Tx1->Control.TCIntEnable = 1;
>
> *LLI_Tx2 = *LLI_Tx1;
> LLI_Tx2->Source = (void*)TxBuf2;
> LLI_Tx2->NextLLI = null;
>
> LLI_Rx1->Source = (void*)
> &SSP1DR;
> LLI_Rx1->Destination = (void*)
> RxBuf1;
> LLI_Rx1->NextLLI > (void*)LLI_Rx2;
> LLI_Rx1->Control.TransferSize = 50;
> LLI_Rx1->Control.SrcBurstSize = 1; //000=1, 001=4,
> 010=8, 011, 1002, 101d, 1108, 111%6
> LLI_Rx1->Control.DstBurstSize = 1;
> LLI_Rx1->Control.SrcWidth = 1; //000its,
> 001bits, 0102bits
> LLI_Rx1->Control.DstWidth = 1;
> LLI_Rx1->Control.SrcIncrement = 0;
> LLI_Rx1->Control.DstIncrement = 1;
> LLI_Rx1->Control.Protection = 0;
> LLI_Rx1->Control.TCIntEnable = 1;
>
> *LLI_Rx2 = *LLI_Rx1;
> LLI_Rx2->Destination = (void*)RxBuf2;
> LLI_Rx2->NextLLI = null;
>
> for (i=0; i<0x100; i++) TxBuf1[i] = 0xAA;
> for (i=0; i<0x100; i++) TxBuf2[i] = 0xBB;
> for (i=0; i<0x100; i++) RxBuf1[i] = 0x00;
> for (i=0; i<0x100; i++) RxBuf2[i] = 0x00;
>
> DMACC0LLI = (int)LLI_Tx1;
> DMACC1LLI = (int)LLI_Rx1;
>
> PacketsReceived = 0;
> t0 = CTC;
> //Enable the SSP DMA requests, receiver first
> SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
> | (0 << SSP0DMACR_TXDMAE_BIT);
> SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
> | (1 << SSP0DMACR_TXDMAE_BIT);
>
> while(PacketsReceived < 3)
> wait++;
> t1 = CTC;
> debug_printf("TestLLI wait cycles: %d \r\n", wait);
> debug_printf("TestLLI time (ticks): %d \r\n", t1-t0);
>
> //check received data
> for(i=0; i > if (recvBuf[i] != i)
> errors++;
> for (i=0; i<50; i++)
> if (RxBuf1[i] != TxBuf1[i])
> errors++;
> for (i=0; i<50; i++)
> if (RxBuf2[i] != TxBuf2[i])
> errors++;
>
> return errors;
> }
> void SPIwithDMA_Init()
> {
> int e, w;
>
> SSP0_Init();
> SSP1_Init();
> DMA_Init();
>
> e = SPIwithDMA_TestWithoutDMA(1000000);
> debug_printf("TestWithoutDMA returned %d errors\r\n", e);
> e = SPIwithDMA_TestDMATransfer();
> debug_printf("TestDMATransfer returned %d errors\r\n", e);
> e = SPIwithDMA_TestLLI();
> debug_printf("TestLLI returned %d errors\r\n", e);
> }
>
> --- In lpc2000@yahoogroups .com, "Ivan
Wu" wrote:
> >
> > Hi Mark,
> >
> > can you send me your code?
> > I am also have problem using the SPI.
> > Many thanks!
> >
> >
> > On 5/5/07, arjanverheij wrote:
> > >
> > > Mark,
> > >
> > > I just now got SSP with DMA working on a LPC2468. If you haven't
> > > resolved your problem I can send you my code.
> > >
> > > Arjan.
> > >
> > > --- In lpc2000@yahoogroups .com
> 40yahoogroups.com>, "markcrow"
> > > wrote:
> > > >
> > > > Using the sample code (from
> > > code.lpc23xx.lpc24xx.peripherals.usvision)
> > > > I got GP DMA to drive the SSP1 port (in SPI mode) on a
> LPC2368. I
> > > > ported that code over to a LPC2468 and now it won't work
(using
> > > SSP0
> > > > this time and also in SPI mode). I get a watchdog reset when I
> > > set the
> > > > Channel Enable bit in the Channel 0 configuration register. I
> > > have
> > > > meticulously checked every setting and every address on every
> > > GPDMA
> > > > register and can make no sense of this. The watchdog reset is
> not
> > > > legitimate as the watchdog timer is set to over 3 seconds and
> the
> > > reset
> > > > occurs instantaneously when the register is written to.
> > > >
> > > > Has anyone seen anything like this? Anyone using a LPC24xx and
> > > driving
> > > > an SSP via DMA with success?
> > > >
> > > > Thanks
> > > >
> > >
> > >
> > >
> >
> >
> >
> > --
> > B.R.
> > Ivan Wu (Өǿ)
> >
> >
> >
>
Yahoo! Groups Links

An Engineer's Guide to the LPC2100 Series

Reply by Daniel Gelbgras May 8, 20072007-05-08
Hi Mark,

just about Watchdog problems:
extract of the LPC2468 Erratsheet :

"WDT.1:Accessing non-Watchdog APB registers
in the middle of the feed sequence causes a reset
Problem:After writing 0xAA to WDFEED, any APB register access
other than writing 0x55 to WDFEED may cause an immediate reset.
...
Workaround:Avoid APB accesses in the middle of the feed sequence.
This implies that interrupts and the GPDMA should be disabled
while feeding the Watchdog"

regards
Daniel

----- Original Message -----
From: "markcrow"
To:
Sent: Tuesday, May 08, 2007 5:21 PM
Subject: [lpc2000] Re: DMA->SSP/SPI Mystery on LPC2468
Just a follow up; I looked at your code and discovered that mine was
the same...AND I'm still getting the watchdog reset.

As it turns out, if a watchdog feed is performed when DMA is enabled
(in the DMA config register) a watchdog feed will cause a watchdog
reset. I'm going to ask NXP to look into this.

RE: the code below; DMACC0Control_SBSize_BIT and
DMACC0Control_DBSize_BIT weren't defined so I don't know for sure
what the two related fields in the DMA Channel 0 control register
were set to. However, I have tried various combinations and only '1'
will work in both fields for some reason. DMA is transferring to
SSP0 which has an 8-byte FIFO and I'd like to set the dest burst size
to 8 (as well as the source burst size). Maybe I misunderstand what
a 'burst size' is???
--- In l..., "arjanverheij"
wrote:
>
> Gents,
>
> Following is the code I used to get SPI going with DMA.
> A couple of notes:
> - the DMA controller can't access the normal RAM, so buffers and
LLI
> structures have to be in USB RAM or external RAM
> - I got weird things to happen (debugger lock up etc.) if I write
to
> DMACC1Configuration register BEFORE setting the enable bit in
> DMACConfiguration
>
> About the code:
> - I soldered SSP0 to SSP1 (4 physical wires)
> - I call SPIwithDMA_Init from Main, after enabling interrupts and
> starting the RTC
> - SPIwithDMA_Init does 3 tests, and on my Embedded Artists 2468
> board they all complete without errors
> - I use Rowley CrossWorks
> #include "platform.h"
> #include
> #include #define VICSourceDMA 25
>
> #define USB_RAM 0x7FD00000
> #define USB_RAM_SIZE 0x00004000 //16KB (8KB on LPC23xx)
> #define ETH_RAM 0x7FE00000
> #define ETH_RAM_SIZE 0x00004000 //16KB
> #define BAT_RAM 0xE0084000
> #define BAT_RAM_SIZE 0x00000800 //2KB
>
> byte* sendBuf = (byte*)0x7FD00000;
> byte* recvBuf = (byte*)0x7FD00100;
> int sendFrameSize = 50;
> int recvFrameSize = 50;
> typedef struct tagDMAControl
> {
> unsigned TransferSize : 12;
> unsigned SrcBurstSize : 3; //000=1, 001=4, 010=8,
> 011, 1002, 101d, 1108, 111%6
> unsigned DstBurstSize : 3;
> unsigned SrcWidth : 3; //000its,
> 001bits, 0102bits
> unsigned DstWidth : 3;
> unsigned reseved : 2;
> unsigned SrcIncrement : 1;
> unsigned DstIncrement : 1;
> unsigned Protection : 3;
> unsigned TCIntEnable : 1;
> } DMAControl;
>
> typedef struct tagDMA_LinkedListItem
> {
> void* Source;
> void* Destination;
> void* NextLLI;
> DMAControl Control;
> } DMA_LinkedListItem;
> //Init SSP0 for master mode, 6Mbits/s
> void SSP0_Init()
> {
> //set I/O pin config for LPC2468
> //available pins:
> //SCK0 P0.15 P1.20 P2.22
> //SSEL0 p0.16 P1.21 P2.23
> //MISO0 p0.17 P1.23 P2.26
> //MOSI0 p0.18 P1.24 P2.27
>
> PINSEL0 |= (2 << 30); //SCK0 on P0.15
> PINSEL1 |= (2 << 0); //SSEL0 on P0.16
> PINSEL1 |= (2 << 2); //MISO0 on P0.17
> PINSEL1 |= (2 << 4); //MOSI0 on P0.18
>
> // enable clock to SSP0 just to make sure. By default, it's
> enabled already
> PCONP |= PCONP_PCSSP0;
> //set PCLK divider for SSP0 to 1
> PCLKSEL1 = (PCLKSEL1 & ~PCLKSEL1_PCLK_SSP0_MASK) | (1 <<
> PCLKSEL1_PCLK_SSP0_BIT);
>
> //NOTE: in slave mode CPSR must be >
> SSP0CPSR = 12; //SCK = CCLK / PCLKdiv /
> CPSR / SCR = 72/1/12/1 = 6 MHz
> SSP0CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
> SSP0CR1 = SSP0CR1_SSE; //Master mode, SSP enabled
>
> }
>
> //init SSP1 for slave mode, 6Mbits/s
> void SSP1_Init()
> {
> //set I/O pin config for LPC2468
> //available pins:
> //SCK1 P0.7 P1.31 P4.20
> //SSEL1 p0.6 P0.14 P4.21
> //MISO1 p0.8 P0.12 P4.22
> //MOSI1 p0.9 P0.13 P2.23
>
> PINSEL0 |= (2 << 14); //SCK0 on P0.7
> PINSEL0 |= (2 << 12); //SSEL0 on P0.6
> PINSEL0 |= (2 << 16); //MISO0 on P0.8
> PINSEL0 |= (2 << 18); //MOSI0 on P0.9
>
> // enable clock to SSP0 just to make sure. By default, it's
> enabled already
> PCONP |= PCONP_PCSSP1;
> //set PCLK divider for SSP0 to 1
> PCLKSEL0 = (PCLKSEL0 & ~PCLKSEL0_PCLK_SSP1_MASK) | (1 <<
> PCLKSEL0_PCLK_SSP1_BIT);
>
> //NOTE: in slave mode CPSR must be >
> SSP1CPSR = 12; //SCK = CCLK / PCLKdiv /
> CPSR / SCR = 72/1/12/1 = 6 MHz
> SSP1CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
> SSP1CR1 = SSP1CR1_MS | SSP1CR1_SSE; //Slave mode, SSP
> enabled
> }
> //this method tests transfering bytes from SSP0 to SSP1 and vice
> versa
> //returns number of errors
> int SPIwithDMA_TestWithoutDMA(int n)
> {
> int errors = 0;
> int i;
> unsigned short s, r, s2, r2;
>
> for (i=0; i > {
> s = (unsigned short)(123 + (i << 5));
> s2 = (unsigned short)(567 + (i << 6));
>
> SSP1DR = s2;
> SSP0DR = s;
> while ( !(SSP1SR & SSP1SR_RNE) )
> ;
> r = SSP1DR;
> r2 = SSP0DR;
> if (r != s || r2 != s2)
> errors++;
> }
>
> return errors;
> }
> volatile uint PacketsReceived = 0;
> volatile uint DMAErrCount = 0;
> void DMAHandler( void )
> {
> uint regVal;
>
> regVal = DMACIntTCStatus;
> if ( regVal )
> {
> if (regVal & DMACIntTCStatus_IntTCStatus1) //then it
> was the receive channel
> PacketsReceived++;
> DMACIntTCClear |= regVal;
> }
>
> regVal = DMACIntErrorStatus;
> if ( regVal )
> {
> DMAErrCount++;
> DMACIntErrClr |= regVal;
> }
>
> #ifdef VECTORED_IRQ_INTERRUPTS
> VICVectAddr = 0; /* Acknowledge Interrupt */
> #endif //otherwise CrossWorks irq_handler will take care of
this
> }
> bool DMA_Init()
> {
> /* USB RAM is used for test.
> Please note, Ethernet has its own SRAM, but GPDMA can't
> access
> that. GPDMA can access USB SRAM and IRAM. Ethernet DMA
> controller can
> access both IRAM and Ethernet SRAM. */
> PCONP |= PCONP_PCGPDMA; /* Enable GPDMA clock */
>
> /* clear all interrupts on both channels */
> DMACIntTCClear = 0x03;
> DMACIntErrClr = 0x03;
>
> //install DMA interrupt handler
> ctl_set_isr(VICSourceDMA, 1, CTL_ISR_TRIGGER_FIXED,
> DMAHandler, 0);
> ctl_unmask_isr(VICSourceDMA);
>
> //NOTE: it seems the following needs to execute before
> accessing
> // DMACC1Configuration, otherwise the CPU locks up
> DMACConfiguration = 0x01; /* Enable DMA channels,
> little endian */
>
> return true;
> }
> //This function tries to transfer 1 packet from SSP0 to SSP1 with
DMA
> int SPIwithDMA_TestDMATransfer()
> {
> int i, wait=0, errors=0;
>
> //disable SSP from sending DMA requests
> SSP1DMACR = 0;
> SSP0DMACR = 0;
>
> /*Set up DMA channel 0 to stream data from memory to SSP0 */
> DMACC0SrcAddr = (int)sendBuf;
> DMACC0DestAddr = (int)&SSP0DR;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC0Control > (sendFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (1 << DMACC0Control_SI_BIT)
> //source increment
> | (0 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
>
> /*Set up DMA channel 1 to stream data from SSP1 to memory */
> DMACC1SrcAddr = (int)&SSP1DR;
> DMACC1DestAddr = (int)recvBuf;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC1Control > (recvFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (0 << DMACC0Control_SI_BIT)
> //source increment
> | (1 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
> //fill send packet with test pattern
> for(i=0; i<0x100; i++)
> {
> sendBuf[i] = i;
> recvBuf[i] = 0;
> }
>
> //src = n/a, dest = SSP0Tx, flow = M2P by P control,
> DMACC0Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (0 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (1 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (1 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> //src = SSP1Rx, dest = n/a, flow = P2M by P control,
> DMACC1Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (3 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (2 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> PacketsReceived = 0;
>
> //Enable the SSP DMA requests, receive first
> SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
> | (0 << SSP0DMACR_TXDMAE_BIT);
> SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
> | (1 << SSP0DMACR_TXDMAE_BIT);
>
> while(PacketsReceived < 1)
> wait++;
>
> //check received data
> for(i=0; i > {
> if (recvBuf[i] != i)
> errors++;
> }
>
> return errors;
> }
> //declare buffers and LLI structs in USB RAM
> byte* TxBuf1 = (byte*)(USB_RAM + 0x200);
> byte* TxBuf2 = (byte*)(USB_RAM + 0x300);
> byte* RxBuf1 = (byte*)(USB_RAM + 0x400);
> byte* RxBuf2 = (byte*)(USB_RAM + 0x500);
> DMA_LinkedListItem* LLI_Tx1 = (DMA_LinkedListItem*)(USB_RAM +
0x600);
> DMA_LinkedListItem* LLI_Tx2 = (DMA_LinkedListItem*)(USB_RAM +
0x610);
> DMA_LinkedListItem* LLI_Rx1 = (DMA_LinkedListItem*)(USB_RAM +
0x620);
> DMA_LinkedListItem* LLI_Rx2 = (DMA_LinkedListItem*)(USB_RAM +
0x630);
>
> int SPIwithDMA_TestLLI()
> {
> int i, wait=0, errors=0;
> unsigned long t0, t1;
>
> //disable both DMA channels while configuring
> // DMACC0Configuration &= ~DMACC0Configuration_E_BIT;
> // DMACC1Configuration &= ~DMACC1Configuration_E_BIT;
>
> //disable SSP from sending DMA requests
> SSP1DMACR = 0;
> SSP0DMACR = 0;
>
> //fill send packet with test pattern
> for(i=0; i<0x100; i++)
> {
> sendBuf[i] = i;
> recvBuf[i] = 0;
> }
>
> /*Set up DMA channel 0 to stream data from memory to SSP0 */
> DMACC0SrcAddr = (int)sendBuf;
> DMACC0DestAddr = (int)&SSP0DR;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC0Control > (sendFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (1 << DMACC0Control_SI_BIT)
> //source increment
> | (0 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
>
> /*Set up DMA channel 1 to stream data from SSP1 to memory */
> DMACC1SrcAddr = (int)&SSP1DR;
> DMACC1DestAddr = (int)recvBuf;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC1Control > (recvFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (0 << DMACC0Control_SI_BIT)
> //source increment
> | (1 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
> //src = n/a, dest = SSP0Tx, flow = M2P by P control,
> DMACC0Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (0 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (1 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> //src = SSP1Rx, dest = n/a, flow = P2M by P control,
> DMACC1Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (3 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (2 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> LLI_Tx1->Source = (void*)
> TxBuf1;
> LLI_Tx1->Destination = (void*)
> &SSP0DR;
> LLI_Tx1->NextLLI > (void*)LLI_Tx2;
> LLI_Tx1->Control.TransferSize = 50;
> LLI_Tx1->Control.SrcBurstSize = 1; //000=1, 001=4,
> 010=8, 011, 1002, 101d, 1108, 111%6
> LLI_Tx1->Control.DstBurstSize = 1;
> LLI_Tx1->Control.SrcWidth = 1; //000its,
> 001bits, 0102bits
> LLI_Tx1->Control.DstWidth = 1;
> LLI_Tx1->Control.SrcIncrement = 1;
> LLI_Tx1->Control.DstIncrement = 0;
> LLI_Tx1->Control.Protection = 0;
> LLI_Tx1->Control.TCIntEnable = 1;
>
> *LLI_Tx2 = *LLI_Tx1;
> LLI_Tx2->Source = (void*)TxBuf2;
> LLI_Tx2->NextLLI = null;
>
> LLI_Rx1->Source = (void*)
> &SSP1DR;
> LLI_Rx1->Destination = (void*)
> RxBuf1;
> LLI_Rx1->NextLLI > (void*)LLI_Rx2;
> LLI_Rx1->Control.TransferSize = 50;
> LLI_Rx1->Control.SrcBurstSize = 1; //000=1, 001=4,
> 010=8, 011, 1002, 101d, 1108, 111%6
> LLI_Rx1->Control.DstBurstSize = 1;
> LLI_Rx1->Control.SrcWidth = 1; //000its,
> 001bits, 0102bits
> LLI_Rx1->Control.DstWidth = 1;
> LLI_Rx1->Control.SrcIncrement = 0;
> LLI_Rx1->Control.DstIncrement = 1;
> LLI_Rx1->Control.Protection = 0;
> LLI_Rx1->Control.TCIntEnable = 1;
>
> *LLI_Rx2 = *LLI_Rx1;
> LLI_Rx2->Destination = (void*)RxBuf2;
> LLI_Rx2->NextLLI = null;
>
> for (i=0; i<0x100; i++) TxBuf1[i] = 0xAA;
> for (i=0; i<0x100; i++) TxBuf2[i] = 0xBB;
> for (i=0; i<0x100; i++) RxBuf1[i] = 0x00;
> for (i=0; i<0x100; i++) RxBuf2[i] = 0x00;
>
> DMACC0LLI = (int)LLI_Tx1;
> DMACC1LLI = (int)LLI_Rx1;
>
> PacketsReceived = 0;
> t0 = CTC;
> //Enable the SSP DMA requests, receiver first
> SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
> | (0 << SSP0DMACR_TXDMAE_BIT);
> SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
> | (1 << SSP0DMACR_TXDMAE_BIT);
>
> while(PacketsReceived < 3)
> wait++;
> t1 = CTC;
> debug_printf("TestLLI wait cycles: %d \r\n", wait);
> debug_printf("TestLLI time (ticks): %d \r\n", t1-t0);
>
> //check received data
> for(i=0; i > if (recvBuf[i] != i)
> errors++;
> for (i=0; i<50; i++)
> if (RxBuf1[i] != TxBuf1[i])
> errors++;
> for (i=0; i<50; i++)
> if (RxBuf2[i] != TxBuf2[i])
> errors++;
>
> return errors;
> }
> void SPIwithDMA_Init()
> {
> int e, w;
>
> SSP0_Init();
> SSP1_Init();
> DMA_Init();
>
> e = SPIwithDMA_TestWithoutDMA(1000000);
> debug_printf("TestWithoutDMA returned %d errors\r\n", e);
> e = SPIwithDMA_TestDMATransfer();
> debug_printf("TestDMATransfer returned %d errors\r\n", e);
> e = SPIwithDMA_TestLLI();
> debug_printf("TestLLI returned %d errors\r\n", e);
> }
>
> --- In l..., "Ivan Wu" wrote:
> >
> > Hi Mark,
> >
> > can you send me your code?
> > I am also have problem using the SPI.
> > Many thanks!
> >
> >
> > On 5/5/07, arjanverheij wrote:
> > >
> > > Mark,
> > >
> > > I just now got SSP with DMA working on a LPC2468. If you haven't
> > > resolved your problem I can send you my code.
> > >
> > > Arjan.
> > >
> > > --- In l... > 40yahoogroups.com>, "markcrow"
> > > wrote:
> > > >
> > > > Using the sample code (from
> > > code.lpc23xx.lpc24xx.peripherals.usvision)
> > > > I got GP DMA to drive the SSP1 port (in SPI mode) on a
> LPC2368. I
> > > > ported that code over to a LPC2468 and now it won't work
(using
> > > SSP0
> > > > this time and also in SPI mode). I get a watchdog reset when I
> > > set the
> > > > Channel Enable bit in the Channel 0 configuration register. I
> > > have
> > > > meticulously checked every setting and every address on every
> > > GPDMA
> > > > register and can make no sense of this. The watchdog reset is
> not
> > > > legitimate as the watchdog timer is set to over 3 seconds and
> the
> > > reset
> > > > occurs instantaneously when the register is written to.
> > > >
> > > > Has anyone seen anything like this? Anyone using a LPC24xx and
> > > driving
> > > > an SSP via DMA with success?
> > > >
> > > > Thanks
> > > >
> > >
> > >
> > >
> >
> >
> >
> > --
> > B.R.
> > Ivan Wu (Өǿ)
> >
> >
> >
>

Yahoo! Groups Links
Reply by markcrow May 8, 20072007-05-08
Just a follow up; I looked at your code and discovered that mine was
the same...AND I'm still getting the watchdog reset.

As it turns out, if a watchdog feed is performed when DMA is enabled
(in the DMA config register) a watchdog feed will cause a watchdog
reset. I'm going to ask NXP to look into this.

RE: the code below; DMACC0Control_SBSize_BIT and
DMACC0Control_DBSize_BIT weren't defined so I don't know for sure
what the two related fields in the DMA Channel 0 control register
were set to. However, I have tried various combinations and only '1'
will work in both fields for some reason. DMA is transferring to
SSP0 which has an 8-byte FIFO and I'd like to set the dest burst size
to 8 (as well as the source burst size). Maybe I misunderstand what
a 'burst size' is???
--- In l..., "arjanverheij"
wrote:
>
> Gents,
>
> Following is the code I used to get SPI going with DMA.
> A couple of notes:
> - the DMA controller can't access the normal RAM, so buffers and
LLI
> structures have to be in USB RAM or external RAM
> - I got weird things to happen (debugger lock up etc.) if I write
to
> DMACC1Configuration register BEFORE setting the enable bit in
> DMACConfiguration
>
> About the code:
> - I soldered SSP0 to SSP1 (4 physical wires)
> - I call SPIwithDMA_Init from Main, after enabling interrupts and
> starting the RTC
> - SPIwithDMA_Init does 3 tests, and on my Embedded Artists 2468
> board they all complete without errors
> - I use Rowley CrossWorks
> #include "platform.h"
> #include
> #include #define VICSourceDMA 25
>
> #define USB_RAM 0x7FD00000
> #define USB_RAM_SIZE 0x00004000 //16KB (8KB on LPC23xx)
> #define ETH_RAM 0x7FE00000
> #define ETH_RAM_SIZE 0x00004000 //16KB
> #define BAT_RAM 0xE0084000
> #define BAT_RAM_SIZE 0x00000800 //2KB
>
> byte* sendBuf = (byte*)0x7FD00000;
> byte* recvBuf = (byte*)0x7FD00100;
> int sendFrameSize = 50;
> int recvFrameSize = 50;
> typedef struct tagDMAControl
> {
> unsigned TransferSize : 12;
> unsigned SrcBurstSize : 3; //000=1, 001=4, 010=8,
> 011, 1002, 101d, 1108, 111%6
> unsigned DstBurstSize : 3;
> unsigned SrcWidth : 3; //000its,
> 001bits, 0102bits
> unsigned DstWidth : 3;
> unsigned reseved : 2;
> unsigned SrcIncrement : 1;
> unsigned DstIncrement : 1;
> unsigned Protection : 3;
> unsigned TCIntEnable : 1;
> } DMAControl;
>
> typedef struct tagDMA_LinkedListItem
> {
> void* Source;
> void* Destination;
> void* NextLLI;
> DMAControl Control;
> } DMA_LinkedListItem;
> //Init SSP0 for master mode, 6Mbits/s
> void SSP0_Init()
> {
> //set I/O pin config for LPC2468
> //available pins:
> //SCK0 P0.15 P1.20 P2.22
> //SSEL0 p0.16 P1.21 P2.23
> //MISO0 p0.17 P1.23 P2.26
> //MOSI0 p0.18 P1.24 P2.27
>
> PINSEL0 |= (2 << 30); //SCK0 on P0.15
> PINSEL1 |= (2 << 0); //SSEL0 on P0.16
> PINSEL1 |= (2 << 2); //MISO0 on P0.17
> PINSEL1 |= (2 << 4); //MOSI0 on P0.18
>
> // enable clock to SSP0 just to make sure. By default, it's
> enabled already
> PCONP |= PCONP_PCSSP0;
> //set PCLK divider for SSP0 to 1
> PCLKSEL1 = (PCLKSEL1 & ~PCLKSEL1_PCLK_SSP0_MASK) | (1 <<
> PCLKSEL1_PCLK_SSP0_BIT);
>
> //NOTE: in slave mode CPSR must be >
> SSP0CPSR = 12; //SCK = CCLK / PCLKdiv /
> CPSR / SCR = 72/1/12/1 = 6 MHz
> SSP0CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
> SSP0CR1 = SSP0CR1_SSE; //Master mode, SSP enabled
>
> }
>
> //init SSP1 for slave mode, 6Mbits/s
> void SSP1_Init()
> {
> //set I/O pin config for LPC2468
> //available pins:
> //SCK1 P0.7 P1.31 P4.20
> //SSEL1 p0.6 P0.14 P4.21
> //MISO1 p0.8 P0.12 P4.22
> //MOSI1 p0.9 P0.13 P2.23
>
> PINSEL0 |= (2 << 14); //SCK0 on P0.7
> PINSEL0 |= (2 << 12); //SSEL0 on P0.6
> PINSEL0 |= (2 << 16); //MISO0 on P0.8
> PINSEL0 |= (2 << 18); //MOSI0 on P0.9
>
> // enable clock to SSP0 just to make sure. By default, it's
> enabled already
> PCONP |= PCONP_PCSSP1;
> //set PCLK divider for SSP0 to 1
> PCLKSEL0 = (PCLKSEL0 & ~PCLKSEL0_PCLK_SSP1_MASK) | (1 <<
> PCLKSEL0_PCLK_SSP1_BIT);
>
> //NOTE: in slave mode CPSR must be >
> SSP1CPSR = 12; //SCK = CCLK / PCLKdiv /
> CPSR / SCR = 72/1/12/1 = 6 MHz
> SSP1CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
> SSP1CR1 = SSP1CR1_MS | SSP1CR1_SSE; //Slave mode, SSP
> enabled
> }
> //this method tests transfering bytes from SSP0 to SSP1 and vice
> versa
> //returns number of errors
> int SPIwithDMA_TestWithoutDMA(int n)
> {
> int errors = 0;
> int i;
> unsigned short s, r, s2, r2;
>
> for (i=0; i > {
> s = (unsigned short)(123 + (i << 5));
> s2 = (unsigned short)(567 + (i << 6));
>
> SSP1DR = s2;
> SSP0DR = s;
> while ( !(SSP1SR & SSP1SR_RNE) )
> ;
> r = SSP1DR;
> r2 = SSP0DR;
> if (r != s || r2 != s2)
> errors++;
> }
>
> return errors;
> }
> volatile uint PacketsReceived = 0;
> volatile uint DMAErrCount = 0;
> void DMAHandler( void )
> {
> uint regVal;
>
> regVal = DMACIntTCStatus;
> if ( regVal )
> {
> if (regVal & DMACIntTCStatus_IntTCStatus1) //then it
> was the receive channel
> PacketsReceived++;
> DMACIntTCClear |= regVal;
> }
>
> regVal = DMACIntErrorStatus;
> if ( regVal )
> {
> DMAErrCount++;
> DMACIntErrClr |= regVal;
> }
>
> #ifdef VECTORED_IRQ_INTERRUPTS
> VICVectAddr = 0; /* Acknowledge Interrupt */
> #endif //otherwise CrossWorks irq_handler will take care of
this
> }
> bool DMA_Init()
> {
> /* USB RAM is used for test.
> Please note, Ethernet has its own SRAM, but GPDMA can't
> access
> that. GPDMA can access USB SRAM and IRAM. Ethernet DMA
> controller can
> access both IRAM and Ethernet SRAM. */
> PCONP |= PCONP_PCGPDMA; /* Enable GPDMA clock */
>
> /* clear all interrupts on both channels */
> DMACIntTCClear = 0x03;
> DMACIntErrClr = 0x03;
>
> //install DMA interrupt handler
> ctl_set_isr(VICSourceDMA, 1, CTL_ISR_TRIGGER_FIXED,
> DMAHandler, 0);
> ctl_unmask_isr(VICSourceDMA);
>
> //NOTE: it seems the following needs to execute before
> accessing
> // DMACC1Configuration, otherwise the CPU locks up
> DMACConfiguration = 0x01; /* Enable DMA channels,
> little endian */
>
> return true;
> }
> //This function tries to transfer 1 packet from SSP0 to SSP1 with
DMA
> int SPIwithDMA_TestDMATransfer()
> {
> int i, wait=0, errors=0;
>
> //disable SSP from sending DMA requests
> SSP1DMACR = 0;
> SSP0DMACR = 0;
>
> /*Set up DMA channel 0 to stream data from memory to SSP0 */
> DMACC0SrcAddr = (int)sendBuf;
> DMACC0DestAddr = (int)&SSP0DR;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC0Control > (sendFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (1 << DMACC0Control_SI_BIT)
> //source increment
> | (0 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
>
> /*Set up DMA channel 1 to stream data from SSP1 to memory */
> DMACC1SrcAddr = (int)&SSP1DR;
> DMACC1DestAddr = (int)recvBuf;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC1Control > (recvFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (0 << DMACC0Control_SI_BIT)
> //source increment
> | (1 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
> //fill send packet with test pattern
> for(i=0; i<0x100; i++)
> {
> sendBuf[i] = i;
> recvBuf[i] = 0;
> }
>
> //src = n/a, dest = SSP0Tx, flow = M2P by P control,
> DMACC0Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (0 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (1 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (1 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> //src = SSP1Rx, dest = n/a, flow = P2M by P control,
> DMACC1Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (3 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (2 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> PacketsReceived = 0;
>
> //Enable the SSP DMA requests, receive first
> SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
> | (0 << SSP0DMACR_TXDMAE_BIT);
> SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
> | (1 << SSP0DMACR_TXDMAE_BIT);
>
> while(PacketsReceived < 1)
> wait++;
>
> //check received data
> for(i=0; i > {
> if (recvBuf[i] != i)
> errors++;
> }
>
> return errors;
> }
> //declare buffers and LLI structs in USB RAM
> byte* TxBuf1 = (byte*)(USB_RAM + 0x200);
> byte* TxBuf2 = (byte*)(USB_RAM + 0x300);
> byte* RxBuf1 = (byte*)(USB_RAM + 0x400);
> byte* RxBuf2 = (byte*)(USB_RAM + 0x500);
> DMA_LinkedListItem* LLI_Tx1 = (DMA_LinkedListItem*)(USB_RAM +
0x600);
> DMA_LinkedListItem* LLI_Tx2 = (DMA_LinkedListItem*)(USB_RAM +
0x610);
> DMA_LinkedListItem* LLI_Rx1 = (DMA_LinkedListItem*)(USB_RAM +
0x620);
> DMA_LinkedListItem* LLI_Rx2 = (DMA_LinkedListItem*)(USB_RAM +
0x630);
>
> int SPIwithDMA_TestLLI()
> {
> int i, wait=0, errors=0;
> unsigned long t0, t1;
>
> //disable both DMA channels while configuring
> // DMACC0Configuration &= ~DMACC0Configuration_E_BIT;
> // DMACC1Configuration &= ~DMACC1Configuration_E_BIT;
>
> //disable SSP from sending DMA requests
> SSP1DMACR = 0;
> SSP0DMACR = 0;
>
> //fill send packet with test pattern
> for(i=0; i<0x100; i++)
> {
> sendBuf[i] = i;
> recvBuf[i] = 0;
> }
>
> /*Set up DMA channel 0 to stream data from memory to SSP0 */
> DMACC0SrcAddr = (int)sendBuf;
> DMACC0DestAddr = (int)&SSP0DR;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC0Control > (sendFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (1 << DMACC0Control_SI_BIT)
> //source increment
> | (0 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
>
> /*Set up DMA channel 1 to stream data from SSP1 to memory */
> DMACC1SrcAddr = (int)&SSP1DR;
> DMACC1DestAddr = (int)recvBuf;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC1Control > (recvFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (0 << DMACC0Control_SI_BIT)
> //source increment
> | (1 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
> //src = n/a, dest = SSP0Tx, flow = M2P by P control,
> DMACC0Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (0 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (1 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> //src = SSP1Rx, dest = n/a, flow = P2M by P control,
> DMACC1Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (3 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (2 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> LLI_Tx1->Source = (void*)
> TxBuf1;
> LLI_Tx1->Destination = (void*)
> &SSP0DR;
> LLI_Tx1->NextLLI > (void*)LLI_Tx2;
> LLI_Tx1->Control.TransferSize = 50;
> LLI_Tx1->Control.SrcBurstSize = 1; //000=1, 001=4,
> 010=8, 011, 1002, 101d, 1108, 111%6
> LLI_Tx1->Control.DstBurstSize = 1;
> LLI_Tx1->Control.SrcWidth = 1; //000its,
> 001bits, 0102bits
> LLI_Tx1->Control.DstWidth = 1;
> LLI_Tx1->Control.SrcIncrement = 1;
> LLI_Tx1->Control.DstIncrement = 0;
> LLI_Tx1->Control.Protection = 0;
> LLI_Tx1->Control.TCIntEnable = 1;
>
> *LLI_Tx2 = *LLI_Tx1;
> LLI_Tx2->Source = (void*)TxBuf2;
> LLI_Tx2->NextLLI = null;
>
> LLI_Rx1->Source = (void*)
> &SSP1DR;
> LLI_Rx1->Destination = (void*)
> RxBuf1;
> LLI_Rx1->NextLLI > (void*)LLI_Rx2;
> LLI_Rx1->Control.TransferSize = 50;
> LLI_Rx1->Control.SrcBurstSize = 1; //000=1, 001=4,
> 010=8, 011, 1002, 101d, 1108, 111%6
> LLI_Rx1->Control.DstBurstSize = 1;
> LLI_Rx1->Control.SrcWidth = 1; //000its,
> 001bits, 0102bits
> LLI_Rx1->Control.DstWidth = 1;
> LLI_Rx1->Control.SrcIncrement = 0;
> LLI_Rx1->Control.DstIncrement = 1;
> LLI_Rx1->Control.Protection = 0;
> LLI_Rx1->Control.TCIntEnable = 1;
>
> *LLI_Rx2 = *LLI_Rx1;
> LLI_Rx2->Destination = (void*)RxBuf2;
> LLI_Rx2->NextLLI = null;
>
> for (i=0; i<0x100; i++) TxBuf1[i] = 0xAA;
> for (i=0; i<0x100; i++) TxBuf2[i] = 0xBB;
> for (i=0; i<0x100; i++) RxBuf1[i] = 0x00;
> for (i=0; i<0x100; i++) RxBuf2[i] = 0x00;
>
> DMACC0LLI = (int)LLI_Tx1;
> DMACC1LLI = (int)LLI_Rx1;
>
> PacketsReceived = 0;
> t0 = CTC;
> //Enable the SSP DMA requests, receiver first
> SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
> | (0 << SSP0DMACR_TXDMAE_BIT);
> SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
> | (1 << SSP0DMACR_TXDMAE_BIT);
>
> while(PacketsReceived < 3)
> wait++;
> t1 = CTC;
> debug_printf("TestLLI wait cycles: %d \r\n", wait);
> debug_printf("TestLLI time (ticks): %d \r\n", t1-t0);
>
> //check received data
> for(i=0; i > if (recvBuf[i] != i)
> errors++;
> for (i=0; i<50; i++)
> if (RxBuf1[i] != TxBuf1[i])
> errors++;
> for (i=0; i<50; i++)
> if (RxBuf2[i] != TxBuf2[i])
> errors++;
>
> return errors;
> }
> void SPIwithDMA_Init()
> {
> int e, w;
>
> SSP0_Init();
> SSP1_Init();
> DMA_Init();
>
> e = SPIwithDMA_TestWithoutDMA(1000000);
> debug_printf("TestWithoutDMA returned %d errors\r\n", e);
> e = SPIwithDMA_TestDMATransfer();
> debug_printf("TestDMATransfer returned %d errors\r\n", e);
> e = SPIwithDMA_TestLLI();
> debug_printf("TestLLI returned %d errors\r\n", e);
> }
>
> --- In l..., "Ivan Wu" wrote:
> >
> > Hi Mark,
> >
> > can you send me your code?
> > I am also have problem using the SPI.
> > Many thanks!
> >
> >
> > On 5/5/07, arjanverheij wrote:
> > >
> > > Mark,
> > >
> > > I just now got SSP with DMA working on a LPC2468. If you haven't
> > > resolved your problem I can send you my code.
> > >
> > > Arjan.
> > >
> > > --- In l... > 40yahoogroups.com>, "markcrow"
> > > wrote:
> > > >
> > > > Using the sample code (from
> > > code.lpc23xx.lpc24xx.peripherals.usvision)
> > > > I got GP DMA to drive the SSP1 port (in SPI mode) on a
> LPC2368. I
> > > > ported that code over to a LPC2468 and now it won't work
(using
> > > SSP0
> > > > this time and also in SPI mode). I get a watchdog reset when I
> > > set the
> > > > Channel Enable bit in the Channel 0 configuration register. I
> > > have
> > > > meticulously checked every setting and every address on every
> > > GPDMA
> > > > register and can make no sense of this. The watchdog reset is
> not
> > > > legitimate as the watchdog timer is set to over 3 seconds and
> the
> > > reset
> > > > occurs instantaneously when the register is written to.
> > > >
> > > > Has anyone seen anything like this? Anyone using a LPC24xx and
> > > driving
> > > > an SSP via DMA with success?
> > > >
> > > > Thanks
> > > >
> > >
> > >
> > >
> >
> >
> >
> > --
> > B.R.
> > Ivan Wu (Өǿ)
> >
> >
> >
>
Reply by markcrow May 7, 20072007-05-07
THANKS A MILLION!

Mark

--- In l..., "arjanverheij"
wrote:
>
> Gents,
>
> Following is the code I used to get SPI going with DMA.
> A couple of notes:
> - the DMA controller can't access the normal RAM, so buffers and
LLI
> structures have to be in USB RAM or external RAM
> - I got weird things to happen (debugger lock up etc.) if I write
to
> DMACC1Configuration register BEFORE setting the enable bit in
> DMACConfiguration
>
> About the code:
> - I soldered SSP0 to SSP1 (4 physical wires)
> - I call SPIwithDMA_Init from Main, after enabling interrupts and
> starting the RTC
> - SPIwithDMA_Init does 3 tests, and on my Embedded Artists 2468
> board they all complete without errors
> - I use Rowley CrossWorks
> #include "platform.h"
> #include
> #include #define VICSourceDMA 25
>
> #define USB_RAM 0x7FD00000
> #define USB_RAM_SIZE 0x00004000 //16KB (8KB on LPC23xx)
> #define ETH_RAM 0x7FE00000
> #define ETH_RAM_SIZE 0x00004000 //16KB
> #define BAT_RAM 0xE0084000
> #define BAT_RAM_SIZE 0x00000800 //2KB
>
> byte* sendBuf = (byte*)0x7FD00000;
> byte* recvBuf = (byte*)0x7FD00100;
> int sendFrameSize = 50;
> int recvFrameSize = 50;
> typedef struct tagDMAControl
> {
> unsigned TransferSize : 12;
> unsigned SrcBurstSize : 3; //000=1, 001=4, 010=8,
> 011, 1002, 101d, 1108, 111%6
> unsigned DstBurstSize : 3;
> unsigned SrcWidth : 3; //000its,
> 001bits, 0102bits
> unsigned DstWidth : 3;
> unsigned reseved : 2;
> unsigned SrcIncrement : 1;
> unsigned DstIncrement : 1;
> unsigned Protection : 3;
> unsigned TCIntEnable : 1;
> } DMAControl;
>
> typedef struct tagDMA_LinkedListItem
> {
> void* Source;
> void* Destination;
> void* NextLLI;
> DMAControl Control;
> } DMA_LinkedListItem;
> //Init SSP0 for master mode, 6Mbits/s
> void SSP0_Init()
> {
> //set I/O pin config for LPC2468
> //available pins:
> //SCK0 P0.15 P1.20 P2.22
> //SSEL0 p0.16 P1.21 P2.23
> //MISO0 p0.17 P1.23 P2.26
> //MOSI0 p0.18 P1.24 P2.27
>
> PINSEL0 |= (2 << 30); //SCK0 on P0.15
> PINSEL1 |= (2 << 0); //SSEL0 on P0.16
> PINSEL1 |= (2 << 2); //MISO0 on P0.17
> PINSEL1 |= (2 << 4); //MOSI0 on P0.18
>
> // enable clock to SSP0 just to make sure. By default, it's
> enabled already
> PCONP |= PCONP_PCSSP0;
> //set PCLK divider for SSP0 to 1
> PCLKSEL1 = (PCLKSEL1 & ~PCLKSEL1_PCLK_SSP0_MASK) | (1 <<
> PCLKSEL1_PCLK_SSP0_BIT);
>
> //NOTE: in slave mode CPSR must be >
> SSP0CPSR = 12; //SCK = CCLK / PCLKdiv /
> CPSR / SCR = 72/1/12/1 = 6 MHz
> SSP0CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
> SSP0CR1 = SSP0CR1_SSE; //Master mode, SSP enabled
>
> }
>
> //init SSP1 for slave mode, 6Mbits/s
> void SSP1_Init()
> {
> //set I/O pin config for LPC2468
> //available pins:
> //SCK1 P0.7 P1.31 P4.20
> //SSEL1 p0.6 P0.14 P4.21
> //MISO1 p0.8 P0.12 P4.22
> //MOSI1 p0.9 P0.13 P2.23
>
> PINSEL0 |= (2 << 14); //SCK0 on P0.7
> PINSEL0 |= (2 << 12); //SSEL0 on P0.6
> PINSEL0 |= (2 << 16); //MISO0 on P0.8
> PINSEL0 |= (2 << 18); //MOSI0 on P0.9
>
> // enable clock to SSP0 just to make sure. By default, it's
> enabled already
> PCONP |= PCONP_PCSSP1;
> //set PCLK divider for SSP0 to 1
> PCLKSEL0 = (PCLKSEL0 & ~PCLKSEL0_PCLK_SSP1_MASK) | (1 <<
> PCLKSEL0_PCLK_SSP1_BIT);
>
> //NOTE: in slave mode CPSR must be >
> SSP1CPSR = 12; //SCK = CCLK / PCLKdiv /
> CPSR / SCR = 72/1/12/1 = 6 MHz
> SSP1CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
> SSP1CR1 = SSP1CR1_MS | SSP1CR1_SSE; //Slave mode, SSP
> enabled
> }
> //this method tests transfering bytes from SSP0 to SSP1 and vice
> versa
> //returns number of errors
> int SPIwithDMA_TestWithoutDMA(int n)
> {
> int errors = 0;
> int i;
> unsigned short s, r, s2, r2;
>
> for (i=0; i > {
> s = (unsigned short)(123 + (i << 5));
> s2 = (unsigned short)(567 + (i << 6));
>
> SSP1DR = s2;
> SSP0DR = s;
> while ( !(SSP1SR & SSP1SR_RNE) )
> ;
> r = SSP1DR;
> r2 = SSP0DR;
> if (r != s || r2 != s2)
> errors++;
> }
>
> return errors;
> }
> volatile uint PacketsReceived = 0;
> volatile uint DMAErrCount = 0;
> void DMAHandler( void )
> {
> uint regVal;
>
> regVal = DMACIntTCStatus;
> if ( regVal )
> {
> if (regVal & DMACIntTCStatus_IntTCStatus1) //then it
> was the receive channel
> PacketsReceived++;
> DMACIntTCClear |= regVal;
> }
>
> regVal = DMACIntErrorStatus;
> if ( regVal )
> {
> DMAErrCount++;
> DMACIntErrClr |= regVal;
> }
>
> #ifdef VECTORED_IRQ_INTERRUPTS
> VICVectAddr = 0; /* Acknowledge Interrupt */
> #endif //otherwise CrossWorks irq_handler will take care of
this
> }
> bool DMA_Init()
> {
> /* USB RAM is used for test.
> Please note, Ethernet has its own SRAM, but GPDMA can't
> access
> that. GPDMA can access USB SRAM and IRAM. Ethernet DMA
> controller can
> access both IRAM and Ethernet SRAM. */
> PCONP |= PCONP_PCGPDMA; /* Enable GPDMA clock */
>
> /* clear all interrupts on both channels */
> DMACIntTCClear = 0x03;
> DMACIntErrClr = 0x03;
>
> //install DMA interrupt handler
> ctl_set_isr(VICSourceDMA, 1, CTL_ISR_TRIGGER_FIXED,
> DMAHandler, 0);
> ctl_unmask_isr(VICSourceDMA);
>
> //NOTE: it seems the following needs to execute before
> accessing
> // DMACC1Configuration, otherwise the CPU locks up
> DMACConfiguration = 0x01; /* Enable DMA channels,
> little endian */
>
> return true;
> }
> //This function tries to transfer 1 packet from SSP0 to SSP1 with
DMA
> int SPIwithDMA_TestDMATransfer()
> {
> int i, wait=0, errors=0;
>
> //disable SSP from sending DMA requests
> SSP1DMACR = 0;
> SSP0DMACR = 0;
>
> /*Set up DMA channel 0 to stream data from memory to SSP0 */
> DMACC0SrcAddr = (int)sendBuf;
> DMACC0DestAddr = (int)&SSP0DR;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC0Control > (sendFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (1 << DMACC0Control_SI_BIT)
> //source increment
> | (0 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
>
> /*Set up DMA channel 1 to stream data from SSP1 to memory */
> DMACC1SrcAddr = (int)&SSP1DR;
> DMACC1DestAddr = (int)recvBuf;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC1Control > (recvFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (0 << DMACC0Control_SI_BIT)
> //source increment
> | (1 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
> //fill send packet with test pattern
> for(i=0; i<0x100; i++)
> {
> sendBuf[i] = i;
> recvBuf[i] = 0;
> }
>
> //src = n/a, dest = SSP0Tx, flow = M2P by P control,
> DMACC0Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (0 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (1 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (1 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> //src = SSP1Rx, dest = n/a, flow = P2M by P control,
> DMACC1Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (3 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (2 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> PacketsReceived = 0;
>
> //Enable the SSP DMA requests, receive first
> SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
> | (0 << SSP0DMACR_TXDMAE_BIT);
> SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
> | (1 << SSP0DMACR_TXDMAE_BIT);
>
> while(PacketsReceived < 1)
> wait++;
>
> //check received data
> for(i=0; i > {
> if (recvBuf[i] != i)
> errors++;
> }
>
> return errors;
> }
> //declare buffers and LLI structs in USB RAM
> byte* TxBuf1 = (byte*)(USB_RAM + 0x200);
> byte* TxBuf2 = (byte*)(USB_RAM + 0x300);
> byte* RxBuf1 = (byte*)(USB_RAM + 0x400);
> byte* RxBuf2 = (byte*)(USB_RAM + 0x500);
> DMA_LinkedListItem* LLI_Tx1 = (DMA_LinkedListItem*)(USB_RAM +
0x600);
> DMA_LinkedListItem* LLI_Tx2 = (DMA_LinkedListItem*)(USB_RAM +
0x610);
> DMA_LinkedListItem* LLI_Rx1 = (DMA_LinkedListItem*)(USB_RAM +
0x620);
> DMA_LinkedListItem* LLI_Rx2 = (DMA_LinkedListItem*)(USB_RAM +
0x630);
>
> int SPIwithDMA_TestLLI()
> {
> int i, wait=0, errors=0;
> unsigned long t0, t1;
>
> //disable both DMA channels while configuring
> // DMACC0Configuration &= ~DMACC0Configuration_E_BIT;
> // DMACC1Configuration &= ~DMACC1Configuration_E_BIT;
>
> //disable SSP from sending DMA requests
> SSP1DMACR = 0;
> SSP0DMACR = 0;
>
> //fill send packet with test pattern
> for(i=0; i<0x100; i++)
> {
> sendBuf[i] = i;
> recvBuf[i] = 0;
> }
>
> /*Set up DMA channel 0 to stream data from memory to SSP0 */
> DMACC0SrcAddr = (int)sendBuf;
> DMACC0DestAddr = (int)&SSP0DR;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC0Control > (sendFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (1 << DMACC0Control_SI_BIT)
> //source increment
> | (0 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
>
> /*Set up DMA channel 1 to stream data from SSP1 to memory */
> DMACC1SrcAddr = (int)&SSP1DR;
> DMACC1DestAddr = (int)recvBuf;
> /* The burst size is set to 8, the size is 8 bit too. */
> /* Terminal Count Int enable */
> DMACC1Control > (recvFrameSize & 0x0FFF)
> //transfer size
> | (1 << DMACC0Control_SBSize_BIT) //source
> burst size
> | (1 << DMACC0Control_DBSize_BIT) //dest.
> burst size
> | (1 << DMACC0Control_SWidth_BIT) //source
> transfer width
> | (1 << DMACC0Control_DWidth_BIT) //dest.
> transfer width
> | (0 << DMACC0Control_SI_BIT)
> //source increment
> | (1 << DMACC0Control_DI_BIT)
> //dest. increment
> | (1 << DMACC0Control_I_BIT);
> //Terminal Count interrupt
> //src = n/a, dest = SSP0Tx, flow = M2P by P control,
> DMACC0Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (0 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (1 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> //src = SSP1Rx, dest = n/a, flow = P2M by P control,
> DMACC1Configuration > (1 << DMACC0Configuration_E_BIT)
> //enable
> | (3 << DMACC0Configuration_SrcPeripheral_BIT)
> //source periph
> | (0 << DMACC0Configuration_DestPeripheral_BIT)
> //dest. periph
> | (2 << DMACC0Configuration_FlowCntrl_BIT)
> //flow ctrl & transfer type
> | (1 << DMACC0Configuration_IE_BIT)
> //Error Int enable
> | (1 << DMACC0Configuration_ITC_BIT)
> //TC Int enable
> | (0 << DMACC0Configuration_L_BIT)
> //Lock AHB
> | (0 << DMACC0Configuration_A_BIT)
> //Active status
> | (0 << DMACC0Configuration_H_BIT);
> //Halt
>
> LLI_Tx1->Source = (void*)
> TxBuf1;
> LLI_Tx1->Destination = (void*)
> &SSP0DR;
> LLI_Tx1->NextLLI > (void*)LLI_Tx2;
> LLI_Tx1->Control.TransferSize = 50;
> LLI_Tx1->Control.SrcBurstSize = 1; //000=1, 001=4,
> 010=8, 011, 1002, 101d, 1108, 111%6
> LLI_Tx1->Control.DstBurstSize = 1;
> LLI_Tx1->Control.SrcWidth = 1; //000its,
> 001bits, 0102bits
> LLI_Tx1->Control.DstWidth = 1;
> LLI_Tx1->Control.SrcIncrement = 1;
> LLI_Tx1->Control.DstIncrement = 0;
> LLI_Tx1->Control.Protection = 0;
> LLI_Tx1->Control.TCIntEnable = 1;
>
> *LLI_Tx2 = *LLI_Tx1;
> LLI_Tx2->Source = (void*)TxBuf2;
> LLI_Tx2->NextLLI = null;
>
> LLI_Rx1->Source = (void*)
> &SSP1DR;
> LLI_Rx1->Destination = (void*)
> RxBuf1;
> LLI_Rx1->NextLLI > (void*)LLI_Rx2;
> LLI_Rx1->Control.TransferSize = 50;
> LLI_Rx1->Control.SrcBurstSize = 1; //000=1, 001=4,
> 010=8, 011, 1002, 101d, 1108, 111%6
> LLI_Rx1->Control.DstBurstSize = 1;
> LLI_Rx1->Control.SrcWidth = 1; //000its,
> 001bits, 0102bits
> LLI_Rx1->Control.DstWidth = 1;
> LLI_Rx1->Control.SrcIncrement = 0;
> LLI_Rx1->Control.DstIncrement = 1;
> LLI_Rx1->Control.Protection = 0;
> LLI_Rx1->Control.TCIntEnable = 1;
>
> *LLI_Rx2 = *LLI_Rx1;
> LLI_Rx2->Destination = (void*)RxBuf2;
> LLI_Rx2->NextLLI = null;
>
> for (i=0; i<0x100; i++) TxBuf1[i] = 0xAA;
> for (i=0; i<0x100; i++) TxBuf2[i] = 0xBB;
> for (i=0; i<0x100; i++) RxBuf1[i] = 0x00;
> for (i=0; i<0x100; i++) RxBuf2[i] = 0x00;
>
> DMACC0LLI = (int)LLI_Tx1;
> DMACC1LLI = (int)LLI_Rx1;
>
> PacketsReceived = 0;
> t0 = CTC;
> //Enable the SSP DMA requests, receiver first
> SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
> | (0 << SSP0DMACR_TXDMAE_BIT);
> SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
> | (1 << SSP0DMACR_TXDMAE_BIT);
>
> while(PacketsReceived < 3)
> wait++;
> t1 = CTC;
> debug_printf("TestLLI wait cycles: %d \r\n", wait);
> debug_printf("TestLLI time (ticks): %d \r\n", t1-t0);
>
> //check received data
> for(i=0; i > if (recvBuf[i] != i)
> errors++;
> for (i=0; i<50; i++)
> if (RxBuf1[i] != TxBuf1[i])
> errors++;
> for (i=0; i<50; i++)
> if (RxBuf2[i] != TxBuf2[i])
> errors++;
>
> return errors;
> }
> void SPIwithDMA_Init()
> {
> int e, w;
>
> SSP0_Init();
> SSP1_Init();
> DMA_Init();
>
> e = SPIwithDMA_TestWithoutDMA(1000000);
> debug_printf("TestWithoutDMA returned %d errors\r\n", e);
> e = SPIwithDMA_TestDMATransfer();
> debug_printf("TestDMATransfer returned %d errors\r\n", e);
> e = SPIwithDMA_TestLLI();
> debug_printf("TestLLI returned %d errors\r\n", e);
> }
>
> --- In l..., "Ivan Wu" wrote:
> >
> > Hi Mark,
> >
> > can you send me your code?
> > I am also have problem using the SPI.
> > Many thanks!
> >
> >
> > On 5/5/07, arjanverheij wrote:
> > >
> > > Mark,
> > >
> > > I just now got SSP with DMA working on a LPC2468. If you haven't
> > > resolved your problem I can send you my code.
> > >
> > > Arjan.
> > >
> > > --- In l... > 40yahoogroups.com>, "markcrow"
> > > wrote:
> > > >
> > > > Using the sample code (from
> > > code.lpc23xx.lpc24xx.peripherals.usvision)
> > > > I got GP DMA to drive the SSP1 port (in SPI mode) on a
> LPC2368. I
> > > > ported that code over to a LPC2468 and now it won't work
(using
> > > SSP0
> > > > this time and also in SPI mode). I get a watchdog reset when I
> > > set the
> > > > Channel Enable bit in the Channel 0 configuration register. I
> > > have
> > > > meticulously checked every setting and every address on every
> > > GPDMA
> > > > register and can make no sense of this. The watchdog reset is
> not
> > > > legitimate as the watchdog timer is set to over 3 seconds and
> the
> > > reset
> > > > occurs instantaneously when the register is written to.
> > > >
> > > > Has anyone seen anything like this? Anyone using a LPC24xx and
> > > driving
> > > > an SSP via DMA with success?
> > > >
> > > > Thanks
> > > >
> > >
> > >
> > >
> >
> >
> >
> > --
> > B.R.
> > Ivan Wu (Өǿ)
> >
> >
> >
>
Reply by arjanverheij May 6, 20072007-05-06
Gents,

Following is the code I used to get SPI going with DMA.
A couple of notes:
- the DMA controller can't access the normal RAM, so buffers and LLI
structures have to be in USB RAM or external RAM
- I got weird things to happen (debugger lock up etc.) if I write to
DMACC1Configuration register BEFORE setting the enable bit in
DMACConfiguration

About the code:
- I soldered SSP0 to SSP1 (4 physical wires)
- I call SPIwithDMA_Init from Main, after enabling interrupts and
starting the RTC
- SPIwithDMA_Init does 3 tests, and on my Embedded Artists 2468
board they all complete without errors
- I use Rowley CrossWorks
#include "platform.h"
#include
#include

#define VICSourceDMA 25

#define USB_RAM 0x7FD00000
#define USB_RAM_SIZE 0x00004000 //16KB (8KB on LPC23xx)
#define ETH_RAM 0x7FE00000
#define ETH_RAM_SIZE 0x00004000 //16KB
#define BAT_RAM 0xE0084000
#define BAT_RAM_SIZE 0x00000800 //2KB

byte* sendBuf = (byte*)0x7FD00000;
byte* recvBuf = (byte*)0x7FD00100;
int sendFrameSize = 50;
int recvFrameSize = 50;
typedef struct tagDMAControl
{
unsigned TransferSize : 12;
unsigned SrcBurstSize : 3; //000=1, 001=4, 010=8,
011, 1002, 101d, 1108, 111%6
unsigned DstBurstSize : 3;
unsigned SrcWidth : 3; //000its,
001bits, 0102bits
unsigned DstWidth : 3;
unsigned reseved : 2;
unsigned SrcIncrement : 1;
unsigned DstIncrement : 1;
unsigned Protection : 3;
unsigned TCIntEnable : 1;
} DMAControl;

typedef struct tagDMA_LinkedListItem
{
void* Source;
void* Destination;
void* NextLLI;
DMAControl Control;
} DMA_LinkedListItem;
//Init SSP0 for master mode, 6Mbits/s
void SSP0_Init()
{
//set I/O pin config for LPC2468
//available pins:
//SCK0 P0.15 P1.20 P2.22
//SSEL0 p0.16 P1.21 P2.23
//MISO0 p0.17 P1.23 P2.26
//MOSI0 p0.18 P1.24 P2.27

PINSEL0 |= (2 << 30); //SCK0 on P0.15
PINSEL1 |= (2 << 0); //SSEL0 on P0.16
PINSEL1 |= (2 << 2); //MISO0 on P0.17
PINSEL1 |= (2 << 4); //MOSI0 on P0.18

// enable clock to SSP0 just to make sure. By default, it's
enabled already
PCONP |= PCONP_PCSSP0;
//set PCLK divider for SSP0 to 1
PCLKSEL1 = (PCLKSEL1 & ~PCLKSEL1_PCLK_SSP0_MASK) | (1 <<
PCLKSEL1_PCLK_SSP0_BIT);

//NOTE: in slave mode CPSR must be >
SSP0CPSR = 12; //SCK = CCLK / PCLKdiv /
CPSR / SCR = 72/1/12/1 = 6 MHz
SSP0CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
SSP0CR1 = SSP0CR1_SSE; //Master mode, SSP enabled

}

//init SSP1 for slave mode, 6Mbits/s
void SSP1_Init()
{
//set I/O pin config for LPC2468
//available pins:
//SCK1 P0.7 P1.31 P4.20
//SSEL1 p0.6 P0.14 P4.21
//MISO1 p0.8 P0.12 P4.22
//MOSI1 p0.9 P0.13 P2.23

PINSEL0 |= (2 << 14); //SCK0 on P0.7
PINSEL0 |= (2 << 12); //SSEL0 on P0.6
PINSEL0 |= (2 << 16); //MISO0 on P0.8
PINSEL0 |= (2 << 18); //MOSI0 on P0.9

// enable clock to SSP0 just to make sure. By default, it's
enabled already
PCONP |= PCONP_PCSSP1;
//set PCLK divider for SSP0 to 1
PCLKSEL0 = (PCLKSEL0 & ~PCLKSEL0_PCLK_SSP1_MASK) | (1 <<
PCLKSEL0_PCLK_SSP1_BIT);

//NOTE: in slave mode CPSR must be >
SSP1CPSR = 12; //SCK = CCLK / PCLKdiv /
CPSR / SCR = 72/1/12/1 = 6 MHz
SSP1CR0 = 0x000F; //16-bit, SPI, SPO=0, SPH=0, SCR=0
SSP1CR1 = SSP1CR1_MS | SSP1CR1_SSE; //Slave mode, SSP
enabled
}
//this method tests transfering bytes from SSP0 to SSP1 and vice
versa
//returns number of errors
int SPIwithDMA_TestWithoutDMA(int n)
{
int errors = 0;
int i;
unsigned short s, r, s2, r2;

for (i=0; i {
s = (unsigned short)(123 + (i << 5));
s2 = (unsigned short)(567 + (i << 6));

SSP1DR = s2;
SSP0DR = s;
while ( !(SSP1SR & SSP1SR_RNE) )
;
r = SSP1DR;
r2 = SSP0DR;
if (r != s || r2 != s2)
errors++;
}

return errors;
}
volatile uint PacketsReceived = 0;
volatile uint DMAErrCount = 0;
void DMAHandler( void )
{
uint regVal;

regVal = DMACIntTCStatus;
if ( regVal )
{
if (regVal & DMACIntTCStatus_IntTCStatus1) //then it
was the receive channel
PacketsReceived++;
DMACIntTCClear |= regVal;
}

regVal = DMACIntErrorStatus;
if ( regVal )
{
DMAErrCount++;
DMACIntErrClr |= regVal;
}

#ifdef VECTORED_IRQ_INTERRUPTS
VICVectAddr = 0; /* Acknowledge Interrupt */
#endif //otherwise CrossWorks irq_handler will take care of this
}
bool DMA_Init()
{
/* USB RAM is used for test.
Please note, Ethernet has its own SRAM, but GPDMA can't
access
that. GPDMA can access USB SRAM and IRAM. Ethernet DMA
controller can
access both IRAM and Ethernet SRAM. */
PCONP |= PCONP_PCGPDMA; /* Enable GPDMA clock */

/* clear all interrupts on both channels */
DMACIntTCClear = 0x03;
DMACIntErrClr = 0x03;

//install DMA interrupt handler
ctl_set_isr(VICSourceDMA, 1, CTL_ISR_TRIGGER_FIXED,
DMAHandler, 0);
ctl_unmask_isr(VICSourceDMA);

//NOTE: it seems the following needs to execute before
accessing
// DMACC1Configuration, otherwise the CPU locks up
DMACConfiguration = 0x01; /* Enable DMA channels,
little endian */

return true;
}
//This function tries to transfer 1 packet from SSP0 to SSP1 with DMA
int SPIwithDMA_TestDMATransfer()
{
int i, wait=0, errors=0;

//disable SSP from sending DMA requests
SSP1DMACR = 0;
SSP0DMACR = 0;

/*Set up DMA channel 0 to stream data from memory to SSP0 */
DMACC0SrcAddr = (int)sendBuf;
DMACC0DestAddr = (int)&SSP0DR;
/* The burst size is set to 8, the size is 8 bit too. */
/* Terminal Count Int enable */
DMACC0Control (sendFrameSize & 0x0FFF)
//transfer size
| (1 << DMACC0Control_SBSize_BIT) //source
burst size
| (1 << DMACC0Control_DBSize_BIT) //dest.
burst size
| (1 << DMACC0Control_SWidth_BIT) //source
transfer width
| (1 << DMACC0Control_DWidth_BIT) //dest.
transfer width
| (1 << DMACC0Control_SI_BIT)
//source increment
| (0 << DMACC0Control_DI_BIT)
//dest. increment
| (1 << DMACC0Control_I_BIT);
//Terminal Count interrupt

/*Set up DMA channel 1 to stream data from SSP1 to memory */
DMACC1SrcAddr = (int)&SSP1DR;
DMACC1DestAddr = (int)recvBuf;
/* The burst size is set to 8, the size is 8 bit too. */
/* Terminal Count Int enable */
DMACC1Control (recvFrameSize & 0x0FFF)
//transfer size
| (1 << DMACC0Control_SBSize_BIT) //source
burst size
| (1 << DMACC0Control_DBSize_BIT) //dest.
burst size
| (1 << DMACC0Control_SWidth_BIT) //source
transfer width
| (1 << DMACC0Control_DWidth_BIT) //dest.
transfer width
| (0 << DMACC0Control_SI_BIT)
//source increment
| (1 << DMACC0Control_DI_BIT)
//dest. increment
| (1 << DMACC0Control_I_BIT);
//Terminal Count interrupt
//fill send packet with test pattern
for(i=0; i<0x100; i++)
{
sendBuf[i] = i;
recvBuf[i] = 0;
}

//src = n/a, dest = SSP0Tx, flow = M2P by P control,
DMACC0Configuration (1 << DMACC0Configuration_E_BIT)
//enable
| (0 << DMACC0Configuration_SrcPeripheral_BIT)
//source periph
| (0 << DMACC0Configuration_DestPeripheral_BIT)
//dest. periph
| (1 << DMACC0Configuration_FlowCntrl_BIT)
//flow ctrl & transfer type
| (1 << DMACC0Configuration_IE_BIT)
//Error Int enable
| (1 << DMACC0Configuration_ITC_BIT)
//TC Int enable
| (1 << DMACC0Configuration_L_BIT)
//Lock AHB
| (0 << DMACC0Configuration_A_BIT)
//Active status
| (0 << DMACC0Configuration_H_BIT);
//Halt

//src = SSP1Rx, dest = n/a, flow = P2M by P control,
DMACC1Configuration (1 << DMACC0Configuration_E_BIT)
//enable
| (3 << DMACC0Configuration_SrcPeripheral_BIT)
//source periph
| (0 << DMACC0Configuration_DestPeripheral_BIT)
//dest. periph
| (2 << DMACC0Configuration_FlowCntrl_BIT)
//flow ctrl & transfer type
| (1 << DMACC0Configuration_IE_BIT)
//Error Int enable
| (1 << DMACC0Configuration_ITC_BIT)
//TC Int enable
| (0 << DMACC0Configuration_L_BIT)
//Lock AHB
| (0 << DMACC0Configuration_A_BIT)
//Active status
| (0 << DMACC0Configuration_H_BIT);
//Halt

PacketsReceived = 0;

//Enable the SSP DMA requests, receive first
SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
| (0 << SSP0DMACR_TXDMAE_BIT);
SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
| (1 << SSP0DMACR_TXDMAE_BIT);

while(PacketsReceived < 1)
wait++;

//check received data
for(i=0; i {
if (recvBuf[i] != i)
errors++;
}

return errors;
}
//declare buffers and LLI structs in USB RAM
byte* TxBuf1 = (byte*)(USB_RAM + 0x200);
byte* TxBuf2 = (byte*)(USB_RAM + 0x300);
byte* RxBuf1 = (byte*)(USB_RAM + 0x400);
byte* RxBuf2 = (byte*)(USB_RAM + 0x500);
DMA_LinkedListItem* LLI_Tx1 = (DMA_LinkedListItem*)(USB_RAM + 0x600);
DMA_LinkedListItem* LLI_Tx2 = (DMA_LinkedListItem*)(USB_RAM + 0x610);
DMA_LinkedListItem* LLI_Rx1 = (DMA_LinkedListItem*)(USB_RAM + 0x620);
DMA_LinkedListItem* LLI_Rx2 = (DMA_LinkedListItem*)(USB_RAM + 0x630);

int SPIwithDMA_TestLLI()
{
int i, wait=0, errors=0;
unsigned long t0, t1;

//disable both DMA channels while configuring
// DMACC0Configuration &= ~DMACC0Configuration_E_BIT;
// DMACC1Configuration &= ~DMACC1Configuration_E_BIT;

//disable SSP from sending DMA requests
SSP1DMACR = 0;
SSP0DMACR = 0;

//fill send packet with test pattern
for(i=0; i<0x100; i++)
{
sendBuf[i] = i;
recvBuf[i] = 0;
}

/*Set up DMA channel 0 to stream data from memory to SSP0 */
DMACC0SrcAddr = (int)sendBuf;
DMACC0DestAddr = (int)&SSP0DR;
/* The burst size is set to 8, the size is 8 bit too. */
/* Terminal Count Int enable */
DMACC0Control (sendFrameSize & 0x0FFF)
//transfer size
| (1 << DMACC0Control_SBSize_BIT) //source
burst size
| (1 << DMACC0Control_DBSize_BIT) //dest.
burst size
| (1 << DMACC0Control_SWidth_BIT) //source
transfer width
| (1 << DMACC0Control_DWidth_BIT) //dest.
transfer width
| (1 << DMACC0Control_SI_BIT)
//source increment
| (0 << DMACC0Control_DI_BIT)
//dest. increment
| (1 << DMACC0Control_I_BIT);
//Terminal Count interrupt

/*Set up DMA channel 1 to stream data from SSP1 to memory */
DMACC1SrcAddr = (int)&SSP1DR;
DMACC1DestAddr = (int)recvBuf;
/* The burst size is set to 8, the size is 8 bit too. */
/* Terminal Count Int enable */
DMACC1Control (recvFrameSize & 0x0FFF)
//transfer size
| (1 << DMACC0Control_SBSize_BIT) //source
burst size
| (1 << DMACC0Control_DBSize_BIT) //dest.
burst size
| (1 << DMACC0Control_SWidth_BIT) //source
transfer width
| (1 << DMACC0Control_DWidth_BIT) //dest.
transfer width
| (0 << DMACC0Control_SI_BIT)
//source increment
| (1 << DMACC0Control_DI_BIT)
//dest. increment
| (1 << DMACC0Control_I_BIT);
//Terminal Count interrupt
//src = n/a, dest = SSP0Tx, flow = M2P by P control,
DMACC0Configuration (1 << DMACC0Configuration_E_BIT)
//enable
| (0 << DMACC0Configuration_SrcPeripheral_BIT)
//source periph
| (0 << DMACC0Configuration_DestPeripheral_BIT)
//dest. periph
| (1 << DMACC0Configuration_FlowCntrl_BIT)
//flow ctrl & transfer type
| (1 << DMACC0Configuration_IE_BIT)
//Error Int enable
| (1 << DMACC0Configuration_ITC_BIT)
//TC Int enable
| (0 << DMACC0Configuration_L_BIT)
//Lock AHB
| (0 << DMACC0Configuration_A_BIT)
//Active status
| (0 << DMACC0Configuration_H_BIT);
//Halt

//src = SSP1Rx, dest = n/a, flow = P2M by P control,
DMACC1Configuration (1 << DMACC0Configuration_E_BIT)
//enable
| (3 << DMACC0Configuration_SrcPeripheral_BIT)
//source periph
| (0 << DMACC0Configuration_DestPeripheral_BIT)
//dest. periph
| (2 << DMACC0Configuration_FlowCntrl_BIT)
//flow ctrl & transfer type
| (1 << DMACC0Configuration_IE_BIT)
//Error Int enable
| (1 << DMACC0Configuration_ITC_BIT)
//TC Int enable
| (0 << DMACC0Configuration_L_BIT)
//Lock AHB
| (0 << DMACC0Configuration_A_BIT)
//Active status
| (0 << DMACC0Configuration_H_BIT);
//Halt

LLI_Tx1->Source = (void*)
TxBuf1;
LLI_Tx1->Destination = (void*)
&SSP0DR;
LLI_Tx1->NextLLI (void*)LLI_Tx2;
LLI_Tx1->Control.TransferSize = 50;
LLI_Tx1->Control.SrcBurstSize = 1; //000=1, 001=4,
010=8, 011, 1002, 101d, 1108, 111%6
LLI_Tx1->Control.DstBurstSize = 1;
LLI_Tx1->Control.SrcWidth = 1; //000its,
001bits, 0102bits
LLI_Tx1->Control.DstWidth = 1;
LLI_Tx1->Control.SrcIncrement = 1;
LLI_Tx1->Control.DstIncrement = 0;
LLI_Tx1->Control.Protection = 0;
LLI_Tx1->Control.TCIntEnable = 1;

*LLI_Tx2 = *LLI_Tx1;
LLI_Tx2->Source = (void*)TxBuf2;
LLI_Tx2->NextLLI = null;

LLI_Rx1->Source = (void*)
&SSP1DR;
LLI_Rx1->Destination = (void*)
RxBuf1;
LLI_Rx1->NextLLI (void*)LLI_Rx2;
LLI_Rx1->Control.TransferSize = 50;
LLI_Rx1->Control.SrcBurstSize = 1; //000=1, 001=4,
010=8, 011, 1002, 101d, 1108, 111%6
LLI_Rx1->Control.DstBurstSize = 1;
LLI_Rx1->Control.SrcWidth = 1; //000its,
001bits, 0102bits
LLI_Rx1->Control.DstWidth = 1;
LLI_Rx1->Control.SrcIncrement = 0;
LLI_Rx1->Control.DstIncrement = 1;
LLI_Rx1->Control.Protection = 0;
LLI_Rx1->Control.TCIntEnable = 1;

*LLI_Rx2 = *LLI_Rx1;
LLI_Rx2->Destination = (void*)RxBuf2;
LLI_Rx2->NextLLI = null;

for (i=0; i<0x100; i++) TxBuf1[i] = 0xAA;
for (i=0; i<0x100; i++) TxBuf2[i] = 0xBB;
for (i=0; i<0x100; i++) RxBuf1[i] = 0x00;
for (i=0; i<0x100; i++) RxBuf2[i] = 0x00;

DMACC0LLI = (int)LLI_Tx1;
DMACC1LLI = (int)LLI_Rx1;

PacketsReceived = 0;
t0 = CTC;
//Enable the SSP DMA requests, receiver first
SSP1DMACR = (1 << SSP0DMACR_RXDMAE_BIT)
| (0 << SSP0DMACR_TXDMAE_BIT);
SSP0DMACR = (0 << SSP0DMACR_RXDMAE_BIT)
| (1 << SSP0DMACR_TXDMAE_BIT);

while(PacketsReceived < 3)
wait++;
t1 = CTC;
debug_printf("TestLLI wait cycles: %d \r\n", wait);
debug_printf("TestLLI time (ticks): %d \r\n", t1-t0);

//check received data
for(i=0; i if (recvBuf[i] != i)
errors++;
for (i=0; i<50; i++)
if (RxBuf1[i] != TxBuf1[i])
errors++;
for (i=0; i<50; i++)
if (RxBuf2[i] != TxBuf2[i])
errors++;

return errors;
}
void SPIwithDMA_Init()
{
int e, w;

SSP0_Init();
SSP1_Init();
DMA_Init();

e = SPIwithDMA_TestWithoutDMA(1000000);
debug_printf("TestWithoutDMA returned %d errors\r\n", e);
e = SPIwithDMA_TestDMATransfer();
debug_printf("TestDMATransfer returned %d errors\r\n", e);
e = SPIwithDMA_TestLLI();
debug_printf("TestLLI returned %d errors\r\n", e);
}

--- In l..., "Ivan Wu" wrote:
>
> Hi Mark,
>
> can you send me your code?
> I am also have problem using the SPI.
> Many thanks!
> On 5/5/07, arjanverheij wrote:
> >
> > Mark,
> >
> > I just now got SSP with DMA working on a LPC2468. If you haven't
> > resolved your problem I can send you my code.
> >
> > Arjan.
> >
> > --- In l...
40yahoogroups.com>, "markcrow"
> > wrote:
> > >
> > > Using the sample code (from
> > code.lpc23xx.lpc24xx.peripherals.usvision)
> > > I got GP DMA to drive the SSP1 port (in SPI mode) on a
LPC2368. I
> > > ported that code over to a LPC2468 and now it won't work (using
> > SSP0
> > > this time and also in SPI mode). I get a watchdog reset when I
> > set the
> > > Channel Enable bit in the Channel 0 configuration register. I
> > have
> > > meticulously checked every setting and every address on every
> > GPDMA
> > > register and can make no sense of this. The watchdog reset is
not
> > > legitimate as the watchdog timer is set to over 3 seconds and
the
> > reset
> > > occurs instantaneously when the register is written to.
> > >
> > > Has anyone seen anything like this? Anyone using a LPC24xx and
> > driving
> > > an SSP via DMA with success?
> > >
> > > Thanks
> > >
> >
> >
> > --
> B.R.
> Ivan Wu (Өǿ)
>
>
Reply by Ivan Wu May 5, 20072007-05-05
Hi Mark,

can you send me your code?
I am also have problem using the SPI.
Many thanks!
On 5/5/07, arjanverheij wrote:
>
> Mark,
>
> I just now got SSP with DMA working on a LPC2468. If you haven't
> resolved your problem I can send you my code.
>
> Arjan.
>
> --- In l... , "markcrow"
> wrote:
> >
> > Using the sample code (from
> code.lpc23xx.lpc24xx.peripherals.usvision)
> > I got GP DMA to drive the SSP1 port (in SPI mode) on a LPC2368. I
> > ported that code over to a LPC2468 and now it won't work (using
> SSP0
> > this time and also in SPI mode). I get a watchdog reset when I
> set the
> > Channel Enable bit in the Channel 0 configuration register. I
> have
> > meticulously checked every setting and every address on every
> GPDMA
> > register and can make no sense of this. The watchdog reset is not
> > legitimate as the watchdog timer is set to over 3 seconds and the
> reset
> > occurs instantaneously when the register is written to.
> >
> > Has anyone seen anything like this? Anyone using a LPC24xx and
> driving
> > an SSP via DMA with success?
> >
> > Thanks
>
--
B.R.
Ivan Wu (Өǿ)
Reply by arjanverheij May 5, 20072007-05-05
Mark,

I just now got SSP with DMA working on a LPC2468. If you haven't
resolved your problem I can send you my code.

Arjan.

--- In l..., "markcrow" wrote:
>
> Using the sample code (from
code.lpc23xx.lpc24xx.peripherals.usvision)
> I got GP DMA to drive the SSP1 port (in SPI mode) on a LPC2368. I
> ported that code over to a LPC2468 and now it won't work (using
SSP0
> this time and also in SPI mode). I get a watchdog reset when I
set the
> Channel Enable bit in the Channel 0 configuration register. I
have
> meticulously checked every setting and every address on every
GPDMA
> register and can make no sense of this. The watchdog reset is not
> legitimate as the watchdog timer is set to over 3 seconds and the
reset
> occurs instantaneously when the register is written to.
>
> Has anyone seen anything like this? Anyone using a LPC24xx and
driving
> an SSP via DMA with success?
>
> Thanks
>
Reply by markcrow April 27, 20072007-04-27
Using the sample code (from code.lpc23xx.lpc24xx.peripherals.usvision)
I got GP DMA to drive the SSP1 port (in SPI mode) on a LPC2368. I
ported that code over to a LPC2468 and now it won't work (using SSP0
this time and also in SPI mode). I get a watchdog reset when I set the
Channel Enable bit in the Channel 0 configuration register. I have
meticulously checked every setting and every address on every GPDMA
register and can make no sense of this. The watchdog reset is not
legitimate as the watchdog timer is set to over 3 seconds and the reset
occurs instantaneously when the register is written to.

Has anyone seen anything like this? Anyone using a LPC24xx and driving
an SSP via DMA with success?

Thanks