Shop OBEX P1 Docs P2 Docs Learn Events
I have begun my Propeller 2 journey! - Page 5 — Parallax Forums

I have begun my Propeller 2 journey!

123578

Comments

  • @RossH said:

    @enorton said:

    Btw the basic functionality code size is without the added stuff I need to add later is:

    code = 86708 bytes
    cnst = 2916 bytes
    init = 64 bytes
    data = 44856 bytes
    file = 146816 bytes

    When I add the backend functionality with added cog support I am sure the usage will increase but we will see how much.

    Looks like you have plenty of headroom, and you won't need to use any of Catalina's memory saving or memory extension options.

    Ross.

    Well I have the whole back end disabled and have yet to do the add-ons. I suspect it will be roughly 300k when everything is said and done.

  • RossHRossH Posts: 5,477

    @enorton said:

    @RossH said:

    @enorton said:

    After searching through the files, I did find cogserial.pasm. I'm not in a huge rush for it as I have other issues I need to address like adding timer functionality and other functions which I am working on now. When you are ready to add it I can send you the function I used to check the rx ring buffer size if that helps.

    Send it to me or just post it here. I will include it in the next release.

    Ross.

    How can I send it to you? If I post it here then it's public.. Let me know.

    Well, if I include it in the next release it will also be public! :)

    I won't post it here, but my email address is in the Catalina Reference Manual (search for "Reporting Bugs").

  • jmgjmg Posts: 15,175

    @enorton said:
    .... I need to add an rx buffer size check to see how much rx buffer is available for the host to send more data if it is needed.
    What and where is the source for this and how easy is it to modify and then compile the library for use with Catalina Geany?

    If your system is such the host is not sure it is ok to send, (ie no message handshakes) you could consider adding hardware handshake, so that the P2 throttles the incoming data via a control pin.
    Usually that is done with stop and restart watermark tests on the RX buffer FIFO

  • RossHRossH Posts: 5,477

    @enorton said:

    Well I have the whole back end disabled and have yet to do the add-ons. I suspect it will be roughly 300k when everything is said and done.

    Should be fine.

    However ... just in case ... keep in mind is that with Catalina you don't need to compile the whole program with the same memory model. If it partitions easily (e.g. has two or more parts that communicate only via shared memory) then you can compile those parts of it that need speed in NATIVE mode (the default on the Propeller 2) and compile other parts in COMPACT mode (which is slower, but can halve the code size).

    There are examples of doing this in the demos\multimodel folder**. It can be complex to set up initially, so it is not recommended unless you have no other options, but others have used it to good effect. Mostly on the Propeller 1, where memory is so tight (only 32kb!).

    Ross.

    ** and I have just realized that I need to add more examples now that the Propeller 2 can also use XMM (eXternal Memory Model). So much to do, so little time ... :(

  • enortonenorton Posts: 144
    edited 2023-04-14 06:31

    @RossH said:

    @enorton said:

    @RossH said:

    @enorton said:

    After searching through the files, I did find cogserial.pasm. I'm not in a huge rush for it as I have other issues I need to address like adding timer functionality and other functions which I am working on now. When you are ready to add it I can send you the function I used to check the rx ring buffer size if that helps.

    Send it to me or just post it here. I will include it in the next release.

    Ross.

    How can I send it to you? If I post it here then it's public.. Let me know.

    Well, if I include it in the next release it will also be public! :)

    I won't post it here, but my email address is in the Catalina Reference Manual (search for "Reporting Bugs").

    Ok well if it is going to be public anyway might as well put it here so everyone can use it :-)

    uint16_t serial_get_rx_buffer_available(void)
    {
        uint16_t rx_tail = rx_buffer_tail;
        if (rx_buffer_head >= rx_tail) 
        {  
            return (RX_BUFFER_SIZE - (rx_buffer_head - rx_tail)); 
        }
        return ((rx_tail - rx_buffer_head - 1));
    }
    

    It's nothing fancy just something I need to keep track of the current buffer size. The names don't have to be the same as long as it functions the same :-)

    Also is there a way to change the serial RX and TX buffer sizes?

  • @jmg said:

    @enorton said:
    .... I need to add an rx buffer size check to see how much rx buffer is available for the host to send more data if it is needed.
    What and where is the source for this and how easy is it to modify and then compile the library for use with Catalina Geany?

    If your system is such the host is not sure it is ok to send, (ie no message handshakes) you could consider adding hardware handshake, so that the P2 throttles the incoming data via a control pin.
    Usually that is done with stop and restart watermark tests on the RX buffer FIFO

    I can't change the host end, unfortunately. If I could design it all over again I would.

  • RossHRossH Posts: 5,477

    @enorton said:
    Ok well if it is going to be public anyway might as well put it here so everyone can use it :-)

    Your code looks like it was written for the Propeller 1 tty library (i.e. using option -ltty to Catalina), which accesses the Full Duplex Serial plugin. The C code for this is in source\lib\catalina_libtty, which is I think may have been where you were looking when you wrote it.

    The equivalent on the Propeller 2 is the serial2 library (i.e. using option -lserial2 to Catalina), which uses the Full Duplex Serial 2 plugin (which I call cogserial.pasm). Your code will not work with that plugin. The C code for that is in source\lib\catalina_libserial2

    But the good news is that this plugin already seems to implement the function you need - I just need to make it accessible via a new C access function. I will include this in the next release.

    Also is there a way to change the serial RX and TX buffer sizes?

    Not with this plugin, no. The buffers are in LUT RAM, not HUB RAM, and their size is fixed by the size of the LUT RAM (2kb total, or 512 bytes for each tx and rx buffer for each of the two ports). You could possibly use the 8 port serial library instead ( (i.e. using option -lserial8 but only enabling 2 of the 8 ports). The 8 port serial port plugin uses HUB RAM for buffers, and the buffer size is configurable. The C code for it is in source\lib\catalina_libserial8

    Sorry if this seems complicated. Catalina tries to "wrap" the complexities of all these different plugins into access routines that are as similar as possible in operation, but since they were all written by different people, have different capabilities, and are significantly different internally, this is not always possible.

    Ross.

  • @RossH said:

    @enorton said:

    Well I have the whole back end disabled and have yet to do the add-ons. I suspect it will be roughly 300k when everything is said and done.

    Should be fine.

    However ... just in case ... keep in mind is that with Catalina you don't need to compile the whole program with the same memory model. If it partitions easily (e.g. has two or more parts that communicate only via shared memory) then you can compile those parts of it that need speed in NATIVE mode (the default on the Propeller 2) and compile other parts in COMPACT mode (which is slower, but can halve the code size).

    There are examples of doing this in the demos\multimodel folder**. It can be complex to set up initially, so it is not recommended unless you have no other options, but others have used it to good effect. Mostly on the Propeller 1, where memory is so tight (only 32kb!).

    Ross.

    ** and I have just realized that I need to add more examples now that the Propeller 2 can also use XMM (eXternal Memory Model). So much to do, so little time ... :(

    When I enable the backend, I will see where we are at with code size and if I need to implement something like this...

  • @RossH said:

    @enorton said:
    Ok well if it is going to be public anyway might as well put it here so everyone can use it :-)

    Your code looks like it was written for the Propeller 1 tty library (i.e. using option -ltty to Catalina), which accesses the Full Duplex Serial plugin. The C code for this is in source\lib\catalina_libtty, which is I think may have been where you were looking when you wrote it.

    The equivalent on the Propeller 2 is the serial2 library (i.e. using option -lserial2 to Catalina), which uses the Full Duplex Serial 2 plugin (which I call cogserial.pasm). Your code will not work with that plugin. The C code for that is in source\lib\catalina_libserial2

    But the good news is that this plugin already seems to implement the function you need - I just need to make it accessible via a new C access function. I will include this in the next release.

    Also is there a way to change the serial RX and TX buffer sizes?

    Not with this plugin, no. The buffers are in LUT RAM, not HUB RAM, and their size is fixed by the size of the LUT RAM (2kb total, or 512 bytes for each tx and rx buffer for each of the two ports). You could possibly use the 8 port serial library instead ( (i.e. using option -lserial8 but only enabling 2 of the 8 ports). The 8 port serial port plugin uses HUB RAM for buffers, and the buffer size is configurable. The C code for it is in source\lib\catalina_libserial8

    Sorry if this seems complicated. Catalina tries to "wrap" the complexities of all these different plugins into access routines that are as similar as possible in operation, but since they were all written by different people, have different capabilities, and are significantly different internally, this is not always possible.

    Ross.

    The function I posted is from another program I use for the other controllers I sell. I suppose it is pretty standard. I am porting over the same code and making enhancements to it to bring in new functionality.

    Ah ok, 512 bytes for RX and TX is fine for testing but will need to do what you said with the 8-port serial library because I will need an 8k buffer for RX and TX at some point. I might sound like a real Smile for mentioning this, but can you make a 2-port version that uses hub ram? Just curious and I can enable the two like you said if that is easier. As long as it doesn't bog down the interface then that is fine. Can you let me know when you have updated Catalina or the library so I can download and use it please :-D.

    On another note, right now, I do serial RX and TX multiplexing in hardware to switch to another port when enabled. Is there a way to do port multiplexing with smart pins? If so, the new design has several serial devices that when enabled, auto-switch into the P2 device thereby connecting to the UART. The pin connections for each UART interface are RX, TX, and EN. Just curious if you know of a way to do this. If not, I can investigate this myself and find out.

  • RossHRossH Posts: 5,477

    @enorton said:

    The function I posted is from another program I use for the other controllers I sell. I suppose it is pretty standard. I am porting over the same code and making enhancements to it to bring in new functionality.

    I wondered why the identifier names didn't quite match. I assumed you had changed them. But as you say it would be fairly standard code for a FIFO buffer. But I think I can add a similar function to the current 2 port serial plugin. I'll let you know.

    Ah ok, 512 bytes for RX and TX is fine for testing but will need to do what you said with the 8-port serial library because I will need an 8k buffer for RX and TX at some point. I might sound like a real Smile for mentioning this, but can you make a 2-port version that uses hub ram? Just curious and I can enable the two like you said if that is easier. As long as it doesn't bog down the interface then that is fine. Can you let me know when you have updated Catalina or the library so I can download and use it please :-D.

    This is not likely to be done by me - :) - but there may be other serial drivers out there that could be adapted - if you find one I will turn it into a Catalina plugin for you.

    But this may not be necessary - just using 2 ports of the 8 port driver should be okay. Just test it first and make sure it is fast enough for your needs (I suspect the 8 port driver is not as fast as the 2 port driver due to the use of Hub RAM rather than LUT RAM, but this would only affect the higher baud rates - at the rates you are using it should be fine). I'd need to modify the C wrapper functions slightly because they currently allocate buffers for all 8 ports even if you don't need all of them, so if your buffer size was 8k that woulds be 8x2x8k = 128k allocated even though only 32k of that is needed for 2 ports. But that's trivial and I may do it anyway. I just never expected anyone would want buffers that large.

    On another note, right now, I do serial RX and TX multiplexing in hardware to switch to another port when enabled. Is there a way to do port multiplexing with smart pins? If so, the new design has several serial devices that when enabled, auto-switch into the P2 device thereby connecting to the UART. The pin connections for each UART interface are RX, TX, and EN. Just curious if you know of a way to do this. If not, I can investigate this myself and find out.

    I am not very knowledgeable about the smart pins. Hopefully someone else will chime in here, or else post your question as a separate topic.

    Ross.

  • jmgjmg Posts: 15,175

    @enorton said:
    On another note, right now, I do serial RX and TX multiplexing in hardware to switch to another port when enabled. Is there a way to do port multiplexing with smart pins?
    If so, the new design has several serial devices that when enabled, auto-switch into the P2 device thereby connecting to the UART.
    The pin connections for each UART interface are RX, TX, and EN. Just curious if you know of a way to do this. If not, I can investigate this myself and find out.

    Every pin can have a UART, so there is no real need for the older MCU multiplex approach on P2.
    You can software multiplex between as many as you have live at a time, at low baud rates, P2 could manage quite a few active UARTS.

    Is the EN driven from P2 to trigger the remote, or is it a plug and play signal to indicate presence, or is it a hardware handshake line ?

  • @RossH said:

    @enorton said:

    The function I posted is from another program I use for the other controllers I sell. I suppose it is pretty standard. I am porting over the same code and making enhancements to it to bring in new functionality.

    I wondered why the identifier names didn't quite match. I assumed you had changed them. But as you say it would be fairly standard code for a FIFO buffer. But I think I can add a similar function to the current 2 port serial plugin. I'll let you know.

    Ok sounds good and appreciate it :smile:

    Ah ok, 512 bytes for RX and TX is fine for testing but will need to do what you said with the 8-port serial library because I will need an 8k buffer for RX and TX at some point. I might sound like a real Smile for mentioning this, but can you make a 2-port version that uses hub ram? Just curious and I can enable the two like you said if that is easier. As long as it doesn't bog down the interface then that is fine. Can you let me know when you have updated Catalina or the library so I can download and use it please :-D.

    This is not likely to be done by me - :) - but there may be other serial drivers out there that could be adapted - if you find one I will turn it into a Catalina plugin for you.

    well I can for now use the 8serial library or stick with the 2 serial one and see how things go...

    But this may not be necessary - just using 2 ports of the 8 port driver should be okay. Just test it first and make sure it is fast enough for your needs (I suspect the 8 port driver is not as fast as the 2 port driver due to the use of Hub RAM rather than LUT RAM, but this would only affect the higher baud rates - at the rates you are using it should be fine). I'd need to modify the C wrapper functions slightly because they currently allocate buffers for all 8 ports even if you don't need all of them, so if your buffer size was 8k that woulds be 8x2x8k = 128k allocated even though only 32k of that is needed for 2 ports. But that's trivial and I may do it anyway. I just never expected anyone would want buffers that large.

    Ill test and let you know.

    On another note, right now, I do serial RX and TX multiplexing in hardware to switch to another port when enabled. Is there a way to do port multiplexing with smart pins? If so, the new design has several serial devices that when enabled, auto-switch into the P2 device thereby connecting to the UART. The pin connections for each UART interface are RX, TX, and EN. Just curious if you know of a way to do this. If not, I can investigate this myself and find out.

    I am not very knowledgeable about the smart pins. Hopefully someone else will chime in here, or else post your question as a separate topic.

    Ross.

    ok, thanks I will try to see what I can do with the multiplexing stuff. I am thinking about just doing it in a small CPLD and be done with it instead of cramming everything in the P2.

  • @jmg said:

    @enorton said:
    On another note, right now, I do serial RX and TX multiplexing in hardware to switch to another port when enabled. Is there a way to do port multiplexing with smart pins?
    If so, the new design has several serial devices that when enabled, auto-switch into the P2 device thereby connecting to the UART.
    The pin connections for each UART interface are RX, TX, and EN. Just curious if you know of a way to do this. If not, I can investigate this myself and find out.

    Every pin can have a UART, so there is no real need for the older MCU multiplex approach on P2.
    You can software multiplex between as many as you have live at a time, at low baud rates, P2 could manage quite a few active UARTS.

    Is the EN driven from P2 to trigger the remote, or is it a plug and play signal to indicate presence, or is it a hardware handshake line ?

    Well, I am doing hardware multiplexing now so that way it doesn't interfere with the processor I am using on my boards. I might just do it with a small CPLD and just be done with it. The EN is the enable line for each device that is connected to the P2.

  • @RossH said:

    @enorton said:

    The function I posted is from another program I use for the other controllers I sell. I suppose it is pretty standard. I am porting over the same code and making enhancements to it to bring in new functionality.

    I wondered why the identifier names didn't quite match. I assumed you had changed them. But as you say it would be fairly standard code for a FIFO buffer. But I think I can add a similar function to the current 2 port serial plugin. I'll let you know.

    Ah ok, 512 bytes for RX and TX is fine for testing but will need to do what you said with the 8-port serial library because I will need an 8k buffer for RX and TX at some point. I might sound like a real Smile for mentioning this, but can you make a 2-port version that uses hub ram? Just curious and I can enable the two like you said if that is easier. As long as it doesn't bog down the interface then that is fine. Can you let me know when you have updated Catalina or the library so I can download and use it please :-D.

    This is not likely to be done by me - :) - but there may be other serial drivers out there that could be adapted - if you find one I will turn it into a Catalina plugin for you.

    But this may not be necessary - just using 2 ports of the 8 port driver should be okay. Just test it first and make sure it is fast enough for your needs (I suspect the 8 port driver is not as fast as the 2 port driver due to the use of Hub RAM rather than LUT RAM, but this would only affect the higher baud rates - at the rates you are using it should be fine). I'd need to modify the C wrapper functions slightly because they currently allocate buffers for all 8 ports even if you don't need all of them, so if your buffer size was 8k that woulds be 8x2x8k = 128k allocated even though only 32k of that is needed for 2 ports. But that's trivial and I may do it anyway. I just never expected anyone would want buffers that large.

    On another note, right now, I do serial RX and TX multiplexing in hardware to switch to another port when enabled. Is there a way to do port multiplexing with smart pins? If so, the new design has several serial devices that when enabled, auto-switch into the P2 device thereby connecting to the UART. The pin connections for each UART interface are RX, TX, and EN. Just curious if you know of a way to do this. If not, I can investigate this myself and find out.

    I am not very knowledgeable about the smart pins. Hopefully someone else will chime in here, or else post your question as a separate topic.

    Ross.

    I finally managed to be able to start a cog woohoo... One thing I am confused about is how does the cog get the data from other variables from other cogs? I did a simple blinking selector in the cog I started, and it seems like variables can be written and read from the new cog or am I missing something? How do I know if some variables are stored locally in the hub ram or the local cog ram?

  • RossHRossH Posts: 5,477

    @enorton said:

    I finally managed to be able to start a cog woohoo... One thing I am confused about is how does the cog get the data from other variables from other cogs? I did a simple blinking selector in the cog I started, and it seems like variables can be written and read from the new cog or am I missing something? How do I know if some variables are stored locally in the hub ram or the local cog ram?

    I added a bit to JonnyMac's answer on the other thread.

    If you are starting a C function in a new cog and it is defined in the same file as where it is started, then the main program and the function can just share any static variables in the file - you don't need to do anything special except be aware of potential access conflicts or race conditions (use a lock if necessary).

    Another way (especially where the main program and the function are in different files) is to pass a pointer from the main program to the function you are starting that points to a shared data structure.

    Ross.

  • @RossH said:

    @enorton said:

    I finally managed to be able to start a cog woohoo... One thing I am confused about is how does the cog get the data from other variables from other cogs? I did a simple blinking selector in the cog I started, and it seems like variables can be written and read from the new cog or am I missing something? How do I know if some variables are stored locally in the hub ram or the local cog ram?

    I added a bit to JonnyMac's answer on the other thread.

    If you are starting a C function in a new cog and it is defined in the same file as where it is started, then the main program and the function can just share any static variables in the file - you don't need to do anything special except be aware of potential access conflicts or race conditions (use a lock if necessary).

    Another way (especially where the main program and the function are in different files) is to pass a pointer from the main program to the function you are starting that points to a shared data structure.

    Ross.

    ok interesting. I will poke around some more to figure this out but at least you answered my question as to if variables are shared between cogs which opens up a new way of thinking for me :-)

  • @RossH said:

    @enorton said:

    I finally managed to be able to start a cog woohoo... One thing I am confused about is how does the cog get the data from other variables from other cogs? I did a simple blinking selector in the cog I started, and it seems like variables can be written and read from the new cog or am I missing something? How do I know if some variables are stored locally in the hub ram or the local cog ram?

    I added a bit to JonnyMac's answer on the other thread.

    If you are starting a C function in a new cog and it is defined in the same file as where it is started, then the main program and the function can just share any static variables in the file - you don't need to do anything special except be aware of potential access conflicts or race conditions (use a lock if necessary).

    Another way (especially where the main program and the function are in different files) is to pass a pointer from the main program to the function you are starting that points to a shared data structure.

    Ross.

    Hi Ross,

    One thing I've noticed is that I have to declare the variables at the top of a function in Catalina Geany. Is there a way to disable this? I need to declare variables throughout the code not at the top or beginning of the function. I have reasons for this, and this might explain the odd behavior I am getting. This is one issue that might shelve the P2 for this project :-(. Also, the interrupts don't seem to function properly for some reason. Do the interrupts run in a different cog or on the same cog the application runs on? When I go to trigger the interrupt, it continuously runs like it's in a forever loop. I need like a one-shot interrupt.

    The other thing that is quite complex is passing variables to a new cog. If it is one variable it is fine but when you want to read and write say thirty of them then it becomes a nightmare.

  • In flexprop variables can be defined throughout and when using COGs I declare the variables as volatile so that they can be used throughout the program and will not be optimized. They must however be defined outside of main.

    Since COGs share the same memory as all the other COGs they can be easily accessed.

    Mike

  • @iseries said:
    In flexprop variables can be defined throughout and when using COGs I declare the variables as volatile so that they can be used throughout the program and will not be optimized. They must however be defined outside of main.

    Since COGs share the same memory as all the other COGs they can be easily accessed.

    Mike

    So, do I have to make all the variables volatile? Most of the functions go through main. The one thing I need is a timer with an interrupt and yes, I tried starting a new cog to have it processed in that cog but passing structures of data back and forth to the new cog doesn't seem to work properly, and not sure if it is a compiler issue or a P2 issue.

  • I don't get it. COGs are started and they run forever on there own. You don't pass anything back and forth.

    #include <stdio.h>
    #include <propeller.h>
    
    int Lock;
    long Stack[50];
    
    
    int main(int argc, char** argv)
    {
        int l;
        int i;
    
        cogstart(DoLock, NULL, Stack, 50);
    
        _waitms(500);
    
        printf("Lock: %d", Lock);
    
        while (1)
        {
            i = _locktry(Lock);
            printf("Try: %d\n", i);
            i = _lockclr(Lock);
            _waitms(500);
    
        }
    }
    
    void DoLock(void *par)
    {
        Lock = _locknew();
    
        while (1)
        {
            _locktry(Lock);
            _waitms(1000);
            _lockrel(Lock);
            _waitms(1000);
        }
    }
    

    This basic cog function obtains a lock where the main function waits for the lock to be release before continuing. The cog function never ends.

    Mike

  • @iseries said:
    I don't get it. COGs are started and they run forever on there own. You don't pass anything back and forth.

    #include <stdio.h>
    #include <propeller.h>
    
    int Lock;
    long Stack[50];
    
    
    int main(int argc, char** argv)
    {
        int l;
        int i;
    
        cogstart(DoLock, NULL, Stack, 50);
    
        _waitms(500);
    
        printf("Lock: %d", Lock);
    
        while (1)
        {
            i = _locktry(Lock);
            printf("Try: %d\n", i);
            i = _lockclr(Lock);
            _waitms(500);
    
      }
    }
    
    void DoLock(void *par)
    {
        Lock = _locknew();
    
        while (1)
        {
            _locktry(Lock);
            _waitms(1000);
            _lockrel(Lock);
            _waitms(1000);
        }
    }
    

    This basic cog function obtains a lock where the main function waits for the lock to be release before continuing. The cog function never ends.

    Mike

    Ok interesting. Why use lock? Do I need to use the lock? My cog start is like so:

    _cogstart_C(&test, NULL, cog_stack, sizeof(cog_stack));

    Here is the test function:

    void test(void *par)
    {
    for(;;) {
    if (settings.st_en == true) {
    _pinw(57, !_pinr(57));
    _waitms(500);

        } else {
            _pinw(57, !_pinr(57));
            _waitms(50);
        }
    }   
    

    }

    The "test" function works as intended. I am using the Propeller 2 by the way.

  • @iseries said:
    I don't get it. COGs are started and they run forever on there own. You don't pass anything back and forth.

    #include <stdio.h>
    #include <propeller.h>
    
    int Lock;
    long Stack[50];
    
    
    int main(int argc, char** argv)
    {
        int l;
        int i;
    
        cogstart(DoLock, NULL, Stack, 50);
    
        _waitms(500);
    
        printf("Lock: %d", Lock);
    
        while (1)
        {
            i = _locktry(Lock);
            printf("Try: %d\n", i);
            i = _lockclr(Lock);
            _waitms(500);
    
      }
    }
    
    void DoLock(void *par)
    {
        Lock = _locknew();
    
        while (1)
        {
            _locktry(Lock);
            _waitms(1000);
            _lockrel(Lock);
            _waitms(1000);
        }
    }
    

    This basic cog function obtains a lock where the main function waits for the lock to be release before continuing. The cog function never ends.

    Mike

    Nevermind about the locks I found out what it does duh...

  • RossHRossH Posts: 5,477
    edited 2023-04-16 22:29

    @enorton said:

    One thing I've noticed is that I have to declare the variables at the top of a function in Catalina Geany. Is there a way to disable this? I need to declare variables throughout the code not at the top or beginning of the function. I have reasons for this, and this might explain the odd behavior I am getting. This is one issue that might shelve the P2 for this project :-(. Also, the interrupts don't seem to function properly for some reason. Do the interrupts run in a different cog or on the same cog the application runs on? When I go to trigger the interrupt, it continuously runs like it's in a forever loop. I need like a one-shot interrupt.

    Unless I am misunderstanding what you mean, this is not a Geany thing. You can declare variables wherever you need them, but in ANSI C you have to do so in a new block. For example, to declare a new int ('my_new_int' in the code below) halfway through your code, just start a new block - e.g.:

    void main() {
       int my_int;
       ... some code ...
       {
          int my_new_int;
         ... more code ...
       }
       ... more code ...
    }
    

    This shouldn't cause odd behaviour.

    What is the problem you are having with interrupts? Can you provide an example? The examples in demos\interrupts are "one shot" interrupts.

    EDIT: Interrupt routines always run in the same cog they are triggered in. Every cog has its own set of interrupts.

    The other thing that is quite complex is passing variables to a new cog. If it is one variable it is fine but when you want to read and write say thirty of them then it becomes a nightmare.

    Use a struct and pass the address of the struct.

    Ross.

  • RossHRossH Posts: 5,477
    edited 2023-04-16 21:51

    @iseries said:
    I don't get it. COGs are started and they run forever on there own. You don't pass anything back and forth.

    You don't have to. But you can do so.

    This basic cog function obtains a lock where the main function waits for the lock to be release before continuing. The cog function never ends.

    I had to add a few lines to compile this code in Catalina:

    #include <propeller2.h>
    void DoLock(void *par);
    #define cogstart _cogstart_C
    

    i.e ...

    #include <stdio.h>
    #include <propeller.h>
    
    /*------------------------------------------*/ 
    #include <propeller2.h>
    void DoLock(void *par);
    #define cogstart _cogstart_C
    /*------------------------------------------*/ 
    
    int Lock;
    long Stack[50];
    
    
    int main(int argc, char** argv)
    {
        int l;
        int i;
    
        cogstart(DoLock, NULL, Stack, 50);
    
        _waitms(500);
    
        printf("Lock: %d", Lock);
    
        while (1)
        {
            i = _locktry(Lock);
            printf("Try: %d\n", i);
            i = _lockclr(Lock);
            _waitms(500);
    
      }
    }
    
    void DoLock(void *par)
    {
        Lock = _locknew();
    
        while (1)
        {
            _locktry(Lock);
            _waitms(1000);
            _lockrel(Lock);
            _waitms(1000);
        }
    }
    
  • RossHRossH Posts: 5,477
    edited 2023-04-16 22:04

    @enorton said:

    @iseries said:
    In flexprop variables can be defined throughout and when using COGs I declare the variables as volatile so that they can be used throughout the program and will not be optimized. They must however be defined outside of main.

    Since COGs share the same memory as all the other COGs they can be easily accessed.

    Mike

    So, do I have to make all the variables volatile? Most of the functions go through main. The one thing I need is a timer with an interrupt and yes, I tried starting a new cog to have it processed in that cog but passing structures of data back and forth to the new cog doesn't seem to work properly, and not sure if it is a compiler issue or a P2 issue.

    You don't have to make your variables volatile in Catalina, as long as they are within scope of the function. It is only when they are not in scope (e.g. declared in a different file, are local, or are dynamically allocated) that you may have to pass an address.

    Post your code (a cut down version is fine).

    Ross.

  • @RossH said:

    @enorton said:

    @iseries said:
    In flexprop variables can be defined throughout and when using COGs I declare the variables as volatile so that they can be used throughout the program and will not be optimized. They must however be defined outside of main.

    Since COGs share the same memory as all the other COGs they can be easily accessed.

    Mike

    So, do I have to make all the variables volatile? Most of the functions go through main. The one thing I need is a timer with an interrupt and yes, I tried starting a new cog to have it processed in that cog but passing structures of data back and forth to the new cog doesn't seem to work properly, and not sure if it is a compiler issue or a P2 issue.

    You don't have to make your variables volatile in Catalina, as long as they are within scope of the function. It is only when they are not in scope (e.g. declared in a different file, are local, or are dynamically allocated) that you may have to pass an address.

    Post your code (a cut down version is fine).

    Ross.

    I will see if I can post something a little later. I am dealing with something that may be causing a major issue and hard to pinpoint it at the moment.

  • @enorton said:
    One thing I've noticed is that I have to declare the variables at the top of a function in Catalina Geany. Is there a way to disable this? I need to declare variables throughout the code not at the top or beginning of the function. I have reasons for this, and this might explain the odd behavior I am getting. This is one issue that might shelve the P2 for this project :-(.

    That's an old leftover from C89. Flexspin, along with other modern compilers that support less obsolete standards than what Catalina supports, lets you naturally declare variables at their first assignment, as it sounds like your existing code already does.

  • RossHRossH Posts: 5,477

    @Electrodude said:

    @enorton said:
    One thing I've noticed is that I have to declare the variables at the top of a function in Catalina Geany. Is there a way to disable this? I need to declare variables throughout the code not at the top or beginning of the function. I have reasons for this, and this might explain the odd behavior I am getting. This is one issue that might shelve the P2 for this project :-(.

    That's an old leftover from C89. Flexspin, along with other modern compilers that support less obsolete standards than what Catalina supports, lets you naturally declare variables at their first assignment, as it sounds like your existing code already does.

    If there were another compiler that could do what Catalina can do, I would probably use it :)

  • RossHRossH Posts: 5,477

    Hello @enorton

    I have made some changes to Catalina that have been discussed in various threads recently. Here is a preview of some of the changes that will be included in the next release:

    New Functionality
    -----------------
    
    1. The multiport serial libraries (serial2, serial4, serial8) have each had two
       new functions added:
    
          int sX_txcount(unsigned port)
          int sX_rxcount(unsigned port)
    
       where X = 2, 4 or 8. The functions return the current count of characters 
       waiting in the transmit or receive buffers.
    
    Other Changes
    -------------
    
    1. The Catalina Propeller 2 Reference Manual said the 8 port serial functions 
       s8_openport() and s8_closeport() returned an int. In fact, they both return 
       a void - i.e. they don't return anything. The manual has been updated.
    
    2. The Catalina maths functions round() and trunc() were incorrectly defined 
       in catalina_float.h as returning floats - in fact, they both returned long 
       values. These functions have been retained, but have been renamed as
       _round() and _trunc(). 
    
       Also, these functions were only available when a maths co-processor was 
       loaded - e.g. if -lma, -lmb or -lmc (P2 only). New software implementation
       called lround() and ltrunc() which return longs have been defined so that
       they are available when any maths library option is used - i.e. including 
       the -lm option.
    
       Also, new functions have been added called fround() and ftrunc() which DO 
       return floats. So now a program that needs round() or trunc() can define 
    
       EITHER:
    
          #define round(x) lround(x)
          #define trunc(x) ltrunc(x)
    
       OR:
    
          #define round(x) fround(x)
          #define trunc(x) ftrunc(x)
    
       OR:
    
          #define round(x) _round(x)
          #define trunc(x) _trunc(x)
    
       depending on whether it needs versions that returns longs, versions that
       return floats (or doubles - in Catalina doubles are the same as floats, so 
       if the program expects these functions to return doubles, it will work 
       perfectly well with the new versions)  or wants to retain the original
       versions.   
    
    3. Catalina's original implementation of trunc(), which was also used when 
       a float was "cast" to an integer, was based on Cam Thompson's original 
       Float32_A co-processor, which unnecessarily limited the range in which 
       it would return a value. That range has been extended to include the 
       maximum range that can be encoded accurately in a float. Note that 
       this does not mean all longs in this range can be encoded - the way 
       IEEE457 floats are implemented means there are "gaps" in the integers
       that can be encoded as floats once you exceed the number of bits in the 
       mantissa. However, within the newly extended range (which corresponds to
       the integer range of -2,147,483,583 to 2,147,483,583) the implementation 
       of both ltrunc() and lround() will now return the correct integer value. 
       Outside that range they will return zero.
    
    4. The documentation regarding the 8 Port Serial plugin was a little 
       contradictory regarding the meaning and use of S8_MAX_PORTS. Setting this 
       determines the maximum number of ports that CAN BE OPENED, not the number 
       of ports that will be opened automatically. A port will only be opened 
       automatically if the port number is less than S8_MAX_PORTS, AND it has 
       pins specified in the range 0 .. 63 in the platform configuration file. 
       If the port has pins specified outside this range (e.g. as -1) then the 
       port will not be opened automatically but can be opened manually using
       the s8_openport() function. A port number greater or equal to S8_MAX_PORTS 
       will never be opened. If you want different baud rates or large buffer 
       sizes, it is recommended to open the ports manually.
    
    5. The accuracy of the various _wait functions (i.e. _waitsec(), _waitms(), 
       _waitus()) has been improved significantly. Also, the calculations of how
       long each unit of time is in clock ticks are now only done on the first
       call and on any call where a change in clock frequency is detected, not  
       on every call as in previous releases. This speeds up the calls, but it
       means that the very first call in such cases will be very slightly longer
       than subsequent calls - if this is a problem, add a call like:
          _waitus(0);
       at the start of the program to calculate the waits for the current
       clock frequency, and all subsequent waits will be more accurate. Note 
       that any call calculates the times for all the _wait functions, not just 
       the one actually called. Also note that for _waitus() there is a minimum 
       number of milliseconds that can be waited for accurately - especially on
       the Propeller 1. The actual value depends on the memory model used, but
       for Propeller 2 NATIVE it is less than 10us. If shorter accurate wait 
       times are required, consider using an inline PASM assembly language 
       function instead of the C _wait functions.
    
    

    Probably not worth a release just for these small issues - just wanted to let you know.

    Ross.

  • @RossH said:
    Hello @enorton

    I have made some changes to Catalina that have been discussed in various threads recently. Here is a preview of some of the changes that will be included in the next release:

    New Functionality
    -----------------
    
    1. The multiport serial libraries (serial2, serial4, serial8) have each had two
       new functions added:
    
          int sX_txcount(unsigned port)
          int sX_rxcount(unsigned port)
    
       where X = 2, 4 or 8. The functions return the current count of characters 
       waiting in the transmit or receive buffers.
    
    Other Changes
    -------------
    
    1. The Catalina Propeller 2 Reference Manual said the 8 port serial functions 
       s8_openport() and s8_closeport() returned an int. In fact, they both return 
       a void - i.e. they don't return anything. The manual has been updated.
    
    2. The Catalina maths functions round() and trunc() were incorrectly defined 
       in catalina_float.h as returning floats - in fact, they both returned long 
       values. These functions have been retained, but have been renamed as
       _round() and _trunc(). 
    
       Also, these functions were only available when a maths co-processor was 
       loaded - e.g. if -lma, -lmb or -lmc (P2 only). New software implementation
       called lround() and ltrunc() which return longs have been defined so that
       they are available when any maths library option is used - i.e. including 
       the -lm option.
    
       Also, new functions have been added called fround() and ftrunc() which DO 
       return floats. So now a program that needs round() or trunc() can define 
       
       EITHER:
    
          #define round(x) lround(x)
          #define trunc(x) ltrunc(x)
    
       OR:
    
          #define round(x) fround(x)
          #define trunc(x) ftrunc(x)
    
       OR:
    
          #define round(x) _round(x)
          #define trunc(x) _trunc(x)
    
       depending on whether it needs versions that returns longs, versions that
       return floats (or doubles - in Catalina doubles are the same as floats, so 
       if the program expects these functions to return doubles, it will work 
       perfectly well with the new versions)  or wants to retain the original
       versions.   
    
    3. Catalina's original implementation of trunc(), which was also used when 
       a float was "cast" to an integer, was based on Cam Thompson's original 
       Float32_A co-processor, which unnecessarily limited the range in which 
       it would return a value. That range has been extended to include the 
       maximum range that can be encoded accurately in a float. Note that 
       this does not mean all longs in this range can be encoded - the way 
       IEEE457 floats are implemented means there are "gaps" in the integers
       that can be encoded as floats once you exceed the number of bits in the 
       mantissa. However, within the newly extended range (which corresponds to
       the integer range of -2,147,483,583 to 2,147,483,583) the implementation 
       of both ltrunc() and lround() will now return the correct integer value. 
       Outside that range they will return zero.
    
    4. The documentation regarding the 8 Port Serial plugin was a little 
       contradictory regarding the meaning and use of S8_MAX_PORTS. Setting this 
       determines the maximum number of ports that CAN BE OPENED, not the number 
       of ports that will be opened automatically. A port will only be opened 
       automatically if the port number is less than S8_MAX_PORTS, AND it has 
       pins specified in the range 0 .. 63 in the platform configuration file. 
       If the port has pins specified outside this range (e.g. as -1) then the 
       port will not be opened automatically but can be opened manually using
       the s8_openport() function. A port number greater or equal to S8_MAX_PORTS 
       will never be opened. If you want different baud rates or large buffer 
       sizes, it is recommended to open the ports manually.
    
    5. The accuracy of the various _wait functions (i.e. _waitsec(), _waitms(), 
       _waitus()) has been improved significantly. Also, the calculations of how
       long each unit of time is in clock ticks are now only done on the first
       call and on any call where a change in clock frequency is detected, not  
       on every call as in previous releases. This speeds up the calls, but it
       means that the very first call in such cases will be very slightly longer
       than subsequent calls - if this is a problem, add a call like:
          _waitus(0);
       at the start of the program to calculate the waits for the current
       clock frequency, and all subsequent waits will be more accurate. Note 
       that any call calculates the times for all the _wait functions, not just 
       the one actually called. Also note that for _waitus() there is a minimum 
       number of milliseconds that can be waited for accurately - especially on
       the Propeller 1. The actual value depends on the memory model used, but
       for Propeller 2 NATIVE it is less than 10us. If shorter accurate wait 
       times are required, consider using an inline PASM assembly language 
       function instead of the C _wait functions.
       
    

    Probably not worth a release just for these small issues - just wanted to let you know.

    Ross.

    Hi Ross,

    This is great news :-) and thank you for your hard work. How do I get access to these changes?

    There are a few things I have found after a couple of days of writing code, testing, and comparing a known working system and the Propeller 2 chip and I really need C99 support. I have found that while porting the code over, the variables need to be initialized throughout the code and not at the beginning as in C89. C89 ANSI works for most cases but not in my particular application. I have protected sections of code and initializing them, in the beginning, doesn't work for what I need. Is there a way to enable C99 support for Catalina Geany? I am porting code that I know for a fact works perfectly on two other chips to the Propeller 2 chip and it's not working as intended. Maybe it could be the interrupt-driven architecture in the other chips that is causing it to work compared to the Propeller 2 chip. I don't have a side-by-side comparison to rule that out. I did notice when I run through one of the loops the structure starts out initialized as NULL and then when called it runs as expected but does not go back to NULL when finished and therefore does not complete the cycle. Is there any reason why NULL can't be used?

Sign In or Register to comment.