Beispiel #1
0
/** @Function Description:  This function registers an interrupt handler. 
  * If the function is succesful, then the requested interrupt will be enabled
  * upon return. Registering a NULL handler will disable the interrupt.
  *
  * @API Type:              External
  * @param ic_id            Interrupt controller ID
  * @param irq              IRQ ID number
  * @param isr              Pointer to interrupt service routine
  * @param isr_context      Opaque pointer passed to ISR
  * @param flags            
  * @return                 0 if successful, else error (-1)
  */
int alt_iic_isr_register(alt_u32 ic_id, alt_u32 irq, alt_isr_func isr, 
  void *isr_context, void *flags)
{
  int rc = -EINVAL;  
  int id = irq;             /* IRQ interpreted as the interrupt ID. */
  alt_irq_context status;

  if (id < ALT_NIRQ)
  {
    /* 
     * interrupts are disabled while the handler tables are updated to ensure
     * that an interrupt doesn't occur while the tables are in an inconsistant
     * state.
     */

    status = alt_irq_disable_all();

    alt_irq[id].handler = isr;
    alt_irq[id].context = isr_context;

    rc = (isr) ? alt_ic_irq_enable(ic_id, id) : alt_ic_irq_disable(ic_id, id);

    alt_irq_enable_all(status);
  }

  return rc; 
}
Beispiel #2
0
static void	handle_dma0_interrupt(void* context)
{
	alt_irq_context        cpu_sr;
	dma_context_state *dma_context_int = (dma_context_state *)context;

	dma_context_int->dma_done = 0;

	// relaunch dma transfer
	alt_dma_txchan_send(dma_context_int->txchan, 
						(void *)dma_context_int->src, 
						dma_context_int->len, 
						NULL, 
						NULL);

	alt_dma_rxchan_prepare(dma_context_int->rxchan, 
						   (void *)dma_context_int->dst, 
						   dma_context_int->len, 
						   dma_context_int->done_callback, 
						   NULL);

	cpu_sr = alt_irq_disable_all();
	alt_irq_enable_all(cpu_sr);

	OSSemPost(SEM_DMA0);
}
static void alt_avalon_timer_sc_irq (void* base, alt_u32 id)
#endif
{
  alt_irq_context cpu_sr;

  /* clear the interrupt */
  IOWR_ALTERA_AVALON_TIMER_STATUS (base, 0);

  /*
   * Dummy read to ensure IRQ is negated before the ISR returns.
   * The control register is read because reading the status
   * register has side-effects per the register map documentation.
   */
  IORD_ALTERA_AVALON_TIMER_CONTROL (base);

  /* ALT_LOG - see altera_hal/HAL/inc/sys/alt_log_printf.h */
  ALT_LOG_SYS_CLK_HEARTBEAT();

  /*
   * Notify the system of a clock tick. disable interrupts
   * during this time to safely support ISR preemption
   */
  cpu_sr = alt_irq_disable_all();
  alt_tick ();
  alt_irq_enable_all(cpu_sr);
}
Beispiel #4
0
/** This function is a re-implementation of the Altera provided function.
 * The function is re-implemented to prevent it from enabling an interrupt
 * when it is registered. Interrupts should only be enabled after the FreeRTOS.org
 * kernel has its scheduler started so that contexts are saved and switched 
 * correctly.
 */
int alt_irq_register( alt_u32 id, void* context, void (*handler)(void*, alt_u32) )
{
	int rc = -EINVAL;  
	alt_irq_context status;

	if (id < ALT_NIRQ)
	{
		/* 
		 * interrupts are disabled while the handler tables are updated to ensure
		 * that an interrupt doesn't occur while the tables are in an inconsistent
		 * state.
		 */
	
		status = alt_irq_disable_all ();
	
		alt_irq[id].handler = handler;
		alt_irq[id].context = context;
	
		rc = (handler) ? alt_irq_enable (id): alt_irq_disable (id);
	
		/* alt_irq_enable_all(status); This line is removed to prevent the interrupt from being immediately enabled. */
	}
    
	return rc; 
}
Beispiel #5
0
/*
 * alt_adc_irq()
 *
 * Interrupt handler for the altera modular adc.
 */
static void alt_adc_irq(void *context)
{
    alt_modular_adc_dev *dev = (alt_modular_adc_dev *) context;
    alt_irq_context cpu_sr = 0;

	if(NULL != dev)
	{
	    cpu_sr = alt_irq_disable_all();
		/* 
		* Other interrupts are explicitly disabled if callbacks
		* are registered because there is no guarantee that they are 
		* pre-emption-safe. This allows the driver to support 
		* interrupt pre-emption.
		*/
		if(dev->callback) 
		{
			dev->callback (dev->callback_context);
		}
    
		/* clear the IRQ status */
		adc_clear_interrupt_status(dev->sample_store_base);
	    
		alt_irq_enable_all(cpu_sr);
	}
	
    return;
}
Beispiel #6
0
void alt_alarm_stop (alt_alarm* alarm)
{
  alt_irq_context irq_context;

  irq_context = alt_irq_disable_all();
  alt_llist_remove (&alarm->llist);
  alt_irq_enable_all (irq_context);
}
void disable_irq(void)
{
  if(INT_Enabled)
  {
    status=alt_irq_disable_all();
    INT_Enabled=0;
  }
}
//------------------------------------------------------------------------------
void target_enableGlobalInterrupt(BOOL fEnable_p)
{
static alt_irq_context  irq_context = 0;
static int              iLockCount = 0;

    if (fEnable_p != FALSE)
    {   // restore interrupts
        if (--iLockCount == 0)
            alt_irq_enable_all(irq_context);
    }
    else
    {   // disable interrupts
        if (iLockCount == 0)
            irq_context = alt_irq_disable_all();

        iLockCount++;
    }
}
void  PUBLIC  ShbTgtEnableGlobalInterrupt(BYTE fEnable_p)
{
static alt_irq_context  irq_context = 0; 
static int              iLockCount = 0;

    if (fEnable_p != FALSE)
    {   // restore interrupts
        if (--iLockCount == 0)
        {
            alt_irq_enable_all(irq_context);
        }
    }
    else
    {   // disable interrupts
        if (iLockCount == 0)
        {
            irq_context = alt_irq_disable_all();
        }
        iLockCount++;
    }
}
// Returns the first item, remember to free its memory!
N2H_isr_info* n2h_isr_fifo_pop (N2H_isr_fifo* fifo)
{
  N2H_isr_info* temp;

  if(fifo->size < 1)
    {
      return NULL;
    }
  
  // Prevent ISR from messing with fifo
  alt_irq_context cntx = alt_irq_disable_all();  
  {
    temp = fifo->root;
    fifo->root = temp->next;
    fifo->size--;
  }
  alt_irq_enable_all(cntx);
  
  temp->next = NULL;
  return temp;
}
Beispiel #11
0
caddr_t ALT_SBRK (int incr)
{ 
  alt_irq_context context;
  char *prev_heap_end; 

  context = alt_irq_disable_all();

  /* Always return data aligned on a word boundary */
  heap_end = (char *)(((unsigned int)heap_end + 3) & ~3);

#ifdef ALT_MAX_HEAP_BYTES
  /*  
   * User specified a maximum heap size.  Return -1 if it would
   * be exceeded by this sbrk call.
   */
  if (((heap_end + incr) - __alt_heap_start) > ALT_MAX_HEAP_BYTES) {
    alt_irq_enable_all(context);
    return (caddr_t)-1;
  }
#else
  if ((heap_end + incr) > __alt_heap_limit) {
    alt_irq_enable_all(context);
    return (caddr_t)-1;
  }
#endif

  prev_heap_end = heap_end; 
  heap_end += incr; 

#ifdef ALT_STACK_CHECK
  /*
   * If the stack and heap are contiguous then extending the heap reduces the
   * space available for the stack.  If we are still using the default stack
   * then adjust the stack limit to note this, while checking for stack
   * pointer overflow. 
   * If the stack limit isn't pointing at the top of the heap then the code
   * is using a different stack so none of this needs to be done.
   */

  if (alt_stack_limit() == prev_heap_end)
  {
    if (alt_stack_pointer() <= heap_end)
      alt_report_stack_overflow();

    alt_set_stack_limit(heap_end);
  }

#ifdef ALT_EXCEPTION_STACK
  /*
   * If we are executing from the exception stack then compare against the
   * stack we switched away from as well.  The exception stack is a fixed
   * size so doesn't need to be checked.
   */

  if (alt_exception_old_stack_limit == prev_heap_end)
  {
    if (alt_exception_old_stack_limit <= heap_end)
      alt_report_stack_overflow();

    alt_exception_old_stack_limit = heap_end;
  }
#endif

#endif

  alt_irq_enable_all(context);

  return (caddr_t) prev_heap_end; 
} 
Beispiel #12
0
//-------------------------------------------------------------------------------
int alt_avn_jtag_uart_read(alt_avn_jtag_uart_state* sp, 
		char * buffer, int space, int flags)
{
	char * ptr = buffer;

	alt_irq_context context;
	unsigned int n;

	/*
	 * When running in a multi threaded environment, obtain the "read_lock"
	 * semaphore. This ensures that reading from the device is thread-safe.
	 */
	ALT_SEM_PEND (sp->read_lock, 0);

	while (space > 0)
	{
		unsigned int in, out;

		/* Read as much data as possible */
		do
		{
			in  = sp->rx_in;
			out = sp->rx_out;

			if (in >= out)
				n = in - out;
			else
				n = ALTERA_AVALON_JTAG_UART_BUF_LEN - out;

			if (n == 0)
				break; /* No more data available */

			if (n > space)
				n = space;

			memcpy(ptr, sp->rx_buf + out, n);
			ptr   += n;
			space -= n;

			sp->rx_out = (out + n) % ALTERA_AVALON_JTAG_UART_BUF_LEN;
		}
		while (space > 0);

		/* If we read any data then return it */
		if (ptr != buffer)
			break;

		/* If in non-blocking mode then return error */
		if (flags & O_NONBLOCK)
			break;

		/* OS Present: Pend on a flag if the OS is running, otherwise spin */
		if(OSRunning == OS_TRUE) {
			/*
			 * When running in a multi-threaded mode, we pend on the read event
			 * flag set and timeout event flag set in the isr. This avoids wasting CPU
			 * cycles waiting in this thread, when we could be doing something more
			 * profitable elsewhere.
			 */
			ALT_FLAG_PEND (sp->events,
					ALT_JTAG_UART_READ_RDY | ALT_JTAG_UART_TIMEOUT,
					OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
					0);
		}
		else {
			/* Spin until more data arrives or until host disconnects */
			while (in == sp->rx_in && sp->host_inactive < sp->timeout)
				;
		}


		if (in == sp->rx_in)
			break;
	}

	/*
	 * Now that access to the circular buffer is complete, release the read
	 * semaphore so that other threads can access the buffer.
	 */

	ALT_SEM_POST (sp->read_lock);

	if (ptr != buffer)
	{
		/* If we read any data then there is space in the buffer so enable interrupts */
		context = alt_irq_disable_all();
		sp->irq_enable |= ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK;
		IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable);
		alt_irq_enable_all(context);
	}

	if (ptr != buffer)
		return ptr - buffer;
	else if (flags & O_NONBLOCK)
		return -EWOULDBLOCK;
	else
		return -EIO;
}
Beispiel #13
0
int alt_avn_jtag_uart_write(alt_avn_jtag_uart_state* sp, 
		const char * ptr, int count, int flags)
{
	/* Remove warning at optimisation level 03 by seting out to 0 */
	unsigned int in, out=0;
	unsigned int n;
	alt_irq_context context;

	const char * start = ptr;

	/*
	 * When running in a multi threaded environment, obtain the "write_lock"
	 * semaphore. This ensures that writing to the device is thread-safe.
	 */
	ALT_SEM_PEND (sp->write_lock, 0);

	do
	{
		/* Copy as much as we can into the transmit buffer */
		while (count > 0)
		{
			/* We need a stable value of the out pointer to calculate the space available */
			in  = sp->tx_in;
			out = sp->tx_out;

			if (in < out)
				n = out - 1 - in;
			else if (out > 0)
				n = ALTERA_AVALON_JTAG_UART_BUF_LEN - in;
			else
				n = ALTERA_AVALON_JTAG_UART_BUF_LEN - 1 - in;

			if (n == 0)
				break;

			if (n > count)
				n = count;

			memcpy(sp->tx_buf + in, ptr, n);
			ptr   += n;
			count -= n;

			sp->tx_in = (in + n) % ALTERA_AVALON_JTAG_UART_BUF_LEN;
		}

		/*
		 * If interrupts are disabled then we could transmit here, we only need 
		 * to enable interrupts if there is no space left in the FIFO
		 *
		 * For now kick the interrupt routine every time to make it transmit 
		 * the data 
		 */
		context = alt_irq_disable_all();
		sp->irq_enable |= ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK;
		IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable);
		alt_irq_enable_all(context);

		/* 
		 * If there is any data left then either return now or block until 
		 * some has been sent 
		 */
		/* consider: test whether there is anything there while doing this and delay for at most 2s. */
		if (count > 0)
		{
			if (flags & O_NONBLOCK)
				break;

			/* OS Present: Pend on a flag if the OS is running, otherwise spin */
			if(OSRunning == OS_TRUE) {
				/*
				 * When running in a multi-threaded mode, we pend on the write event
				 * flag set or the timeout flag in the isr. This avoids wasting CPU
				 * cycles waiting in this thread, when we could be doing something
				 * more profitable elsewhere.
				 */
				ALT_FLAG_PEND (sp->events,
						ALT_JTAG_UART_WRITE_RDY | ALT_JTAG_UART_TIMEOUT,
						OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
						0);
			}
			else {
				/*
				 * OS not running: Wait for data to be removed from buffer.
				 * Once the interrupt routine has removed some data then we
				 * will be able to insert some more.
				 */
				while (out == sp->tx_out && sp->host_inactive < sp->timeout)
					;
			}

			if (out == sp->tx_out)
				break;
		}
	}
	while (count > 0);

	/*
	 * Now that access to the circular buffer is complete, release the write
	 * semaphore so that other threads can access the buffer.
	 */
	ALT_SEM_POST (sp->write_lock);

	if (ptr != start)
		return ptr - start;
	else if (flags & O_NONBLOCK)
		return -EWOULDBLOCK;
	else
		return -EIO; /* Host not connected */
}
int fifoed_avalon_uart_write (fifoed_avalon_uart_state* sp, const char* ptr, int len, int flags)
{
  alt_irq_context context;
  int             no_block;
  alt_u32         next;
  int count                = len;

  /* 
   * Construct a flag to indicate whether the device is being accessed in
   * blocking or non-blocking mode.
   */

  no_block = (flags & O_NONBLOCK);

  /*
   * When running in a multi threaded environment, obtain the "write_lock"
   * semaphore. This ensures that writing to the device is thread-safe.
   */

  ALT_SEM_PEND (sp->write_lock, 0);

  /*
   * Loop transferring data from the input buffer to the transmit circular
   * buffer. The loop is terminated once all the data has been transferred,
   * or, (if in non-blocking mode) the buffer becomes full.
   */

  while (count)
  {
    /* Determine the next slot in the buffer to access */

    next = (sp->tx_end + 1) & FIFOED_AVALON_UART_BUF_MSK;

    /* block waiting for space if necessary */

    if (next == sp->tx_start)
    {
      if (no_block)
      {
        /* Set errno to indicate why this function returned early */
 
        ALT_ERRNO = EWOULDBLOCK;
        break;
      }
      else
      {
        /* Block waiting for space in the circular buffer */

        /* First, ensure transmit interrupts are enabled to avoid deadlock */

        context = alt_irq_disable_all ();
        sp->ctrl |= (FIFOED_AVALON_UART_CONTROL_TRDY_MSK |
                        FIFOED_AVALON_UART_CONTROL_DCTS_MSK);
        IOWR_FIFOED_AVALON_UART_CONTROL(sp->base, sp->ctrl);
        alt_irq_enable_all (context);

        /* wait for space to come free */

        do
        {
          /*
           * When running in a multi-threaded mode, we pend on the write event 
           * flag set in the interrupt service routine. This avoids wasting CPU
           * cycles waiting in this thread, when we could be doing something
           * more profitable elsewhere.
           */

          ALT_FLAG_PEND (sp->events,
                         ALT_UART_WRITE_RDY,
                         OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
                         0);
        }
        while ((next == sp->tx_start));
      }
    }

    count--;

    /* Add the next character to the transmit buffer */

    sp->tx_buf[sp->tx_end] = *ptr++;
    sp->tx_end = next;
  }

  /*
   * Now that access to the circular buffer is complete, release the write
   * semaphore so that other threads can access the buffer.
   */

  ALT_SEM_POST (sp->write_lock);

  /* 
   * Ensure that interrupts are enabled, so that the circular buffer can 
   * drain.
   */

  context = alt_irq_disable_all ();
  sp->ctrl |= FIFOED_AVALON_UART_CONTROL_TRDY_MSK |
                 FIFOED_AVALON_UART_CONTROL_DCTS_MSK;
  IOWR_FIFOED_AVALON_UART_CONTROL(sp->base, sp->ctrl);
  alt_irq_enable_all (context);

  /* return the number of bytes written */

  return (len - count);
}
int fifoed_avalon_uart_read (fifoed_avalon_uart_state* sp, char* ptr, int len, int flags)
{
  alt_irq_context context;
  int             block;
  alt_u32         next;

  int count                = 0;

  /* 
   * Construct a flag to indicate whether the device is being accessed in
   * blocking or non-blocking mode.
   */

  block = !(flags & O_NONBLOCK);

  /*
   * When running in a multi threaded environment, obtain the "read_lock"
   * semaphore. This ensures that reading from the device is thread-safe.
   */

  ALT_SEM_PEND (sp->read_lock, 0);

  /*
   * Calculate which slot in the circular buffer is the next one to read
   * data from.
   */

  next = (sp->rx_start + 1) & FIFOED_AVALON_UART_BUF_MSK;

  /*
   * Loop, copying data from the circular buffer to the destination address
   * supplied in "ptr". This loop is terminated when the required number of
   * bytes have been read. If the circular buffer is empty, and no data has
   * been read, then the loop will block (when in blocking mode).
   *
   * If the circular buffer is empty, and some data has already been 
   * transferred, or the device is being accessed in non-blocking mode, then
   * the loop terminates without necessarily reading all the requested data.
   */

  do
  {
    /*
     * Read the required amount of data, until the circular buffer runs
     * empty
     */

    while ((count < len) && (sp->rx_start != sp->rx_end))
    {
      count++;
      *ptr++ = sp->rx_buf[sp->rx_start];
      
      sp->rx_start = (++sp->rx_start) & FIFOED_AVALON_UART_BUF_MSK;
    }

    /*
     * If no data has been transferred, the circular buffer is empty, and
     * this is not a non-blocking access, block waiting for data to arrive.
     */

    if (!count && (sp->rx_start == sp->rx_end))
    {
      if (!block)
      {
        /* Set errno to indicate the reason we're not returning any data */

        ALT_ERRNO = EWOULDBLOCK;
        break;
      }
      else
      {
       /* Block waiting for some data to arrive */

       /* First, ensure read interrupts are enabled to avoid deadlock */

       context = alt_irq_disable_all ();
       sp->ctrl |= FIFOED_AVALON_UART_CONTROL_RRDY_MSK;
       IOWR_FIFOED_AVALON_UART_CONTROL(sp->base, sp->ctrl);
       alt_irq_enable_all (context);

       /*
        * When running in a multi-threaded mode, we pend on the read event 
        * flag set in the interrupt service routine. This avoids wasting CPU
        * cycles waiting in this thread, when we could be doing something more 
        * profitable elsewhere.
        */

       ALT_FLAG_PEND (sp->events,
                      ALT_UART_READ_RDY,
                      OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
                      0);
      }
    }
  }
  while (!count && len);

  /*
   * Now that access to the circular buffer is complete, release the read
   * semaphore so that other threads can access the buffer.
   */

  ALT_SEM_POST (sp->read_lock);

  /*
   * Ensure that interrupts are enabled, so that the circular buffer can
   * re-fill.
   */

  context = alt_irq_disable_all ();
  sp->ctrl |= FIFOED_AVALON_UART_CONTROL_RRDY_MSK;
  IOWR_FIFOED_AVALON_UART_CONTROL(sp->base, sp->ctrl);
  alt_irq_enable_all (context);

  /* Return the number of bytes read */

  return count;
}