Debugging a hard fault (Precise data bus error) with J-Link and GDB on S32K146

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Debugging a hard fault (Precise data bus error) with J-Link and GDB on S32K146

2,892 Views
NJ37
Contributor II

Hi NXPeeps,

I am trying to use the LPIT (low power interrupt timer) to toggle the LED on NXP S32K146.

I have configured a timer channel (the second channel, LPIT 1) and after init and enabling, it works the first time. However when stopping and starting the timer, I run into the same hard fault each time when I try to clear the interrupt flag:

LPIT_DRV_ClearInterruptFlagTimerChannels(INST_LPIT1, (1 << 1U));


Few notes

- While it always faults at the same address (MSR), when it occurs is indeterministic. i.e. sometimes after the 3rd interrupt, sometimes after 7th, and so on.

BFAR Address: 0x4003700C

- I do not run into this fault when I step through with the debugger (with J-Link GDB server on SWD).

- I have checked the values being written (mask), MCR and if clocks are enabled, and those seem fine.

I am running out of ideas to debug the issue, could you help me?
Thanks!

Tags (4)
0 Kudos
Reply
13 Replies

2,864 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@NJ37

Please share your project, it will be easier for me to handle your issue.

0 Kudos
Reply

2,854 Views
NJ37
Contributor II

Sure, this is the gist:

#define LP_LED_TIMER_CHANNEL  (1U)

// Enable timer
LPIT_DRV_StartTimerChannels(INST_LPIT1, (1 << LP_LED_TIMER_CHANNEL));

// Some other ops

// Disable timer
LPIT_DRV_StopTimerChannels(INST_LPIT1, (1 << LP_LED_TIMER_CHANNEL));
LPIT_DRV_ClearInterruptFlagTimerChannels(INST_LPIT1, (1 << LP_LED_TIMER_CHANNEL));

// Re-enable timer
LPIT_DRV_StartTimerChannels(INST_LPIT1, (1 << LP_LED_TIMER_CHANNEL));


The issue is that when I re-enable timer, it invokes ISR a few times before slowing down (instead of 100 ms, it invokes it once every 4-6 seconds). It does that a few times (between 0 to 20) before eventually hard faulting. I have root caused the instruction to be

static inline void LPIT_ClearInterruptFlagTimerChannels(LPIT_Type * const base, uint32_t mask)
{
    /* Write 1 to clear the interrupt flag. */
    base->MSR = mask; // Accessing base->MSR is invalid for some reason and returns a precise bus error at 0x4003_700C
...
}


How can I debug this further? Thanks.

Config and ISR follows:

The LPIT_DRV functions are from S32_SDK_RTM_3.0.1/platform/drivers/src/lpit/lpit_driver.c.

 I do a Preinit of the timer and channel (I do not use channel 0, only channel 1 for my purpose of toggling LED) in the main RTOS task:

void LP_LED_TIMER_Preinit(void) {
    lpit1_ChnConfig1.period = 100000U;
    lpit1_ChnConfig1.periodUnits = LPIT_PERIOD_UNITS_MICROSECONDS;
    lpit1_ChnConfig1.enableReloadOnTrigger = true;
    lpit1_ChnConfig1.enableStopOnInterrupt = false;
    lpit1_ChnConfig1.timerMode = LPIT_PERIODIC_COUNTER;

    LPIT_DRV_Init(INST_LPIT1, &lpit1_InitConfig);
    
    /* Initialize LPIT channel 1 */
    (void)LPIT_DRV_InitChannel(INST_LPIT1, LP_LED_TIMER_CHANNEL, &lpit1_ChnConfig1);
    
    /* Install LPIT_ISR as LPIT interrupt handler */
    INT_SYS_InstallHandler(LPIT0_Ch1_IRQn, &sLPITIsr_1, (isr_t *)0);
    
    INT_SYS_SetPriority(LPIT0_Ch1_IRQn, 1);
}

 

I used DS to generate timer configuration as follows:

#include "lpit1.h"

/*! Global configuration of lpit1 */
const lpit_user_config_t lpit1_InitConfig =
{
    .enableRunInDebug = true,         /*!< true: LPIT run in debug mode; false: LPIT stop in debug mode */
    .enableRunInDoze = true           /*!< true: LPIT run in doze mode; false: LPIT stop in doze mode */
};

/*! User channel configuration 1 */
lpit_user_channel_config_t lpit1_ChnConfig1 =
{
    .timerMode = LPIT_PERIODIC_COUNTER,
    .periodUnits = LPIT_PERIOD_UNITS_MICROSECONDS,
    .period = 100000U,
    .triggerSource = LPIT_TRIGGER_SOURCE_EXTERNAL,
    .triggerSelect = 0U,
    .enableReloadOnTrigger = true,
    .enableStopOnInterrupt = false,
    .enableStartOnTrigger = false,
    .chainChannel = false,
    .isInterruptEnabled = true
};

 

My ISR looks like:

void sLPITIsr_1(void) {
  LP_LED_TIMER_ClearInterruptFlag();
  // Toggle LED
  DRV_IO_WriteOutput(g_pBlinkLedPin, !g_blinkLedIsOn);
  g_blinkLedIsOn = !g_blinkLedIsOn;
}

 

0 Kudos
Reply

2,848 Views
NJ37
Contributor II

New finding from today:
The hard fault happens after a switch from normal power state to VLPS on the MCU.

The re-enabling of timer also happens at that time. I also read from PCC LPIT register and found that right before it hard faults, the PCC is disabled. i.e. at other times, the value at 0x400650DC is 0xC3000000 but right before the fault it is 0x83000000. I guess since PCC is disabled, that is why LPIT registers are not accessible.

But need to find out what is disabling the PCC during the VLPS switch. Any hints appreciated.

0 Kudos
Reply

2,837 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@NJ37

"The hard fault happens after a switch from normal power state to VLPS on the MCU."

Before entering low power mode, you can turn off LPIT or switch the module clock of LPIT to a clock source that can work in VLPS module.

 

2,816 Views
NJ37
Contributor II
Thank you, I need the LPIT during VLPS. How can I switch its clock source to LPO using the S32_SDK?
0 Kudos
Reply

2,796 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@NJ37

LPIT can not select LPO as clock source,also it will disabled in VLPS mode.

Please share your whole project and i will help you to test .

0 Kudos
Reply

2,763 Views
NJ37
Contributor II

Thanks, I'm unable to share the project as it is under NDA..

But I do see that from the S32K1xx series reference manual, rev 14, LPIT is fully functional in VLPS mode if SIRC is selected as clock source.

Can you confirm this?
Also will LPIT's interrupts get serviced during run mode by NVIC (after AWIC detects the interrupt as an async wake up source and signals run)?

0 Kudos
Reply

2,680 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@NJ37

Yes, LPIT can continue to run in VLPS if SIRC clock is selected. Also I found that this bit also needs to be set.

MCR[DOZE_EN]

Senlent_0-1736733880948.png

An interrupt can be triggered by AWIC in VLPS and the MCU can be taken out of VLPS

0 Kudos
Reply

2,638 Views
NJ37
Contributor II
Many thanks for confirming. I can see that MCR reads as 'D', and that bit is set. I think I may be close to root causing the issue (likely at our end). Could you answer one more thing?

I see that CLOCK_SYS_UpdateConfiguration from NXP SDK says it should only be called in Run mode. I find in our code we use it in a power manager callback registered with VLPS i.e. it gets called when we do POWER_SYS_SetMode(VLPS, POWER_MANAGER_POLICY_AGREEMENT);.

What are the consequences of this?
0 Kudos
Reply

2,615 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@NJ37

The clock configuration is done by the user in the graphical interface.

You can see that POWER_SYS_SetMode() will configure the clock, so when the MCU enters VLPS, you don't need to call "CLOCK_SYS_UpdateConfiguration".

When your MCU wakes up from low power mode, you only need POWER_SYS_SetMode(RUN, POWER_MANAGER_POLICY_AGREEMENT);

2,579 Views
NJ37
Contributor II
Right - but in our case, we have our custom clock_config.c in addition to ProcessorExpert.pe. In that case, doesn't it make sense to configure the clock with additional callbacks whenever POWER_SYS_SetMode is used?
0 Kudos
Reply

2,517 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@NJ37

Please refer to the routine "power_mode_switch_s32k14x" we provide in S32 DS, test it by yourself.

0 Kudos
Reply

2,840 Views
Senlent
NXP TechSupport
NXP TechSupport

Hi@NJ37

Please provide me with the project directly, not the code snippets.

0 Kudos
Reply