S12G - FLASH partitioning

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

S12G - FLASH partitioning

6,704 Views
puppetmaster
Contributor II

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

Labels (1)
Tags (3)
0 Kudos
Reply
11 Replies

6,024 Views
RadekS
NXP Employee
NXP Employee

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.

  1. You can use command #pragma TRAP_PROC SAVE_ALL_REGS prior every interrupt routine – ineffective.
  2. Compiler option –CpPPAGE (or -CpPPAGE=0x15). – best solution
  3. Your code save/restore PPAGE manually only in necessary routines – sometimes too complicated.


0 Kudos
Reply

6,024 Views
puppetmaster
Contributor II

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'??

0 Kudos
Reply

6,024 Views
RadekS
NXP Employee
NXP Employee

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.


0 Kudos
Reply

6,024 Views
puppetmaster
Contributor II

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.

0 Kudos
Reply

6,024 Views
RadekS
NXP Employee
NXP Employee

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"


0 Kudos
Reply

6,024 Views
puppetmaster
Contributor II

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...

0 Kudos
Reply

6,024 Views
RadekS
NXP Employee
NXP Employee

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.


0 Kudos
Reply

6,024 Views
puppetmaster
Contributor II

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...

0 Kudos
Reply

6,024 Views
RadekS
NXP Employee
NXP Employee

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:

debugging memory map-S12G64.PNG


0 Kudos
Reply

6,024 Views
puppetmaster
Contributor II

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,

0 Kudos
Reply

6,024 Views
puppetmaster
Contributor II

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:

0 Kudos
Reply