This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/TM4C123GH6PM: Problem with SSI Interrupt

Part Number: TM4C123GH6PM

Tool/software: TI C/C++ Compiler

Hi everyone, I recently use TM4C123G to control the converter as well as to function protection converter.

I use ADC Timer to sensor voltage and current to control the PWM and to protect converter in case short-circuit. In addition I have to use SSI for MCP4921 ( one part of protection) and UART for communicating to another.

I set priority for each interrupt:

    IntPrioritySet (INT_TIMER0A, 0);
    IntPrioritySet (INT_ADC0SS1, 10);
    IntPrioritySet (INT_UART1, 20);
    IntPrioritySet (INT_UART0, 30);
    IntPrioritySet(INT_PWM0_3,40);
    IntPrioritySet (INT_SSI0, 50);

PWM, ADC, UART work well. But SSI Interrupt do not work. When I test only SSI interrupt, it work well; I do not which problem may I have? Could you give me some suggestion?

Thank you so much.

This is my code

void UartInit(void)
{ // Enable the GPIO port that is used for the on-board LED.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    //
    // Enable the GPIO pins for the LED (PF2).
    //
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_1);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_3);
    GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6);
    // Enable the peripherals used by this example.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    // Enable processor interrupts.
    IntMasterEnable();
    // Set GPIO A0 and A1, B0 and B1 as UART pins.
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    GPIOPinConfigure(GPIO_PB0_U1RX);
    GPIOPinConfigure(GPIO_PB1_U1TX);
    GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    // Configure the UART.
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
                               (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                UART_CONFIG_PAR_NONE));
    UARTConfigSetExpClk(UART1_BASE, SysCtlClockGet(), 115200,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                             UART_CONFIG_PAR_NONE));
    // Enable the UART interrupt.
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);
    IntEnable(INT_UART1);
    UARTIntEnable(UART1_BASE, UART_INT_RX | UART_INT_RT);
    }
//*****************************************************************************
// The PWM configuration.
//*****************************************************************************
void PWMInit(void)
{//Configure PWM clock to match system
    SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
    //Enable the peripherals used by this program.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    ulPeriod = SysCtlClockGet()/62500;//PWM frequency 62500Hz
    //Configure PF1 pins as PWM
    GPIOPinConfigure(GPIO_PD0_M0PWM6);
    GPIOPinConfigure(GPIO_PD1_M0PWM7);
    GPIOPinTypePWM(GPIO_PORTD_BASE, GPIO_PIN_0|GPIO_PIN_1);
    //Configure PWM Options
    PWMGenConfigure(PWM0_BASE, PWM_GEN_3, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
    PWMGenPeriodSet(PWM0_BASE, PWM_GEN_3, ulPeriod);//PWM frequency = 200Hz
    //Turn on the Output pins
    PWMOutputState(PWM0_BASE, PWM_OUT_6_BIT|PWM_OUT_7_BIT, true);
    //Enable the PWM generator
    PWMGenEnable(PWM0_BASE, PWM_GEN_3);
    PWMIntEnable(PWM0_BASE,PWM_INT_GEN_3);
    IntEnable(INT_PWM0_3);
    PWMGenIntTrigEnable(PWM0_BASE,PWM_INT_GEN_3,PWM_INT_CNT_ZERO);
    IntMasterEnable();
    PWMPulseWidthSet(PWM0_BASE, PWM_OUT_6, ulPeriod*ulDutyCycle1/100);
        PWMPulseWidthSet(PWM0_BASE, PWM_OUT_7, ulPeriod*ulDutyCycle2/100);
        PWMGenEnable(PWM0_BASE, PWM_GEN_3);
    }
//*****************************************************************************
// The ADC configuration.
//*****************************************************************************
void ADCInit(void){
    // *** Peripheral Enable
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    // *** ADC0
    //Oversampling is accomplished by averaging multiple
    //samples from the same analog input.
    ADCHardwareOversampleConfigure(ADC0_BASE,4);
    //If ADC_REF_INT is chosen, then an
    //internal 3V reference is used and no external reference is needed. If ADC_REF_EXT_3V is
    //chosen, then a 3V reference must be supplied to the AVREF pin.
    ADCReferenceSet(ADC0_BASE,ADC_REF_INT);
    ////A trigger generated by a timer;
    ADCSequenceConfigure(ADC0_BASE,1,ADC_TRIGGER_TIMER,0);
   
    ADCSequenceStepConfigure(ADC0_BASE,1,0,ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE,1,1,ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE,1,2,ADC_CTL_CH4);
    ADCSequenceStepConfigure(ADC0_BASE,1,3,ADC_CTL_CH8|ADC_CTL_IE|ADC_CTL_END);
    // Since sample sequence 3 is now configured, it must be enabled.
    ADCSequenceEnable(ADC0_BASE,1);
   
    TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
    samplePeriod = SysCtlClockGet()/sampleFreq;     //frequency of the system clock by SysCtlClockGet
    TimerLoadSet(TIMER0_BASE,TIMER_A,samplePeriod - 1);
    //Enables the ADC trigger output.
    TimerControlTrigger(TIMER0_BASE,TIMER_A,true);
    // *** GPIO
    GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3);
    GPIOPinTypeADC(GPIO_PORTD_BASE,GPIO_PIN_3);
    // *** Interrupts
    IntEnable(INT_TIMER0A);
    //Enables individual timer interrupt sources.
    TimerIntEnable(TIMER0_BASE,TIMER_TIMA_TIMEOUT);
    //Enables a sample sequence interrupt.
    IntEnable(INT_ADC0SS1);
    ADCIntEnable(ADC0_BASE,1);
    IntMasterEnable();
    TimerEnable(TIMER0_BASE,TIMER_A);
}
//*****************************************************************************
// The SSI configuration.
//*****************************************************************************
void SSI0Init(void)
{   //Enable the SSI0 peripheral
    SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    GPIOPinConfigure(GPIO_PA4_SSI0RX);
    GPIOPinConfigure(GPIO_PA5_SSI0TX);
    GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5|GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2);
    // wait for the SSI0 module to be ready
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0))
    {
    }
    // Configure the SSI
    SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(),SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 2000000, 16);
    // Enable the SSI module
    SSIEnable(SSI0_BASE);
    SSIIntEnable(SSI0_BASE, SSI_TXFF | SSI_RXFF);
    //Send some data
    pui32DataTx[0]=0x3900;
                SSIDataPut(SSI0_BASE, pui32DataTx[0]);
}
//*****************************************************************************
// The PWM Handler.
//*****************************************************************************
void PWM0GEN3IntHandler(void)
{
    // Clear the timer interrupt
    PWMGenIntClear(PWM0_BASE, PWM_INT_GEN_3,PWM_INT_CNT_ZERO);
}
//*****************************************************************************
// The Timer0 Handler.
//*****************************************************************************
void Timer0IntHandler(void){
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
}
//*****************************************************************************
// The ADC Handler.
//*****************************************************************************
void ADC0SS1IntHandler(void){
    ADCIntClear(ADC0_BASE,1);
    ADCSequenceDataGet(ADC0_BASE,1,ADC0Value); // Get Data from ADC and store it in ADC0Value
    VoltageIN = ((ADC0Value[0])/(4095.0))*3300; //get mV
           VoltageOUT = ((ADC0Value[1])/(4095.0))*3300; //get mV
           uint32_t RawCurrentIn=((ADC0Value[2])/4096.0)*3300; //get uV
           uint32_t RawCurrentOUT=((ADC0Value[3])/4096.0)*3300; //get uV
           CurrentIN=((RawCurrentIn-1620)/65.0)*1000;//get mA Voffset = 2620; mVperAmp = 65
           CurrentOUT=((RawCurrentOUT-1620)/65.0)*1000;//get mA Voffset = 2620; mVperAmp = 65
}
//*****************************************************************************
// The UART0 Handler.
//*****************************************************************************
void
UART0IntHandler(void)
{
    uint32_t ui32Status;
    // Get the interrrupt status.
    ui32Status = UARTIntStatus(UART0_BASE, true);
    // Clear the asserted interrupts.
    UARTIntClear(UART0_BASE, ui32Status);
    // Loop while there are characters in the receive FIFO.
    while(UARTCharsAvail(UART0_BASE))
    {
        // Read the next character from the UART and write it back to the UART.
        UARTCharPut(UART1_BASE, UARTCharGet(UART0_BASE));
        // Blink the LED to show a character transfer is occuring.
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        SysCtlDelay(SysCtlClockGet() / (1000 * 3));
        // Turn off the LED
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
    }
}
//*****************************************************************************
// The UART1 Handler.
//*****************************************************************************
void
UART1IntHandler(void)
{
    uint32_t ui32Status;
    // Get the interrrupt status.
    ui32Status = UARTIntStatus(UART1_BASE, true);
    // Clear the asserted interrupts.
    UARTIntClear(UART1_BASE, ui32Status);
    // Loop while there are characters in the receive FIFO.
    while(UARTCharsAvail(UART1_BASE))
    {
        // Read the next character from the UART and write it back to the UART.
        UARTCharPut(UART0_BASE, UARTCharGet(UART1_BASE));
        RecVoltage=UARTCharGet(UART1_BASE);
        // Blink the LED to show a character transfer is occuring.
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, GPIO_PIN_1);
        // Delay for 1 millisecond.  Each SysCtlDelay is about 3 clocks.
        SysCtlDelay(SysCtlClockGet() / (1000 * 3));
        // Turn off the LED
        GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_1, 0);
    }
}
//*****************************************************************************
// The SSI0 Handler.
//*****************************************************************************
void SSI0IntHandler(void)
{
    // Clear the timer interrupt
    SSIIntClear(SSI0_BASE, SSI_TXFF| SSI_RXFF);
    // Wait for the SSI0 module to be ready.
 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0))
        {
        }
        // Send some data.
    pui32DataTx[0]=0x3F00;
    SSIDataPut(SSI0_BASE, pui32DataTx[0]);
}
//*****************************************************************************
// The Protection function.
//*****************************************************************************
void Protection(void)
{if((VoltageOUT<600)||(VoltageOUT>2500)||(RecVoltage=='b'))
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, GPIO_PIN_3);
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, GPIO_PIN_6);
}
if((VoltageOUT>600)||(VoltageOUT<2500)||RecVoltage=='a')
{
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_3, 0);
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_6, 0);
}
if((VoltageOUT<600)||(VoltageOUT>2500))
        {
            if(isRecVoltageSent==0)
            {
              UARTCharPut(UART1_BASE,'b');
              SysCtlDelay(SysCtlClockGet() / (1000 * 3));
              UARTCharPut(UART1_BASE,'b');
              SysCtlDelay(SysCtlClockGet() / (1000 * 3));
              UARTCharPut(UART1_BASE,'b');
              GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);
              SysCtlDelay(SysCtlClockGet() / (1000 * 3));
              GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);
              isRecVoltageSent=1;
            }
        }
        else
        {
           if(isRecVoltageSent==1)
            {
              UARTCharPut(UART1_BASE,'a');
              SysCtlDelay(SysCtlClockGet() / (1000 * 3));
              UARTCharPut(UART1_BASE,'a');
              SysCtlDelay(SysCtlClockGet() / (1000 * 3));
              isRecVoltageSent=0;
            }
        }
}

int
main(void)
{
   
    FPUEnable();
    FPULazyStackingEnable();
    //
    // Set the clocking to run directly from the crystal.
    //
    SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    UartInit();
    ADCInit();
    PWMInit();
    SSI0Init();
    IntPrioritySet (INT_TIMER0A, 0);
    IntPrioritySet (INT_ADC0SS1, 10);
    IntPrioritySet (INT_UART1, 20);
    IntPrioritySet (INT_UART0, 30);
    IntPrioritySet(INT_PWM0_3,40);
    IntPrioritySet (INT_SSI0, 50);

    while(1)
    {
       Protection();
            }
        }
  • Hi,

    What do you mean the SSI0 interrupt doesn't work? If you have all modules running then the SSI0 interrupt doesn't come but if you only have the SSI0 running then it works ok. Is this the problem?

    The question is if you want higher priority for the SSI0 than other modules or not. You are putting the SSI0 in the lowest priority for now. After reset, the SSI0 is actually higher priority than other PWM0, ADC and TIMER0 but you change to make SSI0 lowest priority among your modules. Is this what you want. In addition, only the upper 3 bits are looked at when decoding the priority.  See below.

    Prototype:
    void
    IntPrioritySet(uint32_t ui32Interrupt,
    uint8_t ui8Priority)
    Parameters:
    ui32Interrupt specifies the interrupt in question.
    ui8Priority specifies the priority of the interrupt.
    Description:
    This function is used to set the priority of an interrupt. The ui32Interrupt parameter must be
    one of the valid INT_ values listed in Peripheral Driver Library User’s Guide and defined in the
    inc/hw_ints.h header file. The ui8Priority parameter specifies the interrupts hardware priority
    level of the interrupt in the interrupt controller. When multiple interrupts are asserted simultaneously,
    the ones with the highest priority are processed before the lower priority interrupts.
    Smaller numbers correspond to higher interrupt priorities; priority 0 is the highest interrupt
    priority.
    Note:
    The hardware priority mechanism only looks at the upper 3 bits of the priority level, so any prioritization
    must be performed in those bits. The remaining bits can be used to sub-prioritize the
    interrupt sources, and may be used by the hardware priority mechanism on a future part. This
    arrangement allows priorities to migrate to different NVIC implementations without changing
    the gross prioritization of the interrupts.
    Example: Set priorities for UART 0 and USB interrupts.
    //
    // Set the UART 0 interrupt priority to the lowest priority.
    //
    IntPrioritySet(INT_UART0, 0xE0);
    //
    // Set the USB 0 interrupt priority to the highest priority.
    //
    IntPrioritySet(INT_USB0, 0);

  • Thank you so much for your response. Actually, I already had problem with priority interrupt before, and I got this too. For my code whatever of priority for SSI Interrupt I put is not the matter, I put the lowest or the highest, it works ( I mean there are signal from SSI pins PA2, PA3, PA4, PA5).
    However, when I just test only function SSIInit qnd SSIHandler, it's fine, but when I put them together with other module I do not get anything from SSI pins (both lowest and highest priority).
    when I cut 2 lines pui32DataTx[0]=0x3F00;
    SSIDataPut(SSI0_BASE, pui32DataTx[0]); from SSIHandler to while() in main(void), it works.
    I do not know which problem I have when I put this function in SSIHandler.
    Thank you so much for your help.

  • Hi,
    I think the reason is due to the FIFO. The FIFO is 8 locations deep. For receive, Interrupt is generated when the FIFO is at least half full. You must have received at least 4 words before interrupt is generated. In order to receive 4 words the master must first generate 4 words of transmission since the SSI is full-duplex. Try to generate 4 SSIDataPut before your while(1) and the rest in your SSIHandler.