diff --git a/arch/arm/src/cortexm3/up_svcall.c b/arch/arm/src/cortexm3/up_svcall.c index 2ec1228b9e..7764f9c09f 100644 --- a/arch/arm/src/cortexm3/up_svcall.c +++ b/arch/arm/src/cortexm3/up_svcall.c @@ -234,7 +234,7 @@ static inline void dispatch_syscall(uint32_t *regs) int up_svcall(int irq, FAR void *context) { - uint32_t *regs = (uint32_t*)context; + uint32_t *regs = (uint32_t*)context; DEBUGASSERT(regs && regs == current_regs); diff --git a/arch/mips/include/pic32mx/irq.h b/arch/mips/include/pic32mx/irq.h index 0b55e9229e..0d2aff173a 100755 --- a/arch/mips/include/pic32mx/irq.h +++ b/arch/mips/include/pic32mx/irq.h @@ -164,7 +164,7 @@ #define PIC32MX_IRQSRC_DMA3 (128+51) /* Vector: 39, DMA Channel 3 */ #define PIC32MX_IRQSRC_FCE (128+56) /* Vector: 44, Flash Control Event */ #define PIC32MX_IRQSRC_USB (128+57) /* Vector: 45, USB */ -#define PIC32MX_IRQSRC1_FIRST (128+57) +#define PIC32MX_IRQSRC1_LAST (128+57) /**************************************************************************** * Public Types diff --git a/arch/mips/src/common/up_internal.h b/arch/mips/src/common/up_internal.h index 3baa912352..0ec2da6985 100755 --- a/arch/mips/src/common/up_internal.h +++ b/arch/mips/src/common/up_internal.h @@ -218,6 +218,7 @@ extern void up_timerinit(void); /* Defined in up_irq.c */ extern void up_maskack_irq(int irq); +extern void up_clrpend_irq(int irq); /* Defined in board/up_leds.c */ diff --git a/arch/mips/src/pic32mx/Make.defs b/arch/mips/src/pic32mx/Make.defs index 3d607d64cc..bcb267d33e 100755 --- a/arch/mips/src/pic32mx/Make.defs +++ b/arch/mips/src/pic32mx/Make.defs @@ -61,7 +61,7 @@ endif # Required PIC32MX files CHIP_ASRCS = -CHIP_CSRCS = pic32mx-irq.c +CHIP_CSRCS = pic32mx-irq.c pic32mx-timerisr.c # Configuration-dependent PIC32MX files diff --git a/arch/mips/src/pic32mx/pic32mx-int.h b/arch/mips/src/pic32mx/pic32mx-int.h index 3479e6a038..985c350baa 100755 --- a/arch/mips/src/pic32mx/pic32mx-int.h +++ b/arch/mips/src/pic32mx/pic32mx-int.h @@ -61,10 +61,10 @@ #define PIC32MX_INT_TPTMRCLR_OFFSET 0x0024 /* Temporal proximity timer clear register */ #define PIC32MX_INT_TPTMRSET_OFFSET 0x0028 /* Temporal proximity timer set register */ #define PIC32MX_INT_TPTMRINV_OFFSET 0x002c /* Temporal proximity timer invert register */ -#define PIC32MX_INT_IFS_OFFSET(n) (0x0030 + 0x10*(n)) -#define PIC32MX_INT_IFSCLR_OFFSET(n) (0x0034 + 0x10*(n)) -#define PIC32MX_INT_IFSSET_OFFSET(n) (0x0038 + 0x10*(n)) -#define PIC32MX_INT_IFSINV_OFFSET(n) (0x003c + 0x10*(n)) +#define PIC32MX_INT_IFS_OFFSET(n) (0x0030 + ((n) << 4)) +#define PIC32MX_INT_IFSCLR_OFFSET(n) (0x0034 + ((n) << 4)) +#define PIC32MX_INT_IFSSET_OFFSET(n) (0x0038 + ((n) << 4)) +#define PIC32MX_INT_IFSINV_OFFSET(n) (0x003c + ((n) << 4)) #define PIC32MX_INT_IFS0_OFFSET 0x0030 /* Interrupt flag status register 0 */ #define PIC32MX_INT_IFS0CLR_OFFSET 0x0034 /* Interrupt flag status clear register 0 */ #define PIC32MX_INT_IFS0SET_OFFSET 0x0038 /* Interrupt flag status set register 0 */ @@ -73,10 +73,10 @@ #define PIC32MX_INT_IFS1CLR_OFFSET 0x0044 /* Interrupt flag status clear register 1 */ #define PIC32MX_INT_IFS1SET_OFFSET 0x0048 /* Interrupt flag status set register 1 */ #define PIC32MX_INT_IFS1INV_OFFSET 0x004c /* Interrupt flag status invert register 1 */ -#define PIC32MX_INT_IEC_OFFSET(n) (0x0060 + 0x10*(n)) -#define PIC32MX_INT_IECCLR_OFFSET(n) (0x0064 + 0x10*(n)) -#define PIC32MX_INT_IECSET_OFFSET(n) (0x0068 + 0x10*(n)) -#define PIC32MX_INT_IECINV_OFFSET(n) (0x006c + 0x10*(n)) +#define PIC32MX_INT_IEC_OFFSET(n) (0x0060 + ((n) << 4)) +#define PIC32MX_INT_IECCLR_OFFSET(n) (0x0064 + ((n) << 4)) +#define PIC32MX_INT_IECSET_OFFSET(n) (0x0068 + ((n) << 4)) +#define PIC32MX_INT_IECINV_OFFSET(n) (0x006c + ((n) << 4)) #define PIC32MX_INT_IEC0_OFFSET 0x0060 /* Interrupt enable control register 0 */ #define PIC32MX_INT_IEC0CLR_OFFSET 0x0064 /* Interrupt enable control clear register 0 */ #define PIC32MX_INT_IEC0SET_OFFSET 0x0068 /* Interrupt enable control set register 0 */ @@ -85,10 +85,10 @@ #define PIC32MX_INT_IEC1CLR_OFFSET 0x0074 /* Interrupt enable control clear register 1 */ #define PIC32MX_INT_IEC1SET_OFFSET 0x0078 /* Interrupt enable control set register 1 */ #define PIC32MX_INT_IEC1INV_OFFSET 0x007c /* Interrupt enable control invert register 1 */ -#define PIC32MX_INT_IPC_OFFSET(n) (0x0090 + 0x10*(n)) -#define PIC32MX_INT_IPCCLR_OFFSET(n) (0x0094 + 0x10*(n)) -#define PIC32MX_INT_IPCSET_OFFSET(n) (0x0098 + 0x10*(n)) -#define PIC32MX_INT_IPCINV_OFFSET(n) (0x009c + 0x10*(n)) +#define PIC32MX_INT_IPC_OFFSET(n) (0x0090 + ((n) << 4)) +#define PIC32MX_INT_IPCCLR_OFFSET(n) (0x0094 + ((n) << 4)) +#define PIC32MX_INT_IPCSET_OFFSET(n) (0x0098 + ((n) << 4)) +#define PIC32MX_INT_IPCINV_OFFSET(n) (0x009c + ((n) << 4)) #define PIC32MX_INT_IPC0_OFFSET 0x0090 /* Interrupt priority control register 0 */ #define PIC32MX_INT_IPC0CLR_OFFSET 0x0094 /* Interrupt priority control clear register 0 */ #define PIC32MX_INT_IPC0SET_OFFSET 0x0098 /* Interrupt priority control set register 0 */ @@ -165,11 +165,11 @@ #define PIC32MX_INT_IECSET(n) (PIC32MX_INT_K1BASE+PIC32MX_INT_IECSET_OFFSET(n)) #define PIC32MX_INT_IECINV(n) (PIC32MX_INT_K1BASE+PIC32MX_INT_IECINV_OFFSET(n)) #define PIC32MX_INT_IEC0 (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC0_OFFSET) -#define PIC32MX_INT_IECCLR0 (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC0CLR_OFFSET) +#define PIC32MX_INT_IEC0CLR (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC0CLR_OFFSET) #define PIC32MX_INT_IEC0SET (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC0SET_OFFSET) #define PIC32MX_INT_IEC0INV (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC0_OFFSET) #define PIC32MX_INT_IEC1 (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC1_OFFSET) -#define PIC32MX_INT_IECCLR1 (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC1CLR_OFFSET) +#define PIC32MX_INT_IEC1CLR (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC1CLR_OFFSET) #define PIC32MX_INT_IEC1SET (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC1SET_OFFSET) #define PIC32MX_INT_IEC1INV (PIC32MX_INT_K1BASE+PIC32MX_INT_IEC1INV_OFFSET) #define PIC32MX_INT_IPC(n) (PIC32MX_INT_K1BASE+PIC32MX_INT_IPC_OFFSET(n)) @@ -317,6 +317,12 @@ /* Interrupt priority control register 0-11 */ +#define INT_CP0_MIN_PRIORITY 0 /* Disabled! */ +#define INT_CP0_MID_PRIORITY 4 /* Can be used as the default */ +#define INT_CP0_MAX_PRIORITY 7 /* Maximum priority */ +#define INT_CP0_MIN_SUBPRIORITY 0 /* Minimum sub-priority */ +#define INT_CP0_MAX_SUBPRIORITY 0 /* Maximum sub-priority */ + #define INT_IPC0_CTIS_SHIFT (0) /* Bits 0-1, Vector: 0, Core Timer Interrupt */ #define INT_IPC0_CTIS_MASK (3 << INT_IPC0_CTIS_SHIFT) #define INT_IPC0_CTIP_SHIFT (2) /* Bits 2-4, Vector: 0, Core Timer Interrupt */ @@ -440,60 +446,60 @@ #define INT_IPC7_PMPIS_MASK (3 << INT_IPC7_PMPIS_SHIFT) #define INT_IPC7_PMPIP_SHIFT (2) /* Bits 2-4, Vector: 28, Parallel Master Port */ #define INT_IPC7_PMPIP_MASK (7 << INT_IPC7_PMPIP_SHIFT) -#define INT_IPC7_CMP1IS_SHIFT (8) /* Bits 8-9, /* Vector: 29, Comparator Interrupt */ +#define INT_IPC7_CMP1IS_SHIFT (8) /* Bits 8-9, Vector: 29, Comparator Interrupt */ #define INT_IPC7_CMP1IS_MASK (3 << INT_IPC7_CMP1IS_SHIFT) -#define INT_IPC7_CMP1IP_SHIFT (10) /* Bits 10-12, /* Vector: 29, Comparator Interrupt */ +#define INT_IPC7_CMP1IP_SHIFT (10) /* Bits 10-12, Vector: 29, Comparator Interrupt */ #define INT_IPC7_CMP1IP_MASK (7 << INT_IPC7_CMP1IP_SHIFT) -#define INT_IPC7_CMP2IS_SHIFT (16) /* Bits 16-17, /* Vector: 30, Comparator Interrupt */ +#define INT_IPC7_CMP2IS_SHIFT (16) /* Bits 16-17, Vector: 30, Comparator Interrupt */ #define INT_IPC7_CMP2IS_MASK (3 << INT_IPC7_CMP2IS_SHIFT) -#define INT_IPC7_CMP2IP_SHIFT (18) /* Bits 18-20, /* Vector: 30, Comparator Interrupt */ +#define INT_IPC7_CMP2IP_SHIFT (18) /* Bits 18-20, Vector: 30, Comparator Interrupt */ #define INT_IPC7_CMP2IP_MASK (7 << INT_IPC7_CMP2IP_SHIFT) -#define INT_IPC7_SPI2IS_SHIFT (24) /* Bits 24-25, /* Vector: 31, SPI2 */ +#define INT_IPC7_SPI2IS_SHIFT (24) /* Bits 24-25, Vector: 31, SPI2 */ #define INT_IPC7_SPI2IS_MASK (3 << INT_IPC7_SPI2IS_SHIFT) -#define INT_IPC7_SPI2IP_SHIFT (26) /* Bits 26-28, /* Vector: 31, SPI2 */ +#define INT_IPC7_SPI2IP_SHIFT (26) /* Bits 26-28, Vector: 31, SPI2 */ #define INT_IPC7_SPI2IP_MASK (7 << INT_IPC7_SPI2IP_SHIFT) -#define INT_IPC8_U2IS_SHIFT (0) /* Bits 0-1, /* Vector: 32, UART2 */ +#define INT_IPC8_U2IS_SHIFT (0) /* Bits 0-1, Vector: 32, UART2 */ #define INT_IPC8_U2IS_MASK (3 << INT_IPC8_U2IS_SHIFT) -#define INT_IPC8_U2IP_SHIFT (2) /* Bits 2-4, /* Vector: 32, UART2 */ +#define INT_IPC8_U2IP_SHIFT (2) /* Bits 2-4, Vector: 32, UART2 */ #define INT_IPC8_U2IP_MASK (7 << INT_IPC8_U2IP_SHIFT) -#define INT_IPC8_I2C2IS_SHIFT (8) /* Bits 8-9, /* Vector: 33, I2C2 */ +#define INT_IPC8_I2C2IS_SHIFT (8) /* Bits 8-9, Vector: 33, I2C2 */ #define INT_IPC8_I2C2IS_MASK (3 << INT_IPC8_I2C2IS_SHIFT) -#define INT_IPC8_I2C2IP_SHIFT (10) /* Bits 10-12, /* Vector: 33, I2C2 */ +#define INT_IPC8_I2C2IP_SHIFT (10) /* Bits 10-12, Vector: 33, I2C2 */ #define INT_IPC8_I2C2IP_MASK (7 << INT_IPC8_I2C2IP_SHIFT) -#define INT_IPC8_FSCMIS_SHIFT (16) /* Bits 16-17, /* Vector: 34, Fail-Safe Clock Monitor */ +#define INT_IPC8_FSCMIS_SHIFT (16) /* Bits 16-17, Vector: 34, Fail-Safe Clock Monitor */ #define INT_IPC8_FSCMIS_MASK (3 << INT_IPC8_FSCMIS_SHIFT) -#define INT_IPC8_FSCMIP_SHIFT (18) /* Bits 18-20, /* Vector: 34, Fail-Safe Clock Monitor */ +#define INT_IPC8_FSCMIP_SHIFT (18) /* Bits 18-20, Vector: 34, Fail-Safe Clock Monitor */ #define INT_IPC8_FSCMIP_MASK (7 << INT_IPC8_FSCMIP_SHIFT) -#define INT_IPC8_RTCCIS_SHIFT (24) /* Bits 24-25, /* Vector: 35, Real-Time Clock and Calendar */ +#define INT_IPC8_RTCCIS_SHIFT (24) /* Bits 24-25, Vector: 35, Real-Time Clock and Calendar */ #define INT_IPC8_RTCCIS_MASK (3 << INT_IPC8_RTCCIS_SHIFT) -#define INT_IPC8_RTCCIP_SHIFT (26) /* Bits 26-28, /* Vector: 35, Real-Time Clock and Calendar */ +#define INT_IPC8_RTCCIP_SHIFT (26) /* Bits 26-28, Vector: 35, Real-Time Clock and Calendar */ #define INT_IPC8_RTCCIP_MASK (7 << INT_IPC8_RTCCIP_SHIFT) -#define INT_IPC9_DMA0IS_SHIFT (0) /* Bits 0-1, /* Vector: 36, DMA Channel 0 */ +#define INT_IPC9_DMA0IS_SHIFT (0) /* Bits 0-1, Vector: 36, DMA Channel 0 */ #define INT_IPC9_DMA0IS_MASK (3 << INT_IPC9_DMA0IS_SHIFT) -#define INT_IPC9_DMA0IP_SHIFT (2) /* Bits 2-4, /* Vector: 36, DMA Channel 0 */ +#define INT_IPC9_DMA0IP_SHIFT (2) /* Bits 2-4, Vector: 36, DMA Channel 0 */ #define INT_IPC9_DMA0IP_MASK (7 << INT_IPC9_DMA0IP_SHIFT) -#define INT_IPC9_DMA1IS_SHIFT (8) /* Bits 8-9, /* Vector: 37, DMA Channel 1 */ +#define INT_IPC9_DMA1IS_SHIFT (8) /* Bits 8-9, Vector: 37, DMA Channel 1 */ #define INT_IPC9_DMA1IS_MASK (3 << INT_IPC9_DMA1IS_SHIFT) -#define INT_IPC9_DMA1IP_SHIFT (10) /* Bits 10-12, /* Vector: 37, DMA Channel 1 */ +#define INT_IPC9_DMA1IP_SHIFT (10) /* Bits 10-12, Vector: 37, DMA Channel 1 */ #define INT_IPC9_DMA1IP_MASK (7 << INT_IPC9_DMA1IP_SHIFT) -#define INT_IPC9_DMA2IS_SHIFT (16) /* Bits 16-17, /* Vector: 38, DMA Channel 2 */ +#define INT_IPC9_DMA2IS_SHIFT (16) /* Bits 16-17, Vector: 38, DMA Channel 2 */ #define INT_IPC9_DMA2IS_MASK (3 << INT_IPC9_DMA2IS_SHIFT) -#define INT_IPC9_DMA2IP_SHIFT (18) /* Bits 18-20, /* Vector: 38, DMA Channel 2 */ +#define INT_IPC9_DMA2IP_SHIFT (18) /* Bits 18-20, Vector: 38, DMA Channel 2 */ #define INT_IPC9_DMA2IP_MASK (7 << INT_IPC9_DMA2IP_SHIFT) -#define INT_IPC9_DMA3IS_SHIFT (24) /* Bits 24-25, /* Vector: 39, DMA Channel 3 */ +#define INT_IPC9_DMA3IS_SHIFT (24) /* Bits 24-25, Vector: 39, DMA Channel 3 */ #define INT_IPC9_DMA3IS_MASK (3 << INT_IPC9_DMA3IS_SHIFT) -#define INT_IPC9_DMA3IP_SHIFT (26) /* Bits 26-28, /* Vector: 39, DMA Channel 3 */ +#define INT_IPC9_DMA3IP_SHIFT (26) /* Bits 26-28, Vector: 39, DMA Channel 3 */ #define INT_IPC9_DMA3IP_MASK (7 << INT_IPC9_DMA3IP_SHIFT) -#define INT_IPC11_FCEIS_SHIFT (0) /* Bits 0-1, /* Vector: 44, Flash Control Event */ +#define INT_IPC11_FCEIS_SHIFT (0) /* Bits 0-1, Vector: 44, Flash Control Event */ #define INT_IPC11_FCEIS_MASK (3 << INT_IPC11_FCEIS_SHIFT) -#define INT_IPC11_FCEIP_SHIFT (2) /* Bits 2-4, /* Vector: 44, Flash Control Event */ +#define INT_IPC11_FCEIP_SHIFT (2) /* Bits 2-4, Vector: 44, Flash Control Event */ #define INT_IPC11_FCEIP_MASK (7 << INT_IPC11_FCEIP_SHIFT) -#define INT_IPC11_USBIS_SHIFT (8) /* Bits 8-9, /* Vector: 45, USB */ +#define INT_IPC11_USBIS_SHIFT (8) /* Bits 8-9, Vector: 45, USB */ #define INT_IPC11_USBIS_MASK (3 << INT_IPC11_USBIS_SHIFT) -#define INT_IPC11_USBIP_SHIFT (10) /* Bits 10-12, /* Vector: 45, USB */ +#define INT_IPC11_USBIP_SHIFT (10) /* Bits 10-12, Vector: 45, USB */ #define INT_IPC11_USBIP_MASK (7 << INT_IPC11_USBIP_SHIFT) /**************************************************************************** diff --git a/arch/mips/src/pic32mx/pic32mx-irq.c b/arch/mips/src/pic32mx/pic32mx-irq.c index 19ecfb8e78..3d7d363bc7 100755 --- a/arch/mips/src/pic32mx/pic32mx-irq.c +++ b/arch/mips/src/pic32mx/pic32mx-irq.c @@ -53,6 +53,8 @@ #include "up_arch.h" #include "os_internal.h" #include "up_internal.h" + +#include "pic32mx-int.h" #include "pic32mx-internal.h" /**************************************************************************** @@ -83,14 +85,43 @@ volatile uint32_t *current_regs; void up_irqinitialize(void) { + uint32_t regval; + int irq; + /* Disable all interrupts */ -#warning "Missing logic" + + putreg32(0xffff, PIC32MX_INT_IEC0CLR); + putreg32(0xffff, PIC32MX_INT_IEC1CLR); + + /* Set all interrupts to the default (middle) priority */ + + for (irq = 0; irq < NR_IRQS; irq++) + { + (void)up_prioritize_irq(irq, (INT_CP0_MID_PRIORITY << 2)); + } + + /* Set the CP0 cause IV bit meaning that the interrupt exception uses + * the "special interrupt vector" + */ + + asm volatile("\tmfc0 %0,$13,0\n" : "=r"(regval)); + regval |= CP0_CAUSE_IV; + asm volatile("\tmtc0 %0,$13,0\n" : : "r"(regval)); + + /* Configure multi- or single- vector interrupts */ + +#ifdef CONFIG_PIC32MX_MVEC + putreg32(INT_INTCON_MVEC, PIC32MX_INT_INTCONSET); +#else + putreg32(INT_INTCON_MVEC, PIC32MX_INT_INTCONCLR); +#endif /* currents_regs is non-NULL only while processing an interrupt */ current_regs = NULL; /* Attach processor exceptions */ +#warning "Missing logic" /* Initialize logic to support a second level of interrupt decoding for * IOPORT pins. @@ -103,6 +134,14 @@ void up_irqinitialize(void) /* And finally, enable interrupts */ #ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* Interrupts are enabled by setting the IE bit in the CP0 status register */ + + regval = 0; + asm volatile("ei %0" : "=r"(regval)); + + /* Then enable all interrupt levels */ + irqrestore(CP0_STATUS_IM_ALL); #endif } @@ -117,7 +156,39 @@ void up_irqinitialize(void) void up_disable_irq(int irq) { -#warning "Missing logic" + uint32_t regaddr; + int bitno; + + /* Disable the interrupt by clearing the associated bit in the IEC register */ + + DEBUGASSERT(irq >= PIC32MX_IRQSRC0_FIRST && irq <= PIC32MX_IRQSRC1_LAST) + if (irq >= PIC32MX_IRQSRC0_FIRST) + { + if (irq <= PIC32MX_IRQSRC0_LAST) + { + /* Use IEC0 */ + + regaddr = PIC32MX_INT_IEC0CLR; + bitno -= PIC32MX_IRQSRC0_FIRST; + } + else if (irq <= PIC32MX_IRQSRC1_LAST) + { + /* Use IEC1 */ + + regaddr = PIC32MX_INT_IEC1CLR; + bitno -= PIC32MX_IRQSRC1_FIRST; + } + else + { + /* Value out of range.. just ignore */ + + return; + } + + /* Disable the interrupt */ + + putreg32((1 << bitno), regaddr); + } } /**************************************************************************** @@ -130,24 +201,201 @@ void up_disable_irq(int irq) void up_enable_irq(int irq) { -#warning "Missing logic" + uint32_t regaddr; + int bitno; + + /* Enable the interrupt by setting the associated bit in the IEC register */ + + DEBUGASSERT(irq >= PIC32MX_IRQSRC0_FIRST && irq <= PIC32MX_IRQSRC1_LAST) + if (irq >= PIC32MX_IRQSRC0_FIRST) + { + if (irq <= PIC32MX_IRQSRC0_LAST) + { + /* Use IEC0 */ + + regaddr = PIC32MX_INT_IEC0SET; + bitno -= PIC32MX_IRQSRC0_FIRST; + } + else if (irq <= PIC32MX_IRQSRC1_LAST) + { + /* Use IEC1 */ + + regaddr = PIC32MX_INT_IEC1SET; + bitno -= PIC32MX_IRQSRC1_FIRST; + } + else + { + /* Value out of range.. just ignore */ + + return; + } + + /* Disable the interrupt */ + + putreg32((1 << bitno), regaddr); + } +} + +/**************************************************************************** + * Name: up_clrpend_irq + * + * Description: + * Clear any pending interrupt + * + ****************************************************************************/ + +void up_clrpend_irq(int irq) +{ + uint32_t regaddr; + int bitno; + + /* Disable the interrupt by clearing the associated bit in the IEC and then + * acknowledge the interrupt by clearing the associated bit in the IFS + * register. It is necessary to do this BEFORE lowering the interrupt + * priority level otherwise recursive interrupts would occur. + */ + + DEBUGASSERT(irq >= PIC32MX_IRQSRC0_FIRST && irq <= PIC32MX_IRQSRC1_LAST) + if (irq >= PIC32MX_IRQSRC0_FIRST) + { + if (irq <= PIC32MX_IRQSRC0_LAST) + { + /* Use IFS0 */ + + regaddr = PIC32MX_INT_IFS0CLR; + bitno -= PIC32MX_IRQSRC0_FIRST; + } + else if (irq <= PIC32MX_IRQSRC1_LAST) + { + /* Use IFS1 */ + + regaddr = PIC32MX_INT_IFS1CLR; + bitno -= PIC32MX_IRQSRC1_FIRST; + } + else + { + /* Value out of range.. just ignore */ + + return; + } + + /* Disable then acknowledge interrupt */ + + putreg32((1 << bitno), regaddr); + } +} + +/**************************************************************************** + * Name: up_maskack_irq + * + * Description: + * Mask the IRQ and acknowledge it. This could be done by calling + * up_disable_irq followed by up_clrpend_irq, but since these function is + * called from interrupt handling logic it is probably worth the improved + * performance by doing doing both here. + * + ****************************************************************************/ + +void up_maskack_irq(int irq) +{ + uint32_t iecaddr; + uint32_t ifsaddr; + int bitno; + + /* Disable the interrupt by clearing the associated bit in the IEC and then + * acknowledge the interrupt by clearing the associated bit in the IFS + * register. It is necessary to do this BEFORE lowering the interrupt + * priority level otherwise recursive interrupts would occur. + */ + + DEBUGASSERT(irq >= PIC32MX_IRQSRC0_FIRST && irq <= PIC32MX_IRQSRC1_LAST) + if (irq >= PIC32MX_IRQSRC0_FIRST) + { + if (irq <= PIC32MX_IRQSRC0_LAST) + { + /* Use IEC0 and IFS0*/ + + iecaddr = PIC32MX_INT_IEC0CLR; + ifsaddr = PIC32MX_INT_IFS0CLR; + bitno -= PIC32MX_IRQSRC0_FIRST; + } + else if (irq <= PIC32MX_IRQSRC1_LAST) + { + /* Use IEC1 and IFS1 */ + + iecaddr = PIC32MX_INT_IEC1CLR; + ifsaddr = PIC32MX_INT_IFS1CLR; + bitno -= PIC32MX_IRQSRC1_FIRST; + } + else + { + /* Value out of range.. just ignore */ + + return; + } + + /* Disable then acknowledge interrupt */ + + putreg32((1 << bitno), iecaddr); + putreg32((1 << bitno), ifsaddr); + } } /**************************************************************************** * Name: up_prioritize_irq * * Description: - * Set the priority of an IRQ. + * Set the priority of an IRQ by setting the priority and sub-priority + * fields in the PIC32MX IPC registers. There are 12 IPC registers, IPC0 + * through IPC11. Each has sub-priority fields for 8 interrupts for a + * total of 96 interrupts max. * - * Since this API is not supported on all architectures, it should be - * avoided in common implementations where possible. + * Each interrupt priority is represent by a group of 5 bits: a 3-bit + * priority and a 2-bit sub-priority. These have different meanings to + * the hardware. The priority is the priority level that is enabled + * or masked by the IPL field of the CAUSE register. The sub-priority + * only mediates ties when two interrupts with the same priority pend + * simultaneously. + * + * In this function, we just treat this as a single 5-bit priority. + * (MS 3-bits=priority; LS 2-bits=sub-priority). + * + * The 5-bit priority/sub-priority fields are arranged at byte boundaries + * within each IPC register: + * + * xxxP PPSS xxxP PPSS xxxP PPSS xxxP PPSS * ****************************************************************************/ #ifdef CONFIG_ARCH_IRQPRIO int up_prioritize_irq(int irq, int priority) { -#warning "Missing logic" - return -ENOSYS; + int regndx; + int shift; + + /* Don't allow this function to be used for disabling interrupts. There is + * no good reason for this restriction other than I want to make sure that + * the 5-bit priority values passed to this function are *not* confused with + * the 3-bit hardware priority values. + */ + + DEBUGASSERT((unsigned)irq < NR_IRQS && (unsigned)(priority >> 2) > 0); + if (irq < NR_IRQS) + { + /* Get the index to the IPC register and the shift to the 5-bit priority + * field for this IRQ. + */ + + regndx = irq >> 2; /* Range: 0-11 */ + shift = (irq & 3) << 3; /* {0, 8, 16, 24 } */ + + /* Set the new interrupt priority (momentarily disabling interrupts) */ + + putreg32(0x1f << shift, PIC32MX_INT_IPCCLR(regndx)); + putreg32(priority << shift, PIC32MX_INT_IPCSET(regndx)); + return OK; + } + + return -EINVAL; } #endif diff --git a/arch/mips/src/pic32mx/pic32mx-memorymap.h b/arch/mips/src/pic32mx/pic32mx-memorymap.h index f81e9695c4..9cf1e8a130 100755 --- a/arch/mips/src/pic32mx/pic32mx-memorymap.h +++ b/arch/mips/src/pic32mx/pic32mx-memorymap.h @@ -43,13 +43,14 @@ #include #include "chip.h" +#include "mips32-memorymap.h" /************************************************************************************ * Pre-Processor Definitions ************************************************************************************/ /* This memory may be valid for other chips as well, but I don't know that */ -#if defined(CHIP_PIC32MX3) || defined(CHIP_PIC32MX3) +#if defined(CHIP_PIC32MX3) || defined(CHIP_PIC32MX4) /* Physical Memory Map **************************************************************/ diff --git a/arch/mips/src/pic32mx/pic32mx-timerisr.c b/arch/mips/src/pic32mx/pic32mx-timerisr.c new file mode 100755 index 0000000000..4b3addf2ce --- /dev/null +++ b/arch/mips/src/pic32mx/pic32mx-timerisr.c @@ -0,0 +1,174 @@ +/**************************************************************************** + * arch/mips/src/pic32mx/pic32mx_timerisr.c + * + * Copyright (C) 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "clock_internal.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "pic32mx-timer.h" +#include "pic32mx-int.h" +#include "pic32mx-internal.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ + +#ifndef CONFIG_PIC32MX_T1PRIO +# define CONFIG_PIC32MX_T1PRIO (INT_CP0_MID_PRIORITY << 2) +#endif + +#if CONFIG_PIC32MX_T1PRIO < 4 +# error "CONFIG_PIC32MX_T1PRIO is too small" +#endif + +#if CONFIG_PIC32MX_T1PRIO > 31 +# error "CONFIG_PIC32MX_T1PRIO is too large" +#endif + +/* Timer Setup **************************************************************/ +/* Select a timer prescale value. Our goal is to select the timer MATCH + * register value givent the board's periperhal clock frequency and the + * desired system timer frequency: + * + * TIMER1_MATCH = BOARD_PERIPHERAL_CLOCK / TIMER1_PRESCALE / CLOCKS_PER_SEC + * + * We want the largest possible value for MATCH that is less than 65,535, the + * maximum value for the 16-bit timer register: + * + * TIMER1_PRESCALE >= BOARD_PERIPHERAL_CLOCK / CLOCKS_PER_SEC / 65535 + * + * Timer 1 does not have very many options for the perscaler value. So we + * can pick the best by brute force. Example: + * + * BOARD_PERIPHERAL_CLOCK = 40000000 + * CLOCKS_PER_SEC = 100 + * OPTIMAL_PRESCALE = 6 + * TIMER1_PRESCALE = 8 + * TIMER1_MATCH = 50,000 + */ + +#define OPTIMAL_PRESCALE (BOARD_PERIPHERAL_CLOCK / CLOCKS_PER_SEC / 65535) +#if OPTIMAL_PRESCALE <= 1 +# define TIMER1_CON_TCKPS TIMER1_CON_TCKPS_1 +# define TIMER1_PRESCALE 1 +#elif OPTIMAL_PRESCALE <= 8 +# define TIMER1_CON_TCKPS TIMER1_CON_TCKPS_8 +# define TIMER1_PRESCALE 8 +#elif OPTIMAL_PRESCALE <= 64 +# define TIMER1_CON_TCKPS TIMER1_CON_TCKPS_64 +# define TIMER1_PRESCALE 64 +#elif OPTIMAL_PRESCALE <= 256 +# define TIMER1_CON_TCKPS TIMER1_CON_TCKPS_256 +# define TIMER1_PRESCALE 256 +#else +# error "This timer frequency cannot be represented" +#endif + +#define TIMER1_MATCH (BOARD_PERIPHERAL_CLOCK / TIMER1_PRESCALE / CLOCKS_PER_SEC) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Global Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +int up_timerisr(int irq, uint32_t *regs) +{ + /* Process timer interrupt */ + + sched_process_timer(); + return 0; +} + +/**************************************************************************** + * Function: up_timerinit + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +void up_timerinit(void) +{ + /* Configure and enable TIMER1 -- source internal (TCS=0) */ + + putreg32(TIMER1_CON_TCKPS, PIC32MX_TIMER1_CON); + putreg32(0, PIC32MX_TIMER1_CNT); + putreg32(TIMER1_MATCH-1, PIC32MX_TIMER1_PR); + putreg32(TIMER_CON_ON, PIC32MX_TIMER1_CONSET); + + /* Configure the timer interrupt */ + + up_clrpend_irq(PIC32MX_IRQSRC_T1); + (void)up_prioritize_irq(PIC32MX_IRQ_T1, CONFIG_PIC32MX_T1PRIO); + + /* Attach the timer interrupt vector */ + + (void)irq_attach(PIC32MX_IRQ_T1, (xcpt_t)up_timerisr); + + /* And enable the timer interrupt */ + + up_enable_irq(PIC32MX_IRQSRC_T1); +}