Exception vectors

I have just browsed the P2 docs a bit more to see its features.

However, I'm a bit concerned about the lack of exception vectors compared to other architectures such as ARM, RISC-V and even PIC.

What happened if I divide by zero? Or what ever happened when I try to access an invalid location? Does this P2 tell me about it, or it goes into undefined operation?

We know that we need to keep an eye on these when we write code. However, even if we code the best that we could, these things can slip out. Catching these automatically during runtime helps us to debug or write a program better.


  • If you divide by zero, I think you'll get $FFFFFFFF.

    If you read a hub location that has no RAM, you'll get zero.

    These kinds of problems amount to a small percentage of the software bugs a programmer will likely deal with.
  • The single instruction TJZ tests a register and jumps if zero. Overhead only two cycles if non-zero or perhaps none if waiting for CORDIC result anyway.
  • Yeah, most of the usual edge cases have defined behavior (for an unsigned divide of non-zero by zero, $FFFFFFFF is arguably the most sensible result...)

    For what it's worth, you can set up an interrupt to fire on the QMT event (GETQ* executed while CORDIC is idle) though.
  • Hello Chip, Thanks for the explanation.

    Returning a 32-bit maximum for a div-0 without stopping the system could lead to the program continuing its faulty ways.

    I could imagine this scenario:
    int function( int a, int b) {
        c = a / b;
        return c;
    .... <other code here>
    int main() {
        int d = function(5,0);
        anotherFunction(d, 15);

    On P2 as mentioned, if b = 0, it'll return c = 0xffffffff, and could lead to very destructive situations. If "anotherFunction" was handling some moving parts outside, this could be harmful. Or, if "anotherFunction" was written to display gibberish on a screen instead of a temperature. Tracking faults like that could take a lot of time if nothing get stopped during function(int a, int b) especially when the code becomes very complex.

    Meanwhile, this goes the same to reading invalid location - the program may run okay and didn't stop in P2, but to track down of this could take a lot of time too. It's better to stop the program than to accidentally read or write values elsewhere if a wrong pointer is passed.

    I would have to write some handler to deal with this if it doesn't exist in the P2 hardware. If the P2 GCC has it, it'll be a good thing to hear.
  • You'll have to ask Eric and Ross about what their respective C compilers do.

  • cgraceycgracey Posts: 13,012
    edited 2020-09-13 - 14:50:09
    To me, these are trivial issues. I write all my code, including PC code, to ensure that I never divide by zero. To rely on a hardware exception to catch a software bug is just poor practice. In an embedded system, especially, there is no fallback position. It just has to work.
  • Returning a 32-bit maximum for a div-0 without stopping the system could lead to the program continuing its faulty ways.
    A program might blow up if a variable is negative, or if it's greater than 1234. If a program will do something really bad if the divisor is 0, then you should test for that to prevent it from doing something bad.

  • The main difference between individual error handling (for example, testing for zero where the division happens) and exception vectors is that the exception handler can be somewhere else, probably many calling levels outside of where the actual error happens. You can install a "global" error handler that catches all cases and you don't have to define a return value that flags "sucessful or not" for each and every function.

    This is useful for big systems and if you have big libraries of "foreign" (written by somebody else) code where you never know what happens inside.

    However, for small systems I prefer the simple method: handle the errors where you expect them and not somewhere else.

    I hate those ARM CPUs where you have to write 50 kB of code just to initialize all exception vectors, watchdogs, protection registers etc. before you can do something useful. The potential risk of doing something wrong with all those "obstacles" is much higher than their actual benefit, at least for small systems.

    When controlling a machine, vehicle or similar things, halting the whole program is often more harmful than to continue with a slighly inaccurate value. If your software is safety critical you have to make it bullet proof by testing every possible case and branch, anyway. And Murphy's law says: There is always one more bug and the most expensive ones are surely not one of those catched by an exception handler. For examples watch this. ;)
Sign In or Register to comment.