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 readme
pull/15337/head
Chun-Chieh Li 2022-02-17 18:24:15 +08:00
parent 8da2e31336
commit 0494866f5f
7 changed files with 388 additions and 31 deletions

View File

@ -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.

View File

@ -21,11 +21,19 @@
#include "../M460_mem.h"
#if !defined(MBED_BOOT_STACK_SIZE)
#define MBED_BOOT_STACK_SIZE 0x400
#define MBED_BOOT_STACK_SIZE 0x400
#endif
#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 {
ER_IROM1 MBED_APP_START MBED_APP_SIZE { ; load address = execution address
*(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)) {
}
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))

View File

@ -23,7 +23,15 @@
#include "../M460_mem.h"
#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
M_CRASH_DATA_RAM_SIZE = 0x100;
@ -34,6 +42,7 @@ MEMORY
VECTORS (rx) : ORIGIN = MBED_APP_START, LENGTH = 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
HYPERRAM (rwx) : ORIGIN = NU_HYPERRAM_START, LENGTH = NU_HYPERRAM_SIZE
}
/**
@ -79,6 +88,52 @@ SECTIONS
. = ALIGN(8);
} > 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 :
{
@ -156,7 +211,17 @@ SECTIONS
. = ALIGN(8);
__CRASH_DATA_RAM_END__ = .; /* Define a global symbol at data end */
} > 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 :
{
PROVIDE( __etext = LOADADDR(.data) );
@ -205,6 +270,20 @@ SECTIONS
__uninitialized_end = .;
} > 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_start__ = .;
@ -226,5 +305,4 @@ SECTIONS
PROVIDE(__heap_size = SIZEOF(.heap));
PROVIDE(__mbed_sbrk_start = ADDR(.heap));
PROVIDE(__mbed_krbs_start = ADDR(.heap) + SIZEOF(.heap));
}

View File

@ -26,6 +26,14 @@ if (!isdefinedsymbol(MBED_BOOT_STACK_SIZE)) {
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-*/
define symbol __ICFEDIT_intvec_start__ = MBED_APP_START;
/*-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 __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 __ICFEDIT_region_HYPERRAM_start__ = NU_HYPERRAM_START;
define symbol __ICFEDIT_region_HYPERRAM_end__ = NU_HYPERRAM_START + NU_HYPERRAM_SIZE - 1;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = MBED_BOOT_STACK_SIZE;
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 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 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 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. */
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 exported symbol __CRASH_DATA_RAM_START__ = __region_CRASH_DATA_RAM_start__;
define exported symbol __CRASH_DATA_RAM_END__ = __region_CRASH_DATA_RAM_end__;
initialize by copy { readwrite };
do not initialize { section .noinit };
initialize by copy { readwrite };
initialize manually { section .text.nu.hyperram };
do not initialize { section .noinit };
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 in IRAM_region { block IRAMVEC };
place in IRAM_region { readwrite };
place in IRAM_region { block HEAP };
place in HYPERRAM_region { block NU_HYPERRAM };

View File

@ -16,6 +16,23 @@
* 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"
/* Suppress warning messages */
@ -64,11 +81,10 @@ extern void __main(void);
void __iar_program_start(void);
#elif defined(__GNUC__)
extern uint32_t __StackTop;
extern uint32_t __etext;
extern uint32_t __data_start__;
extern uint32_t __data_end__;
extern uint32_t __bss_start__;
extern uint32_t __bss_end__;
extern uint32_t __copy_table_start__;
extern uint32_t __copy_table_end__;
extern uint32_t __zero_table_start__;
extern uint32_t __zero_table_end__;
#if defined(TOOLCHAIN_GCC_ARM)
extern void _start(void);
@ -466,31 +482,73 @@ void Reset_Handler_1(void)
void Reset_Handler_2(void)
{
#if defined(__ARMCC_VERSION)
__main();
#elif defined(__ICCARM__)
__iar_program_start();
#elif defined(__GNUC__)
uint32_t *src_ind = (uint32_t *) &__etext;
uint32_t *dst_ind = (uint32_t *) &__data_start__;
uint32_t *dst_end = (uint32_t *) &__data_end__;
/* Move .data section from ROM to RAM */
if (src_ind != dst_ind) {
for (; dst_ind < dst_end;) {
*dst_ind ++ = *src_ind ++;
/* With 'initialize manually { section .text.nu.hyperram }' in .icf, do the
* initialization for .text.nu.hyperram manually.
*
* NOTE: C runtime not initialized yet, don't invoke memcpy() for safe. */
{
/* BSP not defined yet, define it */
#pragma section=".text.nu.hyperram"
#pragma section=".text.nu.hyperram_init"
uint32_t *src_ind = (uint32_t *) __section_begin(".text.nu.hyperram_init");
uint32_t *src_end = (uint32_t *) __section_end(".text.nu.hyperram_init");
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 */
dst_ind = (uint32_t *) &__bss_start__;
dst_end = (uint32_t *) &__bss_end__;
if (dst_ind != dst_end) {
for (; dst_ind < dst_end;) {
*dst_ind ++ = 0;
__iar_program_start();
#elif defined(__GNUC__)
/* Move (multiple) .data section(s) from ROM to RAM */
{
/* 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;
}
}
}

View File

@ -93,4 +93,98 @@ void SystemInit (void)
/* Lock protected registers */
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 (&region_name$$Limit != &region_name$$Base) being true.
* Change to (&region_name$$Limit - &region_name$$Base) instead.
* NOTE: Compiler e.g. GCC can optimize assuming &region_name$$Length being non-zero.
* Change to (&region_name$$Limit - &region_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 */

View File

@ -7414,6 +7414,19 @@
"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",
"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": [
@ -7501,7 +7514,11 @@
"usb-uart": "UART_0",
"usb-uart-tx": "PB_13",
"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": {