[libcpu/aarch64] add gicv3 support and bsp/rockchip/rk3568 (#5722)
* [libcpu/aarch64] add smp support * [libcpu/aarch64] rt_hw_trap_irq get irq instead of iar when using gicv2 * [libcpu/aarch64] disable irq/fiq when switch thread * [libcpu/aarch64] add gtimer frq set and stack align * [libcpu/aarch64] add gicv3 support and bsp/rockchip/rk3568
This commit is contained in:
parent
d23493d05d
commit
f587a55bc2
|
@ -167,6 +167,7 @@ jobs:
|
|||
- {RTT_BSP: "qemu-virt64-aarch64", RTT_TOOL_CHAIN: "sourcery-aarch64"}
|
||||
- {RTT_BSP: "raspberry-pi/raspi3-64", RTT_TOOL_CHAIN: "sourcery-aarch64"}
|
||||
- {RTT_BSP: "raspberry-pi/raspi4-64", RTT_TOOL_CHAIN: "sourcery-aarch64"}
|
||||
- {RTT_BSP: "rockchip/rk3568", RTT_TOOL_CHAIN: "sourcery-aarch64"}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
|
|
|
@ -96,17 +96,8 @@ CONFIG_RT_USING_USER_MAIN=y
|
|||
CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192
|
||||
CONFIG_RT_MAIN_THREAD_PRIORITY=10
|
||||
# CONFIG_RT_USING_LEGACY is not set
|
||||
|
||||
#
|
||||
# C++ features
|
||||
#
|
||||
# CONFIG_RT_USING_CPLUSPLUS is not set
|
||||
|
||||
#
|
||||
# Command shell
|
||||
#
|
||||
CONFIG_RT_USING_FINSH=y
|
||||
CONFIG_RT_USING_MSH=y
|
||||
CONFIG_RT_USING_FINSH=y
|
||||
CONFIG_FINSH_USING_MSH=y
|
||||
CONFIG_FINSH_THREAD_NAME="tshell"
|
||||
CONFIG_FINSH_THREAD_PRIORITY=20
|
||||
|
@ -120,10 +111,6 @@ CONFIG_FINSH_USING_DESCRIPTION=y
|
|||
# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
|
||||
# CONFIG_FINSH_USING_AUTH is not set
|
||||
CONFIG_FINSH_ARG_MAX=10
|
||||
|
||||
#
|
||||
# Device virtual file system
|
||||
#
|
||||
CONFIG_RT_USING_DFS=y
|
||||
CONFIG_DFS_USING_POSIX=y
|
||||
CONFIG_DFS_USING_WORKDIR=y
|
||||
|
@ -157,12 +144,15 @@ CONFIG_RT_DFS_ELM_MUTEX_TIMEOUT=3000
|
|||
CONFIG_RT_USING_DFS_DEVFS=y
|
||||
# CONFIG_RT_USING_DFS_ROMFS is not set
|
||||
# CONFIG_RT_USING_DFS_RAMFS is not set
|
||||
# CONFIG_RT_USING_FAL is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
#
|
||||
CONFIG_RT_USING_DEVICE_IPC=y
|
||||
# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
|
||||
CONFIG_RT_USING_SYSTEM_WORKQUEUE=y
|
||||
CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048
|
||||
CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23
|
||||
CONFIG_RT_USING_SERIAL=y
|
||||
CONFIG_RT_USING_SERIAL_V1=y
|
||||
# CONFIG_RT_USING_SERIAL_V2 is not set
|
||||
|
@ -202,7 +192,7 @@ CONFIG_RT_USING_ALARM=y
|
|||
# CONFIG_RT_USING_USB_DEVICE is not set
|
||||
|
||||
#
|
||||
# POSIX layer and C standard library
|
||||
# C/C++ and POSIX layer
|
||||
#
|
||||
CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
||||
|
||||
|
@ -226,36 +216,16 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
#
|
||||
# Socket is in the 'Network' category
|
||||
#
|
||||
# CONFIG_RT_USING_CPLUSPLUS is not set
|
||||
|
||||
#
|
||||
# Network
|
||||
#
|
||||
|
||||
#
|
||||
# Socket abstraction layer
|
||||
#
|
||||
# CONFIG_RT_USING_SAL is not set
|
||||
|
||||
#
|
||||
# Network interface device
|
||||
#
|
||||
# CONFIG_RT_USING_NETDEV is not set
|
||||
|
||||
#
|
||||
# light weight TCP/IP stack
|
||||
#
|
||||
# CONFIG_RT_USING_LWIP is not set
|
||||
|
||||
#
|
||||
# AT commands
|
||||
#
|
||||
# CONFIG_RT_USING_AT is not set
|
||||
|
||||
#
|
||||
# VBUS(Virtual Software BUS)
|
||||
#
|
||||
# CONFIG_RT_USING_VBUS is not set
|
||||
|
||||
#
|
||||
# Utilities
|
||||
#
|
||||
|
@ -264,6 +234,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# CONFIG_RT_USING_UTEST is not set
|
||||
# CONFIG_RT_USING_VAR_EXPORT is not set
|
||||
# CONFIG_RT_USING_RT_LINK is not set
|
||||
# CONFIG_RT_USING_VBUS is not set
|
||||
|
||||
#
|
||||
# RT-Thread Utestcases
|
||||
|
@ -277,6 +248,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
#
|
||||
# IoT - internet of things
|
||||
#
|
||||
# CONFIG_PKG_USING_LWIP is not set
|
||||
# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
|
||||
# CONFIG_PKG_USING_PAHOMQTT is not set
|
||||
# CONFIG_PKG_USING_UMQTT is not set
|
||||
|
@ -293,6 +265,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# CONFIG_PKG_USING_FREEMODBUS is not set
|
||||
# CONFIG_PKG_USING_LJSON is not set
|
||||
# CONFIG_PKG_USING_EZXML is not set
|
||||
# CONFIG_PKG_USING_SIMPLE_XML is not set
|
||||
# CONFIG_PKG_USING_NANOPB is not set
|
||||
|
||||
#
|
||||
|
@ -332,6 +305,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# CONFIG_PKG_USING_JOYLINK is not set
|
||||
# CONFIG_PKG_USING_EZ_IOT_OS is not set
|
||||
# CONFIG_PKG_USING_NIMBLE is not set
|
||||
# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
|
||||
# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
|
||||
# CONFIG_PKG_USING_IPMSG is not set
|
||||
# CONFIG_PKG_USING_LSSDP is not set
|
||||
|
@ -539,7 +513,8 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# CONFIG_PKG_USING_ARM_2D is not set
|
||||
# CONFIG_PKG_USING_MCUBOOT is not set
|
||||
# CONFIG_PKG_USING_TINYUSB is not set
|
||||
# CONFIG_PKG_USING_USB_STACK is not set
|
||||
# CONFIG_PKG_USING_CHERRYUSB is not set
|
||||
# CONFIG_PKG_USING_KMULTI_RTIMER is not set
|
||||
|
||||
#
|
||||
# peripheral libraries and drivers
|
||||
|
@ -563,6 +538,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# CONFIG_PKG_USING_WM_LIBRARIES is not set
|
||||
# CONFIG_PKG_USING_KENDRYTE_SDK is not set
|
||||
# CONFIG_PKG_USING_INFRARED is not set
|
||||
# CONFIG_PKG_USING_MULTI_INFRARED is not set
|
||||
# CONFIG_PKG_USING_AGILE_BUTTON is not set
|
||||
# CONFIG_PKG_USING_AGILE_LED is not set
|
||||
# CONFIG_PKG_USING_AT24CXX is not set
|
||||
|
@ -619,6 +595,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# CONFIG_PKG_USING_SOFT_SERIAL is not set
|
||||
# CONFIG_PKG_USING_MB85RS16 is not set
|
||||
# CONFIG_PKG_USING_CW2015 is not set
|
||||
# CONFIG_PKG_USING_RFM300 is not set
|
||||
|
||||
#
|
||||
# AI packages
|
||||
|
@ -637,6 +614,10 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# miscellaneous packages
|
||||
#
|
||||
|
||||
#
|
||||
# project laboratory
|
||||
#
|
||||
|
||||
#
|
||||
# samples: kernel and components samples
|
||||
#
|
||||
|
@ -669,6 +650,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# CONFIG_PKG_USING_CANFESTIVAL is not set
|
||||
# CONFIG_PKG_USING_ZLIB is not set
|
||||
# CONFIG_PKG_USING_MINIZIP is not set
|
||||
# CONFIG_PKG_USING_HEATSHRINK is not set
|
||||
# CONFIG_PKG_USING_DSTR is not set
|
||||
# CONFIG_PKG_USING_TINYFRAME is not set
|
||||
# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
|
||||
|
@ -686,6 +668,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
# CONFIG_PKG_USING_DESIGN_PATTERN is not set
|
||||
# CONFIG_PKG_USING_CONTROLLER is not set
|
||||
# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
|
||||
# CONFIG_PKG_USING_MFBD is not set
|
||||
CONFIG_SOC_VIRT64_AARCH64=y
|
||||
|
||||
#
|
||||
|
@ -696,5 +679,6 @@ CONFIG_RT_USING_UART0=y
|
|||
CONFIG_BSP_USING_RTC=y
|
||||
CONFIG_BSP_USING_ALARM=y
|
||||
CONFIG_BSP_USING_VIRTIO_BLK=y
|
||||
CONFIG_RT_USING_VIRTIO_BLK0=y
|
||||
CONFIG_BSP_USING_GIC=y
|
||||
CONFIG_BSP_USING_GICV2=y
|
||||
# CONFIG_BSP_USING_GICV3 is not set
|
||||
|
|
|
@ -19,9 +19,9 @@ Enter directory `rt-thread/bsp/qemu-virt64-aarch64` and input:
|
|||
scons
|
||||
```
|
||||
|
||||
## 2. Execution
|
||||
## 3. Execution
|
||||
|
||||
The project execution tool is `qemu-system-aarch64`
|
||||
The project execution tool is `qemu-system-aarch64`, the project can be configured to `Cortex-A53/A57/A72`, GIC supports `V2/V3` version, and `V2` of GIC can use 8 processors max.
|
||||
|
||||
Download Windows platform from website:
|
||||
```
|
||||
|
@ -33,7 +33,7 @@ sudo apt update
|
|||
sudo apt install qemu-system-arm
|
||||
```
|
||||
|
||||
Run qemu.bat or qemu.sh in terminal:
|
||||
Please fixup the exec scripts if modify the default configuration of the project. Run qemu.bat or qemu.sh in terminal:
|
||||
```
|
||||
heap: [0x40042aa0 - 0x40142aa0]
|
||||
|
||||
|
@ -45,10 +45,10 @@ Hi, this is RT-Thread!!
|
|||
msh />
|
||||
```
|
||||
|
||||
## 3. Condition
|
||||
## 4. Condition
|
||||
|
||||
| Driver | Condition | Remark |
|
||||
| ------ | --------- | ------ |
|
||||
| UART | Support | UART0 |
|
||||
| RTC | Support | - |
|
||||
| VIRTIO BLK | Support | VIRTIO BLK0 |
|
||||
| VIRTIO BLK | Support | - |
|
|
@ -22,7 +22,7 @@ scons
|
|||
|
||||
## 3. 执行
|
||||
|
||||
本工程执行环境为`qemu-system-aarch64`模拟器
|
||||
本工程执行环境为`qemu-system-aarch64`模拟器,工程可配置为使用`Cortex-A53/A57/A72`等芯片,GIC支持`V2/V3`版本,其中`V2`最多可配置8个处理器。
|
||||
|
||||
Windows平台下,可以在此获取到QEMU:
|
||||
```
|
||||
|
@ -34,7 +34,7 @@ sudo apt update
|
|||
sudo apt install qemu-system-arm
|
||||
```
|
||||
|
||||
在终端执行qemu.bat或qemu.sh可以看到程序运行:
|
||||
工程默认配置修改后请注意修改运行脚本。在终端执行qemu.bat或qemu.sh可以看到程序运行:
|
||||
```
|
||||
heap: [0x40042aa0 - 0x40142aa0]
|
||||
|
||||
|
@ -52,4 +52,4 @@ msh />
|
|||
| ------ | ---- | :------: |
|
||||
| UART | 支持 | UART0 |
|
||||
| RTC | 支持 | - |
|
||||
| VIRTIO BLK | 支持 | VIRTIO BLK0 |
|
||||
| VIRTIO BLK | 支持 | - |
|
|
@ -28,13 +28,19 @@ menu "AARCH64 qemu virt64 configs"
|
|||
bool "Using VirtIO BLK"
|
||||
default y
|
||||
|
||||
if BSP_USING_VIRTIO_BLK
|
||||
config RT_USING_VIRTIO_BLK0
|
||||
bool "Enabel VirtIO BLK 0"
|
||||
default y
|
||||
endif
|
||||
|
||||
config BSP_USING_GIC
|
||||
bool
|
||||
default y
|
||||
|
||||
choice
|
||||
prompt "GIC Version"
|
||||
default BSP_USING_GICV2
|
||||
|
||||
config BSP_USING_GICV2
|
||||
bool "GICv2"
|
||||
|
||||
config BSP_USING_GICV3
|
||||
bool "GICv3"
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "board.h"
|
||||
#include <mmu.h>
|
||||
#include <gic.h>
|
||||
#include <gicv3.h>
|
||||
#include <psci.h>
|
||||
#include <gtimer.h>
|
||||
#include <cpuport.h>
|
||||
|
@ -29,8 +30,14 @@ struct mem_desc platform_mem_desc[] =
|
|||
{0x40000000, 0x80000000, 0x40000000, NORMAL_MEM},
|
||||
{PL031_RTC_BASE, PL031_RTC_BASE + 0x1000, PL031_RTC_BASE, DEVICE_MEM},
|
||||
{PL011_UART0_BASE, PL011_UART0_BASE + 0x1000, PL011_UART0_BASE, DEVICE_MEM},
|
||||
{VIRTIO_MMIO_BLK0_BASE, VIRTIO_MMIO_BLK0_BASE + 0x1000, VIRTIO_MMIO_BLK0_BASE, DEVICE_MEM},
|
||||
{VIRTIO_MMIO_BASE, VIRTIO_MMIO_BASE + VIRTIO_MAX_NR * VIRTIO_MMIO_SIZE, VIRTIO_MMIO_BASE, DEVICE_MEM},
|
||||
#ifdef BSP_USING_GICV2
|
||||
{GIC_PL390_DISTRIBUTOR_PPTR, GIC_PL390_DISTRIBUTOR_PPTR + 0x1000, GIC_PL390_DISTRIBUTOR_PPTR, DEVICE_MEM},
|
||||
#endif
|
||||
#ifdef BSP_USING_GICV3
|
||||
{GIC_PL500_DISTRIBUTOR_PPTR, GIC_PL500_DISTRIBUTOR_PPTR + 0x1000, GIC_PL500_DISTRIBUTOR_PPTR, DEVICE_MEM},
|
||||
{GIC_PL500_REDISTRIBUTOR_PPTR, GIC_PL500_REDISTRIBUTOR_PPTR + 0xf60000, GIC_PL500_REDISTRIBUTOR_PPTR, DEVICE_MEM},
|
||||
#endif
|
||||
};
|
||||
|
||||
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
|
||||
|
@ -58,7 +65,7 @@ void rt_hw_board_init(void)
|
|||
rt_hw_gtimer_init();
|
||||
rt_thread_idle_sethook(idle_wfi);
|
||||
|
||||
arm_psci_init(RT_NULL, RT_NULL);
|
||||
arm_psci_init(PSCI_METHOD_HVC, RT_NULL, RT_NULL);
|
||||
|
||||
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
|
||||
/* set console device */
|
||||
|
@ -113,6 +120,9 @@ void secondary_cpu_c_start(void)
|
|||
rt_hw_spin_lock(&_cpus_lock);
|
||||
|
||||
arm_gic_cpu_init(0, platform_get_gic_cpu_base());
|
||||
#ifdef BSP_USING_GICV3
|
||||
arm_gic_redist_init(0, platform_get_gic_redist_base());
|
||||
#endif
|
||||
rt_hw_vector_init();
|
||||
rt_hw_gtimer_local_enable();
|
||||
arm_gic_umask(0, IRQ_ARM_IPI_KICK);
|
||||
|
|
|
@ -6,72 +6,18 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-5-30 Bernard the first version
|
||||
* 2021-07-31 GuEe-GUI add ARM GIC definitions
|
||||
* 2021-09-11 GuEe-GUI rename right macros for gic
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H__
|
||||
#define BOARD_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtdef.h>
|
||||
#include <stdint.h>
|
||||
#include <virt.h>
|
||||
|
||||
extern unsigned char __bss_start;
|
||||
extern unsigned char __bss_end;
|
||||
|
||||
#define RT_HW_HEAP_BEGIN (void*)&__bss_end
|
||||
#define RT_HW_HEAP_END (void*)(RT_HW_HEAP_BEGIN + 1 * 1024 * 1024)
|
||||
|
||||
#define __REG32(x) (*((volatile unsigned int *)(x)))
|
||||
|
||||
#define VIRTIO_SPI_IRQ_BASE 32
|
||||
|
||||
/* Virtio BLK */
|
||||
#define VIRTIO_MMIO_BLK0_BASE 0x0a000000
|
||||
#define VIRTIO_MMIO_BLK0_SIZE 0x00000200
|
||||
#define VIRTIO_MMIO_BLK0_IRQ (VIRTIO_SPI_IRQ_BASE + 0x10)
|
||||
|
||||
/* UART */
|
||||
#define PL011_UARTDR 0x000
|
||||
#define PL011_UARTFR 0x018
|
||||
#define PL011_UARTFR_TXFF_BIT 5
|
||||
#define PL011_UART0_BASE 0x09000000
|
||||
#define PL011_UART0_SIZE 0x00001000
|
||||
#define PL011_UART0_IRQNUM (VIRTIO_SPI_IRQ_BASE + 1)
|
||||
|
||||
/* RTC */
|
||||
#define PL031_RTC_BASE 0x9010000
|
||||
#define PL031_RTC_SIZE 0x00001000
|
||||
#define PL031_RTC_IRQNUM (VIRTIO_SPI_IRQ_BASE + 2)
|
||||
|
||||
/* DIST and CPU */
|
||||
#define GIC_PL390_DISTRIBUTOR_PPTR 0x08000000
|
||||
#define GIC_PL390_CONTROLLER_PPTR 0x08010000
|
||||
|
||||
#define MAX_HANDLERS 96
|
||||
#define GIC_IRQ_START 0
|
||||
/* number of interrupts on board */
|
||||
#define ARM_GIC_NR_IRQS 96
|
||||
/* only one GIC available */
|
||||
#define ARM_GIC_MAX_NR 1
|
||||
|
||||
/* ipi interrupt number */
|
||||
#define IRQ_ARM_IPI_KICK 0
|
||||
#define IRQ_ARM_IPI_CALL 1
|
||||
|
||||
#define IRQ_ARM_VTIMER 27
|
||||
|
||||
/* the basic constants and interfaces needed by gic */
|
||||
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
||||
{
|
||||
return GIC_PL390_DISTRIBUTOR_PPTR;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
|
||||
{
|
||||
return GIC_PL390_CONTROLLER_PPTR;
|
||||
}
|
||||
#define RT_HW_HEAP_END (void*)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024)
|
||||
|
||||
void rt_hw_board_init(void);
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
#include "board.h"
|
||||
|
||||
#define PL011_UARTDR 0x000
|
||||
#define PL011_UARTFR 0x018
|
||||
#define PL011_UARTFR_TXFF_BIT 5
|
||||
|
||||
unsigned int readl(volatile void *addr)
|
||||
{
|
||||
return *(volatile unsigned int *)addr;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-11-11 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <virtio.h>
|
||||
#ifdef BSP_USING_VIRTIO_BLK
|
||||
#include <virtio_blk.h>
|
||||
#endif
|
||||
|
||||
#include <board.h>
|
||||
|
||||
static virtio_device_init_handler virtio_device_init_handlers[] =
|
||||
{
|
||||
#ifdef BSP_USING_VIRTIO_BLK
|
||||
[VIRTIO_DEVICE_ID_BLOCK] = rt_virtio_blk_init,
|
||||
#endif
|
||||
};
|
||||
|
||||
int rt_virtio_devices_init(void)
|
||||
{
|
||||
int i;
|
||||
rt_uint32_t irq = VIRTIO_IRQ_BASE;
|
||||
rt_ubase_t mmio_base = VIRTIO_MMIO_BASE;
|
||||
struct virtio_mmio_config *mmio_config;
|
||||
virtio_device_init_handler init_handler;
|
||||
|
||||
if (sizeof(virtio_device_init_handlers) == 0)
|
||||
{
|
||||
/* The compiler will optimize the codes after here. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < VIRTIO_MAX_NR; ++i, ++irq, mmio_base += VIRTIO_MMIO_SIZE)
|
||||
{
|
||||
mmio_config = (struct virtio_mmio_config *)mmio_base;
|
||||
|
||||
if (mmio_config->magic != VIRTIO_MAGIC_VALUE ||
|
||||
mmio_config->version != RT_USING_VIRTIO_VERSION ||
|
||||
mmio_config->vendor_id != VIRTIO_VENDOR_ID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
init_handler = virtio_device_init_handlers[mmio_config->device_id];
|
||||
|
||||
if (init_handler != RT_NULL)
|
||||
{
|
||||
init_handler((rt_ubase_t *)mmio_base, irq);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_DEVICE_EXPORT(rt_virtio_devices_init);
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-11-11 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_VIRTIO_H__
|
||||
#define __DRV_VIRTIO_H__
|
||||
|
||||
int rt_virtio_devices_init(void);
|
||||
|
||||
#endif /* __DRV_VIRTIO_H__ */
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-02-17 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#ifndef VIRT_H__
|
||||
#define VIRT_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
/* UART */
|
||||
#define PL011_UART0_BASE 0x09000000
|
||||
#define PL011_UART0_SIZE 0x00001000
|
||||
#define PL011_UART0_IRQNUM (32 + 1)
|
||||
|
||||
/* RTC */
|
||||
#define PL031_RTC_BASE 0x9010000
|
||||
#define PL031_RTC_SIZE 0x00001000
|
||||
#define PL031_RTC_IRQNUM (32 + 2)
|
||||
|
||||
/* VirtIO */
|
||||
#define VIRTIO_MMIO_BASE 0x0a000000
|
||||
#define VIRTIO_MMIO_SIZE 0x00000200
|
||||
#define VIRTIO_MAX_NR 32
|
||||
#define VIRTIO_IRQ_BASE (32 + 16)
|
||||
#define VIRTIO_VENDOR_ID 0x554d4551 /* "QEMU" */
|
||||
|
||||
/* GIC */
|
||||
#define MAX_HANDLERS 96
|
||||
#define GIC_IRQ_START 0
|
||||
#define ARM_GIC_NR_IRQS 96
|
||||
#define ARM_GIC_MAX_NR 1
|
||||
|
||||
#define IRQ_ARM_IPI_KICK 0
|
||||
#define IRQ_ARM_IPI_CALL 1
|
||||
|
||||
/* GICv2 */
|
||||
#define GIC_PL390_DISTRIBUTOR_PPTR 0x08000000
|
||||
#define GIC_PL390_CONTROLLER_PPTR 0x08010000
|
||||
|
||||
/* GICv3 */
|
||||
#define GIC_PL500_DISTRIBUTOR_PPTR GIC_PL390_DISTRIBUTOR_PPTR
|
||||
#define GIC_PL500_REDISTRIBUTOR_PPTR 0x080a0000
|
||||
#define GIC_PL500_CONTROLLER_PPTR GIC_PL390_CONTROLLER_PPTR
|
||||
#define GIC_PL500_ITS_PPTR 0x08080000
|
||||
|
||||
/* the basic constants and interfaces needed by gic */
|
||||
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
||||
{
|
||||
#ifdef BSP_USING_GICV2
|
||||
return GIC_PL390_DISTRIBUTOR_PPTR;
|
||||
#else
|
||||
return GIC_PL500_DISTRIBUTOR_PPTR;
|
||||
#endif
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_redist_base(void)
|
||||
{
|
||||
return GIC_PL500_REDISTRIBUTOR_PPTR;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
|
||||
{
|
||||
#ifdef BSP_USING_GICV2
|
||||
return GIC_PL390_CONTROLLER_PPTR;
|
||||
#else
|
||||
return GIC_PL500_CONTROLLER_PPTR;
|
||||
#endif
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_its_base(void)
|
||||
{
|
||||
return GIC_PL500_ITS_PPTR;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,405 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-9-16 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rtconfig.h>
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <cpuport.h>
|
||||
#include <board.h>
|
||||
|
||||
#include "virtio.h"
|
||||
#include "virtio_mmio.h"
|
||||
#include "drv_virtio_blk.h"
|
||||
|
||||
#ifdef BSP_USING_VIRTIO_BLK
|
||||
|
||||
#ifdef RT_USING_VIRTIO_BLK0
|
||||
static struct virtio_blk blk0;
|
||||
static struct virtio_blk_device virtio_blk_dev0;
|
||||
#endif /* RT_USING_VIRTIO_BLK0 */
|
||||
|
||||
static int alloc_desc(struct virtio_blk *blk)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < QUEUE_SIZE; i++)
|
||||
{
|
||||
if (blk->free[i])
|
||||
{
|
||||
blk->free[i] = 0;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
static void free_desc(struct virtio_blk *blk, int i)
|
||||
{
|
||||
if (i >= QUEUE_SIZE)
|
||||
{
|
||||
rt_kprintf("Out of queue number");
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
if (blk0.free[i])
|
||||
{
|
||||
rt_kprintf("Already freed");
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
blk->desc[i].addr = 0;
|
||||
blk->desc[i].len = 0;
|
||||
blk->desc[i].flags = 0;
|
||||
blk->desc[i].next = 0;
|
||||
blk->free[i] = 1;
|
||||
}
|
||||
|
||||
static void free_chain(struct virtio_blk *blk, int i)
|
||||
{
|
||||
int flag, nxt;
|
||||
for (;;)
|
||||
{
|
||||
flag = blk->desc[i].flags;
|
||||
nxt = blk->desc[i].next;
|
||||
|
||||
free_desc(blk, i);
|
||||
|
||||
if (flag & VRING_DESC_F_NEXT)
|
||||
{
|
||||
i = nxt;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int alloc3_desc(struct virtio_blk *blk, int *idx)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
idx[i] = alloc_desc(blk);
|
||||
if (idx[i] < 0)
|
||||
{
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
free_desc(blk, idx[j]);
|
||||
}
|
||||
return -RT_ERROR;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virtio_blk_device_init(struct virtio_blk_device *virtio_blk_dev)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
uint32_t max;
|
||||
uint64_t features;
|
||||
int i;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_lock_init(&virtio_blk_dev->spinlock);
|
||||
#endif
|
||||
|
||||
if (virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_MAGIC_VALUE) != VIRTIO_MMIO_MAGIC ||
|
||||
virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_VERSION) != 1 ||
|
||||
virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_DEVICE_ID) != 2 ||
|
||||
virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_VENDOR_ID) != VIRTIO_MMIO_VENDOR)
|
||||
{
|
||||
rt_kprintf("Could not find virtio disk");
|
||||
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
status |= VIRTIO_STAT_ACKNOWLEDGE;
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_STATUS, status);
|
||||
|
||||
status |= VIRTIO_STAT_DRIVER;
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_STATUS, status);
|
||||
|
||||
/* negotiate features */
|
||||
features = virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_DEVICE_FEATURES);
|
||||
features &= ~(1 << VIRTIO_BLK_F_RO);
|
||||
features &= ~(1 << VIRTIO_BLK_F_SCSI);
|
||||
features &= ~(1 << VIRTIO_BLK_F_CONFIG_WCE);
|
||||
features &= ~(1 << VIRTIO_BLK_F_MQ);
|
||||
features &= ~(1 << VIRTIO_F_ANY_LAYOUT);
|
||||
features &= ~(1 << VIRTIO_RING_F_EVENT_IDX);
|
||||
features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_DRIVER_FEATURES, features);
|
||||
|
||||
/* tell device that feature negotiation is complete */
|
||||
status |= VIRTIO_STAT_FEATURES_OK;
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_STATUS, status);
|
||||
|
||||
/* tell device we're completely ready */
|
||||
status |= VIRTIO_STAT_DRIVER_OK;
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_STATUS, status);
|
||||
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_GUEST_PAGE_SIZE, PAGE_SIZE);
|
||||
|
||||
/* initialize queue 0 */
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_SEL, 0);
|
||||
|
||||
max = virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_NUM_MAX);
|
||||
if (max == 0)
|
||||
{
|
||||
rt_kprintf("Virtio disk has no queue 0");
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
if (max < QUEUE_SIZE)
|
||||
{
|
||||
rt_kprintf("Virtio disk max queue too short");
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_NUM, QUEUE_SIZE);
|
||||
|
||||
rt_memset(virtio_blk_dev->blk->pages, 0, sizeof(virtio_blk_dev->blk->pages));
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_PFN, ((uint64_t)blk0.pages) >> PAGE_SHIFT);
|
||||
|
||||
virtio_blk_dev->blk->desc = (struct virtq_desc *)virtio_blk_dev->blk->pages;
|
||||
virtio_blk_dev->blk->avail = (struct virtq_avail *)(virtio_blk_dev->blk->pages + QUEUE_SIZE * sizeof(struct virtq_desc));
|
||||
virtio_blk_dev->blk->used = (struct virtq_used *)(virtio_blk_dev->blk->pages + PAGE_SIZE);
|
||||
|
||||
/* all QUEUE_SIZE descriptors start out unused */
|
||||
for (i = 0; i < QUEUE_SIZE; ++i)
|
||||
{
|
||||
virtio_blk_dev->blk->free[i] = 1;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void virtio_blk_rw(struct virtio_blk_device *virtio_blk_dev, struct virtio_blk_buf *buf, int flag)
|
||||
{
|
||||
struct virtio_blk *blk = virtio_blk_dev->blk;
|
||||
uint64_t sector = buf->block_no * (VIRTIO_BLK_BUF_DATA_SIZE / 512);
|
||||
int idx[3];
|
||||
struct virtio_blk_req *req;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_base_t level;
|
||||
|
||||
level = rt_spin_lock_irqsave(&virtio_blk_dev->spinlock);
|
||||
#endif
|
||||
|
||||
/* allocate the three descriptors */
|
||||
for (;;)
|
||||
{
|
||||
if (alloc3_desc(blk, idx) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
req = &(blk->ops[idx[0]]);
|
||||
req->type = flag;
|
||||
req->reserved = 0;
|
||||
req->sector = sector;
|
||||
|
||||
blk->desc[idx[0]].addr = (uint64_t)req;
|
||||
blk->desc[idx[0]].len = sizeof(struct virtio_blk_req);
|
||||
blk->desc[idx[0]].flags = VRING_DESC_F_NEXT;
|
||||
blk->desc[idx[0]].next = idx[1];
|
||||
|
||||
blk->desc[idx[1]].addr = (uint64_t)buf->data;
|
||||
blk->desc[idx[1]].len = VIRTIO_BLK_BUF_DATA_SIZE;
|
||||
|
||||
blk->desc[idx[1]].flags = flag ? 0 : VRING_DESC_F_WRITE;
|
||||
|
||||
blk->desc[idx[1]].flags |= VRING_DESC_F_NEXT;
|
||||
blk->desc[idx[1]].next = idx[2];
|
||||
|
||||
/* device writes 0 on success */
|
||||
blk->info[idx[0]].status = 0xff;
|
||||
blk->desc[idx[2]].addr = (uint64_t)&(blk->info[idx[0]].status);
|
||||
blk->desc[idx[2]].len = 1;
|
||||
/* device writes the status */
|
||||
blk->desc[idx[2]].flags = VRING_DESC_F_WRITE;
|
||||
blk->desc[idx[2]].next = 0;
|
||||
|
||||
/* record struct buf for virtio_blk_isr() */
|
||||
buf->valid = 1;
|
||||
blk->info[idx[0]].buf = buf;
|
||||
|
||||
/* tell the device the first index in our chain of descriptors */
|
||||
blk->avail->ring[blk->avail->idx % QUEUE_SIZE] = idx[0];
|
||||
|
||||
rt_hw_dsb();
|
||||
|
||||
/* tell the device another avail ring entry is available */
|
||||
blk->avail->idx += 1;
|
||||
|
||||
rt_hw_dsb();
|
||||
|
||||
/* value is queue number */
|
||||
virtio_mmio_write32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_QUEUE_NOTIFY, 0);
|
||||
|
||||
/* wait for virtio_blk_isr() to done */
|
||||
while (buf->valid == 1)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_unlock_irqrestore(&virtio_blk_dev->spinlock, level);
|
||||
#endif
|
||||
rt_thread_yield();
|
||||
#ifdef RT_USING_SMP
|
||||
level = rt_spin_lock_irqsave(&virtio_blk_dev->spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
blk->info[idx[0]].buf = 0;
|
||||
free_chain(blk, idx[0]);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_unlock_irqrestore(&virtio_blk_dev->spinlock, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void virtio_blk_isr(int irqno, void *param)
|
||||
{
|
||||
int id;
|
||||
struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)param;
|
||||
struct virtio_blk *blk = virtio_blk_dev->blk;
|
||||
struct virtio_blk_buf *buf_tmp;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_base_t level;
|
||||
|
||||
level = rt_spin_lock_irqsave(&virtio_blk_dev->spinlock);
|
||||
#endif
|
||||
|
||||
virtio_mmio_write32(
|
||||
virtio_blk_dev->mmio_base,
|
||||
VIRTIO_MMIO_INTERRUPT_ACK,
|
||||
virtio_mmio_read32(virtio_blk_dev->mmio_base, VIRTIO_MMIO_INTERRUPT_STATUS) & 0x3);
|
||||
|
||||
rt_hw_dsb();
|
||||
|
||||
/*
|
||||
* the device increments disk.used->idx
|
||||
* when it adds an entry to the used ring
|
||||
*/
|
||||
while (blk->used_idx != blk->used->idx)
|
||||
{
|
||||
rt_hw_dsb();
|
||||
id = blk->used->ring[blk->used_idx % QUEUE_SIZE].id;
|
||||
|
||||
if (blk->info[id].status != 0)
|
||||
{
|
||||
rt_kprintf("Virtio BLK Status");
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
||||
buf_tmp = blk->info[id].buf;
|
||||
|
||||
/* done with buf */
|
||||
buf_tmp->valid = 0;
|
||||
rt_thread_yield();
|
||||
|
||||
blk->used_idx += 1;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_unlock_irqrestore(&virtio_blk_dev->spinlock, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
static rt_err_t virtio_blk_init(rt_device_t dev)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t virtio_blk_open(rt_device_t dev, rt_uint16_t oflag)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t virtio_blk_close(rt_device_t dev)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_size_t virtio_blk_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
||||
{
|
||||
struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)dev;
|
||||
struct virtio_blk_buf buf =
|
||||
{
|
||||
.block_no = (uint32_t)pos,
|
||||
.data = (uint8_t *)buffer
|
||||
};
|
||||
|
||||
virtio_blk_rw(virtio_blk_dev, &buf, VIRTIO_BLK_T_IN);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_size_t virtio_blk_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
||||
{
|
||||
struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)dev;
|
||||
struct virtio_blk_buf buf =
|
||||
{
|
||||
.block_no = (uint32_t)pos,
|
||||
.data = (uint8_t *)buffer
|
||||
};
|
||||
|
||||
virtio_blk_rw(virtio_blk_dev, &buf, VIRTIO_BLK_T_OUT);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_err_t virtio_blk_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
|
||||
{
|
||||
struct rt_device_blk_geometry *geometry;
|
||||
|
||||
geometry = (struct rt_device_blk_geometry *)args;
|
||||
if (geometry == RT_NULL)
|
||||
{
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
geometry->bytes_per_sector = VIRTIO_BLK_BYTES_PER_SECTOR;
|
||||
geometry->block_size = VIRTIO_BLK_BLOCK_SIZE;
|
||||
geometry->sector_count = VIRTIO_BLK_SECTOR_COUNT;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
const static struct rt_device_ops virtio_blk_ops =
|
||||
{
|
||||
virtio_blk_init,
|
||||
virtio_blk_open,
|
||||
virtio_blk_close,
|
||||
virtio_blk_read,
|
||||
virtio_blk_write,
|
||||
virtio_blk_control
|
||||
};
|
||||
|
||||
int rt_virtio_blk_init(void)
|
||||
{
|
||||
rt_err_t status = RT_EOK;
|
||||
|
||||
#ifdef RT_USING_VIRTIO_BLK0
|
||||
virtio_blk_dev0.parent.type = RT_Device_Class_Block;
|
||||
virtio_blk_dev0.parent.ops = &virtio_blk_ops;
|
||||
virtio_blk_dev0.blk = &blk0;
|
||||
virtio_blk_dev0.mmio_base = (uint32_t *)VIRTIO_MMIO_BLK0_BASE;
|
||||
|
||||
status = virtio_blk_device_init(&virtio_blk_dev0);
|
||||
rt_device_register((rt_device_t)&virtio_blk_dev0, "virtio-blk0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
|
||||
rt_hw_interrupt_install(VIRTIO_MMIO_BLK0_IRQ, virtio_blk_isr, &virtio_blk_dev0, "virtio-blk0");
|
||||
rt_hw_interrupt_umask(VIRTIO_MMIO_BLK0_IRQ);
|
||||
#endif /* RT_USING_VIRTIO_BLK0 */
|
||||
|
||||
return status;
|
||||
}
|
||||
INIT_DEVICE_EXPORT(rt_virtio_blk_init);
|
||||
#endif /* BSP_USING_VIRTIO_BLK */
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-9-16 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#ifndef DRV_VIRTIO_BLK_H__
|
||||
#define DRV_VIRTIO_BLK_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <stdint.h>
|
||||
#include "virtio.h"
|
||||
|
||||
#define VIRTIO_BLK_BUF_DATA_SIZE 512
|
||||
#define VIRTIO_BLK_BYTES_PER_SECTOR 512
|
||||
#define VIRTIO_BLK_BLOCK_SIZE 512
|
||||
#define VIRTIO_BLK_SECTOR_COUNT 0x40000 /* 128MB */
|
||||
|
||||
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
|
||||
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
|
||||
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
|
||||
#define VIRTIO_BLK_F_MQ 12 /* Support more than one vq */
|
||||
|
||||
#define VIRTIO_BLK_T_IN 0 /* Read the blk */
|
||||
#define VIRTIO_BLK_T_OUT 1 /* Write the blk */
|
||||
|
||||
#define VIRTIO_F_ANY_LAYOUT 27
|
||||
#define VIRTIO_RING_F_INDIRECT_DESC 28
|
||||
#define VIRTIO_RING_F_EVENT_IDX 29
|
||||
|
||||
struct virtio_blk_buf
|
||||
{
|
||||
int valid;
|
||||
uint32_t block_no;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
struct virtio_blk_req
|
||||
{
|
||||
uint32_t type;
|
||||
uint32_t reserved;
|
||||
uint64_t sector;
|
||||
};
|
||||
|
||||
/*
|
||||
* virtio_blk must be a static variable because
|
||||
* pages must consist of two contiguous pages of
|
||||
* page-aligned physical memory
|
||||
*/
|
||||
struct virtio_blk
|
||||
{
|
||||
char pages[2 * PAGE_SIZE];
|
||||
struct virtq_desc *desc;
|
||||
struct virtq_avail *avail;
|
||||
struct virtq_used *used;
|
||||
|
||||
char free[QUEUE_SIZE];
|
||||
uint16_t used_idx;
|
||||
struct
|
||||
{
|
||||
struct virtio_blk_buf *buf;
|
||||
char status;
|
||||
} info[QUEUE_SIZE];
|
||||
|
||||
struct virtio_blk_req ops[QUEUE_SIZE];
|
||||
} __attribute__ ((aligned (PAGE_SIZE)));
|
||||
|
||||
struct virtio_blk_device
|
||||
{
|
||||
struct rt_device parent;
|
||||
struct virtio_blk *blk;
|
||||
|
||||
uint32_t *mmio_base;
|
||||
#ifdef RT_USING_SMP
|
||||
struct rt_spinlock spinlock;
|
||||
#endif
|
||||
};
|
||||
|
||||
int rt_hw_virtio_blk_init(void);
|
||||
|
||||
#endif /* DRV_VIRTIO_BLK_H__ */
|
|
@ -0,0 +1,274 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-11-11 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
#include <virtio.h>
|
||||
|
||||
rt_inline void _virtio_dev_check(struct virtio_device *dev)
|
||||
{
|
||||
RT_ASSERT(dev != RT_NULL);
|
||||
RT_ASSERT(dev->mmio_config != RT_NULL);
|
||||
}
|
||||
|
||||
void virtio_reset_device(struct virtio_device *dev)
|
||||
{
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
dev->mmio_config->status = 0;
|
||||
}
|
||||
|
||||
void virtio_status_acknowledge_driver(struct virtio_device *dev)
|
||||
{
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
dev->mmio_config->status |= VIRTIO_STATUS_ACKNOWLEDGE | VIRTIO_STATUS_DRIVER;
|
||||
}
|
||||
|
||||
void virtio_status_driver_ok(struct virtio_device *dev)
|
||||
{
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
dev->mmio_config->status |= VIRTIO_STATUS_FEATURES_OK | VIRTIO_STATUS_DRIVER_OK;
|
||||
}
|
||||
|
||||
void virtio_interrupt_ack(struct virtio_device *dev, rt_uint32_t ack)
|
||||
{
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
dev->mmio_config->interrupt_ack = ack;
|
||||
}
|
||||
|
||||
rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t ring_size)
|
||||
{
|
||||
int i;
|
||||
void *pages;
|
||||
rt_ubase_t pages_paddr;
|
||||
rt_size_t pages_total_size;
|
||||
struct virtq *queue;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
RT_ASSERT(dev->mmio_config->queue_num_max > 0);
|
||||
RT_ASSERT(dev->mmio_config->queue_num_max > queue_index);
|
||||
/* ring_size is power of 2 */
|
||||
RT_ASSERT(ring_size > 0);
|
||||
RT_ASSERT(((ring_size - 1) & ring_size) == 0);
|
||||
|
||||
queue = &dev->queues[queue_index];
|
||||
pages_total_size = VIRTIO_PAGE_ALIGN(
|
||||
VIRTQ_DESC_TOTAL_SIZE(ring_size) + VIRTQ_AVAIL_TOTAL_SIZE(ring_size) + VIRTQ_USED_TOTAL_SIZE(ring_size));
|
||||
|
||||
pages = rt_malloc_align(pages_total_size, VIRTIO_PAGE_SIZE);
|
||||
|
||||
if (pages == RT_NULL)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
queue->free = rt_malloc(sizeof(rt_bool_t) * ring_size);
|
||||
|
||||
if (queue->free == RT_NULL)
|
||||
{
|
||||
rt_free_align(pages);
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
rt_memset(pages, 0, pages_total_size);
|
||||
pages_paddr = VIRTIO_VA2PA(pages);
|
||||
|
||||
dev->mmio_config->guest_page_size = VIRTIO_PAGE_SIZE;
|
||||
dev->mmio_config->queue_sel = queue_index;
|
||||
dev->mmio_config->queue_num = ring_size;
|
||||
dev->mmio_config->queue_align = VIRTIO_PAGE_SIZE;
|
||||
dev->mmio_config->queue_pfn = pages_paddr >> VIRTIO_PAGE_SHIFT;
|
||||
|
||||
queue->num = ring_size;
|
||||
queue->desc = (struct virtq_desc *)pages_paddr;
|
||||
queue->avail = (struct virtq_avail *)(pages_paddr + VIRTQ_DESC_TOTAL_SIZE(ring_size));
|
||||
queue->used = (struct virtq_used *)VIRTIO_PAGE_ALIGN(
|
||||
(rt_ubase_t)&queue->avail->ring[ring_size] + VIRTQ_AVAIL_RES_SIZE);
|
||||
|
||||
queue->used_idx = 0;
|
||||
|
||||
/* All descriptors start out unused */
|
||||
for (i = 0; i < ring_size; ++i)
|
||||
{
|
||||
queue->free[i] = RT_TRUE;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void virtio_queue_destroy(struct virtio_device *dev, rt_uint32_t queue_index)
|
||||
{
|
||||
struct virtq *queue;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
RT_ASSERT(dev->mmio_config->queue_num_max > 0);
|
||||
RT_ASSERT(dev->mmio_config->queue_num_max > queue_index);
|
||||
|
||||
queue = &dev->queues[queue_index];
|
||||
|
||||
RT_ASSERT(queue->num > 0);
|
||||
|
||||
rt_free(queue->free);
|
||||
rt_free_align((void *)queue->desc);
|
||||
|
||||
dev->mmio_config->queue_sel = queue_index;
|
||||
dev->mmio_config->queue_pfn = RT_NULL;
|
||||
|
||||
queue->num = 0;
|
||||
queue->desc = RT_NULL;
|
||||
queue->avail = RT_NULL;
|
||||
queue->used = RT_NULL;
|
||||
}
|
||||
|
||||
void virtio_queue_notify(struct virtio_device *dev, rt_uint32_t queue_index)
|
||||
{
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
dev->mmio_config->queue_notify = queue_index;
|
||||
}
|
||||
|
||||
void virtio_submit_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index)
|
||||
{
|
||||
rt_size_t ring_size;
|
||||
struct virtq *queue;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
queue = &dev->queues[queue_index];
|
||||
ring_size = queue->num;
|
||||
|
||||
/* Tell the device the first index in our chain of descriptors */
|
||||
queue->avail->ring[queue->avail->idx % ring_size] = desc_index;
|
||||
rt_hw_dsb();
|
||||
|
||||
/* Tell the device another avail ring entry is available */
|
||||
queue->avail->idx++;
|
||||
rt_hw_dsb();
|
||||
}
|
||||
|
||||
rt_uint16_t virtio_alloc_desc(struct virtio_device *dev, rt_uint32_t queue_index)
|
||||
{
|
||||
int i;
|
||||
rt_size_t ring_size;
|
||||
struct virtq *queue;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
RT_ASSERT(queue_index < RT_USING_VIRTIO_QUEUE_MAX_NR);
|
||||
|
||||
queue = &dev->queues[queue_index];
|
||||
ring_size = queue->num;
|
||||
|
||||
for (i = 0; i < ring_size; ++i)
|
||||
{
|
||||
if (queue->free[i])
|
||||
{
|
||||
queue->free[i] = RT_FALSE;
|
||||
|
||||
return (rt_uint16_t)i;
|
||||
}
|
||||
}
|
||||
|
||||
return RT_UINT16_MAX;
|
||||
}
|
||||
|
||||
void virtio_free_desc(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index)
|
||||
{
|
||||
struct virtq *queue;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
queue = &dev->queues[queue_index];
|
||||
|
||||
RT_ASSERT(queue_index + 1 < RT_USING_VIRTIO_QUEUE_MAX_NR);
|
||||
RT_ASSERT(!queue->free[desc_index]);
|
||||
|
||||
queue->desc[desc_index].addr = 0;
|
||||
queue->desc[desc_index].len = 0;
|
||||
queue->desc[desc_index].flags = 0;
|
||||
queue->desc[desc_index].next = 0;
|
||||
|
||||
queue->free[desc_index] = RT_TRUE;
|
||||
}
|
||||
|
||||
rt_err_t virtio_alloc_desc_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t count,
|
||||
rt_uint16_t *indexs)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
RT_ASSERT(indexs != RT_NULL);
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
indexs[i] = virtio_alloc_desc(dev, queue_index);
|
||||
|
||||
if (indexs[i] == RT_UINT16_MAX)
|
||||
{
|
||||
for (j = 0; j < i; ++j)
|
||||
{
|
||||
virtio_free_desc(dev, queue_index, indexs[j]);
|
||||
}
|
||||
|
||||
return -RT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void virtio_free_desc_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index)
|
||||
{
|
||||
rt_uint16_t flags, next;
|
||||
struct virtq_desc *desc;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
desc = &dev->queues[queue_index].desc[0];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
flags = desc[desc_index].flags;
|
||||
next = desc[desc_index].next;
|
||||
|
||||
virtio_free_desc(dev, queue_index, desc_index);
|
||||
|
||||
if (flags & VIRTQ_DESC_F_NEXT)
|
||||
{
|
||||
desc_index = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void virtio_fill_desc(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index,
|
||||
rt_uint64_t addr, rt_uint32_t len, rt_uint16_t flags, rt_uint16_t next)
|
||||
{
|
||||
struct virtq_desc *desc;
|
||||
|
||||
_virtio_dev_check(dev);
|
||||
|
||||
desc = &dev->queues[queue_index].desc[desc_index];
|
||||
|
||||
desc->addr = addr;
|
||||
desc->len = len;
|
||||
desc->flags = flags;
|
||||
desc->next = next;
|
||||
}
|
|
@ -6,55 +6,115 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-9-16 GuEe-GUI the first version
|
||||
* 2021-11-11 GuEe-GUI modify to virtio common interface
|
||||
*/
|
||||
|
||||
#ifndef VIRTIO_H__
|
||||
#define VIRTIO_H__
|
||||
#ifndef __VIRTIO_H__
|
||||
#define __VIRTIO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <rthw.h>
|
||||
#include <rtdef.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define PAGE_SHIFT 12
|
||||
#ifndef RT_USING_VIRTIO_VERSION
|
||||
#define RT_USING_VIRTIO_VERSION 0x1
|
||||
#endif
|
||||
|
||||
#define VIRTIO_STAT_ACKNOWLEDGE 1
|
||||
#define VIRTIO_STAT_DRIVER 2
|
||||
#define VIRTIO_STAT_DRIVER_OK 4
|
||||
#define VIRTIO_STAT_FEATURES_OK 8
|
||||
#define VIRTIO_STAT_NEEDS_RESET 64
|
||||
#define VIRTIO_STAT_FAILED 128
|
||||
#ifndef RT_USING_VIRTIO_QUEUE_MAX_NR
|
||||
#define RT_USING_VIRTIO_QUEUE_MAX_NR 4
|
||||
#endif
|
||||
|
||||
#define QUEUE_SIZE 8
|
||||
#include <virtio_mmio.h>
|
||||
#include <virtio_queue.h>
|
||||
|
||||
struct virtq_desc
|
||||
#define VIRTIO_MAGIC_VALUE 0x74726976 /* "virt" */
|
||||
|
||||
#define VIRTIO_STATUS_ACKNOWLEDGE (1 << 0)
|
||||
#define VIRTIO_STATUS_DRIVER (1 << 1)
|
||||
#define VIRTIO_STATUS_DRIVER_OK (1 << 2)
|
||||
#define VIRTIO_STATUS_FEATURES_OK (1 << 3)
|
||||
#define VIRTIO_STATUS_NEEDS_RESET (1 << 6)
|
||||
#define VIRTIO_STATUS_FAILED (1 << 7)
|
||||
|
||||
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
|
||||
#define VIRTIO_F_ANY_LAYOUT 27
|
||||
#define VIRTIO_F_RING_INDIRECT_DESC 28
|
||||
#define VIRTIO_F_RING_EVENT_IDX 29
|
||||
#define VIRTIO_F_VERSION_1 32
|
||||
#define VIRTIO_F_RING_PACKED 34
|
||||
|
||||
#define VIRTIO_VA2PA(vaddr) ((rt_ubase_t)vaddr)
|
||||
#define VIRTIO_PAGE_SHIFT 12
|
||||
#define VIRTIO_PAGE_SIZE (1 << VIRTIO_PAGE_SHIFT)
|
||||
#define VIRTIO_PAGE_ALIGN(addr) (RT_ALIGN(addr, VIRTIO_PAGE_SIZE))
|
||||
|
||||
enum
|
||||
{
|
||||
uint64_t addr;
|
||||
uint32_t len;
|
||||
uint16_t flags;
|
||||
uint16_t next;
|
||||
/* virtio 1.0 */
|
||||
VIRTIO_DEVICE_ID_INVALID = 0, /* Invalid device */
|
||||
VIRTIO_DEVICE_ID_NET = 1, /* Net */
|
||||
VIRTIO_DEVICE_ID_BLOCK = 2, /* Block */
|
||||
VIRTIO_DEVICE_ID_CONSOLE = 3, /* Console */
|
||||
VIRTIO_DEVICE_ID_RNG = 4, /* Rng */
|
||||
VIRTIO_DEVICE_ID_BALLOON = 5, /* Balloon */
|
||||
VIRTIO_DEVICE_ID_IOMEM = 6, /* IO memory */
|
||||
VIRTIO_DEVICE_ID_RPMSG = 7, /* Remote processor messaging */
|
||||
VIRTIO_DEVICE_ID_SCSI = 8, /* SCSI */
|
||||
VIRTIO_DEVICE_ID_9P = 9, /* 9p console */
|
||||
VIRTIO_DEVICE_ID_MAC80211_WLAN = 10, /* Mac80211 wlan */
|
||||
VIRTIO_DEVICE_ID_RPROC_SERIAL = 11, /* Remoteproc serial link */
|
||||
VIRTIO_DEVICE_ID_CAIF = 12, /* CAIF */
|
||||
VIRTIO_DEVICE_ID_MEM_BALLOON = 13, /* Memory balloon */
|
||||
VIRTIO_DEVICE_ID_GPU = 16, /* GPU */
|
||||
VIRTIO_DEVICE_ID_TIME = 17, /* Timer/clock device */
|
||||
VIRTIO_DEVICE_ID_INPUT = 18, /* Input */
|
||||
/* virtio 1.1 */
|
||||
VIRTIO_DEVICE_ID_SOCKET = 19, /* Socket device */
|
||||
VIRTIO_DEVICE_ID_CRYPTO = 20, /* Crypto device */
|
||||
VIRTIO_DEVICE_ID_SIG_DIS_MOD = 21, /* Signal Distribution Module */
|
||||
VIRTIO_DEVICE_ID_PSTORE = 22, /* Pstore device */
|
||||
VIRTIO_DEVICE_ID_IOMMU = 23, /* IOMMU device */
|
||||
VIRTIO_DEVICE_ID_MEM = 24, /* Memory device */
|
||||
|
||||
VIRTIO_DEVICE_TYPE_SIZE
|
||||
};
|
||||
|
||||
#define VRING_DESC_F_NEXT 1 // chained with another descriptor
|
||||
#define VRING_DESC_F_WRITE 2 // device writes (vs read)
|
||||
|
||||
struct virtq_avail
|
||||
struct virtio_device
|
||||
{
|
||||
uint16_t flags; // always zero
|
||||
uint16_t idx; // driver will write ring[idx] next
|
||||
uint16_t ring[QUEUE_SIZE]; // descriptor numbers of chain heads
|
||||
uint16_t unused;
|
||||
rt_uint32_t irq;
|
||||
|
||||
struct virtq queues[RT_USING_VIRTIO_QUEUE_MAX_NR];
|
||||
union
|
||||
{
|
||||
rt_ubase_t *mmio_base;
|
||||
struct virtio_mmio_config *mmio_config;
|
||||
};
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
struct rt_spinlock spinlock;
|
||||
#endif
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct virtq_used_elem
|
||||
{
|
||||
uint32_t id; // index of start of completed descriptor chain
|
||||
uint32_t len;
|
||||
};
|
||||
typedef rt_err_t (*virtio_device_init_handler)(rt_ubase_t *mmio_base, rt_uint32_t irq);
|
||||
|
||||
struct virtq_used
|
||||
{
|
||||
uint16_t flags; // always zero
|
||||
uint16_t idx; // device increments when it adds a ring[] entry
|
||||
struct virtq_used_elem ring[QUEUE_SIZE];
|
||||
};
|
||||
void virtio_reset_device(struct virtio_device *dev);
|
||||
void virtio_status_acknowledge_driver(struct virtio_device *dev);
|
||||
void virtio_status_driver_ok(struct virtio_device *dev);
|
||||
void virtio_interrupt_ack(struct virtio_device *dev, rt_uint32_t ack);
|
||||
|
||||
#endif /* VIRTIO_H__ */
|
||||
rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t ring_size);
|
||||
void virtio_queue_destroy(struct virtio_device *dev, rt_uint32_t queue_index);
|
||||
void virtio_queue_notify(struct virtio_device *dev, rt_uint32_t queue_index);
|
||||
|
||||
void virtio_submit_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index);
|
||||
|
||||
rt_uint16_t virtio_alloc_desc(struct virtio_device *dev, rt_uint32_t queue_index);
|
||||
void virtio_free_desc(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index);
|
||||
rt_err_t virtio_alloc_desc_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t count,
|
||||
rt_uint16_t *indexs);
|
||||
void virtio_free_desc_chain(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index);
|
||||
void virtio_fill_desc(struct virtio_device *dev, rt_uint32_t queue_index, rt_uint16_t desc_index,
|
||||
rt_uint64_t addr, rt_uint32_t len, rt_uint16_t flags, rt_uint16_t next);
|
||||
|
||||
#endif /* __VIRTIO_H__ */
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-9-16 GuEe-GUI the first version
|
||||
* 2021-11-11 GuEe-GUI using virtio common interface
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
#include <virtio_blk.h>
|
||||
|
||||
#ifdef BSP_USING_VIRTIO_BLK
|
||||
static void virtio_blk_rw(struct virtio_blk_device *virtio_blk_dev, rt_off_t pos, void *buffer, int flags)
|
||||
{
|
||||
rt_uint16_t idx[3];
|
||||
struct virtio_device *virtio_dev = &virtio_blk_dev->virtio_dev;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
|
||||
#endif
|
||||
|
||||
/* Allocate 3 descriptors */
|
||||
while (virtio_alloc_desc_chain(virtio_dev, 0, 3, idx))
|
||||
{
|
||||
}
|
||||
|
||||
virtio_blk_dev->info[idx[0]].status = 0xff;
|
||||
virtio_blk_dev->info[idx[0]].valid = RT_TRUE;
|
||||
virtio_blk_dev->info[idx[0]].req.type = flags;
|
||||
virtio_blk_dev->info[idx[0]].req.ioprio = 0;
|
||||
virtio_blk_dev->info[idx[0]].req.sector = pos * (VIRTIO_BLK_BUF_DATA_SIZE / 512);
|
||||
|
||||
flags = flags == VIRTIO_BLK_T_OUT ? 0 : VIRTQ_DESC_F_WRITE;
|
||||
|
||||
virtio_fill_desc(virtio_dev, 0, idx[0],
|
||||
VIRTIO_VA2PA(&virtio_blk_dev->info[idx[0]].req), sizeof(struct virtio_blk_req), VIRTQ_DESC_F_NEXT, idx[1]);
|
||||
|
||||
virtio_fill_desc(virtio_dev, 0, idx[1],
|
||||
VIRTIO_VA2PA(buffer), VIRTIO_BLK_BUF_DATA_SIZE, flags | VIRTQ_DESC_F_NEXT, idx[2]);
|
||||
|
||||
virtio_fill_desc(virtio_dev, 0, idx[2],
|
||||
VIRTIO_VA2PA(&virtio_blk_dev->info[idx[0]].status), 1, VIRTQ_DESC_F_WRITE, 0);
|
||||
|
||||
virtio_submit_chain(virtio_dev, 0, idx[0]);
|
||||
|
||||
virtio_queue_notify(virtio_dev, 0);
|
||||
|
||||
/* Wait for virtio_blk_isr() to done */
|
||||
while (virtio_blk_dev->info[idx[0]].valid)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
|
||||
#endif
|
||||
rt_thread_yield();
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
virtio_free_desc_chain(virtio_dev, 0, idx[0]);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
static rt_size_t virtio_blk_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
|
||||
{
|
||||
virtio_blk_rw((struct virtio_blk_device *)dev, pos, buffer, VIRTIO_BLK_T_IN);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_size_t virtio_blk_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
|
||||
{
|
||||
virtio_blk_rw((struct virtio_blk_device *)dev, pos, (void *)buffer, VIRTIO_BLK_T_OUT);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static rt_err_t virtio_blk_control(rt_device_t dev, int cmd, void *args)
|
||||
{
|
||||
rt_err_t status = RT_EOK;
|
||||
struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)dev;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case RT_DEVICE_CTRL_BLK_GETGEOME:
|
||||
{
|
||||
struct rt_device_blk_geometry *geometry = (struct rt_device_blk_geometry *)args;
|
||||
|
||||
if (geometry == RT_NULL)
|
||||
{
|
||||
status = -RT_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
geometry->bytes_per_sector = VIRTIO_BLK_BYTES_PER_SECTOR;
|
||||
geometry->block_size = VIRTIO_BLK_BLOCK_SIZE;
|
||||
geometry->sector_count = virtio_blk_dev->virtio_dev.mmio_config->config[0];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const static struct rt_device_ops virtio_blk_ops =
|
||||
{
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
RT_NULL,
|
||||
virtio_blk_read,
|
||||
virtio_blk_write,
|
||||
virtio_blk_control
|
||||
};
|
||||
|
||||
static void virtio_blk_isr(int irqno, void *param)
|
||||
{
|
||||
rt_uint32_t id;
|
||||
struct virtio_blk_device *virtio_blk_dev = (struct virtio_blk_device *)param;
|
||||
struct virtio_device *virtio_dev = &virtio_blk_dev->virtio_dev;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_base_t level = rt_spin_lock_irqsave(&virtio_dev->spinlock);
|
||||
#endif
|
||||
|
||||
virtio_interrupt_ack(virtio_dev, virtio_dev->mmio_config->interrupt_status & 0x3);
|
||||
rt_hw_dsb();
|
||||
|
||||
/* The device increments disk.used->idx when it adds an entry to the used ring */
|
||||
while (virtio_dev->queues[0].used_idx != virtio_dev->queues[0].used->idx)
|
||||
{
|
||||
rt_hw_dsb();
|
||||
id = virtio_dev->queues[0].used->ring[virtio_dev->queues[0].used_idx % VIRTIO_BLK_QUEUE_RING_SIZE].id;
|
||||
|
||||
RT_ASSERT(virtio_blk_dev->info[id].status == 0);
|
||||
|
||||
/* Done with buffer */
|
||||
virtio_blk_dev->info[id].valid = RT_FALSE;
|
||||
rt_thread_yield();
|
||||
|
||||
virtio_dev->queues[0].used_idx++;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_unlock_irqrestore(&virtio_dev->spinlock, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq)
|
||||
{
|
||||
static int dev_no = 0;
|
||||
char dev_name[RT_NAME_MAX];
|
||||
struct virtio_device *virtio_dev;
|
||||
struct virtio_blk_device *virtio_blk_dev;
|
||||
|
||||
virtio_blk_dev = rt_malloc(sizeof(struct virtio_blk_device));
|
||||
|
||||
if (virtio_blk_dev == RT_NULL)
|
||||
{
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
virtio_dev = &virtio_blk_dev->virtio_dev;
|
||||
virtio_dev->irq = irq;
|
||||
virtio_dev->mmio_base = mmio_base;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_lock_init(&virtio_dev->spinlock);
|
||||
#endif
|
||||
|
||||
virtio_reset_device(virtio_dev);
|
||||
virtio_status_acknowledge_driver(virtio_dev);
|
||||
|
||||
/* Negotiate features */
|
||||
virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~(
|
||||
(1 << VIRTIO_BLK_F_RO) |
|
||||
(1 << VIRTIO_BLK_F_MQ) |
|
||||
(1 << VIRTIO_BLK_F_SCSI) |
|
||||
(1 << VIRTIO_BLK_F_CONFIG_WCE) |
|
||||
(1 << VIRTIO_F_ANY_LAYOUT) |
|
||||
(1 << VIRTIO_F_RING_EVENT_IDX) |
|
||||
(1 << VIRTIO_F_RING_INDIRECT_DESC));
|
||||
|
||||
/* Tell device that feature negotiation is complete and we're completely ready */
|
||||
virtio_status_driver_ok(virtio_dev);
|
||||
|
||||
/* Initialize queue 0 */
|
||||
if (virtio_queue_init(virtio_dev, 0, VIRTIO_BLK_QUEUE_RING_SIZE) != RT_EOK)
|
||||
{
|
||||
rt_free(virtio_blk_dev);
|
||||
|
||||
return -RT_ENOMEM;
|
||||
}
|
||||
|
||||
virtio_blk_dev->parent.type = RT_Device_Class_Block;
|
||||
virtio_blk_dev->parent.ops = &virtio_blk_ops;
|
||||
|
||||
rt_snprintf(dev_name, RT_NAME_MAX, "%s%d", "virtio-blk", dev_no++);
|
||||
|
||||
rt_hw_interrupt_install(irq, virtio_blk_isr, virtio_blk_dev, dev_name);
|
||||
rt_hw_interrupt_umask(irq);
|
||||
|
||||
return rt_device_register((rt_device_t)virtio_blk_dev, dev_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE);
|
||||
}
|
||||
#endif /* BSP_USING_VIRTIO_BLK */
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-9-16 GuEe-GUI the first version
|
||||
* 2021-11-11 GuEe-GUI using virtio common interface
|
||||
*/
|
||||
|
||||
#ifndef __VIRTIO_BLK_H__
|
||||
#define __VIRTIO_BLK_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
#include <virtio.h>
|
||||
|
||||
#define VIRTIO_BLK_BUF_DATA_SIZE 512
|
||||
#define VIRTIO_BLK_BYTES_PER_SECTOR 512
|
||||
#define VIRTIO_BLK_BLOCK_SIZE 512
|
||||
#define VIRTIO_BLK_QUEUE_RING_SIZE 4
|
||||
|
||||
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
|
||||
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
|
||||
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
|
||||
#define VIRTIO_BLK_F_MQ 12 /* Support more than one vq */
|
||||
|
||||
#define VIRTIO_BLK_T_IN 0 /* Read the blk */
|
||||
#define VIRTIO_BLK_T_OUT 1 /* Write the blk */
|
||||
#define VIRTIO_BLK_T_SCSI_CMD 2
|
||||
#define VIRTIO_BLK_T_SCSI_CMD_OUT 3
|
||||
#define VIRTIO_BLK_T_FLUSH 4
|
||||
#define VIRTIO_BLK_T_FLUSH_OUT 5
|
||||
|
||||
struct virtio_blk_req
|
||||
{
|
||||
rt_uint32_t type;
|
||||
rt_uint32_t ioprio;
|
||||
rt_uint64_t sector;
|
||||
};
|
||||
|
||||
struct virtio_blk_device
|
||||
{
|
||||
struct rt_device parent;
|
||||
|
||||
struct virtio_device virtio_dev;
|
||||
|
||||
struct
|
||||
{
|
||||
rt_bool_t valid;
|
||||
rt_uint8_t status;
|
||||
|
||||
struct virtio_blk_req req;
|
||||
|
||||
} info[VIRTIO_BLK_QUEUE_RING_SIZE];
|
||||
};
|
||||
|
||||
rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq);
|
||||
|
||||
#endif /* __VIRTIO_BLK_H__ */
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-9-16 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
#include "virtio_mmio.h"
|
||||
|
||||
void virtio_mmio_print_configs(uint32_t *device_base)
|
||||
{
|
||||
rt_kprintf("MagicValue:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_MAGIC_VALUE));
|
||||
rt_kprintf("Version:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_VERSION));
|
||||
rt_kprintf("DeviceID:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_DEVICE_ID));
|
||||
rt_kprintf("VendorID:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_VENDOR_ID));
|
||||
rt_kprintf("DeviceFeatures0:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_HOST_FEATURES));
|
||||
rt_kprintf("DeviceFeaturesSel0:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_HOST_FEATURES_SEL));
|
||||
|
||||
virtio_mmio_write32(device_base, VIRTIO_MMIO_HOST_FEATURES_SEL, 1);
|
||||
rt_hw_dsb();
|
||||
|
||||
rt_kprintf("DeviceFeatures1:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_HOST_FEATURES));
|
||||
rt_kprintf("DriverFeatures:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_GUEST_FEATURES));
|
||||
rt_kprintf("DriverFeaturesSel:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_GUEST_FEATURES_SEL));
|
||||
rt_kprintf("PageSize:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_GUEST_PAGE_SIZE));
|
||||
|
||||
virtio_mmio_write32(device_base, VIRTIO_MMIO_QUEUE_SEL, 0);
|
||||
rt_hw_dsb();
|
||||
|
||||
rt_kprintf("QueueSel:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_SEL));
|
||||
rt_kprintf("QueueNumMax:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NUM_MAX));
|
||||
rt_kprintf("QueueNum:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NUM));
|
||||
|
||||
virtio_mmio_write32(device_base, VIRTIO_MMIO_QUEUE_SEL, 1);
|
||||
rt_hw_dsb();
|
||||
|
||||
rt_kprintf("QueueSel:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_SEL));
|
||||
rt_kprintf("QueueNumMax1:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NUM_MAX));
|
||||
rt_kprintf("QueueNum1:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NUM));
|
||||
rt_kprintf("QueueAlign:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_ALIGN));
|
||||
rt_kprintf("QueuePFN:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_PFN));
|
||||
rt_kprintf("QueueReady:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_READY));
|
||||
rt_kprintf("QueueNotify:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_NOTIFY));
|
||||
rt_kprintf("InterruptStatus:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_INTERRUPT_STATUS));
|
||||
rt_kprintf("InterruptACK:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_INTERRUPT_ACK));
|
||||
rt_kprintf("Status:\t\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_STATUS));
|
||||
rt_kprintf("QueueDescLow:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_DESC_LOW));
|
||||
rt_kprintf("QueueDescHigh:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_DESC_HIGH));
|
||||
rt_kprintf("QueueDriverLow:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_AVAIL_LOW));
|
||||
rt_kprintf("QueueDriverHigh:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_AVAIL_HIGH));
|
||||
rt_kprintf("QueueDeviceLow:\t\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_USED_LOW));
|
||||
rt_kprintf("QueueDeviceHigh:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_QUEUE_USED_HIGH));
|
||||
rt_kprintf("ConfigGeneration:\t 0x%x\n", virtio_mmio_read32(device_base, VIRTIO_MMIO_CONFIG_GENERATION));
|
||||
rt_kprintf("Config:\t\t\t 0x%x\n", virtio_mmio_read32(device_base,VIRTIO_MMIO_CONFIG));
|
||||
}
|
|
@ -6,70 +6,52 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-9-16 GuEe-GUI the first version
|
||||
* 2021-11-11 GuEe-GUI modify to virtio common interface
|
||||
*/
|
||||
|
||||
#ifndef VIRTIO_MMIO_H
|
||||
#define VIRTIO_MMIO_H
|
||||
#ifndef __VIRTIO_MMIO_H__
|
||||
#define __VIRTIO_MMIO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <rtdef.h>
|
||||
|
||||
#define VIRTIO_MMIO_MAGIC 0x74726976
|
||||
#define VIRTIO_MMIO_VENDOR 0x554d4551
|
||||
|
||||
#define VIRTIO_MMIO_MAGIC_VALUE 0x000 /* VIRTIO_MMIO_MAGIC */
|
||||
#define VIRTIO_MMIO_VERSION 0x004 /* version: 1 is legacy */
|
||||
#define VIRTIO_MMIO_DEVICE_ID 0x008 /* device type: 1 is net, 2 is disk */
|
||||
#define VIRTIO_MMIO_VENDOR_ID 0x00c /* VIRTIO_MMIO_VENDOR */
|
||||
#define VIRTIO_MMIO_DEVICE_FEATURES 0x010
|
||||
#define VIRTIO_MMIO_DRIVER_FEATURES 0x020
|
||||
#define VIRTIO_MMIO_HOST_FEATURES 0x010
|
||||
#define VIRTIO_MMIO_HOST_FEATURES_SEL 0x014
|
||||
#define VIRTIO_MMIO_GUEST_FEATURES 0x020
|
||||
#define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024
|
||||
#define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 /* version 1 only */
|
||||
#define VIRTIO_MMIO_QUEUE_SEL 0x030
|
||||
#define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034
|
||||
#define VIRTIO_MMIO_QUEUE_NUM 0x038
|
||||
#define VIRTIO_MMIO_QUEUE_ALIGN 0x03c /* version 1 only */
|
||||
#define VIRTIO_MMIO_QUEUE_PFN 0x040 /* version 1 only */
|
||||
#define VIRTIO_MMIO_QUEUE_READY 0x044 /* requires version 2 */
|
||||
#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050
|
||||
#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060
|
||||
#define VIRTIO_MMIO_INTERRUPT_ACK 0x064
|
||||
#define VIRTIO_MMIO_STATUS 0x070
|
||||
#define VIRTIO_MMIO_QUEUE_DESC_LOW 0x080 /* requires version 2 */
|
||||
#define VIRTIO_MMIO_QUEUE_DESC_HIGH 0x084 /* requires version 2 */
|
||||
#define VIRTIO_MMIO_QUEUE_AVAIL_LOW 0x090 /* requires version 2 */
|
||||
#define VIRTIO_MMIO_QUEUE_AVAIL_HIGH 0x094 /* requires version 2 */
|
||||
#define VIRTIO_MMIO_QUEUE_USED_LOW 0x0a0 /* requires version 2 */
|
||||
#define VIRTIO_MMIO_QUEUE_USED_HIGH 0x0a4 /* requires version 2 */
|
||||
#define VIRTIO_MMIO_CONFIG_GENERATION 0x100 /* requires version 2 */
|
||||
#define VIRTIO_MMIO_CONFIG 0x100
|
||||
#define VIRTIO_MMIO_INT_VRING (1 << 0)
|
||||
#define VIRTIO_MMIO_INT_CONFIG (1 << 1)
|
||||
#define VIRTIO_MMIO_VRING_ALIGN 4096
|
||||
|
||||
static inline uint32_t virtio_mmio_read32(uint32_t *base, size_t offset)
|
||||
struct virtio_mmio_config
|
||||
{
|
||||
return *((volatile uint32_t*) (((uintptr_t) base) + offset));
|
||||
}
|
||||
rt_uint32_t magic; /* [0x00]<RO> Magic value */
|
||||
rt_uint32_t version; /* [0x04]<RO> Device version number */
|
||||
rt_uint32_t device_id; /* [0x08]<RO> Virtio Subsystem Device ID */
|
||||
rt_uint32_t vendor_id; /* [0x0c]<RO> Virtio Subsystem Vendor ID */
|
||||
rt_uint32_t device_features; /* [0x10]<RO> Flags representing features the device supports */
|
||||
rt_uint32_t device_features_sel; /* [0x14]<WO> Device (host) features word selection. */
|
||||
rt_uint32_t res0[2]; /* [0x18] */
|
||||
rt_uint32_t driver_features; /* [0x20]<WO> Device features understood and activated by the driver */
|
||||
rt_uint32_t driver_features_sel; /* [0x24]<WO> Activated (guest) features word selection */
|
||||
rt_uint32_t guest_page_size; /* [0x28]<WO> Guest page size, this value should be a power of 2 */
|
||||
rt_uint32_t res1[1]; /* [0x2c] */
|
||||
rt_uint32_t queue_sel; /* [0x30]<WO> Virtual queue index */
|
||||
rt_uint32_t queue_num_max; /* [0x34]<RO> Maximum virtual queue size */
|
||||
rt_uint32_t queue_num; /* [0x38]<WO> Virtual queue size */
|
||||
rt_uint32_t queue_align; /* [0x3c]<WO> Used Ring alignment in the virtual queue */
|
||||
rt_uint32_t queue_pfn; /* [0x40]<RW> Guest physical page number of the virtual queue */
|
||||
rt_uint32_t queue_ready; /* [0x44]<RW> Virtual queue ready bit */
|
||||
rt_uint32_t res2[2]; /* [0x48] */
|
||||
rt_uint32_t queue_notify; /* [0x50]<WO> Queue notifier */
|
||||
rt_uint32_t res3[3]; /* [0x54] */
|
||||
rt_uint32_t interrupt_status; /* [0x60]<RO> Interrupt status */
|
||||
rt_uint32_t interrupt_ack; /* [0x64]<WO> Interrupt acknowledge */
|
||||
rt_uint32_t res4[2]; /* [0x68] */
|
||||
rt_uint32_t status; /* [0x70]<RW> Device status */
|
||||
rt_uint32_t res5[3]; /* [0x74] */
|
||||
rt_uint32_t queue_desc_low; /* [0x80]<WO> Virtual queue’s Descriptor Area 64 bit long physical address */
|
||||
rt_uint32_t queue_desc_high; /* [0x84]<WO> */
|
||||
rt_uint32_t res6[2]; /* [0x88] */
|
||||
rt_uint32_t queue_driver_low; /* [0x90]<WO> Virtual queue’s Driver Area 64 bit long physical address */
|
||||
rt_uint32_t queue_driver_high; /* [0x94]<WO> */
|
||||
rt_uint32_t res7[2]; /* [0x98] */
|
||||
rt_uint32_t queue_device_low; /* [0xa0]<WO> Virtual queue’s Device Area 64 bit long physical address */
|
||||
rt_uint32_t queue_device_high; /* [0xa4]<WO> */
|
||||
rt_uint32_t res8[21]; /* [0xa8] */
|
||||
rt_uint32_t config_generation; /* [0xfc]<RO> Configuration atomicity value */
|
||||
rt_uint32_t config[]; /* [0x100+]<RO> Configuration space */
|
||||
} __attribute__((packed));
|
||||
|
||||
static inline uint16_t virtio_mmio_read16(uint32_t *base, size_t offset)
|
||||
{
|
||||
return *((volatile uint16_t*) (((uintptr_t) base) + offset));
|
||||
}
|
||||
|
||||
static inline uint8_t virtio_mmio_read8(uint32_t *base, size_t offset)
|
||||
{
|
||||
return *((volatile uint8_t*) (((uintptr_t) base) + offset));
|
||||
}
|
||||
|
||||
static inline void virtio_mmio_write32(uint32_t *base, size_t offset, uint32_t val)
|
||||
{
|
||||
*((volatile uint32_t*) (((uintptr_t) base) + offset)) = val;
|
||||
}
|
||||
|
||||
void virtio_mmio_print_configs(uint32_t *device_base);
|
||||
|
||||
#endif /* VIRTIO_MMIO_H */
|
||||
#endif /* __VIRTIO_MMIO_H__ */
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-11-11 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#ifndef __VIRTIO_QUEUE_H__
|
||||
#define __VIRTIO_QUEUE_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
#define VIRTQ_DESC_F_NEXT 1 /* This marks a buffer as continuing via the next field. */
|
||||
#define VIRTQ_DESC_F_WRITE 2 /* This marks a buffer as write-only (otherwise read-only). */
|
||||
#define VIRTQ_DESC_F_INDIRECT 4 /* This means the buffer contains a list of buffer descriptors. */
|
||||
|
||||
/*
|
||||
* The device uses this in used->flags to advise the driver: don't kick me
|
||||
* when you add a buffer. It's unreliable, so it's simply an optimization.
|
||||
*/
|
||||
#define VIRTQ_USED_F_NO_NOTIFY 1
|
||||
|
||||
/*
|
||||
* The driver uses this in avail->flags to advise the device: don't
|
||||
* interrupt me when you consume a buffer. It's unreliable, so it's
|
||||
* simply an optimization.
|
||||
*/
|
||||
#define VIRTQ_AVAIL_F_NO_INTERRUPT 1
|
||||
|
||||
/* Virtqueue descriptors: 16 bytes. These can chain together via "next". */
|
||||
struct virtq_desc
|
||||
{
|
||||
rt_uint64_t addr; /* Address (guest-physical). */
|
||||
rt_uint32_t len; /* Length. */
|
||||
rt_uint16_t flags; /* The flags as indicated above. */
|
||||
rt_uint16_t next; /* We chain unused descriptors via this, too */
|
||||
};
|
||||
|
||||
struct virtq_avail
|
||||
{
|
||||
rt_uint16_t flags; /* Notifications */
|
||||
rt_uint16_t idx; /* Where the driver would put the next descriptor entry in the ring (modulo the queue size) */
|
||||
rt_uint16_t ring[];
|
||||
|
||||
/*
|
||||
* Only if VIRTIO_F_RING_EVENT_IDX
|
||||
* rt_uint16_t used_event;
|
||||
*/
|
||||
};
|
||||
|
||||
struct virtq_used_elem
|
||||
{
|
||||
rt_uint32_t id; /* Index of start of used descriptor chain. */
|
||||
rt_uint32_t len; /* Total length of the descriptor chain which was written to. */
|
||||
};
|
||||
|
||||
struct virtq_used
|
||||
{
|
||||
rt_uint16_t flags;
|
||||
rt_uint16_t idx;
|
||||
struct virtq_used_elem ring[];
|
||||
|
||||
/*
|
||||
* Only if VIRTIO_F_RING_EVENT_IDX
|
||||
* rt_uint16_t avail_event;
|
||||
*/
|
||||
};
|
||||
|
||||
struct virtq
|
||||
{
|
||||
rt_uint32_t num;
|
||||
|
||||
struct virtq_desc *desc;
|
||||
struct virtq_avail *avail;
|
||||
struct virtq_used *used;
|
||||
|
||||
/* Helper of driver */
|
||||
rt_uint32_t used_idx;
|
||||
rt_bool_t *free;
|
||||
};
|
||||
|
||||
#define VIRTQ_DESC_TOTAL_SIZE(ring_size) (sizeof(struct virtq_desc) * (ring_size))
|
||||
/* flags, idx, used_event + ring * ring_size */
|
||||
#define VIRTQ_AVAIL_TOTAL_SIZE(ring_size) (sizeof(rt_uint16_t) * 3 + sizeof(rt_uint16_t) * (ring_size))
|
||||
/* flags, idx, avail_event + ring * ring_size */
|
||||
#define VIRTQ_USED_TOTAL_SIZE(ring_size) (sizeof(rt_uint16_t) * 3 + sizeof(struct virtq_used_elem) * (ring_size))
|
||||
|
||||
#define VIRTQ_AVAIL_RES_SIZE (sizeof(rt_uint16_t)) /* used_event */
|
||||
#define VIRTQ_USED_RES_SIZE (sizeof(rt_uint16_t)) /* avail_event */
|
||||
|
||||
#endif /* __VIRTIO_QUEUE_H__ */
|
|
@ -3,5 +3,6 @@ if exist sd.bin goto run
|
|||
qemu-img create -f raw sd.bin 64M
|
||||
|
||||
:run
|
||||
qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 4 -kernel rtthread.elf -nographic ^
|
||||
-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0
|
||||
qemu-system-aarch64 -M virt,gic-version=2 -cpu cortex-a53 -smp 4 -kernel rtthread.elf -nographic ^
|
||||
-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 ^
|
||||
-netdev user,id=net0 -device virtio-net-device,netdev=net0,bus=virtio-mmio-bus.1
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
if [ ! -f "sd.bin" ]; then
|
||||
dd if=/dev/zero of=sd.bin bs=1024 count=65536
|
||||
fi
|
||||
qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 4 -kernel rtthread.elf -nographic \
|
||||
-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0
|
||||
qemu-system-aarch64 -M virt,gic-version=2 -cpu cortex-a53 -smp 4 -kernel rtthread.elf -nographic \
|
||||
-drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 \
|
||||
-netdev user,id=net0 -device virtio-net-device,netdev=net0,bus=virtio-mmio-bus.1
|
||||
|
|
|
@ -61,14 +61,8 @@
|
|||
#define RT_USING_USER_MAIN
|
||||
#define RT_MAIN_THREAD_STACK_SIZE 8192
|
||||
#define RT_MAIN_THREAD_PRIORITY 10
|
||||
|
||||
/* C++ features */
|
||||
|
||||
|
||||
/* Command shell */
|
||||
|
||||
#define RT_USING_FINSH
|
||||
#define RT_USING_MSH
|
||||
#define RT_USING_FINSH
|
||||
#define FINSH_USING_MSH
|
||||
#define FINSH_THREAD_NAME "tshell"
|
||||
#define FINSH_THREAD_PRIORITY 20
|
||||
|
@ -80,9 +74,6 @@
|
|||
#define MSH_USING_BUILT_IN_COMMANDS
|
||||
#define FINSH_USING_DESCRIPTION
|
||||
#define FINSH_ARG_MAX 10
|
||||
|
||||
/* Device virtual file system */
|
||||
|
||||
#define RT_USING_DFS
|
||||
#define DFS_USING_POSIX
|
||||
#define DFS_USING_WORKDIR
|
||||
|
@ -109,6 +100,9 @@
|
|||
/* Device Drivers */
|
||||
|
||||
#define RT_USING_DEVICE_IPC
|
||||
#define RT_USING_SYSTEM_WORKQUEUE
|
||||
#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048
|
||||
#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
|
||||
#define RT_USING_SERIAL
|
||||
#define RT_USING_SERIAL_V1
|
||||
#define RT_SERIAL_RB_BUFSZ 64
|
||||
|
@ -119,7 +113,7 @@
|
|||
/* Using USB */
|
||||
|
||||
|
||||
/* POSIX layer and C standard library */
|
||||
/* C/C++ and POSIX layer */
|
||||
|
||||
#define RT_LIBC_DEFAULT_TIMEZONE 8
|
||||
|
||||
|
@ -131,22 +125,9 @@
|
|||
|
||||
/* Socket is in the 'Network' category */
|
||||
|
||||
|
||||
/* Network */
|
||||
|
||||
/* Socket abstraction layer */
|
||||
|
||||
|
||||
/* Network interface device */
|
||||
|
||||
|
||||
/* light weight TCP/IP stack */
|
||||
|
||||
|
||||
/* AT commands */
|
||||
|
||||
|
||||
/* VBUS(Virtual Software BUS) */
|
||||
|
||||
|
||||
/* Utilities */
|
||||
|
||||
|
@ -215,6 +196,8 @@
|
|||
|
||||
/* miscellaneous packages */
|
||||
|
||||
/* project laboratory */
|
||||
|
||||
/* samples: kernel and components samples */
|
||||
|
||||
|
||||
|
@ -229,7 +212,7 @@
|
|||
#define BSP_USING_RTC
|
||||
#define BSP_USING_ALARM
|
||||
#define BSP_USING_VIRTIO_BLK
|
||||
#define RT_USING_VIRTIO_BLK0
|
||||
#define BSP_USING_GIC
|
||||
#define BSP_USING_GICV2
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,17 +94,8 @@ CONFIG_RT_USING_USER_MAIN=y
|
|||
CONFIG_RT_MAIN_THREAD_STACK_SIZE=4096
|
||||
CONFIG_RT_MAIN_THREAD_PRIORITY=10
|
||||
# CONFIG_RT_USING_LEGACY is not set
|
||||
|
||||
#
|
||||
# C++ features
|
||||
#
|
||||
# CONFIG_RT_USING_CPLUSPLUS is not set
|
||||
|
||||
#
|
||||
# Command shell
|
||||
#
|
||||
CONFIG_RT_USING_FINSH=y
|
||||
CONFIG_RT_USING_MSH=y
|
||||
CONFIG_RT_USING_FINSH=y
|
||||
CONFIG_FINSH_USING_MSH=y
|
||||
CONFIG_FINSH_THREAD_NAME="tshell"
|
||||
CONFIG_FINSH_THREAD_PRIORITY=20
|
||||
|
@ -118,10 +109,6 @@ CONFIG_FINSH_USING_DESCRIPTION=y
|
|||
# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
|
||||
# CONFIG_FINSH_USING_AUTH is not set
|
||||
CONFIG_FINSH_ARG_MAX=10
|
||||
|
||||
#
|
||||
# Device virtual file system
|
||||
#
|
||||
CONFIG_RT_USING_DFS=y
|
||||
CONFIG_DFS_USING_POSIX=y
|
||||
CONFIG_DFS_USING_WORKDIR=y
|
||||
|
@ -156,6 +143,7 @@ CONFIG_RT_USING_DFS_DEVFS=y
|
|||
# CONFIG_RT_USING_DFS_ROMFS is not set
|
||||
# CONFIG_RT_USING_DFS_RAMFS is not set
|
||||
# CONFIG_RT_USING_DFS_NFS is not set
|
||||
# CONFIG_RT_USING_FAL is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
|
@ -209,7 +197,7 @@ CONFIG_RT_USING_WDT=y
|
|||
# CONFIG_RT_USING_USB_DEVICE is not set
|
||||
|
||||
#
|
||||
# POSIX layer and C standard library
|
||||
# C/C++ and POSIX layer
|
||||
#
|
||||
CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
||||
|
||||
|
@ -233,25 +221,11 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
|||
#
|
||||
# Socket is in the 'Network' category
|
||||
#
|
||||
|
||||
#
|
||||
# Interprocess Communication (IPC)
|
||||
#
|
||||
# CONFIG_RT_USING_POSIX_PIPE is not set
|
||||
# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set
|
||||
# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set
|
||||
|
||||
#
|
||||
# Socket is in the 'Network' category
|
||||
#
|
||||
# CONFIG_RT_USING_CPLUSPLUS is not set
|
||||
|
||||
#
|
||||
# Network
|
||||
#
|
||||
|
||||
#
|
||||
# Socket abstraction layer
|
||||
#
|
||||
CONFIG_RT_USING_SAL=y
|
||||
CONFIG_SAL_INTERNET_CHECK=y
|
||||
|
||||
|
@ -261,10 +235,6 @@ CONFIG_SAL_INTERNET_CHECK=y
|
|||
CONFIG_SAL_USING_LWIP=y
|
||||
# CONFIG_SAL_USING_POSIX is not set
|
||||
CONFIG_SAL_SOCKETS_NUM=16
|
||||
|
||||
#
|
||||
# Network interface device
|
||||
#
|
||||
CONFIG_RT_USING_NETDEV=y
|
||||
CONFIG_NETDEV_USING_IFCONFIG=y
|
||||
CONFIG_NETDEV_USING_PING=y
|
||||
|
@ -274,14 +244,13 @@ CONFIG_NETDEV_USING_AUTO_DEFAULT=y
|
|||
CONFIG_NETDEV_IPV4=1
|
||||
CONFIG_NETDEV_IPV6=0
|
||||
# CONFIG_NETDEV_IPV6_SCOPES is not set
|
||||
|
||||
#
|
||||
# light weight TCP/IP stack
|
||||
#
|
||||
CONFIG_RT_USING_LWIP=y
|
||||
# CONFIG_RT_USING_LWIP_LOCAL_VERSION is not set
|
||||
# CONFIG_RT_USING_LWIP141 is not set
|
||||
CONFIG_RT_USING_LWIP203=y
|
||||
# CONFIG_RT_USING_LWIP212 is not set
|
||||
# CONFIG_RT_USING_LWIP_LATEST is not set
|
||||
CONFIG_RT_USING_LWIP_VER_NUM=0x20003
|
||||
# CONFIG_RT_USING_LWIP_IPV6 is not set
|
||||
CONFIG_RT_LWIP_MEM_ALIGNMENT=4
|
||||
CONFIG_RT_LWIP_IGMP=y
|
||||
|
@ -331,18 +300,9 @@ CONFIG_LWIP_NETIF_LOOPBACK=0
|
|||
# CONFIG_RT_LWIP_STATS is not set
|
||||
# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set
|
||||
CONFIG_RT_LWIP_USING_PING=y
|
||||
# CONFIG_RT_LWIP_DEBUG is not set
|
||||
|
||||
#
|
||||
# AT commands
|
||||
#
|
||||
# CONFIG_RT_USING_AT is not set
|
||||
# CONFIG_LWIP_USING_DHCPD is not set
|
||||
|
||||
#
|
||||
# VBUS(Virtual Software BUS)
|
||||
#
|
||||
# CONFIG_RT_USING_VBUS is not set
|
||||
# CONFIG_RT_LWIP_DEBUG is not set
|
||||
# CONFIG_RT_USING_AT is not set
|
||||
|
||||
#
|
||||
# Utilities
|
||||
|
@ -354,6 +314,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# CONFIG_RT_USING_UTEST is not set
|
||||
# CONFIG_RT_USING_VAR_EXPORT is not set
|
||||
# CONFIG_RT_USING_RT_LINK is not set
|
||||
# CONFIG_RT_USING_VBUS is not set
|
||||
|
||||
#
|
||||
# RT-Thread Utestcases
|
||||
|
@ -367,6 +328,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
#
|
||||
# IoT - internet of things
|
||||
#
|
||||
# CONFIG_PKG_USING_LWIP is not set
|
||||
# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
|
||||
# CONFIG_PKG_USING_PAHOMQTT is not set
|
||||
# CONFIG_PKG_USING_UMQTT is not set
|
||||
|
@ -383,6 +345,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# CONFIG_PKG_USING_FREEMODBUS is not set
|
||||
# CONFIG_PKG_USING_LJSON is not set
|
||||
# CONFIG_PKG_USING_EZXML is not set
|
||||
# CONFIG_PKG_USING_SIMPLE_XML is not set
|
||||
# CONFIG_PKG_USING_NANOPB is not set
|
||||
|
||||
#
|
||||
|
@ -422,6 +385,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# CONFIG_PKG_USING_JOYLINK is not set
|
||||
# CONFIG_PKG_USING_EZ_IOT_OS is not set
|
||||
# CONFIG_PKG_USING_NIMBLE is not set
|
||||
# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
|
||||
# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
|
||||
# CONFIG_PKG_USING_IPMSG is not set
|
||||
# CONFIG_PKG_USING_LSSDP is not set
|
||||
|
@ -629,8 +593,8 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# CONFIG_PKG_USING_ARM_2D is not set
|
||||
# CONFIG_PKG_USING_MCUBOOT is not set
|
||||
# CONFIG_PKG_USING_TINYUSB is not set
|
||||
# CONFIG_PKG_USING_USB_STACK is not set
|
||||
# CONFIG_PKG_USING_LUATOS_SOC is not set
|
||||
# CONFIG_PKG_USING_CHERRYUSB is not set
|
||||
# CONFIG_PKG_USING_KMULTI_RTIMER is not set
|
||||
|
||||
#
|
||||
# peripheral libraries and drivers
|
||||
|
@ -654,6 +618,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# CONFIG_PKG_USING_WM_LIBRARIES is not set
|
||||
# CONFIG_PKG_USING_KENDRYTE_SDK is not set
|
||||
# CONFIG_PKG_USING_INFRARED is not set
|
||||
# CONFIG_PKG_USING_MULTI_INFRARED is not set
|
||||
# CONFIG_PKG_USING_AGILE_BUTTON is not set
|
||||
# CONFIG_PKG_USING_AGILE_LED is not set
|
||||
# CONFIG_PKG_USING_AT24CXX is not set
|
||||
|
@ -710,6 +675,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# CONFIG_PKG_USING_SOFT_SERIAL is not set
|
||||
# CONFIG_PKG_USING_MB85RS16 is not set
|
||||
# CONFIG_PKG_USING_CW2015 is not set
|
||||
# CONFIG_PKG_USING_RFM300 is not set
|
||||
|
||||
#
|
||||
# AI packages
|
||||
|
@ -728,6 +694,10 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# miscellaneous packages
|
||||
#
|
||||
|
||||
#
|
||||
# project laboratory
|
||||
#
|
||||
|
||||
#
|
||||
# samples: kernel and components samples
|
||||
#
|
||||
|
@ -760,6 +730,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# CONFIG_PKG_USING_CANFESTIVAL is not set
|
||||
# CONFIG_PKG_USING_ZLIB is not set
|
||||
# CONFIG_PKG_USING_MINIZIP is not set
|
||||
# CONFIG_PKG_USING_HEATSHRINK is not set
|
||||
# CONFIG_PKG_USING_DSTR is not set
|
||||
# CONFIG_PKG_USING_TINYFRAME is not set
|
||||
# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
|
||||
|
@ -777,6 +748,7 @@ CONFIG_YMODEM_USING_FILE_TRANSFER=y
|
|||
# CONFIG_PKG_USING_DESIGN_PATTERN is not set
|
||||
# CONFIG_PKG_USING_CONTROLLER is not set
|
||||
# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
|
||||
# CONFIG_PKG_USING_MFBD is not set
|
||||
CONFIG_BCM2711_SOC=y
|
||||
|
||||
#
|
||||
|
@ -793,6 +765,7 @@ CONFIG_RT_USING_UART0=y
|
|||
# CONFIG_RT_USING_UART4 is not set
|
||||
# CONFIG_RT_USING_UART5 is not set
|
||||
CONFIG_BSP_USING_GIC=y
|
||||
CONFIG_BSP_USING_GICV2=y
|
||||
CONFIG_BSP_USING_PIN=y
|
||||
CONFIG_BSP_USING_CORETIMER=y
|
||||
# CONFIG_BSP_USING_SYSTIMER is not set
|
||||
|
|
|
@ -31,6 +31,10 @@ menu "Hardware Drivers Config"
|
|||
bool
|
||||
default y
|
||||
|
||||
config BSP_USING_GICV2
|
||||
bool
|
||||
default y
|
||||
|
||||
config BSP_USING_PIN
|
||||
bool "Using PIN"
|
||||
select RT_USING_PIN
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include <rthw.h>
|
||||
#include "drv_wdt.h"
|
||||
#include "drv_gpio.h"
|
||||
#include "mbox.h"
|
||||
#include "raspi4.h"
|
||||
|
||||
#ifdef BSP_USING_WDT
|
||||
|
@ -122,6 +124,48 @@ int rt_hw_wdt_init(void)
|
|||
}
|
||||
INIT_DEVICE_EXPORT(rt_hw_wdt_init);
|
||||
|
||||
void poweroff(void)
|
||||
{
|
||||
unsigned long r;
|
||||
|
||||
rt_kprintf("poweroff...\n");
|
||||
|
||||
/* power off devices one by one */
|
||||
for (r = 0; r < 16; ++r)
|
||||
{
|
||||
bcm271x_mbox_poweroff_devices(r);
|
||||
}
|
||||
|
||||
/* power off gpio pins (but not VCC pins) */
|
||||
GPIO_REG_GPFSEL0(GPIO_BASE) = 0;
|
||||
GPIO_REG_GPFSEL1(GPIO_BASE) = 0;
|
||||
GPIO_REG_GPFSEL2(GPIO_BASE) = 0;
|
||||
GPIO_REG_GPFSEL3(GPIO_BASE) = 0;
|
||||
GPIO_REG_GPFSEL4(GPIO_BASE) = 0;
|
||||
GPIO_REG_GPFSEL5(GPIO_BASE) = 0;
|
||||
GPIO_REG_GPPUD(GPIO_BASE) = 0;
|
||||
rt_thread_mdelay(150);
|
||||
|
||||
GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0xffffffff;
|
||||
GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0xffffffff;
|
||||
rt_thread_mdelay(150);
|
||||
|
||||
/* flush GPIO setup */
|
||||
GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0;
|
||||
GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0;
|
||||
|
||||
/* power off the SoC (GPU + CPU), partition 63 used to indicate halt */
|
||||
r = PM_RSTS;
|
||||
r &= ~0xfffffaaa;
|
||||
r |= 0x555;
|
||||
PM_RSTS |= PM_PASSWORD | r;
|
||||
PM_WDOG |= PM_PASSWORD | 0x0A;
|
||||
PM_RSTC |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
|
||||
|
||||
while (1) {};
|
||||
}
|
||||
MSH_CMD_EXPORT(poweroff, poweroff...);
|
||||
|
||||
void reboot(void)
|
||||
{
|
||||
unsigned int r;
|
||||
|
|
|
@ -53,6 +53,24 @@ int mbox_call(unsigned char ch, int mmu_enable)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bcm271x_mbox_poweroff_devices(int id)
|
||||
{
|
||||
mbox[0] = 8 * 4; /* length of the message */
|
||||
mbox[1] = MBOX_REQUEST; /* this is a request message */
|
||||
|
||||
mbox[2] = MBOX_TAG_SETPOWER; /* set power state */
|
||||
mbox[3] = 8; /* buffer size */
|
||||
mbox[4] = 8; /* len */
|
||||
|
||||
mbox[5] = (unsigned int)id; /* device id */
|
||||
mbox[6] = 0; /* bit 0: off, bit 1: no wait */
|
||||
|
||||
mbox[7] = MBOX_TAG_LAST;
|
||||
mbox_call(8, MBOX_CH_PROP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bcm271x_mbox_get_touch(void)
|
||||
{
|
||||
mbox[0] = 8 * 4; // length of the message
|
||||
|
|
|
@ -161,6 +161,7 @@ enum
|
|||
#define PWM_CLK_ID (0x00000000a)
|
||||
|
||||
int mbox_call(unsigned char ch, int mmu_enable);
|
||||
int bcm271x_mbox_poweroff_devices(int id);
|
||||
int bcm271x_mbox_get_touch(void);
|
||||
int bcm271x_notify_reboot(void);
|
||||
int bcm271x_notify_xhci_reset(void);
|
||||
|
|
|
@ -56,14 +56,8 @@
|
|||
#define RT_USING_USER_MAIN
|
||||
#define RT_MAIN_THREAD_STACK_SIZE 4096
|
||||
#define RT_MAIN_THREAD_PRIORITY 10
|
||||
|
||||
/* C++ features */
|
||||
|
||||
|
||||
/* Command shell */
|
||||
|
||||
#define RT_USING_FINSH
|
||||
#define RT_USING_MSH
|
||||
#define RT_USING_FINSH
|
||||
#define FINSH_USING_MSH
|
||||
#define FINSH_THREAD_NAME "tshell"
|
||||
#define FINSH_THREAD_PRIORITY 20
|
||||
|
@ -75,9 +69,6 @@
|
|||
#define MSH_USING_BUILT_IN_COMMANDS
|
||||
#define FINSH_USING_DESCRIPTION
|
||||
#define FINSH_ARG_MAX 10
|
||||
|
||||
/* Device virtual file system */
|
||||
|
||||
#define RT_USING_DFS
|
||||
#define DFS_USING_POSIX
|
||||
#define DFS_USING_WORKDIR
|
||||
|
@ -125,7 +116,7 @@
|
|||
/* Using USB */
|
||||
|
||||
|
||||
/* POSIX layer and C standard library */
|
||||
/* C/C++ and POSIX layer */
|
||||
|
||||
#define RT_LIBC_DEFAULT_TIMEZONE 8
|
||||
|
||||
|
@ -137,9 +128,8 @@
|
|||
|
||||
/* Socket is in the 'Network' category */
|
||||
|
||||
/* Network */
|
||||
|
||||
/* Socket abstraction layer */
|
||||
/* Network */
|
||||
|
||||
#define RT_USING_SAL
|
||||
#define SAL_INTERNET_CHECK
|
||||
|
@ -148,9 +138,6 @@
|
|||
|
||||
#define SAL_USING_LWIP
|
||||
#define SAL_SOCKETS_NUM 16
|
||||
|
||||
/* Network interface device */
|
||||
|
||||
#define RT_USING_NETDEV
|
||||
#define NETDEV_USING_IFCONFIG
|
||||
#define NETDEV_USING_PING
|
||||
|
@ -158,11 +145,9 @@
|
|||
#define NETDEV_USING_AUTO_DEFAULT
|
||||
#define NETDEV_IPV4 1
|
||||
#define NETDEV_IPV6 0
|
||||
|
||||
/* light weight TCP/IP stack */
|
||||
|
||||
#define RT_USING_LWIP
|
||||
#define RT_USING_LWIP203
|
||||
#define RT_USING_LWIP_VER_NUM 0x20003
|
||||
#define RT_LWIP_MEM_ALIGNMENT 4
|
||||
#define RT_LWIP_IGMP
|
||||
#define RT_LWIP_ICMP
|
||||
|
@ -203,12 +188,6 @@
|
|||
#define LWIP_NETIF_LOOPBACK 0
|
||||
#define RT_LWIP_USING_PING
|
||||
|
||||
/* AT commands */
|
||||
|
||||
|
||||
/* VBUS(Virtual Software BUS) */
|
||||
|
||||
|
||||
/* Utilities */
|
||||
|
||||
#define RT_USING_RYM
|
||||
|
@ -278,6 +257,8 @@
|
|||
|
||||
/* miscellaneous packages */
|
||||
|
||||
/* project laboratory */
|
||||
|
||||
/* samples: kernel and components samples */
|
||||
|
||||
|
||||
|
@ -292,6 +273,7 @@
|
|||
#define BSP_USING_UART
|
||||
#define RT_USING_UART0
|
||||
#define BSP_USING_GIC
|
||||
#define BSP_USING_GICV2
|
||||
#define BSP_USING_PIN
|
||||
#define BSP_USING_CORETIMER
|
||||
#define BSP_USING_WDT
|
||||
|
|
|
@ -0,0 +1,653 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# RT-Thread Project Configuration
|
||||
#
|
||||
|
||||
#
|
||||
# RT-Thread Kernel
|
||||
#
|
||||
CONFIG_RT_NAME_MAX=8
|
||||
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
|
||||
# CONFIG_RT_USING_SMP is not set
|
||||
CONFIG_RT_ALIGN_SIZE=4
|
||||
# CONFIG_RT_THREAD_PRIORITY_8 is not set
|
||||
CONFIG_RT_THREAD_PRIORITY_32=y
|
||||
# CONFIG_RT_THREAD_PRIORITY_256 is not set
|
||||
CONFIG_RT_THREAD_PRIORITY_MAX=32
|
||||
CONFIG_RT_TICK_PER_SECOND=100
|
||||
CONFIG_RT_USING_OVERFLOW_CHECK=y
|
||||
CONFIG_RT_USING_HOOK=y
|
||||
CONFIG_RT_HOOK_USING_FUNC_PTR=y
|
||||
CONFIG_RT_USING_IDLE_HOOK=y
|
||||
CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
|
||||
CONFIG_IDLE_THREAD_STACK_SIZE=4096
|
||||
CONFIG_RT_USING_TIMER_SOFT=y
|
||||
CONFIG_RT_TIMER_THREAD_PRIO=4
|
||||
CONFIG_RT_TIMER_THREAD_STACK_SIZE=4096
|
||||
|
||||
#
|
||||
# kservice optimization
|
||||
#
|
||||
# CONFIG_RT_KSERVICE_USING_STDLIB is not set
|
||||
# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
|
||||
# CONFIG_RT_USING_TINY_FFS is not set
|
||||
# CONFIG_RT_PRINTF_LONGLONG is not set
|
||||
CONFIG_RT_DEBUG=y
|
||||
CONFIG_RT_DEBUG_COLOR=y
|
||||
# CONFIG_RT_DEBUG_INIT_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_THREAD_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_IPC_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_TIMER_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_IRQ_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_MEM_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_SLAB_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_MODULE_CONFIG is not set
|
||||
|
||||
#
|
||||
# Inter-Thread communication
|
||||
#
|
||||
CONFIG_RT_USING_SEMAPHORE=y
|
||||
CONFIG_RT_USING_MUTEX=y
|
||||
CONFIG_RT_USING_EVENT=y
|
||||
CONFIG_RT_USING_MAILBOX=y
|
||||
CONFIG_RT_USING_MESSAGEQUEUE=y
|
||||
# CONFIG_RT_USING_SIGNALS is not set
|
||||
|
||||
#
|
||||
# Memory Management
|
||||
#
|
||||
CONFIG_RT_USING_MEMPOOL=y
|
||||
CONFIG_RT_USING_SMALL_MEM=y
|
||||
# CONFIG_RT_USING_SLAB is not set
|
||||
CONFIG_RT_USING_MEMHEAP=y
|
||||
CONFIG_RT_MEMHEAP_FAST_MODE=y
|
||||
# CONFIG_RT_MEMHEAP_BSET_MODE is not set
|
||||
CONFIG_RT_USING_SMALL_MEM_AS_HEAP=y
|
||||
# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
|
||||
# CONFIG_RT_USING_SLAB_AS_HEAP is not set
|
||||
# CONFIG_RT_USING_USERHEAP is not set
|
||||
# CONFIG_RT_USING_NOHEAP is not set
|
||||
CONFIG_RT_USING_MEMTRACE=y
|
||||
# CONFIG_RT_USING_HEAP_ISR is not set
|
||||
CONFIG_RT_USING_HEAP=y
|
||||
|
||||
#
|
||||
# Kernel Device Object
|
||||
#
|
||||
CONFIG_RT_USING_DEVICE=y
|
||||
CONFIG_RT_USING_DEVICE_OPS=y
|
||||
# CONFIG_RT_USING_INTERRUPT_INFO is not set
|
||||
CONFIG_RT_USING_CONSOLE=y
|
||||
CONFIG_RT_CONSOLEBUF_SIZE=128
|
||||
CONFIG_RT_CONSOLE_DEVICE_NAME="uart2"
|
||||
CONFIG_RT_VER_NUM=0x40100
|
||||
CONFIG_ARCH_CPU_64BIT=y
|
||||
# CONFIG_RT_USING_CPU_FFS is not set
|
||||
CONFIG_ARCH_ARMV8=y
|
||||
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
|
||||
|
||||
#
|
||||
# RT-Thread Components
|
||||
#
|
||||
CONFIG_RT_USING_COMPONENTS_INIT=y
|
||||
CONFIG_RT_USING_USER_MAIN=y
|
||||
CONFIG_RT_MAIN_THREAD_STACK_SIZE=8192
|
||||
CONFIG_RT_MAIN_THREAD_PRIORITY=10
|
||||
# CONFIG_RT_USING_LEGACY is not set
|
||||
CONFIG_RT_USING_MSH=y
|
||||
CONFIG_RT_USING_FINSH=y
|
||||
CONFIG_FINSH_USING_MSH=y
|
||||
CONFIG_FINSH_THREAD_NAME="tshell"
|
||||
CONFIG_FINSH_THREAD_PRIORITY=20
|
||||
CONFIG_FINSH_THREAD_STACK_SIZE=4096
|
||||
CONFIG_FINSH_USING_HISTORY=y
|
||||
CONFIG_FINSH_HISTORY_LINES=5
|
||||
CONFIG_FINSH_USING_SYMTAB=y
|
||||
CONFIG_FINSH_CMD_SIZE=80
|
||||
CONFIG_MSH_USING_BUILT_IN_COMMANDS=y
|
||||
CONFIG_FINSH_USING_DESCRIPTION=y
|
||||
# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
|
||||
# CONFIG_FINSH_USING_AUTH is not set
|
||||
CONFIG_FINSH_ARG_MAX=10
|
||||
# CONFIG_RT_USING_DFS is not set
|
||||
# CONFIG_RT_USING_FAL is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
#
|
||||
CONFIG_RT_USING_DEVICE_IPC=y
|
||||
# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
|
||||
CONFIG_RT_USING_SERIAL=y
|
||||
CONFIG_RT_USING_SERIAL_V1=y
|
||||
# CONFIG_RT_USING_SERIAL_V2 is not set
|
||||
# CONFIG_RT_SERIAL_USING_DMA is not set
|
||||
CONFIG_RT_SERIAL_RB_BUFSZ=64
|
||||
# CONFIG_RT_USING_CAN is not set
|
||||
# CONFIG_RT_USING_HWTIMER is not set
|
||||
# CONFIG_RT_USING_CPUTIME is not set
|
||||
# CONFIG_RT_USING_I2C is not set
|
||||
# CONFIG_RT_USING_PHY is not set
|
||||
CONFIG_RT_USING_PIN=y
|
||||
# CONFIG_RT_USING_ADC is not set
|
||||
# CONFIG_RT_USING_DAC is not set
|
||||
# CONFIG_RT_USING_PWM is not set
|
||||
# CONFIG_RT_USING_MTD_NOR is not set
|
||||
# CONFIG_RT_USING_MTD_NAND is not set
|
||||
# CONFIG_RT_USING_PM is not set
|
||||
# CONFIG_RT_USING_RTC is not set
|
||||
# CONFIG_RT_USING_SDIO is not set
|
||||
# CONFIG_RT_USING_SPI is not set
|
||||
# CONFIG_RT_USING_WDT is not set
|
||||
# CONFIG_RT_USING_AUDIO is not set
|
||||
# CONFIG_RT_USING_SENSOR is not set
|
||||
# CONFIG_RT_USING_TOUCH is not set
|
||||
# CONFIG_RT_USING_HWCRYPTO is not set
|
||||
# CONFIG_RT_USING_PULSE_ENCODER is not set
|
||||
# CONFIG_RT_USING_INPUT_CAPTURE is not set
|
||||
# CONFIG_RT_USING_WIFI is not set
|
||||
|
||||
#
|
||||
# Using USB
|
||||
#
|
||||
# CONFIG_RT_USING_USB is not set
|
||||
# CONFIG_RT_USING_USB_HOST is not set
|
||||
# CONFIG_RT_USING_USB_DEVICE is not set
|
||||
|
||||
#
|
||||
# C/C++ and POSIX layer
|
||||
#
|
||||
CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
|
||||
|
||||
#
|
||||
# POSIX (Portable Operating System Interface) layer
|
||||
#
|
||||
# CONFIG_RT_USING_POSIX_FS is not set
|
||||
# CONFIG_RT_USING_POSIX_DELAY is not set
|
||||
# CONFIG_RT_USING_POSIX_CLOCK is not set
|
||||
# CONFIG_RT_USING_POSIX_TIMER is not set
|
||||
# CONFIG_RT_USING_PTHREADS is not set
|
||||
# CONFIG_RT_USING_MODULE is not set
|
||||
|
||||
#
|
||||
# Interprocess Communication (IPC)
|
||||
#
|
||||
# CONFIG_RT_USING_POSIX_PIPE is not set
|
||||
# CONFIG_RT_USING_POSIX_MESSAGE_QUEUE is not set
|
||||
# CONFIG_RT_USING_POSIX_MESSAGE_SEMAPHORE is not set
|
||||
|
||||
#
|
||||
# Socket is in the 'Network' category
|
||||
#
|
||||
# CONFIG_RT_USING_CPLUSPLUS is not set
|
||||
|
||||
#
|
||||
# Network
|
||||
#
|
||||
# CONFIG_RT_USING_SAL is not set
|
||||
# CONFIG_RT_USING_NETDEV is not set
|
||||
# CONFIG_RT_USING_LWIP is not set
|
||||
# CONFIG_RT_USING_AT is not set
|
||||
|
||||
#
|
||||
# Utilities
|
||||
#
|
||||
# CONFIG_RT_USING_RYM is not set
|
||||
# CONFIG_RT_USING_ULOG is not set
|
||||
# CONFIG_RT_USING_UTEST is not set
|
||||
# CONFIG_RT_USING_VAR_EXPORT is not set
|
||||
# CONFIG_RT_USING_RT_LINK is not set
|
||||
# CONFIG_RT_USING_VBUS is not set
|
||||
|
||||
#
|
||||
# RT-Thread Utestcases
|
||||
#
|
||||
# CONFIG_RT_USING_UTESTCASES is not set
|
||||
|
||||
#
|
||||
# RT-Thread online packages
|
||||
#
|
||||
|
||||
#
|
||||
# IoT - internet of things
|
||||
#
|
||||
# CONFIG_PKG_USING_LWIP is not set
|
||||
# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
|
||||
# CONFIG_PKG_USING_PAHOMQTT is not set
|
||||
# CONFIG_PKG_USING_UMQTT is not set
|
||||
# CONFIG_PKG_USING_WEBCLIENT is not set
|
||||
# CONFIG_PKG_USING_WEBNET is not set
|
||||
# CONFIG_PKG_USING_MONGOOSE is not set
|
||||
# CONFIG_PKG_USING_MYMQTT is not set
|
||||
# CONFIG_PKG_USING_KAWAII_MQTT is not set
|
||||
# CONFIG_PKG_USING_BC28_MQTT is not set
|
||||
# CONFIG_PKG_USING_WEBTERMINAL is not set
|
||||
# CONFIG_PKG_USING_CJSON is not set
|
||||
# CONFIG_PKG_USING_JSMN is not set
|
||||
# CONFIG_PKG_USING_LIBMODBUS is not set
|
||||
# CONFIG_PKG_USING_FREEMODBUS is not set
|
||||
# CONFIG_PKG_USING_LJSON is not set
|
||||
# CONFIG_PKG_USING_EZXML is not set
|
||||
# CONFIG_PKG_USING_SIMPLE_XML is not set
|
||||
# CONFIG_PKG_USING_NANOPB is not set
|
||||
|
||||
#
|
||||
# Wi-Fi
|
||||
#
|
||||
|
||||
#
|
||||
# Marvell WiFi
|
||||
#
|
||||
# CONFIG_PKG_USING_WLANMARVELL is not set
|
||||
|
||||
#
|
||||
# Wiced WiFi
|
||||
#
|
||||
# CONFIG_PKG_USING_WLAN_WICED is not set
|
||||
# CONFIG_PKG_USING_RW007 is not set
|
||||
# CONFIG_PKG_USING_COAP is not set
|
||||
# CONFIG_PKG_USING_NOPOLL is not set
|
||||
# CONFIG_PKG_USING_NETUTILS is not set
|
||||
# CONFIG_PKG_USING_CMUX is not set
|
||||
# CONFIG_PKG_USING_PPP_DEVICE is not set
|
||||
# CONFIG_PKG_USING_AT_DEVICE is not set
|
||||
# CONFIG_PKG_USING_ATSRV_SOCKET is not set
|
||||
# CONFIG_PKG_USING_WIZNET is not set
|
||||
# CONFIG_PKG_USING_ZB_COORDINATOR is not set
|
||||
|
||||
#
|
||||
# IoT Cloud
|
||||
#
|
||||
# CONFIG_PKG_USING_ONENET is not set
|
||||
# CONFIG_PKG_USING_GAGENT_CLOUD is not set
|
||||
# CONFIG_PKG_USING_ALI_IOTKIT is not set
|
||||
# CONFIG_PKG_USING_AZURE is not set
|
||||
# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set
|
||||
# CONFIG_PKG_USING_JIOT-C-SDK is not set
|
||||
# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
|
||||
# CONFIG_PKG_USING_JOYLINK is not set
|
||||
# CONFIG_PKG_USING_EZ_IOT_OS is not set
|
||||
# CONFIG_PKG_USING_NIMBLE is not set
|
||||
# CONFIG_PKG_USING_LLSYNC_SDK_ADAPTER is not set
|
||||
# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
|
||||
# CONFIG_PKG_USING_IPMSG is not set
|
||||
# CONFIG_PKG_USING_LSSDP is not set
|
||||
# CONFIG_PKG_USING_AIRKISS_OPEN is not set
|
||||
# CONFIG_PKG_USING_LIBRWS is not set
|
||||
# CONFIG_PKG_USING_TCPSERVER is not set
|
||||
# CONFIG_PKG_USING_PROTOBUF_C is not set
|
||||
# CONFIG_PKG_USING_DLT645 is not set
|
||||
# CONFIG_PKG_USING_QXWZ is not set
|
||||
# CONFIG_PKG_USING_SMTP_CLIENT is not set
|
||||
# CONFIG_PKG_USING_ABUP_FOTA is not set
|
||||
# CONFIG_PKG_USING_LIBCURL2RTT is not set
|
||||
# CONFIG_PKG_USING_CAPNP is not set
|
||||
# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
|
||||
# CONFIG_PKG_USING_AGILE_TELNET is not set
|
||||
# CONFIG_PKG_USING_NMEALIB is not set
|
||||
# CONFIG_PKG_USING_AGILE_JSMN is not set
|
||||
# CONFIG_PKG_USING_PDULIB is not set
|
||||
# CONFIG_PKG_USING_BTSTACK is not set
|
||||
# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set
|
||||
# CONFIG_PKG_USING_WAYZ_IOTKIT is not set
|
||||
# CONFIG_PKG_USING_MAVLINK is not set
|
||||
# CONFIG_PKG_USING_RAPIDJSON is not set
|
||||
# CONFIG_PKG_USING_BSAL is not set
|
||||
# CONFIG_PKG_USING_AGILE_MODBUS is not set
|
||||
# CONFIG_PKG_USING_AGILE_FTP is not set
|
||||
# CONFIG_PKG_USING_EMBEDDEDPROTO is not set
|
||||
# CONFIG_PKG_USING_RT_LINK_HW is not set
|
||||
# CONFIG_PKG_USING_LORA_PKT_FWD is not set
|
||||
# CONFIG_PKG_USING_LORA_GW_DRIVER_LIB is not set
|
||||
# CONFIG_PKG_USING_LORA_PKT_SNIFFER is not set
|
||||
# CONFIG_PKG_USING_HM is not set
|
||||
# CONFIG_PKG_USING_SMALL_MODBUS is not set
|
||||
# CONFIG_PKG_USING_NET_SERVER is not set
|
||||
|
||||
#
|
||||
# security packages
|
||||
#
|
||||
# CONFIG_PKG_USING_MBEDTLS is not set
|
||||
# CONFIG_PKG_USING_LIBSODIUM is not set
|
||||
# CONFIG_PKG_USING_TINYCRYPT is not set
|
||||
# CONFIG_PKG_USING_TFM is not set
|
||||
# CONFIG_PKG_USING_YD_CRYPTO is not set
|
||||
|
||||
#
|
||||
# language packages
|
||||
#
|
||||
# CONFIG_PKG_USING_LUATOS_SOC is not set
|
||||
# CONFIG_PKG_USING_LUA is not set
|
||||
# CONFIG_PKG_USING_JERRYSCRIPT is not set
|
||||
# CONFIG_PKG_USING_MICROPYTHON is not set
|
||||
# CONFIG_PKG_USING_PIKASCRIPT is not set
|
||||
|
||||
#
|
||||
# multimedia packages
|
||||
#
|
||||
|
||||
#
|
||||
# LVGL: powerful and easy-to-use embedded GUI library
|
||||
#
|
||||
# CONFIG_PKG_USING_LVGL is not set
|
||||
# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
|
||||
# CONFIG_PKG_USING_LV_MUSIC_DEMO is not set
|
||||
|
||||
#
|
||||
# u8g2: a monochrome graphic library
|
||||
#
|
||||
# CONFIG_PKG_USING_U8G2_OFFICIAL is not set
|
||||
# CONFIG_PKG_USING_U8G2 is not set
|
||||
# CONFIG_PKG_USING_OPENMV is not set
|
||||
# CONFIG_PKG_USING_MUPDF is not set
|
||||
# CONFIG_PKG_USING_STEMWIN is not set
|
||||
# CONFIG_PKG_USING_WAVPLAYER is not set
|
||||
# CONFIG_PKG_USING_TJPGD is not set
|
||||
# CONFIG_PKG_USING_PDFGEN is not set
|
||||
# CONFIG_PKG_USING_HELIX is not set
|
||||
# CONFIG_PKG_USING_AZUREGUIX is not set
|
||||
# CONFIG_PKG_USING_TOUCHGFX2RTT is not set
|
||||
# CONFIG_PKG_USING_NUEMWIN is not set
|
||||
# CONFIG_PKG_USING_MP3PLAYER is not set
|
||||
# CONFIG_PKG_USING_TINYJPEG is not set
|
||||
# CONFIG_PKG_USING_UGUI is not set
|
||||
|
||||
#
|
||||
# PainterEngine: A cross-platform graphics application framework written in C language
|
||||
#
|
||||
# CONFIG_PKG_USING_PAINTERENGINE is not set
|
||||
# CONFIG_PKG_USING_PAINTERENGINE_AUX is not set
|
||||
# CONFIG_PKG_USING_MCURSES is not set
|
||||
# CONFIG_PKG_USING_TERMBOX is not set
|
||||
# CONFIG_PKG_USING_VT100 is not set
|
||||
# CONFIG_PKG_USING_QRCODE is not set
|
||||
|
||||
#
|
||||
# tools packages
|
||||
#
|
||||
# CONFIG_PKG_USING_CMBACKTRACE is not set
|
||||
# CONFIG_PKG_USING_EASYFLASH is not set
|
||||
# CONFIG_PKG_USING_EASYLOGGER is not set
|
||||
# CONFIG_PKG_USING_SYSTEMVIEW is not set
|
||||
# CONFIG_PKG_USING_SEGGER_RTT is not set
|
||||
# CONFIG_PKG_USING_RDB is not set
|
||||
# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
|
||||
# CONFIG_PKG_USING_ULOG_FILE is not set
|
||||
# CONFIG_PKG_USING_LOGMGR is not set
|
||||
# CONFIG_PKG_USING_ADBD is not set
|
||||
# CONFIG_PKG_USING_COREMARK is not set
|
||||
# CONFIG_PKG_USING_DHRYSTONE is not set
|
||||
# CONFIG_PKG_USING_MEMORYPERF is not set
|
||||
# CONFIG_PKG_USING_NR_MICRO_SHELL is not set
|
||||
# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
|
||||
# CONFIG_PKG_USING_LUNAR_CALENDAR is not set
|
||||
# CONFIG_PKG_USING_BS8116A is not set
|
||||
# CONFIG_PKG_USING_GPS_RMC is not set
|
||||
# CONFIG_PKG_USING_URLENCODE is not set
|
||||
# CONFIG_PKG_USING_UMCN is not set
|
||||
# CONFIG_PKG_USING_LWRB2RTT is not set
|
||||
# CONFIG_PKG_USING_CPU_USAGE is not set
|
||||
# CONFIG_PKG_USING_GBK2UTF8 is not set
|
||||
# CONFIG_PKG_USING_VCONSOLE is not set
|
||||
# CONFIG_PKG_USING_KDB is not set
|
||||
# CONFIG_PKG_USING_WAMR is not set
|
||||
# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set
|
||||
# CONFIG_PKG_USING_LWLOG is not set
|
||||
# CONFIG_PKG_USING_ANV_TRACE is not set
|
||||
# CONFIG_PKG_USING_ANV_MEMLEAK is not set
|
||||
# CONFIG_PKG_USING_ANV_TESTSUIT is not set
|
||||
# CONFIG_PKG_USING_ANV_BENCH is not set
|
||||
# CONFIG_PKG_USING_DEVMEM is not set
|
||||
# CONFIG_PKG_USING_REGEX is not set
|
||||
# CONFIG_PKG_USING_MEM_SANDBOX is not set
|
||||
# CONFIG_PKG_USING_SOLAR_TERMS is not set
|
||||
# CONFIG_PKG_USING_GAN_ZHI is not set
|
||||
# CONFIG_PKG_USING_FDT is not set
|
||||
|
||||
#
|
||||
# system packages
|
||||
#
|
||||
|
||||
#
|
||||
# enhanced kernel services
|
||||
#
|
||||
# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
|
||||
# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set
|
||||
# CONFIG_PKG_USING_RT_VSNPRINTF_FULL is not set
|
||||
|
||||
#
|
||||
# POSIX extension functions
|
||||
#
|
||||
# CONFIG_PKG_USING_POSIX_GETLINE is not set
|
||||
# CONFIG_PKG_USING_POSIX_WCWIDTH is not set
|
||||
# CONFIG_PKG_USING_POSIX_ITOA is not set
|
||||
# CONFIG_PKG_USING_POSIX_STRINGS is not set
|
||||
|
||||
#
|
||||
# acceleration: Assembly language or algorithmic acceleration packages
|
||||
#
|
||||
# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set
|
||||
# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set
|
||||
# CONFIG_PKG_USING_QFPLIB_M3 is not set
|
||||
|
||||
#
|
||||
# CMSIS: ARM Cortex-M Microcontroller Software Interface Standard
|
||||
#
|
||||
# CONFIG_PKG_USING_CMSIS_5 is not set
|
||||
# CONFIG_PKG_USING_CMSIS_RTOS2 is not set
|
||||
|
||||
#
|
||||
# Micrium: Micrium software products porting for RT-Thread
|
||||
#
|
||||
# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set
|
||||
# CONFIG_PKG_USING_UCOSII_WRAPPER is not set
|
||||
# CONFIG_PKG_USING_UC_CRC is not set
|
||||
# CONFIG_PKG_USING_UC_CLK is not set
|
||||
# CONFIG_PKG_USING_UC_COMMON is not set
|
||||
# CONFIG_PKG_USING_UC_MODBUS is not set
|
||||
# CONFIG_RT_USING_ARDUINO is not set
|
||||
# CONFIG_PKG_USING_GUIENGINE is not set
|
||||
# CONFIG_PKG_USING_CAIRO is not set
|
||||
# CONFIG_PKG_USING_PIXMAN is not set
|
||||
# CONFIG_PKG_USING_PARTITION is not set
|
||||
# CONFIG_PKG_USING_FAL is not set
|
||||
# CONFIG_PKG_USING_FLASHDB is not set
|
||||
# CONFIG_PKG_USING_SQLITE is not set
|
||||
# CONFIG_PKG_USING_RTI is not set
|
||||
# CONFIG_PKG_USING_DFS_YAFFS is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS is not set
|
||||
# CONFIG_PKG_USING_DFS_JFFS2 is not set
|
||||
# CONFIG_PKG_USING_DFS_UFFS is not set
|
||||
# CONFIG_PKG_USING_LWEXT4 is not set
|
||||
# CONFIG_PKG_USING_THREAD_POOL is not set
|
||||
# CONFIG_PKG_USING_ROBOTS is not set
|
||||
# CONFIG_PKG_USING_EV is not set
|
||||
# CONFIG_PKG_USING_SYSWATCH is not set
|
||||
# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
|
||||
# CONFIG_PKG_USING_PLCCORE is not set
|
||||
# CONFIG_PKG_USING_RAMDISK is not set
|
||||
# CONFIG_PKG_USING_MININI is not set
|
||||
# CONFIG_PKG_USING_QBOOT is not set
|
||||
# CONFIG_PKG_USING_PPOOL is not set
|
||||
# CONFIG_PKG_USING_OPENAMP is not set
|
||||
# CONFIG_PKG_USING_LPM is not set
|
||||
# CONFIG_PKG_USING_TLSF is not set
|
||||
# CONFIG_PKG_USING_EVENT_RECORDER is not set
|
||||
# CONFIG_PKG_USING_ARM_2D is not set
|
||||
# CONFIG_PKG_USING_MCUBOOT is not set
|
||||
# CONFIG_PKG_USING_TINYUSB is not set
|
||||
# CONFIG_PKG_USING_CHERRYUSB is not set
|
||||
# CONFIG_PKG_USING_KMULTI_RTIMER is not set
|
||||
|
||||
#
|
||||
# peripheral libraries and drivers
|
||||
#
|
||||
# CONFIG_PKG_USING_SENSORS_DRIVERS is not set
|
||||
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
|
||||
# CONFIG_PKG_USING_SHT2X is not set
|
||||
# CONFIG_PKG_USING_SHT3X is not set
|
||||
# CONFIG_PKG_USING_AS7341 is not set
|
||||
# CONFIG_PKG_USING_STM32_SDIO is not set
|
||||
# CONFIG_PKG_USING_ICM20608 is not set
|
||||
# CONFIG_PKG_USING_BUTTON is not set
|
||||
# CONFIG_PKG_USING_PCF8574 is not set
|
||||
# CONFIG_PKG_USING_SX12XX is not set
|
||||
# CONFIG_PKG_USING_SIGNAL_LED is not set
|
||||
# CONFIG_PKG_USING_LEDBLINK is not set
|
||||
# CONFIG_PKG_USING_LITTLED is not set
|
||||
# CONFIG_PKG_USING_LKDGUI is not set
|
||||
# CONFIG_PKG_USING_NRF5X_SDK is not set
|
||||
# CONFIG_PKG_USING_NRFX is not set
|
||||
# CONFIG_PKG_USING_WM_LIBRARIES is not set
|
||||
# CONFIG_PKG_USING_KENDRYTE_SDK is not set
|
||||
# CONFIG_PKG_USING_INFRARED is not set
|
||||
# CONFIG_PKG_USING_MULTI_INFRARED is not set
|
||||
# CONFIG_PKG_USING_AGILE_BUTTON is not set
|
||||
# CONFIG_PKG_USING_AGILE_LED is not set
|
||||
# CONFIG_PKG_USING_AT24CXX is not set
|
||||
# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set
|
||||
# CONFIG_PKG_USING_AD7746 is not set
|
||||
# CONFIG_PKG_USING_PCA9685 is not set
|
||||
# CONFIG_PKG_USING_I2C_TOOLS is not set
|
||||
# CONFIG_PKG_USING_NRF24L01 is not set
|
||||
# CONFIG_PKG_USING_TOUCH_DRIVERS is not set
|
||||
# CONFIG_PKG_USING_MAX17048 is not set
|
||||
# CONFIG_PKG_USING_RPLIDAR is not set
|
||||
# CONFIG_PKG_USING_AS608 is not set
|
||||
# CONFIG_PKG_USING_RC522 is not set
|
||||
# CONFIG_PKG_USING_WS2812B is not set
|
||||
# CONFIG_PKG_USING_EMBARC_BSP is not set
|
||||
# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set
|
||||
# CONFIG_PKG_USING_MULTI_RTIMER is not set
|
||||
# CONFIG_PKG_USING_MAX7219 is not set
|
||||
# CONFIG_PKG_USING_BEEP is not set
|
||||
# CONFIG_PKG_USING_EASYBLINK is not set
|
||||
# CONFIG_PKG_USING_PMS_SERIES is not set
|
||||
# CONFIG_PKG_USING_CAN_YMODEM is not set
|
||||
# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set
|
||||
# CONFIG_PKG_USING_QLED is not set
|
||||
# CONFIG_PKG_USING_PAJ7620 is not set
|
||||
# CONFIG_PKG_USING_AGILE_CONSOLE is not set
|
||||
# CONFIG_PKG_USING_LD3320 is not set
|
||||
# CONFIG_PKG_USING_WK2124 is not set
|
||||
# CONFIG_PKG_USING_LY68L6400 is not set
|
||||
# CONFIG_PKG_USING_DM9051 is not set
|
||||
# CONFIG_PKG_USING_SSD1306 is not set
|
||||
# CONFIG_PKG_USING_QKEY is not set
|
||||
# CONFIG_PKG_USING_RS485 is not set
|
||||
# CONFIG_PKG_USING_RS232 is not set
|
||||
# CONFIG_PKG_USING_NES is not set
|
||||
# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set
|
||||
# CONFIG_PKG_USING_VDEVICE is not set
|
||||
# CONFIG_PKG_USING_SGM706 is not set
|
||||
# CONFIG_PKG_USING_STM32WB55_SDK is not set
|
||||
# CONFIG_PKG_USING_RDA58XX is not set
|
||||
# CONFIG_PKG_USING_LIBNFC is not set
|
||||
# CONFIG_PKG_USING_MFOC is not set
|
||||
# CONFIG_PKG_USING_TMC51XX is not set
|
||||
# CONFIG_PKG_USING_TCA9534 is not set
|
||||
# CONFIG_PKG_USING_KOBUKI is not set
|
||||
# CONFIG_PKG_USING_ROSSERIAL is not set
|
||||
# CONFIG_PKG_USING_MICRO_ROS is not set
|
||||
# CONFIG_PKG_USING_MCP23008 is not set
|
||||
# CONFIG_PKG_USING_BLUETRUM_SDK is not set
|
||||
# CONFIG_PKG_USING_MISAKA_AT24CXX is not set
|
||||
# CONFIG_PKG_USING_MISAKA_RGB_BLING is not set
|
||||
# CONFIG_PKG_USING_LORA_MODEM_DRIVER is not set
|
||||
# CONFIG_PKG_USING_BL_MCU_SDK is not set
|
||||
# CONFIG_PKG_USING_SOFT_SERIAL is not set
|
||||
# CONFIG_PKG_USING_MB85RS16 is not set
|
||||
# CONFIG_PKG_USING_CW2015 is not set
|
||||
# CONFIG_PKG_USING_RFM300 is not set
|
||||
|
||||
#
|
||||
# AI packages
|
||||
#
|
||||
# CONFIG_PKG_USING_LIBANN is not set
|
||||
# CONFIG_PKG_USING_NNOM is not set
|
||||
# CONFIG_PKG_USING_ONNX_BACKEND is not set
|
||||
# CONFIG_PKG_USING_ONNX_PARSER is not set
|
||||
# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
|
||||
# CONFIG_PKG_USING_ELAPACK is not set
|
||||
# CONFIG_PKG_USING_ULAPACK is not set
|
||||
# CONFIG_PKG_USING_QUEST is not set
|
||||
# CONFIG_PKG_USING_NAXOS is not set
|
||||
|
||||
#
|
||||
# miscellaneous packages
|
||||
#
|
||||
|
||||
#
|
||||
# project laboratory
|
||||
#
|
||||
|
||||
#
|
||||
# samples: kernel and components samples
|
||||
#
|
||||
# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
|
||||
# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set
|
||||
# CONFIG_PKG_USING_NETWORK_SAMPLES is not set
|
||||
# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set
|
||||
|
||||
#
|
||||
# entertainment: terminal games and other interesting software packages
|
||||
#
|
||||
# CONFIG_PKG_USING_CMATRIX is not set
|
||||
# CONFIG_PKG_USING_SL is not set
|
||||
# CONFIG_PKG_USING_CAL is not set
|
||||
# CONFIG_PKG_USING_ACLOCK is not set
|
||||
# CONFIG_PKG_USING_THREES is not set
|
||||
# CONFIG_PKG_USING_2048 is not set
|
||||
# CONFIG_PKG_USING_SNAKE is not set
|
||||
# CONFIG_PKG_USING_TETRIS is not set
|
||||
# CONFIG_PKG_USING_DONUT is not set
|
||||
# CONFIG_PKG_USING_COWSAY is not set
|
||||
# CONFIG_PKG_USING_LIBCSV is not set
|
||||
# CONFIG_PKG_USING_OPTPARSE is not set
|
||||
# CONFIG_PKG_USING_FASTLZ is not set
|
||||
# CONFIG_PKG_USING_MINILZO is not set
|
||||
# CONFIG_PKG_USING_QUICKLZ is not set
|
||||
# CONFIG_PKG_USING_LZMA is not set
|
||||
# CONFIG_PKG_USING_MULTIBUTTON is not set
|
||||
# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
|
||||
# CONFIG_PKG_USING_CANFESTIVAL is not set
|
||||
# CONFIG_PKG_USING_ZLIB is not set
|
||||
# CONFIG_PKG_USING_MINIZIP is not set
|
||||
# CONFIG_PKG_USING_HEATSHRINK is not set
|
||||
# CONFIG_PKG_USING_DSTR is not set
|
||||
# CONFIG_PKG_USING_TINYFRAME is not set
|
||||
# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
|
||||
# CONFIG_PKG_USING_DIGITALCTRL is not set
|
||||
# CONFIG_PKG_USING_UPACKER is not set
|
||||
# CONFIG_PKG_USING_UPARAM is not set
|
||||
# CONFIG_PKG_USING_HELLO is not set
|
||||
# CONFIG_PKG_USING_VI is not set
|
||||
# CONFIG_PKG_USING_KI is not set
|
||||
# CONFIG_PKG_USING_ARMv7M_DWT is not set
|
||||
# CONFIG_PKG_USING_UKAL is not set
|
||||
# CONFIG_PKG_USING_CRCLIB is not set
|
||||
# CONFIG_PKG_USING_LWGPS is not set
|
||||
# CONFIG_PKG_USING_STATE_MACHINE is not set
|
||||
# CONFIG_PKG_USING_DESIGN_PATTERN is not set
|
||||
# CONFIG_PKG_USING_CONTROLLER is not set
|
||||
# CONFIG_PKG_USING_PHASE_LOCKED_LOOP is not set
|
||||
# CONFIG_PKG_USING_MFBD is not set
|
||||
CONFIG_SOC_RK3568=y
|
||||
|
||||
#
|
||||
# Hardware Drivers Config
|
||||
#
|
||||
CONFIG_BSP_USING_UART=y
|
||||
# CONFIG_RT_USING_UART0 is not set
|
||||
# CONFIG_RT_USING_UART1 is not set
|
||||
CONFIG_RT_USING_UART2=y
|
||||
# CONFIG_RT_USING_UART3 is not set
|
||||
# CONFIG_RT_USING_UART4 is not set
|
||||
# CONFIG_RT_USING_UART5 is not set
|
||||
# CONFIG_RT_USING_UART6 is not set
|
||||
# CONFIG_RT_USING_UART7 is not set
|
||||
# CONFIG_RT_USING_UART8 is not set
|
||||
# CONFIG_RT_USING_UART9 is not set
|
||||
CONFIG_BSP_USING_GIC=y
|
||||
CONFIG_BSP_USING_GICV3=y
|
|
@ -0,0 +1,29 @@
|
|||
mainmenu "RT-Thread Project Configuration"
|
||||
|
||||
config BSP_DIR
|
||||
string
|
||||
option env="BSP_ROOT"
|
||||
default "."
|
||||
|
||||
config RTT_DIR
|
||||
string
|
||||
option env="RTT_ROOT"
|
||||
default "../../.."
|
||||
|
||||
config PKGS_DIR
|
||||
string
|
||||
option env="PKGS_ROOT"
|
||||
default "packages"
|
||||
|
||||
source "$RTT_DIR/Kconfig"
|
||||
source "$PKGS_DIR/Kconfig"
|
||||
|
||||
config SOC_RK3568
|
||||
bool
|
||||
select ARCH_ARMV8
|
||||
select ARCH_CPU_64BIT
|
||||
select RT_USING_COMPONENTS_INIT
|
||||
select RT_USING_USER_MAIN
|
||||
default y
|
||||
|
||||
source "$BSP_DIR/driver/Kconfig"
|
|
@ -0,0 +1,55 @@
|
|||
# RK3568 BSP Introduction
|
||||
|
||||
[中文页](README_zh.md) | English
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
RK3568 is a general-purpose SOC, quad-core 64-bit Cortex-A55 processor, with 22nm lithography process, has frequency up to 2.0GHz and Mali G52 GPU, support 4K decoding and 1080P encoding. Support mangy interfaces such as SATA/PCIE/USB3.0, an 0.8T NPU for lightweight AI applications. Support dual Gigabit Ethernet ports, LPDDR4 memory, etc.
|
||||
|
||||
This project ported RT-Thread on RK3568, you can use the RADXA ROCK 3A version of the RK3568 in low-priced, which can even replace the Raspberry Pi 4B.
|
||||
|
||||
## 2. Compiling
|
||||
|
||||
Usage ARM Developer GNU ToolChain, it support Linux and Windows:
|
||||
```
|
||||
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads/
|
||||
```
|
||||
Download the `xxx-aarch64-none-elf` of x86_64 hosted platform, set the `RTT_EXEC_PATH` is system environment after decompress the binary.
|
||||
|
||||
Enter directory `rt-thread/bsp/qemu-virt64-aarch64` and input:
|
||||
```
|
||||
scons
|
||||
```
|
||||
|
||||
## 3. Execution
|
||||
|
||||
RK3568 has different Kernel install methods according to different boardsit, recommend to install into the SD card: ([Official](https://wiki.t-firefly.com/en/ROC-RK3568-PC/hardware_doc.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/install/microSD)).
|
||||
|
||||
After install Kernel, storage the `rtthread.bin` to EFI partition (the second partition), and add this line in the front of `boot.cmd` in this partition:
|
||||
```shell
|
||||
fatload mmc 1:1 0x208000 /rtthread.bin;dcache flush;go 0x208000
|
||||
```
|
||||
After modifying the script, build a binary script `boot.scr ` in this partition:
|
||||
```shell
|
||||
# Install the uboot-mkimage package on Linux, or use MSYS2 to install the u-boot-tools package on Windows
|
||||
mkimage -C none -A arm -T script -d boot.cmd boot.scr
|
||||
```
|
||||
|
||||
According to different boards, the serial port can support up to UART0~9, this project uses UART2 ([Official](https://wiki.t-firefly.com/en/ROC-RK3568-PC/debug.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/dev/serial-console)) by default, the baud rate is 1500000, please make sure that the serial port used supports this baud rate.
|
||||
|
||||
```
|
||||
heap: [0x002663f0 - 0x042663f0]
|
||||
|
||||
\ | /
|
||||
- RT - Thread Operating System
|
||||
/ | \ 4.1.0 build Mar 19 2022 17:17:29
|
||||
2006 - 2022 Copyright by RT-Thread team
|
||||
Hi, this is RT-Thread!!
|
||||
msh />
|
||||
```
|
||||
|
||||
## 4. Condition
|
||||
|
||||
| Driver | Condition | Remark |
|
||||
| ------ | --------- | ------ |
|
||||
| UART | Support | UART0~9 |
|
|
@ -0,0 +1,56 @@
|
|||
# RK3568 板级支持包说明
|
||||
|
||||
中文页 | [English](README.md)
|
||||
|
||||
## 1. 简介
|
||||
|
||||
RK3568 是一款定位中高端的通用型 SOC,采用 22nm 制程工艺,集成四核 2GHz,Cortex-A55 架构和 Mali G52 GPU,支持 4K 解码和 1080P 编码。支持 SATA/PCIE/USB3.0 等各类型外围接口,内置独立的 0.8T NPU,可用于轻量级 AI 应用。支持双千兆以太网口,LPDDR4 内存等。
|
||||
|
||||
这份 RT-Thread BSP是针对 RK3568 的一份移植。开发者可选择使用 RADXA ROCK 3A 版本的 RK3568 廉价体验,其甚至可超量替代树莓派4B。
|
||||
|
||||
## 2. 编译说明
|
||||
|
||||
建议使用ARM Developer GNU交叉编译工具链,目前支持Linux/Windows平台:
|
||||
```
|
||||
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads/
|
||||
```
|
||||
下载x86_64 Hosted平台下载对应的`xxx-aarch64-none-elf`二进制包,解压后设置`RTT_EXEC_PATH`环境变量为该编译器的bin目录下即可。
|
||||
|
||||
进入到`rt-thread/bsp/rockchip/rk3568`目录进行输入:
|
||||
```
|
||||
scons
|
||||
```
|
||||
可以看到正常生成`rtthread.elf`与`rtthread.bin`文件。
|
||||
|
||||
## 3. 执行
|
||||
|
||||
RK3568 根据不同的开发板实现有不同的 Kernel 烧写方式,推荐烧录进 SD 卡:([官方板](https://wiki.t-firefly.com/zh_CN/ROC-RK3568-PC/hardware_doc.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/install/microSD))。
|
||||
|
||||
在烧写完 Kernel 后,将`rtthread.bin`放入 EFI 分区(第二分区),并在该分区的`boot.cmd`最前面中添加如下行:
|
||||
```shell
|
||||
fatload mmc 1:1 0x208000 /rtthread.bin;dcache flush;go 0x208000
|
||||
```
|
||||
修改脚本后,在该分区生成二进制脚本`boot.scr`:
|
||||
```shell
|
||||
# Linux 下安装 uboot-mkimage 软件包,Windows 下使用 MSYS2 安装 u-boot-tools 软件包
|
||||
mkimage -C none -A arm -T script -d boot.cmd boot.scr
|
||||
```
|
||||
|
||||
根据不同的开发板实现串口最多可支持到 UART0~9,本工程默认使用 UART2([官方板](https://wiki.t-firefly.com/zh_CN/ROC-RK3568-PC/debug.html)|[RADXA ROCK 3A](https://wiki.radxa.com/Rock3/dev/serial-console)),波特率 1500000,请确保使用的串口支持该波特率。
|
||||
|
||||
```
|
||||
heap: [0x002663f0 - 0x042663f0]
|
||||
|
||||
\ | /
|
||||
- RT - Thread Operating System
|
||||
/ | \ 4.1.0 build Mar 19 2022 17:17:29
|
||||
2006 - 2022 Copyright by RT-Thread team
|
||||
Hi, this is RT-Thread!!
|
||||
msh />
|
||||
```
|
||||
|
||||
## 4.支持情况
|
||||
|
||||
| 驱动 | 支持情况 | 备注 |
|
||||
| ------ | ---- | :------: |
|
||||
| UART | 支持 | UART0~9 |
|
|
@ -0,0 +1,14 @@
|
|||
# for module compiling
|
||||
import os
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
objs = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
Return('objs')
|
|
@ -0,0 +1,29 @@
|
|||
import os
|
||||
import sys
|
||||
import rtconfig
|
||||
|
||||
from rtconfig import RTT_ROOT
|
||||
|
||||
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
|
||||
from building import *
|
||||
|
||||
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
|
||||
|
||||
DefaultEnvironment(tools=[])
|
||||
env = Environment(tools = ['mingw'],
|
||||
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
|
||||
CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
|
||||
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
|
||||
AR = rtconfig.AR, ARFLAGS = '-rc',
|
||||
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
|
||||
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
|
||||
env['ASCOM'] = env['ASPPCOM']
|
||||
|
||||
Export('RTT_ROOT')
|
||||
Export('rtconfig')
|
||||
|
||||
# prepare building environment
|
||||
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False)
|
||||
|
||||
# make a building
|
||||
DoBuilding(TARGET, objs)
|
|
@ -0,0 +1,9 @@
|
|||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-5-30 Bernard the first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
rt_kprintf("Hi, this is RT-Thread!!\n");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
menu "Hardware Drivers Config"
|
||||
|
||||
menuconfig BSP_USING_UART
|
||||
bool "Using UART"
|
||||
select RT_USING_SERIAL
|
||||
default y
|
||||
|
||||
if BSP_USING_UART
|
||||
config RT_USING_UART0
|
||||
bool "Enable UART 0"
|
||||
default n
|
||||
|
||||
config RT_USING_UART1
|
||||
bool "Enable UART 1"
|
||||
default n
|
||||
|
||||
config RT_USING_UART2
|
||||
bool "Enable UART 2"
|
||||
default y
|
||||
|
||||
config RT_USING_UART3
|
||||
bool "Enable UART 3"
|
||||
default n
|
||||
|
||||
config RT_USING_UART4
|
||||
bool "Enable UART 4"
|
||||
default n
|
||||
|
||||
config RT_USING_UART5
|
||||
bool "Enable UART 5"
|
||||
default n
|
||||
|
||||
config RT_USING_UART6
|
||||
bool "Enable UART 6"
|
||||
default n
|
||||
|
||||
config RT_USING_UART7
|
||||
bool "Enable UART 7"
|
||||
default n
|
||||
|
||||
config RT_USING_UART8
|
||||
bool "Enable UART 8"
|
||||
default n
|
||||
|
||||
config RT_USING_UART9
|
||||
bool "Enable UART 9"
|
||||
default n
|
||||
endif
|
||||
|
||||
config BSP_USING_GIC
|
||||
bool
|
||||
default y
|
||||
|
||||
config BSP_USING_GICV3
|
||||
bool
|
||||
default y
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,19 @@
|
|||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c')
|
||||
list = os.listdir(cwd)
|
||||
CPPPATH = [cwd]
|
||||
objs = []
|
||||
|
||||
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
objs = objs + group
|
||||
|
||||
Return('objs')
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <mmu.h>
|
||||
#include <psci.h>
|
||||
#include <gicv3.h>
|
||||
#include <gtimer.h>
|
||||
#include <cpuport.h>
|
||||
#include <interrupt.h>
|
||||
|
||||
#include <board.h>
|
||||
#include <drv_uart.h>
|
||||
|
||||
struct mem_desc platform_mem_desc[] =
|
||||
{
|
||||
{0x200000, 0x80000000, 0x200000, NORMAL_MEM},
|
||||
{UART0_MMIO_BASE, UART0_MMIO_BASE + 0x10000, UART0_MMIO_BASE, DEVICE_MEM},
|
||||
{UART1_MMIO_BASE, UART1_MMIO_BASE + 0x90000, UART1_MMIO_BASE, DEVICE_MEM},
|
||||
{GIC_PL600_DISTRIBUTOR_PPTR, GIC_PL600_DISTRIBUTOR_PPTR + 0x10000, GIC_PL600_DISTRIBUTOR_PPTR, DEVICE_MEM},
|
||||
{GIC_PL600_REDISTRIBUTOR_PPTR, GIC_PL600_REDISTRIBUTOR_PPTR + 0xc0000, GIC_PL600_REDISTRIBUTOR_PPTR, DEVICE_MEM},
|
||||
};
|
||||
|
||||
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc) / sizeof(platform_mem_desc[0]);
|
||||
|
||||
void idle_wfi(void)
|
||||
{
|
||||
__asm__ volatile ("wfi");
|
||||
}
|
||||
|
||||
void rt_hw_board_init(void)
|
||||
{
|
||||
rt_hw_init_mmu_table(platform_mem_desc, platform_mem_desc_size);
|
||||
rt_hw_mmu_init();
|
||||
|
||||
/* initialize hardware interrupt */
|
||||
rt_hw_interrupt_init();
|
||||
/* initialize uart */
|
||||
rt_hw_uart_init();
|
||||
/* initialize timer for os tick */
|
||||
rt_hw_gtimer_init();
|
||||
|
||||
rt_thread_idle_sethook(idle_wfi);
|
||||
|
||||
arm_psci_init(PSCI_METHOD_SMC, RT_NULL, RT_NULL);
|
||||
|
||||
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
|
||||
/* set console device */
|
||||
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
/* initialize memory system */
|
||||
rt_kprintf("heap: [0x%08x - 0x%08x]\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
|
||||
rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_COMPONENTS_INIT
|
||||
rt_components_board_init();
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
/* install IPI handle */
|
||||
rt_hw_ipi_handler_install(RT_SCHEDULE_IPI, rt_scheduler_ipi_handler);
|
||||
arm_gic_umask(0, IRQ_ARM_IPI_KICK);
|
||||
#endif
|
||||
}
|
||||
|
||||
void reboot(void)
|
||||
{
|
||||
arm_psci_system_reboot();
|
||||
}
|
||||
MSH_CMD_EXPORT(reboot, reboot...);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_uint64_t rt_cpu_mpidr_early[] =
|
||||
{
|
||||
[0] = 0x81000000,
|
||||
[1] = 0x81000100,
|
||||
[2] = 0x81000200,
|
||||
[3] = 0x81000300,
|
||||
};
|
||||
|
||||
void rt_hw_secondary_cpu_up(void)
|
||||
{
|
||||
int i;
|
||||
extern void secondary_cpu_start(void);
|
||||
|
||||
for (i = 1; i < RT_CPUS_NR; ++i)
|
||||
{
|
||||
arm_psci_cpu_on(rt_cpu_mpidr_early[i], (rt_uint64_t)secondary_cpu_start);
|
||||
}
|
||||
}
|
||||
|
||||
void secondary_cpu_c_start(void)
|
||||
{
|
||||
rt_hw_mmu_init();
|
||||
rt_hw_spin_lock(&_cpus_lock);
|
||||
|
||||
arm_gic_cpu_init(0, platform_get_gic_cpu_base());
|
||||
arm_gic_redist_init(0, platform_get_gic_redist_base());
|
||||
rt_hw_vector_init();
|
||||
rt_hw_gtimer_local_enable();
|
||||
arm_gic_umask(0, IRQ_ARM_IPI_KICK);
|
||||
|
||||
rt_kprintf("\rcall cpu %d on success\n", rt_hw_cpu_id());
|
||||
|
||||
rt_system_scheduler_start();
|
||||
}
|
||||
|
||||
void rt_hw_secondary_cpu_idle_exec(void)
|
||||
{
|
||||
__WFE();
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-5-30 Bernard the first version
|
||||
*/
|
||||
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
|
||||
#include <rk3568.h>
|
||||
|
||||
extern unsigned char __bss_start;
|
||||
extern unsigned char __bss_end;
|
||||
|
||||
#define RT_HW_HEAP_BEGIN (void *)&__bss_end
|
||||
#define RT_HW_HEAP_END (void *)(RT_HW_HEAP_BEGIN + 64 * 1024 * 1024)
|
||||
|
||||
void rt_hw_board_init(void);
|
||||
|
||||
#endif /* __BOARD_H__ */
|
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#include <board.h>
|
||||
|
||||
/*
|
||||
* The Synopsys DesignWare 8250 has an extra feature whereby it detects if the
|
||||
* LCR is written whilst busy. If it is, then a busy detect interrupt is
|
||||
* raised, the LCR needs to be rewritten and the uart status register read.
|
||||
*/
|
||||
|
||||
#define UART_RX 0 /* In: Receive buffer */
|
||||
#define UART_TX 0 /* Out: Transmit buffer */
|
||||
|
||||
#define UART_DLL 0 /* Out: Divisor Latch Low */
|
||||
#define UART_DLM 1 /* Out: Divisor Latch High */
|
||||
|
||||
#define UART_IER 1 /* Out: Interrupt Enable Register */
|
||||
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
|
||||
|
||||
#define UART_SSR 0x22 /* In: Software Reset Register */
|
||||
#define UART_USR 0x1f /* UART Status Register */
|
||||
|
||||
#define UART_LCR 3 /* Out: Line Control Register */
|
||||
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
|
||||
#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
|
||||
#define UART_LCR_PARITY 0x8 /* Parity Enable */
|
||||
#define UART_LCR_STOP 0x4 /* Stop bits: 0=1 bit, 1=2 bits */
|
||||
#define UART_LCR_WLEN8 0x3 /* Wordlength: 8 bits */
|
||||
|
||||
#define UART_MCR 4 /* Out: Modem Control Register */
|
||||
#define UART_MCR_RTS 0x02 /* RTS complement */
|
||||
|
||||
#define UART_LSR 5 /* In: Line Status Register */
|
||||
#define UART_LSR_BI 0x10 /* Break interrupt indicator */
|
||||
#define UART_LSR_DR 0x01 /* Receiver data ready */
|
||||
|
||||
#define UART_IIR 2 /* In: Interrupt ID Register */
|
||||
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
|
||||
#define UART_IIR_BUSY 0x07 /* DesignWare APB Busy Detect */
|
||||
#define UART_IIR_RX_TIMEOUT 0x0c /* OMAP RX Timeout interrupt */
|
||||
|
||||
#define UART_FCR 2 /* Out: FIFO Control Register */
|
||||
#define UART_FCR_EN_FIFO 0x01 /* Enable the FIFO */
|
||||
#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
|
||||
#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
|
||||
|
||||
#define UART_REG_SHIFT 0x2 /* Register Shift*/
|
||||
#define UART_INPUT_CLK 24000000
|
||||
|
||||
struct hw_uart_device
|
||||
{
|
||||
rt_ubase_t hw_base;
|
||||
rt_uint32_t irqno;
|
||||
#ifdef RT_USING_SMP
|
||||
struct rt_spinlock spinlock;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define BSP_DEFINE_UART_DEVICE(no) \
|
||||
static struct hw_uart_device _uart##no##_device = \
|
||||
{ \
|
||||
UART##no##_MMIO_BASE, \
|
||||
UART##no##_IRQ \
|
||||
}; \
|
||||
static struct rt_serial_device _serial##no;
|
||||
|
||||
#ifdef RT_USING_UART0
|
||||
BSP_DEFINE_UART_DEVICE(0);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART1
|
||||
BSP_DEFINE_UART_DEVICE(1);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART2
|
||||
BSP_DEFINE_UART_DEVICE(2);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART3
|
||||
BSP_DEFINE_UART_DEVICE(3);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART4
|
||||
BSP_DEFINE_UART_DEVICE(4);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART5
|
||||
BSP_DEFINE_UART_DEVICE(5);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART6
|
||||
BSP_DEFINE_UART_DEVICE(6);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART7
|
||||
BSP_DEFINE_UART_DEVICE(7);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART8
|
||||
BSP_DEFINE_UART_DEVICE(8);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART9
|
||||
BSP_DEFINE_UART_DEVICE(9);
|
||||
#endif
|
||||
|
||||
rt_inline rt_uint32_t dw8250_read32(rt_ubase_t addr, rt_ubase_t offset)
|
||||
{
|
||||
return *((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT)));
|
||||
}
|
||||
|
||||
rt_inline void dw8250_write32(rt_ubase_t addr, rt_ubase_t offset, rt_uint32_t value)
|
||||
{
|
||||
*((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT))) = value;
|
||||
|
||||
if (offset == UART_LCR)
|
||||
{
|
||||
int tries = 1000;
|
||||
|
||||
/* Make sure LCR write wasn't ignored */
|
||||
while (tries--)
|
||||
{
|
||||
unsigned int lcr = dw8250_read32(addr, UART_LCR);
|
||||
|
||||
if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dw8250_write32(addr, UART_FCR, UART_FCR_EN_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
|
||||
dw8250_read32(addr, UART_RX);
|
||||
|
||||
*((volatile rt_uint32_t *)(addr + (offset << UART_REG_SHIFT))) = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static rt_err_t dw8250_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
|
||||
{
|
||||
rt_base_t base, rate;
|
||||
struct hw_uart_device *uart;
|
||||
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
uart = (struct hw_uart_device *)serial->parent.user_data;
|
||||
base = uart->hw_base;
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_lock_init(&uart->spinlock);
|
||||
#endif
|
||||
|
||||
/* Resset UART */
|
||||
dw8250_write32(base, UART_SSR, 1);
|
||||
dw8250_write32(base, UART_SSR, 0);
|
||||
|
||||
dw8250_write32(base, UART_IER, !UART_IER_RDI);
|
||||
dw8250_write32(base, UART_FCR, UART_FCR_EN_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
|
||||
|
||||
/* Disable flow ctrl */
|
||||
dw8250_write32(base, UART_MCR, 0);
|
||||
/* Clear RTS */
|
||||
dw8250_write32(base, UART_MCR, dw8250_read32(base, UART_MCR) | UART_MCR_RTS);
|
||||
|
||||
rate = UART_INPUT_CLK / 16 / serial->config.baud_rate;
|
||||
|
||||
/* Enable access DLL & DLH */
|
||||
dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) | UART_LCR_DLAB);
|
||||
dw8250_write32(base, UART_DLL, (rate & 0xff));
|
||||
dw8250_write32(base, UART_DLM, (rate & 0xff00) >> 8);
|
||||
/* Clear DLAB bit */
|
||||
dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_DLAB));
|
||||
|
||||
dw8250_write32(base, UART_LCR, (dw8250_read32(base, UART_LCR) & (~UART_LCR_WLEN8)) | UART_LCR_WLEN8);
|
||||
dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_STOP));
|
||||
dw8250_write32(base, UART_LCR, dw8250_read32(base, UART_LCR) & (~UART_LCR_PARITY));
|
||||
|
||||
dw8250_write32(base, UART_IER, UART_IER_RDI);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t dw8250_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
|
||||
{
|
||||
struct hw_uart_device *uart;
|
||||
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
uart = (struct hw_uart_device *)serial->parent.user_data;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case RT_DEVICE_CTRL_CLR_INT:
|
||||
/* Disable rx irq */
|
||||
dw8250_write32(uart->hw_base, UART_IER, !UART_IER_RDI);
|
||||
rt_hw_interrupt_mask(uart->irqno);
|
||||
break;
|
||||
|
||||
case RT_DEVICE_CTRL_SET_INT:
|
||||
/* Enable rx irq */
|
||||
dw8250_write32(uart->hw_base, UART_IER, UART_IER_RDI);
|
||||
rt_hw_interrupt_umask(uart->irqno);
|
||||
break;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static int dw8250_uart_putc(struct rt_serial_device *serial, char c)
|
||||
{
|
||||
rt_base_t base;
|
||||
struct hw_uart_device *uart;
|
||||
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
uart = (struct hw_uart_device *)serial->parent.user_data;
|
||||
base = uart->hw_base;
|
||||
|
||||
while ((dw8250_read32(base, UART_USR) & 0x2) == 0)
|
||||
{
|
||||
}
|
||||
|
||||
dw8250_write32(base, UART_TX, c);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dw8250_uart_getc(struct rt_serial_device *serial)
|
||||
{
|
||||
int ch = -1;
|
||||
rt_base_t base;
|
||||
struct hw_uart_device *uart;
|
||||
|
||||
RT_ASSERT(serial != RT_NULL);
|
||||
uart = (struct hw_uart_device *)serial->parent.user_data;
|
||||
base = uart->hw_base;
|
||||
|
||||
if ((dw8250_read32(base, UART_LSR) & 0x1))
|
||||
{
|
||||
ch = dw8250_read32(base, UART_RX) & 0xff;
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
static const struct rt_uart_ops _uart_ops =
|
||||
{
|
||||
dw8250_uart_configure,
|
||||
dw8250_uart_control,
|
||||
dw8250_uart_putc,
|
||||
dw8250_uart_getc,
|
||||
};
|
||||
|
||||
static void rt_hw_uart_isr(int irqno, void *param)
|
||||
{
|
||||
unsigned int iir, status;
|
||||
struct rt_serial_device *serial = (struct rt_serial_device *)param;
|
||||
struct hw_uart_device *uart = (struct hw_uart_device *)serial->parent.user_data;
|
||||
|
||||
iir = dw8250_read32(uart->hw_base, UART_IIR);
|
||||
|
||||
/* If don't do this in non-DMA mode then the "RX TIMEOUT" interrupt will fire forever. */
|
||||
if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT)
|
||||
{
|
||||
#ifdef RT_USING_SMP
|
||||
rt_base_t level = rt_spin_lock_irqsave(&uart->spinlock);
|
||||
#endif
|
||||
|
||||
status = dw8250_read32(uart->hw_base, UART_LSR);
|
||||
|
||||
if (!(status & (UART_LSR_DR | UART_LSR_BI)))
|
||||
{
|
||||
dw8250_read32(uart->hw_base, UART_RX);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
rt_spin_unlock_irqrestore(&uart->spinlock, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!(iir & UART_IIR_NO_INT))
|
||||
{
|
||||
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
|
||||
}
|
||||
|
||||
if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY)
|
||||
{
|
||||
/* Clear the USR */
|
||||
dw8250_read32(uart->hw_base, UART_USR);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int rt_hw_uart_init(void)
|
||||
{
|
||||
struct hw_uart_device *uart;
|
||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
||||
|
||||
config.baud_rate = 1500000;
|
||||
|
||||
#define BSP_INSTALL_UART_DEVICE(no) \
|
||||
uart = &_uart##no##_device; \
|
||||
_serial##no.ops = &_uart_ops; \
|
||||
_serial##no.config = config; \
|
||||
rt_hw_serial_register(&_serial##no, "uart" #no, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); \
|
||||
rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial##no, "uart" #no);
|
||||
|
||||
#ifdef RT_USING_UART0
|
||||
BSP_INSTALL_UART_DEVICE(0);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART1
|
||||
BSP_INSTALL_UART_DEVICE(1);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART2
|
||||
BSP_INSTALL_UART_DEVICE(2);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART3
|
||||
BSP_INSTALL_UART_DEVICE(3);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART4
|
||||
BSP_INSTALL_UART_DEVICE(4);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART5
|
||||
BSP_INSTALL_UART_DEVICE(5);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART6
|
||||
BSP_INSTALL_UART_DEVICE(6);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART7
|
||||
BSP_INSTALL_UART_DEVICE(7);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART8
|
||||
BSP_INSTALL_UART_DEVICE(8);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_UART9
|
||||
BSP_INSTALL_UART_DEVICE(9);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#ifndef __DRV_UART_H__
|
||||
#define __DRV_UART_H__
|
||||
|
||||
int rt_hw_uart_init(void);
|
||||
|
||||
#endif /* __DRV_UART_H__ */
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-3-08 GuEe-GUI the first version
|
||||
*/
|
||||
|
||||
#ifndef __RK3568_H__
|
||||
#define __RK3568_H__
|
||||
|
||||
/* UART */
|
||||
#define UART_MMIO_BASE 0xfe650000
|
||||
#define UART0_MMIO_BASE 0xfdd50000
|
||||
#define UART1_MMIO_BASE (UART_MMIO_BASE + 0)
|
||||
#define UART2_MMIO_BASE (UART_MMIO_BASE + 0x10000)
|
||||
#define UART3_MMIO_BASE (UART_MMIO_BASE + 0x20000)
|
||||
#define UART4_MMIO_BASE (UART_MMIO_BASE + 0x30000)
|
||||
#define UART5_MMIO_BASE (UART_MMIO_BASE + 0x40000)
|
||||
#define UART6_MMIO_BASE (UART_MMIO_BASE + 0x50000)
|
||||
#define UART7_MMIO_BASE (UART_MMIO_BASE + 0x60000)
|
||||
#define UART8_MMIO_BASE (UART_MMIO_BASE + 0x70000)
|
||||
#define UART9_MMIO_BASE (UART_MMIO_BASE + 0x80000)
|
||||
|
||||
#define UART_MMIO_SIZE 0x100
|
||||
|
||||
#define UART_IRQ_BASE (32 + 116)
|
||||
#define UART0_IRQ (UART_IRQ_BASE + 0)
|
||||
#define UART1_IRQ (UART_IRQ_BASE + 1)
|
||||
#define UART2_IRQ (UART_IRQ_BASE + 2)
|
||||
#define UART3_IRQ (UART_IRQ_BASE + 3)
|
||||
#define UART4_IRQ (UART_IRQ_BASE + 4)
|
||||
#define UART5_IRQ (UART_IRQ_BASE + 5)
|
||||
#define UART6_IRQ (UART_IRQ_BASE + 6)
|
||||
#define UART7_IRQ (UART_IRQ_BASE + 7)
|
||||
#define UART8_IRQ (UART_IRQ_BASE + 8)
|
||||
#define UART9_IRQ (UART_IRQ_BASE + 9)
|
||||
|
||||
/* GPIO */
|
||||
#define GPIO0_MMIO_BASE 0xfdd60000
|
||||
#define GPIO1_MMIO_BASE 0xfe740000
|
||||
#define GPIO2_MMIO_BASE 0xfe750000
|
||||
#define GPIO3_MMIO_BASE 0xfe760000
|
||||
#define GPIO4_MMIO_BASE 0xfe770000
|
||||
|
||||
#define GPIO_MMIO_SIZE 0x100
|
||||
|
||||
#define GPIO_IRQ_BASE (32 + 33)
|
||||
#define GPIO0_IRQ (GPIO_IRQ_BASE + 0)
|
||||
#define GPIO1_IRQ (GPIO_IRQ_BASE + 1)
|
||||
#define GPIO2_IRQ (GPIO_IRQ_BASE + 2)
|
||||
#define GPIO3_IRQ (GPIO_IRQ_BASE + 3)
|
||||
#define GPIO4_IRQ (GPIO_IRQ_BASE + 4)
|
||||
|
||||
/* MMC */
|
||||
#define MMC0_MMIO_BASE 0xfe310000 /* sdhci */
|
||||
#define MMC1_MMIO_BASE 0xfe2b0000 /* sdmmc0 */
|
||||
#define MMC2_MMIO_BASE 0xfe2c0000 /* sdmmc1 */
|
||||
#define MMC3_MMIO_BASE 0xfe000000 /* sdmmc2 */
|
||||
|
||||
#define MMC0_MMIO_SIZE 0x10000
|
||||
#define MMC_MMIO_SIZE 0x4000
|
||||
|
||||
#define MMC0_IRQ (32 + 19)
|
||||
#define MMC1_IRQ (32 + 98)
|
||||
#define MMC2_IRQ (32 + 99)
|
||||
#define MMC3_IRQ (32 + 100)
|
||||
|
||||
/* Ethernet */
|
||||
#define GMAC0_MMIO_BASE 0xfe2a0000
|
||||
#define GMAC1_MMIO_BASE 0xfe010000
|
||||
|
||||
#define GMAC_MMIO_SIZE 0x10000
|
||||
|
||||
#define GMAC0_MAC_IRQ (32 + 27)
|
||||
#define GMAC0_WAKE_IRQ (32 + 24)
|
||||
#define GMAC1_MAC_IRQ (32 + 32)
|
||||
#define GMAC1_WAKE_IRQ (32 + 29)
|
||||
|
||||
/* GIC */
|
||||
#define MAX_HANDLERS 256
|
||||
#define GIC_IRQ_START 0
|
||||
#define ARM_GIC_NR_IRQS 256
|
||||
#define ARM_GIC_MAX_NR 1
|
||||
|
||||
#define IRQ_ARM_IPI_KICK 0
|
||||
#define IRQ_ARM_IPI_CALL 1
|
||||
|
||||
#define GIC_PL600_DISTRIBUTOR_PPTR 0xfd400000
|
||||
#define GIC_PL600_REDISTRIBUTOR_PPTR 0xfd460000
|
||||
#define GIC_PL600_CONTROLLER_PPTR RT_NULL
|
||||
#define GIC_PL600_ITS_PPTR 0xfd440000
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
||||
{
|
||||
return GIC_PL600_DISTRIBUTOR_PPTR;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_redist_base(void)
|
||||
{
|
||||
return GIC_PL600_REDISTRIBUTOR_PPTR;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
|
||||
{
|
||||
return GIC_PL600_CONTROLLER_PPTR;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_its_base(void)
|
||||
{
|
||||
return GIC_PL600_ITS_PPTR;
|
||||
}
|
||||
|
||||
#endif /* __RK3568_H__ */
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2017-5-30 bernard first version
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
|
||||
OUTPUT_ARCH(aarch64)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x208000;
|
||||
. = ALIGN(4096);
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.text.entrypoint)) /* The entry point */
|
||||
*(.vectors)
|
||||
*(.text) /* remaining code */
|
||||
*(.text.*) /* remaining code */
|
||||
|
||||
*(.rodata) /* read-only data (constants) */
|
||||
*(.rodata*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.gnu.linkonce.t*)
|
||||
|
||||
*(COMMON)
|
||||
|
||||
/* section information for finsh shell */
|
||||
. = ALIGN(16);
|
||||
__fsymtab_start = .;
|
||||
KEEP(*(FSymTab))
|
||||
__fsymtab_end = .;
|
||||
. = ALIGN(16);
|
||||
__vsymtab_start = .;
|
||||
KEEP(*(VSymTab))
|
||||
__vsymtab_end = .;
|
||||
. = ALIGN(16);
|
||||
|
||||
/* section information for initial. */
|
||||
. = ALIGN(16);
|
||||
__rt_init_start = .;
|
||||
KEEP(*(SORT(.rti_fn*)))
|
||||
__rt_init_end = .;
|
||||
. = ALIGN(16);
|
||||
|
||||
. = ALIGN(16);
|
||||
_etext = .;
|
||||
}
|
||||
|
||||
.eh_frame_hdr :
|
||||
{
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame_entry)
|
||||
}
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
|
||||
|
||||
. = ALIGN(16);
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
|
||||
*(.data1)
|
||||
*(.data1.*)
|
||||
|
||||
. = ALIGN(16);
|
||||
_gp = ABSOLUTE(.); /* Base of small data */
|
||||
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
}
|
||||
|
||||
. = ALIGN(16);
|
||||
.ctors :
|
||||
{
|
||||
PROVIDE(__ctors_start__ = .);
|
||||
KEEP(*(SORT(.ctors.*)))
|
||||
KEEP(*(.ctors))
|
||||
PROVIDE(__ctors_end__ = .);
|
||||
}
|
||||
|
||||
.dtors :
|
||||
{
|
||||
PROVIDE(__dtors_start__ = .);
|
||||
KEEP(*(SORT(.dtors.*)))
|
||||
KEEP(*(.dtors))
|
||||
PROVIDE(__dtors_end__ = .);
|
||||
}
|
||||
|
||||
. = ALIGN(16);
|
||||
.bss :
|
||||
{
|
||||
PROVIDE(__bss_start = .);
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.dynbss)
|
||||
|
||||
. = ALIGN(16);
|
||||
PROVIDE(__bss_end = .);
|
||||
}
|
||||
_end = .;
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
* Symbols in the DWARF debugging sections are relative to the beginning
|
||||
* of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
}
|
||||
|
||||
__bss_size = SIZEOF(.bss);
|
|
@ -0,0 +1,188 @@
|
|||
#ifndef RT_CONFIG_H__
|
||||
#define RT_CONFIG_H__
|
||||
|
||||
/* Automatically generated file; DO NOT EDIT. */
|
||||
/* RT-Thread Project Configuration */
|
||||
|
||||
/* RT-Thread Kernel */
|
||||
|
||||
#define RT_NAME_MAX 8
|
||||
#define RT_ALIGN_SIZE 4
|
||||
#define RT_THREAD_PRIORITY_32
|
||||
#define RT_THREAD_PRIORITY_MAX 32
|
||||
#define RT_TICK_PER_SECOND 100
|
||||
#define RT_USING_OVERFLOW_CHECK
|
||||
#define RT_USING_HOOK
|
||||
#define RT_HOOK_USING_FUNC_PTR
|
||||
#define RT_USING_IDLE_HOOK
|
||||
#define RT_IDLE_HOOK_LIST_SIZE 4
|
||||
#define IDLE_THREAD_STACK_SIZE 4096
|
||||
#define RT_USING_TIMER_SOFT
|
||||
#define RT_TIMER_THREAD_PRIO 4
|
||||
#define RT_TIMER_THREAD_STACK_SIZE 4096
|
||||
|
||||
/* kservice optimization */
|
||||
|
||||
#define RT_DEBUG
|
||||
#define RT_DEBUG_COLOR
|
||||
|
||||
/* Inter-Thread communication */
|
||||
|
||||
#define RT_USING_SEMAPHORE
|
||||
#define RT_USING_MUTEX
|
||||
#define RT_USING_EVENT
|
||||
#define RT_USING_MAILBOX
|
||||
#define RT_USING_MESSAGEQUEUE
|
||||
|
||||
/* Memory Management */
|
||||
|
||||
#define RT_USING_MEMPOOL
|
||||
#define RT_USING_SMALL_MEM
|
||||
#define RT_USING_MEMHEAP
|
||||
#define RT_MEMHEAP_FAST_MODE
|
||||
#define RT_USING_SMALL_MEM_AS_HEAP
|
||||
#define RT_USING_MEMTRACE
|
||||
#define RT_USING_HEAP
|
||||
|
||||
/* Kernel Device Object */
|
||||
|
||||
#define RT_USING_DEVICE
|
||||
#define RT_USING_DEVICE_OPS
|
||||
#define RT_USING_CONSOLE
|
||||
#define RT_CONSOLEBUF_SIZE 128
|
||||
#define RT_CONSOLE_DEVICE_NAME "uart2"
|
||||
#define RT_VER_NUM 0x40100
|
||||
#define ARCH_CPU_64BIT
|
||||
#define ARCH_ARMV8
|
||||
|
||||
/* RT-Thread Components */
|
||||
|
||||
#define RT_USING_COMPONENTS_INIT
|
||||
#define RT_USING_USER_MAIN
|
||||
#define RT_MAIN_THREAD_STACK_SIZE 8192
|
||||
#define RT_MAIN_THREAD_PRIORITY 10
|
||||
#define RT_USING_MSH
|
||||
#define RT_USING_FINSH
|
||||
#define FINSH_USING_MSH
|
||||
#define FINSH_THREAD_NAME "tshell"
|
||||
#define FINSH_THREAD_PRIORITY 20
|
||||
#define FINSH_THREAD_STACK_SIZE 4096
|
||||
#define FINSH_USING_HISTORY
|
||||
#define FINSH_HISTORY_LINES 5
|
||||
#define FINSH_USING_SYMTAB
|
||||
#define FINSH_CMD_SIZE 80
|
||||
#define MSH_USING_BUILT_IN_COMMANDS
|
||||
#define FINSH_USING_DESCRIPTION
|
||||
#define FINSH_ARG_MAX 10
|
||||
|
||||
/* Device Drivers */
|
||||
|
||||
#define RT_USING_DEVICE_IPC
|
||||
#define RT_USING_SERIAL
|
||||
#define RT_USING_SERIAL_V1
|
||||
#define RT_SERIAL_RB_BUFSZ 64
|
||||
#define RT_USING_PIN
|
||||
|
||||
/* Using USB */
|
||||
|
||||
|
||||
/* C/C++ and POSIX layer */
|
||||
|
||||
#define RT_LIBC_DEFAULT_TIMEZONE 8
|
||||
|
||||
/* POSIX (Portable Operating System Interface) layer */
|
||||
|
||||
|
||||
/* Interprocess Communication (IPC) */
|
||||
|
||||
|
||||
/* Socket is in the 'Network' category */
|
||||
|
||||
|
||||
/* Network */
|
||||
|
||||
|
||||
/* Utilities */
|
||||
|
||||
|
||||
/* RT-Thread Utestcases */
|
||||
|
||||
|
||||
/* RT-Thread online packages */
|
||||
|
||||
/* IoT - internet of things */
|
||||
|
||||
|
||||
/* Wi-Fi */
|
||||
|
||||
/* Marvell WiFi */
|
||||
|
||||
|
||||
/* Wiced WiFi */
|
||||
|
||||
|
||||
/* IoT Cloud */
|
||||
|
||||
|
||||
/* security packages */
|
||||
|
||||
|
||||
/* language packages */
|
||||
|
||||
|
||||
/* multimedia packages */
|
||||
|
||||
/* LVGL: powerful and easy-to-use embedded GUI library */
|
||||
|
||||
|
||||
/* u8g2: a monochrome graphic library */
|
||||
|
||||
|
||||
/* PainterEngine: A cross-platform graphics application framework written in C language */
|
||||
|
||||
|
||||
/* tools packages */
|
||||
|
||||
|
||||
/* system packages */
|
||||
|
||||
/* enhanced kernel services */
|
||||
|
||||
|
||||
/* POSIX extension functions */
|
||||
|
||||
|
||||
/* acceleration: Assembly language or algorithmic acceleration packages */
|
||||
|
||||
|
||||
/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
|
||||
|
||||
|
||||
/* Micrium: Micrium software products porting for RT-Thread */
|
||||
|
||||
|
||||
/* peripheral libraries and drivers */
|
||||
|
||||
|
||||
/* AI packages */
|
||||
|
||||
|
||||
/* miscellaneous packages */
|
||||
|
||||
/* project laboratory */
|
||||
|
||||
/* samples: kernel and components samples */
|
||||
|
||||
|
||||
/* entertainment: terminal games and other interesting software packages */
|
||||
|
||||
#define SOC_RK3568
|
||||
|
||||
/* Hardware Drivers Config */
|
||||
|
||||
#define BSP_USING_UART
|
||||
#define RT_USING_UART2
|
||||
#define BSP_USING_GIC
|
||||
#define BSP_USING_GICV3
|
||||
|
||||
#endif
|
|
@ -0,0 +1,53 @@
|
|||
import os
|
||||
|
||||
# toolchains options
|
||||
ARCH ='aarch64'
|
||||
CPU ='cortex-a'
|
||||
CROSS_TOOL ='gcc'
|
||||
|
||||
if os.getenv('RTT_ROOT'):
|
||||
RTT_ROOT = os.getenv('RTT_ROOT')
|
||||
else:
|
||||
RTT_ROOT = os.path.join(os.getcwd(), '..', '..', '..')
|
||||
|
||||
if os.getenv('RTT_CC'):
|
||||
CROSS_TOOL = os.getenv('RTT_CC')
|
||||
|
||||
PLATFORM = 'gcc'
|
||||
EXEC_PATH = r'/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/'
|
||||
|
||||
if os.getenv('RTT_EXEC_PATH'):
|
||||
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
|
||||
|
||||
BUILD = 'debug'
|
||||
|
||||
if PLATFORM == 'gcc':
|
||||
# toolchains
|
||||
PREFIX = 'aarch64-none-elf-'
|
||||
CC = PREFIX + 'gcc'
|
||||
CXX = PREFIX + 'g++'
|
||||
AS = PREFIX + 'gcc'
|
||||
AR = PREFIX + 'ar'
|
||||
LINK = PREFIX + 'gcc'
|
||||
TARGET_EXT = 'elf'
|
||||
SIZE = PREFIX + 'size'
|
||||
OBJDUMP = PREFIX + 'objdump'
|
||||
OBJCPY = PREFIX + 'objcopy'
|
||||
|
||||
DEVICE = ' -g -march=armv8-a -mtune=cortex-a55'
|
||||
CFLAGS = DEVICE + ' -Wall'
|
||||
AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__'
|
||||
LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'
|
||||
CPATH = ''
|
||||
LPATH = ''
|
||||
|
||||
if BUILD == 'debug':
|
||||
CFLAGS += ' -O0 -gdwarf-2'
|
||||
AFLAGS += ' -gdwarf-2'
|
||||
else:
|
||||
CFLAGS += ' -O2'
|
||||
|
||||
CXXFLAGS = CFLAGS
|
||||
|
||||
DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n'
|
||||
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
|
|
@ -26,6 +26,9 @@ extern "C" {
|
|||
/*
|
||||
* Some macros define
|
||||
*/
|
||||
#ifndef HWREG64
|
||||
#define HWREG64(x) (*((volatile rt_uint64_t *)(x)))
|
||||
#endif
|
||||
#ifndef HWREG32
|
||||
#define HWREG32(x) (*((volatile rt_uint32_t *)(x)))
|
||||
#endif
|
||||
|
|
|
@ -6,10 +6,6 @@ Import('rtconfig')
|
|||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*.S')
|
||||
|
||||
if not GetDepend('BSP_USING_GIC'):
|
||||
SrcRemove(src, 'gic.c')
|
||||
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('common', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
|
|
@ -9,20 +9,25 @@
|
|||
* 2014-04-03 Grissiom many enhancements
|
||||
* 2018-11-22 Jesven add rt_hw_ipi_send()
|
||||
* add rt_hw_ipi_handler_install()
|
||||
* 2022-03-08 GuEe-GUI add BSP bind SPI CPU self support
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#if defined(BSP_USING_GIC) && defined(BSP_USING_GICV2)
|
||||
|
||||
#include <gic.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
#include <board.h>
|
||||
|
||||
struct arm_gic
|
||||
{
|
||||
rt_uint64_t offset; /* the first interrupt index in the vector table */
|
||||
|
||||
rt_uint64_t dist_hw_base; /* the base address of the gic distributor */
|
||||
rt_uint64_t cpu_hw_base; /* the base addrees of the gic cpu interface */
|
||||
rt_uint64_t cpu_hw_base; /* the base address of the gic cpu interface */
|
||||
};
|
||||
|
||||
/* 'ARM_GIC_MAX_NR' is the number of cores */
|
||||
|
@ -30,33 +35,33 @@ static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
|
|||
|
||||
/** Macro to access the Generic Interrupt Controller Interface (GICC)
|
||||
*/
|
||||
#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00U)
|
||||
#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04U)
|
||||
#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08U)
|
||||
#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0cU)
|
||||
#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10U)
|
||||
#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14U)
|
||||
#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18U)
|
||||
#define GIC_CPU_IIDR(hw_base) __REG32((hw_base) + 0xFCU)
|
||||
#define GIC_CPU_CTRL(hw_base) HWREG32((hw_base) + 0x00U)
|
||||
#define GIC_CPU_PRIMASK(hw_base) HWREG32((hw_base) + 0x04U)
|
||||
#define GIC_CPU_BINPOINT(hw_base) HWREG32((hw_base) + 0x08U)
|
||||
#define GIC_CPU_INTACK(hw_base) HWREG32((hw_base) + 0x0cU)
|
||||
#define GIC_CPU_EOI(hw_base) HWREG32((hw_base) + 0x10U)
|
||||
#define GIC_CPU_RUNNINGPRI(hw_base) HWREG32((hw_base) + 0x14U)
|
||||
#define GIC_CPU_HIGHPRI(hw_base) HWREG32((hw_base) + 0x18U)
|
||||
#define GIC_CPU_IIDR(hw_base) HWREG32((hw_base) + 0xFCU)
|
||||
|
||||
/** Macro to access the Generic Interrupt Controller Distributor (GICD)
|
||||
*/
|
||||
#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000U)
|
||||
#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004U)
|
||||
#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400U + ((n)/4U) * 4U)
|
||||
#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800U + ((n)/4U) * 4U)
|
||||
#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00U + ((n)/16U) * 4U)
|
||||
#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00U)
|
||||
#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10U + ((n)/4U) * 4U)
|
||||
#define GIC_DIST_SPENDSGI(hw_base, n) __REG32((hw_base) + 0xf20U + ((n)/4U) * 4U)
|
||||
#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8U)
|
||||
#define GIC_DIST_CTRL(hw_base) HWREG32((hw_base) + 0x000U)
|
||||
#define GIC_DIST_TYPE(hw_base) HWREG32((hw_base) + 0x004U)
|
||||
#define GIC_DIST_IGROUP(hw_base, n) HWREG32((hw_base) + 0x080U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_ENABLE_SET(hw_base, n) HWREG32((hw_base) + 0x100U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_ENABLE_CLEAR(hw_base, n) HWREG32((hw_base) + 0x180U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_PENDING_SET(hw_base, n) HWREG32((hw_base) + 0x200U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_PENDING_CLEAR(hw_base, n) HWREG32((hw_base) + 0x280U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_ACTIVE_SET(hw_base, n) HWREG32((hw_base) + 0x300U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) HWREG32((hw_base) + 0x380U + ((n)/32U) * 4U)
|
||||
#define GIC_DIST_PRI(hw_base, n) HWREG32((hw_base) + 0x400U + ((n)/4U) * 4U)
|
||||
#define GIC_DIST_TARGET(hw_base, n) HWREG32((hw_base) + 0x800U + ((n)/4U) * 4U)
|
||||
#define GIC_DIST_CONFIG(hw_base, n) HWREG32((hw_base) + 0xc00U + ((n)/16U) * 4U)
|
||||
#define GIC_DIST_SOFTINT(hw_base) HWREG32((hw_base) + 0xf00U)
|
||||
#define GIC_DIST_CPENDSGI(hw_base, n) HWREG32((hw_base) + 0xf10U + ((n)/4U) * 4U)
|
||||
#define GIC_DIST_SPENDSGI(hw_base, n) HWREG32((hw_base) + 0xf20U + ((n)/4U) * 4U)
|
||||
#define GIC_DIST_ICPIDR2(hw_base) HWREG32((hw_base) + 0xfe8U)
|
||||
|
||||
static unsigned int _gic_max_irq;
|
||||
|
||||
|
@ -179,7 +184,7 @@ void arm_gic_clear_pending_irq(rt_uint64_t index, int irq)
|
|||
}
|
||||
}
|
||||
|
||||
void arm_gic_set_configuration(rt_uint64_t index, int irq, uint32_t config)
|
||||
void arm_gic_set_configuration(rt_uint64_t index, int irq, rt_uint32_t config)
|
||||
{
|
||||
rt_uint64_t icfgr;
|
||||
rt_uint64_t shift;
|
||||
|
@ -323,6 +328,8 @@ void arm_gic_send_sgi(rt_uint64_t index, int irq, rt_uint64_t target_list, rt_ui
|
|||
|
||||
GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) =
|
||||
((filter_list & 0x3U) << 24U) | ((target_list & 0xFFUL) << 16U) | (irq & 0x0FUL);
|
||||
|
||||
__DSB();
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_high_pending_irq(rt_uint64_t index)
|
||||
|
@ -341,8 +348,8 @@ rt_uint64_t arm_gic_get_interface_id(rt_uint64_t index)
|
|||
|
||||
void arm_gic_set_group(rt_uint64_t index, int irq, rt_uint64_t group)
|
||||
{
|
||||
uint32_t igroupr;
|
||||
uint32_t shift;
|
||||
rt_uint32_t igroupr;
|
||||
rt_uint32_t shift;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
RT_ASSERT(group <= 1U);
|
||||
|
@ -373,6 +380,10 @@ int arm_gic_dist_init(rt_uint64_t index, rt_uint64_t dist_base, int irq_start)
|
|||
unsigned int gic_type, i;
|
||||
rt_uint64_t cpumask = 1U << 0U;
|
||||
|
||||
#ifdef ARM_SPI_BIND_CPU_ID
|
||||
cpumask = 1U << ARM_SPI_BIND_CPU_ID;
|
||||
#endif
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
_gic_table[index].dist_hw_base = dist_base;
|
||||
|
@ -502,3 +513,4 @@ long gic_dump(void)
|
|||
}
|
||||
MSH_CMD_EXPORT(gic_dump, show gic status);
|
||||
|
||||
#endif /* defined(BSP_USING_GIC) && defined(BSP_USING_GICV2) */
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
#ifndef __GIC_H__
|
||||
#define __GIC_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <stdint.h>
|
||||
#include <board.h>
|
||||
#include <rtdef.h>
|
||||
|
||||
#if defined(BSP_USING_GIC) && defined(BSP_USING_GICV2)
|
||||
|
||||
int arm_gic_get_active_irq(rt_uint64_t index);
|
||||
void arm_gic_ack(rt_uint64_t index, int irq);
|
||||
|
@ -25,7 +25,7 @@ rt_uint64_t arm_gic_get_pending_irq(rt_uint64_t index, int irq);
|
|||
void arm_gic_set_pending_irq(rt_uint64_t index, int irq);
|
||||
void arm_gic_clear_pending_irq(rt_uint64_t index, int irq);
|
||||
|
||||
void arm_gic_set_configuration(rt_uint64_t index, int irq, uint32_t config);
|
||||
void arm_gic_set_configuration(rt_uint64_t index, int irq, rt_uint32_t config);
|
||||
rt_uint64_t arm_gic_get_configuration(rt_uint64_t index, int irq);
|
||||
|
||||
void arm_gic_clear_active(rt_uint64_t index, int irq);
|
||||
|
@ -59,5 +59,7 @@ int arm_gic_cpu_init(rt_uint64_t index, rt_uint64_t cpu_base);
|
|||
void arm_gic_dump_type(rt_uint64_t index);
|
||||
void arm_gic_dump(rt_uint64_t index);
|
||||
|
||||
#endif /* defined(BSP_USING_GIC) && defined(BSP_USING_GICV2) */
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,849 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-20 Bernard first version
|
||||
* 2014-04-03 Grissiom many enhancements
|
||||
* 2018-11-22 Jesven add rt_hw_ipi_send()
|
||||
* add rt_hw_ipi_handler_install()
|
||||
* 2022-03-08 GuEe-GUI add BSP bind SPI CPU self support
|
||||
* add GICv3 AArch64 system register interface
|
||||
* modify arm_gic_redist_init() args
|
||||
* modify arm_gic_cpu_init() args
|
||||
* modify arm_gic_send_affinity_sgi() args
|
||||
* remove arm_gic_redist_address_set()
|
||||
* remove arm_gic_cpu_interface_address_set()
|
||||
* remove arm_gic_secondary_cpu_init()
|
||||
* remove get_main_cpu_affval()
|
||||
* remove arm_gic_cpumask_to_affval()
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#if defined(BSP_USING_GIC) && defined(BSP_USING_GICV3)
|
||||
|
||||
#include <gicv3.h>
|
||||
#include <cpuport.h>
|
||||
|
||||
#include <board.h>
|
||||
|
||||
#ifndef ARM_SPI_BIND_CPU_ID
|
||||
#define ARM_SPI_BIND_CPU_ID 0
|
||||
#endif
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
#define RT_CPUS_NR 1
|
||||
extern int rt_hw_cpu_id(void);
|
||||
#else
|
||||
extern rt_uint64_t rt_cpu_mpidr_early[];
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
struct arm_gic
|
||||
{
|
||||
rt_uint64_t offset; /* the first interrupt index in the vector table */
|
||||
rt_uint64_t redist_hw_base[RT_CPUS_NR]; /* the pointer of the gic redistributor */
|
||||
rt_uint64_t dist_hw_base; /* the base address of the gic distributor */
|
||||
rt_uint64_t cpu_hw_base[RT_CPUS_NR]; /* the base address of the gic cpu interface */
|
||||
};
|
||||
|
||||
/* 'ARM_GIC_MAX_NR' is the number of cores */
|
||||
static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
|
||||
static unsigned int _gic_max_irq;
|
||||
|
||||
#define GET_GICV3_REG(reg, out) __asm__ volatile ("mrs %0, " reg:"=r"(out)::"memory");
|
||||
#define SET_GICV3_REG(reg, in) __asm__ volatile ("msr " reg ", %0"::"r"(in):"memory");
|
||||
|
||||
/* AArch64 System register interface to GICv3 */
|
||||
#define ICC_IAR0_EL1 "S3_0_C12_C8_0"
|
||||
#define ICC_IAR1_EL1 "S3_0_C12_C12_0"
|
||||
#define ICC_EOIR0_EL1 "S3_0_C12_C8_1"
|
||||
#define ICC_EOIR1_EL1 "S3_0_C12_C12_1"
|
||||
#define ICC_HPPIR0_EL1 "S3_0_C12_C8_2"
|
||||
#define ICC_HPPIR1_EL1 "S3_0_C12_C12_2"
|
||||
#define ICC_BPR0_EL1 "S3_0_C12_C8_3"
|
||||
#define ICC_BPR1_EL1 "S3_0_C12_C12_3"
|
||||
#define ICC_DIR_EL1 "S3_0_C12_C11_1"
|
||||
#define ICC_PMR_EL1 "S3_0_C4_C6_0"
|
||||
#define ICC_RPR_EL1 "S3_0_C12_C11_3"
|
||||
#define ICC_CTLR_EL1 "S3_0_C12_C12_4"
|
||||
#define ICC_CTLR_EL3 "S3_6_C12_C12_4"
|
||||
#define ICC_SRE_EL1 "S3_0_C12_C12_5"
|
||||
#define ICC_SRE_EL2 "S3_4_C12_C9_5"
|
||||
#define ICC_SRE_EL3 "S3_6_C12_C12_5"
|
||||
#define ICC_IGRPEN0_EL1 "S3_0_C12_C12_6"
|
||||
#define ICC_IGRPEN1_EL1 "S3_0_C12_C12_7"
|
||||
#define ICC_IGRPEN1_EL3 "S3_6_C12_C12_7"
|
||||
#define ICC_SGI0R_EL1 "S3_0_C12_C11_7"
|
||||
#define ICC_SGI1R_EL1 "S3_0_C12_C11_5"
|
||||
#define ICC_ASGI1R_EL1 "S3_0_C12_C11_6"
|
||||
|
||||
/* Macro to access the Distributor Control Register (GICD_CTLR) */
|
||||
#define GICD_CTLR_RWP (1 << 31)
|
||||
#define GICD_CTLR_E1NWF (1 << 7)
|
||||
#define GICD_CTLR_DS (1 << 6)
|
||||
#define GICD_CTLR_ARE_NS (1 << 5)
|
||||
#define GICD_CTLR_ARE_S (1 << 4)
|
||||
#define GICD_CTLR_ENGRP1S (1 << 2)
|
||||
#define GICD_CTLR_ENGRP1NS (1 << 1)
|
||||
#define GICD_CTLR_ENGRP0 (1 << 0)
|
||||
|
||||
/* Macro to access the Redistributor Control Register (GICR_CTLR) */
|
||||
#define GICR_CTLR_UWP (1 << 31)
|
||||
#define GICR_CTLR_DPG1S (1 << 26)
|
||||
#define GICR_CTLR_DPG1NS (1 << 25)
|
||||
#define GICR_CTLR_DPG0 (1 << 24)
|
||||
#define GICR_CTLR_RWP (1 << 3)
|
||||
#define GICR_CTLR_IR (1 << 2)
|
||||
#define GICR_CTLR_CES (1 << 1)
|
||||
#define GICR_CTLR_EnableLPI (1 << 0)
|
||||
|
||||
/* Macro to access the Generic Interrupt Controller Interface (GICC) */
|
||||
#define GIC_CPU_CTRL(hw_base) HWREG32((hw_base) + 0x00U)
|
||||
#define GIC_CPU_PRIMASK(hw_base) HWREG32((hw_base) + 0x04U)
|
||||
#define GIC_CPU_BINPOINT(hw_base) HWREG32((hw_base) + 0x08U)
|
||||
#define GIC_CPU_INTACK(hw_base) HWREG32((hw_base) + 0x0cU)
|
||||
#define GIC_CPU_EOI(hw_base) HWREG32((hw_base) + 0x10U)
|
||||
#define GIC_CPU_RUNNINGPRI(hw_base) HWREG32((hw_base) + 0x14U)
|
||||
#define GIC_CPU_HIGHPRI(hw_base) HWREG32((hw_base) + 0x18U)
|
||||
#define GIC_CPU_IIDR(hw_base) HWREG32((hw_base) + 0xFCU)
|
||||
|
||||
/* Macro to access the Generic Interrupt Controller Distributor (GICD) */
|
||||
#define GIC_DIST_CTRL(hw_base) HWREG32((hw_base) + 0x000U)
|
||||
#define GIC_DIST_TYPE(hw_base) HWREG32((hw_base) + 0x004U)
|
||||
#define GIC_DIST_IGROUP(hw_base, n) HWREG32((hw_base) + 0x080U + ((n) / 32U) * 4U)
|
||||
#define GIC_DIST_ENABLE_SET(hw_base, n) HWREG32((hw_base) + 0x100U + ((n) / 32U) * 4U)
|
||||
#define GIC_DIST_ENABLE_CLEAR(hw_base, n) HWREG32((hw_base) + 0x180U + ((n) / 32U) * 4U)
|
||||
#define GIC_DIST_PENDING_SET(hw_base, n) HWREG32((hw_base) + 0x200U + ((n) / 32U) * 4U)
|
||||
#define GIC_DIST_PENDING_CLEAR(hw_base, n) HWREG32((hw_base) + 0x280U + ((n) / 32U) * 4U)
|
||||
#define GIC_DIST_ACTIVE_SET(hw_base, n) HWREG32((hw_base) + 0x300U + ((n) / 32U) * 4U)
|
||||
#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) HWREG32((hw_base) + 0x380U + ((n) / 32U) * 4U)
|
||||
#define GIC_DIST_PRI(hw_base, n) HWREG32((hw_base) + 0x400U + ((n) / 4U) * 4U)
|
||||
#define GIC_DIST_TARGET(hw_base, n) HWREG32((hw_base) + 0x800U + ((n) / 4U) * 4U)
|
||||
#define GIC_DIST_CONFIG(hw_base, n) HWREG32((hw_base) + 0xc00U + ((n) / 16U) * 4U)
|
||||
#define GIC_DIST_SOFTINT(hw_base) HWREG32((hw_base) + 0xf00U)
|
||||
#define GIC_DIST_CPENDSGI(hw_base, n) HWREG32((hw_base) + 0xf10U + ((n) / 4U) * 4U)
|
||||
#define GIC_DIST_SPENDSGI(hw_base, n) HWREG32((hw_base) + 0xf20U + ((n) / 4U) * 4U)
|
||||
#define GIC_DIST_ICPIDR2(hw_base) HWREG32((hw_base) + 0xfe8U)
|
||||
#define GIC_DIST_IROUTER(hw_base, n) HWREG64((hw_base) + 0x6000U + (n) * 8U)
|
||||
|
||||
/* SGI base address is at 64K offset from Redistributor base address */
|
||||
#define GIC_RSGI_OFFSET 0x10000
|
||||
|
||||
/* Macro to access the Generic Interrupt Controller Redistributor (GICR) */
|
||||
#define GIC_RDIST_CTRL(hw_base) HWREG32((hw_base) + 0x000U)
|
||||
#define GIC_RDIST_IIDR(hw_base) HWREG32((hw_base) + 0x004U)
|
||||
#define GIC_RDIST_TYPER(hw_base) HWREG64((hw_base) + 0x008U)
|
||||
#define GIC_RDIST_TSTATUSR(hw_base) HWREG32((hw_base) + 0x010U)
|
||||
#define GIC_RDIST_WAKER(hw_base) HWREG32((hw_base) + 0x014U)
|
||||
#define GIC_RDIST_SETLPIR(hw_base) HWREG32((hw_base) + 0x040U)
|
||||
#define GIC_RDIST_CLRLPIR(hw_base) HWREG32((hw_base) + 0x048U)
|
||||
#define GIC_RDIST_PROPBASER(hw_base) HWREG32((hw_base) + 0x070U)
|
||||
#define GIC_RDIST_PENDBASER(hw_base) HWREG32((hw_base) + 0x078U)
|
||||
#define GIC_RDIST_INVLPIR(hw_base) HWREG32((hw_base) + 0x0A0U)
|
||||
#define GIC_RDIST_INVALLR(hw_base) HWREG32((hw_base) + 0x0B0U)
|
||||
#define GIC_RDIST_SYNCR(hw_base) HWREG32((hw_base) + 0x0C0U)
|
||||
|
||||
#define GIC_RDISTSGI_IGROUPR0(hw_base, n) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x080U + (n) * 4U)
|
||||
#define GIC_RDISTSGI_ISENABLER0(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x100U)
|
||||
#define GIC_RDISTSGI_ICENABLER0(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x180U)
|
||||
#define GIC_RDISTSGI_ISPENDR0(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x200U)
|
||||
#define GIC_RDISTSGI_ICPENDR0(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x280U)
|
||||
#define GIC_RDISTSGI_ISACTIVER0(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x300U)
|
||||
#define GIC_RDISTSGI_ICACTIVER0(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x380U)
|
||||
#define GIC_RDISTSGI_IPRIORITYR(hw_base, n) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0x400U + ((n) / 4U) * 4U)
|
||||
#define GIC_RDISTSGI_ICFGR0(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0xC00U)
|
||||
#define GIC_RDISTSGI_ICFGR1(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0xC04U)
|
||||
#define GIC_RDISTSGI_IGRPMODR0(hw_base, n) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0xD00U + (n) * 4)
|
||||
#define GIC_RDISTSGI_NSACR(hw_base) HWREG32((hw_base) + GIC_RSGI_OFFSET + 0xE00U)
|
||||
|
||||
int arm_gic_get_active_irq(rt_uint64_t index)
|
||||
{
|
||||
int irq;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
GET_GICV3_REG(ICC_IAR1_EL1, irq);
|
||||
|
||||
irq = (irq & 0x1ffffff) + _gic_table[index].offset;
|
||||
return irq;
|
||||
}
|
||||
|
||||
void arm_gic_ack(rt_uint64_t index, int irq)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
__DSB();
|
||||
SET_GICV3_REG(ICC_EOIR1_EL1, irq);
|
||||
}
|
||||
|
||||
void arm_gic_mask(rt_uint64_t index, int irq)
|
||||
{
|
||||
rt_uint64_t mask = 1 << (irq % 32);
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
if (irq < 32)
|
||||
{
|
||||
rt_int32_t cpu_id = rt_hw_cpu_id();
|
||||
|
||||
GIC_RDISTSGI_ICENABLER0(_gic_table[index].redist_hw_base[cpu_id]) = mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
}
|
||||
|
||||
void arm_gic_umask(rt_uint64_t index, int irq)
|
||||
{
|
||||
rt_uint64_t mask = 1 << (irq % 32);
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
if (irq < 32)
|
||||
{
|
||||
rt_int32_t cpu_id = rt_hw_cpu_id();
|
||||
|
||||
GIC_RDISTSGI_ISENABLER0(_gic_table[index].redist_hw_base[cpu_id]) = mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_pending_irq(rt_uint64_t index, int irq)
|
||||
{
|
||||
rt_uint64_t pend;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
if (irq >= 16)
|
||||
{
|
||||
pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32)) & 0x1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* INTID 0-15 Software Generated Interrupt */
|
||||
pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4) * 8)) & 0xff;
|
||||
/* No CPU identification offered */
|
||||
if (pend != 0)
|
||||
{
|
||||
pend = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pend = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return pend;
|
||||
}
|
||||
|
||||
void arm_gic_set_pending_irq(rt_uint64_t index, int irq)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
if (irq >= 16)
|
||||
{
|
||||
GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) = 1 << (irq % 32);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* INTID 0-15 Software Generated Interrupt */
|
||||
/* Forward the interrupt to the CPU interface that requested it */
|
||||
GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) = (irq | 0x02000000);
|
||||
}
|
||||
}
|
||||
|
||||
void arm_gic_clear_pending_irq(rt_uint64_t index, int irq)
|
||||
{
|
||||
rt_uint64_t mask;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
if (irq >= 16)
|
||||
{
|
||||
mask = 1 << (irq % 32);
|
||||
GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = 1 << ((irq % 4) * 8);
|
||||
GIC_DIST_CPENDSGI(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
}
|
||||
|
||||
void arm_gic_set_configuration(rt_uint64_t index, int irq, rt_uint32_t config)
|
||||
{
|
||||
rt_uint64_t icfgr;
|
||||
rt_uint64_t shift;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
icfgr = GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq);
|
||||
shift = (irq % 16) << 1;
|
||||
|
||||
icfgr &= (~(3 << shift));
|
||||
icfgr |= (config << shift);
|
||||
|
||||
GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) = icfgr;
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_configuration(rt_uint64_t index, int irq)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
return (GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) >> ((irq % 16) >> 1));
|
||||
}
|
||||
|
||||
void arm_gic_clear_active(rt_uint64_t index, int irq)
|
||||
{
|
||||
rt_uint64_t mask = 1 << (irq % 32);
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
|
||||
/* Set up the cpu mask for the specific interrupt */
|
||||
void arm_gic_set_cpu(rt_uint64_t index, int irq, unsigned int cpumask)
|
||||
{
|
||||
rt_uint64_t old_tgt;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq);
|
||||
|
||||
old_tgt &= ~(0x0ff << ((irq % 4) * 8));
|
||||
old_tgt |= cpumask << ((irq % 4) * 8);
|
||||
|
||||
GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_target_cpu(rt_uint64_t index, int irq)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
return (GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) >> ((irq % 4) * 8)) & 0xff;
|
||||
}
|
||||
|
||||
void arm_gic_set_priority(rt_uint64_t index, int irq, rt_uint64_t priority)
|
||||
{
|
||||
rt_uint64_t mask;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
if (irq < 32)
|
||||
{
|
||||
rt_int32_t cpu_id = rt_hw_cpu_id();
|
||||
|
||||
mask = GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq);
|
||||
mask &= ~(0xff << ((irq % 4) * 8));
|
||||
mask |= ((priority & 0xff) << ((irq % 4) * 8));
|
||||
GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq) = mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq);
|
||||
mask &= ~(0xff << ((irq % 4) * 8));
|
||||
mask |= ((priority & 0xff) << ((irq % 4) * 8));
|
||||
GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) = mask;
|
||||
}
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_priority(rt_uint64_t index, int irq)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
if (irq < 32)
|
||||
{
|
||||
rt_int32_t cpu_id = rt_hw_cpu_id();
|
||||
|
||||
return (GIC_RDISTSGI_IPRIORITYR(_gic_table[index].redist_hw_base[cpu_id], irq) >> ((irq % 4) * 8)) & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4) * 8)) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void arm_gic_set_system_register_enable_mask(rt_uint64_t index, rt_uint64_t value)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
value &= 0xff;
|
||||
/* set priority mask */
|
||||
SET_GICV3_REG(ICC_SRE_EL1, value);
|
||||
__ISB();
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_system_register_enable_mask(rt_uint64_t index)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
rt_uint64_t value;
|
||||
|
||||
GET_GICV3_REG(ICC_SRE_EL1, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void arm_gic_set_interface_prior_mask(rt_uint64_t index, rt_uint64_t priority)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
priority &= 0xff;
|
||||
/* set priority mask */
|
||||
SET_GICV3_REG(ICC_PMR_EL1, priority);
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_interface_prior_mask(rt_uint64_t index)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
rt_uint64_t priority;
|
||||
|
||||
GET_GICV3_REG(ICC_PMR_EL1, priority);
|
||||
return priority;
|
||||
}
|
||||
|
||||
void arm_gic_set_binary_point(rt_uint64_t index, rt_uint64_t binary_point)
|
||||
{
|
||||
index = index;
|
||||
binary_point &= 0x7;
|
||||
|
||||
SET_GICV3_REG(ICC_BPR1_EL1, binary_point);
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_binary_point(rt_uint64_t index)
|
||||
{
|
||||
rt_uint64_t binary_point;
|
||||
|
||||
index = index;
|
||||
GET_GICV3_REG(ICC_BPR1_EL1, binary_point);
|
||||
return binary_point;
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_irq_status(rt_uint64_t index, int irq)
|
||||
{
|
||||
rt_uint64_t pending, active;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
active = (GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32)) & 0x1;
|
||||
pending = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32)) & 0x1;
|
||||
|
||||
return ((active << 1) | pending);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
void arm_gic_send_affinity_sgi(rt_uint64_t index, int irq, rt_uint64_t cpu_masks[], rt_uint64_t routing_mode)
|
||||
{
|
||||
const int cpu_mask_cpu_max_nr = sizeof(cpu_masks[0]) * 8;
|
||||
rt_uint64_t int_id = (irq & 0xf) << 24;
|
||||
rt_uint64_t irm = routing_mode << 40; /* Interrupt Routing Mode */
|
||||
|
||||
if (routing_mode == GICV3_ROUTED_TO_SPEC)
|
||||
{
|
||||
int cpu_id, cpu_mask_bit, i, cpu_masks_nr = RT_CPUS_NR / cpu_mask_cpu_max_nr;
|
||||
rt_uint16_t target_list;
|
||||
rt_uint64_t rs = 0; /* Range Selector */
|
||||
rt_uint64_t affinity_val, next_affinity_val;
|
||||
|
||||
if (cpu_masks_nr * cpu_mask_cpu_max_nr != RT_CPUS_NR)
|
||||
{
|
||||
++cpu_masks_nr;
|
||||
}
|
||||
|
||||
for (i = cpu_id = 0; i < cpu_masks_nr;)
|
||||
{
|
||||
/* No cpu in this mask */
|
||||
if (cpu_masks[i] == 0)
|
||||
{
|
||||
++i;
|
||||
cpu_id += cpu_mask_cpu_max_nr;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get last cpu affinity value */
|
||||
affinity_val = rt_cpu_mpidr_early[cpu_id] & 0xff00ffff00ULL;
|
||||
|
||||
/* Read 16 cpus information */
|
||||
for (cpu_mask_bit = 0; cpu_mask_bit < 16; ++cpu_mask_bit, ++cpu_id)
|
||||
{
|
||||
/* MPIDR_EL1: aff3[39:32], aff2[23:16], aff1[15:8] */
|
||||
next_affinity_val = rt_cpu_mpidr_early[cpu_id] & 0xff00ffff00ULL;
|
||||
|
||||
/* Affinity value is different, read end */
|
||||
if (affinity_val != next_affinity_val)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get all valid cpu mask */
|
||||
target_list = (0xffff >> (16 - cpu_mask_bit)) & cpu_masks[i];
|
||||
/* Clear read mask */
|
||||
cpu_masks[i] >>= cpu_mask_bit;
|
||||
/* ICC_SGI1R_EL1: aff3[55:48], aff2[39:32], aff1[23:16] */
|
||||
affinity_val <<= 8;
|
||||
|
||||
__DSB();
|
||||
/* Interrupts routed to the PEs specified by Aff3.Aff2.Aff1.<target list>. */
|
||||
SET_GICV3_REG(ICC_SGI1R_EL1, affinity_val | (rs << 44) | irm | int_id | target_list);
|
||||
__ISB();
|
||||
|
||||
/* Check if reset the range selector */
|
||||
rs = affinity_val != next_affinity_val ? 0 : rs + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__DSB();
|
||||
/* Interrupts routed to all PEs in the system, excluding "self". */
|
||||
SET_GICV3_REG(ICC_SGI1R_EL1, irm | int_id);
|
||||
__ISB();
|
||||
}
|
||||
}
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
rt_uint64_t arm_gic_get_high_pending_irq(rt_uint64_t index)
|
||||
{
|
||||
rt_uint64_t irq;
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
index = index;
|
||||
GET_GICV3_REG(ICC_HPPIR1_EL1, irq);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_interface_id(rt_uint64_t index)
|
||||
{
|
||||
rt_uint64_t ret = 0;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
if (_gic_table[index].cpu_hw_base != RT_NULL)
|
||||
{
|
||||
ret = GIC_CPU_IIDR(_gic_table[index].cpu_hw_base);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void arm_gic_set_group(rt_uint64_t index, int irq, rt_uint64_t group)
|
||||
{
|
||||
rt_uint64_t igroupr;
|
||||
rt_uint64_t shift;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
RT_ASSERT(group <= 1);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
igroupr = GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq);
|
||||
shift = (irq % 32);
|
||||
igroupr &= (~(1U << shift));
|
||||
igroupr |= ((group & 0x1U) << shift);
|
||||
|
||||
GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) = igroupr;
|
||||
}
|
||||
|
||||
rt_uint64_t arm_gic_get_group(rt_uint64_t index, int irq)
|
||||
{
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
irq = irq - _gic_table[index].offset;
|
||||
RT_ASSERT(irq >= 0);
|
||||
|
||||
return (GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) >> (irq % 32)) & 0x1UL;
|
||||
}
|
||||
|
||||
static int arm_gicv3_wait_rwp(rt_uint64_t index, rt_uint64_t irq)
|
||||
{
|
||||
rt_uint64_t rwp_bit;
|
||||
rt_uint64_t base;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
if (irq < 32)
|
||||
{
|
||||
rt_int32_t cpu_id = rt_hw_cpu_id();
|
||||
|
||||
base = _gic_table[index].redist_hw_base[cpu_id];
|
||||
rwp_bit = GICR_CTLR_RWP;
|
||||
}
|
||||
else
|
||||
{
|
||||
base = _gic_table[index].dist_hw_base;
|
||||
rwp_bit = GICD_CTLR_RWP;
|
||||
}
|
||||
|
||||
while (HWREG32(base) & rwp_bit)
|
||||
{
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arm_gic_dist_init(rt_uint64_t index, rt_uint64_t dist_base, int irq_start)
|
||||
{
|
||||
int i;
|
||||
unsigned int gic_type;
|
||||
rt_uint64_t main_cpu_affinity_val;
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
_gic_table[index].dist_hw_base = dist_base;
|
||||
_gic_table[index].offset = irq_start;
|
||||
|
||||
|
||||
/* Find out how many interrupts are supported. */
|
||||
gic_type = GIC_DIST_TYPE(dist_base);
|
||||
_gic_max_irq = ((gic_type & 0x1f) + 1) * 32;
|
||||
|
||||
/*
|
||||
* The GIC only supports up to 1020 interrupt sources.
|
||||
* Limit this to either the architected maximum, or the
|
||||
* platform maximum.
|
||||
*/
|
||||
if (_gic_max_irq > 1020)
|
||||
{
|
||||
_gic_max_irq = 1020;
|
||||
}
|
||||
if (_gic_max_irq > ARM_GIC_NR_IRQS) /* the platform maximum interrupts */
|
||||
{
|
||||
_gic_max_irq = ARM_GIC_NR_IRQS;
|
||||
}
|
||||
|
||||
GIC_DIST_CTRL(dist_base) = 0;
|
||||
/* Wait for register write pending */
|
||||
arm_gicv3_wait_rwp(0, 32);
|
||||
|
||||
/* Set all global interrupts to be level triggered, active low. */
|
||||
for (i = 32; i < _gic_max_irq; i += 16)
|
||||
{
|
||||
GIC_DIST_CONFIG(dist_base, i) = 0;
|
||||
}
|
||||
|
||||
arm_gicv3_wait_rwp(0, 32);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
main_cpu_affinity_val = rt_cpu_mpidr_early[ARM_SPI_BIND_CPU_ID];
|
||||
#else
|
||||
__asm__ volatile ("mrs %0, mpidr_el1":"=r"(main_cpu_affinity_val));
|
||||
#endif
|
||||
|
||||
/* aff3[39:32], aff2[23:16], aff1[15:8], aff0[7:0] */
|
||||
main_cpu_affinity_val &= 0xff00ffffffULL;
|
||||
|
||||
/* Set all global interrupts to this CPU only. */
|
||||
for (i = 32; i < _gic_max_irq; i++)
|
||||
{
|
||||
GIC_DIST_IROUTER(dist_base, i) = main_cpu_affinity_val | (GICV3_ROUTED_TO_SPEC << 31);
|
||||
}
|
||||
|
||||
arm_gicv3_wait_rwp(0, 32);
|
||||
|
||||
/* Set priority on spi interrupts. */
|
||||
for (i = 32; i < _gic_max_irq; i += 4)
|
||||
{
|
||||
GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0;
|
||||
}
|
||||
|
||||
arm_gicv3_wait_rwp(0, 32);
|
||||
/* Disable all interrupts. */
|
||||
for (i = 0; i < _gic_max_irq; i += 32)
|
||||
{
|
||||
GIC_DIST_PENDING_CLEAR(dist_base, i) = 0xffffffff;
|
||||
GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffff;
|
||||
}
|
||||
|
||||
arm_gicv3_wait_rwp(0, 32);
|
||||
/* All interrupts defaults to IGROUP1(IRQ). */
|
||||
for (i = 0; i < _gic_max_irq; i += 32)
|
||||
{
|
||||
GIC_DIST_IGROUP(dist_base, i) = 0xffffffff;
|
||||
}
|
||||
|
||||
arm_gicv3_wait_rwp(0, 32);
|
||||
|
||||
/*
|
||||
* The Distributor control register (GICD_CTLR) must be configured to enable the interrupt groups and to set the routing mode.
|
||||
* Enable Affinity routing (ARE bits) The ARE bits in GICD_CTLR control whether affinity routing is enabled.
|
||||
* If affinity routing is not enabled, GICv3 can be configured for legacy operation.
|
||||
* Whether affinity routing is enabled or not can be controlled separately for Secure and Non-secure state.
|
||||
* Enables GICD_CTLR contains separate enable bits for Group 0, Secure Group 1 and Non-secure Group 1:
|
||||
* GICD_CTLR.EnableGrp1S enables distribution of Secure Group 1 interrupts.
|
||||
* GICD_CTLR.EnableGrp1NS enables distribution of Non-secure Group 1 interrupts.
|
||||
* GICD_CTLR.EnableGrp0 enables distribution of Group 0 interrupts.
|
||||
*/
|
||||
GIC_DIST_CTRL(dist_base) = GICD_CTLR_ARE_NS | GICD_CTLR_ENGRP1NS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arm_gic_redist_init(rt_uint64_t index, rt_uint64_t redist_base)
|
||||
{
|
||||
int i;
|
||||
int cpu_id = rt_hw_cpu_id();
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
redist_base += cpu_id * (2 << 16);
|
||||
_gic_table[index].redist_hw_base[cpu_id] = redist_base;
|
||||
|
||||
/* redistributor enable */
|
||||
GIC_RDIST_WAKER(redist_base) &= ~(1 << 1);
|
||||
while (GIC_RDIST_WAKER(redist_base) & (1 << 2))
|
||||
{
|
||||
}
|
||||
|
||||
/* Disable all sgi and ppi interrupt */
|
||||
GIC_RDISTSGI_ICENABLER0(redist_base) = 0xffffffff;
|
||||
arm_gicv3_wait_rwp(0, 0);
|
||||
|
||||
/* Clear all inetrrupt pending */
|
||||
GIC_RDISTSGI_ICPENDR0(redist_base) = 0xffffffff;
|
||||
|
||||
/* the corresponding interrupt is Group 1 or Non-secure Group 1. */
|
||||
GIC_RDISTSGI_IGROUPR0(redist_base, 0) = 0xffffffff;
|
||||
GIC_RDISTSGI_IGRPMODR0(redist_base, 0) = 0xffffffff;
|
||||
|
||||
/* Configure default priorities for SGI 0:15 and PPI 16:31. */
|
||||
for (i = 0; i < 32; i += 4)
|
||||
{
|
||||
GIC_RDISTSGI_IPRIORITYR(redist_base, i) = 0xa0a0a0a0U;
|
||||
}
|
||||
|
||||
/* Trigger level for PPI interrupts*/
|
||||
GIC_RDISTSGI_ICFGR1(redist_base) = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arm_gic_cpu_init(rt_uint64_t index, rt_uint64_t cpu_base)
|
||||
{
|
||||
rt_uint64_t value;
|
||||
int cpu_id = rt_hw_cpu_id();
|
||||
|
||||
RT_ASSERT(index < ARM_GIC_MAX_NR);
|
||||
|
||||
_gic_table[index].cpu_hw_base[cpu_id] = cpu_base;
|
||||
|
||||
value = arm_gic_get_system_register_enable_mask(index);
|
||||
value |= (1 << 0);
|
||||
arm_gic_set_system_register_enable_mask(index, value);
|
||||
SET_GICV3_REG(ICC_CTLR_EL1, 0);
|
||||
|
||||
arm_gic_set_interface_prior_mask(index, 0xff);
|
||||
|
||||
/* Enable group1 interrupt */
|
||||
value = 1;
|
||||
SET_GICV3_REG(ICC_IGRPEN1_EL1, value);
|
||||
|
||||
arm_gic_set_binary_point(0, 0);
|
||||
|
||||
/* ICC_BPR0_EL1 determines the preemption group for both Group 0 and Group 1 interrupts. */
|
||||
value = 1; /* ICC_BPR0_EL1 determines the preemption group for both Group 0 and Group 1 interrupts.*/
|
||||
value |= 1 << 18; /* Targeted SGIs with affinity level 0 values of 0 - 255 are supported. */
|
||||
SET_GICV3_REG(ICC_CTLR_EL1, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arm_gic_dump_type(rt_uint64_t index)
|
||||
{
|
||||
unsigned int gic_type;
|
||||
|
||||
gic_type = GIC_DIST_TYPE(_gic_table[index].dist_hw_base);
|
||||
rt_kprintf("GICv%d on %p, max IRQs: %d, %s security extension(%08x)\n",
|
||||
(GIC_DIST_ICPIDR2(_gic_table[index].dist_hw_base) >> 4) & 0xf,
|
||||
_gic_table[index].dist_hw_base,
|
||||
_gic_max_irq,
|
||||
gic_type & (1 << 10) ? "has" : "no",
|
||||
gic_type);
|
||||
}
|
||||
|
||||
void arm_gic_dump(rt_uint64_t index)
|
||||
{
|
||||
int i;
|
||||
unsigned int val;
|
||||
|
||||
val = arm_gic_get_high_pending_irq(0);
|
||||
rt_kprintf("--- high pending priority: %d(%08x)\n", val, val);
|
||||
|
||||
rt_kprintf("--- hw mask ---\n");
|
||||
for (i = 0; i < _gic_max_irq / 32; ++i)
|
||||
{
|
||||
rt_kprintf("0x%08x, ", GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, i * 32));
|
||||
}
|
||||
|
||||
rt_kprintf("\b\b\n--- hw pending ---\n");
|
||||
for (i = 0; i < _gic_max_irq / 32; ++i)
|
||||
{
|
||||
rt_kprintf("0x%08x, ", GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, i * 32));
|
||||
}
|
||||
|
||||
rt_kprintf("\b\b\n--- hw active ---\n");
|
||||
for (i = 0; i < _gic_max_irq / 32; ++i)
|
||||
{
|
||||
rt_kprintf("0x%08x, ", GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, i * 32));
|
||||
}
|
||||
|
||||
rt_kprintf("\b\b\n");
|
||||
}
|
||||
|
||||
long gic_dump(void)
|
||||
{
|
||||
arm_gic_dump_type(0);
|
||||
arm_gic_dump(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
MSH_CMD_EXPORT(gic_dump, show gic status);
|
||||
|
||||
#endif /* defined(BSP_USING_GIC) && defined(BSP_USING_GICV3) */
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-20 Bernard first version
|
||||
* 2014-04-03 Grissiom many enhancements
|
||||
* 2018-11-22 Jesven add rt_hw_ipi_send()
|
||||
* add rt_hw_ipi_handler_install()
|
||||
*/
|
||||
|
||||
#ifndef __GICV3_H__
|
||||
#define __GICV3_H__
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
#if defined(BSP_USING_GIC) && defined(BSP_USING_GICV3)
|
||||
|
||||
#define GICV3_ROUTED_TO_ALL 1UL
|
||||
#define GICV3_ROUTED_TO_SPEC 0UL
|
||||
|
||||
int arm_gic_get_active_irq(rt_uint64_t index);
|
||||
void arm_gic_ack(rt_uint64_t index, int irq);
|
||||
|
||||
void arm_gic_mask(rt_uint64_t index, int irq);
|
||||
void arm_gic_umask(rt_uint64_t index, int irq);
|
||||
|
||||
rt_uint64_t arm_gic_get_pending_irq(rt_uint64_t index, int irq);
|
||||
void arm_gic_set_pending_irq(rt_uint64_t index, int irq);
|
||||
void arm_gic_clear_pending_irq(rt_uint64_t index, int irq);
|
||||
|
||||
void arm_gic_set_configuration(rt_uint64_t index, int irq, rt_uint32_t config);
|
||||
rt_uint64_t arm_gic_get_configuration(rt_uint64_t index, int irq);
|
||||
|
||||
void arm_gic_clear_active(rt_uint64_t index, int irq);
|
||||
|
||||
void arm_gic_set_cpu(rt_uint64_t index, int irq, unsigned int cpumask);
|
||||
rt_uint64_t arm_gic_get_target_cpu(rt_uint64_t index, int irq);
|
||||
|
||||
void arm_gic_set_priority(rt_uint64_t index, int irq, rt_uint64_t priority);
|
||||
rt_uint64_t arm_gic_get_priority(rt_uint64_t index, int irq);
|
||||
|
||||
void arm_gic_set_interface_prior_mask(rt_uint64_t index, rt_uint64_t priority);
|
||||
rt_uint64_t arm_gic_get_interface_prior_mask(rt_uint64_t index);
|
||||
|
||||
void arm_gic_set_binary_point(rt_uint64_t index, rt_uint64_t binary_point);
|
||||
rt_uint64_t arm_gic_get_binary_point(rt_uint64_t index);
|
||||
|
||||
rt_uint64_t arm_gic_get_irq_status(rt_uint64_t index, int irq);
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
void arm_gic_send_affinity_sgi(rt_uint64_t index, int irq, rt_uint64_t cpu_masks[], rt_uint64_t routing_mode);
|
||||
#endif
|
||||
|
||||
rt_uint64_t arm_gic_get_high_pending_irq(rt_uint64_t index);
|
||||
|
||||
rt_uint64_t arm_gic_get_interface_id(rt_uint64_t index);
|
||||
|
||||
void arm_gic_set_group(rt_uint64_t index, int irq, rt_uint64_t group);
|
||||
rt_uint64_t arm_gic_get_group(rt_uint64_t index, int irq);
|
||||
|
||||
int arm_gic_redist_address_set(rt_uint64_t index, rt_uint64_t redist_addr, int cpu_id);
|
||||
int arm_gic_cpu_interface_address_set(rt_uint64_t index, rt_uint64_t interface_addr, int cpu_id);
|
||||
|
||||
int arm_gic_dist_init(rt_uint64_t index, rt_uint64_t dist_base, int irq_start);
|
||||
int arm_gic_redist_init(rt_uint64_t index, rt_uint64_t redist_base);
|
||||
int arm_gic_cpu_init(rt_uint64_t index, rt_uint64_t cpu_base);
|
||||
|
||||
void arm_gic_dump_type(rt_uint64_t index);
|
||||
void arm_gic_dump(rt_uint64_t index);
|
||||
|
||||
#endif /* defined(BSP_USING_GIC) && defined(BSP_USING_GICV3) */
|
||||
|
||||
#endif
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include <rtthread.h>
|
||||
#include "interrupt.h"
|
||||
#include "gic.h"
|
||||
#include "gicv3.h"
|
||||
#include "armv8.h"
|
||||
#include "mmu.h"
|
||||
#include "cpuport.h"
|
||||
|
@ -52,6 +53,9 @@ void rt_hw_interrupt_init(void)
|
|||
/* initialize ARM GIC */
|
||||
arm_gic_dist_init(0, platform_get_gic_dist_base(), GIC_IRQ_START);
|
||||
arm_gic_cpu_init(0, platform_get_gic_cpu_base());
|
||||
#ifdef BSP_USING_GICV3
|
||||
arm_gic_redist_init(0, platform_get_gic_redist_base());
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -346,7 +350,11 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
|||
void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
|
||||
{
|
||||
#ifdef BSP_USING_GIC
|
||||
#ifdef BSP_USING_GICV2
|
||||
arm_gic_send_sgi(0, ipi_vector, cpu_mask, 0);
|
||||
#else
|
||||
arm_gic_send_affinity_sgi(0, ipi_vector, (rt_uint64_t *)&cpu_mask, GICV3_ROUTED_TO_SPEC);
|
||||
#endif
|
||||
#else
|
||||
int i;
|
||||
|
||||
|
@ -359,8 +367,9 @@ void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
|
|||
IPI_MAILBOX_SET(i) = 1 << ipi_vector;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__DSB();
|
||||
#endif
|
||||
}
|
||||
|
||||
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)
|
||||
|
|
|
@ -29,11 +29,19 @@ static psci_call_handle psci_call = psci_smc_call;
|
|||
static uint64_t shutdown_args[3] = {0, 0, 0};
|
||||
static uint64_t reboot_args[3] = {0, 0, 0};
|
||||
|
||||
void arm_psci_init(uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args)
|
||||
void arm_psci_init(uint64_t method, uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args)
|
||||
{
|
||||
if (rt_hw_get_current_el() < 2)
|
||||
switch (method)
|
||||
{
|
||||
psci_call = psci_hvc_call;
|
||||
case PSCI_METHOD_SMC:
|
||||
psci_call = psci_smc_call;
|
||||
break;
|
||||
case PSCI_METHOD_HVC:
|
||||
if (rt_hw_get_current_el() < 2)
|
||||
{
|
||||
psci_call = psci_hvc_call;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (platform_shutdown_args != RT_NULL)
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
*/
|
||||
#define PSCI_VER_0_2 0x00000002
|
||||
|
||||
#define PSCI_METHOD_SMC 3
|
||||
#define PSCI_METHOD_HVC 2
|
||||
|
||||
/* PSCI 0.2 interface */
|
||||
#define PSCI_0_2_FN_BASE 0x84000000
|
||||
#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n))
|
||||
|
@ -114,7 +117,7 @@
|
|||
#define PSCI_RET_DISABLED (-8)
|
||||
#define PSCI_RET_INVALID_ADDRESS (-9)
|
||||
|
||||
void arm_psci_init(uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args);
|
||||
void arm_psci_init(uint64_t method, uint64_t *platform_shutdown_args, uint64_t *platform_reboot_args);
|
||||
|
||||
uint32_t arm_psci_get_version();
|
||||
uint32_t arm_psci_get_affinity_info(uint64_t target_affinity, uint64_t lowest_affinity_level);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2020, RT-Thread Development Team
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
|
@ -11,19 +11,28 @@
|
|||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
.section ".text.entrypoint","ax"
|
||||
|
||||
#define SECONDARY_STACK_SIZE 4096
|
||||
|
||||
.section ".text.entrypoint","ax"
|
||||
|
||||
.globl _start
|
||||
.globl secondary_cpu_start
|
||||
_start:
|
||||
#ifdef RT_USING_SMP
|
||||
mrs x1, mpidr_el1
|
||||
and x1, x1, #0xff
|
||||
cbnz x1, cpu_idle /* If cpu id > 0, stop slave cores */
|
||||
adr x4, .boot_cpu_mpidr
|
||||
str x1, [x4]
|
||||
dsb sy
|
||||
#endif
|
||||
|
||||
bl __asm_flush_dcache_all /* The kernel and data must flush to DDR */
|
||||
|
||||
secondary_cpu_start:
|
||||
#ifdef RT_USING_SMP
|
||||
adr x4, .boot_cpu_mpidr
|
||||
ldr x4, [x4]
|
||||
dsb sy
|
||||
/* Read cpu mpidr_el1 */
|
||||
mrs x1, mpidr_el1
|
||||
|
||||
|
@ -34,6 +43,7 @@ secondary_cpu_start:
|
|||
cpu_id_confirm:
|
||||
add x2, x2, #1 /* Next cpu id inc */
|
||||
ldr x3, [x0], #8
|
||||
dsb sy
|
||||
cmp x3, #0
|
||||
beq cpu_idle /* Mean that `rt_cpu_mpidr_early' table is end */
|
||||
cmp x3, x1
|
||||
|
@ -42,7 +52,8 @@ cpu_id_confirm:
|
|||
/* Get cpu id success */
|
||||
sub x0, x2, #1
|
||||
msr tpidr_el1, x0 /* Save cpu id global */
|
||||
cbz x0, cpu_setup /* Only go to cpu_setup when cpu id = 0 */
|
||||
cmp x3, x4 /* If it is boot cpu */
|
||||
beq boot_cpu_setup
|
||||
|
||||
/* Set current cpu's stack top */
|
||||
sub x0, x0, #1
|
||||
|
@ -53,14 +64,9 @@ cpu_id_confirm:
|
|||
b cpu_check_el
|
||||
#else
|
||||
msr tpidr_el1, xzr
|
||||
b cpu_setup
|
||||
#endif /* RT_USING_SMP */
|
||||
|
||||
cpu_idle:
|
||||
wfe
|
||||
b cpu_idle
|
||||
|
||||
cpu_setup:
|
||||
boot_cpu_setup:
|
||||
ldr x1, =_start
|
||||
|
||||
cpu_check_el:
|
||||
|
@ -75,7 +81,7 @@ cpu_check_el:
|
|||
mov x2, #(1 << 0) /* EL0 and EL1 are in Non-Secure state */
|
||||
orr x2, x2, #(1 << 4) /* RES1 */
|
||||
orr x2, x2, #(1 << 5) /* RES1 */
|
||||
orr x2, x2, #(1 << 7) /* SMC instructions are undefined at EL1 and above */
|
||||
bic x2, x2, #(1 << 7) /* SMC instructions are enabled at EL1 and above */
|
||||
orr x2, x2, #(1 << 8) /* HVC instructions are enabled at EL1 and above */
|
||||
orr x2, x2, #(1 << 10) /* The next lower level is AArch64 */
|
||||
msr scr_el3, x2
|
||||
|
@ -91,7 +97,7 @@ cpu_check_el:
|
|||
eret
|
||||
|
||||
cpu_not_in_el3: /* Running at EL2 or EL1 */
|
||||
cmp x0, #4 /* EL1 = 0100 */
|
||||
cmp x0, #4 /* EL1 = 0100 */
|
||||
beq cpu_in_el1
|
||||
|
||||
cpu_in_el2:
|
||||
|
@ -159,9 +165,16 @@ clean_bss_check:
|
|||
|
||||
jump_to_entry:
|
||||
b rtthread_startup
|
||||
b cpu_idle /* For failsafe, halt this core too */
|
||||
|
||||
cpu_idle:
|
||||
wfe
|
||||
b cpu_idle
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
.align 3
|
||||
.boot_cpu_mpidr:
|
||||
.quad 0x0
|
||||
|
||||
.align 12
|
||||
.secondary_cpu_stack:
|
||||
.space (SECONDARY_STACK_SIZE * (RT_CPUS_NR - 1))
|
||||
|
|
Loading…
Reference in New Issue