DSPRelated.com
Forums

ISR falls off cliff...sometimes.

Started by jim October 23, 2007
Jim-

> Well, I did find at least part of my problem.
>
> There seems to be a hardware issue with the memory address/refresh logic.
> I've been wrestling with inconsistent behavior, and while I have strongly
> suspected hardware, that isn't an easy call to make particularly when
> programming at such a low level.
>
> However, I can now document some random changes in program code (which cannot
> be accounted for by wild pointers), and using code composer, I watched the
> program change a local unsigned int variable (which it was supposed to do),
> which also caused the next local unsigned int variable on the same stack to
> change as well to the same value (which should be impossible). The variable
> that was supposed to be changed was a return from an exec function
> (HWI_disable), so if this change is due to some pointer problem, the problem
> must be in the HWI_disable function.
>
> This accounts for a lot of things, and I still have some hair left, having not
> pulled it all out.

Random changes in program code? If this were really happening, it would be extremely
bad. It would not be worth it to work on any other area of the project until this is
resolved. My suggestion is to run small, simple code that uses only internal mem and
try to track down a case of this.

-Jeff

> On Tuesday 23 October 2007 11:42:31 you wrote:
> > Hi Jim,
> >
> > Please look at the page 77 of SPRU581C.pdf, on the bit 4 INTRST of RSTSRC.
> > It says that "This bit must be asserted before another host interrupt can
> > be generated."
> >
> > Next, it would help to parse all the bits in the PCIIS (even if they are
> > all disabled in the PCIIEN) and clear them in the PCI ISR.
> >
> > Third, it is recommended to parse an interrupt source register (any of
> > them, not only the PCIIS) in a loop inside an ISR and clear any set bits
> > until the register becomes zero, e.g. for the PCI:
> >
> > volatile uint32 temp;
> >
> > while (temp = PCIIS) // this reads the PCIIS
> > {
> > test if bit[0], ..., [n] is set
> > if set, clear bit[0], ... [n] and perform the necessary
> > actions, e.g: if bit[3] HOSTSW was set then clear bit[4] INTRST in RSTSRC }
> >
> > // PCIIS is clear now, exit the ISR
> >
> > Hope this helps,
> >
> > Andrew
> >
> > > 11a. ISR falls off cliff...sometimes.
> > > Posted by: "jim" j...@justsosoftware.com jiml8
> > > Date: Mon Oct 22, 2007 8:42 pm ((PDT))
> > >
> > > I have defined an ISR that responds to an interrupt on the PCI bus from a
> > > host. The current code for this ISR is this:
> > >
> > > interrupt void DMAtoHost(void)
> > > {
> > > unsigned int intval,*datastatusregister;
> > > puts("interrupted\n");
> > > datastatusregister = (unsigned int *)DATASTATUSREGISTER;
> > > intval = *datastatusregister & 0x04;
> > > if(intval == 4) { /* is this a host interrupt */
> > > intval = *datastatusregister;
> > > intval = intval & 0xfffffffb;
> > > *datastatusregister = intval; /* if so clear it */
> > > SEM_post(HostDMASem);
> > > puts("resetting PCIIS\n");
> > > }
> > > PCI_RSET(PCIIS,0x00000008);
> > > }
> > >
> > > Now, DATASTATUSREGISTER is a memory location on the DSP SDRAM that I have
> > > taken over for tracking status information between my Linux driver and my
> > > DSP interface. Here I am testing a flag in that register to make sure
> > > that this interrupt really was set by the host (my linux driver both sets
> > > the interrupt and sets this flag to tell that it did it), and if so, I
> > > clear that location as well as clearing the PCIIS register.
> > >
> > > Basically, if this really was an interrupt from the host, this ISR posts
> > > to a semaphore called HostDMASem, and there is a task sleeping on this
> > > semaphore waiting to be told to transfer data.
> > >
> > > I have defined this ISR statically using the Code Composer configuration
> > > tool, and it is hooked to interrupt 13.
> > >
> > > I have tried various ways to set that semaphore; my current iteration has
> > > the semaphore defined statically using the configuration tool, and it is
> > > initialized as one of the very first things done in the main routine of
> > > the program when it starts, like this:
> > >
> > > SEM_new(HostDMASem,0);
> > >
> > > That main task then spawns a new task called buildall_tsk, which is the
> > > task which winds up sleeping on the semaphore. This task arrives at the
> > > semaphore through a subroutine call, like this:
> > >
> > > void WaitForDMA(void)
> > > {
> > > Bool semstatus;
> > > SEM_reset(HostDMASem,0);
> > > semstatus = SEM_pend(HostDMASem,SYS_FOREVER);
> > > if(!semstatus){puts("semaphore bombed\n");} else {puts("semaphore
> > > worked\n");}
> > > }
> > >
> > > My problem is this. When an interrupt from the host is set, this ISR
> > > invokes apparently correctly. However, sometimes when it reaches the
> > > end, it falls off the cliff (apparently the semaphore is not being
> > > recognized properly or some such) and nothing happens.
> > >
> > > Further, when the routine falls off the cliff, subsequent interrupts are
> > > apparently ignored; when the routine falls off the cliff, it doesn't get
> > > invoked again until I completely reset the system (which sometimes
> > > involves cycling power as well as restarting Code Composer.
> > >
> > > This seems to be erratic and I can't define specific conditions that
> > > cause it or not. I suspecte some initialization thing that Code Composer
> > > is doing, but I have no idea what.
> > >
> > > The card is a Spectrum Digital 6416 card.
> > >
> > > I am tearing my hair out over this, and trust me; I don't look good bald.
> > > Anyone here have any idea what is going on?
Hello,

I want to read binary data from PC to DSP DSK board memory using fread() function. The .pjt I am using is a DSP BIOS based project.

I managed to read the input binary file correctly from PC using fread() in a non-DSP BIOS environment or project.

When I do the same thing in DSP BIOS based environment that has hardware interrupts, fread() fails. fread() reads some constant or same garbage data, for any input file.

My question is: Can we use fread() and fwrite() functions in DSP BIOS .pjt? If yes, could anyone show me the way to do it?

I am aware of CCS FIle --> Data --> Load procedure. But my input file is quite large (running to at least 60MB) and I wish to have a sample application program that reads data from PC to DSK using fread().

Please help. Thanks in advance.

BR,
-/Madhav

__________________________________________________
Madhav,

On 10/25/07, Madhav Last NameMadhav wrote:
> Hello,
>
> I want to read binary data from PC to DSP DSK board memory using fread() function. The .pjt I am using is a DSP BIOS based project.
>
> I managed to read the input binary file correctly from PC using fread() in a non-DSP BIOS environment or project.
>
> When I do the same thing in DSP BIOS based environment that has hardware interrupts, fread() fails. fread() reads some constant or same garbage data, for any input file.

You should not use fread() [or any other stdio functions] in the
presence of interrupts [it is possible in some circumstances when the
size of the I/O is very small and in frequent]. The stdio functions
work by setting breakpoints and performing memory reads and writes
through CCS "behind the scenes. This process is very slow compared to
any "realtime data rate". If you try it, you will very quickly run
into 'over run problems' that will manifest themselves as 'strange
failures'.

I do not know of anyway to get data from the PC to the DSK to process
it realtime.

Some possible solutions [I am not sure what you are trying to do:
1. If you can process the data in segments, you can load it into the
free memory on your DSK and process it in segments.
2. If your data happens to be "highly compressable", you may be able
to compress it and embed it into your application [of course you would
have to add the decompression code to your app].
3. You could add separate hardware to create a PC-to-DSK link that
provides the data.

>
> My question is: Can we use fread() and fwrite() functions in DSP BIOS .pjt? If yes, could anyone show me the way to do it?

I do not think it is feasible.

>
> I am aware of CCS FIle --> Data --> Load procedure. But my input file is quite large (running to at least 60MB) and I wish to have a sample application program that reads data from PC to DSK using fread().

The only way that I would attempt using fread() would be to use something like:
1. Disable ALL interrupts
2. fread() my as large of a chunk of data as I could
3. Enable interrupts
4. Process data chunk
5. If not finished, goto #1.

mikedunn
>
> Please help. Thanks in advance.
>
> BR,
> -/Madhav
> __________________________________________________
>
... And now...the REST of the story!

My client came up with a brand new board, and we wired it to be a PCI
interface (rather than GPIO) and plugged it in. Behavior of this new board
was consistent; it would transfer data two or three times, then hang. I
checked the initialization EMIF stuff; the board was set to run at 500 MHz
when it was a 1000 MHz board. So I turned up the speed. Behavior remained
exactly the same as it had been; two or three correct transfers, then hang.

Now, while working with the previous board, I had added a number of code hacks
while trying to deal with the inconsistency in behavior, before finally
determining absolutely that mine was a hardware problem.

So, I removed these hacks. Instantly, the thing ran exactly the way I wanted
it to run.

My PCI DMA Master code is derived from the asynch_pcitest code provided with
the driver development environment, and described in spru616.pdf, and it now
works...almost.

Well, it DOES work, but there is a bug which will become a problem eventually
(though I'll get through my demo on Monday).

The one problem I still have that I know about is this. My Linux driver
(written from scratch) triggers an interrupt to the DSP to tell it to do a
DMA transfer. The DSP reconfigures the interrupts and registers as required
(the async code does this), transfers the data, then my program reconfigures
the interrupts to what I need and sends an interrupt to the Linux system
telling it the data is transferred.

Now, my Linux driver expects to share the interrupt, and if the interrupt
really is for it, it tests to see if the interrupt is valid. If the
interrupt is not valid, it writes a message into the log saying that it
received an interrupt for an unknown reason, then clears the interrupt and
takes no action.

So, here is the bug. After loading the DSP program, the first time my Linux
client program orders the DSP to do a DMA transfer, I get one message in the
Linux log file saying that an interrupt was received for an unknown reason.

The second time my client program orders a DMA transfer, I get two messages in
the log file about an interrupt for an unknown reason

The tenth time, I get ten messages in the log (actually I get one message,
then another message which says: "the previous message was repeated 9
times").

The 100th time, 100 messages.

What this means is that something someplace in the DSP is counting and not
clearing, and it is setting NOT EMIFA as many times as it has in its count.
Eventually, this is going to slow down the PCI bus to a noticeable degree.

Given that I am using the async demo code (so far, I might add, I have found
and fixed no fewer than three bugs in that code) as the basis for the DSP
side of my PCI interface driver, does anyone have any idea what is counting?

On Wednesday 24 October 2007 12:08:22 you wrote:
> Jim,
>
> On 10/24/07, jim wrote:
> > On Wednesday 24 October 2007 11:06:48 you wrote:
> > > Jim,
> > >
> > > On 10/24/07, jim wrote:
> > > > Well, I did find at least part of my problem.
> > > >
> > > > There seems to be a hardware issue with the memory address/refresh
> > > > logic. I've been wrestling with inconsistent behavior, and while I
> > > > have strongly suspected hardware, that isn't an easy call to make
> > > > particularly when programming at such a low level.
> > >
> > > Make sure that you go through the EMIF setup parameters, clocks, etc.
> > > to be sure that it is setup correctly. If you used the 'delivered
> > > EMIF settings' and changed any of the clock configuration, your
> > > refresh rate could be too slow.
> > >
> > > mikedunn
> >
> > I will certainly look at that. I would not have thought it would be
> > possible to configure the refresh rate from outside. It is certainly not
> > something I would have ever looked for.
>
> I am not sure what you mean by "from outside" [from outside the RAM??].
> Hopefully your [or someone's] low level initialization code is taking
> care of the EMIF setup. Are you using DSP/BIOS?? or some other
> executive??
>
> > That actually is a possibility???
>
> Yes, and I have the "have I lost my mind??" experience and the gray
> hair to prove it. I abstain from pulling my hair out :-)
>
> > > > However, I can now document some random changes in program code
> > > > (which cannot be accounted for by wild pointers), and using code
> > > > composer, I watched the program change a local unsigned int variable
> > > > (which it was supposed to do), which also caused the next local
> > > > unsigned int variable on the same stack to change as well to the same
> > > > value (which should be impossible). The variable that was supposed to
> > > > be changed was a return from an exec function (HWI_disable), so if
> > > > this change is due to some pointer problem, the problem must be in
> > > > the HWI_disable function.
> > > >
> > > > This accounts for a lot of things, and I still have some hair left,
> > > > having not pulled it all out.
> > > >
> > > > On Tuesday 23 October 2007 11:42:31 you wrote:
> > > > > Hi Jim,
> > > > >
> > > > > Please look at the page 77 of SPRU581C.pdf, on the bit 4 INTRST of
> > > > > RSTSRC. It says that "This bit must be asserted before another host
> > > > > interrupt can be generated."
> > > > >
> > > > > Next, it would help to parse all the bits in the PCIIS (even if
> > > > > they are all disabled in the PCIIEN) and clear them in the PCI ISR.
> > > > >
> > > > > Third, it is recommended to parse an interrupt source register (any
> > > > > of them, not only the PCIIS) in a loop inside an ISR and clear any
> > > > > set bits until the register becomes zero, e.g. for the PCI:
> > > > >
> > > > > volatile uint32 temp;
> > > > >
> > > > > while (temp = PCIIS) // this reads the PCIIS
> > > > > {
> > > > > test if bit[0], ..., [n] is set
> > > > > if set, clear bit[0], ... [n] and perform the necessary
> > > > > actions, e.g: if bit[3] HOSTSW was set then clear bit[4] INTRST in
> > > > > RSTSRC }
> > > > >
> > > > > // PCIIS is clear now, exit the ISR
> > > > >
> > > > > Hope this helps,
> > > > >
> > > > > Andrew
> > > > >
> > > > > > 11a. ISR falls off cliff...sometimes.
> > > > > > Posted by: "jim" j...@justsosoftware.com jiml8
> > > > > > Date: Mon Oct 22, 2007 8:42 pm ((PDT))
> > > > > >
> > > > > > I have defined an ISR that responds to an interrupt on the PCI
> > > > > > bus from a host. The current code for this ISR is this:
> > > > > >
> > > > > > interrupt void DMAtoHost(void)
> > > > > > {
> > > > > > unsigned int intval,*datastatusregister;
> > > > > > puts("interrupted\n");
> > > > > > datastatusregister = (unsigned int *)DATASTATUSREGISTER;
> > > > > > intval = *datastatusregister & 0x04;
> > > > > > if(intval == 4) { /* is this a host interrupt */
> > > > > > intval = *datastatusregister;
> > > > > > intval = intval & 0xfffffffb;
> > > > > > *datastatusregister = intval; /* if so clear it */
> > > > > > SEM_post(HostDMASem);
> > > > > > puts("resetting PCIIS\n");
> > > > > > }
> > > > > > PCI_RSET(PCIIS,0x00000008);
> > > > > > }
> > > > > >
> > > > > > Now, DATASTATUSREGISTER is a memory location on the DSP SDRAM
> > > > > > that I have taken over for tracking status information between my
> > > > > > Linux driver and my DSP interface. Here I am testing a flag in
> > > > > > that register to make sure that this interrupt really was set by
> > > > > > the host (my linux driver both sets the interrupt and sets this
> > > > > > flag to tell that it did it), and if so, I clear that location as
> > > > > > well as clearing the PCIIS register.
> > > > > >
> > > > > > Basically, if this really was an interrupt from the host, this
> > > > > > ISR posts to a semaphore called HostDMASem, and there is a task
> > > > > > sleeping on this semaphore waiting to be told to transfer data.
> > > > > >
> > > > > > I have defined this ISR statically using the Code Composer
> > > > > > configuration tool, and it is hooked to interrupt 13.
> > > > > >
> > > > > > I have tried various ways to set that semaphore; my current
> > > > > > iteration has the semaphore defined statically using the
> > > > > > configuration tool, and it is initialized as one of the very
> > > > > > first things done in the main routine of the program when it
> > > > > > starts, like this:
> > > > > >
> > > > > > SEM_new(HostDMASem,0);
> > > > > >
> > > > > > That main task then spawns a new task called buildall_tsk, which
> > > > > > is the task which winds up sleeping on the semaphore. This task
> > > > > > arrives at the semaphore through a subroutine call, like this:
> > > > > >
> > > > > > void WaitForDMA(void)
> > > > > > {
> > > > > > Bool semstatus;
> > > > > > SEM_reset(HostDMASem,0);
> > > > > > semstatus = SEM_pend(HostDMASem,SYS_FOREVER);
> > > > > > if(!semstatus){puts("semaphore bombed\n");} else {puts("semaphore
> > > > > > worked\n");}
> > > > > > }
> > > > > >
> > > > > > My problem is this. When an interrupt from the host is set, this
> > > > > > ISR invokes apparently correctly. However, sometimes when it
> > > > > > reaches the end, it falls off the cliff (apparently the semaphore
> > > > > > is not being recognized properly or some such) and nothing
> > > > > > happens.
> > > > > >
> > > > > > Further, when the routine falls off the cliff, subsequent
> > > > > > interrupts are apparently ignored; when the routine falls off the
> > > > > > cliff, it doesn't get invoked again until I completely reset the
> > > > > > system (which sometimes involves cycling power as well as
> > > > > > restarting Code Composer.
> > > > > >
> > > > > > This seems to be erratic and I can't define specific conditions
> > > > > > that cause it or not. I suspecte some initialization thing that
> > > > > > Code Composer is doing, but I have no idea what.
> > > > > >
> > > > > > The card is a Spectrum Digital 6416 card.
> > > > > >
> > > > > > I am tearing my hair out over this, and trust me; I don't look
> > > > > > good bald. Anyone here have any idea what is going on?
> > > > >
> > > > >
> > > >
> > > >
Jim-

> ... And now...the REST of the story!
>
> My client came up with a brand new board, and we wired it to be a PCI
> interface (rather than GPIO) and plugged it in. Behavior of this new board
> was consistent; it would transfer data two or three times, then hang. I
> checked the initialization EMIF stuff; the board was set to run at 500 MHz
> when it was a 1000 MHz board. So I turned up the speed. Behavior remained
> exactly the same as it had been; two or three correct transfers, then hang.

If the 6416 runs at 1 GHz, what is your external mem speed? 641x supports SDRAM, not DDR2, so your mem speed can't be
more than 166 MHz, probably better to use 125 to 133 MHz.

Also what do you mean by GPIO? There is no effective way to use host-to-DSP interface using GPIO.

The basic way to know your mem transfer is truly working is to write an area of DSP internal memory, then write
another area with different address, then go back and read the first area. This avoids any possible "bus hold" or
"stale data" issue, whether at driver, bus, or DSP interface level. I would think this would be a necessary
requirement for you to give a solid demo. If you do this, what do you get?

-Jeff

> Now, while working with the previous board, I had added a number of code hacks
> while trying to deal with the inconsistency in behavior, before finally
> determining absolutely that mine was a hardware problem.
>
> So, I removed these hacks. Instantly, the thing ran exactly the way I wanted
> it to run.
>
> My PCI DMA Master code is derived from the asynch_pcitest code provided with
> the driver development environment, and described in spru616.pdf, and it now
> works...almost.
>
> Well, it DOES work, but there is a bug which will become a problem eventually
> (though I'll get through my demo on Monday).
>
> The one problem I still have that I know about is this. My Linux driver
> (written from scratch) triggers an interrupt to the DSP to tell it to do a
> DMA transfer. The DSP reconfigures the interrupts and registers as required
> (the async code does this), transfers the data, then my program reconfigures
> the interrupts to what I need and sends an interrupt to the Linux system
> telling it the data is transferred.
>
> Now, my Linux driver expects to share the interrupt, and if the interrupt
> really is for it, it tests to see if the interrupt is valid. If the
> interrupt is not valid, it writes a message into the log saying that it
> received an interrupt for an unknown reason, then clears the interrupt and
> takes no action.
>
> So, here is the bug. After loading the DSP program, the first time my Linux
> client program orders the DSP to do a DMA transfer, I get one message in the
> Linux log file saying that an interrupt was received for an unknown reason.
>
> The second time my client program orders a DMA transfer, I get two messages in
> the log file about an interrupt for an unknown reason
>
> The tenth time, I get ten messages in the log (actually I get one message,
> then another message which says: "the previous message was repeated 9
> times").
>
> The 100th time, 100 messages.
>
> What this means is that something someplace in the DSP is counting and not
> clearing, and it is setting NOT EMIFA as many times as it has in its count.
> Eventually, this is going to slow down the PCI bus to a noticeable degree.
>
> Given that I am using the async demo code (so far, I might add, I have found
> and fixed no fewer than three bugs in that code) as the basis for the DSP
> side of my PCI interface driver, does anyone have any idea what is counting?
>
> On Wednesday 24 October 2007 12:08:22 you wrote:
>> Jim,
>>
>> On 10/24/07, jim wrote:
>> > On Wednesday 24 October 2007 11:06:48 you wrote:
>> > > Jim,
>> > >
>> > > On 10/24/07, jim wrote:
>> > > > Well, I did find at least part of my problem.
>> > > >
>> > > > There seems to be a hardware issue with the memory address/refresh
>> > > > logic. I've been wrestling with inconsistent behavior, and while I
>> > > > have strongly suspected hardware, that isn't an easy call to make
>> > > > particularly when programming at such a low level.
>> > >
>> > > Make sure that you go through the EMIF setup parameters, clocks, etc.
>> > > to be sure that it is setup correctly. If you used the 'delivered
>> > > EMIF settings' and changed any of the clock configuration, your
>> > > refresh rate could be too slow.
>> > >
>> > > mikedunn
>> >
>> > I will certainly look at that. I would not have thought it would be
>> > possible to configure the refresh rate from outside. It is certainly not
>> > something I would have ever looked for.
>>
>> I am not sure what you mean by "from outside" [from outside the RAM??].
>> Hopefully your [or someone's] low level initialization code is taking
>> care of the EMIF setup. Are you using DSP/BIOS?? or some other
>> executive??
>>
>> > That actually is a possibility???
>>
>> Yes, and I have the "have I lost my mind??" experience and the gray
>> hair to prove it. I abstain from pulling my hair out :-)
>>
>> > > > However, I can now document some random changes in program code
>> > > > (which cannot be accounted for by wild pointers), and using code
>> > > > composer, I watched the program change a local unsigned int variable
>> > > > (which it was supposed to do), which also caused the next local
>> > > > unsigned int variable on the same stack to change as well to the same
>> > > > value (which should be impossible). The variable that was supposed to
>> > > > be changed was a return from an exec function (HWI_disable), so if
>> > > > this change is due to some pointer problem, the problem must be in
>> > > > the HWI_disable function.
>> > > >
>> > > > This accounts for a lot of things, and I still have some hair left,
>> > > > having not pulled it all out.
>> > > >
>> > > > On Tuesday 23 October 2007 11:42:31 you wrote:
>> > > > > Hi Jim,
>> > > > >
>> > > > > Please look at the page 77 of SPRU581C.pdf, on the bit 4 INTRST of
>> > > > > RSTSRC. It says that "This bit must be asserted before another host
>> > > > > interrupt can be generated."
>> > > > >
>> > > > > Next, it would help to parse all the bits in the PCIIS (even if
>> > > > > they are all disabled in the PCIIEN) and clear them in the PCI ISR.
>> > > > >
>> > > > > Third, it is recommended to parse an interrupt source register (any
>> > > > > of them, not only the PCIIS) in a loop inside an ISR and clear any
>> > > > > set bits until the register becomes zero, e.g. for the PCI:
>> > > > >
>> > > > > volatile uint32 temp;
>> > > > >
>> > > > > while (temp = PCIIS) // this reads the PCIIS
>> > > > > {
>> > > > > test if bit[0], ..., [n] is set
>> > > > > if set, clear bit[0], ... [n] and perform the necessary
>> > > > > actions, e.g: if bit[3] HOSTSW was set then clear bit[4] INTRST in
>> > > > > RSTSRC }
>> > > > >
>> > > > > // PCIIS is clear now, exit the ISR
>> > > > >
>> > > > > Hope this helps,
>> > > > >
>> > > > > Andrew
>> > > > >
>> > > > > > 11a. ISR falls off cliff...sometimes.
>> > > > > > Posted by: "jim" j...@justsosoftware.com jiml8
>> > > > > > Date: Mon Oct 22, 2007 8:42 pm ((PDT))
>> > > > > >
>> > > > > > I have defined an ISR that responds to an interrupt on the PCI
>> > > > > > bus from a host. The current code for this ISR is this:
>> > > > > >
>> > > > > > interrupt void DMAtoHost(void)
>> > > > > > {
>> > > > > > unsigned int intval,*datastatusregister;
>> > > > > > puts("interrupted\n");
>> > > > > > datastatusregister = (unsigned int *)DATASTATUSREGISTER;
>> > > > > > intval = *datastatusregister & 0x04;
>> > > > > > if(intval == 4) { /* is this a host interrupt */
>> > > > > > intval = *datastatusregister;
>> > > > > > intval = intval & 0xfffffffb;
>> > > > > > *datastatusregister = intval; /* if so clear it */
>> > > > > > SEM_post(HostDMASem);
>> > > > > > puts("resetting PCIIS\n");
>> > > > > > }
>> > > > > > PCI_RSET(PCIIS,0x00000008);
>> > > > > > }
>> > > > > >
>> > > > > > Now, DATASTATUSREGISTER is a memory location on the DSP SDRAM
>> > > > > > that I have taken over for tracking status information between my
>> > > > > > Linux driver and my DSP interface. Here I am testing a flag in
>> > > > > > that register to make sure that this interrupt really was set by
>> > > > > > the host (my linux driver both sets the interrupt and sets this
>> > > > > > flag to tell that it did it), and if so, I clear that location as
>> > > > > > well as clearing the PCIIS register.
>> > > > > >
>> > > > > > Basically, if this really was an interrupt from the host, this
>> > > > > > ISR posts to a semaphore called HostDMASem, and there is a task
>> > > > > > sleeping on this semaphore waiting to be told to transfer data.
>> > > > > >
>> > > > > > I have defined this ISR statically using the Code Composer
>> > > > > > configuration tool, and it is hooked to interrupt 13.
>> > > > > >
>> > > > > > I have tried various ways to set that semaphore; my current
>> > > > > > iteration has the semaphore defined statically using the
>> > > > > > configuration tool, and it is initialized as one of the very
>> > > > > > first things done in the main routine of the program when it
>> > > > > > starts, like this:
>> > > > > >
>> > > > > > SEM_new(HostDMASem,0);
>> > > > > >
>> > > > > > That main task then spawns a new task called buildall_tsk, which
>> > > > > > is the task which winds up sleeping on the semaphore. This task
>> > > > > > arrives at the semaphore through a subroutine call, like this:
>> > > > > >
>> > > > > > void WaitForDMA(void)
>> > > > > > {
>> > > > > > Bool semstatus;
>> > > > > > SEM_reset(HostDMASem,0);
>> > > > > > semstatus = SEM_pend(HostDMASem,SYS_FOREVER);
>> > > > > > if(!semstatus){puts("semaphore bombed\n");} else {puts("semaphore
>> > > > > > worked\n");}
>> > > > > > }
>> > > > > >
>> > > > > > My problem is this. When an interrupt from the host is set, this
>> > > > > > ISR invokes apparently correctly. However, sometimes when it
>> > > > > > reaches the end, it falls off the cliff (apparently the semaphore
>> > > > > > is not being recognized properly or some such) and nothing
>> > > > > > happens.
>> > > > > >
>> > > > > > Further, when the routine falls off the cliff, subsequent
>> > > > > > interrupts are apparently ignored; when the routine falls off the
>> > > > > > cliff, it doesn't get invoked again until I completely reset the
>> > > > > > system (which sometimes involves cycling power as well as
>> > > > > > restarting Code Composer.
>> > > > > >
>> > > > > > This seems to be erratic and I can't define specific conditions
>> > > > > > that cause it or not. I suspecte some initialization thing that
>> > > > > > Code Composer is doing, but I have no idea what.
>> > > > > >
>> > > > > > The card is a Spectrum Digital 6416 card.
>> > > > > >
>> > > > > > I am tearing my hair out over this, and trust me; I don't look
>> > > > > > good bald. Anyone here have any idea what is going on?
Jim,

On 10/29/07, Andrew Nesterov wrote:
> > Subject: Re: ISR falls off cliff...sometimes.
> > Posted by: "jim" j...@justsosoftware.com jiml8
> > Date: Sun Oct 28, 2007 7:20 am ((PDT))
> >
> > ... And now...the REST of the story!
> >
> > My client came up with a brand new board, and we wired it to be a PCI
> > interface (rather than GPIO) and plugged it in. Behavior of this new board
> > was consistent; it would transfer data two or three times, then hang. I
> > checked the initialization EMIF stuff; the board was set to run at 500 MHz
> > when it was a 1000 MHz board. So I turned up the speed. Behavior remained
> > exactly the same as it had been; two or three correct transfers, then hang.
>
> I saw that Spectrum Digital's C6416 EVM does not have a PCI connector, does it?
> So you needed to to wire its on board connector into an external PCI connector,
> right? Perhaps this on-board connector hass muxed GPIO and PCI pins - this is
> probably is what Jeff was asking, if I got him correct.

The brand new board was designed by the customer. Correct??
The Spectrum Digital board was probably using HPI as opposed to the
stated 'GPIO'. Correct??

Just trying to get calibrated.
>
> > Now, while working with the previous board, I had added a number of code hacks
> > while trying to deal with the inconsistency in behavior, before finally
> > determining absolutely that mine was a hardware problem.
> >
> > So, I removed these hacks. Instantly, the thing ran exactly the way I wanted
> > it to run.
> >
> > My PCI DMA Master code is derived from the asynch_pcitest code provided with
> > the driver development environment, and described in spru616.pdf, and it now
> > works...almost.
>
> I assume that your DSP-side code does master reads from the host, is it close
> to the truth?
>
> > Well, it DOES work, but there is a bug which will become a problem eventually
> > (though I'll get through my demo on Monday).
> >
Its not Monday any more, I wonder how the demo went... :-)

> > The one problem I still have that I know about is this. My Linux driver
> > (written from scratch) triggers an interrupt to the DSP to tell it to do a
> > DMA transfer. The DSP reconfigures the interrupts and registers as required
> > (the async code does this), transfers the data, then my program reconfigures
> > the interrupts to what I need and sends an interrupt to the Linux system
> > telling it the data is transferred.
>
> Can you be more specific here? I am not certain what do you mean by
> reconfiguring interrupts. Does the DSP-side program remaps interrupts
> on the fly? What do you mean by DMA transfer? Is it simply a PCI Master
> read or you've set up a separate DMA transfer to move the data that had been
> read by the PCI controller into an input buffer from this intermediate
> buffer into a final destination?

I agree with Andrew. It is not clear what you are trying to accomplish.
>
> > Now, my Linux driver expects to share the interrupt, and if the interrupt
> > really is for it, it tests to see if the interrupt is valid. If the
> > interrupt is not valid, it writes a message into the log saying that it
> > received an interrupt for an unknown reason, then clears the interrupt and
> > takes no action.
>
> To share the interrupt with whom? Do you mean that there are several PCI
> devices on your host machine, or there are several processes on the DSP
> side that may assert the PCI interrupt? How does your host-side code decides
> on the interrupt is for it and is valid?

Andrew,
This is part of the PCI spec. Two separate PCI drivers must be able
to share a single interrupt. I don't know if you were around in the
early days of PCs transistioning to PCI. You sometimes [dpending on
interrupt assignments] couldn't run certain "board combinations" [it
was actually driver combinations].

mikedunn
>
> The problem looks for me like a sync problem. The code (both host and DSP
> side) do not work in concert, do not synchronize their actions with each
> other. Have you thought over the communication protocol, ready/not ready
> /ack software signaling?
>
> Rgds,
>
> Andrew
> > So, here is the bug. After loading the DSP program, the first time my Linux
> > client program orders the DSP to do a DMA transfer, I get one message in the
> > Linux log file saying that an interrupt was received for an unknown reason.
> >
> > The second time my client program orders a DMA transfer, I get two messages in
> > the log file about an interrupt for an unknown reason
> >
> > The tenth time, I get ten messages in the log (actually I get one message,
> > then another message which says: "the previous message was repeated 9
> > times").
> >
> > The 100th time, 100 messages.
> >
> > What this means is that something someplace in the DSP is counting and not
> > clearing, and it is setting NOT EMIFA as many times as it has in its count.
> > Eventually, this is going to slow down the PCI bus to a noticeable degree.
> >
> > Given that I am using the async demo code (so far, I might add, I have found
> > and fixed no fewer than three bugs in that code) as the basis for the DSP
> > side of my PCI interface driver, does anyone have any idea what is counting?
> >
> > On Wednesday 24 October 2007 12:08:22 you wrote:
> >> Jim,
> >>
> >> On 10/24/07, jim wrote:
> >>> On Wednesday 24 October 2007 11:06:48 you wrote:
> >>>> Jim,
> >>>>
> >>>> On 10/24/07, jim wrote:
> >>>>> Well, I did find at least part of my problem.
> >>>>>
> >>>>> There seems to be a hardware issue with the memory address/refresh
> >>>>> logic. I've been wrestling with inconsistent behavior, and while I
> >>>>> have strongly suspected hardware, that isn't an easy call to make
> >>>>> particularly when programming at such a low level.
> >>>>
> >>>> Make sure that you go through the EMIF setup parameters, clocks, etc.
> >>>> to be sure that it is setup correctly. If you used the 'delivered
> >>>> EMIF settings' and changed any of the clock configuration, your
> >>>> refresh rate could be too slow.
> >>>>
> >>>> mikedunn
> >>>
> >>> I will certainly look at that. I would not have thought it would be
> >>> possible to configure the refresh rate from outside. It is certainly not
> >>> something I would have ever looked for.
> >>
> >> I am not sure what you mean by "from outside" [from outside the RAM??].
> >> Hopefully your [or someone's] low level initialization code is taking
> >> care of the EMIF setup. Are you using DSP/BIOS?? or some other
> >> executive??
> >>
> >>> That actually is a possibility???
> >>
> >> Yes, and I have the "have I lost my mind??" experience and the gray
> >> hair to prove it. I abstain from pulling my hair out :-)
> >>
> >>>>> However, I can now document some random changes in program code
> >>>>> (which cannot be accounted for by wild pointers), and using code
> >>>>> composer, I watched the program change a local unsigned int variable
> >>>>> (which it was supposed to do), which also caused the next local
> >>>>> unsigned int variable on the same stack to change as well to the same
> >>>>> value (which should be impossible). The variable that was supposed to
> >>>>> be changed was a return from an exec function (HWI_disable), so if
> >>>>> this change is due to some pointer problem, the problem must be in
> >>>>> the HWI_disable function.
> >>>>>
> >>>>> This accounts for a lot of things, and I still have some hair left,
> >>>>> having not pulled it all out.
> >>>>>
> >>>>> On Tuesday 23 October 2007 11:42:31 you wrote:
> >>>>>> Hi Jim,
> >>>>>>
> >>>>>> Please look at the page 77 of SPRU581C.pdf, on the bit 4 INTRST of
> >>>>>> RSTSRC. It says that "This bit must be asserted before another host
> >>>>>> interrupt can be generated."
> >>>>>>
> >>>>>> Next, it would help to parse all the bits in the PCIIS (even if
> >>>>>> they are all disabled in the PCIIEN) and clear them in the PCI ISR.
> >>>>>>
> >>>>>> Third, it is recommended to parse an interrupt source register (any
> >>>>>> of them, not only the PCIIS) in a loop inside an ISR and clear any
> >>>>>> set bits until the register becomes zero, e.g. for the PCI:
> >>>>>>
> >>>>>> volatile uint32 temp;
> >>>>>>
> >>>>>> while (temp = PCIIS) // this reads the PCIIS
> >>>>>> {
> >>>>>> test if bit[0], ..., [n] is set
> >>>>>> if set, clear bit[0], ... [n] and perform the necessary
> >>>>>> actions, e.g: if bit[3] HOSTSW was set then clear bit[4] INTRST in
> >>>>>> RSTSRC }
> >>>>>>
> >>>>>> // PCIIS is clear now, exit the ISR
> >>>>>>
> >>>>>> Hope this helps,
> >>>>>>
> >>>>>> Andrew
> >>>>>>
> >>>>>>> 11a. ISR falls off cliff...sometimes.
> >>>>>>> Posted by: "jim" j...@justsosoftware.com jiml8
> >>>>>>> Date: Mon Oct 22, 2007 8:42 pm ((PDT))
> >>>>>>>
> >>>>>>> I have defined an ISR that responds to an interrupt on the PCI
> >>>>>>> bus from a host. The current code for this ISR is this:
> >>>>>>>
> >>>>>>> interrupt void DMAtoHost(void)
> >>>>>>> {
> >>>>>>> unsigned int intval,*datastatusregister;
> >>>>>>> puts("interrupted\n");
> >>>>>>> datastatusregister = (unsigned int *)DATASTATUSREGISTER;
> >>>>>>> intval = *datastatusregister & 0x04;
> >>>>>>> if(intval == 4) { /* is this a host interrupt */
> >>>>>>> intval = *datastatusregister;
> >>>>>>> intval = intval & 0xfffffffb;
> >>>>>>> *datastatusregister = intval; /* if so clear it */
> >>>>>>> SEM_post(HostDMASem);
> >>>>>>> puts("resetting PCIIS\n");
> >>>>>>> }
> >>>>>>> PCI_RSET(PCIIS,0x00000008);
> >>>>>>> }
> >>>>>>>
> >>>>>>> Now, DATASTATUSREGISTER is a memory location on the DSP SDRAM
> >>>>>>> that I have taken over for tracking status information between my
> >>>>>>> Linux driver and my DSP interface. Here I am testing a flag in
> >>>>>>> that register to make sure that this interrupt really was set by
> >>>>>>> the host (my linux driver both sets the interrupt and sets this
> >>>>>>> flag to tell that it did it), and if so, I clear that location as
> >>>>>>> well as clearing the PCIIS register.
> >>>>>>>
> >>>>>>> Basically, if this really was an interrupt from the host, this
> >>>>>>> ISR posts to a semaphore called HostDMASem, and there is a task
> >>>>>>> sleeping on this semaphore waiting to be told to transfer data.
> >>>>>>>
> >>>>>>> I have defined this ISR statically using the Code Composer
> >>>>>>> configuration tool, and it is hooked to interrupt 13.
> >>>>>>>
> >>>>>>> I have tried various ways to set that semaphore; my current
> >>>>>>> iteration has the semaphore defined statically using the
> >>>>>>> configuration tool, and it is initialized as one of the very
> >>>>>>> first things done in the main routine of the program when it
> >>>>>>> starts, like this:
> >>>>>>>
> >>>>>>> SEM_new(HostDMASem,0);
> >>>>>>>
> >>>>>>> That main task then spawns a new task called buildall_tsk, which
> >>>>>>> is the task which winds up sleeping on the semaphore. This task
> >>>>>>> arrives at the semaphore through a subroutine call, like this:
> >>>>>>>
> >>>>>>> void WaitForDMA(void)
> >>>>>>> {
> >>>>>>> Bool semstatus;
> >>>>>>> SEM_reset(HostDMASem,0);
> >>>>>>> semstatus = SEM_pend(HostDMASem,SYS_FOREVER);
> >>>>>>> if(!semstatus){puts("semaphore bombed\n");} else {puts("semaphore
> >>>>>>> worked\n");}
> >>>>>>> }
> >>>>>>>
> >>>>>>> My problem is this. When an interrupt from the host is set, this
> >>>>>>> ISR invokes apparently correctly. However, sometimes when it
> >>>>>>> reaches the end, it falls off the cliff (apparently the semaphore
> >>>>>>> is not being recognized properly or some such) and nothing
> >>>>>>> happens.
> >>>>>>>
> >>>>>>> Further, when the routine falls off the cliff, subsequent
> >>>>>>> interrupts are apparently ignored; when the routine falls off the
> >>>>>>> cliff, it doesn't get invoked again until I completely reset the
> >>>>>>> system (which sometimes involves cycling power as well as
> >>>>>>> restarting Code Composer.
> >>>>>>>
> >>>>>>> This seems to be erratic and I can't define specific conditions
> >>>>>>> that cause it or not. I suspecte some initialization thing that
> >>>>>>> Code Composer is doing, but I have no idea what.
> >>>>>>>
> >>>>>>> The card is a Spectrum Digital 6416 card.
> >>>>>>>
> >>>>>>> I am tearing my hair out over this, and trust me; I don't look
> >>>>>>> good bald. Anyone here have any idea what is going on?
> >>>>>>
> >>>>>
> >
> >
> Date: 30-Oct-2007 08:20:05 -0700
> From: Michael Dunn
> To: Andrew Nesterov
> Cc: c..., j...@justsosoftware.com
> Subject: Re: [c6x] Re: Re: ISR falls off cliff...sometimes.
>
> Jim,
>
> On 10/29/07, Andrew Nesterov wrote:
>>> Subject: Re: ISR falls off cliff...sometimes.
>>> Posted by: "jim" j...@justsosoftware.com jiml8
>>> Date: Sun Oct 28, 2007 7:20 am ((PDT))
>>>
>>> ... And now...the REST of the story!
>>>
>>> My client came up with a brand new board, and we wired it to be a PCI
>>> interface (rather than GPIO) and plugged it in. Behavior of this new board
>>> was consistent; it would transfer data two or three times, then hang. I
>>> checked the initialization EMIF stuff; the board was set to run at 500 MHz
>>> when it was a 1000 MHz board. So I turned up the speed. Behavior remained
>>> exactly the same as it had been; two or three correct transfers, then hang.
>>
>> I saw that Spectrum Digital's C6416 EVM does not have a PCI connector, does it?
>> So you needed to to wire its on board connector into an external PCI connector,
>> right? Perhaps this on-board connector hass muxed GPIO and PCI pins - this is
>> probably is what Jeff was asking, if I got him correct.
>
> The brand new board was designed by the customer. Correct??
> The Spectrum Digital board was probably using HPI as opposed to the
> stated 'GPIO'. Correct??
>
> Just trying to get calibrated.
>>
>>> Now, while working with the previous board, I had added a number of code hacks
>>> while trying to deal with the inconsistency in behavior, before finally
>>> determining absolutely that mine was a hardware problem.
>>>
>>> So, I removed these hacks. Instantly, the thing ran exactly the way I wanted
>>> it to run.
>>>
>>> My PCI DMA Master code is derived from the asynch_pcitest code provided with
>>> the driver development environment, and described in spru616.pdf, and it now
>>> works...almost.
>>
>> I assume that your DSP-side code does master reads from the host, is it close
>> to the truth?
>>
>>> Well, it DOES work, but there is a bug which will become a problem eventually
>>> (though I'll get through my demo on Monday).
>>>
> Its not Monday any more, I wonder how the demo went... :-)
>
>>> The one problem I still have that I know about is this. My Linux driver
>>> (written from scratch) triggers an interrupt to the DSP to tell it to do a
>>> DMA transfer. The DSP reconfigures the interrupts and registers as required
>>> (the async code does this), transfers the data, then my program reconfigures
>>> the interrupts to what I need and sends an interrupt to the Linux system
>>> telling it the data is transferred.
>>
>> Can you be more specific here? I am not certain what do you mean by
>> reconfiguring interrupts. Does the DSP-side program remaps interrupts
>> on the fly? What do you mean by DMA transfer? Is it simply a PCI Master
>> read or you've set up a separate DMA transfer to move the data that had been
>> read by the PCI controller into an input buffer from this intermediate
>> buffer into a final destination?
>
> I agree with Andrew. It is not clear what you are trying to accomplish.
>>
>>> Now, my Linux driver expects to share the interrupt, and if the interrupt
>>> really is for it, it tests to see if the interrupt is valid. If the
>>> interrupt is not valid, it writes a message into the log saying that it
>>> received an interrupt for an unknown reason, then clears the interrupt and
>>> takes no action.
>>
>> To share the interrupt with whom? Do you mean that there are several PCI
>> devices on your host machine, or there are several processes on the DSP
>> side that may assert the PCI interrupt? How does your host-side code decides
>> on the interrupt is for it and is valid?
>
> Andrew,
> This is part of the PCI spec. Two separate PCI drivers must be able
> to share a single interrupt. I don't know if you were around in the
> early days of PCs transistioning to PCI. You sometimes [dpending on
> interrupt assignments] couldn't run certain "board combinations" [it
> was actually driver combinations].

Hi Jim, Mike,

Thanks for this comment. No, I didn't know that. I must admit however
that the idea of multiple requestors to a single event isn't new, but
could be implementable only provided there is an additional signal that
differentiate between the requestors?

What really interesting is how a pair of ISRs (may I substitute an ISR for
a driver?) can be binded to a single interrupt? :) I can hardly imagine
such a situation on the C6x, and taking into account that all computers
are more or less the same, the answer is... unknown for me. There must
be something that makes them different. For example, there are many
interrupt events for the PCI controller embedded to a C6x device, that
generate a single PCI interrupt and there is just one ISR that processes
this interrupt. But there is also a register with a set of flags each of
which uniquely corresponds to a certain event. This seem to be simple :)
Yet to make myself absolutely clear, no I do not say that this is impossible,
I just do not know how it is implemented.

This was the PC side of which I do know almost nothing. Getting back to
the C6x hardware, and the doc says that it fully conformant to the PCI
standard, but anyway is it capable to assert such a sharead interrurpt
to the host? Is there a probability that it cannot and the situation
of the precense of a shared interrupts should be removed on the host
side in the first place? So far I have never faced with shared interrupts
when I coded the DSP side of a PCI driver (on a custom designed DM642 board).
Thus was my surprise, probably too much vivid. Sorry for that.

Rgds,

Andrew

> mikedunn
>>
>> The problem looks for me like a sync problem. The code (both host and DSP
>> side) do not work in concert, do not synchronize their actions with each
>> other. Have you thought over the communication protocol, ready/not ready
>> /ack software signaling?
>>
>> Rgds,
>>
>> Andrew
>>> So, here is the bug. After loading the DSP program, the first time my Linux
>>> client program orders the DSP to do a DMA transfer, I get one message in the
>>> Linux log file saying that an interrupt was received for an unknown reason.
>>>
>>> The second time my client program orders a DMA transfer, I get two messages in
>>> the log file about an interrupt for an unknown reason
>>>
>>> The tenth time, I get ten messages in the log (actually I get one message,
>>> then another message which says: "the previous message was repeated 9
>>> times").
>>>
>>> The 100th time, 100 messages.
>>>
>>> What this means is that something someplace in the DSP is counting and not
>>> clearing, and it is setting NOT EMIFA as many times as it has in its count.
>>> Eventually, this is going to slow down the PCI bus to a noticeable degree.
>>>
>>> Given that I am using the async demo code (so far, I might add, I have found
>>> and fixed no fewer than three bugs in that code) as the basis for the DSP
>>> side of my PCI interface driver, does anyone have any idea what is counting?
>>>
>>> On Wednesday 24 October 2007 12:08:22 you wrote:
>>>> Jim,
>>>>
>>>> On 10/24/07, jim wrote:
>>>>> On Wednesday 24 October 2007 11:06:48 you wrote:
>>>>>> Jim,
>>>>>>
>>>>>> On 10/24/07, jim wrote:
>>>>>>> Well, I did find at least part of my problem.
>>>>>>>
>>>>>>> There seems to be a hardware issue with the memory address/refresh
>>>>>>> logic. I've been wrestling with inconsistent behavior, and while I
>>>>>>> have strongly suspected hardware, that isn't an easy call to make
>>>>>>> particularly when programming at such a low level.
>>>>>>
>>>>>> Make sure that you go through the EMIF setup parameters, clocks, etc.
>>>>>> to be sure that it is setup correctly. If you used the 'delivered
>>>>>> EMIF settings' and changed any of the clock configuration, your
>>>>>> refresh rate could be too slow.
>>>>>>
>>>>>> mikedunn
>>>>>
>>>>> I will certainly look at that. I would not have thought it would be
>>>>> possible to configure the refresh rate from outside. It is certainly not
>>>>> something I would have ever looked for.
>>>>
>>>> I am not sure what you mean by "from outside" [from outside the RAM??].
>>>> Hopefully your [or someone's] low level initialization code is taking
>>>> care of the EMIF setup. Are you using DSP/BIOS?? or some other
>>>> executive??
>>>>
>>>>> That actually is a possibility???
>>>>
>>>> Yes, and I have the "have I lost my mind??" experience and the gray
>>>> hair to prove it. I abstain from pulling my hair out :-)
>>>>
>>>>>>> However, I can now document some random changes in program code
>>>>>>> (which cannot be accounted for by wild pointers), and using code
>>>>>>> composer, I watched the program change a local unsigned int variable
>>>>>>> (which it was supposed to do), which also caused the next local
>>>>>>> unsigned int variable on the same stack to change as well to the same
>>>>>>> value (which should be impossible). The variable that was supposed to
>>>>>>> be changed was a return from an exec function (HWI_disable), so if
>>>>>>> this change is due to some pointer problem, the problem must be in
>>>>>>> the HWI_disable function.
>>>>>>>
>>>>>>> This accounts for a lot of things, and I still have some hair left,
>>>>>>> having not pulled it all out.
>>>>>>>
>>>>>>> On Tuesday 23 October 2007 11:42:31 you wrote:
>>>>>>>> Hi Jim,
>>>>>>>>
>>>>>>>> Please look at the page 77 of SPRU581C.pdf, on the bit 4 INTRST of
>>>>>>>> RSTSRC. It says that "This bit must be asserted before another host
>>>>>>>> interrupt can be generated."
>>>>>>>>
>>>>>>>> Next, it would help to parse all the bits in the PCIIS (even if
>>>>>>>> they are all disabled in the PCIIEN) and clear them in the PCI ISR.
>>>>>>>>
>>>>>>>> Third, it is recommended to parse an interrupt source register (any
>>>>>>>> of them, not only the PCIIS) in a loop inside an ISR and clear any
>>>>>>>> set bits until the register becomes zero, e.g. for the PCI:
>>>>>>>>
>>>>>>>> volatile uint32 temp;
>>>>>>>>
>>>>>>>> while (temp = PCIIS) // this reads the PCIIS
>>>>>>>> {
>>>>>>>> test if bit[0], ..., [n] is set
>>>>>>>> if set, clear bit[0], ... [n] and perform the necessary
>>>>>>>> actions, e.g: if bit[3] HOSTSW was set then clear bit[4] INTRST in
>>>>>>>> RSTSRC }
>>>>>>>>
>>>>>>>> // PCIIS is clear now, exit the ISR
>>>>>>>>
>>>>>>>> Hope this helps,
>>>>>>>>
>>>>>>>> Andrew
>>>>>>>>
>>>>>>>>> 11a. ISR falls off cliff...sometimes.
>>>>>>>>> Posted by: "jim" j...@justsosoftware.com jiml8
>>>>>>>>> Date: Mon Oct 22, 2007 8:42 pm ((PDT))
>>>>>>>>>
>>>>>>>>> I have defined an ISR that responds to an interrupt on the PCI
>>>>>>>>> bus from a host. The current code for this ISR is this:
>>>>>>>>>
>>>>>>>>> interrupt void DMAtoHost(void)
>>>>>>>>> {
>>>>>>>>> unsigned int intval,*datastatusregister;
>>>>>>>>> puts("interrupted\n");
>>>>>>>>> datastatusregister = (unsigned int *)DATASTATUSREGISTER;
>>>>>>>>> intval = *datastatusregister & 0x04;
>>>>>>>>> if(intval == 4) { /* is this a host interrupt */
>>>>>>>>> intval = *datastatusregister;
>>>>>>>>> intval = intval & 0xfffffffb;
>>>>>>>>> *datastatusregister = intval; /* if so clear it */
>>>>>>>>> SEM_post(HostDMASem);
>>>>>>>>> puts("resetting PCIIS\n");
>>>>>>>>> }
>>>>>>>>> PCI_RSET(PCIIS,0x00000008);
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> Now, DATASTATUSREGISTER is a memory location on the DSP SDRAM
>>>>>>>>> that I have taken over for tracking status information between my
>>>>>>>>> Linux driver and my DSP interface. Here I am testing a flag in
>>>>>>>>> that register to make sure that this interrupt really was set by
>>>>>>>>> the host (my linux driver both sets the interrupt and sets this
>>>>>>>>> flag to tell that it did it), and if so, I clear that location as
>>>>>>>>> well as clearing the PCIIS register.
>>>>>>>>>
>>>>>>>>> Basically, if this really was an interrupt from the host, this
>>>>>>>>> ISR posts to a semaphore called HostDMASem, and there is a task
>>>>>>>>> sleeping on this semaphore waiting to be told to transfer data.
>>>>>>>>>
>>>>>>>>> I have defined this ISR statically using the Code Composer
>>>>>>>>> configuration tool, and it is hooked to interrupt 13.
>>>>>>>>>
>>>>>>>>> I have tried various ways to set that semaphore; my current
>>>>>>>>> iteration has the semaphore defined statically using the
>>>>>>>>> configuration tool, and it is initialized as one of the very
>>>>>>>>> first things done in the main routine of the program when it
>>>>>>>>> starts, like this:
>>>>>>>>>
>>>>>>>>> SEM_new(HostDMASem,0);
>>>>>>>>>
>>>>>>>>> That main task then spawns a new task called buildall_tsk, which
>>>>>>>>> is the task which winds up sleeping on the semaphore. This task
>>>>>>>>> arrives at the semaphore through a subroutine call, like this:
>>>>>>>>>
>>>>>>>>> void WaitForDMA(void)
>>>>>>>>> {
>>>>>>>>> Bool semstatus;
>>>>>>>>> SEM_reset(HostDMASem,0);
>>>>>>>>> semstatus = SEM_pend(HostDMASem,SYS_FOREVER);
>>>>>>>>> if(!semstatus){puts("semaphore bombed\n");} else {puts("semaphore
>>>>>>>>> worked\n");}
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> My problem is this. When an interrupt from the host is set, this
>>>>>>>>> ISR invokes apparently correctly. However, sometimes when it
>>>>>>>>> reaches the end, it falls off the cliff (apparently the semaphore
>>>>>>>>> is not being recognized properly or some such) and nothing
>>>>>>>>> happens.
>>>>>>>>>
>>>>>>>>> Further, when the routine falls off the cliff, subsequent
>>>>>>>>> interrupts are apparently ignored; when the routine falls off the
>>>>>>>>> cliff, it doesn't get invoked again until I completely reset the
>>>>>>>>> system (which sometimes involves cycling power as well as
>>>>>>>>> restarting Code Composer.
>>>>>>>>>
>>>>>>>>> This seems to be erratic and I can't define specific conditions
>>>>>>>>> that cause it or not. I suspecte some initialization thing that
>>>>>>>>> Code Composer is doing, but I have no idea what.
>>>>>>>>>
>>>>>>>>> The card is a Spectrum Digital 6416 card.
>>>>>>>>>
>>>>>>>>> I am tearing my hair out over this, and trust me; I don't look
>>>>>>>>> good bald. Anyone here have any idea what is going on?
>>>>>>>>
>>>>>>>
>>>
>>
Andrew,

On 10/30/07, Andrew Nesterov wrote:
> > Date: 30-Oct-2007 08:20:05 -0700
> > From: Michael Dunn
> > To: Andrew Nesterov
> > Cc: c..., j...@justsosoftware.com
> > Subject: Re: [c6x] Re: Re: ISR falls off cliff...sometimes.
> >
> > Jim,
> >
> > On 10/29/07, Andrew Nesterov wrote:
> >>> Subject: Re: ISR falls off cliff...sometimes.
> >>> Posted by: "jim" j...@justsosoftware.com jiml8
> >>> Date: Sun Oct 28, 2007 7:20 am ((PDT))
> >>>
> >>> ... And now...the REST of the story!
> >>>
> >>> My client came up with a brand new board, and we wired it to be a PCI
> >>> interface (rather than GPIO) and plugged it in. Behavior of this new board
> >>> was consistent; it would transfer data two or three times, then hang. I
> >>> checked the initialization EMIF stuff; the board was set to run at 500 MHz
> >>> when it was a 1000 MHz board. So I turned up the speed. Behavior remained
> >>> exactly the same as it had been; two or three correct transfers, then hang.
> >>
> >> I saw that Spectrum Digital's C6416 EVM does not have a PCI connector, does it?
> >> So you needed to to wire its on board connector into an external PCI connector,
> >> right? Perhaps this on-board connector hass muxed GPIO and PCI pins - this is
> >> probably is what Jeff was asking, if I got him correct.
> >
> > The brand new board was designed by the customer. Correct??
> > The Spectrum Digital board was probably using HPI as opposed to the
> > stated 'GPIO'. Correct??
> >
> > Just trying to get calibrated.
> >>
> >>> Now, while working with the previous board, I had added a number of code hacks
> >>> while trying to deal with the inconsistency in behavior, before finally
> >>> determining absolutely that mine was a hardware problem.
> >>>
> >>> So, I removed these hacks. Instantly, the thing ran exactly the way I wanted
> >>> it to run.
> >>>
> >>> My PCI DMA Master code is derived from the asynch_pcitest code provided with
> >>> the driver development environment, and described in spru616.pdf, and it now
> >>> works...almost.
> >>
> >> I assume that your DSP-side code does master reads from the host, is it close
> >> to the truth?
> >>
> >>> Well, it DOES work, but there is a bug which will become a problem eventually
> >>> (though I'll get through my demo on Monday).
> >>>
> > Its not Monday any more, I wonder how the demo went... :-)
> >
> >>> The one problem I still have that I know about is this. My Linux driver
> >>> (written from scratch) triggers an interrupt to the DSP to tell it to do a
> >>> DMA transfer. The DSP reconfigures the interrupts and registers as required
> >>> (the async code does this), transfers the data, then my program reconfigures
> >>> the interrupts to what I need and sends an interrupt to the Linux system
> >>> telling it the data is transferred.
> >>
> >> Can you be more specific here? I am not certain what do you mean by
> >> reconfiguring interrupts. Does the DSP-side program remaps interrupts
> >> on the fly? What do you mean by DMA transfer? Is it simply a PCI Master
> >> read or you've set up a separate DMA transfer to move the data that had been
> >> read by the PCI controller into an input buffer from this intermediate
> >> buffer into a final destination?
> >
> > I agree with Andrew. It is not clear what you are trying to accomplish.
> >>
> >>> Now, my Linux driver expects to share the interrupt, and if the interrupt
> >>> really is for it, it tests to see if the interrupt is valid. If the
> >>> interrupt is not valid, it writes a message into the log saying that it
> >>> received an interrupt for an unknown reason, then clears the interrupt and
> >>> takes no action.
> >>
> >> To share the interrupt with whom? Do you mean that there are several PCI
> >> devices on your host machine, or there are several processes on the DSP
> >> side that may assert the PCI interrupt? How does your host-side code decides
> >> on the interrupt is for it and is valid?
> >
> > Andrew,
> > This is part of the PCI spec. Two separate PCI drivers must be able
> > to share a single interrupt. I don't know if you were around in the
> > early days of PCs transistioning to PCI. You sometimes [dpending on
> > interrupt assignments] couldn't run certain "board combinations" [it
> > was actually driver combinations].
>
> Hi Jim, Mike,
>
> Thanks for this comment. No, I didn't know that. I must admit however
> that the idea of multiple requestors to a single event isn't new, but
> could be implementable only provided there is an additional signal that
> differentiate between the requestors?

see Wikipedia for a decent description of shared interrupts.
Separate interrupt lines are a modern [speed] convenience. Several
minicomputers were built with a single interrupt.
Think of a single ISR that knows 'who is out there'. He asks each
one, 'is it you?' until he gets a taker. He thens calls the 'sub-ISR'
to do its thing. When the sub-ISR services the device, the device
'lets go' of the interrupt and returns to the ISR. If the interrupt
is still there, the ISR continues down the list until he gets another
taker... and so on. Shared interrupts must be level triggered.

Yes, you too can do it on a c6x.

mikedunn
>
> What really interesting is how a pair of ISRs (may I substitute an ISR for
> a driver?) can be binded to a single interrupt? :) I can hardly imagine
> such a situation on the C6x, and taking into account that all computers
> are more or less the same, the answer is... unknown for me. There must
> be something that makes them different. For example, there are many
> interrupt events for the PCI controller embedded to a C6x device, that
> generate a single PCI interrupt and there is just one ISR that processes
> this interrupt. But there is also a register with a set of flags each of
> which uniquely corresponds to a certain event. This seem to be simple :)
> Yet to make myself absolutely clear, no I do not say that this is impossible,
> I just do not know how it is implemented.
>
> This was the PC side of which I do know almost nothing. Getting back to
> the C6x hardware, and the doc says that it fully conformant to the PCI
> standard, but anyway is it capable to assert such a sharead interrurpt
> to the host? Is there a probability that it cannot and the situation
> of the precense of a shared interrupts should be removed on the host
> side in the first place? So far I have never faced with shared interrupts
> when I coded the DSP side of a PCI driver (on a custom designed DM642 board).
> Thus was my surprise, probably too much vivid. Sorry for that.
>
> Rgds,
>
> Andrew
>
> > mikedunn
> >>
> >> The problem looks for me like a sync problem. The code (both host and DSP
> >> side) do not work in concert, do not synchronize their actions with each
> >> other. Have you thought over the communication protocol, ready/not ready
> >> /ack software signaling?
> >>
> >> Rgds,
> >>
> >> Andrew
> >>
> >>
> >>> So, here is the bug. After loading the DSP program, the first time my Linux
> >>> client program orders the DSP to do a DMA transfer, I get one message in the
> >>> Linux log file saying that an interrupt was received for an unknown reason.
> >>>
> >>> The second time my client program orders a DMA transfer, I get two messages in
> >>> the log file about an interrupt for an unknown reason
> >>>
> >>> The tenth time, I get ten messages in the log (actually I get one message,
> >>> then another message which says: "the previous message was repeated 9
> >>> times").
> >>>
> >>> The 100th time, 100 messages.
> >>>
> >>> What this means is that something someplace in the DSP is counting and not
> >>> clearing, and it is setting NOT EMIFA as many times as it has in its count.
> >>> Eventually, this is going to slow down the PCI bus to a noticeable degree.
> >>>
> >>> Given that I am using the async demo code (so far, I might add, I have found
> >>> and fixed no fewer than three bugs in that code) as the basis for the DSP
> >>> side of my PCI interface driver, does anyone have any idea what is counting?
> >>>
> >>> On Wednesday 24 October 2007 12:08:22 you wrote:
> >>>> Jim,
> >>>>
> >>>> On 10/24/07, jim wrote:
> >>>>> On Wednesday 24 October 2007 11:06:48 you wrote:
> >>>>>> Jim,
> >>>>>>
> >>>>>> On 10/24/07, jim wrote:
> >>>>>>> Well, I did find at least part of my problem.
> >>>>>>>
> >>>>>>> There seems to be a hardware issue with the memory address/refresh
> >>>>>>> logic. I've been wrestling with inconsistent behavior, and while I
> >>>>>>> have strongly suspected hardware, that isn't an easy call to make
> >>>>>>> particularly when programming at such a low level.
> >>>>>>
> >>>>>> Make sure that you go through the EMIF setup parameters, clocks, etc.
> >>>>>> to be sure that it is setup correctly. If you used the 'delivered
> >>>>>> EMIF settings' and changed any of the clock configuration, your
> >>>>>> refresh rate could be too slow.
> >>>>>>
> >>>>>> mikedunn
> >>>>>
> >>>>> I will certainly look at that. I would not have thought it would be
> >>>>> possible to configure the refresh rate from outside. It is certainly not
> >>>>> something I would have ever looked for.
> >>>>
> >>>> I am not sure what you mean by "from outside" [from outside the RAM??].
> >>>> Hopefully your [or someone's] low level initialization code is taking
> >>>> care of the EMIF setup. Are you using DSP/BIOS?? or some other
> >>>> executive??
> >>>>
> >>>>> That actually is a possibility???
> >>>>
> >>>> Yes, and I have the "have I lost my mind??" experience and the gray
> >>>> hair to prove it. I abstain from pulling my hair out :-)
> >>>>
> >>>>>>> However, I can now document some random changes in program code
> >>>>>>> (which cannot be accounted for by wild pointers), and using code
> >>>>>>> composer, I watched the program change a local unsigned int variable
> >>>>>>> (which it was supposed to do), which also caused the next local
> >>>>>>> unsigned int variable on the same stack to change as well to the same
> >>>>>>> value (which should be impossible). The variable that was supposed to
> >>>>>>> be changed was a return from an exec function (HWI_disable), so if
> >>>>>>> this change is due to some pointer problem, the problem must be in
> >>>>>>> the HWI_disable function.
> >>>>>>>
> >>>>>>> This accounts for a lot of things, and I still have some hair left,
> >>>>>>> having not pulled it all out.
> >>>>>>>
> >>>>>>> On Tuesday 23 October 2007 11:42:31 you wrote:
> >>>>>>>> Hi Jim,
> >>>>>>>>
> >>>>>>>> Please look at the page 77 of SPRU581C.pdf, on the bit 4 INTRST of
> >>>>>>>> RSTSRC. It says that "This bit must be asserted before another host
> >>>>>>>> interrupt can be generated."
> >>>>>>>>
> >>>>>>>> Next, it would help to parse all the bits in the PCIIS (even if
> >>>>>>>> they are all disabled in the PCIIEN) and clear them in the PCI ISR.
> >>>>>>>>
> >>>>>>>> Third, it is recommended to parse an interrupt source register (any
> >>>>>>>> of them, not only the PCIIS) in a loop inside an ISR and clear any
> >>>>>>>> set bits until the register becomes zero, e.g. for the PCI:
> >>>>>>>>
> >>>>>>>> volatile uint32 temp;
> >>>>>>>>
> >>>>>>>> while (temp = PCIIS) // this reads the PCIIS
> >>>>>>>> {
> >>>>>>>> test if bit[0], ..., [n] is set
> >>>>>>>> if set, clear bit[0], ... [n] and perform the necessary
> >>>>>>>> actions, e.g: if bit[3] HOSTSW was set then clear bit[4] INTRST in
> >>>>>>>> RSTSRC }
> >>>>>>>>
> >>>>>>>> // PCIIS is clear now, exit the ISR
> >>>>>>>>
> >>>>>>>> Hope this helps,
> >>>>>>>>
> >>>>>>>> Andrew
> >>>>>>>>
> >>>>>>>>> 11a. ISR falls off cliff...sometimes.
> >>>>>>>>> Posted by: "jim" j...@justsosoftware.com jiml8
> >>>>>>>>> Date: Mon Oct 22, 2007 8:42 pm ((PDT))
> >>>>>>>>>
> >>>>>>>>> I have defined an ISR that responds to an interrupt on the PCI
> >>>>>>>>> bus from a host. The current code for this ISR is this:
> >>>>>>>>>
> >>>>>>>>> interrupt void DMAtoHost(void)
> >>>>>>>>> {
> >>>>>>>>> unsigned int intval,*datastatusregister;
> >>>>>>>>> puts("interrupted\n");
> >>>>>>>>> datastatusregister = (unsigned int *)DATASTATUSREGISTER;
> >>>>>>>>> intval = *datastatusregister & 0x04;
> >>>>>>>>> if(intval == 4) { /* is this a host interrupt */
> >>>>>>>>> intval = *datastatusregister;
> >>>>>>>>> intval = intval & 0xfffffffb;
> >>>>>>>>> *datastatusregister = intval; /* if so clear it */
> >>>>>>>>> SEM_post(HostDMASem);
> >>>>>>>>> puts("resetting PCIIS\n");
> >>>>>>>>> }
> >>>>>>>>> PCI_RSET(PCIIS,0x00000008);
> >>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> Now, DATASTATUSREGISTER is a memory location on the DSP SDRAM
> >>>>>>>>> that I have taken over for tracking status information between my
> >>>>>>>>> Linux driver and my DSP interface. Here I am testing a flag in
> >>>>>>>>> that register to make sure that this interrupt really was set by
> >>>>>>>>> the host (my linux driver both sets the interrupt and sets this
> >>>>>>>>> flag to tell that it did it), and if so, I clear that location as
> >>>>>>>>> well as clearing the PCIIS register.
> >>>>>>>>>
> >>>>>>>>> Basically, if this really was an interrupt from the host, this
> >>>>>>>>> ISR posts to a semaphore called HostDMASem, and there is a task
> >>>>>>>>> sleeping on this semaphore waiting to be told to transfer data.
> >>>>>>>>>
> >>>>>>>>> I have defined this ISR statically using the Code Composer
> >>>>>>>>> configuration tool, and it is hooked to interrupt 13.
> >>>>>>>>>
> >>>>>>>>> I have tried various ways to set that semaphore; my current
> >>>>>>>>> iteration has the semaphore defined statically using the
> >>>>>>>>> configuration tool, and it is initialized as one of the very
> >>>>>>>>> first things done in the main routine of the program when it
> >>>>>>>>> starts, like this:
> >>>>>>>>>
> >>>>>>>>> SEM_new(HostDMASem,0);
> >>>>>>>>>
> >>>>>>>>> That main task then spawns a new task called buildall_tsk, which
> >>>>>>>>> is the task which winds up sleeping on the semaphore. This task
> >>>>>>>>> arrives at the semaphore through a subroutine call, like this:
> >>>>>>>>>
> >>>>>>>>> void WaitForDMA(void)
> >>>>>>>>> {
> >>>>>>>>> Bool semstatus;
> >>>>>>>>> SEM_reset(HostDMASem,0);
> >>>>>>>>> semstatus = SEM_pend(HostDMASem,SYS_FOREVER);
> >>>>>>>>> if(!semstatus){puts("semaphore bombed\n");} else {puts("semaphore
> >>>>>>>>> worked\n");}
> >>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> My problem is this. When an interrupt from the host is set, this
> >>>>>>>>> ISR invokes apparently correctly. However, sometimes when it
> >>>>>>>>> reaches the end, it falls off the cliff (apparently the semaphore
> >>>>>>>>> is not being recognized properly or some such) and nothing
> >>>>>>>>> happens.
> >>>>>>>>>
> >>>>>>>>> Further, when the routine falls off the cliff, subsequent
> >>>>>>>>> interrupts are apparently ignored; when the routine falls off the
> >>>>>>>>> cliff, it doesn't get invoked again until I completely reset the
> >>>>>>>>> system (which sometimes involves cycling power as well as
> >>>>>>>>> restarting Code Composer.
> >>>>>>>>>
> >>>>>>>>> This seems to be erratic and I can't define specific conditions
> >>>>>>>>> that cause it or not. I suspecte some initialization thing that
> >>>>>>>>> Code Composer is doing, but I have no idea what.
> >>>>>>>>>
> >>>>>>>>> The card is a Spectrum Digital 6416 card.
> >>>>>>>>>
> >>>>>>>>> I am tearing my hair out over this, and trust me; I don't look
> >>>>>>>>> good bald. Anyone here have any idea what is going on?
> >>>>>>>>
> >>>>>>>
> >>>
> >>>
> >>
> >>
> >>
> >>
>
> Subject: Re: ISR falls off cliff...sometimes.
> Posted by: "jim" j...@justsosoftware.com jiml8
> Date: Sun Oct 28, 2007 7:20 am ((PDT))
>
> ... And now...the REST of the story!
>
> My client came up with a brand new board, and we wired it to be a PCI
> interface (rather than GPIO) and plugged it in. Behavior of this new board
> was consistent; it would transfer data two or three times, then hang. I
> checked the initialization EMIF stuff; the board was set to run at 500 MHz
> when it was a 1000 MHz board. So I turned up the speed. Behavior remained
> exactly the same as it had been; two or three correct transfers, then hang.

I saw that Spectrum Digital's C6416 EVM does not have a PCI connector, does it?
So you needed to to wire its on board connector into an external PCI connector,
right? Perhaps this on-board connector hass muxed GPIO and PCI pins - this is
probably is what Jeff was asking, if I got him correct.

> Now, while working with the previous board, I had added a number of code hacks
> while trying to deal with the inconsistency in behavior, before finally
> determining absolutely that mine was a hardware problem.
>
> So, I removed these hacks. Instantly, the thing ran exactly the way I wanted
> it to run.
>
> My PCI DMA Master code is derived from the asynch_pcitest code provided with
> the driver development environment, and described in spru616.pdf, and it now
> works...almost.

I assume that your DSP-side code does master reads from the host, is it close
to the truth?

> Well, it DOES work, but there is a bug which will become a problem eventually
> (though I'll get through my demo on Monday).
>
> The one problem I still have that I know about is this. My Linux driver
> (written from scratch) triggers an interrupt to the DSP to tell it to do a
> DMA transfer. The DSP reconfigures the interrupts and registers as required
> (the async code does this), transfers the data, then my program reconfigures
> the interrupts to what I need and sends an interrupt to the Linux system
> telling it the data is transferred.

Can you be more specific here? I am not certain what do you mean by
reconfiguring interrupts. Does the DSP-side program remaps interrupts
on the fly? What do you mean by DMA transfer? Is it simply a PCI Master
read or you've set up a separate DMA transfer to move the data that had been
read by the PCI controller into an input buffer from this intermediate
buffer into a final destination?

> Now, my Linux driver expects to share the interrupt, and if the interrupt
> really is for it, it tests to see if the interrupt is valid. If the
> interrupt is not valid, it writes a message into the log saying that it
> received an interrupt for an unknown reason, then clears the interrupt and
> takes no action.

To share the interrupt with whom? Do you mean that there are several PCI
devices on your host machine, or there are several processes on the DSP
side that may assert the PCI interrupt? How does your host-side code decides
on the interrupt is for it and is valid?

The problem looks for me like a sync problem. The code (both host and DSP
side) do not work in concert, do not synchronize their actions with each
other. Have you thought over the communication protocol, ready/not ready
/ack software signaling?

Rgds,

Andrew

> So, here is the bug. After loading the DSP program, the first time my Linux
> client program orders the DSP to do a DMA transfer, I get one message in the
> Linux log file saying that an interrupt was received for an unknown reason.
>
> The second time my client program orders a DMA transfer, I get two messages in
> the log file about an interrupt for an unknown reason
>
> The tenth time, I get ten messages in the log (actually I get one message,
> then another message which says: "the previous message was repeated 9
> times").
>
> The 100th time, 100 messages.
>
> What this means is that something someplace in the DSP is counting and not
> clearing, and it is setting NOT EMIFA as many times as it has in its count.
> Eventually, this is going to slow down the PCI bus to a noticeable degree.
>
> Given that I am using the async demo code (so far, I might add, I have found
> and fixed no fewer than three bugs in that code) as the basis for the DSP
> side of my PCI interface driver, does anyone have any idea what is counting?
>
> On Wednesday 24 October 2007 12:08:22 you wrote:
>> Jim,
>>
>> On 10/24/07, jim wrote:
>>> On Wednesday 24 October 2007 11:06:48 you wrote:
>>>> Jim,
>>>>
>>>> On 10/24/07, jim wrote:
>>>>> Well, I did find at least part of my problem.
>>>>>
>>>>> There seems to be a hardware issue with the memory address/refresh
>>>>> logic. I've been wrestling with inconsistent behavior, and while I
>>>>> have strongly suspected hardware, that isn't an easy call to make
>>>>> particularly when programming at such a low level.
>>>>
>>>> Make sure that you go through the EMIF setup parameters, clocks, etc.
>>>> to be sure that it is setup correctly. If you used the 'delivered
>>>> EMIF settings' and changed any of the clock configuration, your
>>>> refresh rate could be too slow.
>>>>
>>>> mikedunn
>>>
>>> I will certainly look at that. I would not have thought it would be
>>> possible to configure the refresh rate from outside. It is certainly not
>>> something I would have ever looked for.
>>
>> I am not sure what you mean by "from outside" [from outside the RAM??].
>> Hopefully your [or someone's] low level initialization code is taking
>> care of the EMIF setup. Are you using DSP/BIOS?? or some other
>> executive??
>>
>>> That actually is a possibility???
>>
>> Yes, and I have the "have I lost my mind??" experience and the gray
>> hair to prove it. I abstain from pulling my hair out :-)
>>
>>>>> However, I can now document some random changes in program code
>>>>> (which cannot be accounted for by wild pointers), and using code
>>>>> composer, I watched the program change a local unsigned int variable
>>>>> (which it was supposed to do), which also caused the next local
>>>>> unsigned int variable on the same stack to change as well to the same
>>>>> value (which should be impossible). The variable that was supposed to
>>>>> be changed was a return from an exec function (HWI_disable), so if
>>>>> this change is due to some pointer problem, the problem must be in
>>>>> the HWI_disable function.
>>>>>
>>>>> This accounts for a lot of things, and I still have some hair left,
>>>>> having not pulled it all out.
>>>>>
>>>>> On Tuesday 23 October 2007 11:42:31 you wrote:
>>>>>> Hi Jim,
>>>>>>
>>>>>> Please look at the page 77 of SPRU581C.pdf, on the bit 4 INTRST of
>>>>>> RSTSRC. It says that "This bit must be asserted before another host
>>>>>> interrupt can be generated."
>>>>>>
>>>>>> Next, it would help to parse all the bits in the PCIIS (even if
>>>>>> they are all disabled in the PCIIEN) and clear them in the PCI ISR.
>>>>>>
>>>>>> Third, it is recommended to parse an interrupt source register (any
>>>>>> of them, not only the PCIIS) in a loop inside an ISR and clear any
>>>>>> set bits until the register becomes zero, e.g. for the PCI:
>>>>>>
>>>>>> volatile uint32 temp;
>>>>>>
>>>>>> while (temp = PCIIS) // this reads the PCIIS
>>>>>> {
>>>>>> test if bit[0], ..., [n] is set
>>>>>> if set, clear bit[0], ... [n] and perform the necessary
>>>>>> actions, e.g: if bit[3] HOSTSW was set then clear bit[4] INTRST in
>>>>>> RSTSRC }
>>>>>>
>>>>>> // PCIIS is clear now, exit the ISR
>>>>>>
>>>>>> Hope this helps,
>>>>>>
>>>>>> Andrew
>>>>>>
>>>>>>> 11a. ISR falls off cliff...sometimes.
>>>>>>> Posted by: "jim" j...@justsosoftware.com jiml8
>>>>>>> Date: Mon Oct 22, 2007 8:42 pm ((PDT))
>>>>>>>
>>>>>>> I have defined an ISR that responds to an interrupt on the PCI
>>>>>>> bus from a host. The current code for this ISR is this:
>>>>>>>
>>>>>>> interrupt void DMAtoHost(void)
>>>>>>> {
>>>>>>> unsigned int intval,*datastatusregister;
>>>>>>> puts("interrupted\n");
>>>>>>> datastatusregister = (unsigned int *)DATASTATUSREGISTER;
>>>>>>> intval = *datastatusregister & 0x04;
>>>>>>> if(intval == 4) { /* is this a host interrupt */
>>>>>>> intval = *datastatusregister;
>>>>>>> intval = intval & 0xfffffffb;
>>>>>>> *datastatusregister = intval; /* if so clear it */
>>>>>>> SEM_post(HostDMASem);
>>>>>>> puts("resetting PCIIS\n");
>>>>>>> }
>>>>>>> PCI_RSET(PCIIS,0x00000008);
>>>>>>> }
>>>>>>>
>>>>>>> Now, DATASTATUSREGISTER is a memory location on the DSP SDRAM
>>>>>>> that I have taken over for tracking status information between my
>>>>>>> Linux driver and my DSP interface. Here I am testing a flag in
>>>>>>> that register to make sure that this interrupt really was set by
>>>>>>> the host (my linux driver both sets the interrupt and sets this
>>>>>>> flag to tell that it did it), and if so, I clear that location as
>>>>>>> well as clearing the PCIIS register.
>>>>>>>
>>>>>>> Basically, if this really was an interrupt from the host, this
>>>>>>> ISR posts to a semaphore called HostDMASem, and there is a task
>>>>>>> sleeping on this semaphore waiting to be told to transfer data.
>>>>>>>
>>>>>>> I have defined this ISR statically using the Code Composer
>>>>>>> configuration tool, and it is hooked to interrupt 13.
>>>>>>>
>>>>>>> I have tried various ways to set that semaphore; my current
>>>>>>> iteration has the semaphore defined statically using the
>>>>>>> configuration tool, and it is initialized as one of the very
>>>>>>> first things done in the main routine of the program when it
>>>>>>> starts, like this:
>>>>>>>
>>>>>>> SEM_new(HostDMASem,0);
>>>>>>>
>>>>>>> That main task then spawns a new task called buildall_tsk, which
>>>>>>> is the task which winds up sleeping on the semaphore. This task
>>>>>>> arrives at the semaphore through a subroutine call, like this:
>>>>>>>
>>>>>>> void WaitForDMA(void)
>>>>>>> {
>>>>>>> Bool semstatus;
>>>>>>> SEM_reset(HostDMASem,0);
>>>>>>> semstatus = SEM_pend(HostDMASem,SYS_FOREVER);
>>>>>>> if(!semstatus){puts("semaphore bombed\n");} else {puts("semaphore
>>>>>>> worked\n");}
>>>>>>> }
>>>>>>>
>>>>>>> My problem is this. When an interrupt from the host is set, this
>>>>>>> ISR invokes apparently correctly. However, sometimes when it
>>>>>>> reaches the end, it falls off the cliff (apparently the semaphore
>>>>>>> is not being recognized properly or some such) and nothing
>>>>>>> happens.
>>>>>>>
>>>>>>> Further, when the routine falls off the cliff, subsequent
>>>>>>> interrupts are apparently ignored; when the routine falls off the
>>>>>>> cliff, it doesn't get invoked again until I completely reset the
>>>>>>> system (which sometimes involves cycling power as well as
>>>>>>> restarting Code Composer.
>>>>>>>
>>>>>>> This seems to be erratic and I can't define specific conditions
>>>>>>> that cause it or not. I suspecte some initialization thing that
>>>>>>> Code Composer is doing, but I have no idea what.
>>>>>>>
>>>>>>> The card is a Spectrum Digital 6416 card.
>>>>>>>
>>>>>>> I am tearing my hair out over this, and trust me; I don't look
>>>>>>> good bald. Anyone here have any idea what is going on?
>>>>>>
>>>>>
Mike,

> Date: Tue, 30 Oct 2007 17:38:38 -0500
> From: Michael Dunn Andrew,
>
> On 10/30/07, Andrew Nesterov wrote:
>>> Date: 30-Oct-2007 08:20:05 -0700
>>> From: Michael Dunn
>>> To: Andrew Nesterov
>>> Cc: c..., j...@justsosoftware.com
>>> Subject: Re: [c6x] Re: Re: ISR falls off cliff...sometimes.
>>>
>>> Jim,
>>>
>>> On 10/29/07, Andrew Nesterov wrote:
>>>>> Subject: Re: ISR falls off cliff...sometimes.
>>>>> Posted by: "jim" j...@justsosoftware.com jiml8
>>>>> Date: Sun Oct 28, 2007 7:20 am ((PDT))
>>>>>
>>>>> ... And now...the REST of the story!
>>>>>
>>>>> My client came up with a brand new board, and we wired it to be a PCI
>>>>> interface (rather than GPIO) and plugged it in. Behavior of this new board
>>>>> was consistent; it would transfer data two or three times, then hang. I
>>>>> checked the initialization EMIF stuff; the board was set to run at 500 MHz
>>>>> when it was a 1000 MHz board. So I turned up the speed. Behavior remained
>>>>> exactly the same as it had been; two or three correct transfers, then hang.
>>>>
>>>> I saw that Spectrum Digital's C6416 EVM does not have a PCI connector, does it?
>>>> So you needed to to wire its on board connector into an external PCI connector,
>>>> right? Perhaps this on-board connector hass muxed GPIO and PCI pins - this is
>>>> probably is what Jeff was asking, if I got him correct.
>>>
>>> The brand new board was designed by the customer. Correct??
>>> The Spectrum Digital board was probably using HPI as opposed to the
>>> stated 'GPIO'. Correct??
>>>
>>> Just trying to get calibrated.
>>>>
>>>>> Now, while working with the previous board, I had added a number of code hacks
>>>>> while trying to deal with the inconsistency in behavior, before finally
>>>>> determining absolutely that mine was a hardware problem.
>>>>>
>>>>> So, I removed these hacks. Instantly, the thing ran exactly the way I wanted
>>>>> it to run.
>>>>>
>>>>> My PCI DMA Master code is derived from the asynch_pcitest code provided with
>>>>> the driver development environment, and described in spru616.pdf, and it now
>>>>> works...almost.
>>>>
>>>> I assume that your DSP-side code does master reads from the host, is it close
>>>> to the truth?
>>>>
>>>>> Well, it DOES work, but there is a bug which will become a problem eventually
>>>>> (though I'll get through my demo on Monday).
>>>>>
>>> Its not Monday any more, I wonder how the demo went... :-)
>>>
>>>>> The one problem I still have that I know about is this. My Linux driver
>>>>> (written from scratch) triggers an interrupt to the DSP to tell it to do a
>>>>> DMA transfer. The DSP reconfigures the interrupts and registers as required
>>>>> (the async code does this), transfers the data, then my program reconfigures
>>>>> the interrupts to what I need and sends an interrupt to the Linux system
>>>>> telling it the data is transferred.
>>>>
>>>> Can you be more specific here? I am not certain what do you mean by
>>>> reconfiguring interrupts. Does the DSP-side program remaps interrupts
>>>> on the fly? What do you mean by DMA transfer? Is it simply a PCI Master
>>>> read or you've set up a separate DMA transfer to move the data that had been
>>>> read by the PCI controller into an input buffer from this intermediate
>>>> buffer into a final destination?
>>>
>>> I agree with Andrew. It is not clear what you are trying to accomplish.
>>>>
>>>>> Now, my Linux driver expects to share the interrupt, and if the interrupt
>>>>> really is for it, it tests to see if the interrupt is valid. If the
>>>>> interrupt is not valid, it writes a message into the log saying that it
>>>>> received an interrupt for an unknown reason, then clears the interrupt and
>>>>> takes no action.
>>>>
>>>> To share the interrupt with whom? Do you mean that there are several PCI
>>>> devices on your host machine, or there are several processes on the DSP
>>>> side that may assert the PCI interrupt? How does your host-side code decides
>>>> on the interrupt is for it and is valid?
>>>
>>> Andrew,
>>> This is part of the PCI spec. Two separate PCI drivers must be able
>>> to share a single interrupt. I don't know if you were around in the
>>> early days of PCs transistioning to PCI. You sometimes [dpending on
>>> interrupt assignments] couldn't run certain "board combinations" [it
>>> was actually driver combinations].
>>
>> Hi Jim, Mike,
>>
>> Thanks for this comment. No, I didn't know that. I must admit however
>> that the idea of multiple requestors to a single event isn't new, but
>> could be implementable only provided there is an additional signal that
>> differentiate between the requestors?
>
> see Wikipedia for a decent description of shared interrupts.
> Separate interrupt lines are a modern [speed] convenience. Several
> minicomputers were built with a single interrupt.
> Think of a single ISR that knows 'who is out there'. He asks each
> one, 'is it you?' until he gets a taker. He thens calls the 'sub-ISR'
> to do its thing. When the sub-ISR services the device, the device
> 'lets go' of the interrupt and returns to the ISR. If the interrupt
> is still there, the ISR continues down the list until he gets another
> taker... and so on. Shared interrupts must be level triggered.

Now I am absolutely clear as far as shared interrupts go. Thanks.
I can answer my previous question "to share the interrupt with whom?"
on my own :)

Andrew

> Yes, you too can do it on a c6x.
>
> mikedunn
>>
>> What really interesting is how a pair of ISRs (may I substitute an ISR for
>> a driver?) can be binded to a single interrupt? :) I can hardly imagine
>> such a situation on the C6x, and taking into account that all computers
>> are more or less the same, the answer is... unknown for me. There must
>> be something that makes them different. For example, there are many
>> interrupt events for the PCI controller embedded to a C6x device, that
>> generate a single PCI interrupt and there is just one ISR that processes
>> this interrupt. But there is also a register with a set of flags each of
>> which uniquely corresponds to a certain event. This seem to be simple :)
>> Yet to make myself absolutely clear, no I do not say that this is impossible,
>> I just do not know how it is implemented.
>>
>> This was the PC side of which I do know almost nothing. Getting back to
>> the C6x hardware, and the doc says that it fully conformant to the PCI
>> standard, but anyway is it capable to assert such a sharead interrurpt
>> to the host? Is there a probability that it cannot and the situation
>> of the precense of a shared interrupts should be removed on the host
>> side in the first place? So far I have never faced with shared interrupts
>> when I coded the DSP side of a PCI driver (on a custom designed DM642 board).
>> Thus was my surprise, probably too much vivid. Sorry for that.
>>
>> Rgds,
>>
>> Andrew
>>
>>> mikedunn
>>>>
>>>> The problem looks for me like a sync problem. The code (both host and DSP
>>>> side) do not work in concert, do not synchronize their actions with each
>>>> other. Have you thought over the communication protocol, ready/not ready
>>>> /ack software signaling?
>>>>
>>>> Rgds,
>>>>
>>>> Andrew
>>>>
>>>>
>>>>> So, here is the bug. After loading the DSP program, the first time my Linux
>>>>> client program orders the DSP to do a DMA transfer, I get one message in the
>>>>> Linux log file saying that an interrupt was received for an unknown reason.
>>>>>
>>>>> The second time my client program orders a DMA transfer, I get two messages in
>>>>> the log file about an interrupt for an unknown reason
>>>>>
>>>>> The tenth time, I get ten messages in the log (actually I get one message,
>>>>> then another message which says: "the previous message was repeated 9
>>>>> times").
>>>>>
>>>>> The 100th time, 100 messages.
>>>>>
>>>>> What this means is that something someplace in the DSP is counting and not
>>>>> clearing, and it is setting NOT EMIFA as many times as it has in its count.
>>>>> Eventually, this is going to slow down the PCI bus to a noticeable degree.
>>>>>
>>>>> Given that I am using the async demo code (so far, I might add, I have found
>>>>> and fixed no fewer than three bugs in that code) as the basis for the DSP
>>>>> side of my PCI interface driver, does anyone have any idea what is counting?
>>>>>
>>>>> On Wednesday 24 October 2007 12:08:22 you wrote:
>>>>>> Jim,
>>>>>>
>>>>>> On 10/24/07, jim wrote:
>>>>>>> On Wednesday 24 October 2007 11:06:48 you wrote:
>>>>>>>> Jim,
>>>>>>>>
>>>>>>>> On 10/24/07, jim wrote:
>>>>>>>>> Well, I did find at least part of my problem.
>>>>>>>>>
>>>>>>>>> There seems to be a hardware issue with the memory address/refresh
>>>>>>>>> logic. I've been wrestling with inconsistent behavior, and while I
>>>>>>>>> have strongly suspected hardware, that isn't an easy call to make
>>>>>>>>> particularly when programming at such a low level.
>>>>>>>>
>>>>>>>> Make sure that you go through the EMIF setup parameters, clocks, etc.
>>>>>>>> to be sure that it is setup correctly. If you used the 'delivered
>>>>>>>> EMIF settings' and changed any of the clock configuration, your
>>>>>>>> refresh rate could be too slow.
>>>>>>>>
>>>>>>>> mikedunn
>>>>>>>
>>>>>>> I will certainly look at that. I would not have thought it would be
>>>>>>> possible to configure the refresh rate from outside. It is certainly not
>>>>>>> something I would have ever looked for.
>>>>>>
>>>>>> I am not sure what you mean by "from outside" [from outside the RAM??].
>>>>>> Hopefully your [or someone's] low level initialization code is taking
>>>>>> care of the EMIF setup. Are you using DSP/BIOS?? or some other
>>>>>> executive??
>>>>>>
>>>>>>> That actually is a possibility???
>>>>>>
>>>>>> Yes, and I have the "have I lost my mind??" experience and the gray
>>>>>> hair to prove it. I abstain from pulling my hair out :-)
>>>>>>
>>>>>>>>> However, I can now document some random changes in program code
>>>>>>>>> (which cannot be accounted for by wild pointers), and using code
>>>>>>>>> composer, I watched the program change a local unsigned int variable
>>>>>>>>> (which it was supposed to do), which also caused the next local
>>>>>>>>> unsigned int variable on the same stack to change as well to the same
>>>>>>>>> value (which should be impossible). The variable that was supposed to
>>>>>>>>> be changed was a return from an exec function (HWI_disable), so if
>>>>>>>>> this change is due to some pointer problem, the problem must be in
>>>>>>>>> the HWI_disable function.
>>>>>>>>>
>>>>>>>>> This accounts for a lot of things, and I still have some hair left,
>>>>>>>>> having not pulled it all out.
>>>>>>>>>
>>>>>>>>> On Tuesday 23 October 2007 11:42:31 you wrote:
>>>>>>>>>> Hi Jim,
>>>>>>>>>>
>>>>>>>>>> Please look at the page 77 of SPRU581C.pdf, on the bit 4 INTRST of
>>>>>>>>>> RSTSRC. It says that "This bit must be asserted before another host
>>>>>>>>>> interrupt can be generated."
>>>>>>>>>>
>>>>>>>>>> Next, it would help to parse all the bits in the PCIIS (even if
>>>>>>>>>> they are all disabled in the PCIIEN) and clear them in the PCI ISR.
>>>>>>>>>>
>>>>>>>>>> Third, it is recommended to parse an interrupt source register (any
>>>>>>>>>> of them, not only the PCIIS) in a loop inside an ISR and clear any
>>>>>>>>>> set bits until the register becomes zero, e.g. for the PCI:
>>>>>>>>>>
>>>>>>>>>> volatile uint32 temp;
>>>>>>>>>>
>>>>>>>>>> while (temp = PCIIS) // this reads the PCIIS
>>>>>>>>>> {
>>>>>>>>>> test if bit[0], ..., [n] is set
>>>>>>>>>> if set, clear bit[0], ... [n] and perform the necessary
>>>>>>>>>> actions, e.g: if bit[3] HOSTSW was set then clear bit[4] INTRST in
>>>>>>>>>> RSTSRC }
>>>>>>>>>>
>>>>>>>>>> // PCIIS is clear now, exit the ISR
>>>>>>>>>>
>>>>>>>>>> Hope this helps,
>>>>>>>>>>
>>>>>>>>>> Andrew
>>>>>>>>>>
>>>>>>>>>>> 11a. ISR falls off cliff...sometimes.
>>>>>>>>>>> Posted by: "jim" j...@justsosoftware.com jiml8
>>>>>>>>>>> Date: Mon Oct 22, 2007 8:42 pm ((PDT))
>>>>>>>>>>>
>>>>>>>>>>> I have defined an ISR that responds to an interrupt on the PCI
>>>>>>>>>>> bus from a host. The current code for this ISR is this:
>>>>>>>>>>>
>>>>>>>>>>> interrupt void DMAtoHost(void)
>>>>>>>>>>> {
>>>>>>>>>>> unsigned int intval,*datastatusregister;
>>>>>>>>>>> puts("interrupted\n");
>>>>>>>>>>> datastatusregister = (unsigned int *)DATASTATUSREGISTER;
>>>>>>>>>>> intval = *datastatusregister & 0x04;
>>>>>>>>>>> if(intval == 4) { /* is this a host interrupt */
>>>>>>>>>>> intval = *datastatusregister;
>>>>>>>>>>> intval = intval & 0xfffffffb;
>>>>>>>>>>> *datastatusregister = intval; /* if so clear it */
>>>>>>>>>>> SEM_post(HostDMASem);
>>>>>>>>>>> puts("resetting PCIIS\n");
>>>>>>>>>>> }
>>>>>>>>>>> PCI_RSET(PCIIS,0x00000008);
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>> Now, DATASTATUSREGISTER is a memory location on the DSP SDRAM
>>>>>>>>>>> that I have taken over for tracking status information between my
>>>>>>>>>>> Linux driver and my DSP interface. Here I am testing a flag in
>>>>>>>>>>> that register to make sure that this interrupt really was set by
>>>>>>>>>>> the host (my linux driver both sets the interrupt and sets this
>>>>>>>>>>> flag to tell that it did it), and if so, I clear that location as
>>>>>>>>>>> well as clearing the PCIIS register.
>>>>>>>>>>>
>>>>>>>>>>> Basically, if this really was an interrupt from the host, this
>>>>>>>>>>> ISR posts to a semaphore called HostDMASem, and there is a task
>>>>>>>>>>> sleeping on this semaphore waiting to be told to transfer data.
>>>>>>>>>>>
>>>>>>>>>>> I have defined this ISR statically using the Code Composer
>>>>>>>>>>> configuration tool, and it is hooked to interrupt 13.
>>>>>>>>>>>
>>>>>>>>>>> I have tried various ways to set that semaphore; my current
>>>>>>>>>>> iteration has the semaphore defined statically using the
>>>>>>>>>>> configuration tool, and it is initialized as one of the very
>>>>>>>>>>> first things done in the main routine of the program when it
>>>>>>>>>>> starts, like this:
>>>>>>>>>>>
>>>>>>>>>>> SEM_new(HostDMASem,0);
>>>>>>>>>>>
>>>>>>>>>>> That main task then spawns a new task called buildall_tsk, which
>>>>>>>>>>> is the task which winds up sleeping on the semaphore. This task
>>>>>>>>>>> arrives at the semaphore through a subroutine call, like this:
>>>>>>>>>>>
>>>>>>>>>>> void WaitForDMA(void)
>>>>>>>>>>> {
>>>>>>>>>>> Bool semstatus;
>>>>>>>>>>> SEM_reset(HostDMASem,0);
>>>>>>>>>>> semstatus = SEM_pend(HostDMASem,SYS_FOREVER);
>>>>>>>>>>> if(!semstatus){puts("semaphore bombed\n");} else {puts("semaphore
>>>>>>>>>>> worked\n");}
>>>>>>>>>>> }
>>>>>>>>>>>
>>>>>>>>>>> My problem is this. When an interrupt from the host is set, this
>>>>>>>>>>> ISR invokes apparently correctly. However, sometimes when it
>>>>>>>>>>> reaches the end, it falls off the cliff (apparently the semaphore
>>>>>>>>>>> is not being recognized properly or some such) and nothing
>>>>>>>>>>> happens.
>>>>>>>>>>>
>>>>>>>>>>> Further, when the routine falls off the cliff, subsequent
>>>>>>>>>>> interrupts are apparently ignored; when the routine falls off the
>>>>>>>>>>> cliff, it doesn't get invoked again until I completely reset the
>>>>>>>>>>> system (which sometimes involves cycling power as well as
>>>>>>>>>>> restarting Code Composer.
>>>>>>>>>>>
>>>>>>>>>>> This seems to be erratic and I can't define specific conditions
>>>>>>>>>>> that cause it or not. I suspecte some initialization thing that
>>>>>>>>>>> Code Composer is doing, but I have no idea what.
>>>>>>>>>>>
>>>>>>>>>>> The card is a Spectrum Digital 6416 card.
>>>>>>>>>>>
>>>>>>>>>>> I am tearing my hair out over this, and trust me; I don't look
>>>>>>>>>>> good bald. Anyone here have any idea what is going on?
>>>>>>>>>>
>>>>>>>>>
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>>
>>>
>