cancel
Showing results for 
Search instead for 
Did you mean: 

How to declare a struct in CCM

jean
Senior
Posted on December 22, 2016 at 18:10

Hello,

I work on a STM32F4 and I want use the CCM memory to declare my structures.

For example I want this kind of structure to be always declared in the CCM memory:

typedef struct Assign_Pot Assign_Pot;

struct Assign_Pot {

uint8_t variable1;

uint8_t variable2;

uint16_t variable3;

};

Assign_Pot* Assign_Tab[100];

I've been looking across the forum but I can't find a solution that works.

If I declare my structure like this:

struct Assign_Pot {

uint8_t variable1;

uint8_t variable2;

uint16_t variable3;

} __attribute__ ((section('.ccm')));

I have the warning: 'section' attribute does not apply to types [-Wattributes]

And the structure is not created in the CCM

Do you have some experience to share with this problem?

Thanks a lot, have a great day!

Note: this post was migrated and contained many threaded conversations, some content may be missing.
12 REPLIES 12
Posted on December 23, 2016 at 01:25

The warning clearly tells you what's the problem: you can use the section attribute only when you declare variables, not when you create types. In other words, declaring a type (a struct tag here) only tells the compiler, what the variable looks like, not where variables of that type are going to be located, nor how many of them will be defined. OTOH if you define variable of whatever type, you tell the compiler to allocate a space in memory for that variable, so that's the right time to tell the compiler where exactly to allocate that space (normally you tell nothing and the compiler allocates it into its default space).

Nor does a pointer - either a pointer variable or a pointer type - define, where is the pointed-to object allocated, so defining pointers is not a way to tell the allocation of the pointed-to objects (you can allocate a pointer variable itself, though)

Declare a variable of struct Assign_Pot type and give it a section attribute.

JW

Seb
ST Employee
Posted on December 23, 2016 at 03:42

Normally the default linker configuration file (say IAR) would put the stack in the CCM if available.

As such, all local variables (struct based) declared inside a function should end up in the CCM, so developers benefits from it right away.

The main difference between main RAM and CCM is when lots of DMA transfer is going on.

DMA will take CPU cycles to read/write the main RAM. If using USB HS, SPI DMA, ADC/DAC DMA, then frequently accessed variables (or pointers) might be worth going to the CCM memory. Naturally, DMA accessed variables shouldn't be moved in the CCM. The lower the core frequency (on battery budget?) the more of a difference it could make.

Hope this help!

jean
Senior
Posted on December 23, 2016 at 11:31

Thanks a lot for all your tips!

, If I declare myvariable of

struct Assign_Pot

type and give it a section attribute, for example:

Assign_Pot* Assign_Tab[100] __attribute__ ((section('.ccm')));

It will only declare the 100

pointer in the CCM, not all the variables inside the structure, isn't it?

, how can be sure that my default linker configuration file put all my 'static' or 'global' variables end up in CCM memory? For your interest you can find attached the linker file I made. In my code, only the variables declared with

__attribute__ ((section('.ccm'))); are going into the CCM.

________________

Attachments :

cutom_link.ld.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hz1Z&d=%2Fa%2F0X0000000bFM%2FtpDumIzm66M.y_H08VP2Os_FgbmFISqytecR4tOBk7I&asPdf=false
Seb
ST Employee
Posted on December 23, 2016 at 11:44

 ,

 ,

I'm an IAR toolchain user, in IAR there is a linker config file *.lnk which describes the various memory segments and name them.

To force a particular source code portion to put their code or variables in a specific segment, I use a ♯ pragma ,

Each compiler and linker have their own method to get the job done, this is where digging the doc becomes handy.

Posted on December 23, 2016 at 12:31

Thank you. I use Coocox together with GNU Tools ARM Embedded, but it seems that I can't use 

♯ pragma (I found this doc 

http://www.st.com/content/ccc/resource/technical/document/application_note/bb/09/ca/83/14/e9/44/c5/DM00083249.pdf/files/DM00083249.pdf/jcr:content/translations/en.DM00083249.pdf

 )
Posted on December 23, 2016 at 13:39

 ,

 ,

If I declare my ,variable of

struct Assign_Pot

type and give it a section attribute, for example:

Assign_Pot* Assign_Tab[100]

__attribute__ ((section('.ccm'))),

It will only declare the 100 ,

pointer in the CCM, not all the variables inside the structure, isn't it?

Yes, but this is basic C, nothing STM- or gcc-specific. By defining a pointer (or, here, an array of pointers) you tell the compiler to allocate space for those pointers, not for the pointed-to objects.

how can be sure that my default linker configuration file put all my 'static' or 'global' variables end up in CCM memory? For your interest you can find attached the linker file I made. In my code, only the variables declared with ,

__attribute__ ((section('.ccm'))),

are going into the CCM.

Modify the linker script so that both .data and .bss output sections are placed into the ram1 region (in the same way as .ccm output section). The relevant part of GNU linker documentation is

https://sourceware.org/binutils/docs/ld/Output-Section-Description.html ♯ Output-Section-Description

.

JW

Posted on December 23, 2016 at 14:22

Thanks a lot!

Do you think it's possible to set that 

.data and .bss output sections are placed into the ram and ram1 region ? For example when the 

ram1 is full, the other variables will be automatically placed in the ram. Because I don't want to only use the ram1 (CCM) of course.

Something like this in my linker file:

// variables with __attribute__ ((section('.ccm'))); will always be placed into the ram1 memory

.ccm (NOLOAD) :

 

{

 

. = ALIGN(4);

 

*(.ccm)

 

*(.ccm.*)

 

. = ALIGN(4);

 

} > ram1

// the other variables will be placed in both ram and ram1 memory

.data : AT (_etext)

 

{

 

_sdata = .;

 

*(.data .data.*)

 

. = ALIGN(4);

 

_edata = . ;

 

} > ram > ram1

 

.bss (NOLOAD) :

 

{

 

_sbss = . ;

 

*(.bss .bss.*)

 

*(COMMON)

 

. = ALIGN(4);

 

_ebss = . ;

 

} > ram > ram1

Sorry for all these beginners questions

Posted on December 23, 2016 at 14:36

The GNU linker isn't going to automatically spill or allocate memory across discontinuous memory regions, you have to micro-manage that at a function/object/section level. Or write a script.

Alternatively you could have both regions on a heap, and dynamically allocate.

On the F4 the CCM can't be used for DMA buffers, or code execution.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 23, 2016 at 15:56

Thanks!

Now I configured my .data to always be located in the ccm, it's a good thing.

But my main problem maybe remains the same: to be able to declare my struct variables into CCM.

I'm not sure that, by declaring ma .data in ccm, my struct variables will be in the CCM, for e.g. when I do:

struct Assign_Pot {

 

   uint8_t variable1;

 

   uint8_t variable2;

 

   uint16_t variable3;

 

};

Assign_Pot* Assign_Tab[100];