DSPRelated.com
Forums

codec generated interrupts working with RTDX interrupts

Started by "B. Korst, Comm.Lab." February 28, 2007
Greetings all,

I am working on an experiment to demonstrate pulse shaping and bit error
rate. The platform is DSK6711, using CCS2.2 and Matlab. The idea is simple:
random bits are generated through a PN sequence generator, then they are
"slowed down" by decimation (to 6kbps), a pulse-shaping filter is applied
(sqrrcos) on what would be a transmitter, gaussian noise is added, then a
matched filter is applied on what would be the receiver. Both _faux_
transmitter and receiver occur on the same platform, and students will
experiment with a) different excess bandwidths for RX and TX pulse-shaping,
b) signal to noise ratio and c) bit error rate calculation (i.e., more noise
means more errors). The output produced is to be sent both to the CODEC for
display (eye diagram) and to a host computer via RTDX and use Matlab to do
the detecting part.

The system without RTDX implemented works like a charm. I've been using
interrupt 8, generated by the codec (PCM3003).

My headache starts when I try to incorporate RTDX in order to transmit the
bit sequence (PN) generated to the computer. The idea is to transmit the
original bit sequence as well as the output signal using RTDX, and detect
bits via Matlab to count the errors. At the same time I want to display the
output with a scope. HOWEVER, as soon as I incorporate the necessary steps
into my vectors.asm file, the compiler refuses it. The problem points to my
branch instruction on interrupt 8: b _c_int08. It indicates that the call is
"too far", which prompts me to change the compiler/linker options to far, as
well as changing the command file to allow for every culprit to be within
internal RAM. Now the map file indicates (at least to me) that things are
"not as far". Nonetheless, the compiler still refuses it with the same error
message. I can't see what is wrong, and right now I'm on the verge of
writing a petition proposing the flogging at a public square of those
writing the error messages.

So, my intention is to use the hardware-generated interrupt 8 to dictate
when the output data is to be sent to the codec, and have RTDX send bursts
of data to Matlab inbetween occurrences of interrupt 8. I just don't see why
my approach would not work if I keep a limited size on the RTDX transfer.
Either I'm missing something really obvious, or I should change my whole
approach, i.e., go for polling+RTDX. I have looked at Chassaing
"rtdx_matlabfft" example, which uses rtdx plus polling. I'd prefer to use
the hardware interrupt, if I could.

I would like to hear any insight from those more experienced, and if you
have a sample code I would really appreciate it.

Take care, and thanks in advance,
bkf@
--- In c..., Jeff Brower wrote:

> Date: Thu, Mar 1 2007 6:45am
> Subject: Re: codec generated interrupts working with RTDX interrupts
>
> In addition to using far mode in Build
> Options, you should use code of this form:
>
> MVKL .S2 _c_int08, B0
> MVKH .S2 _c_int08, B0
> B .S2 B0
>
> for the interrupt vector. When using a reg as the branch addr the target code
> does not have to be in internal RAM (although for an interrupt which you want
> to be high-performance without interfering with current cache contents, it
> may be advisable).

Hi Jeff and everyone in this thread,

Somehow I have missed Jeff's post. Below are my comments on it:

The method of jumping to the ISR described above is right, however
it is not complete:

The two MVKs effectively kill the contents of B0, and this fact is
completely unknown to the interrupted code. Therefore, after return
from an ISR (B IRP), the interrupted code would erroneously assume
that B0 (if it is used, of course) still contains its original data,
but in fact it does not...

Therefore, if the ISR entry is far from ISFP by more than +/-1M instructions,
the interrupt processing algorithm must be more indirect. Actually, this was
the reason I once started here to discuss the C6000 interrupt hardware logic.

The algorithm outline:

1. In the ISFP:

1.1 Modify SP
1.2 Push B0
1.3 Push B3
1.4 Push IRP ; if interrupt nesting is needed, optional
1.5 B3 = _Return_from_int_xx_module
1.6 B0 = _ISR
1.7 Branch to B0

Which is rather difficult to properly implement, taking into account
that there are only 8 instructions in the ISFP.

The other method is to jump to a trampoline (indirect call) from the ISFP,
and relocate trampoline code inside the +/-1M instructions memory range
of the IST:

_int_xx: B _int_xx_trampoline ; no registers were modified
...
_int_xx_trampoline: ; perform steps 1.1 - 1.7

2. Since some of the registers have been modified before the ISR entry
point, they need to be restored after the ISR returns. Therefore,
the ISR would never return using B IRP, and the ISR cannot be defined
with the "interrupt" keyword. Instead it must be defined as a regular
function: void ISR (void) {...};

2.1 The ISR function completes it job and return to the address in B3

3. _Return_from_int_xx_module: ; which performs the following actions:

3.1 Pop IRP ; restore IRP
3.2 Pop B3 ; restore B3
3.3 Pop B0 ; restore B0
3.4 Restore SP ; set to original SP address
3.4 Branch to IRP ; jump to interrupted code

Looks really cumbersome...

The reason of it is that the interrupt hardware logic does not automatically
load the full 32 bit address of the matching ISR from a table.

Regards,

Andrew
Hi Andrew-

> --- In c..., Jeff Brower wrote:
>
> > Date: Thu, Mar 1 2007 6:45am
> > Subject: Re: codec generated interrupts working with RTDX interrupts
> >
> > In addition to using far mode in Build
> > Options, you should use code of this form:
> >
> > MVKL .S2 _c_int08, B0
> > MVKH .S2 _c_int08, B0
> > B .S2 B0
> >
> > for the interrupt vector. When using a reg as the branch addr the target code
> > does not have to be in internal RAM (although for an interrupt which you want
> > to be high-performance without interfering with current cache contents, it
> > may be advisable).
>
> Hi Jeff and everyone in this thread,
>
> Somehow I have missed Jeff's post. Below are my comments on it:
>
> The method of jumping to the ISR described above is right, however
> it is not complete:
>
> The two MVKs effectively kill the contents of B0, and this fact is
> completely unknown to the interrupted code. Therefore, after return
> from an ISR (B IRP), the interrupted code would erroneously assume
> that B0 (if it is used, of course) still contains its original data,
> but in fact it does not...

Here is the whole ISR that I used:

INT08:
STW .D2 B0, *SP--[4]
MVKL .S2 _c_int08, B0
MVKH .S2 _c_int08, B0
B .S2 B0
LDW .D2 *++SP[4], B0
NOP 4
NOP
NOP

Do you see any issue with SP alignment? 8-byte is the norm, but in this case GIE is
disabled upon entry, so I didn't worry about it.

-Jeff

> Therefore, if the ISR entry is far from ISFP by more than +/-1M instructions,
> the interrupt processing algorithm must be more indirect. Actually, this was
> the reason I once started here to discuss the C6000 interrupt hardware logic.
>
> The algorithm outline:
>
> 1. In the ISFP:
>
> 1.1 Modify SP
> 1.2 Push B0
> 1.3 Push B3
> 1.4 Push IRP ; if interrupt nesting is needed, optional
> 1.5 B3 = _Return_from_int_xx_module
> 1.6 B0 = _ISR
> 1.7 Branch to B0
>
> Which is rather difficult to properly implement, taking into account
> that there are only 8 instructions in the ISFP.
>
> The other method is to jump to a trampoline (indirect call) from the ISFP,
> and relocate trampoline code inside the +/-1M instructions memory range
> of the IST:
>
> _int_xx: B _int_xx_trampoline ; no registers were modified
> ...
> _int_xx_trampoline: ; perform steps 1.1 - 1.7
>
> 2. Since some of the registers have been modified before the ISR entry
> point, they need to be restored after the ISR returns. Therefore,
> the ISR would never return using B IRP, and the ISR cannot be defined
> with the "interrupt" keyword. Instead it must be defined as a regular
> function: void ISR (void) {...};
>
> 2.1 The ISR function completes it job and return to the address in B3
>
> 3. _Return_from_int_xx_module: ; which performs the following actions:
>
> 3.1 Pop IRP ; restore IRP
> 3.2 Pop B3 ; restore B3
> 3.3 Pop B0 ; restore B0
> 3.4 Restore SP ; set to original SP address
> 3.4 Branch to IRP ; jump to interrupted code
>
> Looks really cumbersome...
>
> The reason of it is that the interrupt hardware logic does not automatically
> load the full 32 bit address of the matching ISR from a table.
>
> Regards,
>
> Andrew
> Date: 13-Mar-2007 12:08:42 -0700
> From: Jeff Brower Hi Andrew-
>
> Here is the whole ISR that I used:
>
> INT08:
> STW .D2 B0, *SP--[4]
> MVKL .S2 _c_int08, B0
> MVKH .S2 _c_int08, B0
> B .S2 B0
> LDW .D2 *++SP[4], B0
> NOP 4
> NOP
> NOP
>
> Do you see any issue with SP alignment? 8-byte is the norm, but in this
> case GIE is disabled upon entry, so I didn't worry about it.
>
> -Jeff
>

Hi Jeff,

It's just amaizing! :) I really did not consider to restore the used register
in the delay slots of a branch... Clever. Thanks.

Rgds,

Andrew

P.S. No, of course there's nothing wrong with SP :)