How to make CW11.1 Trace break on address range?

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

How to make CW11.1 Trace break on address range?

Jump to solution
1,498 Views
GaryOlmstead
Senior Contributor I

Hello All --

I am still developing a project using a 9S08QE128, CW 11.1 and a P&E Cyclone Pro.  The program worked well until it overflowed into banked memory.  I have managed to recover, mostly, and it was showing signs of life until the other day when it started locking up.  Some investigation revealed that the program is running properly for a few to several seconds, and is then jumping to RAM or the peripheral register space, and trying to execute code there.  The program halts at that point, but CW is unable to give me more than the program counter. 

I am trying to use CW's Trace.  I would like to have it break on any reference to an address in a range, with the range defined as 0x0000 to 0x207F.  I would like it to stop on any address in that range, and then step backwards to find out where it went astray.

I have found the process to set up the Trace, and the option to select "break on any address within range", but there is no way to enter the desired addresses.

I'm sure I'll have more questions, but I will start with, How do I tell it what range of addresses I am interested in?

Labels (1)
0 Kudos
1 Solution
1,305 Views
GaryOlmstead
Senior Contributor I

Hi Edward --

No, it's available in my version.  You select Window-> Show View-> Software Analysis, and then expand the view, and there it is!!

So, what was causing the problem?  Processor Expert generated code for a UART (named "Debug") that has code in page zero for the interrupt, as it should, but "On_Tx_Complete" is in CODE_SEG Debug_CODE, which ended up at 0x9a9a.  It ends in RTS.

The assignment for Debug_CODE doesn't specify NEAR or FAR, so I need to reassign it to NEAR, ideally without modifying any of the files marked Do Not Modify.  There are a half dozen other interrupts that also have code on banked and non-banked memory.

Thanks for your help.

Gary Olmstead

View solution in original post

0 Kudos
8 Replies
1,305 Views
tonyp
Senior Contributor II

Is your app in C or Assembly?

If in C, we have to assume (just assume, though) the compiler's calling of subroutines is done correctly using CALL and JSR/BSR as required with corresponding RTC/RTS instructions.

If in Assembly, my guess is that some code is called with CALL and returns with RTS, or called with JSR/BSR and returns with RTC causing it to go to 'random' address.

As for the issue of overflowing into the page window, if you define your memory map to exclude the one byte right before the memory window's start address and one byte right after its end address, your compiler should warn you.

0 Kudos
1,305 Views
GaryOlmstead
Senior Contributor I

It's all written in C, and the compiler does the right thing almost all the time.  It is OK for "my" code, but some of the library routines are not modified and don't work across memory banks.  For example, switch statements with consecutive indexes are handled as jump tables, and the table indexes are always two bytes.  So the switch has to be in bank zero, and the body of each case calls the actual code which can be in any bank.  That code always ends in an RTC. It's fiddly, but now that I have figured that out, I can live with it. 

Another fiddly, and totally undocumented part, is that every function definition has to explicitly have the same bank assignment as the main routine, or you get a memory assignment doesn't match warning ( I forget the exact text).  But the warning messages tend to come and go.  I have gotten dozens of them, fixed a few, and all of them disappeared.  Did I fix them? Or is it just normal C errors, where one real error causes a cascade of fake errors? And what happens if I miss any?  Who knows?

Another problem is that certain canned routines, like multi-bit shift routines, don't know about memory banks, and always end in RTS.  I'm pretty sure my current problem is one of these, but the only way to see them is to generate a .lst file, and search it.  But that's a lot of code, and not all the RTS's matter, and this may not be the problem. 

I would like to just run the code until it quits, then back up to the last address that isn't in RAM or the peripheral block.  But the normal P&E debugger can't deal with that.  Once the code goes into the weeds, P&E is done.  I hope Trace will be able to let me find the code.

I probably misused the word "overflow".  I just meant that it outgrew the default space of 0x2080-0x7FFF, and I had to convert to banked memory.  It's around 27K at the moment.

So, to close, I would like Trace to break on a range of addresses.  Although this is a documented option, there isn't any obvious way to do that.

0 Kudos
1,305 Views
kef2
Senior Contributor V

Hi Gary,

  •  but some of the library routines are not modified and don't work across memory banks.  For example, switch statements with consecutive indexes are handled as jump tables, and the table indexes are always two bytes.  So the switch has to be in bank zero, and the body of each case calls the actual code which can be in any bank.  That code always ends in an RTC. It's fiddly, but now that I have figured that out, I can live with it. 

Switch doesn't have to be in back zero! Jump table with 16bit jump (and not call) addresses is perfect within the page. If indeed you mean you have some array of pointers to functions, then all such array entries must be either all nonpaged pointers or all paged pointers. Calling part must know in advance are those function banked or not banked. If you have mix of banked and nonbanked functions, then you need to provide some unifying functions. big() and nonbanked nbig(), which just calls banked big(), or the opposite, small nonbanked calling big banked functions. The problem is function pointers are not compatible banked vs nonbanked. If caller expects (non)banked callee, then you need to feed it with (non)banked callee, no other options.

  • Another fiddly, and totally undocumented part, is that every function definition has to explicitly have the same bank assignment as the main routine, or you get a memory assignment doesn't match warning ( I forget the exact text). 

You can't mix paged/nonpaged function pointers, they are not compatible. Compiler as I remember by default was emitting warnings, which are indeed serious errors. Please provide an example.

  • Another problem is that certain canned routines, like multi-bit shift routines, don't know about memory banks, and always end in RTS.

Compiler should see proper banked/nonbanked prototype for such function. Either use near/far keywords or round your (functions and) declarations with proper pragmas

#pragma CODE_SEG __NEAR_SEG ...

....

#pragma CODE_SEG DEFAULT

Presence of __NEAR_SEG above is kind of applying near keyword to all functions. BTW you need to do the same for your interrupt handlers, which can't be paged. You need both near for ISR's and as well place them to nonbanked flash.

Regarding breakpoints, I'm little busy to try now what you ask. Try reading chapter Debug Module in QE128 RM. It should answer what module can and what can't. Classic Codewarrior supported simple code breakpoints and data watchpoints. For fancy triggers one could have to switch from Automatic breakpoints mode to nonautomatic, which was breaking all comfort of debugging since you could just doubleclick to place breakpoint where you wish, but you may try. You can even add your own code to set up breakpoint registers the way you wish.

Edward

0 Kudos
1,305 Views
kef2
Senior Contributor V

Hi again,

CW11.1 is fine for address range breakpoint. Perhaps not the best way but here's how:

1. You will need to enable trace. As well you may need to change trace settings from time to time while debugging. To do so from debug session in the top left Debug window select and right click item starting with "HCS08, <project name>" string. -> Edit <project name>_FLASH_PnE U-Multilink...-> Trace and Profile tab, the edit the settings like in the screenshot

rangebkp.png

Depending on what you are chasing you need to choose the right setting for Trigger Selection. Memory Access (read) will trigger on code execution as well.

2. You may wonder where you could specify A and B addresses. You can do it from Memory, Disassembly or code, In code window right click on gutter then Trace Triggers, then Toggle Trace Trigger A or B. In Disassemble window right click on address. In Memory window first add Monitor, then right click on memory cell you want to place trigger at. You may as well Window->Show View->Other...->Software Analysis->Analysis points. In that view you may add or remove points A and B.

Hope it helps

Edward

0 Kudos
1,305 Views
GaryOlmstead
Senior Contributor I

It helped a little. 

I read the DBG section of the manual.  in CW, I selected Run-> Debug Configurations... and set the Trace & Profile screen as above. I set it to trigger between A and B.  I selected Debug. It stopped at main(). The DBG registers had not changed.  I stepped one instruction, and the DBG registers had been set up to what I believe are the right values (DBGCA = 0x0000, DGBCB = 0x207e, DGBF = 0x644B, DGBT = 0x87, all others zero).

  I restarted the program.  It ran and halted at address 0x48.  DBGCNT says there are 8 values in the FIFO, but how do I get them out?  The DBG section of the manual rather blithely says to use the BDM commands, but Run -> Debug History... just asks if I want to start over, and none of the other menu choices looks even remotely helpful.  P&E Micro says they don't do anything with the DBG module except set break points.  So where are they?

Gary Olmstead

0 Kudos
1,305 Views
kef2
Senior Contributor V

Hi Gary,

I wonder which edition of CW for MCU's 11.1 is required to work with Trace. CW 6.3 one had to use Pro. I suspect you need Pro or not expired Evaluation, but it is quite tricky to find that information on nxp.com. When I tried my code with Special Edition of CW 11.1 it showed something in Open View-> Software Analysis (sorry if not exact wording, I don't S08 board at hand), but where I expected to see Trace data I saw bunch of Error's, I think it's due too cheap CW edition, But trace breakpoint worked as expected.

Trace data FIFO is read via DBGFX, DBGFH and DBGFL registers. See the note below the DBGFL:

  • When reading FIFO words, read DBGFX and DBGFH before reading DBGFL because reading DBGFL causes the
    FIFO pointers to advance to the next FIFO location. In event-only modes, there is no useful information in DBGFX
    and DBGFH so it is not necessary to read them before reading DBGFL.

Edward

0 Kudos
1,306 Views
GaryOlmstead
Senior Contributor I

Hi Edward --

No, it's available in my version.  You select Window-> Show View-> Software Analysis, and then expand the view, and there it is!!

So, what was causing the problem?  Processor Expert generated code for a UART (named "Debug") that has code in page zero for the interrupt, as it should, but "On_Tx_Complete" is in CODE_SEG Debug_CODE, which ended up at 0x9a9a.  It ends in RTS.

The assignment for Debug_CODE doesn't specify NEAR or FAR, so I need to reassign it to NEAR, ideally without modifying any of the files marked Do Not Modify.  There are a half dozen other interrupts that also have code on banked and non-banked memory.

Thanks for your help.

Gary Olmstead

0 Kudos
1,305 Views
kef2
Senior Contributor V

Hi

What you mean by page zero. Paged flash, page number zero? Or indeed non-banked flash? Please don't mix these.

RTS instruction is not forbidden in paged flash. It is perfectly OK to JSR-RTS routine, which is allocated on the same page like paged caller routine. Static routines may be good candidates for JSR/BSR-RTS provided compiler/linker allocate them to the same page like caller. 

Regarding PE UART code, if PE didn't make dedicated placement for Debug_CODE in nonbanked flash in PRM file, then perhaps it's PE bug.

Edward

0 Kudos