0

I don't know what I'm getting the following error:

proc1.o: In function `procEx1':
/cygdrive/c/armprojects/projekt/motor/proc1.c:45: undefined reference to `motorTest_test'
collect2: ld returned 1 exit status
make: *** [main.hex] Error 1

I've checked the following threads on this issue:

This is my output:

13:46:46 **** Build of configuration Default for project motor ****
make all 
make[1]: Entering directory `/cygdrive/c/armprojects/projekt/motor/startup'
rm -f .depend 
arm-elf-gcc -c -mcpu=arm7tdmi  -I . -DEL -DGCC   -mthumb-interwork -DLPC2148  -Os -    gdwarf-2 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch     -Wreturn-type  -Wa,-ahlms=consol.lst -o consol.o consol.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I . -DEL -DGCC   -mthumb-interwork -DLPC2148  -Os -    gdwarf-2 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch -Wreturn-type  -Wa,-ahlms=framework.lst -o framework.o framework.c
framework.c: In function 'exceptionHandlerInit':
framework.c:201: warning: pointer targets in assignment differ in signedness
arm-elf-gcc -c -mcpu=arm7tdmi  -I . -DEL -DGCC   -mthumb-interwork -DLPC2148  -x           assembler-with-cpp -gstabs -Wa,-alhms=startup.lst -o startup.o startup.S
arm-elf-ar cr libea_startup_thumb.a consol.o framework.o startup.o
arm-elf-ranlib libea_startup_thumb.a
make[1]: Leaving directory `/cygdrive/c/armprojects/projekt/motor/startup'
make[1]: Entering directory `/cygdrive/c/armprojects/projekt/motor/LCD'
rm -f .depend 
arm-elf-gcc -c -mcpu=arm7tdmi  -I . -DEL -DGCC   -mthumb-interwork -DLPC2148  -O0 -    gdwarf-2 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch     -Wreturn-type  -Wa,-ahlms=LCD.lst -o LCD.o LCD.c
arm-elf-ar cr lib_LCD.a LCD.o 
arm-elf-ranlib lib_LCD.a
make[1]: Leaving directory `/cygdrive/c/armprojects/projekt/motor/LCD'
make[1]: Entering directory `/cygdrive/c/armprojects/projekt/motor/interrupt'
rm -f .depend 
arm-elf-gcc -c -mcpu=arm7tdmi  -I . -DEL -DGCC   -mthumb-interwork -DLPC2148  -Os -    gdwarf-2 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch     -Wreturn-type  -Wa,-ahlms=interrupt_timer.lst -o interrupt_timer.o interrupt_timer.c
arm-elf-gcc -c -mcpu=arm7tdmi  -I . -DEL -DGCC   -mthumb-interwork -DLPC2148  -Os -    gdwarf-2 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch     -Wreturn-type  -Wa,-ahlms=interrupt_tacho.lst -o interrupt_tacho.o interrupt_tacho.c
arm-elf-ar cr lib_interrupt.a interrupt_timer.o interrupt_tacho.o 
arm-elf-ranlib lib_interrupt.a
make[1]: Leaving directory `/cygdrive/c/armprojects/projekt/motor/interrupt'
rm -f .depend 
arm-elf-gcc -c -mcpu=arm7tdmi -mthumb-interwork -I./startup -DEL -DGCC -mthumb-interwork     -mthumb -DTHUMB_CSTART -DTHUMB_INTERWORK -mthumb-interwork -DLPC2148  -O0 -gdwarf-2 -Wall -    Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch -Wreturn-type      -Wa,-ahlms=main.lst -o main.o main.c
arm-elf-gcc -c -mcpu=arm7tdmi -mthumb-interwork -I./startup -DEL -DGCC -mthumb-interwork     -mthumb -DTHUMB_CSTART -DTHUMB_INTERWORK -mthumb-interwork -DLPC2148  -O0 -gdwarf-2 -Wall -    Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch -Wreturn-type      -Wa,-ahlms=proc1.lst -o proc1.o proc1.c
motor/motor_test.h:18: warning: 'duty1' defined but not used
motor/motor_test.h:19: warning: 'duty2' defined but not used
arm-elf-gcc -c -mcpu=arm7tdmi -mthumb-interwork -I./startup -DEL -DGCC -mthumb-interwork     -mthumb -DTHUMB_CSTART -DTHUMB_INTERWORK -mthumb-interwork -DLPC2148  -O0 -gdwarf-2 -Wall -    Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch -Wreturn-type      -Wa,-ahlms=proc2.lst -o proc2.o proc2.c
arm-elf-gcc -c -mcpu=arm7tdmi -mthumb-interwork -I./startup -DEL -DGCC -mthumb-interwork     -mthumb -DTHUMB_CSTART -DTHUMB_INTERWORK -mthumb-interwork -DLPC2148  -O0 -gdwarf-2 -Wall -    Wcast-align -Wcast-qual -Wimplicit -Wnested-externs -Wpointer-arith -Wswitch -Wreturn-type      -Wa,-ahlms=proc3.lst -o proc3.o proc3.c
arm-elf-gcc main.o proc1.o proc2.o proc3.o  startup/libea_startup_thumb.a     pre_emptive_os/pre_emptive_os.a LCD/lib_LCD.a interrupt/lib_interrupt.a -I./startup -    mcpu=arm7tdmi -mthumb-interwork -mthumb-interwork -nostartfiles -T     build_files/link_32k_512k_rom.ld -o main.elf -Wl,-Map=main.map,--cref
proc1.o: In function `procEx1':
/cygdrive/c/armprojects/projekt/motor/proc1.c:45: undefined reference to     `motorTest_test'
collect2: ld returned 1 exit status
make: *** [main.hex] Error 1

13:46:52 Build Finished (took 6s.46ms)

If you want to you could checkout my repository at: http://dt3-robotlego-2012ht-white.googlecode.com/svn/branches/motor/Project12/

Here's some of my code (the relevant parts):
proc1.c

/*
 * proc1.c
 *
 *  Created on: 31 okt 2011
 *      Author: Tommy
 */

/*****************************************************************************
 * Process 1
 ****************************************************************************/
#include "pre_emptive_os/api/osapi.h"
#include "general.h"
#include "startup/lpc2xxx.h"
#include "startup/printf_P.h"
#include "startup/ea_init.h"
#include "startup/consol.h"
#include "startup/config.h"
#include "startup/framework.h"
#include "utils/utils.h"
#include "LCD/LCD.h"
#include "motor/motor_test.h"

extern long const delayshort;
extern long const delaylong;

extern tCntSem mutexLCD;

/*****************************************************************************
 * Function prototypes
 ****************************************************************************/
void LCD_clearDisplay(void);

/****************************************************************************/

void
procEx1(void* arg)
{
  tU8 error;

    for (;;) {  // QUESTION: why use for-loop?

        osSemTake(&mutexLCD, 0, &error);

        // REMARK: doesn't work at the moment... issues including runPwm()
        motorTest_test();

        osSemGive(&mutexLCD, &error);

        osSleep(100);
    }

}

void LCD_clearDisplay(void) {
    delay(delayshort);
    send_instruction(1);    //clears the display
    delay(delaylong);
    send_instruction(2);    //the cursor is moved to the first position
}

motor_test.h

/******************************************************************************
 * Includes
 *****************************************************************************/
#include "motor.h"

/******************************************************************************
 * Defines
 *****************************************************************************/
#define TASK                9       // task 1 - use circulary loop
                                    // task 2 - use constant PWM signal
                                    // ...
#define RUN_SETPWM_IN_LOOP  1       // dictates whether setPwmDutyPercentx(tU32) should be run outside the "TASK conditional statement"

/*****************************************************************************
 * Global variables
 ****************************************************************************/
static tU32 duty1;
static tU32 duty2;


/******************************************************************************
 * Prototypes
 *****************************************************************************/
void motorTest_test();
void dev_run(tU32 duty1, tU32 duty2);
void pwm_motor_init();
void pwm_motor_run(tU32 duty1, tU32 duty2);
void change_mode(short mode);

motor_test.c

#include "motor_test.h"

/******************************************************************************
 * Functions
 *****************************************************************************/
void motorTest_test() {
    init();
    dev_run(duty1, duty2);
}



// dev function - not used in release
// COMMENT: PWM signal is continuously generated when the setPwmDutyPercent(tU32) function is called, no need to endlessly iterate the calls
// EDIT:    seems like you need to iterate over the setPwmDutyPercent(tU32) functions afterall...
// COMMENT: the duty sets the speed of the motor driver
//          the value that can be set is 0-10000
//          a higher value means a lower speed, conversely a low value means a higher speed
void dev_run(tU32 duty1, tU32 duty2) {
    //wait 10 ms
    //delayMs(10);

    //wait 100 ms
    //delayMs(100);

    // COMMENT: try running without delays
    //          seems to work fine..

    while (1) {

        //set frequency value
        if (RUN_SETPWM_IN_LOOP == 1) {
            setPwmDutyPercent1(duty1);
            setPwmDutyPercent2(duty2);
        }

        //  delayMs(10);

        switch (TASK) {
        case 1: {
            //update duty cycle (0.00 - 100.00%, in steps of 0.10%)
            duty1 += 10;
            if (duty1 > 10000)
                duty1 = 0;
            break;
        }
        case 2: {
            duty1 = 0;
            duty2 = 8500;
            // COMMENT: slowest speed = 8500 duty
            //          fastest speed = 0    duty
            break;
        }
        case 3: { // left
            duty1 = 6000;
            duty2 = 8000;
            break;
        }
        case 4: { // right
            duty1 = 8000;
            duty2 = 6000;
            break;
        }
        case 5: {
            duty1 = 6000;
            duty2 = 6000;
            break;
        }

        case 6: {
            short delay = 1;
            short duty_vals = 6000;
            short section[3] = { 1, 0, 0 };

            if (section[0] == 1) {
                setMode1(MODE_FORWARD);
                setMode2(MODE_FORWARD);
                duty1 = duty_vals;
                duty2 = duty_vals;
                setPwmDutyPercent1(duty1);
                setPwmDutyPercent2(duty2);
                //delayMs(0);
                delay_millis(delay);
            }

            if (section[1] == 1) {
                setMode1(MODE_BRAKE);
                setMode2(MODE_BRAKE);
                setPwmDutyPercent1(duty1);
                setPwmDutyPercent2(duty2);
                delay_millis(delay);
            }

            if (section[2] == 1) {
                setMode1(MODE_REVERSE);
                setMode2(MODE_REVERSE);
                duty1 = duty_vals;
                duty2 = duty_vals;
                setPwmDutyPercent1(duty1);
                setPwmDutyPercent2(duty2);
                delay_millis(delay);
            }
            break;
        }
        case 7: {
            pwm_motor_init();
            duty1 = 6000;
            duty2 = 6000;

            //delayMs(10);
            delay_millis(10);

            pwm_motor_run(duty1, duty2);
            break;
        }
        case 8: {


            setMode1(MODE_FORWARD);
            setMode2(MODE_FORWARD);

            delay_millis(700);

            duty1 = 7000;
            duty2 = 7000;


            setMode1(MODE_REVERSE);
            setMode2(MODE_REVERSE);

            delay_millis(700);

            duty1 = 1000;
            duty2 = 1000;

            break;
        }

        case 9: {
            duty1 = 0;
            duty2 = 0;
            break;
        }

        }
    }
}

/*****************************************************************************
 * Temporary developer functions
 ****************************************************************************/
void pwm_motor_init() {
    setMode1(MODE_FORWARD);
    setMode2(MODE_FORWARD);

    delay_millis(10);
}

void pwm_motor_run(tU32 duty1, tU32 duty2) {
    setPwmDutyPercent1(duty1);
    setPwmDutyPercent2(duty2);

    while(1) {
        change_mode(MODE_FORWARD);
        change_mode(MODE_BRAKE);
        change_mode(MODE_REVERSE);
        change_mode(MODE_BRAKE);
    }
}

void change_mode(short mode) {
    setMode1(mode);
    setMode2(mode);
    delay_millis(10);
}
Community
  • 1
  • 1
Petrus K.
  • 840
  • 7
  • 27
  • 56
  • You don't want to include the file motor_test.c into the shared object? – Jay Jan 17 '13 at 13:30
  • There is no `motorTest_test()` defined anywhere in your sources in that repository. – Sean Bright Jan 17 '13 at 13:30
  • 3
    I don't see `motor_test.o` in your command line for linking. If it's not linked in, that explains the problem... – Anton Kovalenko Jan 17 '13 at 13:30
  • @SeanBright The repo isn't up-to-date, I'll commit the changes soon.. – Petrus K. Jan 17 '13 at 13:40
  • @AntonKovalenko where do I add it? (I'm not really familiar with makefiles...) – Petrus K. Jan 17 '13 at 13:40
  • @Jay How do I add motor_test.c into the shared object (I don't understand this concept) – Petrus K. Jan 17 '13 at 13:41
  • `CSRCS := $(wildcard *.c)` automatically compiles all `*.c` files in the current directory. This avoids the Makefile breaking whenever you add a source file. Yes, it *can* break if you add a source file to the directory but *don't* want it added to the project, but that shouldn't happen as often. Note that ":=" evaluates only once at startup, while "=" evaluates anew at every occurrence of `$(CSRCS)`. This can make some difference, both performance- and functionality-wise. – DevSolar Jan 17 '13 at 13:59
  • Tell me more about the := and = operators, I don't really grasp what you're saying.. Also, will `$(wildcard *.c)` compile .c files contained in folders? or only the ones that are on the same level in the filesystem hierarchy? – Petrus K. Jan 17 '13 at 14:04
  • @DevSolar, wildcards won't work that easily for subdirectories. `$(wildcard */*.c)` might work. `$(shell find . -name '*.c')` is another alternative. Portability goes down with all of these approaches, I believe. Ryuji, wrt. `:=` vs. `=` see [the Flavors section](http://www.gnu.org/software/make/manual/html_node/Flavors.html) of the GNU make manual. – MvG Jan 17 '13 at 14:19
  • Thanks for the link (regarding `:=` vs `=`). I'll try compiling with the other settings. – Petrus K. Jan 17 '13 at 14:23

1 Answers1

2

Make sure to include all C sources into the CSRCS variable of your makefile. Then the build system will know it has to compile that file as well, and include the resulting object into the link.

MvG
  • 57,380
  • 22
  • 148
  • 276
  • I'm getting more and weirder compile errors now.. Let me ask you a general question (set in this specific context). If I do this: `# List C source files here.`
    (gosh! how do I linebreak..) `CSRCS = main.c proc1.c proc2.c proc3.c motor/motor.c` Will it correctly compile motor.c into an object?
    – Petrus K. Jan 17 '13 at 13:59
  • @Ryuji, can't test here as I don't have an arm gcc here. But from the way `build_files/general.mk` forms `OBJS ?= $(CSRCS:.c=.o) $(ASRCS:.S=.o)` I guess it should, at least if everything works as intended. By the way, there are [no newlines in comments](http://meta.stackexchange.com/q/197/188688). – MvG Jan 17 '13 at 14:09
  • I've tried setting `CSRCS = main.c proc1.c proc2.c proc3.c motor/motor.c` and also as suggested by DevSolar `CSRCS := $(wildcard *.c)` but this generates a new set of issues (even if I revert to the old setting.. weird). Too bad you can't add newlines to comments.. – Petrus K. Jan 17 '13 at 14:18
  • @Ryuji, you can `make motor/motor.o` to see whether that step works. You probably should add `motor/motor_test.c` to `CSRCS` as well. And give some indication as to what errors you encounter now. Although a new question might be better suited for these. – MvG Jan 17 '13 at 14:23
  • I've added all C sources manually, this is how I do it in the outer makefile: `CSRCS = interrupt/interrupt_tacho.c interrupt/interrupt_timer.c LCD/LCD.c motor/motor.c motor/motor_test.c utils/utils.c main.c proc1.c proc2.c proc3.c`. This seems to work (although there should be a better and more automated way to solve this..) – Petrus K. Jan 17 '13 at 14:50
  • Please check r110 of my repo for this solution: https://code.google.com/p/dt3-robotlego-2012ht-white/source/browse/?r=110 – Petrus K. Jan 17 '13 at 14:53