DSPRelated.com
Forums

Using DMA on DSP56309

Started by Wygonski, John March 31, 2004
I'm having some trouble modifying a working app to use DMA. I have timer 2 on
the DSP56309 set up in "Toggle" mode so that I can produce waveforms whose pulse
width varies. The current version of the program works fine as I am using the
timer compare interrupt to update the TCPR value which varies the pulse width.
The ISR repeatedly cycles through a buffer (OutBuf) of 12 TCPR values to produce
a periodic waveform.

Now I want to use a DMA channel to feed the TCPR of timer 2, and so the timer
compare interrupt is not used. I have instead installed a DMA transfer complete
interrupt to restart the DMA transfer. Here's the code:

TCPR2 = 498; // initial delay value
coreInstallIntVec(0x18/2, (_P UInt24*) cic3DMA0ISR ); // install
interrupt vector for DMA
IPRC.B.D0L = 3; // High priority for DMA channel 0
DSR0 = (int * )OutBuf;
DDR0 = (int *) 0xFFFF85; // dest is TCPR2
DCO0 = 12-1; // (num values in OutBuf)-1
DCR0.B.DSS = 0; // source is in X
DCR0.B.DDS = 0; // dest is in X
DCR0.B.DAM = 0x25; // source addr is ++, no update of dest addr
DCR0.B.D3D = 0; // non-3D mode
DCR0.B.DRS = 0x12; // DMA Req Source is Tmr 2 Cmp Flag
DCR0.B.DCON = 0; //
DCR0.B.DPR = 3; //
DCR0.B.DTM = 1; // word-by-word block transfer; DE cleared after
transfer complete
DCR0.B.DIE = 1; //
DCR0.B.DE = 1; //

And here's the DMA complete interrupt service routine:

void _long_interrupt (-1)
cic3DMA0ISR (void) {
DCO0 = 12-1; //
DSR0 = (int * )&OutBuf[0];
DCR0.B.DE = 1; // do it again
}

With this code running, everything seems to be working fine, except that the
TCPR2 vaue never changes from the initial value of 498. The source of the DMA
transfer (OutBuf) contains values other than 498. As I step through the code, I
note that the DMA controller is functioning as I expect because: DSR0 increments
as it should while DDR0 is fixed at the address of TCPR2, DCO0 counts in step
with DSR0, and the DACT and DTD0 bits in the status reg change as I expect them
to. What I observe in this case is that the TIO2 pin produces a square wave
proportional to the initial TCSR2 value, indicating that it never gets updated.

I have a feeling I'm missing something obvious, but for the life of me I can't
see it. Any help is much appreciated.




John,

DMA cannot be used to update configuration registers in I/O space. The
only registers it can communicate within I/O space are transmit and
receive registers. See item number 2 in Section 10.6 DMA Restrictions
in the 56300 Family Manual...

--
dB

--- "Wygonski, John" <> wrote:
> I'm having some trouble modifying a working app to use DMA. I have
> timer 2 on the DSP56309 set up in "Toggle" mode so that I can produce
> waveforms whose pulse width varies. The current version of the
> program works fine as I am using the timer compare interrupt to
> update the TCPR value which varies the pulse width. The ISR
> repeatedly cycles through a buffer (OutBuf) of 12 TCPR values to
> produce a periodic waveform.
>
> Now I want to use a DMA channel to feed the TCPR of timer 2, and so
> the timer compare interrupt is not used. I have instead installed a
> DMA transfer complete interrupt to restart the DMA transfer. Here's
> the code:
>
> TCPR2 = 498; // initial delay value
> coreInstallIntVec(0x18/2, (_P UInt24*) cic3DMA0ISR ); //
> install interrupt vector for DMA
> IPRC.B.D0L = 3; // High priority for DMA channel 0
> DSR0 = (int * )OutBuf;
> DDR0 = (int *) 0xFFFF85; // dest is TCPR2
> DCO0 = 12-1; // (num values in OutBuf)-1
> DCR0.B.DSS = 0; // source is in X
> DCR0.B.DDS = 0; // dest is in X
> DCR0.B.DAM = 0x25; // source addr is ++, no update of dest
> addr
> DCR0.B.D3D = 0; // non-3D mode
> DCR0.B.DRS = 0x12; // DMA Req Source is Tmr 2 Cmp Flag
> DCR0.B.DCON = 0; //
> DCR0.B.DPR = 3; //
> DCR0.B.DTM = 1; // word-by-word block transfer; DE
> cleared after transfer complete
> DCR0.B.DIE = 1; //
> DCR0.B.DE = 1; //
>
> And here's the DMA complete interrupt service routine:
>
> void _long_interrupt (-1)
> cic3DMA0ISR (void) {
> DCO0 = 12-1; //
> DSR0 = (int * )&OutBuf[0];
> DCR0.B.DE = 1; // do it again
> }
>
> With this code running, everything seems to be working fine, except
> that the TCPR2 vaue never changes from the initial value of 498. The
> source of the DMA transfer (OutBuf) contains values other than 498.
> As I step through the code, I note that the DMA controller is
> functioning as I expect because: DSR0 increments as it should while
> DDR0 is fixed at the address of TCPR2, DCO0 counts in step with DSR0,
> and the DACT and DTD0 bits in the status reg change as I expect them
> to. What I observe in this case is that the TIO2 pin produces a
> square wave proportional to the initial TCSR2 value, indicating that
> it never gets updated.
>
> I have a feeling I'm missing something obvious, but for the life of
> me I can't see it. Any help is much appreciated.
>


__________________________________




Sorry, it's item number 3 in that section not number 2...

--
dB

--- "Wygonski, John" <> wrote:
> I'm having some trouble modifying a working app to use DMA. I have
> timer 2 on the DSP56309 set up in "Toggle" mode so that I can produce
> waveforms whose pulse width varies. The current version of the
> program works fine as I am using the timer compare interrupt to
> update the TCPR value which varies the pulse width. The ISR
> repeatedly cycles through a buffer (OutBuf) of 12 TCPR values to
> produce a periodic waveform.
>
> Now I want to use a DMA channel to feed the TCPR of timer 2, and so
> the timer compare interrupt is not used. I have instead installed a
> DMA transfer complete interrupt to restart the DMA transfer. Here's
> the code:
>
> TCPR2 = 498; // initial delay value
> coreInstallIntVec(0x18/2, (_P UInt24*) cic3DMA0ISR ); //
> install interrupt vector for DMA
> IPRC.B.D0L = 3; // High priority for DMA channel 0
> DSR0 = (int * )OutBuf;
> DDR0 = (int *) 0xFFFF85; // dest is TCPR2
> DCO0 = 12-1; // (num values in OutBuf)-1
> DCR0.B.DSS = 0; // source is in X
> DCR0.B.DDS = 0; // dest is in X
> DCR0.B.DAM = 0x25; // source addr is ++, no update of dest
> addr
> DCR0.B.D3D = 0; // non-3D mode
> DCR0.B.DRS = 0x12; // DMA Req Source is Tmr 2 Cmp Flag
> DCR0.B.DCON = 0; //
> DCR0.B.DPR = 3; //
> DCR0.B.DTM = 1; // word-by-word block transfer; DE
> cleared after transfer complete
> DCR0.B.DIE = 1; //
> DCR0.B.DE = 1; //
>
> And here's the DMA complete interrupt service routine:
>
> void _long_interrupt (-1)
> cic3DMA0ISR (void) {
> DCO0 = 12-1; //
> DSR0 = (int * )&OutBuf[0];
> DCR0.B.DE = 1; // do it again
> }
>
> With this code running, everything seems to be working fine, except
> that the TCPR2 vaue never changes from the initial value of 498. The
> source of the DMA transfer (OutBuf) contains values other than 498.
> As I step through the code, I note that the DMA controller is
> functioning as I expect because: DSR0 increments as it should while
> DDR0 is fixed at the address of TCPR2, DCO0 counts in step with DSR0,
> and the DACT and DTD0 bits in the status reg change as I expect them
> to. What I observe in this case is that the TIO2 pin produces a
> square wave proportional to the initial TCSR2 value, indicating that
> it never gets updated.
>
> I have a feeling I'm missing something obvious, but for the life of
> me I can't see it. Any help is much appreciated.
>


__________________________________



Well, thanks so much for clearing that up. I did see that item, but
I just mis-interpreted it.

So even though the timer compare event can trigger a DMA transfer, I
basically can't reprogram the timer using DMA at all because it has
no Tx/Rx regs.

Well, back to the drawing board, as they say.

--- In , dbaudiopro <dbaudiopro@y...>
wrote:
> John,
>
> DMA cannot be used to update configuration registers in I/O space.
The
> only registers it can communicate within I/O space are transmit and
> receive registers. See item number 2 in Section 10.6 DMA
Restrictions
> in the 56300 Family Manual...
>
> --
> dB
>
> --- "Wygonski, John" <jwygonski@h...> wrote:
> > I'm having some trouble modifying a working app to use DMA. I
have
> > timer 2 on the DSP56309 set up in "Toggle" mode so that I can
produce
> > waveforms whose pulse width varies. The current version of the
> > program works fine as I am using the timer compare interrupt to
> > update the TCPR value which varies the pulse width. The ISR
> > repeatedly cycles through a buffer (OutBuf) of 12 TCPR values to
> > produce a periodic waveform.
> >
> > Now I want to use a DMA channel to feed the TCPR of timer 2, and
so
> > the timer compare interrupt is not used. I have instead
installed a
> > DMA transfer complete interrupt to restart the DMA transfer.
Here's
> > the code:
> >
> > TCPR2 = 498; // initial delay value
> > coreInstallIntVec(0x18/2, (_P UInt24*) cic3DMA0ISR ); //
> > install interrupt vector for DMA
> > IPRC.B.D0L = 3; // High priority for DMA channel 0
> > DSR0 = (int * )OutBuf;
> > DDR0 = (int *) 0xFFFF85; // dest is TCPR2
> > DCO0 = 12-1; // (num values in OutBuf)-1
> > DCR0.B.DSS = 0; // source is in X
> > DCR0.B.DDS = 0; // dest is in X
> > DCR0.B.DAM = 0x25; // source addr is ++, no update of
dest
> > addr
> > DCR0.B.D3D = 0; // non-3D mode
> > DCR0.B.DRS = 0x12; // DMA Req Source is Tmr 2 Cmp Flag
> > DCR0.B.DCON = 0; //
> > DCR0.B.DPR = 3; //
> > DCR0.B.DTM = 1; // word-by-word block transfer; DE
> > cleared after transfer complete
> > DCR0.B.DIE = 1; //
> > DCR0.B.DE = 1; //
> >
> > And here's the DMA complete interrupt service routine:
> >
> > void _long_interrupt (-1)
> > cic3DMA0ISR (void) {
> > DCO0 = 12-1; //
> > DSR0 = (int * )&OutBuf[0];
> > DCR0.B.DE = 1; // do it again
> > }
> >
> > With this code running, everything seems to be working fine,
except
> > that the TCPR2 vaue never changes from the initial value of 498.
The
> > source of the DMA transfer (OutBuf) contains values other than
498.
> > As I step through the code, I note that the DMA controller is
> > functioning as I expect because: DSR0 increments as it should
while
> > DDR0 is fixed at the address of TCPR2, DCO0 counts in step with
DSR0,
> > and the DACT and DTD0 bits in the status reg change as I expect
them
> > to. What I observe in this case is that the TIO2 pin produces a
> > square wave proportional to the initial TCSR2 value, indicating
that
> > it never gets updated.
> >
> > I have a feeling I'm missing something obvious, but for the life
of
> > me I can't see it. Any help is much appreciated.
> > __________________________________
>




It doesn't matter if the peripheral has TX or RX registers. The point
is that DMA can only read or write peripheral TX or TX registers. For
instance, you can't use DMA to write an ESSI control register. However,
you can service an ESSI TX or RX register with DMA. No control register
for any peripheral located in I/O space can be written or read with
DMA...

--
dB --- wygonski <> wrote:
> Well, thanks so much for clearing that up. I did see that item, but
> I just mis-interpreted it.
>
> So even though the timer compare event can trigger a DMA transfer, I
> basically can't reprogram the timer using DMA at all because it has
> no Tx/Rx regs.
>
> Well, back to the drawing board, as they say.
>
> --- In , dbaudiopro <dbaudiopro@y...>
> wrote:
> > John,
> >
> > DMA cannot be used to update configuration registers in I/O space.
> The
> > only registers it can communicate within I/O space are transmit and
> > receive registers. See item number 2 in Section 10.6 DMA
> Restrictions
> > in the 56300 Family Manual...
> >
> > --
> > dB
> >
> > --- "Wygonski, John" <jwygonski@h...> wrote:
> > > I'm having some trouble modifying a working app to use DMA. I
> have
> > > timer 2 on the DSP56309 set up in "Toggle" mode so that I can
> produce
> > > waveforms whose pulse width varies. The current version of the
> > > program works fine as I am using the timer compare interrupt to
> > > update the TCPR value which varies the pulse width. The ISR
> > > repeatedly cycles through a buffer (OutBuf) of 12 TCPR values to
> > > produce a periodic waveform.
> > >
> > > Now I want to use a DMA channel to feed the TCPR of timer 2, and
> so
> > > the timer compare interrupt is not used. I have instead
> installed a
> > > DMA transfer complete interrupt to restart the DMA transfer.
> Here's
> > > the code:
> > >
> > > TCPR2 = 498; // initial delay value
> > > coreInstallIntVec(0x18/2, (_P UInt24*) cic3DMA0ISR ); //
> > > install interrupt vector for DMA
> > > IPRC.B.D0L = 3; // High priority for DMA channel 0
> > > DSR0 = (int * )OutBuf;
> > > DDR0 = (int *) 0xFFFF85; // dest is TCPR2
> > > DCO0 = 12-1; // (num values in OutBuf)-1
> > > DCR0.B.DSS = 0; // source is in X
> > > DCR0.B.DDS = 0; // dest is in X
> > > DCR0.B.DAM = 0x25; // source addr is ++, no update of
> dest
> > > addr
> > > DCR0.B.D3D = 0; // non-3D mode
> > > DCR0.B.DRS = 0x12; // DMA Req Source is Tmr 2 Cmp Flag
> > > DCR0.B.DCON = 0; //
> > > DCR0.B.DPR = 3; //
> > > DCR0.B.DTM = 1; // word-by-word block transfer; DE
> > > cleared after transfer complete
> > > DCR0.B.DIE = 1; //
> > > DCR0.B.DE = 1; //
> > >
> > > And here's the DMA complete interrupt service routine:
> > >
> > > void _long_interrupt (-1)
> > > cic3DMA0ISR (void) {
> > > DCO0 = 12-1; //
> > > DSR0 = (int * )&OutBuf[0];
> > > DCR0.B.DE = 1; // do it again
> > > }
> > >
> > > With this code running, everything seems to be working fine,
> except
> > > that the TCPR2 vaue never changes from the initial value of 498.
>
> The
> > > source of the DMA transfer (OutBuf) contains values other than
> 498.
> > > As I step through the code, I note that the DMA controller is
> > > functioning as I expect because: DSR0 increments as it should
> while
> > > DDR0 is fixed at the address of TCPR2, DCO0 counts in step with
> DSR0,
> > > and the DACT and DTD0 bits in the status reg change as I expect
> them
> > > to. What I observe in this case is that the TIO2 pin produces a
> > > square wave proportional to the initial TCSR2 value, indicating
> that
> > > it never gets updated.
> > >
> > > I have a feeling I'm missing something obvious, but for the life
> of
> > > me I can't see it. Any help is much appreciated.
> > >
> >
> >
> > __________________________________
> >
>


__________________________________