How to get multiple (reference) models using the same c-code (RAM instance) variables during simulation.

I am struggling to setup a model that uses a reference model such that when they call c-code, they are accessing the same RAM (variable instances). The hierarchy is as follows:
In both "main_model" and "function_model" the Simulation Target is set to use "interface.[ch]", which very simply contains an array of 4 structures to allow both global and accessor functions for access. The header is as follows:
typedef struct
{
bool enabled;
uint32_t value;
} counter_t;
counter_t counter_list[4];
#define COUNTER_0 ((counter_t *)&(counter_list[0]))
#define COUNTER_1 ((counter_t *)&(counter_list[1]))
#define COUNTER_2 ((counter_t *)&(counter_list[2]))
#define COUNTER_3 ((counter_t *)&(counter_list[3]))
void initialize(void);
void counter_enable(counter_t *ptr);
void counter_disable(counter_t *ptr);
uint32_t counter_get_current(counter_t *ptr);
void counter_reset(counter_t *ptr);
I do understand in regards to C-code, choose either the global access or accessor functions, however, this scenerio is setup to mimic that of a hardware and firmware relationship special function register (SFR) access to something like an input compare using vendor supplied packages (such as NXP or STM) and maintain the call footprint for code generation.
The problem is when this setup is run, the "main_model" and the "function_model" each have their own internal values for "counter_list" rather than sharing a single instance of them. The "main_model" will initialize the counter value to 100 and the "function_model" increments by 1 per function call (occuring every 0.1 seconds). Looking at the values during simulation from both the "main_model" and "function_model" the following is observed:
The expectation would be that they both have the same value, starting at 100 and incrementing up to 200 over the 10 seconds. Is this possible? If so, how what am I missing? or help point me to the proper documentation (I haven't been able to find this in the user guide... yet). I've also attached the project and all files (2019b). Appreciate any guidance, thanks!

7 Comments

I haven't looked at your setup code, but I would note this this code
#define COUNTER_0 ((counter_t *)&(counter_list[0]))
#define COUNTER_1 ((counter_t *)&(counter_list[1]))
#define COUNTER_2 ((counter_t *)&(counter_list[2]))
#define COUNTER_3 ((counter_t *)&(counter_list[3]))
is basically the convoluted equivalent of this code
#define COUNTER_0 counter_list
#define COUNTER_1 (counter_list+1)
#define COUNTER_2 (counter_list+2)
#define COUNTER_3 (counter_list+3)
I am reluctant to open a zip file. Can you post relevant parts of code that shows where counter_list lives at the top level, and how the function(s) are called and with what inputs?
interface.h
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef INTERFACE_H
#define INTERFACE_H
#include <stdint.h>
#include <stdbool.h>
typedef struct
{
bool enabled;
uint32_t value;
} counter_t;
counter_t counter_list[4];
#define COUNTER_0 ((counter_t *)&(counter_list[0]))
#define COUNTER_1 ((counter_t *)&(counter_list[1]))
#define COUNTER_2 ((counter_t *)&(counter_list[2]))
#define COUNTER_3 ((counter_t *)&(counter_list[3]))
void initialize(void);
void counter_enable(counter_t *ptr);
void counter_disable(counter_t *ptr);
uint32_t counter_get_current(counter_t *ptr);
void counter_reset(counter_t *ptr);
#endif // INTERFACE_H
#ifdef __cplusplus
}
#endif
interface.c
#include <string.h>
#include "interface.h"
void initialize(void)
{
memset(&counter_list, 0, sizeof(counter_list));
}
void counter_enable(counter_t *ptr)
{
if (NULL != ptr)
{
ptr->enabled = true;
}
}
void counter_disable(counter_t *ptr)
{
if (NULL != ptr)
{
ptr->enabled = false;
}
}
uint32_t counter_get_current(counter_t *ptr)
{
if (NULL != ptr)
{
return (ptr->value);
}
else
{
return (0);
}
}
void counter_reset(counter_t *ptr)
{
if (NULL != ptr)
{
ptr->value = 0;
}
}
"Target Simulation" setup for both models (they are the same):
I hope that gets everything for you to see. Thank you for having a look, I appreciate it!
I don't see how the functions are being called. Do you have multiple source files that are including interface.h? Where is the code that is calling these functions?
They are being called from charts in the models themsleves. The "main_model",
where the chart is,
This will just force the value to 100 and then monitor the counter value. Meanwhile, the "function_model" is a reference model and called per the function call block every 0.1 seconds. The "function_model" then,
where the chart is,
This is just incrementing the counters value and then returning it for comparison. That comparison is as follows,
and why I don't believe they are sharing the RAM value.
So main_model and function_model are two different s-functions? That is, you have two different sets of source code that include interface.h, and these two different sets of source code inlude interface.h? If that is the case, then yes the s-functions do not share anything. You would have to set up communication between them at the model level (e.g., have main_model feed function_model the starting value).
Also, worth noting, the chart Action Language is set to C. Further, if I modify the model by moving the contents of the reference model into the main model and execute the results are as follows,
(no longer a reference)

Sign in to comment.

 Accepted Answer

I was able to get this working. It wasn't explicitly in the reference manual, but I was able to draw the resolve from some lines of an example. In a nutshell, all the variables are moved internal to the code module (i.e. into the source) and declared statically. The source module then becomes as follows:
interface.h
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef INTERFACE_H
#define INTERFACE_H
#include <stdint.h>
#include <stdbool.h>
typedef struct
{
bool enabled;
uint32_t value;
} counter_t;
#define COUNTER_0 counter_object(0)
#define COUNTER_1 counter_object(1)
#define COUNTER_2 counter_object(2)
#define COUNTER_3 counter_object(3)
extern void initialize(void);
extern void counter_enable(counter_t *ptr);
extern void counter_disable(counter_t *ptr);
extern uint32_t counter_get_current(counter_t *ptr);
extern void counter_reset(counter_t *ptr);
extern counter_t *counter_object(uint8_t id);
#endif // INTERFACE_H
#ifdef __cplusplus
}
#endif
interface.c
#include <string.h>
#include "interface.h"
static counter_t counter_list[4];
void initialize(void)
{
memset(&counter_list, 0, sizeof(counter_list));
}
void counter_enable(counter_t *ptr)
{
if (NULL != ptr)
{
ptr->enabled = true;
}
}
void counter_disable(counter_t *ptr)
{
if (NULL != ptr)
{
ptr->enabled = false;
}
}
uint32_t counter_get_current(counter_t *ptr)
{
if (NULL != ptr)
{
return (ptr->value);
}
else
{
return (0);
}
}
void counter_reset(counter_t *ptr)
{
if (NULL != ptr)
{
ptr->value = 0;
}
}
counter_t *counter_object(uint8_t id)
{
if (id < 4)
{
return (&(counter_list[id]));
}
else
{
return (NULL);
}
}
All the syntax in the state charts then operate identical.

More Answers (0)

Categories

Find more on Simulink Coder in Help Center and File Exchange

Products

Release

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!