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.

FaultISR on ROM_GPIOPinConfigure(GPIO_PD3_SSI2CLK)?

Other Parts Discussed in Thread: EK-TM4C1294XL

Hi there,

I am new to ARM programming. I am using the Tiva C Series Connected Launchpad EK-TM4C1294XL. And I am always very confused about these whole bunch of new commands. Before I began trying to write programs for ARM I was only collecting experience about Atmega and Atxmega.


Today I have a weird problem and I hope there will be a simple answer to that. But first the code:

main.cpp

//#include "tm4c1294ncpdt.h"

#include <stdint.h>
#include <stdbool.h>
#include "UART.h"
#include "AD5754.h"

uint32_t F_CPU;

int main(void) {
	// Set the clocking to run directly from the crystal at 120MHz.
	F_CPU = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
									SYSCTL_OSC_MAIN |
									SYSCTL_USE_PLL |
									SYSCTL_CFG_VCO_480), 120000000);

	UARTInit();					// initialize

	AD5754* da = new AD5754();

	da->init();
	da->clear();
	da->setPowerControl(DAC_A_POWER_UP | DAC_B_POWER_UP | DAC_C_POWER_UP | DAC_D_POWER_UP);
	da->setControl(SDO_DISABLE | CLEAR_MODE);
	da->setRangeAll(PM10);
	da->autoTrigger(true);
	da->clear();

	// Prompt for text to be entered.

	unsigned long long steps = F_CPU % 12345;

	char buf[50];
	size_t size = sprintf(buf, "Enter Text (%llu):", steps);
	UARTSend((uint8_t*) buf, size);

	// Loop forever echoing data through the UART.
	while(1) {
		da->setVoltage(0, 2.5);
		da->setVoltage(1, 2.5);
		da->setVoltage(2, 2.5);
		da->setVoltage(3, 2.5);
		da->sendAll();
	}
}

AD5753.h

/*
 * AD5754.h
 *
 *  Created on: 04.08.2013
 *      Author: nicolas
 */

#ifndef AD5754_H_
#define AD5754_H_

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "driverlib/debug.h"
#include "common.h"

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/ssi.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom_map.h"

extern uint32_t F_CPU;

/* XMega		Pin	AD5754	Pin
 *
 * PC2			SYNC	 	7
 * PC7			SCLK	 	8
 * PC5			SDIN	 	9
 * PC4			LDAC		10
 * PC3			CLR			11
 *
 * PC2			SYNC	 	7
 * PC3			CLR			11
 * PC4			LDAC		10
 * PC5			SDIN		 9
 * PC6			n/c
 * PC7			SCLK	 	8
 */

#define AD5754_SSI_BASE		SSI2_BASE

#define AD5754_LDAC_PORT	GPIO_PORTC_BASE
#define AD5754_LDAC 		GPIO_PIN_7
#define AD5754_CLR_PORT		GPIO_PORTE_BASE
#define AD5754_CLR  		GPIO_PIN_5
#define AD5754_SYNC_PORT	GPIO_PORTN_BASE
#define AD5754_SYNC			GPIO_PIN_2

enum AD5754_Range {
	PLUS5		= 0,	//+5V
	PLUS10		= 1,	//+10V
	PLUS10_8	= 2,	//+10.8V
	PM5			= 3,	//±5V
	PM10		= 4,	//±10V
	PM10_8		= 5		//±10.8V
};

enum PowerControl {
	DAC_A_POWER_UP = _BV(0),
	DAC_B_POWER_UP = _BV(1),
	DAC_C_POWER_UP = _BV(2),
	DAC_D_POWER_UP = _BV(3),
	THERMAL_SHUTDOWN = _BV(5),
	DAC_A_OVERCURRENT_ALERT = _BV(7),
	DAC_B_OVERCURRENT_ALERT = _BV(8),
	DAC_C_OVERCURRENT_ALERT = _BV(9),
	DAC_D_OVERCURRENT_ALERT = _BV(10)
};

enum Control {
	SDO_DISABLE = _BV(0),
	CLEAR_MODE = _BV(1),
	CLAMP_ENABLE = _BV(2),
	TSD_ENABLE = _BV(3)
};

class AD5754 {
	private:
		uint16_t value[4];
		bool autoTriggerActive;
		AD5754_Range range;

		void send(uint8_t control, uint16_t value) {
			ROM_GPIOPinWrite(GPIO_PORTN_BASE, AD5754_SYNC, 0);

			ROM_GPIOPinWrite(GPIO_PORTN_BASE, AD5754_SYNC, AD5754_SYNC);
		}

		void inline trimRange(float &v, const float min, const float max) {
			if (v < min) {
				v = min;
			}
			if (v > max) {
				v = max;
			}
		}

	public:
		AD5754() {
			init();
		}

		void init() {
			// Aktiviere SSI2
			ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2);

			ROM_SSIDisable(AD5754_SSI_BASE);

			// Konfiguriere die Pins für SS2 als MOSI und SCLK
			ROM_GPIOPinConfigure(GPIO_PD3_SSI2CLK);
			ROM_GPIOPinConfigure(GPIO_PD1_SSI2XDAT0);
			ROM_GPIOPinTypeSSI(GPIO_PORTD_BASE, GPIO_PIN_3 | GPIO_PIN_1);

			ROM_SSIClockSourceSet(AD5754_SSI_BASE, SSI_CLOCK_SYSTEM);

			// Initialisiere SSI2
			ROM_SSIConfigSetExpClk(AD5754_SSI_BASE, F_CPU, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 24000000, 8);

			ROM_SSIEnable(AD5754_SSI_BASE);

			// Clear out any initial data that might be present in the RX FIFO
			unsigned long initialData = 0;
			while (ROM_SSIDataGetNonBlocking(AD5754_SSI_BASE, (uint32_t*) &initialData));

			// Aktiviere alle GPIO-Ports, die hier verwendet werden
			ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);	// für CLR
			ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);	// für LDAC
			ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);	// für SYNC

			// Konfiguriere die Pins als Output
			ROM_GPIODirModeSet(AD5754_CLR_PORT, AD5754_CLR, GPIO_DIR_MODE_OUT);
			ROM_GPIODirModeSet(AD5754_LDAC_PORT, AD5754_LDAC, GPIO_DIR_MODE_OUT);
			ROM_GPIODirModeSet(AD5754_SYNC_PORT, AD5754_SYNC, GPIO_DIR_MODE_OUT);
			MAP_GPIOPadConfigSet(AD5754_CLR_PORT, AD5754_CLR, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD);
			MAP_GPIOPadConfigSet(AD5754_LDAC_PORT, AD5754_LDAC, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD);
			MAP_GPIOPadConfigSet(AD5754_SYNC_PORT, AD5754_SYNC, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD);


			// Aktiviere die Pins, die gebraucht werden
//			ROM_GPIOPinTypeGPIOOutput(AD5754_CLR_PORT, AD5754_CLR);
//			ROM_GPIOPinTypeGPIOOutput(AD5754_LDAC_PORT, AD5754_LDAC);
//			ROM_GPIOPinTypeGPIOOutput(AD5754_SYNC_PORT, AD5754_SYNC);

			// Setze die Pins auf HIGH
			ROM_GPIOPinWrite(AD5754_CLR_PORT, AD5754_CLR, AD5754_CLR);
			ROM_GPIOPinWrite(AD5754_LDAC_PORT, AD5754_LDAC, AD5754_LDAC);
			ROM_GPIOPinWrite(AD5754_SYNC_PORT, AD5754_SYNC, AD5754_SYNC);

			this->autoTriggerActive = false;
		}

		~AD5754() {};

		void autoTrigger(bool v) {
			if (v) {
				autoTriggerActive = true;
				ROM_GPIOPinWrite(AD5754_LDAC_PORT, AD5754_LDAC, 0);
			} else {
				autoTriggerActive = false;
				ROM_GPIOPinWrite(AD5754_LDAC_PORT, AD5754_LDAC, AD5754_LDAC);
			}
		}

		void setSigned(uint8_t dacChannel, int16_t v) {
			ASSERT(dacChannel < 4);
			value[dacChannel] = (uint16_t) (v + (1 << 15));
		}

		void setUnsigned(uint8_t dacChannel, uint16_t v) {
			ASSERT(dacChannel < 4);
			value[dacChannel] = v;
		}

		void setVoltage(uint16_t dacChannel, float voltage) {
			ASSERT(dacChannel < 4);
			switch (range) {
				case PLUS5:
					voltage *= 0.2;
					break;
				case PLUS10:
					voltage *= 0.1;
					break;
				case PLUS10_8:
					voltage *= 0.092592593;
					break;
				case PM5:
					voltage *= 0.1;
					voltage += 0.5;
					break;
				case PM10:
					voltage *= 0.05;
					voltage += 0.5;
					break;
				case PM10_8:
					voltage *= 0.046296296;
					voltage += 0.5;
					break;
			}
			trimRange(voltage, 0.0, 1.0);
			setUnsigned(dacChannel, voltage * 65535);
		}

		void sendChannel(uint8_t dacChannel) {
			ASSERT(dacChannel < 4);
			send(dacChannel, (uint16_t) value[dacChannel]);
		}

		void sendAllSigned(int16_t v) {
			send((1 << 2), (uint16_t) (v + (1 << 15)));
		}

		void sendAll() {
			sendChannel(0);
			sendChannel(1);
			sendChannel(2);
			sendChannel(3);
		}

		void setRange(uint8_t dacChannel, AD5754_Range range) {
			ASSERT(dacChannel < 4);
			send((1 << 3) | dacChannel, range);
		}

		void setRangeAll(AD5754_Range range) {
			send((1 << 3) | 0, range);
			send((1 << 3) | 1, range);
			send((1 << 3) | 2, range);
			send((1 << 3) | 3, range);
		}

		void setPowerControl(uint16_t powerControl) {
			send((1 << 4), powerControl);
		}

		void setControl(uint16_t control) {
			send((1 << 4) | (1 << 3) | (1 << 0), control);
		}

		void triggerNow() {
			if (!autoTriggerActive) {
				ROM_GPIOPinWrite(AD5754_LDAC_PORT, AD5754_LDAC, 0);
				//FIXME Delay?
				ROM_GPIOPinWrite(AD5754_LDAC_PORT, AD5754_LDAC, AD5754_LDAC);
			}
		}

		void clear() {
			ROM_GPIOPinWrite(AD5754_CLR_PORT, AD5754_CLR, 0);

			//FIXME 1 µs
			ROM_GPIOPinWrite(AD5754_CLR_PORT, AD5754_CLR, AD5754_CLR);
			//FIXME 3 µs
		}
};


#endif /* AD5754_H_ */

In line 116 of AD5754.h (ROM_GPIOPinConfigure(GPIO_PD3_SSI2CLK);) the program runs into the FaultISR and I don't know why. Here are two screenshots before and after calling this line.

https://dl.dropboxusercontent.com/u/28394458/Bastelkeller/FaultISR/before.png

https://dl.dropboxusercontent.com/u/28394458/Bastelkeller/FaultISR/after.png

The strange thing about that is that there is no error in the constructor of the AD5754 class. But the error occurs if I call the 'init()' method manually.

I really appreciate your help! Thanks!

  • Hello user1597705,

    It seems that the clock to the GPIO Port-D has not been enabled.

    Try using ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); followed by a small delay loop of 3 before accessing the GPIO Port D Register

    Regards

    Amit

  • If you are just starting with the Tiva and want to use TivaWare, check this out https://sites.google.com/site/luiselectronicprojects/tutorials/tiva-tutorials.

  • The problem was that I have not enabled GPIOD for SSI2.

    With 'ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);' it is working now.

    But here is a new problem. In line 157 you find this method:

    		void autoTrigger(bool v) {
    			if (v) {
    				autoTriggerActive = true;
    				ROM_GPIOPinWrite(AD5754_LDAC_PORT, AD5754_LDAC, 0);
    			} else {
    				autoTriggerActive = false;
    				ROM_GPIOPinWrite(AD5754_LDAC_PORT, AD5754_LDAC, AD5754_LDAC);
    			}
    		}

    There I got also a FaultISR while calling 'ROM_GPIOPinWrite(AD5754_LDAC_PORT, AD5754_LDAC, 0);'.

    If I remove the line 'autoTriggerActive = true;' the code works fine. But why? Is there a reason for that? Anyone an idea?

    And thank you for the tutorial, Luis. I will take a look.