mirror of https://github.com/ARMmbed/mbed-os.git
M467: Support HyperRAM
1. For GCC, support multi-block .data/.bss initialization 2. HyperRAM is mapped to two regions: 0x0A000000 and 0x80000000 According to default system address map, 0x0A000000 is located at 'Code' region and 0x80000000 at 'RAM' region. With MPU enabled on Mbed OS, 'Code' region is write-never and 'RAM' region execute-never. 0x80000000 is chosen because 'RAM' regioin is naturally for HyperRAM. 3. Configurable multi-function pins for HBI 4. To locate code/data at external HyperRAM: - Specify __attribute__((section(".text.nu.exthyperram"))) for RO/.text/readonly section type Invoke mbed_mpu_manager_lock_ram_execution()/mbed_mpu_manager_unlock_ram_execution() to run HyperRAM code - Specify __attribute__((section(".data.nu.exthyperram"))) for RW/.data/readwrite section type - Specify __attribute__((section(".bss.nu.exthyperram"))) for ZI/.bss/zeroinit section type 5. Add readmepull/15337/head
parent
8da2e31336
commit
0494866f5f
|
@ -0,0 +1,67 @@
|
||||||
|
# Nuvoton M460 series
|
||||||
|
|
||||||
|
## HyperRAM
|
||||||
|
|
||||||
|
HyperRAM, via Hyper Bus Interface Controller (HBI), is mapped to two regions: `0x0A00_0000`–`0x0BFF_FFFF` and `0x8000_0000`–`0x81FF_FFFF`, through which CPU can direct access.
|
||||||
|
|
||||||
|
### Enable HBI for HyperRAM
|
||||||
|
|
||||||
|
To enable HBI for HyperRAM, create one Mbed OS application configuration file named `mbed_app.json` under root directory of your sample program.
|
||||||
|
The file should have the following content which will enable HBI and configure its multi-function pins:
|
||||||
|
|
||||||
|
**mbed_app.json**:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
......
|
||||||
|
"target_overrides": {
|
||||||
|
......
|
||||||
|
"NUMAKER_IOT_M467": {
|
||||||
|
"target.hbi-enable": true,
|
||||||
|
"target.hbi-mfp-reg-list": "0x40000534, 0x4000057C, 0x40000590, 0x40000594",
|
||||||
|
"target.hbi-mfp-reg-msk-list": "0xFFFFFF00, 0xFFFFFFFF, 0xFFFF0000, 0xFFFFFFFF",
|
||||||
|
"target.hbi-mfp-reg-val-list": "0x10101000, 0x10101010, 0x10100000, 0x10101010"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
- `hbi-mfp-reg-list`: Comma-separated list of relevant multi-function pin registers
|
||||||
|
- `hbi-mfp-reg-msk-list`: Comma-separated list of relevant multi-function pin register masks
|
||||||
|
- `hbi-mfp-reg-val-list`: Comma-separated list of relevant multi-function pin register values
|
||||||
|
|
||||||
|
> **_NOTE:_** Make sure your HyperRAM hardware is ready.
|
||||||
|
|
||||||
|
> **_NOTE:_** Change the multi-function pins to align with your hardware.
|
||||||
|
|
||||||
|
### Locate data at HyperRAM
|
||||||
|
|
||||||
|
In the port, the region `0x8000_0000`–`0x81FF_FFFF` is chosen for the goal because on Mbed OS, MPU is enabled and the region is configured to be write-able, which naturally fits HyperRAM.
|
||||||
|
To get to the goal, data must place in specified sections:
|
||||||
|
|
||||||
|
**Locate initialized data**
|
||||||
|
|
||||||
|
Initialized data are just like `RW` sections for ARM, `.data` sectionis for GCC_ARM, and `readwrite` sections for IAR.
|
||||||
|
To locate them at HyperRAM, place in specified sections named `.data.nu.hyperram`.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
__attribute__((section(".data.nu.hyperram")))
|
||||||
|
uint32_t my_data = 100;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Locate zero-initialized data**
|
||||||
|
|
||||||
|
Zero-initialized data are just like `ZI` sections for ARM, `.bss` sections for GCC_ARM, and `zeroinit` sections for IAR.
|
||||||
|
To locate them at HyperRAM, place in specified sections named`.bss.nu.hyperram`.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
__attribute__((section(".bss.nu.hyperram")))
|
||||||
|
uint32_t my_bss;
|
||||||
|
```
|
||||||
|
|
||||||
|
> **_NOTE:_** Don't mis-place in sections,
|
||||||
|
or behavior is undefined because C runtime is not correctly initialized for these sections.
|
||||||
|
|
||||||
|
> **_NOTE:_** Check linker-generated .map file to make sure your data are actually located at HyperRAM.
|
|
@ -21,11 +21,19 @@
|
||||||
#include "../M460_mem.h"
|
#include "../M460_mem.h"
|
||||||
|
|
||||||
#if !defined(MBED_BOOT_STACK_SIZE)
|
#if !defined(MBED_BOOT_STACK_SIZE)
|
||||||
#define MBED_BOOT_STACK_SIZE 0x400
|
#define MBED_BOOT_STACK_SIZE 0x400
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define VECTOR_SIZE (4*(16 + 128))
|
#define VECTOR_SIZE (4*(16 + 128))
|
||||||
|
|
||||||
|
#if !defined(NU_HYPERRAM_START)
|
||||||
|
#define NU_HYPERRAM_START 0x80000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(NU_HYPERRAM_SIZE)
|
||||||
|
#define NU_HYPERRAM_SIZE 0x800000
|
||||||
|
#endif
|
||||||
|
|
||||||
LR_IROM1 MBED_APP_START MBED_APP_SIZE {
|
LR_IROM1 MBED_APP_START MBED_APP_SIZE {
|
||||||
ER_IROM1 MBED_APP_START MBED_APP_SIZE { ; load address = execution address
|
ER_IROM1 MBED_APP_START MBED_APP_SIZE { ; load address = execution address
|
||||||
*(RESET, +First)
|
*(RESET, +First)
|
||||||
|
@ -53,6 +61,12 @@ LR_IROM1 MBED_APP_START MBED_APP_SIZE {
|
||||||
|
|
||||||
ARM_LIB_HEAP AlignExpr(+0, 16) EMPTY (MBED_RAM_APP_START + MBED_RAM_APP_SIZE - AlignExpr(ImageLimit(RW_IRAM1), 16)) {
|
ARM_LIB_HEAP AlignExpr(+0, 16) EMPTY (MBED_RAM_APP_START + MBED_RAM_APP_SIZE - AlignExpr(ImageLimit(RW_IRAM1), 16)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NU_HYPERRAM NU_HYPERRAM_START NU_HYPERRAM_SIZE {
|
||||||
|
*(.text.nu.hyperram)
|
||||||
|
*(.data.nu.hyperram)
|
||||||
|
*(.bss.nu.hyperram)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScatterAssert(LoadLimit(LR_IROM1) <= (MBED_APP_START + MBED_APP_SIZE))
|
ScatterAssert(LoadLimit(LR_IROM1) <= (MBED_APP_START + MBED_APP_SIZE))
|
||||||
|
|
|
@ -23,7 +23,15 @@
|
||||||
#include "../M460_mem.h"
|
#include "../M460_mem.h"
|
||||||
|
|
||||||
#if !defined(MBED_BOOT_STACK_SIZE)
|
#if !defined(MBED_BOOT_STACK_SIZE)
|
||||||
#define MBED_BOOT_STACK_SIZE 0x400
|
#define MBED_BOOT_STACK_SIZE 0x400
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(NU_HYPERRAM_START)
|
||||||
|
#define NU_HYPERRAM_START 0x80000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(NU_HYPERRAM_SIZE)
|
||||||
|
#define NU_HYPERRAM_SIZE 0x800000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
M_CRASH_DATA_RAM_SIZE = 0x100;
|
M_CRASH_DATA_RAM_SIZE = 0x100;
|
||||||
|
@ -34,6 +42,7 @@ MEMORY
|
||||||
VECTORS (rx) : ORIGIN = MBED_APP_START, LENGTH = 0x00000400
|
VECTORS (rx) : ORIGIN = MBED_APP_START, LENGTH = 0x00000400
|
||||||
FLASH (rx) : ORIGIN = MBED_APP_START + 0x400, LENGTH = MBED_APP_SIZE - 0x00000400
|
FLASH (rx) : ORIGIN = MBED_APP_START + 0x400, LENGTH = MBED_APP_SIZE - 0x00000400
|
||||||
RAM_INTERN (rwx) : ORIGIN = MBED_RAM_APP_START, LENGTH = MBED_RAM_APP_SIZE
|
RAM_INTERN (rwx) : ORIGIN = MBED_RAM_APP_START, LENGTH = MBED_RAM_APP_SIZE
|
||||||
|
HYPERRAM (rwx) : ORIGIN = NU_HYPERRAM_START, LENGTH = NU_HYPERRAM_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,6 +88,52 @@ SECTIONS
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
} > VECTORS
|
} > VECTORS
|
||||||
|
|
||||||
|
.copy.table : ALIGN(4)
|
||||||
|
{
|
||||||
|
__copy_table_start__ = .;
|
||||||
|
|
||||||
|
/* .data located at internal SRAM */
|
||||||
|
LONG (LOADADDR(.data))
|
||||||
|
LONG (ADDR(.data))
|
||||||
|
LONG (SIZEOF(.data))
|
||||||
|
|
||||||
|
/* .text.nu.hyperram located at HyperRAM */
|
||||||
|
LONG (LOADADDR(.text.nu.hyperram))
|
||||||
|
LONG (ADDR(.text.nu.hyperram))
|
||||||
|
LONG (SIZEOF(.text.nu.hyperram))
|
||||||
|
|
||||||
|
/* .data.nu.hyperram located at HyperRAM */
|
||||||
|
LONG (LOADADDR(.data.nu.hyperram))
|
||||||
|
LONG (ADDR(.data.nu.hyperram))
|
||||||
|
LONG (SIZEOF(.data.nu.hyperram))
|
||||||
|
|
||||||
|
__copy_table_end__ = .;
|
||||||
|
} > FLASH
|
||||||
|
|
||||||
|
.zero.table : ALIGN(4)
|
||||||
|
{
|
||||||
|
__zero_table_start__ = .;
|
||||||
|
|
||||||
|
/* .bss located at internal SRAM */
|
||||||
|
LONG (ADDR(.bss))
|
||||||
|
LONG (SIZEOF(.bss))
|
||||||
|
|
||||||
|
/* .bss.nu.hyperram located at HyperRAM */
|
||||||
|
LONG (ADDR(.bss.nu.hyperram))
|
||||||
|
LONG (SIZEOF(.bss.nu.hyperram))
|
||||||
|
|
||||||
|
__zero_table_end__ = .;
|
||||||
|
} > FLASH
|
||||||
|
|
||||||
|
/* First match used, so place in front of .text */
|
||||||
|
.text.nu.hyperram :
|
||||||
|
{
|
||||||
|
*(.text.nu.hyperram)
|
||||||
|
} >HYPERRAM AT>FLASH
|
||||||
|
|
||||||
|
Image$$NU_HYPERRAM$$RO$$Base = ADDR(.text.nu.hyperram);
|
||||||
|
Image$$NU_HYPERRAM$$RO$$Limit = ADDR(.text.nu.hyperram) + SIZEOF(.text.nu.hyperram);
|
||||||
|
Image$$NU_HYPERRAM$$RO$$Length = SIZEOF(.text.nu.hyperram);
|
||||||
|
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
|
@ -156,7 +211,17 @@ SECTIONS
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
__CRASH_DATA_RAM_END__ = .; /* Define a global symbol at data end */
|
__CRASH_DATA_RAM_END__ = .; /* Define a global symbol at data end */
|
||||||
} > RAM_INTERN
|
} > RAM_INTERN
|
||||||
|
|
||||||
|
/* First match used, so place in front of .data */
|
||||||
|
.data.nu.hyperram :
|
||||||
|
{
|
||||||
|
*(.data.nu.hyperram)
|
||||||
|
} >HYPERRAM AT>FLASH
|
||||||
|
|
||||||
|
Image$$NU_HYPERRAM$$RW$$Base = ADDR(.data.nu.hyperram);
|
||||||
|
Image$$NU_HYPERRAM$$RW$$Limit = ADDR(.data.nu.hyperram) + SIZEOF(.data.nu.hyperram);
|
||||||
|
Image$$NU_HYPERRAM$$RW$$Length = SIZEOF(.data.nu.hyperram);
|
||||||
|
|
||||||
.data :
|
.data :
|
||||||
{
|
{
|
||||||
PROVIDE( __etext = LOADADDR(.data) );
|
PROVIDE( __etext = LOADADDR(.data) );
|
||||||
|
@ -205,6 +270,20 @@ SECTIONS
|
||||||
__uninitialized_end = .;
|
__uninitialized_end = .;
|
||||||
} > RAM_INTERN
|
} > RAM_INTERN
|
||||||
|
|
||||||
|
/* First match used, so place in front of .bss */
|
||||||
|
/* If a variable defined with __attribute__((section())) keyword the
|
||||||
|
* variable is treated like an initialized variable. To not waste memory
|
||||||
|
* NOLOAD attribute used here. The whole section is zero initialized by
|
||||||
|
* adding section information to .zero.table */
|
||||||
|
.bss.nu.hyperram (NOLOAD):
|
||||||
|
{
|
||||||
|
*(.bss.nu.hyperram)
|
||||||
|
} > HYPERRAM
|
||||||
|
|
||||||
|
Image$$NU_HYPERRAM$$ZI$$Base = ADDR(.bss.nu.hyperram);
|
||||||
|
Image$$NU_HYPERRAM$$ZI$$Limit = ADDR(.bss.nu.hyperram) + SIZEOF(.bss.nu.hyperram);
|
||||||
|
Image$$NU_HYPERRAM$$ZI$$Length = SIZEOF(.bss.nu.hyperram);
|
||||||
|
|
||||||
.bss (NOLOAD):
|
.bss (NOLOAD):
|
||||||
{
|
{
|
||||||
__bss_start__ = .;
|
__bss_start__ = .;
|
||||||
|
@ -226,5 +305,4 @@ SECTIONS
|
||||||
PROVIDE(__heap_size = SIZEOF(.heap));
|
PROVIDE(__heap_size = SIZEOF(.heap));
|
||||||
PROVIDE(__mbed_sbrk_start = ADDR(.heap));
|
PROVIDE(__mbed_sbrk_start = ADDR(.heap));
|
||||||
PROVIDE(__mbed_krbs_start = ADDR(.heap) + SIZEOF(.heap));
|
PROVIDE(__mbed_krbs_start = ADDR(.heap) + SIZEOF(.heap));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,14 @@ if (!isdefinedsymbol(MBED_BOOT_STACK_SIZE)) {
|
||||||
define symbol MBED_BOOT_STACK_SIZE = 0x400;
|
define symbol MBED_BOOT_STACK_SIZE = 0x400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isdefinedsymbol(NU_HYPERRAM_START)) {
|
||||||
|
define symbol NU_HYPERRAM_START = 0x80000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isdefinedsymbol(NU_HYPERRAM_SIZE)) {
|
||||||
|
define symbol NU_HYPERRAM_SIZE = 0x800000;
|
||||||
|
}
|
||||||
|
|
||||||
/*-Specials-*/
|
/*-Specials-*/
|
||||||
define symbol __ICFEDIT_intvec_start__ = MBED_APP_START;
|
define symbol __ICFEDIT_intvec_start__ = MBED_APP_START;
|
||||||
/*-Memory Regions-*/
|
/*-Memory Regions-*/
|
||||||
|
@ -35,6 +43,8 @@ define symbol __ICFEDIT_region_IRAM_start__ = MBED_RAM_APP_START;
|
||||||
define symbol __ICFEDIT_region_IRAM_end__ = MBED_RAM_APP_START + MBED_RAM_APP_SIZE - 0x100 - 1;
|
define symbol __ICFEDIT_region_IRAM_end__ = MBED_RAM_APP_START + MBED_RAM_APP_SIZE - 0x100 - 1;
|
||||||
define symbol __region_CRASH_DATA_RAM_start__ = MBED_RAM_APP_START + MBED_RAM_APP_SIZE - 0x100;
|
define symbol __region_CRASH_DATA_RAM_start__ = MBED_RAM_APP_START + MBED_RAM_APP_SIZE - 0x100;
|
||||||
define symbol __region_CRASH_DATA_RAM_end__ = MBED_RAM_APP_START + MBED_RAM_APP_SIZE - 1;
|
define symbol __region_CRASH_DATA_RAM_end__ = MBED_RAM_APP_START + MBED_RAM_APP_SIZE - 1;
|
||||||
|
define symbol __ICFEDIT_region_HYPERRAM_start__ = NU_HYPERRAM_START;
|
||||||
|
define symbol __ICFEDIT_region_HYPERRAM_end__ = NU_HYPERRAM_START + NU_HYPERRAM_SIZE - 1;
|
||||||
/*-Sizes-*/
|
/*-Sizes-*/
|
||||||
define symbol __ICFEDIT_size_cstack__ = MBED_BOOT_STACK_SIZE;
|
define symbol __ICFEDIT_size_cstack__ = MBED_BOOT_STACK_SIZE;
|
||||||
define symbol __ICFEDIT_size_intvec__ = (4 * (16 + 128));
|
define symbol __ICFEDIT_size_intvec__ = (4 * (16 + 128));
|
||||||
|
@ -46,23 +56,42 @@ define memory mem with size = 4G;
|
||||||
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
|
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
|
||||||
define region IRAM_region = mem:[from __ICFEDIT_region_IRAM_start__ to __ICFEDIT_region_IRAM_end__];
|
define region IRAM_region = mem:[from __ICFEDIT_region_IRAM_start__ to __ICFEDIT_region_IRAM_end__];
|
||||||
define region CRASH_DATA_RAM_region = mem:[from __region_CRASH_DATA_RAM_start__ to __region_CRASH_DATA_RAM_end__];
|
define region CRASH_DATA_RAM_region = mem:[from __region_CRASH_DATA_RAM_start__ to __region_CRASH_DATA_RAM_end__];
|
||||||
|
define region HYPERRAM_region = mem:[from __ICFEDIT_region_HYPERRAM_start__ to __ICFEDIT_region_HYPERRAM_end__];
|
||||||
|
|
||||||
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
|
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
|
||||||
define block HEAP with expanding size, alignment = 8, minimum size = __ICFEDIT_size_heap__ { };
|
define block HEAP with expanding size, alignment = 8, minimum size = __ICFEDIT_size_heap__ { };
|
||||||
/* NOTE: Vector table base requires to be aligned to the power of vector table size. Give a safe value here. */
|
/* NOTE: Vector table base requires to be aligned to the power of vector table size. Give a safe value here. */
|
||||||
define block IRAMVEC with alignment = 1024, size = __ICFEDIT_size_intvec__ { };
|
define block IRAMVEC with alignment = 1024, size = __ICFEDIT_size_intvec__ { };
|
||||||
|
/* Place .text.nu.hyperram/.data.nu.hyperram/.bss.nu.hyperram together
|
||||||
|
*
|
||||||
|
* NOTE: Don't use wildcard like .text.nu.hyperram*. This can collide with .text.nu.hyperram*_init or
|
||||||
|
* linker-generated initializer for .text.nu.hyperram*.
|
||||||
|
* NOTE: Per test, 'section .data.nu.hyperram*' will cause linker-generated initializer (const)
|
||||||
|
* also placed here, resulting in large gap, though it can get fixed with
|
||||||
|
* 'readwrite section .data.nu.hyperram*'.
|
||||||
|
* NOTE: With 'initialize by copy { section .text.nu.hyperram }', .text.nu.hyperram is still taken
|
||||||
|
* as readonly (for initializer), resulting in large gap.
|
||||||
|
* NOTE: With 'initialize manually { section .text.nu.hyperram }', .text.nu.hyperram becomes readwrite
|
||||||
|
* .text.nu.hyperram_init is generated by linker to be readonly. We need to do the initialization
|
||||||
|
* for .text.nu.hyperram manually.
|
||||||
|
*/
|
||||||
|
define block NU_HYPERRAM with alignment = 8 { section .text.nu.hyperram,
|
||||||
|
section .data.nu.hyperram,
|
||||||
|
section .bss.nu.hyperram };
|
||||||
|
|
||||||
/* Define Crash Data Symbols */
|
/* Define Crash Data Symbols */
|
||||||
define exported symbol __CRASH_DATA_RAM_START__ = __region_CRASH_DATA_RAM_start__;
|
define exported symbol __CRASH_DATA_RAM_START__ = __region_CRASH_DATA_RAM_start__;
|
||||||
define exported symbol __CRASH_DATA_RAM_END__ = __region_CRASH_DATA_RAM_end__;
|
define exported symbol __CRASH_DATA_RAM_END__ = __region_CRASH_DATA_RAM_end__;
|
||||||
|
|
||||||
initialize by copy { readwrite };
|
initialize by copy { readwrite };
|
||||||
do not initialize { section .noinit };
|
initialize manually { section .text.nu.hyperram };
|
||||||
|
do not initialize { section .noinit };
|
||||||
|
|
||||||
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
|
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
|
||||||
|
|
||||||
place in ROM_region { readonly };
|
place in ROM_region { readonly };
|
||||||
place at start of IRAM_region { block CSTACK };
|
place at start of IRAM_region { block CSTACK };
|
||||||
place in IRAM_region { block IRAMVEC };
|
place in IRAM_region { block IRAMVEC };
|
||||||
place in IRAM_region { readwrite };
|
place in IRAM_region { readwrite };
|
||||||
place in IRAM_region { block HEAP };
|
place in IRAM_region { block HEAP };
|
||||||
|
place in HYPERRAM_region { block NU_HYPERRAM };
|
||||||
|
|
|
@ -16,6 +16,23 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
|
||||||
|
/* Get around error: conflicting type qualifiers for '__copy_table_start__'
|
||||||
|
*
|
||||||
|
* cmsis_gcc.h also imports the following symbols but with different type qualifier:
|
||||||
|
*
|
||||||
|
* __copy_table_start__
|
||||||
|
* __copy_table_end__
|
||||||
|
* __zero_table_start__
|
||||||
|
* __zero_table_end__
|
||||||
|
*
|
||||||
|
* Define `__PROGRAM_START` to exclude __cmsis_start() in cmsis_gcc.h.
|
||||||
|
*/
|
||||||
|
#define __PROGRAM_START
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "M460.h"
|
#include "M460.h"
|
||||||
|
|
||||||
/* Suppress warning messages */
|
/* Suppress warning messages */
|
||||||
|
@ -64,11 +81,10 @@ extern void __main(void);
|
||||||
void __iar_program_start(void);
|
void __iar_program_start(void);
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
extern uint32_t __StackTop;
|
extern uint32_t __StackTop;
|
||||||
extern uint32_t __etext;
|
extern uint32_t __copy_table_start__;
|
||||||
extern uint32_t __data_start__;
|
extern uint32_t __copy_table_end__;
|
||||||
extern uint32_t __data_end__;
|
extern uint32_t __zero_table_start__;
|
||||||
extern uint32_t __bss_start__;
|
extern uint32_t __zero_table_end__;
|
||||||
extern uint32_t __bss_end__;
|
|
||||||
|
|
||||||
#if defined(TOOLCHAIN_GCC_ARM)
|
#if defined(TOOLCHAIN_GCC_ARM)
|
||||||
extern void _start(void);
|
extern void _start(void);
|
||||||
|
@ -466,31 +482,73 @@ void Reset_Handler_1(void)
|
||||||
|
|
||||||
void Reset_Handler_2(void)
|
void Reset_Handler_2(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined(__ARMCC_VERSION)
|
#if defined(__ARMCC_VERSION)
|
||||||
__main();
|
__main();
|
||||||
|
|
||||||
#elif defined(__ICCARM__)
|
#elif defined(__ICCARM__)
|
||||||
__iar_program_start();
|
/* With 'initialize manually { section .text.nu.hyperram }' in .icf, do the
|
||||||
|
* initialization for .text.nu.hyperram manually.
|
||||||
#elif defined(__GNUC__)
|
*
|
||||||
uint32_t *src_ind = (uint32_t *) &__etext;
|
* NOTE: C runtime not initialized yet, don't invoke memcpy() for safe. */
|
||||||
uint32_t *dst_ind = (uint32_t *) &__data_start__;
|
{
|
||||||
uint32_t *dst_end = (uint32_t *) &__data_end__;
|
/* BSP not defined yet, define it */
|
||||||
|
#pragma section=".text.nu.hyperram"
|
||||||
/* Move .data section from ROM to RAM */
|
#pragma section=".text.nu.hyperram_init"
|
||||||
if (src_ind != dst_ind) {
|
uint32_t *src_ind = (uint32_t *) __section_begin(".text.nu.hyperram_init");
|
||||||
for (; dst_ind < dst_end;) {
|
uint32_t *src_end = (uint32_t *) __section_end(".text.nu.hyperram_init");
|
||||||
*dst_ind ++ = *src_ind ++;
|
uint32_t *dst_ind = (uint32_t *) __section_begin(".text.nu.hyperram");
|
||||||
|
if (src_ind != dst_ind) {
|
||||||
|
for (; src_ind < src_end;) {
|
||||||
|
*dst_ind ++ = *src_ind ++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize .bss section to zero */
|
__iar_program_start();
|
||||||
dst_ind = (uint32_t *) &__bss_start__;
|
|
||||||
dst_end = (uint32_t *) &__bss_end__;
|
#elif defined(__GNUC__)
|
||||||
if (dst_ind != dst_end) {
|
/* Move (multiple) .data section(s) from ROM to RAM */
|
||||||
for (; dst_ind < dst_end;) {
|
{
|
||||||
*dst_ind ++ = 0;
|
/* Struct of copy table entry which must match linker script */
|
||||||
|
typedef struct copy_table_entry_ {
|
||||||
|
uint32_t src; // Address to copy from
|
||||||
|
uint32_t dst; // Address to copy to
|
||||||
|
uint32_t size; // Copy size in bytes
|
||||||
|
} copy_table_entry;
|
||||||
|
|
||||||
|
copy_table_entry *copy_table_ind = (copy_table_entry *) &__copy_table_start__;
|
||||||
|
copy_table_entry *copy_table_end = (copy_table_entry *) &__copy_table_end__;
|
||||||
|
|
||||||
|
for (; copy_table_ind != copy_table_end; copy_table_ind ++) {
|
||||||
|
uint32_t *src_ind = (uint32_t *) copy_table_ind->src;
|
||||||
|
uint32_t *src_end = (uint32_t *) (copy_table_ind->src + copy_table_ind->size);
|
||||||
|
uint32_t *dst_ind = (uint32_t *) copy_table_ind->dst;
|
||||||
|
if (src_ind != dst_ind) {
|
||||||
|
for (; src_ind < src_end;) {
|
||||||
|
*dst_ind ++ = *src_ind ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize (multiple) .bss sections to zero */
|
||||||
|
{
|
||||||
|
/* Struct of zero table entry which must match linker script */
|
||||||
|
typedef struct zero_table_entry_ {
|
||||||
|
uint32_t start; // Address to start zero'ing
|
||||||
|
uint32_t size; // Zero size in bytes
|
||||||
|
} zero_table_entry;
|
||||||
|
|
||||||
|
zero_table_entry *zero_table_ind = (zero_table_entry *) &__zero_table_start__;
|
||||||
|
zero_table_entry *zero_table_end = (zero_table_entry *) &__zero_table_end__;
|
||||||
|
|
||||||
|
for (; zero_table_ind != zero_table_end; zero_table_ind ++) {
|
||||||
|
uint32_t *dst_ind = (uint32_t *) zero_table_ind->start;
|
||||||
|
uint32_t *dst_end = (uint32_t *) (zero_table_ind->start + zero_table_ind->size);
|
||||||
|
|
||||||
|
for (; dst_ind < dst_end; ) {
|
||||||
|
*dst_ind ++ = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,4 +93,98 @@ void SystemInit (void)
|
||||||
/* Lock protected registers */
|
/* Lock protected registers */
|
||||||
SYS_LockReg();
|
SYS_LockReg();
|
||||||
|
|
||||||
|
#if defined(MBED_CONF_TARGET_HBI_ENABLE) && MBED_CONF_TARGET_HBI_ENABLE
|
||||||
|
/* Initialize HBI for HyperRAM */
|
||||||
|
void nu_hbi_init(void);
|
||||||
|
nu_hbi_init();
|
||||||
|
#else
|
||||||
|
int32_t nu_hyperram_used(void);
|
||||||
|
if (nu_hyperram_used()) {
|
||||||
|
/* TODO: Report error: HyperRAM used but HBI not enabled */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Detect whether or not HyperRAM is used
|
||||||
|
*
|
||||||
|
* NOTE: For Arm Compiler, Image$$region_name doesn't include ZI. To avoid
|
||||||
|
* confusion, use Image$$region_name$$RO/Image$$region_name$$RW/
|
||||||
|
* Image$$region_name$$ZI instead.
|
||||||
|
* NOTE: Compiler e.g. Arm Compiler can optimize assuming (®ion_name$$Limit != ®ion_name$$Base) being true.
|
||||||
|
* Change to (®ion_name$$Limit - ®ion_name$$Base) instead.
|
||||||
|
* NOTE: Compiler e.g. GCC can optimize assuming ®ion_name$$Length being non-zero.
|
||||||
|
* Change to (®ion_name$$Limit - ®ion_name$$Base) instead.
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) || defined(__GNUC__)
|
||||||
|
extern uint32_t Image$$NU_HYPERRAM$$RO$$Base;
|
||||||
|
extern uint32_t Image$$NU_HYPERRAM$$RO$$Limit;
|
||||||
|
extern uint32_t Image$$NU_HYPERRAM$$RW$$Base;
|
||||||
|
extern uint32_t Image$$NU_HYPERRAM$$RW$$Limit;
|
||||||
|
extern uint32_t Image$$NU_HYPERRAM$$ZI$$Base;
|
||||||
|
extern uint32_t Image$$NU_HYPERRAM$$ZI$$Limit;
|
||||||
|
#define NU_HYPERRAM_USED \
|
||||||
|
((((uint32_t) &Image$$NU_HYPERRAM$$RO$$Limit) - ((uint32_t) &Image$$NU_HYPERRAM$$RO$$Base)) || \
|
||||||
|
(((uint32_t) &Image$$NU_HYPERRAM$$RW$$Limit) - ((uint32_t) &Image$$NU_HYPERRAM$$RW$$Base)) || \
|
||||||
|
(((uint32_t) &Image$$NU_HYPERRAM$$ZI$$Limit) - ((uint32_t) &Image$$NU_HYPERRAM$$ZI$$Base)))
|
||||||
|
#elif defined(__ICCARM__)
|
||||||
|
extern uint32_t NU_HYPERRAM$$Base;
|
||||||
|
extern uint32_t NU_HYPERRAM$$Limit;
|
||||||
|
#define NU_HYPERRAM_USED \
|
||||||
|
(!!(((uint32_t) &NU_HYPERRAM$$Limit) - ((uint32_t) &NU_HYPERRAM$$Base)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int32_t nu_hyperram_used(void)
|
||||||
|
{
|
||||||
|
return NU_HYPERRAM_USED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBED_CONF_TARGET_HBI_ENABLE) && MBED_CONF_TARGET_HBI_ENABLE
|
||||||
|
|
||||||
|
/* Simple array size macro without type check */
|
||||||
|
#define _NU_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
|
||||||
|
|
||||||
|
void nu_hbi_init(void)
|
||||||
|
{
|
||||||
|
/* Configurable HBI multi-function pin
|
||||||
|
*
|
||||||
|
* NOTE: C runtime not initialized yet, locate at ROM region.
|
||||||
|
*/
|
||||||
|
static const uint32_t hbi_mfp_reg_arr[] = {
|
||||||
|
MBED_CONF_TARGET_HBI_MFP_REG_LIST
|
||||||
|
};
|
||||||
|
static const uint32_t hbi_mfp_reg_msk_arr[] = {
|
||||||
|
MBED_CONF_TARGET_HBI_MFP_REG_MSK_LIST
|
||||||
|
};
|
||||||
|
static const uint32_t hbi_mfp_reg_val_arr[] = {
|
||||||
|
MBED_CONF_TARGET_HBI_MFP_REG_VAL_LIST
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Make sure consistent HBI multi-function pin configurations */
|
||||||
|
_Static_assert(_NU_ARRAY_SIZE(hbi_mfp_reg_arr) == _NU_ARRAY_SIZE(hbi_mfp_reg_msk_arr),
|
||||||
|
"Inconsistent HBI MFP register and mask list length");
|
||||||
|
_Static_assert(_NU_ARRAY_SIZE(hbi_mfp_reg_arr) == _NU_ARRAY_SIZE(hbi_mfp_reg_val_arr),
|
||||||
|
"Inconsistent HBI MFP register and value list length");
|
||||||
|
|
||||||
|
/* Unlock protected registers */
|
||||||
|
SYS_UnlockReg();
|
||||||
|
|
||||||
|
/* Initialize HBI module */
|
||||||
|
SYS_ResetModule(HBI_RST);
|
||||||
|
|
||||||
|
/* Enable HBI module clock */
|
||||||
|
CLK_EnableModuleClock(HBI_MODULE);
|
||||||
|
|
||||||
|
/* Set HBI multi-function pins */
|
||||||
|
const uint32_t *reg_pos = hbi_mfp_reg_arr;
|
||||||
|
const uint32_t *reg_end = hbi_mfp_reg_arr + _NU_ARRAY_SIZE(hbi_mfp_reg_arr);
|
||||||
|
const uint32_t *msk_pos = hbi_mfp_reg_msk_arr;
|
||||||
|
const uint32_t *val_pos = hbi_mfp_reg_val_arr;
|
||||||
|
for (; reg_pos != reg_end; reg_pos ++, msk_pos ++, val_pos ++) {
|
||||||
|
M32(*reg_pos) = (M32(*reg_pos) & ~*msk_pos) | *val_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock protected registers */
|
||||||
|
SYS_LockReg();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #if defined(MBED_CONF_TARGET_HBI_ENABLE) && MBED_CONF_TARGET_HBI_ENABLE */
|
||||||
|
|
|
@ -7414,6 +7414,19 @@
|
||||||
"gpio-irq-debounce-sample-rate": {
|
"gpio-irq-debounce-sample-rate": {
|
||||||
"help": "Select GPIO IRQ debounce sample rate: GPIO_DBCTL_DBCLKSEL_1, GPIO_DBCTL_DBCLKSEL_2, GPIO_DBCTL_DBCLKSEL_4, ..., or GPIO_DBCTL_DBCLKSEL_32768",
|
"help": "Select GPIO IRQ debounce sample rate: GPIO_DBCTL_DBCLKSEL_1, GPIO_DBCTL_DBCLKSEL_2, GPIO_DBCTL_DBCLKSEL_4, ..., or GPIO_DBCTL_DBCLKSEL_32768",
|
||||||
"value": "GPIO_DBCTL_DBCLKSEL_16"
|
"value": "GPIO_DBCTL_DBCLKSEL_16"
|
||||||
|
},
|
||||||
|
"hbi-enable": {
|
||||||
|
"help": "Enable HBI for HyperRAM",
|
||||||
|
"options": [false, true]
|
||||||
|
},
|
||||||
|
"hbi-mfp-reg-list": {
|
||||||
|
"help": "Comma separated multi-function pin register list to enable HBI for HyperRAM"
|
||||||
|
},
|
||||||
|
"hbi-mfp-reg-msk-list": {
|
||||||
|
"help": "Comma separated multi-function pin register mask list to enable HBI for HyperRAM"
|
||||||
|
},
|
||||||
|
"hbi-mfp-reg-val-list": {
|
||||||
|
"help": "Comma separated multi-function pin register value list to enable HBI for HyperRAM"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"inherits": [
|
"inherits": [
|
||||||
|
@ -7501,7 +7514,11 @@
|
||||||
"usb-uart": "UART_0",
|
"usb-uart": "UART_0",
|
||||||
"usb-uart-tx": "PB_13",
|
"usb-uart-tx": "PB_13",
|
||||||
"usb-uart-rx": "PB_12",
|
"usb-uart-rx": "PB_12",
|
||||||
"network-default-interface-type": "WIFI"
|
"network-default-interface-type": "WIFI",
|
||||||
|
"hbi-enable": false,
|
||||||
|
"hbi-mfp-reg-list": "0x40000534, 0x4000057C, 0x40000590, 0x40000594",
|
||||||
|
"hbi-mfp-reg-msk-list": "0xFFFFFF00, 0xFFFFFFFF, 0xFFFF0000, 0xFFFFFFFF",
|
||||||
|
"hbi-mfp-reg-val-list": "0x10101000, 0x10101010, 0x10100000, 0x10101010"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"MCU_M480": {
|
"MCU_M480": {
|
||||||
|
|
Loading…
Reference in New Issue