/*---------------------------------------------------------------------------* * Routine: RX62N_PWM_MTU_DisableOutput *---------------------------------------------------------------------------* * Description: * PWM is going to have a single edge output (high until matches, then * low, reset counter goes back to high). * Inputs: * void *aWorkspace -- PWM's workspace * TUInt8 aMatchRegister -- Point in Fpclk cycles where PWM switches * Outputs: * T_uezError -- UEZ_ERROR_NONE *---------------------------------------------------------------------------*/ static T_uezError RX62N_PWM_MTU_DisableOutput( void *aWorkspace, TUInt8 aMatchRegister) { T_RX62N_MTU_Workspace *p = (T_RX62N_MTU_Workspace *)aWorkspace; const T_RX62N_MTU_Info *p_info = p->iInfo; TUInt8 i; if(aMatchRegister >= p_info->iNumOutputs) return UEZ_ERROR_ILLEGAL_ARGUMENT; if(!InterruptIsRegistered(p_info->iVECT[aMatchRegister])) { if(aMatchRegister == 0) *p_info->iTIORH &= ~5; else if(aMatchRegister == 1) *p_info->iTIORH &= ~(1<<5); else if(aMatchRegister == 2) *p_info->iTIORL &= ~5; else if(aMatchRegister == 3) *p_info->iTIORL &= ~(1<<5); } else { // Enable any registered interrupts for(i=0; i<p_info->iNumOutputs; i++) { if(InterruptIsRegistered(p_info->iVECT[i])) InterruptDisable(p_info->iVECT[i]); } } return UEZ_ERROR_NONE; }
/*---------------------------------------------------------------------------* * Routine: RX62N_PWM_MTU_EnableSingleEdgeOutput *---------------------------------------------------------------------------* * Description: * PWM is going to have a single edge output (high until matches, then * low, reset counter goes back to high). * Inputs: * void *aWorkspace -- PWM's workspace * TUInt8 aMatchRegister -- Point in Fpclk cycles where PWM switches * Outputs: * T_uezError -- UEZ_ERROR_NONE *---------------------------------------------------------------------------*/ static T_uezError RX62N_PWM_MTU_EnableSingleEdgeOutput( void *aWorkspace, TUInt8 aMatchRegister) { T_RX62N_MTU_Workspace *p = (T_RX62N_MTU_Workspace *)aWorkspace; const T_RX62N_MTU_Info *p_info = p->iInfo; TUInt8 i; if(aMatchRegister >= p_info->iNumOutputs) return UEZ_ERROR_ILLEGAL_ARGUMENT; // This needs to be changed once there is a rx62n timer driver // - for now, if a callback is set, output is software controlled if( p->iMatchCallback[aMatchRegister] && !InterruptIsRegistered(p_info->iVECT[aMatchRegister]) ) { InterruptRegister( p_info->iVECT[aMatchRegister], p_info->iVectISR[aMatchRegister], p->iISRPriority, p_info->iVectName[aMatchRegister]); *p_info->iTIER |= 1 << aMatchRegister; } if(!InterruptIsRegistered(p_info->iVECT[aMatchRegister])) { if(aMatchRegister == 0) *p_info->iTIORH |= 5; else if(aMatchRegister == 1) *p_info->iTIORH |= (1<<5); else if(aMatchRegister == 2) *p_info->iTIORL |= 5; else if(aMatchRegister == 3) *p_info->iTIORL |= (1<<5); } else { // Enable any registered interrupts for(i=0; i<p_info->iNumOutputs; i++) { if(InterruptIsRegistered(p_info->iVECT[i])) InterruptEnable(p_info->iVECT[i]); } } return UEZ_ERROR_NONE; }
/*---------------------------------------------------------------------------* * Routine: RX62N_PWM_MTU_SetMatchRegister *---------------------------------------------------------------------------* * Description: * Configure one of the several match registers for this PWM bank. * Outputs: * void *aWorkspace -- PWM's workspace * TUInt8 aMatchRegister -- Index to match register (0-7) * TUInt32 aMatchPoint -- Number of PWM cycles until match * TBool aDoInterrupt -- ETrue if want an interrupt, else EFalse * (NOTE: Interrupts currently not * implemented) * TBool aDoCounterReset -- ETrue if counter for this PWM bank is * to be reset on match. * TBool aDoStop -- ETrue if counter is to be stopped * when match occurs. *---------------------------------------------------------------------------*/ static T_uezError RX62N_PWM_MTU_SetMatchRegister( void *aWorkspace, TUInt8 aMatchRegister, TUInt32 aMatchPoint, TBool aDoInterrupt, TBool aDoCounterReset, TBool aDoStop) { T_RX62N_MTU_Workspace *p = (T_RX62N_MTU_Workspace *)aWorkspace; const T_RX62N_MTU_Info *p_info = p->iInfo; if(aMatchRegister >= p_info->iNumOutputs) return UEZ_ERROR_ILLEGAL_ARGUMENT; aMatchPoint /= 2; // Adjust Fcclk to Fpclk *p_info->iTGR[aMatchRegister] = (aMatchPoint/4); if( p->iMatchCallback[aMatchRegister] && !InterruptIsRegistered(p_info->iVECT[aMatchRegister]) ) { InterruptRegister( p_info->iVECT[aMatchRegister], p_info->iVectISR[aMatchRegister], p->iISRPriority, p_info->iVectName[aMatchRegister]); *p_info->iTIER |= 1 << aMatchRegister; } return UEZ_ERROR_NONE; }
/*---------------------------------------------------------------------------* * Routine: RX62N_PWM_MTU_SetMaster *---------------------------------------------------------------------------* * Description: * PWM is going to start -- chip select enabled for device * Outputs: * void *aWorkspace -- Workspace for PWM * TUInt32 aPeriod -- Number of Fpclk intervals per period * TUInt8 aMatchRegister -- Which register is used for master counter *---------------------------------------------------------------------------*/ static T_uezError RX62N_PWM_MTU_SetMaster( void *aWorkspace, TUInt32 aPeriod, TUInt8 aMatchRegister) { T_RX62N_MTU_Workspace *p = (T_RX62N_MTU_Workspace *)aWorkspace; const T_RX62N_MTU_Info *p_info = p->iInfo; if(aMatchRegister >= p_info->iNumOutputs) return UEZ_ERROR_ILLEGAL_ARGUMENT; // Ensure MTU is on SYSTEM.MSTPCRA.LONG &= ~(1<<p_info->iMSTPBit); // MSTP(MTUx) = 0; // Ensure it is stopped *p_info->iTSTR &= ~(1<<p_info->iCSTBit); // CST = 0; // Set clear control bit to this match register if(aMatchRegister == 0) *p_info->iTCR = 1 << 5; else if(aMatchRegister == 1) *p_info->iTCR = 2 << 5; else if(aMatchRegister == 2) *p_info->iTCR = 5 << 5; else if(aMatchRegister == 3) *p_info->iTCR = 6 << 5; *p_info->iTCR |= 0 << 3; // Clock on rising edge *p_info->iTCR |= 1 << 0, // PCLK/4, for now *p_info->iTMDR = 2 << 0; // PWM mode 1: TMDR.MD = 2 aPeriod /= 2; // Adjust Fcclk to Fpclk // Set Period *p_info->iTGR[aMatchRegister] = (aPeriod/4); // Configure Interrupt if Needed if( p->iMatchCallback[aMatchRegister] && !InterruptIsRegistered(p_info->iVECT[aMatchRegister]) ) { InterruptRegister( p_info->iVECT[aMatchRegister], p_info->iVectISR[aMatchRegister], p->iISRPriority, p_info->iVectName[aMatchRegister]); *p_info->iTIER |= 1 << aMatchRegister; } // Set start bit *p_info->iTSTR |= (1<<p_info->iCSTBit); // CST = 1; return UEZ_ERROR_NONE; }
/*---------------------------------------------------------------------------* * Routine: USBSharedInterruptSetup *---------------------------------------------------------------------------* * Description: * Both Host and Device setup their interrupts by calling this routine * Outputs: * T_LPC247x_SSP_Workspace *aW -- Particular SSP workspace * SSP_Request *aRequest -- Configuration of SSP device *---------------------------------------------------------------------------*/ void USBSharedInterruptSetup(void) { if (!InterruptIsRegistered(USB_IRQn)) { InterruptRegister( USB_IRQn, ILPC17xx_40xx_USB_InterruptVector, INTERRUPT_PRIORITY_NORMAL, "USB"); InterruptEnable(USB_IRQn); } }
/*---------------------------------------------------------------------------* * Routine: LPC2478_GPDMA_Enable *---------------------------------------------------------------------------* * Description: * Enable GPDMA controller and register interrupt handler. * Inputs: * void *aW -- Particular GPDMA workspace * Outputs: * T_uezError -- Error code *---------------------------------------------------------------------------*/ static void LPC2478_GPDMA_Enable(void *aWorkspace) { (void)aWorkspace; // Increase number of G_opened channels. G_opened++; // Enable peripheral power PCONP |= PCONP_PCGPDMA; // Was registered already? if(EFalse == InterruptIsRegistered(INTERRUPT_CHANNEL_GP_DMA)) { // Enable interrupt. InterruptRegister(INTERRUPT_CHANNEL_GP_DMA, (TISRFPtr)IGPDMA, INTERRUPT_PRIORITY_NORMAL, "GPDMA"); InterruptEnable(INTERRUPT_CHANNEL_GP_DMA); } // Enable GPDMA by writing ENABLE bit. // Always little-endian. DMACConfiguration = DMACConfiguration_E; }
/*---------------------------------------------------------------------------* * Routine: LPC247x_Timer_SetMatchCallback *---------------------------------------------------------------------------* * Description: * Setup a callback routine for this timer on one of the match * registers. The callback is called when a match occurs and an * interrupt occurs. The callback is called from within the ISR. * Inputs: * void *aWorkspace -- Timer workspace * TUInt8 aMatchRegister -- Which match register to set callback * T_Timer_Callback aCallbackFunc -- Function to call, or 0 to clear. * void *aCallbackWorkspace -- Workspace to pass to callback * Outputs: * T_uezError -- UEZ_ERROR_ILLEGAL_PARAMETER if match register is out * of range. *---------------------------------------------------------------------------*/ static T_uezError LPC1756_Timer_SetMatchCallback( void *aWorkspace, TUInt8 aMatchRegister, T_HALTimer_Callback aCallbackFunc, void *aCallbackWorkspace) { T_LPC1756_Timer_Workspace *p = (T_LPC1756_Timer_Workspace *)aWorkspace; TBool any; TUInt8 i; // Determine if legal match register if (aMatchRegister >= 4) return UEZ_ERROR_ILLEGAL_PARAMETER; // Set the callback (which can be 0 as well as an address) p->iCallbacks[aMatchRegister].iCallbackFunc = aCallbackFunc; p->iCallbacks[aMatchRegister].iCallbackWorkspace = aCallbackWorkspace; // Check to see if there are any callbacks any = EFalse; for (i = 0; i < 4; i++) { if (p->iCallbacks[i].iCallbackFunc) { any = ETrue; break; } } // Register or deregister the interrupt if (any) { // Register if not already registered if (!InterruptIsRegistered(p->iInfo->iVector)) InterruptRegister(p->iInfo->iVector, p->iInfo->iISR, INTERRUPT_PRIORITY_HIGH, p->iInfo->iName); InterruptEnable(p->iInfo->iVector); } else { // No one registered anymore, turn off this callback (but leave registered) InterruptDisable(p->iInfo->iVector); } return UEZ_ERROR_NONE; }
/*---------------------------------------------------------------------------* * Routine: ExternalInterrupt_NXP_LPC1756_Set *---------------------------------------------------------------------------* * Description: * Set the rate of a given blink register (as close as possible). * Inputs: * void *aW -- Workspace * TUInt32 aChannel -- EINT channel (0 to 3) * TUInt8 aTrigger -- Trigger type (if used) * EINTCallback aCallbackFunc -- Function to call when trigger. * void *aCallbackWorkspace -- Parameter to pass to callback function. * Outputs: * T_uezError -- Error code *---------------------------------------------------------------------------*/ T_uezError ExternalInterrupt_NXP_LPC1756_Set( void *aWorkspace, TUInt32 aChannel, T_EINTTrigger aTrigger, EINT_Callback aCallbackFunc, void *aCallbackWorkspace, T_EINTPriority aPriority, const char *aName) { TUInt32 irqNum; T_ExternalInterrupt_NXP_LPC1756_Workspace *p = (T_ExternalInterrupt_NXP_LPC1756_Workspace *)aWorkspace; T_eintCallback *p_callback; T_uezError error = UEZ_ERROR_NONE; IGrab(p); // Fake loop while (1) { // Is this a valid channel? if (aChannel >= NUM_EXTERNAL_INTERRUPTS) { error = UEZ_ERROR_OUT_OF_RANGE; break; } // Is this external interrupt already in use? p_callback = G_eintCallbacks+aChannel; if (p_callback->iCallbackFunc) { error = UEZ_ERROR_ALREADY_EXISTS; break; } // Is this interrupt already registered? irqNum = EINT0_IRQn+aChannel; if (InterruptIsRegistered(irqNum)) { error = UEZ_ERROR_NOT_AVAILABLE; break; } // Interrupt is available. Register it p_callback->iPriority = (T_irqPriority) aPriority; p_callback->iTrigger = aTrigger; p_callback->iCallbackWorkspace = aCallbackWorkspace; p_callback->iCallbackFunc = aCallbackFunc; // Start disabled InterruptDisable(irqNum); InterruptRegister( irqNum, G_eintFuncs[aChannel], (T_irqPriority) aPriority, aName); // Setup the proper mode (edge or level) if ((aTrigger == EINT_TRIGGER_EDGE_FALLING) || (aTrigger == EINT_TRIGGER_EDGE_RISING)) { // Edge triggered SC->EXTMODE |= (1 << aChannel); } else { // Level triggered SC->EXTMODE &= ~(1 << aChannel); } // Setup the proper polarity if ((aTrigger == EINT_TRIGGER_LEVEL_HIGH) || (aTrigger == EINT_TRIGGER_EDGE_RISING)) { // high or rising is 1 SC->EXTPOLAR |= (1 << aChannel); } else { // low or falling is 0 SC->EXTPOLAR &= ~(1 << aChannel); } // Make sure the external interrupt has been cleared SC->EXTINT = (1<<aChannel); // Do not loop break; } IRelease(p); return error; }
/*---------------------------------------------------------------------------* * Routine: ExternalInterrupt_Renesas_RX62N_Set *---------------------------------------------------------------------------* * Description: * Set the rate of a given blink register (as close as possible). * Inputs: * void *aWorkspace -- Workspace * TUInt32 aChannel -- EINT channel (0 to 15) * TUInt8 aTrigger -- Trigger type (if used) * EINTCallback aCallbackFunc -- Function to call when trigger. * void *aCallbackWorkspace -- Parameter to pass to callback function. * Outputs: * T_uezError -- Error code *---------------------------------------------------------------------------*/ T_uezError ExternalInterrupt_Renesas_RX62N_Set( void *aWorkspace, TUInt32 aChannel, T_EINTTrigger aTrigger, EINT_Callback aCallbackFunc, void *aCallbackWorkspace, T_irqPriority aPriority, const char *aName) { TUInt32 irqNum; // T_ExternalInterrupt_Renesas_RX62N_Workspace *p = // (T_ExternalInterrupt_Renesas_RX62N_Workspace *)aWorkspace; T_eintEntry *p_entry; T_uezError error = UEZ_ERROR_NONE; TUInt8 edge; const T_ExternalInterrupt_Renesas_RX62N_Info *p_info; HAL_GPIOPort **p_gpio; TUInt32 gpioPinIndex; // Fake loop while (1) { // Is this a valid channel? if (aChannel >= NUM_EXTERNAL_INTERRUPTS) { error = UEZ_ERROR_OUT_OF_RANGE; break; } // Is this external interrupt already in use? p_entry = G_eintEntries + aChannel; if (p_entry->iCallbackFunc) { error = UEZ_ERROR_ALREADY_EXISTS; break; } // Is this interrupt already registered? irqNum = VECT_ICU_IRQ0 + aChannel; if (InterruptIsRegistered(irqNum)) { error = UEZ_ERROR_NOT_AVAILABLE; break; } // Interrupt is available. Register it p_entry->iPriority = aPriority; p_entry->iTrigger = aTrigger; p_entry->iCallbackWorkspace = aCallbackWorkspace; p_entry->iCallbackFunc = aCallbackFunc; // Start disabled InterruptDisable(irqNum); // Find the info about this pin p_info = G_eintInfo + aChannel; error = HALInterfaceFind((p_entry->iIsPinSetB) ? p_info->iGPIONameB : p_info->iGPIONameA, (T_halWorkspace **)&p_gpio); if (error) break; gpioPinIndex = (p_entry->iIsPinSetB) ? p_info->iGPIOPinIndexB : p_info->iGPIOPinIndexA; (*p_gpio)->SetInputMode(p_gpio, (1<<gpioPinIndex)); (*p_gpio)->Control(p_gpio, gpioPinIndex, GPIO_CONTROL_ENABLE_INPUT_BUFFER, 0); // Map the trigger type to a constant switch (aTrigger) { case EINT_TRIGGER_EDGE_FALLING: edge = (1 << 3); break; case EINT_TRIGGER_EDGE_RISING: edge = (2 << 3); break; case EINT_TRIGGER_LEVEL_LOW: edge = (0 << 3); break; case EINT_TRIGGER_EDGE_BOTH: edge = (3 << 3); break; case EINT_TRIGGER_LEVEL_HIGH: default: edge = 0xFF; break; } if (edge == 0xFF) { error = UEZ_ERROR_INVALID_PARAMETER; break; } ICU.IRQCR[aChannel].BYTE = edge; // Clear the interrupt ICU.IR[irqNum].BIT.IR = 0; InterruptRegister(irqNum, G_eintFuncs[aChannel], aPriority, aName); // Do not loop break; } return error; }