Permalink
Browse files

F3-port: option to put code into core coupled memory (CCM)

  • Loading branch information...
ventosus committed Nov 21, 2013
1 parent 0b6c65f commit 3a745ec937647f48bc94a58b938ab26f882e752c
Showing with 45 additions and 13 deletions.
  1. +10 −3 README.md
  2. +18 −10 support/ld/common.inc
  3. +17 −0 wirish/start_c.c
@@ -316,12 +316,19 @@ The F3 series have gotten a new I2C peripheral. It is much cleaner in design com
##### CCM: core coupled memory
(under construction)
The F3 series have 8kB of core coupled memory. This is memory that has zero wait-state compared to flash memory that has a wait-state of 2 (at the maximal 72MHz). Currently, the linker scripts are configured to only allow uninitialized data to be put into this memory, it can therefore be used as additional memory only. There is a convenience macro definition to bind a given data to the CCM.
The F3 series have 8kB of core coupled memory. This is memory that is only accessible from the CPU, not from DMA. This memory can either be used to store data or code, bot not both at the same time. Storing data simply extends your RAM. Storing data can considerably speed up code execution, as core coupled memory exihibits zero wait-state compared to flash memory that has a wait-state of 2 (at the maximal 72MHz). This therefore is the right place to put interrupts and other critical code to get a considerable performance increase. You can tell the linker to put data or code into the core coupled memory with GCC's section attributes or use the already predefined convenience macro \_\_CCM\_\_. To mark code to be put into a given memory section, you have to set the attributes for its prototype definition.
#define __CCM__ __attribute__((section(".CCM")))
uint16_t my_vector [0x400] __CCM__;
The support to bind functions (e.g. interrupt callbacks) to the CCM is planned to be added, those then would actually profit from zero wait-state execution.
// put this data into core coupled memory
uint16_t my_vec [0x400] __CCM__;
uint16_t my_var __CCM__ = 34U;
// put this code into core coupled memory for fastest (zero wait-state) execution
void my_irq(void *dat) __CCM__;
void my_rq(void *dat) {
...
}
##### OpAmp peripheral
(under construction)
@@ -143,6 +143,18 @@ SECTIONS
__data_end__ = .;
} > REGION_DATA AT> REGION_RODATA
/*
* CCM RAM section
*/
.ccmram :
{
. = ALIGN(4);
__ccm_start__ = .;
*(.CCM .CCM.* .gnu.linkonce.c.*)
. = ALIGN(4);
__ccm_end__ = .;
} > REGION_CCM AT> REGION_RODATA
/*
* Read-only data
*/
@@ -155,6 +167,12 @@ SECTIONS
. = ALIGN(4);
_lm_rom_img_cfgp = .;
LONG(LOADADDR(.data));
/* CCM image configuration; for C startup */
. = ALIGN(4);
_lm_ccm_img_cfgp = .;
LONG(LOADADDR(.ccmram));
/*
* Heap: Linker scripts may choose a custom heap by overriding
* _lm_heap_start and _lm_heap_end. Otherwise, the heap is in
@@ -182,16 +200,6 @@ SECTIONS
_end = __bss_end__;
} > REGION_BSS
/*
* .ccm
*/
.ccm (NOLOAD) :
{
. = ALIGN(4);
*(.CCM)
. = ALIGN(4);
} > REGION_CCM
/*
* Debugging sections
*/
@@ -53,12 +53,18 @@ extern void exit(int) __attribute__((noreturn, weak));
/* The linker must ensure that these are at least 4-byte aligned. */
extern char __data_start__, __data_end__;
extern char __bss_start__, __bss_end__;
extern char __ccm_start__, __ccm_end__;
struct rom_img_cfg {
int *img_start;
};
struct ccm_img_cfg {
int *img_start;
};
extern char _lm_rom_img_cfgp;
extern char _lm_ccm_img_cfgp;
void __attribute__((noreturn)) start_c(void) {
struct rom_img_cfg *img_cfg = (struct rom_img_cfg*)&_lm_rom_img_cfgp;
@@ -74,6 +80,17 @@ void __attribute__((noreturn)) start_c(void) {
}
}
/* Initialize .ccmram, if necessary. */
struct ccm_img_cfg *ccm_cfg = (struct ccm_img_cfg*)&_lm_ccm_img_cfgp;
src = ccm_cfg->img_start;
dst = (int*)&__ccm_start__;
if (src != dst) {
int *end = (int*)&__ccm_end__;
while (dst < end) {
*dst++ = *src++;
}
}
/* Zero .bss. */
dst = (int*)&__bss_start__;
while (dst < (int*)&__bss_end__) {

0 comments on commit 3a745ec

Please sign in to comment.