Hi,
I've come up with another yet funny problems. Currently I'm trying to figure out how the Codewarrior linker works since it causes random crashed in the software if I try different features.
Attached to this post is a currently working PRM (not yet finished, just rough set-up). The derivative of choice is a S12G64; 64 KiB of Flash. However, if you sum up all the sections in there you will end up with approx 55 KiB.
I have deleted a section which Codewarrior did define which was 0x0C00-0x2FFF (9 KiB). The reason is that if I use this section everything crashes. Even so, in the MC9S12GRMV1 (Rev 1.23), Section 5.4.3 this section is defined as 'unimplemented' in S12G64!
So, I'm wondering where I can get my remaining 9 KiB which I'm missing?!
Second problem:
The S12 shall have the ability to use paged constants and variables.
Paged variables are out of question; Debugger crashes immediately (not responding); but was just a test after all (curiousity).
Moreover I tried to use paged constants, I did as the build tools reference manual described, BUT NONE of my paged constants were initialized at all; leading to total software crash (took me a while to find that out!).
So, why don't get these paged constants initialized?
Third problem:
I've implemented an OSEK based OS and everything runs smoothly. I explicitly tell the compiler whether the function is located in __near or __far otherwise the optimization it does goes totally wrong. So far it works unless I explicitly put functions in paged flash and mix a lot (like 5-6 layers) of unpaged and paged function calls. I tracked down the problem to the SWI instruction (this is my Yield-function, for switching the TCB).
The SWI call goes smoothly until doing the described mix up. Then it'll cause a random re-write of my Task-SP variable; so when leaving the SWI-ISR-handler it loads bulls into the Registers causing a total crash.
Though in ASM there is no pre-text happening to indicate this; I can't even see this re-write in the bus trace (though I wouldn't call this reliable as the bus trace seems to be pretty random at times). But even the CPU register does not point to that location... #pragma no_entry and the likes do not change this behavior. The assigned task stack is not a problem, I tried with up to 1 KiB but it does not even use up 96 Bytes.
An interrupt mix up should be out of question; at least I think so. The kernel task gets called periodically, disables all interrupts does some management code, enables them and does a SWI to re-load the interrupted task; takes less than 30us.
Has anyone came across the same problem or might know what I might possible be doing wrong here or where I could look into to narrow it down?
Thanks in advance for useful hints!
Kind regards,
Original Attachment has been moved to: Project.prm.zip
About interrupt crashes)
This could be caused by user manipulation with PPAGE register.
Problem is that interrupt routine doesn’t store PPAGE register on stack in default state. When code changes PPAGE in interrupt routine, access to unexpected address in main program will cause reset.
There are three basic ways how to handle PPAGE during enter/leave of interrupt routine.
I'm using the following compiler setting
-DPPAGE_ADDR=0x15
My SAVE and RESTORE context is PPAGE aware.
Since this is pretty much standard code I can post this
__asm { /* store TCB (previous task) */ #ifdef CPU_USE_BANK_MODEL ldaa PPAGE_ADDR ; PPAGE is not fixed to 0x30 -> see datapage.c psha #endif ldx OS_Task_TCB_Previous sts 0, x }
__asm { /* restore TCB (next task) */ ldx OS_Task_TCB_Current lds 0, x #ifdef CPU_USE_BANK_MODEL pula staa PPAGE_ADDR ; PPAGE is not fixed to 0x30 -> see datapage.c #endif }
As you can see PPAGE awareness is given. The thing I'm talking about is that two Task TCB get pretty much messed up...
Their SP are like 100 Bytes apart and out of the sudden.. the SP of the (possible/eventually preempted) task gets loaded whilst the other TCB is still active.
So I have currently TCB_A active and working on it, suddenly SP in the CPU gets the address of TCB_B from somewhere (as said there is no ASM instruction to be found which causes this and nothing appears on the bus trace either) and as soon as the SWI is left (RTI) the software crashes (naturally)
Below is the TASK where the fault occurs, but only in a extreme mix up combination as described... otherwise this is rock stable
The RTC - instruction shall never be called, (there would never be an RTC since the KernelTask is loaded via stack manipulation.
538: TASK( KernelTask ) { *** EVALUATION *** Function: OS_Task_KernelTask 539: /* since this task will always start here, assure it to be non-interruptable */ 540: DisableAllInterrupts(); 0000 160000 [4] JSR DisableAllInterrupts 541: 542: /* handle alarm events */ 543: OS_Kernel_AlarmHandler(); 0003 160000 [4] JSR OS_Kernel_AlarmHandler 544: 545: /* if the current task is configured as preemptive then execute the scheduler */ 546: if ( TASK_SCHEDULE_FULL == OS_Task_TCB_Current->descriptor->ucSchedule ) { 0006 fe0000 [3] LDX OS_Task_TCB_Current 0009 ed02 [3] LDY 2,X 000b e647 [3] LDAB 7,Y 000d 042106 [3] DBNE B,*+9 ;abs = 0016 547: OS_ReturnValue = Schedule(); 0010 160000 [4] JSR Schedule 0013 7b0000 [3] STAB OS_ReturnValue 548: } 549: 550: 551: /* can be interruptable once again */ 552: EnableAllInterrupts(); 0016 160000 [4] JSR EnableAllInterrupts 553: /* re-schedule */ 554: TASK_SWITCH(); 0019 3f [9] SWI 555: } 001a 0a [7] RTC 556:
Actually I've checked other OS implementations for S12 and they do almost the same as I do; therefore I don't know what's actually going wrong... maybe this is caused by the same strange oddity which causes the constants to be 'killed'??
Just idea: Default project has enabled Branch optimizer. One of the optimization is change JSR to BSR instruction (). If we use any page other except 0x0F (last page 0xC000 to 0xFFFF) as non banked memory, we have to disable this optimization.
Please try add compiler option -OnB=b to your project.
Note: BSR uses relative addressing mode to generate the effective address of the subroutine.
Actually I'm already using this flag
-CPUHCS12 -DPPAGE_ADDR=0x15 -D__NO_FLOAT__ -DCPU_USE_BANK_MODEL -Mb -OnB=b -WmsgSd3303
A really strange error... at least I think so.
About constants in paged ROM.
I suppose that MCU reset is caused by Illegal Address reset source. This is caused typically by user manipulation with PAGE registers.
In safety state PAGE registers should be handled only by compiler or code with PAGE manipulation has to be protected against interruption (interrupts disabled) and save/restore PAGE registers at begin/end of this code.
When we want use paged memory, we have to used at least 24bit addresses.
Paged variables are out of question. S12G64 hasn’t paged RAM.
Default ROM location is banked ROM. In case of constants we could told to compiler/linker that we want place constants out of default location in ROM by #pragma commands. For example:
#pragma CONST_SEG USRAPPL_BANKED_CODE
Unsigned int variable1;
#pragma CONST_SEG DEFAULT
Note: CONST_SEG is for constants, similar way you can use also drive placement of code, variables and strings (CODE_SEG, DATA_SEG and STRING_SEG).
There is keyword “far”(or __far) which is typically used for pointers to paged memory. PPAGE/GPAGE is selected automatically according used MCU (compiler option). PPAGE is default and only one option for S12G family.
For variable placement by #pragmas we could add similar keyword. For example:
#pragma DATA_SEG __FAR_SEG MY_RAM_F3
Note: For more details, I would like recommend our application note AN3784 Understanding the Memory Scheme
http://www.freescale.com/files/soft_dev_tools/doc/app_note/AN3784.pdf
and TN238 HCS12X – Data Definition in CodeWarrior installation directory on your disk. Default path:
"c:\Program Files\Freescale\CWS12v5.1\Help\PDF\TN238.pdf"
I have made sure that the PPAGE is correctly used in all cases... but I get exactly the same result like with 0x0C00-0x2FFF
When I moved the constants to a paged location I did as you wrote
#pragma CONST_SEG OS_APPL_CONST_UNSPECIFIED
const int __far dummy = 5;
#pragma CONST_SEG DEFAULT
The map file shows correct 24 Bit addresses. Actually I don't know whether the linker does the error here or the burner since the flash looks strange in these memory area as well...
About missing 9kB of flash)
You deleted 0x0C00-0x2FFF (9 KiB) from memory map.
I agree with you that Table 5-8. Global Address Ranges in RM is confusing. However there is one detail which you miss. Table 5-8. describes Global address map.
Range 0x0C00-0x2FFF in local memory map is equal to 0x0C8C00-0x0CAFFF (local memory map-paged) and this equal to 0x30C00’G-0x32FFF’G(global memory map).
Linker understood addresses in local memory map, for global addresses you should add “ ’G ”.
Page 0x0C you can define as:
PAGE_0C = READ_ONLY 0x0C8000 TO 0x0C8BFF;
ROM_0C00 = READ_ONLY 0x0C00 TO 0x2FFF; /*equal to 0x0C8C00-0x0CAFFF*/
PAGE_0C_B000 = READ_ONLY 0x0CB000 TO 0x0CBFFF;
Or you can omit non-banked mirror and just use banked form:
PAGE_0C = READ_ONLY 0x0C8000 TO 0x0CBFFF;
Access to non banked flash is faster, therefore default CW project use ROM_0C00 sector.
Thank you for all these answers.. I try to give a proper response on each of them.
Actually I deleted this sections since I didn't get it to run with my constants. It's exactly the same behavior as if I would put them into the paged area
I've attached three screenshots to clarify what I mean
I even tried to use
0x30CC'G TO 0x32FFF'G
as you suggested, but the elf loader does not understand it; though the linker does.
So next to the screenshot here is what the map-file says (don't be confused with the section, didn't change the name, just the destination address)
OS_APPL_CONST_UNSPECIFIED 640 R 0xC00 0xE7F ROM_4000_MODULE_CONF
OS_APPL_CONST_8 4 R 0xE80 0xE83 ROM_4000_MODULE_CONF
As you can see the addresses are correct, but the contents are 'empty' for the 0xC00 to 0x2FFF range
It looks exactly the same (except the address) in comparison to the 0x4000 address range.
OS_APPL_CONST_UNSPECIFIED 640 R 0x4000 0x427F ROM_4000_MODULE_CONF
OS_APPL_CONST_8 4 R 0x4280 0x4283 ROM_4000_MODULE_CONF
"Access to non banked flash is faster, therefore default CW project use ROM_0C00 sector."
My Codewarrior 5.9 does 0xC000 as default , ignoring 0x0C00 and outcommented 0x4000.
I gladly would like to use this 9 KiB section since I assume to never blow that boundary which makes it way easier for my bootloader (I partly erase flash, thus the 512Byte alignment) and having every constant in one place is the best after all...
0x30CC'G TO 0x32FFF'G is wrong range. 0x30CC'G is address from RAM.
Valid range is for example 0x30000'G TO 0x33FFF'G.
However S12G hasn’t GPAGE therefore range in global addresses has not sense.
Equivalent range in logical addresses is 0x0C8000 TO 0x0CBFFF.
I tested project in CodeWarrior and you are right. There is some issue with flash data in range 0x0C00 to 0x2FFF. CodeWarrior is not able program it. For example in case of S12G128 it works correctly (range 0x1400 to 0x1FFF).
I will contact CW experts with this issue.
As workaround I would like to recommend define page 0C as paged flash:
PAGE_0C = READ_ONLY 0x0C8000 TO 0x0CBFFF;
If you write constant at address 0x0C8C00, you will see the same constant also at address 0x0C00.
I also discover that Debugging Memory Map in default project doesn’t contain banked flash range.
For debugging is necessary change memory map in menu->HC12MultilinkCyclonepro (or another BDM interface)-> Debugging Memory Map…
For example:
Hi there!
I've been wondering if there is any progress about the Codewarrior bug?! I know I've been added to the list, but I've not seen anything since weeks?!
In the meantime I've helped myself and wrote a second bootloader to flash the whole software including the Codewarrior-"damaged" memory area (0xc00-0x2FFF); works splendid! Fun fact: with the now changed memory map I cannot flash the main application without my bootloader anymore :smileywink: .
I'm just asking because my colleague is working on the same derivative, but on another project which might not get this bootloader. Currently his software is not as huge as mine, but eventually he will stumble across this problem (missing 9.2KiB unbanked memory) sooner or later...
Kind regards,
Hi,
so I'm more or less happy about having found a bug. :smileywink: Well, I tried your suggestion. Indeed the memory is found at 0x0C00... BUT I need to declare all const as FAR and here arise three problems (and I finally figured out what led my program to crash)
First problem:
The overall code sizes (currently) increases by roughly 5 KiB :smileyalert: Not acceptable.
Second and most major problem:
It adds additional code after (and before) some routines.
As you can see in my post below how I handle PPAGE awareness:
I do a PULA and then a STAA 0x15
Fun stuff: the compiler adds additional PULA and STAA 0x15 before a RTI (maybe to other exits too; didn't check this); kills me everything.
Out-commenting my lines won't do as well as putting "no entry/exit" to each function.
Third problem:
Huge latencies. The software is heavily dependent on its ROM configuration. Each time a CONST is accessed, it jumps into FSC func to load page and out and that's a lot in this code...
So, I guess I have to wait for a CW fix.... (or write a RAM bootloader to download my software - wouldn't really like to do this)
The debugging memory map issue occurred to me as well... Thanks for the suggested fix, it works splendid :smileyhappy: