Hi everyone,
I am trying to port code from Stellaris LM4F232H5QD Development Kit to Tiva TM4C1231H6PM on a custom board. However, I occasionally face a FaultISR error. Code works correctly on the Development Kit.
I am using CCS v5.2.1 and the StellarisWare library.
The attached files are extracted code that involve collecting data from an analog temperature sensor (TMP20).
Problem:
- FaultISR occurs occasionally during program execution, sometimes the program works and runs to completion.
- FaultISR occurs randomly during the return operation from any of the following functions in the code: configureAnalogTemperature(), enableAnalogTemperature(), startAnalogTemperatureConversion(), and readAnalogTemperature(). This is checked via stepping through the assembly code.
What was done:
- Ensure correct port, pin, ADC channel used for the sensor.
- Tried increasing the stack size to 2048 and then to 4096.
- Disabled optimizations by the compiler.
- Ensured that peripherals used were properly enabled with sufficient delay.
- Following registers were checked when fault occurred.
PC and SP: Looks okay to me.
LR: 0xFFFF.FFF9
xPSR: 0x2100.0003, hard fault occurred.
NVIC_CFG_CTRL: 0x0000.0200, Stack Alignment on Exception Entry occurred.
NVIC_FAULT_STAT: 0x0000.0100 or 0x0000.0001, "Instruction Bus Error" or "Instruction Access Violation"
NVIC_HFAULT_STAT: 0x4000.000, forced hard fault occurred.
I can't seem to make out what is wrong even with the info above, with the lines of code causing the fault looking okay. Could anyone kindly suggest how I should proceed?
Regards,
Tian Hao
// test. // $HeadURL: $ // $Author: $ // $Date: $ // $Revision: $ // General. #include "inc/hw_types.h" #include "driverlib/rom.h" #include "driverlib/sysctl.h" // For Debug LED. #include "inc/hw_memmap.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" // For ADC testing. #include "driverlib/adc.h" // For Interrupt. #include "inc/hw_ints.h" #define ANALOG_TEMPERATURE_SYSCTL_PERIPH_ADC SYSCTL_PERIPH_ADC0 #define ANALOG_TEMPERATURE_ADC_BASE ADC0_BASE #define ANALOG_TEMPERATURE_ADC_SEQUENCE 3 #define ANALOG_TEMPERATURE_ADC_CHANNEL ADC_CTL_CH4 #define ANALOG_TEMPERATURE_SYSCTL_PERIPH_GPIO SYSCTL_PERIPH_GPIOD #define ANALOG_TEMPERATURE_GPIO_PORT_BASE GPIO_PORTD_BASE #define ANALOG_TEMPERATURE_GPIO_PIN GPIO_PIN_3 // Temporary buffer to hold data acquired from sensor. static unsigned long analog_temperature_buffer[1]; // Configure Analog Temperature Sensor. void configureAnalogTemperature (void) { // Enable the ADC peripheral. ROM_SysCtlPeripheralEnable(ANALOG_TEMPERATURE_SYSCTL_PERIPH_ADC); ROM_SysCtlDelay(1000); // Select the external reference for greatest accuracy. ROM_ADCReferenceSet(ANALOG_TEMPERATURE_ADC_BASE, ADC_REF_EXT_3V); // Enable the GPIO Port and its pins used for the analog temperature // sensor. ROM_SysCtlPeripheralEnable(ANALOG_TEMPERATURE_SYSCTL_PERIPH_GPIO); ROM_SysCtlDelay(1000); ROM_GPIOPinTypeADC(ANALOG_TEMPERATURE_GPIO_PORT_BASE, ANALOG_TEMPERATURE_GPIO_PIN); // Configure ADC sequencer for processor trigger, priority 0 ROM_ADCSequenceConfigure(ANALOG_TEMPERATURE_ADC_BASE, ANALOG_TEMPERATURE_ADC_SEQUENCE, ADC_TRIGGER_PROCESSOR, 0); // Configure input source for the ADC sequencer. unsigned long channel_control; channel_control = ANALOG_TEMPERATURE_ADC_CHANNEL; channel_control |= ADC_CTL_IE | ADC_CTL_END; ROM_ADCSequenceStepConfigure(ANALOG_TEMPERATURE_ADC_BASE, ANALOG_TEMPERATURE_ADC_SEQUENCE, 0, channel_control); return; } // Enable Analog Temperature Sensor data capture. void enableAnalogTemperature (void) { // Enable the ADC sequencer. ROM_ADCSequenceEnable(ANALOG_TEMPERATURE_ADC_BASE, ANALOG_TEMPERATURE_ADC_SEQUENCE); // Flush the ADC sequencer to be sure there is no lingering data. ROM_ADCSequenceDataGet(ANALOG_TEMPERATURE_ADC_BASE, ANALOG_TEMPERATURE_ADC_SEQUENCE, analog_temperature_buffer); return; } // Capture Data from Analog Temperature Sensor. void startAnalogTemperatureConversion (void) { // Kick off ADC Conversion. ROM_ADCProcessorTrigger(ANALOG_TEMPERATURE_ADC_BASE, ANALOG_TEMPERATURE_ADC_SEQUENCE); // Loop until conversion is complete. while (!ROM_ADCIntStatus(ANALOG_TEMPERATURE_ADC_BASE, ANALOG_TEMPERATURE_ADC_SEQUENCE, false)); // Clear the interrupt. ROM_ADCIntClear(ANALOG_TEMPERATURE_ADC_BASE, ANALOG_TEMPERATURE_ADC_SEQUENCE); return; } // Retrieve data from the ADC Sequencer. void readAnalogTemperature (void) { // Retrieve the data from ADC sequencer. ROM_ADCSequenceDataGet(ANALOG_TEMPERATURE_ADC_BASE, ANALOG_TEMPERATURE_ADC_SEQUENCE, &analog_temperature_buffer[0]); // Process the data. These will be processed and stored in units of 1/10 // Degrees Celsius. analog_temperature_buffer[0] = ( 1866300 - ((200000 * analog_temperature_buffer[0]) / 273) ) /1169; return; } // Main function. int main (void) { // Set the clocking to run directly from the crystal at 50 MHz. ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); // Enable Debug LED. ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD; HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = 0x1; ROM_GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_DIR_MODE_OUT); ROM_GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x00); configureAnalogTemperature(); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x01); ROM_SysCtlDelay(12500000); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x00); ROM_SysCtlDelay(12500000); enableAnalogTemperature(); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x01); ROM_SysCtlDelay(12500000); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x00); ROM_SysCtlDelay(12500000); startAnalogTemperatureConversion(); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x01); ROM_SysCtlDelay(12500000); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x00); ROM_SysCtlDelay(12500000); readAnalogTemperature(); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x01); while(1); }
//***************************************************************************** // // startup_ccs.c - Startup code for use with TI's Code Composer Studio. // // Copyright (c) 2011-2012 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 8555 of the EK-LM4F232 Firmware Package. // //***************************************************************************** //***************************************************************************** // // Forward declaration of the default fault handlers. // //***************************************************************************** void ResetISR(void); static void NmiSR(void); static void FaultISR(void); static void IntDefaultHandler(void); static void MPUFaultHandler(void); static void BusFaultHandler(void); static void UsageFaultHandler(void); //***************************************************************************** // // External declaration for the reset handler that is to be called when the // processor is started // //***************************************************************************** extern void _c_int00(void); //***************************************************************************** // // Linker variable that marks the top of the stack. // //***************************************************************************** extern unsigned long __STACK_TOP; //***************************************************************************** // // The vector table. Note that the proper constructs must be placed on this to // ensure that it ends up at physical address 0x0000.0000 or at the start of // the program if located at a start address other than 0. // //***************************************************************************** #pragma DATA_SECTION(g_pfnVectors, ".intvecs") void (* const g_pfnVectors[])(void) = { (void (*)(void))((unsigned long)&__STACK_TOP), // The initial stack pointer ResetISR, // The reset handler NmiSR, // The NMI handler FaultISR, // The hard fault handler MPUFaultHandler,//IntDefaultHandler, // The MPU fault handler BusFaultHandler,//IntDefaultHandler, // The bus fault handler UsageFaultHandler,//IntDefaultHandler, // The usage fault handler 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved IntDefaultHandler, // SVCall handler IntDefaultHandler, // Debug monitor handler 0, // Reserved IntDefaultHandler, // The PendSV handler IntDefaultHandler, // The SysTick handler IntDefaultHandler, // GPIO Port A IntDefaultHandler, // GPIO Port B IntDefaultHandler, // GPIO Port C IntDefaultHandler, // GPIO Port D IntDefaultHandler, // GPIO Port E IntDefaultHandler, // UART0 Rx and Tx IntDefaultHandler, // UART1 Rx and Tx IntDefaultHandler, // SSI0 Rx and Tx IntDefaultHandler, // I2C0 Master and Slave IntDefaultHandler, // PWM Fault IntDefaultHandler, // PWM Generator 0 IntDefaultHandler, // PWM Generator 1 IntDefaultHandler, // PWM Generator 2 IntDefaultHandler, // Quadrature Encoder 0 IntDefaultHandler, // ADC Sequence 0 IntDefaultHandler, // ADC Sequence 1 IntDefaultHandler, // ADC Sequence 2 IntDefaultHandler, // ADC Sequence 3 IntDefaultHandler, // Watchdog timer IntDefaultHandler, // Timer 0 subtimer A IntDefaultHandler, // Timer 0 subtimer B IntDefaultHandler, // Timer 1 subtimer A IntDefaultHandler, // Timer 1 subtimer B IntDefaultHandler, // Timer 2 subtimer A IntDefaultHandler, // Timer 2 subtimer B IntDefaultHandler, // Analog Comparator 0 IntDefaultHandler, // Analog Comparator 1 IntDefaultHandler, // Analog Comparator 2 IntDefaultHandler, // System Control (PLL, OSC, BO) IntDefaultHandler, // FLASH Control IntDefaultHandler, // GPIO Port F IntDefaultHandler, // GPIO Port G IntDefaultHandler, // GPIO Port H IntDefaultHandler, // UART2 Rx and Tx IntDefaultHandler, // SSI1 Rx and Tx IntDefaultHandler, // Timer 3 subtimer A IntDefaultHandler, // Timer 3 subtimer B IntDefaultHandler, // I2C1 Master and Slave IntDefaultHandler, // Quadrature Encoder 1 IntDefaultHandler, // CAN0 IntDefaultHandler, // CAN1 IntDefaultHandler, // CAN2 0,//IntDefaultHandler, // Reserved // Ethernet IntDefaultHandler, // Hibernate IntDefaultHandler, // USB0 IntDefaultHandler, // PWM Generator 3 IntDefaultHandler, // uDMA Software Transfer IntDefaultHandler, // uDMA Error IntDefaultHandler, // ADC1 Sequence 0 IntDefaultHandler, // ADC1 Sequence 1 IntDefaultHandler, // ADC1 Sequence 2 IntDefaultHandler, // ADC1 Sequence 3 0,//IntDefaultHandler, // Reserved // I2S0 0,//IntDefaultHandler, // Reserved // External Bus Interface 0 IntDefaultHandler, // GPIO Port J IntDefaultHandler, // GPIO Port K IntDefaultHandler, // GPIO Port L IntDefaultHandler, // SSI2 Rx and Tx IntDefaultHandler, // SSI3 Rx and Tx IntDefaultHandler, // UART3 Rx and Tx IntDefaultHandler, // UART4 Rx and Tx IntDefaultHandler, // UART5 Rx and Tx IntDefaultHandler, // UART6 Rx and Tx IntDefaultHandler, // UART7 Rx and Tx 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved IntDefaultHandler, // I2C2 Master and Slave IntDefaultHandler, // I2C3 Master and Slave IntDefaultHandler, // Timer 4 subtimer A IntDefaultHandler, // Timer 4 subtimer B 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // Reserved IntDefaultHandler, // Timer 5 subtimer A IntDefaultHandler, // Timer 5 subtimer B IntDefaultHandler, // Wide Timer 0 subtimer A IntDefaultHandler, // Wide Timer 0 subtimer B IntDefaultHandler, // Wide Timer 1 subtimer A IntDefaultHandler, // Wide Timer 1 subtimer B IntDefaultHandler, // Wide Timer 2 subtimer A IntDefaultHandler, // Wide Timer 2 subtimer B IntDefaultHandler, // Wide Timer 3 subtimer A IntDefaultHandler, // Wide Timer 3 subtimer B IntDefaultHandler, // Wide Timer 4 subtimer A IntDefaultHandler, // Wide Timer 4 subtimer B IntDefaultHandler, // Wide Timer 5 subtimer A IntDefaultHandler, // Wide Timer 5 subtimer B IntDefaultHandler, // FPU IntDefaultHandler, // PECI 0 IntDefaultHandler, // LPC 0 IntDefaultHandler, // I2C4 Master and Slave IntDefaultHandler, // I2C5 Master and Slave IntDefaultHandler, // GPIO Port M IntDefaultHandler, // GPIO Port N IntDefaultHandler, // Quadrature Encoder 2 IntDefaultHandler, // Fan 0 0, // Reserved IntDefaultHandler, // GPIO Port P (Summary or P0) IntDefaultHandler, // GPIO Port P1 IntDefaultHandler, // GPIO Port P2 IntDefaultHandler, // GPIO Port P3 IntDefaultHandler, // GPIO Port P4 IntDefaultHandler, // GPIO Port P5 IntDefaultHandler, // GPIO Port P6 IntDefaultHandler, // GPIO Port P7 IntDefaultHandler, // GPIO Port Q (Summary or Q0) IntDefaultHandler, // GPIO Port Q1 IntDefaultHandler, // GPIO Port Q2 IntDefaultHandler, // GPIO Port Q3 IntDefaultHandler, // GPIO Port Q4 IntDefaultHandler, // GPIO Port Q5 IntDefaultHandler, // GPIO Port Q6 IntDefaultHandler, // GPIO Port Q7 IntDefaultHandler, // GPIO Port R IntDefaultHandler, // GPIO Port S IntDefaultHandler, // PWM 1 Generator 0 IntDefaultHandler, // PWM 1 Generator 1 IntDefaultHandler, // PWM 1 Generator 2 IntDefaultHandler, // PWM 1 Generator 3 IntDefaultHandler // PWM 1 Fault }; //***************************************************************************** // // This is the code that gets called when the processor first starts execution // following a reset event. Only the absolutely necessary set is performed, // after which the application supplied entry() routine is called. Any fancy // actions (such as making decisions based on the reset cause register, and // resetting the bits in that register) are left solely in the hands of the // application. // //***************************************************************************** void ResetISR(void) { // // Jump to the CCS C initialization routine. This will enable the // floating-point unit as well, so that does not need to be done here. // __asm(" .global _c_int00\n" " b.w _c_int00"); } //***************************************************************************** // // This is the code that gets called when the processor receives a NMI. This // simply enters an infinite loop, preserving the system state for examination // by a debugger. // //***************************************************************************** static void NmiSR(void) { // // Enter an infinite loop. // while(1) { } } //***************************************************************************** // // 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. // //***************************************************************************** // TODO #include "inc/hw_types.h" #include "inc/hw_memmap.h" #include "inc/hw_gpio.h" #include "driverlib/gpio.h" #include "driverlib/rom.h" static void FaultISR(void) { // // Enter an infinite loop. // while(1) { ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x01); ROM_SysCtlDelay(2500000); ROM_GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0, 0x00); ROM_SysCtlDelay(2500000); } } //***************************************************************************** // // This is the code that gets called when the processor receives an unexpected // interrupt. This simply enters an infinite loop, preserving the system state // for examination by a debugger. // //***************************************************************************** static void IntDefaultHandler(void) { // // Go into an infinite loop. // while(1) { } } // TODO static void MPUFaultHandler(void) { while(1) { } } static void BusFaultHandler(void) { while(1) { } } static void UsageFaultHandler(void) { while(1) { } }