F002 Hello flux

The first example creates the simple uncompressed trace with an integer and a float signal and writes it into a file.

The example will show you the basic steps to create a trace.

  • Prepare the memory (c-language only)
  • Create trace object and at leat one buffer
  • Write head
  • Add items (signals and scopes) - optional
  • Open a trace sequence (e.g start at 10ms)
    • Write enumeration and member information - optional
    • Iterate over the domain (e.g. 10-20ms)
      • Write samples
  • Close the sequence (e.g end at 20ms)
  • You may open/close additional sequences ...

Preparing the memory (c-language only)

The c-language emitter of flux does not depend on any library (embedded systems). Therefor the memory for the trace and the buffer object need to be prepared.

The first step in setting up a flux trace is calculating the required memory. The required memories for buffers and tables need to be passed as arguments to the 

  • flxCreateXXXXBuffer and
  • flxCreateTrace methods.

In this example (and most others) we use the macros 

  • FLX_BUFFER_BYTES and 
  • FLX_TRACE_BYTES

to calculate the memory size for buffer and trace and define static memory chunks.

  • C

        // calculate required memory for trace and buffers
    	unsigned bufferSize = FLX_BUFFER_BYTES(MAX_ENTRY_SIZE);
    	unsigned traceSize = FLX_TRACE_BYTES(0, MAX_ITEM_ID);
    
    	// static memory
    	unsigned char memoryBuffer[bufferSize];
    	unsigned char memoryTrace[traceSize];

Creating the buffer and the trace object

Buffers are used to store, organize and handle the trace data. The trace information is packed into snippets (entries).

In this example, we use a simple flat buffer that writes to a file.

c-language

We use the method flxCreateSimpleBuffer. The third and fourth arguments are the 'write to file' handler and the file object. 

Java-, Python-, Typescript- and JacaScript-language

The SimpleFileOutputBuffer class contains a simple buffer with a 'write to file' handler.

  • Java

        // buffer
        Flx.Buffer buffer = new Flx.SimpleFileOutputBuffer(MAX_ENTRY_SIZE, "traces/example01.recTr");
    
        // trace
        Flx.Trace trace = new Flx.Trace(0, MAX_ITEM_ID, MAX_ENTRY_SIZE, false, buffer);
    
  • C/C++

    	// buffer
    	flxBuffer buffer = flxCreateSimpleBuffer(memoryBuffer, bufferSize, flxWriteToFile, out);
    
    	// trace
    	flxTrace trace = flxCreateTrace(0, MAX_ITEM_ID, MAX_ENTRY_SIZE, memoryTrace, traceSize, buffer);
    
    
  • Python

        # buffer
        buffer =  Flx.SimpleFileOutputBuffer(MAX_ENTRY_SIZE, "traces/example01.recTr");
    
        # trace
        trace =  Flx.Trace(0, MAX_ITEM_ID, MAX_ENTRY_SIZE, False, buffer);
    
  • TypeScript

    	// buffer
        let buffer : Flx.Buffer = new Flx.SimpleFileOutputBuffer(Example01.MAX_ENTRY_SIZE, "traces/example01.recTr");
        
    	// trace
        let trace : Flx.Trace = new Flx.Trace(0, Example01.MAX_ITEM_ID, Example01.MAX_ENTRY_SIZE, false, buffer);
        
        
  • JavaScript

        // buffer
        var buffer = new Flx.SimpleFileOutputBuffer(Example01.MAX_ENTRY_SIZE, "traces/example01.recTr");
        
        // trace
        var trace = new Flx.Trace(0, Example01.MAX_ITEM_ID, Example01.MAX_ENTRY_SIZE, false, buffer);
        

For the trace creation we need the following arguments:

  • the traceId,
  • the max itemId,
  • the maxEntrySize value,
  • the trace object memory and size (c-language only - this is for trace handling, not for the trace data itself)
  • and the initial buffer (may be changed later) to store the trace data. 
  • maxItemId defines the largest id used for an item. This parameter is used on emitter and receiver side to set-up required structures.
  • maxEntrySize defines the maximum allowed size of an entry. On receiver and emitter side, this parameter is used  to prepare the buffers (each entry should fit completely into a buffer).
  • Adding items

    The trace object is prepared and we can start to add content. With flxAddHead/addHead we start the trace with a label and description of the following trace. The method flxAddSignal/addSignal adds a signal to the trace. The arguments are:

    • the trace object (c-language only),
    • itemId for the signal,
    • parentId, here 0 for the root scope,
    • a name and description (2 arguments),
    • the type of the signal
    • and a signal descriptor (not used in this example)
    • Java

              // head
              trace.addHead("example", "flux example");
      
              // add signals
              // parent 0 is root
              trace.addSignal(1, 0, "integer", "an integer", Flx.TYPE_INTEGER, null);
              trace.addSignal(2, 0, "float", "a float", Flx.TYPE_FLOAT, null);
      
    • C/C++

      		// head
      		flxAddHead(trace, "example", "flux example");
      
      		// add signals
      		// parent 0 is root
      		flxAddSignal(trace, 1, 0, "integer", "an integer", FLX_TYPE_INTEGER, 0);
      		flxAddSignal(trace, 2, 0, "float", "a float", FLX_TYPE_FLOAT, 0);
      
    • Python

              // head
              flxAddHead(trace, "example", "flux example");
      
              // add signals
              // parent 0 is root
              flxAddSignal(trace, 1, 0, "integer", "an integer", FLX_TYPE_INTEGER, None);
              flxAddSignal(trace, 2, 0, "float", "a float", FLX_TYPE_FLOAT, None);
      
    • TypeScript

          	// head
              trace.addHead("example", "flux example");
              
          	// add signals
          	// parent 0 is root            
              trace.addSignal(1, 0, "integer", "an integer", Flx.TYPE_INTEGER, null);
              trace.addSignal(2, 0, "float", "a float", Flx.TYPE_FLOAT, null);
          
    • JavaScript

          	// head
              trace.addHead("example", "flux example");
              
              // add signals
              // parent 0 is root            
              trace.addSignal(1, 0, "integer", "an integer", Flx.TYPE_INTEGER, null);
              trace.addSignal(2, 0, "float", "a float", Flx.TYPE_FLOAT, null);
          

    Open and close

    With flxOpen/open we start a trace sequence and finalize it with flxClose/close. Both methods are used to define the domain range and the process. The parameters of flxOpen/open are:

    • the trace object (c-language only),
    • itemId to be opened (0 == root; we open all items)
    • domainBase ("ns": the smallest delta between two samples is 1 ns )
    • start position (0ns)
    • sample rate (0: discrete process)

    And flxClose/close has:

    • the trace object (c-language only),
    • itemId to be opened (0 == root; we close all items)
    • end position (50000 * 10 ns)

    To open an item id != 0, you need to offer a larger memory space to the trace object (more complex handling). You do this by setting the first argument of FLX_TRACE_BYTES to 1.

    • Java

              // open
              trace.open(0, "ns", 0, 0);
      
              // generate example trace
              for (int n = 0; n < 50000; n++) {
      
                  // time in ns
                  current = n * 10;
      
      ...
      
              // close
              trace.close(0, current + 10);
      
    • C/C++

      		// open
      		flxOpen(trace, 0, "ns", 0, 0);
      
      		// generate example trace
      		for (int n = 0; n < 50000; n++) {
      
      			// time in ns
      			current = n * 10;
      
      ...
      
      		// close
      		flxClose(trace, 0, current + 10);
      
      
    • Python

              # open
              trace.open(0, "ns", 0, 0);
      
              # generate example trace
              for n in range(0, 50000) :
      
                  # time in ns
                  current = n * 10;
      
      ...
      
              # close
              trace.close(0, current + 10);
      
    • TypeScript

              // open
              trace.open(0, "ns", 0, 0);
              
              // generate example trace
              for(let n : number = 0; n < 50000; n++){
                  
                  // time in ns
                  current = n * 10;
                  
      ...
              // close
              trace.close(0, current + 10);
          
    • JavaScript

              // open
              trace.open(0, "ns", 0, 0);
              
              // generate example trace            
              for (var n = 0; n < 50000; n++) {
      
                   // time in ns              	
                   current = n * 10;
      
      ...
              
              // close
              trace.close(0, current + 10);
          

    Writing the data samples

    The flxWriteXXXAt/writeXXXAt methods are intended to add events and value changes to a signal.

    The domain position (e.g. when a change occurs) can be given absolute or relative. If you choose an absolute domain position, the value must to be equal or larger than the one used in a previous write (and larger than the open position).

    A relative domain position (means relative to a previous write) must be larger or equal to 0.

    The parameters:

    • the trace object (c-language only),
    • itemId of the signal,
    • the tag flag (samples can have a tag, e.g. error),
    • domain position,
    • isRelative flag (1: relative, 0:absolute),
    • the value,
    • and finally the size of the value in bytes (c-language only).
    • Java

                  // integer
                  iVal = n % 444;
                  trace.writeIntAt(1, 0, current, false, iVal);
      
                  // float - same time - use domain=0; isDelta=1
                  fVal = (n / 1000.0);
                  trace.writeFloatAt(2, 0, 0, true, fVal);
      
    • C/C++

      			// integer
      			iVal = n % 444;
      			flxWriteIntAt(trace, 1, 0, current, 0, &iVal, sizeof(int), 1);
      
      			// float - same time - use domain=0; isDelta=1
      			fVal = (n / 1000.0);
      			flxWriteFloatAt(trace, 2, 0, 0, 1, &fVal, sizeof(double));
      
    • Python

                  // integer
                  iVal = n % 444;
                  trace.writeIntAt(1, 0, current, false, iVal);
                  
                  // float - same time - use domain=0; isDelta=1
                  fVal = (n / 1000.0);
                  trace.writeFloatAt(2, 0, 0, true, fVal);
      
    • TypeScript

                  // integer
                  iVal = n % 444;
                  trace.writeIntAt(1, 0, current, false, iVal);
                  
                  // float - same time - use domain=0; isDelta=1
                  fVal = (n / 1000.0);
                  trace.writeFloatAt(2, 0, 0, true, fVal);
          
    • JavaScript

                  // integer                	
                  iVal = n % 444;
                  trace.writeIntAt(1, 0, current, false, iVal);
      
                  // float - same time - use domain=0; isDelta=1                    
                  fVal = (n / 1000.0);
                  trace.writeFloatAt(2, 0, 0, true, fVal);
          
    toem

    technical software and tooling

    Company

    Contact Us

    This email address is being protected from spambots. You need JavaScript enabled to view it.