DSPRelated.com
Forums

C6747/Omap L137 interrupt handler problem

Started by Jason February 7, 2011
I'm having trouble getting an interrupt to work on a C6747. The interrupt is causing the processor to lockup. (When I hit break from within the debugger, the DSP is no longer executing my program code, but is apparently "lost" in memory somewhere.) I've been able to get the DMA2_ISR() function to be called with the interrupt fires, but things only work when the code that the DSP is executing is a simple loop like:

while(wait_for_dma_flg)
;

If the code is calling other functions, the DSP locks up when the interrupt in called. I'm wondering if I've made a mistake with my interrupt handler so the function isn't returning to the correct point in the code or some registers have been corrupted.
The snippets from the command linker file and from the *.cpp file that holds the code are below.

Please look at how I setup the interrupt callback function and see if you can find a reason why the DMA2_ISR() can't return w/o locking up the system.

I also would appreciate information on how I was supposed to setup the interrupts. I'm not using any library functions, but just setting everything up "manually".

linker.cmd file snippet

MEMORY
{
VECS: o = 0xFFFF0000 l = 0x00000080
ARMRAM: o = 0xFFFF0080 l = 0x00001f80
ISRRAM: o = 0x11800000 l = 0x00000200
DSPRAM: o = 0x11800200 l = 0x0003FE00
SHAREDRAM: o = 0x80000000 l = 0x00020000
SDRAM: o = 0xC3000000 l = 0x01000000
}

SECTIONS
{
.bss > DSPRAM
.cinit > SHAREDRAM
.cio > SHAREDRAM
.const > DSPRAM
.stack > DSPRAM
.sysmem > DSPRAM
.text > DSPRAM
.switch > DSPRAM
.far > DSPRAM
.pextmem > DSPRAM
.isrvects > ISRRAM
}

new location for IRS vectors

#pragma DATA_SECTION(".isrvects");
unsigned char ISR_VECTORS_p[0x200];

The following code setups the interrupt. Overall, the code:
1) copies the interrupt service table from ram to rom
2) replaces the 32 bytes for interrupt 10 with code that will branch to DMA2_ISR() function
3) enables interrupts through IER and CSR registers

/*
below is a section of code taken from a interrupt handler that's 32 bytes long.
it shows the address 1000db38 being loaded into B0 and branched to.
that address is embedded into the MVK and MVKH op codes.
by replacing the address in the op codes with an ISR location, an interrupt
handler can be created for the Interrupt Service Table (IST)

10000100 003C30F6 STW.D2T2 B0,*--SP[1]
10000104 006D9C2A MVK.S2 0xffffdb38,B0
10000108 0008006A MVKH.S2 0x10000000,B0
1000010C 00000362 B.S2 B0
10000110 003C36E6 LDW.D2T2 *SP++[1],B0
10000114 00006000 NOP 4
10000118 00000000 NOP
1000011C 00000000 NOP
31 27 23 19 15 11 7 3 bit location
. . . . . . . nybble separators
MVK = 006D9C2A = 00000000011011011001110000101010 binary representation of MVK with db38 address
db38 = 1101101100111000 dB38 shifted to bit fields 22 - 7

The address in MVK and MVKH are in bit fields 22-7.
below is a table of a interrupt service fetch packet with the address set to 0, which
will make it eash to or in an actual ISR jump addres
*/

Uint32 isr_fetch_packet_p[32]= { 0x003C30F6,
0x0000002A, // MVK w address 0
0x0000006A, // MVKH w address 0
0x00000362,
0x003C36E6,
0x00006000,
0x00000000,
0x00000000};

extern cregister volatile unsigned int ISTP; // interrupt service table pointer register
extern cregister volatile unsigned int CSR; // control status register
extern cregister volatile unsigned int IER; // Interrupt Enable Register
// these registers are described in "sprufe8 TMS320C674x DSP CPU and Instruction Set User's Guide .pdf"

Uint32 isr_address=(Uint32) DMA2_ISR;
// interrupt function callback address
Uint32 isr_INTn=8;
// one of the 128 DSP interrupts given in "Table 6-9. OMAP-L137 DSP Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor (Rev. C) .pdf"
// thst is to be processed by the isr_address callback function
//
// I setup the DMA2 to fire off a "EDMA3CC_INT0" interrupt
// interrupt #'s given in "Table 6-9. OMAP-L137 DSP Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor (Rev. C) .pdf"
// the EDMA interrupts I' have ot choose from are:
// 8 EDMA3_CC0_INT1 EDMA3 CC0 Region 1 interrupt
// 56 EDMA3_CC0_ERRINT EDMA3 Channel Controller 0
// 57 EDMA3_TC0_ERRINT EDMA3 Transfer Controller 0
// 58 EDMA3_TC1_ERRINT EDMA3 Transfer Controller 1
// NOTE: I looked at the EVTFLAG1 (see the MegaModule manual) register after
// the DMA complted and saw that Event 56 had been set, so apparently
// i want to trigger on event 56... :)
// I'm trying to use a "transfer complete" (TC) interrupt for DRAE shadow region 0, so I suppose
// interrupt 57 is what I want... but this is clear as mud from the above interrupt descirptions,
// and the Figure 12 on page 44 of the EDMA manual only shows CC interrupts...
// the description for 57 as "ERRINT" make it sound like an error interrupt, but maybe it's
// both an TC and error interrupts... :)
Uint32 CPUINTn;
// CPU interrupt that the isr_INTn interrupt will be mapped to
// this is one of the 12 CPU maskable interrupts specfied in figure 7-8 on page 164 of "sprufk5 TMS320C674x DSP Megamodule Reference Guide .pdf"
// this is the entry in the interrupt service callback function that gets executed
//
// it's unclear to me if this event has anything to do with the events specfied
// in table 7-2 on page 167 of "sprufk5 TMS320C674x DSP Megamodule Reference Guide .pdf"
// but it doesn't appear to be the case as this table matches the main 128 interrupt
// table given in table 6-9 of the the main processor manual "OMAP-L137 Low-Power Applications Processor (Rev. C) .pdf"

Uint32 *i_u_p,mask;
unsigned char * c_u_p;

// copy rom based ist to ram based ist
c_u_p=(unsigned char*)ISTP;
for(i=0;i<0x200;i++)
ISR_VECTORS_p[i]=c_u_p[i];
ISTP=(unsigned int)ISR_VECTORS_p;

i_u=ISTP+CPUINTn*32; // address of interrupt fetch packet in memory
i_u_p=(Uint32*)i_u;

// copy fetch packet to IST
for(i=0;i<8;i++)
{
// modify address?
i_u=0;
if(i==1)
i_u=isr_address&0xffff; // low address
if(i==2)
i_u=(isr_address>>16)&0xffff; // high address
i_u<<=7;
i_u_p[i]=isr_fetch_packet_p[i]|i_u;
}
// interrupts are described in "sprufk5 TMS320C674x DSP Megamodule Reference Guide.pdf"
// section "7 interrupt controller"

INTMUX1=0xffffffff;
INTMUX2=0xffffffff;
INTMUX3=0xffffffff;
// clear all interrupt mux mappings

EVTCLR0=0xffffffff;
EVTCLR1=0xffffffff;
EVTCLR2=0xffffffff;
EVTCLR3=0xffffffff;
// clear all interrupt event flags

i_u=isr_INTn;
i_u<<=((CPUINTn&0x3)*8);
mask= 0xff<<((CPUINTn&0x3)*8);
mask^=0xffffffff;
if((CPUINTn>=4)&&(CPUINTn<=7))
INTMUX1=(INTMUX1&mask)|i_u;
if((CPUINTn>=8)&&(CPUINTn<))
INTMUX2=(INTMUX2&mask)|i_u;
if((CPUINTn>)&&(CPUINTn<))
INTMUX3=(INTMUX3&mask)|i_u;
i_u=1< i_u|=2; // enable NMIE
IER|=i_u;

CSR|=1; // GIE : enable maskable interrupts

The interrupt callback function is:

interrupt void DMA2_ISR(void)
// interrupt called when DMA2 is complted.
// this is the DMA servicing the receive data stream (microphone echo data)
// when we're done reading the mic echo, then turn off the
// D/A stream to the transmitters so we don't get any spurious transmitter
// behavior.
{
EDMA3_ICR=dma_tcc_mask_d;
// clear the dma interrupt flag so the event can be triggerd again.
wait_for_dma_flg=0;
}

When this code is executing when the interrupt fires, everything is fine
while(wait_for_dma_flg) // wait_for_dma_flg is set to 0 in interrupt handler
;

When this code is executing when the interrupt fires, the DSP locks up.

while(!IsDMAAcquireDone()) // function checks wait_for_dma_flg, return's 0 if interrupt hasn't fired.
;

_____________________________________
Jason,

Just a simple guess here, but; I do not see the return from interrupt
instruction in the 32 bytes of code.

per SPRU733a.pdf
5.3.4.2 Returning From Nonmaskable Interrupts
The NMI return pointer register (NRP), shown in Figure 2−12
(page 2-22),
contains the return pointer that directs the CPU to the
proper location to contin-
ue program execution after NMI processing. A branch using
the address in
NRP (B NRP) in your interrupt service routine returns to
the program flow
when NMI servicing is complete. Example 5−8 shows how to
return from an
NMI.
Example 5−8. Code to Return From NMI
B NRP ; return, sets NMIE
NOP 5 ; delay slots

5.3.4.3 Returning From Maskable Interrupts
The interrupt return pointer register (IRP), shown in
Figure 2−9 (page 2-19),
contains the return pointer that directs the CPU to the
proper location to contin-
ue program execution after processing a maskable interrupt.
A branch using
the address in IRP (B IRP) in your interrupt service
routine returns to the
program flow when interrupt servicing is complete. Example
5−9 shows how
to return from a maskable interrupt.
Example 5−9. Code to Return from a Maskable Interrupt
B IRP ; return, moves PGIE to GIE
NOP 5 ; delay slots

This comes down to RTFM.

BTW:
I found this info in less than 5 minutes.

R. Williams

---------- Original Message -----------
From: "Jason"
To: c...
Sent: Sun, 06 Feb 2011 23:31:07 -0000
Subject: [c6x] C6747/Omap L137 interrupt handler problem

> I'm having trouble getting an interrupt to work on a C6747. The
> interrupt is causing the processor to lockup. (When I hit break from
> within the debugger, the DSP is no longer executing my program code,
> but is apparently "lost" in memory somewhere.) I've been able to get
> the DMA2_ISR() function to be called with the interrupt fires, but
> things only work when the code that the DSP is executing is a simple
> loop like:
>
> while(wait_for_dma_flg)
> ;
>
> If the code is calling other functions, the DSP locks up when the
> interrupt in called. I'm wondering if I've made a mistake with my
> interrupt handler so the function isn't returning to the correct point
> in the code or some registers have been corrupted.
>
> The snippets from the command linker file and from the *.cpp file that
> holds the code are below.
>
> Please look at how I setup the interrupt callback function and see if
> you can find a reason why the DMA2_ISR() can't return w/o locking up
> the system.
>
> I also would appreciate information on how I was supposed to setup the
> interrupts. I'm not using any library functions, but just setting
> everything up "manually".
>
> linker.cmd file snippet
>
> MEMORY
> {
> VECS: o = 0xFFFF0000 l = 0x00000080
> ARMRAM: o = 0xFFFF0080 l = 0x00001f80
> ISRRAM: o = 0x11800000 l = 0x00000200
> DSPRAM: o = 0x11800200 l = 0x0003FE00
> SHAREDRAM: o = 0x80000000 l = 0x00020000
> SDRAM: o = 0xC3000000 l = 0x01000000
> }
>
> SECTIONS
> {
> .bss > DSPRAM
> .cinit > SHAREDRAM
> .cio > SHAREDRAM
> .const > DSPRAM
> .stack > DSPRAM
> .sysmem > DSPRAM
> .text > DSPRAM
> .switch > DSPRAM
> .far > DSPRAM
> .pextmem > DSPRAM
> .isrvects > ISRRAM
> }
>
> new location for IRS vectors
>
> #pragma DATA_SECTION(".isrvects");
> unsigned char ISR_VECTORS_p[0x200];
>
> The following code setups the interrupt. Overall, the code:
> 1) copies the interrupt service table from ram to rom
> 2) replaces the 32 bytes for interrupt 10 with code that will branch
> to DMA2_ISR() function 3) enables interrupts through IER and CSR registers
>
> /*
> below is a section of code taken from a interrupt handler that's 32
> bytes long. it shows the address 1000db38 being loaded into B0 and
> branched to. that address is embedded into the MVK and MVKH op codes.
> by replacing the address in the op codes with an ISR location, an interrupt
> handler can be created for the Interrupt Service Table (IST)
>
> 10000100 003C30F6 STW.D2T2 B0,*--SP[1]
> 10000104 006D9C2A MVK.S2 0xffffdb38,B0
> 10000108 0008006A MVKH.S2 0x10000000,B0
> 1000010C 00000362 B.S2 B0
> 10000110 003C36E6 LDW.D2T2 *SP++[1],B0
> 10000114 00006000 NOP 4
> 10000118 00000000 NOP
> 1000011C 00000000 NOP
> 31 27 23 19 15 11 7 3 bit location
> . . . . . . . nybble separators
> MVK = 006D9C2A = 00000000011011011001110000101010 binary
> representation of MVK with db38 address db38 > 1101101100111000 dB38 shifted to bit fields 22 - 7
>
> The address in MVK and MVKH are in bit fields 22-7.
> below is a table of a interrupt service fetch packet with the address
> set to 0, which will make it eash to or in an actual ISR jump addres
> */
>
> Uint32 isr_fetch_packet_p[32]= { 0x003C30F6,
> 0x0000002A, // MVK w address 0
> 0x0000006A, // MVKH w address 0
> 0x00000362,
> 0x003C36E6,
> 0x00006000,
> 0x00000000,
> 0x00000000};
>
> extern cregister volatile unsigned int ISTP; // interrupt service
> table pointer register extern cregister volatile unsigned int CSR;
> // control status register extern cregister volatile unsigned int
> IER; // Interrupt Enable Register // these registers are described
> in "sprufe8 TMS320C674x DSP CPU and Instruction Set User's Guide .pdf"
>
> Uint32 isr_address=(Uint32) DMA2_ISR;
> // interrupt function callback address
> Uint32 isr_INTn=8;
> // one of the 128 DSP interrupts given in "Table 6-9. OMAP-L137 DSP
> Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> (Rev. C) .pdf" // thst is to be processed by the isr_address callback
> function // // I setup the DMA2 to fire off a "EDMA3CC_INT0"
> interrupt // interrupt #'s given in "Table 6-9. OMAP-L137 DSP
> Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> (Rev. C) .pdf" // the EDMA interrupts I' have ot choose from are: //
> 8 EDMA3_CC0_INT1 EDMA3 CC0 Region 1 interrupt // 56
> EDMA3_CC0_ERRINT EDMA3 Channel Controller 0 // 57
> EDMA3_TC0_ERRINT EDMA3 Transfer Controller 0 // 58
> EDMA3_TC1_ERRINT EDMA3 Transfer Controller 1 // NOTE: I looked at
> the EVTFLAG1 (see the MegaModule manual) register after // the
> DMA complted and saw that Event 56 had been set, so apparently //
> i want to trigger on event 56... :) // I'm trying to use a
> "transfer complete" (TC) interrupt for DRAE shadow region 0, so I suppose
> // interrupt 57 is what I want... but this is clear as mud from the
> above interrupt descirptions, // and the Figure 12 on page 44 of the
> EDMA manual only shows CC interrupts... // the description for 57 as
> "ERRINT" make it sound like an error interrupt, but maybe it's //
> both an TC and error interrupts... :) Uint32 CPUINTn; // CPU
> interrupt that the isr_INTn interrupt will be mapped to // this is
> one of the 12 CPU maskable interrupts specfied in figure 7-8 on page
> 164 of "sprufk5 TMS320C674x DSP Megamodule Reference Guide .pdf" //
> this is the entry in the interrupt service callback function that gets
> executed // // it's unclear to me if this event has anything to do
> with the events specfied // in table 7-2 on page 167 of "sprufk5
> TMS320C674x DSP Megamodule Reference Guide .pdf" // but it doesn't
> appear to be the case as this table matches the main 128 interrupt //
> table given in table 6-9 of the the main processor manual "OMAP-L137
> Low-Power Applications Processor (Rev. C) .pdf"
>
>
> Uint32 *i_u_p,mask;
> unsigned char * c_u_p;
>
> // copy rom based ist to ram based ist
> c_u_p=(unsigned char*)ISTP;
> for(i=0;i<0x200;i++)
> ISR_VECTORS_p[i]=c_u_p[i];
> ISTP=(unsigned int)ISR_VECTORS_p;
>
> i_u=ISTP+CPUINTn*32; // address of interrupt fetch packet in memory
> i_u_p=(Uint32*)i_u;
>
> // copy fetch packet to IST
> for(i=0;i<8;i++)
> {
> // modify address?
> i_u=0;
> if(i==1)
> i_u=isr_address&0xffff; // low address
> if(i==2)
> i_u=(isr_address>>16)&0xffff; // high address
> i_u<<=7;
> i_u_p[i]=isr_fetch_packet_p[i]|i_u;
> }
>
> // interrupts are described in "sprufk5 TMS320C674x DSP Megamodule
> Reference Guide.pdf" // section "7 interrupt controller"
>
> INTMUX1=0xffffffff;
> INTMUX2=0xffffffff;
> INTMUX3=0xffffffff;
> // clear all interrupt mux mappings
>
> EVTCLR0=0xffffffff;
> EVTCLR1=0xffffffff;
> EVTCLR2=0xffffffff;
> EVTCLR3=0xffffffff;
> // clear all interrupt event flags
>
> i_u=isr_INTn;
> i_u<<=((CPUINTn&0x3)*8);
> mask= 0xff<<((CPUINTn&0x3)*8);
> mask^=0xffffffff;
> if((CPUINTn>=4)&&(CPUINTn<=7))
> INTMUX1=(INTMUX1&mask)|i_u;
> if((CPUINTn>=8)&&(CPUINTn<))
> INTMUX2=(INTMUX2&mask)|i_u;
> if((CPUINTn>)&&(CPUINTn<))
> INTMUX3=(INTMUX3&mask)|i_u;
>
> i_u=1< > i_u|=2; // enable NMIE
> IER|=i_u;
>
> CSR|=1; // GIE : enable maskable interrupts
>
> The interrupt callback function is:
>
>
> interrupt void DMA2_ISR(void)
> // interrupt called when DMA2 is complted.
> // this is the DMA servicing the receive data stream (microphone echo
> data) // when we're done reading the mic echo, then turn off the //
> D/A stream to the transmitters so we don't get any spurious
> transmitter // behavior. { EDMA3_ICR=dma_tcc_mask_d; // clear
> the dma interrupt flag so the event can be triggerd again. wait_for_dma_flg=0;
> }
>
> When this code is executing when the interrupt fires, everything is
> fine while(wait_for_dma_flg) // wait_for_dma_flg is set to 0 in
> interrupt handler ;
>
> When this code is executing when the interrupt fires, the DSP locks
> up.
>
> while(!IsDMAAcquireDone()) // function checks wait_for_dma_flg,
> return's 0 if interrupt hasn't fired. ;
------- End of Original Message -------

_____________________________________
Jason,

address 1000db38 does not exist on the OMAP-L137 - of course the DSP will
get lost in memory nirvana if your interrupt branches into a non-existing
memory area.

Since there is no reference to this memory area in your linker command
file, the problem is most likely caused by an erroneous pointer operation:
make sure the address of your DMA2_ISR() function is calculated correctly.

The disassembly of your interrupt vector table shows addresses 10000100
etc, which again are non-existent on the L137. You linker command file
defines ARM local memory at 0xFFFF0000, which is not accessible for the
DSP, and therefore should not be included in the DSP .cmd file. Check the
memory map in the L137 data sheet.

Regards,
Adolf Klemenz

_____________________________________
Jason,

I think you could just put a breakpoint at the first instruction in the desired
interrupt vectors table entry.

Then, 1) you would know the cpu actually got to the point.
2) you could single step through the code to determine where the code fails.

I would suggest keeping an eye on the stack pointer and the contents of the
stack while performing the single stepping.

R. Williams

---------- Original Message -----------
From: "Jason"
To: c...
Sent: Sun, 06 Feb 2011 23:31:07 -0000
Subject: [c6x] C6747/Omap L137 interrupt handler problem

> I'm having trouble getting an interrupt to work on a C6747. The
> interrupt is causing the processor to lockup. (When I hit break from
> within the debugger, the DSP is no longer executing my program code,
> but is apparently "lost" in memory somewhere.) I've been able to get
> the DMA2_ISR() function to be called with the interrupt fires, but
> things only work when the code that the DSP is executing is a simple
> loop like:
>
> while(wait_for_dma_flg)
> ;
>
> If the code is calling other functions, the DSP locks up when the
> interrupt in called. I'm wondering if I've made a mistake with my
> interrupt handler so the function isn't returning to the correct point
> in the code or some registers have been corrupted.
>
> The snippets from the command linker file and from the *.cpp file that
> holds the code are below.
>
> Please look at how I setup the interrupt callback function and see if
> you can find a reason why the DMA2_ISR() can't return w/o locking up
> the system.
>
> I also would appreciate information on how I was supposed to setup the
> interrupts. I'm not using any library functions, but just setting
> everything up "manually".
>
> linker.cmd file snippet
>
> MEMORY
> {
> VECS: o = 0xFFFF0000 l = 0x00000080
> ARMRAM: o = 0xFFFF0080 l = 0x00001f80
> ISRRAM: o = 0x11800000 l = 0x00000200
> DSPRAM: o = 0x11800200 l = 0x0003FE00
> SHAREDRAM: o = 0x80000000 l = 0x00020000
> SDRAM: o = 0xC3000000 l = 0x01000000
> }
>
> SECTIONS
> {
> .bss > DSPRAM
> .cinit > SHAREDRAM
> .cio > SHAREDRAM
> .const > DSPRAM
> .stack > DSPRAM
> .sysmem > DSPRAM
> .text > DSPRAM
> .switch > DSPRAM
> .far > DSPRAM
> .pextmem > DSPRAM
> .isrvects > ISRRAM
> }
>
> new location for IRS vectors
>
> #pragma DATA_SECTION(".isrvects");
> unsigned char ISR_VECTORS_p[0x200];
>
> The following code setups the interrupt. Overall, the code:
> 1) copies the interrupt service table from ram to rom
> 2) replaces the 32 bytes for interrupt 10 with code that will branch
> to DMA2_ISR() function 3) enables interrupts through IER and CSR registers
>
> /*
> below is a section of code taken from a interrupt handler that's 32
> bytes long. it shows the address 1000db38 being loaded into B0 and
> branched to. that address is embedded into the MVK and MVKH op codes.
> by replacing the address in the op codes with an ISR location, an interrupt
> handler can be created for the Interrupt Service Table (IST)
>
> 10000100 003C30F6 STW.D2T2 B0,*--SP[1]
> 10000104 006D9C2A MVK.S2 0xffffdb38,B0
> 10000108 0008006A MVKH.S2 0x10000000,B0
> 1000010C 00000362 B.S2 B0
> 10000110 003C36E6 LDW.D2T2 *SP++[1],B0
> 10000114 00006000 NOP 4
> 10000118 00000000 NOP
> 1000011C 00000000 NOP
> 31 27 23 19 15 11 7 3 bit location
> . . . . . . . nybble separators
> MVK = 006D9C2A = 00000000011011011001110000101010 binary
> representation of MVK with db38 address db38 > 1101101100111000 dB38 shifted to bit fields 22 - 7
>
> The address in MVK and MVKH are in bit fields 22-7.
> below is a table of a interrupt service fetch packet with the address
> set to 0, which will make it eash to or in an actual ISR jump addres
> */
>
> Uint32 isr_fetch_packet_p[32]= { 0x003C30F6,
> 0x0000002A, // MVK w address 0
> 0x0000006A, // MVKH w address 0
> 0x00000362,
> 0x003C36E6,
> 0x00006000,
> 0x00000000,
> 0x00000000};
>
> extern cregister volatile unsigned int ISTP; // interrupt service
> table pointer register extern cregister volatile unsigned int CSR;
> // control status register extern cregister volatile unsigned int
> IER; // Interrupt Enable Register // these registers are described
> in "sprufe8 TMS320C674x DSP CPU and Instruction Set User's Guide .pdf"
>
> Uint32 isr_address=(Uint32) DMA2_ISR;
> // interrupt function callback address
> Uint32 isr_INTn=8;
> // one of the 128 DSP interrupts given in "Table 6-9. OMAP-L137 DSP
> Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> (Rev. C) .pdf" // thst is to be processed by the isr_address callback
> function // // I setup the DMA2 to fire off a "EDMA3CC_INT0"
> interrupt // interrupt #'s given in "Table 6-9. OMAP-L137 DSP
> Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> (Rev. C) .pdf" // the EDMA interrupts I' have ot choose from are: //
> 8 EDMA3_CC0_INT1 EDMA3 CC0 Region 1 interrupt // 56
> EDMA3_CC0_ERRINT EDMA3 Channel Controller 0 // 57
> EDMA3_TC0_ERRINT EDMA3 Transfer Controller 0 // 58
> EDMA3_TC1_ERRINT EDMA3 Transfer Controller 1 // NOTE: I looked at
> the EVTFLAG1 (see the MegaModule manual) register after // the
> DMA complted and saw that Event 56 had been set, so apparently //
> i want to trigger on event 56... :) // I'm trying to use a
> "transfer complete" (TC) interrupt for DRAE shadow region 0, so I suppose
> // interrupt 57 is what I want... but this is clear as mud from the
> above interrupt descirptions, // and the Figure 12 on page 44 of the
> EDMA manual only shows CC interrupts... // the description for 57 as
> "ERRINT" make it sound like an error interrupt, but maybe it's //
> both an TC and error interrupts... :) Uint32 CPUINTn; // CPU
> interrupt that the isr_INTn interrupt will be mapped to // this is
> one of the 12 CPU maskable interrupts specfied in figure 7-8 on page
> 164 of "sprufk5 TMS320C674x DSP Megamodule Reference Guide .pdf" //
> this is the entry in the interrupt service callback function that gets
> executed // // it's unclear to me if this event has anything to do
> with the events specfied // in table 7-2 on page 167 of "sprufk5
> TMS320C674x DSP Megamodule Reference Guide .pdf" // but it doesn't
> appear to be the case as this table matches the main 128 interrupt //
> table given in table 6-9 of the the main processor manual "OMAP-L137
> Low-Power Applications Processor (Rev. C) .pdf"
>
>
> Uint32 *i_u_p,mask;
> unsigned char * c_u_p;
>
> // copy rom based ist to ram based ist
> c_u_p=(unsigned char*)ISTP;
> for(i=0;i<0x200;i++)
> ISR_VECTORS_p[i]=c_u_p[i];
> ISTP=(unsigned int)ISR_VECTORS_p;
>
> i_u=ISTP+CPUINTn*32; // address of interrupt fetch packet in memory
> i_u_p=(Uint32*)i_u;
>
> // copy fetch packet to IST
> for(i=0;i<8;i++)
> {
> // modify address?
> i_u=0;
> if(i==1)
> i_u=isr_address&0xffff; // low address
> if(i==2)
> i_u=(isr_address>>16)&0xffff; // high address
> i_u<<=7;
> i_u_p[i]=isr_fetch_packet_p[i]|i_u;
> }
>
> // interrupts are described in "sprufk5 TMS320C674x DSP Megamodule
> Reference Guide.pdf" // section "7 interrupt controller"
>
> INTMUX1=0xffffffff;
> INTMUX2=0xffffffff;
> INTMUX3=0xffffffff;
> // clear all interrupt mux mappings
>
> EVTCLR0=0xffffffff;
> EVTCLR1=0xffffffff;
> EVTCLR2=0xffffffff;
> EVTCLR3=0xffffffff;
> // clear all interrupt event flags
>
> i_u=isr_INTn;
> i_u<<=((CPUINTn&0x3)*8);
> mask= 0xff<<((CPUINTn&0x3)*8);
> mask^=0xffffffff;
> if((CPUINTn>=4)&&(CPUINTn<=7))
> INTMUX1=(INTMUX1&mask)|i_u;
> if((CPUINTn>=8)&&(CPUINTn<))
> INTMUX2=(INTMUX2&mask)|i_u;
> if((CPUINTn>)&&(CPUINTn<))
> INTMUX3=(INTMUX3&mask)|i_u;
>
> i_u=1< > i_u|=2; // enable NMIE
> IER|=i_u;
>
> CSR|=1; // GIE : enable maskable interrupts
>
> The interrupt callback function is:
>
>
> interrupt void DMA2_ISR(void)
> // interrupt called when DMA2 is complted.
> // this is the DMA servicing the receive data stream (microphone echo
> data) // when we're done reading the mic echo, then turn off the //
> D/A stream to the transmitters so we don't get any spurious
> transmitter // behavior. { EDMA3_ICR=dma_tcc_mask_d; // clear
> the dma interrupt flag so the event can be triggerd again. wait_for_dma_flg=0;
> }
>
> When this code is executing when the interrupt fires, everything is
> fine while(wait_for_dma_flg) // wait_for_dma_flg is set to 0 in
> interrupt handler ;
>
> When this code is executing when the interrupt fires, the DSP locks
> up.
>
> while(!IsDMAAcquireDone()) // function checks wait_for_dma_flg,
> return's 0 if interrupt hasn't fired. ;
------- End of Original Message -------

_____________________________________
jason,

First, normally post to the group, not to me.

The detail you gave:
--
while(GetFlag())
;

void GetFlag(void) { return clear_this_flag_in_the_interrupt_fn;}
--
has a problem.
specifically, the function GetFlag() is defined as a 'void' return type.
This means the statement:
while(GetFlag());
will never exit the loop.
This leads me to believe your post has a few oops items.

If your representation of the code is not absolutely correct, I would suggest
you email me (direct) the actual code in the interrupt function and in the main
function.
Note: I'm currently assuming your code is not using the BIOS.

R. Williams

---------- Original Message -----------
From: Jason McIntosh
To: Richard Williams
Sent: Mon, 7 Feb 2011 09:05:39 -0800 (PST)
Subject: Re: [c6x] C6747/Omap L137 interrupt handler problem

> Richard,
>
> I appreciate the guess. I used the keyword "interrupt" when I
> declared and defined the function I branched to in the "32 byte
> interrupt service routine" block. I looked at the assembly that the
> C++ compiler generated for the function and found:
>
> 11803C68 DMA2_ISR:
> 11803C68 2277 STW.D2T1 A4,*B15--[2]
> 11803C6A AC35 STW.D2T1 A3,*B15[1]
> 11803C6C 02083828 MVK.S1 0x1070,A4
> 11803C70 0200E069 MVKH.S1 0x1c00000,A4
> 11803C74 85A6 || MVK.L1 4,A3
> 11803C76 0034 STW.D1T1 A3,*A4[0]
> 11803C78 AC3D LDW.D2T1 *B15[1],A3
> 11803C7A 6277 LDW.D2T1 *++B15[2],A4
> 11803C7C EC800000 .fphead n, l, W, BU, nobr, nosat, 1100100
> 11803C80 001800E2 B.S2 IRP
> 11803C84 00008000 NOP 5
>
> I'm using interrupt 10 (INT10), which I believe is a maskable
> interrupt, so the IRP would be the correct return instruction.
>
> As I indicated in my post, the interrupt does work when the code
> that's interrupted is very simple, like:
>
> clear_this_flag_in_the_interrupt_fn=1;
> while(clear_this_flag_in_the_interrupt_fn)
> ;
>
> The interrupt function will clear
> "clear_this_flag_in_the_interrupt_fn" and the while loop breaks and
> everything continues just fine. So it seems that the interrupt is
> causing the CPU to get sent my interrupt function and returns
> executing to the main program. But if I'm executing some code like:
>
> clear_this_flag_in_the_interrupt_fn=1;
> while(GetFlag())
> ;
>
> void GetFlag(void) { return clear_this_flag_in_the_interrupt_fn;}
>
> The processor hangs. There seems to be something about having the
> interrupt hit when I'm executing some "complex code" that is a problem.
>
> >This comes down to RTFM.
> >BTW:
> >I found this info in less than 5 minutes.
>
> Got another 5 mins?
>
> Jason
>
> ________________________________
> From: Richard Williams
> To: Jason ; c...
> Sent: Mon, February 7, 2011 5:09:56 AM
> Subject: Re: [c6x] C6747/Omap L137 interrupt handler problem
>
> Jason,
>
> Just a simple guess here, but; I do not see the return from interrupt
> instruction in the 32 bytes of code.
>
> per SPRU733a.pdf
>
> 5.3.4.2 Returning From Nonmaskable Interrupts
> The NMI return pointer register (NRP), shown in
> Figure 2−12
> (page 2-22), contains the return pointer that
> directs the CPU to the proper location to contin-
> ue program execution after NMI processing. A branch using the address
> in NRP (B NRP) in your interrupt service routine
> returns to the program flow when NMI servicing is
> complete. Example 5−8 shows how to return from an
> NMI.
>
> Example 5−8. Code to Return >From NMI
> B NRP ; return, sets NMIE
> NOP 5 ; delay slots
>
> 5.3.4.3 Returning From Maskable Interrupts
> The interrupt return pointer register (IRP),
> shown in Figure 2−9 (page 2-19), contains the
> return pointer that directs the CPU to the proper location to contin-
> ue program execution after processing a maskable interrupt.
> A branch using
> the address in IRP (B IRP) in your interrupt service
> routine returns to the
> program flow when interrupt servicing is
> complete. Example 5−9 shows how to return from a
> maskable interrupt.
>
> Example 5−9. Code to Return from a Maskable Interrupt
> B IRP ; return, moves PGIE to GIE
> NOP 5 ; delay slots
>
> This comes down to RTFM.
>
> BTW:
> I found this info in less than 5 minutes.
>
> R. Williams
>
> ---------- Original Message -----------
> From: "Jason"
> To: c...
> Sent: Sun, 06 Feb 2011 23:31:07 -0000
> Subject: [c6x] C6747/Omap L137 interrupt handler problem
>
> > I'm having trouble getting an interrupt to work on a C6747. The
> > interrupt is causing the processor to lockup. (When I hit break from
> > within the debugger, the DSP is no longer executing my program code,
> > but is apparently "lost" in memory somewhere.) I've been able to get
> > the DMA2_ISR() function to be called with the interrupt fires, but
> > things only work when the code that the DSP is executing is a simple
> > loop like:
> >
> > while(wait_for_dma_flg)
> > ;
> >
> > If the code is calling other functions, the DSP locks up when the
> > interrupt in called. I'm wondering if I've made a mistake with my
> > interrupt handler so the function isn't returning to the correct point
> > in the code or some registers have been corrupted.
> >
> > The snippets from the command linker file and from the *.cpp file that
> > holds the code are below.
> >
> > Please look at how I setup the interrupt callback function and see if
> > you can find a reason why the DMA2_ISR() can't return w/o locking up
> > the system.
> >
> > I also would appreciate information on how I was supposed to setup the
> > interrupts. I'm not using any library functions, but just setting
> > everything up "manually".
> >
> > linker.cmd file snippet
> >
> > MEMORY
> > {
> > VECS: o = 0xFFFF0000 l = 0x00000080
> > ARMRAM: o = 0xFFFF0080 l = 0x00001f80
> > ISRRAM: o = 0x11800000 l = 0x00000200
> > DSPRAM: o = 0x11800200 l = 0x0003FE00
> > SHAREDRAM: o = 0x80000000 l = 0x00020000
> > SDRAM: o = 0xC3000000 l = 0x01000000
> > }
> >
> > SECTIONS
> > {
> > .bss > DSPRAM
> > .cinit > SHAREDRAM
> > .cio > SHAREDRAM
> > .const > DSPRAM
> > .stack > DSPRAM
> > .sysmem > DSPRAM
> > .text > DSPRAM
> > .switch > DSPRAM
> > .far > DSPRAM
> > .pextmem > DSPRAM
> > .isrvects > ISRRAM
> > }
> >
> > new location for IRS vectors
> >
> > #pragma DATA_SECTION(".isrvects");
> > unsigned char ISR_VECTORS_p[0x200];
> >
> > The following code setups the interrupt. Overall, the code:
> > 1) copies the interrupt service table from ram to rom
> > 2) replaces the 32 bytes for interrupt 10 with code that will branch
> > to DMA2_ISR() function 3) enables interrupts through IER and CSR registers
> >
> > /*
> > below is a section of code taken from a interrupt handler that's 32
> > bytes long. it shows the address 1000db38 being loaded into B0 and
> > branched to. that address is embedded into the MVK and MVKH op codes.
> > by replacing the address in the op codes with an ISR location, an
> interrupt
> > handler can be created for the Interrupt Service Table (IST)
> >
> > 10000100 003C30F6 STW.D2T2 B0,*--SP[1]
> > 10000104 006D9C2A MVK.S2 0xffffdb38,B0
> > 10000108 0008006A MVKH.S2 0x10000000,B0
> > 1000010C 00000362 B.S2 B0
> > 10000110 003C36E6 LDW.D2T2 *SP++[1],B0
> > 10000114 00006000 NOP 4
> > 10000118 00000000 NOP
> > 1000011C 00000000 NOP
> > 31 27 23 19 15 11 7 3 bit location
> > . . . . . . . nybble separators
> > MVK = 006D9C2A = 00000000011011011001110000101010 binary
> > representation of MVK with db38 address db38 > > 1101101100111000 dB38 shifted to bit fields 22 - 7
> >
> > The address in MVK and MVKH are in bit fields 22-7.
> > below is a table of a interrupt service fetch packet with the address
> > set to 0, which will make it eash to or in an actual ISR jump addres
> > */
> >
> > Uint32 isr_fetch_packet_p[32]= { 0x003C30F6,
> > 0x0000002A, // MVK w address 0
> > 0x0000006A, // MVKH w address 0
> > 0x00000362,
> > 0x003C36E6,
> > 0x00006000,
> > 0x00000000,
> > 0x00000000};
> >
> > extern cregister volatile unsigned int ISTP; // interrupt service
> > table pointer register extern cregister volatile unsigned int CSR;
> > // control status register extern cregister volatile unsigned int
> > IER; // Interrupt Enable Register // these registers are described
> > in "sprufe8 TMS320C674x DSP CPU and Instruction Set User's Guide .pdf"
> >
> > Uint32 isr_address=(Uint32) DMA2_ISR;
> > // interrupt function callback address
> > Uint32 isr_INTn=8;
> > // one of the 128 DSP interrupts given in "Table 6-9. OMAP-L137 DSP
> > Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> > (Rev. C) .pdf" // thst is to be processed by the isr_address callback
> > function // // I setup the DMA2 to fire off a "EDMA3CC_INT0"
> > interrupt // interrupt #'s given in "Table 6-9. OMAP-L137 DSP
> > Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> > (Rev. C) .pdf" // the EDMA interrupts I' have ot choose from are: //
> > 8 EDMA3_CC0_INT1 EDMA3 CC0 Region 1 interrupt // 56
> > EDMA3_CC0_ERRINT EDMA3 Channel Controller 0 // 57
> > EDMA3_TC0_ERRINT EDMA3 Transfer Controller 0 // 58
> > EDMA3_TC1_ERRINT EDMA3 Transfer Controller 1 // NOTE: I looked at
> > the EVTFLAG1 (see the MegaModule manual) register after // the
> > DMA complted and saw that Event 56 had been set, so apparently //
> > i want to trigger on event 56... :) // I'm trying to use a
> > "transfer complete" (TC) interrupt for DRAE shadow region 0, so I suppose
> > // interrupt 57 is what I want... but this is clear as mud from the
> > above interrupt descirptions, // and the Figure 12 on page 44 of the
> > EDMA manual only shows CC interrupts... // the description for 57 as
> > "ERRINT" make it sound like an error interrupt, but maybe it's //
> > both an TC and error interrupts... :) Uint32 CPUINTn; // CPU
> > interrupt that the isr_INTn interrupt will be mapped to // this is
> > one of the 12 CPU maskable interrupts specfied in figure 7-8 on page
> > 164 of "sprufk5 TMS320C674x DSP Megamodule Reference Guide .pdf" //
> > this is the entry in the interrupt service callback function that gets
> > executed // // it's unclear to me if this event has anything to do
> > with the events specfied // in table 7-2 on page 167 of "sprufk5
> > TMS320C674x DSP Megamodule Reference Guide .pdf" // but it doesn't
> > appear to be the case as this table matches the main 128 interrupt //
> > table given in table 6-9 of the the main processor manual "OMAP-L137
> > Low-Power Applications Processor (Rev. C) .pdf"
> >
> >
> > Uint32 *i_u_p,mask;
> > unsigned char * c_u_p;
> >
> > // copy rom based ist to ram based ist
> > c_u_p=(unsigned char*)ISTP;
> > for(i=0;i<0x200;i++)
> > ISR_VECTORS_p[i]=c_u_p[i];
> > ISTP=(unsigned int)ISR_VECTORS_p;
> >
> > i_u=ISTP+CPUINTn*32; // address of interrupt fetch packet in memory
> > i_u_p=(Uint32*)i_u;
> >
> > // copy fetch packet to IST
> > for(i=0;i<8;i++)
> > {
> > // modify address?
> > i_u=0;
> > if(i==1)
> > i_u=isr_address&0xffff; // low address
> > if(i==2)
> > i_u=(isr_address>>16)&0xffff; // high address
> > i_u<<=7;
> > i_u_p[i]=isr_fetch_packet_p[i]|i_u;
> > }
> >
> > // interrupts are described in "sprufk5 TMS320C674x DSP Megamodule
> > Reference Guide.pdf" // section "7 interrupt controller"
> >
> > INTMUX1=0xffffffff;
> > INTMUX2=0xffffffff;
> > INTMUX3=0xffffffff;
> > // clear all interrupt mux mappings
> >
> > EVTCLR0=0xffffffff;
> > EVTCLR1=0xffffffff;
> > EVTCLR2=0xffffffff;
> > EVTCLR3=0xffffffff;
> > // clear all interrupt event flags
> >
> > i_u=isr_INTn;
> > i_u<<=((CPUINTn&0x3)*8);
> > mask= 0xff<<((CPUINTn&0x3)*8);
> > mask^=0xffffffff;
> > if((CPUINTn>=4)&&(CPUINTn<=7))
> > INTMUX1=(INTMUX1&mask)|i_u;
> > if((CPUINTn>=8)&&(CPUINTn<))
> > INTMUX2=(INTMUX2&mask)|i_u;
> > if((CPUINTn>)&&(CPUINTn<))
> > INTMUX3=(INTMUX3&mask)|i_u;
> >
> > i_u=1< > > i_u|=2; // enable NMIE
> > IER|=i_u;
> >
> > CSR|=1; // GIE : enable maskable interrupts
> >
> > The interrupt callback function is:
> >
> >
> > interrupt void DMA2_ISR(void)
> > // interrupt called when DMA2 is complted.
> > // this is the DMA servicing the receive data stream (microphone echo
> > data) // when we're done reading the mic echo, then turn off the //
> > D/A stream to the transmitters so we don't get any spurious
> > transmitter // behavior. { EDMA3_ICR=dma_tcc_mask_d; //
> >clear
> >
> > the dma interrupt flag so the event can be triggerd again.
> >wait_for_dma_flg=0;
> > }
> >
> > When this code is executing when the interrupt fires, everything is
> > fine while(wait_for_dma_flg) // wait_for_dma_flg is set to 0 in
> > interrupt handler ;
> >
> > When this code is executing when the interrupt fires, the DSP locks
> > up.
> >
> > while(!IsDMAAcquireDone()) // function checks wait_for_dma_flg,
> > return's 0 if interrupt hasn't fired. ;
> ------- End of Original Message -------
------- End of Original Message -------

_____________________________________
I had a few replies to my problem. Thanks for trying to help out, but I'm still stuck.

Richard's thought was that there's no IRP, but I put the "interrupt" keyword in my DMA2_ISR() interrupt function. I looked at the functions dissassembly and I do see the IRP instruction at the end:

11803C68 DMA2_ISR:
11803C68 2277 STW.D2T1 A4,*B15--[2]
11803C6A AC35 STW.D2T1 A3,*B15[1]
11803C6C 02083828 MVK.S1 0x1070,A4
11803C70 0200E069 MVKH.S1 0x1c00000,A4
11803C74 85A6 || MVK.L1 4,A3
11803C76 0034 STW.D1T1 A3,*A4[0]
11803C78 AC3D LDW.D2T1 *B15[1],A3
11803C7A 6277 LDW.D2T1 *++B15[2],A4
11803C7C EC800000 .fphead n, l, W, BU, nobr, nosat, 1100100
11803C80 001800E2 B.S2 IRP
11803C84 00008000 NOP 5
As I indicated in my post, the interrupt does work when the code that's interrupted is very simple, like:

clear_this_flag_in_the_interrupt_fn=1;
while(clear_this_flag_in_the_interrupt_fn)
;

The interrupt function will clear "clear_this_flag_in_the_interrupt_fn" and the while loop breaks and everything continues just fine. So it seems that the interrupt is causing the CPU to get sent my interrupt function and returns executing to the main program. But if I'm executing some code like:

clear_this_flag_in_the_interrupt_fn=1;
while(GetFlag())
;

void GetFlag(void) { return clear_this_flag_in_the_interrupt_fn;}

The processor hangs and when I hit break, it's trying to execute garbage code outside of my program. There seems to be something about having the interrupt hit when I'm executing some "complex code" that is a problem.

Obviously there's something wrong, but I can't think of anything else to check.

I'm not using any CSL, just directly programming all of the registers myself (McASP, EDMA, interrupt module, etc.) I suppose there may be something I'm missing because I'm not using a CSL, but I've been able to get by w/o one and so I'm not excited about trying to use one now.

Any thoughts are appreciated.

Jason

--- In c..., "Richard Williams" wrote:
>
> Jason,
>
> Just a simple guess here, but; I do not see the return from interrupt
> instruction in the 32 bytes of code.
>
> per SPRU733a.pdf
>
>
> 5.3.4.2 Returning From Nonmaskable Interrupts
> The NMI return pointer register (NRP), shown in Figure 2#039;12
> (page 2-22),
> contains the return pointer that directs the CPU to the
> proper location to contin-
> ue program execution after NMI processing. A branch using
> the address in
> NRP (B NRP) in your interrupt service routine returns to
> the program flow
> when NMI servicing is complete. Example 5#039;8 shows how to
> return from an
> NMI.
>
>
> Example 5#039;8. Code to Return From NMI
> B NRP ; return, sets NMIE
> NOP 5 ; delay slots
>
>
>
>
> 5.3.4.3 Returning From Maskable Interrupts
> The interrupt return pointer register (IRP), shown in
> Figure 2#039;9 (page 2-19),
> contains the return pointer that directs the CPU to the
> proper location to contin-
> ue program execution after processing a maskable interrupt.
> A branch using
> the address in IRP (B IRP) in your interrupt service
> routine returns to the
> program flow when interrupt servicing is complete. Example
> 5#039;9 shows how
> to return from a maskable interrupt.
>
>
> Example 5#039;9. Code to Return from a Maskable Interrupt
> B IRP ; return, moves PGIE to GIE
> NOP 5 ; delay slots
>
>
>
>
> This comes down to RTFM.
>
> BTW:
> I found this info in less than 5 minutes.
>
> R. Williams
>
> ---------- Original Message -----------
> From: "Jason"
> To: c...
> Sent: Sun, 06 Feb 2011 23:31:07 -0000
> Subject: [c6x] C6747/Omap L137 interrupt handler problem
>
> > I'm having trouble getting an interrupt to work on a C6747. The
> > interrupt is causing the processor to lockup. (When I hit break from
> > within the debugger, the DSP is no longer executing my program code,
> > but is apparently "lost" in memory somewhere.) I've been able to get
> > the DMA2_ISR() function to be called with the interrupt fires, but
> > things only work when the code that the DSP is executing is a simple
> > loop like:
> >
> > while(wait_for_dma_flg)
> > ;
> >
> > If the code is calling other functions, the DSP locks up when the
> > interrupt in called. I'm wondering if I've made a mistake with my
> > interrupt handler so the function isn't returning to the correct point
> > in the code or some registers have been corrupted.
> >
> > The snippets from the command linker file and from the *.cpp file that
> > holds the code are below.
> >
> > Please look at how I setup the interrupt callback function and see if
> > you can find a reason why the DMA2_ISR() can't return w/o locking up
> > the system.
> >
> > I also would appreciate information on how I was supposed to setup the
> > interrupts. I'm not using any library functions, but just setting
> > everything up "manually".
> >
> > linker.cmd file snippet
> >
> > MEMORY
> > {
> > VECS: o = 0xFFFF0000 l = 0x00000080
> > ARMRAM: o = 0xFFFF0080 l = 0x00001f80
> > ISRRAM: o = 0x11800000 l = 0x00000200
> > DSPRAM: o = 0x11800200 l = 0x0003FE00
> > SHAREDRAM: o = 0x80000000 l = 0x00020000
> > SDRAM: o = 0xC3000000 l = 0x01000000
> > }
> >
> > SECTIONS
> > {
> > .bss > DSPRAM
> > .cinit > SHAREDRAM
> > .cio > SHAREDRAM
> > .const > DSPRAM
> > .stack > DSPRAM
> > .sysmem > DSPRAM
> > .text > DSPRAM
> > .switch > DSPRAM
> > .far > DSPRAM
> > .pextmem > DSPRAM
> > .isrvects > ISRRAM
> > }
> >
> > new location for IRS vectors
> >
> > #pragma DATA_SECTION(".isrvects");
> > unsigned char ISR_VECTORS_p[0x200];
> >
> > The following code setups the interrupt. Overall, the code:
> > 1) copies the interrupt service table from ram to rom
> > 2) replaces the 32 bytes for interrupt 10 with code that will branch
> > to DMA2_ISR() function 3) enables interrupts through IER and CSR registers
> >
> > /*
> > below is a section of code taken from a interrupt handler that's 32
> > bytes long. it shows the address 1000db38 being loaded into B0 and
> > branched to. that address is embedded into the MVK and MVKH op codes.
> > by replacing the address in the op codes with an ISR location, an interrupt
> > handler can be created for the Interrupt Service Table (IST)
> >
> > 10000100 003C30F6 STW.D2T2 B0,*--SP[1]
> > 10000104 006D9C2A MVK.S2 0xffffdb38,B0
> > 10000108 0008006A MVKH.S2 0x10000000,B0
> > 1000010C 00000362 B.S2 B0
> > 10000110 003C36E6 LDW.D2T2 *SP++[1],B0
> > 10000114 00006000 NOP 4
> > 10000118 00000000 NOP
> > 1000011C 00000000 NOP
> > 31 27 23 19 15 11 7 3 bit location
> > . . . . . . . nybble separators
> > MVK = 006D9C2A = 00000000011011011001110000101010 binary
> > representation of MVK with db38 address db38 =
> > 1101101100111000 dB38 shifted to bit fields 22 - 7
> >
> > The address in MVK and MVKH are in bit fields 22-7.
> > below is a table of a interrupt service fetch packet with the address
> > set to 0, which will make it eash to or in an actual ISR jump addres
> > */
> >
> > Uint32 isr_fetch_packet_p[32]= { 0x003C30F6,
> > 0x0000002A, // MVK w address 0
> > 0x0000006A, // MVKH w address 0
> > 0x00000362,
> > 0x003C36E6,
> > 0x00006000,
> > 0x00000000,
> > 0x00000000};
> >
> > extern cregister volatile unsigned int ISTP; // interrupt service
> > table pointer register extern cregister volatile unsigned int CSR;
> > // control status register extern cregister volatile unsigned int
> > IER; // Interrupt Enable Register // these registers are described
> > in "sprufe8 TMS320C674x DSP CPU and Instruction Set User's Guide .pdf"
> >
> > Uint32 isr_address=(Uint32) DMA2_ISR;
> > // interrupt function callback address
> > Uint32 isr_INTn=8;
> > // one of the 128 DSP interrupts given in "Table 6-9. OMAP-L137 DSP
> > Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> > (Rev. C) .pdf" // thst is to be processed by the isr_address callback
> > function // // I setup the DMA2 to fire off a "EDMA3CC_INT0"
> > interrupt // interrupt #'s given in "Table 6-9. OMAP-L137 DSP
> > Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> > (Rev. C) .pdf" // the EDMA interrupts I' have ot choose from are: //
> > 8 EDMA3_CC0_INT1 EDMA3 CC0 Region 1 interrupt // 56
> > EDMA3_CC0_ERRINT EDMA3 Channel Controller 0 // 57
> > EDMA3_TC0_ERRINT EDMA3 Transfer Controller 0 // 58
> > EDMA3_TC1_ERRINT EDMA3 Transfer Controller 1 // NOTE: I looked at
> > the EVTFLAG1 (see the MegaModule manual) register after // the
> > DMA complted and saw that Event 56 had been set, so apparently //
> > i want to trigger on event 56... :) // I'm trying to use a
> > "transfer complete" (TC) interrupt for DRAE shadow region 0, so I suppose
> > // interrupt 57 is what I want... but this is clear as mud from the
> > above interrupt descirptions, // and the Figure 12 on page 44 of the
> > EDMA manual only shows CC interrupts... // the description for 57 as
> > "ERRINT" make it sound like an error interrupt, but maybe it's //
> > both an TC and error interrupts... :) Uint32 CPUINTn=10; // CPU
> > interrupt that the isr_INTn interrupt will be mapped to // this is
> > one of the 12 CPU maskable interrupts specfied in figure 7-8 on page
> > 164 of "sprufk5 TMS320C674x DSP Megamodule Reference Guide .pdf" //
> > this is the entry in the interrupt service callback function that gets
> > executed // // it's unclear to me if this event has anything to do
> > with the events specfied // in table 7-2 on page 167 of "sprufk5
> > TMS320C674x DSP Megamodule Reference Guide .pdf" // but it doesn't
> > appear to be the case as this table matches the main 128 interrupt //
> > table given in table 6-9 of the the main processor manual "OMAP-L137
> > Low-Power Applications Processor (Rev. C) .pdf"
> >
> >
> > Uint32 *i_u_p,mask;
> > unsigned char * c_u_p;
> >
> > // copy rom based ist to ram based ist
> > c_u_p=(unsigned char*)ISTP;
> > for(i=0;i<0x200;i++)
> > ISR_VECTORS_p[i]=c_u_p[i];
> > ISTP=(unsigned int)ISR_VECTORS_p;
> >
> > i_u=ISTP+CPUINTn*32; // address of interrupt fetch packet in memory
> > i_u_p=(Uint32*)i_u;
> >
> > // copy fetch packet to IST
> > for(i=0;i<8;i++)
> > {
> > // modify address?
> > i_u=0;
> > if(i==1)
> > i_u=isr_address&0xffff; // low address
> > if(i==2)
> > i_u=(isr_address>>16)&0xffff; // high address
> > i_u<<=7;
> > i_u_p[i]=isr_fetch_packet_p[i]|i_u;
> > }
> >
> > // interrupts are described in "sprufk5 TMS320C674x DSP Megamodule
> > Reference Guide.pdf" // section "7 interrupt controller"
> >
> > INTMUX1=0xffffffff;
> > INTMUX2=0xffffffff;
> > INTMUX3=0xffffffff;
> > // clear all interrupt mux mappings
> >
> > EVTCLR0=0xffffffff;
> > EVTCLR1=0xffffffff;
> > EVTCLR2=0xffffffff;
> > EVTCLR3=0xffffffff;
> > // clear all interrupt event flags
> >
> > i_u=isr_INTn;
> > i_u<<=((CPUINTn&0x3)*8);
> > mask= 0xff<<((CPUINTn&0x3)*8);
> > mask^=0xffffffff;
> > if((CPUINTn>=4)&&(CPUINTn<=7))
> > INTMUX1=(INTMUX1&mask)|i_u;
> > if((CPUINTn>=8)&&(CPUINTn<=11))
> > INTMUX2=(INTMUX2&mask)|i_u;
> > if((CPUINTn>=12)&&(CPUINTn<=15))
> > INTMUX3=(INTMUX3&mask)|i_u;
> >
> > i_u=1< > > i_u|=2; // enable NMIE
> > IER|=i_u;
> >
> > CSR|=1; // GIE : enable maskable interrupts
> >
> > The interrupt callback function is:
> >
> >
> > interrupt void DMA2_ISR(void)
> > // interrupt called when DMA2 is complted.
> > // this is the DMA servicing the receive data stream (microphone echo
> > data) // when we're done reading the mic echo, then turn off the //
> > D/A stream to the transmitters so we don't get any spurious
> > transmitter // behavior. { EDMA3_ICR=dma_tcc_mask_d; // clear
> > the dma interrupt flag so the event can be triggerd again. wait_for_dma_flg=0;
> > }
> >
> > When this code is executing when the interrupt fires, everything is
> > fine while(wait_for_dma_flg) // wait_for_dma_flg is set to 0 in
> > interrupt handler ;
> >
> > When this code is executing when the interrupt fires, the DSP locks
> > up.
> >
> > while(!IsDMAAcquireDone()) // function checks wait_for_dma_flg,
> > return's 0 if interrupt hasn't fired. ;
> ------- End of Original Message -------
>

_____________________________________
Jason,

the dissasembly of your working DMA_ISR shows only the
clear_this_flag_in_the_interrupt_fn=1; instruction. The while(...) has been
removed by optimization.

If a function is called within an interrupt, the compiler will save and
restore all 64 CPU registers as prolog and epilog of the interrupt. This
requires 256 bytes on the stack. Additional stack space is required for
local variables, return addresses etc.

If your program crashes with a function call inside the interrupt, the
problem may be caused by insufficient stack size.

Regards,
Adolf Klemenz

_____________________________________
Jason,

My suggestion of putting a breakpoint at the beginning of the interrupt and
single stepping from there will tell you what is going on and where the
processor is "stepping into the weeds."
You might try the single stepping with global interrupts disabled and again with
global interrupts enabled.

Are you perhaps getting a different nterrupt, of a higher priority, that does
not have the appropriate interrupt handler installed?

R. Williams

---------- Original Message -----------
From: "Jason"
To: c...
Sent: Mon, 07 Feb 2011 17:25:58 -0000
Subject: [c6x] Re: C6747/Omap L137 interrupt handler problem

> I had a few replies to my problem. Thanks for trying to help out, but
> I'm still stuck.
>
> Richard's thought was that there's no IRP, but I put the "interrupt"
> keyword in my DMA2_ISR() interrupt function. I looked at the
> functions dissassembly and I do see the IRP instruction at the end:
>
> 11803C68 DMA2_ISR:
> 11803C68 2277 STW.D2T1 A4,*B15--[2]
> 11803C6A AC35 STW.D2T1 A3,*B15[1]
> 11803C6C 02083828 MVK.S1 0x1070,A4
> 11803C70 0200E069 MVKH.S1 0x1c00000,A4
> 11803C74 85A6 || MVK.L1 4,A3
> 11803C76 0034 STW.D1T1 A3,*A4[0]
> 11803C78 AC3D LDW.D2T1 *B15[1],A3
> 11803C7A 6277 LDW.D2T1 *++B15[2],A4
> 11803C7C EC800000 .fphead n, l, W, BU, nobr, nosat, 1100100
> 11803C80 001800E2 B.S2 IRP
> 11803C84 00008000 NOP 5
>
> As I indicated in my post, the interrupt does work when the code
> that's interrupted is very simple, like:
>
> clear_this_flag_in_the_interrupt_fn=1;
> while(clear_this_flag_in_the_interrupt_fn)
> ;
>
> The interrupt function will clear
> "clear_this_flag_in_the_interrupt_fn" and the while loop breaks and
> everything continues just fine. So it seems that the interrupt is
> causing the CPU to get sent my interrupt function and returns
> executing to the main program. But if I'm executing some code like:
>
> clear_this_flag_in_the_interrupt_fn=1;
> while(GetFlag())
> ;
>
> void GetFlag(void) { return clear_this_flag_in_the_interrupt_fn;}
>
> The processor hangs and when I hit break, it's trying to execute
> garbage code outside of my program. There seems to be something about
> having the interrupt hit when I'm executing some "complex code" that
> is a problem.
>
> Obviously there's something wrong, but I can't think of anything else
> to check.
>
> I'm not using any CSL, just directly programming all of the registers
> myself (McASP, EDMA, interrupt module, etc.) I suppose there may be
> something I'm missing because I'm not using a CSL, but I've been able
> to get by w/o one and so I'm not excited about trying to use one now.
>
> Any thoughts are appreciated.
>
> Jason
>
> --- In c..., "Richard Williams" wrote:
> >
> > Jason,
> >
> > Just a simple guess here, but; I do not see the return from interrupt
> > instruction in the 32 bytes of code.
> >
> > per SPRU733a.pdf
> >
> >
> > 5.3.4.2 Returning From Nonmaskable Interrupts
> > The NMI return pointer register (NRP), shown in
Figure 2â'12
> > (page 2-22),
> > contains the return pointer that directs the CPU to the
> > proper location to contin-
> > ue program execution after NMI processing. A branch using
> > the address in
> > NRP (B NRP) in your interrupt service routine returns to
> > the program flow
> > when NMI servicing is complete. Example 5â'8 shows how to
> > return from an
> > NMI.
> >
> >
> > Example 5â'8. Code to Return From NMI
> > B NRP ; return, sets NMIE
> > NOP 5 ; delay slots
> >
> >
> >
> >
> > 5.3.4.3 Returning From Maskable Interrupts
> > The interrupt return pointer register (IRP), shown in
> > Figure 2â'9 (page 2-19),
> > contains the return pointer that directs the CPU to the
> > proper location to contin-
> > ue program execution after processing a maskable interrupt.
> > A branch using
> > the address in IRP (B IRP) in your interrupt service
> > routine returns to the
> > program flow when interrupt servicing is complete. Example
> > 5â'9 shows how
> > to return from a maskable interrupt.
> >
> >
> > Example 5â'9. Code to Return from a Maskable Interrupt
> > B IRP ; return, moves PGIE to GIE
> > NOP 5 ; delay slots
> >
> >
> >
> >
> > This comes down to RTFM.
> >
> > BTW:
> > I found this info in less than 5 minutes.
> >
> > R. Williams
> >
> > ---------- Original Message -----------
> > From: "Jason"
> > To: c...
> > Sent: Sun, 06 Feb 2011 23:31:07 -0000
> > Subject: [c6x] C6747/Omap L137 interrupt handler problem
> >
> > > I'm having trouble getting an interrupt to work on a C6747. The
> > > interrupt is causing the processor to lockup. (When I hit break from
> > > within the debugger, the DSP is no longer executing my program code,
> > > but is apparently "lost" in memory somewhere.) I've been able to get
> > > the DMA2_ISR() function to be called with the interrupt fires, but
> > > things only work when the code that the DSP is executing is a simple
> > > loop like:
> > >
> > > while(wait_for_dma_flg)
> > > ;
> > >
> > > If the code is calling other functions, the DSP locks up when the
> > > interrupt in called. I'm wondering if I've made a mistake with my
> > > interrupt handler so the function isn't returning to the correct point
> > > in the code or some registers have been corrupted.
> > >
> > > The snippets from the command linker file and from the *.cpp file that
> > > holds the code are below.
> > >
> > > Please look at how I setup the interrupt callback function and see if
> > > you can find a reason why the DMA2_ISR() can't return w/o locking up
> > > the system.
> > >
> > > I also would appreciate information on how I was supposed to setup the
> > > interrupts. I'm not using any library functions, but just setting
> > > everything up "manually".
> > >
> > > linker.cmd file snippet
> > >
> > > MEMORY
> > > {
> > > VECS: o = 0xFFFF0000 l = 0x00000080
> > > ARMRAM: o = 0xFFFF0080 l = 0x00001f80
> > > ISRRAM: o = 0x11800000 l = 0x00000200
> > > DSPRAM: o = 0x11800200 l = 0x0003FE00
> > > SHAREDRAM: o = 0x80000000 l = 0x00020000
> > > SDRAM: o = 0xC3000000 l = 0x01000000
> > > }
> > >
> > > SECTIONS
> > > {
> > > .bss > DSPRAM
> > > .cinit > SHAREDRAM
> > > .cio > SHAREDRAM
> > > .const > DSPRAM
> > > .stack > DSPRAM
> > > .sysmem > DSPRAM
> > > .text > DSPRAM
> > > .switch > DSPRAM
> > > .far > DSPRAM
> > > .pextmem > DSPRAM
> > > .isrvects > ISRRAM
> > > }
> > >
> > > new location for IRS vectors
> > >
> > > #pragma DATA_SECTION(".isrvects");
> > > unsigned char ISR_VECTORS_p[0x200];
> > >
> > > The following code setups the interrupt. Overall, the code:
> > > 1) copies the interrupt service table from ram to rom
> > > 2) replaces the 32 bytes for interrupt 10 with code that will branch
> > > to DMA2_ISR() function 3) enables interrupts through IER and CSR registers
> > >
> > > /*
> > > below is a section of code taken from a interrupt handler that's 32
> > > bytes long. it shows the address 1000db38 being loaded into B0 and
> > > branched to. that address is embedded into the MVK and MVKH op codes.
> > > by replacing the address in the op codes with an ISR location, an interrupt
> > > handler can be created for the Interrupt Service Table (IST)
> > >
> > > 10000100 003C30F6 STW.D2T2 B0,*--SP[1]
> > > 10000104 006D9C2A MVK.S2 0xffffdb38,B0
> > > 10000108 0008006A MVKH.S2 0x10000000,B0
> > > 1000010C 00000362 B.S2 B0
> > > 10000110 003C36E6 LDW.D2T2 *SP++[1],B0
> > > 10000114 00006000 NOP 4
> > > 10000118 00000000 NOP
> > > 1000011C 00000000 NOP
> > > 31 27 23 19 15 11 7 3 bit location
> > > . . . . . . . nybble separators
> > > MVK = 006D9C2A = 00000000011011011001110000101010 binary
> > > representation of MVK with db38 address db38 > > > 1101101100111000 dB38 shifted to bit fields 22 - 7
> > >
> > > The address in MVK and MVKH are in bit fields 22-7.
> > > below is a table of a interrupt service fetch packet with the address
> > > set to 0, which will make it eash to or in an actual ISR jump addres
> > > */
> > >
> > > Uint32 isr_fetch_packet_p[32]= { 0x003C30F6,
> > > 0x0000002A, // MVK w address 0
> > > 0x0000006A, // MVKH w address 0
> > > 0x00000362,
> > > 0x003C36E6,
> > > 0x00006000,
> > > 0x00000000,
> > > 0x00000000};
> > >
> > > extern cregister volatile unsigned int ISTP; // interrupt service
> > > table pointer register extern cregister volatile unsigned int CSR;
> > > // control status register extern cregister volatile unsigned int
> > > IER; // Interrupt Enable Register // these registers are described
> > > in "sprufe8 TMS320C674x DSP CPU and Instruction Set User's Guide .pdf"
> > >
> > > Uint32 isr_address=(Uint32) DMA2_ISR;
> > > // interrupt function callback address
> > > Uint32 isr_INTn=8;
> > > // one of the 128 DSP interrupts given in "Table 6-9. OMAP-L137 DSP
> > > Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> > > (Rev. C) .pdf" // thst is to be processed by the isr_address callback
> > > function // // I setup the DMA2 to fire off a "EDMA3CC_INT0"
> > > interrupt // interrupt #'s given in "Table 6-9. OMAP-L137 DSP
> > > Interrupts" on page 66 of "OMAP-L137 Low-Power Applications Processor
> > > (Rev. C) .pdf" // the EDMA interrupts I' have ot choose from are: //
> > > 8 EDMA3_CC0_INT1 EDMA3 CC0 Region 1 interrupt // 56
> > > EDMA3_CC0_ERRINT EDMA3 Channel Controller 0 // 57
> > > EDMA3_TC0_ERRINT EDMA3 Transfer Controller 0 // 58
> > > EDMA3_TC1_ERRINT EDMA3 Transfer Controller 1 // NOTE: I looked at
> > > the EVTFLAG1 (see the MegaModule manual) register after // the
> > > DMA complted and saw that Event 56 had been set, so apparently //
> > > i want to trigger on event 56... :) // I'm trying to use a
> > > "transfer complete" (TC) interrupt for DRAE shadow region 0, so I suppose
> > > // interrupt 57 is what I want... but this is clear as mud from the
> > > above interrupt descirptions, // and the Figure 12 on page 44 of the
> > > EDMA manual only shows CC interrupts... // the description for 57 as
> > > "ERRINT" make it sound like an error interrupt, but maybe it's //
> > > both an TC and error interrupts... :) Uint32 CPUINTn; // CPU
> > > interrupt that the isr_INTn interrupt will be mapped to // this is
> > > one of the 12 CPU maskable interrupts specfied in figure 7-8 on page
> > > 164 of "sprufk5 TMS320C674x DSP Megamodule Reference Guide .pdf" //
> > > this is the entry in the interrupt service callback function that gets
> > > executed // // it's unclear to me if this event has anything to do
> > > with the events specfied // in table 7-2 on page 167 of "sprufk5
> > > TMS320C674x DSP Megamodule Reference Guide .pdf" // but it doesn't
> > > appear to be the case as this table matches the main 128 interrupt //
> > > table given in table 6-9 of the the main processor manual "OMAP-L137
> > > Low-Power Applications Processor (Rev. C) .pdf"
> > >
> > >
> > > Uint32 *i_u_p,mask;
> > > unsigned char * c_u_p;
> > >
> > > // copy rom based ist to ram based ist
> > > c_u_p=(unsigned char*)ISTP;
> > > for(i=0;i<0x200;i++)
> > > ISR_VECTORS_p[i]=c_u_p[i];
> > > ISTP=(unsigned int)ISR_VECTORS_p;
> > >
> > > i_u=ISTP+CPUINTn*32; // address of interrupt fetch packet in memory
> > > i_u_p=(Uint32*)i_u;
> > >
> > > // copy fetch packet to IST
> > > for(i=0;i<8;i++)
> > > {
> > > // modify address?
> > > i_u=0;
> > > if(i==1)
> > > i_u=isr_address&0xffff; // low address
> > > if(i==2)
> > > i_u=(isr_address>>16)&0xffff; // high address
> > > i_u<<=7;
> > > i_u_p[i]=isr_fetch_packet_p[i]|i_u;
> > > }
> > >
> > > // interrupts are described in "sprufk5 TMS320C674x DSP Megamodule
> > > Reference Guide.pdf" // section "7 interrupt controller"
> > >
> > > INTMUX1=0xffffffff;
> > > INTMUX2=0xffffffff;
> > > INTMUX3=0xffffffff;
> > > // clear all interrupt mux mappings
> > >
> > > EVTCLR0=0xffffffff;
> > > EVTCLR1=0xffffffff;
> > > EVTCLR2=0xffffffff;
> > > EVTCLR3=0xffffffff;
> > > // clear all interrupt event flags
> > >
> > > i_u=isr_INTn;
> > > i_u<<=((CPUINTn&0x3)*8);
> > > mask= 0xff<<((CPUINTn&0x3)*8);
> > > mask^=0xffffffff;
> > > if((CPUINTn>=4)&&(CPUINTn<=7))
> > > INTMUX1=(INTMUX1&mask)|i_u;
> > > if((CPUINTn>=8)&&(CPUINTn<))
> > > INTMUX2=(INTMUX2&mask)|i_u;
> > > if((CPUINTn>)&&(CPUINTn<))
> > > INTMUX3=(INTMUX3&mask)|i_u;
> > >
> > > i_u=1< > > > i_u|=2; // enable NMIE
> > > IER|=i_u;
> > >
> > > CSR|=1; // GIE : enable maskable interrupts
> > >
> > > The interrupt callback function is:
> > >
> > >
> > > interrupt void DMA2_ISR(void)
> > > // interrupt called when DMA2 is complted.
> > > // this is the DMA servicing the receive data stream (microphone echo
> > > data) // when we're done reading the mic echo, then turn off the //
> > > D/A stream to the transmitters so we don't get any spurious
> > > transmitter // behavior. { EDMA3_ICR=dma_tcc_mask_d; // clear
> > > the dma interrupt flag so the event can be triggerd again.
wait_for_dma_flg=0;
> > > }
> > >
> > > When this code is executing when the interrupt fires, everything is
> > > fine while(wait_for_dma_flg) // wait_for_dma_flg is set to 0 in
> > > interrupt handler ;
> > >
> > > When this code is executing when the interrupt fires, the DSP locks
> > > up.
> > >
> > > while(!IsDMAAcquireDone()) // function checks wait_for_dma_flg,
> > > return's 0 if interrupt hasn't fired. ;
> > ------- End of Original Message -------
> >
------- End of Original Message -------

_____________________________________