Shop OBEX P1 Docs P2 Docs Learn Events
P2 Interrupts in Catalina — Parallax Forums

P2 Interrupts in Catalina

I've been trying to use interrupts in my latest project. However, I seem to be confused on how they work on the P2 and in Catalina.
The P2 docs seem to indicate each cog has it's own set of 3 interrupts. Is this correct?
If so, is this supported by Catalina?
In my experiments, if I setup an interrupt on a cog and then setup the same interrupt number on another cog, the first interrupt gets clobbered.
I've modified a version of the Catalina demo test_interrupts_2.c (attached below) to help me test the behavior.
The code as attached works. (NOTE the while(1) loop for the new cog can't be empty in TINY or COMPACT or the cog seems to shut down)
If the same interrupt number is used in both cogs, only the last to be assigned runs.

#include <stdio.h>
#include <propeller2.h>
#include <catalina_interrupts.h>

// define the stack size each interrupt needs 
#define INT_STACK_SIZE (MIN_INT_STACK_SIZE + 100)
#define COG_STACK_SIZE  500

long int_stack[INT_STACK_SIZE * 3];
long cog_2_stack[COG_STACK_SIZE];

// interrupt_1 - increment the counter INTERRUPTS_PER_SECOND times per second 
void interrupt_1(void) {
    // we are a counter interrupt, so add to the counter for next time
    _add_CT1(_clockfreq()/4);
    _pinnot(57);
}

// interrupt_2 - print the current value of the counter every second
void interrupt_2(void) {
    // we are a counter interrupt, so add to the counter for next time
    _add_CT2(_clockfreq()/2);
    _pinnot(58);
}

// interrupt 3 - throw a random spanner into the works!
void interrupt_3(void) {
    // we are a counter interrupt, so add to the counter for next time
    _add_CT3(_clockfreq());
    _pinnot(59);
}

void cog_2(void) {
  _set_CT2(_clockfreq()/2);
  _set_int_2(CT2, &interrupt_2, &int_stack[INT_STACK_SIZE * 2]);
  while(1) {
    _pinnot(60);
  }
}

void main(void) {
    int i;


    // these are counter interrupts so set up the initial counters 
    _set_CT1(_clockfreq()/4);
    _set_CT3(_clockfreq()/2);

    _coginit_C(&cog_2, &cog_2_stack[COG_STACK_SIZE]);

    // set up our interrupt service routines
    _set_int_1(CT1, &interrupt_1, &int_stack[INT_STACK_SIZE * 1]);
    _set_int_3(CT3, &interrupt_3, &int_stack[INT_STACK_SIZE * 3]);

    // now just let the interrupts do their thing
    while(1) {
        // toggle the LED to show some activity. 
        _pinnot(56);
        // waste some time just to slow things down (note that we can't
        // just use the various _wait functions because doing so stalls 
        // the interrupts - but we also can't use the _iwait functions 
        // because they use interrupt 2 which we want to use ourselves). 
        // For programs wanting to use all the interrupts, busy waiting 
        // may be the only solution ...
        for (i = 1; i < 1000000; i++) { }
    }
}

Comments

  • RossHRossH Posts: 5,477
    edited 2024-01-19 02:29

    Hello @currentc

    Yes, each cog has separate interrupts. I know this works in Catalina because one of the interrupts (#3) is used to implement the multi-threading, and multi-threading can execute on multiple cogs.

    (The rest of this post deleted since I have found the problem - see next post)

    Ross.

  • RossHRossH Posts: 5,477

    Hello @currentc

    Ok - spotted the problem after just a quick look. The code that sets up the C interrupts does indeed assume interrupts are global, and not per cog. It stores the C interrupt configuration data in Hub RAM, where it is getting overwritten if the same number interrupt is used by a different cog. I must have written that code before I fully understood the P2 interrupt design. The code that does the multi-threading was written later, and correctly uses only Cog RAM.

    It will be fairly easy to fix - I just need to store the C interrupt configuration data in Cog RAM as well - but this will take me a day or two.

    Ross.

  • RossHRossH Posts: 5,477
    edited 2024-01-20 01:17

    Hello @currentc

    Fixed. It was easier than I thought because I can still use Hub RAM - I just need to allocate enough space for all cogs. I'll issue a new release with the fix shortly. Here is my test program, which now works as expected in NATIVE, TINY and COMPACT modes. It is a minor variation of your program. Mainly, I have added a delay in the main loop of the cog_2 function - without that it does indeed lock up in COMPACT and TINY modes because of the way the kernel works in these modes - a loop that consists of only a single JMP instruction (which is the code that while (1) { } generates) never allows the interrupts to execute (this is not true in NATIVE mode). But it's a fairly pathological case not to have any code in such a loop.

    #include <stdio.h>
    #include <propeller2.h>
    #include <catalina_interrupts.h>
    
    // define the stack size each interrupt needs 
    #define INT_STACK_SIZE (MIN_INT_STACK_SIZE + 100)
    #define COG_STACK_SIZE  500
    
    long int_stack[INT_STACK_SIZE * 3];
    long cog_2_stack[COG_STACK_SIZE];
    
    // interrupt_1 - repeat the interrupt every 1/4 second, using counter 1 
    void interrupt_1(void) {
        // we are a counter interrupt, so add to the counter for next time
        _add_CT1(_clockfreq()/4);
        _pinnot(57);
    }
    
    // interrupt_2 - repeat the interrupt every 1/2 second using counter 2
    void interrupt_2(void) {
        // we are a counter interrupt, so add to the counter for next time
        _add_CT2(_clockfreq()/2);
        _pinnot(58);
    }
    
    // interrupt 3 - repeat the interrupt every 1 second using counter 3
    void interrupt_3(void) {
        // we are a counter interrupt, so add to the counter for next time
        _add_CT3(_clockfreq());
        _pinnot(59);
    }
    
    void cog_2(void) {
      int i;
    
      // we use counter interrupts so set up the initial counters 
      _set_CT2(_clockfreq()/2);
    
      // choose any ONE of the following, to demonstrate that the
      // interrupts on this cog are independent of the interrupts
      // on other cogs ...
    
      //_set_int_1(CT2, &interrupt_2, &int_stack[INT_STACK_SIZE * 2]);
      _set_int_2(CT2, &interrupt_2, &int_stack[INT_STACK_SIZE * 2]);
      //_set_int_3(CT2, &interrupt_2, &int_stack[INT_STACK_SIZE * 2]);
    
      while(1) {
        _pinnot(60);
        // waste some time just to slow things down (note that we can't
        // just use the various wait functions because they use the counters
        // and/or the interrupts. For programs wanting to use the counters 
        // and interrupts themselves, busy waiting may be the only solution ...
        for (i = 1; i < 1000000; i++) { }
      }
    }
    
    void main(void) {
        int i;
    
        // we use counter interrupts so set up the initial counters 
        _set_CT1(_clockfreq()/4);
        _set_CT3(_clockfreq());
    
        _coginit_C(&cog_2, &cog_2_stack[COG_STACK_SIZE]);
    
        // set up our interrupt service routines
        _set_int_1(CT1, &interrupt_1, &int_stack[INT_STACK_SIZE * 1]);
        _set_int_3(CT3, &interrupt_3, &int_stack[INT_STACK_SIZE * 3]);
    
        // now just let the interrupts do their thing
        while(1) {
            // toggle the LED to show some activity. 
            _pinnot(56);
            // waste some time just to slow things down (note that we can't
            // just use the various wait functions because they use the counters
            // and/or the interrupts. For programs wanting to use the counters 
            // and interrupts themselves, busy waiting may be the only solution ...
            for (i = 1; i < 1000000; i++) { }
        }
    }
    

    Ross.

  • RossHRossH Posts: 5,477

    Hello @currentc

    Catalina version 6.5.5 has been released - see this post.

    This should address your interrupt issue.

    Ross.

  • currentccurrentc Posts: 17
    edited 2024-01-20 18:24

    Thanks @RossH

    This update saved my project. I need more than 3 interrupts to make it work the way I envisioned.
    Catalina seems to be the only way to use interrupts on the P2 without being forced to use and maintain assembly. Something I have no desire to do.
    I originally wrote a proof of concept interrupt routine in assembly. Then I realized what a pain that was to modify and maintain.
    If it hadn't been for Catalina, I would have changed to a different chip. That would have been a shame. The combination of smart pins, interrupts and multiple cores makes the P2 very powerful.
    I think that the P2 would have better adoption in the hobby market if it had better documentation and support for programming languages hobbyists already know.

    Thanks again for all of your hard work in creating and maintaining Catalina.

    Charles

  • RossHRossH Posts: 5,477

    Hello @currentc

    No worries. Hope your project goes well.

    Ross.

Sign In or Register to comment.