We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello, I developed an emmbedded application for a C167CR-LM. In this application I've some very big data structures stored in internal RAM (IDATA) and some dynamic list managed using malloc and free. For dynamic allocation I define the pool:
unsigned char far equivalence_pool[0x4000]; init_mempool (equivalence_pool, sizeof (equivalence_pool));
In my application there is a IRQ routine on a Timer T6 with a period of 0.5 ms.
In some situations the ILLOPA exception is trapped an the application crashes. It generally happens when many digital input (linked to port P2 pins) are active together.
I tried to increase the user stack with no effect.
Adding 2 calls to printf in the IRQ routine, ILLOPA is not generated.
Have you some suggestions for help me how to investigate this problem?
Testing with Mon166 the trap routines are not available, and using Simulator is too complex cause the hardware and input sequences to generate.
Thanks, Marco
This ISR rotine is a quarter of another one in another application for the same boards in the same plant, and it runs always good ...
There are stunt drivers that can drive their cars on two wheels - that doesn't mean that it is good to drive a car with two wheels in the air...
your ISR is miles long. it contains wasteful references to array elements, multiple loops... try what Per suggested: move the whole block outside of interrupt context - put it in a function and call it from your main loop. what happens then? again: the fact that code works means nothing beyond that it does not fail on that hardware, under certain circumstance
I cannot modify the structure of this program. It's not my property. I had received this code with this function by the company customer and I removed some unuseful pieces and add a new part. I cannot split this routine.
Hi Marco,
Back to your original question: what causes the Illegal Operation trap? You should add a trap handler to collect some debugging information (address of the offending opcode, contents of some CPU registers etc.) Soon you'll be able to map the offending opcode to the exact line of source code.
Regards, - mike
Small correction. Just looked it up: ILLOPA is 'Illegal Word Operand Access.' It happens when a word access is attempted at an odd address. Look out for unaligned pointers. The method I suggested should allow you to pinpoint the exact line of source code and the offending unaligned pointer.
Thanks Mike,
so at this moment I've a trap function that, in case of ILLOPA event, print a string "ILLOPA trap!" on serial link. I can add here a complete printf whith more informations. Now I try to understand what are the registers or pointers of interest about my problem.
Thank you very much.
Marco
See the MCU manual. The C167 CPU will push PSW, CSP and IP onto the system stack. Print them. CSP and IP will point to the offending instruction. Using a disassembler, you'll be able to map the instruction to the source code.
More thanks.
Hello Mike,
I looked to User Manual but is written that IP and CSP are not directly accessible, so how can I print IP and CSP?
Thanks
I looked to User Manual but is written that IP and CSP are not directly accessible
You mean this, right? The IP register is not mapped into the C167CS's address space, and thus it is not directly accessible by the programmer
That's true, but why would you want to read IP in the trap handler? It will not do you any good. You don't need to read the actual registers. You need the contents of those registers at the time when the trap occured. And those are saved on the stack by the CPU (see manual, section on trap functions.) If I remember correctly, Keil's C166 compiler has an intrinsic function for popping words off the stack. _pop_(), maybe? Look it up. Here is what I would do:
void trap_handler(void) { uint16_t psw, csp, ip; ip = _pop_(); csp = _pop_(); psw = _pop_(); ... print psw, csp, ip ... }
You are correct.
Summary: #include <intrins.h> int _pop_ (void); Description: The _pop_ function inserts a POP instruction into the program which pops the next word from the system stack. Return Value: The _pop_ function returns the 16-bit value poped from the system stack.
Example:
#include <intrins.h> void testpop (void) { volatile unsigned temp; _push_ (temp); temp = _pop_ (); }
you may want to have a look at the Keil provided traps.c file, too.
Yes, Ok.
I've in my project a custom version of traps.c.
Using the calls to _pop_ function I will insert them in a function called by ILLOPA trap in my traps.c.
Thanks.
Using the calls to _pop_ function I will insert them in a function called by ILLOPA trap in my traps.c
Be careful, though. Each function call pushes more data onto the stack. You have to account for that when trying to extract the saved PSW, CSP, IP. The three simple pops will not do.
You are correct, it's a problem. I will try to find a solution.
Thanks!