Shop OBEX P1 Docs P2 Docs Learn Events
Strange behavior — Parallax Forums

Strange behavior

EnriqueEnrique Posts: 90
edited 2013-01-15 21:05 in Propeller 1
Hi,

A program I am writing starting behaving in a strange way and I managed to duplicate its behavior in the code I am posting bellow. I solved the problem by inserting an extra statement which I think serves no purpose.

If you comment out the "pinLow(16);" statement the sits in the " while(received_data->blink_now == 0x00)" loop of the blinker function the program will not work. I don't see what this statement does as in my opinion it is totally useless.

I run this program on a Propeller Professional Development Board where I wired one of the switches to pin 17 and an LED to pin 16.
#include <propeller.h>
#include "pin.h"


typedef struct data_block
{
    char blink_now;
} data_block;

data_block actual_data;
char stack[160];

void blinker(data_block *received_data)
{
    pinOutput(16);
    pinLow(16);

    while(1)
    {
        while(received_data->blink_now == 0x00)
        {
            pinLow(16); // If you comment out this statement the program will not work
        }

        while(received_data->blink_now != 0x00)
        {
            pinHigh(16);
            waitcnt(CLKFREQ / 10 * 2 + CNT);
            pinLow(16);
            waitcnt(CLKFREQ / 10 * 2 + CNT);
        }
    }
}

int main(void)
{
    pinInput(17);

    actual_data.blink_now = 0x00;
    cogstart(blinker, &actual_data, &stack, sizeof(stack));

    while(1)
    {
        if(pinGet(17) == 0)
        {
            actual_data.blink_now = 0x01;
        }
        else
        {
            actual_data.blink_now = 0x00;
        }
    }

    return 0;
}

Your comments will be appreciated.
Enrique

Comments

  • jazzedjazzed Posts: 11,803
    edited 2013-01-07 09:05
    What optimization level are you using?
    Try -O0 (Oh Zero, that is no optimization).
  • ersmithersmith Posts: 6,054
    edited 2013-01-07 10:05
    You need to declare the "received_data" parameter to the blinker() function as volatile; that tells the compiler that it can be changed by something outside of the program's control (hardware, or another COG). Without "volatile" the compiler is justified in optimizing:
      while (received_data->blink_now != 0)
          ;
    
    into
      if (received_data->blink_now != 0)
        for(;;); /* loop forever */
    

    Eric
  • EnriqueEnrique Posts: 90
    edited 2013-01-07 11:27
    Jazzed,

    I have the compiler set to Board Type: Hub, Compiler Type: C, Memory Model: LMM and Optimization -O2 Speed. With these settings the program behaves as I have described.

    When I set the compiler to -O0 None, as you suggested, the LED blinks continuously.

    I also followed Eric's suggestion and changed the code as follows but it didn't help.
    volatile data_block actual_data;
    char stack[160];
    
    void blinker(volatile data_block *received_data)
    

    Enrique
  • David BetzDavid Betz Posts: 14,516
    edited 2013-01-07 12:02
    You might need to try this:
    typedef struct data_block
    {
        volatile char blink_now;
    } data_block;
    
    It isn't the pointer that is volatile. It is the field in the structure.
  • EnriqueEnrique Posts: 90
    edited 2013-01-07 12:21
    With this change when I optimize for speed everything works fine, with no optimization the program doesn't perform as expected
  • David BetzDavid Betz Posts: 14,516
    edited 2013-01-07 12:36
    Enrique wrote: »
    With this change when I optimize for speed everything works fine, with no optimization the program doesn't perform as expected
    That's odd. Usually if there is going to be a problem it will be with the optimized code not the unoptimized code.
  • EnriqueEnrique Posts: 90
    edited 2013-01-07 12:47
    I also found this strange, that's why I posted this result in my previous reply. I just double checked again and the problem now occurs with no optimization. Maybe on of you can reproduce the problem.

    Enrique
  • jazzedjazzed Posts: 11,803
    edited 2013-01-07 14:44
    Hi.

    The stack is the problem (+ need for volatile).

    Calculating the minimum stack size is better than using a number which can be arbitrary.
    The cogstart web page had 160 bytes minimum (wrong, sorry). The actual need is 176+ longs.
    https://sites.google.com/site/propellergcc/documentation/libraries/propeller-h-library#TOC-cogstart

    The minimum stack size is this:

    int stacksize = sizeof(_thread_state_t)+sizeof(int)*3;
    int stack[stacksize]; // valid with C99 ... use malloc otherwise.

    Also, &stack to cogstart is wrong. If you want to use &, it should be &stack[0].
    --Steve
  • EnriqueEnrique Posts: 90
    edited 2013-01-08 00:36
    Problem solved.

    Thanks
  • SRLMSRLM Posts: 5,045
    edited 2013-01-08 00:58
    @GCC team

    On the link that jazzed posted, I noticed that "size" doesn't have any units. It mentions that the minimum is 176 longs, so maybe (int) is the unit. Which would seem to contrast with other references that say size is in bytes: http://www.cplusplus.com/reference/cstdlib/malloc/

    Also, it would be nice to mention where the stack goes, just to clarify. ie, hub, cog, external(?), etc.
  • EnriqueEnrique Posts: 90
    edited 2013-01-08 01:00
    He does mention bytes.
  • ersmithersmith Posts: 6,054
    edited 2013-01-08 07:13
    SRLM wrote: »
    Also, it would be nice to mention where the stack goes, just to clarify. ie, hub, cog, external(?), etc.

    The stack always goes in hub memory, even in XMM modes.

    Eric
  • jazzedjazzed Posts: 11,803
    edited 2013-01-08 09:54
    SRLM wrote: »
    @GCC team

    On the link that jazzed posted, I noticed that "size" doesn't have any units. It mentions that the minimum is 176 longs, so maybe (int) is the unit. Which would seem to contrast with other references that say size is in bytes: http://www.cplusplus.com/reference/cstdlib/malloc/

    Also, it would be nice to mention where the stack goes, just to clarify. ie, hub, cog, external(?), etc.

    Yes, sizeof(type) returns number of bytes used by type. So the expression sizeof(_thread_state_t)+sizeof(int)*3 should return number of bytes needed for the stack. Sorry for the confusion.

    The original program does work using these changes: 1) volatile char blink_now, 2) &stack[0] or stack instead of &stack as the third parameter to cogstart, and 3) 176 bytes of stack as int stack[176/4+1] (the stack as a general rule should have N bytes evenly divisible by four) ... additionally, the stack size should be calculated but the code I mentioned before should use int stack[stacksize/4+1] rather than int stack[stacksize].
  • SRLMSRLM Posts: 5,045
    edited 2013-01-15 16:58
    This question pertains to "cogstart": If I have a variable that is used by two or more cogs running LMM C code (via cogstart), do I need to mark that variable as volatile? Or is the compiler smart enough to know (based on the fact that it's used in several cogstart'ed functions) that a variable may be modified out of scope?
  • SRLMSRLM Posts: 5,045
    edited 2013-01-15 21:05
    SRLM wrote: »
    This question pertains to "cogstart": If I have a variable that is used by two or more cogs running LMM C code (via cogstart), do I need to mark that variable as volatile? Or is the compiler smart enough to know (based on the fact that it's used in several cogstart'ed functions) that a variable may be modified out of scope?

    The answer seems to be yes (if it's used by multiple cogstart'ed functions, it must be volatile).
Sign In or Register to comment.