mirror of
https://github.com/apache/nuttx.git
synced 2026-05-19 20:06:24 +08:00
arm: support reboot / poweroff for qemu virt arm
Signed-off-by: Shanmin Zhang <zhangshanmin@xiaomi.com>
This commit is contained in:
committed by
Xiang Xiao
parent
9f10ddc9b0
commit
b9fb9bea1d
@@ -645,11 +645,17 @@ config ARCH_CHIP_TLSR82
|
||||
|
||||
config ARCH_CHIP_QEMU_ARM
|
||||
bool "QEMU virt platform (ARMv7a)"
|
||||
select ARCH_HAVE_PSCI
|
||||
select ARCH_HAVE_POWEROFF
|
||||
select ARCH_HAVE_RESET
|
||||
---help---
|
||||
QEMU virt platform (ARMv7a)
|
||||
|
||||
config ARCH_CHIP_GOLDFISH_ARM
|
||||
bool "GOLDFISH virt platform (ARMv7a)"
|
||||
select ARCH_HAVE_PSCI
|
||||
select ARCH_HAVE_POWEROFF
|
||||
select ARCH_HAVE_RESET
|
||||
---help---
|
||||
GOLDFISH virt platform (ARMv7a)
|
||||
|
||||
@@ -1064,6 +1070,16 @@ config ARM_THUMB
|
||||
bool "Thumb Mode"
|
||||
default n
|
||||
|
||||
config ARCH_HAVE_PSCI
|
||||
bool "ARM PCSI (Power State Coordination Interface) Support"
|
||||
default n
|
||||
---help---
|
||||
This Power State Coordination Interface (PSCI) defines
|
||||
a standard interface for power management. the PCSI need
|
||||
to implement handling firmware at EL2 or EL3. The option
|
||||
maybe not applicable for arm core without PCSI firmware
|
||||
interface implement
|
||||
|
||||
config ARM_HAVE_WFE_SEV
|
||||
bool
|
||||
default n
|
||||
|
||||
@@ -126,6 +126,31 @@
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Result from SMC/HVC call
|
||||
* a0-a7 result values from registers 0 to 7
|
||||
*/
|
||||
|
||||
struct arm_smccc_res
|
||||
{
|
||||
unsigned long a0;
|
||||
unsigned long a1;
|
||||
unsigned long a2;
|
||||
unsigned long a3;
|
||||
unsigned long a4;
|
||||
unsigned long a5;
|
||||
unsigned long a6;
|
||||
unsigned long a7;
|
||||
};
|
||||
|
||||
typedef struct arm_smccc_res arm_smccc_res_t;
|
||||
|
||||
enum arm_smccc_conduit
|
||||
{
|
||||
SMCCC_CONDUIT_NONE,
|
||||
SMCCC_CONDUIT_SMC,
|
||||
SMCCC_CONDUIT_HVC,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Inline functions
|
||||
****************************************************************************/
|
||||
@@ -316,6 +341,32 @@ static inline long smh_call(unsigned int nbr, void *parm)
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Make HVC calls
|
||||
*
|
||||
* param a0 function identifier
|
||||
* param a1-a7 parameters registers
|
||||
* param res results
|
||||
*/
|
||||
|
||||
void arm_smccc_hvc(unsigned long a0, unsigned long a1,
|
||||
unsigned long a2, unsigned long a3,
|
||||
unsigned long a4, unsigned long a5,
|
||||
unsigned long a6, unsigned long a7,
|
||||
struct arm_smccc_res *res);
|
||||
|
||||
/* Make SMC calls
|
||||
*
|
||||
* param a0 function identifier
|
||||
* param a1-a7 parameters registers
|
||||
* param res results
|
||||
*/
|
||||
|
||||
void arm_smccc_smc(unsigned long a0, unsigned long a1,
|
||||
unsigned long a2, unsigned long a3,
|
||||
unsigned long a4, unsigned long a5,
|
||||
unsigned long a6, unsigned long a7,
|
||||
struct arm_smccc_res *res);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
|
||||
@@ -55,6 +55,11 @@ if(NOT CONFIG_ARCH_IDLE_CUSTOM)
|
||||
list(APPEND SRCS arm_idle.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ARCH_HAVE_PSCI)
|
||||
list(APPEND SRCS arm_smccc.S)
|
||||
list(APPEND SRCS arm_cpu_psci.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_BUILD_PROTECTED OR CONFIG_BUILD_KERNEL)
|
||||
list(APPEND SRCS arm_task_start.c arm_pthread_start.c arm_signal_dispatch.c)
|
||||
|
||||
|
||||
@@ -41,6 +41,11 @@ ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y)
|
||||
CMN_CSRCS += arm_idle.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_HAVE_PSCI),y)
|
||||
CMN_ASRCS += arm_smccc.S
|
||||
CMN_CSRCS += arm_cpu_psci.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BUILD_PROTECTED)$(CONFIG_BUILD_KERNEL),y)
|
||||
CMN_CSRCS += arm_task_start.c arm_pthread_start.c
|
||||
CMN_CSRCS += arm_signal_dispatch.c
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
/***************************************************************************
|
||||
* arch/arm/src/common/arm_cpu_psci.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Included Files
|
||||
***************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/chip/chip.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arch/syscall.h"
|
||||
|
||||
#include "arm_cpu_psci.h"
|
||||
|
||||
/***************************************************************************
|
||||
* Private Data
|
||||
***************************************************************************/
|
||||
|
||||
static struct psci_interface psci_data;
|
||||
|
||||
/***************************************************************************
|
||||
* Private Functions
|
||||
***************************************************************************/
|
||||
|
||||
static int psci_to_dev_err(int ret)
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case PSCI_RET_SUCCESS:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
case PSCI_RET_NOT_SUPPORTED:
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
case PSCI_RET_INVALID_PARAMS:
|
||||
case PSCI_RET_INVALID_ADDRESS:
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
case PSCI_RET_DENIED:
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static unsigned long __invoke_psci_fn_hvc(unsigned long function_id,
|
||||
unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
unsigned long arg2)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
arm_smccc_hvc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
|
||||
return res.a0;
|
||||
}
|
||||
|
||||
static unsigned long __invoke_psci_fn_smc(unsigned long function_id,
|
||||
unsigned long arg0,
|
||||
unsigned long arg1,
|
||||
unsigned long arg2)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
|
||||
return res.a0;
|
||||
}
|
||||
|
||||
static uint32_t psci_get_version(void)
|
||||
{
|
||||
return psci_data.invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
|
||||
}
|
||||
|
||||
static int set_conduit_method(const char *method)
|
||||
{
|
||||
if (!strcmp("hvc", method))
|
||||
{
|
||||
psci_data.conduit = SMCCC_CONDUIT_HVC;
|
||||
psci_data.invoke_psci_fn = __invoke_psci_fn_hvc;
|
||||
}
|
||||
else if (!strcmp("smc", method))
|
||||
{
|
||||
psci_data.conduit = SMCCC_CONDUIT_SMC;
|
||||
psci_data.invoke_psci_fn = __invoke_psci_fn_smc;
|
||||
}
|
||||
else
|
||||
{
|
||||
serr("Invalid conduit method");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int psci_detect(void)
|
||||
{
|
||||
uint32_t ver = psci_get_version();
|
||||
|
||||
sinfo("Detected PSCI v%ld.%ld\n",
|
||||
PSCI_VERSION_MAJOR(ver), PSCI_VERSION_MINOR(ver));
|
||||
|
||||
if (PSCI_VERSION_MAJOR(ver) == 0 && PSCI_VERSION_MINOR(ver) < 2)
|
||||
{
|
||||
serr("PSCI unsupported version");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
psci_data.version = ver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Public Functions
|
||||
***************************************************************************/
|
||||
|
||||
uint32_t psci_version(void)
|
||||
{
|
||||
return psci_data.version;
|
||||
}
|
||||
|
||||
int psci_cpu_off(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (psci_data.conduit == SMCCC_CONDUIT_NONE)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = psci_data.invoke_psci_fn(PSCI_0_2_FN_CPU_OFF, 0, 0, 0);
|
||||
|
||||
return psci_to_dev_err(ret);
|
||||
}
|
||||
|
||||
int psci_cpu_reset(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (psci_data.conduit == SMCCC_CONDUIT_NONE)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = psci_data.invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
|
||||
|
||||
return psci_to_dev_err(ret);
|
||||
}
|
||||
|
||||
int psci_cpu_on(unsigned long cpuid, uintptr_t entry_point)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (psci_data.conduit == SMCCC_CONDUIT_NONE)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = psci_data.invoke_psci_fn(PSCI_FN_NATIVE(0_2, CPU_ON),
|
||||
cpuid, (unsigned long)entry_point, 0);
|
||||
|
||||
return psci_to_dev_err(ret);
|
||||
}
|
||||
|
||||
int psci_sys_reset(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (psci_data.conduit == SMCCC_CONDUIT_NONE)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = psci_data.invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
|
||||
|
||||
return psci_to_dev_err(ret);
|
||||
}
|
||||
|
||||
int psci_sys_poweroff(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (psci_data.conduit == SMCCC_CONDUIT_NONE)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = psci_data.invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
|
||||
|
||||
return psci_to_dev_err(ret);
|
||||
}
|
||||
|
||||
int arm_psci_init(const char * method)
|
||||
{
|
||||
psci_data.conduit = SMCCC_CONDUIT_NONE;
|
||||
|
||||
if (set_conduit_method(method))
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return psci_detect();
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/common/arm_cpu_psci.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_COMMON_ARM_CPU_PSCI_H
|
||||
#define __ARCH_ARM_SRC_COMMON_ARM_CPU_PSCI_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
#include <nuttx/config.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/chip/chip.h>
|
||||
#include <arch/syscall.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name
|
||||
|
||||
/* PSCI v0.2 interface */
|
||||
#define PSCI_0_2_FN_BASE 0x84000000
|
||||
#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n))
|
||||
#define PSCI_0_2_64BIT 0x40000000
|
||||
#define PSCI_0_2_FN64_BASE \
|
||||
(PSCI_0_2_FN_BASE + PSCI_0_2_64BIT)
|
||||
#define PSCI_0_2_FN64(n) (PSCI_0_2_FN64_BASE + (n))
|
||||
|
||||
#define PSCI_0_2_FN_PSCI_VERSION PSCI_0_2_FN(0)
|
||||
#define PSCI_0_2_FN_CPU_SUSPEND PSCI_0_2_FN(1)
|
||||
#define PSCI_0_2_FN_CPU_OFF PSCI_0_2_FN(2)
|
||||
#define PSCI_0_2_FN_CPU_ON PSCI_0_2_FN(3)
|
||||
#define PSCI_0_2_FN_AFFINITY_INFO PSCI_0_2_FN(4)
|
||||
#define PSCI_0_2_FN_MIGRATE PSCI_0_2_FN(5)
|
||||
#define PSCI_0_2_FN_MIGRATE_INFO_TYPE PSCI_0_2_FN(6)
|
||||
#define PSCI_0_2_FN_MIGRATE_INFO_UP_CPU PSCI_0_2_FN(7)
|
||||
#define PSCI_0_2_FN_SYSTEM_OFF PSCI_0_2_FN(8)
|
||||
#define PSCI_0_2_FN_SYSTEM_RESET PSCI_0_2_FN(9)
|
||||
|
||||
#define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1)
|
||||
#define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3)
|
||||
#define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4)
|
||||
#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5)
|
||||
#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7)
|
||||
|
||||
/* PSCI return values (inclusive of all PSCI versions) */
|
||||
#define PSCI_RET_SUCCESS 0
|
||||
#define PSCI_RET_NOT_SUPPORTED -1
|
||||
#define PSCI_RET_INVALID_PARAMS -2
|
||||
#define PSCI_RET_DENIED -3
|
||||
#define PSCI_RET_ALREADY_ON -4
|
||||
#define PSCI_RET_ON_PENDING -5
|
||||
#define PSCI_RET_INTERNAL_FAILURE -6
|
||||
#define PSCI_RET_NOT_PRESENT -7
|
||||
#define PSCI_RET_DISABLED -8
|
||||
#define PSCI_RET_INVALID_ADDRESS -9
|
||||
|
||||
/* PSCI version decoding (independent of PSCI version) */
|
||||
#define PSCI_VERSION_MAJOR_SHIFT 16
|
||||
#define PSCI_VERSION_MINOR_MASK \
|
||||
((1U << PSCI_VERSION_MAJOR_SHIFT) - 1)
|
||||
#define PSCI_VERSION_MAJOR_MASK ~PSCI_VERSION_MINOR_MASK
|
||||
|
||||
#define PSCI_VERSION_MAJOR(ver) \
|
||||
(((ver) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT)
|
||||
#define PSCI_VERSION_MINOR(ver) \
|
||||
((ver) & PSCI_VERSION_MINOR_MASK)
|
||||
|
||||
typedef unsigned long (*psci_fn)(unsigned long, unsigned long, unsigned long,
|
||||
unsigned long);
|
||||
|
||||
struct psci_interface
|
||||
{
|
||||
enum arm_smccc_conduit conduit;
|
||||
psci_fn invoke_psci_fn;
|
||||
uint32_t version;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
uint32_t psci_version(void);
|
||||
int psci_cpu_off(void);
|
||||
int psci_cpu_reset(void);
|
||||
int psci_cpu_on(unsigned long cpuid, uintptr_t entry_point);
|
||||
int psci_sys_poweroff(void);
|
||||
int psci_sys_reset(void);
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_COMMON_ARM_CPU_PSCI_H */
|
||||
@@ -323,6 +323,8 @@ void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits);
|
||||
|
||||
void arm_boot(void);
|
||||
|
||||
int arm_psci_init(const char *method);
|
||||
|
||||
/* Context switching */
|
||||
|
||||
uint32_t *arm_decodeirq(uint32_t *regs);
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/common/arm_smccc.S
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Symbols
|
||||
****************************************************************************/
|
||||
|
||||
.file "arm_smccc.S"
|
||||
|
||||
/****************************************************************************
|
||||
* Assembly Macros
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/* The SMC instruction is used to generate a synchronous exception that is
|
||||
* handled by Secure Monitor code running in EL3.
|
||||
*/
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
.global arm_smccc_smc
|
||||
.type arm_smccc_smc, function
|
||||
arm_smccc_smc:
|
||||
mov r12, sp
|
||||
push {r4-r7}
|
||||
ldm r12, {r4-r7}
|
||||
smc #0
|
||||
pop {r4-r7}
|
||||
ldr r12, [sp, #(4 * 4)]
|
||||
stm r12, {r0-r3}
|
||||
bx lr
|
||||
|
||||
/* The HVC instruction is used to generate a synchronous exception that is
|
||||
* handled by a hypervisor running in EL2.
|
||||
*/
|
||||
|
||||
.global arm_smccc_hvc
|
||||
.type arm_smccc_hvc, function
|
||||
arm_smccc_hvc:
|
||||
mov r12, sp
|
||||
push {r4-r7}
|
||||
ldm r12, {r4-r7}
|
||||
hvc #0
|
||||
pop {r4-r7}
|
||||
ldr r12, [sp, #(4 * 4)]
|
||||
stm r12, {r0-r3}
|
||||
bx lr
|
||||
@@ -22,3 +22,4 @@ include armv7-a/Make.defs
|
||||
|
||||
# goldfish-specific C source files
|
||||
CHIP_CSRCS = goldfish_boot.c goldfish_serial.c goldfish_irq.c goldfish_timer.c goldfish_memorymap.c
|
||||
|
||||
|
||||
@@ -55,6 +55,10 @@ void arm_boot(void)
|
||||
fdt_register((FAR const char *)0x40000000);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_HAVE_PSCI)
|
||||
arm_psci_init("smc");
|
||||
#endif
|
||||
|
||||
#ifdef USE_EARLYSERIALINIT
|
||||
/* Perform early serial initialization if we are going to use the serial
|
||||
* driver.
|
||||
|
||||
@@ -51,6 +51,10 @@ void arm_boot(void)
|
||||
|
||||
qemu_setupmappings();
|
||||
|
||||
#if defined(CONFIG_ARCH_HAVE_PSCI)
|
||||
arm_psci_init("hvc");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEVICE_TREE
|
||||
fdt_register((FAR const char *)0x40000000);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user