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.

TM4C129 Hard fault error after Interrupts are enabled.

Other Parts Discussed in Thread: TM4C129ENCPDT

Hi,

Hi, I'm running code on Cortex TM4C129ENCPDT.

Our boot loader runs and make a jump to address 0x8000 where our application resides.

our application/main.c runs until I enable interrupts (call to IntMasterEnable() ) and immediately after, I jump to hard fault handler.

If I disable our boot loader/Ethernet configuration, our application runs fine. This is telling me that there is no problem with the Ethernet interrupts that are waiting to be serviced.

I tried disabling all interrupts and clearing pending interrupts after the jump to 0x8000 in our application/main( ) but no success:

  1. SysCtlPeripheralReset( ) for all peripherals
  2. IntDisable( ) for all interrupts
  3. IntPendClear( ) for all interrupts

I have included extract of the boot loader main( ) and the application main( ).

//extract of our main.c 
int main(void) { 
	IntMasterDisable(); 
	SystemInit();			//clock and system setup 
	GPIO_Init();			//setup GPIO 

	IntMasterEnable();		//goes into hard fault AFTER this instruction 

	os_sys_init(taskInit);
} 
//extract of our bootloader 
int main.c(void) { 
	IntMasterDisable( ); 
	SystemInit();				//set's gSysCtlClock
	GPIO_Init(); 
	EnetReconfig(gSysCtlClock);	//from boot_loader/bl_emac.c

	//bootloader code goes here ... 
	
	HWREG(NVIC_VTABLE) = 0x8000; 
	jump_to_application(); 
} 
//jump to application 
__asm void jump_to_application(void) { 
	ldr r1, [r0] 
	mov sp, r1 
	ldr r0, [r0, #4] 
	bx r0 
}

What Am I missing?

Khaled.

  • Hello Khaled

    Has the Vector table base address updated with the application base address for interrupts. Also if you debug the Fault Status and Fault Address register in NVIC address space, what type of fault is being shown.

    Regards
    Amit
  • Hi Amit
    The vector address table seems to be pointing to the proper values
    //extract from the .map file
    __Vectors 0x00008000 Data 4 startup_tm4c129.o(RESET)
    __Vectors_End 0x00008200 Data 0 startup_tm4c129.o(RESET)

    I'm not sure how to check the NVIC address space for the fault status and fault address.
    But I checked the PC value and its pointing to rt_put_rdy_first function! I beleive its an RTL bios function.

    Khaled.
  • Hello Khaled,

    See Issue#7 in the following post

    e2e.ti.com/.../374640

    Regards
    Amit
  • 0xE000ED28: 0x00000400

    0xE000ED38: 0xE000EDF8

    I'm including the fault report provided by Keil/uVision tools

  • Hi Amit,
    Just as a reminder: if I disable the bootloader/Ethernet, everything works fine.
    This is probably pointing to a problem with an interrupt that was generated by the Ethernet AFTER I finished with the bootloader but was serviced only after I started our application and AFTER I re-eanble the interrupts (call to IntMasterEnable() ).

    Is there a way to clean up the bootloader configurations and start fresh?
    khaled
  • Hello Khaled,

    Has the Vector Table been relocated to the application offset?

    Regards
    Amit
  • Amit

    I did not do anything specific to relocate the vector Table. I changed the Flash start address to 0x8000 and build the project. I checked the map file and it seems that everything was offset to 0x8000. I'm attaching the map file for your reference.

    Khaled.

    Cortex_Release_map.txt

  • Hello Khaled,

    I understand that. But does the boot loader correctly configure the VECTTABLE register for 0x8000?

    Regards
    Amit
  • I believe it does. I manually checked the first few bites at address 0x8000 and they seems to be correct. In addition, if I disable the bootloader/Ethernet driver, I'm the application which uses Interrupts, tasks, Mutex... runs fine.
    Khaled.
  • Hello Khaled,

    Did you try to single step to see what action causes the FaultISR?

    Regards
    Amit
  • Hello Amit

    Yes I did try it. The fault happens as soon as I enable interrupts in our application and just before starting RTX Bios.

    Khaled

  • Hello Khaled

    Since it is an Imprecise Bus Fault, you need to check the value of the CPU registers, assembly instruction being executed and which location it is accessing. There is no alternative other than to debug.

    Regards
    Amit
  • Hi Amit,

    I did the manual debug on the assembly code using F11 all the way the behavior change and I'm able to run all the way. If I use F10, I go into hardfault handler just after I enable interrupts using IntMasterEnable( ) function and as soon as I start the RTX/os_sys_init( ) function . I'm not sure what other clues I can give to you.

    I tried to move the IntMasterEnable( ) function to the end of taskInit( ) (our tasks initialization function that is called at the end of main.c/os_sys_init(taskInit) to start RTX, but no change: I still go into hard fault handler as soon as I start the RTX/os_sys_init( ).

    It has to do with an EMAC interrupt that was pending and was serviced before I got the chance to enable RTX. I'm attaching the NVIC snapshot.

    Khaled.

  • Hello Khaled,

    That is strange. An un-pending should clear the interrupt. unless a background task is setting it back. When it goes to the fault handler, does the unpending operation show that it has been cleared? If not, then perhaps there is a task which is still setting it.

    Regards
    Amit
  • Hi Amit
    I agree, the un-pending should clear the interrupt, but another interrupt is beeing scheduled after!
    I tried to disable as much of our application/main.c code but the hard fault is still being triggered.
    Only when I disable the Ethernet in the bootloader/main.c that the hard fault error goes away.

    So, as a test, I kept all the code enabled and physically disconnected the Ethernet plug, but the hard fault still triggered ==> the interrupt is not generated from the PC! I even checked the NVIC table and there is no pending interrupt from Ethernet when the Ethernet is unplugged. But a UART3 interrupt is pending although I have no physical connection to that port!

    Nothing makes sens.
    Khaled.
  • Hello Khaled,

    OK, as another experiment, disable all Interrupts using a direct write to the NVIC DIS registers and unpend, then do a clean start in the Application.

    Regards
    Amit
  • Hi Amit,
    Another dead end: disabled and un-pend all interrupts just before I jump in our bootloader/main.c AND disabled and un-pend all interrupts in our application/main.c and STILL had a hard fault.

    For some reason the UART3 interrupt and the systick interrupt did not get cleared!
    checked the code and I AM calling IntDisable(INT_UART3_TM4C129); and IntPendClear(INT_UART3_TM4C129); and I have no physical connection to that port, so where did the interrupt come from?

    Khaled
  • Hello Khaled

    Is SysTick Timer enabled when the jump happens? Also IntDisable(INT_UART3) and IntPendClear(INT_UART3) is sufficient.

    Regards
    Amit
  • Yes systick is enabled (see NVIC snapshot from 11:28).
    IntDisable(INT_UART3) and IntPendClear(INT_UART3) should be enough but they are not!

    The more I think about it, it seems that it has to do with RTX bios and how it's configured. I don't see any other logic cause.

    Khaled.
  • Hello Khaled

    Disable the SysTick timer before branching to the application, ensure VTABLE is updated with the application base address and once in the application enable the SysTick Timer.

    Regards
    Amit
  • I will need help, I tried to disable systick using SysTickDisable( ) function from tivaware but no success: from the NVIC, the system tick timer is still enabled and still pending.

    As for Vtable, how can I ensure that the Vtable is updated with the application base address? is there a command or I should check it manually (and how)?
    Khaled.
  • Hello Khaled

    Looks like the RTOS is enabling it. You would need to check the with RTOS vendor.

    As for the VTABLE, check the address 0xE000ED08. It should have the value 0x8000.

    Regards
    Amit
  • checked the memory at address 0xE000ED08 and its 0x8000.
    I will check with keil on the systick.

    But where does that leaves us? what is next?
    Khaled.
  • Hello Khaled,

    So the boot loader has correctly loaded the VTABLE and that is good news.

    As for the SysTick Timer, I checked and the SysTickDisable API call in my use case correctly disables the SysTickTimer.

    Regards
    Amit
  • Hi Amit,

    Reaching the end now :-) I spoke with Keil support and they suggested (among other things) to explicitly clear the  systick's exception pending bit

         "SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk; //clear systick's exception pending bit"
    where SCB == 0xE000E000UL, ICSR == 0x04 and SCB_ICSR_PENDSTCLR_Msk is the 25th bit.

    Adding this instruction did the job.

    But I had to include Keil .h files which are conflicting with TI's .h files.

    Does Tivaware has similar instruction that I could use?

    thanks.

    Khaled.

  • Hello Khaled

    IntPendClear(FAULT_SYSTICK) in the interrupt.c does the same operation.

    HWREG(NVIC_INT_CTRL) |= NVIC_INT_CTRL_PENDSTCLR;

    Regards
    Amit