Forum: Compiler & IDEs AVRGCC C++ undefined reference to Max7456::Max7456()


von Hannes (Gast)


Lesenswert?

Hallo,
ich benutze Xcode zum AVR programmieren(328),
leider kann ich kein object aus meiner klasse erzeugen und ich finde den 
Fehler nich.

code:


//including lib`s
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "src/AVRTools/ArduinoPins.h"
#include "src/Max7456/max7456.hpp"
#include "src/SPI/SPI.hpp"
#include "src/Uart/uart.h"

//-----define object---//
Max7456 osd;

//-----define global var---//

void setup( void ){

}


int main(void) {
    //init
    setup();

    //main lopp
    while ( 1 )
    {


    }
}

cpp:

//
//  max7456.hpp
//  Quanum_CyclopOSD
//
//  Created by Dominik Loher on 29.08.16.
//  Copyright © 2016 Dominik Loher. All rights reserved.
//

#ifndef max7456_hpp
#define max7456_hpp

//#include <stdio.h>


//def next only if you changed your table for an ascii one
//i.e address 0x00 -> ' '
//....
//    address 0x5A -> 'z'
//#define MAX7456_TABLE_ASCII

#include "max7456registers.h"
#define byte uint8_t


/**
 *  @mainpage Max7456 Arduino library
 */

/**
 *  @example Max7456WriteTable.cpp
 */


/**
 *  @class Max7456
 *  @brief Represents a max7456 device communicating through SPI port
 */
class Max7456
{
public:


    /**
     *  Default constructor
     */
    Max7456();


    /**
     *  Constructor
     *  Initialize communications and device
     *  @param pinCS : pin ~CS of the arduino where max7456 is plugged.
     */
    Max7456(byte pinCS);


    /**
     *  Initialize communications and device
     *  @param pinCS : pin ~CS of the arduino where max7456 is plugged.
     *  @code
     *  Max7456 osd;
     *  osd.init(9); //Note it's that it's the same than usinge 
constructor Max7456(byte pinCS).
     *  @endcode
     */
    void init(byte pinCS);

    /**
     * Set the base time for blink.
     * @param blinkBase : the base time (see datasheet)
     * @param blinkDC : blink Duty cycle (see datasheet).
     */
    void setBlinkParams(byte blinkBase, byte blinkDC);


    /**
     * Set Horizontal and Vertical display offset
     * @param horizontal : the horizontal offset in pixels (between 0 
and 63).
     * @param vertical : the vertical offset in pixels (between 0 and 
31).
     */
    void setDisplayOffsets(byte horizontal, byte vertical);


    /**
     *  Erase Display Memory.
     */
    void clearScreen();


    /**
     *  Activate osd on screen
     *  @param act :
     *  @li if true OSD is activated
     *  @li if false OSD is deactivated
     */
    void activateOSD(bool act = true);


    /**
     *  Activate input video as a background
     *  @param activExtVid :
     *  @li if true external video is displayed
     *  @li if false external video is not displayed (bakground = grey)
     */
    void activateExternalVideo(bool activExtVid = true);


    /**
     *  Put a character in the memory character of max7456
     *  @param array : the byte array representing the character (54 
bytes long)
     *  @param x : the horizontal position of character in memory
     *  @param y : the vertical position of character in memory.
     *  @code
     *  charact c={0x44,....} //Whatever charact here
     *  max.sendCharacter(c,4,5); //put c at 4th line 5th column ie. 
address 54.
     *  max.sendCharacter(c,0x43); //put c in mem at address 43.
     *  @endcode
     */
    void sendCharacter(const charact array, byte x, byte y);
//    void write_NVM(int font_count, uint8_t *character_bitmap);


    /**
     *  Get a character from the character memory of max7456
     *  @param array : the byte array representing the character (54 
bytes long)
     *  @param x : the horizontal position of character in character 
memory
     *  @param y : the vertical position of character in character 
memory
     */
    void getCharacter(charact array, byte x, byte y);


    /**
     *  Put a string in the display memory of max7456
     *  @param string : The string to be displayed
     *  @param x : the horizontal position of the string on screen
     *  @param y : the vertical position of the string on screen
     *  @param blink : if 1 then character will blink
     *  @param inv : if 1 then color character will be inverted
     *  @note : In order to have this function working,
     *  you must rewrite your Max7456 Eeprom memory and make the first
     *  characters the ascii characters between ' ' and 'z'
     *  (' ' being at address 0x00, z being at address 'z'-' ').
     */
    void print(const char string[], byte x, byte y, byte blink = 0,byte 
inv = 0);



    /**
     *  Put a float in the display memory of max7456
     *  @param value : The value to be displayed
     *  @param x : the horizontal position of the value on screen
     *  @param y : the vertical position of the value on screen
     *  @param before : number of digits before comma
     *  @param after : number of digits after comma
     *  @param blink : if 1 then character will blink
     *  @param inv : if 1 then color character will be inverted
     *  @note The number of printed characters will be : before + after 
+ 1.
     *  @note Be aware of having a coherence between the number of 
digits you
     *  enter in the function and the max. value of your double. If not 
may
     *  result in unpredictable printed string.
     *  @code
     *  max.print(3.14,x,y,3,4);
     *  //Will print "003.1400" on screen
     *  @endcode
     */
    void print(double value, byte x, byte y, byte before, byte after, 
byte blink=0,byte inv=0);


    /**
     *  Put some characters in the display memory of max7456.
     *    The characters are given by their address in the
     *    character memory of the max7456.
     *  @param chars : The characters address array to display
     *  @param size : the array size
     *  @param x : the horizontal position of the value on screen
     *  @param y : the vertical position of the value on screen
     *  @param blink : if 1 then character will blink
     *  @param inv : if 1 then color character will be inverted
     *  @code
     *  char chars[0x04,0x45,0x54]; //the chars addresses array to be 
send to function.
     *  max.printMax7456Chars(chars,3,x,y);
     *  @endcode
     */
    void printMax7456Chars(byte chars[],byte size,byte x, byte y, byte 
blink = 0,byte inv = 0);


    /**
     *  Put one character from the character memory in the display 
memory of max7456
     *  @param address : The address in character memory of the 
character to be displayed
     *  @param x : the horizontal position of the string on screen
     *  @param y : the vertical position of the string on screen
     *  @param blink : if 1 then character will blink
     *  @param inv : if 1 then color character will be inverted
     */
    void printMax7456Char(const byte address, byte x, byte y, byte 
blink=0, byte inv=0);

    /**
     *  Print a character to Serial port
     *  @param array : the byte array representing the character (54 
bytes long)
     *  @param img :
     *  @li true : the character will be displayed as a picture
     *  @li false : the character will be displayed as a byte array
     */
    static void printCharacterToSerial(const charact array, bool img = 
true);


    /**
     *  Converts a CARACT character to a byte array representation.
     *  @param car : the CARACT character
     *  @return : the byte array representing the character (54 bytes 
long)
     */
    static byte* CARACT2ByteArray(const CARACT car);


    /**
     *  Converts a byte array to a CARACT character.
     *  @param array : the byte array representing the character (54 
bytes long)
     *  @return : the CARACT character
     */
    static CARACT byteArray2CARACT(const charact array);


    /**
     * Get the ith character from program memory
     * @param table the address of the array in prog memory
     * @param i the index of character.
     * @param c the returned character.
     * @note The table must be in program memory as an array of bytes (a 
multiple of 54).
     * @note When accessing this array, 0x55 are interpreted as 0xFF 
(you can't have 0xFF in program memory.
     * @note See file example for more informations.
     */
    static void getCARACFromProgMem(const char *table, byte i,charact 
c);

private:

    byte giveMax7456CharFromAsciiChar(char ascii);
    static void printPixel(byte value);

    byte _pinCS;
    bool _isActivatedOsd;
    //registers (only here for convenience : not forced to be used).
    REG_VM0   _regVm0;
    REG_VM1   _regVm1;
    REG_HOS   _regHos;
    REG_VOS   _regVos;
    REG_DMM   _regDmm;
    REG_DMAH  _regDmah; // not used yet
    REG_DMAL  _regDmal; // not used yet
    REG_DMDI  _regDmdi; // not used yet
    REG_CMM   _regCmm;
    REG_CMAH  _regCmah; // not used yet
    REG_CMAL  _regCmal; // not used yet
    REG_CMDI  _regCmdi; // not used yet
    REG_OSDM  _regOsdm; // not used yet
    REG_RBN   _regRb[16];  // not used yet
    REG_OSDBL _regOsdbl; // not used yet
    REG_STAT  _regStat; // not used yet
    DMDO  _regDmdo; // not used yet
    REG_CMDO  _regCmdo; // not used yet
};


#endif /* MAX7456_H_ */

: Verschoben durch User
von Oliver S. (oliverso)


Lesenswert?

Die Fehlermeldung kommt vom linker, und dem fehlt die Implementierung 
des Konstruktors. In deinem geposteten Quellcode fehlt die auch.

Olivef

von Hannes (Gast)


Lesenswert?

dazu gibt es natürlich noch die .cpp.

Die ist doch hier ->
    /**
     *  Default constructor
     */
    Max7456();

Oder was meinst du genau ?

von Oliver S. (oliverso)


Lesenswert?

Die cpp ist wohl eher eine hpp.

Und das enthält nur die Deklarationen. Die Implementierungrm dazu stehen 
vermutlich im tatsächlichen (und dir fehlenden) cpp-file.

Oliver

von Hannes (Gast)


Lesenswert?

Ja das war ein tipp fehler von mir

//
//  Quanum_CyclopOSD
//
//  Created by Dominik Loher on 29.08.16.
//  Copyright © 2016 Dominik Loher. All rights reserved.
//
#include "max7456.hpp"
#include "SPI.hpp"

//---------------------------------------------------------------------- 
-------
// Implements Max7456::Max7456
//---------------------------------------------------------------------- 
-------
Max7456::Max7456(byte pinCS)
{
    this->init(pinCS);
}

//---------------------------------------------------------------------- 
-------
// Implements Max7456::setBlinkParams
//---------------------------------------------------------------------- 
-------
void Max7456::setBlinkParams(byte blinkBase, byte blinkDC)
{
    _regVm1.bits.blinkingTime = blinkBase;
    _regVm1.bits.blinkingDutyCycle = blinkDC;
    digitalWrite(_pinCS,LOW);
    SPI.transfer(VM1_ADDRESS_WRITE);
    SPI.transfer(_regVm1.whole);
    digitalWrite(_pinCS,HIGH);
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::setDisplayOffsets
//---------------------------------------------------------------------- 
------
void Max7456::setDisplayOffsets(byte horizontal, byte vertical)
{

    _regHos.whole = 0;
    _regVos.whole = 0;

    _regHos.bits.horizontalPositionOffset = horizontal;
    _regVos.bits.verticalPositionOffset = vertical;

    digitalWrite(_pinCS,LOW);
    SPI.transfer(HOS_ADDRESS_WRITE);
    SPI.transfer(_regHos.whole);

    SPI.transfer(VOS_ADDRESS_WRITE);
    SPI.transfer(_regVos.whole);

    digitalWrite(_pinCS,HIGH);
}

//---------------------------------------------------------------------- 
-------
// Implements Max7456::Max7456
//---------------------------------------------------------------------- 
-------
Max7456::Max7456()
{
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::sendCharacter
//---------------------------------------------------------------------- 
-------
void Max7456::sendCharacter(const charact chara, byte x, byte y)
{
    byte charAddress;
    if(y<0)
        charAddress = x;
    else
        charAddress = x + (y<<4);
    activateOSD(false);
    //datasheet p38
    digitalWrite(_pinCS,LOW);
    SPI.transfer(CMAH_ADDRESS_WRITE);
    SPI.transfer(charAddress);

    for(byte i = 0 ; i < 54 ; i++)
    {
        SPI.transfer(CMAL_ADDRESS_WRITE);
        SPI.transfer(i);
        SPI.transfer(CMDI_ADDRESS_WRITE);
        SPI.transfer(chara[i]);
    }

    _regCmm = 0xA0; //To write the NVM array
    SPI.transfer(CMM_ADDRESS_WRITE);
    SPI.transfer(_regCmm);
    //while STAT[5] is not good, we wait.
    _regStat.bits.characterMemoryStatus = 1;
    while(  _regStat.bits.characterMemoryStatus ==1)
    {
        SPI.transfer(STAT_ADDRESS_READ);
        _regStat.whole = SPI.transfer(0x00);
    }


    digitalWrite(_pinCS,HIGH);
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::getCharacter
//---------------------------------------------------------------------- 
-------
void Max7456::getCharacter(charact chara, byte x, byte y)
{
    byte charAddress;


    if(y<=0)
        charAddress = x;
    else
        charAddress = x + y*16;

    activateOSD(false);
    //datasheet p38
    digitalWrite(_pinCS,LOW);


    SPI.transfer(CMAH_ADDRESS_WRITE);
    SPI.transfer(charAddress);

    _regCmm = 0x50; //To read from the NVM array
    SPI.transfer(CMM_ADDRESS_WRITE);
    SPI.transfer(_regCmm);


    for(byte i = 0 ; i < 54 ; i++)
    {
        SPI.transfer(CMAL_ADDRESS_WRITE);
        SPI.transfer(i);

        SPI.transfer(CMDO_ADDRESS_READ); //read from device through spi
        chara[i] = SPI.transfer(0x00);
    }

    digitalWrite(_pinCS,HIGH);

}
//---------------------------------------------------------------------- 
-------
// Implements Max7456::printCharacterToSerial
//---------------------------------------------------------------------- 
-------
void Max7456::printCharacterToSerial(const charact array, bool img)
{

    if(img)
    {
        CARACT car ;
        car = Max7456::byteArray2CARACT(array);

        Serial.println("------------");
        for(int i = 0 ; i < 18 ; i++)
        {
            for(int j = 0 ; j < 3 ; j++)
            {
                printPixel(car.line[i].pixels[j].pix0);
                printPixel(car.line[i].pixels[j].pix1);
                printPixel(car.line[i].pixels[j].pix2);
                printPixel(car.line[i].pixels[j].pix3);
            }

            Serial.println("");
        }
        Serial.println("------------");
    }

    else
    {
        Serial.print("{");
        for(unsigned int i = 0 ; i < 53 ; i++)
        {
            Serial.print("0x");
            Serial.print(String(array[i],HEX));
            Serial.print(", ");
        }
        Serial.print("0x");
        Serial.print(String(array[53],HEX));
        Serial.println("};");
    }
}

void Max7456::printPixel(byte value)
{
    switch(value )
    {
        case COLOR_BLACK :
            Serial.print("#");
            return;
        case COLOR_WHITE :
            Serial.print("*");
            return;
        default:
            Serial.print(" ");
            return;
    }
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::print
//---------------------------------------------------------------------- 
-------
void Max7456::print(const char string[], byte x, byte y, byte blink,byte 
inv)
{
    char          currentChar;
    byte          size;
    byte *chars = NULL;

    if(!string) return;

    size = 0;
    currentChar = string[0];

    while(currentChar != '\0')
    {
        currentChar = string[++size];
    }

    chars = (byte*) malloc(size * sizeof(byte));

    for(byte i = 0 ; i < size ; i++)
    {
        chars[i] = Max7456::giveMax7456CharFromAsciiChar(string[i]);
    }

    printMax7456Chars(chars, size, x,  y,  blink , inv );
    free(chars);
}


void Max7456::printMax7456Char(const byte address, byte x, byte y, byte 
blink, byte inv)
{
    byte ad = address;
    printMax7456Chars(&ad,1,x,y,blink,inv);
}

//---------------------------------------------------------------------- 
-------
// Implements Max7456::printMax7456Chars
//---------------------------------------------------------------------- 
-------
void Max7456::printMax7456Chars(byte chars[],byte size,byte x, byte y, 
byte blink ,byte inv )
{
    byte          currentCharMax7456;
    byte          posAddressLO;
    byte          posAddressHI;
    unsigned int  posAddress;

    posAddress = 30*y+x;

    posAddressHI = posAddress >> 8;
    posAddressLO = posAddress;

    _regDmm.whole = 0x01;

    _regDmm.bits.INV = inv;
    _regDmm.bits.BLK = blink;

    digitalWrite(_pinCS,LOW);
    SPI.transfer(DMM_ADDRESS_WRITE);



    SPI.transfer(_regDmm.whole);


    SPI.transfer(DMAH_ADDRESS_WRITE); // set start address high
    SPI.transfer(posAddressHI);

    SPI.transfer(DMAL_ADDRESS_WRITE); // set start address low
    SPI.transfer(posAddressLO);


    for(int i = 0; i < size ; i++)
    {
        currentCharMax7456 = chars[i];
        SPI.transfer(DMDI_ADDRESS_WRITE);
        SPI.transfer(currentCharMax7456);

    }

    //end character (we're done).
    SPI.transfer(DMDI_ADDRESS_WRITE);
    SPI.transfer(0xff);

    /*
     _regVm0.bits.
     SPI.transfer(VM0_ADDRESS_WRITE);
     SPI.transfer(0x4c);*/


    digitalWrite(_pinCS,HIGH);
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::print
//---------------------------------------------------------------------- 
-------

void Max7456::print(double value, byte x, byte y, byte before, byte 
after, byte blink,byte inv)
{
    char *strValue = NULL;

    strValue = (char*) malloc((before+after+2)* sizeof(char));


    if(after==0)
        dtostrf(value,before+after,after,strValue);
    else
        dtostrf(value,before+after+1,after,strValue);

    for(int i = 0 ; i < before+after+1;i++)
    {
        if(strValue[i] == ' ' || strValue[i] == '-')
            strValue[i]='0';
    }
    if(value < 0)
        strValue[0]='-';
    if(after==0) //If the result is bigger, we truncate it so the OSD 
won't be falsed.
        strValue[before]='\0';
    else
        strValue[before+after+1]='\0';

    print(strValue,x,y,blink,inv);

    free(strValue);
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::giveMax7456CharFromAsciiChar
//---------------------------------------------------------------------- 
-------
byte Max7456::giveMax7456CharFromAsciiChar(char ascii)
{
#ifdef MAX7456_TABLE_ASCII
    if(ascii >= ' ' && ascii <= 'z')
        return ascii-' ';
    else
        return ascii;
#else
    return ascii;
#endif
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::clearScreen
//---------------------------------------------------------------------- 
-------
void Max7456::clearScreen()
{
    _regDmm.bits.clearDisplayMemory = 1 ;

    digitalWrite(_pinCS, LOW);

    SPI.transfer(DMM_ADDRESS_WRITE);
    SPI.transfer(_regDmm.whole);

    //wait for operation to be complete.
    while(_regDmm.bits.clearDisplayMemory == 1 )
    {
        SPI.transfer(DMM_ADDRESS_READ);
        _regDmm.whole = SPI.transfer(0x00);
    }
    digitalWrite(_pinCS, HIGH); //disable device
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::init
//---------------------------------------------------------------------- 
-------
void Max7456::init(uint8_t iPinCS)
{
    _pinCS = iPinCS;
    _isActivatedOsd = false;

    _regVm1.whole = 0b01000111;
    pinMode(iPinCS, OUTPUT);
    digitalWrite(iPinCS, HIGH); //disable device
    delay(100); //power up time

    digitalWrite(_pinCS,LOW);
    SPI.transfer(VM0_ADDRESS_WRITE);

    _regVm0.whole = 0x00;
    _regVm0.bits.videoSelect=1; //PAL
    _regVm0.bits.softwareResetBit = 1;
    SPI.transfer(_regVm0.whole);
    digitalWrite(_pinCS,HIGH);
    delay(500);


    digitalWrite(_pinCS,LOW);
    for(int x = 0 ; x < 16 ; x++)
    {
        _regRb[x].whole = 0x00;
        _regRb[x].bits.characterWhiteLevel = 2;
        SPI.transfer(x+RB0_ADDRESS_WRITE);
        SPI.transfer(_regRb[x].whole);
    }

    _regVm0.whole = 0x00;

    _regVm0.bits.verticalSynch = 1;

    SPI.transfer(VM0_ADDRESS_WRITE);

    SPI.transfer(_regVm0.whole);


    //  digitalWrite(_pinCS,HIGH);
    //
    //  digitalWrite(_pinCS,LOW);
    //SPI.transfer(VM1_ADDRESS_WRITE);
    //SPI.transfer(0x0C);

    digitalWrite(_pinCS,HIGH);

}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::activateOSD
//---------------------------------------------------------------------- 
-------
void Max7456::activateOSD(bool act)
{
    if(_isActivatedOsd != act)
    {

        _regVm0.bits.videoSelect = 1;
        if(act)
            _regVm0.bits.enableOSD = 1;
        else
            _regVm0.bits.enableOSD = 0;

        digitalWrite(_pinCS,LOW);
        SPI.transfer(VM0_ADDRESS_WRITE);
        SPI.transfer(_regVm0.whole);
        digitalWrite(_pinCS,HIGH);
        _isActivatedOsd = act;
    }
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::activateExternalVideo
//---------------------------------------------------------------------- 
-------
void Max7456::activateExternalVideo(bool activExtVid)
{
    if(!activExtVid)
        _regVm0.bits.synchSelect = 3; //11
    else
        _regVm0.bits.synchSelect = 0; //0

    digitalWrite(_pinCS,LOW);
    SPI.transfer(VM0_ADDRESS_WRITE);
    SPI.transfer(_regVm0.whole);
    digitalWrite(_pinCS,HIGH);
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::CARACT2ByteArray
//---------------------------------------------------------------------- 
-------
byte* Max7456::CARACT2ByteArray(const CARACT car)
{
    byte *array = NULL;
    array = new charact;
    for(int i = 0 ; i < 54 ; i++)
        array[i]= car.whole[i];

    return array;
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::byteArray2CARACT
//---------------------------------------------------------------------- 
-------
CARACT Max7456::byteArray2CARACT(const charact array)
{
    CARACT car;
    for(int i = 0 ; i < 54 ; i++)
        car.whole[i] = array[i];

    return car;
}


//---------------------------------------------------------------------- 
-------
// Implements Max7456::getCARACFromProgMem
//---------------------------------------------------------------------- 
-------
void Max7456::getCARACFromProgMem(const char *table, byte i, charact 
car)
{
    unsigned long index;
    byte read;
    index = i*54;
    for(unsigned long j = 0 ; j < 54 ; j++)
    {
        read = pgm_read_byte_near(table +index+j );
        car[j] = read;
        if (car[j] == 0x55)
            car[j] = 0xff;
    }
}

von Hannes (Gast)


Lesenswert?

Kann mir mein Problem keiner erklären ?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Welchen Teil von

    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang


hast Du jetzt eigentlich nicht verstanden?


Dein Problem ist, daß der Compiler zwar wahrscheinlich Deine *.cpp-Datei 
übersetzt, dem Linker aber das Ergebnis nicht vorgeworfen wird. Sieh Dir 
Deine Projektverwaltung an, sieh Dir Dein Makefile an.

von Hannes (Gast)


Lesenswert?

Ich gehöre zu den blutigen Anfängern dh. ist das gerade nicht so
Ich benutze Xavr (Xcode) dies erstellt das Makefile selbst ->

1
# Hey Emacs, this is a -*- makefile -*-
2
#----------------------------------------------------------------------------
3
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
4
#
5
# Released to the Public Domain
6
#
7
# Additional material for this makefile was written by:
8
# Peter Fleury
9
# Tim Henigan
10
# Colin O'Flynn
11
# Reiner Patommel
12
# Markus Pfaff
13
# Sander Pool
14
# Frederik Rouleau
15
#
16
#----------------------------------------------------------------------------
17
# On command line:
18
#
19
# make all = Make software.
20
#
21
# make clean = Clean out built project files.
22
#
23
# make coff = Convert ELF to AVR COFF.
24
#
25
# make extcoff = Convert ELF to AVR Extended COFF.
26
#
27
# make program = Download the hex file to the device, using avrdude.
28
#                Please customize the avrdude settings below first!
29
#
30
# make debug = Start either simulavr or avarice as specified for debugging, 
31
#              with avr-gdb or avr-insight as the front end for debugging.
32
#
33
# make filename.s = Just compile filename.c into the assembler code only.
34
#
35
# make filename.i = Create a preprocessed source file for use in submitting
36
#                   bug reports to the GCC project.
37
#
38
# To rebuild project do "make clean" then "make all".
39
#----------------------------------------------------------------------------
40
41
#include conf.mk
42
# MCU name
43
MCU = atmega328p
44
45
46
# Processor frequency.
47
#     This will define a symbol, F_CPU, in all source code files equal to the 
48
#     processor frequency. You can then use this symbol in your source code to 
49
#     calculate timings. Do NOT tack on a 'UL' at the end, this will be done
50
#     automatically to create a 32-bit value in your source code.
51
F_CPU = 8000000
52
53
AVRDUDE_PROGRAMMER = stk500
54
55
# com1 = serial port. Use lpt1 to connect to parallel port.
56
AVRDUDE_PORT = /dev/cu.usbmodem*    # programmer connected to serial device
57
58
# Output format. (can be srec, ihex, binary)
59
FORMAT = ihex
60
61
62
# Target file name (without extension).
63
TARGET = main
64
65
66
# List C source files here. (C dependencies are automatically generated.)
67
68
SRC = $(wildcard *.cpp)
69
70
OBJDIR = Builds
71
# List Assembler source files here.
72
#     Make them always end in a capital .S.  Files ending in a lowercase .s
73
#     will not be considered source files but generated files (assembler
74
#     output from the compiler), and will be deleted upon "make clean"!
75
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
76
#     it will preserve the spelling of the filenames, and gcc itself does
77
#     care about how the name is spelled on its command-line.
78
ASRC = $(wildcard *.S)
79
80
81
# Optimization level, can be [0, 1, 2, 3, s]. 
82
#     0 = turn off optimization. s = optimize for size.
83
#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
84
OPT = s
85
86
87
# Debugging format.
88
#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
89
#     AVR Studio 4.10 requires dwarf-2.
90
#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
91
DEBUG = stabs
92
93
94
# List any extra directories to look for include files here.
95
#     Each directory must be seperated by a space.
96
#     Use forward slashes for directory separators.
97
#     For a directory that has spaces, enclose it in quotes.
98
EXTRAINCDIRS = 
99
100
101
# Compiler flag to set the C Standard level.
102
#     c89   = "ANSI" C
103
#     gnu89 = c89 plus GCC extensions
104
#     c99   = ISO C99 standard (not yet fully implemented)
105
#     gnu99 = c99 plus GCC extensions
106
CSTANDARD = -std=gnu99
107
108
109
# Place -D or -U options here
110
CDEFS = -DF_CPU=$(F_CPU)UL
111
112
113
# Place -I options here
114
CINCS =
115
116
117
118
#---------------- Compiler Options ----------------
119
#  -g*:          generate debugging information
120
#  -O*:          optimization level
121
#  -f...:        tuning, see GCC manual and avr-libc documentation
122
#  -Wall...:     warning level
123
#  -Wa,...:      tell GCC to pass this to the assembler.
124
#    -adhlns...: create assembler listing
125
CFLAGS = -g$(DEBUG)
126
CFLAGS += $(CDEFS) $(CINCS)
127
CFLAGS += -O$(OPT)
128
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
129
CFLAGS += -Wall -Wstrict-prototypes
130
CFLAGS += -Wa,-adhlns=$(addprefix $(OBJDIR)/,$(<:.cpp=.lst))
131
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
132
CFLAGS += $(CSTANDARD)
133
CFLAGS += -gstabs
134
CFLAGS += -gstrict-dwarf
135
136
#---------------- Assembler Options ----------------
137
#  -Wa,...:   tell GCC to pass this to the assembler.
138
#  -ahlms:    create listing
139
#  -gstabs:   have the assembler create line number information; note that
140
#             for use in COFF files, additional information about filenames
141
#             and function names needs to be present in the assembler source
142
#             files -- see avr-libc docs [FIXME: not yet described there]
143
#  -listing-cont-lines: Sets the maximum number of continuation lines of hex 
144
#       dump that will be displayed for a given single line of source input.
145
ASFLAGS = -Wa,-adhlns=$(addprefix $(OBJDIR)/,$(<:.S=.lst)),-gstabs,--listing-cont-lines=100
146
147
148
#---------------- Library Options ----------------
149
# Minimalistic printf version
150
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
151
152
# Floating point printf version (requires MATH_LIB = -lm below)
153
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
154
155
# If this is left blank, then it will use the Standard printf version.
156
PRINTF_LIB = 
157
#PRINTF_LIB = $(PRINTF_LIB_MIN)
158
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
159
160
161
# Minimalistic scanf version
162
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
163
164
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
165
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
166
167
# If this is left blank, then it will use the Standard scanf version.
168
SCANF_LIB = 
169
#SCANF_LIB = $(SCANF_LIB_MIN)
170
#SCANF_LIB = $(SCANF_LIB_FLOAT)
171
172
173
MATH_LIB = -lm
174
175
176
177
#---------------- External Memory Options ----------------
178
179
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
180
# used for variables (.data/.bss) and heap (malloc()).
181
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
182
183
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
184
# only used for heap (malloc()).
185
#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
186
187
EXTMEMOPTS =
188
189
190
191
#---------------- Linker Options ----------------
192
#  -Wl,...:     tell GCC to pass this to linker.
193
#    -Map:      create map file
194
#    --cref:    add cross reference to  map file
195
LDFLAGS = -Wl,-Map=$(OBJDIR)/$(TARGET).map,--cref 
196
LDFLAGS += $(EXTMEMOPTS)
197
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
198
199
200
201
#---------------- Programming Options (avrdude) ----------------
202
203
# Programming hardware: alf avr910 avrisp bascom bsd 
204
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
205
#
206
# Type: avrdude -c ?
207
# to get a full listing.
208
#
209
210
AVRDUDE_WRITE_FLASH = -U flash:w:$(OBJDIR)/$(TARGET).hex
211
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
212
213
214
# Uncomment the following if you want avrdude's erase cycle counter.
215
# Note that this counter needs to be initialized first using -Yn,
216
# see avrdude manual.
217
#AVRDUDE_ERASE_COUNTER = -y
218
219
# Uncomment the following if you do /not/ wish a verification to be
220
# performed after programming the device.
221
#AVRDUDE_NO_VERIFY = -V
222
223
# Increase verbosity level.  Please use this when submitting bug
224
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
225
# to submit bug reports.
226
#AVRDUDE_VERBOSE = -v -v
227
228
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
229
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
230
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
231
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
232
233
234
235
#---------------- Debugging Options ----------------
236
237
# For simulavr only - target MCU frequency.
238
DEBUG_MFREQ = $(F_CPU)
239
240
# Set the DEBUG_UI to either gdb or insight.
241
# DEBUG_UI = gdb
242
DEBUG_UI = insight
243
244
# Set the debugging back-end to either avarice, simulavr.
245
DEBUG_BACKEND = avarice
246
#DEBUG_BACKEND = simulavr
247
248
# GDB Init Filename.
249
GDBINIT_FILE = __avr_gdbinit
250
251
# When using avarice settings for the JTAG
252
JTAG_DEV = /dev/com1
253
254
# Debugging port used to communicate between GDB / avarice / simulavr.
255
DEBUG_PORT = 4242
256
257
# Debugging host used to communicate between GDB / avarice / simulavr, normally
258
#     just set to localhost unless doing some sort of crazy debugging when 
259
#     avarice is running on a different computer.
260
DEBUG_HOST = localhost
261
262
263
264
#============================================================================
265
266
267
# Define programs and commands.
268
SHELL = sh
269
CC = /usr/local/CrossPack-AVR/bin/avr-gcc
270
OBJCOPY = /usr/local/CrossPack-AVR/bin/avr-objcopy
271
OBJDUMP = /usr/local/CrossPack-AVR/bin/avr-objdump
272
SIZE = /usr/local/CrossPack-AVR/bin/avr-size
273
NM = /usr/local/CrossPack-AVR/bin/avr-nm
274
AVRDUDE = /usr/local/CrossPack-AVR/bin/avrdude
275
REMOVE = rm -f
276
COPY = cp
277
WINSHELL = cmd
278
279
280
# Define Messages
281
# English
282
MSG_ERRORS_NONE = Errors: none
283
MSG_BEGIN = -------- begin --------
284
MSG_END = --------  end  --------
285
MSG_SIZE_BEFORE = Size before: 
286
MSG_SIZE_AFTER = Size after:
287
MSG_COFF = Converting to AVR COFF:
288
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
289
MSG_FLASH = Creating load file for Flash:
290
MSG_EEPROM = Creating load file for EEPROM:
291
MSG_EXTENDED_LISTING = Creating Extended Listing:
292
MSG_SYMBOL_TABLE = Creating Symbol Table:
293
MSG_LINKING = Linking:
294
MSG_COMPILING = Compiling:
295
MSG_ASSEMBLING = Assembling:
296
MSG_CLEANING = Cleaning project:
297
298
299
300
301
# Define all object files.
302
OBJ = $(addprefix $(OBJDIR)/,$(SRC:.cpp=.o)) $(addprefix $(OBJDIR)/,$(ASRC:.S=.o))
303
304
# Define all listing files.
305
LST = $(addprefix $(OBJDIR)/,$(SRC:.cpp=.lst)) $(addprefix $(OBJDIR)/,$(ASRC:.S=.lst))
306
307
308
# Compiler flags to generate dependency files.
309
GENDEPFLAGS = -M
310
311
312
# Combine all necessary flags and optional flags.
313
# Add target processor to flags.
314
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
315
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
316
317
318
# Generate dependency files
319
DEPSDIR   = $(OBJDIR)/.dep
320
DEPS      = $(SRC:%.cpp=$(DEPSDIR)/%.d)
321
322
-include $(DEPS)
323
324
$(DEPSDIR):
325
  mkdir -p $(DEPSDIR)
326
327
.DELETE_ON_ERROR:
328
$(DEPSDIR)/%.d: %.cpp | $(DEPSDIR)
329
  $(CC) $(ALL_ASFLAGS) $(GENDEPFLAGS) -MT $(patsubst %.cpp,$(OBJDIR)/%.o,$<) -MF $@ $<
330
331
332
# Default target.
333
all: begin gccversion sizebefore clean build program sizeafter end
334
335
build: $(OBJDIR) elf hex eep lss sym
336
337
elf: $(OBJDIR)/$(TARGET).elf
338
hex: $(OBJDIR)/$(TARGET).hex
339
eep: $(OBJDIR)/$(TARGET).eep
340
lss: $(OBJDIR)/$(TARGET).lss 
341
sym: $(OBJDIR)/$(TARGET).sym
342
343
$(OBJDIR):
344
  @mkdir -p $@
345
346
# Eye candy.
347
# AVR Studio 3.x does not check make's exit code but relies on
348
# the following magic strings to be generated by the compile job.
349
begin:
350
  @echo
351
  @echo $(MSG_BEGIN)
352
353
end:
354
  @echo $(MSG_END)
355
  @echo
356
357
358
# Display size of file.
359
HEXSIZE = $(SIZE) --target=$(FORMAT) $(OBJDIR)/$(TARGET).hex
360
ELFSIZE = $(SIZE) --format=avr $(OBJDIR)/$(TARGET).elf
361
362
sizebefore:
363
  @if test -f $(OBJDIR)/$(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
364
  2>/dev/null; echo; fi
365
366
sizeafter:
367
  @if test -f $(OBJDIR)/$(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
368
  2>/dev/null; echo; fi
369
370
371
372
# Display compiler version information.
373
gccversion : 
374
  @$(CC) --version
375
376
377
378
# Program the device.  
379
program: $(OBJDIR)/$(TARGET).hex $(OBJDIR)/$(TARGET).eep
380
  $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
381
382
# Generate avr-gdb config/init file which does the following:
383
#     define the reset signal, load the target file, connect to target, and set 
384
#     a breakpoint at main().
385
gdb-config: 
386
  @$(REMOVE) $(GDBINIT_FILE)
387
  @echo define reset >> $(GDBINIT_FILE)
388
  @echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
389
  @echo end >> $(GDBINIT_FILE)
390
  @echo file $(OBJDIR)/$(TARGET).elf >> $(GDBINIT_FILE)
391
  @echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
392
ifeq ($(DEBUG_BACKEND),simulavr)
393
  @echo load  >> $(GDBINIT_FILE)
394
endif  
395
  @echo break main >> $(GDBINIT_FILE)
396
397
debug: gdb-config $(OBJDIR)/$(TARGET).elf
398
ifeq ($(DEBUG_BACKEND), avarice)
399
  @echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
400
  @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
401
  $(OBJDIR)/$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
402
  @$(WINSHELL) /c pause
403
else
404
  @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
405
  $(DEBUG_MFREQ) --port $(DEBUG_PORT)
406
endif
407
  @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
408
409
410
411
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
412
COFFCONVERT=$(OBJCOPY) --debugging \
413
--change-section-address .data-0x800000 \
414
--change-section-address .bss-0x800000 \
415
--change-section-address .noinit-0x800000 \
416
--change-section-address .eeprom-0x810000 
417
418
419
coff: $(OBJDIR)/$(TARGET).elf
420
  @echo
421
  @echo $(MSG_COFF) $(OBJDIR)/$(TARGET).cof
422
  $(COFFCONVERT) -O coff-avr $< $(OBJDIR)/$(TARGET).cof
423
424
425
extcoff: $(OBJDIR)/$(TARGET).elf
426
  @echo
427
  @echo $(MSG_EXTENDED_COFF) $(OBJDIR)/$(TARGET).cof
428
  $(COFFCONVERT) -O coff-ext-avr $< $(OBJDIR)/$(TARGET).cof
429
430
431
432
# Create final output files (.hex, .eep) from ELF output file.
433
$(OBJDIR)/%.hex: $(OBJDIR)/%.elf
434
  @echo
435
  @echo $(MSG_FLASH) $@
436
  $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
437
438
$(OBJDIR)/%.eep: $(OBJDIR)/%.elf
439
  @echo
440
  @echo $(MSG_EEPROM) $@
441
  -$(OBJCOPY) -j .eeprom --set-section-flags .eeprom=alloc,load \
442
  --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
443
444
# Create extended listing file from ELF output file.
445
$(OBJDIR)/%.lss: $(OBJDIR)/%.elf
446
  @echo
447
  @echo $(MSG_EXTENDED_LISTING) $@
448
  $(OBJDUMP) -h -S $< > $@
449
450
# Create a symbol table from ELF output file.
451
$(OBJDIR)/%.sym: $(OBJDIR)/%.elf
452
  @echo
453
  @echo $(MSG_SYMBOL_TABLE) $@
454
  $(NM) -n $< > $@
455
456
457
458
# Link: create ELF output file from object files.
459
.SECONDARY : $(OBJDIR)/$(TARGET).elf
460
.PRECIOUS : $(OBJ)
461
$(OBJDIR)/%.elf: $(OBJ)
462
  @echo
463
  @echo $(MSG_LINKING) $@
464
  $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
465
466
467
# Compile: create object files from C source files.
468
$(OBJDIR)/%.o : %.cpp
469
  @echo
470
  @echo $(MSG_COMPILING) $<
471
  $(CC) -c $(ALL_CFLAGS) "$(abspath $<)" -o $@ 
472
473
474
# Compile: create assembler files from C source files.
475
$(OBJDIR)/%.s : %.cpp
476
  $(CC) -S $(ALL_CFLAGS) $< -o $@
477
478
479
# Assemble: create object files from assembler source files.
480
$(OBJDIR)/%.o : %.S
481
  @echo
482
  @echo $(MSG_ASSEMBLING) $<
483
  $(CC) -c $(ALL_ASFLAGS) $< -o $@
484
485
# Create preprocessed source for use in sending a bug report.
486
$(OBJDIR)/%.i : %.cpp
487
  $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 
488
489
490
# Target: clean project.
491
clean: begin clean_list end
492
493
clean_list :
494
  @echo
495
  @echo $(MSG_CLEANING)
496
  $(REMOVE) $(OBJDIR)/$(TARGET).hex
497
  $(REMOVE) $(OBJDIR)/$(TARGET).eep
498
  $(REMOVE) $(OBJDIR)/$(TARGET).cof
499
  $(REMOVE) $(OBJDIR)/$(TARGET).elf
500
  $(REMOVE) $(OBJDIR)/$(TARGET).map
501
  $(REMOVE) $(OBJDIR)/$(TARGET).sym
502
  $(REMOVE) $(OBJDIR)/$(TARGET).lss
503
  $(REMOVE) $(OBJ)
504
  $(REMOVE) $(LST)
505
  $(REMOVE) $(OBJDIR)/$(SRC:.cpp=.s)
506
  $(REMOVE) $(OBJDIR)/$(SRC:.cpp=.d)
507
  $(REMOVE) $(OBJDIR)/.dep/*
508
509
510
# Listing of phony targets.
511
.PHONY : all begin finish end sizebefore sizeafter gccversion \
512
build elf hex eep lss sym coff extcoff \
513
clean clean_list program debug gdb-config

von Hannes (Gast)


Lesenswert?

Ich würde jetzt sagen, dieses Makefile kann ich vergessen. Denn ich will 
C und C++ files Compilern und linken.

Gibt es dazu Abhilfe ?

von Oliver S. (oliverso)


Lesenswert?

Ich sach mal:

C++ Buch besorgen
"hello world" ans laufen bekommen
Google bemühen, und nachlesen, was man für C++ auf dem AVR alles tun muß
Alternativ, da mir XCode nichts sagt: RTFM

Vor dem laufen kommt das gehen. Und davor erstmal freihändig auf beiden 
Beinen stehen..

Oliver

Rufus Τ. F. schrieb:
> Welchen Teil von
>
>     Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
>
> hast Du jetzt eigentlich nicht verstanden?

Das gilt für alles, auch für makefile. Im Text liest das keiner...

Oliver

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.