void arm_cpu_boot(int cpu) { /* Enable SMP cache coherency for the CPU */ arm_enable_smp(cpu); #ifdef CONFIG_ARCH_FPU /* Initialize the FPU */ arm_fpuconfig(); #endif /* Initialize the Generic Interrupt Controller (GIC) for CPUn (n != 0) */ arm_gic_initialize(); #ifdef CONFIG_ARCH_LOWVECTORS /* If CONFIG_ARCH_LOWVECTORS is defined, then the vectors located at the * beginning of the .text region must appear at address at the address * specified in the VBAR. There are two ways to accomplish this: * * 1. By explicitly mapping the beginning of .text region with a page * table entry so that the virtual address zero maps to the beginning * of the .text region. VBAR == 0x0000:0000. * * 2. Set the Cortex-A5 VBAR register so that the vector table address * is moved to a location other than 0x0000:0000. * * The second method is used by this logic. */ /* Set the VBAR register to the address of the vector table */ DEBUGASSERT((((uintptr_t)&_vector_start) & ~VBAR_MASK) == 0); cp15_wrvbar((uint32_t)&_vector_start); #endif /* CONFIG_ARCH_LOWVECTORS */ #ifndef CONFIG_SUPPRESS_INTERRUPTS /* And finally, enable interrupts */ (void)up_irq_enable(); #endif /* The next thing that we expect to happen is for logic running on CPU0 * to call up_cpu_start() which generate an SGI and a context switch to * the configured NuttX IDLE task. */ for (; ; ) { asm("WFI"); } }
void up_irqinitialize(void) { uint32_t regaddr; int i; /* Disable all interrupts */ putreg32(0xffffffff, ARMV6M_NVIC_ICER); /* Set all interrupts (and exceptions) to the default priority */ putreg32(DEFPRIORITY32, ARMV6M_SYSCON_SHPR2); putreg32(DEFPRIORITY32, ARMV6M_SYSCON_SHPR3); /* Now set all of the interrupt lines to the default priority */ for (i = 0; i < 8; i++) { regaddr = ARMV6M_NVIC_IPR(i); putreg32(DEFPRIORITY32, regaddr); } /* currents_regs is non-NULL only while processing an interrupt */ CURRENT_REGS = NULL; /* Attach the SVCall and Hard Fault exception handlers. The SVCall * exception is used for performing context switches; The Hard Fault * must also be caught because a SVCall may show up as a Hard Fault * under certain conditions. */ irq_attach(SAM_IRQ_SVCALL, up_svcall); irq_attach(SAM_IRQ_HARDFAULT, up_hardfault); /* Attach all other processor exceptions (except reset and sys tick) */ #ifdef CONFIG_DEBUG_FEATURES irq_attach(SAM_IRQ_NMI, sam_nmi); irq_attach(SAM_IRQ_PENDSV, sam_pendsv); irq_attach(SAM_IRQ_RESERVED, sam_reserved); #endif sam_dumpnvic("initial", NR_IRQS); #ifndef CONFIG_SUPPRESS_INTERRUPTS /* And finally, enable interrupts */ up_irq_enable(); #endif }
void up_irqinitialize(void) { uintptr_t regaddr; #if defined(CONFIG_DEBUG_SYMBOLS) && !defined(CONFIG_ARMV7M_USEBASEPRI) uint32_t regval; #endif int nintlines; int i; /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt * lines that the NVIC supports, defined in groups of 32. That is, * the total number of interrupt lines is up to (32*(INTLINESNUM+1)). * * 0 -> 32 interrupt lines, 1 enable register, 8 priority registers * 1 -> 64 " " " ", 2 enable registers, 16 priority registers * 2 -> 96 " " " ", 3 enable regsiters, 24 priority registers * ... */ nintlines = (getreg32(NVIC_ICTR) & NVIC_ICTR_INTLINESNUM_MASK) + 1; /* Disable all interrupts. There are nintlines interrupt enable * registers. */ for (i = nintlines, regaddr = NVIC_IRQ0_31_CLEAR; i > 0; i--, regaddr += 4) { putreg32(0xffffffff, regaddr); } /* Make sure that we are using the correct vector table. The default * vector address is 0x0000:0000 but if we are executing code that is * positioned in SRAM or in external FLASH, then we may need to reset * the interrupt vector so that it refers to the table in SRAM or in * external FLASH. */ putreg32((uint32_t)_vectors, NVIC_VECTAB); #ifdef CONFIG_ARCH_RAMVECTORS /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ up_ramvec_initialize(); #endif /* Set all interrupts (and exceptions) to the default priority */ putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); /* Now set all of the interrupt lines to the default priority. There are * nintlines * 8 priority registers. */ for (i = (nintlines << 3), regaddr = NVIC_IRQ0_3_PRIORITY; i > 0; i--, regaddr += 4) { putreg32(DEFPRIORITY32, regaddr); } /* currents_regs is non-NULL only while processing an interrupt */ CURRENT_REGS = NULL; /* Attach the SVCall and Hard Fault exception handlers. The SVCall * exception is used for performing context switches; The Hard Fault * must also be caught because a SVCall may show up as a Hard Fault * under certain conditions. */ irq_attach(STM32_IRQ_SVCALL, up_svcall, NULL); irq_attach(STM32_IRQ_HARDFAULT, up_hardfault, NULL); /* Set the priority of the SVCall interrupt */ #ifdef CONFIG_ARCH_IRQPRIO /* up_prioritize_irq(STM32_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */ #endif #ifdef CONFIG_ARMV7M_USEBASEPRI stm32_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); #endif /* If the MPU is enabled, then attach and enable the Memory Management * Fault handler. */ #ifdef CONFIG_ARM_MPU irq_attach(STM32_IRQ_MEMFAULT, up_memfault, NULL); up_enable_irq(STM32_IRQ_MEMFAULT); #endif /* Attach all other processor exceptions (except reset and sys tick) */ #ifdef CONFIG_DEBUG_FEATURES irq_attach(STM32_IRQ_NMI, stm32_nmi, NULL); #ifndef CONFIG_ARM_MPU irq_attach(STM32_IRQ_MEMFAULT, up_memfault, NULL); #endif irq_attach(STM32_IRQ_BUSFAULT, stm32_busfault, NULL); irq_attach(STM32_IRQ_USAGEFAULT, stm32_usagefault, NULL); irq_attach(STM32_IRQ_PENDSV, stm32_pendsv, NULL); irq_attach(STM32_IRQ_DBGMONITOR, stm32_dbgmonitor, NULL); irq_attach(STM32_IRQ_RESERVED, stm32_reserved, NULL); #endif stm32_dumpnvic("initial", STM32_IRQ_NIRQS); /* If a debugger is connected, try to prevent it from catching hardfaults. * If CONFIG_ARMV7M_USEBASEPRI, no hardfaults are expected in normal * operation. */ #if defined(CONFIG_DEBUG_SYMBOLS) && !defined(CONFIG_ARMV7M_USEBASEPRI) regval = getreg32(NVIC_DEMCR); regval &= ~NVIC_DEMCR_VCHARDERR; putreg32(regval, NVIC_DEMCR); #endif #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Initialize logic to support a second level of interrupt decoding for * GPIO pins. */ #ifdef CONFIG_STM32H7_GPIO_IRQ stm32_gpioirqinitialize(); #endif /* And finally, enable interrupts */ up_irq_enable(); #endif }
void up_sigdeliver(void) { struct tcb_s *rtcb = this_task(); #if 0 uint32_t regs[XCPTCONTEXT_REGS+3]; /* Why +3? See below */ #else uint32_t regs[XCPTCONTEXT_REGS]; #endif sig_deliver_t sigdeliver; /* Save the errno. This must be preserved throughout the signal handling * so that the user code final gets the correct errno value (probably EINTR). */ int saved_errno = rtcb->pterrno; board_autoled_on(LED_SIGNAL); sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); /* Save the real return state on the stack. */ up_copystate(regs, rtcb->xcp.regs); regs[REG_PC] = rtcb->xcp.saved_pc; regs[REG_SR] = rtcb->xcp.saved_sr; /* Get a local copy of the sigdeliver function pointer. We do this so that * we can nullify the sigdeliver function pointer in the TCB and accept * more signal deliveries while processing the current pending signals. */ sigdeliver = rtcb->xcp.sigdeliver; rtcb->xcp.sigdeliver = NULL; #ifndef CONFIG_SUPPRESS_INTERRUPTS /* Then make sure that interrupts are enabled. Signal handlers must always * run with interrupts enabled. */ up_irq_enable(); #endif /* Deliver the signals */ sigdeliver(rtcb); /* Output any debug messages BEFORE restoring errno (because they may * alter errno), then disable interrupts again and restore the original * errno that is needed by the user logic (it is probably EINTR). */ sinfo("Resuming\n"); (void)up_irq_save(); rtcb->pterrno = saved_errno; /* Then restore the correct state for this thread of execution. This is an * unusual case that must be handled by up_fullcontextresore. This case is * unusal in two ways: * * 1. It is not a context switch between threads. Rather, up_fullcontextrestore * must behave more it more like a longjmp within the same task, using * he same stack. * 2. In this case, up_fullcontextrestore is called with r12 pointing to * a register save area on the stack to be destroyed. This is * dangerous because there is the very real possibility that the new * stack pointer might overlap with the register save area and hat stack * usage in up_fullcontextrestore might corrupt the register save data * before the state is restored. At present, there does not appear to * be any stack overlap problems. If there were, then adding 3 words * to the size of register save structure size will protect its contents. */ board_autoled_off(LED_SIGNAL); up_fullcontextrestore(regs); }
void up_irqinitialize(void) { uint32_t regaddr; #ifdef CONFIG_DEBUG_FEATURES uint32_t regval; #endif int num_priority_registers; int i; /* Disable all interrupts */ for (i = 0; i < LPC43M4_IRQ_NEXTINT; i += 32) { putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); } /* Make sure that we are using the correct vector table. The default * vector address is 0x0000:0000 but if we are executing code that is * positioned in SRAM or in external FLASH, then we may need to reset * the interrupt vector so that it refers to the table in SRAM or in * external FLASH. */ putreg32((uint32_t)_vectors, NVIC_VECTAB); #ifdef CONFIG_ARCH_RAMVECTORS /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ up_ramvec_initialize(); #endif /* Set all interrupts (and exceptions) to the default priority */ putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt * lines that the NVIC supports: * * 0 -> 32 interrupt lines, 8 priority registers * 1 -> 64 " " " ", 16 priority registers * 2 -> 96 " " " ", 32 priority registers * ... */ num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; /* Now set all of the interrupt lines to the default priority */ regaddr = NVIC_IRQ0_3_PRIORITY; while (num_priority_registers--) { putreg32(DEFPRIORITY32, regaddr); regaddr += 4; } /* currents_regs is non-NULL only while processing an interrupt */ CURRENT_REGS = NULL; /* Attach the SVCall and Hard Fault exception handlers. The SVCall * exception is used for performing context switches; The Hard Fault * must also be caught because a SVCall may show up as a Hard Fault * under certain conditions. */ irq_attach(LPC43_IRQ_SVCALL, up_svcall, NULL); irq_attach(LPC43_IRQ_HARDFAULT, up_hardfault, NULL); /* Set the priority of the SVCall interrupt */ #ifdef CONFIG_ARCH_IRQPRIO /* up_prioritize_irq(LPC43_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */ #endif #ifdef CONFIG_ARMV7M_USEBASEPRI lpc43_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); #endif /* If the MPU is enabled, then attach and enable the Memory Management * Fault handler. */ #ifdef CONFIG_ARM_MPU irq_attach(LPC43_IRQ_MEMFAULT, up_memfault, NULL); up_enable_irq(LPC43_IRQ_MEMFAULT); #endif /* Attach all other processor exceptions (except reset and sys tick) */ #ifdef CONFIG_DEBUG_FEATURES irq_attach(LPC43_IRQ_NMI, lpc43_nmi, NULL); #ifndef CONFIG_ARM_MPU irq_attach(LPC43_IRQ_MEMFAULT, up_memfault, NULL); #endif irq_attach(LPC43_IRQ_BUSFAULT, lpc43_busfault, NULL); irq_attach(LPC43_IRQ_USAGEFAULT, lpc43_usagefault, NULL); irq_attach(LPC43_IRQ_PENDSV, lpc43_pendsv, NULL); irq_attach(LPC43_IRQ_DBGMONITOR, lpc43_dbgmonitor, NULL); irq_attach(LPC43_IRQ_RESERVED, lpc43_reserved, NULL); #endif lpc43_dumpnvic("initial", LPC43M4_IRQ_NIRQS); /* If a debugger is connected, try to prevent it from catching hardfaults. * If CONFIG_ARMV7M_USEBASEPRI, no hardfaults are expected in normal * operation. */ #if defined(CONFIG_DEBUG_FEATURES) && !defined(CONFIG_ARMV7M_USEBASEPRI) regval = getreg32(NVIC_DEMCR); regval &= ~NVIC_DEMCR_VCHARDERR; putreg32(regval, NVIC_DEMCR); #endif /* And finally, enable interrupts */ #ifndef CONFIG_SUPPRESS_INTERRUPTS up_irq_enable(); #endif }
void up_irqinitialize(void) { /* The following operations need to be atomic, but since this function is * called early in the initialization sequence, we expect to have exclusive * access to the GIC. */ /* Colorize the interrupt stack for debug purposes */ #if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 3 { size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~3); up_stack_color((FAR void *)((uintptr_t)&g_intstackbase - intstack_size), intstack_size); } #endif /* Initialize the Generic Interrupt Controller (GIC) for CPU0 */ arm_gic0_initialize(); /* Initialization unique to CPU0 */ arm_gic_initialize(); /* Initialization common to all CPUs */ #ifdef CONFIG_ARCH_LOWVECTORS /* If CONFIG_ARCH_LOWVECTORS is defined, then the vectors located at the * beginning of the .text region must appear at address at the address * specified in the VBAR. There are two ways to accomplish this: * * 1. By explicitly mapping the beginning of .text region with a page * table entry so that the virtual address zero maps to the beginning * of the .text region. VBAR == 0x0000:0000. * * 2. Set the Cortex-A5 VBAR register so that the vector table address * is moved to a location other than 0x0000:0000. * * The second method is used by this logic. */ /* Set the VBAR register to the address of the vector table */ DEBUGASSERT((((uintptr_t)&_vector_start) & ~VBAR_MASK) == 0); cp15_wrvbar((uint32_t)&_vector_start); #endif /* CONFIG_ARCH_LOWVECTORS */ /* currents_regs is non-NULL only while processing an interrupt */ CURRENT_REGS = NULL; #ifndef CONFIG_SUPPRESS_INTERRUPTS #ifdef CONFIG_IMX6_PIO_IRQ /* Initialize logic to support a second level of interrupt decoding for * PIO pins. */ imx_gpioirq_initialize(); #endif /* And finally, enable interrupts */ (void)up_irq_enable(); #endif }
void up_irqinitialize(void) { FAR uintptr_t *vimram; int i; /* Initialize VIM RAM vectors. These vectors are not used in the current * interrupt handler logic. */ vimram = (FAR uintptr_t *)TMS570_VIMRAM_BASE; for (i = 0; i < (TMS570_IRQ_NCHANNELS + 1); i++) { *vimram++ = (uintptr_t)tms570_error_handler; } /* Set Fall-Back Address Parity Error Register (also not used) */ putreg32((uint32_t)tms570_error_handler, TMS570_VIM_FBPARERR); /* Assign all interrupt requests to the VIM channel of the same value. * NOTE: Nothing need be done. That is the power-on default mapping. */ /* Assign all channels to IRQs */ putreg32(0, TMS570_VIM_FIRQPR0); putreg32(0, TMS570_VIM_FIRQPR1); putreg32(0, TMS570_VIM_FIRQPR2); #ifdef TMS570_VIM_FIRQPR3 putreg32(0, TMS570_VIM_FIRQPR3); #endif /* Disable all interrupts */ putreg32(0xfffffffc, TMS570_VIM_REQENACLR0); putreg32(0xffffffff, TMS570_VIM_REQENACLR1); putreg32(0xffffffff, TMS570_VIM_REQENACLR2); #ifdef TMS570_VIM_REQENACLR3 putreg32(0xffffffff, TMS570_VIM_REQENACLR3); #endif /* currents_regs is non-NULL only while processing an interrupt */ CURRENT_REGS = NULL; #ifdef CONFIG_ARMV7R_HAVE_DECODEFIQ /* By default, interrupt CHAN0 is mapped to ESM (Error Signal Module) * high level interrupt and CHAN1 is reserved for other NMI. For safety * reasons, these two channels are mapped to FIQ only and can NOT be * disabled through ENABLE registers. */ #endif #ifndef CONFIG_SUPPRESS_INTERRUPTS #ifdef CONFIG_TMS570_GIO_IRQ /* Initialize logic to support a second level of interrupt decoding for * GIO pins. */ tms570_gioirq_initialize(); #endif /* Attach and enable ESM interrupts. The high level interrupt is really * an NMI. */ (void)irq_attach(TMS570_REQ_ESMHIGH, tms570_esm_interrupt, NULL); (void)irq_attach(TMS570_REQ_ESMLO, tms570_esm_interrupt, NULL); up_enable_irq(TMS570_REQ_ESMHIGH); up_enable_irq(TMS570_REQ_ESMLO); /* And finally, enable interrupts globally */ up_irq_enable(); #endif }
void up_irqinitialize(void) { uint32_t regaddr; int num_priority_registers; int i; /* Disable all interrupts */ for (i = 0; i < NR_VECTORS - EFM32_IRQ_INTERRUPTS; i += 32) { putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); } #if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 3 /* Colorize the interrupt stack for debug purposes */ { size_t intstack_size = (CONFIG_ARCH_INTERRUPTSTACK & ~3); up_stack_color((FAR void *)((uintptr_t)&g_intstackbase - intstack_size), intstack_size); } #endif /* Make sure that we are using the correct vector table. The default * vector address is 0x0000:0000 but if we are executing code that is * positioned in SRAM or in external FLASH, then we may need to reset * the interrupt vector so that it refers to the table in SRAM or in * external FLASH. */ putreg32((uint32_t)_vectors, NVIC_VECTAB); #ifdef CONFIG_ARCH_RAMVECTORS /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based * vector table that requires special initialization. */ up_ramvec_initialize(); #endif /* Set all interrupts (and exceptions) to the default priority */ putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); /* The NVIC ICTR register (bits 0-4) holds the number of of interrupt * lines that the NVIC supports: * * 0 -> 32 interrupt lines, 8 priority registers * 1 -> 64 " " " ", 16 priority registers * 2 -> 96 " " " ", 32 priority registers * ... */ num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; /* Now set all of the interrupt lines to the default priority */ regaddr = NVIC_IRQ0_3_PRIORITY; while (num_priority_registers--) { putreg32(DEFPRIORITY32, regaddr); regaddr += 4; } /* currents_regs is non-NULL only while processing an interrupt */ CURRENT_REGS = NULL; /* Attach the SVCall and Hard Fault exception handlers. The SVCall * exception is used for performing context switches; The Hard Fault * must also be caught because a SVCall may show up as a Hard Fault * under certain conditions. */ irq_attach(EFM32_IRQ_SVCALL, up_svcall); irq_attach(EFM32_IRQ_HARDFAULT, up_hardfault); /* Set the priority of the SVCall interrupt */ #ifdef CONFIG_ARMV7M_USEBASEPRI efm32_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); #endif /* If the MPU is enabled, then attach and enable the Memory Management * Fault handler. */ #ifdef CONFIG_ARM_MPU irq_attach(EFM32_IRQ_MEMFAULT, up_memfault); up_enable_irq(EFM32_IRQ_MEMFAULT); #endif /* Attach all other processor exceptions (except reset and sys tick) */ #ifdef CONFIG_DEBUG_FEATURES irq_attach(EFM32_IRQ_NMI, efm32_nmi); #ifndef CONFIG_ARM_MPU irq_attach(EFM32_IRQ_MEMFAULT, up_memfault); #endif irq_attach(EFM32_IRQ_BUSFAULT, efm32_busfault); irq_attach(EFM32_IRQ_USAGEFAULT, efm32_usagefault); irq_attach(EFM32_IRQ_PENDSV, efm32_pendsv); irq_attach(EFM32_IRQ_DBGMONITOR, efm32_dbgmonitor); irq_attach(EFM32_IRQ_RESERVED, efm32_reserved); #endif efm32_dumpnvic("initial", NR_VECTORS); #ifndef CONFIG_SUPPRESS_INTERRUPTS #ifdef CONFIG_EFM32_GPIO_IRQ /* Initialize logic to support a second level of interrupt decoding for * GPIO pins. */ efm32_gpioirqinitialize(); #endif /* And finally, enable interrupts */ up_irq_enable(); #endif }