Merge pull request #5090 from GuEe-GUI/master

Merge AArch64 libcpu and add some drivers for their bsps
This commit is contained in:
Bernard Xiong 2021-09-26 17:18:43 +08:00 committed by GitHub
commit 8bf5c27406
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 6137 additions and 1900 deletions

View File

@ -14,7 +14,7 @@ CONFIG_RT_ALIGN_SIZE=4
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=1000
CONFIG_RT_TICK_PER_SECOND=100
CONFIG_RT_USING_OVERFLOW_CHECK=y
CONFIG_RT_USING_HOOK=y
CONFIG_RT_USING_IDLE_HOOK=y
@ -29,6 +29,7 @@ CONFIG_RT_TIMER_THREAD_STACK_SIZE=2048
#
# CONFIG_RT_KSERVICE_USING_STDLIB is not set
# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
# CONFIG_RT_USING_ASM_MEMCPY is not set
CONFIG_RT_DEBUG=y
CONFIG_RT_DEBUG_COLOR=y
# CONFIG_RT_DEBUG_INIT_CONFIG is not set
@ -97,19 +98,19 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10
# Command shell
#
CONFIG_RT_USING_FINSH=y
CONFIG_RT_USING_MSH=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_THREAD_PRIORITY=20
CONFIG_FINSH_THREAD_STACK_SIZE=4096
CONFIG_FINSH_CMD_SIZE=80
# CONFIG_FINSH_USING_AUTH is not set
CONFIG_FINSH_USING_MSH=y
CONFIG_FINSH_USING_MSH_DEFAULT=y
CONFIG_FINSH_USING_MSH_ONLY=y
CONFIG_FINSH_ARG_MAX=10
#
@ -121,7 +122,28 @@ CONFIG_DFS_FILESYSTEMS_MAX=2
CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
CONFIG_DFS_FD_MAX=16
# CONFIG_RT_USING_DFS_MNTTABLE is not set
# CONFIG_RT_USING_DFS_ELMFAT is not set
CONFIG_RT_USING_DFS_ELMFAT=y
#
# elm-chan's FatFs, Generic FAT Filesystem Module
#
CONFIG_RT_DFS_ELM_CODE_PAGE=437
CONFIG_RT_DFS_ELM_WORD_ACCESS=y
# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set
# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set
# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
CONFIG_RT_DFS_ELM_USE_LFN_3=y
CONFIG_RT_DFS_ELM_USE_LFN=3
CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y
# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set
# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set
# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set
CONFIG_RT_DFS_ELM_LFN_UNICODE=0
CONFIG_RT_DFS_ELM_MAX_LFN=255
CONFIG_RT_DFS_ELM_DRIVES=2
CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
# CONFIG_RT_DFS_ELM_USE_ERASE is not set
CONFIG_RT_DFS_ELM_REENTRANT=y
CONFIG_RT_USING_DFS_DEVFS=y
# CONFIG_RT_USING_DFS_ROMFS is not set
# CONFIG_RT_USING_DFS_RAMFS is not set
@ -180,7 +202,7 @@ CONFIG_RT_USING_POSIX=y
# CONFIG_RT_USING_POSIX_GETLINE is not set
# CONFIG_RT_USING_POSIX_AIO is not set
# CONFIG_RT_USING_MODULE is not set
CONFIG_RT_LIBC_FIXED_TIMEZONE=8
CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
#
# Network
@ -312,6 +334,8 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# 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_HM is not set
#
# security packages
@ -328,6 +352,7 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# 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
@ -438,6 +463,9 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# 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_WCWIDTH is not set
# CONFIG_PKG_USING_MCUBOOT is not set
#
# peripheral libraries and drivers
@ -508,6 +536,9 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# 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
#
# AI packages
@ -525,6 +556,27 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
#
# miscellaneous packages
#
#
# 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_LIBCSV is not set
# CONFIG_PKG_USING_OPTPARSE is not set
# CONFIG_PKG_USING_FASTLZ is not set
@ -542,14 +594,6 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# CONFIG_PKG_USING_DIGITALCTRL is not set
# CONFIG_PKG_USING_UPACKER is not set
# CONFIG_PKG_USING_UPARAM is not set
#
# 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
# CONFIG_PKG_USING_HELLO is not set
# CONFIG_PKG_USING_VI is not set
# CONFIG_PKG_USING_KI is not set
@ -557,20 +601,11 @@ CONFIG_RT_LIBC_FIXED_TIMEZONE=8
# CONFIG_PKG_USING_VT100 is not set
# CONFIG_PKG_USING_UKAL is not set
# CONFIG_PKG_USING_CRCLIB is not set
#
# entertainment: terminal games and other interesting software packages
#
# 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_ACLOCK is not set
# CONFIG_PKG_USING_LWGPS is not set
# CONFIG_PKG_USING_STATE_MACHINE is not set
# CONFIG_PKG_USING_MCURSES is not set
# CONFIG_PKG_USING_COWSAY is not set
# CONFIG_PKG_USING_TERMBOX is not set
CONFIG_SOC_VIRT64_AARCH64=y
#
@ -579,5 +614,6 @@ CONFIG_SOC_VIRT64_AARCH64=y
CONFIG_BSP_SUPPORT_FPU=y
CONFIG_BSP_USING_UART=y
CONFIG_RT_USING_UART0=y
CONFIG_BSP_USING_VIRTIO_BLK=y
CONFIG_RT_USING_VIRTIO_BLK0=y
CONFIG_BSP_USING_GIC=y
CONFIG_BSP_USING_GIC390=y

View File

@ -49,4 +49,5 @@ msh />
| Driver | Condition | Remark |
| ------ | --------- | ------ |
| UART | Support | UART0 |
| UART | Support | UART0 |
| VIRTIO BLK | Support | VIRTIO BLK0 |

View File

@ -50,4 +50,5 @@ msh />
| 驱动 | 支持情况 | 备注 |
| ------ | ---- | :------: |
| UART | 支持 | UART0 |
| UART | 支持 | UART0 |
| VIRTIO BLK | 支持 | VIRTIO BLK0 |

View File

@ -17,6 +17,8 @@ env = Environment(tools = ['mingw'],
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
env['ASCOM'] = env['ASPPCOM']
env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS -Wl,--start-group $_LIBFLAGS -Wl,--end-group'
Export('RTT_ROOT')
Export('rtconfig')

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2006-2021, 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>
#ifdef RT_USING_DFS
#include <dfs_fs.h>
int mnt_init(void)
{
if(rt_device_find("virtio-blk0"))
{
/* mount virtio-blk as root directory */
if (dfs_mount("virtio-blk0", "/", "elm", 0, RT_NULL) == 0)
{
rt_kprintf("file system initialization done!\n");
}
}
return 0;
}
INIT_ENV_EXPORT(mnt_init);
#endif

View File

@ -15,11 +15,17 @@ menu "AARCH64 qemu virt64 configs"
default y
endif
menuconfig BSP_USING_VIRTIO_BLK
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
config BSP_USING_GIC390
bool
default y
endmenu

View File

@ -3,12 +3,17 @@
from building import *
cwd = GetCurrentDir()
src = Split('''
board.c
drv_uart.c
''')
src = Glob('*.c')
list = os.listdir(cwd)
CPPPATH = [cwd]
objs = []
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
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')

View File

@ -7,6 +7,7 @@
* Date Author Notes
* 2019-07-29 zdzn first version
* 2021-07-31 GuEe-GUI config the memory/io address map
* 2021-09-11 GuEe-GUI remove do-while in rt_hw_timer_isr
*/
#include <rthw.h>
@ -18,38 +19,34 @@
void rt_hw_vector_init(void);
static uint64_t tickval = 0;
static uint64_t timer_val;
static uint64_t timer_step;
void rt_hw_timer_isr(int vector, void *parameter)
{
uint64_t cntvct_el0;
do
{
tickval += 0xF424;
__asm__ volatile ("msr CNTV_CVAL_EL0, %0"::"r"(tickval));
__asm__ volatile ("mrs %0, CNTVCT_EL0":"=r"(cntvct_el0));
}
while (cntvct_el0 >= tickval);
timer_val += timer_step;
__asm__ volatile ("msr CNTV_CVAL_EL0, %0"::"r"(timer_val));
__asm__ volatile ("isb":::"memory");
rt_tick_increase();
}
int rt_hw_timer_init()
int rt_hw_timer_init(void)
{
uint64_t val;
rt_hw_interrupt_install(27, rt_hw_timer_isr, RT_NULL, "tick");
rt_hw_interrupt_umask(27);
val = 0;
__asm__ volatile ("msr CNTV_CTL_EL0, %0"::"r"(val));
val = 0x03B9ACA0;
__asm__ volatile ("msr CNTFRQ_EL0, %0"::"r"(val));
tickval += 0xF424;
__asm__ volatile ("msr CNTV_CVAL_EL0, %0"::"r"(tickval));
val = 1;
__asm__ volatile ("msr CNTV_CTL_EL0, %0"::"r"(val));
__asm__ volatile ("msr CNTV_CTL_EL0, %0"::"r"(0));
__asm__ volatile ("isb 0xf":::"memory");
__asm__ volatile ("mrs %0, CNTFRQ_EL0" : "=r" (timer_step));
timer_step /= RT_TICK_PER_SECOND;
timer_val = timer_step;
__asm__ volatile ("dsb 0xf":::"memory");
__asm__ volatile ("msr CNTV_CVAL_EL0, %0"::"r"(timer_val));
__asm__ volatile ("msr CNTV_CTL_EL0, %0"::"r"(1));
return 0;
}
@ -73,6 +70,8 @@ void rt_hw_board_init(void)
cont >>= 21;
/* memory location */
armv8_map_2M(0x40000000, 0x40000000, cont, MEM_ATTR_MEMORY);
/* virtio blk0 */
armv8_map_2M(VIRTIO_MMIO_BLK0_BASE, VIRTIO_MMIO_BLK0_BASE, 0x1, MEM_ATTR_IO);
/* uart location*/
armv8_map_2M(PL011_UART0_BASE, PL011_UART0_BASE, 0x1, MEM_ATTR_IO);
/* gic location*/

View File

@ -7,12 +7,15 @@
* 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>
extern unsigned char __bss_start;
extern unsigned char __bss_end;
@ -20,17 +23,36 @@ 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)
/* 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
#define IRQ_ARM_VTIMER 27
/* the basic constants and interfaces needed by gic */
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
{

View File

@ -116,7 +116,7 @@ static void rt_hw_uart_isr(int irqno, void *param)
static struct hw_uart_device _uart0_device =
{
PL011_UART0_BASE,
33,
PL011_UART0_IRQNUM,
};
static struct rt_serial_device _serial0;
#endif

View File

@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,405 @@
/*
* 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 */

View File

@ -0,0 +1,85 @@
/*
* 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__ */

View File

@ -0,0 +1,60 @@
/*
* 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 VIRTIO_H__
#define VIRTIO_H__
#include <stdint.h>
#define PAGE_SIZE 4096
#define PAGE_SHIFT 12
#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
#define QUEUE_SIZE 8
struct virtq_desc
{
uint64_t addr;
uint32_t len;
uint16_t flags;
uint16_t next;
};
#define VRING_DESC_F_NEXT 1 // chained with another descriptor
#define VRING_DESC_F_WRITE 2 // device writes (vs read)
struct virtq_avail
{
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;
};
struct virtq_used_elem
{
uint32_t id; // index of start of completed descriptor chain
uint32_t len;
};
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];
};
#endif /* VIRTIO_H__ */

View File

@ -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
*/
#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));
}

View File

@ -0,0 +1,75 @@
/*
* 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 VIRTIO_MMIO_H
#define VIRTIO_MMIO_H
#include <stdint.h>
#include <stddef.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)
{
return *((volatile uint32_t*) (((uintptr_t) base) + offset));
}
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 */

View File

@ -24,7 +24,7 @@
SECTIONS
{
. = 0x40000000;
. = 0x40008000;
. = ALIGN(4096);
.text :
{

View File

@ -1 +1,6 @@
qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 1 -kernel rtthread.elf -nographic
@echo off
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 -drive if=none,file=sd.bin,format=raw,id=blk0 -device virtio-blk-device,drive=blk0,bus=virtio-mmio-bus.0 -nographic

View File

@ -1 +1,4 @@
qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 1 -kernel rtthread.elf -nographic -monitor pty
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 -monitor pty

View File

@ -10,7 +10,7 @@
#define RT_ALIGN_SIZE 4
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
#define RT_TICK_PER_SECOND 1000
#define RT_TICK_PER_SECOND 100
#define RT_USING_OVERFLOW_CHECK
#define RT_USING_HOOK
#define RT_USING_IDLE_HOOK
@ -64,17 +64,17 @@
/* Command shell */
#define RT_USING_FINSH
#define RT_USING_MSH
#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_USING_DESCRIPTION
#define FINSH_THREAD_PRIORITY 20
#define FINSH_THREAD_STACK_SIZE 4096
#define FINSH_CMD_SIZE 80
#define FINSH_USING_MSH
#define FINSH_USING_MSH_DEFAULT
#define FINSH_USING_MSH_ONLY
#define MSH_USING_BUILT_IN_COMMANDS
#define FINSH_USING_DESCRIPTION
#define FINSH_ARG_MAX 10
/* Device virtual file system */
@ -84,6 +84,20 @@
#define DFS_FILESYSTEMS_MAX 2
#define DFS_FILESYSTEM_TYPES_MAX 2
#define DFS_FD_MAX 16
#define RT_USING_DFS_ELMFAT
/* elm-chan's FatFs, Generic FAT Filesystem Module */
#define RT_DFS_ELM_CODE_PAGE 437
#define RT_DFS_ELM_WORD_ACCESS
#define RT_DFS_ELM_USE_LFN_3
#define RT_DFS_ELM_USE_LFN 3
#define RT_DFS_ELM_LFN_UNICODE_0
#define RT_DFS_ELM_LFN_UNICODE 0
#define RT_DFS_ELM_MAX_LFN 255
#define RT_DFS_ELM_DRIVES 2
#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
#define RT_DFS_ELM_REENTRANT
#define RT_USING_DFS_DEVFS
/* Device Drivers */
@ -103,7 +117,7 @@
#define RT_USING_LIBC
#define RT_USING_POSIX
#define RT_LIBC_FIXED_TIMEZONE 8
#define RT_LIBC_DEFAULT_TIMEZONE 8
/* Network */
@ -172,7 +186,6 @@
/* miscellaneous packages */
/* samples: kernel and components samples */
@ -185,7 +198,8 @@
#define BSP_SUPPORT_FPU
#define BSP_USING_UART
#define RT_USING_UART0
#define BSP_USING_VIRTIO_BLK
#define RT_USING_VIRTIO_BLK0
#define BSP_USING_GIC
#define BSP_USING_GIC390
#endif

View File

@ -2,7 +2,7 @@ import os
# toolchains options
ARCH ='aarch64'
CPU ='cortex-a53'
CPU ='cortex-a'
CROSS_TOOL ='gcc'
if os.getenv('RTT_ROOT'):

View File

@ -23,6 +23,13 @@ CONFIG_IDLE_THREAD_STACK_SIZE=2048
CONFIG_RT_USING_TIMER_SOFT=y
CONFIG_RT_TIMER_THREAD_PRIO=4
CONFIG_RT_TIMER_THREAD_STACK_SIZE=2048
#
# kservice optimization
#
# CONFIG_RT_KSERVICE_USING_STDLIB is not set
# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
# CONFIG_RT_USING_ASM_MEMCPY is not set
CONFIG_RT_DEBUG=y
CONFIG_RT_DEBUG_COLOR=y
# CONFIG_RT_DEBUG_INIT_CONFIG is not set
@ -55,6 +62,7 @@ CONFIG_RT_USING_MEMHEAP=y
CONFIG_RT_USING_SMALL_MEM=y
# CONFIG_RT_USING_SLAB is not set
# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set
# CONFIG_RT_USING_USERHEAP is not set
CONFIG_RT_USING_MEMTRACE=y
CONFIG_RT_USING_HEAP=y
@ -67,7 +75,8 @@ CONFIG_RT_USING_DEVICE_OPS=y
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=512
CONFIG_RT_CONSOLE_DEVICE_NAME="uart1"
CONFIG_RT_VER_NUM=0x40003
# CONFIG_RT_PRINTF_LONGLONG is not set
CONFIG_RT_VER_NUM=0x40004
CONFIG_ARCH_CPU_64BIT=y
# CONFIG_RT_USING_CPU_FFS is not set
CONFIG_ARCH_ARMV8=y
@ -90,19 +99,19 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10
# Command shell
#
CONFIG_RT_USING_FINSH=y
CONFIG_RT_USING_MSH=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_THREAD_PRIORITY=20
CONFIG_FINSH_THREAD_STACK_SIZE=4096
CONFIG_FINSH_CMD_SIZE=80
# CONFIG_FINSH_USING_AUTH is not set
CONFIG_FINSH_USING_MSH=y
CONFIG_FINSH_USING_MSH_DEFAULT=y
CONFIG_FINSH_USING_MSH_ONLY=y
CONFIG_FINSH_ARG_MAX=10
#
@ -126,6 +135,11 @@ CONFIG_RT_DFS_ELM_WORD_ACCESS=y
# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
CONFIG_RT_DFS_ELM_USE_LFN_3=y
CONFIG_RT_DFS_ELM_USE_LFN=3
CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y
# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set
# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set
# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set
CONFIG_RT_DFS_ELM_LFN_UNICODE=0
CONFIG_RT_DFS_ELM_MAX_LFN=255
CONFIG_RT_DFS_ELM_DRIVES=2
CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
@ -134,8 +148,6 @@ CONFIG_RT_DFS_ELM_REENTRANT=y
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_UFFS is not set
# CONFIG_RT_USING_DFS_JFFS2 is not set
#
# Device Drivers
@ -144,6 +156,8 @@ CONFIG_RT_USING_DEVICE_IPC=y
CONFIG_RT_PIPE_BUFSZ=512
# 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
@ -153,8 +167,10 @@ CONFIG_RT_USING_I2C=y
CONFIG_RT_I2C_DEBUG=y
CONFIG_RT_USING_I2C_BITOPS=y
# CONFIG_RT_I2C_BITOPS_DEBUG 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
@ -196,8 +212,10 @@ CONFIG_RT_USING_LIBC=y
CONFIG_RT_USING_POSIX=y
# CONFIG_RT_USING_POSIX_MMAP is not set
# CONFIG_RT_USING_POSIX_TERMIOS is not set
# CONFIG_RT_USING_POSIX_GETLINE is not set
# CONFIG_RT_USING_POSIX_AIO is not set
# CONFIG_RT_USING_MODULE is not set
CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
#
# Network
@ -234,6 +252,12 @@ CONFIG_RT_USING_POSIX=y
# CONFIG_RT_USING_RYM is not set
# CONFIG_RT_USING_ULOG is not set
# CONFIG_RT_USING_UTEST is not set
# CONFIG_RT_USING_RT_LINK is not set
#
# RT-Thread Utestcases
#
# CONFIG_RT_USING_UTESTCASES is not set
#
# RT-Thread online packages
@ -242,7 +266,9 @@ CONFIG_RT_USING_POSIX=y
#
# IoT - internet of things
#
# 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
@ -280,6 +306,7 @@ CONFIG_RT_USING_POSIX=y
# 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
@ -288,7 +315,7 @@ CONFIG_RT_USING_POSIX=y
# 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_IOTHUB 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
@ -300,8 +327,6 @@ CONFIG_RT_USING_POSIX=y
# 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_ONNX_PARSER is not set
# CONFIG_PKG_USING_ONNX_BACKEND 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
@ -310,6 +335,20 @@ CONFIG_RT_USING_POSIX=y
# 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_HM is not set
#
# security packages
@ -318,6 +357,7 @@ CONFIG_RT_USING_POSIX=y
# 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
@ -325,6 +365,7 @@ CONFIG_RT_USING_POSIX=y
# 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
@ -334,6 +375,13 @@ CONFIG_RT_USING_POSIX=y
# 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
#
# tools packages
@ -342,25 +390,65 @@ CONFIG_RT_USING_POSIX=y
# 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_QRCODE 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
#
# system packages
#
#
# acceleration: Assembly language or algorithmic acceleration packages
#
# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
# 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
#
# 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_PKG_USING_GUIENGINE is not set
# CONFIG_PKG_USING_CAIRO is not set
# CONFIG_PKG_USING_PIXMAN is not set
# CONFIG_PKG_USING_LWEXT4 is not set
# CONFIG_PKG_USING_PARTITION is not set
# CONFIG_PKG_USING_FAL is not set
# CONFIG_PKG_USING_FLASHDB is not set
@ -370,12 +458,27 @@ CONFIG_RT_USING_POSIX=y
# CONFIG_PKG_USING_CMSIS 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_RT_KPRINTF_THREADSAFE 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_WCWIDTH is not set
# CONFIG_PKG_USING_MCUBOOT is not set
#
# peripheral libraries and drivers
@ -384,6 +487,7 @@ CONFIG_RT_USING_POSIX=y
# 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_U8G2 is not set
@ -399,7 +503,6 @@ CONFIG_RT_USING_POSIX=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_ROSSERIAL 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
@ -413,6 +516,7 @@ CONFIG_RT_USING_POSIX=y
# 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
@ -421,25 +525,50 @@ CONFIG_RT_USING_POSIX=y
# 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_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
#
# 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
#
# 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_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_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
#
# samples: kernel and components samples
@ -448,17 +577,50 @@ CONFIG_RT_USING_POSIX=y
# 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_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_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_NNOM is not set
# CONFIG_PKG_USING_LIBANN is not set
# CONFIG_PKG_USING_ELAPACK is not set
# CONFIG_PKG_USING_KI is not set
# CONFIG_PKG_USING_ARMv7M_DWT is not set
# CONFIG_PKG_USING_VT100 is not set
# CONFIG_PKG_USING_ULAPACK 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_MCURSES is not set
# CONFIG_PKG_USING_COWSAY is not set
# CONFIG_PKG_USING_TERMBOX is not set
CONFIG_BCM2836_SOC=y
# CONFIG_BSP_SUPPORT_FPU is not set
CONFIG_BSP_SUPPORT_FPU=y
#
# Hardware Drivers Config

View File

@ -13,6 +13,7 @@
#define __MBOX_H__
#include <rtthread.h>
#include <stdint.h>
/* a properly aligned buffer */
extern volatile unsigned int* mbox;

View File

@ -118,6 +118,7 @@ typedef enum
#define BSC2_BASE_OFFSET (0x805000)
/* IRQ */
#define MAX_HANDLERS 72
#define IRQ_SYSTEM_TIMER_0 0
#define IRQ_SYSTEM_TIMER_1 1
#define IRQ_SYSTEM_TIMER_2 2

View File

@ -1,4 +1,6 @@
if [ ! -f "sd.bin" ]; then
dd if=/dev/zero of=sd.bin bs=1024 count=65536
fi
qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio -sd sd.bin -nographic -monitor pty
@echo off
if exist sd.bin goto run
qemu-img create -f raw sd.bin 64M
:run
qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio -sd sd.bin

View File

@ -0,0 +1,4 @@
if [ ! -f "sd.bin" ]; then
dd if=/dev/zero of=sd.bin bs=1024 count=65536
fi
qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio -sd sd.bin -nographic -monitor pty

View File

@ -19,6 +19,9 @@
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
#define RT_TIMER_THREAD_STACK_SIZE 2048
/* kservice optimization */
#define RT_DEBUG
#define RT_DEBUG_COLOR
@ -45,7 +48,7 @@
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 512
#define RT_CONSOLE_DEVICE_NAME "uart1"
#define RT_VER_NUM 0x40003
#define RT_VER_NUM 0x40004
#define ARCH_CPU_64BIT
#define ARCH_ARMV8
@ -62,17 +65,17 @@
/* Command shell */
#define RT_USING_FINSH
#define RT_USING_MSH
#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_USING_DESCRIPTION
#define FINSH_THREAD_PRIORITY 20
#define FINSH_THREAD_STACK_SIZE 4096
#define FINSH_CMD_SIZE 80
#define FINSH_USING_MSH
#define FINSH_USING_MSH_DEFAULT
#define FINSH_USING_MSH_ONLY
#define MSH_USING_BUILT_IN_COMMANDS
#define FINSH_USING_DESCRIPTION
#define FINSH_ARG_MAX 10
/* Device virtual file system */
@ -90,6 +93,8 @@
#define RT_DFS_ELM_WORD_ACCESS
#define RT_DFS_ELM_USE_LFN_3
#define RT_DFS_ELM_USE_LFN 3
#define RT_DFS_ELM_LFN_UNICODE_0
#define RT_DFS_ELM_LFN_UNICODE 0
#define RT_DFS_ELM_MAX_LFN 255
#define RT_DFS_ELM_DRIVES 2
#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
@ -101,6 +106,7 @@
#define RT_USING_DEVICE_IPC
#define RT_PIPE_BUFSZ 512
#define RT_USING_SERIAL
#define RT_USING_SERIAL_V1
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_HWTIMER
#define RT_USING_I2C
@ -124,6 +130,7 @@
#define RT_USING_LIBC
#define RT_USING_POSIX
#define RT_LIBC_DEFAULT_TIMEZONE 8
/* Network */
@ -145,6 +152,9 @@
/* Utilities */
/* RT-Thread Utestcases */
/* RT-Thread online packages */
/* IoT - internet of things */
@ -175,16 +185,27 @@
/* system packages */
/* acceleration: Assembly language or algorithmic acceleration packages */
/* Micrium: Micrium software products porting for RT-Thread */
/* peripheral libraries and drivers */
/* miscellaneous packages */
/* AI packages */
/* miscellaneous packages */
/* samples: kernel and components samples */
/* entertainment: terminal games and other interesting software packages */
#define BCM2836_SOC
#define BSP_SUPPORT_FPU
/* Hardware Drivers Config */

View File

@ -2,7 +2,7 @@ import os
# toolchains options
ARCH ='aarch64'
CPU ='cortex-a53'
CPU ='cortex-a'
CROSS_TOOL ='gcc'
if os.getenv('RTT_ROOT'):

View File

@ -23,6 +23,13 @@ CONFIG_IDLE_THREAD_STACK_SIZE=2048
CONFIG_RT_USING_TIMER_SOFT=y
CONFIG_RT_TIMER_THREAD_PRIO=4
CONFIG_RT_TIMER_THREAD_STACK_SIZE=2048
#
# kservice optimization
#
# CONFIG_RT_KSERVICE_USING_STDLIB is not set
# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set
# CONFIG_RT_USING_ASM_MEMCPY is not set
CONFIG_RT_DEBUG=y
# CONFIG_RT_DEBUG_COLOR is not set
# CONFIG_RT_DEBUG_INIT_CONFIG is not set
@ -54,6 +61,7 @@ CONFIG_RT_USING_MEMPOOL=y
# CONFIG_RT_USING_NOHEAP is not set
CONFIG_RT_USING_SMALL_MEM=y
# CONFIG_RT_USING_SLAB is not set
# CONFIG_RT_USING_USERHEAP is not set
# CONFIG_RT_USING_MEMTRACE is not set
CONFIG_RT_USING_HEAP=y
@ -65,8 +73,9 @@ CONFIG_RT_USING_DEVICE=y
# CONFIG_RT_USING_INTERRUPT_INFO is not set
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=128
CONFIG_RT_CONSOLE_DEVICE_NAME="uart"
CONFIG_RT_VER_NUM=0x40003
CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
# CONFIG_RT_PRINTF_LONGLONG is not set
CONFIG_RT_VER_NUM=0x40004
CONFIG_ARCH_CPU_64BIT=y
# CONFIG_RT_USING_CPU_FFS is not set
CONFIG_ARCH_ARMV8=y
@ -89,19 +98,19 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10
# Command shell
#
CONFIG_RT_USING_FINSH=y
CONFIG_RT_USING_MSH=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_THREAD_PRIORITY=20
CONFIG_FINSH_THREAD_STACK_SIZE=4096
CONFIG_FINSH_CMD_SIZE=80
# CONFIG_FINSH_USING_AUTH is not set
CONFIG_FINSH_USING_MSH=y
CONFIG_FINSH_USING_MSH_DEFAULT=y
# CONFIG_FINSH_USING_MSH_ONLY is not set
CONFIG_FINSH_ARG_MAX=10
#
@ -113,34 +122,68 @@ CONFIG_DFS_FILESYSTEMS_MAX=2
CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
CONFIG_DFS_FD_MAX=16
# CONFIG_RT_USING_DFS_MNTTABLE is not set
# CONFIG_RT_USING_DFS_ELMFAT is not set
CONFIG_RT_USING_DFS_ELMFAT=y
#
# elm-chan's FatFs, Generic FAT Filesystem Module
#
CONFIG_RT_DFS_ELM_CODE_PAGE=437
CONFIG_RT_DFS_ELM_WORD_ACCESS=y
# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set
# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set
# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
CONFIG_RT_DFS_ELM_USE_LFN_3=y
CONFIG_RT_DFS_ELM_USE_LFN=3
CONFIG_RT_DFS_ELM_LFN_UNICODE_0=y
# CONFIG_RT_DFS_ELM_LFN_UNICODE_1 is not set
# CONFIG_RT_DFS_ELM_LFN_UNICODE_2 is not set
# CONFIG_RT_DFS_ELM_LFN_UNICODE_3 is not set
CONFIG_RT_DFS_ELM_LFN_UNICODE=0
CONFIG_RT_DFS_ELM_MAX_LFN=255
CONFIG_RT_DFS_ELM_DRIVES=2
CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
# CONFIG_RT_DFS_ELM_USE_ERASE is not set
CONFIG_RT_DFS_ELM_REENTRANT=y
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_UFFS is not set
# CONFIG_RT_USING_DFS_JFFS2 is not set
# CONFIG_RT_USING_DFS_NFS is not set
#
# Device Drivers
#
CONFIG_RT_USING_DEVICE_IPC=y
CONFIG_RT_PIPE_BUFSZ=512
# 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
CONFIG_RT_SERIAL_USING_DMA=y
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_RTC=y
CONFIG_RT_USING_ALARM=y
# CONFIG_RT_USING_SOFT_RTC is not set
CONFIG_RT_USING_SDIO=y
CONFIG_RT_SDIO_STACK_SIZE=512
CONFIG_RT_SDIO_THREAD_PRIORITY=15
CONFIG_RT_MMCSD_STACK_SIZE=2048
CONFIG_RT_MMCSD_THREAD_PREORITY=22
CONFIG_RT_MMCSD_MAX_PARTITION=16
# CONFIG_RT_SDIO_DEBUG is not set
# CONFIG_RT_USING_SPI is not set
# CONFIG_RT_USING_WDT is not set
# CONFIG_RT_USING_AUDIO is not set
@ -165,8 +208,10 @@ CONFIG_RT_USING_LIBC=y
CONFIG_RT_USING_POSIX=y
# CONFIG_RT_USING_POSIX_MMAP is not set
# CONFIG_RT_USING_POSIX_TERMIOS is not set
# CONFIG_RT_USING_POSIX_GETLINE is not set
# CONFIG_RT_USING_POSIX_AIO is not set
# CONFIG_RT_USING_MODULE is not set
CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8
#
# Network
@ -175,22 +220,93 @@ CONFIG_RT_USING_POSIX=y
#
# Socket abstraction layer
#
# CONFIG_RT_USING_SAL is not set
CONFIG_RT_USING_SAL=y
CONFIG_SAL_INTERNET_CHECK=y
#
# protocol stack implement
#
CONFIG_SAL_USING_LWIP=y
# CONFIG_SAL_USING_POSIX is not set
CONFIG_SAL_SOCKETS_NUM=16
#
# Network interface device
#
# CONFIG_RT_USING_NETDEV is not set
CONFIG_RT_USING_NETDEV=y
CONFIG_NETDEV_USING_IFCONFIG=y
CONFIG_NETDEV_USING_PING=y
CONFIG_NETDEV_USING_NETSTAT=y
CONFIG_NETDEV_USING_AUTO_DEFAULT=y
# CONFIG_NETDEV_USING_IPV6 is not set
CONFIG_NETDEV_IPV4=1
CONFIG_NETDEV_IPV6=0
# CONFIG_NETDEV_IPV6_SCOPES is not set
#
# light weight TCP/IP stack
#
# CONFIG_RT_USING_LWIP is not set
CONFIG_RT_USING_LWIP=y
# CONFIG_RT_USING_LWIP141 is not set
# CONFIG_RT_USING_LWIP202 is not set
CONFIG_RT_USING_LWIP203=y
# CONFIG_RT_USING_LWIP212 is not set
# CONFIG_RT_USING_LWIP_IPV6 is not set
CONFIG_RT_LWIP_MEM_ALIGNMENT=4
CONFIG_RT_LWIP_IGMP=y
CONFIG_RT_LWIP_ICMP=y
# CONFIG_RT_LWIP_SNMP is not set
CONFIG_RT_LWIP_DNS=y
CONFIG_RT_LWIP_DHCP=y
CONFIG_IP_SOF_BROADCAST=1
CONFIG_IP_SOF_BROADCAST_RECV=1
#
# Static IPv4 Address
#
CONFIG_RT_LWIP_IPADDR="192.168.1.30"
CONFIG_RT_LWIP_GWADDR="192.168.1.1"
CONFIG_RT_LWIP_MSKADDR="255.255.255.0"
CONFIG_RT_LWIP_UDP=y
CONFIG_RT_LWIP_TCP=y
CONFIG_RT_LWIP_RAW=y
# CONFIG_RT_LWIP_PPP is not set
CONFIG_RT_MEMP_NUM_NETCONN=8
CONFIG_RT_LWIP_PBUF_NUM=16
CONFIG_RT_LWIP_RAW_PCB_NUM=4
CONFIG_RT_LWIP_UDP_PCB_NUM=4
CONFIG_RT_LWIP_TCP_PCB_NUM=4
CONFIG_RT_LWIP_TCP_SEG_NUM=40
CONFIG_RT_LWIP_TCP_SND_BUF=8196
CONFIG_RT_LWIP_TCP_WND=8196
CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10
CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8
CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=2048
# CONFIG_LWIP_NO_RX_THREAD is not set
# CONFIG_LWIP_NO_TX_THREAD is not set
CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12
CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=2048
CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8
# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set
CONFIG_LWIP_NETIF_STATUS_CALLBACK=1
CONFIG_LWIP_NETIF_LINK_CALLBACK=1
CONFIG_SO_REUSE=1
CONFIG_LWIP_SO_RCVTIMEO=1
CONFIG_LWIP_SO_SNDTIMEO=1
CONFIG_LWIP_SO_RCVBUF=1
CONFIG_LWIP_SO_LINGER=0
# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set
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)
@ -200,9 +316,17 @@ CONFIG_RT_USING_POSIX=y
#
# Utilities
#
# CONFIG_RT_USING_RYM is not set
CONFIG_RT_USING_RYM=y
# CONFIG_YMODEM_USING_CRC_TABLE is not set
CONFIG_YMODEM_USING_FILE_TRANSFER=y
# CONFIG_RT_USING_ULOG is not set
# CONFIG_RT_USING_UTEST is not set
# CONFIG_RT_USING_RT_LINK is not set
#
# RT-Thread Utestcases
#
# CONFIG_RT_USING_UTESTCASES is not set
#
# RT-Thread online packages
@ -211,7 +335,9 @@ CONFIG_RT_USING_POSIX=y
#
# IoT - internet of things
#
# 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
@ -249,6 +375,7 @@ CONFIG_RT_USING_POSIX=y
# 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
@ -257,7 +384,7 @@ CONFIG_RT_USING_POSIX=y
# 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_IOTHUB 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
@ -269,8 +396,6 @@ CONFIG_RT_USING_POSIX=y
# 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_ONNX_PARSER is not set
# CONFIG_PKG_USING_ONNX_BACKEND 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
@ -279,6 +404,20 @@ CONFIG_RT_USING_POSIX=y
# 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_HM is not set
#
# security packages
@ -287,6 +426,7 @@ CONFIG_RT_USING_POSIX=y
# 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
@ -294,6 +434,7 @@ CONFIG_RT_USING_POSIX=y
# 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
@ -303,6 +444,13 @@ CONFIG_RT_USING_POSIX=y
# 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
#
# tools packages
@ -311,25 +459,65 @@ CONFIG_RT_USING_POSIX=y
# 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_QRCODE 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
#
# system packages
#
#
# acceleration: Assembly language or algorithmic acceleration packages
#
# CONFIG_PKG_USING_RT_MEMCPY_CM is not set
# 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
#
# 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_PKG_USING_GUIENGINE is not set
# CONFIG_PKG_USING_CAIRO is not set
# CONFIG_PKG_USING_PIXMAN is not set
# CONFIG_PKG_USING_LWEXT4 is not set
# CONFIG_PKG_USING_PARTITION is not set
# CONFIG_PKG_USING_FAL is not set
# CONFIG_PKG_USING_FLASHDB is not set
@ -339,12 +527,27 @@ CONFIG_RT_USING_POSIX=y
# CONFIG_PKG_USING_CMSIS 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_RT_KPRINTF_THREADSAFE 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_WCWIDTH is not set
# CONFIG_PKG_USING_MCUBOOT is not set
#
# peripheral libraries and drivers
@ -353,6 +556,7 @@ CONFIG_RT_USING_POSIX=y
# 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_U8G2 is not set
@ -368,7 +572,6 @@ CONFIG_RT_USING_POSIX=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_ROSSERIAL 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
@ -382,6 +585,7 @@ CONFIG_RT_USING_POSIX=y
# 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
@ -390,25 +594,50 @@ CONFIG_RT_USING_POSIX=y
# 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_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
#
# 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
#
# 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_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_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
#
# samples: kernel and components samples
@ -417,17 +646,50 @@ CONFIG_RT_USING_POSIX=y
# 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_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_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_NNOM is not set
# CONFIG_PKG_USING_LIBANN is not set
# CONFIG_PKG_USING_ELAPACK is not set
# CONFIG_PKG_USING_KI is not set
# CONFIG_PKG_USING_ARMv7M_DWT is not set
# CONFIG_PKG_USING_VT100 is not set
# CONFIG_PKG_USING_ULAPACK 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_MCURSES is not set
# CONFIG_PKG_USING_COWSAY is not set
# CONFIG_PKG_USING_TERMBOX is not set
CONFIG_BCM2711_SOC=y
# CONFIG_BSP_SUPPORT_FPU is not set
CONFIG_BSP_SUPPORT_FPU=y
#
# Hardware Drivers Config
@ -438,15 +700,22 @@ CONFIG_BCM2711_SOC=y
#
CONFIG_BSP_USING_UART=y
CONFIG_RT_USING_UART0=y
# CONFIG_RT_USING_UART1 is not set
# CONFIG_RT_USING_UART3 is not set
# CONFIG_RT_USING_UART4 is not set
# CONFIG_RT_USING_UART5 is not set
CONFIG_BSP_USING_GIC=y
CONFIG_BSP_USING_GIC400=y
# CONFIG_BSP_USING_GIC500 is not set
CONFIG_BSP_USING_PIN=y
CONFIG_BSP_USING_CORETIMER=y
# CONFIG_BSP_USING_SYSTIMER is not set
CONFIG_BSP_USING_ETH=y
# CONFIG_BSP_USING_WDT is not set
# CONFIG_BSP_USING_RTC is not set
# CONFIG_BSP_USING_SDIO is not set
CONFIG_BSP_USING_RTC=y
CONFIG_BSP_USING_ALARM=y
CONFIG_BSP_USING_SDIO=y
CONFIG_BSP_USING_SDIO0=y
#
# Board Peripheral Drivers

View File

@ -101,7 +101,11 @@ msh />
| 驱动 | 支持情况 | 备注 |
| ------ | ---- | :------: |
| UART | 支持 | UART0|
| UART | 支持 | UART0,UART2,UART3,UART4,UART5 |
| GPIO | 支持 | - |
| MAILBOX | 支持 | - |
| SDIO | 支持 | - |
| ETH | 支持 | - |
## 5. 联系人信息

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2006-2021, 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>
#ifdef BSP_USING_SDIO0
#include <dfs_fs.h>
int mnt_init(void)
{
rt_thread_delay(RT_TICK_PER_SECOND);
if (dfs_mount("sd0", "/", "elm", 0, 0) == 0)
{
rt_kprintf("file system initialization done!\n");
}
return 0;
}
INIT_ENV_EXPORT(mnt_init);
#endif

View File

@ -14,8 +14,24 @@ menu "Hardware Drivers Config"
config RT_USING_UART0
bool "Enabel UART 0"
default y
config RT_USING_UART1
bool "Enabel UART 1"
default n
config RT_USING_UART3
bool "Enabel UART 3"
default n
config RT_USING_UART4
bool "Enabel UART 4"
default n
config RT_USING_UART5
bool "Enabel UART 5"
default n
endif
menuconfig BSP_USING_GIC
bool "Enable GIC"
select RT_USING_GIC
@ -53,6 +69,10 @@ menu "Hardware Drivers Config"
default n
endif
config BSP_USING_ETH
bool "Enable ETH"
default n
config BSP_USING_WDT
bool "Enable WDT"
select RT_USING_WDT

View File

@ -16,7 +16,9 @@
#include "cp15.h"
#include "mmu.h"
#include "mbox.h"
#ifdef BSP_USING_CORETIMER
static rt_uint64_t timerStep;
int rt_hw_get_gtimer_frq(void);
@ -29,15 +31,21 @@ void core0_timer_enable_interrupt_controller(void)
{
CORE0_TIMER_IRQ_CTRL |= NON_SECURE_TIMER_IRQ;
}
#endif
void rt_hw_timer_isr(int vector, void *parameter)
{
#ifdef BSP_USING_CORETIMER
rt_hw_set_gtimer_val(timerStep);
#else
ARM_TIMER_IRQCLR = 0;
#endif
rt_tick_increase();
}
void rt_hw_timer_init(void)
{
#ifdef BSP_USING_CORETIMER
rt_hw_interrupt_install(TIMER_IRQ, rt_hw_timer_isr, RT_NULL, "tick");
rt_hw_interrupt_umask(TIMER_IRQ);
__ISB();
@ -48,6 +56,27 @@ void rt_hw_timer_init(void)
rt_hw_gtimer_enable();
rt_hw_set_gtimer_val(timerStep);
core0_timer_enable_interrupt_controller();
#else
rt_uint32_t apb_clock = 0;
rt_uint32_t timer_clock = 1000000;
apb_clock = bcm271x_mbox_clock_get_rate(CORE_CLK_ID);
ARM_TIMER_PREDIV = (apb_clock/timer_clock - 1);
ARM_TIMER_RELOAD = 0;
ARM_TIMER_LOAD = 0;
ARM_TIMER_IRQCLR = 0;
ARM_TIMER_CTRL = 0;
ARM_TIMER_RELOAD = 1000000 / RT_TICK_PER_SECOND;
ARM_TIMER_LOAD = 1000000 / RT_TICK_PER_SECOND;
/* 23-bit counter, enable interrupt, enable timer */
ARM_TIMER_CTRL = (1 << 1) | (1 << 5) | (1 << 7);
rt_hw_interrupt_install(ARM_TIMER_IRQ, rt_hw_timer_isr, RT_NULL, "tick");
rt_hw_interrupt_umask(ARM_TIMER_IRQ);
#endif
}
void idle_wfi(void)
@ -65,6 +94,13 @@ void rt_hw_board_init(void)
armv8_map(0, 0, 0x6400000, MEM_ATTR_MEMORY);
armv8_map(0xFE200000, 0xFE200000, 0x200000, MEM_ATTR_IO);//uart gpio
armv8_map(0xFF800000, 0xFF800000, 0x200000, MEM_ATTR_IO);//gic timer
armv8_map(ARM_TIMER_BASE, ARM_TIMER_BASE, 0x200000, MEM_ATTR_IO);//arm timer
armv8_map(STIMER_BASE, STIMER_BASE, 0x200000, MEM_ATTR_IO);//stimer
armv8_map(MMC2_BASE_ADDR, MMC2_BASE_ADDR, 0x200000, MEM_ATTR_IO);//mmc
armv8_map(MBOX_ADDR, MBOX_ADDR, 0x200000, MEM_ATTR_IO);//mbox msg
armv8_map((unsigned long)MAC_REG_BASE_ADDR, (unsigned long)MAC_REG_BASE_ADDR, 0x80000, MEM_ATTR_IO);//mac
armv8_map(SEND_DATA_NO_CACHE, SEND_DATA_NO_CACHE, 0x200000, MEM_ATTR_MEMORY);//eth send
armv8_map(RECV_DATA_NO_CACHE, RECV_DATA_NO_CACHE, 0x200000, MEM_ATTR_MEMORY);//eth recv
mmu_enable();
/* initialize hardware interrupt */

View File

@ -0,0 +1,723 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-10-30 bigmagic first version
*/
#include <rtdef.h>
#include <rthw.h>
#include <stdint.h>
#include <rtthread.h>
#include <lwip/sys.h>
#include <netif/ethernetif.h>
#include <mmu.h>
#include "mbox.h"
#include "raspi4.h"
#include "drv_eth.h"
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>
#define LOG_TAG "drv.eth"
#define RECV_CACHE_BUF (2048)
#define SEND_CACHE_BUF (2048)
#define DMA_DISC_ADDR_SIZE (2 * 1024 *1024)
#define RX_DESC_BASE (MAC_REG_BASE_ADDR + GENET_RX_OFF)
#define TX_DESC_BASE (MAC_REG_BASE_ADDR + GENET_TX_OFF)
#define MAX_ADDR_LEN (6)
#define upper_32_bits(n) ((rt_uint32_t)(((n) >> 16) >> 16))
#define lower_32_bits(n) ((rt_uint32_t)(n))
#define BIT(nr) (1UL << (nr))
#define LINK_THREAD_STACK_SIZE (1024)
#define LINK_THREAD_PRIORITY (20)
#define LINK_THREAD_TIMESLICE (10)
static int link_speed = 0;
static int link_flag = 0;
static rt_thread_t link_thread_tid = RT_NULL;
static rt_uint32_t tx_index = 0;
static rt_uint32_t rx_index = 0;
static rt_uint32_t index_flag = 0;
struct rt_eth_dev
{
struct eth_device parent;
rt_uint8_t dev_addr[MAX_ADDR_LEN];
char *name;
void *iobase;
int state;
int index;
struct rt_timer link_timer;
void *priv;
};
static struct rt_eth_dev eth_dev;
static struct rt_semaphore send_finsh_sem_lock;
static struct rt_semaphore link_ack;
rt_inline rt_uint32_t read32(void *addr)
{
return (*((volatile unsigned int *)(addr)));
}
rt_inline void write32(void *addr, rt_uint32_t value)
{
(*((volatile unsigned int *)(addr))) = value;
}
static void eth_rx_irq(int irq, void *param)
{
rt_uint32_t val = 0;
val = read32(MAC_REG_BASE_ADDR + GENET_INTRL2_CPU_STAT);
val &= ~read32(MAC_REG_BASE_ADDR + GENET_INTRL2_CPU_STAT_MASK);
write32(MAC_REG_BASE_ADDR + GENET_INTRL2_CPU_CLEAR, val);
if (val & GENET_IRQ_RXDMA_DONE)
{
eth_device_ready(&eth_dev.parent);
}
if (val & GENET_IRQ_TXDMA_DONE)
{
rt_sem_release(&send_finsh_sem_lock);
}
}
/* we only support RGMII (as used on the RPi4) */
static int bcmgenet_interface_set(void)
{
int phy_mode = PHY_INTERFACE_MODE_RGMII;
switch (phy_mode)
{
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_RXID:
write32(MAC_REG_BASE_ADDR + SYS_PORT_CTRL, PORT_MODE_EXT_GPHY);
break;
default:
rt_kprintf("unknown phy mode: %d\n", MAC_REG_BASE_ADDR);
return -1;
}
return 0;
}
static void bcmgenet_umac_reset(void)
{
rt_uint32_t reg;
reg = read32(MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL);
reg |= BIT(1);
write32((MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL), reg);
reg &= ~BIT(1);
write32((MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL), reg);
DELAY_MICROS(10);
write32((MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL), 0);
DELAY_MICROS(10);
write32(MAC_REG_BASE_ADDR + UMAC_CMD, 0);
write32(MAC_REG_BASE_ADDR + UMAC_CMD, (CMD_SW_RESET | CMD_LCL_LOOP_EN));
DELAY_MICROS(2);
write32(MAC_REG_BASE_ADDR + UMAC_CMD, 0);
/* clear tx/rx counter */
write32(MAC_REG_BASE_ADDR + UMAC_MIB_CTRL, MIB_RESET_RX | MIB_RESET_TX | MIB_RESET_RUNT);
write32(MAC_REG_BASE_ADDR + UMAC_MIB_CTRL, 0);
write32(MAC_REG_BASE_ADDR + UMAC_MAX_FRAME_LEN, ENET_MAX_MTU_SIZE);
/* init rx registers, enable ip header optimization */
reg = read32(MAC_REG_BASE_ADDR + RBUF_CTRL);
reg |= RBUF_ALIGN_2B;
write32(MAC_REG_BASE_ADDR + RBUF_CTRL, reg);
write32(MAC_REG_BASE_ADDR + RBUF_TBUF_SIZE_CTRL, 1);
}
static void bcmgenet_disable_dma(void)
{
rt_uint32_t tdma_reg = 0, rdma_reg = 0;
tdma_reg = read32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_CTRL);
tdma_reg &= ~(1UL << DMA_EN);
write32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_CTRL, tdma_reg);
rdma_reg = read32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_CTRL);
rdma_reg &= ~(1UL << DMA_EN);
write32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_CTRL, rdma_reg);
write32(MAC_REG_BASE_ADDR + UMAC_TX_FLUSH, 1);
DELAY_MICROS(100);
write32(MAC_REG_BASE_ADDR + UMAC_TX_FLUSH, 0);
}
static void bcmgenet_enable_dma(void)
{
rt_uint32_t reg = 0;
rt_uint32_t dma_ctrl = 0;
dma_ctrl = (1 << (DEFAULT_Q + DMA_RING_BUF_EN_SHIFT)) | DMA_EN;
write32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_CTRL, dma_ctrl);
reg = read32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_CTRL);
write32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_CTRL, dma_ctrl | reg);
}
static int bcmgenet_mdio_write(rt_uint32_t addr, rt_uint32_t reg, rt_uint32_t value)
{
int count = 10000;
rt_uint32_t val;
rt_uint32_t reg_val;
val = MDIO_WR | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT) | (0xffff & value);
write32(MAC_REG_BASE_ADDR + MDIO_CMD, val);
reg_val = read32(MAC_REG_BASE_ADDR + MDIO_CMD);
reg_val = reg_val | MDIO_START_BUSY;
write32(MAC_REG_BASE_ADDR + MDIO_CMD, reg_val);
while ((read32(MAC_REG_BASE_ADDR + MDIO_CMD) & MDIO_START_BUSY) && (--count))
{
DELAY_MICROS(1);
}
reg_val = read32(MAC_REG_BASE_ADDR + MDIO_CMD);
return reg_val & 0xffff;
}
static int bcmgenet_mdio_read(rt_uint32_t addr, rt_uint32_t reg)
{
int count = 10000;
rt_uint32_t val = 0;
rt_uint32_t reg_val = 0;
val = MDIO_RD | (addr << MDIO_PMD_SHIFT) | (reg << MDIO_REG_SHIFT);
write32(MAC_REG_BASE_ADDR + MDIO_CMD, val);
reg_val = read32(MAC_REG_BASE_ADDR + MDIO_CMD);
reg_val = reg_val | MDIO_START_BUSY;
write32(MAC_REG_BASE_ADDR + MDIO_CMD, reg_val);
while ((read32(MAC_REG_BASE_ADDR + MDIO_CMD) & MDIO_START_BUSY) && (--count))
{
DELAY_MICROS(1);
}
reg_val = read32(MAC_REG_BASE_ADDR + MDIO_CMD);
return reg_val & 0xffff;
}
static int bcmgenet_gmac_write_hwaddr(void)
{
rt_uint8_t addr[6];
rt_uint32_t reg;
bcm271x_mbox_hardware_get_mac_address(&addr[0]);
reg = addr[0] << 24 | addr[1] << 16 | addr[2] << 8 | addr[3];
write32(MAC_REG_BASE_ADDR + UMAC_MAC0, reg);
reg = addr[4] << 8 | addr[5];
write32(MAC_REG_BASE_ADDR + UMAC_MAC1, reg);
return 0;
}
static int get_ethernet_uid(void)
{
rt_uint32_t uid_high = 0;
rt_uint32_t uid_low = 0;
rt_uint32_t uid = 0;
uid_high = bcmgenet_mdio_read(1, BCM54213PE_PHY_IDENTIFIER_HIGH);
uid_low = bcmgenet_mdio_read(1, BCM54213PE_PHY_IDENTIFIER_LOW);
uid = (uid_high << 16 | uid_low);
if (BCM54213PE_VERSION_B1 == uid)
{
LOG_I("version is B1\n");
}
return uid;
}
static void bcmgenet_mdio_init(void)
{
/* get ethernet uid */
if (get_ethernet_uid() == 0)
{
return;
}
/* reset phy */
bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, MII_CONTROL_PHY_RESET);
/* read control reg */
bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
/* reset phy again */
bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, MII_CONTROL_PHY_RESET);
/* read control reg */
bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
/* read status reg */
bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS);
/* read status reg */
bcmgenet_mdio_read(1, BCM54213PE_IEEE_EXTENDED_STATUS);
bcmgenet_mdio_read(1, BCM54213PE_AUTO_NEGOTIATION_ADV);
bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS);
bcmgenet_mdio_read(1, BCM54213PE_CONTROL);
/* half full duplex capability */
bcmgenet_mdio_write(1, BCM54213PE_CONTROL, (CONTROL_HALF_DUPLEX_CAPABILITY | CONTROL_FULL_DUPLEX_CAPABILITY));
bcmgenet_mdio_read(1, BCM54213PE_MII_CONTROL);
/* set mii control */
bcmgenet_mdio_write(1, BCM54213PE_MII_CONTROL, (MII_CONTROL_AUTO_NEGOTIATION_ENABLED | MII_CONTROL_AUTO_NEGOTIATION_RESTART | MII_CONTROL_PHY_FULL_DUPLEX | MII_CONTROL_SPEED_SELECTION));
}
static void rx_ring_init(void)
{
write32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH);
write32(MAC_REG_BASE_ADDR + RDMA_RING_REG_BASE + DMA_START_ADDR, 0x0);
write32(MAC_REG_BASE_ADDR + RDMA_READ_PTR, 0x0);
write32(MAC_REG_BASE_ADDR + RDMA_WRITE_PTR, 0x0);
write32(MAC_REG_BASE_ADDR + RDMA_RING_REG_BASE + DMA_END_ADDR, RX_DESCS * DMA_DESC_SIZE / 4 - 1);
write32(MAC_REG_BASE_ADDR + RDMA_PROD_INDEX, 0x0);
write32(MAC_REG_BASE_ADDR + RDMA_CONS_INDEX, 0x0);
write32(MAC_REG_BASE_ADDR + RDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (RX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH);
write32(MAC_REG_BASE_ADDR + RDMA_XON_XOFF_THRESH, DMA_FC_THRESH_VALUE);
write32(MAC_REG_BASE_ADDR + RDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q);
}
static void tx_ring_init(void)
{
write32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_SCB_BURST_SIZE, DMA_MAX_BURST_LENGTH);
write32(MAC_REG_BASE_ADDR + TDMA_RING_REG_BASE + DMA_START_ADDR, 0x0);
write32(MAC_REG_BASE_ADDR + TDMA_READ_PTR, 0x0);
write32(MAC_REG_BASE_ADDR + TDMA_READ_PTR, 0x0);
write32(MAC_REG_BASE_ADDR + TDMA_READ_PTR, 0x0);
write32(MAC_REG_BASE_ADDR + TDMA_WRITE_PTR, 0x0);
write32(MAC_REG_BASE_ADDR + TDMA_RING_REG_BASE + DMA_END_ADDR, TX_DESCS * DMA_DESC_SIZE / 4 - 1);
write32(MAC_REG_BASE_ADDR + TDMA_PROD_INDEX, 0x0);
write32(MAC_REG_BASE_ADDR + TDMA_CONS_INDEX, 0x0);
write32(MAC_REG_BASE_ADDR + TDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH, 0x1);
write32(MAC_REG_BASE_ADDR + TDMA_FLOW_PERIOD, 0x0);
write32(MAC_REG_BASE_ADDR + TDMA_RING_REG_BASE + DMA_RING_BUF_SIZE, (TX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH);
write32(MAC_REG_BASE_ADDR + TDMA_REG_BASE + DMA_RING_CFG, 1 << DEFAULT_Q);
}
static void rx_descs_init(void)
{
char *rxbuffs = (char *)RECV_DATA_NO_CACHE;
rt_uint32_t len_stat, i;
void *desc_base = (void *)RX_DESC_BASE;
len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN;
for (i = 0; i < RX_DESCS; i++)
{
write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_LO), lower_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]));
write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_ADDRESS_HI), upper_32_bits((uintptr_t)&rxbuffs[i * RX_BUF_LENGTH]));
write32((desc_base + i * DMA_DESC_SIZE + DMA_DESC_LENGTH_STATUS), len_stat);
}
}
static int bcmgenet_adjust_link(void)
{
rt_uint32_t speed;
rt_uint32_t phy_dev_speed = link_speed;
rt_uint32_t reg1;
switch (phy_dev_speed)
{
case SPEED_1000:
speed = UMAC_SPEED_1000;
break;
case SPEED_100:
speed = UMAC_SPEED_100;
break;
case SPEED_10:
speed = UMAC_SPEED_10;
break;
default:
rt_kprintf("bcmgenet: Unsupported PHY speed: %d\n", phy_dev_speed);
return -1;
}
reg1 = read32(MAC_REG_BASE_ADDR + EXT_RGMII_OOB_CTRL);
reg1 |= (RGMII_LINK | RGMII_MODE_EN | ID_MODE_DIS);
write32(MAC_REG_BASE_ADDR + EXT_RGMII_OOB_CTRL, reg1);
DELAY_MICROS(1000);
write32(MAC_REG_BASE_ADDR + UMAC_CMD, speed << CMD_SPEED_SHIFT);
return 0;
}
void link_irq(void *param)
{
if ((bcmgenet_mdio_read(1, BCM54213PE_MII_STATUS) & MII_STATUS_LINK_UP) != 0)
{
rt_sem_release(&link_ack);
}
}
static int bcmgenet_gmac_eth_start(void)
{
rt_uint32_t ret;
rt_uint32_t count = 10000;
bcmgenet_umac_reset();
bcmgenet_gmac_write_hwaddr();
/* disable RX/TX DMA and flush TX queues */
bcmgenet_disable_dma();
rx_ring_init();
rx_descs_init();
tx_ring_init();
/* enable RX/TX DMA */
bcmgenet_enable_dma();
/* ppdate MAC registers based on PHY property */
ret = bcmgenet_adjust_link();
if (ret)
{
rt_kprintf("bcmgenet: adjust PHY link failed: %d\n", ret);
return ret;
}
/* wait tx index clear */
while ((read32(MAC_REG_BASE_ADDR + TDMA_CONS_INDEX) != 0) && (--count))
{
DELAY_MICROS(1);
}
tx_index = read32(MAC_REG_BASE_ADDR + TDMA_CONS_INDEX);
write32(MAC_REG_BASE_ADDR + TDMA_PROD_INDEX, tx_index);
index_flag = read32(MAC_REG_BASE_ADDR + RDMA_PROD_INDEX);
rx_index = index_flag % RX_DESCS;
write32(MAC_REG_BASE_ADDR + RDMA_CONS_INDEX, index_flag);
write32(MAC_REG_BASE_ADDR + RDMA_PROD_INDEX, index_flag);
/* enable Rx/Tx */
rt_uint32_t rx_tx_en;
rx_tx_en = read32(MAC_REG_BASE_ADDR + UMAC_CMD);
rx_tx_en |= (CMD_TX_EN | CMD_RX_EN);
write32(MAC_REG_BASE_ADDR + UMAC_CMD, rx_tx_en);
/* eanble IRQ for TxDMA done and RxDMA done */
write32(MAC_REG_BASE_ADDR + GENET_INTRL2_CPU_CLEAR_MASK, GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE);
return 0;
}
static rt_uint32_t prev_recv_cnt = 0;
static rt_uint32_t cur_recv_cnt = 0;
static rt_uint32_t bcmgenet_gmac_eth_recv(rt_uint8_t **packetp)
{
void *desc_base;
rt_uint32_t length = 0, addr = 0;
rt_uint32_t prod_index = read32(MAC_REG_BASE_ADDR + RDMA_PROD_INDEX);
/* no buff */
if (prod_index == index_flag)
{
cur_recv_cnt = index_flag;
index_flag = 0x7fffffff;
return 0;
}
else
{
/* no new buff */
if (prev_recv_cnt == (prod_index & 0xffff))
{
return 0;
}
desc_base = RX_DESC_BASE + rx_index * DMA_DESC_SIZE;
length = read32(desc_base + DMA_DESC_LENGTH_STATUS);
length = (length >> DMA_BUFLENGTH_SHIFT) & DMA_BUFLENGTH_MASK;
addr = read32(desc_base + DMA_DESC_ADDRESS_LO);
/*
* to cater for the IP headepr alignment the hardware does.
* This would actually not be needed if we don't program
* RBUF_ALIGN_2B
*/
/* convert to memory address */
addr = addr + RECV_DATA_NO_CACHE - RECV_DATA_NO_CACHE;
rt_hw_dcache_invalidate_range(addr, length);
*packetp = (rt_uint8_t *)(unsigned long)(addr + RX_BUF_OFFSET);
rx_index = rx_index + 1;
if (rx_index >= RX_DESCS)
{
rx_index = 0;
}
write32(MAC_REG_BASE_ADDR + RDMA_CONS_INDEX, cur_recv_cnt);
cur_recv_cnt = cur_recv_cnt + 1;
if (cur_recv_cnt > 0xffff)
{
cur_recv_cnt = 0;
}
prev_recv_cnt = cur_recv_cnt;
return length - RX_BUF_OFFSET;
}
}
static int bcmgenet_gmac_eth_send(rt_uint32_t packet, int length, struct pbuf *p)
{
void *desc_base = (TX_DESC_BASE + tx_index * DMA_DESC_SIZE);
pbuf_copy_partial(p, (void *)(unsigned long)(packet + tx_index * SEND_CACHE_BUF), p->tot_len, 0);
rt_uint32_t len_stat = length << DMA_BUFLENGTH_SHIFT;
len_stat |= 0x3F << DMA_TX_QTAG_SHIFT;
len_stat |= DMA_TX_APPEND_CRC | DMA_SOP | DMA_EOP;
rt_hw_dcache_flush_range(packet + tx_index * SEND_CACHE_BUF, length);
rt_uint32_t prod_index;
prod_index = read32(MAC_REG_BASE_ADDR + TDMA_PROD_INDEX);
write32((desc_base + DMA_DESC_ADDRESS_LO), SEND_DATA_NO_CACHE + tx_index * SEND_CACHE_BUF);
write32((desc_base + DMA_DESC_ADDRESS_HI), 0);
write32((desc_base + DMA_DESC_LENGTH_STATUS), len_stat);
tx_index++;
if (tx_index >= TX_DESCS)
{
tx_index = 0;
}
prod_index = prod_index + 1;
if (prod_index > 0xffff)
{
prod_index = 0;
}
/* start Transmisson */
write32(MAC_REG_BASE_ADDR + TDMA_PROD_INDEX, prod_index);
return 0;
}
static void link_task_entry(void *param)
{
struct eth_device *eth_device = (struct eth_device *)param;
RT_ASSERT(eth_device != RT_NULL);
struct rt_eth_dev *dev = &eth_dev;
/* start mdio */
bcmgenet_mdio_init();
/* start timer link */
rt_timer_init(&dev->link_timer, "link_timer",
link_irq,
NULL,
100,
RT_TIMER_FLAG_PERIODIC);
rt_timer_start(&dev->link_timer);
/* link wait forever */
rt_sem_take(&link_ack, RT_WAITING_FOREVER);
/* link up */
eth_device_linkchange(&eth_dev.parent, RT_TRUE);
rt_timer_stop(&dev->link_timer);
/* set mac */
bcmgenet_gmac_write_hwaddr();
/* check link speed */
if ((bcmgenet_mdio_read(1, BCM54213PE_STATUS) & (1 << 10)) || (bcmgenet_mdio_read(1, BCM54213PE_STATUS) & (1 << 11)))
{
link_speed = 1000;
rt_kprintf("Support link mode Speed 1000M\n");
}
else if ((bcmgenet_mdio_read(1, 0x05) & (1 << 7)) || (bcmgenet_mdio_read(1, 0x05) & (1 << 8)) || (bcmgenet_mdio_read(1, 0x05) & (1 << 9)))
{
link_speed = 100;
rt_kprintf("Support link mode Speed 100M\n");
}
else
{
link_speed = 10;
rt_kprintf("Support link mode Speed 10M\n");
}
/* convert to memory address */
bcmgenet_gmac_eth_start();
rt_hw_interrupt_install(ETH_IRQ, eth_rx_irq, NULL, "eth_irq");
rt_hw_interrupt_umask(ETH_IRQ);
link_flag = 1;
}
static rt_err_t bcmgenet_eth_init(rt_device_t device)
{
rt_uint32_t ret = 0;
rt_uint32_t hw_reg = 0;
/* read GENET HW version */
rt_uint8_t major = 0;
hw_reg = read32(MAC_REG_BASE_ADDR + SYS_REV_CTRL);
major = (hw_reg >> 24) & 0x0f;
if (major != 6)
{
if (major == 5)
{
major = 4;
}
else if (major == 0)
{
major = 1;
}
rt_kprintf("Uns upported GENETv%d.%d\n", major, (hw_reg >> 16) & 0x0f);
return RT_ERROR;
}
/* set interface */
ret = bcmgenet_interface_set();
if (ret)
{
return ret;
}
/* rbuf clear */
write32(MAC_REG_BASE_ADDR + SYS_RBUF_FLUSH_CTRL, 0);
/* disable MAC while updating its registers */
write32(MAC_REG_BASE_ADDR + UMAC_CMD, 0);
/* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
write32(MAC_REG_BASE_ADDR + UMAC_CMD, CMD_SW_RESET | CMD_LCL_LOOP_EN);
link_thread_tid = rt_thread_create("link", link_task_entry, (void *)device,
LINK_THREAD_STACK_SIZE,
LINK_THREAD_PRIORITY, LINK_THREAD_TIMESLICE);
if (link_thread_tid != RT_NULL)
{
rt_thread_startup(link_thread_tid);
}
return RT_EOK;
}
static rt_err_t bcmgenet_eth_control(rt_device_t dev, int cmd, void *args)
{
switch (cmd)
{
case NIOCTL_GADDR:
if (args)
{
rt_memcpy(args, eth_dev.dev_addr, 6);
}
else
{
return -RT_ERROR;
}
break;
default:
break;
}
return RT_EOK;
}
rt_err_t rt_eth_tx(rt_device_t device, struct pbuf *p)
{
if (link_flag == 1)
{
bcmgenet_gmac_eth_send((rt_uint32_t)SEND_DATA_NO_CACHE, p->tot_len, p);
rt_sem_take(&send_finsh_sem_lock, RT_WAITING_FOREVER);
}
return RT_EOK;
}
struct pbuf *rt_eth_rx(rt_device_t device)
{
int recv_len = 0;
rt_uint8_t *addr_point = RT_NULL;
struct pbuf *pbuf = RT_NULL;
if (link_flag == 1)
{
recv_len = bcmgenet_gmac_eth_recv(&addr_point);
if (recv_len > 0)
{
pbuf = pbuf_alloc(PBUF_LINK, recv_len, PBUF_RAM);
if (pbuf)
{
rt_memcpy(pbuf->payload, addr_point, recv_len);
}
}
}
return pbuf;
}
int rt_hw_eth_init(void)
{
rt_uint8_t mac_addr[6];
rt_sem_init(&send_finsh_sem_lock, "send_finsh_sem_lock", TX_DESCS, RT_IPC_FLAG_FIFO);
rt_sem_init(&link_ack, "link_ack", 0, RT_IPC_FLAG_FIFO);
memset(&eth_dev, 0, sizeof(eth_dev));
memset((void *)SEND_DATA_NO_CACHE, 0, DMA_DISC_ADDR_SIZE);
memset((void *)RECV_DATA_NO_CACHE, 0, DMA_DISC_ADDR_SIZE);
bcm271x_mbox_hardware_get_mac_address(&mac_addr[0]);
eth_dev.iobase = MAC_REG_BASE_ADDR;
eth_dev.name = "e0";
eth_dev.dev_addr[0] = mac_addr[0];
eth_dev.dev_addr[1] = mac_addr[1];
eth_dev.dev_addr[2] = mac_addr[2];
eth_dev.dev_addr[3] = mac_addr[3];
eth_dev.dev_addr[4] = mac_addr[4];
eth_dev.dev_addr[5] = mac_addr[5];
eth_dev.parent.parent.type = RT_Device_Class_NetIf;
eth_dev.parent.parent.init = bcmgenet_eth_init;
eth_dev.parent.parent.open = RT_NULL;
eth_dev.parent.parent.close = RT_NULL;
eth_dev.parent.parent.read = RT_NULL;
eth_dev.parent.parent.write = RT_NULL;
eth_dev.parent.parent.control = bcmgenet_eth_control;
eth_dev.parent.parent.user_data = RT_NULL;
eth_dev.parent.eth_tx = rt_eth_tx;
eth_dev.parent.eth_rx = rt_eth_rx;
eth_device_init(&(eth_dev.parent), "e0");
/* link down */
eth_device_linkchange(&eth_dev.parent, RT_FALSE);
return 0;
}
INIT_COMPONENT_EXPORT(rt_hw_eth_init);

View File

@ -0,0 +1,216 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-10-30 bigmagic first version
*/
#ifndef __DRV_ETH_H__
#define __DRV_ETH_H__
#define MAC_REG (void *)(0xfd580000)
#define SYS_REV_CTRL (0x00)
#define SYS_PORT_CTRL (0x04)
#define PORT_MODE_EXT_GPHY (3)
#define GENET_SYS_OFF (0x0000)
#define SYS_RBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x08)
#define SYS_TBUF_FLUSH_CTRL (GENET_SYS_OFF + 0x0c)
#define GENET_EXT_OFF (0x0080)
#define EXT_RGMII_OOB_CTRL (GENET_EXT_OFF + 0x0c)
#define RGMII_LINK BIT(4)
#define OOB_DISABLE BIT(5)
#define RGMII_MODE_EN BIT(6)
#define ID_MODE_DIS BIT(16)
#define GENET_RBUF_OFF (0x0300)
#define RBUF_TBUF_SIZE_CTRL (GENET_RBUF_OFF + 0xb4)
#define RBUF_CTRL (GENET_RBUF_OFF + 0x00)
#define RBUF_ALIGN_2B BIT(1)
#define GENET_UMAC_OFF (0x0800)
#define UMAC_MIB_CTRL (GENET_UMAC_OFF + 0x580)
#define UMAC_MAX_FRAME_LEN (GENET_UMAC_OFF + 0x014)
#define UMAC_MAC0 (GENET_UMAC_OFF + 0x00c)
#define UMAC_MAC1 (GENET_UMAC_OFF + 0x010)
#define UMAC_CMD (GENET_UMAC_OFF + 0x008)
#define MDIO_CMD (GENET_UMAC_OFF + 0x614)
#define UMAC_TX_FLUSH (GENET_UMAC_OFF + 0x334)
#define MDIO_START_BUSY BIT(29)
#define MDIO_READ_FAIL BIT(28)
#define MDIO_RD (2 << 26)
#define MDIO_WR BIT(26)
#define MDIO_PMD_SHIFT (21)
#define MDIO_PMD_MASK (0x1f)
#define MDIO_REG_SHIFT (16)
#define MDIO_REG_MASK (0x1f)
#define GENET_INTRL2_OFF (0x0200)
#define GENET_INTRL2_CPU_STAT (GENET_INTRL2_OFF + 0x00)
#define GENET_INTRL2_CPU_CLEAR (GENET_INTRL2_OFF + 0x08)
#define GENET_INTRL2_CPU_STAT_MASK (GENET_INTRL2_OFF + 0x0c)
#define GENET_INTRL2_CPU_SET_MASK (GENET_INTRL2_OFF + 0x10)
#define GENET_INTRL2_CPU_CLEAR_MASK (GENET_INTRL2_OFF + 0x14)
#define GENET_IRQ_MDIO_ERROR BIT(24)
#define GENET_IRQ_MDIO_DONE BIT(23)
#define GENET_IRQ_TXDMA_DONE BIT(16)
#define GENET_IRQ_RXDMA_DONE BIT(13)
#define CMD_TX_EN BIT(0)
#define CMD_RX_EN BIT(1)
#define UMAC_SPEED_10 (0)
#define UMAC_SPEED_100 (1)
#define UMAC_SPEED_1000 (2)
#define UMAC_SPEED_2500 (3)
#define CMD_SPEED_SHIFT (2)
#define CMD_SPEED_MASK (3)
#define CMD_SW_RESET BIT(13)
#define CMD_LCL_LOOP_EN BIT(15)
#define CMD_TX_EN BIT(0)
#define CMD_RX_EN BIT(1)
#define MIB_RESET_RX BIT(0)
#define MIB_RESET_RUNT BIT(1)
#define MIB_RESET_TX BIT(2)
/* total number of Buffer Descriptors, same for Rx/Tx */
#define TOTAL_DESCS (256)
#define RX_DESCS TOTAL_DESCS
#define TX_DESCS TOTAL_DESCS
#define DEFAULT_Q (0x10)
#define ETH_DATA_LEN (1500)
#define ETH_HLEN (14)
#define VLAN_HLEN (4)
#define ETH_FCS_LEN (4)
/*
* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
* 1536 is multiple of 256 bytes
*/
#define ENET_BRCM_TAG_LEN (6)
#define ENET_PAD (8)
#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
/* Tx/Rx Dma Descriptor common bits */
#define DMA_EN BIT(0)
#define DMA_RING_BUF_EN_SHIFT (0x01)
#define DMA_RING_BUF_EN_MASK (0xffff)
#define DMA_BUFLENGTH_MASK (0x0fff)
#define DMA_BUFLENGTH_SHIFT (16)
#define DMA_RING_SIZE_SHIFT (16)
#define DMA_OWN (0x8000)
#define DMA_EOP (0x4000)
#define DMA_SOP (0x2000)
#define DMA_WRAP (0x1000)
#define DMA_MAX_BURST_LENGTH (0x8)
/* Tx specific DMA descriptor bits */
#define DMA_TX_UNDERRUN (0x0200)
#define DMA_TX_APPEND_CRC (0x0040)
#define DMA_TX_OW_CRC (0x0020)
#define DMA_TX_DO_CSUM (0x0010)
#define DMA_TX_QTAG_SHIFT (7)
/* DMA rings size */
#define DMA_RING_SIZE (0x40)
#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DEFAULT_Q + 1))
/* DMA descriptor */
#define DMA_DESC_LENGTH_STATUS (0x00)
#define DMA_DESC_ADDRESS_LO (0x04)
#define DMA_DESC_ADDRESS_HI (0x08)
#define DMA_DESC_SIZE (12)
#define GENET_RX_OFF (0x2000)
#define GENET_RDMA_REG_OFF (GENET_RX_OFF + TOTAL_DESCS * DMA_DESC_SIZE)
#define GENET_TX_OFF (0x4000)
#define GENET_TDMA_REG_OFF (GENET_TX_OFF + TOTAL_DESCS * DMA_DESC_SIZE)
#define DMA_FC_THRESH_HI (RX_DESCS >> 4)
#define DMA_FC_THRESH_LO (5)
#define DMA_FC_THRESH_VALUE ((DMA_FC_THRESH_LO << 16) | DMA_FC_THRESH_HI)
#define DMA_XOFF_THRESHOLD_SHIFT (16)
#define TDMA_RING_REG_BASE (GENET_TDMA_REG_OFF + DEFAULT_Q * DMA_RING_SIZE)
#define TDMA_READ_PTR (TDMA_RING_REG_BASE + 0x00)
#define TDMA_CONS_INDEX (TDMA_RING_REG_BASE + 0x08)
#define TDMA_PROD_INDEX (TDMA_RING_REG_BASE + 0x0c)
#define DMA_RING_BUF_SIZE (0x10)
#define DMA_START_ADDR (0x14)
#define DMA_END_ADDR (0x1c)
#define DMA_MBUF_DONE_THRESH (0x24)
#define TDMA_FLOW_PERIOD (TDMA_RING_REG_BASE + 0x28)
#define TDMA_WRITE_PTR (TDMA_RING_REG_BASE + 0x2c)
#define RDMA_RING_REG_BASE (GENET_RDMA_REG_OFF + DEFAULT_Q * DMA_RING_SIZE)
#define RDMA_WRITE_PTR (RDMA_RING_REG_BASE + 0x00)
#define RDMA_PROD_INDEX (RDMA_RING_REG_BASE + 0x08)
#define RDMA_CONS_INDEX (RDMA_RING_REG_BASE + 0x0c)
#define RDMA_XON_XOFF_THRESH (RDMA_RING_REG_BASE + 0x28)
#define RDMA_READ_PTR (RDMA_RING_REG_BASE + 0x2c)
#define TDMA_REG_BASE (GENET_TDMA_REG_OFF + DMA_RINGS_SIZE)
#define RDMA_REG_BASE (GENET_RDMA_REG_OFF + DMA_RINGS_SIZE)
#define DMA_RING_CFG (0x00)
#define DMA_CTRL (0x04)
#define DMA_SCB_BURST_SIZE (0x0c)
#define RX_BUF_LENGTH (2048)
#define RX_TOTAL_BUFSIZE (RX_BUF_LENGTH * RX_DESCS)
#define RX_BUF_OFFSET (2)
#define PHY_INTERFACE_MODE_RGMII (7)
#define PHY_INTERFACE_MODE_RGMII_RXID (9)
#define BCM54213PE_MII_CONTROL (0x00)
#define BCM54213PE_MII_STATUS (0x01)
#define BCM54213PE_PHY_IDENTIFIER_HIGH (0x02)
#define BCM54213PE_PHY_IDENTIFIER_LOW (0x03)
#define BCM54213PE_AUTO_NEGOTIATION_ADV (0x04)
#define BCM54213PE_AUTO_NEGOTIATION_LINK (0x05)
#define BCM54213PE_AUTO_NEGOTIATION_EXPANSION (0x06)
#define BCM54213PE_NEXT_PAGE_TX (0x07)
#define BCM54213PE_PARTNER_RX (0x08)
#define BCM54213PE_CONTROL (0x09)
#define BCM54213PE_STATUS (0x0A)
#define BCM54213PE_IEEE_EXTENDED_STATUS (0x0F)
#define BCM54213PE_PHY_EXTENDED_CONTROL (0x10)
#define BCM54213PE_PHY_EXTENDED_STATUS (0x11)
#define BCM54213PE_RECEIVE_ERROR_COUNTER (0x12)
#define BCM54213PE_FALSE_C_S_COUNTER (0x13)
#define BCM54213PE_RECEIVE_NOT_OK_COUNTER (0x14)
#define BCM54213PE_VERSION_B1 (0x600d84a2)
#define BCM54213PE_VERSION_X (0x600d84a0)
//BCM54213PE_MII_CONTROL
#define MII_CONTROL_PHY_RESET (1 << 15)
#define MII_CONTROL_AUTO_NEGOTIATION_ENABLED (1 << 12)
#define MII_CONTROL_AUTO_NEGOTIATION_RESTART (1 << 9)
#define MII_CONTROL_PHY_FULL_DUPLEX (1 << 8)
#define MII_CONTROL_SPEED_SELECTION (1 << 6)
//BCM54213PE_MII_STATUS
#define MII_STATUS_LINK_UP (1 << 2)
//BCM54213PE_CONTROL
#define CONTROL_FULL_DUPLEX_CAPABILITY (1 << 9)
#define CONTROL_HALF_DUPLEX_CAPABILITY (1 << 8)
#define SPEED_1000 (1000)
#define SPEED_100 (100)
#define SPEED_10 (10)
#endif/* __DRV_ETH_H__ */

View File

@ -12,6 +12,63 @@
#ifdef BSP_USING_PIN
uint32_t raspi_get_pin_state(uint32_t fselnum)
{
uint32_t gpfsel = 0;
switch (fselnum)
{
case 0:
gpfsel = GPIO_REG_GPFSEL0(GPIO_BASE);
break;
case 1:
gpfsel = GPIO_REG_GPFSEL1(GPIO_BASE);
break;
case 2:
gpfsel = GPIO_REG_GPFSEL2(GPIO_BASE);
break;
case 3:
gpfsel = GPIO_REG_GPFSEL3(GPIO_BASE);
break;
case 4:
gpfsel = GPIO_REG_GPFSEL4(GPIO_BASE);
break;
case 5:
gpfsel = GPIO_REG_GPFSEL5(GPIO_BASE);
break;
default:
break;
}
return gpfsel;
}
void raspi_set_pin_state(uint32_t fselnum, uint32_t gpfsel)
{
switch (fselnum)
{
case 0:
GPIO_REG_GPFSEL0(GPIO_BASE) = gpfsel;
break;
case 1:
GPIO_REG_GPFSEL1(GPIO_BASE) = gpfsel;
break;
case 2:
GPIO_REG_GPFSEL2(GPIO_BASE) = gpfsel;
break;
case 3:
GPIO_REG_GPFSEL3(GPIO_BASE) = gpfsel;
break;
case 4:
GPIO_REG_GPFSEL4(GPIO_BASE) = gpfsel;
break;
case 5:
GPIO_REG_GPFSEL5(GPIO_BASE) = gpfsel;
break;
default:
break;
}
}
static void raspi_pin_mode(struct rt_device *dev, rt_base_t pin, rt_base_t mode)
{
uint32_t fselnum = pin / 10;
@ -46,6 +103,18 @@ static void raspi_pin_mode(struct rt_device *dev, rt_base_t pin, rt_base_t mode)
}
}
void prev_raspi_pin_mode(GPIO_PIN pin, GPIO_FUNC mode)
{
uint32_t fselnum = pin / 10;
uint32_t fselrest = pin % 10;
uint32_t gpfsel = 0;
gpfsel = raspi_get_pin_state(fselnum);
gpfsel &= ~((uint32_t)(0x07 << (fselrest * 3)));
gpfsel |= (uint32_t)(mode << (fselrest * 3));
raspi_set_pin_state(fselnum, gpfsel);
}
static void raspi_pin_write(struct rt_device *dev, rt_base_t pin, rt_base_t value)
{
uint32_t num = pin / 32;

View File

@ -60,6 +60,50 @@
#define GPIO_REG_REV9(BASE) HWREG32(BASE + 0xA0)
#define GPIO_REG_TEST(BASE) HWREG32(BASE + 0xA4)
typedef enum {
GPIO_PIN_0,
GPIO_PIN_1,
GPIO_PIN_2,
GPIO_PIN_3,
GPIO_PIN_4,
GPIO_PIN_5,
GPIO_PIN_6,
GPIO_PIN_7,
GPIO_PIN_8,
GPIO_PIN_9,
GPIO_PIN_10,
GPIO_PIN_11,
GPIO_PIN_12,
GPIO_PIN_13,
GPIO_PIN_14,
GPIO_PIN_15,
GPIO_PIN_16,
GPIO_PIN_17,
GPIO_PIN_18,
GPIO_PIN_19,
GPIO_PIN_20,
GPIO_PIN_21,
GPIO_PIN_22,
GPIO_PIN_23,
GPIO_PIN_24,
GPIO_PIN_25,
GPIO_PIN_26,
GPIO_PIN_27,
GPIO_PIN_28,
GPIO_PIN_29,
GPIO_PIN_30,
GPIO_PIN_31,
GPIO_PIN_32,
GPIO_PIN_33,
GPIO_PIN_34,
GPIO_PIN_35,
GPIO_PIN_36,
GPIO_PIN_37,
GPIO_PIN_38,
GPIO_PIN_39,
GPIO_PIN_40,
} GPIO_PIN;
typedef enum {
INPUT = 0b000,
OUTPUT = 0b001,
@ -71,7 +115,8 @@ typedef enum {
ALT5 = 0b010
} GPIO_FUNC;
void prev_raspi_pin_mode(GPIO_PIN pin, GPIO_FUNC mode);
void prev_raspi_pin_write(GPIO_PIN pin, int pin_value);
int rt_hw_gpio_init(void);
#endif /* __DRV_GPIO_H__ */

View File

@ -0,0 +1,720 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-10-27 bigmagic first version
*/
#include <rtdef.h>
#include "mbox.h"
#include "raspi4.h"
#include "drv_sdio.h"
#include "mmu.h"
static rt_uint32_t mmc_base_clock = 0;
static rt_uint32_t sdCommandTable[] =
{
SD_CMD_INDEX(0),
SD_CMD_RESERVED(1),
SD_CMD_INDEX(2) | SD_RESP_R2,
SD_CMD_INDEX(3) | SD_RESP_R1,
SD_CMD_INDEX(4),
SD_CMD_RESERVED(5), //SD_CMD_INDEX(5) | SD_RESP_R4,
SD_CMD_INDEX(6) | SD_RESP_R1,
SD_CMD_INDEX(7) | SD_RESP_R1b,
SD_CMD_INDEX(8) | SD_RESP_R1,
SD_CMD_INDEX(9) | SD_RESP_R2,
SD_CMD_INDEX(10) | SD_RESP_R2,
SD_CMD_INDEX(11) | SD_RESP_R1,
SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT,
SD_CMD_INDEX(13) | SD_RESP_R1,
SD_CMD_RESERVED(14),
SD_CMD_INDEX(15),
SD_CMD_INDEX(16) | SD_RESP_R1,
SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ,
SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ,
SD_CMD_INDEX(20) | SD_RESP_R1b,
SD_CMD_RESERVED(21),
SD_CMD_RESERVED(22),
SD_CMD_INDEX(23) | SD_RESP_R1,
SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE,
SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN,
SD_CMD_INDEX(26) | SD_RESP_R1 | SD_DATA_WRITE, // add
SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE,
SD_CMD_INDEX(28) | SD_RESP_R1b,
SD_CMD_INDEX(29) | SD_RESP_R1b,
SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ,
SD_CMD_RESERVED(31),
SD_CMD_INDEX(32) | SD_RESP_R1,
SD_CMD_INDEX(33) | SD_RESP_R1,
SD_CMD_RESERVED(34),
SD_CMD_INDEX(35) | SD_RESP_R1, // add
SD_CMD_INDEX(36) | SD_RESP_R1, // add
SD_CMD_RESERVED(37),
SD_CMD_INDEX(38) | SD_RESP_R1b,
SD_CMD_INDEX(39) | SD_RESP_R4, // add
SD_CMD_INDEX(40) | SD_RESP_R5, // add
SD_CMD_INDEX(41) | SD_RESP_R3, // add, mov from harbote
SD_CMD_RESERVED(42) | SD_RESP_R1,
SD_CMD_RESERVED(43),
SD_CMD_RESERVED(44),
SD_CMD_RESERVED(45),
SD_CMD_RESERVED(46),
SD_CMD_RESERVED(47),
SD_CMD_RESERVED(48),
SD_CMD_RESERVED(49),
SD_CMD_RESERVED(50),
SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ,
SD_CMD_RESERVED(52),
SD_CMD_RESERVED(53),
SD_CMD_RESERVED(54),
SD_CMD_INDEX(55) | SD_RESP_R3,
SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA,
SD_CMD_RESERVED(57),
SD_CMD_RESERVED(58),
SD_CMD_RESERVED(59),
SD_CMD_RESERVED(60),
SD_CMD_RESERVED(61),
SD_CMD_RESERVED(62),
SD_CMD_RESERVED(63)
};
rt_inline rt_uint32_t read32(rt_ubase_t addr)
{
return (*((volatile unsigned int *)(addr)));
}
rt_inline void write32(rt_ubase_t addr, rt_uint32_t value)
{
(*((volatile unsigned int *)(addr))) = value;
}
rt_err_t sd_int(struct sdhci_pdata_t *pdat, rt_uint32_t mask)
{
rt_uint32_t r;
rt_uint32_t m = mask | INT_ERROR_MASK;
int cnt = 1000000;
while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--)
{
DELAY_MICROS(1);
}
r = read32(pdat->virt + EMMC_INTERRUPT);
if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT))
{
write32(pdat->virt + EMMC_INTERRUPT, r);
/* qemu maybe can not use sdcard */
rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n", mask, r, read32(pdat->virt + EMMC_STATUS));
return -RT_ETIMEOUT;
}
else if (r & INT_ERROR_MASK)
{
write32(pdat->virt + EMMC_INTERRUPT, r);
rt_kprintf("send cmd/data error %x -> %x\n", r, read32(pdat->virt + EMMC_INTERRUPT));
return -RT_ERROR;
}
write32(pdat->virt + EMMC_INTERRUPT, mask);
return RT_EOK;
}
rt_err_t sd_status(struct sdhci_pdata_t *pdat, unsigned int mask)
{
int cnt = 500000;
while ((read32(pdat->virt + EMMC_STATUS) & mask) && !(read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) && cnt--)
{
DELAY_MICROS(1);
}
if (cnt <= 0)
{
return -RT_ETIMEOUT;
}
else if (read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK)
{
return -RT_ERROR;
}
return RT_EOK;
}
static rt_err_t raspi_transfer_command(struct sdhci_pdata_t *pdat, struct sdhci_cmd_t *cmd)
{
rt_uint32_t cmdidx;
rt_err_t ret = RT_EOK;
ret = sd_status(pdat, SR_CMD_INHIBIT);
if (ret)
{
rt_kprintf("ERROR: EMMC busy %d\n", ret);
return ret;
}
cmdidx = sdCommandTable[cmd->cmdidx];
if (cmdidx == 0xFFFFFFFF)
{
return -RT_EINVAL;
}
if (cmd->datarw == DATA_READ)
{
cmdidx |= SD_DATA_READ;
}
if (cmd->datarw == DATA_WRITE)
{
cmdidx |= SD_DATA_WRITE;
}
mmcsd_dbg("transfer cmd %x(%d) %x %x\n", cmdidx, cmd->cmdidx, cmd->cmdarg, read32(pdat->virt + EMMC_INTERRUPT));
write32(pdat->virt + EMMC_INTERRUPT, read32(pdat->virt + EMMC_INTERRUPT));
write32(pdat->virt + EMMC_ARG1, cmd->cmdarg);
write32(pdat->virt + EMMC_CMDTM, cmdidx);
if (cmd->cmdidx == SD_APP_OP_COND)
{
DELAY_MICROS(1000);
}
else if ((cmd->cmdidx == SD_SEND_IF_COND) || (cmd->cmdidx == APP_CMD))
{
DELAY_MICROS(100);
}
ret = sd_int(pdat, INT_CMD_DONE);
if (ret)
{
return ret;
}
if (cmd->resptype & RESP_MASK)
{
if (cmd->resptype & RESP_R2)
{
rt_uint32_t resp[4];
resp[0] = read32(pdat->virt + EMMC_RESP0);
resp[1] = read32(pdat->virt + EMMC_RESP1);
resp[2] = read32(pdat->virt + EMMC_RESP2);
resp[3] = read32(pdat->virt + EMMC_RESP3);
if (cmd->resptype == RESP_R2)
{
cmd->response[0] = resp[3] << 8 | ((resp[2] >> 24) & 0xff);
cmd->response[1] = resp[2] << 8 | ((resp[1] >> 24) & 0xff);
cmd->response[2] = resp[1] << 8 | ((resp[0] >> 24) & 0xff);
cmd->response[3] = resp[0] << 8 ;
}
else
{
cmd->response[0] = resp[0];
cmd->response[1] = resp[1];
cmd->response[2] = resp[2];
cmd->response[3] = resp[3];
}
}
else
{
cmd->response[0] = read32(pdat->virt + EMMC_RESP0);
}
}
mmcsd_dbg("response: %x: %x %x %x %x (%x, %x)\n", cmd->resptype, cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3], read32(pdat->virt + EMMC_STATUS), read32(pdat->virt + EMMC_INTERRUPT));
return ret;
}
static rt_err_t read_bytes(struct sdhci_pdata_t *pdat, rt_uint32_t *buf, rt_uint32_t blkcount, rt_uint32_t blksize)
{
int c = 0;
rt_err_t ret;
int d;
while (c < blkcount)
{
if ((ret = sd_int(pdat, INT_READ_RDY)))
{
rt_kprintf("timeout happens when reading block %d\n", c);
return ret;
}
for (d = 0; d < blksize / 4; d++)
{
if (read32(pdat->virt + EMMC_STATUS) & SR_READ_AVAILABLE)
{
buf[d] = read32(pdat->virt + EMMC_DATA);
}
}
c++;
buf += blksize / 4;
}
return RT_EOK;
}
static rt_err_t write_bytes(struct sdhci_pdata_t *pdat, rt_uint32_t *buf, rt_uint32_t blkcount, rt_uint32_t blksize)
{
int c = 0;
rt_err_t ret;
int d;
while (c < blkcount)
{
if ((ret = sd_int(pdat, INT_WRITE_RDY)))
{
return ret;
}
for (d = 0; d < blksize / 4; d++)
{
write32(pdat->virt + EMMC_DATA, buf[d]);
}
c++;
buf += blksize / 4;
}
if ((ret = sd_int(pdat, INT_DATA_DONE)))
{
return ret;
}
return RT_EOK;
}
static rt_err_t raspi_transfer_data(struct sdhci_pdata_t *pdat, struct sdhci_cmd_t *cmd, struct sdhci_data_t *dat)
{
rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz);
rt_err_t ret = sd_status(pdat, SR_DAT_INHIBIT);
if (ret)
{
rt_kprintf("ERROR: EMMC busy\n");
return ret;
}
if (dat->blkcnt > 1)
{
struct sdhci_cmd_t newcmd;
newcmd.cmdidx = SET_BLOCK_COUNT;
newcmd.cmdarg = dat->blkcnt;
newcmd.resptype = RESP_R1;
ret = raspi_transfer_command(pdat, &newcmd);
if (ret)
{
return ret;
}
}
if (dlen < 512)
{
write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16);
}
else
{
write32(pdat->virt + EMMC_BLKSIZECNT, 512 | (dat->blkcnt) << 16);
}
if (dat->flag & DATA_DIR_READ)
{
cmd->datarw = DATA_READ;
ret = raspi_transfer_command(pdat, cmd);
if (ret)
{
return ret;
}
mmcsd_dbg("read_block %d, %d\n", dat->blkcnt, dat->blksz);
ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
}
else if (dat->flag & DATA_DIR_WRITE)
{
cmd->datarw = DATA_WRITE;
ret = raspi_transfer_command(pdat, cmd);
if (ret)
{
return ret;
}
mmcsd_dbg("write_block %d, %d", dat->blkcnt, dat->blksz);
ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz);
}
return ret;
}
static rt_err_t sdhci_transfer(struct sdhci_t *sdhci, struct sdhci_cmd_t *cmd, struct sdhci_data_t *dat)
{
struct sdhci_pdata_t *pdat = (struct sdhci_pdata_t *)sdhci->priv;
if (!dat)
{
return raspi_transfer_command(pdat, cmd);
}
return raspi_transfer_data(pdat, cmd, dat);
}
static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req)
{
struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
struct sdhci_cmd_t cmd;
struct sdhci_cmd_t stop;
struct sdhci_data_t dat;
rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t));
rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t));
rt_memset(&dat, 0, sizeof(struct sdhci_data_t));
cmd.cmdidx = req->cmd->cmd_code;
cmd.cmdarg = req->cmd->arg;
cmd.resptype = resp_type(req->cmd);
if (req->data)
{
dat.buf = (rt_uint8_t *)req->data->buf;
dat.flag = req->data->flags;
dat.blksz = req->data->blksize;
dat.blkcnt = req->data->blks;
req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat);
}
else
{
req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL);
}
req->cmd->resp[3] = cmd.response[3];
req->cmd->resp[2] = cmd.response[2];
req->cmd->resp[1] = cmd.response[1];
req->cmd->resp[0] = cmd.response[0];
if (req->stop)
{
stop.cmdidx = req->stop->cmd_code;
stop.cmdarg = req->stop->arg;
cmd.resptype = resp_type(req->stop);
req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL);
}
mmcsd_req_complete(host);
}
rt_int32_t mmc_card_status(struct rt_mmcsd_host *host)
{
return 0;
}
static rt_err_t sdhci_detect(struct sdhci_t *sdhci)
{
return RT_EOK;
}
static rt_err_t sdhci_setwidth(struct sdhci_t *sdhci, rt_uint32_t width)
{
rt_uint32_t temp = 0;
struct sdhci_pdata_t *pdat = (struct sdhci_pdata_t *)sdhci->priv;
if (width == MMCSD_BUS_WIDTH_4)
{
temp = read32((pdat->virt + EMMC_CONTROL0));
temp |= C0_HCTL_HS_EN;
temp |= C0_HCTL_DWITDH; // always use 4 data lines:
write32((pdat->virt + EMMC_CONTROL0), temp);
}
return RT_EOK;
}
static uint32_t sd_get_clock_divider(rt_uint32_t sdHostVer, rt_uint32_t base_clock, rt_uint32_t target_rate)
{
rt_uint32_t targetted_divisor = 0;
rt_uint32_t freq_select = 0;
rt_uint32_t upper_bits = 0;
rt_uint32_t ret = 0;
int divisor = -1;
if (target_rate > base_clock)
{
targetted_divisor = 1;
}
else
{
targetted_divisor = base_clock / target_rate;
rt_uint32_t mod = base_clock % target_rate;
if (mod)
{
targetted_divisor--;
}
}
// Decide on the clock mode to use
// Currently only 10-bit divided clock mode is supported
// HCI version 3 or greater supports 10-bit divided clock mode
// This requires a power-of-two divider
// Find the first bit set
for (int first_bit = 31; first_bit >= 0; first_bit--)
{
rt_uint32_t bit_test = (1 << first_bit);
if (targetted_divisor & bit_test)
{
divisor = first_bit;
targetted_divisor &= ~bit_test;
if (targetted_divisor)
{
// The divisor is not a power-of-two, increase it
divisor++;
}
break;
}
}
if (divisor == -1)
{
divisor = 31;
}
if (divisor >= 32)
{
divisor = 31;
}
if (divisor != 0)
{
divisor = (1 << (divisor - 1));
}
if (divisor >= 0x400)
{
divisor = 0x3ff;
}
freq_select = divisor & 0xff;
upper_bits = (divisor >> 8) & 0x3;
ret = (freq_select << 8) | (upper_bits << 6) | (0 << 5);
return ret;
}
static rt_err_t sdhci_setclock(struct sdhci_t *sdhci, rt_uint32_t clock)
{
rt_uint32_t temp = 0;
rt_uint32_t sdHostVer = 0;
int count = 100000;
struct sdhci_pdata_t *pdat = (struct sdhci_pdata_t *)(sdhci->priv);
while ((read32(pdat->virt + EMMC_STATUS) & (SR_CMD_INHIBIT | SR_DAT_INHIBIT)) && (--count))
{
DELAY_MICROS(1);
}
if (count <= 0)
{
rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n", read32(pdat->virt + EMMC_STATUS));
return RT_ERROR;
}
// Switch clock off.
temp = read32((pdat->virt + EMMC_CONTROL1));
temp &= ~C1_CLK_EN;
write32((pdat->virt + EMMC_CONTROL1), temp);
DELAY_MICROS(10);
// Request the new clock setting and enable the clock
temp = read32(pdat->virt + EMMC_SLOTISR_VER);
sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT;
int cdiv = sd_get_clock_divider(sdHostVer, mmc_base_clock, clock);
temp = read32((pdat->virt + EMMC_CONTROL1));
temp |= 1;
temp |= cdiv;
temp |= (7 << 16);
temp = (temp & 0xffff003f) | cdiv;
write32((pdat->virt + EMMC_CONTROL1), temp);
DELAY_MICROS(10);
// Enable the clock.
temp = read32(pdat->virt + EMMC_CONTROL1);
temp |= C1_CLK_EN;
write32((pdat->virt + EMMC_CONTROL1), temp);
DELAY_MICROS(10);
// wait for clock to be stable.
count = 10000;
while (!(read32(pdat->virt + EMMC_CONTROL1) & C1_CLK_STABLE) && count--)
{
DELAY_MICROS(10);
}
if (count <= 0)
{
rt_kprintf("EMMC: ERROR: failed to get stable clock %d.\n", clock);
return RT_ERROR;
}
mmcsd_dbg("set stable clock %d.\n", clock);
return RT_EOK;
}
static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg)
{
struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data;
sdhci_setclock(sdhci, io_cfg->clock);
sdhci_setwidth(sdhci, io_cfg->bus_width);
}
static const struct rt_mmcsd_host_ops ops =
{
mmc_request_send,
mmc_set_iocfg,
RT_NULL,
RT_NULL,
};
static rt_err_t reset_emmc(struct sdhci_pdata_t *pdat)
{
rt_uint32_t control1;
int cnt = 10000;
/* reset the controller */
control1 = read32((pdat->virt + EMMC_CONTROL1));
control1 |= (1 << 24);
/* disable clock */
control1 &= ~(1 << 2);
control1 &= ~(1 << 0);
/* temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX; */
write32((pdat->virt + EMMC_CONTROL1), control1);
do
{
DELAY_MICROS(10);
--cnt;
if (cnt == 0)
{
break;
}
}
while ((read32(pdat->virt + EMMC_CONTROL1) & (0x7 << 24)) != 0);
// Enable SD Bus Power VDD1 at 3.3V
rt_uint32_t control0 = read32(pdat->virt + EMMC_CONTROL0);
control0 |= 0x0F << 8;
write32(pdat->virt + EMMC_CONTROL0, control0);
rt_thread_delay(100);
/* check for a valid card */
mmcsd_dbg("EMMC: checking for an inserted card\n");
cnt = 10000;
do
{
DELAY_MICROS(10);
--cnt;
if (cnt == 0)
{
break;
}
}
while ((read32(pdat->virt + EMMC_STATUS) & (0x1 << 16)) == 0);
rt_uint32_t status_reg = read32(pdat->virt + EMMC_STATUS);
if ((status_reg & (1 << 16)) == 0)
{
rt_kprintf("EMMC: no card inserted\n");
return -1;
}
else
{
mmcsd_dbg("EMMC: status: %08x\n", status_reg);
}
/* clear control2 */
write32(pdat->virt + EMMC_CONTROL2, 0);
/* get the base clock rate */
mmc_base_clock = bcm271x_mbox_clock_get_rate(EMMC_CLK_ID);
if (mmc_base_clock == 0)
{
rt_kprintf("EMMC: assuming clock rate to be 100MHz\n");
mmc_base_clock = 100000000;
}
mmcsd_dbg("EMMC: setting clock rate is %d\n", mmc_base_clock);
return RT_EOK;
}
#ifdef RT_MMCSD_DBG
void dump_registers(struct sdhci_pdata_t *pdat)
{
int i = EMMC_ARG2;
rt_kprintf("EMMC registers:");
for (; i <= EMMC_CONTROL2; i += 4)
{
rt_kprintf("\t%x:%x\n", i, read32(pdat->virt + i));
}
rt_kprintf("\t%x:%x\n", 0x50, read32(pdat->virt + 0x50));
rt_kprintf("\t%x:%x\n", 0x70, read32(pdat->virt + 0x70));
rt_kprintf("\t%x:%x\n", 0x74, read32(pdat->virt + 0x74));
rt_kprintf("\t%x:%x\n", 0x80, read32(pdat->virt + 0x80));
rt_kprintf("\t%x:%x\n", 0x84, read32(pdat->virt + 0x84));
rt_kprintf("\t%x:%x\n", 0x88, read32(pdat->virt + 0x88));
rt_kprintf("\t%x:%x\n", 0x8c, read32(pdat->virt + 0x8c));
rt_kprintf("\t%x:%x\n", 0x90, read32(pdat->virt + 0x90));
rt_kprintf("\t%x:%x\n", 0xf0, read32(pdat->virt + 0xf0));
rt_kprintf("\t%x:%x\n", 0xfc, read32(pdat->virt + 0xfc));
}
#endif
int raspi_sdmmc_init(void)
{
size_t virt;
struct rt_mmcsd_host *host = RT_NULL;
struct sdhci_pdata_t *pdat = RT_NULL;
struct sdhci_t *sdhci = RT_NULL;
#ifdef BSP_USING_SDIO0
host = mmcsd_alloc_host();
if (!host)
{
rt_kprintf("alloc host failed");
goto err;
}
sdhci = rt_malloc(sizeof(struct sdhci_t));
if (!sdhci)
{
rt_kprintf("alloc sdhci failed");
goto err;
}
rt_memset(sdhci, 0, sizeof(struct sdhci_t));
virt = MMC2_BASE_ADDR;
pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t));
RT_ASSERT(pdat != RT_NULL);
pdat->virt = virt;
reset_emmc(pdat);
sdhci->name = "sd0";
sdhci->voltages = VDD_33_34;
sdhci->width = MMCSD_BUSWIDTH_4;
sdhci->clock = 1000 * 1000 * 1000;
sdhci->removeable = RT_TRUE;
sdhci->detect = sdhci_detect;
sdhci->setwidth = sdhci_setwidth;
sdhci->setclock = sdhci_setclock;
sdhci->transfer = sdhci_transfer;
sdhci->priv = pdat;
host->ops = &ops;
host->freq_min = 400000;
host->freq_max = 50000000;
host->valid_ocr = VDD_32_33 | VDD_33_34;
host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4;
host->max_seg_size = 2048;
host->max_dma_segs = 10;
host->max_blk_size = 512;
host->max_blk_count = 1;
host->private_data = sdhci;
write32((pdat->virt + EMMC_IRPT_EN), 0xffffffff);
write32((pdat->virt + EMMC_IRPT_MASK), 0xffffffff);
#ifdef RT_MMCSD_DBG
dump_registers(pdat);
#endif
mmcsd_change(host);
#endif
return RT_EOK;
err:
if (host) rt_free(host);
if (sdhci) rt_free(sdhci);
return -RT_EIO;
}
INIT_DEVICE_EXPORT(raspi_sdmmc_init);

View File

@ -0,0 +1,268 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-10-27 bigmagic first version
*/
#ifndef __DRV_SDIO_H__
#define __DRV_SDIO_H__
#include <rtthread.h>
#include <rtdevice.h>
#include <drivers/mmcsd_core.h>
#include "board.h"
#include "raspi4.h"
/* Struct for Intrrrupt Information */
#define SDXC_CmdDone BIT(0)
#define SDXC_DataDone BIT(1)
#define SDXC_BlockGap BIT(2)
#define SDXC_WriteRdy BIT(4)
#define SDXC_ReadRdy BIT(5)
#define SDXC_Card BIT(8)
#define SDXC_Retune BIT(12)
#define SDXC_BootAck BIT(13)
#define SDXC_EndBoot BIT(14)
#define SDXC_Err BIT(15)
#define SDXC_CTOErr BIT(16)
#define SDXC_CCRCErr BIT(17)
#define SDXC_CENDErr BIT(18)
#define SDXC_CBADErr BIT(19)
#define SDXC_DTOErr BIT(20)
#define SDXC_DCRCErr BIT(21)
#define SDXC_DENDErr BIT(22)
#define SDXC_ACMDErr BIT(24)
#define SDXC_BLKCNT_EN BIT(1)
#define SDXC_AUTO_CMD12_EN BIT(2)
#define SDXC_AUTO_CMD23_EN BIT(3)
#define SDXC_DAT_DIR BIT(4) // from card to host
#define SDXC_MULTI_BLOCK BIT(5)
#define SDXC_CMD_RSPNS_136 BIT(16)
#define SDXC_CMD_RSPNS_48 BIT(17)
#define SDXC_CMD_RSPNS_48busy BIT(16)|BIT(17)
#define SDXC_CHECK_CRC_CMD BIT(19)
#define SDXC_CMD_IXCHK_EN BIT(20)
#define SDXC_CMD_ISDATA BIT(21)
#define SDXC_CMD_SUSPEND BIT(22)
#define SDXC_CMD_RESUME BIT(23)
#define SDXC_CMD_ABORT BIT(23)|BIT(22)
#define SDXC_CMD_INHIBIT BIT(0)
#define SDXC_DAT_INHIBIT BIT(1)
#define SDXC_DAT_ACTIVE BIT(2)
#define SDXC_WRITE_TRANSFER BIT(8)
#define SDXC_READ_TRANSFER BIT(9)
struct sdhci_cmd_t
{
rt_uint32_t cmdidx;
rt_uint32_t cmdarg;
rt_uint32_t resptype;
rt_uint32_t datarw;
#define DATA_READ 1
#define DATA_WRITE 2
rt_uint32_t response[4];
};
struct sdhci_data_t
{
rt_uint8_t *buf;
rt_uint32_t flag;
rt_uint32_t blksz;
rt_uint32_t blkcnt;
};
struct sdhci_t
{
char *name;
rt_uint32_t voltages;
rt_uint32_t width;
rt_uint32_t clock;
rt_err_t removeable;
void *sdcard;
rt_err_t (*detect)(struct sdhci_t *sdhci);
rt_err_t (*setwidth)(struct sdhci_t *sdhci, rt_uint32_t width);
rt_err_t (*setclock)(struct sdhci_t *sdhci, rt_uint32_t clock);
rt_err_t (*transfer)(struct sdhci_t *sdhci, struct sdhci_cmd_t *cmd, struct sdhci_data_t *dat);
void *priv;
};
struct sdhci_pdata_t
{
size_t virt;
};
// EMMC command flags
#define CMD_TYPE_NORMAL (0x00000000)
#define CMD_TYPE_SUSPEND (0x00400000)
#define CMD_TYPE_RESUME (0x00800000)
#define CMD_TYPE_ABORT (0x00c00000)
#define CMD_IS_DATA (0x00200000)
#define CMD_IXCHK_EN (0x00100000)
#define CMD_CRCCHK_EN (0x00080000)
#define CMD_RSPNS_NO (0x00000000)
#define CMD_RSPNS_136 (0x00010000)
#define CMD_RSPNS_48 (0x00020000)
#define CMD_RSPNS_48B (0x00030000)
#define TM_MULTI_BLOCK (0x00000020)
#define TM_DAT_DIR_HC (0x00000000)
#define TM_DAT_DIR_CH (0x00000010)
#define TM_AUTO_CMD23 (0x00000008)
#define TM_AUTO_CMD12 (0x00000004)
#define TM_BLKCNT_EN (0x00000002)
#define TM_MULTI_DATA (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN)
#define RCA_NO (1)
#define RCA_YES (2)
// INTERRUPT register settings
#define INT_AUTO_ERROR (0x01000000)
#define INT_DATA_END_ERR (0x00400000)
#define INT_DATA_CRC_ERR (0x00200000)
#define INT_DATA_TIMEOUT (0x00100000)
#define INT_INDEX_ERROR (0x00080000)
#define INT_END_ERROR (0x00040000)
#define INT_CRC_ERROR (0x00020000)
#define INT_CMD_TIMEOUT (0x00010000)
#define INT_ERR (0x00008000)
#define INT_ENDBOOT (0x00004000)
#define INT_BOOTACK (0x00002000)
#define INT_RETUNE (0x00001000)
#define INT_CARD (0x00000100)
#define INT_READ_RDY (0x00000020)
#define INT_WRITE_RDY (0x00000010)
#define INT_BLOCK_GAP (0x00000004)
#define INT_DATA_DONE (0x00000002)
#define INT_CMD_DONE (0x00000001)
#define INT_ERROR_MASK \
( \
INT_CRC_ERROR | \
INT_END_ERROR | \
INT_INDEX_ERROR | \
INT_DATA_TIMEOUT | \
INT_DATA_CRC_ERR | \
INT_DATA_END_ERR | \
INT_ERR|INT_AUTO_ERROR \
)
#define INT_ALL_MASK \
(\
INT_CMD_DONE | \
INT_DATA_DONE | \
INT_READ_RDY | \
INT_WRITE_RDY | \
INT_ERROR_MASK \
)
#define EMMC_ARG2 (0x00)
#define EMMC_BLKSIZECNT (0x04)
#define EMMC_ARG1 (0x08)
#define EMMC_CMDTM (0x0c)
#define EMMC_RESP0 (0x10)
#define EMMC_RESP1 (0x14)
#define EMMC_RESP2 (0x18)
#define EMMC_RESP3 (0x1c)
#define EMMC_DATA (0x20)
#define EMMC_STATUS (0x24)
#define EMMC_CONTROL0 (0x28)
#define EMMC_CONTROL1 (0x2c)
#define EMMC_INTERRUPT (0x30)
#define EMMC_IRPT_MASK (0x34)
#define EMMC_IRPT_EN (0x38)
#define EMMC_CONTROL2 (0x3c)
#define EMMC_CAPABILITIES_0 (0x40)
#define EMMC_CAPABILITIES_1 (0x44)
#define EMMC_BOOT_TIMEOUT (0x70)
#define EMMC_EXRDFIFO_EN (0x84)
#define EMMC_SPI_INT_SPT (0xf0)
#define EMMC_SLOTISR_VER (0xfc)
// CONTROL register settings
#define C0_SPI_MODE_EN (0x00100000)
#define C0_HCTL_HS_EN (0x00000004)
#define C0_HCTL_DWITDH (0x00000002)
#define C1_SRST_DATA (0x04000000)
#define C1_SRST_CMD (0x02000000)
#define C1_SRST_HC (0x01000000)
#define C1_TOUNIT_DIS (0x000f0000)
#define C1_TOUNIT_MAX (0x000e0000)
#define C1_CLK_GENSEL (0x00000020)
#define C1_CLK_EN (0x00000004)
#define C1_CLK_STABLE (0x00000002)
#define C1_CLK_INTLEN (0x00000001)
#define FREQ_SETUP (400000) // 400 Khz
#define FREQ_NORMAL (25000000) // 25 Mhz
// SLOTISR_VER values
#define HOST_SPEC_NUM 0x00ff0000
#define HOST_SPEC_NUM_SHIFT 16
#define HOST_SPEC_V3 2
#define HOST_SPEC_V2 1
#define HOST_SPEC_V1 0
// STATUS register settings
#define SR_DAT_LEVEL1 (0x1e000000)
#define SR_CMD_LEVEL (0x01000000)
#define SR_DAT_LEVEL0 (0x00f00000)
#define SR_DAT3 (0x00800000)
#define SR_DAT2 (0x00400000)
#define SR_DAT1 (0x00200000)
#define SR_DAT0 (0x00100000)
#define SR_WRITE_PROT (0x00080000) // From SDHC spec v2, BCM says reserved
#define SR_READ_AVAILABLE (0x00000800) // ???? undocumented
#define SR_WRITE_AVAILABLE (0x00000400) // ???? undocumented
#define SR_READ_TRANSFER (0x00000200)
#define SR_WRITE_TRANSFER (0x00000100)
#define SR_DAT_ACTIVE (0x00000004)
#define SR_DAT_INHIBIT (0x00000002)
#define SR_CMD_INHIBIT (0x00000001)
#define CONFIG_MMC_USE_DMA
#define DMA_ALIGN (32U)
#define SD_CMD_INDEX(a) ((a) << 24)
#define SD_CMD_RESERVED(a) (0xffffffff)
#define SD_CMD_INDEX(a) ((a) << 24)
#define SD_CMD_TYPE_NORMAL (0x0)
#define SD_CMD_TYPE_SUSPEND (1 << 22)
#define SD_CMD_TYPE_RESUME (2 << 22)
#define SD_CMD_TYPE_ABORT (3 << 22)
#define SD_CMD_TYPE_MASK (3 << 22)
#define SD_CMD_ISDATA (1 << 21)
#define SD_CMD_IXCHK_EN (1 << 20)
#define SD_CMD_CRCCHK_EN (1 << 19)
#define SD_CMD_RSPNS_TYPE_NONE (0) // For no response
#define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC)
#define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC)
#define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC)
#define SD_CMD_RSPNS_TYPE_MASK (3 << 16)
#define SD_CMD_MULTI_BLOCK (1 << 5)
#define SD_CMD_DAT_DIR_HC (0)
#define SD_CMD_DAT_DIR_CH (1 << 4)
#define SD_CMD_AUTO_CMD_EN_NONE (0)
#define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2)
#define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2)
#define SD_CMD_BLKCNT_EN (1 << 1)
#define SD_CMD_DMA (1)
#define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE
#define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48)
#define SD_RESP_R1b (SD_CMD_RSPNS_TYPE_48B)
#define SD_RESP_R2 (SD_CMD_RSPNS_TYPE_136)
#define SD_RESP_R3 SD_CMD_RSPNS_TYPE_48
#define SD_RESP_R4 SD_CMD_RSPNS_TYPE_136
#define SD_RESP_R5 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
#define SD_RESP_R5b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN)
#define SD_RESP_R6 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
#define SD_RESP_R7 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN)
#define SD_DATA_READ (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH)
#define SD_DATA_WRITE (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC)
#endif

View File

@ -22,6 +22,26 @@ struct hw_uart_device
rt_uint32_t irqno;
};
#ifdef RT_USING_UART0
static struct rt_serial_device _serial0;
#endif
#ifdef RT_USING_UART1
static struct rt_serial_device _serial1;
#endif
#ifdef RT_USING_UART3
static struct rt_serial_device _serial3;
#endif
#ifdef RT_USING_UART4
static struct rt_serial_device _serial4;
#endif
#ifdef RT_USING_UART5
static struct rt_serial_device _serial5;
#endif
static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
struct hw_uart_device *uart;
@ -30,26 +50,54 @@ static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_co
RT_ASSERT(serial != RT_NULL);
uart = (struct hw_uart_device *)serial->parent.user_data;
if(uart->hw_base == PL011_BASE)
if(uart->hw_base == AUX_BASE)
{
uint32_t gpfsel = 0;
prev_raspi_pin_mode(GPIO_PIN_14, ALT5);
prev_raspi_pin_mode(GPIO_PIN_15, ALT5);
gpfsel &= ~((uint32_t)(0x07 << (4 * 3)));
gpfsel |= (uint32_t)(ALT0 << (4 * 3));
GPIO_REG_GPFSEL1(GPIO_BASE) = gpfsel;
gpfsel &= ~((uint32_t)(0x07 << (5 * 3)));
gpfsel |= (uint32_t)(ALT0 << (5 * 3));
GPIO_REG_GPFSEL1(GPIO_BASE) = gpfsel;
PL011_REG_CR(uart->hw_base) = 0;/*Clear UART setting*/
PL011_REG_LCRH(uart->hw_base) = 0;/*disable FIFO*/
PL011_REG_IBRD(uart->hw_base) = ibrd;
PL011_REG_FBRD(uart->hw_base) = (((bauddiv - ibrd * 1000) * 64 + 500) / 1000);
PL011_REG_LCRH(uart->hw_base) = PL011_LCRH_WLEN_8;/*FIFO*/
PL011_REG_CR(uart->hw_base) = PL011_CR_UARTEN | PL011_CR_TXE | PL011_CR_RXE;/*art enable, TX/RX enable*/
AUX_ENABLES(uart->hw_base) = 1; /* Enable UART1 */
AUX_MU_IER_REG(uart->hw_base) = 0; /* Disable interrupt */
AUX_MU_CNTL_REG(uart->hw_base) = 0; /* Disable Transmitter and Receiver */
AUX_MU_LCR_REG(uart->hw_base) = 3; /* Works in 8-bit mode */
AUX_MU_MCR_REG(uart->hw_base) = 0; /* Disable RTS */
AUX_MU_IIR_REG(uart->hw_base) = 0xC6; /* Enable FIFO, Clear FIFO */
AUX_MU_BAUD_REG(uart->hw_base) = 270; /* 115200 = system clock 250MHz / (8 * (baud + 1)), baud = 270 */
AUX_MU_CNTL_REG(uart->hw_base) = 3; /* Enable Transmitter and Receiver */
return RT_EOK;
}
if(uart->hw_base == UART0_BASE)
{
prev_raspi_pin_mode(GPIO_PIN_14, ALT0);
prev_raspi_pin_mode(GPIO_PIN_15, ALT0);
}
if(uart->hw_base == UART3_BASE)
{
prev_raspi_pin_mode(GPIO_PIN_4, ALT4);
prev_raspi_pin_mode(GPIO_PIN_5, ALT4);
}
if(uart->hw_base == UART4_BASE)
{
prev_raspi_pin_mode(GPIO_PIN_8, ALT4);
prev_raspi_pin_mode(GPIO_PIN_9, ALT4);
}
if(uart->hw_base == UART5_BASE)
{
prev_raspi_pin_mode(GPIO_PIN_12, ALT4);
prev_raspi_pin_mode(GPIO_PIN_13, ALT4);
}
PL011_REG_CR(uart->hw_base) = 0;/*Clear UART setting*/
PL011_REG_LCRH(uart->hw_base) = 0;/*disable FIFO*/
PL011_REG_IBRD(uart->hw_base) = ibrd;
PL011_REG_FBRD(uart->hw_base) = (((bauddiv - ibrd * 1000) * 64 + 500) / 1000);
PL011_REG_LCRH(uart->hw_base) = PL011_LCRH_WLEN_8;/*FIFO*/
PL011_REG_CR(uart->hw_base) = PL011_CR_UARTEN | PL011_CR_TXE | PL011_CR_RXE;/*art enable, TX/RX enable*/
return RT_EOK;
}
@ -70,7 +118,14 @@ static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg
case RT_DEVICE_CTRL_SET_INT:
/* enable rx irq */
PL011_REG_IMSC(uart->hw_base) |= PL011_IMSC_RXIM;
if(uart->hw_base == AUX_BASE)
{
AUX_MU_IER_REG(uart->hw_base) = 0x1;
}
else
{
PL011_REG_IMSC(uart->hw_base) |= PL011_IMSC_RXIM;
}
rt_hw_interrupt_umask(uart->irqno);
break;
}
@ -85,8 +140,16 @@ static int uart_putc(struct rt_serial_device *serial, char c)
RT_ASSERT(serial != RT_NULL);
uart = (struct hw_uart_device *)serial->parent.user_data;
while ((PL011_REG_FR(uart->hw_base) & PL011_FR_TXFF));
PL011_REG_DR(uart->hw_base) = (uint8_t)c;
if(uart->hw_base == AUX_BASE)
{
while (!(AUX_MU_LSR_REG(uart->hw_base) & 0x20));
AUX_MU_IO_REG(uart->hw_base) = c;
}
else
{
while ((PL011_REG_FR(uart->hw_base) & PL011_FR_TXFF));
PL011_REG_DR(uart->hw_base) = (uint8_t)c;
}
return 1;
}
@ -99,9 +162,19 @@ static int uart_getc(struct rt_serial_device *serial)
RT_ASSERT(serial != RT_NULL);
uart = (struct hw_uart_device *)serial->parent.user_data;
if((PL011_REG_FR(uart->hw_base) & PL011_FR_RXFE) == 0)
if(uart->hw_base == AUX_BASE)
{
ch = PL011_REG_DR(uart->hw_base) & 0xff;
if ((AUX_MU_LSR_REG(uart->hw_base) & 0x01))
{
ch = AUX_MU_IO_REG(uart->hw_base) & 0xff;
}
}
else
{
if((PL011_REG_FR(uart->hw_base) & PL011_FR_RXFE) == 0)
{
ch = PL011_REG_DR(uart->hw_base) & 0xff;
}
}
return ch;
@ -115,38 +188,180 @@ static const struct rt_uart_ops _uart_ops =
uart_getc,
};
static void rt_hw_uart_isr(int irqno, void *param)
#ifdef RT_USING_UART1
static void rt_hw_aux_uart_isr(int irqno, void *param)
{
struct rt_serial_device *serial = (struct rt_serial_device*)param;
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
PL011_REG_ICR(UART0_BASE) = PL011_INTERRUPT_RECEIVE;
}
#endif
static void rt_hw_uart_isr(int irqno, void *param)
{
#ifdef RT_USING_UART0
if((PACTL_CS & IRQ_UART0) == IRQ_UART0)
{
PACTL_CS &= ~(IRQ_UART0);
rt_hw_serial_isr(&_serial0, RT_SERIAL_EVENT_RX_IND);
PL011_REG_ICR(UART0_BASE) = PL011_INTERRUPT_RECEIVE;
}
#endif
#ifdef RT_USING_UART3
if((PACTL_CS & IRQ_UART3) == IRQ_UART3)
{
PACTL_CS &= ~(IRQ_UART3);
rt_hw_serial_isr(&_serial3, RT_SERIAL_EVENT_RX_IND);
PL011_REG_ICR(uart3_addr) = PL011_INTERRUPT_RECEIVE;
}
#endif
#ifdef RT_USING_UART4
if((PACTL_CS & IRQ_UART4) == IRQ_UART4)
{
PACTL_CS &= ~(IRQ_UART4);
rt_hw_serial_isr(&_serial4, RT_SERIAL_EVENT_RX_IND);
PL011_REG_ICR(uart4_addr) = PL011_INTERRUPT_RECEIVE;
}
#endif
#ifdef RT_USING_UART5
if((PACTL_CS & IRQ_UART5) == IRQ_UART5)
{
PACTL_CS &= ~(IRQ_UART5);
rt_hw_serial_isr(&_serial5, RT_SERIAL_EVENT_RX_IND);
PL011_REG_ICR(uart5_addr) = PL011_INTERRUPT_RECEIVE;
}
#endif
}
#ifdef RT_USING_UART0
/* UART device driver structure */
static struct hw_uart_device _uart0_device =
{
PL011_BASE,
UART0_BASE,
IRQ_PL011,
};
#endif
#ifdef RT_USING_UART1
/* UART device driver structure */
static struct hw_uart_device _uart1_device =
{
AUX_BASE,
IRQ_AUX_UART,
};
#endif
#ifdef RT_USING_UART3
static struct hw_uart_device _uart3_device =
{
UART3_BASE,
IRQ_PL011,
};
#endif
#ifdef RT_USING_UART4
static struct hw_uart_device _uart4_device =
{
UART4_BASE,
IRQ_PL011,
};
#endif
#ifdef RT_USING_UART5
static struct hw_uart_device _uart5_device =
{
UART5_BASE,
IRQ_PL011,
};
#endif
static struct rt_serial_device _serial0;
int rt_hw_uart_init(void)
{
struct hw_uart_device *uart;
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
uart = &_uart0_device;
#ifdef RT_USING_UART0
struct hw_uart_device *uart0;
uart0 = &_uart0_device;
_serial0.ops = &_uart_ops;
_serial0.config = config;
/* register UART1 device */
rt_hw_serial_register(&_serial0, "uart",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart);
rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial0, "uart");
uart0->hw_base = UART0_BASE;
/* register UART0 device */
rt_hw_serial_register(&_serial0, "uart0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart0);
rt_hw_interrupt_install(uart0->irqno, rt_hw_uart_isr, &_serial0, "uart0");
#endif
#ifdef RT_USING_UART1
struct hw_uart_device *uart1;
uart1 = &_uart1_device;
_serial1.ops = &_uart_ops;
_serial1.config = config;
uart1->hw_base = AUX_BASE;
/* register UART1 device */
rt_hw_serial_register(&_serial1, "uart1",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart1);
rt_hw_interrupt_install(uart1->irqno, rt_hw_aux_uart_isr, &_serial1, "uart1");
#endif
#ifdef RT_USING_UART3
struct hw_uart_device *uart3;
uart3 = &_uart3_device;
_serial3.ops = &_uart_ops;
_serial3.config = config;
uart3_addr = UART3_BASE;
/* register UART3 device */
rt_hw_serial_register(&_serial3, "uart3",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart3);
rt_hw_interrupt_install(uart3->irqno, rt_hw_uart_isr, &_serial3, "uart3");
#endif
#ifdef RT_USING_UART4
struct hw_uart_device *uart4;
uart4 = &_uart4_device;
_serial4.ops = &_uart_ops;
_serial4.config = config;
uart4_addr = UART4_BASE;
/* register UART4 device */
rt_hw_serial_register(&_serial4, "uart4",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart4);
rt_hw_interrupt_install(uart4->irqno, rt_hw_uart_isr, &_serial4, "uart4");
#endif
#ifdef RT_USING_UART5
struct hw_uart_device *uart5;
uart5 = &_uart5_device;
_serial5.ops = &_uart_ops;
_serial5.config = config;
uart5_addr = UART5_BASE;
/* register UART5 device */
rt_hw_serial_register(&_serial5, "uart5",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
uart5);
rt_hw_interrupt_install(uart5->irqno, rt_hw_uart_isr, &_serial5, "uart5");
#endif
return 0;
}

View File

@ -78,6 +78,30 @@
#define PL011_REG_ITOP(BASE) HWREG32(BASE + 0x88)
#define PL011_REG_TDR(BASE) HWREG32(BASE + 0x8C)
/*
* Auxiliary
*/
#define AUX_IRQ(BASE) HWREG32(BASE + 0x00) /* Auxiliary Interrupt status 3 */
#define AUX_ENABLES(BASE) HWREG32(BASE + 0x04) /* Auxiliary enables 3bit */
#define AUX_MU_IO_REG(BASE) HWREG32(BASE + 0x40) /* Mini Uart I/O Data 8bit */
#define AUX_MU_IER_REG(BASE) HWREG32(BASE + 0x44) /* Mini Uart Interrupt Enable 8bit */
#define AUX_MU_IIR_REG(BASE) HWREG32(BASE + 0x48) /* Mini Uart Interrupt Identify 8bit */
#define AUX_MU_LCR_REG(BASE) HWREG32(BASE + 0x4C) /* Mini Uart Line Control 8bit */
#define AUX_MU_MCR_REG(BASE) HWREG32(BASE + 0x50) /* Mini Uart Modem Control 8bit */
#define AUX_MU_LSR_REG(BASE) HWREG32(BASE + 0x54) /* Mini Uart Line Status 8bit */
#define AUX_MU_MSR_REG(BASE) HWREG32(BASE + 0x58) /* Mini Uart Modem Status 8bit */
#define AUX_MU_SCRATCH(BASE) HWREG32(BASE + 0x5C) /* Mini Uart Scratch 8bit */
#define AUX_MU_CNTL_REG(BASE) HWREG32(BASE + 0x60) /* Mini Uart Extra Control 8bit */
#define AUX_MU_STAT_REG(BASE) HWREG32(BASE + 0x64) /* Mini Uart Extra Status 32bit */
#define AUX_MU_BAUD_REG(BASE) HWREG32(BASE + 0x68) /* Mini Uart Baudrate 16bit */
#define AUX_SPI0_CNTL0_REG(BASE) HWREG32(BASE + 0x80) /* SPI 1 Control register 0 32bit */
#define AUX_SPI0_CNTL1_REG(BASE) HWREG32(BASE + 0x84) /* SPI 1 Control register 1 8bit */
#define AUX_SPI0_STAT_REG(BASE) HWREG32(BASE + 0x88) /* SPI 1 Status 32bit */
#define AUX_SPI0_IO_REG(BASE) HWREG32(BASE + 0x90) /* SPI 1 Data 32bit */
#define AUX_SPI0_PEEK_REG(BASE) HWREG32(BASE + 0x94) /* SPI 1 Peek 16bit */
#define AUX_SPI1_CNTL0_REG(BASE) HWREG32(BASE + 0xC0) /* SPI 2 Control register 0 32bit */
#define AUX_SPI1_CNTL1_REG(BASE) HWREG32(BASE + 0xC4) /* SPI 2 Control register 1 8bit */
int rt_hw_uart_init(void);
#endif /* DRV_UART_H__ */

View File

@ -0,0 +1,519 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-08-29 zdzn first version
* 2020-09-10 bigmagic add other mbox option
*/
/* mailbox message buffer */
#include "mbox.h"
#include "mmu.h"
volatile unsigned int *mbox = (volatile unsigned int *) MBOX_ADDR;
#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000)
/**
* Make a mailbox call. Returns 0 on failure, non-zero on success
*/
int mbox_call(unsigned char ch, int mmu_enable)
{
unsigned int r = (((MBOX_ADDR) & ~0xF) | (ch & 0xF));
if (mmu_enable)
{
r = BUS_ADDRESS(r);
}
/* wait until we can write to the mailbox */
do
{
__asm__ volatile ("nop");
}
while (*MBOX_STATUS & MBOX_FULL);
/* write the address of our message to the mailbox with channel identifier */
*MBOX_WRITE = r;
/* now wait for the response */
while (1)
{
/* is there a response? */
do
{
__asm__ volatile ("nop");
}
while (*MBOX_STATUS & MBOX_EMPTY);
/* is it a response to our message? */
if (r == *MBOX_READ)
{
/* is it a valid successful response? */
return mbox[1] == MBOX_RESPONSE;
}
}
return 0;
}
int bcm271x_mbox_get_touch(void)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_GET_TOUCHBUF;
mbox[3] = 4; // buffer size
mbox[4] = 0; // len
mbox[5] = 0; // id
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
return (int)(mbox[5] & ~0xC0000000);
}
int bcm271x_notify_reboot(void)
{
mbox[0] = 7 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_NOTIFY_REBOOT; // (the tag id)
mbox[3] = 0x00000004; // length + 4
mbox[4] = 0x00000000; // size of the data
mbox[5] = 0x00000000; // request
mbox[6] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
return 0;
}
int bcm271x_notify_xhci_reset(void)
{
mbox[0] = 7 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_NOTIFY_XHCI_RESET; // (the tag id)
mbox[3] = 0x00000004; // length + 4
mbox[4] = 0x00000004; // size of the data
mbox[5] = 0x00100000; // request
mbox[6] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
return 0;
}
int bcm271x_gpu_enable(void)
{
mbox[0] = 12 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_SET_RATE;
mbox[3] = 0x00000008; // (the tag id)
mbox[4] = 0x00000008; // (the tag id)
mbox[5] = 5; // V3D
mbox[6] = 250 * 1000 * 1000;
mbox[7] = MBOX_TAG_ENABLE_QPU; // (the tag id)
mbox[8] = 0x00000004; // (size of the buffer)
mbox[9] = 0x00000004; // (size of the data)
mbox[10] = 0x00000001;
mbox[11] = MBOX_TAG_LAST; // end tag
mbox_call(8, MMU_DISABLE);
return mbox[1];
}
int bcm271x_mbox_hardware_get_model(void)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_HARDWARE_GET_MODEL;
mbox[3] = 4; // buffer size
mbox[4] = 0; // len
mbox[5] = 0;
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
return mbox[5];
}
int bcm271x_mbox_hardware_get_revison(void)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_HARDWARE_GET_REV;
mbox[3] = 4; // buffer size
mbox[4] = 0; // len
mbox[5] = 0;
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
return mbox[5];
}
int bcm271x_mbox_hardware_get_mac_address(uint8_t *mac)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_HARDWARE_GET_MAC_ADDRESS;
mbox[3] = 6; // buffer size
mbox[4] = 0; // len
mbox[5] = 0;
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
char *mac_str = (char *)&mbox[5];
mac[0] = mac_str[0];
mac[1] = mac_str[1];
mac[2] = mac_str[2];
mac[3] = mac_str[3];
mac[4] = mac_str[4];
mac[5] = mac_str[5];
return 0;
}
int bcm271x_mbox_hardware_get_serial(rt_uint64_t *sn)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_HARDWARE_GET_SERIAL;
mbox[3] = 8; // buffer size
mbox[4] = 0; // len
mbox[5] = 0;
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
sn = (rt_uint64_t *)&mbox[5];
return 0;
}
int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t *base, rt_uint32_t *size)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_HARDWARE_GET_ARM_MEMORY;
mbox[3] = 8; // buffer size
mbox[4] = 0; // len
mbox[5] = 0;
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
*base = mbox[5];
*size = mbox[6];
return 0;
}
int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t *base, rt_uint32_t *size)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_HARDWARE_GET_VC_MEMORY;
mbox[3] = 8; // buffer size
mbox[4] = 0; // len
mbox[5] = 0;
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
*base = mbox[5];
*size = mbox[6];
return 0;
}
int bcm271x_mbox_clock_get_turbo(void)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_GET_TURBO;
mbox[3] = 8; // buffer size
mbox[4] = 4; // len
mbox[5] = 0; // id
mbox[6] = 0; // val
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != 0)
{
return -1;
}
return mbox[6];
}
int bcm271x_mbox_clock_set_turbo(int level)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_SET_TURBO;
mbox[3] = 8; // buffer size
mbox[4] = 8; // len
mbox[5] = 0; // id
mbox[6] = level ? 1 : 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != 0)
{
return -1;
}
return mbox[6];
}
int bcm271x_mbox_clock_get_state(int id)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_GET_STATE;
mbox[3] = 8; // buffer size
mbox[4] = 4; // len
mbox[5] = id; // id
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != id)
{
return -1;
}
return (mbox[6] & 0x3);
}
int bcm271x_mbox_clock_set_state(int id, int state)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_SET_STATE;
mbox[3] = 8; // buffer size
mbox[4] = 8; // len
mbox[5] = id; // id
mbox[6] = state & 0x3;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != id)
{
return -1;
}
return (mbox[6] & 0x3);
}
int bcm271x_mbox_clock_get_rate(int id)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_GET_RATE;
mbox[3] = 8; // buffer size
mbox[4] = 4; // len
mbox[5] = id; // id
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != id)
{
return -1;
}
return mbox[6];
}
int bcm271x_mbox_clock_set_rate(int id, int rate)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_SET_RATE;
mbox[3] = 8; // buffer size
mbox[4] = 8; // len
mbox[5] = id; // id
mbox[6] = rate;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != id)
{
return -1;
}
return mbox[6];
}
int bcm271x_mbox_clock_get_max_rate(int id)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_GET_MAX_RATE;
mbox[3] = 8; // buffer size
mbox[4] = 4; // len
mbox[5] = id; // id
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != id)
{
return -1;
}
return mbox[6];
}
int bcm271x_mbox_clock_get_min_rate(int id)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_CLOCK_GET_MIN_RATE;
mbox[3] = 8; // buffer size
mbox[4] = 4; // len
mbox[5] = id; // id
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != id)
{
return -1;
}
return mbox[6];
}
int bcm271x_mbox_power_get_state(int id)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_POWER_GET_STATE;
mbox[3] = 8; // buffer size
mbox[4] = 4; // len
mbox[5] = id; // id
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != id)
{
return -1;
}
return (mbox[6] & 0x3);
}
int bcm271x_mbox_power_set_state(int id, int state)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_POWER_SET_STATE;
mbox[3] = 8; // buffer size
mbox[4] = 8; // len
mbox[5] = id; // id
mbox[6] = state & 0x3;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != id)
{
return -1;
}
return (mbox[6] & 0x3);
}
int bcm271x_mbox_temp_get(void)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_TEMP_GET;
mbox[3] = 8; // buffer size
mbox[4] = 4; // len
mbox[5] = 0; //id
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != 0)
{
return -1;
}
return mbox[6];
}
int bcm271x_mbox_temp_get_max(void)
{
mbox[0] = 8 * 4; // length of the message
mbox[1] = MBOX_REQUEST; // this is a request message
mbox[2] = MBOX_TAG_TEMP_GET_MAX;
mbox[3] = 8; // buffer size
mbox[4] = 4; // len
mbox[5] = 0; // id
mbox[6] = 0;
mbox[7] = MBOX_TAG_LAST;
mbox_call(8, MMU_DISABLE);
if (mbox[5] != 0)
{
return -1;
}
return mbox[6];
}

View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-09-10 bigmagic first version
*/
#ifndef __MBOX_H__
#define __MBOX_H__
#include <rtthread.h>
#include <stdint.h>
// https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
// https://github.com/hermanhermitage/videocoreiv
/* a properly aligned buffer */
extern volatile unsigned int *mbox;
#define MBOX_REQUEST 0
/* channels */
#define MBOX_CH_POWER 0
#define MBOX_CH_FB 1
#define MBOX_CH_VUART 2
#define MBOX_CH_VCHIQ 3
#define MBOX_CH_LEDS 4
#define MBOX_CH_BTNS 5
#define MBOX_CH_TOUCH 6
#define MBOX_CH_COUNT 7
#define MBOX_CH_PROP 8
/* tags */
#define MBOX_TAG_SETPOWER 0x28001
#define MBOX_TAG_SETCLKRATE 0x38002
#define MBOX_GET_MAC_ADDRESS 0x10003
#define MBOX_TAG_LAST 0
#define MMIO_BASE 0xFE000000
#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880)
#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0))
#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10))
#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14))
#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18))
#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C))
#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20))
#define MBOX_RESPONSE 0x80000000
#define MBOX_FULL 0x80000000
#define MBOX_EMPTY 0x40000000
#define DEVICE_ID_SD_CARD (0)
#define DEVICE_ID_USB_HCD (3)
#define POWER_STATE_OFF (0 << 0)
#define POWER_STATE_ON (1 << 0)
#define POWER_STATE_WAIT (1 << 1)
#define POWER_STATE_NO_DEVICE (1 << 1) // in response
#define MMU_ENABLE (1)
#define MMU_DISABLE (0)
/*
* raspi hardware info
*/
enum
{
MBOX_TAG_HARDWARE_GET_MODEL = 0x00010001,
MBOX_TAG_HARDWARE_GET_REV = 0x00010002,
MBOX_TAG_HARDWARE_GET_MAC_ADDRESS = 0x00010003,
MBOX_TAG_HARDWARE_GET_SERIAL = 0x00010004,
MBOX_TAG_HARDWARE_GET_ARM_MEMORY = 0x00010005,
MBOX_TAG_HARDWARE_GET_VC_MEMORY = 0x00010006,
MBOX_TAG_HARDWARE_GET_CLOCKS = 0x00010007,
};
/*
* raspi clock
*/
enum
{
MBOX_TAG_CLOCK_GET_TURBO = 0x00030009,
MBOX_TAG_CLOCK_SET_TURBO = 0x00038009,
MBOX_TAG_CLOCK_GET_STATE = 0x00030001,
MBOX_TAG_CLOCK_SET_STATE = 0x00038001,
MBOX_TAG_CLOCK_GET_RATE = 0x00030002,
MBOX_TAG_CLOCK_SET_RATE = 0x00038002,
MBOX_TAG_CLOCK_GET_MAX_RATE = 0x00030004,
MBOX_TAG_CLOCK_GET_MIN_RATE = 0x00030007,
};
/*
* raspi power
*/
enum
{
MBOX_TAG_POWER_GET_STATE = 0x00020001,
MBOX_TAG_POWER_SET_STATE = 0x00028001,
};
/*
* raspi temperature
*/
enum
{
MBOX_TAG_TEMP_GET = 0x00030006,
MBOX_TAG_TEMP_GET_MAX = 0x0003000A,
};
/*
* raspi Memory
*/
enum
{
MBOX_TAG_ALLOCATE_MEMORY = 0x0003000C, // Memory: Allocates Contiguous Memory On The GPU (Response: Handle)
MBOX_TAG_LOCK_MEMORY = 0x0003000D, // Memory: Unlock Buffer (Response: Status)
MBOX_TAG_UNLOCK_MEMORY = 0x0003000E, // Memory: Unlock Buffer (Response: Status)
MBOX_TAG_RELEASE_MEMORY = 0x0003000F, // Memory: Free The Memory Buffer (Response: Status)
MBOX_TAG_EXECUTE_CODE = 0x00030010, // Memory: Calls The Function At Given (Bus) Address And With Arguments Given
};
/*
* raspi GPU
*/
enum
{
MBOX_TAG_EXECUTE_QPU = 0x00030011, // QPU: Calls The QPU Function At Given (Bus) Address And With Arguments Given
// (Response: Number Of QPUs, Control, No Flush, Timeout In ms)
MBOX_TAG_ENABLE_QPU = 0x00030012, // QPU: Enables The QPU (Response: Enable State)
};
/*
* raspi HDMI
*/
#define MBOX_TAG_GET_EDID_BLOCK 0x00030020 // HDMI: Read Specificed EDID Block From Attached HDMI/DVI Device
// (Response: Block Number, Status, EDID Block (128 Bytes))
/*
* raspi NOTIFY
*/
#define MBOX_TAG_NOTIFY_REBOOT 0x00030048
#define MBOX_TAG_NOTIFY_XHCI_RESET 0x00030058
/*
* touch
*/
#define MBOX_TAG_GET_TOUCHBUF (0x0004000F)
#define MBOX_ADDR 0x08000000
#define RES_CLK_ID (0x000000000)
#define EMMC_CLK_ID (0x000000001)
#define UART_CLK_ID (0x000000002)
#define ARM_CLK_ID (0x000000003)
#define CORE_CLK_ID (0x000000004)
#define V3D_CLK_ID (0x000000005)
#define H264_CLK_ID (0x000000006)
#define ISP_CLK_ID (0x000000007)
#define SDRAM_CLK_ID (0x000000008)
#define PIXEL_CLK_ID (0x000000009)
#define PWM_CLK_ID (0x00000000a)
int mbox_call(unsigned char ch, int mmu_enable);
int bcm271x_mbox_get_touch(void);
int bcm271x_notify_reboot(void);
int bcm271x_notify_xhci_reset(void);
int bcm271x_gpu_enable(void);
int bcm271x_mbox_hardware_get_model(void);
int bcm271x_mbox_hardware_get_revison(void);
int bcm271x_mbox_hardware_get_mac_address(uint8_t *mac);
int bcm271x_mbox_hardware_get_serial(rt_uint64_t *sn);
int bcm271x_mbox_hardware_get_arm_memory(rt_uint32_t *base, rt_uint32_t *size);
int bcm271x_mbox_hardware_get_vc_memory(rt_uint32_t *base, rt_uint32_t *size);
int bcm271x_mbox_clock_get_turbo(void);
int bcm271x_mbox_clock_set_turbo(int level);
int bcm271x_mbox_clock_get_state(int id);
int bcm271x_mbox_clock_set_state(int id, int state);
int bcm271x_mbox_clock_get_rate(int id);
int bcm271x_mbox_clock_set_rate(int id, int rate);
int bcm271x_mbox_clock_get_max_rate(int id);
int bcm271x_mbox_clock_get_min_rate(int id);
int bcm271x_mbox_power_get_state(int id);
int bcm271x_mbox_power_set_state(int id, int state);
int bcm271x_mbox_temp_get(void);
int bcm271x_mbox_temp_get_max(void);
#endif

View File

@ -1,29 +1,145 @@
#ifndef __RASPI4_H__
#define __RASPI4_H__
#include <rthw.h>
#define __REG32(x) (*((volatile unsigned int *)(x)))
//base address
#define PER_BASE (0xFE000000)
//gpio offset
#define GPIO_BASE_OFFSET (0x00200000)
//pl011 offset
#define PL011_UART_BASE_OFFSET (0x00201000)
//pactl cs offset
#define PACTL_CS_OFFSET (0x00204E00)
//aux offset
#define AUX_BASE_OFFSET (0x00215000)
//gpio
#define GPIO_BASE (0xFE000000 + 0x00200000)
#define GPIO_BASE (PER_BASE + GPIO_BASE_OFFSET)
#define GPIO_IRQ_NUM (3) //40 pin mode
#define IRQ_GPIO0 (96 + 49) //bank0 (0 to 27)
#define IRQ_GPIO1 (96 + 50) //bank1 (28 to 45)
#define IRQ_GPIO2 (96 + 51) //bank2 (46 to 57)
#define IRQ_GPIO3 (96 + 52) //bank3
//system timer
#define ARM_TIMER_IRQ (64)
#define ARM_TIMER_BASE (PER_BASE + 0xB000)
#define ARM_TIMER_LOAD HWREG32(ARM_TIMER_BASE + 0x400)
#define ARM_TIMER_VALUE HWREG32(ARM_TIMER_BASE + 0x404)
#define ARM_TIMER_CTRL HWREG32(ARM_TIMER_BASE + 0x408)
#define ARM_TIMER_IRQCLR HWREG32(ARM_TIMER_BASE + 0x40C)
#define ARM_TIMER_RAWIRQ HWREG32(ARM_TIMER_BASE + 0x410)
#define ARM_TIMER_MASKIRQ HWREG32(ARM_TIMER_BASE + 0x414)
#define ARM_TIMER_RELOAD HWREG32(ARM_TIMER_BASE + 0x418)
#define ARM_TIMER_PREDIV HWREG32(ARM_TIMER_BASE + 0x41C)
#define ARM_TIMER_CNTR HWREG32(ARM_TIMER_BASE + 0x420)
//uart
#define UART0_BASE (0xFE000000 + 0x00201000)
#define PL011_BASE UART0_BASE
#define IRQ_PL011 (121 + 32)
#define UART_REFERENCE_CLOCK (48000000)
#define UART_BASE (PER_BASE + PL011_UART_BASE_OFFSET)
#define UART0_BASE (UART_BASE + 0x0)
#define UART2_BASE (UART_BASE + 0x400)
#define UART3_BASE (UART_BASE + 0x600)
#define UART4_BASE (UART_BASE + 0x800)
#define UART5_BASE (UART_BASE + 0xA00)
#define IRQ_AUX_UART (96 + 29)
#define UART_REFERENCE_CLOCK (48000000)
//aux
#define AUX_BASE (PER_BASE + AUX_BASE_OFFSET)
#define IRQ_PL011 (96 + 57)
//pactl cs
#define PACTL_CS_ADDR (PER_BASE + PACTL_CS_OFFSET)
#define PACTL_CS HWREG32(PACTL_CS_ADDR)
typedef enum
{
IRQ_SPI0 = 0x00000000,
IRQ_SPI1 = 0x00000002,
IRQ_SPI2 = 0x00000004,
IRQ_SPI3 = 0x00000008,
IRQ_SPI4 = 0x00000010,
IRQ_SPI5 = 0x00000020,
IRQ_SPI6 = 0x00000040,
IRQ_I2C0 = 0x00000100,
IRQ_I2C1 = 0x00000200,
IRQ_I2C2 = 0x00000400,
IRQ_I2C3 = 0x00000800,
IRQ_I2C4 = 0x00001000,
IRQ_I2C5 = 0x00002000,
IRQ_I2C6 = 0x00004000,
IRQ_I2C7 = 0x00008000,
IRQ_UART5 = 0x00010000,
IRQ_UART4 = 0x00020000,
IRQ_UART3 = 0x00040000,
IRQ_UART2 = 0x00080000,
IRQ_UART0 = 0x00100000
} PACTL_CS_VAL;
// 0x40, 0x44, 0x48, 0x4c: Core 0~3 Timers interrupt control
#define CORE0_TIMER_IRQ_CTRL HWREG32(0xFF800040)
#define TIMER_IRQ 30
#define NON_SECURE_TIMER_IRQ (1 << 1)
//core timer
#define ST_BASE_OFFSET (0x003000)
#define STIMER_BASE (PER_BASE + ST_BASE_OFFSET)
#define STIMER_CS HWREG32(STIMER_BASE + 0x0000)
#define STIMER_CLO HWREG32(STIMER_BASE + 0x0004)
#define STIMER_CHI HWREG32(STIMER_BASE + 0x0008)
#define STIMER_C0 HWREG32(STIMER_BASE + 0x000C)
#define STIMER_C1 HWREG32(STIMER_BASE + 0x0010)
#define STIMER_C2 HWREG32(STIMER_BASE + 0x0014)
#define STIMER_C3 HWREG32(STIMER_BASE + 0x0018)
#define DELAY_MICROS(micros) \
do { \
rt_uint32_t compare = STIMER_CLO + micros * 25; \
while (STIMER_CLO < compare); \
} while (0) \
//mmc
#define MMC0_BASE_ADDR (PER_BASE + 0x300000)
#define MMC2_BASE_ADDR (PER_BASE + 0x340000)
//eth
#define MAC_REG_BASE_ADDR (void *)(0xfd580000)
#define ETH_IRQ (160 + 29)
#define SEND_DATA_NO_CACHE (0x08200000)
#define RECV_DATA_NO_CACHE (0x08400000)
//gic max
#define MAX_HANDLERS (256)
#define ARM_GIC_NR_IRQS (512)
#define INTC_BASE (0xff800000)
#define ARM_GIC_MAX_NR (512)
#define GIC_V2_BASE (INTC_BASE + 0x00040000)
#define GIC_V2_DISTRIBUTOR_BASE (INTC_BASE + 0x00041000)
#define GIC_V2_CPU_INTERFACE_BASE (INTC_BASE + 0x00042000)
#define GIC_V2_HYPERVISOR_BASE (INTC_BASE + 0x00044000)
#define GIC_V2_VIRTUAL_CPU_BASE (INTC_BASE + 0x00046000)
#define GIC_IRQ_START 0
#define GIC_ACK_INTID_MASK 0x000003ff
#define GIC_PL400_DISTRIBUTOR_PPTR GIC_V2_DISTRIBUTOR_BASE
#define GIC_PL400_CONTROLLER_PPTR GIC_V2_CPU_INTERFACE_BASE
/* the basic constants and interfaces needed by gic */
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
{
return GIC_PL400_DISTRIBUTOR_PPTR;
}
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
{
return GIC_PL400_CONTROLLER_PPTR;
}
#endif

View File

@ -19,6 +19,9 @@
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
#define RT_TIMER_THREAD_STACK_SIZE 2048
/* kservice optimization */
#define RT_DEBUG
/* Inter-Thread communication */
@ -40,8 +43,8 @@
#define RT_USING_DEVICE
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 128
#define RT_CONSOLE_DEVICE_NAME "uart"
#define RT_VER_NUM 0x40003
#define RT_CONSOLE_DEVICE_NAME "uart0"
#define RT_VER_NUM 0x40004
#define ARCH_CPU_64BIT
#define ARCH_ARMV8
@ -58,16 +61,17 @@
/* Command shell */
#define RT_USING_FINSH
#define RT_USING_MSH
#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_USING_DESCRIPTION
#define FINSH_THREAD_PRIORITY 20
#define FINSH_THREAD_STACK_SIZE 4096
#define FINSH_CMD_SIZE 80
#define FINSH_USING_MSH
#define FINSH_USING_MSH_DEFAULT
#define MSH_USING_BUILT_IN_COMMANDS
#define FINSH_USING_DESCRIPTION
#define FINSH_ARG_MAX 10
/* Device virtual file system */
@ -77,16 +81,42 @@
#define DFS_FILESYSTEMS_MAX 2
#define DFS_FILESYSTEM_TYPES_MAX 2
#define DFS_FD_MAX 16
#define RT_USING_DFS_ELMFAT
/* elm-chan's FatFs, Generic FAT Filesystem Module */
#define RT_DFS_ELM_CODE_PAGE 437
#define RT_DFS_ELM_WORD_ACCESS
#define RT_DFS_ELM_USE_LFN_3
#define RT_DFS_ELM_USE_LFN 3
#define RT_DFS_ELM_LFN_UNICODE_0
#define RT_DFS_ELM_LFN_UNICODE 0
#define RT_DFS_ELM_MAX_LFN 255
#define RT_DFS_ELM_DRIVES 2
#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
#define RT_DFS_ELM_REENTRANT
#define RT_USING_DFS_DEVFS
/* Device Drivers */
#define RT_USING_DEVICE_IPC
#define RT_PIPE_BUFSZ 512
#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_USING_DMA
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_PIN
#define RT_USING_RTC
#define RT_USING_ALARM
#define RT_USING_SDIO
#define RT_SDIO_STACK_SIZE 512
#define RT_SDIO_THREAD_PRIORITY 15
#define RT_MMCSD_STACK_SIZE 2048
#define RT_MMCSD_THREAD_PREORITY 22
#define RT_MMCSD_MAX_PARTITION 16
/* Using USB */
@ -95,17 +125,73 @@
#define RT_USING_LIBC
#define RT_USING_POSIX
#define RT_LIBC_DEFAULT_TIMEZONE 8
/* Network */
/* Socket abstraction layer */
#define RT_USING_SAL
#define SAL_INTERNET_CHECK
/* protocol stack implement */
#define SAL_USING_LWIP
#define SAL_SOCKETS_NUM 16
/* Network interface device */
#define RT_USING_NETDEV
#define NETDEV_USING_IFCONFIG
#define NETDEV_USING_PING
#define NETDEV_USING_NETSTAT
#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_LWIP_MEM_ALIGNMENT 4
#define RT_LWIP_IGMP
#define RT_LWIP_ICMP
#define RT_LWIP_DNS
#define RT_LWIP_DHCP
#define IP_SOF_BROADCAST 1
#define IP_SOF_BROADCAST_RECV 1
/* Static IPv4 Address */
#define RT_LWIP_IPADDR "192.168.1.30"
#define RT_LWIP_GWADDR "192.168.1.1"
#define RT_LWIP_MSKADDR "255.255.255.0"
#define RT_LWIP_UDP
#define RT_LWIP_TCP
#define RT_LWIP_RAW
#define RT_MEMP_NUM_NETCONN 8
#define RT_LWIP_PBUF_NUM 16
#define RT_LWIP_RAW_PCB_NUM 4
#define RT_LWIP_UDP_PCB_NUM 4
#define RT_LWIP_TCP_PCB_NUM 4
#define RT_LWIP_TCP_SEG_NUM 40
#define RT_LWIP_TCP_SND_BUF 8196
#define RT_LWIP_TCP_WND 8196
#define RT_LWIP_TCPTHREAD_PRIORITY 10
#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
#define RT_LWIP_TCPTHREAD_STACKSIZE 2048
#define RT_LWIP_ETHTHREAD_PRIORITY 12
#define RT_LWIP_ETHTHREAD_STACKSIZE 2048
#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define SO_REUSE 1
#define LWIP_SO_RCVTIMEO 1
#define LWIP_SO_SNDTIMEO 1
#define LWIP_SO_RCVBUF 1
#define LWIP_SO_LINGER 0
#define LWIP_NETIF_LOOPBACK 0
#define RT_LWIP_USING_PING
/* AT commands */
@ -115,6 +201,11 @@
/* Utilities */
#define RT_USING_RYM
#define YMODEM_USING_FILE_TRANSFER
/* RT-Thread Utestcases */
/* RT-Thread online packages */
@ -146,16 +237,27 @@
/* system packages */
/* acceleration: Assembly language or algorithmic acceleration packages */
/* Micrium: Micrium software products porting for RT-Thread */
/* peripheral libraries and drivers */
/* miscellaneous packages */
/* AI packages */
/* miscellaneous packages */
/* samples: kernel and components samples */
/* entertainment: terminal games and other interesting software packages */
#define BCM2711_SOC
#define BSP_SUPPORT_FPU
/* Hardware Drivers Config */
@ -167,6 +269,11 @@
#define BSP_USING_GIC400
#define BSP_USING_PIN
#define BSP_USING_CORETIMER
#define BSP_USING_ETH
#define BSP_USING_RTC
#define BSP_USING_ALARM
#define BSP_USING_SDIO
#define BSP_USING_SDIO0
/* Board Peripheral Drivers */

View File

@ -2,7 +2,7 @@ import os
# toolchains options
ARCH ='aarch64'
CPU ='cortex-a72'
CPU ='cortex-a'
CROSS_TOOL ='gcc'
if os.getenv('RTT_ROOT'):

View File

@ -6,9 +6,13 @@ 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('CPU', src, depend = [''], CPPPATH = CPPPATH)
group = DefineGroup('common', src, depend = [''], CPPPATH = CPPPATH)
# build for sub-directory
list = os.listdir(cwd)

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-09-10 GuEe-GUI first version
*/
#ifndef __CPUPORT_H__
#define __CPUPORT_H__
#include <rtdef.h>
rt_inline void rt_hw_isb(void)
{
__asm__ volatile ("isb":::"memory");
}
rt_inline void rt_hw_dmb(void)
{
__asm__ volatile ("dmb sy":::"memory");
}
rt_inline void rt_hw_dsb(void)
{
__asm__ volatile ("dsb sy":::"memory");
}
#endif /* __CPUPORT_H__ */

504
libcpu/aarch64/common/gic.c Normal file
View File

@ -0,0 +1,504 @@
/*
* Copyright (c) 2006-2021, 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()
*/
#include <rthw.h>
#include <rtthread.h>
#include <gic.h>
#include <cp15.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 */
};
/* 'ARM_GIC_MAX_NR' is the number of cores */
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)
/** 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)
static unsigned int _gic_max_irq;
int arm_gic_get_active_irq(rt_uint64_t index)
{
int irq;
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = GIC_CPU_INTACK(_gic_table[index].cpu_hw_base);
irq += _gic_table[index].offset;
return irq;
}
void arm_gic_ack(rt_uint64_t index, int irq)
{
rt_uint64_t mask = 1U << (irq % 32U);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0U);
GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
GIC_CPU_EOI(_gic_table[index].cpu_hw_base) = irq;
}
void arm_gic_mask(rt_uint64_t index, int irq)
{
rt_uint64_t mask = 1U << (irq % 32U);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0U);
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 = 1U << (irq % 32U);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0U);
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 >= 0U);
if (irq >= 16U)
{
pend = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
}
else
{
/* INTID 0-15 Software Generated Interrupt */
pend = (GIC_DIST_SPENDSGI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
/* No CPU identification offered */
if (pend != 0U)
{
pend = 1U;
}
else
{
pend = 0U;
}
}
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 >= 0U);
if (irq >= 16U)
{
GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) = 1U << (irq % 32U);
}
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 | 0x02000000U);
}
}
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 >= 0U);
if (irq >= 16U)
{
mask = 1U << (irq % 32U);
GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
}
else
{
mask = 1U << ((irq % 4U) * 8U);
GIC_DIST_CPENDSGI(_gic_table[index].dist_hw_base, irq) = mask;
}
}
void arm_gic_set_configuration(rt_uint64_t index, int irq, 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 >= 0U);
icfgr = GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq);
shift = (irq % 16U) << 1U;
icfgr &= (~(3U << 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 >= 0U);
return (GIC_DIST_CONFIG(_gic_table[index].dist_hw_base, irq) >> ((irq % 16U) >> 1U));
}
void arm_gic_clear_active(rt_uint64_t index, int irq)
{
rt_uint64_t mask = 1U << (irq % 32U);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0U);
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 >= 0U);
old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq);
old_tgt &= ~(0x0FFUL << ((irq % 4U)*8U));
old_tgt |= cpumask << ((irq % 4U)*8U);
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 >= 0U);
return (GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
}
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 >= 0U);
mask = GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq);
mask &= ~(0xFFUL << ((irq % 4U) * 8U));
mask |= ((priority & 0xFFUL) << ((irq % 4U) * 8U));
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 >= 0U);
return (GIC_DIST_PRI(_gic_table[index].dist_hw_base, irq) >> ((irq % 4U) * 8U)) & 0xFFUL;
}
void arm_gic_set_interface_prior_mask(rt_uint64_t index, rt_uint64_t priority)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
/* set priority mask */
GIC_CPU_PRIMASK(_gic_table[index].cpu_hw_base) = priority & 0xFFUL;
}
rt_uint64_t arm_gic_get_interface_prior_mask(rt_uint64_t index)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
return GIC_CPU_PRIMASK(_gic_table[index].cpu_hw_base);
}
void arm_gic_set_binary_point(rt_uint64_t index, rt_uint64_t binary_point)
{
GIC_CPU_BINPOINT(_gic_table[index].cpu_hw_base) = binary_point & 0x7U;
}
rt_uint64_t arm_gic_get_binary_point(rt_uint64_t index)
{
return GIC_CPU_BINPOINT(_gic_table[index].cpu_hw_base);
}
rt_uint64_t arm_gic_get_irq_status(rt_uint64_t index, int irq)
{
rt_uint64_t pending;
rt_uint64_t active;
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0U);
active = (GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
pending = (GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
return ((active << 1U) | pending);
}
void arm_gic_send_sgi(rt_uint64_t index, int irq, rt_uint64_t target_list, rt_uint64_t filter_list)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0U);
GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) =
((filter_list & 0x3U) << 24U) | ((target_list & 0xFFUL) << 16U) | (irq & 0x0FUL);
}
rt_uint64_t arm_gic_get_high_pending_irq(rt_uint64_t index)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
return GIC_CPU_HIGHPRI(_gic_table[index].cpu_hw_base);
}
rt_uint64_t arm_gic_get_interface_id(rt_uint64_t index)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
return GIC_CPU_IIDR(_gic_table[index].cpu_hw_base);
}
void arm_gic_set_group(rt_uint64_t index, int irq, rt_uint64_t group)
{
uint32_t igroupr;
uint32_t shift;
RT_ASSERT(index < ARM_GIC_MAX_NR);
RT_ASSERT(group <= 1U);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0U);
igroupr = GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq);
shift = (irq % 32U);
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 >= 0U);
return (GIC_DIST_IGROUP(_gic_table[index].dist_hw_base, irq) >> (irq % 32U)) & 0x1UL;
}
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;
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 & 0x1fU) + 1U) * 32U;
/*
* The GIC only supports up to 1020 interrupt sources.
* Limit this to either the architected maximum, or the
* platform maximum.
*/
if (_gic_max_irq > 1020U)
{
_gic_max_irq = 1020U;
}
if (_gic_max_irq > ARM_GIC_NR_IRQS) /* the platform maximum interrupts */
{
_gic_max_irq = ARM_GIC_NR_IRQS;
}
cpumask |= cpumask << 8U;
cpumask |= cpumask << 16U;
cpumask |= cpumask << 24U;
GIC_DIST_CTRL(dist_base) = 0x0U;
/* Set all global interrupts to be level triggered, active low. */
for (i = 32U; i < _gic_max_irq; i += 16U)
{
GIC_DIST_CONFIG(dist_base, i) = 0x0U;
}
/* Set all global interrupts to this CPU only. */
for (i = 32U; i < _gic_max_irq; i += 4U)
{
GIC_DIST_TARGET(dist_base, i) = cpumask;
}
/* Set priority on all interrupts. */
for (i = 0U; i < _gic_max_irq; i += 4U)
{
GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0U;
}
/* Disable all interrupts. */
for (i = 0U; i < _gic_max_irq; i += 32U)
{
GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffffU;
}
/* All interrupts defaults to IGROUP1(IRQ). */
for (i = 0U; i < _gic_max_irq; i += 32U)
{
GIC_DIST_IGROUP(dist_base, i) = 0U;
}
/* Enable group0 and group1 interrupt forwarding. */
GIC_DIST_CTRL(dist_base) = 0x01U;
return 0;
}
int arm_gic_cpu_init(rt_uint64_t index, rt_uint64_t cpu_base)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
if (!_gic_table[index].cpu_hw_base)
{
_gic_table[index].cpu_hw_base = cpu_base;
}
cpu_base = _gic_table[index].cpu_hw_base;
GIC_CPU_PRIMASK(cpu_base) = 0xf0U;
GIC_CPU_BINPOINT(cpu_base) = 0x7U;
/* Enable CPU interrupt */
GIC_CPU_CTRL(cpu_base) = 0x01U;
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) >> 4U) & 0xfUL,
_gic_table[index].dist_hw_base,
_gic_max_irq,
gic_type & (1U << 10U) ? "has" : "no",
gic_type);
}
void arm_gic_dump(rt_uint64_t index)
{
unsigned int i, k;
k = GIC_CPU_HIGHPRI(_gic_table[index].cpu_hw_base);
rt_kprintf("--- high pending priority: %d(%08x)\n", k, k);
rt_kprintf("--- hw mask ---\n");
for (i = 0U; i < _gic_max_irq / 32U; i++)
{
rt_kprintf("0x%08x, ", GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, i * 32U));
}
rt_kprintf("\n--- hw pending ---\n");
for (i = 0U; i < _gic_max_irq / 32U; i++)
{
rt_kprintf("0x%08x, ", GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base, i * 32U));
}
rt_kprintf("\n--- hw active ---\n");
for (i = 0U; i < _gic_max_irq / 32U; i++)
{
rt_kprintf("0x%08x, ", GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base, i * 32U));
}
rt_kprintf("\n");
}
long gic_dump(void)
{
arm_gic_dump_type(0);
arm_gic_dump(0);
return 0;
}
MSH_CMD_EXPORT(gic_dump, show gic status);

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-20 Bernard first version
*/
#ifndef __GIC_H__
#define __GIC_H__
#include <rthw.h>
#include <stdint.h>
#include <board.h>
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, 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);
void arm_gic_send_sgi(rt_uint64_t index, int irq, rt_uint64_t target_list, rt_uint64_t filter_list);
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_dist_init(rt_uint64_t index, rt_uint64_t dist_base, int irq_start);
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

View File

@ -1,30 +0,0 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd]
gic390_group = Split('''
gic_pl390.c
''')
gic400_group = Split('''
gic_pl400.c
''')
gic500_group = Split('''
gic_pl500.c
''')
src = ()
if GetDepend('BSP_USING_GIC390'):
src = gic390_group
if GetDepend('BSP_USING_GIC400'):
src = gic400_group
if GetDepend('BSP_USING_GIC500'):
src = gic500_group
group = DefineGroup('gic', src, depend = ['BSP_USING_GIC'], CPPPATH = CPPPATH)
Return('group')

View File

@ -1,273 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-07-31 GuEe-GUI the first version
*/
#include <rtthread.h>
#include "gic_pl390.h"
#define BIT(n) (1ul<<(n))
#define MASK(n) (BIT(n)-1ul)
#define IRQ_REG(IRQ) ((IRQ) / 32)
#define IRQ_BIT(IRQ) BIT((IRQ) % 32)
#define IRQ_MASK MASK(10)
#define IRQ_SET_ALL 0xffffffff
#define IS_IRQ_VALID(X) (((X)&IRQ_MASK) < GIC390_SPECIAL_IRQ_START)
#define TARGET_CPU_ALLINT(CPU) \
( \
(((CPU) & 0xff) << 0 ) | \
(((CPU) & 0xff) << 8 ) | \
(((CPU) & 0xff) << 16) | \
(((CPU) & 0xff) << 24) \
)
#define CPU(X) (1<<(X))
#define TARGET_CPU0_ALLINT TARGET_CPU_ALLINT(CPU(0))
/* memory map for GIC distributor */
struct gic_dist_map
{
rt_uint32_t enable; /* 0x000 */
rt_uint32_t ic_type; /* 0x004 */
rt_uint32_t dist_ident; /* 0x008 */
rt_uint32_t res1[29]; /* [0x00C, 0x080) */
rt_uint32_t security[32]; /* [0x080, 0x100) */
rt_uint32_t enable_set[32]; /* [0x100, 0x180) */
rt_uint32_t enable_clr[32]; /* [0x180, 0x200) */
rt_uint32_t pending_set[32]; /* [0x200, 0x280) */
rt_uint32_t pending_clr[32]; /* [0x280, 0x300) */
rt_uint32_t active[32]; /* [0x300, 0x380) */
rt_uint32_t res2[32]; /* [0x380, 0x400) */
rt_uint32_t priority[255]; /* [0x400, 0x7FC) */
rt_uint32_t res3; /* 0x7FC */
rt_uint32_t targets[255]; /* [0x800, 0xBFC) */
rt_uint32_t res4; /* 0xBFC */
rt_uint32_t config[64]; /* [0xC00, 0xD00) */
rt_uint32_t spi[32]; /* [0xD00, 0xD80) */
rt_uint32_t res5[20]; /* [0xD80, 0xDD0) */
rt_uint32_t res6; /* 0xDD0 */
rt_uint32_t legacy_int; /* 0xDD4 */
rt_uint32_t res7[2]; /* [0xDD8, 0xDE0) */
rt_uint32_t match_d; /* 0xDE0 */
rt_uint32_t enable_d; /* 0xDE4 */
rt_uint32_t res8[70]; /* [0xDE8, 0xF00) */
rt_uint32_t sgi_control; /* 0xF00 */
rt_uint32_t res9[3]; /* [0xF04, 0xF10) */
rt_uint32_t sgi_pending_clr[4]; /* [0xF10, 0xF20) */
rt_uint32_t res10[40]; /* [0xF20, 0xFC0) */
rt_uint32_t periph_id[12]; /* [0xFC0, 0xFF0) */
rt_uint32_t component_id[4]; /* [0xFF0, 0xFFF] */
};
/* memory map for GIC CPU interface */
struct gic_cpu_iface_map
{
rt_uint32_t icontrol; /* 0x000 */
rt_uint32_t pri_msk_c; /* 0x004 */
rt_uint32_t pb_c; /* 0x008 */
rt_uint32_t int_ack; /* 0x00C */
rt_uint32_t eoi; /* 0x010 */
rt_uint32_t run_priority; /* 0x014 */
rt_uint32_t hi_pend; /* 0x018 */
rt_uint32_t ns_alias_bp_c; /* 0x01C */
rt_uint32_t ns_alias_ack; /* 0x020 GIC400 only */
rt_uint32_t ns_alias_eoi; /* 0x024 GIC400 only */
rt_uint32_t ns_alias_hi_pend; /* 0x028 GIC400 only */
rt_uint32_t res1[5]; /* [0x02C, 0x040) */
rt_uint32_t integ_en_c; /* 0x040 PL390 only */
rt_uint32_t interrupt_out; /* 0x044 PL390 only */
rt_uint32_t res2[2]; /* [0x048, 0x050) */
rt_uint32_t match_c; /* 0x050 PL390 only */
rt_uint32_t enable_c; /* 0x054 PL390 only */
rt_uint32_t res3[30]; /* [0x058, 0x0FC) */
rt_uint32_t active_priority[4]; /* [0x0D0, 0xDC] GIC400 only */
rt_uint32_t ns_active_priority[4]; /* [0xE0,0xEC] GIC400 only */
rt_uint32_t res4[3];
rt_uint32_t cpu_if_ident; /* 0x0FC */
rt_uint32_t res5[948]; /* [0x100. 0xFC0) */
rt_uint32_t periph_id[8]; /* [0xFC0, 9xFF0) PL390 only */
rt_uint32_t component_id[4]; /* [0xFF0, 0xFFF] PL390 only */
};
volatile struct gic_dist_map *gic_dist =
(volatile struct gic_dist_map*)(GIC_PL390_DISTRIBUTOR_PPTR);
volatile struct gic_cpu_iface_map *gic_cpuiface =
(volatile struct gic_cpu_iface_map*)(GIC_PL390_CONTROLLER_PPTR);
/*
* The only sane way to get an GIC IRQ number that can be properly
* ACKED later is through the int_ack register. Unfortunately, reading
* this register changes the interrupt state to pending so future
* reads will not return the same value For this reason, we have a
* global variable to store the IRQ number.
*/
static rt_uint32_t active_irq = GIC390_IRQ_NONE;
rt_inline int is_irq_edge_triggered(int irq)
{
int word = irq / 16;
int bit = ((irq & 0xf) * 2);
return !!(gic_dist->config[word] & BIT(bit + 1));
}
rt_inline void dist_pending_clr(int irq)
{
int word = irq / 32;
int bit = irq & 0x1f;
gic_dist->pending_clr[word] = BIT(bit);
}
rt_inline void dist_init(void)
{
int i;
int nirqs = 32 * ((gic_dist->ic_type & 0x1f) + 1);
gic_dist->enable = 0;
for (i = 0; i < nirqs; i += 32)
{
/* disable */
gic_dist->enable_clr[i / 32] = IRQ_SET_ALL;
/* clear pending */
gic_dist->pending_clr[i / 32] = IRQ_SET_ALL;
}
/* reset interrupts priority */
for (i = 32; i < nirqs; i += 4)
{
gic_dist->priority[i / 4] = 0x0;
}
/*
* reset int target to cpu 0
* (Should really query which processor we're running on and use that)
*/
for (i = 0; i < nirqs; i += 4)
{
gic_dist->targets[i / 4] = TARGET_CPU0_ALLINT;
}
/* level-triggered, 1-N */
for (i = 64; i < nirqs; i += 32)
{
gic_dist->config[i / 32] = 0;
}
/* enable the int controller */
gic_dist->enable = 1;
}
rt_inline void cpu_iface_init(void)
{
rt_uint32_t i;
/* For non-Exynos4, the registers are banked per CPU, need to clear them */
gic_dist->enable_clr[0] = IRQ_SET_ALL;
gic_dist->pending_clr[0] = IRQ_SET_ALL;
gic_dist->priority[0] = 0x00;
/* put everything in group 0 */
/* clear any software generated interrupts */
for (i = 0; i < 16; i += 4)
{
gic_dist->sgi_pending_clr[i / 4] = IRQ_SET_ALL;
}
gic_cpuiface->icontrol = 0;
gic_cpuiface->pri_msk_c = 0x000000f0;
gic_cpuiface->pb_c = 0x00000003;
while (((i = gic_cpuiface->int_ack) & IRQ_MASK) != GIC390_IRQ_NONE)
{
gic_cpuiface->eoi = i;
}
gic_cpuiface->icontrol = 0x1;
}
void arm_gic_irq_init(void)
{
dist_init();
cpu_iface_init();
}
int arm_gic_get_active_irq(void)
{
int irq;
if (!IS_IRQ_VALID(active_irq))
{
active_irq = gic_cpuiface->int_ack;
}
if (IS_IRQ_VALID(active_irq))
{
irq = active_irq & IRQ_MASK;
}
else
{
irq = GIC390_IRQ_NONE;
}
return irq;
}
void arm_gic_mask(int irq)
{
int word = irq / 32;
int bit = irq & 0x1f;
gic_dist->enable_clr[word] = BIT(bit);
}
void arm_gic_umask(int irq)
{
int word = irq / 32;
int bit = irq & 0x1f;
gic_dist->enable_set[word] = BIT(bit);
}
void arm_gic_ack(int irq)
{
if (!(IS_IRQ_VALID(active_irq) && (active_irq & IRQ_MASK) == irq))
{
return;
}
if (is_irq_edge_triggered(irq))
{
dist_pending_clr(irq);
}
gic_cpuiface->eoi = active_irq;
active_irq = GIC390_IRQ_NONE;
}
int rt_hw_interrupt_get_irq(void)
{
return arm_gic_get_active_irq();
}
void rt_hw_interrupt_ack(int fiq_irq)
{
return arm_gic_ack(fiq_irq);
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-07-31 GuEe-GUI the first version
*/
#ifndef GIC_PL390_H__
#define GIC_PL390_H__
#include <board.h>
#define GIC390_SPECIAL_IRQ_START 1020
#define GIC390_IRQ_NONE 1023
void arm_gic_irq_init(void);
int arm_gic_get_active_irq(void);
void arm_gic_ack(int irq);
void arm_gic_mask(int irq);
void arm_gic_umask(int irq);
#endif

View File

@ -1,261 +0,0 @@
/*
* Copyright (c) 2006-2021, 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()
*/
#include <rtthread.h>
#include "gic_pl400.h"
#include "cp15.h"
#define ARM_GIC_MAX_NR 1
struct arm_gic
{
rt_uint32_t offset; /* the first interrupt index in the vector table */
rt_uint32_t dist_hw_base; /* the base address of the gic distributor */
rt_uint32_t cpu_hw_base; /* the base addrees 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;
int arm_gic_get_active_irq(rt_uint32_t index)
{
int irq;
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = GIC_CPU_INTACK(_gic_table[index].cpu_hw_base);
irq += _gic_table[index].offset;
return irq;
}
void arm_gic_ack(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1 << (irq % 32);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0);
GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
GIC_CPU_EOI(_gic_table[index].cpu_hw_base) = irq;
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
}
void arm_gic_mask(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1 << (irq % 32);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0);
GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
}
void arm_gic_clear_pending(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1 << (irq % 32);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0);
GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
}
void arm_gic_clear_active(rt_uint32_t index, int irq)
{
rt_uint32_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_uint32_t index, int irq, unsigned int cpumask)
{
rt_uint32_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 &= ~(0x0FFUL << ((irq % 4)*8));
old_tgt |= cpumask << ((irq % 4)*8);
GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
}
void arm_gic_umask(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1 << (irq % 32);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0);
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
}
void arm_gic_dump_type(rt_uint32_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_uint32_t index)
{
unsigned int i, k;
k = GIC_CPU_HIGHPRI(_gic_table[index].cpu_hw_base);
rt_kprintf("--- high pending priority: %d(%08x)\n", k, k);
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("\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("\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("\n");
}
#ifdef RT_USING_FINSH
#include <finsh.h>
FINSH_FUNCTION_EXPORT_ALIAS(arm_gic_dump, gic, show gic status);
#endif
int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
{
unsigned int gic_type, i;
rt_uint32_t cpumask = 1 << 0;
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;
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
cpumask |= cpumask << 24;
GIC_DIST_CTRL(dist_base) = 0x0;
/* 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) = 0x0;
/* Set all global interrupts to this CPU only. */
for (i = 32; i < _gic_max_irq; i += 4)
GIC_DIST_TARGET(dist_base, i) = cpumask;
/* Set priority on all interrupts. */
for (i = 0; i < _gic_max_irq; i += 4)
GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0;
/* Disable all interrupts. */
for (i = 0; i < _gic_max_irq; i += 32)
GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffff;
#if 0
/* All interrupts defaults to IGROUP1(IRQ). */
for (i = 0; i < _gic_max_irq; i += 32)
GIC_DIST_IGROUP(dist_base, i) = 0xffffffff;
#endif
for (i = 0; i < _gic_max_irq; i += 32)
GIC_DIST_IGROUP(dist_base, i) = 0;
/* Enable group0 and group1 interrupt forwarding. */
GIC_DIST_CTRL(dist_base) = 0x01;
return 0;
}
int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
_gic_table[index].cpu_hw_base = cpu_base;
GIC_CPU_PRIMASK(cpu_base) = 0xf0;
GIC_CPU_BINPOINT(cpu_base) = 0x7;
/* Enable CPU interrupt */
GIC_CPU_CTRL(cpu_base) = 0x01;
return 0;
}
void arm_gic_set_group(rt_uint32_t index, int vector, int group)
{
/* As for GICv2, there are only group0 and group1. */
RT_ASSERT(group <= 1);
RT_ASSERT(vector < _gic_max_irq);
if (group == 0)
{
GIC_DIST_IGROUP(_gic_table[index].dist_hw_base,
vector) &= ~(1 << (vector % 32));
}
else if (group == 1)
{
GIC_DIST_IGROUP(_gic_table[index].dist_hw_base,
vector) |= (1 << (vector % 32));
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-20 Bernard first version
*/
#ifndef __GIC_PL400_H__
#define __GIC_PL400_H__
#include <rthw.h>
#include <board.h>
#define __REG32(x) (*((volatile unsigned int*)((rt_uint64_t)x)))
#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00)
#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04)
#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08)
#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0c)
#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10)
#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14)
#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18)
#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000)
#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004)
#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080 + ((n)/32) * 4)
#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100 + ((n)/32) * 4)
#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180 + ((n)/32) * 4)
#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200 + ((n)/32) * 4)
#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280 + ((n)/32) * 4)
#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300 + ((n)/32) * 4)
#define GIC_DIST_ACTIVE_CLEAR(hw_base, n) __REG32((hw_base) + 0x380 + ((n)/32) * 4)
#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400 + ((n)/4) * 4)
#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800 + ((n)/4) * 4)
#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00 + ((n)/16) * 4)
#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00)
#define GIC_DIST_CPENDSGI(hw_base, n) __REG32((hw_base) + 0xf10 + ((n)/4) * 4)
#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8)
int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start);
int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base);
void arm_gic_mask(rt_uint32_t index, int irq);
void arm_gic_umask(rt_uint32_t index, int irq);
void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask);
void arm_gic_set_group(rt_uint32_t index, int vector, int group);
int arm_gic_get_active_irq(rt_uint32_t index);
void arm_gic_ack(rt_uint32_t index, int irq);
void arm_gic_clear_active(rt_uint32_t index, int irq);
void arm_gic_clear_pending(rt_uint32_t index, int irq);
void arm_gic_dump_type(rt_uint32_t index);
void arm_gic_dump(rt_uint32_t index);
#endif

View File

@ -0,0 +1,409 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard first version
* 2018-11-22 Jesven add smp support
*/
#include <rthw.h>
#include <rtthread.h>
#include "interrupt.h"
#include "gic.h"
#include "armv8.h"
#include "mmu.h"
/* exception and interrupt handler table */
struct rt_irq_desc isr_table[MAX_HANDLERS];
#ifndef RT_USING_SMP
/* Those variables will be accessed in ISR, so we need to share them. */
rt_ubase_t rt_interrupt_from_thread = 0;
rt_ubase_t rt_interrupt_to_thread = 0;
rt_ubase_t rt_thread_switch_interrupt_flag = 0;
#endif
const unsigned int VECTOR_BASE = 0x00;
extern int system_vectors;
#ifdef RT_USING_SMP
#define rt_interrupt_nest rt_cpu_self()->irq_nest
#else
extern volatile rt_uint8_t rt_interrupt_nest;
#endif
#ifndef BSP_USING_GIC
static void default_isr_handler(int vector, void *param)
{
#ifdef RT_USING_SMP
rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector);
#else
rt_kprintf("unhandled irq: %d\n",vector);
#endif
}
#endif
void rt_hw_vector_init(void)
{
rt_hw_set_current_vbar((rt_ubase_t)&system_vectors);
}
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
#ifndef BSP_USING_GIC
rt_uint32_t index;
/* initialize vector table */
rt_hw_vector_init();
/* initialize exceptions table */
rt_memset(isr_table, 0x00, sizeof(isr_table));
/* mask all of interrupts */
IRQ_DISABLE_BASIC = 0x000000ff;
IRQ_DISABLE1 = 0xffffffff;
IRQ_DISABLE2 = 0xffffffff;
for (index = 0; index < MAX_HANDLERS; index ++)
{
isr_table[index].handler = default_isr_handler;
isr_table[index].param = RT_NULL;
#ifdef RT_USING_INTERRUPT_INFO
rt_strncpy(isr_table[index].name, "unknown", RT_NAME_MAX);
isr_table[index].counter = 0;
#endif
}
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrupt_flag = 0;
#else
rt_uint64_t gic_cpu_base;
rt_uint64_t gic_dist_base;
rt_uint64_t gic_irq_start;
/* initialize vector table */
rt_hw_vector_init();
/* initialize exceptions table */
rt_memset(isr_table, 0x00, sizeof(isr_table));
/* initialize ARM GIC */
gic_dist_base = platform_get_gic_dist_base();
gic_cpu_base = platform_get_gic_cpu_base();
gic_irq_start = GIC_IRQ_START;
arm_gic_dist_init(0, gic_dist_base, gic_irq_start);
arm_gic_cpu_init(0, gic_cpu_base);
#endif
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int vector)
{
#ifndef BSP_USING_GIC
if (vector < 32)
{
IRQ_DISABLE1 = (1 << vector);
}
else if (vector < 64)
{
vector = vector % 32;
IRQ_DISABLE2 = (1 << vector);
}
else
{
vector = vector - 64;
IRQ_DISABLE_BASIC = (1 << vector);
}
#else
arm_gic_mask(0, vector);
#endif
}
/**
* This function will un-mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_umask(int vector)
{
#ifndef BSP_USING_GIC
if (vector < 32)
{
IRQ_ENABLE1 = (1 << vector);
}
else if (vector < 64)
{
vector = vector % 32;
IRQ_ENABLE2 = (1 << vector);
}
else
{
vector = vector - 64;
IRQ_ENABLE_BASIC = (1 << vector);
}
#else
arm_gic_umask(0, vector);
#endif
}
/**
* This function returns the active interrupt number.
* @param none
*/
int rt_hw_interrupt_get_irq(void)
{
#ifdef BSP_USING_GIC
return arm_gic_get_active_irq(0);
#else
return 0;
#endif
}
/**
* This function acknowledges the interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_ack(int vector)
{
#ifdef BSP_USING_GIC
arm_gic_ack(0, vector);
#endif
}
/**
* This function set interrupt CPU targets.
* @param vector: the interrupt number
* cpu_mask: target cpus mask, one bit for one core
*/
void rt_hw_interrupt_set_target_cpus(int vector, unsigned int cpu_mask)
{
#ifdef BSP_USING_GIC
arm_gic_set_cpu(0, vector, cpu_mask);
#endif
}
/**
* This function get interrupt CPU targets.
* @param vector: the interrupt number
* @return target cpus mask, one bit for one core
*/
unsigned int rt_hw_interrupt_get_target_cpus(int vector)
{
#ifdef BSP_USING_GIC
return arm_gic_get_target_cpu(0, vector);
#else
return -RT_ERROR;
#endif
}
/**
* This function set interrupt triger mode.
* @param vector: the interrupt number
* mode: interrupt triger mode; 0: level triger, 1: edge triger
*/
void rt_hw_interrupt_set_triger_mode(int vector, unsigned int mode)
{
#ifdef BSP_USING_GIC
arm_gic_set_configuration(0, vector, mode);
#endif
}
/**
* This function get interrupt triger mode.
* @param vector: the interrupt number
* @return interrupt triger mode; 0: level triger, 1: edge triger
*/
unsigned int rt_hw_interrupt_get_triger_mode(int vector)
{
#ifdef BSP_USING_GIC
return arm_gic_get_configuration(0, vector);
#else
return -RT_ERROR;
#endif
}
/**
* This function set interrupt pending flag.
* @param vector: the interrupt number
*/
void rt_hw_interrupt_set_pending(int vector)
{
#ifdef BSP_USING_GIC
arm_gic_set_pending_irq(0, vector);
#endif
}
/**
* This function get interrupt pending flag.
* @param vector: the interrupt number
* @return interrupt pending flag, 0: not pending; 1: pending
*/
unsigned int rt_hw_interrupt_get_pending(int vector)
{
#ifdef BSP_USING_GIC
return arm_gic_get_pending_irq(0, vector);
#else
return -RT_ERROR;
#endif
}
/**
* This function clear interrupt pending flag.
* @param vector: the interrupt number
*/
void rt_hw_interrupt_clear_pending(int vector)
{
#ifdef BSP_USING_GIC
arm_gic_clear_pending_irq(0, vector);
#endif
}
/**
* This function set interrupt priority value.
* @param vector: the interrupt number
* priority: the priority of interrupt to set
*/
void rt_hw_interrupt_set_priority(int vector, unsigned int priority)
{
#ifdef BSP_USING_GIC
arm_gic_set_priority(0, vector, priority);
#endif
}
/**
* This function get interrupt priority.
* @param vector: the interrupt number
* @return interrupt priority value
*/
unsigned int rt_hw_interrupt_get_priority(int vector)
{
#ifdef BSP_USING_GIC
return arm_gic_get_priority(0, vector);
#else
return -RT_ERROR;
#endif
}
/**
* This function set priority masking threshold.
* @param priority: priority masking threshold
*/
void rt_hw_interrupt_set_priority_mask(unsigned int priority)
{
#ifdef BSP_USING_GIC
arm_gic_set_interface_prior_mask(0, priority);
#endif
}
/**
* This function get priority masking threshold.
* @param none
* @return priority masking threshold
*/
unsigned int rt_hw_interrupt_get_priority_mask(void)
{
#ifdef BSP_USING_GIC
return arm_gic_get_interface_prior_mask(0);
#else
return -RT_ERROR;
#endif
}
/**
* This function set priority grouping field split point.
* @param bits: priority grouping field split point
* @return 0: success; -1: failed
*/
int rt_hw_interrupt_set_prior_group_bits(unsigned int bits)
{
#ifdef BSP_USING_GIC
int status;
if (bits < 8)
{
arm_gic_set_binary_point(0, (7 - bits));
status = 0;
}
else
{
status = -1;
}
return (status);
#else
return -RT_ERROR;
#endif
}
/**
* This function get priority grouping field split point.
* @param none
* @return priority grouping field split point
*/
unsigned int rt_hw_interrupt_get_prior_group_bits(void)
{
#ifdef BSP_USING_GIC
unsigned int bp;
bp = arm_gic_get_binary_point(0) & 0x07;
return (7 - bp);
#else
return -RT_ERROR;
#endif
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param new_handler the interrupt service routine to be installed
* @param old_handler the old interrupt service routine
*/
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if (vector < MAX_HANDLERS)
{
old_handler = isr_table[vector].handler;
if (handler != RT_NULL)
{
#ifdef RT_USING_INTERRUPT_INFO
rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
#endif /* RT_USING_INTERRUPT_INFO */
isr_table[vector].handler = handler;
isr_table[vector].param = param;
}
}
return old_handler;
}
#ifdef RT_USING_SMP
void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
{
#ifdef BSP_USING_GIC
arm_gic_send_sgi(0, ipi_vector, cpu_mask, 0);
#endif
}
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)
{
/* note: ipi_vector maybe different with irq_vector */
rt_hw_interrupt_install(ipi_vector, ipi_isr_handler, 0, "IPI_HANDLER");
}
#endif

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-06 Bernard first version
*/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#include <rthw.h>
#include <board.h>
#define INT_IRQ 0x00
#define INT_FIQ 0x01
#define IRQ_MODE_TRIG_LEVEL (0x00) /* Trigger: level triggered interrupt */
#define IRQ_MODE_TRIG_EDGE (0x01) /* Trigger: edge triggered interrupt */
void rt_hw_vector_init(void);
void rt_hw_interrupt_init(void);
void rt_hw_interrupt_mask(int vector);
void rt_hw_interrupt_umask(int vector);
int rt_hw_interrupt_get_irq(void);
void rt_hw_interrupt_ack(int vector);
void rt_hw_interrupt_set_target_cpus(int vector, unsigned int cpu_mask);
unsigned int rt_hw_interrupt_get_target_cpus(int vector);
void rt_hw_interrupt_set_triger_mode(int vector, unsigned int mode);
unsigned int rt_hw_interrupt_get_triger_mode(int vector);
void rt_hw_interrupt_set_pending(int vector);
unsigned int rt_hw_interrupt_get_pending(int vector);
void rt_hw_interrupt_clear_pending(int vector);
void rt_hw_interrupt_set_priority(int vector, unsigned int priority);
unsigned int rt_hw_interrupt_get_priority(int vector);
void rt_hw_interrupt_set_priority_mask(unsigned int priority);
unsigned int rt_hw_interrupt_get_priority_mask(void);
int rt_hw_interrupt_set_prior_group_bits(unsigned int bits);
unsigned int rt_hw_interrupt_get_prior_group_bits(void);
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name);
#ifdef RT_USING_SMP
void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask);
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler);
#endif
#endif

View File

@ -27,8 +27,7 @@
*
* @return stack address
*/
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit)
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_addr, void *texit)
{
rt_ubase_t *stk;
rt_ubase_t current_el;

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-20 Bernard first version
*/
#include <rtthread.h>
#include <rthw.h>
#include <board.h>
#include <armv8.h>
#include <interrupt.h>
#ifdef RT_USING_FINSH
extern long list_thread(void);
#endif
/**
* this function will show registers of CPU
*
* @param regs the registers point
*/
void rt_hw_show_register(struct rt_hw_exp_stack *regs)
{
rt_kprintf("Execption:\n");
rt_kprintf("X00:0x%16.16p X01:0x%16.16p X02:0x%16.16p X03:0x%16.16p\n", (void *)regs->x0, (void *)regs->x1, (void *)regs->x2, (void *)regs->x3);
rt_kprintf("X04:0x%16.16p X05:0x%16.16p X06:0x%16.16p X07:0x%16.16p\n", (void *)regs->x4, (void *)regs->x5, (void *)regs->x6, (void *)regs->x7);
rt_kprintf("X08:0x%16.16p X09:0x%16.16p X10:0x%16.16p X11:0x%16.16p\n", (void *)regs->x8, (void *)regs->x9, (void *)regs->x10, (void *)regs->x11);
rt_kprintf("X12:0x%16.16p X13:0x%16.16p X14:0x%16.16p X15:0x%16.16p\n", (void *)regs->x12, (void *)regs->x13, (void *)regs->x14, (void *)regs->x15);
rt_kprintf("X16:0x%16.16p X17:0x%16.16p X18:0x%16.16p X19:0x%16.16p\n", (void *)regs->x16, (void *)regs->x17, (void *)regs->x18, (void *)regs->x19);
rt_kprintf("X20:0x%16.16p X21:0x%16.16p X22:0x%16.16p X23:0x%16.16p\n", (void *)regs->x20, (void *)regs->x21, (void *)regs->x22, (void *)regs->x23);
rt_kprintf("X24:0x%16.16p X25:0x%16.16p X26:0x%16.16p X27:0x%16.16p\n", (void *)regs->x24, (void *)regs->x25, (void *)regs->x26, (void *)regs->x27);
rt_kprintf("X28:0x%16.16p X29:0x%16.16p X30:0x%16.16p\n", (void *)regs->x28, (void *)regs->x29, (void *)regs->x30);
rt_kprintf("SPSR :0x%16.16p\n", (void *)regs->spsr);
rt_kprintf("EPC :0x%16.16p\n", (void *)regs->pc);
}
/**
* When comes across an instruction which it cannot handle,
* it takes the undefined instruction trap.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_error(struct rt_hw_exp_stack *regs)
{
rt_kprintf("error exception:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
void rt_hw_trap_irq(void)
{
#ifndef BSP_USING_GIC
void *param;
uint32_t irq;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
uint32_t value = 0;
value = IRQ_PEND_BASIC & 0x3ff;
#ifdef BSP_USING_CORETIMER
uint32_t cpu_id = 0;
#ifdef RT_USING_SMP
cpu_id = rt_hw_cpu_id();
#endif
uint32_t int_source = CORE_IRQSOURCE(cpu_id) & 0x3ff;
if (int_source & 0x02)
{
isr_func = isr_table[IRQ_ARM_TIMER].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[IRQ_ARM_TIMER].counter++;
#endif
if (isr_func)
{
param = isr_table[IRQ_ARM_TIMER].param;
isr_func(IRQ_ARM_TIMER, param);
}
}
#endif
/* local interrupt*/
if (value)
{
if (value & (1 << 8))
{
value = IRQ_PEND1;
irq = __rt_ffs(value) - 1;
}
else if (value & (1 << 9))
{
value = IRQ_PEND2;
irq = __rt_ffs(value) + 31;
}
else
{
value &= 0x0f;
irq = __rt_ffs(value) + 63;
}
/* get interrupt service routine */
isr_func = isr_table[irq].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[irq].counter++;
#endif
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[irq].param;
/* turn to interrupt service routine */
isr_func(irq, param);
}
}
#else
void *param;
int ir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
ir = rt_hw_interrupt_get_irq();
if (ir == 1023)
{
/* Spurious interrupt */
return;
}
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[ir].counter++;
#endif
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
}
/* end of interrupt */
rt_hw_interrupt_ack(ir);
#endif
}
void rt_hw_trap_fiq(void)
{
void *param;
int ir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
ir = rt_hw_interrupt_get_irq();
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
/* end of interrupt */
rt_hw_interrupt_ack(ir);
}

View File

@ -8,6 +8,6 @@ cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp') + Glob('*.S')
CPPPATH = [cwd]
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
group = DefineGroup('common', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Date Author Notes
* 2020-01-15 bigmagic the first version
* 2020-08-10 SummerGift support clang compiler
*/
.section ".text.entrypoint","ax"
.globl _start
_start:
/* Read cpu id */
mrs x1, mpidr_el1
and x1, x1, #3
cbz x1, cpu_setup /* If cpu id > 0, stop slave cores */
cpu_idle:
wfe
b cpu_idle
cpu_setup:
ldr x1, =_start
mrs x0, CurrentEL /* CurrentEL Register. bit 2, 3. Others reserved */
and x0, x0, #12 /* Clear reserved bits */
/* Running at EL3? */
cmp x0, #12 /* EL3 value is 0b1100 */
bne cpu_not_in_el3
/* Should never be executed, just for completeness. (EL3) */
mov x0, #(1 << 0) /* EL0 and EL1 are in Non-Secure state */
orr x0, x0, #(1 << 4) /* RES1 */
orr x0, x0, #(1 << 5) /* RES1 */
orr x0, x0, #(1 << 7) /* SMC instructions are undefined at EL1 and above */
orr x0, x0, #(1 << 8) /* HVC instructions are enabled at EL1 and above */
orr x0, x0, #(1 << 10) /* The next lower level is AArch64 */
msr scr_el3, x2
mov x2, #0x3c9
msr spsr_el3, x2 /* 0b1111001001 */
adr x2, cpu_not_in_el3
msr elr_el3, x2
eret /* Exception Return: from EL3, continue from cpu_not_in_el3 */
cpu_not_in_el3: /* Running at EL2 or EL1 */
cmp x0, #4 /* EL1 = 0100 */
beq cpu_in_el1 /* Halt this core if running in El1 */
cpu_in_el2:
msr sp_el1, x1
/* Enable CNTP for EL1 */
mrs x0, cnthctl_el2 /* Counter-timer Hypervisor Control register */
orr x0, x0, #3
msr cnthctl_el2, x0
msr cntvoff_el2, xzr
mov x0, #(1 << 31) /* Enable AArch64 in EL1 */
orr x0, x0, #(1 << 1) /* SWIO hardwired on Pi3 */
msr hcr_el2, x0
/* Change execution level to EL1 */
mov x2, #0x3c4
msr spsr_el2, x2 /* 0b1111000100 */
adr x2, cpu_in_el1
msr elr_el2, x2
eret
cpu_in_el1:
mov sp, x1 /* Set sp in el1 */
/* Avoid trap from SIMD or float point instruction */
mov x1, #0x00300000 /* Don't trap any SIMD/FP instructions in both EL0 and EL1 */
msr cpacr_el1, x1
mrs x1, sctlr_el1
orr x1, x1, #(1 << 12) /* Enable Instruction */
bic x1, x1, #(3 << 3) /* Disable SP Alignment check */
bic x1, x1, #(1 << 1) /* Disable Alignment check */
msr sctlr_el1, x1
ldr x1, =__bss_start
ldr w2, =__bss_size
clean_bss_loop:
cbz w2, jump_to_entry
str xzr, [x1], #8
sub w2, w2, #1
cbnz w2, clean_bss_loop
jump_to_entry:
b rtthread_startup
b cpu_idle /* For failsafe, halt this core too */

View File

@ -1,116 +0,0 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Date Author Notes
* 2020-01-15 bigmagic the first version
*/
.section ".text.entrypoint"
.set EL1_stack, __el1_stack
.global _start
// This symbol is set to 0x80000 in ld script. That is the address that raspi3's firmware
// loads 'kernel8.img' file in.
_start:
// read cpu id, stop slave cores
mrs x1, mpidr_el1 // MPIDR_EL1: Multi-Processor Affinity Register
and x1, x1, #3
cbz x1, .L__cpu_0 // .L prefix is the local label in ELF
// cpu id > 0, stop
// cpu id == 0 will also goto here after returned from entry() if possible
.L__current_cpu_idle:
wfe
b .L__current_cpu_idle
.L__cpu_0: // cpu id == 0
// set stack before our code
/* Define stack pointer for current exception level */
// ldr x2, =EL1_stack
// mov sp, x2
ldr x1, =init_el1_stack_limit
// set up EL1
mrs x0, CurrentEL // CurrentEL Register. bit 2, 3. Others reserved
and x0, x0, #12 // clear reserved bits
// running at EL3?
cmp x0, #12 // 1100b. So, EL3
bne .L__not_in_el3 // 11? !EL3 -> 5:
// should never be executed, just for completeness. (EL3)
mov x2, #0x5b1
msr scr_el3, x2 // SCR_ELn Secure Configuration Register
mov x2, #0x3c9
msr spsr_el3, x2 // SPSR_ELn. Saved Program Status Register. 1111001001
adr x2, .L__not_in_el3
msr elr_el3, x2
eret // Exception Return: from EL3, continue from .L__not_in_el3
// running at EL2 or EL1
.L__not_in_el3:
cmp x0, #4 // 0x04 0100 EL1
beq .L__in_el1 // EL1 -> 5:
// in EL2
msr sp_el1, x1 // Set sp of EL1 to _start
// enable CNTP for EL1
mrs x0, cnthctl_el2 // Counter-timer Hypervisor Control register
orr x0, x0, #3
msr cnthctl_el2, x0
msr cntvoff_el2, xzr
// enable AArch64 in EL1
mov x0, #(1 << 31) // AArch64
orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3
msr hcr_el2, x0
mrs x0, hcr_el2
// change execution level to EL1
mov x2, #0x3c4
msr spsr_el2, x2 // 1111000100
adr x2, .L__in_el1
msr elr_el2, x2
eret // exception return. from EL2. continue from .L__in_el1
.L__in_el1:
mov sp, x1 // in EL1. Set sp to _start
// Set CPACR_EL1 (Architecture Feature Access Control Register) to avoid trap from SIMD or float point instruction
mov x1, #0x00300000 // Don't trap any SIMD/FP instructions in both EL0 and EL1
msr cpacr_el1, x1
mrs x1, sctlr_el1
orr x1, x1, #(1 << 12)
bic x1, x1, #(3 << 3)
bic x1, x1, #(1 << 1)
msr sctlr_el1, x1
// clear bss
ldr x1, =__bss_start
ldr w2, =__bss_size
.L__clean_bss_loop:
cbz w2, .L__jump_to_entry
str xzr, [x1], #8
sub w2, w2, #1
cbnz w2, .L__clean_bss_loop
// jump to C code, should not return
.L__jump_to_entry:
bl entry
// for failsafe, halt this core too
b .L__current_cpu_idle
.bss
.align 3
init_el1_stack:
.space 4096
init_el1_stack_limit:

View File

@ -1,202 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018/5/3 Bernard first version
* 2019-07-28 zdzn add smp support
* 2019-08-09 zhangjun fixup the problem of smp startup and scheduling issues,
* write addr to mailbox3 to startup smp, and we use mailbox0 for ipi
* 2021-07-31 GuEe-GUI Add gic pl390 branch
*/
#include <rthw.h>
#include <board.h>
#include <rtthread.h>
#include "cp15.h"
#include "armv8.h"
#include "interrupt.h"
#ifdef BSP_USING_GIC390
#include <gic_pl390.h>
#endif
#define MAX_HANDLERS 72
#ifdef RT_USING_SMP
#define rt_interrupt_nest rt_cpu_self()->irq_nest
#else
extern volatile rt_uint8_t rt_interrupt_nest;
#endif
extern int system_vectors;
/* exception and interrupt handler table */
struct rt_irq_desc isr_table[MAX_HANDLERS];
rt_ubase_t rt_interrupt_from_thread;
rt_ubase_t rt_interrupt_to_thread;
rt_ubase_t rt_thread_switch_interrupt_flag;
void rt_hw_vector_init(void)
{
rt_hw_set_current_vbar((rt_ubase_t)&system_vectors); // cpu_gcc.S
}
#ifndef BSP_USING_GIC
static void default_isr_handler(int vector, void *param)
{
#ifdef RT_USING_SMP
rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector);
#else
rt_kprintf("unhandled irq: %d\n",vector);
#endif
}
#endif
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
#ifdef BSP_USING_GIC390
arm_gic_irq_init();
#else
rt_uint32_t index;
/* mask all of interrupts */
IRQ_DISABLE_BASIC = 0x000000ff;
IRQ_DISABLE1 = 0xffffffff;
IRQ_DISABLE2 = 0xffffffff;
for (index = 0; index < MAX_HANDLERS; index ++)
{
isr_table[index].handler = default_isr_handler;
isr_table[index].param = NULL;
#ifdef RT_USING_INTERRUPT_INFO
rt_strncpy(isr_table[index].name, "unknown", RT_NAME_MAX);
isr_table[index].counter = 0;
#endif
}
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrupt_flag = 0;
#endif
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int vector)
{
#ifdef BSP_USING_GIC390
arm_gic_mask(vector);
#else
if (vector < 32)
{
IRQ_DISABLE1 = (1 << vector);
}
else if (vector<64)
{
vector = vector % 32;
IRQ_DISABLE2 = (1 << vector);
}
else
{
vector = vector - 64;
IRQ_DISABLE_BASIC = (1 << vector);
}
#endif
}
/**
* This function will un-mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_umask(int vector)
{
#ifdef BSP_USING_GIC390
arm_gic_umask(vector);
#else
if (vector < 32)
{
IRQ_ENABLE1 = (1 << vector);
}
else if (vector < 64)
{
vector = vector % 32;
IRQ_ENABLE2 = (1 << vector);
}
else
{
vector = vector - 64;
IRQ_ENABLE_BASIC = (1 << vector);
}
#endif
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param new_handler the interrupt service routine to be installed
* @param old_handler the old interrupt service routine
*/
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if (vector < MAX_HANDLERS)
{
old_handler = isr_table[vector].handler;
if (handler != RT_NULL)
{
#ifdef RT_USING_INTERRUPT_INFO
rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
#endif /* RT_USING_INTERRUPT_INFO */
isr_table[vector].handler = handler;
isr_table[vector].param = param;
}
}
return old_handler;
}
#ifdef RT_USING_SMP
void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
{
__DSB();
if(cpu_mask & 0x1)
{
send_ipi_msg(0, ipi_vector);
}
if(cpu_mask & 0x2)
{
send_ipi_msg(1, ipi_vector);
}
if(cpu_mask & 0x4)
{
send_ipi_msg(2, ipi_vector);
}
if(cpu_mask & 0x8)
{
send_ipi_msg(3, ipi_vector);
}
__DSB();
}
#endif
#ifdef RT_USING_SMP
void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler)
{
/* note: ipi_vector maybe different with irq_vector */
rt_hw_interrupt_install(ipi_vector, ipi_isr_handler, 0, "IPI_HANDLER");
}
#endif

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-04-16 bigmagic first version
*/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#include <rthw.h>
#include <board.h>
#define INT_IRQ 0x00
#define INT_FIQ 0x01
void rt_hw_interrupt_init(void);
void rt_hw_interrupt_mask(int vector);
void rt_hw_interrupt_umask(int vector);
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name);
#endif

View File

@ -1,90 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-09-23 Bernard the first version
* 2011-10-05 Bernard add thumb mode
*/
#include <rtthread.h>
#include <board.h>
#include <armv8.h>
#define INITIAL_SPSR_EL3 (PSTATE_EL3 | SP_EL0)
#define INITIAL_SPSR_EL2 (PSTATE_EL2 | SP_EL0)
#define INITIAL_SPSR_EL1 (PSTATE_EL1 | SP_EL0)
/**
* This function will initialize thread stack
*
* @param tentry the entry of thread
* @param parameter the parameter of entry
* @param stack_addr the beginning stack address
* @param texit the function will be called when thread exit
*
* @return stack address
*/
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit)
{
rt_ubase_t *stk;
rt_ubase_t current_el;
stk = (rt_ubase_t*)stack_addr;
*(--stk) = ( rt_ubase_t ) 11; /* X1 */
*(--stk) = ( rt_ubase_t ) parameter; /* X0 */
*(--stk) = ( rt_ubase_t ) 33; /* X3 */
*(--stk) = ( rt_ubase_t ) 22; /* X2 */
*(--stk) = ( rt_ubase_t ) 55; /* X5 */
*(--stk) = ( rt_ubase_t ) 44; /* X4 */
*(--stk) = ( rt_ubase_t ) 77; /* X7 */
*(--stk) = ( rt_ubase_t ) 66; /* X6 */
*(--stk) = ( rt_ubase_t ) 99; /* X9 */
*(--stk) = ( rt_ubase_t ) 88; /* X8 */
*(--stk) = ( rt_ubase_t ) 11; /* X11 */
*(--stk) = ( rt_ubase_t ) 10; /* X10 */
*(--stk) = ( rt_ubase_t ) 13; /* X13 */
*(--stk) = ( rt_ubase_t ) 12; /* X12 */
*(--stk) = ( rt_ubase_t ) 15; /* X15 */
*(--stk) = ( rt_ubase_t ) 14; /* X14 */
*(--stk) = ( rt_ubase_t ) 17; /* X17 */
*(--stk) = ( rt_ubase_t ) 16; /* X16 */
*(--stk) = ( rt_ubase_t ) 19; /* X19 */
*(--stk) = ( rt_ubase_t ) 18; /* X18 */
*(--stk) = ( rt_ubase_t ) 21; /* X21 */
*(--stk) = ( rt_ubase_t ) 20; /* X20 */
*(--stk) = ( rt_ubase_t ) 23; /* X23 */
*(--stk) = ( rt_ubase_t ) 22; /* X22 */
*(--stk) = ( rt_ubase_t ) 25; /* X25 */
*(--stk) = ( rt_ubase_t ) 24; /* X24 */
*(--stk) = ( rt_ubase_t ) 27; /* X27 */
*(--stk) = ( rt_ubase_t ) 26; /* X26 */
*(--stk) = ( rt_ubase_t ) 29; /* X29 */
*(--stk) = ( rt_ubase_t ) 28; /* X28 */
*(--stk) = ( rt_ubase_t ) 0; /* XZR - has no effect, used so there are an even number of registers. */
*(--stk) = ( rt_ubase_t ) texit; /* X30 - procedure call link register. */
current_el = rt_hw_get_current_el();
if(current_el == 3)
{
*(--stk) = INITIAL_SPSR_EL3;
}
else if(current_el == 2)
{
*(--stk) = INITIAL_SPSR_EL2;
}
else
{
*(--stk) = INITIAL_SPSR_EL1;
}
*(--stk) = ( rt_ubase_t ) tentry; /* Exception return address. */
/* return task's current stack address */
return (rt_uint8_t *)stk;
}

View File

@ -1,225 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Date Author Notes
* 2018-10-06 ZhaoXiaowei the first version
* 2021-07-31 GuEe-GUI Add gic_pl390 branch
*/
#include <rtthread.h>
#include <rthw.h>
#include "interrupt.h"
#include "armv8.h"
#ifdef BSP_USING_GIC390
#include <gic_pl390.h>
#endif
extern struct rt_thread *rt_current_thread;
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
extern long list_thread(void);
#endif
/**
* this function will show registers of CPU
*
* @param regs the registers point
*/
void rt_hw_show_register(struct rt_hw_exp_stack *regs)
{
rt_kprintf("Execption:\n");
rt_kprintf("r00:0x%16.16lx r01:0x%16.16lx r02:0x%16.16lx r03:0x%16.16lx\n", regs->x0, regs->x1, regs->x2, regs->x3);
rt_kprintf("r04:0x%16.16lx r05:0x%16.16lx r06:0x%16.16lx r07:0x%16.16lx\n", regs->x4, regs->x5, regs->x6, regs->x7);
rt_kprintf("r08:0x%16.16lx r09:0x%16.16lx r10:0x%16.16lx r11:0x%16.16lx\n", regs->x8, regs->x9, regs->x10, regs->x11);
rt_kprintf("r12:0x%16.16lx r13:0x%16.16lx r14:0x%16.16lx r15:0x%16.16lx\n", regs->x12, regs->x13, regs->x14, regs->x15);
rt_kprintf("r16:0x%16.16lx r17:0x%16.16lx r18:0x%16.16lx r19:0x%16.16lx\n", regs->x16, regs->x17, regs->x18, regs->x19);
rt_kprintf("r20:0x%16.16lx r21:0x%16.16lx r22:0x%16.16lx r23:0x%16.16lx\n", regs->x20, regs->x21, regs->x22, regs->x23);
rt_kprintf("r24:0x%16.16lx r25:0x%16.16lx r26:0x%16.16lx r27:0x%16.16lx\n", regs->x24, regs->x25, regs->x26, regs->x27);
rt_kprintf("r28:0x%16.16lx r29:0x%16.16lx r30:0x%16.16lx\n", regs->x28, regs->x29, regs->x30);
rt_kprintf("spsr:0x%16.16lx\n", regs->spsr);
rt_kprintf("return pc:0x%16.16lx\n", regs->pc);
}
/**
* When comes across an instruction which it cannot handle,
* it takes the undefined instruction trap.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_error(struct rt_hw_exp_stack *regs)
{
rt_kprintf("error exception:\n");
rt_hw_show_register(regs);
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
list_thread();
#endif
rt_hw_cpu_shutdown();
}
#define GIC_ACK_INTID_MASK (0x000003ff)
#define CORE0_IRQ_SOURCE (0x40000060)
void rt_hw_trap_irq(void)
{
void *param;
uint32_t irq;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
#ifndef BSP_USING_GIC390
uint32_t value = 0;
value = IRQ_PEND_BASIC & 0x3ff;
#ifdef BSP_USING_CORETIMER
uint32_t int_source = HWREG32(CORE0_IRQ_SOURCE) & 0x3ff;
if (int_source & 0x02)
{
isr_func = isr_table[IRQ_ARM_TIMER].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[IRQ_ARM_TIMER].counter++;
#endif
if (isr_func)
{
param = isr_table[IRQ_ARM_TIMER].param;
isr_func(IRQ_ARM_TIMER, param);
}
}
#endif
/* local interrupt*/
if (value)
{
if (value & (1 << 8))
{
value = IRQ_PEND1;
irq = __rt_ffs(value) - 1;
}
else if (value & (1 << 9))
{
value = IRQ_PEND2;
irq = __rt_ffs(value) + 31;
}
else
{
value &= 0x0f;
irq = __rt_ffs(value) + 63;
}
#else
irq = arm_gic_get_active_irq();
if (irq == GIC390_IRQ_NONE)
{
/* Spurious interrupt */
return;
}
#endif
/* get interrupt service routine */
isr_func = isr_table[irq].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[irq].counter++;
#endif
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[irq].param;
/* turn to interrupt service routine */
isr_func(irq, param);
}
#ifndef BSP_USING_GIC390
}
#else
/* end of interrupt */
arm_gic_ack(irq);
#endif
}
void rt_hw_trap_fiq(void)
{
#ifndef BSP_USING_GIC390
void *param;
uint32_t irq;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
uint32_t value = 0;
value = IRQ_PEND_BASIC & 0x3ff;
#ifdef RT_USING_SMP
uint32_t mailbox_data;
uint32_t cpu_id = rt_hw_cpu_id();
uint32_t int_source = CORE_IRQSOURCE(cpu_id);
mailbox_data = IPI_MAILBOX_CLEAR(cpu_id);
if (int_source & 0x0f)
{
if (int_source & 0x08)
{
isr_func = isr_table[IRQ_ARM_TIMER].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[IRQ_ARM_TIMER].counter++;
#endif
if (isr_func)
{
param = isr_table[IRQ_ARM_TIMER].param;
isr_func(IRQ_ARM_TIMER, param);
}
}
}
if (int_source & 0xf0)
{
/*it's a ipi interrupt*/
if (mailbox_data & 0x1)
{
/* clear mailbox */
IPI_MAILBOX_CLEAR(cpu_id) = mailbox_data;
isr_func = isr_table[IRQ_ARM_MAILBOX].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[IRQ_ARM_MAILBOX].counter++;
#endif
if (isr_func)
{
param = isr_table[IRQ_ARM_MAILBOX].param;
isr_func(IRQ_ARM_MAILBOX, param);
}
}
else
CORE_MAILBOX3_CLEAR(cpu_id) = mailbox_data;
}
#endif
/* local interrupt*/
if (value)
{
if (value & (1 << 8))
{
value = IRQ_PEND1;
irq = __rt_ffs(value) - 1;
}
else if (value & (1 << 9))
{
value = IRQ_PEND2;
irq = __rt_ffs(value) + 31;
}
else
{
value &= 0x0f;
irq = __rt_ffs(value) + 63;
}
/* get interrupt service routine */
isr_func = isr_table[irq].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[irq].counter++;
#endif
if (irq > 1)
rt_kprintf("interrupt fiq %d\n", irq);
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[irq].param;
/* turn to interrupt service routine */
isr_func(irq, param);
}
}
#endif
}

View File

@ -1,13 +0,0 @@
# RT-Thread building script for component
from building import *
Import('rtconfig')
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp') + Glob('*.S')
CPPPATH = [cwd]
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -1,111 +0,0 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Date Author Notes
* 2020-01-15 bigmagic the first version
*/
.section ".text.entrypoint"
.set EL1_stack, __el1_stack
.global _start
// This symbol is set to 0x80000 in ld script. That is the address that raspi3's firmware
// loads 'kernel8.img' file in.
_start:
// read cpu id, stop slave cores
mrs x1, mpidr_el1 // MPIDR_EL1: Multi-Processor Affinity Register
and x1, x1, #3
cbz x1, .L__cpu_0 // .L prefix is the local label in ELF
// cpu id > 0, stop
// cpu id == 0 will also goto here after returned from entry() if possible
.L__current_cpu_idle:
wfe
b .L__current_cpu_idle
.L__cpu_0: // cpu id == 0
// set stack before our code
/* Define stack pointer for current exception level */
// ldr x2, =EL1_stack
// mov sp, x2
ldr x1, =_start
// set up EL1
mrs x0, CurrentEL // CurrentEL Register. bit 2, 3. Others reserved
and x0, x0, #12 // clear reserved bits
// running at EL3?
cmp x0, #12 // 1100b. So, EL3
bne .L__not_in_el3 // 11? !EL3 -> 5:
// should never be executed, just for completeness. (EL3)
mov x2, #0x5b1
msr scr_el3, x2 // SCR_ELn Secure Configuration Register
mov x2, #0x3c9
msr spsr_el3, x2 // SPSR_ELn. Saved Program Status Register. 1111001001
adr x2, .L__not_in_el3
msr elr_el3, x2
eret // Exception Return: from EL3, continue from .L__not_in_el3
// running at EL2 or EL1
.L__not_in_el3:
cmp x0, #4 // 0x04 0100 EL1
beq .L__in_el1 // EL1 -> 5:
// in EL2
msr sp_el1, x1 // Set sp of EL1 to _start
// enable CNTP for EL1
mrs x0, cnthctl_el2 // Counter-timer Hypervisor Control register
orr x0, x0, #3
msr cnthctl_el2, x0
msr cntvoff_el2, xzr
// enable AArch64 in EL1
mov x0, #(1 << 31) // AArch64
orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3
msr hcr_el2, x0
mrs x0, hcr_el2
// change execution level to EL1
mov x2, #0x3c4
msr spsr_el2, x2 // 1111000100
adr x2, .L__in_el1
msr elr_el2, x2
eret // exception return. from EL2. continue from .L__in_el1
.L__in_el1:
mov sp, x1 // in EL1. Set sp to _start
// Set CPACR_EL1 (Architecture Feature Access Control Register) to avoid trap from SIMD or float point instruction
mov x1, #0x00300000 // Don't trap any SIMD/FP instructions in both EL0 and EL1
msr cpacr_el1, x1
mrs x1, sctlr_el1
orr x1, x1, #(1 << 12)
bic x1, x1, #(3 << 3)
bic x1, x1, #(1 << 1)
msr sctlr_el1, x1
// clear bss
ldr x1, =__bss_start
ldr w2, =__bss_size
.L__clean_bss_loop:
cbz w2, .L__jump_to_entry
str xzr, [x1], #8
sub w2, w2, #1
cbnz w2, .L__clean_bss_loop
// jump to C code, should not return
.L__jump_to_entry:
bl entry
// for failsafe, halt this core too
b .L__current_cpu_idle

View File

@ -1,118 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-04-16 bigmagic first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <gic_pl400.h>
#include <board.h>
#include <armv8.h>
#define MAX_HANDLERS 256
#define GIC_ACK_INTID_MASK 0x000003ff
#ifdef RT_USING_SMP
#define rt_interrupt_nest rt_cpu_self()->irq_nest
#else
extern volatile rt_uint8_t rt_interrupt_nest;
#endif
extern int system_vectors;
/* exception and interrupt handler table */
struct rt_irq_desc isr_table[MAX_HANDLERS];
rt_ubase_t rt_interrupt_from_thread;
rt_ubase_t rt_interrupt_to_thread;
rt_ubase_t rt_thread_switch_interrupt_flag;
void rt_hw_vector_init(void)
{
rt_hw_set_current_vbar((rt_ubase_t)&system_vectors); // cpu_gcc.S
}
/**
* This function will initialize hardware interrupt
*/
void rt_hw_interrupt_init(void)
{
rt_uint32_t gic_cpu_base = 0;
rt_uint32_t gic_dist_base = 0;
/* initialize ARM GIC */
gic_dist_base = GIC_PL400_DISTRIBUTOR_PPTR;
gic_cpu_base = GIC_PL400_CONTROLLER_PPTR;
arm_gic_dist_init(0, gic_dist_base, 0);
arm_gic_cpu_init(0, gic_cpu_base);
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param new_handler the interrupt service routine to be installed
* @param old_handler the old interrupt service routine
*/
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if (vector < MAX_HANDLERS)
{
old_handler = isr_table[vector].handler;
if (handler != RT_NULL)
{
#ifdef RT_USING_INTERRUPT_INFO
rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
#endif /* RT_USING_INTERRUPT_INFO */
isr_table[vector].handler = handler;
isr_table[vector].param = param;
}
}
return old_handler;
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int vector)
{
arm_gic_mask(0, vector);
}
/**
* This function will un-mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_umask(int vector)
{
arm_gic_umask(0, vector);
}
/**
* This function returns the active interrupt number.
* @param none
*/
int rt_hw_interrupt_get_irq(void)
{
return arm_gic_get_active_irq(0) & GIC_ACK_INTID_MASK;
}
/**
* This function acknowledges the interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_ack(int vector)
{
arm_gic_ack(0, vector);
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-04-16 bigmagic first version
*/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#include <rthw.h>
#include <board.h>
#define INT_IRQ 0x00
#define INT_FIQ 0x01
void rt_hw_interrupt_init(void);
void rt_hw_interrupt_mask(int vector);
void rt_hw_interrupt_umask(int vector);
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name);
#endif

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Date Author Notes
* 2018-10-06 ZhaoXiaowei the first version
*/
#include <rtthread.h>
#include <rthw.h>
#include "interrupt.h"
#include "armv8.h"
extern struct rt_thread *rt_current_thread;
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
extern long list_thread(void);
#endif
/**
* this function will show registers of CPU
*
* @param regs the registers point
*/
void rt_hw_show_register(struct rt_hw_exp_stack *regs)
{
rt_kprintf("Execption:\n");
rt_kprintf("r00:0x%16.16lx r01:0x%16.16lx r02:0x%16.16lx r03:0x%16.16lx\n", regs->x0, regs->x1, regs->x2, regs->x3);
rt_kprintf("r04:0x%16.16lx r05:0x%16.16lx r06:0x%16.16lx r07:0x%16.16lx\n", regs->x4, regs->x5, regs->x6, regs->x7);
rt_kprintf("r08:0x%16.16lx r09:0x%16.16lx r10:0x%16.16lx r11:0x%16.16lx\n", regs->x8, regs->x9, regs->x10, regs->x11);
rt_kprintf("r12:0x%16.16lx r13:0x%16.16lx r14:0x%16.16lx r15:0x%16.16lx\n", regs->x12, regs->x13, regs->x14, regs->x15);
rt_kprintf("r16:0x%16.16lx r17:0x%16.16lx r18:0x%16.16lx r19:0x%16.16lx\n", regs->x16, regs->x17, regs->x18, regs->x19);
rt_kprintf("r20:0x%16.16lx r21:0x%16.16lx r22:0x%16.16lx r23:0x%16.16lx\n", regs->x20, regs->x21, regs->x22, regs->x23);
rt_kprintf("r24:0x%16.16lx r25:0x%16.16lx r26:0x%16.16lx r27:0x%16.16lx\n", regs->x24, regs->x25, regs->x26, regs->x27);
rt_kprintf("r28:0x%16.16lx r29:0x%16.16lx r30:0x%16.16lx\n", regs->x28, regs->x29, regs->x30);
rt_kprintf("spsr:0x%16.16lx\n", regs->spsr);
rt_kprintf("return pc:0x%16.16lx\n", regs->pc);
}
/**
* When comes across an instruction which it cannot handle,
* it takes the undefined instruction trap.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_error(struct rt_hw_exp_stack *regs)
{
rt_kprintf("error exception:\n");
rt_hw_show_register(regs);
#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS)
list_thread();
#endif
rt_hw_cpu_shutdown();
}
#define GIC_ACK_INTID_MASK 0x000003ff
int rt_hw_interrupt_get_irq(void);
void rt_hw_interrupt_ack(int fiq_irq);
void rt_hw_trap_irq(void)
{
void *param;
int ir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
ir = rt_hw_interrupt_get_irq();
if (ir == 1023)
{
/* Spurious interrupt */
return;
}
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[ir].counter++;
#endif
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
}
/* end of interrupt */
rt_hw_interrupt_ack(ir);
}
void rt_hw_trap_fiq(void)
{
}