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]

serial line ISR problem -- again:(


Hi,

I still have a problem with my ISR, which should simply act when signal
transition on DCD pin of COM1 serial port (i386 PC). I'm 100% signal
is 200ms 'high', and then 800ms 'low'. Tested with both linux, freebsd,
qnx.

The worst is that this code used to work on my another PC machine:(,
but only on _that_ one...

Please, help, what do I do wrong?

-- 
Piotr Trojanek
#include <cyg/kernel/kapi.h>
#include <cyg/hal/hal_arch.h>
#include <stdio.h>

volatile unsigned int c;

cyg_interrupt intr;
cyg_handle_t intr_handle;

/*
ttyS00 at 0x03f8 (irq = 4) is a 16550A
ttyS01 at 0x02f8 (irq = 3) is a 16550A
*/

#define	COM_IRQ		4
#define	COM_ADDR	0x3f8

#define CYGNUM_HAL_PRI_HIGH 0

#define PRODUCER_PRIORITY   0
#define PRODUCER_STACKSIZE  CYGNUM_HAL_STACK_SIZE_TYPICAL

unsigned char producer_stack[PRODUCER_STACKSIZE];
cyg_handle_t producer_handle;
cyg_thread producer_thread;

cyg_sem_t data_ready;

volatile cyg_uint8 ier;

cyg_uint32 isr(
	cyg_vector_t vector,
	cyg_addrword_t data)
{
	/* do the work... */
	int i;
	c++;

	/* reenable IRQ on UART */
	for (i = 0; i < 8; i++)
		HAL_READ_UINT8(COM_ADDR + i, ier);
	cyg_interrupt_acknowledge( vector );
	return CYG_ISR_HANDLED;
}

void dsr(
	cyg_vector_t vector,
	cyg_ucount32 count,
	cyg_addrword_t data)
{
	/* 0x08 means transition from low go high */
	if (ier == 0x08) {
       		cyg_semaphore_post( &data_ready );
	}
}

void
producer(cyg_addrword_t data)
{
	for (;;)
	{
		cyg_semaphore_wait( &data_ready );
		printf("c = %d\n", c);
	}
}

int dcd_main( void)
{
	cyg_vector_t intr_vector = CYGNUM_HAL_ISR_MIN + COM_IRQ;
	cyg_priority_t intr_priority = CYGNUM_HAL_PRI_HIGH;
	int in_use;

	cyg_semaphore_init( &data_ready, 0 );

	HAL_INTERRUPT_IN_USE( intr_vector, in_use );
	printf("in_use(%d) = %d\n", intr_vector, in_use);

	cyg_thread_create(PRODUCER_PRIORITY, &producer, 0, "producer",
		producer_stack, PRODUCER_STACKSIZE,
		&producer_handle, &producer_thread);
	cyg_thread_resume(producer_handle);
	
	cyg_interrupt_create(
			intr_vector,
			intr_priority,
			0,
			isr,
			dsr,
			&intr_handle,
			&intr);
	
	// Attach the interrupt created to the vector.
	cyg_interrupt_attach( intr_handle );

	// Unmask the interrupt we just configured.
	cyg_interrupt_unmask( intr_vector );

	/* get acces to Interrupt Enable Register */
	HAL_READ_UINT8 (COM_ADDR + 3, ier);
	HAL_WRITE_UINT8 (COM_ADDR + 3, ier & 0x7f);

	/* make UART interrupt on DCD transition */
	HAL_WRITE_UINT8 (COM_ADDR + 1, 0x08);

	HAL_INTERRUPT_IN_USE( intr_vector, in_use );
	printf("in_use(%d) = %d\n", intr_vector, in_use);

	printf("cyg_scheduler_start()\n");
	cyg_scheduler_start();
}

externC void
cyg_start( void )
{
	dcd_main();
}

-- 
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]