First project with CodeWarrior and first 2 problems

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

First project with CodeWarrior and first 2 problems

6,556 Views
mjbcswitzerland
Specialist V
Hi All
 
I have just installed CodeWarrior 3.1 for the HCS12 (I know it's not the latest version but I don't think upgrading will solve the two (probably) simple issues).
 
1. When I run a demo project I can use the simulator with source level debugging but after adding my own source files the debugger says it has no debug information and the linker gives the following warning *.o has no DWARF debug info.
I assume that there is a setting somewhere to tell the compiler to include the debug info but after comparing each option in the compiler and linker settings I don't see which one it is - also there is no difference between the settings in my project and the demo project.
Any one know the answer?
 
2. The project which I have used was available as an IAR embedded workbench project and I had no problems getting it to compile and link (presumably without errors since it will simulate - although only as assember without source level info - see point 1 above).
The size of the original IAR project was 23k code with 350 bytes data.
The size of the CodeWarrior generated code (I played a bit with the optimisation sliders but could get it noticably smaller) is 32k with 2k data (rounded), whereas the ANSI library is taking up 7k [7846 bytes to be exact] code and 2k [2012 bytes] data.
The project shouldn't actually use any library functions apart from low level stuff such as MUL and DIV etc. The reason is that the project uses its own library functions eg. Xmalloc() rather than malloc().
I expect the CodeWarrior code efficiency to be equivalent to the IAR efficiency and so I conclude that almost 7k of code is being unnecessarily linked from the ANSI library.
Can anyone suggest why this may be the case or how it can be stopped? I didn't take the risk of removing the library from the project because it probably will cause other problems - there is a warning that such actions are not reversibly and as a first time user I didn't take any risks...
 
Thanks for any help. It will be appreciated.
 
Best regards
 
Mark Butcher
www.mjbc.ch
 
Labels (1)
Tags (1)
0 Kudos
11 Replies

585 Views
CrasyCat
Specialist III
Hello
 
In order to get debug info for your application make sure there is a dot next to each source file in the column with the green bug on top.
This indicate to the compiler it should generate debug info.
 
To get a dot there just click with the right mouse button next to the source file (or source folder) in the column headed with the green bug.
 
On question 2, there is no magic answer to that one.
Basic thing you can check:
 - Is IAR providing startup code, which only initializes the stack pointer or are they initializing all variables during Startup?
 - What is int size when you build your application with IAR?
 - What is enumerated variable size you are using with IAR?
 - Which memory model are you using in CodeWarrior?
 - Where did you look at code size? The code size indicated in the .mcp window status bar is not the size of the application. THe size of the application can be retrieved from the .map file.
Scrolling in the.map file you will see something like
"Summary of section sizes per section type:
READ_ONLY (R):          88 (dec:      136)
READ_WRITE (R/W):      101 (dec:      257)
NO_INIT (N/I):         23D (dec:      573)"
Which indicates actual code and data size.
 
Size for READ_WRITE sections includes stack size.
Size for READ_ONLY sections includes vector table size.
 
I hope this helps. 
 
CrasyCat
0 Kudos

585 Views
mjbcswitzerland
Specialist V

Hi and thanks for the help so far.

The little dot to the right of the file, under the little green bug was the solution. I just had to click on all dots (or on the dot to the right of a group to configure all). I had tried all sorts of things including setting some compiler flags manually to ensure the correct format (DWARF or HIWARE) - none of which helped...

About the library size. I think that the value I was using was really not the correct size and probably represents the code size if it actually gets linked because now that I have started with the serial monitor I have seen that 24k is downloaded rather than 32k as displayed. This is very similar to the code size I get with the IAR compiler. Therefore I believe that i can use the library as it is - I don't think that the malloc functions have allocated any memory since I didn't see anything in the map file. The operating system which I use defines its own space at run time which is much more practical than having to set limits and compile libraries - it also means the heap space can be changed dynamically so that the stack has more room if not so much heap is required...

Is the simulator of any real use? My code stopped in a forever loop waiting for the PLL to lock - which was simply avoided by jumping over it but then it just ran in the operating system kernal in a forever loop. I also found that the simulator was set up quite differently (with respect to memory map) and so didn't really show me that the target was not going to work when I first tried it. I set up the memory correctly and got first signs of life.

Now I have just 3 things to adjust and then the project should also run when compiled with CodeWarrior.
1. Set up the heap space.
2. Get interrupts to work - although the peripherals are set up correctly no interrupts are arriving.
3. Force a few routines into a specific page so that they can manipulate another page (without unintentionally being located in the that page...)

1 - What I need to konw is the memory location just after the highest variable. With the GNU compiler there is a variable called _end which is set here and its address can simply be looked at using &_end. With the UAR compile it is necessary to use
    #pragma segment="DATA16_Z"
    pucBottomOfHeap = (unsigned char*)__segment_end("DATA16_Z");
Do you know the best way of getting this info from CodeWarrior?

By the way I did look at the structure _tagStartup which is used for initialisation of bss and data segments but didn't see that it delivered the answer in an easy fashion. Quite surprisingly I saw that it was clearing about 280 bytes in bss from 0x2c00 and then setting 6 bytes of initialised data also from 0x2c00 - meaning that the initialisation first clears all data (initialised + bss) and then writes initialised. In my case I see that the address which I am looking for is 0x2c00 + 281 but to get this from the structure woul dmean checking the structure carefully for the highest address - bss is actually after initialised here.

2 - Probably trivial - have seen that there are no entries in the interrupt vector so they are obviously being handled by the monitor's general catch interrupt. Will read the docs.

3 - To ensure that code is at a certain location I use (for example)
 #pragma location="FILE_ROUTINE" where FILE_ROUTINE is declared as a segment for the linker.
I wonder whether I can simply use something equivalent to force it into the ROM_4000 segment which is already defined in my prm file?

Thanks for any last hints.

Regards

Mark Butcher
www.mjbc.ch

0 Kudos

585 Views
CrasyCat
Specialist III

Hello

The linker is a smart linker. Only functions and variables really referenced in the application
will be linked to the application.
If malloc is not present in the .map file, the linker did not link it to the application.

Which HCS12 derivative are you trying to simulate?
Which derivative did you configure in the Simulator -> Derivative dialog?

1. Set up the heap space.
 Do you really need dynamic memory allocation in your application?
 If not there is no need to define a heap...

2. Get interrupts to work - although the peripherals are set up correctly no interrupts are arriving.
 Which connection are you using?
 If you are using a Multilink or Cyclone pro, you need to initialize the vector table directly.
 If you are using the serial monitor, there is a mirrored vector table somewhere in Flash and you have to
 initialize the corresponding entry in that mirrored table.
 If you are not sure about the address of the mirrored vector table check the "Vector Table Mirroring" tab in the
 "Monitor Setup" dialog.
 Also make sure to allocate your interrupt function in NON_BANKED flash (in section NON_BANKED for instance)
#pragma CODE_SEG NEAR NON_BANKED
interrupt void myInt(void) {
}
#pragma CODE_SEG DEFAULT
 
3. Force a few routines into a specific page so that they can manipulate another page (without unintentionally being located in the that page...)
If the question is how should I define that a function should be located in NON_BANKED memory, define it in NON:BANKED section as recommended above.

I hope this helps.


CrasyCat

0 Kudos

585 Views
mjbcswitzerland
Specialist V

By the way.

I managed to get the address after the top-most variable by doing the following

1. Set stack size definition to 1.
2. Use _startupData.stackOffset as the address of the RAM loaction after the last variable.
3. In the startup code I don't use _startupData.stackOffset but rather the top of memory to set the stack pointer.

Then it operates as desired (as far as I can see).

Regards

Mark Butcher
www.mjbc.ch

0 Kudos

585 Views
CrasyCat
Specialist III

Hello

Another way of doing that is to use the Linker predefined symbol __SEG_END_STACK.

Please refer to Linker manual or TN103 for more information on how to do that.

I have attached the technical note to this thread for your reference.

CrasyCat

 

0 Kudos

585 Views
mjbcswitzerland
Specialist V

Hi CrasyCat

Thanks for the tips. I have now been able to steer the code to the address range I wanted.

Unfortunately I had to stick with the previous solution to determine the end of the variables since the linker said it didn't know __SEG_END_STACK, or __SEG_START_STACK which is what I think that I need. I read TN103 which you posted (thanks also) and I am assuming that this feature in only available in newer CodeWarrior versions (I  have 3.1) - it does say from linker v.5.0.10 (in the components list I get 5.0.9.0 so this must be the case). Never mind, I think that the 'older' solution is adequate.

By the way do you have any ideas about my download/debugging problem. The flash is deleted and the download starts until there is code at 0x8000 and then it aborts with an error, saying that there is no memory at this address. I believe it is because it believes that there is memory at 0x4000..0x7fff and 0xc000..0xffff, with pages at 0x3C8000..0x3CBFFF and 0x3D8000..0x3DBFFF, which is basically correct but at the same time not absolutely true.

My code uses a linear range from 0x4000...0xffff (48k) and then just one page for a file system at 0x3D8000..0x3DBFFF (which is controlled by the code itself rather than the compiler) - hence the need to avoid the controlling routine being in put into the range 0x8000..0xbfff since it would otherwise shut itself out when paging in the file system....

With my other debuggers and download tools I have no problem with this strategy but I haven't yet found a solution with CodeWarrior. As a last resort I could do assembler level debugging with another tool which I have but will need a file with interleaved C-code and assembler code, such as that which the GNU compiler generates with " objdump -S target.elf > target.psa". Do you know whether CodeWarrior has something suitable?

Thanks for the support!!

Regards

Mark Butcher
www.mjbc.ch

 

0 Kudos

585 Views
CrasyCat
Specialist III

Hello

CodeWarrior for HC12 V3.1 does not support memory at address 0x8000..0xBFFF. It requires you to place the code in the real banked memory (0x3C8000..0x3CBFFF).

This is something which has been added in CodeWarrior for HC(S)12 V4.5. Extract from the V4.5 release notes:

"-Contiguous/flat flash programming support over the bank window for HCS12 devices, like programming from $4000 to $FFFF as a single flash block.
 The project setup should be changed by the user, as this way of using flash resource does not take advantage of the entire size of the flash (therefore, not the default setup)."

In order to be able to use that you have to upgrade to V4.5.  

CrasyCat

0 Kudos

585 Views
mjbcswitzerland
Specialist V

Hi
Thanks. That clears it up. I will update now so that my project will be possible.

Regards

Mark Butcher
www.mjbc.ch

 

0 Kudos

585 Views
mjbcswitzerland
Specialist V

Hi CrasyCat

1. The operating system and TCP/IP work with malloc so the heap is necessary. This is no longer a problem since I see that teh libraries version is not linked.

.2 Interrupts are working OK now - the vector table had not been added properly, which I corrected.

3. The project uses not banked memory. What I want is to force a routine to be at the address 0x4000 (to ensure that it is in the first page).

With the IAR project I do this with

#pragma location="FILE_ROUTINE"

where this is defined in the linker control file as follows:

-DFILE_ROUTINESTART=04000
-DFILE_ROUTINEEND=0407f

The code then starts at the desired location. I am sure that there is some method of doing something similar with CodeWarrior.

 

My biggest problem is the fact that I can not debug once the code is linked to addresses 0x8000..0xbfff - see my later posting. This is bugging me since I have a TELNET application which works fine when I compile it with the GNU compiler or the IAR compiler but crashes when I compile it with CodeWarrior. Since TELNET makes the code somewhat larger and it needs to be placed into the region which stops the debugger from working it is a real problem - how can I debug it to find out what CodeWarrior is compiling differently??

Any ideas?

Regards

Mark Butcher
www.mjbc.ch

 

0 Kudos

585 Views
CrasyCat
Specialist III
Hello
 
To make sure a function is allocated at address 0x4000, you have to define it in a user defined section and place the section accordingly in the .prm file.
 
Define the function as follows:
#pragma CODE_SEG NEAR MyCode
void MyFunc(void) {
}
#pragma CODE_SEG DEFAULT
 
Then in the PRM file if you are not using ROM_4000 currently add the following line in your placement block:
  MyCode  INTO ROM_4000;
If you are already using ROM_4000, specify MyCode first on the left side:
 MyCode, DEFAULT_ROM INTO ROM_4000;
 
CrasyCat
0 Kudos

585 Views
Technoman64
Contributor III
When I import files into a project I must open the Project Properties dialog and check the Debug box. This is the far right icon at the top of the project explorer window. After doing this the debug info will be included when you complie and link the project. You must highlight the file you have imported before clicking on the the Project Properties icon.
 
Not sure on the #2 question. The size of the Heap for malloc is set in the Liddefs.h file. This is located at c:\metrowerks\codewarrior CW12_V3.1\lib\hc12c\include if you choose the default install directory.
 
To change the size of the heap you must open the Codewarrior Library project located in the ...\lib\hc12c directory. You need to select the Library for your project from the list. Open Libdefs.h scroll down to the define for the heapsize and set for the number of bytes needed. Rebuild the library and the re-compile your project using the modified library.
 
I usually copy the modified library file to my project directory. Delete the library from the project(only removes the link to the library file). Then right click on the Library Folder in project explorer and Add the file that I placed in the project directory. This way if you modify the standard library for a later project it will not mess up previous work and you end up scracthing your head when you go back to it and forget!
 
Hope all that makes sense.
 

Message Edited by Technoman64 on 04-27-200606:45 PM

Message Edited by Technoman64 on 04-27-200606:48 PM

Message Edited by Technoman64 on 04-27-200606:49 PM

0 Kudos