Hey there,
I'm developing a project with the F28377S c2000 launchpad. I just converted some exploratory code into a more streamlined library for my application. When I try and compile the project, I get the compilation error #10056 saying that I first defined a symbol in one library, and then tried to redefine it in another. I have included the pragma statements such as:
#ifndef F28X_PROJECT_H
#include "F28x_Project.h"
#endif
for all my includes and header files, but the error is still there. I'm not sure what i'm doing wrong. Here is the error CCS is giving me:
>> Compilation failure
error #10056: symbol "_TICK_EVENTS" redefined: first defined in "./Scan.obj"; redefined in "./main.obj"
error #10056: symbol "_servo1" redefined: first defined in "./Scan.obj"; redefined in "./main.obj"
error #10010: errors encountered during linking; "AssistiveMeasure-rev-0.out" not built
gmake: *** [AssistiveMeasure-rev-0.out] Error 1
and here is the code which seems to be giving me the issue:
global.h file:
#ifndef F28X_PROJECT_H #include "F28x_Project.h" #endif #ifndef GLOBAL_H_ #define GLOBAL_H_ // Device Headerfile and Examples Include File //#include "pinmux_qep_epwm.c" // Pin Configuration VIA pinmux. //#include "F2837xS_I2C.c" //#include "lcd.h" //#include "I2C.h" typedef struct { Uint32 Scan_TS; // Time stamp used to trigger a delayed event Uint32 TickCount; // The Systems Tick Count Uint32 TickCountCMP; // Used to determine if a System Tick has occured since last pass. }Events; typedef struct { float angle; float distance; }Measurement; // Global Variables Events TICK_EVENTS; #endif /* GLOBAL_H_ */
Main:
//####################### // Global Include Section // global includes everything for the project. //####################### #ifndef SERVOCONTROL_H_ #include "ServoControl.h" #endif #include "lcd.h" #ifndef GLOBAL_H_ #include "global.h" #endif //#include "scan.h" /*///////////////////// * Interrupt Prototypes *///////////////////// __interrupt void epwm1_isr(void); __interrupt void eqep1_isr(void); __interrupt void SysTick_ISR(void); /* * Extern Function definitions */ extern void servoInit(Servo *servo); extern void setServoAngle(Servo *servo); extern void quadInit(void); extern void InitEQep3Gpio(void); extern __interrupt void i2c_int1a_isr(void); extern __interrupt void measure_isr(void); extern void test(void); extern void I2CA_Init(void); extern void InitECapture(); /*//////////////////////// * Global Variables *//////////////////////// extern Servo servo1; Uint16 testCount = 0; Uint16 SysTickCount = 0; Uint16 MeasureCount = 0; Uint16 MeasureFlags = 0x0000; Uint16 pos = 0; int i = 0; float temp = 0.0; void initialize(void) { // Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // Modified for 200 MHz Sysclock InitSysCtrl(); // Initialize GPIO: /* * This needs to be cleaned up * Functions defined where InitGpio is * can easily be used to configure the peripherals i'm * interested in * * GPIO_setPinMuxConfig is currently setting up the ePWM for the servo * InitEQep3Gpio is setting up the eQEP, I want to keep that. */ InitGpio(); // General IO Setup //GPIO_setPinMuxConfig(); // Pin Multiplex Information. InitEPwm2Gpio(); InitEQep3Gpio(); // Initialize the eQEP module I2cAGpioConfig(I2C_A_GPIO91_GPIO92); // Configure I2C A module for pins 91 & 92 InitECap1Gpio(71); // Conigure eCap Pin GPIO_SetupPinOptions(90, output, NOFLAGS); // Configure pins for eCap operations //GPIO_SetupPinOptions(71, input, NOFLAGS); // Configure pins for eCAP operations // Disable CPU interrupts DINT; // Initialize the PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the F2837xS_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in F2837xS_DefaultIsr.c. // This function is found in F2837xS_PieVect.c. InitPieVectTable(); // Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.TIMER0_INT = &SysTick_ISR; PieVectTable.EPWM2_INT = &epwm1_isr; PieVectTable.EQEP3_INT = &eqep1_isr; PieVectTable.I2CA_INT = &i2c_int1a_isr; PieVectTable.ECAP1_INT = &measure_isr; EDIS; // This is needed to disable write to EALLOW protected registers // Initialize the system's peripherals for components. InitCpuTimers(); servoInit(&servo1); // Load ePWM for Servo quadInit(); // Load eQEP for Motor angle. I2CA_Init(); // Initialize I2C module InitECapture(); // Initialize eCAP module //LCDInit(); // LCD Initialization // Configure System Tick here ConfigCpuTimer(&CpuTimer0, 200, 5000); // Configure system tick for 5ms. CpuTimer0Regs.TCR.all = 0x4001; // Use write-only instruction to set TSS bit = 0 // Step 4. User specific code, enable interrupts: // Enable CPU Interrupt groups for interrupts. IER |= M_INT1; // Ground 1 for Timer 0 IER |= M_INT3; // Ground 3 for PWM interrupts IER |= M_INT4; // Group 4 for eCAP interrupts IER |= M_INT8; // Group 8 for I2C interrupts // Enable EPWM INTn in the PIE: Group 3 interrupt 1-3 PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // Enable interrupt for Timer 0. PieCtrlRegs.PIEIER3.bit.INTx2 = 1; // Enable PWM 2 Interrupt PieCtrlRegs.PIEIER5.bit.INTx3 = 1; // eQEP Interrupt PieCtrlRegs.PIEIER8.bit.INTx1 = 1; // Enable I2C interrupt PieCtrlRegs.PIEIER4.bit.INTx1 = 1; // Enable eCAP1 Interrupt // Enable Clock to Peripherals CpuSysRegs.PCLKCR2.bit.EPWM2=1; CpuSysRegs.PCLKCR4.bit.EQEP3=1; CpuSysRegs.PCLKCR3.bit.ECAP1=1; //CpuSysRegs.PCLKCR0.bit.CPUTIMER0 = 1; // Enable global Interrupts and higher priority real-time debug events: EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM EnableInterrupts(); return; } void main(void) { initialize(); // Perform all initializations // main loop. for(;;) { //testLidar(); } //putrsLCD("-"); } __interrupt void epwm1_isr(void) { // Acknowledge this interrupt to receive more interrupts from group 3 PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; } __interrupt void eqep1_isr(void) { //servo1.angle= (EQep1Regs.QPOSILAT) / 2 ; //setServoAngle(&servo1); PieCtrlRegs.PIEACK.all = PIEACK_GROUP5; } __interrupt void SysTick_ISR(void) { // Here's are system tick folks if (TICK_EVENTS.TickCount != 0xFFFFFFFF) { TICK_EVENTS.TickCount++; } else { TICK_EVENTS.TickCount = 0; } //CpuTimer0.RegsAddr->TCR.bit.TIF = 0; PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Ack this interrupt. }
Scan.h:
#ifndef F28X_PROJECT_H #include "F28x_Project.h" #endif #ifndef GLOBAL_H_ #include "global.h" #endif #ifndef SERVOCONTROL_H_ #include "ServoControl.h" #endif #ifndef SCAN_H_ #define SCAN_H_ #define SCAN_EN 0x0001 // Flag that a scan has started #define SCAN_SAMPLE 0x0002 // Flag that a sample has started #define SCAN_FIN 0x0010 // Flag that a scan has completed #define FIRSTDELAY 200 // Number of tick counts before the first scan is to start #define MOVEDELAY 20 // Number of ticks used in between measurements #define SCAN_LIMIT 8 // Number of scan cycles for each measurement, hopefully this artificually increases accuracy. Uint16 ScanFlags; // Flags used within the Scan Cycle unsigned char SampleCount; // Capture the Sampling Cycle Count unsigned char MeasurementCount; // float MeasurementBuffer[SCAN_LIMIT]; // Measurement Buffer Measurement testMeasurements[360]; // scan Measurements void InitECapture( void ); // Initialize the Capture Module void StartScan( void ); // Used to initiate a full scan. void ScanEvent( void ); // Used to handle a scan event float sumBuffer (float Buffer[]); // Sum the Sample Measurements __interrupt void measure_isr(void); // Interrupt for Capture Module #endif /* SCAN_H_ */
Scan.c:
/* * Scan.c * * Created on: Mar 8, 2016 * Author: user */ //#ifndef GLOBAL_H_ //#include "global.h" //#endif //#ifndef SERVOCONTROL_H_ ///#include "ServoControl.h" //#endif #include "Scan.h" // External Variables extern Servo servo1; void InitECapture() { ECap1Regs.ECEINT.all = 0x0000; // Disable all capture __interrupts ECap1Regs.ECCLR.all = 0xFFFF; // Clear all CAP __interrupt flags ECap1Regs.ECCTL1.bit.CAPLDEN = 0; // Disable CAP1-CAP4 register loads ECap1Regs.ECCTL2.bit.TSCTRSTOP = 0; // Make sure the counter is stopped // Configure peripheral registers ECap1Regs.ECCTL2.bit.CONT_ONESHT = 1; // One-shot ECap1Regs.ECCTL2.bit.STOP_WRAP = 3; // Stop at 4 events ECap1Regs.ECCTL1.bit.CAP1POL = 0; // R edge ECap1Regs.ECCTL1.bit.CAP2POL = 1; // F edge ECap1Regs.ECCTL1.bit.CAP3POL = 0; // R edge ECap1Regs.ECCTL1.bit.CAP4POL = 1; // F edge ECap1Regs.ECCTL1.bit.CTRRST1 = 1; // Difference operation Ressets counter after event ECap1Regs.ECCTL1.bit.CTRRST2 = 1; // Difference operation ECap1Regs.ECCTL1.bit.CTRRST3 = 1; // Difference operation ECap1Regs.ECCTL1.bit.CTRRST4 = 1; // Difference operation ECap1Regs.ECCTL2.bit.SYNCI_EN = 1; // ECap1Regs.ECCTL2.bit.SYNCO_SEL = 0; // Pass through ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // Enable capture units ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // Start Counter ECap1Regs.ECCTL2.bit.REARM = 1; // arm one-shot ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // Enable CAP1-CAP4 register loads ECap1Regs.ECEINT.bit.CEVT4 = 1; // 4 events = __interrupt return; } // Start Scan // This is used to initiate a scan void StartScan( void ) { int i; for (i = 0; i < SCAN_LIMIT; i++) { MeasurementBuffer[i] = 0; } for (i = 0; i < servoSteps; i++) { testMeasurements[i].angle = 0; testMeasurements[i].distance = 0; } SampleCount = 0; // Clear the Sample count MeasurementCount = 0; // Clear the Measurement Count servo1.angle = 0; // Set the servo Angle to 0 setServoAngle(&servo1); // Update the Servo angle TICK_EVENTS.Scan_TS = TICK_EVENTS.TickCount + FIRSTDELAY; // Stamp the Next event time. ScanFlags |= SCAN_EN; // Set the scanning flag } // Scan Event, this is used to handle the events that take place during a scan void ScanEvent( void ){ if (TICK_EVENTS.Scan_TS == TICK_EVENTS.TickCount) // Check to see if it's time to handle the event. { if ((ScanFlags & SCAN_SAMPLE) == 0) // If there isn't a sample happening { if (SampleCount < SCAN_LIMIT) // Check for number of scan cycles. { GPIO_WritePin(90, 0); // Not Done Measuring, Start the Sample again ScanFlags |= SCAN_SAMPLE; // Flag a sample has started } else { ScanFlags &= ~SCAN_SAMPLE; // Acknowledge the sample is done testMeasurements[MeasurementCount].distance = sumBuffer(MeasurementBuffer); testMeasurements[MeasurementCount].angle = servo1.angle; if (servo1.angle == 180) // Reached the scan limit? { ScanFlags &= ~SCAN_EN; // Clear the Scan Flag ScanFlags |= SCAN_FIN; } else { servo1.angle += servoResolution; // Increment the angle fo the servo motor. setServoAngle(&servo1); // Set the angle TICK_EVENTS.Scan_TS = TICK_EVENTS.TickCount + MOVEDELAY; // Stamp the tick count for the next event } } } } } float sumBuffer (float Buffer[]) { float result; int i; for (i = 0; i < SCAN_LIMIT; i++) // Sum the measurements { result += Buffer[i]; } result /= SCAN_LIMIT; return result; } __interrupt void measure_isr(void) { GPIO_WritePin(90, 1); // Stop the Lidar Module //MeasurementBuffer[SampleCount].angle = servo1.angle; MeasurementBuffer[SampleCount] = (ECap1Regs.CAP2 + ECap1Regs.CAP4) / 4000; // Add the two capture events and average the result. Clean this computation up SampleCount++; // Rearm the eCAP ECap1Regs.ECCLR.all = 0xFFFF; // Clear ALL flags ECap1Regs.ECCTL2.bit.REARM = 1; // arm one-shot PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; }
Servo.h:
#include "F28x_Project.h" #ifndef SERVOCONTROL_H_ #define SERVOCONTROL_H_ typedef struct { volatile struct EPWM_REGS *EPwmRegHandle; float angle; uint16_t CaptureValue; uint16_t flags; }Servo; Servo servo1; void servoInit(Servo *servo); void setServoAngle(Servo *servo); // Configure the period for each timer #define SERVO_PRD 62500 // Period register #define servoResolution 0.5 // Resolution in Degrees #define servo180Cal 7385 // ePWM count for 180' #define servo0Cal 1850 // ePWM count for 0' #define servoSteps (180 / servoResolution) // nummber of steps for set res. #define EPWM1_MIN_CMPA 7385 // Initial Value #define EPWM1_MIN_CMPB 7385 // Initial Value #define SERVO_UPDATE_CAPVAL 0x01 #define angleStep ((servo180Cal - servo0Cal) / servoSteps) // ePWM count inc/dec for a single step #endif /* SERVOCONTROL_H_ */
and servo.c:
#ifndef SERVOCONTROL_H_
#include "ServoControl.h"
#endif
void servoInit(Servo *servo)
{
(*servo).EPwmRegHandle = &EPwm2Regs;
(*servo).CaptureValue = 0;
(*servo).angle = 0.0;
(*servo).flags = 0x00;
// Setup TBCLK
ClkCfgRegs.PERCLKDIVSEL.bit.EPWMCLKDIV = 0x1; // Make sure 200MHz clock is divided by 2.
(*servo).EPwmRegHandle->TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
(*servo).EPwmRegHandle->TBPRD = SERVO_PRD; // Set timer period
(*servo).EPwmRegHandle->TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
(*servo).EPwmRegHandle->TBPHS.bit.TBPHS = 0x0000; // Phase is 0
(*servo).EPwmRegHandle->TBCTR = 0x0000; // Clear counter
(*servo).EPwmRegHandle->TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
(*servo).EPwmRegHandle->TBCTL.bit.CLKDIV = 0x5; // 101 sets to div 32. input clk = 3.125MHz
// Setup shadow register load on ZERO
(*servo).EPwmRegHandle->CMPCTL.bit.SHDWAMODE = CC_SHADOW;
(*servo).EPwmRegHandle->CMPCTL.bit.SHDWBMODE = CC_SHADOW;
(*servo).EPwmRegHandle->CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
(*servo).EPwmRegHandle->CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
// Set Compare values
//(*servo).angle = 90.0;
//setServoAngle(servo);
// Set actions
(*servo).EPwmRegHandle->AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero
(*servo).EPwmRegHandle->AQCTLA.bit.CAU = AQ_CLEAR; // Clear PWM1A on event A, up count
(*servo).EPwmRegHandle->AQCTLB.bit.ZRO = AQ_SET; // Set PWM1B on Zero
(*servo).EPwmRegHandle->AQCTLB.bit.CBU = AQ_CLEAR; // Clear PWM1B on event B, up count
// Interrupt where we will change the Compare Values
//(*servo).EPwmRegHandle->ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
//(*servo).EPwmRegHandle->ETSEL.bit.INTEN = 1; // Enable INT
//(*servo).EPwmRegHandle->ETPS.bit.INTPRD = ET_3RD; // Generate INT on 3rd event
return;
}
void setServoAngle(Servo *servo) {
uint16_t pAngle = (uint16_t)((*servo).angle * 10);
//uint16_t mod; // Not super need
//float angleStepVar = angleStep;
//float servoStepsVar = servoSteps;
// Remove 'inbetween' angle settings by subtracting the modulus of the
// servo resolution
//mod = (pAngle % (int)(servoResolution * 10));
//pAngle -= (pAngle % (int)(servoResolution * 10));
// Prevent any errors
if (pAngle > 1800) {
pAngle = 1800;
}
// Convert to number of angle steps
pAngle /= (int)(servoResolution * 10);
// Calculate the compare value for the desired angle
// 0' compare value + ((Angle * 10) * compare values per angle value)
(*servo).CaptureValue = servo0Cal + (pAngle * angleStep);
// Set Compare values
(*servo).EPwmRegHandle->CMPA.bit.CMPA = (*servo).CaptureValue; // Set compare A value
(*servo).EPwmRegHandle->CMPB.bit.CMPB = (*servo).CaptureValue; // Set Compare B value
return;
}
I'm super stuck with this and need a helping hand to point me in the right direction.
Thanks.