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!