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)
{
}
}