Different Storage Classes In MATLAB Simulink

Different Storage Classes In MATLAB Simulink

Hello guys, welcome back to our blog. In this article, I will discuss the different storage classes in MATLAB Simulink and use cases of storage classes.

Ask questions if you have any electrical,  electronics, or computer science doubts. You can also catch me on Instagram – CS Electrical & Electronics

Different Storage Classes In MATLAB Simulink

Simulink, a model-based design tool from MathWorks, is widely used in control system development, embedded systems, automotive software development, and many other engineering domains. When generating code using Simulink Coder or Embedded Coder, the way in which model signals, parameters, and states are stored and accessed in the generated C code becomes crucial, not only for performance but also for integration with legacy systems, real-time execution, memory optimization, and compliance with safety standards.

One of the essential mechanisms to control the memory mapping of variables in the generated code is the use of Storage Classes. Storage Classes in Simulink define how variables are declared, defined, and accessed in the target C code. This is a powerful feature that allows engineers to influence the structure of the generated code, ensuring that it aligns with coding standards, facilitates reuse, and meets system architecture constraints.

When designing embedded systems, especially for automotive or aerospace applications, engineers often work in teams with different roles. One team might develop plant models, while another writes embedded software that runs on a microcontroller. In such cases, it is important that the generated code integrates well with hand-written or legacy C code. This is where selecting the appropriate storage class becomes critical — whether a signal should be local, global, extern, or even volatile can dramatically affect how the code is compiled and executed on target hardware.

Furthermore, using storage classes appropriately ensures better maintainability and testability of the generated code. For example, tuning parameters at runtime, interfacing with hardware registers, and conforming to software architecture standards like AUTOSAR or ISO 26262 all benefit from a well-thought-out storage class configuration. In real-time systems, the correct use of storage classes can even impact timing behavior and determinism, making it a fundamental concept for embedded developers working with Simulink.

This article explores each of the common storage classes used in Simulink in detail. Whether you’re generating code for deployment or simulation, understanding these storage classes will give you greater control over the structure, safety, and efficiency of your code.

🔎 Detailed Explanation of Common Simulink Storage Classes

Let’s now explore each storage class, understand what it does, where it’s used, and its impact on generated code.

01. Auto

Auto is the default storage class. When a signal, state, or parameter is assigned the ‘Auto’ storage class, Simulink and the code generation tool determine the most appropriate way to declare and define the variable based on usage and context.

Use Case: Ideal for quick prototyping and testing models without focusing on code integration. Best suited when the internal implementation of code is not important to the user.

Generated Code Behavior: Depending on signal scope and data type, Auto storage class variables could become:

  • Local variables inside functions
  • Static file-scope variables
  • Function arguments

Advantages:

  • Simplifies development — no manual configuration required.
  • Good for simulation and rapid iteration.

Limitations: Lack of control over memory placement. Harder to integrate with external code or test the generated code in isolation.

Example:

In the generated .c file, a signal may appear like:

real_T mySignal;

or inside a function:

void myFunction(void) {
   real_T temp = 0;
}

02. ExportedGlobal

The variable is declared in a C source file (.c) and defined in a header file (.h). This allows the variable to be globally accessible across different translation units (C files).

Use Case: Used when the signal or parameter must be accessed from multiple modules. Ideal for inter-module communication or test harnesses.

Generated Code Behavior:

  • The variable is declared in the header file:
extern real_T globalSignal;
  • And defined in the source file:
real_T globalSignal;

Advantages:

  • Enables global access.
  • Useful in shared memory or global control logic.

Limitations:

  • Risk of data corruption if not protected (no access control).
  • Difficult to manage in large systems without strict naming conventions.

Example:

Multiple .c files can use the variable without defining it again:

// main.c
#include "model.h"
globalSignal = 25.0;

03. ImportedExtern

Specifies that the variable is declared as extern in the model, but it is defined elsewhere, i.e., outside the generated code, typically in manually written C code or another compiled library.

Use Case: Ideal for integration with legacy or third-party code. Useful when the model uses global variables maintained by another software module.

Generated Code Behavior:

  • Only declares:
extern real_T legacyVar;

Advantages:

  • Clean separation between generated and handwritten code.
  • Ensures no duplication or redefinition.

Limitations:

  • Mismanagement can lead to linker errors if the definition is missing.
  • No memory is allocated — must be handled externally.

Example:

// model.c (generated)
extern real_T legacyVar;
// legacy.c (user-defined)
real_T legacyVar = 12.5;

04. ImportedExternPointer

Similar to ImportedExtern, but instead of referencing a variable, it references a pointer to a variable. This is particularly useful when data must be passed by reference, such as during pointer-based hardware access or shared memory systems.

Use Case: Common in device drivers, shared memory systems, and hardware abstraction layers.

Generated Code Behavior:

extern real_T *deviceStatusPtr;

Advantages:

  • Flexible — allows redirection to different memory areas.
  • Facilitates memory-mapped I/O.

Limitations:

  • Dereferencing must be managed carefully to avoid runtime crashes.
  • Debugging is more complex due to pointer indirection.

Example:

// model.c
extern real_T *deviceStatusPtr;
...
*deviceStatusPtr = 100.0;
// hardware.c
real_T status;
real_T *deviceStatusPtr = &status;

05. FileScope

The variable is declared as static in the generated .c file. It is private to the file and cannot be accessed outside of it.

Use Case: Good for variables used only internally within a module. Enhances encapsulation and prevents namespace pollution.

Generated Code Behavior:

static real_T localSignal;

Advantages:

  • Keeps variables hidden from other modules.
  • Promotes modular code.

Limitations:

  • Cannot access from test code or external modules.
  • Makes integration with legacy systems harder.

Example:

  • Only the .c file containing the declaration can use the variable.

06. Define

The variable is turned into a #define macro, meaning it is replaced by the preprocessor before compilation.

Use Case: Used for constants or tunable parameters that should not occupy memory. Ideal for compile-time configuration.

Generated Code Behavior:

#define GAIN_VALUE (2.5)

Advantages:

  • No runtime memory required.
  • Extremely fast to use in computations.

Limitations:

  • Cannot be changed at runtime.
  • No type checking.

Example:

output = GAIN_VALUE * input;

07. Struct

Signals, states, or parameters are grouped into a struct (structure). Useful for packaging related variables together.

Use Case: Useful for hierarchical data organization, e.g., grouping subsystem data or configuration parameters.

Generated Code Behavior:

typedef struct {
   real_T signal1;
   real_T signal2;
} MyStruct;

MyStruct modelData;

Advantages:

  • Better namespace control.
  • Cleaner, readable code.

Limitations:

  • Requires dot-notation (modelData.signal1).
  • Pointers to structures must be managed carefully.

Example:

modelData.signal1 = 10.0;

08. Bitfield

Creates bitfields inside a struct to optimize memory usage, especially when variables are limited to a few bits (e.g., flags, enums).

Use Case: Critical in memory-constrained systems, such as automotive ECUs or microcontrollers.

Generated Code Behavior:

typedef struct {
   uint8_T flag1:1;
   uint8_T flag2:2;
} BitfieldStruct;

Advantages:

  • Reduces RAM/ROM usage.
  • Useful for flags, status bits, and modes.

Limitations:

  • Platform-dependent behavior (bitfield ordering may vary).
  • Access speed might be slower on some architectures.

Example:

BitfieldStruct status;
status.flag1 = 1;

09. Volatile

Tells the compiler not to optimize accesses to the variable. This ensures that every read/write is executed exactly as written in the code.

Use Case: Critical for real-time hardware I/O, where memory-mapped registers change outside of software control (e.g., ADCs, timers).

Generated Code Behavior:

volatile uint16_T adcValue;

Advantages:

  • Ensures real-time behavior.
  • Required for I/O devices and interrupt-driven variables.

Limitations:

  • Slower access times due to suppressed optimizations.
  • Should be used sparingly.

Example:

while (adcValue < THRESHOLD) {
    // Wait until ADC value exceeds threshold
}
Different Storage Classes In MATLAB Simulink

🧾 Conclusion

Understanding and applying the right storage class in Simulink can greatly enhance the usability, performance, and integration of your generated code. Whether you’re developing a complex automotive controller or a simple embedded system, proper use of storage classes ensures better memory management, safer code, and smoother collaboration with other software components.

By using Auto for simple simulations, ExportedGlobal or ImportedExtern for module-level communication, Volatile for hardware I/O, and Struct or Bitfield for optimized memory organization, you can tailor your code to meet rigorous engineering standards.

This was about “Different Storage Classes In MATLAB Simulink”. Thank you for reading.

Also, read:

About The Author

Share Now