Forum: Mikrocontroller und Digitale Elektronik Keil uVision 3 Warning L16


von Florian W. (duensch)


Lesenswert?

Hallo,

ich hatte alle Funktionen in einem main.c File. Aus Übersichtsgründen 
habe ich nun die Funktionen auf mehrere c Files verteilt. Nun bemängelt 
der Compiler, dass die Main Funkion nicht aufgerufen wird.
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    SEGMENT: ?PR?MAIN?MAIN
Aber die MAin FUnktion wird doch nie von einer anderen aufgerufen, ist 
ja schließlich die Hauptfunktion
Muss man den Compiler sagen, welche die Main Funktion ist die zuerst 
aufgerufen werden soll? Oder was kann sonst der Fehler sein?

Grüße
Florian

von Robert W. (rweber)


Lesenswert?

Dein main.c ist auch in der Liste der zu compilierenden Dateien mit 
drin?

von keiler (Gast)


Lesenswert?

hast du mehrer main's?

von Florian W. (duensch)


Lesenswert?

@Keiler: Nein das ist die einzige Main Funktion in meinem Projekt.

@Rober Weber: Also ich hab die Datei nicht explizit eingetragen, aber 
die main.c wurde bevor ich andere c Files angelegt habe ja auch immer 
kompiliert. In der Dateiansicht links ist auf dem Weissen Papier Symbol 
ein blauer Pfeil. Heisst das, dass es mitkompiliert wird?

von Robert W. (rweber)


Lesenswert?

Klick do einfach auf Project->Rebuild all Target files und schau im 
Build Fenster nach, was alles übersetzt wird.

von Florian W. (duensch)


Lesenswert?

Ahh ok, also dann wird das File mitkompiliert. Die Meldungen sehen wie 
folgt aus:
Build target 'Target 1'
compiling Main.c...
assembling STARTUP.A51...
assembling flash_lib.a51...
compiling RS232.c...
linking...
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
    SEGMENT: ?PR?MAIN?MAIN
Program Size: data=45.2 xdata=0 code=429

von B e r n d W. (smiley46)


Lesenswert?

Hallo Florian

Also erstmal bedeutet die Warnung, dass die Funktion main() nicht 
eingebunden wird, weil sie nicht verwendet wird.

Das Assemblerfile Startup.a51 muss ganz unten main aufrufen. Ab dann 
übernimmt "C" das Kommando. Hast Du eine eigene Startup verwendet oder 
was daran geändert?

Es gibt eine Einstellung in der Projektverwaltung, wo uVision 2/3 gesagt 
wird, ob eine Startup dazugebunden werden soll. Fehlt dort ein Häckchen?

Mfg. Bernd

von Florian W. (duensch)


Lesenswert?

Hallo Bernd,

ich verwende die vom Keil erzeugt Datei STARTUP.A51 . Änderungen habe 
ich keine vorgenommen. Die einzige Änderung war, dass ich zu dem 
einzigen c file main.c ein zweites c File erzeugt habe und einige 
Funktionen ausgelagert habe. Sonst habe ich keine Einstellungen 
verändert.

Grüße
Florian

von Florian W. (duensch)


Lesenswert?

Ich habe gerade Testhalber die 2te c Datei wieder aus dem Projekt 
rausgenommen und die entsprechenden Funnktionen im main.c file 
auskommentiert. Dann ist die Warning wieder verschwunden.
Ich hab den Eindruck, dass der Keil einfach net checkt, dass die main() 
meine Hauptfunktion ist.

von Robert W. (rweber)


Lesenswert?

poste doch mal deinen quellcode.

von Florian W. (duensch)


Lesenswert?

Das ist die Datei main.c



#include "main.h"
#include "definitions.h"
#include "RS232.h"
#include <at89c51RC2.h>


// GLOBAL VARIABLES

// Timer 1 counter
unsigned char time_counter;

// Baudrate
unsigned char baudrate;

// Eingangspuffer
unsigned char data input_buffer[MAX_INPUT];
bit new_input_data;
unsigned char input_len;




void main (void)
{
//  int i;
  EnterBootLoader();
  init();
  while (1)
  {
    ES = 0;          // lock serial interrupt during input buffer 
analysis
    if (new_input_data)    // check flag if new data is in input buffer
    {
      new_input_data = 0;  // reset flag
      if((input_len>=MAX_INPUT)&&(input_buffer[MAX_INPUT-1]==13))  // 
check length of input data buffer
      {
        input_buffer[MAX_INPUT-1] = 0;    // clear last char in buffer, 
this replaces the <CR> with the termination zero -> more practical for 
string processing
        //send_error_message(ERROR_NUMBER_BUF_OVERFLOW);  // generate a 
overflow error message
        input_len=0;            // reset length of input buffer->clear 
input buffer
      }
      else
      {
        if(input_buffer[input_len-1]==13)  //  check if <CR> was 
received as last
        {
          input_buffer[input_len-1]=0;  //  replace the <CR> with a 
terminating zero which makes it easier in further string processing
          //analyse_input_buffer();      //  call the command processing 
function
          send_string_with_cr(input_buffer);
        }
      }
    }
    ES = 1;  // unlock the serial interrupt again
    //send_char('A');
  }

}

void EnterBootLoader(void)
{
  int i;
  bit ea_save;
  ea_save = EA;
  EA = 0;
  DPH = 0x00;
  DPL = 0x00;
  ACC = 0x04;
  ASM_MOV_R1_A();
  ACC = 0x00;
  MAP_BOOT;
  __API_FLASH_ENTRY_POINT();
  UNMAP_BOOT;
  EA = ea_save; // restore interrupt state
  for(i=0;i<=2000;i++)
  {;}
//  send_string("Programmiermodus aktiv");
//  send_char(0x0D);
  for(i=0;i<=2000;i++)
  {;}
}


//////////////////////////////////////////////////////
//  Name:  timer1_interrupt            //
//--------------------------------------------------//
//  Parameter:                    //
//  none                      //
//--------------------------------------------------//
// Timer 1 Interrupt Routine            //
// Wird zur Read-Timeout Erkennung, Torzeit     //
// und für das Blinken der OP-LED verwendet      //
// hierfür wird die Routine normalerweise       //
// alle 50ms aufgerufen                //
//////////////////////////////////////////////////////
void timer1_interrupt(void)  interrupt 3 using 2
{
  TF1 = 0;        // reset timer 1 interrupt-flag
  time_counter++;      // Zähler für Timeout und OP-Signal
  if (time_counter>=7)  // 500ms sind verstrichen ?
  {
    time_counter=0;    // Timeout Zähler rücksetzen
    LED5 = ~LED5;  // OP-Signal umschalten
  }
/*
  if (time_counter%2 == 0)
  {
    Relais1
  }
  else
  {
    Relais2
  } */
}





void init(void)
{
  EX0 = 0;  // disable external interrupt0 for digital in detection
  EA = 0;      // disable interrupts

  Relais0
  baudrate = 2;
  time_counter=0;
  input_len=0;
  new_input_data=0;


  init_communication();

  ET1 = 0;    // disable timer1 interrupt
  TR1 = 0;    // disable timer1
  TF1 = 0;    // reset timer 1 interrupt-flag
  TL1 = 0;    //  reset timer value
  TH1 = 0;    //
  TMOD = 0x10;  // clear timer1 mode bits
  ET1  = 1;    // enable timer1 overflow interrupt
  TR1 = 1;    // enable timer1 again
  EX0 = 0;  // disable external interrupt0 for digital in detection


  EA = 1;    // enable interrupts
}



Das ist die Datei RS232.c

#include "RS232.h"
#include "Definitions.h"
#include <at89c51RC2.h>

extern unsigned char baudrate;
extern unsigned char data input_buffer[MAX_INPUT];
extern bit new_input_data;
extern unsigned char input_len;


void init_communication(void)
{
  ES = 0;        // Disable serial interrupt
  SCON = 0x52;    // Set to 8-Bit UART
  T2CON  = 0x30;    // set timer 2 control register for use as baudrate 
generator
  RCAP2H = 0xFF;    // preset the timer 2 register for correct rollover
  switch(baudrate)
  {
    case 0:
        {
          RCAP2L = 0xB8;  //4800 RCAP2 = 0xFF98
          break;
        }
    case 1:
        {
          RCAP2L = 0xDC;  //9600 RCAP2 = 0xFFCC
          break;
        }
    case 2:
        {
          RCAP2L = 0xEE;  //19200 RCAP2 = 0xFFE6
          break;
        }
    case 3:
        {
          RCAP2L = 0xF7;  //38400 RCAP2 = 0xFFF3
          break;
        }
    default:
        {
          RCAP2L = 0xEE;  //19200
          break;
        }
  }
  TR2 = 1;      // start timer 2
  IPL0 = 0x10;//&=0xEF
  IPH0 |= 0x18;//|=0x10    // Serieller Interrupt hat hohe priority
  RI = 0;
  TI = 0;
  ES = 1;
}


//////////////////////////////////////////////////////
//  Name:  send_char                //
//--------------------------------------------------//
//  Parameter:                    //
//  char Text  -  The char which is to output    //
//--------------------------------------------------//
//  Purpose:                    //
//  Routine to write a single char          //
//  to the serial port                //
//////////////////////////////////////////////////////
void send_char(char single_char)  //reentrant  //reentrant because could 
be executed from interrupt
{
//  while (!TI);      //  Wait until Char has send
//  TI=0;
  SBUF = single_char;    //  Write Char to serial Buffer
  while (!TI);      //  Wait until Char has send
  TI=0;
}


//////////////////////////////////////////////////////
//  Name:  send_string_with_cr            //
//--------------------------------------------------//
//  Parameter:                    //
//  char* Text  -  The string which is to output  //
//--------------------------------------------------//
//  Purpose:                    //
//  Routine to write a zero terminated char_string  //
//  to the serial port                //
//////////////////////////////////////////////////////
void send_string_with_cr(char* string)
{
  send_string(string);
  send_char(0x0D);
}

//////////////////////////////////////////////////////
//  Name:  send_string              //
//--------------------------------------------------//
//  Parameter:                    //
//  char* Text  -  The string which is to output  //
//--------------------------------------------------//
//  Purpose:                    //
//  Routine to write a zero terminated char_string  //
//  to the serial port                //
//////////////////////////////////////////////////////
void send_string(char* string) //  reentrant  //reentrant because could 
be executed from interrupt
{
  unsigned char i=0;

  while (string[i]!=0)      //  Countinue until zero termination
  {
    send_char(string[i]);
    i++;          //  next Character
  }
}

//////////////////////////////////////////////////////
//  Name:  Serial_Interrupt0            //
//--------------------------------------------------//
//  Parameter:                    //
//  none                      //
//--------------------------------------------------//
//  Purpose:                    //
//  A Routine to handle Serial Interrupt      //
//  Supports serial ASB Commands          //
//////////////////////////////////////////////////////
void Serial_Interrupt0(void) interrupt 4
{
  char c = 0;

  if (RI != 0)
  {
    c = SBUF;              //  Lese das Zeichen aus dem 
Schnittstellepuffer
    RI=0;                 //  Clear the existing interrupt request
    new_input_data=1;          //  new_input_data ist ein verlängerte 
Interrupt Flag
    if (input_len<MAX_INPUT)      //  Check if Input Buffer is Full
      input_buffer[input_len] = c;  //  store the Char in the Input 
Buffer Array
    else
      input_buffer[MAX_INPUT-1] = c;  //  und speichere es am Ende des 
Einagebpuffers
    input_len++;          //  Next Array Position
  }
}


Das ist die Datei STARTUP.A51

$NOMOD51
;----------------------------------------------------------------------- 
-------
;  This file is part of the C51 Compiler package
;  Copyright (c) 1988-2005 Keil Elektronik GmbH and Keil Software, Inc.
;  Version 8.01
;
;  *** <<< Use Configuration Wizard in Context Menu >>> ***
;----------------------------------------------------------------------- 
-------
;  STARTUP.A51:  This code is executed after processor reset.
;
;  To translate this file use A51 with the following invocation:
;
;     A51 STARTUP.A51
;
;  To link the modified STARTUP.OBJ file to your application use the 
following
;  Lx51 invocation:
;
;     Lx51 your object file list, STARTUP.OBJ  controls
;
;----------------------------------------------------------------------- 
-------
;
;  User-defined <h> Power-On Initialization of Memory
;
;  With the following EQU statements the initialization of memory
;  at processor reset can be defined:
;
; <o> IDATALEN: IDATA memory size <0x0-0x100>
;     <i> Note: The absolute start-address of IDATA memory is always 0
;     <i>       The IDATA space overlaps physically the DATA and BIT 
areas.
IDATALEN        EQU     80H
;
; <o> XDATASTART: XDATA memory start address <0x0-0xFFFF>
;     <i> The absolute start address of XDATA memory
XDATASTART      EQU     0
;
; <o> XDATALEN: XDATA memory size <0x0-0xFFFF>
;     <i> The length of XDATA memory in bytes.
XDATALEN        EQU     0
;
; <o> PDATASTART: PDATA memory start address <0x0-0xFFFF>
;     <i> The absolute start address of PDATA memory
PDATASTART      EQU     0H
;
; <o> PDATALEN: PDATA memory size <0x0-0xFF>
;     <i> The length of PDATA memory in bytes.
PDATALEN        EQU     0H
;
;</h>
;----------------------------------------------------------------------- 
-------
;
;<h> Reentrant Stack Initialization
;
;  The following EQU statements define the stack pointer for reentrant
;  functions and initialized it:
;
; <h> Stack Space for reentrant functions in the SMALL model.
;  <q> IBPSTACK: Enable SMALL model reentrant stack
;     <i> Stack space for reentrant functions in the SMALL model.
IBPSTACK        EQU     0       ; set to 1 if small reentrant is used.
;  <o> IBPSTACKTOP: End address of SMALL model stack <0x0-0xFF>
;     <i> Set the top of the stack to the highest location.
IBPSTACKTOP     EQU     0xFF +1     ; default 0FFH+1
; </h>
;
; <h> Stack Space for reentrant functions in the LARGE model.
;  <q> XBPSTACK: Enable LARGE model reentrant stack
;     <i> Stack space for reentrant functions in the LARGE model.
XBPSTACK        EQU     0       ; set to 1 if large reentrant is used.
;  <o> XBPSTACKTOP: End address of LARGE model stack <0x0-0xFFFF>
;     <i> Set the top of the stack to the highest location.
XBPSTACKTOP     EQU     0xFFFF +1   ; default 0FFFFH+1
; </h>
;
; <h> Stack Space for reentrant functions in the COMPACT model.
;  <q> PBPSTACK: Enable COMPACT model reentrant stack
;     <i> Stack space for reentrant functions in the COMPACT model.
PBPSTACK        EQU     0       ; set to 1 if compact reentrant is used.
;
;   <o> PBPSTACKTOP: End address of COMPACT model stack <0x0-0xFFFF>
;     <i> Set the top of the stack to the highest location.
PBPSTACKTOP     EQU     0xFF +1     ; default 0FFH+1
; </h>
;</h>
;----------------------------------------------------------------------- 
-------
;
;  Memory Page for Using the Compact Model with 64 KByte xdata RAM
;  <e>Compact Model Page Definition
;
;  <i>Define the XDATA page used for PDATA variables.
;  <i>PPAGE must conform with the PPAGE set in the linker invocation.
;
; Enable pdata memory page initalization
PPAGEENABLE     EQU     0       ; set to 1 if pdata object are used.
;
; <o> PPAGE number <0x0-0xFF>
; <i> uppermost 256-byte address of the page used for PDATA variables.
PPAGE           EQU     0
;
; <o> SFR address which supplies uppermost address byte <0x0-0xFF>
; <i> most 8051 variants use P2 as uppermost address byte
PPAGE_SFR       DATA    0A0H
;
; </e>
;----------------------------------------------------------------------- 
-------

; Standard SFR Symbols
ACC     DATA    0E0H
B       DATA    0F0H
SP      DATA    81H
DPL     DATA    82H
DPH     DATA    83H

                NAME    ?C_STARTUP


?C_C51STARTUP   SEGMENT   CODE
?STACK          SEGMENT   IDATA

                RSEG    ?STACK
                DS      1

                EXTRN CODE (?C_START)
                PUBLIC  ?C_STARTUP

                CSEG    AT      0
?C_STARTUP:     LJMP    STARTUP1

                RSEG    ?C_C51STARTUP

STARTUP1:

IF IDATALEN <> 0
                MOV     R0,#IDATALEN - 1
                CLR     A
IDATALOOP:      MOV     @R0,A
                DJNZ    R0,IDATALOOP
ENDIF

IF XDATALEN <> 0
                MOV     DPTR,#XDATASTART
                MOV     R7,#LOW (XDATALEN)
  IF (LOW (XDATALEN)) <> 0
                MOV     R6,#(HIGH (XDATALEN)) +1
  ELSE
                MOV     R6,#HIGH (XDATALEN)
  ENDIF
                CLR     A
XDATALOOP:      MOVX    @DPTR,A
                INC     DPTR
                DJNZ    R7,XDATALOOP
                DJNZ    R6,XDATALOOP
ENDIF

IF PPAGEENABLE <> 0
                MOV     PPAGE_SFR,#PPAGE
ENDIF

IF PDATALEN <> 0
                MOV     R0,#LOW (PDATASTART)
                MOV     R7,#LOW (PDATALEN)
                CLR     A
PDATALOOP:      MOVX    @R0,A
                INC     R0
                DJNZ    R7,PDATALOOP
ENDIF

IF IBPSTACK <> 0
EXTRN DATA (?C_IBP)

                MOV     ?C_IBP,#LOW IBPSTACKTOP
ENDIF

IF XBPSTACK <> 0
EXTRN DATA (?C_XBP)

                MOV     ?C_XBP,#HIGH XBPSTACKTOP
                MOV     ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF

IF PBPSTACK <> 0
EXTRN DATA (?C_PBP)
                MOV     ?C_PBP,#LOW PBPSTACKTOP
ENDIF

                MOV     SP,#?STACK-1

; This code is required if you use L51_BANK.A51 with Banking Mode 4
;<h> Code Banking
; <q> Select Bank 0 for L51_BANK.A51 Mode 4
#if 0
;     <i> Initialize bank mechanism to code bank 0 when using 
L51_BANK.A51 with Banking Mode 4.
EXTRN CODE (?B_SWITCH0)
                CALL    ?B_SWITCH0      ; init bank mechanism to code 
bank 0
#endif
;</h>
                LJMP    ?C_START

                END


Die Headerdateien habe ich mir mal gespart. Wenn ich sie auch posten 
soll bitte Bescheid geben.

Grüße

von Robert W. (rweber)


Lesenswert?

als zip file, mit der Keil Projekt datei wäre praktischer

von Florian W. (duensch)


Angehängte Dateien:

Lesenswert?

Ohh sorry, dann jetzt hier im Anhang die Zip Datei :-)

von B e r n d W. (smiley46)


Angehängte Dateien:

Lesenswert?

Hallo Florian

Also bei mir gehts. War wohl irgendwas am Projektfile.

Gruß, Bernd

von Florian W. (Gast)


Lesenswert?

Hi Bernd,

sry für die späte Antwort, war eine Woche ausser Haus. Das ist komisch, 
ich hab mir die Zip Datei nochmal geladen aber die Warning ist wie 
gehabt.
Hast Du noch eine Idee was für eine Einstellung bei mir falsch sein 
könnte?

Grüße
Florian

von Max (Gast)


Lesenswert?

Hallo Florian,

bei dir wird alles ohne Fehler kompiliert, nur das Linken klappt nicht. 
Versuch mal aus irgend einem Example die Scriptdatei für den Linker zu 
kopieren.

Verwendest du GCC? Falls ja, kann es sein, dass der GCC-Script für den 
Linker nicht richtig installiert wurde...

Gruß
Max

von S.You (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem und ich brauche eine Unterstützung:
Ich versuche eine CAN-Kommunikation zwischen zwei Keil/MCB2100 
aufzubauen und daraus eine Anzeige zu machen.

Die Hardware habe beSTELLT, hat jemand da schon Erfahrung?

Bitte um Unterstützung

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.