How much RAM area can a program use?

Post Reply
Masaki
Posts: 12
Joined: Mon Aug 13, 2007 2:39 am
Location: Japan

How much RAM area can a program use?

Post by Masaki » Fri Mar 21, 2008 11:54 am

Hi Lubin,

My project is to build a sensor filtering and logging program.
In order to make a longing period longer, I would like to use as much RAM area as possible.

My implementation in Simulink program is to use Data Store Memory block in which I declear
an UINT16 array of size 300. When I increase the size to 325, the dsPIC hangs up.
The memory usage is investigated as follows. My CPU is 30f3013 with ROM 24k and RAM 2k.

Size = 300: Program Memory 4107bytes, Data memory 1282bytes, Max dynamic memory 766bytes.
Size = 325: Program Memory 4158bytes, Data memory 1382bytes, Max dynamic memory 666bytes.

My question here is:

1) What is a criteria to know the maximum available memory space?
2) When I increase the UINT16 array size by 325-300=25, Data memory size increases 100bytes,
where I think should be 50bytes. Is there any trick here? Maybe some Simulink programing tip?

Thanks in advance,

Masaki

LubinKerhuel
Site Admin - Expert
Posts: 616
Joined: Wed Mar 07, 2007 11:23 pm
Location: Bayonne- France
Contact:

Re: How much RAM area can a program use?

Post by LubinKerhuel » Fri Mar 21, 2008 1:09 pm

Hi Masaki,

I do not know exactly what simulink is doing in your case. It may be some Simulink tricks.

It would be easier to see the mdl file to propose tips. Could you send it (either with the forum upload function or by email if you can't upload (In the last case, tell me if I can publish it on the forum).

There is several optimization options for RTW C code generation. Some of theses optimization are very efficient to reduce code size and memory (RAM) usage.

Regards

Lubin

LubinKerhuel
Site Admin - Expert
Posts: 616
Joined: Wed Mar 07, 2007 11:23 pm
Location: Bayonne- France
Contact:

Optimizing RAM usage

Post by LubinKerhuel » Wed Mar 26, 2008 12:55 am

Hi Masaki,

I provide few tricks to optimize RAM usage.

First of all, checking the "inline parameters" greatly reduce RAM usage. (It means that all constant variables are stored inside the ROM memory rather than inside the RAM)
Menu : Simulink \ Simulaiton ==> Configuration parameters ==> Optimization ==> inline parameters checkbox
Menu : Simulink \ Simulaiton ==> Configuration parameters ==> Optimization ==> inline parameters checkbox
inline.png (10.72 KiB) Viewed 8188 times
About storing data inside a vector; I noticed that the generated code of the assignment block is not very efficient:
assignment block (Standard Simulink Library)
assignment block (Standard Simulink Library)
assignment2.png (4.71 KiB) Viewed 8188 times
Generated code (RTW Embedded Coder, Matlab 2007b):

Code: Select all

/* Assignment: '<S1>/Assignment' incorporates:
*  DataStoreRead: '<S1>/Data Store Read'
*/
for (i = 0; i < 700; i++) {
 rtb_Assignment[i] = Model8_DWork.HISTORY[i];
}

i = 0;
for (yDimIdx = 0; yDimIdx < 2; yDimIdx++) {
 rtb_Assignment[(int32_T)cg_in_0[yDimIdx] - 1L] = cg_in[i];
 i = (int16_T)((int32_T)i + 1L);
}

for (i = 0; i < 700; i++) {
 /* DataStoreWrite: '<S1>/Data Store Write' */
 Model8_DWork.HISTORY[i] = rtb_Assignment[i];
}
As you may notice, the Variable HISTORY (vector) is copied into the variable rtb_Assignment. Then modified and copied back into the
HISTORY vector. This code is slow and needs a lots of memory because during a short moment, two version of the vector ( called table in C language) are present in memory.

A better way is to not use the block Assignment. Replace this block by a very simple C function that will write into the vector at the desired location the desired value. This function will takes 2 parameters: index and value. The variable should be declared as a global variable in Simulink.
Have a look on the post viewtopic.php?f=1&p=273#p271 to see details about including C function into the model. The example given here uses a global variable which is declared in simulink.

Masaki
Posts: 12
Joined: Mon Aug 13, 2007 2:39 am
Location: Japan

Re: How much RAM area can a program use?

Post by Masaki » Sat Mar 29, 2008 3:27 am

Thanks Lubin,

I understand your techniques.

As for the first one (checking inline parameters), it increased the memory usage performance by 50%.
In other words, I can take 450 history length compared to 300 before.

For the second one (introducing C functions), I still cannot make it happen.
My C programs goes:

Code: Select all


/* Data history reading */
unsigned int ReadHistory(unsigned int index)
{
    extern volatile unsigned int *HISTORY;
    return(HISTORY[index-1]); /* 1-base indexing */
}

/* Data history logging */
void WriteHistory(unsigned int index, unsigned int value)
{
    extern volatile unsigned int *HISTORY;
    HISTORY[index-1]=value;  /* 1-base indexing */
}

I also prepared correspoinding C Function Call blocks and compiled the program without errors.
Still the downloaded code won't work, maybe getting trouble with C interfacing.
Can you tell what might be a problem?

Masaki

LubinKerhuel
Site Admin - Expert
Posts: 616
Joined: Wed Mar 07, 2007 11:23 pm
Location: Bayonne- France
Contact:

Re: How much RAM area can a program use?

Post by LubinKerhuel » Sat Mar 29, 2008 11:41 am

C code seems Ok,

Sampling time of some blocks or subsystem seems to be the problem on your model.

Any blocks with a sample time set of inf ( or set to -1, where value inf is inherited) will execute only once at the initialisation time.
Using the "Sample Time Color" option of the Port/Signal display of simulink is very helpfull to see how sample time is inherited on your model's blocks.

Lubin

malife
Expert
Posts: 56
Joined: Tue Apr 17, 2007 7:24 am
Location: Santa Cruz, CA
Contact:

Re: How much RAM area can a program use?

Post by malife » Tue May 13, 2008 1:13 am

Hello All,
So your general advise is to use inline parameters always? or just for this application?

Also, I noticed that Masaki's model was not posted, could we at least know what dsPIC is being used and at what sampling frequency and Fcy, just to have an upper bound in case someone else is using the same part?

Thanks!

Masaki
Posts: 12
Joined: Mon Aug 13, 2007 2:39 am
Location: Japan

Re: How much RAM area can a program use?

Post by Masaki » Tue May 13, 2008 4:03 am

So your general advise is to use inline parameters always? or just for this application?
This is Masaki.
My way of understanding is this:
- When you have a plenty of ROM area, chech inline parameters.
- When you don't have enough ROM area, don't check inline parameters.

In my application, the program is fairly simple but requires a large amout of RAM to keep data history.
So I used inline parameters.
Also, I noticed that Masaki's model was not posted, could we at least know what dsPIC is being used and at what sampling frequency and Fcy, just to have an upper bound in case someone else is using the same part?
I used dsPIC30F3013 which has 2kByte RAM and 24kByte ROM with Fosc=120MHz.
The program is running at 1kHz sampling rate.

Finally, I'm using this program with history length of 450.
I could not make in-line C program work correctly from some unknow reason.

Masaki

malife
Expert
Posts: 56
Joined: Tue Apr 17, 2007 7:24 am
Location: Santa Cruz, CA
Contact:

Re: How much RAM area can a program use?

Post by malife » Tue May 13, 2008 5:12 pm

Thanks for posting that information Masaki. I am sure many will find it useful.
I could not make in-line C program work correctly from some unknow reason.
When you say that you were not able to get the in-line C program to work, do you mean the C function call inside the Simulink Model. If so, I would be more than glad to help you out on how to get it to work. I would be really interested in seeing how much that can improve the performance. I still think that 450 if kind of low for a 2K RAM chip, so maybe implementing the C function call is the way to go.

Again, thanks for the info

Mariano

Masaki
Posts: 12
Joined: Mon Aug 13, 2007 2:39 am
Location: Japan

Re: How much RAM area can a program use?

Post by Masaki » Wed May 14, 2008 1:42 am

Hi Mariano,

Thanks for your comment.

My final C-code looks like this:

Code: Select all

    extern volatile unsigned int HISTORY[];

/* Data history reading */
unsigned int ReadHistory(unsigned int index)
{
	if (index < 1) index = 1;
    return(HISTORY[index-1]); /* 1-base indexing */
}

/* Data history logging */
void WriteHistory(unsigned int index, unsigned int value)
{
	if (index < 1) index = 1;
    HISTORY[index-1]=value;  /* 1-base indexing */
}
In this manner, the program can be compiled and downloaded onto a dsPIC.
As I wrote before, history size can be 900, which is almost theoretical limit for the RAM size.
But unfortunately, the program won't work correctly.

The problem was:
- The program seems to be reading hisotory correctly.
- But it cannot write a correct value in History array in a right position.

I thought RTW's core program is interfereing with my C-function, and that this is beyond my ability.

Masaki

malife
Expert
Posts: 56
Joined: Tue Apr 17, 2007 7:24 am
Location: Santa Cruz, CA
Contact:

Re: How much RAM area can a program use?

Post by malife » Wed May 14, 2008 7:51 pm

Hello Masaki,
It's kind of hard to help you without seeing the overall model and the C-source. I understand if you can not post your model, so I will do my best to help you out from what I see.

First, if you are using the C-function call block in your model, then your functions should have the following prototypes:

uint16_T ReadHistory(uint16_T index)
void WriteHistory(uint16_T index, uint16_T value)

since that is how Lubin's code inserts the declaration in the Main file (you can actually read that out in the grayed area of the C-function call block).

Also, you should include rtwtypes.h in this C file.

If you can, try posting the generated C-Code files if you do not want to post the model, so I can go over the generated code and see if I can find what is wrong.

Hope this helps

Masaki
Posts: 12
Joined: Mon Aug 13, 2007 2:39 am
Location: Japan

Re: How much RAM area can a program use?

Post by Masaki » Thu May 15, 2008 12:50 pm

Hi Mariano,

Sorry for my not positing the model file. But all of the C source code is posted in my perevious writing.
First, if you are using the C-function call block in your model, then your functions should have the following prototypes:

uint16_T ReadHistory(uint16_T index)
void WriteHistory(uint16_T index, uint16_T value)
I have confirmed almost the same definition:
extern uint16_T ReadHistory(uint16_T u1);
extern void WriteHistory(uint16_T u1, uint16_T u2);
Also, you should include rtwtypes.h in this C file.
I didn't include it in my C source file, because there wasn't no error.
If you can, try posting the generated C-Code files if you do not want to post the model, so I can go over the generated code and see if I can find what is wrong.
OK, I try.
I picked the biggest C source file from the three. Is this right?

Hoping this big post won't screw up the system,

Masaki

Code: Select all

/*
 * File: testanemo9a.c
 *
 * Real-Time Workshop code generated for Simulink model testanemo9a.
 *
 * Model version                        : 1.57
 * Real-Time Workshop file version      : 7.0  (R2007b)  02-Aug-2007
 * Real-Time Workshop file generated on : Sun Apr 13 10:48:00 2008
 * TLC version                          : 7.0 (Jul 26 2007)
 * C source code generated on           : Sun Apr 13 10:48:01 2008
 *--------------------------------------------------------------
 *   Embedded Coder for Microchip dsPIC family.                 |
 *   Generate .c and .h files from your Matlab/simulink model   |
 *   and compile the diagram to .hex and .coff file that can be |
 *   downloaded directly into the microcontroller               |
 *                                                              |
 * 
 * 
 *                                                              |
 *   Written by Lubin KERHUEL -  http://www.kerhuel.eu          |
 *  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
 *   Version 0.95ba                            07-Feb-2008      |
 *   For Matlab 7.5             R2007b                          |
 *--------------------------------------------------------------
 */

#include "testanemo9a.h"
#include "testanemo9a_private.h"

/* Exported block states */
uint16_T HISTORY[900];                 /* '<Root>/Data Store Memory' */

/* Block signals (auto storage) */
BlockIO_testanemo9a testanemo9a_B;

/* Block states (auto storage) */
D_Work_testanemo9a testanemo9a_DWork;

/* Real-time model */
RT_MODEL_testanemo9a testanemo9a_M_;
RT_MODEL_testanemo9a *testanemo9a_M = &testanemo9a_M_;
static void rate_monotonic_scheduler(void);

/* Set which subrates need to run this base step (base rate always runs).
 * This function must be called prior to calling the model step function
 * in order to "remember" which rates need to run this base step.  The
 * buffering of events allows for overlapping preemption.
 */
void testanemo9a_SetEventsForThisBaseStep(boolean_T *eventFlags)
{
  /* Task runs when its counter is zero, computed via rtmStepTask macro */
  eventFlags[1] = ((boolean_T)rtmStepTask(testanemo9a_M, 1));
}

/* This function updates active task flag for each subrate
 * and rate transition flags for tasks that exchagne data.
 * The function assumes rate-monotonic multitasking scheduler.
 * The function must be called at model base rate so that
 * the generated code self-manages all its subrates and rate
 * transition flags.
 */
static void rate_monotonic_scheduler(void)
{
  /* To ensure a safe and deterministic data transfer between two rates,
   * data is transferred at the priority of a fast task and the frequency
   * of the slow task.  The following flags indicate when the data transfer
   * happens.  That is, a rate interaction flag is set true when both rates
   * will run, and false otherwise.
   */

  /* tid 0 shares data with slower tid rate: 1 */
  testanemo9a_M->Timing.RateInteraction.TID0_1 =
    (testanemo9a_M->Timing.TaskCounters.TID[1] == 0);

  /* Compute which subrates run during the next base time step.  Subrates
   * are an integer multiple of the base rate counter.  Therefore, the subtask
   * counter is reset when it reaches its limit (zero means run).
   */
  if (++testanemo9a_M->Timing.TaskCounters.TID[1] == 3000) {/* Sample time: [3.0s, 0.0s] */
    testanemo9a_M->Timing.TaskCounters.TID[1] = 0;
  }
}

/* Model step function for TID0 */
void testanemo9a_step0(void)           /* Sample time: [0.001s, 0.0s] */
{
  /* local block i/o variables */
  real_T rtb_Add3;
  real_T rtb_Divide;
  real_T rtb_DiscreteFilter1f001Hz;
  uint16_T rtb_Add1;
  uint16_T rtb_Add2;

  {                                    /* Sample time: [0.001s, 0.0s] */
    rate_monotonic_scheduler();
  }

  {
    int16_T s4_iter;

    /* S-Function "ADC" Block: <Root>/ADC Input */
    testanemo9a_B.ADCInput_o1 = ADCBUF0;
    testanemo9a_B.ADCInput_o2 = ADCBUF1;
    testanemo9a_B.ADCInput_o3 = ADCBUF2;

    /* DataTypeConversion: '<Root>/Data Type Conversion4' */
    rtb_DiscreteFilter1f001Hz = (real_T)testanemo9a_B.ADCInput_o2;

    /* Sum: '<Root>/Add3' incorporates:
     *  DataTypeConversion: '<Root>/Data Type Conversion3'
     */
    rtb_Add3 = (real_T)testanemo9a_B.ADCInput_o1 - rtb_DiscreteFilter1f001Hz;

    /* DataTypeConversion: '<Root>/Data Type Conversion5' */
    rtb_DiscreteFilter1f001Hz = (real_T)testanemo9a_B.ADCInput_o3;

    /* Product: '<Root>/Divide' incorporates:
     *  Constant: '<Root>/Constant3'
     *  Saturate: '<Root>/Saturation'
     */
    rtb_Divide = rtb_Add3 * 600.0 / rt_SATURATE(rtb_DiscreteFilter1f001Hz, 1.0,
      65535.0);

    /* DiscreteFilter: '<Root>/Discrete Filter f=1Hz' */
    rtb_DiscreteFilter1f001Hz = 3.1317539583613544E-003*rtb_Divide;
    rtb_DiscreteFilter1f001Hz += 6.2438921510112842E-003*
      testanemo9a_DWork.DiscreteFilterf1Hz_DSTATE;

    /* Sum: '<Root>/Add1' incorporates:
     *  Constant: '<Root>/Constant'
     *  Gain: '<Root>/Gain'
     */
    rtb_Add3 = fmod(floor(30.0 * rtb_DiscreteFilter1f001Hz - 32768.0), 65536.0);
    if (rtb_Add3 < 0.0) {
      rtb_Add3 += 65536.0;
    }

    rtb_Add1 = (uint16_T)rtb_Add3;

    /* DiscreteFilter: '<Root>/Discrete Filter1 f=0.01Hz' */
    rtb_DiscreteFilter1f001Hz = 3.1414939606463125E-005*rtb_Divide;
    rtb_DiscreteFilter1f001Hz += 6.2827905416065283E-005*
      testanemo9a_DWork.DiscreteFilter1f001Hz_DSTATE;

    /* Sum: '<Root>/Add2' incorporates:
     *  Constant: '<Root>/Constant2'
     *  Gain: '<Root>/Gain1'
     */
    rtb_Add3 = fmod(floor(30.0 * rtb_DiscreteFilter1f001Hz - 32768.0), 65536.0);
    if (rtb_Add3 < 0.0) {
      rtb_Add3 += 65536.0;
    }

    rtb_Add2 = (uint16_T)rtb_Add3;

    /* RateTransition: '<Root>/Rate Transition' */
    if (testanemo9a_M->Timing.RateInteraction.TID0_1) {
      testanemo9a_B.RateTransition = rtb_Add2;
    }

    /* S-Function "UART_RX" Block: <Root>/Rx Input */
    if (U1STAbits.URXDA == 1) {
      testanemo9a_B.RxInput = (unsigned char) U1RXREG;/* Use only the 8 low bytes or RxReg */
    } else {
      testanemo9a_B.RxInput = 0;
    }

    U1STAbits.OERR = 0;                /* Buffer Overflow cleared */

    /* SwitchCase: '<Root>/Switch Case' */
    switch (testanemo9a_B.RxInput) {
     case 97L:
      /* Outputs for iterator SubSystem: '<S2>/For Iterator Subsystem' incorporates:
       *  Constant: '<Root>/Constant1'
       */
      for (s4_iter = 1; s4_iter <= 900; s4_iter++) {
        /* DataTypeConversion: '<S4>/Data Type Conversion1' */
        testanemo9a_B.DataTypeConversion1 = (uint16_T)s4_iter;

        /* S-Function "dsPIC_C_function_Call" Block: <S4>/C Function Call */
        testanemo9a_B.CFunctionCall = ReadHistory
          (testanemo9a_B.DataTypeConversion1);

        /* DataTypeConversion: '<S6>/Extract Desired Bits' */
        testanemo9a_B.ExtractDesiredBits_i = (uint8_T)
          testanemo9a_B.CFunctionCall;

        /* DataTypeConversion: '<S5>/Extract Desired Bits' */
        testanemo9a_B.ExtractDesiredBits_n = (uint8_T)
          (testanemo9a_B.CFunctionCall >> 8);

        /* S-Function "UART_Tx" Block: <S4>/Tx Output */
        while (BusyUART1()) ;
        WriteUART1(testanemo9a_B.ExtractDesiredBits_i);
        while (BusyUART1()) ;
        WriteUART1(testanemo9a_B.ExtractDesiredBits_n);
      }

      /* end of Outputs for SubSystem: '<S2>/For Iterator Subsystem' */
      break;

     case 114L:
      /* DataTypeConversion: '<S8>/Extract Desired Bits' */
      testanemo9a_B.ExtractDesiredBits = (uint8_T)rtb_Add1;

      /* DataTypeConversion: '<S7>/Extract Desired Bits' */
      testanemo9a_B.ExtractDesiredBits_o = (uint8_T)(rtb_Add1 >> 8);

      /* S-Function "UART_Tx" Block: <S3>/Tx Output */
      while (BusyUART1()) ;
      WriteUART1(testanemo9a_B.ExtractDesiredBits);
      while (BusyUART1()) ;
      WriteUART1(testanemo9a_B.ExtractDesiredBits_o);
      break;
    }

    /* DiscreteFilter Block: '<Root>/Discrete Filter f=1Hz' */
    {
      testanemo9a_DWork.DiscreteFilterf1Hz_DSTATE = rtb_Divide +
        9.9373649208327730E-001*testanemo9a_DWork.DiscreteFilterf1Hz_DSTATE;
    }

    /* DiscreteFilter Block: '<Root>/Discrete Filter1 f=0.01Hz' */
    {
      testanemo9a_DWork.DiscreteFilter1f001Hz_DSTATE = rtb_Divide +
        9.9993717012078698E-001*testanemo9a_DWork.DiscreteFilter1f001Hz_DSTATE;
    }
  }
}

/* Model step function for TID1 */
void testanemo9a_step1(void)           /* Sample time: [3.0s, 0.0s] */
{
  /* S-Function "dsPIC_C_function_Call" Block: <S1>/C Function Call2 */
  WriteHistory(testanemo9a_ConstB.DataTypeConversion,
               testanemo9a_B.RateTransition);
}

void testanemo9a_step(int_T tid)
{
  switch (tid) {
   case 0 :
    testanemo9a_step0();
    break;

   case 1 :
    testanemo9a_step1();
    break;

   default :
    break;
  }
}

/* Model initialize function */
void testanemo9a_initialize(boolean_T firstTime)
{
  (void)firstTime;

  /* Registration code */
  /* initialize real-time model */
  (void) memset((char_T *)testanemo9a_M,0,
                sizeof(RT_MODEL_testanemo9a));

  /* block I/O */
  (void) memset(((void *) &testanemo9a_B),0,
                sizeof(BlockIO_testanemo9a));

  /* states (dwork) */
  {
    real_T *dwork_ptr = (real_T *) &testanemo9a_DWork.DiscreteFilterf1Hz_DSTATE;
    dwork_ptr[0] = 0.0;
    dwork_ptr[1] = 0.0;
  }

  /* exported global states */
  (void) memset(&HISTORY,0,
                900*sizeof(uint16_T));

  {
    int16_T i;

    /* S-Function "dsPIC_MASTER" initialization Block: <Root>/Master */
    /* 0 testfcy 	*/
    /*  3.0E+007	*/
    /* CONFIG TIMER 1 for scheduling steps 	*/
    ConfigIntTimer1(T1_INT_PRIOR_0 & T1_INT_OFF);
    T1CON = 0x8000 ;                   /* T1_PS_1_1	*/
    PR1 = 30000;

    /* Configuration TRIS */
    TRISB = 65023;

    /* Configuration ADCHS */
    ADPCFG = 512;

    /* S-Function "dsPIC_UART_config" initialization Block: <Root>/UART Configuration */
    /* set priority */
    _U1RXIP = 0x0007 & 1;
    _U1TXIP = 0x0007 & 1;

    /* enable/disable interrupt */
    _U1RXIE = 0;
    _U1TXIE = 0;
    U1MODE = 0x8080 + 1024;
    U1STA = 0x0 + 32768 + 1024;
    U1BRG = 15;

    /* S-Function "dsPIC_ADC" initialization Block: <Root>/ADC Input */
    /* Initialise ADC converter */
    /* 0 mean each 1 conversion */
#define NoSamplesADC                   2
#define ADCSval                        39
#define SAMCval                        (1 << 8)
#define OutFormatBitsval               (0 << 8)
#define VoltRef                        (0 << 13)

    /* Use internal counter Trigger, continuous simulatenous sampling */
    ADCON1 = 0x00E4 | (1 << 10)| OutFormatBitsval;
    ADCON2 = 0x0400 | (NoSamplesADC << 2) | VoltRef;
    ADCSSL = 14;
    ADCON3 = (ADCSval | SAMCval) & 0xff7f;
    ADCHS = 0x0000;
    IPC2 = (IPC2 | (6 << 12));         /*Interrupt Priority : 6*/
    IFS0bits.ADIF = 0;

    /* _ADIE = 1; */
    /* 1 sample/output-Step ; Do not need interrupt so do not enable it. */
    /* Clear Off Any Interrupt Due To Configuration */
    /* Turn on ADC Module */
    ADCON1bits.ADON= 1;
    for (i = 0; i < 900; i++) {
      /* Start for DataStoreMemory: '<Root>/Data Store Memory' */
      HISTORY[i] = testanemo9a_ConstP.DataStoreMemory_Ini[i];
    }
  }

  /* S-Function "dsPIC_C_function_Call" Block: <S1>/C Function Call */
  WriteHistory(1U,testanemo9a_ConstB.DataTypeConversion);
}

/* File trailer for Real-Time Workshop generated code.
 *
 * [EOF]
 */

malife
Expert
Posts: 56
Joined: Tue Apr 17, 2007 7:24 am
Location: Santa Cruz, CA
Contact:

Re: How much RAM area can a program use?

Post by malife » Thu May 15, 2008 6:25 pm

Masaki,
The only thing that I noticed from your code is that WriteHistory is called every three seconds, which seems kind a long considering your main sample rate is 0.001, but this by no means implies it is wrong. Also, you did not post the H-files, but in your function declarations (i.e. you C file) you SHOULD NOT include the extern keyword. Lubin does so, so the code nows that your functions are in another file. rtwtypes.h allows you to use the real time workshop types like uint8_T, uint16_T and so on.

It is quite hard for me to help you any further without seeing your model. Sorry I could not be of any further help.

LubinKerhuel
Site Admin - Expert
Posts: 616
Joined: Wed Mar 07, 2007 11:23 pm
Location: Bayonne- France
Contact:

Re: How much RAM area can a program use?

Post by LubinKerhuel » Fri May 16, 2008 12:21 am

Hi Mariano, Hi Masaki,
malife wrote:in your function declarations (i.e. you C file) you SHOULD NOT include the extern keyword
If you declare the variable (in the sense that you want the C file to provide a memory place to store it) in the C file, you are true (i.e. needs to remove extern keyword).
However, there is the possibility to declare the variable in simulink using the block "Data Store memory" (from simulink standard library) and defining it as "global". In this way, the variable can be used easily anywhere in the simulink file with the "Data Store Read" or "Data Store Write" block ; ans can be used in the C file if you precise (with "extern") that the variable is being declared in another c file.

It's a good point to use rtwtypes.h to use exactly the same declaration keyword ! Thanks for that trick.

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest