Search code examples
cembeddedc-preprocessorinterrupt-handlingavr-gcc

Embedded C, and AVR GCC compilation issue with multiple definitions


It seems that my compiler does not willing to build the firmware in stepper_motor.c and as you can see below, it throws this error, which I am unable to solve.

I have created a stepper_motor.c source where all my functions and variables are placed, and a stepper_motor.h header where all the #defines and function prototypes are. In main.c I just include the stepper_motor.h header and use the functions. As you can see from shell log data, it does not compile and tells that 4 x variables are defined multiple times. Those ones are used in ISR() routine for a timer, so they need to be also volatile.

Any information would be highly appreciated on this issue.

this is my main.c includes: --------

#include <avr/io.h>
#include <Hardware_Bay.h>
#include <util/delay.h>
#include <USART.h>
#include <string.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <avr/interrupt.h>
#include <scale16.h>
#include <stepper_motor.h>

const uint8_t motor_Phases[] = {
    (1 << COIL_B1),                             // full step
    (1 << COIL_B1) | (1 << COIL_A2),            // half step
    (1 << COIL_A2),                             // full step
    (1 << COIL_A2) | (1 << COIL_B2),            // half step
    (1 << COIL_B2),                             // full step
    (1 << COIL_B2) | (1 << COIL_A1),            // etc..
    (1 << COIL_A1),
    (1 << COIL_A1) | (1 << COIL_B1),
};

volatile uint8_t stepPhase = 0;
volatile uint16_t stepCounter = 0;
volatile int8_t direction = FORWARD;

ISR(TIMER0_COMPA_vect) {                    // Timer/Counter-0 Compare match interrupt vector enable
    stepPhase += direction;                 // take step in right direction
    stepPhase &= 0b00000111;                // keep the stepPhase in range (0 - 7)
    STEPPER_PORT = motor_Phases[stepPhase]; // write phase out to motor COIL-1 A/B
    HALL_PORT = motor_Phases[stepPhase];    // write phase out to motor COIL-2 A/B
    stepCounter ++;
}

------------------------------header file -----------------------------------------------

#ifndef STEPPER_MOTOR_H_INCLUDED
#define STEPPER_MOTOR_H_INCLUDED

#endif // STEPPER_MOTOR_H_INCLUDED

#define FORWARD           1                      
#define BACKWARD         -1
#define TURN              200  

#define MAX_DELAY         255                                                  
#define MIN_DELAY         10                                                      
#define ACCELERATION      16                                        

#define RAMP_STEPS        (MAX_DELAY - MIN_DELAY) / ACCELERATION

void stepperDrive(uint8_t number_of_steps, uint8_t delay);

void trapezoidDrive_Stepper(int16_t number_of_steps);
PS D:\Users\Arhitect\Documents\C_Programs\Physalis_Banshee\Physalis_GEO_version_3.6> make flash
avr-gcc -Wl,-Map,Physalis_GEO_version_3.6.map -Wl,--gc-sections -mmcu=atmega1284p fuse.o main.o stepper_motor.o USART.o  -o Physalis_GEO_version_3.6.elf
stepper_motor.o: In function `stepperDrive':
D:\Users\Arhitect\Documents\C_Programs\Physalis_Banshee\Physalis_GEO_version_3.6/stepper_motor.c:50: multiple definition of `stepCounter'
main.o:(.bss.stepCounter+0x0): first defined here
stepper_motor.o:(.data.direction+0x0): multiple definition of `direction'
main.o:(.data.direction+0x0): first defined here
stepper_motor.o:(.rodata.motor_Phases+0x0): multiple definition of `motor_Phases'
main.o:(.rodata.motor_Phases+0x0): first defined here
stepper_motor.o: In function `stepperDrive':
D:\Users\Arhitect\Documents\C_Programs\Physalis_Banshee\Physalis_GEO_version_3.6/stepper_motor.c:50: multiple definition of `stepPhase'
main.o:(.bss.stepPhase+0x0): first defined here
make: *** [Physalis_GEO_version_3.6.elf] Error 1
PS D:\Users\Arhitect\Documents\C_Programs\Physalis_Banshee\Physalis_GEO_version_3.6>

Solution

  • Really the error messages tell you all you need to know - you have defined these symbols in two places - main.c and setpper_motor.c.

    You have defined stepCounter at line 50 of stepper_motor.c and also as shown in main.c. Similarly for stepPase and motor_Phases.

    • If they are independent and should not be visible externally then both should be declared static so that they are visible only in their respective translation units.

    • If it is intended that the symbol refers to the they are the same object, then one of them needs to be declared extern to indicate to the compiler its type and name, but that it is defined elsewhere..

    • If they are independent but "need" to be global (because you cannot think of a better solution), then they cannot have the same name.

    • If you do not reference them in main.c, then they should in any event be removed from there. It seems odd that you would define them here when they clearly relate to stepper motor control and should probably be encapsulated in stepper_motor.c.

    Avoiding the use of globals in the fist place is a much better solution see https://www.embedded.com/a-pox-on-globals/