/** @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; }
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); }
/** 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; }
/* * 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; }
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; }
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; }
//------------------------------------------------------------------------------- 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; }
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; }