Author Topic: Code hitting irq_hard_fault(void)  (Read 16337 times)

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Code hitting irq_hard_fault(void)
« on: August 05, 2010, 06:07:07 PM »
Hi Mark,

Just after a bit of advice, I'm using Rowley crossworks V1.7b22 and have an application, that seems to have problems running with the JTAG.

If I build the code as "Bare minimum bootloader" it works fine with the bootloader.
If I build it using the Rowley command "Build and Debug" in either "THUMB Flash Debug" or "THUMB Flash Release" modes it hits irq_hard_fault and thats it.
If I build it using the Rowley command "Build and Run" it builds but does not run (maybe it locks up as above) but if you press the reset switch it runs.

I can get arround this by building then resetting the board then attaching the debugger, but this operation is different to all the other projects I've created.

When I hit the irq_hard_fault loop the call stack does not show anything helpful, just irq_hard_fault.

Any pointers that might help me?

Cheers

Martin

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Code hitting irq_hard_fault(void)
« Reply #1 on: August 09, 2010, 11:21:40 PM »
Hi Martin

Sorry about being so quiet for the past few days - unfortunately I haven't experienced this behavior and therefore don't have any immediate suggestions.
Did you manage to get an improvement in the meantime?

Regards

Mark

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Code hitting irq_hard_fault(void)
« Reply #2 on: August 17, 2010, 11:48:33 PM »
Hi Martin

I have actually hit a similar problem after adding TFT touch panel control to a board with the LM3S1958 on it. The touch control uses a timer at 1kHz triggering ADC conversions - the completion of the conversion interrupts the processor.

The SW runs when reset but fails with hard error when working with the debugger. What I can't however do is connect after the board is running since it immediately goes to the hard error again after connection.

What I have however see is the following - I didn't find a work around yet though:
1) When the debugger connects it lets the board run for about 2.5s. In this time everything works normally since I can see images in the display and a PWM output is controlling its intensity.
2) The the debugger resets and stops at main()
3) What I noticed as that the PWM output was however still controlling the brightness although the debugger has supposedly just reset the chip. Looking at the peripheral power register all peripherals are still powered up.
4) What seems to happen is that when the touch screen configuration takes place the ADC already has samples waiting and, when the IRQ in the NIC is enabled it is in fact immediately interrupting although the ADC has neither been started. The interrupt handler is probably not ready and so it hard-faults.
5) What I saw was that an ADC source interrupt was pending in the NVIC even before the code had started. Even if I remove power to the timer and ADC I don't seem to be able to get rid of the pending interrupt.

For the moment I can't debug when the touch screen code is enabled...

Does your problem perhaps have a similar source???

Regards

Mark


Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Code hitting irq_hard_fault(void)
« Reply #3 on: August 18, 2010, 05:58:55 PM »
Hi Mark,

Interesting thought, maybe the think to do is to put an Idle timer in the startup code that will wait for 1 - 2 secs in a loop at powerup, if you are in debug mode. This way the chip would not do anything (not enable any peripherals etc).

Its not the biggest thing on my list at the moment just a frustration.

Regards

Martin

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Code hitting irq_hard_fault(void)
« Reply #4 on: October 27, 2010, 10:34:14 AM »
Hi Mark,

I've done a bit of investigation on another board that exhibits the same symptons, in debug mode it hits irq_hard_fault. But runs if the debugger is not connected. Like you I've found it to be ADC related.

If I don't initialise the ADC then it works fine.

I noticed that fnEnterInterrupt was being called quite late in the routine and wondered if this needed to be setup earlier, I tried moving it up but still had the same problem :-(

Have you managed to make any progress with this?

Cheers

Martin
               

fnEnterInterrupt(irq_ADC_Sequence_0_ID, ptrADC_settings->int_priority, _ADC_sequence_0_complete); // enter the interrupt

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Code hitting irq_hard_fault(void)
« Reply #5 on: October 27, 2010, 12:37:43 PM »
Hi Martin

I thought that I had removed this by clearing pending interrupts when entering new interrupts.

Certainly the reason is that the debugger stops the processor after it has run for a short time and has started timers (for example) and then its reset doesn't seem to be a (full) hardware reset, thus leaving timers running and some interrupts possibly pending.

When these interrupts are enabled this is performed before the timers have been started by the code and so it is not expected that they are already running and can already have interrupts pending. The result is that as soon as the interrupt source is enabled at source the interrupt fires even though its handler has not been entered yet. Also stopping or resetting the timer beforehand doesn't necessarily help since the interrupt is still pending in the NVIC.

I made the following change, which I thought that you had:


// Function used to enter processor interrupts
//
static void fnEnterInterrupt(int iInterruptID, unsigned char ucPriority, void (*InterruptFunc)(void))
{
    unsigned long *ptrIntSet = IRQ0_31_SER_ADD;
    unsigned char *ptrPriority = IRQ0_3_PRIORITY_REGISTER_ADD;
    VECTOR_TABLE *ptrVect;
    void ( **processor_ints )( void );
    unsigned long ulInterruptBit;
    ptrVect = (VECTOR_TABLE *)(START_OF_SRAM + RESERVE_DMA_MEMORY);
    processor_ints = (void (**)(void))&ptrVect->processor_interrupts;
    processor_ints += iInterruptID;
    *processor_ints = InterruptFunc;

    ptrIntSet += (iInterruptID/32);                                      // move to the corresponding set enable register address
    ulInterruptBit = (0x01 << (iInterruptID%32));
    *(ptrIntSet + (IRQ0_31_CPR_ADD - IRQ0_31_SER_ADD)) = ulInterruptBit; // {31} clear possibly pending bit (can occur when working with debugger)
    *ptrIntSet = ulInterruptBit;                                         // enable the interrupt

    ptrPriority += iInterruptID;
    *ptrPriority = ucPriority;                                           // define the interrupt's priority
}


[note that some simulator code has been removed for clarity].

This solved my problem (when developing some 16 bit timer code).

I don't know whether this is restricted to the Crossworks debugger or not(?)

Regards

Mark

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Code hitting irq_hard_fault(void)
« Reply #6 on: October 27, 2010, 01:15:50 PM »
Hi Mark,

Yes I have this code, but I still get the problem. I'm using Rowley 1.7b22 and the Luminary Micro ICDI as my Jtag.

What I was trying to do by moving

fnEnterInterrupt(irq_ADC_Sequence_0_ID, ptrADC_settings->int_priority, _ADC_sequence_0_complete); // enter the interrupt

was to ensure that the interupt handler was setup first, before the ADC was enabled.

Regards

Martin

Offline mhoneywill

  • Full Member
  • ***
  • Posts: 173
    • View Profile
Re: Code hitting irq_hard_fault(void)
« Reply #7 on: March 03, 2011, 07:00:05 PM »
Hi Mark,

I'd been ignoring this problem as most of my code does not use the ADC, but have just come across it again.

I think I've fixed my problem by doing the following

                    RCGC0 |= CGC_SARADC0;                                // enable clocks to ADC module
                    RCGC0 |= CGC_SARADC0;                                // repeat above command to give the ADC module time to wakeup
                    ADCACTSS_0 &= ~ASEN0;                                // ensure sequencer is disabled before configuring
                    ADCEMUX_0 &= ~SS0_MASK;                              // clear sequencer mode

Arround line 4657 in the function fnConfigureInterrupt in LM3Sxxxx.c I've added the above line in RED, I think the access to the ADCACTSS_0 register was happening before the ADC module had powered up. Hence I was getting an irq_hard_fault

It seems to be working fine now, I can download from Rowley in Debug mode and start debugging into the code. This may not have been your problem but it might be worth incorporating or checking out (Still not quite sure why the release build without the JTAG just worked)

Cheers

Martin

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Code hitting irq_hard_fault(void)
« Reply #8 on: March 04, 2011, 11:31:28 PM »
Hi Martin

It is true that it may take a few clocks before peripherals are ready for use after they are powered on.
I know that the Luminary library doesn't have this problem since it uses subroutine calls which slow the code down enough avoid this, but most code in the uTasker project avoids "unnecessary" subroutine calls or uses macros and so can encounter conditions where there could be such problems.
In most cases you will see that, where possible, code is inserted between the power up of the peripheral and the first access to it, which effectively also gives the peripheral some extra clock times to get ready.

In the case of the ADC I didn't notice any problems but it may be device and CPU speed dependent. In this case I have also added your suggestion so that this code location shouldn't become a potential source of difficulties.

Regards

Mark