-1

I am writing a program in C for NXP freescale kinetis microcontroller KEA128. I modified the linker description file and proceeded to write a simple C program in C. But when I build the project, it gives the following error message

build\src\flash.o:(.rodata.flashLocat+0x0): multiple definition of `flashLocat'
build\src\main.o:(.rodata.flashLocat+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

Here I am attaching my C program file and main file that calls the functions for erasing and writing into the flash and my linker description file. Following is my flash.c and flash.h files

#include "flash.h"

int flashEraseSector(long int locat)
{
        int temp1,temp2,temp3;

            temp1 = (locat << 8);
            temp1 = temp1 >> 24;
            temp2 = (locat << 16);
            temp2 = temp2 >> 24;
            temp3 = (locat << 24);
            temp3 = temp3 >> 24;


            while(((FTMRE_FSTAT)&(1UL << 7))==0x00);

            if(!((FTMRE_FSTAT)==0x80))
                    {FTMRE_FSTAT = 0x30;}

            int IX = 0;
            FTMRE_FCCOBIX = temp1;
            IX = 1;
            FTMRE_FCCOBIX = temp2;
            IX = 2;
            FTMRE_FCCOBIX = temp3;
            IX = 3;
            FTMRE_FCCOBIX = 0x0A;   //erase a sector

            FTMRE_FSTAT = 0x80;

            while(((FTMRE_FSTAT)&(1UL << 7))==0x00);
        return 1;
}

/*------------------------------------------------------------------------------
  Write a long word to an erased flash block
 *------------------------------------------------------------------------------*/

int flashWriteLongWord(long int locat,long int value)
{
        int temp1,temp2,temp3,temp4,temp5,temp6,temp7;

            temp1 = (locat << 8);
            temp1 = temp1 >> 24;
            temp2 = (locat << 16);
            temp2 = temp2 >> 24;
            temp3 = (locat << 24);
            temp3 = temp3 >> 24;
            temp4 = value >> 24;
            temp5 = (value << 8);
            temp5 = temp5 >> 24;
            temp6 = (value << 16);
            temp6 = temp6 >> 24;
            temp7 = (value << 24);
            temp7 = temp7 >> 24;

            while(((FTMRE_FSTAT)&(1UL << 7))==0x00);

            if(!((FTMRE_FSTAT)==0x80))
                    {FTMRE_FSTAT = 0x30;}
            int IX = 0;
            FTMRE_FCCOBIX = 0x06;    //0x06 is instruction code for write long word.
            IX = 1;
            FTMRE_FCCOBIX = temp1;
            IX = 2;
            FTMRE_FCCOBIX = temp2;
            IX = 3;
            FTMRE_FCCOBIX = temp3;
            IX = 4;
            FTMRE_FCCOBIX = temp4;
            IX = 5;
            FTMRE_FCCOBIX = temp5;
            IX = 6;
            FTMRE_FCCOBIX = temp6;
            IX = 7;
            FTMRE_FCCOBIX = temp7;

            FTMRE_FSTAT = 0x80;

            while(((FTMRE_FSTAT)&(1UL << 7))==0x00);
        return 1;
}

Here is my flash.h file

#ifndef SRC_FLASH_H_
#define SRC_FLASH_H_

#include "derivative.h" /* include peripheral declarations */
const long int flashLocat = 0x00000800;
int flashEraseSector(long int locat);
int flashWriteLongWord(long int locat,long int value);

#endif /* SRC_FLASH_H_ */

Here is my main file int main(void) { long int value; uint8_t flashStatus; value = 2147483648;

    NVIC_ISER |= ((unsigned int)0x1<<22); // Interrupt Set-Enable Register, IRQ22 (PIT_CH0)

    PIT_TFLG0 = 0x1; // clear TIF
    PIT_TCTRL0 = 0x03; // CHN = 0 -> not chained, TIE = 1 -> interrupt enabled, TEN = 1 -> timer enabled

    CpuComm_Init();

    flashStatus = flashEraseSector(flashLocat);
    flashWriteLongWord(flashLocat,value);

    for(;;)
    {
    }

    return 0;
}

Here is my linker description file:

/*


**
**  File        : KEAZ128M4_flash.ld
**
**  Default linker command file for Flash targets
**
*****************************************************************************
*/
/* Entry Point */
/*ENTRY(__init_hardware)*/
ENTRY(RESET_handler)

/* Highest address of the user mode stack */
_estack = 0x20003000;    /* end of SRAM */
__SP_INIT = _estack;

/* Generate a link error if heap and stack don't fit into RAM */
/*__heap_size = 0x100;  */          /* required amount of heap is 256 Bytes */
/*__stack_size = 0x100; */              /* required amount of stack is 256 Bytes*/

/* Specify the memory areas */
MEMORY
{
  m_interrupts  (rx) : ORIGIN = 0x00000000, LENGTH = 0xC0   /*192 Bytes*/
  m_cfmprotrom  (rx) : ORIGIN = 0x00000400, LENGTH = 0x10   /*16 Bytes*/
  m_text        (rx) : ORIGIN = 0x00000800, LENGTH = 128K - 0x800
  /*reserving the last 2KB of flash by subtracting those bytes (0x800) from m_text segment*/
  m_data       (rwx) : ORIGIN = 0x1FFFF000, LENGTH = 16K            /* SRAM */
}


/* Define output sections */
SECTIONS
{
  /* The startup code goes first into Flash */

  /*'.' means the location coounter, at the start of SECTIONS 
   *  command the location counter is set to the value '0'
   */

  .interrupts :
  {
    __vector_table = .;             
    . = ALIGN(4);
    KEEP(*(.vectortable)) /* Startup code */
    . = ALIGN(4);
  } > m_interrupts

  /* Above lines of code mean an output section '.interrupts'
   * has input sections called vector_table and *(.vectortable)
   * means all '.vectortable' input sections in all input files.
   */
  .cfmprotect :
  {
    . = ALIGN(4);
    KEEP(*(.cfmconfig)) /* Flash Configuration Field (FCF) */
    . = ALIGN(4);
  } > m_cfmprotrom

  /* The program code and other data goes into Flash */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } > m_text

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > m_text
  .ARM : {
    __exidx_start = .;
      *(.ARM.exidx*)
      __exidx_end = .;
  } > m_text

  .ctors :
  {
    __CTOR_LIST__ = .;
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    /* We don't want to include the .ctor section from
       from the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
    __CTOR_END__ = .;
  } > m_text  
  .dtors :
  {
    __DTOR_LIST__ = .;
    KEEP (*crtbegin.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
    __DTOR_END__ = .;
  } > m_text  

  .preinit_array :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } > m_text
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } > m_text
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);

    ___ROM_AT = .;
  } > m_text

  /* reserve MTB memory at the beginning of m_data */
  .mtb : /* MTB buffer address as defined by the hardware */
  {
    . = ALIGN(8);
    _mtb_start = .;
    KEEP(*(.mtb_buf)) /* need to KEEP Micro Trace Buffer as not referenced by application */
    . = ALIGN(8);
    _mtb_end = .;
  } > m_data  

  /* Initialized data sections goes into RAM, load LMA copy after code */

   __stacktop = ORIGIN(m_data) + LENGTH(m_data);
    __data_load = LOADADDR(.data);
    . = ORIGIN(m_data);
  .data : AT(___ROM_AT)
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } > m_data

  ___data_size = _edata - _sdata;

  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    __START_BSS = .;
    PROVIDE ( __bss_start__ = __START_BSS );
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    __END_BSS = .;
    PROVIDE ( __bss_end__ = __END_BSS );
  } > m_data

  _romp_at = ___ROM_AT + SIZEOF(.data);
  .romp : AT(_romp_at)
  {
    __S_romp = _romp_at;
    LONG(___ROM_AT);
    LONG(_sdata);
    LONG(___data_size);
    LONG(0);
    LONG(0);
    LONG(0);
  } > m_data

  /* User_heap_stack section, used to check that there is enough RAM left */
 /* ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    __heap_addr = .;
    . = . + __heap_size;
    . = . + __stack_size;
    . = ALIGN(4);
  } > m_data
 */
  .ARM.attributes 0 : { *(.ARM.attributes) }
}
user8540390
  • 143
  • 1
  • 10
  • 3
    Don't define variables or constants in header files. If you do, then they will be defined in each [*translation unit*](https://en.wikipedia.org/wiki/Translation_unit_(programming)) where you include the header file. Only *declare* the variables and constants in the header file. – Some programmer dude Jun 05 '18 at 14:32
  • If i declare in main function, and built it and it is showing an error called `src\main.c:358:14: error: assignment of read-only variable 'flashLocat' flashLocat = 0x00000800;` – user8540390 Jun 05 '18 at 14:35
  • 1
    Also note that while the code you have might be for a specific purpose, the problem you have is really unrelated to that purpose. You should make the titles of your questions short summaries of the actual problem you have. Please [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask), and I also recommend you read [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). – Some programmer dude Jun 05 '18 at 14:35

2 Answers2

2

In the header file you should declare the constant:

extern const long int flashLocat;

Then in one single source file, in the global scope outside of any function, you define the constant:

const long int flashLocat = 0x00000800;
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Yeah I did like you said, but the error is `src\main.c:358:14: error: assignment of read-only variable 'flashLocat' flashLocat = 0x00000800;` Should i do any changes in linker description file ? – user8540390 Jun 05 '18 at 14:43
  • @user8540390 Then you're doing something else wrong. If you do exactly as I say in my answer you should not have that problem. It seems to me like you're doing a lot you don't show us, and one of those things is an *assignment* of the constant, which is not allowed. – Some programmer dude Jun 05 '18 at 14:46
  • Build gave no errors, when remove const keyword but the address i specified is in flash memory (from my linker description file 0x00000800 address is in flash) Will this work? It gave no errors... before porting on the board will this not corrupt my flash right? Am I doing it in right way based on the concept? just erasing 512 Bytes and writing into the flash – user8540390 Jun 05 '18 at 14:49
  • `flashLocat` is **not** a constant. C does not support symbolic constants (except for enum-constants). – too honest for this site Jun 05 '18 at 15:34
1

Since you include flash.h in both flash.c and main.c, the variable flashLocat is defined twice. That's why you are getting an error.

Luke B
  • 1,143
  • 1
  • 11
  • 22