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.

SW-EK-TM4C1294XL: Problems while debugging

Part Number: SW-EK-TM4C1294XL
Other Parts Discussed in Thread: TM4C1294NCPDT

Hi, fellas! I'm having some problems while debugging a software with TM4C1294NCPDT(Using TM4C1294XL evaluation board), in few words my code is getting stuck in the function SysCtlClockFreqSet(It takes to faultISR) and after read my code lots of times I couldn't see any problem in it. So I decided to use the fault registers, specifically the one located at  0xD28. After look around the CCS debugger, I saw the value 0x00009200 in the NVIC_FAULT_STAT register and after look in the datasheet it was easy to conclude that the fallowing bits are set :


BFARV --> Bus fault adress register valid

BSTKE --> Stack Bus Fault

PRECISE --> Precise Data Bus Error

BSTKE bit is set and this is driving me crazy because on the contrary I could easily solve the problem using the Texas manual to solve Faults(there is a problem in this doc that would perfectly fit). So I'm here to ask you guys help.

The code that I'm trying to run is attached to this thread.

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/adc.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "adc_utils.h"


void adc_init(void){

    /* Enabling the Peripheral ADC0 */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);

    /* Enabling Port E in order to read the values in ADC0 */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

	/* Selecting the pins to read ADC0 Values */
	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);

	/* Configuring Sample Sequence 3 in ADC0 */
	ADCSequenceConfigure(ADC0_BASE, ADC_SAMPLE_SEQUENCE_NUMBER,
	                     ADC_TRIGGER_PROCESSOR, 0);

	/*Configure steps in ADC0*/
	ADCSequenceStepConfigure(ADC0_BASE, ADC_SAMPLE_SEQUENCE_NUMBER, 0,
	                         (ADC_CTL_CH3 |ADC_CTL_IE| ADC_CTL_END));

	/* Enable the sample sequence in ADC0 */
	ADCSequenceEnable(ADC0_BASE, ADC_SAMPLE_SEQUENCE_NUMBER);

	/*cleaning the interrupt flag */
	ADCIntClear(ADC0_BASE, ADC_SAMPLE_SEQUENCE_NUMBER);
}


void adc_getSamples(uint32_t* adc0){
	/* Cleaning after aquisition*/
	ADCIntClear(ADC0_BASE,ADC_SAMPLE_SEQUENCE_NUMBER);

	/* Taking the samples*/
	ADCSequenceDataGet(ADC0_BASE, ADC_SAMPLE_SEQUENCE_NUMBER ,adc0);

}

/**
 * return 0 when data is not ready
 * return 1 when data is ready
 */
uint32_t inline adc_dataReady(void){

	/* Waiting the conversion complete */
	return ADCIntStatus(ADC0_BASE,ADC_SAMPLE_SEQUENCE_NUMBER,false);

}


void adc_trigger(void){
	/* Triggering the ADC0 */
	ADCProcessorTrigger(ADC0_BASE, ADC_SAMPLE_SEQUENCE_NUMBER);

}
adc_utils.h
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "adc_utils.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"

void myTimer0ISR(void);

void ConfigureTimer(void);

/*Global Variables */
uint32_t g_ui32SysClock;



/* implementing the FSM */
typedef enum my_states{
    SAMPLING,
    DISABLE_SAMPLING,
    PRINTING,
    IDLE
}State_t;

void
InitConsole(void)
{
    //
    // Enable GPIO port A which is used for UART0 pins.
    // TODO: change this to whichever GPIO port you are using.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Configure the pin muxing for UART0 functions on port A0 and A1.
    // This step is not necessary if your part does not support pin muxing.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinConfigure(GPIO_PA0_U0RX);
    GPIOPinConfigure(GPIO_PA1_U0TX);

    //
    // Enable UART0 so that we can configure the clock.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Use the internal 16MHz oscillator as the UART clock source.
    //
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);

    //
    // Select the alternate (UART) function for these pins.
    // TODO: change this to select the port/pin you are using.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 9600, 16000000);
}






int main(void) {

    /* Set the clocking to run at 120MHz */
    g_ui32SysClock= SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                        SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                        SYSCTL_CFG_VCO_480), 120000000);

    float adc_samples_voltage[NUMBER_OF_SAMPLES];
    uint32_t amostra_adc_0 = 1;

    /* control variables */
    //with 16bits we're able to get up to 65535
    uint16_t counter = 0;
    State_t current_state = SAMPLING;

    uint32_t loop= 0;
    adc_init();
    ConfigureTimer();

    /*starting the MCU's Job */
     while(1){
         switch(current_state){
             case SAMPLING:
                 while(!adc_dataReady());
                 adc_getSamples(&amostra_adc_0);
                 adc_samples_voltage[counter] = (amostra_adc_0);
                 counter++;

                if(counter == NUMBER_OF_SAMPLES){
                    current_state = DISABLE_SAMPLING;
                }
                else{
                    current_state = SAMPLING;

                }
                break;

            case DISABLE_SAMPLING:
                SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER0);
                current_state = PRINTING;
                break;

            case PRINTING:
                for(loop=0;loop<NUMBER_OF_SAMPLES;loop++){
                    UARTprintf("AIN0 = %4d\r", adc_samples_voltage[loop]);
                }
                break;

             case IDLE:
                /* do nothing */
                break;

            default:
                break;
         }
     }
    return 0;
}


void myTimer0ISR(void){
    /* cleaning the timer interruptions for timer 0 module in full-with mode */
    TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
    adc_trigger();

}

void ConfigureTimer(void){

    /* enabling the timer 0 peripheral */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    /* configurating the TIMER to use a 32bit periodic timer */
    TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);

    /* setting the timer load value */
    /* using only timer A cause we want a 32 bit timer */
    /* here we've 1Khz*/
    TimerLoadSet(TIMER0_BASE, TIMER_A,g_ui32SysClock/1000);


    /* Allow the use of the processor interrupts */
    IntMasterEnable();

    /* here we're setting the ISR to timer 0 */
    TimerIntRegister(TIMER0_BASE,TIMER_A,myTimer0ISR);

    /* enabling the interruptions for timer0 in full-with mode */
    /* It appears when timeout situation is got */
    /* again, using timer A because we're using full-with mode */
    TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);






    /* allowing interruptions for timer 0 */
    /* we use only timera because we're using full-with mode */
    IntEnable(INT_TIMER0A);



    /* Enabling Timer */
    TimerEnable(TIMER0_BASE, TIMER_A);
}

  • Hi James,
    Is the fault address something like 0x1FFFXXXX? If this is the case then you have overflowed your stack allocation. Can you try to increase your stack to see if it makes a difference since you indicated you had a stack bus fault.
  • Hi Charles,

    As such issues occur SO frequently here - might a "successful alternative" be to recommend such "increased stack" as the default?

    Users - thus avoiding such issue - may (later) dial down their stack usage - as and if - needed...
  • Hey, Charles. No, actually the NVIC_FAULT_ADDR has the value 0x1FFF67F8. Also, how con I increase the stack? Thanks
  • Hi cb1,
    I think it is always a compromise to not wasting memory resources. Currently the default stack size is 512. User normally needs to estimate the worst case based on the usage of local variables, return addresses and function arguments. Certainly this is not easy to do manually. There are tools to help analyze the required amounts even though I never used any of these 3rd party tools. People using the RTOS such as TI-RTOS can analyze the stack usage with the build-in tool.
  • Here I change to stack size to 1024. 

    In your .cmd file you need to change the stack pointer like:

    __STACK_TOP = __stack + 1024;

  • The code still stucks in SysCtlClockFreqSet even with a bigger stack
  • I will suggest you first decrease the number of samples from 10000 to something much smaller as you are creating an array of 10000 elements of float type. I don't think 1024 stack size will be sufficient. Try your like 10 elements and work your way up in conjunction with adjustment to the stack size.
  • Charles Tsai said:
    I think it is always a compromise to not wasting memory resources.

    But Charles - is not such, "(potential) waste of memory resources" FAR LESS DAMAGING than arriving bankrupt - entombed w/in Fault_ISR HELL?

  • Hi cb1,

    In this particular case, doubling or even quadruple the stack size may not cut it with a 10000 element float array. We don't know every customer's use case. For different TivaWare examples, there are different stack sizes used. For example, some Ethernet examples use 2kB of stack compared to 256 bytes for the timer examples. I don't think we can just use one stack size for all examples. There will be time when whatever the default stack size is not sufficient and it is very application dependent.
  • Particular cases aside - any survey here confirms that "insufficient stack size" is the dominant cause of, "User arrival w/in Fault_ISR!"

    Increasing the stack size - beyond that currently "in play" - (properly REACTS) to (i.e. lessens) a known issue!      (such reaction (strangely) encounters much resistance here!     (as proven by 0Ω LPad resistors (Plague-istors) long judged by (hapless) users as, "less than optimal" - yet "cast in concrete" - never to be corrected!)    (R9/R10 should be "bagged" - to be "fitted" (only) by those (very) FEW - who (may) use them!)