This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: AW: help needed: interrupt + semaphore


FWIW, I start a main thread and do all interrupt enabling in the initial
part of the thread procedure. This will avoid any problems with limitations
of what you can do before the scheduler is started. Note (as Bart points
out) I do not find it necessary to call cyg_scheduler_start() at the end of
cyg_user_start().

WRT the comment about continuously interrupting - AFAICT, if
cyg_interrupt_mask() is called at the beginning of the ISR, EINT1 interrupts
will no longer be active, so this should not happen as
cyg_interrupt_unmask() is not called until the DSR. So the DSR should
eventually run, assuming everything else is OK.

Here are the important bits of the code for your implementation (DSR and ISR
as before). I have put additional points in /****><****/ comments. I would
try this and initially see if you can get to the first line of
main_thread() - at least this will prove that the scheduler is running.

<code>
#define MAIN_THREAD_PRIORITY      4     /* On this scale 0 - 31: 0 lowest,
31 highest */
#define MAIN_THREAD_STACK_SIZE 4096     /* ...or the minimum you can get
away with */

/* Resource for the thread */
static cyg_thread main_thread_rsrc;

/* Handle for the thread */
static cyg_handle_t main_thread_handle;

/* Stack for the thread */
static char main_thread_stack[MAIN_THREAD_STACK_SIZE];

/* Entry point */
static cyg_thread_entry_t main_thread;

void cyg_user_start(void)
{
    /* Create thread */
    cyg_thread_create(ECOS_MIN_PRIORITY - MAIN_THREAD_PRIORITY,   /*
Priority */
                      main_thread,                                /* Entry
point */
                      (cyg_addrword_t)NULL,                       /*
Parameters - you may want to put something here */
                      "main",                                     /* Name */
                      (void *)main_thread_stack,                  /*
Allocated stack space */
                      MAIN_THREAD_STACK_SIZE,                     /* Stack
size */
                      &main_thread_handle,                        /* Ptr. to
Thread Handle (passed back) */
                      &main_thread_rsrc);                         /* Ptr. to
Thread Resource */

    /* Start it */
    cyg_thread_resume(main_thread_handle);                        /* And
we're off... */
}

static void main_thread(cyg_addrword_t arg)
{
    cyg_semaphore_init(&semEINT1, 0);

    cyg_interrupt_create(CYGNUM_HAL_INTERRUPT_EINT1,
                         6,                     // Priority - unused
                         1,   //  Data item passed to interrupt handler
                         intE1ISR,
                         intDSR,
                         &hEInt1,
                         &iEInt1);
    cyg_interrupt_attach(hEInt1);

    /****> is this necessary?? <****/
    //cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EINT1);

    /****> You may need to clear any pending interrupts at the source here
<****/

    /* Enable the interrupt */
    cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EINT1);

    /****>
     * You don't need to do this, as this is what
     * cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EINT1) does.
     * Note it could be dangerous to manipulate low-level interrupt
registers
     * directly in case they are shadowed somehow by the OS. I don't think
they
     * are in this case, but as a rule, I wouldn't do it.
     * In any case shouldn't INTMR1 cast as 'volatile cyg_uint32*', not
     * 'volatile unsigned char *'?
     <****/
    //*(volatile unsigned char *)INTMR1 |= 0x20;

    for (;;)
    {
        /* Background tasks */
    }

    return; /* Never reached */
}
</code>

Robert Cragie, Design Engineer
_______________________________________________________________
Jennic Ltd, Furnival Street, Sheffield, S1 4QT,  UK
http://www.jennic.com  Tel: +44 (0) 114 281 2655

> -----Original Message-----
> From: ecos-discuss-owner@sources.redhat.com
> [mailto:ecos-discuss-owner@sources.redhat.com]On Behalf Of Bart Veer
> Sent: 20 August 2002 22:57
> To: thomas.edelmann@siemens.com
> Cc: ecos-discuss@sources.redhat.com
> Subject: Re: AW: [ECOS] help needed: interrupt + semaphore
>
>
> >>>>> "Gary" == Gary Thomas <gthomas@ecoscentric.com> writes:
>
>     Gary> On Tue, 2002-08-20 at 04:56, Edelmann Thomas wrote:
>     >> But this doesn't solve the problem. The ISR is always called,
>     >> but then nothing happens, no DSR, no INTThread.
>     >>
>     >> Knows someone something else?
>
>     Gary> You need to start the scheduler, otherwise nothing else will
>     Gary> happen - the threads won't run and the DSR will never be
>     Gary> called.
>
> Not quite true. See infra/current/src/startup.cxx, there is an
> implicit call to Cyg_Scheduler::start() once cyg_user_start() has
> returned, assuming the kernel is present. You can start the scheduler
> inside cyg_user_start() if you really want to, but typical
> applications are not going to gain anything.
>
> However you are right that cyg_user_start() must not enable
> interrupts - and at this point there may well be a clock interrupt
> pending, not to mention some other interrupts. I am not quite sure
> just what could go wrong if DSRs started running that early.
>
> I assume the hardware is some sort of edb7xxx variant, and I am not
> really familiar with that hardware. My first guess would be that the
> FPGA hardware (or possibly some other interrupt source) is
> interrupting continuously, so the system is spending all its time
> running ISRs and never gets a chance to run a DSR or thread. Possibly
> the interrupt mask hardware or HAL macros are misbehaving. A logic
> probe may prove helpful here, as would a gdb breakpoint on the kernel
> function interrupt_end().
>
> >>>>> "Robert" == Robert Cragie <rcc@jennic.com> writes:
>
>     Robert> I do it like this and it works for me:
>
>     Robert> static cyg_uint32 intE1ISR(cyg_vector_t vector,
> cyg_addrword_t data)
>     Robert> {
>     Robert> 	cyg_interrupt_mask(vector);
>     Robert> 	cyg_interrupt_acknowledge(vector);
>     Robert> 	return CYG_ISR_CALL_DSR;
>     Robert> }
>
>     Robert> static void intDSR(cyg_vector_t vector, cyg_ucount32
> count, cyg_addrword_t data)
>     Robert> {
>     Robert>     cyg_semaphore_post(&semEINT1);
>     Robert>     cyg_interrupt_unmask(vector);
>     Robert> }
>
>     Robert> I also commented that cyg_interrupt_acknowledge() must be
>     Robert> called in the ISR - the docs. seem to say this must be
>     Robert> done.
>
> The effect of cyg_interrupt_acknowledge() is somewhat
> hardware-specific, but typically it tells the interrupt controller
> that the interrupt has been processed so the appropriate bit in the
> interrupts-pending register can be cleared. The exact interaction
> between the pending and mask registers depends on the hardware.
> Calling cyg_interrupt_acknowledge() in the ISR is nearly always the
> right thing to do.
>
> Re. the mask and unmask, that depends on the device and the
> application. If you can handle another interrupt for the same device
> straightaway, e.g. because bytes arrive one at a time and there is
> plenty of buffer space left, then there is no need to mask the
> interrupt at all. If you cannot handle another interrupt until after
> the DSR, mask the interrupt source in the ISR and unmask it at the end
> of the DSR. If some work is needed at thread level, mask in the ISR
> and unmask in the thread.
>
> Bart
>
> --
> Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
> and search the list archive: http://sources.redhat.com/ml/ecos-discuss
>
>


-- 
Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
and search the list archive: http://sources.redhat.com/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]