TM4C123GH6PM: This is the code that gets called when the processor receives a fault interrupt" message

Part Number: TM4C123GH6PM

Hello Guys,

Good day.

Our customer is trying to build GPIO drive from scratch and as he work on instruction on gpio section by setting the corresponding bit on RCGCTIMER register, the bit did not set and go to interrupt . What could be the possible issue?
The debugger gives him this note
"This is the code that gets called when the processor receives a fault
interrupt.  This simply enters an infinite loop, preserving the system state
  for examination by a debugger."

Thanks and regards,

Art

  • Hi,

      Is there any reason why the customer would not use the TivaWare peripheral driver library? It is a proven driver library for customer to have a fast s/w development. You said about building GPIO driver and then mentioned about setting bits in RCGCTIMER. The RCGCTIMER is a clock gating register for TIMER module, not for GPIO. The RCGCGPIO register is the one to enable the clock to the GPIO module if the problem the customer has is due to the clock. Again, I strongly recommend customer use the TivaWare library for s/w development. Writing code in DRM (direct memory manipulation) is very prone to mistakes. Please also refer to the FAQ #4 in https://e2e.ti.com/support/microcontrollers/other/f/other-microcontrollers-forum/695568/faq-read-before-posting-tm4c-forum-general-guidelines that we do not support DRM style of coding. 

  • Hi Charles,

    I have attached the file from the customer. See "GPIO_TEST4.rar"
    Maybe you'll find error upon reviewing. He is still encountering the same issue.

    GPIO_TEST4.rar

    Thanks and regards,

    Art

  • Hi,

      I ran the test code and the code got stuck in the RCC_INIT which is the clock initiation. There is really no benefit to reinvent the wheel writing the clock initialization routine when TivaWare already has the driver doing exactly the same. Same can  be said for the rest of the drivers. The clock initiation is a very complicated software sequence and I will never recommend anyone writing their own. If the customer must write his own driver for it, I will suggest he references the TivaWare SysCtlClcokSet() on how it is done. I don't want to be rude but I will repeat again, I will not recommend writing the clock initiation from scratch and I have clearly stated in my last reply that we do not support DRM style of coding per our FAQ. If someone must write in DRM then please reference the TivaWare source code. 

    void
    SysCtlClockSet(uint32_t ui32Config)
    {
        uint32_t ui32Delay, ui32RCC, ui32RCC2;
    
        //
        // Get the current value of the RCC and RCC2 registers.
        //
        ui32RCC = HWREG(SYSCTL_RCC);
        ui32RCC2 = HWREG(SYSCTL_RCC2);
    
        //
        // Bypass the PLL and system clock dividers for now.
        //
        ui32RCC |= SYSCTL_RCC_BYPASS;
        ui32RCC &= ~(SYSCTL_RCC_USESYSDIV);
        ui32RCC2 |= SYSCTL_RCC2_BYPASS2;
    
        //
        // Write the new RCC value.
        //
        HWREG(SYSCTL_RCC) = ui32RCC;
        HWREG(SYSCTL_RCC2) = ui32RCC2;
    
        //
        // See if the oscillator needs to be enabled.
        //
        if((ui32RCC & SYSCTL_RCC_MOSCDIS) && !(ui32Config & SYSCTL_MAIN_OSC_DIS))
        {
            //
            // Make sure that the required oscillators are enabled.  For now, the
            // previously enabled oscillators must be enabled along with the newly
            // requested oscillators.
            //
            ui32RCC &= (~SYSCTL_RCC_MOSCDIS | (ui32Config & SYSCTL_MAIN_OSC_DIS));
    
            //
            // Clear the MOSC power up raw interrupt status to be sure it is not
            // set when waiting below.
            //
            HWREG(SYSCTL_MISC) = SYSCTL_MISC_MOSCPUPMIS;
    
            //
            // Write the new RCC value.
            //
            HWREG(SYSCTL_RCC) = ui32RCC;
    
            //
            // Timeout using the legacy delay value.
            //
            ui32Delay = 524288;
    
            while((HWREG(SYSCTL_RIS) & SYSCTL_RIS_MOSCPUPRIS) == 0)
            {
                ui32Delay--;
    
                if(ui32Delay == 0)
                {
                    break;
                }
            }
    
            //
            // If the main oscillator failed to start up then do not switch to
            // it and return.
            //
            if(ui32Delay == 0)
            {
                return;
            }
    
        }
    
        //
        // Set the new crystal value and oscillator source.  Because the OSCSRC2
        // field in RCC2 overlaps the XTAL field in RCC, the OSCSRC field has a
        // special encoding within ui32Config to avoid the overlap.
        //
        ui32RCC &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
        ui32RCC |= ui32Config & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
        ui32RCC2 &= ~(SYSCTL_RCC2_USERCC2 | SYSCTL_RCC2_OSCSRC2_M);
        ui32RCC2 |= ui32Config & (SYSCTL_RCC2_USERCC2 | SYSCTL_RCC_OSCSRC_M);
        ui32RCC2 |= (ui32Config & 0x00000008) << 3;
    
        //
        // Write the new RCC value.
        //
        HWREG(SYSCTL_RCC) = ui32RCC;
        HWREG(SYSCTL_RCC2) = ui32RCC2;
    
        //
        // Set the PLL configuration.
        //
        ui32RCC &= ~SYSCTL_RCC_PWRDN;
        ui32RCC |= ui32Config & SYSCTL_RCC_PWRDN;
        ui32RCC2 &= ~SYSCTL_RCC2_PWRDN2;
        ui32RCC2 |= ui32Config & SYSCTL_RCC2_PWRDN2;
    
        //
        // Clear the PLL lock interrupt.
        //
        HWREG(SYSCTL_MISC) = SYSCTL_MISC_PLLLMIS;
    
        //
        // Write the new RCC value.
        //
        if(ui32RCC2 & SYSCTL_RCC2_USERCC2)
        {
            HWREG(SYSCTL_RCC2) = ui32RCC2;
            HWREG(SYSCTL_RCC) = ui32RCC;
        }
        else
        {
            HWREG(SYSCTL_RCC) = ui32RCC;
            HWREG(SYSCTL_RCC2) = ui32RCC2;
        }
    
        //
        // Set the requested system divider and disable the appropriate
        // oscillators.  This value is not written immediately.
        //
        ui32RCC &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
                     SYSCTL_RCC_MOSCDIS);
        ui32RCC |= ui32Config & (SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
                                 SYSCTL_RCC_MOSCDIS);
        ui32RCC2 &= ~(SYSCTL_RCC2_SYSDIV2_M);
        ui32RCC2 |= ui32Config & SYSCTL_RCC2_SYSDIV2_M;
        if(ui32Config & SYSCTL_RCC2_DIV400)
        {
            ui32RCC |= SYSCTL_RCC_USESYSDIV;
            ui32RCC2 &= ~(SYSCTL_RCC_USESYSDIV);
            ui32RCC2 |= ui32Config & (SYSCTL_RCC2_DIV400 | SYSCTL_RCC2_SYSDIV2LSB);
        }
        else
        {
            ui32RCC2 &= ~(SYSCTL_RCC2_DIV400);
        }
    
        //
        // See if the PLL output is being used to clock the system.
        //
        if(!(ui32Config & SYSCTL_RCC_BYPASS))
        {
            //
            // Wait until the PLL has locked.
            //
            for(ui32Delay = 32768; ui32Delay > 0; ui32Delay--)
            {
                if((HWREG(SYSCTL_PLLSTAT) & SYSCTL_PLLSTAT_LOCK))
                {
                    break;
                }
            }
    
            //
            // Enable use of the PLL.
            //
            ui32RCC &= ~(SYSCTL_RCC_BYPASS);
            ui32RCC2 &= ~(SYSCTL_RCC2_BYPASS2);
        }
    
        //
        // Write the final RCC value.
        //
        HWREG(SYSCTL_RCC) = ui32RCC;
        HWREG(SYSCTL_RCC2) = ui32RCC2;
    
        //
        // Delay for a little bit so that the system divider takes effect.
        //
        SysCtlDelay(16);
    }
    
     

  • No worries Charles. I'll let the customer know as he is persistent for the code to be reviewed.

    Best regards,

    Art