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.