Main Content

Generate Sender and Receiver C Interface Code for Component Deployment

Since R2022b

This example shows how to generate sender and receiver service functions to send and receive data to and from the target environment by using environment-specific data communication methods. Use data communication methods that match the needs of the target environment. For more information about data communication methods, see Data Communication Methods.

Inspect Model

Open the model.

model = "ComponentDeploymentFcn";
open_system(model);

modelScreenshot.png

The model contains mixed periodic and aperiodic rates, which require data concurrency safeguards. To enforce data concurrency safeguards, use the Outside Execution or During Execution data communication methods. With these data communication methods, the code generator uses a buffer rather than writing to memory directly. For models that do not require data concurrency safeguards, consider using the Direct Access data communication method, which allows the generated code to read from and write to the target environment memory directly.

Inspect Embedded Coder Dictionary

Inspect the shared Embedded Coder Dictionary and verify the sender and receiver service configuration.

1. Open the Embedded Coder Dictionary. From the C Code tab, under Code Interface, select Embedded Coder Dictionary (Shared).

2. In the Embedded Coder Dictionary, in the left pane, select Service Interfaces. The center pane populates with service interfaces.

3. In the center pane, under Receiver, verify that the ReceiverOutsideExe service interface has the Dictionary Default check box selected.

4. Click the ReceiverOutsideExe row. The right pane populates with information about the service interface. In this case, the service interface uses the Outside Execution data communication method and the function naming rule get_$X_input. The $X token represents the name of the entry-point function that encloses the access function.

5. Under Sender, verify that the SenderOutsideExe row is selected as Dictionary Default and that the service uses the Outside Execution data communication method and the function naming rule set_$X_output.

When you select the Outside Execution data communicaiton method, the generated code applies data concurrency safeguards by using a buffer provided by the target environment. Outside Execution allows communication with the target environment to occur only between task iterations.

Inspect Code Mappings

Inspect the Code Mappings editor and verify that the model root inports and outports map to the default sender and receiver services.

1. From the C Code tab, under Code Interface, select Component Interface. The Code Mappings editor pane opens.

2. In the Code Mappings editor, select the Inports tab. The model contains two Bus Element Inport blocks, InBus.NVM and InBus.u. Verify that, for both inports, the Receiver Service column is set to Dictionary default: ReceiverOutsideExe.

3. From the Outports tab, verify that both of the Bus Element Outport blocks, OutBus.NVM and OutBus.y, use the Dictionary default: SenderOutsideExe sender service.

Generate Code

Verify that the generated code uses the Outside Execution communication method.

1. Generate the code.

slbuild(model);
### Starting build procedure for: ComponentDeploymentFcn
### Successful completion of code generation for: ComponentDeploymentFcn

Build Summary

Top model targets:

Model                   Build Reason                                         Status           Build Duration
============================================================================================================
ComponentDeploymentFcn  Information cache folder or artifacts were missing.  Code generated.  0h 0m 13.979s 

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 15.514s

2. Inspect the services.h file.

/* receiver services */
extern const real_T * get_CD_integrator_input(void);
extern const real_T * get_CD_initialize_input(void);

/* sender services */
extern real_T * set_CD_accumulator_output(void);
extern real_T * set_CD_terminate_output(void);

With the Outside Execution data communication method, the code generator expects the target environment to provide a buffer for data communication. The sender and receiver function services do not need a pointer to a generated buffer; each service function takes no arguments.

In the service function names, the code generator replaces the $X token with the name of the enclosing entry-point function, CD_accumulator.

3. Inspect the CD_accumulator function in ComponentDeploymentFcn.c.

void CD_accumulator(void)
{
  const real_T *tmpIrvIRead;
  int32_T i;
  tmpIrvIRead = get_CD_accumulator_DataTransfer();
  for (i = 0; i < 10; i++) {
    CD_sig.delay[i] += tmpIrvIRead[i];
    (set_CD_accumulator_output())[i] = CD_param.tunable_gain * CD_sig.delay[i];
  }
}

With the Outside Execution data communication method, the generated code calls the sender service inside the for loop. The sender service populates the provided buffer or gives access to that buffer for the entry-point function to populate. The target environment reads the buffer after the entry-point function executes and uses it for the next task iteration.

Modify Code Mappings and Regenerate Code

1. Open the Code Mappings editor and navigate to the Inports tab. For each inport, change the Receiver Service column from Dictionary default: SenderOutsideExe to ReceiverDuringExe. When you select this service, the sender services use the During Execution data communication method. When using this data communication method, the code generator still enforces data concurrency safeguards by using a buffer, but generates the buffer in the code rather than expecting the buffer to be provided by the target environment. The During Execution data communication method allows services to transfer data during a task iteration.

2. Navigate to the Outports tab and map each outport to SenderDuringExe.

3. Generate the code.

slbuild(model);
### Starting build procedure for: ComponentDeploymentFcn
### Generated code for 'ComponentDeploymentFcn' is up to date because no structural, parameter or code replacement library changes were found.
### Successful completion of code generation for: ComponentDeploymentFcn

Build Summary

0 of 1 models built (1 models already up to date)
Build duration: 0h 0m 4.5493s

4. Inspect the CD_accumulator function in ComponentDeploymentFcn.c.

void CD_accumulator(void)
{
  real_T OutBus_y[10];
  const real_T *tmpIrvIRead;
  int32_T i;
  tmpIrvIRead = get_CD_accumulator_DataTransfer();
  for (i = 0; i < 10; i++) {
    CD_sig.delay[i] += tmpIrvIRead[i];
    OutBus_y[i] = CD_param.tunable_gain * CD_sig.delay[i];
  }

  set_CD_accumulator_output(&OutBus_y[0]);
}

With the During Execution data communication method, the generated code includes the same sender and receiver services as before, but these services can now execute during task iterations. The code generator generates a data buffer, OutBus_y, in the code. The generated code populates this buffer inside the for loop, then sends this buffer through the sender service after the for loop. This means that the sender service is called only once during the function execution.

5. Inspect the services.h file.

/* receiver services */
extern void get_CD_integrator_input(real_T *const rty_InBus_u_value);
extern void get_CD_initialize_input(real_T *const rty_InBus_NVM_value);

/* sender services */
extern void set_CD_accumulator_output(const real_T *const rtu_OutBus_y);
extern void set_CD_terminate_output(const real_T *const rtu_OutBus_NVM);

The generated sender and receiver services each take a pointer to a buffer in the generated code as an argument.

Related Examples

More About