parallaxinc / SimpleIDE

SimpleIDE for Propeller
26 stars 13 forks source link

SimpleIDE Create Project Library does not link .cog objects. #184

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
A) What steps will reproduce the problem?

  1. Create a project that adds/uses one or more .cogc files.
  2. Compile without Create Project Library. Compile ok.

B) What is the expected behavior (output)?

Check Create Project Library, and the project should still compile.

C) What do you see instead?

With Create Project Library checked a linker error will be generated.

D) Classify the bug as one of the following:

2. Medium Priority

E) Application Version and Platform:

Version
    SimpleIDE 0-9-43

Provide any links or additional information below if possible.

http://forums.parallax.com/showthread.php/150112-SimpleIDE-and-multiple-.cogc-fi
les

Original issue reported on code.google.com by jsden...@gmail.com on 8 Sep 2013 at 7:29

GoogleCodeExporter commented 9 years ago
This is a very interesting bug.

GOOD OUTPUT LOOKS LIKE THIS:

Project Directory: C:/Users/Steve/Documents/SimpleIDE/My Projects/

propeller-elf-gcc.exe -v GCC 4.6.1 (propellergcc_v1_0_0_2162)
propeller-elf-gcc.exe -r -Os -mcog -o cmm/cogcA.cog -xc cogcA.cogc
propeller-elf-objcopy --localize-text --rename-section .text=cogcA.cog 
cmm/cogcA.cog
propeller-elf-gcc.exe -r -Os -mcog -o cmm/cogcB.cog -xc cogcB.cogc
propeller-elf-objcopy --localize-text --rename-section .text=cogcB.cog 
cmm/cogcB.cog
propeller-elf-gcc.exe -I . -L . -I ../Learn/Simple 
Libraries/Utility/libsimpletools -L ../Learn/Simple 
Libraries/Utility/libsimpletools/cmm/ -I 
C:/Users/Steve/Documents/SimpleIDE/Learn/Simple Libraries/Text 
Devices/libsimpletext -L C:/Users/Steve/Documents/SimpleIDE/Learn/Simple 
Libraries/Text Devices/libsimpletext/cmm/ -I 
C:/Users/Steve/Documents/SimpleIDE/Learn/Simple Libraries/Protocol/libsimplei2c 
-L C:/Users/Steve/Documents/SimpleIDE/Learn/Simple 
Libraries/Protocol/libsimplei2c/cmm/ -o cmm/multicogc.elf -Os -mcmm 
-m32bit-doubles -fno-exceptions -std=c99 cmm/cogcA.cog cmm/cogcB.cog 
multicogc.c -lsimpletools -lsimpletext -lsimplei2c -lsimpletools -lsimpletext 
-lsimpletools
propeller-load -s cmm/multicogc.elf
propeller-elf-objdump -h cmm/multicogc.elf
Done. Build Succeeded!

BAD OUTPUT LOOKS LIKE THIS:

Project Directory: C:/Users/Steve/Documents/SimpleIDE/My Projects/

propeller-elf-gcc.exe -v GCC 4.6.1 (propellergcc_v1_0_0_2162)
propeller-elf-gcc.exe -r -Os -mcog -o cmm/cogcA.cog -xc cogcA.cogc
propeller-elf-objcopy --localize-text --rename-section .text=cogcA.cog 
cmm/cogcA.cog
propeller-elf-gcc.exe -r -Os -mcog -o cmm/cogcB.cog -xc cogcB.cogc
propeller-elf-objcopy --localize-text --rename-section .text=cogcB.cog 
cmm/cogcB.cog
propeller-elf-ar.exe rs cmm/multicogc.a cmm/cogcA.cog cmm/cogcB.cog
propeller-elf-ar.exe: creating cmm/multicogc.a
propeller-elf-gcc.exe -I . -L . -I ../Learn/Simple 
Libraries/Utility/libsimpletools -L ../Learn/Simple 
Libraries/Utility/libsimpletools/cmm/ -I 
C:/Users/Steve/Documents/SimpleIDE/Learn/Simple Libraries/Text 
Devices/libsimpletext -L C:/Users/Steve/Documents/SimpleIDE/Learn/Simple 
Libraries/Text Devices/libsimpletext/cmm/ -I 
C:/Users/Steve/Documents/SimpleIDE/Learn/Simple Libraries/Protocol/libsimplei2c 
-L C:/Users/Steve/Documents/SimpleIDE/Learn/Simple 
Libraries/Protocol/libsimplei2c/cmm/ -o cmm/multicogc.elf -Os -mcmm 
-m32bit-doubles -fno-exceptions -std=c99 multicogc.c cmm/multicogc.a 
-lsimpletools -lsimpletext -lsimplei2c -lsimpletools -lsimpletext -lsimpletools
C:\Users\Steve\AppData\Local\Temp\ccI84tly.o: In function `_startB':
(.text+0x20): undefined reference to `__load_start_cogcB_cog'
collect2: ld returned 1 exit status
Done. Build Failed!

Check source for bad function call or global variable name _load_start_cogcB_cog

C:\Users\Steve\Documents\SimpleIDE\My Projects>propeller-elf-objdump -h 
cmm/multicogc.a
In archive cmm/multicogc.a:

cogcA.cog:     file format elf32-propeller

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 cogcA.cog     000000c0  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .bss          00000000  00000000  00000000  000000f4  2**2
                  ALLOC
  2 .data         00000020  00000000  00000000  000000f4  2**2
                  CONTENTS, ALLOC, LOAD, DATA

cogcB.cog:     file format elf32-propeller

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 cogcB.cog     000000c0  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .bss          00000000  00000000  00000000  000000f4  2**2
                  ALLOC
  2 .data         00000020  00000000  00000000  000000f4  2**2
                  CONTENTS, ALLOC, LOAD, DATA

Original comment by jsden...@gmail.com on 2 Feb 2014 at 6:28

GoogleCodeExporter commented 9 years ago
Build with library works startB() and call to startB() are removed.

Original comment by jsden...@gmail.com on 2 Feb 2014 at 6:32

GoogleCodeExporter commented 9 years ago
According to Eric, we need to add some assignments in the cog code to ensure 
that COGC programs get linked correctly. Eric explained it in email ....

> Adding this makes no difference:
> const unsigned int *cogA_code = _load_start_cogA_cog;
> const unsigned int *cogB_code = _load_start_cogB_cog;

Perhaps I didn't explain it well. Those statements should go in the
source code for the .cog files, not in the main file. The first line
goes in cogA.cogc, the second in cogB.cogc. (You'll also have to add
appropriate definitions for extern unsigned int _load_start_cogX_cog[]
to those files).

Then the main program refers to those symbols instead of to
_load_start_cogX_cog. There should be no references to _load_start_XXX
outside of the .cog files. The reference to cogA_code in the main
program will force the cogA.cog file to be linked from the library;
similarly for the reference to cogB_code.

This is necessary because _load_start_XXX symbols are only defined at
the very end of linking. They do not appear anywhere in the .cog files,
so the linker has no way of knowing (for example) that
_load_start_cogA_cog is associated with cogA.cog. This may seem
counter-intuitive at first, but it's because in _load_start_XXX the XXX
stands for a *section* name, not a file name. We happen to have adopted
the convention that COG code is placed in a section that has a name
based on the file, but that is arbitrary (controlled by the options to
objcopy).

Thanks to Eric!

Original comment by jsden...@gmail.com on 4 Feb 2014 at 6:56

GoogleCodeExporter commented 9 years ago
Here is an example of what works with Create Project Library selected in 
SimpleIDE.

<<< multicogc.c >>>

/**
 * This is the main multicogc program file.
 */
#include "cog_test.h"
#include "simpletools.h"                      // Include simpletools library 

/* control block for cogA */
struct {
    unsigned stack[STACK_SIZE_A];
    volatile struct cogA_mailbox A;
} parA;

/* control block for cogB */
struct {
    unsigned stack[STACK_SIZE_B];
    volatile struct cogB_mailbox B;
} parB;

/* start cogA */
void startA(volatile void *parptr)
{
    extern unsigned int *cogcA_code;
#if defined(__PROPELLER_XMM__) || defined(__PROPELLER_XMMC__)
    load_cog_driver_xmm(cogcA_code, 496, (uint32_t *)parptr);
#else
    cognew(cogcA_code, parptr);
#endif
}

/* start cogB */
void startB(volatile void *parptr)
{
    extern unsigned int *cogcB_code;
#if defined(__PROPELLER_XMM__) || defined(__PROPELLER_XMMC__)
    load_cog_driver_xmm(cogcB_code, 496, (uint32_t *)parptr);
#else
    cognew(cogcB_code, parptr);
#endif
}

int main(void)
{
/* start the A cog */
    putLine("starting cogA");
    startA(&parA.A);

/* start the B cog */
    putLine("starting cogB");
    startB(&parB.B);

/* loop forever */
    while(1) {
        sleep(1);
        putStr("cogA: ");
        putLine(parA.A.cog_message);
        putStr("cogB: ");
        putLine(parB.B.cog_message);
    }
    return 0;
}

<<< cog_test.h >>>

#ifndef __COG_TEST_H__
#define __COG_TEST_H__

#define STACK_SIZE_A 16
#define STACK_SIZE_B 16
#define COG_MESSAGE_SIZE    128

struct cogA_mailbox {
    int     data;
    char    cog_message[COG_MESSAGE_SIZE];
};

struct cogB_mailbox {
    int     data;
    char    cog_message[COG_MESSAGE_SIZE];
};

#endif

<<< cogcA.cogc >>>

#include <propeller.h>
#include "cog_test.h"

extern unsigned int _load_start_cogcA_cog[];
const unsigned int *cogcA_code = _load_start_cogcA_cog;

_NATIVE
void main (struct cogA_mailbox *m)
{
    strcpy(m->cog_message,"cogA started");
    for(;;) strcpy(m->cog_message,"cogA running");
}

<<< cogcB.cogc >>>

#include <propeller.h>
#include "cog_test.h"

extern unsigned int _load_start_cogcB_cog[];
const unsigned int *cogcB_code = _load_start_cogcB_cog;

_NATIVE
void main (struct cogB_mailbox *m)
{
    strcpy(m->cog_message,"cogB started");
    for(;;) strcpy(m->cog_message,"cogB running");
}

Original comment by jsden...@gmail.com on 4 Feb 2014 at 6:59