Codewarrior Build-Tools - Problem with ROM Libraries and code optimization

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Codewarrior Build-Tools - Problem with ROM Libraries and code optimization

1,713 次查看
puppetmaster
Contributor II

Hello,

 

first of all:

 

Environment: Codewarrior IDE 5.9.0 Build 5294

Using Codewarrior 5.1 SP for HCS12 G64 Build 110727

MCU:  HCS12 G64

 

Problem description:

 

I've cut my software project in several small projects after I assured that the complete software was running fine.

I decided to use ROM libraries as this technic allowed me to share major functional parts within my application without redefining them several times; saves space and troubles (which I naively thought).

 

The software is split in two functional core parts (which are segmented within itself again).

 

SEGMENTATIONS

 

Boot/Diagnostic Core

 

0x4000-0x41FF Bootloader and Device Initialisation

0x4200-0x4DFF Device Drivers

0x5F00-0x5FFF Bootloader ISR Vector

0x4E00-0x5EFF and 0x6000-0x7FFF UDS (ISO compliant implementation)

0xFE00-0xFFFF Low Vectors

 

Main Software

0xC000-0xFDFF  Software device post-initalisation and near-segmented software functionality (like the scheduler)

0xC8000-0xC8BFF, 0xCB000-0xCBFFF, 0xE8000-0xEBFFF - far-segmented software functionality

 

Ok, this should cover the question "where is what located?"

 

Everything works as before the cut... So the functionality is given

 

But now for the functional part which fails me hard due to the compiler; I think it's the optimization and I don't know how to turn it off (what flags)

 

It took me about an hour to realise this error! (You'll read why later)

 

First of: ALL ROM-Libraries are compiled as functions, so the end signature is "RTC" (Return from CALL)

 

When I call my device driver API from within a far-segment the compiler does a correct

 

CALL  DeviceDriverFunction, PAGE(DeviceDriverFunction)

 

HOWEVER

 

IF I call a DeviceDriverFunction from within the near-segment 0xC000 I get a

 

JSR DeviceDriverFunction

 

As result the function runs over - as it ignores RTC and it searches for RTS; ending in a Illegal Breakpoint some time LATER (hard to debug!! <-!!)

 

BUT, and that is the funny thing, if I call it from within the 0x4000-0x7FFF - segment I get a correct

 

CALL DeviceDriverFunction, PAGE(DeviceDriverFunction)

 

 

ALL Projects have the  "-OnB=b" option in the compiler settings

 

The only possible workaround for now is inline assembly with a hard call so that the compile won't optimize that fraction. It's an ugly hack and error prone due to some parameters I eventually have to push correclty into the registers!

 

The projects have the same dependency setup:

 

DeviceDrivers.lib is the root for all

Uds.lib includes DeviceDrivers.lib

Bootloader does include DeviceDrivers.lib and Uds.lib

Main-SW does include DeviceDrivers.lib and Uds.lib

 

The Bootloader combines Uds.lib and DeviceDriver.lib in it's final s19 via HEXFILE - command. I can't flash the ROM libraries otherwise.

 

Main-SW uses only the addresses the Uds.lib and DeviceDriver.lib are providing

 

 

The link-order does not affect this behavior at all!

 

My custom startup code to initialize the ROM-Libraries (used in the bootloader) works fine too (I have code to execute in RAM, if that would not work, my software would not work at all as I have to flash the main software via CAN). Base-Template was given by the Build-Tools-Manual (didn't work just as given, the Smartlinker in Codewarrior Version 5.04 seems to have more restrictions than the version used to compile the informations in the manual!)

 

I'd really appreciate any useful hint to solve this stupid problem as I already fiddled around for a few hours and can't come up with a solution... 

 

Thanks in advance

 

   :smileyhappy:

标签 (1)
0 项奖励
回复
2 回复数

1,069 次查看
CompilerGuru
NXP Employee
NXP Employee

The compiler decides to use a far or near function call depending on these conditions:

- If  the function is explicitely __far (far) or __near qualified, then this wins.

- Otherwise, if the called function is declared in a section being qualified as far (__FAR_SEG) or near (__NEAR_SEG), then this wins.

- Otherwise, the memory model used defines the calling convention. It is __near in the SMALL memory model and __far in the BANKED or LARGE memory model.

 

If you want that the compiler makes call's to a function, place the functions and their declarations into a __FAR_SEG qualified section.

E.g. (might contain typos, just typing this in here, did not compile it)

 

/* fun.h */#pragma push#pragma CODE_SEG __FAR_SEG HAVE_FUN_SECTIONvoid haveFun();#pragma pop/* fun.c */#include "fun.h"void haveFun() {  /* fun stuff here */}

 

In my point of view, the calling convention to be used is closely related in how the function gets allocated. Therefore the use of section qualifiers is the proper approach over the use of function qualifiers.

 

 

As note, while a ROM library allows to reuse the code in the bootloader in the actual app, it also means that

the actual app has to be built against a specific revision of the bootloader. Basically updating the bootloader in the future might be problematic. Therefore I would consider implementing the boot loader and the actual app as 2 separate applications, and if any sharing is helpful, to code the reuse in the app explicitely via defined entry points into the bootloader.

 

PS: I don't see why using CALL/__far calling convention is necessary for bootloader code as apparently all the code in the bootloader is allocated non banked. I don't see any reason for that, just disadvantages like more code, more stack space used and slower execution.

 

0 项奖励
回复

1,069 次查看
puppetmaster
Contributor II

Hello!

 

thanks for your reply.

 

Well, I just tried an approach based on your suggestions. I set the __NEAR_SEG keyword explicitly... strange, but it worked?! I assumed, as the bootloader and its core drivers were located in the NEAR segment, that the compiler would figure that out by itself. Guess I was totally wrong :smileysurprised:

 

About my ROM Library approach; I read about possible drawbacks, but rest assured my approach goes beyond those limits. We use specified interfaces in the software project, so as long as the interface names don't change it doesn't matter at all. It is supposed to replace the code behind those interfaces. The bootloader and its components, like the diagnostic application and device drivers, are divided in protected and unprotected code segments. So, within the bootloader application I can replace the unprotected parts of the bootloader itself as well as parts of the ROM libraries used. The main application software itself is completely replaceable. I know that I have to reflash the whole application after replacing parts of the bootloader (that is, because addresses might change), but that is an accepted design concept.

 

It may seem that I shoot sparrows with a cannon, but the software architecture is a modular design which can easily comply to the given ISO standards. So we can deliver a ECU specified as class A and fall back (i.e. due to a flash fault) to class C (means: still flashable and responsive).

It is just a question on how you react to draw backs to turn them into advantages. :smileywink:

 

By the way, do you know this error message?! I can't find a solution either:

 

I'm getting the Linker Error

 

L1702: Startup data structure field _Range.size is unknown

 

for each ROM Library.

 

Though I have not touched the provided start.h files from the Codewarrior Libraries!

 

In there it's defined as this:

 

typedef struct _Range {  unsigned char * beg; int size;      /* [beg..beg+size] */} _Range;extern struct _tagStartup {#ifndef __NO_FLAGS_OFFSET     unsigned char   flags;#endif#ifndef __NO_MAIN_OFFSET     _PFunc          main;            /* top level procedure of user program */#endif#ifndef __NO_STACKOFFSET_OFFSET     Word            stackOffset;     /* 16bit, initial value of the stack pointer */#endif     unsigned int    nofZeroOuts;     /* number of zero out ranges */     _Range *PTR16   pZeroOut;        /* vector of ranges with nofZeroOuts elements */#if defined(__BANKED_COPY_DOWN)     _Copy *__pptr    toCopyDownBeg;   /* rom-address where copydown-data begins */#else     _Copy *PTR16    toCopyDownBeg;   /* rom-address where copydown-data begins */#endif#if 0 /* switch on to implement ROM libraries */     unsigned int    nofLibInits;     /* number of library startup descriptors */     _LibInit *PTR16 libInits;        /* vector of pointers to library startup descriptors */#endif#ifdef __cplusplus     unsigned int    nofInitBodies;   /* number of init functions for C++ constructors */     _Cpp *PTR16     initBodies;      /* vector of function pointers to init functions for C++ constructors */     unsigned int    nofFiniBodies;   /* number of fini functions for C++ destructors */     _Cpp *PTR16     finiBodies;      /* vector of function pointers to fini functions for C++ destructors */#endif} _startupData;

 

So, what kind of fields for _Range is the SmartLinker v5.04 expecting?! Sadly ROM Libraries (as well as the startupData in general) are not well documented.... :smileyindifferent:  I just want to get rid of those message without suppressing them...

 

Thank you in advance!

0 项奖励
回复