cancel
Showing results for 
Search instead for 
Did you mean: 

Make use of the 64k CCM

jorgen2
Associate
Posted on January 11, 2012 at 11:08

I've spent (too many) hours trying to figure out how to use the CCM for something useful.

And with useful I mean easy access from my code written in C. I use GNU GCC, etc

(the Yagarto toolchain).

At first I thought that putting some variable, array into a specified section, let's call it .ccm, (and of course the appropriate lines in the linker script) would be the solution.

For example:

uint8_t test[1024] __attribute__ ((section(''.cmm'')));

Well, it works... Kind of... :\

I compiles and links nicely. Checking the memory map/dump of the generated ELF-file I see that the array is located @0x1000 0000

However, producing a binary image produces a LARGE 100+MB file. Doing a hex-file makes it smaller but will not load into ST-Link Utility (file too large to fit, it says)

Now... That's probably due to the gap between 0x1000 FFFF and 0x2000 0000

The part in the linker script is something like (under the SECTIONS part)

.ccm :

{

  .= ALING(4);

  *(.ccm)

  .= ALIGN(4);

} >CCMRAM

And CCM is defined under MEMORY as

  CCRAM    (rwx)      : ORIGIN = 0x10000000, LENGTH = 64K

Also tried to use NOLOAD to make it NOBITS instead of PROGBITS but it still takes

up space in the binary or hex-file. Removing the section with objcopy and --remove-section .ccm does nothing to help either.

Isn't there anyway of makeing your own section behave like the .bss section and not

taking space in the image?

I hope I make sense with my problem/question.

Best regards // J�rgen

#stm32-stm32f4-ccm-linker-section #gcc-linker-ccm
44 REPLIES 44
Posted on June 20, 2013 at 23:09

It's not a silver bullet.

I could describe the joys of virtual memory, where you have to pin and lock physical memory before you can DMA to it, or writing kernel mode drivers. If you even get an IRQL_NOT_LESS_OR_EQUAL blue screen, it's because some fool tried to DMA into, or access, a user memory context that switched out before the transfer completed/started.

Generally it's inadvisable to DMA on the stack, due to it's transient nature, and the potential for the DMA controller settings to out live the current activity. Much hilarity ensues when the stack gets trashed by a lingering transfer.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
alexandr
Associate II
Posted on June 21, 2013 at 00:31

I think you have another troubles with SDIO, because I suceccfully used FatFs + SDIO in 2 projects, where IRAM2 (CCM) was set by default as the main RAM.

Huge IRAM1 was used only as a buffer for SD-card writing and some variables.

Also I put ff,c,fatfs_drv.c, stm32f4sd.c into IRAM1.

Bill Lewis
Associate III
Posted on June 21, 2013 at 03:03

That's exactly the problem I had.  Buffers were in CCM passed to the SD read/write functions.

alexandr
Associate II
Posted on June 21, 2013 at 09:34

Buffers you MUST put at big RAM, but stack and other variables, not used by DMA - in CCM.

The simplest way in KEil is to use IRAM2 (CCM) by default, buffers should be at separate file, and in this file' properties - say to use IRAM1.

How to do this in GCC - I don't know.

totti001
Associate II
Posted on October 01, 2013 at 14:34

I try to use ccm for STemWIN gui stack.

I use CoIDE with this linker script.

OUTPUT_FORMAT (''elf32-littlearm'', ''elf32-bigarm'', ''elf32-littlearm'')
/* Internal Memory Map*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 0x00100000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
ram1 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x00010000
}
_eram = 0x20000000 + 0x00020000;
/* Section Definitions */ 
SECTIONS 
{ 
.text : 
{ 
KEEP(*(.isr_vector .isr_vector.*)) 
*(.text .text.* .gnu.linkonce.t.*) 
*(.glue_7t) *(.glue_7) 
*(.rodata .rodata* .gnu.linkonce.r.*) 
} > rom
.ARM.extab : 
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > rom
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
__exidx_end = .;
. = ALIGN(4); 
_etext = .;
_sidata = .; 
.data : AT (_etext) 
{ 
_sdata = .; 
*(.data .data.*) 
. = ALIGN(4); 
_edata = . ;
} > ram
/* .bss section which is used for uninitialized data */ 
.bss (NOLOAD) : 
{ 
_sbss = . ; 
*(.bss .bss.*) 
*(COMMON) 
. = ALIGN(4); 
_ebss = . ; 
} > ram
/* stack section */
.co_stack (NOLOAD):
{
. = ALIGN(8);
*(.co_stack .co_stack.*)
} > ram
. = ALIGN(4); 
_end = . ; 
} 
/*********************************************************************
* Portions COPYRIGHT 2013 STMicroelectronics *
* Portions SEGGER Microcontroller GmbH & Co. KG *
* Solutions for real time microcontroller applications *
**********************************************************************
* *
* (c) 1996 - 2013 SEGGER Microcontroller GmbH & Co. KG *
* *
* Internet: www.segger.com Support: support@segger.com *
* *
**********************************************************************
** emWin V5.20 - Graphical user interface for embedded applications **
All Intellectual Property rights in the Software belongs to SEGGER.
emWin is protected by international copyright laws. Knowledge of the
source code may not be used to write a similar product. This file may
only be used in accordance with the following terms:
The software has been licensed to STMicroelectronics International
N.V. a Dutch company with a Swiss branch and its headquarters in Plan-
les-Ouates, Geneva, 39 Chemin du Champ des Filles, Switzerland for the
purposes of creating libraries for ARM Cortex-M-based 32-bit microcon_
troller products commercialized by Licensee only, sublicensed and dis_
tributed under the terms and conditions of the End User License Agree_
ment supplied by STMicroelectronics International N.V.
Full source code is available at: www.segger.com
We appreciate your understanding and fairness.
----------------------------------------------------------------------
File : GUIConf.c
Purpose : Display controller initialization
---------------------------END-OF-HEADER------------------------------
*/
/**
******************************************************************************
* @file GUIConf.c
* @author MCD Application Team
* @version V1.0.0
* @date 22-July-2013
* @brief Display controller initialization
******************************************************************************
* @attention
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the ''License'');
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software 
* distributed under the License is distributed on an ''AS IS'' BASIS, 
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
#include ''GUI.h''
/*********************************************************************
*
* Defines, configurable
*
**********************************************************************
*/
//
// Define the available number of bytes available for the GUI
//
#define GUI_NUMBYTES (1024) * 64 // x KByte
/*********************************************************************
*
* Static data
*
**********************************************************************
*/
/* 32 bit aligned memory area */
U32 extMem[GUI_NUMBYTES / 4] __attribute__ ((section(''.cmm'')));
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* GUI_X_Config
*
* Purpose:
* Called during the initialization process in order to set up the
* available memory for the GUI.
*/
void GUI_X_Config(void)
{
GUI_ALLOC_AssignMemory(extMem, GUI_NUMBYTES);
}
/*************************** End of file ****************************/

I put this to the ld file

.ccm (NOLOAD) :
{
.= ALING(4);
*(.ccm)
.= ALIGN(4);
} >ram1

Everything is working, but if delete the section definition from the file, then compile with no error and the program run. The question why the program run without the section definition?
Posted on October 01, 2013 at 15:40

U32 extMem[GUI_NUMBYTES / 4] __attribute__ ((section(''.cmm'')));

CCM not CMM

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
totti001
Associate II
Posted on October 01, 2013 at 16:10

I write to ccm, but the working is the same. I hope that is working well.

This is is the map file: ccm 0x20000adc 0x10000 load address 0x0803c6a4 .ccm 0x20000adc 0x10000 ..\obj\GUIConf.o 0x20000adc extMem the linker script:

OUTPUT_FORMAT (''elf32-littlearm'', ''elf32-bigarm'', ''elf32-littlearm'')
/* Internal Memory Map*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 0x00100000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
ram1 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x00010000
}
_eram = 0x20000000 + 0x00020000;
/* Section Definitions */ 
SECTIONS 
{ 
.ccm (NOLOAD) :
{
.= ALING(4);
*(.ccm)
.= ALIGN(4);
} > ram1
.text : 
{ 
KEEP(*(.isr_vector .isr_vector.*)) 
*(.text .text.* .gnu.linkonce.t.*) 
*(.glue_7t) *(.glue_7) 
*(.rodata .rodata* .gnu.linkonce.r.*) 
} > rom
.ARM.extab : 
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > rom
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
__exidx_end = .;
. = ALIGN(4); 
_etext = .;
_sidata = .; 
.data : AT (_etext) 
{ 
_sdata = .; 
*(.data .data.*) 
. = ALIGN(4); 
_edata = . ;
} > ram
/* .bss section which is used for uninitialized data */ 
.bss (NOLOAD) : 
{ 
_sbss = . ; 
*(.bss .bss.*) 
*(COMMON) 
. = ALIGN(4); 
_ebss = . ; 
} > ram
/* stack section */
.co_stack (NOLOAD):
{
. = ALIGN(8);
*(.co_stack .co_stack.*)
} > ram
. = ALIGN(4); 
_end = . ; 
} 

Posted on October 01, 2013 at 17:23

This worked for me (Yagarto 4.7.2)

#define GUI_NUMBYTES 10240
uint32_t extMem[GUI_NUMBYTES / 4] __attribute__ ((section(''.ccm'')));

OUTPUT_FORMAT (''elf32-littlearm'', ''elf32-bigarm'', ''elf32-littlearm'')
/* Internal Memory Map*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 0x00100000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
ram1 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x00010000
}
_eram = 0x20000000 + 0x00020000;
/* Section Definitions */
SECTIONS
{
.ccm (NOLOAD) :
{
. = ALIGN(4);
*(.ccm)
*(.ccm.*)
. = ALIGN(4);
} > ram1
.text :
{
KEEP(*(.isr_vector .isr_vector.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
} > rom
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > rom
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
__exidx_end = .;
. = ALIGN(4);
_etext = .;
_sidata = .;
.data : AT (_etext)
{
_sdata = .;
*(.data .data.*)
. = ALIGN(4);
_edata = . ;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
_sbss = . ;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
} > ram
/* stack section */
.co_stack (NOLOAD):
{
. = ALIGN(8);
*(.co_stack .co_stack.*)
} > ram
. = ALIGN(4);
_end = . ;
}

..
0x20020000 _eram = 0x20020000
.ccm 0x10000000 0x2800
0x10000000 . = ALIGN (0x4)
*(.ccm)
.ccm 0x10000000 0x2800 out/main.o
0x10000000 extMem
*(.ccm.*)
0x10002800 . = ALIGN (0x4)
.text 0x08000000 0xa148
*(.isr_vector .isr_vector.*)
.isr_vector 0x08000000 0x188 out/startup_stm32f401xx.o
0x08000000 g_pfnVectors
..

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
totti001
Associate II
Posted on October 03, 2013 at 10:18

Thank you very much. One question is for linker script.

This line

*(.ccm.*)

What do this line exactly?
Posted on October 03, 2013 at 10:37

> *(.ccm.*)

> What do this line exactly?

The first asterisk means ''any input file''. The second is a wildcard in the input section name, i.e. it means ''accept any input section which starts with '.ccm.'''. https://sourceware.org/binutils/docs/ld/Input-Section-Basics.html http://wiki.hup.hu/index.php/RTFM 😉 JW