Use of 'out port' violates parallel usage rules

If you have a simple question and just want an answer.
Orkun
Junior Member
Posts: 7
Joined: Fri Mar 11, 2016 9:53 pm

Use of 'out port' violates parallel usage rules

Post by Orkun »

Hi. I'm new in xMOS devices and compiler. I need 16-bit wide data bus and it is just write only port and I want to write port when the one button is pressed. I'm trying to drive the XS1_PORT_16A to output as the same as simple gpio example of xMos examples. I'm using xCORE 200 explorerKit

I've defined the output port,

Code: Select all

  #include "xs1.h"
  #include "platform.h"
  #include "gpio.h"

  unsigned short data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

  on tile[0] : out port explorer_outs = XS1_PORT_16A;
  on tile[0] : in port explorer_butts = XS1_PORT_4E

  [[combinable]]
  void xCoreDriveOutputs(unsigned short *data, int n, out port oPort, client input_gpio_if butt) {
      int i;
      unsigned value = 1;
      while (1) {
        seleect {
          case butt.event():
            phPort <: value;
            delay_microseconds(5);

            for (i = 0; i < n; i++) {
              value = ((data[i] << 1) | 0x01);
              phPort <: value;
              value &= ~((unsigned)0x01);
              phPort <: value;
            }
            break;
        }
      }
  }
  
  int main() {
    input_gpio_if i_explore_butts[2];
    output_gpio_if i_explore_outs[16];
    
    par
    {
      on tile[0] : input_gpio_with_events(i_explore_butts, 2, explorer_butts, null);
      on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
      on tile[0] : xCoreDriveOutputs(data, 10, explorer_outs, i_explore_butts[0]);
    }
    return 0;
  }
When I compile the codes, the output is;

Code: Select all

12:15:37 **** Incremental Build of configuration Default for project AN00190_Getting_started_with_xTIMEcomposer_Studio ****
xmake CONFIG=Default all 
Checking build modules
Using build modules: lib_gpio(1.0.1) lib_xassert(2.0.1)
Analyzing main.xc
../src/main.xc:158:5: error: use of `explorer_outs' violates parallel usage rules
    par
    ^~~
../src/main.xc:165:65: note: violation occurs here
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                                                ^~~~~~~~~~~~~~~~~~
../src/main.xc:168:47: note: violation occurs here
                                              explorer_printhead,
                                              ^~~~~~~~~~~~~~~~~~
../src/main.xc:160:45: warning: `i_explore_butts' not used in two parallel statements (byte range 4..8)
        on tile[0] : input_gpio_with_events(i_explore_butts, 2, explorer_buttons, null);
                                            ^~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 0..4)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 4..8)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 8..12)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 12..16)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 16..20)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 20..24)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 24..28)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 28..32)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 32..36)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 36..40)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 40..44)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 44..48)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 48..52)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 52..56)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 56..60)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:165:34: warning: `i_explore_outs' not used in two parallel statements (byte range 60..64)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
xmake[1]: *** [.build/src//main.xc.pca.xml] Error 1
xmake: *** [analyze] Error 2

12:15:38 Build Finished (took 1s.555ms)

I've read the problems about that but I did not find any similar issue. Thanks.
henk
Verified
Respected Member
Posts: 347
Joined: Wed Jan 27, 2016 5:21 pm

Post by henk »

Hi Orkun, welcome.

Each port can only be used from a single logical core; otherwise there would be chaos in ordering the events on that port, or in deciding which logical core should be notified when something happens on the port.

In your case

Code: Select all

explorer_outs
is used in two logical cores; the logical core that executes

Code: Select all

xCoreDriveOutputs
and the logical core that executes

Code: Select all

output_gpio
. Only one of those should use

Code: Select all

explorer_outs
.

If you want two logical cores to use IO pins, use an extra port (there are 28 of them). Each port can be used independently by a logical core.

Cheers,
Henk
Orkun
Junior Member
Posts: 7
Joined: Fri Mar 11, 2016 9:53 pm

Post by Orkun »

Thanks Henk. Now I have another question about driving all the port in one C line like;

Code: Select all

explorer_outs <: value;
without sending as argument the "out port". How can I do that?
Orkun
Junior Member
Posts: 7
Joined: Fri Mar 11, 2016 9:53 pm

Post by Orkun »

Now I've changed the code and not sending the "out port" parameter as an argument to

Code: Select all

xCoreDriveOutputs
function. I've changed codes to;

Code: Select all

void xCoreDriveOutputs(unsigned short *data, int n, client output_gpio_if oPort, client input_gpio_if butt) {
  int i;
  unsigned value = 1;

  oPort.output(value);
  delay_microseconds(5);

  for (i = 0; i < n; i++) {
    value = ((data[i] << 1) | 0x01);
    oPort.output(value);
    value &= ~((unsigned)0x01);
    oPort.output(value);
  }
}
  
int main() {
  input_gpio_if i_explore_butts[2];
  output_gpio_if i_explore_outs[16];
    
  par
  {
    on tile[0] : input_gpio_with_events(i_explore_butts, 2, explorer_butts, null);
    on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
    on tile[0] : xCoreDriveOutputs(data, 10, i_explore_outs[0], i_explore_butts[0]);
  }
  return 0;
}
but it is giving a lot of warning about the variables which are created at the top of main function;

Code: Select all

  input_gpio_if i_explore_butts[2];
  output_gpio_if i_explore_outs[16];
the warnings are the same as my first post;

Code: Select all

16:42:49 **** Incremental Build of configuration Default for project AN00190_Getting_started_with_xTIMEcomposer_Studio ****
xmake CONFIG=Default all 
Checking build modules
Using build modules: lib_gpio(1.0.1) lib_xassert(2.0.1)
Analyzing main.xc
../src/main.xc:167:45: warning: `i_explore_butts' not used in two parallel statements (byte range 4..8)
        on tile[0] : input_gpio_with_events(i_explore_butts, 2, explorer_buttons, null);
                                            ^~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 4..8)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 8..12)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 12..16)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 16..20)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 20..24)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 24..28)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 28..32)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 32..36)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 36..40)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 40..44)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 44..48)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 48..52)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 52..56)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 56..60)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 60..64)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
Propagating analysis
Creating dependencies for main.xc
Compiling main.xc
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 4..8)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 8..12)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 12..16)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 16..20)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 20..24)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 24..28)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 28..32)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 32..36)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 36..40)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 40..44)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 44..48)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 48..52)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 52..56)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 56..60)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:172:34: warning: `i_explore_outs' not used in two parallel statements (byte range 60..64)
        on tile[0] : output_gpio(i_explore_outs, 16, explorer_outs, null);
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../src/main.xc:167:45: warning: `i_explore_butts' not used in two parallel statements (byte range 4..8)
        on tile[0] : input_gpio_with_events(i_explore_butts, 2, explorer_buttons, null);
                                            ^~~~~~~~~~~~~~~
Creating app_getting_started.xe
Build Complete

16:42:53 Build Finished (took 3s.418ms)
but it builded. I don't know these warnings cause a problem?
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1156
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

Nice interface naming ;-)

So you don't have any errors - however you have declared an array of interfaces, most of which are only connected at one end. The slightly cryptic byte range message says which interface is connected (each one is 4 bytes) and you can see no error for range 0..3.

You can supply a pin map array so that only the individual pins within the wide ports you want are setup..
See the comment about the 4th argument below...

The lib_gpio library does seem like a complex way just to waggle a pin. However, when you have lots of tasks (clients) all wanting to manipulate an individual pin concurrently and safely, and those tasks may be on different cores/tile, then it starts to make a lot more sense.

Code: Select all

/** Task that splits a multibit port into several 1 bit GPIO interfaces.
 *
 * This component allows other tasks to access the individual bits of
 * a multi-bit output port.
 *
 * \param   i         The array of interfaces to connect to other tasks.
 * \param   n         The number of interfaces connected.
 * \param   p         The output port to be split.
 * \param   pin_map   This array maps the connected interfaces to the pin
 *                    of the port. For example, if 3 clients are connected
 *                    to split a 8-bit port and the array {2,5,3} is supplied.
 *                    Then bit 2 will go to interface 0, bit 5 to inteface 1
 *                    and bit 3 to inteface 2. If null is supplied for this
 *                    argument then the pin map is assumed to be {0,1,2...}.
 */
[[distributable]]
void output_gpio(server output_gpio_if i[n], static const size_t n, out port p,
                 char (&?pin_map)[n]);
Orkun
Junior Member
Posts: 7
Joined: Fri Mar 11, 2016 9:53 pm

Post by Orkun »

Thanks infiniteimprobability,

I want to verify I understood or not.

When I send null to 4th argument, then the port is starting at 0 and goes to 16 (in my code). Port mapping is like a some swapping.

Sorry for wasting your time.
Thanks again.
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1156
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

Sorry for wasting your time.
Not at all! Helping someone learn XC is not a waste of time!

When you send a null, then the I/O driver assumes the interface mapping is interface(0) manipulates bit zero of the port and interface(1) manipulates pin 1 etc...
Orkun
Junior Member
Posts: 7
Joined: Fri Mar 11, 2016 9:53 pm

Post by Orkun »

Ok now I'm understanding. Can I set or reset all the port in one operation? I'm usually using arm based microcontrollers, for example I want to change the all port a pins like this way;

Code: Select all

GPIOA->ODR = value;
or can I define two different out port parameter but they are addressing the same ports;

Code: Select all

in tile[0] : out port explorer_outs_act = XS1_PORT_16A;
in tile[0] : out port explorer_outs_mir = XS1_PORT_16A;
Are they now pointing the same memory area and can I send them individual parallel tasks?
User avatar
infiniteimprobability
Verified
XCore Legend
Posts: 1156
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

Yes ...

Code: Select all

out port my_port = XS1_PORT_8A;

unsigned new_port_val = 0xff;
my_port <: new_port_val;
Ports are not memory mapped - they use specific in/out operations. They can do rather a lot that ARM ports cannot do (serialise, clock, timing, comparisons...).