Make 'qemu-vexpress-a9' and 'imx6ul' use the same libcpu code.
This commit is contained in:
parent
efd8b404a3
commit
2eb1bef773
|
@ -0,0 +1,358 @@
|
|||
#
|
||||
# Automatically generated file; DO NOT EDIT.
|
||||
# RT-Thread Configuration
|
||||
#
|
||||
CONFIG_BOARD_IMX6UL=y
|
||||
|
||||
#
|
||||
# RT-Thread Kernel
|
||||
#
|
||||
CONFIG_RT_NAME_MAX=8
|
||||
# CONFIG_RT_USING_SMP is not set
|
||||
CONFIG_RT_ALIGN_SIZE=4
|
||||
# CONFIG_RT_THREAD_PRIORITY_8 is not set
|
||||
CONFIG_RT_THREAD_PRIORITY_32=y
|
||||
# CONFIG_RT_THREAD_PRIORITY_256 is not set
|
||||
CONFIG_RT_THREAD_PRIORITY_MAX=32
|
||||
CONFIG_RT_TICK_PER_SECOND=100
|
||||
CONFIG_RT_USING_OVERFLOW_CHECK=y
|
||||
CONFIG_RT_USING_HOOK=y
|
||||
CONFIG_RT_USING_IDLE_HOOK=y
|
||||
CONFIG_RT_IDEL_HOOK_LIST_SIZE=4
|
||||
CONFIG_IDLE_THREAD_STACK_SIZE=256
|
||||
# CONFIG_RT_USING_TIMER_SOFT is not set
|
||||
CONFIG_RT_DEBUG=y
|
||||
# CONFIG_RT_DEBUG_INIT_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_THREAD_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_IPC_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_TIMER_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_IRQ_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_MEM_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_SLAB_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set
|
||||
# CONFIG_RT_DEBUG_MODULE_CONFIG is not set
|
||||
|
||||
#
|
||||
# Inter-Thread communication
|
||||
#
|
||||
CONFIG_RT_USING_SEMAPHORE=y
|
||||
CONFIG_RT_USING_MUTEX=y
|
||||
CONFIG_RT_USING_EVENT=y
|
||||
CONFIG_RT_USING_MAILBOX=y
|
||||
CONFIG_RT_USING_MESSAGEQUEUE=y
|
||||
# CONFIG_RT_USING_SIGNALS is not set
|
||||
|
||||
#
|
||||
# Memory Management
|
||||
#
|
||||
CONFIG_RT_USING_MEMPOOL=y
|
||||
# CONFIG_RT_USING_MEMHEAP is not set
|
||||
# CONFIG_RT_USING_NOHEAP is not set
|
||||
CONFIG_RT_USING_SMALL_MEM=y
|
||||
# CONFIG_RT_USING_SLAB is not set
|
||||
# CONFIG_RT_USING_MEMTRACE is not set
|
||||
CONFIG_RT_USING_HEAP=y
|
||||
|
||||
#
|
||||
# Kernel Device Object
|
||||
#
|
||||
CONFIG_RT_USING_DEVICE=y
|
||||
# CONFIG_RT_USING_DEVICE_OPS is not set
|
||||
# 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=0x40001
|
||||
CONFIG_ARCH_ARM=y
|
||||
CONFIG_ARCH_ARM_CORTEX_A=y
|
||||
CONFIG_ARCH_ARM_CORTEX_A7=y
|
||||
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
|
||||
|
||||
#
|
||||
# RT-Thread Components
|
||||
#
|
||||
CONFIG_RT_USING_COMPONENTS_INIT=y
|
||||
CONFIG_RT_USING_USER_MAIN=y
|
||||
CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048
|
||||
CONFIG_RT_MAIN_THREAD_PRIORITY=10
|
||||
|
||||
#
|
||||
# C++ features
|
||||
#
|
||||
# CONFIG_RT_USING_CPLUSPLUS is not set
|
||||
|
||||
#
|
||||
# Command shell
|
||||
#
|
||||
CONFIG_RT_USING_FINSH=y
|
||||
CONFIG_FINSH_THREAD_NAME="tshell"
|
||||
CONFIG_FINSH_USING_HISTORY=y
|
||||
CONFIG_FINSH_HISTORY_LINES=5
|
||||
CONFIG_FINSH_USING_SYMTAB=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
|
||||
|
||||
#
|
||||
# Device virtual file system
|
||||
#
|
||||
CONFIG_RT_USING_DFS=y
|
||||
CONFIG_DFS_USING_WORKDIR=y
|
||||
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_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
|
||||
#
|
||||
CONFIG_RT_USING_DEVICE_IPC=y
|
||||
CONFIG_RT_PIPE_BUFSZ=512
|
||||
CONFIG_RT_USING_SERIAL=y
|
||||
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_PIN=y
|
||||
# CONFIG_RT_USING_ADC 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_MTD is not set
|
||||
# CONFIG_RT_USING_PM is not set
|
||||
# CONFIG_RT_USING_RTC is not set
|
||||
# CONFIG_RT_USING_SDIO is not set
|
||||
# CONFIG_RT_USING_SPI is not set
|
||||
# CONFIG_RT_USING_WDT is not set
|
||||
# CONFIG_RT_USING_AUDIO is not set
|
||||
# CONFIG_RT_USING_SENSOR is not set
|
||||
|
||||
#
|
||||
# Using WiFi
|
||||
#
|
||||
# CONFIG_RT_USING_WIFI is not set
|
||||
|
||||
#
|
||||
# Using USB
|
||||
#
|
||||
# CONFIG_RT_USING_USB_HOST is not set
|
||||
# CONFIG_RT_USING_USB_DEVICE is not set
|
||||
|
||||
#
|
||||
# POSIX layer and C standard library
|
||||
#
|
||||
CONFIG_RT_USING_LIBC=y
|
||||
# CONFIG_RT_USING_PTHREADS is not set
|
||||
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_AIO is not set
|
||||
# CONFIG_RT_USING_MODULE is not set
|
||||
|
||||
#
|
||||
# Network
|
||||
#
|
||||
|
||||
#
|
||||
# Socket abstraction layer
|
||||
#
|
||||
# CONFIG_RT_USING_SAL is not set
|
||||
|
||||
#
|
||||
# light weight TCP/IP stack
|
||||
#
|
||||
# CONFIG_RT_USING_LWIP is not set
|
||||
|
||||
#
|
||||
# Modbus master and slave stack
|
||||
#
|
||||
# CONFIG_RT_USING_MODBUS is not set
|
||||
|
||||
#
|
||||
# AT commands
|
||||
#
|
||||
# CONFIG_RT_USING_AT is not set
|
||||
|
||||
#
|
||||
# VBUS(Virtual Software BUS)
|
||||
#
|
||||
# CONFIG_RT_USING_VBUS is not set
|
||||
|
||||
#
|
||||
# Utilities
|
||||
#
|
||||
# CONFIG_RT_USING_LOGTRACE is not set
|
||||
# CONFIG_RT_USING_RYM is not set
|
||||
# CONFIG_RT_USING_ULOG is not set
|
||||
# CONFIG_RT_USING_UTEST is not set
|
||||
# CONFIG_RT_USING_LWP is not set
|
||||
|
||||
#
|
||||
# RT-Thread online packages
|
||||
#
|
||||
|
||||
#
|
||||
# IoT - internet of things
|
||||
#
|
||||
# CONFIG_PKG_USING_PAHOMQTT is not set
|
||||
# CONFIG_PKG_USING_WEBCLIENT is not set
|
||||
# CONFIG_PKG_USING_WEBNET is not set
|
||||
# CONFIG_PKG_USING_MONGOOSE is not set
|
||||
# CONFIG_PKG_USING_WEBTERMINAL is not set
|
||||
# CONFIG_PKG_USING_CJSON is not set
|
||||
# CONFIG_PKG_USING_JSMN is not set
|
||||
# CONFIG_PKG_USING_LIBMODBUS is not set
|
||||
# CONFIG_PKG_USING_LJSON is not set
|
||||
# CONFIG_PKG_USING_EZXML is not set
|
||||
# CONFIG_PKG_USING_NANOPB is not set
|
||||
|
||||
#
|
||||
# Wi-Fi
|
||||
#
|
||||
|
||||
#
|
||||
# Marvell WiFi
|
||||
#
|
||||
# CONFIG_PKG_USING_WLANMARVELL is not set
|
||||
|
||||
#
|
||||
# Wiced WiFi
|
||||
#
|
||||
# CONFIG_PKG_USING_WLAN_WICED is not set
|
||||
# CONFIG_PKG_USING_RW007 is not set
|
||||
# CONFIG_PKG_USING_COAP is not set
|
||||
# CONFIG_PKG_USING_NOPOLL is not set
|
||||
# CONFIG_PKG_USING_NETUTILS is not set
|
||||
# CONFIG_PKG_USING_AT_DEVICE is not set
|
||||
# CONFIG_PKG_USING_WIZNET is not set
|
||||
|
||||
#
|
||||
# IoT Cloud
|
||||
#
|
||||
# CONFIG_PKG_USING_ONENET is not set
|
||||
# CONFIG_PKG_USING_GAGENT_CLOUD is not set
|
||||
# CONFIG_PKG_USING_ALI_IOTKIT is not set
|
||||
# CONFIG_PKG_USING_AZURE is not set
|
||||
# CONFIG_PKG_USING_TENCENT_IOTKIT is not set
|
||||
# CONFIG_PKG_USING_NIMBLE is not set
|
||||
# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
|
||||
|
||||
#
|
||||
# security packages
|
||||
#
|
||||
# CONFIG_PKG_USING_MBEDTLS is not set
|
||||
# CONFIG_PKG_USING_libsodium is not set
|
||||
# CONFIG_PKG_USING_TINYCRYPT is not set
|
||||
|
||||
#
|
||||
# language packages
|
||||
#
|
||||
# CONFIG_PKG_USING_LUA is not set
|
||||
# CONFIG_PKG_USING_JERRYSCRIPT is not set
|
||||
# CONFIG_PKG_USING_MICROPYTHON is not set
|
||||
|
||||
#
|
||||
# multimedia packages
|
||||
#
|
||||
# CONFIG_PKG_USING_OPENMV is not set
|
||||
# CONFIG_PKG_USING_MUPDF is not set
|
||||
|
||||
#
|
||||
# tools packages
|
||||
#
|
||||
# CONFIG_PKG_USING_CMBACKTRACE is not set
|
||||
# CONFIG_PKG_USING_EASYFLASH is not set
|
||||
# CONFIG_PKG_USING_EASYLOGGER is not set
|
||||
# CONFIG_PKG_USING_SYSTEMVIEW is not set
|
||||
# CONFIG_PKG_USING_RDB is not set
|
||||
# CONFIG_PKG_USING_QRCODE is not set
|
||||
# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
|
||||
# CONFIG_PKG_USING_ADBD is not set
|
||||
|
||||
#
|
||||
# system packages
|
||||
#
|
||||
# CONFIG_PKG_USING_GUIENGINE is not set
|
||||
# CONFIG_PKG_USING_PERSIMMON 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_SQLITE is not set
|
||||
# CONFIG_PKG_USING_RTI is not set
|
||||
# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
|
||||
# CONFIG_PKG_USING_CMSIS is not set
|
||||
# CONFIG_PKG_USING_DFS_YAFFS is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS is not set
|
||||
|
||||
#
|
||||
# peripheral libraries and drivers
|
||||
#
|
||||
|
||||
#
|
||||
# sensors drivers
|
||||
#
|
||||
# CONFIG_PKG_USING_LSM6DSL is not set
|
||||
# CONFIG_PKG_USING_LPS22HB is not set
|
||||
# CONFIG_PKG_USING_HTS221 is not set
|
||||
# CONFIG_PKG_USING_LSM303AGR is not set
|
||||
# CONFIG_PKG_USING_BME280 is not set
|
||||
# CONFIG_PKG_USING_BMA400 is not set
|
||||
# CONFIG_PKG_USING_BMI160_BMX160 is not set
|
||||
# CONFIG_PKG_USING_SPL0601 is not set
|
||||
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
|
||||
# CONFIG_PKG_USING_SHT2X is not set
|
||||
# CONFIG_PKG_USING_AHT10 is not set
|
||||
# CONFIG_PKG_USING_AP3216C 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
|
||||
# CONFIG_PKG_USING_BUTTON is not set
|
||||
# CONFIG_PKG_USING_MPU6XXX is not set
|
||||
# CONFIG_PKG_USING_PCF8574 is not set
|
||||
# CONFIG_PKG_USING_SX12XX is not set
|
||||
# CONFIG_PKG_USING_KENDRYTE_SDK 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_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
|
||||
|
||||
#
|
||||
# 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_RT_USING_UART0 is not set
|
||||
CONFIG_RT_USING_UART1=y
|
|
@ -20,6 +20,15 @@
|
|||
#include <epit.h>
|
||||
#include <cortex_a.h>
|
||||
|
||||
#include <mmu.h>
|
||||
|
||||
struct mem_desc platform_mem_desc[] = {
|
||||
{0x00000000, 0x80000000, 0x00000000, DEVICE_MEM},
|
||||
{0x80000000, 0xFFF00000, 0x80000000, NORMAL_MEM}
|
||||
};
|
||||
|
||||
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
|
||||
|
||||
static void rt_hw_timer_isr(int vector, void *param)
|
||||
{
|
||||
rt_tick_increase();
|
||||
|
@ -32,17 +41,17 @@ int rt_hw_timer_init(void)
|
|||
|
||||
// Make sure the timer is off.
|
||||
HW_ARMGLOBALTIMER_CONTROL.B.TIMER_ENABLE = 0;
|
||||
|
||||
|
||||
HW_ARMGLOBALTIMER_CONTROL.B.FCR0 =1;
|
||||
|
||||
|
||||
HW_ARMGLOBALTIMER_CONTROL.B.FCR1 =0;
|
||||
|
||||
|
||||
HW_ARMGLOBALTIMER_CONTROL.B.DBG_ENABLE =0;
|
||||
|
||||
|
||||
// Clear counter.
|
||||
HW_ARMGLOBALTIMER_COUNTER_HI_WR(0);
|
||||
HW_ARMGLOBALTIMER_COUNTER_LO_WR(0);
|
||||
|
||||
|
||||
// Now turn on the timer.
|
||||
HW_ARMGLOBALTIMER_CONTROL.B.TIMER_ENABLE = 1;
|
||||
|
||||
|
|
|
@ -8,14 +8,12 @@ drivers/imx_timer.c
|
|||
drivers/imx_i2c.c
|
||||
drivers/imx_uart.c
|
||||
cpu/armv7_cache.c
|
||||
cpu/gic.c
|
||||
cpu/ccm_pll2.c
|
||||
cpu/mmu.c
|
||||
cpu/cortex_a_gcc.S
|
||||
''')
|
||||
|
||||
CPPPATH = [ cwd + '/cpu',
|
||||
cwd + '/include',
|
||||
cwd + '/include',
|
||||
cwd + '/include/mx6ul',
|
||||
cwd + '/include/mx6ul/registers'
|
||||
]
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "gic.h"
|
||||
#include "gic_registers.h"
|
||||
#include "cortex_a.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Prototypes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline gicd_t * gic_get_gicd(void);
|
||||
static inline gicc_t * gic_get_gicc(void);
|
||||
static inline uint32_t irq_get_register_offset(uint32_t irqID);
|
||||
static inline uint32_t irq_get_bit_offset(uint32_t irqID);
|
||||
static inline uint32_t irq_get_bit_mask(uint32_t irqID);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline gicd_t * gic_get_gicd(void)
|
||||
{
|
||||
uint32_t base = get_arm_private_peripheral_base() + kGICDBaseOffset;
|
||||
return (gicd_t *)base;
|
||||
}
|
||||
|
||||
static inline gicc_t * gic_get_gicc(void)
|
||||
{
|
||||
uint32_t base = get_arm_private_peripheral_base() + kGICCBaseOffset;
|
||||
return (gicc_t *)base;
|
||||
}
|
||||
|
||||
static inline uint32_t irq_get_register_offset(uint32_t irqID)
|
||||
{
|
||||
return irqID / 32;
|
||||
}
|
||||
|
||||
static inline uint32_t irq_get_bit_offset(uint32_t irqID)
|
||||
{
|
||||
return irqID & 0x1f;
|
||||
}
|
||||
|
||||
static inline uint32_t irq_get_bit_mask(uint32_t irqID)
|
||||
{
|
||||
return 1 << irq_get_bit_offset(irqID);
|
||||
}
|
||||
|
||||
void gic_enable(bool enableIt)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
if (enableIt)
|
||||
{
|
||||
// Enable both secure and non-secure.
|
||||
gicd->CTLR |= kBM_GICD_CTLR_EnableGrp0 | kBM_GICD_CTLR_EnableGrp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clear the enable bits.
|
||||
gicd->CTLR &= ~(kBM_GICD_CTLR_EnableGrp0 | kBM_GICD_CTLR_EnableGrp1);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_set_irq_security(uint32_t irqID, bool isSecure)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
uint32_t reg = irq_get_register_offset(irqID);
|
||||
uint32_t mask = irq_get_bit_mask(irqID);
|
||||
|
||||
uint32_t value = gicd->IGROUPRn[reg];
|
||||
if (!isSecure)
|
||||
{
|
||||
value &= ~mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
value |= mask;
|
||||
}
|
||||
gicd->IGROUPRn[reg] = value;
|
||||
}
|
||||
|
||||
void gic_enable_irq(uint32_t irqID, bool isEnabled)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
uint32_t reg = irq_get_register_offset(irqID);
|
||||
uint32_t mask = irq_get_bit_mask(irqID);
|
||||
|
||||
// Select set-enable or clear-enable register based on enable flag.
|
||||
if (isEnabled)
|
||||
{
|
||||
gicd->ISENABLERn[reg] = mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
gicd->ICENABLERn[reg] = mask;
|
||||
}
|
||||
}
|
||||
|
||||
void gic_set_irq_priority(uint32_t ID, uint32_t priority)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
// Update the priority register. The priority registers are byte accessible, and the register
|
||||
// struct has the priority registers as a byte array, so we can just index directly by the
|
||||
// interrupt ID.
|
||||
gicd->IPRIORITYRn[ID] = priority & 0xff;
|
||||
}
|
||||
|
||||
void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt)
|
||||
{
|
||||
// Make sure the CPU number is valid.
|
||||
assert(cpuNumber <= 7);
|
||||
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
uint8_t cpuMask = 1 << cpuNumber;
|
||||
|
||||
// Like the priority registers, the target registers are byte accessible, and the register
|
||||
// struct has the them as a byte array, so we can just index directly by the
|
||||
// interrupt ID.
|
||||
if (enableIt)
|
||||
{
|
||||
gicd->ITARGETSRn[irqID] |= (cpuMask & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
gicd->ITARGETSRn[irqID] &= ~(cpuMask & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_send_sgi(uint32_t irqID, uint32_t target_list, uint32_t filter_list)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
gicd->SGIR = (filter_list << kBP_GICD_SGIR_TargetListFilter)
|
||||
| (target_list << kBP_GICD_SGIR_CPUTargetList)
|
||||
| (irqID & 0xf);
|
||||
}
|
||||
|
||||
void gic_cpu_enable(bool enableIt)
|
||||
{
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
|
||||
if (enableIt)
|
||||
{
|
||||
gicc->CTLR |= kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS;
|
||||
}
|
||||
else
|
||||
{
|
||||
gicc->CTLR &= ~(kBM_GICC_CTLR_EnableS | kBM_GICC_CTLR_EnableNS);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_set_cpu_priority_mask(uint32_t priority)
|
||||
{
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
gicc->PMR = priority & 0xff;
|
||||
}
|
||||
|
||||
uint32_t gic_read_irq_ack(void)
|
||||
{
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
return gicc->IAR;
|
||||
}
|
||||
|
||||
void gic_write_end_of_irq(uint32_t irqID)
|
||||
{
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
gicc->EOIR = irqID;
|
||||
}
|
||||
|
||||
void gic_init(void)
|
||||
{
|
||||
gicd_t * gicd = gic_get_gicd();
|
||||
|
||||
// First disable the distributor.
|
||||
gic_enable(false);
|
||||
|
||||
// Clear all pending interrupts.
|
||||
int i;
|
||||
for (i = 0; i < 32; ++i)
|
||||
{
|
||||
gicd->ICPENDRn[i] = 0xffffffff;
|
||||
}
|
||||
|
||||
// Set all interrupts to secure.
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
gicd->IGROUPRn[i] = 0;
|
||||
}
|
||||
|
||||
// Init the GIC CPU interface.
|
||||
gic_init_cpu();
|
||||
|
||||
// Now enable the distributor.
|
||||
gic_enable(true);
|
||||
}
|
||||
|
||||
void gic_init_cpu(void)
|
||||
{
|
||||
// Init the GIC CPU interface.
|
||||
gic_set_cpu_priority_mask(0xff);
|
||||
|
||||
// Disable preemption.
|
||||
gicc_t * gicc = gic_get_gicc();
|
||||
gicc->BPR = 7;
|
||||
|
||||
// Enable signaling the CPU.
|
||||
gic_cpu_enable(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -1,285 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* @file mmu.c
|
||||
* @brief System memory arangement.
|
||||
*/
|
||||
#include "cortex_a.h"
|
||||
#include "mmu.h"
|
||||
#include "arm_cp_registers.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Size in bytes of the first-level page table.
|
||||
#define MMU_L1_PAGE_TABLE_SIZE (16 * 1024)
|
||||
|
||||
//! @brief First-level 1MB section descriptor entry.
|
||||
typedef union mmu_l1_section {
|
||||
uint32_t u;
|
||||
struct {
|
||||
uint32_t id:2; //!< ID
|
||||
uint32_t b:1; //!< Bufferable
|
||||
uint32_t c:1; //!< Cacheable
|
||||
uint32_t xn:1; //!< Execute-not
|
||||
uint32_t domain:4; //!< Domain
|
||||
uint32_t _impl_defined:1; //!< Implementation defined, should be zero.
|
||||
uint32_t ap1_0:2; //!< Access permissions AP[1:0]
|
||||
uint32_t tex:3; //!< TEX remap
|
||||
uint32_t ap2:1; //!< Access permissions AP[2]
|
||||
uint32_t s:1; //!< Shareable
|
||||
uint32_t ng:1; //!< Not-global
|
||||
uint32_t _zero:1; //!< Should be zero.
|
||||
uint32_t ns:1; //!< Non-secure
|
||||
uint32_t address:12; //!< Physical base address
|
||||
};
|
||||
} mmu_l1_section_t;
|
||||
|
||||
enum {
|
||||
kMMU_L1_Section_ID = 2, //!< ID value for a 1MB section first-level entry.
|
||||
kMMU_L1_Section_Address_Shift = 20 //!< Bit offset of the physical base address field.
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Externs
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern char __l1_page_table_start;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void mmu_enable()
|
||||
{
|
||||
// invalidate all tlb
|
||||
arm_unified_tlb_invalidate();
|
||||
|
||||
// read SCTLR
|
||||
uint32_t sctlr;
|
||||
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
|
||||
|
||||
// set MMU enable bit
|
||||
sctlr |= BM_SCTLR_M;
|
||||
|
||||
// write modified SCTLR
|
||||
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
|
||||
}
|
||||
|
||||
void mmu_disable()
|
||||
{
|
||||
// read current SCTLR
|
||||
uint32_t sctlr;
|
||||
_ARM_MRC(15, 0, sctlr, 1, 0, 0);
|
||||
|
||||
// clear MMU enable bit
|
||||
sctlr &=~ BM_SCTLR_M;
|
||||
|
||||
// write modified SCTLR
|
||||
_ARM_MCR(15, 0, sctlr, 1, 0, 0);
|
||||
}
|
||||
|
||||
void mmu_init()
|
||||
{
|
||||
// Get the L1 page table base address.
|
||||
uint32_t * table = (uint32_t *)&__l1_page_table_start;
|
||||
uint32_t share_attr = kShareable;
|
||||
|
||||
// write table address to TTBR0
|
||||
_ARM_MCR(15, 0, table, 2, 0, 0);
|
||||
|
||||
// set Client mode for all Domains
|
||||
uint32_t dacr = 0x55555555;
|
||||
_ARM_MCR(15, 0, dacr, 3, 0, 0); // MCR p15, 0, <Rd>, c3, c0, 0 ; Write DACR
|
||||
|
||||
// Clear the L1 table.
|
||||
bzero(table, MMU_L1_PAGE_TABLE_SIZE);
|
||||
|
||||
// Create default mappings.
|
||||
mmu_map_l1_range(0x00000000, 0x00000000, 0x00900000, kStronglyOrdered, kShareable, kRWAccess); // ROM and peripherals
|
||||
mmu_map_l1_range(0x00900000, 0x00900000, 0x00100000, kStronglyOrdered, kShareable, kRWAccess); // OCRAM
|
||||
mmu_map_l1_range(0x00a00000, 0x00a00000, 0x0f600000, kStronglyOrdered, kShareable, kRWAccess); // More peripherals
|
||||
|
||||
// Check whether SMP is enabled. If it is not, then we don't want to make SDRAM shareable.
|
||||
uint32_t actlr = 0x0;
|
||||
_ARM_MRC(15, 0, actlr, 1, 0, 1);
|
||||
if (actlr & BM_ACTLR_SMP)
|
||||
{
|
||||
share_attr = kShareable;
|
||||
}
|
||||
else
|
||||
{
|
||||
share_attr = kNonshareable;
|
||||
}
|
||||
|
||||
#if defined(CHIP_MX6DQ) || defined(CHIP_MX6SDL)
|
||||
mmu_map_l1_range(0x10000000, 0x10000000, 0x80000000, kOuterInner_WB_WA, share_attr, kRWAccess); // 2GB DDR
|
||||
#elif defined(CHIP_MX6SL) || defined(CHIP_MX6UL)
|
||||
mmu_map_l1_range(0x80000000, 0x80000000, 0x40000000, kOuterInner_WB_WA, share_attr, kRWAccess); // 1GB DDR
|
||||
#else
|
||||
#error Unknown chip type!
|
||||
#endif
|
||||
}
|
||||
|
||||
void mmu_map_l1_range(uint32_t pa, uint32_t va, uint32_t length, mmu_memory_type_t memoryType, mmu_shareability_t isShareable, mmu_access_t access)
|
||||
{
|
||||
register mmu_l1_section_t entry;
|
||||
entry.u = 0;
|
||||
|
||||
// Set constant attributes.
|
||||
entry.id = kMMU_L1_Section_ID;
|
||||
entry.xn = 0; // Allow execution
|
||||
entry.domain = 0; // Domain 0
|
||||
entry.ng = 0; // Global
|
||||
entry.ns = 0; // Secure
|
||||
|
||||
// Set attributes based on the selected memory type.
|
||||
switch (memoryType)
|
||||
{
|
||||
case kStronglyOrdered:
|
||||
entry.c = 0;
|
||||
entry.b = 0;
|
||||
entry.tex = 0;
|
||||
entry.s = 1; // Ignored
|
||||
break;
|
||||
case kDevice:
|
||||
if (isShareable)
|
||||
{
|
||||
entry.c = 0;
|
||||
entry.b = 1;
|
||||
entry.tex = 0;
|
||||
entry.s = 1; // Ignored
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.c = 0;
|
||||
entry.b = 0;
|
||||
entry.tex = 2;
|
||||
entry.s = 0; // Ignored
|
||||
}
|
||||
break;
|
||||
case kOuterInner_WB_WA:
|
||||
entry.c = 1;
|
||||
entry.b = 1;
|
||||
entry.tex = 1;
|
||||
entry.s = isShareable;
|
||||
break;
|
||||
case kOuterInner_WT:
|
||||
entry.c = 1;
|
||||
entry.b = 0;
|
||||
entry.tex = 0;
|
||||
entry.s = isShareable;
|
||||
break;
|
||||
case kNoncacheable:
|
||||
entry.c = 0;
|
||||
entry.b = 0;
|
||||
entry.tex = 1;
|
||||
entry.s = isShareable;
|
||||
break;
|
||||
}
|
||||
|
||||
// Set attributes from specified access mode.
|
||||
switch (access)
|
||||
{
|
||||
case kNoAccess:
|
||||
entry.ap2 = 0;
|
||||
entry.ap1_0 = 0;
|
||||
break;
|
||||
case kROAccess:
|
||||
entry.ap2 = 1;
|
||||
entry.ap1_0 = 3;
|
||||
break;
|
||||
case kRWAccess:
|
||||
entry.ap2 = 0;
|
||||
entry.ap1_0 = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the L1 page table base address.
|
||||
uint32_t * table = (uint32_t *)&__l1_page_table_start;
|
||||
|
||||
// Convert addresses to 12-bit bases.
|
||||
uint32_t vbase = va >> kMMU_L1_Section_Address_Shift;
|
||||
uint32_t pbase = pa >> kMMU_L1_Section_Address_Shift;
|
||||
uint32_t entries = length >> kMMU_L1_Section_Address_Shift;
|
||||
|
||||
// Fill in L1 page table entries.
|
||||
for (; entries > 0; ++pbase, ++vbase, --entries)
|
||||
{
|
||||
entry.address = pbase;
|
||||
table[vbase] = entry.u;
|
||||
}
|
||||
|
||||
// Invalidate TLB
|
||||
arm_unified_tlb_invalidate();
|
||||
}
|
||||
|
||||
bool mmu_virtual_to_physical(uint32_t virtualAddress, uint32_t * physicalAddress)
|
||||
{
|
||||
uint32_t pa = 0;
|
||||
|
||||
// VA to PA translation with privileged read permission check
|
||||
_ARM_MCR(15, 0, virtualAddress & 0xfffffc00, 7, 8, 0);
|
||||
|
||||
// Read PA register
|
||||
_ARM_MRC(15, 0, pa, 7, 4, 0);
|
||||
|
||||
// First bit of returned value is Result of conversion (0 is successful translation)
|
||||
if (pa & 1)
|
||||
{
|
||||
// We can try write permission also
|
||||
// VA to PA translation with privileged write permission check
|
||||
_ARM_MCR(15, 0, virtualAddress & 0xfffffc00, 7, 8, 1);
|
||||
|
||||
// Read PA register
|
||||
_ARM_MRC(15, 0, pa, 7, 4, 0);
|
||||
|
||||
// First bit of returned value is Result of conversion (0 is successful translation)
|
||||
if (pa & 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (physicalAddress)
|
||||
{
|
||||
// complete address returning base + offset
|
||||
pa = (pa & 0xfffff000) | (virtualAddress & 0x00000fff);
|
||||
*physicalAddress = pa;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
//! @addtogroup diag_mmu
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
* @file mmu.h
|
||||
* @brief System memory arrangement.
|
||||
*/
|
||||
|
||||
#ifndef _MMU_H_
|
||||
#define _MMU_H_
|
||||
|
||||
#include "sdk.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Memory region attributes.
|
||||
typedef enum _mmu_memory_type
|
||||
{
|
||||
kStronglyOrdered,
|
||||
kDevice,
|
||||
kOuterInner_WB_WA,
|
||||
kOuterInner_WT,
|
||||
kNoncacheable,
|
||||
} mmu_memory_type_t;
|
||||
|
||||
//! @brief Memory region shareability options.
|
||||
typedef enum _mmu_shareability
|
||||
{
|
||||
kShareable = 1,
|
||||
kNonshareable = 0
|
||||
} mmu_shareability_t;
|
||||
|
||||
//! @brief Access permissions for a memory region.
|
||||
typedef enum _mmu_access
|
||||
{
|
||||
kNoAccess,
|
||||
kROAccess,
|
||||
kRWAccess
|
||||
} mmu_access_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Prototypes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Enable the MMU.
|
||||
*
|
||||
* The L1 page tables and MMU settings must have already been configured by
|
||||
* calling mmu_init() before the MMU is enabled.
|
||||
*/
|
||||
void mmu_enable();
|
||||
|
||||
/*!
|
||||
* @brief Disable the MMU.
|
||||
*/
|
||||
void mmu_disable();
|
||||
|
||||
/*!
|
||||
* @brief Set up the default first-level page table.
|
||||
*
|
||||
* Initializes the L1 page table with the following regions:
|
||||
* - 0x00000000...0x00900000 : ROM and peripherals, strongly-ordered
|
||||
* - 0x00900000...0x00a00000 : OCRAM, strongly-ordered
|
||||
* - For MX6DQ or MX6SDL: 0x10000000...0x90000000 : DDR, normal, outer inner, write-back, write-allocate
|
||||
* - For MX6SL: 0x80000000...0xc0000000 : DDR, normal, outer inner, write-back, write-allocate
|
||||
*
|
||||
* If the CPU is participating in SMP, then the DDR regions are made shareable. Otherwise they
|
||||
* are marked as non-shareable.
|
||||
*
|
||||
* The TTBR0 register is set to the base of the L1 table.
|
||||
*
|
||||
* All memory domains are configured to allow client access. However, note that only domain 0 is
|
||||
* used by mmu_map_l1_range().
|
||||
*/
|
||||
void mmu_init();
|
||||
|
||||
/*!
|
||||
* @brief Maps a range of memory in the first-level page table.
|
||||
*
|
||||
* Entries in the first-level page table are filled in for the range of virtual addresses
|
||||
* starting at @a va and continuing for @a length bytes. These virtual addreses are mapped
|
||||
* to the physical addresses starting at @a pa and continuing for @a length bytes. All table
|
||||
* entries for the range of mapped memory have the same attributes, which are selected with
|
||||
* the @a memoryType, @a isShareable, and @a access parameters.
|
||||
*
|
||||
* @param pa The base physical address of the range to which the virtual address will be mapped.
|
||||
* @param va The base virtual address of the range.
|
||||
* @param length The size of the range to be mapped, in bytes. This value must be divisible by 1MB.
|
||||
* @param memoryType The type of the memory region. This controls caching, buffering, ordering of
|
||||
* memory accesses, and other attributes of the region.
|
||||
* @param isShareable The shareability of the physical memory. Ignored for strongly-ordered memory.
|
||||
* @param access Access permissions.
|
||||
*/
|
||||
void mmu_map_l1_range(uint32_t pa, uint32_t va, uint32_t length, mmu_memory_type_t memoryType, mmu_shareability_t isShareable, mmu_access_t access);
|
||||
|
||||
/*!
|
||||
* @brief Convert virtual address to physical.
|
||||
*
|
||||
* First attempts a priviledged read translation for the current security mode. If that fails,
|
||||
* a priviledged write translation, also for the current security mode, is attempted. If this
|
||||
* second attempt at translation fails, then false will be returned.
|
||||
*
|
||||
* @param virtualAddress Virtual address to convert to a physical address.
|
||||
* @param[out] physicalAddress This parameter is filled in with the physical address corresponding
|
||||
* to the virtual address passed in @a virtualAddress.
|
||||
* @retval true The address returned through @a physicalAddress is valid.
|
||||
* @retval false The conversion failed for some reason.
|
||||
*/
|
||||
bool mmu_virtual_to_physical(uint32_t virtualAddress, uint32_t * physicalAddress);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _MMU_H_
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-03-22 quanzhao first version
|
||||
*/
|
||||
#ifndef __PLATFORM_H__
|
||||
#define __PLATFORM_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
/* SOC-relative definitions */
|
||||
//#include "realview.h"
|
||||
#include "gic_registers.h"
|
||||
#include "irq_numbers.h"
|
||||
|
||||
/* the maximum number of gic */
|
||||
# define ARM_GIC_MAX_NR 1
|
||||
|
||||
/* the maximum number of interrupts */
|
||||
#define ARM_GIC_NR_IRQS IMX_INTERRUPT_COUNT
|
||||
|
||||
/* the maximum entries of the interrupt table */
|
||||
#define MAX_HANDLERS IMX_INTERRUPT_COUNT
|
||||
|
||||
/* the basic constants needed by gic */
|
||||
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
||||
{
|
||||
rt_uint32_t gic_base;
|
||||
asm volatile ("mrc p15, 4, %0, c15, c0, 0" : "=r"(gic_base));
|
||||
return gic_base + kGICDBaseOffset;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
|
||||
{
|
||||
rt_uint32_t gic_base;
|
||||
asm volatile ("mrc p15, 4, %0, c15, c0, 0" : "=r"(gic_base));
|
||||
return gic_base + kGICCBaseOffset;
|
||||
}
|
||||
|
||||
#define GIC_IRQ_START 0
|
||||
|
||||
#define GIC_ACK_INTID_MASK 0x000003ff
|
||||
|
||||
/* the definition needed by gic.c */
|
||||
#define __REG32(x) (*((volatile unsigned int *)(x)))
|
||||
|
||||
/* keep compatible with platform SDK */
|
||||
typedef enum {
|
||||
CPU_0,
|
||||
CPU_1,
|
||||
CPU_2,
|
||||
CPU_3,
|
||||
} cpuid_e;
|
||||
|
||||
enum _gicd_sgi_filter
|
||||
{
|
||||
//! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter.
|
||||
kGicSgiFilter_UseTargetList = 0,
|
||||
|
||||
//! Forward the interrupt to all CPU interfaces except that of the processor that requested
|
||||
//! the interrupt.
|
||||
kGicSgiFilter_AllOtherCPUs = 1,
|
||||
|
||||
//! Forward the interrupt only to the CPU interface of the processor that requested the
|
||||
//! interrupt.
|
||||
kGicSgiFilter_OnlyThisCPU = 2
|
||||
};
|
||||
|
||||
typedef void (*irq_hdlr_t) (void);
|
||||
|
||||
extern void rt_hw_interrupt_mask(int vector);
|
||||
extern void rt_hw_interrupt_umask(int vector);
|
||||
extern rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name);
|
||||
|
||||
rt_inline void register_interrupt_routine(uint32_t irq_id, irq_hdlr_t isr)
|
||||
{
|
||||
rt_hw_interrupt_install(irq_id, (rt_isr_handler_t)isr, NULL, "unknown");
|
||||
}
|
||||
|
||||
rt_inline void enable_interrupt(uint32_t irq_id, uint32_t cpu_id, uint32_t priority)
|
||||
{
|
||||
rt_hw_interrupt_umask(irq_id);
|
||||
}
|
||||
|
||||
rt_inline void disable_interrupt(uint32_t irq_id, uint32_t cpu_id)
|
||||
{
|
||||
rt_hw_interrupt_mask(irq_id);
|
||||
}
|
||||
|
||||
#endif /* __PLATFORM_H__ */
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __GIC_H__
|
||||
#define __GIC_H__
|
||||
|
||||
#include "sdk_types.h"
|
||||
|
||||
//! @addtogroup gic
|
||||
//! @{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Options for sending a software generated interrupt.
|
||||
//!
|
||||
//! These options are used for the @a filter_list parameter of the gic_send_sgi()
|
||||
//! function. They control how to select which CPUs that the interrupt is
|
||||
//! sent to.
|
||||
enum _gicd_sgi_filter
|
||||
{
|
||||
//! Forward the interrupt to the CPU interfaces specified in the @a target_list parameter.
|
||||
kGicSgiFilter_UseTargetList = 0,
|
||||
|
||||
//! Forward the interrupt to all CPU interfaces except that of the processor that requested
|
||||
//! the interrupt.
|
||||
kGicSgiFilter_AllOtherCPUs = 1,
|
||||
|
||||
//! Forward the interrupt only to the CPU interface of the processor that requested the
|
||||
//! interrupt.
|
||||
kGicSgiFilter_OnlyThisCPU = 2
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//! @name Initialization
|
||||
//@{
|
||||
//! @brief Init interrupt handling.
|
||||
//!
|
||||
//! This function is intended to be called only by the primary CPU init code, so it will
|
||||
//! only be called once during system bootup.
|
||||
//!
|
||||
//! Also inits the current CPU. You don't need to call gic_init_cpu() separately.
|
||||
//!
|
||||
//! @post The interrupt distributor and the current CPU interface are enabled. All interrupts
|
||||
//! that were pending are cleared, and all interrupts are made secure (group 0).
|
||||
void gic_init(void);
|
||||
|
||||
//! @brief Init the current CPU's GIC interface.
|
||||
//!
|
||||
//! @post Enables the CPU interface and sets the priority mask to 255. Interrupt preemption
|
||||
//! is disabled by setting the Binary Point to a value of 7.
|
||||
void gic_init_cpu(void);
|
||||
//@}
|
||||
|
||||
//! @name GIC Interrupt Distributor Functions
|
||||
//@{
|
||||
//! @brief Enable or disable the GIC Distributor.
|
||||
//!
|
||||
//! Enables or disables the GIC distributor passing both secure (group 0) and non-secure
|
||||
//! (group 1) interrupts to the CPU interfaces.
|
||||
//!
|
||||
//! @param enableIt Pass true to enable or false to disable.
|
||||
void gic_enable(bool enableIt);
|
||||
|
||||
//! @brief Set the security mode for an interrupt.
|
||||
//!
|
||||
//! @param irqID The interrupt number.
|
||||
//! @param isSecure Whether the interrupt is taken to secure mode.
|
||||
void gic_set_irq_security(uint32_t irqID, bool isSecure);
|
||||
|
||||
//! @brief Enable or disable an interrupt.
|
||||
//!
|
||||
//! @param irqID The number of the interrupt to control.
|
||||
//! @param isEnabled Pass true to enable or false to disable.
|
||||
void gic_enable_irq(uint32_t irqID, bool isEnabled);
|
||||
|
||||
//! @brief Set whether a CPU will receive a particular interrupt.
|
||||
//!
|
||||
//! @param irqID The interrupt number.
|
||||
//! @param cpuNumber The CPU number. The first CPU core is 0.
|
||||
//! @param enableIt Whether to send the interrupt to the specified CPU. Pass true to enable
|
||||
//! or false to disable.
|
||||
void gic_set_cpu_target(uint32_t irqID, unsigned cpuNumber, bool enableIt);
|
||||
|
||||
//! @brief Set an interrupt's priority.
|
||||
//!
|
||||
//! @param irq_id The interrupt number.
|
||||
//! @param priority The priority for the interrupt. In the range of 0 through 0xff, with
|
||||
//! 0 being the highest priority.
|
||||
void gic_set_irq_priority(uint32_t irq_id, uint32_t priority);
|
||||
|
||||
//! @brief Send a software generated interrupt to a specific CPU.
|
||||
//!
|
||||
//! @param irq_id The interrupt number to send.
|
||||
//! @param target_list Each bit indicates a CPU to which the interrupt will be forwarded.
|
||||
//! Bit 0 is CPU 0, bit 1 is CPU 1, and so on. If the value is 0, then the interrupt
|
||||
//! will not be forwarded to any CPUs. This parameter is only used if @a filter_list
|
||||
//! is set to #kGicSgiFilter_UseTargetList.
|
||||
//! @param filter_list One of the enums of the #_gicd_sgi_filter enumeration. The selected
|
||||
//! option determines which CPUs the interrupt will be sent to. If the value
|
||||
//! is #kGicSgiFilter_UseTargetList, then the @a target_list parameter is used.
|
||||
void gic_send_sgi(uint32_t irq_id, uint32_t target_list, uint32_t filter_list);
|
||||
//@}
|
||||
|
||||
//! @name GIC CPU Interface Functions
|
||||
//@{
|
||||
//! @brief Enable or disable the interface to the GIC for the current CPU.
|
||||
//!
|
||||
//! @param enableIt Pass true to enable or false to disable.
|
||||
void gic_cpu_enable(bool enableIt);
|
||||
|
||||
//! @brief Set the mask of which interrupt priorities the CPU will receive.
|
||||
//!
|
||||
//! @param priority The lowest priority that will be passed to the current CPU. Pass 0xff to
|
||||
//! allow all priority interrupts to signal the CPU.
|
||||
void gic_set_cpu_priority_mask(uint32_t priority);
|
||||
|
||||
//! @brief Acknowledge starting of interrupt handling and get the interrupt number.
|
||||
//!
|
||||
//! Normally, this function is called at the beginning of the IRQ handler. It tells the GIC
|
||||
//! that you are starting to handle an interupt, and returns the number of the interrupt you
|
||||
//! need to handle. After the interrupt is handled, you should call gic_write_end_of_irq()
|
||||
//! to signal that the interrupt is completely handled.
|
||||
//!
|
||||
//! In some cases, a spurious interrupt might happen. One possibility is if another CPU handles
|
||||
//! the interrupt. When a spurious interrupt occurs, the end of the interrupt should be indicated
|
||||
//! but nothing else.
|
||||
//!
|
||||
//! @return The number for the highest priority interrupt available for the calling CPU. If
|
||||
//! the return value is 1022 or 1023, a spurious interrupt has occurred.
|
||||
uint32_t gic_read_irq_ack(void);
|
||||
|
||||
//! @brief Signal the end of handling an interrupt.
|
||||
//!
|
||||
//! @param irq_id The number of the interrupt for which handling has finished.
|
||||
void gic_write_end_of_irq(uint32_t irq_id);
|
||||
//@}
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // __GIC_H__
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2012, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __INTERRUPT_H__
|
||||
#define __INTERRUPT_H__
|
||||
|
||||
#include "sdk_types.h"
|
||||
#include "irq_numbers.h"
|
||||
|
||||
//! @addtogroup diag_interrupt
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
* @file interrupt.h
|
||||
* @brief Interface for the interrupt manager.
|
||||
*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief
|
||||
typedef enum {
|
||||
CPU_0,
|
||||
CPU_1,
|
||||
CPU_2,
|
||||
CPU_3,
|
||||
} cpuid_e;
|
||||
|
||||
//! @brief Interrupt service routine.
|
||||
typedef void (*irq_hdlr_t) (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//! @brief Enable an interrupt.
|
||||
//!
|
||||
//! Sets the interrupt priority and makes it non-secure. Then the interrupt is
|
||||
//! enabled on the CPU specified by @a cpu_id.
|
||||
//!
|
||||
//! @param irq_id The interrupt number to enable.
|
||||
//! @param cpu_id The index of the CPU for which the interrupt will be enabled.
|
||||
//! @param priority The interrupt priority, from 0-255. Lower numbers have higher priority.
|
||||
void enable_interrupt(uint32_t irq_id, uint32_t cpu_id, uint32_t priority);
|
||||
|
||||
//! @brief Disable an interrupt on the specified CPU.
|
||||
//!
|
||||
//! @param irq_id The interrupt number to disabled.
|
||||
//! @param cpu_id The index of the CPU for which the interrupt will be disabled.
|
||||
void disable_interrupt(uint32_t irq_id, uint32_t cpu_id);
|
||||
|
||||
//! @brief Set the interrupt service routine for the specified interrupt.
|
||||
//!
|
||||
//! @param irq_id The interrupt number.
|
||||
//! @param isr Function that will be called to handle the interrupt.
|
||||
void register_interrupt_routine(uint32_t irq_id, irq_hdlr_t isr);
|
||||
|
||||
//! @brief Interrupt handler that simply prints a message.
|
||||
void default_interrupt_routine(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -10,7 +10,7 @@ if os.getenv('RTT_CC'):
|
|||
|
||||
# only support GNU GCC compiler.
|
||||
PLATFORM = 'gcc'
|
||||
EXEC_PATH = '/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin'
|
||||
EXEC_PATH = '/usr/bin'
|
||||
|
||||
if os.getenv('RTT_EXEC_PATH'):
|
||||
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
|
||||
|
|
|
@ -322,6 +322,7 @@ CONFIG_RT_USING_LWP=y
|
|||
# CONFIG_PKG_USING_WEBTERMINAL is not set
|
||||
# CONFIG_PKG_USING_CJSON is not set
|
||||
# CONFIG_PKG_USING_JSMN is not set
|
||||
# CONFIG_PKG_USING_LIBMODBUS is not set
|
||||
# CONFIG_PKG_USING_LJSON is not set
|
||||
# CONFIG_PKG_USING_EZXML is not set
|
||||
# CONFIG_PKG_USING_NANOPB is not set
|
||||
|
|
|
@ -5,7 +5,7 @@ import rtconfig
|
|||
if os.getenv('RTT_ROOT'):
|
||||
RTT_ROOT = os.getenv('RTT_ROOT')
|
||||
else:
|
||||
RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
|
||||
RTT_ROOT = os.path.join(os.getcwd(), '..', '..')
|
||||
|
||||
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
|
||||
from building import *
|
||||
|
@ -25,7 +25,7 @@ Export('RTT_ROOT')
|
|||
Export('rtconfig')
|
||||
|
||||
# prepare building environment
|
||||
objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=True)
|
||||
objs = PrepareBuilding(env, RTT_ROOT)
|
||||
|
||||
# make a building
|
||||
DoBuilding(TARGET, objs)
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
Import('rtconfig')
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
if rtconfig.PLATFORM == 'iar':
|
||||
src += Glob('*_iar.S')
|
||||
elif rtconfig.PLATFORM == 'gcc':
|
||||
src += Glob('*_gcc.S')
|
||||
elif rtconfig.PLATFORM == 'armcc':
|
||||
src += Glob('*_rvds.S')
|
||||
|
||||
group = DefineGroup('CPU', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
|
@ -1,64 +0,0 @@
|
|||
#ifndef __ARMV7_H__
|
||||
#define __ARMV7_H__
|
||||
|
||||
/* the exception stack without VFP registers */
|
||||
struct rt_hw_exp_stack
|
||||
{
|
||||
unsigned long r0;
|
||||
unsigned long r1;
|
||||
unsigned long r2;
|
||||
unsigned long r3;
|
||||
unsigned long r4;
|
||||
unsigned long r5;
|
||||
unsigned long r6;
|
||||
unsigned long r7;
|
||||
unsigned long r8;
|
||||
unsigned long r9;
|
||||
unsigned long r10;
|
||||
unsigned long fp;
|
||||
unsigned long ip;
|
||||
unsigned long sp;
|
||||
unsigned long lr;
|
||||
unsigned long pc;
|
||||
unsigned long cpsr;
|
||||
};
|
||||
|
||||
struct rt_hw_stack
|
||||
{
|
||||
unsigned long cpsr;
|
||||
unsigned long r0;
|
||||
unsigned long r1;
|
||||
unsigned long r2;
|
||||
unsigned long r3;
|
||||
unsigned long r4;
|
||||
unsigned long r5;
|
||||
unsigned long r6;
|
||||
unsigned long r7;
|
||||
unsigned long r8;
|
||||
unsigned long r9;
|
||||
unsigned long r10;
|
||||
unsigned long fp;
|
||||
unsigned long ip;
|
||||
unsigned long lr;
|
||||
unsigned long pc;
|
||||
};
|
||||
|
||||
#define USERMODE 0x10
|
||||
#define FIQMODE 0x11
|
||||
#define IRQMODE 0x12
|
||||
#define SVCMODE 0x13
|
||||
#define MONITORMODE 0x16
|
||||
#define ABORTMODE 0x17
|
||||
#define HYPMODE 0x1b
|
||||
#define UNDEFMODE 0x1b
|
||||
#define MODEMASK 0x1f
|
||||
#define NOINT 0xc0
|
||||
|
||||
#define T_Bit (1<<5)
|
||||
#define F_Bit (1<<6)
|
||||
#define I_Bit (1<<7)
|
||||
#define A_Bit (1<<8)
|
||||
#define E_Bit (1<<9)
|
||||
#define J_Bit (1<<24)
|
||||
|
||||
#endif
|
|
@ -1,198 +0,0 @@
|
|||
/*
|
||||
* File : context.S
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2013, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
* 2018-11-22 Jesven in the smp version, using macro to
|
||||
* define rt_hw_interrupt_enable and rt_hw_interrupt_disable
|
||||
* rt_hw_context_switch_interrupt switches to the new thread directly
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
.section .text, "ax"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
|
||||
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable();
|
||||
*/
|
||||
.globl rt_hw_interrupt_disable
|
||||
rt_hw_interrupt_disable:
|
||||
mrs r0, cpsr
|
||||
cpsid i
|
||||
bx lr
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t level);
|
||||
*/
|
||||
.globl rt_hw_interrupt_enable
|
||||
rt_hw_interrupt_enable:
|
||||
msr cpsr, r0
|
||||
bx lr
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_to(rt_uint32 to);
|
||||
* r0 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
ldr sp, [r0] @ get new task stack pointer
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mov r0, r1
|
||||
bl rt_cpus_lock_status_restore
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
ldmfd sp, {r13, r14}^ @ pop usr_sp usr_lr
|
||||
add sp, #8
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task spsr
|
||||
msr spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc
|
||||
|
||||
.section .bss.share.isr
|
||||
_guest_switch_lvl:
|
||||
.word 0
|
||||
|
||||
.section .text.isr, "ax"
|
||||
/*
|
||||
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
|
||||
* r0 --> from
|
||||
* r1 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC)
|
||||
stmfd sp!, {r0-r12, lr} @ push lr & register file
|
||||
|
||||
mrs r4, cpsr
|
||||
tst lr, #0x01
|
||||
orrne r4, r4, #0x20 @ it's thumb code
|
||||
|
||||
stmfd sp!, {r4} @ push cpsr
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
stmfd sp, {r13, r14}^ @ push usr_sp usr_lr
|
||||
sub sp, #8
|
||||
#endif
|
||||
|
||||
str sp, [r0] @ store sp in preempted tasks TCB
|
||||
ldr sp, [r1] @ get new task stack pointer
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mov r0, r2
|
||||
bl rt_cpus_lock_status_restore
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
ldmfd sp, {r13, r14}^ @ pop usr_sp usr_lr
|
||||
add sp, #8
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task cpsr to spsr
|
||||
msr spsr_cxsf, r4
|
||||
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
|
||||
*/
|
||||
.equ Mode_USR, 0x10
|
||||
.equ Mode_FIQ, 0x11
|
||||
.equ Mode_IRQ, 0x12
|
||||
.equ Mode_SVC, 0x13
|
||||
.equ Mode_ABT, 0x17
|
||||
.equ Mode_UND, 0x1B
|
||||
.equ Mode_SYS, 0x1F
|
||||
|
||||
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
|
||||
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
|
||||
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
#ifdef RT_USING_SMP
|
||||
/* r0 :irq_mod context
|
||||
* r1 :addr of from_thread's sp
|
||||
* r2 :addr of to_thread's sp
|
||||
* r3 :to_thread's tcb
|
||||
*/
|
||||
|
||||
@ r0 point to {r0-r3} in stack
|
||||
push {r1 - r3}
|
||||
mov r1, r0
|
||||
add r0, r0, #4*4
|
||||
ldmfd r0!, {r4-r12,lr}@ reload saved registers
|
||||
mrs r3, spsr @ get cpsr of interrupt thread
|
||||
sub r2, lr, #4 @ save old task's pc to r2
|
||||
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
|
||||
|
||||
stmfd sp!, {r2} @ push old task's pc
|
||||
stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
|
||||
ldmfd r1, {r4-r7} @ restore r0-r3 of the interrupt thread
|
||||
stmfd sp!, {r4-r7} @ push old task's r0-r3
|
||||
stmfd sp!, {r3} @ push old task's cpsr
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
stmfd sp, {r13,r14}^ @push usr_sp usr_lr
|
||||
sub sp, #8
|
||||
#endif
|
||||
|
||||
msr cpsr_c, #I_Bit|F_Bit|Mode_IRQ
|
||||
pop {r1 - r3}
|
||||
mov sp, r0
|
||||
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
|
||||
str sp, [r1]
|
||||
|
||||
ldr sp, [r2]
|
||||
mov r0, r3
|
||||
bl rt_cpus_lock_status_restore
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
ldmfd sp, {r13,r14}^ @pop usr_sp usr_lr
|
||||
add sp, #8
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
|
||||
msr spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
|
||||
|
||||
#else /*RT_USING_SMP*/
|
||||
ldr r2, =rt_thread_switch_interrupt_flag
|
||||
ldr r3, [r2]
|
||||
cmp r3, #1
|
||||
beq _reswitch
|
||||
ldr ip, =rt_interrupt_from_thread @ set rt_interrupt_from_thread
|
||||
mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1
|
||||
str r0, [ip]
|
||||
str r3, [r2]
|
||||
_reswitch:
|
||||
ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
|
||||
str r1, [r2]
|
||||
bx lr
|
||||
#endif /*RT_USING_SMP*/
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef __CP15_H__
|
||||
#define __CP15_H__
|
||||
|
||||
unsigned long rt_cpu_get_smp_id(void);
|
||||
|
||||
void rt_cpu_mmu_disable(void);
|
||||
void rt_cpu_mmu_enable(void);
|
||||
void rt_cpu_tlb_set(volatile unsigned long*);
|
||||
|
||||
void rt_cpu_vector_set_base(unsigned int addr);
|
||||
|
||||
#endif
|
|
@ -1,140 +0,0 @@
|
|||
/*
|
||||
* File : cp15_gcc.S
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2013, RT-Thread Development Team
|
||||
* http://www.rt-thread.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
|
||||
.globl rt_cpu_get_smp_id
|
||||
rt_cpu_get_smp_id:
|
||||
mrc p15, #0, r0, c0, c0, #5
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_vector_set_base
|
||||
rt_cpu_vector_set_base:
|
||||
mcr p15, #0, r0, c12, c0, #0
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_dcache_enable
|
||||
rt_hw_cpu_dcache_enable:
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
orr r0, r0, #0x00000004
|
||||
mcr p15, #0, r0, c1, c0, #0
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_icache_enable
|
||||
rt_hw_cpu_icache_enable:
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
orr r0, r0, #0x00001000
|
||||
mcr p15, #0, r0, c1, c0, #0
|
||||
bx lr
|
||||
|
||||
_FLD_MAX_WAY:
|
||||
.word 0x3ff
|
||||
_FLD_MAX_IDX:
|
||||
.word 0x7ff
|
||||
|
||||
.globl rt_cpu_dcache_clean_flush
|
||||
rt_cpu_dcache_clean_flush:
|
||||
push {r4-r11}
|
||||
dmb
|
||||
mrc p15, #1, r0, c0, c0, #1 @ read clid register
|
||||
ands r3, r0, #0x7000000 @ get level of coherency
|
||||
mov r3, r3, lsr #23
|
||||
beq finished
|
||||
mov r10, #0
|
||||
loop1:
|
||||
add r2, r10, r10, lsr #1
|
||||
mov r1, r0, lsr r2
|
||||
and r1, r1, #7
|
||||
cmp r1, #2
|
||||
blt skip
|
||||
mcr p15, #2, r10, c0, c0, #0
|
||||
isb
|
||||
mrc p15, #1, r1, c0, c0, #0
|
||||
and r2, r1, #7
|
||||
add r2, r2, #4
|
||||
ldr r4, _FLD_MAX_WAY
|
||||
ands r4, r4, r1, lsr #3
|
||||
clz r5, r4
|
||||
ldr r7, _FLD_MAX_IDX
|
||||
ands r7, r7, r1, lsr #13
|
||||
loop2:
|
||||
mov r9, r4
|
||||
loop3:
|
||||
orr r11, r10, r9, lsl r5
|
||||
orr r11, r11, r7, lsl r2
|
||||
mcr p15, #0, r11, c7, c14, #2
|
||||
subs r9, r9, #1
|
||||
bge loop3
|
||||
subs r7, r7, #1
|
||||
bge loop2
|
||||
skip:
|
||||
add r10, r10, #2
|
||||
cmp r3, r10
|
||||
bgt loop1
|
||||
|
||||
finished:
|
||||
dsb
|
||||
isb
|
||||
pop {r4-r11}
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_dcache_disable
|
||||
rt_hw_cpu_dcache_disable:
|
||||
push {r4-r11, lr}
|
||||
bl rt_cpu_dcache_clean_flush
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
bic r0, r0, #0x00000004
|
||||
mcr p15, #0, r0, c1, c0, #0
|
||||
pop {r4-r11, lr}
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_icache_disable
|
||||
rt_hw_cpu_icache_disable:
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
bic r0, r0, #0x00001000
|
||||
mcr p15, #0, r0, c1, c0, #0
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_mmu_disable
|
||||
rt_cpu_mmu_disable:
|
||||
mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
bic r0, r0, #1
|
||||
mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_mmu_enable
|
||||
rt_cpu_mmu_enable:
|
||||
mrc p15, #0, r0, c1, c0, #0
|
||||
orr r0, r0, #0x001
|
||||
mcr p15, #0, r0, c1, c0, #0 @ set mmu enable bit
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_tlb_set
|
||||
rt_cpu_tlb_set:
|
||||
mcr p15, #0, r0, c2, c0, #0
|
||||
dmb
|
||||
bx lr
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-09-15 Bernard first version
|
||||
* 2018-11-22 Jesven add rt_hw_cpu_id()
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
int rt_hw_cpu_id(void)
|
||||
{
|
||||
int cpu_id;
|
||||
__asm__ volatile (
|
||||
"mrc p15, 0, %0, c0, c0, 5"
|
||||
:"=r"(cpu_id)
|
||||
);
|
||||
cpu_id &= 0xf;
|
||||
return cpu_id;
|
||||
};
|
||||
|
||||
void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
unsigned long tmp;
|
||||
unsigned long newval;
|
||||
rt_hw_spinlock_t lockval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"pld [%0]"
|
||||
::"r"(&lock->slock)
|
||||
);
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldrex %0, [%3]\n"
|
||||
" add %1, %0, %4\n"
|
||||
" strex %2, %1, [%3]\n"
|
||||
" teq %2, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
|
||||
: "r" (&lock->slock), "I" (1 << 16)
|
||||
: "cc");
|
||||
|
||||
while (lockval.tickets.next != lockval.tickets.owner) {
|
||||
__asm__ __volatile__("wfe":::"memory");
|
||||
lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner);
|
||||
}
|
||||
|
||||
__asm__ volatile ("dmb":::"memory");
|
||||
}
|
||||
|
||||
void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
__asm__ volatile ("dmb":::"memory");
|
||||
lock->tickets.owner++;
|
||||
__asm__ volatile ("dsb ishst\nsev":::"memory");
|
||||
}
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
/**
|
||||
* @addtogroup ARM CPU
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/** shutdown CPU */
|
||||
void rt_hw_cpu_shutdown()
|
||||
{
|
||||
rt_uint32_t level;
|
||||
rt_kprintf("shutdown...\n");
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*@}*/
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* File : interrupt.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2013-2014, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* 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 "realview.h"
|
||||
#include "gic.h"
|
||||
|
||||
#define MAX_HANDLERS NR_IRQS_PBA8
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
/* Those varibles will be accessed in ISR, so we need to share them. */
|
||||
rt_uint32_t rt_interrupt_from_thread = 0;
|
||||
rt_uint32_t rt_interrupt_to_thread = 0;
|
||||
rt_uint32_t rt_thread_switch_interrupt_flag = 0;
|
||||
#endif
|
||||
|
||||
const unsigned int VECTOR_BASE = 0x00;
|
||||
extern void rt_cpu_vector_set_base(unsigned int addr);
|
||||
extern int system_vectors;
|
||||
|
||||
void rt_hw_vector_init(void)
|
||||
{
|
||||
rt_cpu_vector_set_base((unsigned int)&system_vectors);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize hardware interrupt
|
||||
*/
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
rt_uint32_t gic_cpu_base;
|
||||
rt_uint32_t gic_dist_base;
|
||||
|
||||
/* initialize vector table */
|
||||
rt_hw_vector_init();
|
||||
|
||||
/* initialize exceptions table */
|
||||
rt_memset(isr_table, 0x00, sizeof(isr_table));
|
||||
|
||||
/* initialize ARM GIC */
|
||||
gic_dist_base = REALVIEW_GIC_DIST_BASE;
|
||||
gic_cpu_base = REALVIEW_GIC_CPU_BASE;
|
||||
|
||||
arm_gic_dist_init(0, gic_dist_base, 0);
|
||||
arm_gic_cpu_init(0, gic_cpu_base);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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;
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* File : interrupt.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2011, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-06 Bernard first version
|
||||
*/
|
||||
|
||||
#ifndef __INTERRUPT_H__
|
||||
#define __INTERRUPT_H__
|
||||
|
||||
#define INT_IRQ 0x00
|
||||
#define INT_FIQ 0x01
|
||||
|
||||
void rt_hw_interrupt_control(int vector, int priority, int route);
|
||||
|
||||
void rt_hw_interrupt_init(void);
|
||||
|
||||
#endif
|
|
@ -1,207 +0,0 @@
|
|||
/*
|
||||
* File : mmu.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2012-01-10 bernard porting to AM1808
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <board.h>
|
||||
|
||||
#include "cp15.h"
|
||||
|
||||
#define DESC_SEC (0x2)
|
||||
#define CB (3<<2) //cache_on, write_back
|
||||
#define CNB (2<<2) //cache_on, write_through
|
||||
#define NCB (1<<2) //cache_off,WR_BUF on
|
||||
#define NCNB (0<<2) //cache_off,WR_BUF off
|
||||
#define AP_RW (3<<10) //supervisor=RW, user=RW
|
||||
#define AP_RO (2<<10) //supervisor=RW, user=RO
|
||||
#define XN (1<<4) // eXecute Never
|
||||
|
||||
#define DOMAIN_FAULT (0x0)
|
||||
#define DOMAIN_CHK (0x1)
|
||||
#define DOMAIN_NOTCHK (0x3)
|
||||
#define DOMAIN0 (0x0<<5)
|
||||
#define DOMAIN1 (0x1<<5)
|
||||
|
||||
#define DOMAIN0_ATTR (DOMAIN_CHK<<0)
|
||||
#define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
|
||||
|
||||
/* Read/Write, cache, write back */
|
||||
#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC)
|
||||
/* Read/Write, cache, write through */
|
||||
#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC)
|
||||
/* Read/Write without cache and write buffer */
|
||||
#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC)
|
||||
/* Read/Write without cache and write buffer, no execute */
|
||||
#define RW_NCNBXN (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN)
|
||||
/* Read/Write without cache and write buffer */
|
||||
#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC)
|
||||
|
||||
/* dump 2nd level page table */
|
||||
void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb)
|
||||
{
|
||||
int i;
|
||||
int fcnt = 0;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
rt_uint32_t pte2 = ptb[i];
|
||||
if ((pte2 & 0x3) == 0)
|
||||
{
|
||||
if (fcnt == 0)
|
||||
rt_kprintf(" ");
|
||||
rt_kprintf("%04x: ", i);
|
||||
fcnt++;
|
||||
if (fcnt == 16)
|
||||
{
|
||||
rt_kprintf("fault\n");
|
||||
fcnt = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (fcnt != 0)
|
||||
{
|
||||
rt_kprintf("fault\n");
|
||||
fcnt = 0;
|
||||
}
|
||||
|
||||
rt_kprintf(" %04x: %x: ", i, pte2);
|
||||
if ((pte2 & 0x3) == 0x1)
|
||||
{
|
||||
rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n",
|
||||
((pte2 >> 7) | (pte2 >> 4))& 0xf,
|
||||
(pte2 >> 15) & 0x1,
|
||||
((pte2 >> 10) | (pte2 >> 2)) & 0x1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n",
|
||||
((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1,
|
||||
((pte2 >> 4) | (pte2 >> 2)) & 0x1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb)
|
||||
{
|
||||
int i;
|
||||
int fcnt = 0;
|
||||
|
||||
rt_kprintf("page table@%p\n", ptb);
|
||||
for (i = 0; i < 1024*4; i++)
|
||||
{
|
||||
rt_uint32_t pte1 = ptb[i];
|
||||
if ((pte1 & 0x3) == 0)
|
||||
{
|
||||
rt_kprintf("%03x: ", i);
|
||||
fcnt++;
|
||||
if (fcnt == 16)
|
||||
{
|
||||
rt_kprintf("fault\n");
|
||||
fcnt = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (fcnt != 0)
|
||||
{
|
||||
rt_kprintf("fault\n");
|
||||
fcnt = 0;
|
||||
}
|
||||
|
||||
rt_kprintf("%03x: %08x: ", i, pte1);
|
||||
if ((pte1 & 0x3) == 0x3)
|
||||
{
|
||||
rt_kprintf("LPAE\n");
|
||||
}
|
||||
else if ((pte1 & 0x3) == 0x1)
|
||||
{
|
||||
rt_kprintf("pte,ns:%d,domain:%d\n",
|
||||
(pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf);
|
||||
/*
|
||||
*rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000)
|
||||
* - 0x80000000 + 0xC0000000));
|
||||
*/
|
||||
}
|
||||
else if (pte1 & (1 << 18))
|
||||
{
|
||||
rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n",
|
||||
(pte1 >> 19) & 0x1,
|
||||
((pte1 >> 13) | (pte1 >> 10))& 0xf,
|
||||
(pte1 >> 4) & 0x1,
|
||||
((pte1 >> 10) | (pte1 >> 2)) & 0x1f);
|
||||
}
|
||||
else
|
||||
{
|
||||
rt_kprintf("section,ns:%d,ap:%x,"
|
||||
"xn:%d,texcb:%02x,domain:%d\n",
|
||||
(pte1 >> 19) & 0x1,
|
||||
((pte1 >> 13) | (pte1 >> 10))& 0xf,
|
||||
(pte1 >> 4) & 0x1,
|
||||
(((pte1 & (0x7 << 12)) >> 10) |
|
||||
((pte1 & 0x0c) >> 2)) & 0x1f,
|
||||
(pte1 >> 5) & 0xf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* level1 page table, each entry for 1MB memory. */
|
||||
volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024)));
|
||||
void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart,
|
||||
rt_uint32_t vaddrEnd,
|
||||
rt_uint32_t paddrStart,
|
||||
rt_uint32_t attr)
|
||||
{
|
||||
volatile rt_uint32_t *pTT;
|
||||
volatile int i, nSec;
|
||||
pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20);
|
||||
nSec = (vaddrEnd >> 20) - (vaddrStart >> 20);
|
||||
for(i = 0; i <= nSec; i++)
|
||||
{
|
||||
*pTT = attr | (((paddrStart >> 20) + i) << 20);
|
||||
pTT++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long rt_hw_set_domain_register(unsigned long domain_val)
|
||||
{
|
||||
unsigned long old_domain;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain));
|
||||
asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory");
|
||||
|
||||
return old_domain;
|
||||
}
|
||||
|
||||
void rt_hw_mmu_init(void)
|
||||
{
|
||||
rt_hw_cpu_dcache_disable();
|
||||
rt_hw_cpu_icache_disable();
|
||||
rt_cpu_mmu_disable();
|
||||
|
||||
/* set page table */
|
||||
/* 4G 1:1 memory */
|
||||
rt_hw_mmu_setmtt(0, 0xffffffff-1, 0, RW_CB);
|
||||
/* IO memory region */
|
||||
rt_hw_mmu_setmtt(0x44000000, 0x80000000-1, 0x44000000, RW_NCNBXN);
|
||||
|
||||
/*rt_hw_cpu_dump_page_table(MMUTable);*/
|
||||
rt_hw_set_domain_register(0x55555555);
|
||||
|
||||
rt_cpu_tlb_set(MMUTable);
|
||||
|
||||
rt_cpu_mmu_enable();
|
||||
|
||||
rt_hw_cpu_icache_enable();
|
||||
rt_hw_cpu_dcache_enable();
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#include <rtthread.h>
|
||||
#include "pmu.h"
|
||||
|
||||
void rt_hw_pmu_dump_feature(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
|
||||
reg = rt_hw_pmu_get_control();
|
||||
rt_kprintf("ARM PMU Implementor: %c, ID code: %02x, %d counters\n",
|
||||
reg >> 24, (reg >> 16) & 0xff, (reg >> 11) & 0x1f);
|
||||
RT_ASSERT(ARM_PMU_CNTER_NR == ((reg >> 11) & 0x1f));
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
#ifndef __PMU_H__
|
||||
#define __PMU_H__
|
||||
|
||||
#include "board.h"
|
||||
|
||||
/* Number of counters */
|
||||
#define ARM_PMU_CNTER_NR 4
|
||||
|
||||
enum rt_hw_pmu_event_type {
|
||||
ARM_PMU_EVENT_PMNC_SW_INCR = 0x00,
|
||||
ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01,
|
||||
ARM_PMU_EVENT_ITLB_REFILL = 0x02,
|
||||
ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03,
|
||||
ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04,
|
||||
ARM_PMU_EVENT_DTLB_REFILL = 0x05,
|
||||
ARM_PMU_EVENT_MEM_READ = 0x06,
|
||||
ARM_PMU_EVENT_MEM_WRITE = 0x07,
|
||||
ARM_PMU_EVENT_INSTR_EXECUTED = 0x08,
|
||||
ARM_PMU_EVENT_EXC_TAKEN = 0x09,
|
||||
ARM_PMU_EVENT_EXC_EXECUTED = 0x0A,
|
||||
ARM_PMU_EVENT_CID_WRITE = 0x0B,
|
||||
};
|
||||
|
||||
/* Enable bit */
|
||||
#define ARM_PMU_PMCR_E (0x01 << 0)
|
||||
/* Event counter reset */
|
||||
#define ARM_PMU_PMCR_P (0x01 << 1)
|
||||
/* Cycle counter reset */
|
||||
#define ARM_PMU_PMCR_C (0x01 << 2)
|
||||
/* Cycle counter divider */
|
||||
#define ARM_PMU_PMCR_D (0x01 << 3)
|
||||
|
||||
#ifdef __GNUC__
|
||||
rt_inline void rt_hw_pmu_enable_cnt(int divide64)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
unsigned long pmcntenset;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C;
|
||||
if (divide64)
|
||||
pmcr |= ARM_PMU_PMCR_D;
|
||||
else
|
||||
pmcr &= ~ARM_PMU_PMCR_D;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
|
||||
/* enable all the counters */
|
||||
pmcntenset = ~0;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset));
|
||||
/* clear overflows(just in case) */
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset));
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_control(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
return pmcr;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_ceid(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
/* only PMCEID0 is supported, PMCEID1 is RAZ. */
|
||||
asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_cnten(void)
|
||||
{
|
||||
unsigned long pmcnt;
|
||||
asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt));
|
||||
return pmcnt;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_reset_cycle(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_C;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_reset_event(void)
|
||||
{
|
||||
unsigned long pmcr;
|
||||
|
||||
asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
|
||||
pmcr |= ARM_PMU_PMCR_P;
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_cycle(void)
|
||||
{
|
||||
unsigned long cyc;
|
||||
asm volatile ("isb");
|
||||
asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc));
|
||||
return cyc;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_select_counter(int idx)
|
||||
{
|
||||
RT_ASSERT(idx < ARM_PMU_CNTER_NR);
|
||||
|
||||
asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx));
|
||||
/* Linux add an isb here, don't know why here. */
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_select_event(int idx,
|
||||
enum rt_hw_pmu_event_type eve)
|
||||
{
|
||||
RT_ASSERT(idx < ARM_PMU_CNTER_NR);
|
||||
|
||||
rt_hw_pmu_select_counter(idx);
|
||||
asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve));
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_read_counter(int idx)
|
||||
{
|
||||
unsigned long reg;
|
||||
|
||||
rt_hw_pmu_select_counter(idx);
|
||||
asm volatile ("isb");
|
||||
asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline unsigned long rt_hw_pmu_get_ovsr(void)
|
||||
{
|
||||
unsigned long reg;
|
||||
asm volatile ("isb");
|
||||
asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg));
|
||||
return reg;
|
||||
}
|
||||
|
||||
rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg)
|
||||
{
|
||||
asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg));
|
||||
asm volatile ("isb");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void rt_hw_pmu_dump_feature(void);
|
||||
|
||||
#endif /* end of include guard: __PMU_H__ */
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* File : stack.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2011, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* 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>
|
||||
|
||||
/**
|
||||
* @addtogroup AM33xx
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* 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_uint32_t *stk;
|
||||
|
||||
stack_addr += sizeof(rt_uint32_t);
|
||||
stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8);
|
||||
stk = (rt_uint32_t*)stack_addr;
|
||||
*(--stk) = (rt_uint32_t)tentry; /* entry point */
|
||||
*(--stk) = (rt_uint32_t)texit; /* lr */
|
||||
*(--stk) = 0; /* r12 */
|
||||
*(--stk) = 0; /* r11 */
|
||||
*(--stk) = 0; /* r10 */
|
||||
*(--stk) = 0; /* r9 */
|
||||
*(--stk) = 0; /* r8 */
|
||||
*(--stk) = 0; /* r7 */
|
||||
*(--stk) = 0; /* r6 */
|
||||
*(--stk) = 0; /* r5 */
|
||||
*(--stk) = 0; /* r4 */
|
||||
*(--stk) = 0; /* r3 */
|
||||
*(--stk) = 0; /* r2 */
|
||||
*(--stk) = 0; /* r1 */
|
||||
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
|
||||
/* cpsr */
|
||||
if ((rt_uint32_t)tentry & 0x01)
|
||||
*(--stk) = SVCMODE | 0x20; /* thumb mode */
|
||||
else
|
||||
*(--stk) = SVCMODE; /* arm mode */
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
*(--stk) = 0; /* user lr */
|
||||
*(--stk) = 0; /* user sp*/
|
||||
#endif
|
||||
|
||||
/* return task's current stack address */
|
||||
return (rt_uint8_t *)stk;
|
||||
}
|
||||
|
||||
/*@}*/
|
|
@ -1,447 +0,0 @@
|
|||
/*
|
||||
* File : start_gcc.S
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2013-2014, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
* 2018-11-22 Jesven in the interrupt context, use rt_scheduler_do_irq_switch checks
|
||||
* and switches to a new thread
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
|
||||
.equ Mode_USR, 0x10
|
||||
.equ Mode_FIQ, 0x11
|
||||
.equ Mode_IRQ, 0x12
|
||||
.equ Mode_SVC, 0x13
|
||||
.equ Mode_ABT, 0x17
|
||||
.equ Mode_UND, 0x1B
|
||||
.equ Mode_SYS, 0x1F
|
||||
|
||||
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
|
||||
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
|
||||
|
||||
.equ UND_Stack_Size, 0x00000000
|
||||
.equ SVC_Stack_Size, 0x00000400
|
||||
.equ ABT_Stack_Size, 0x00000000
|
||||
.equ RT_FIQ_STACK_PGSZ, 0x00000000
|
||||
.equ RT_IRQ_STACK_PGSZ, 0x00000800
|
||||
.equ USR_Stack_Size, 0x00000400
|
||||
|
||||
#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
|
||||
RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ)
|
||||
|
||||
.section .data.share.isr
|
||||
/* stack */
|
||||
.globl stack_start
|
||||
.globl stack_top
|
||||
|
||||
stack_start:
|
||||
.rept ISR_Stack_Size
|
||||
.byte 0
|
||||
.endr
|
||||
stack_top:
|
||||
|
||||
.text
|
||||
/* reset entry */
|
||||
.globl _reset
|
||||
_reset:
|
||||
/* set the cpu to SVC32 mode and disable interrupt */
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #0x1f
|
||||
orr r0, r0, #0x13
|
||||
msr cpsr_c, r0
|
||||
|
||||
mrc p15, 0, r1, c1, c0, 1
|
||||
mov r0, #(1<<6)
|
||||
orr r1, r0
|
||||
mcr p15, 0, r1, c1, c0, 1 //enable smp
|
||||
|
||||
ldr lr, =after_enable_mmu
|
||||
ldr r0, =mtbl
|
||||
b enable_mmu
|
||||
|
||||
after_enable_mmu:
|
||||
|
||||
/* setup stack */
|
||||
bl stack_setup
|
||||
|
||||
/* clear .bss */
|
||||
mov r0,#0 /* get a zero */
|
||||
ldr r1,=__bss_start /* bss start */
|
||||
ldr r2,=__bss_end /* bss end */
|
||||
|
||||
bss_loop:
|
||||
cmp r1,r2 /* check if data to clear */
|
||||
strlo r0,[r1],#4 /* clear 4 bytes */
|
||||
blo bss_loop /* loop until done */
|
||||
|
||||
/* call C++ constructors of global objects */
|
||||
ldr r0, =__ctors_start__
|
||||
ldr r1, =__ctors_end__
|
||||
|
||||
ctor_loop:
|
||||
cmp r0, r1
|
||||
beq ctor_end
|
||||
ldr r2, [r0], #4
|
||||
stmfd sp!, {r0-r1}
|
||||
mov lr, pc
|
||||
bx r2
|
||||
ldmfd sp!, {r0-r1}
|
||||
b ctor_loop
|
||||
ctor_end:
|
||||
|
||||
/* start RT-Thread Kernel */
|
||||
bl flush_cache_all
|
||||
ldr pc, _rtthread_startup
|
||||
_rtthread_startup:
|
||||
.word rtthread_startup
|
||||
|
||||
stack_setup:
|
||||
ldr r0, =stack_top
|
||||
|
||||
@ Set the startup stack for svc
|
||||
mov sp, r0
|
||||
|
||||
@ Enter Undefined Instruction Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_UND|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #UND_Stack_Size
|
||||
|
||||
@ Enter Abort Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_ABT|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #ABT_Stack_Size
|
||||
|
||||
@ Enter FIQ Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #RT_FIQ_STACK_PGSZ
|
||||
|
||||
@ Enter IRQ Mode and set its Stack Pointer
|
||||
msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit
|
||||
mov sp, r0
|
||||
sub r0, r0, #RT_IRQ_STACK_PGSZ
|
||||
|
||||
/* come back to SVC mode */
|
||||
msr cpsr_c, #Mode_SVC|I_Bit|F_Bit
|
||||
bx lr
|
||||
|
||||
.global enable_mmu
|
||||
enable_mmu:
|
||||
orr r0, #0x18
|
||||
mcr p15, 0, r0, c2, c0, 0 @ttbr0
|
||||
|
||||
mov r0, #(1 << 5) @PD1=1
|
||||
mcr p15, 0, r0, c2, c0, 2 @ttbcr
|
||||
|
||||
mov r0, #1
|
||||
mcr p15, 0, r0, c3, c0, 0 @dacr
|
||||
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c8, c7, 0
|
||||
mcr p15, 0, r0, c7, c5, 0 @iciallu
|
||||
mcr p15, 0, r0, c7, c5, 6 @bpiall
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
orr r0, #(1 | 4)
|
||||
orr r0, #(1 << 12)
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
dsb
|
||||
isb
|
||||
mov pc, lr
|
||||
|
||||
.global flush_cache_all
|
||||
flush_cache_all:
|
||||
stmfd sp!, {r0-r12, lr}
|
||||
bl v7_flush_dcache_all
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
|
||||
dsb
|
||||
isb
|
||||
ldmfd sp!, {r0-r12, lr}
|
||||
mov pc, lr
|
||||
|
||||
v7_flush_dcache_all:
|
||||
dmb @ ensure ordering with previous memory accesses
|
||||
mrc p15, 1, r0, c0, c0, 1 @ read clidr
|
||||
ands r3, r0, #0x7000000 @ extract loc from clidr
|
||||
mov r3, r3, lsr #23 @ left align loc bit field
|
||||
beq finished @ if loc is 0, then no need to clean
|
||||
mov r10, #0 @ start clean at cache level 0
|
||||
loop1:
|
||||
add r2, r10, r10, lsr #1 @ work out 3x current cache level
|
||||
mov r1, r0, lsr r2 @ extract cache type bits from clidr
|
||||
and r1, r1, #7 @ mask of the bits for current cache only
|
||||
cmp r1, #2 @ see what cache we have at this level
|
||||
blt skip @ skip if no cache, or just i-cache
|
||||
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
|
||||
isb @ isb to sych the new cssr&csidr
|
||||
mrc p15, 1, r1, c0, c0, 0 @ read the new csidr
|
||||
and r2, r1, #7 @ extract the length of the cache lines
|
||||
add r2, r2, #4 @ add 4 (line length offset)
|
||||
ldr r4, =0x3ff
|
||||
ands r4, r4, r1, lsr #3 @ find maximum number on the way size
|
||||
clz r5, r4 @ find bit position of way size increment
|
||||
ldr r7, =0x7fff
|
||||
ands r7, r7, r1, lsr #13 @ extract max number of the index size
|
||||
loop2:
|
||||
mov r9, r4 @ create working copy of max way size
|
||||
loop3:
|
||||
orr r11, r10, r9, lsl r5 @ factor way and cache number into r11
|
||||
orr r11, r11, r7, lsl r2 @ factor index number into r11
|
||||
mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
|
||||
subs r9, r9, #1 @ decrement the way
|
||||
bge loop3
|
||||
subs r7, r7, #1 @ decrement the index
|
||||
bge loop2
|
||||
skip:
|
||||
add r10, r10, #2 @ increment cache number
|
||||
cmp r3, r10
|
||||
bgt loop1
|
||||
finished:
|
||||
mov r10, #0 @ swith back to cache level 0
|
||||
mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr
|
||||
dsb
|
||||
isb
|
||||
mov pc, lr
|
||||
|
||||
/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */
|
||||
.section .text.isr, "ax"
|
||||
.align 5
|
||||
.globl vector_fiq
|
||||
vector_fiq:
|
||||
stmfd sp!,{r0-r7,lr}
|
||||
bl rt_hw_trap_fiq
|
||||
ldmfd sp!,{r0-r7,lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
.globl rt_interrupt_enter
|
||||
.globl rt_interrupt_leave
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
|
||||
.align 5
|
||||
.globl vector_irq
|
||||
vector_irq:
|
||||
#ifdef RT_USING_SMP
|
||||
clrex
|
||||
#endif
|
||||
stmfd sp!, {r0-r12,lr}
|
||||
|
||||
bl rt_interrupt_enter
|
||||
bl rt_hw_trap_irq
|
||||
bl rt_interrupt_leave
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mov r0, sp
|
||||
bl rt_scheduler_do_irq_switch
|
||||
|
||||
ldmfd sp!, {r0-r12,lr}
|
||||
subs pc, lr, #4
|
||||
#else
|
||||
@ if rt_thread_switch_interrupt_flag set, jump to
|
||||
@ rt_hw_context_switch_interrupt_do and don't return
|
||||
ldr r0, =rt_thread_switch_interrupt_flag
|
||||
ldr r1, [r0]
|
||||
cmp r1, #1
|
||||
beq rt_hw_context_switch_interrupt_do
|
||||
|
||||
ldmfd sp!, {r0-r12,lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
rt_hw_context_switch_interrupt_do:
|
||||
mov r1, #0 @ clear flag
|
||||
str r1, [r0]
|
||||
|
||||
mov r1, sp @ r1 point to {r0-r3} in stack
|
||||
add sp, sp, #4*4
|
||||
ldmfd sp!, {r4-r12,lr}@ reload saved registers
|
||||
mrs r0, spsr @ get cpsr of interrupt thread
|
||||
sub r2, lr, #4 @ save old task's pc to r2
|
||||
|
||||
@ Switch to SVC mode with no interrupt. If the usr mode guest is
|
||||
@ interrupted, this will just switch to the stack of kernel space.
|
||||
@ save the registers in kernel space won't trigger data abort.
|
||||
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
|
||||
|
||||
stmfd sp!, {r2} @ push old task's pc
|
||||
stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
|
||||
ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread
|
||||
stmfd sp!, {r1-r4} @ push old task's r0-r3
|
||||
stmfd sp!, {r0} @ push old task's cpsr
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
stmfd sp, {r13, r14}^ @push usr_sp, usr_lr
|
||||
sub sp, #8
|
||||
#endif
|
||||
|
||||
ldr r4, =rt_interrupt_from_thread
|
||||
ldr r5, [r4]
|
||||
str sp, [r5] @ store sp in preempted tasks's TCB
|
||||
|
||||
ldr r6, =rt_interrupt_to_thread
|
||||
ldr r6, [r6]
|
||||
ldr sp, [r6] @ get new task's stack pointer
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
ldmfd sp, {r13, r14}^ @pop usr_sp, usr_lr
|
||||
add sp, #8
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
|
||||
msr spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
|
||||
|
||||
#endif
|
||||
|
||||
.macro push_svc_reg
|
||||
sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */
|
||||
stmia sp, {r0 - r12} @/* Calling r0-r12 */
|
||||
mov r0, sp
|
||||
mrs r6, spsr @/* Save CPSR */
|
||||
str lr, [r0, #15*4] @/* Push PC */
|
||||
str r6, [r0, #16*4] @/* Push CPSR */
|
||||
cps #Mode_SVC
|
||||
str sp, [r0, #13*4] @/* Save calling SP */
|
||||
str lr, [r0, #14*4] @/* Save calling PC */
|
||||
.endm
|
||||
|
||||
.align 5
|
||||
.globl vector_swi
|
||||
.weak SVC_Handler
|
||||
SVC_Handler:
|
||||
vector_swi:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_swi
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_undef
|
||||
vector_undef:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_undef
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_pabt
|
||||
vector_pabt:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_pabt
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_dabt
|
||||
vector_dabt:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_dabt
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_resv
|
||||
vector_resv:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_resv
|
||||
b .
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
.global set_secondary_cpu_boot_address
|
||||
set_secondary_cpu_boot_address:
|
||||
ldr r0, =secondary_cpu_start
|
||||
|
||||
mvn r1, #0 //0xffffffff
|
||||
ldr r2, =0x10000034
|
||||
str r1, [r2]
|
||||
str r0, [r2, #-4]
|
||||
mov pc, lr
|
||||
|
||||
.global secondary_cpu_start
|
||||
secondary_cpu_start:
|
||||
mrc p15, 0, r1, c1, c0, 1
|
||||
mov r0, #(1<<6)
|
||||
orr r1, r0
|
||||
mcr p15, 0, r1, c1, c0, 1 //enable smp
|
||||
|
||||
ldr r0, =mtbl
|
||||
ldr lr, =1f
|
||||
|
||||
b enable_mmu
|
||||
1:
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, #(1<<13)
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
cps #Mode_IRQ
|
||||
ldr sp, =irq_stack_2_limit
|
||||
|
||||
cps #Mode_FIQ
|
||||
ldr sp, =irq_stack_2_limit
|
||||
|
||||
cps #Mode_SVC
|
||||
ldr sp, =svc_stack_2_limit
|
||||
|
||||
b secondary_cpu_c_start
|
||||
#endif
|
||||
|
||||
.bss
|
||||
.align 2 //align to 2~2=4
|
||||
svc_stack_2:
|
||||
.space (1 << 10)
|
||||
svc_stack_2_limit:
|
||||
|
||||
irq_stack_2:
|
||||
.space (1 << 10)
|
||||
irq_stack_2_limit:
|
||||
|
||||
.data
|
||||
#define DEVICE_MEM 0x10c06
|
||||
#define NORMAL_MEM 0x11c0e
|
||||
.align 14
|
||||
mtbl:
|
||||
|
||||
//vaddr: 0x00000000
|
||||
.rept 0x100
|
||||
.word 0x0
|
||||
.endr
|
||||
|
||||
//vaddr: 0x10000000
|
||||
.equ mmu_tbl_map_paddr, 0x10000000
|
||||
.rept 0x400
|
||||
.word mmu_tbl_map_paddr | DEVICE_MEM
|
||||
.equ mmu_tbl_map_paddr, mmu_tbl_map_paddr + 0x100000
|
||||
.endr
|
||||
|
||||
//vaddr: 0x50000000
|
||||
.rept 0x100
|
||||
.word 0x0
|
||||
.endr
|
||||
|
||||
//vaddr: 0x60000000
|
||||
.equ mmu_tbl_map_paddr, 0x60000000
|
||||
.rept 0x800
|
||||
.word mmu_tbl_map_paddr | NORMAL_MEM
|
||||
.equ mmu_tbl_map_paddr, mmu_tbl_map_paddr + 0x100000
|
||||
.endr
|
||||
|
||||
//vaddr: 0xe0000000
|
||||
.rept 0x200
|
||||
.word 0x0
|
||||
.endr
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
* File : trap.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2013, RT-Thread Develop Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-20 Bernard first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <board.h>
|
||||
|
||||
#include "armv7.h"
|
||||
|
||||
#include "gic.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("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3);
|
||||
rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7);
|
||||
rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10);
|
||||
rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip);
|
||||
rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc);
|
||||
rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_undef(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("undefined instruction:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* The software interrupt instruction (SWI) is used for entering
|
||||
* Supervisor mode, usually to request a particular supervisor
|
||||
* function.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_swi(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("software interrupt:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* An abort indicates that the current memory access cannot be completed,
|
||||
* which occurs during an instruction prefetch.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("prefetch abort:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* An abort indicates that the current memory access cannot be completed,
|
||||
* which occurs during a data access.
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("data abort:");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally, system will never reach here
|
||||
*
|
||||
* @param regs system registers
|
||||
*
|
||||
* @note never invoke this function in application
|
||||
*/
|
||||
void rt_hw_trap_resv(struct rt_hw_exp_stack *regs)
|
||||
{
|
||||
rt_kprintf("reserved trap:\n");
|
||||
rt_hw_show_register(regs);
|
||||
#ifdef RT_USING_FINSH
|
||||
list_thread();
|
||||
#endif
|
||||
rt_hw_cpu_shutdown();
|
||||
}
|
||||
|
||||
#define GIC_ACK_INTID_MASK 0x000003ff
|
||||
|
||||
void rt_hw_trap_irq(void)
|
||||
{
|
||||
void *param;
|
||||
unsigned long ir;
|
||||
unsigned long fullir;
|
||||
rt_isr_handler_t isr_func;
|
||||
extern struct rt_irq_desc isr_table[];
|
||||
|
||||
fullir = arm_gic_get_active_irq(0);
|
||||
ir = fullir & GIC_ACK_INTID_MASK;
|
||||
|
||||
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 */
|
||||
arm_gic_ack(0, fullir);
|
||||
}
|
||||
|
||||
void rt_hw_trap_fiq(void)
|
||||
{
|
||||
void *param;
|
||||
unsigned long ir;
|
||||
unsigned long fullir;
|
||||
rt_isr_handler_t isr_func;
|
||||
extern struct rt_irq_desc isr_table[];
|
||||
|
||||
fullir = arm_gic_get_active_irq(0);
|
||||
ir = fullir & GIC_ACK_INTID_MASK;
|
||||
|
||||
/* 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 */
|
||||
arm_gic_ack(0, fullir);
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* File : vector_gcc.S
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2013, RT-Thread Development Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
|
||||
.section .vectors, "ax"
|
||||
.code 32
|
||||
|
||||
.globl system_vectors
|
||||
system_vectors:
|
||||
ldr pc, _vector_reset
|
||||
ldr pc, _vector_undef
|
||||
ldr pc, _vector_swi
|
||||
ldr pc, _vector_pabt
|
||||
ldr pc, _vector_dabt
|
||||
ldr pc, _vector_resv
|
||||
ldr pc, _vector_irq
|
||||
ldr pc, _vector_fiq
|
||||
|
||||
.globl _reset
|
||||
.globl vector_undef
|
||||
.globl vector_swi
|
||||
.globl vector_pabt
|
||||
.globl vector_dabt
|
||||
.globl vector_resv
|
||||
.globl vector_irq
|
||||
.globl vector_fiq
|
||||
|
||||
_vector_reset:
|
||||
.word _reset
|
||||
_vector_undef:
|
||||
.word vector_undef
|
||||
_vector_swi:
|
||||
.word SVC_Handler
|
||||
_vector_pabt:
|
||||
.word vector_pabt
|
||||
_vector_dabt:
|
||||
.word vector_dabt
|
||||
_vector_resv:
|
||||
.word vector_resv
|
||||
_vector_irq:
|
||||
.word vector_irq
|
||||
_vector_fiq:
|
||||
.word vector_fiq
|
||||
|
||||
.balignl 16,0xdeadbeef
|
|
@ -17,6 +17,15 @@
|
|||
#include "board.h"
|
||||
#include "drv_timer.h"
|
||||
|
||||
#include <mmu.h>
|
||||
|
||||
struct mem_desc platform_mem_desc[] = {
|
||||
{0x10000000, 0x50000000, 0x10000000, DEVICE_MEM},
|
||||
{0x60000000, 0xe0000000, 0x60000000, NORMAL_MEM}
|
||||
};
|
||||
|
||||
const rt_uint32_t platform_mem_desc_size = sizeof(platform_mem_desc)/sizeof(platform_mem_desc[0]);
|
||||
|
||||
#define SYS_CTRL __REG32(REALVIEW_SCTL_BASE)
|
||||
|
||||
extern void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Split('''
|
||||
''')
|
||||
|
||||
CPPPATH = [ cwd + '/cpu',
|
||||
cwd + '/include',
|
||||
]
|
||||
|
||||
group = DefineGroup('Platform', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-03-22 quanzhao first version
|
||||
*/
|
||||
|
||||
#ifndef __PLATFORM_H__
|
||||
#define __PLATFORM_H__
|
||||
|
||||
/* for 'rt_inline' */
|
||||
#include <rtdef.h>
|
||||
/* SOC-relative definitions */
|
||||
#include "realview.h"
|
||||
|
||||
/* the maximum entries of the exception table */
|
||||
#define MAX_HANDLERS NR_IRQS_PBA8
|
||||
|
||||
/* the basic constants and interfaces needed by gic */
|
||||
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
||||
{
|
||||
return REALVIEW_GIC_DIST_BASE;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_cpu_base(void)
|
||||
{
|
||||
return REALVIEW_GIC_CPU_BASE;
|
||||
}
|
||||
|
||||
#define GIC_IRQ_START 0
|
||||
|
||||
#define GIC_ACK_INTID_MASK 0x000003ff
|
||||
|
||||
#endif /* __PLATFORM_H__ */
|
|
@ -10,7 +10,9 @@
|
|||
#define RT_USING_SMP
|
||||
#define RT_CPUS_NR 2
|
||||
#define RT_ALIGN_SIZE 4
|
||||
/* RT_THREAD_PRIORITY_8 is not set */
|
||||
#define RT_THREAD_PRIORITY_32
|
||||
/* RT_THREAD_PRIORITY_256 is not set */
|
||||
#define RT_THREAD_PRIORITY_MAX 32
|
||||
#define RT_TICK_PER_SECOND 100
|
||||
#define RT_USING_OVERFLOW_CHECK
|
||||
|
@ -37,7 +39,10 @@
|
|||
|
||||
#define RT_USING_MEMPOOL
|
||||
#define RT_USING_MEMHEAP
|
||||
/* RT_USING_NOHEAP is not set */
|
||||
#define RT_USING_SMALL_MEM
|
||||
/* RT_USING_SLAB is not set */
|
||||
/* RT_USING_MEMHEAP_AS_HEAP is not set */
|
||||
#define RT_USING_MEMTRACE
|
||||
#define RT_USING_HEAP
|
||||
|
||||
|
@ -53,6 +58,7 @@
|
|||
#define ARCH_ARM
|
||||
#define ARCH_ARM_CORTEX_A
|
||||
#define ARCH_ARM_CORTEX_A9
|
||||
/* ARCH_CPU_STACK_GROWS_UPWARD is not set */
|
||||
|
||||
/* RT-Thread Components */
|
||||
|
||||
|
@ -73,11 +79,14 @@
|
|||
#define FINSH_HISTORY_LINES 5
|
||||
#define FINSH_USING_SYMTAB
|
||||
#define FINSH_USING_DESCRIPTION
|
||||
/* FINSH_ECHO_DISABLE_DEFAULT is not set */
|
||||
#define FINSH_THREAD_PRIORITY 20
|
||||
#define FINSH_THREAD_STACK_SIZE 4096
|
||||
#define FINSH_CMD_SIZE 80
|
||||
/* FINSH_USING_AUTH is not set */
|
||||
#define FINSH_USING_MSH
|
||||
#define FINSH_USING_MSH_DEFAULT
|
||||
/* FINSH_USING_MSH_ONLY is not set */
|
||||
#define FINSH_ARG_MAX 10
|
||||
|
||||
/* Device virtual file system */
|
||||
|
@ -87,21 +96,29 @@
|
|||
#define DFS_FILESYSTEMS_MAX 2
|
||||
#define DFS_FILESYSTEM_TYPES_MAX 8
|
||||
#define DFS_FD_MAX 16
|
||||
/* RT_USING_DFS_MNTTABLE is not set */
|
||||
#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
|
||||
/* RT_DFS_ELM_USE_LFN_0 is not set */
|
||||
/* RT_DFS_ELM_USE_LFN_1 is not set */
|
||||
/* RT_DFS_ELM_USE_LFN_2 is not set */
|
||||
#define RT_DFS_ELM_USE_LFN_3
|
||||
#define RT_DFS_ELM_USE_LFN 3
|
||||
#define RT_DFS_ELM_MAX_LFN 255
|
||||
#define RT_DFS_ELM_DRIVES 2
|
||||
#define RT_DFS_ELM_MAX_SECTOR_SIZE 4096
|
||||
/* RT_DFS_ELM_USE_ERASE is not set */
|
||||
#define RT_DFS_ELM_REENTRANT
|
||||
#define RT_USING_DFS_DEVFS
|
||||
#define RT_USING_DFS_ROMFS
|
||||
#define RT_USING_DFS_RAMFS
|
||||
/* RT_USING_DFS_UFFS is not set */
|
||||
/* RT_USING_DFS_JFFS2 is not set */
|
||||
/* RT_USING_DFS_NFS is not set */
|
||||
|
||||
/* Device Drivers */
|
||||
|
||||
|
@ -110,12 +127,19 @@
|
|||
#define RT_USING_SERIAL
|
||||
#define RT_SERIAL_USING_DMA
|
||||
#define RT_SERIAL_RB_BUFSZ 64
|
||||
/* RT_USING_CAN is not set */
|
||||
/* RT_USING_HWTIMER is not set */
|
||||
/* RT_USING_CPUTIME is not set */
|
||||
#define RT_USING_I2C
|
||||
#define RT_USING_I2C_BITOPS
|
||||
#define RT_USING_PIN
|
||||
/* RT_USING_ADC is not set */
|
||||
/* RT_USING_PWM is not set */
|
||||
#define RT_USING_MTD_NOR
|
||||
#define RT_USING_MTD_NAND
|
||||
#define RT_MTD_NAND_DEBUG
|
||||
/* RT_USING_MTD is not set */
|
||||
/* RT_USING_PM is not set */
|
||||
#define RT_USING_RTC
|
||||
#define RT_USING_SOFT_RTC
|
||||
#define RT_USING_SDIO
|
||||
|
@ -124,18 +148,31 @@
|
|||
#define RT_MMCSD_STACK_SIZE 1024
|
||||
#define RT_MMCSD_THREAD_PREORITY 22
|
||||
#define RT_MMCSD_MAX_PARTITION 16
|
||||
/* RT_SDIO_DEBUG is not set */
|
||||
#define RT_USING_SPI
|
||||
/* RT_USING_QSPI is not set */
|
||||
#define RT_USING_SPI_MSD
|
||||
#define RT_USING_SFUD
|
||||
#define RT_SFUD_USING_SFDP
|
||||
#define RT_SFUD_USING_FLASH_INFO_TABLE
|
||||
/* RT_SFUD_USING_QSPI is not set */
|
||||
/* RT_DEBUG_SFUD is not set */
|
||||
/* RT_USING_W25QXX is not set */
|
||||
/* RT_USING_GD is not set */
|
||||
/* RT_USING_ENC28J60 is not set */
|
||||
/* RT_USING_SPI_WIFI is not set */
|
||||
#define RT_USING_WDT
|
||||
/* RT_USING_AUDIO is not set */
|
||||
/* RT_USING_SENSOR is not set */
|
||||
|
||||
/* Using WiFi */
|
||||
|
||||
/* RT_USING_WIFI is not set */
|
||||
|
||||
/* Using USB */
|
||||
|
||||
/* RT_USING_USB_HOST is not set */
|
||||
/* RT_USING_USB_DEVICE is not set */
|
||||
|
||||
/* POSIX layer and C standard library */
|
||||
|
||||
|
@ -145,6 +182,7 @@
|
|||
#define RT_USING_POSIX_MMAP
|
||||
#define RT_USING_POSIX_TERMIOS
|
||||
#define RT_USING_POSIX_AIO
|
||||
/* RT_USING_MODULE is not set */
|
||||
|
||||
/* Network */
|
||||
|
||||
|
@ -161,9 +199,13 @@
|
|||
/* light weight TCP/IP stack */
|
||||
|
||||
#define RT_USING_LWIP
|
||||
/* RT_USING_LWIP141 is not set */
|
||||
#define RT_USING_LWIP202
|
||||
/* RT_USING_LWIP210 is not set */
|
||||
#define RT_USING_LWIP_IPV6
|
||||
/* RT_LWIP_IGMP is not set */
|
||||
#define RT_LWIP_ICMP
|
||||
/* RT_LWIP_SNMP is not set */
|
||||
#define RT_LWIP_DNS
|
||||
#define RT_LWIP_DHCP
|
||||
#define IP_SOF_BROADCAST 1
|
||||
|
@ -176,6 +218,8 @@
|
|||
#define RT_LWIP_MSKADDR "255.255.255.0"
|
||||
#define RT_LWIP_UDP
|
||||
#define RT_LWIP_TCP
|
||||
/* RT_LWIP_RAW is not set */
|
||||
/* RT_LWIP_PPP is not set */
|
||||
#define RT_MEMP_NUM_NETCONN 8
|
||||
#define RT_LWIP_PBUF_NUM 16
|
||||
#define RT_LWIP_RAW_PCB_NUM 4
|
||||
|
@ -187,6 +231,8 @@
|
|||
#define RT_LWIP_TCPTHREAD_PRIORITY 10
|
||||
#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8
|
||||
#define RT_LWIP_TCPTHREAD_STACKSIZE 1024
|
||||
/* LWIP_NO_RX_THREAD is not set */
|
||||
/* LWIP_NO_TX_THREAD is not set */
|
||||
#define RT_LWIP_ETHTHREAD_PRIORITY 12
|
||||
#define RT_LWIP_ETHTHREAD_STACKSIZE 1024
|
||||
#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8
|
||||
|
@ -196,62 +242,164 @@
|
|||
#define LWIP_SO_RCVTIMEO 1
|
||||
#define LWIP_SO_SNDTIMEO 1
|
||||
#define LWIP_SO_RCVBUF 1
|
||||
/* RT_LWIP_NETIF_LOOPBACK is not set */
|
||||
#define LWIP_NETIF_LOOPBACK 0
|
||||
/* RT_LWIP_STATS is not set */
|
||||
/* RT_LWIP_DEBUG is not set */
|
||||
|
||||
/* Modbus master and slave stack */
|
||||
|
||||
/* RT_USING_MODBUS is not set */
|
||||
|
||||
/* AT commands */
|
||||
|
||||
/* RT_USING_AT is not set */
|
||||
/* LWIP_USING_DHCPD is not set */
|
||||
|
||||
/* VBUS(Virtual Software BUS) */
|
||||
|
||||
/* RT_USING_VBUS is not set */
|
||||
|
||||
/* Utilities */
|
||||
|
||||
#define RT_USING_LOGTRACE
|
||||
#define LOG_TRACE_MAX_SESSION 16
|
||||
/* LOG_TRACE_USING_LEVEL_NOTRACE is not set */
|
||||
/* LOG_TRACE_USING_LEVEL_ERROR is not set */
|
||||
/* LOG_TRACE_USING_LEVEL_WARNING is not set */
|
||||
#define LOG_TRACE_USING_LEVEL_INFO
|
||||
/* LOG_TRACE_USING_LEVEL_VERBOSE is not set */
|
||||
/* LOG_TRACE_USING_LEVEL_DEBUG is not set */
|
||||
/* LOG_TRACE_USING_MEMLOG is not set */
|
||||
/* RT_USING_RYM is not set */
|
||||
/* RT_USING_ULOG is not set */
|
||||
/* RT_USING_UTEST is not set */
|
||||
#define RT_USING_LWP
|
||||
|
||||
/* RT-Thread online packages */
|
||||
|
||||
/* IoT - internet of things */
|
||||
|
||||
/* PKG_USING_PAHOMQTT is not set */
|
||||
/* PKG_USING_WEBCLIENT is not set */
|
||||
/* PKG_USING_WEBNET is not set */
|
||||
/* PKG_USING_MONGOOSE is not set */
|
||||
/* PKG_USING_WEBTERMINAL is not set */
|
||||
/* PKG_USING_CJSON is not set */
|
||||
/* PKG_USING_JSMN is not set */
|
||||
/* PKG_USING_LIBMODBUS is not set */
|
||||
/* PKG_USING_LJSON is not set */
|
||||
/* PKG_USING_EZXML is not set */
|
||||
/* PKG_USING_NANOPB is not set */
|
||||
|
||||
/* Wi-Fi */
|
||||
|
||||
/* Marvell WiFi */
|
||||
|
||||
/* PKG_USING_WLANMARVELL is not set */
|
||||
|
||||
/* Wiced WiFi */
|
||||
|
||||
/* PKG_USING_WLAN_WICED is not set */
|
||||
/* PKG_USING_RW007 is not set */
|
||||
/* PKG_USING_COAP is not set */
|
||||
/* PKG_USING_NOPOLL is not set */
|
||||
/* PKG_USING_NETUTILS is not set */
|
||||
/* PKG_USING_AT_DEVICE is not set */
|
||||
/* PKG_USING_WIZNET is not set */
|
||||
|
||||
/* IoT Cloud */
|
||||
|
||||
/* PKG_USING_ONENET is not set */
|
||||
/* PKG_USING_GAGENT_CLOUD is not set */
|
||||
/* PKG_USING_ALI_IOTKIT is not set */
|
||||
/* PKG_USING_AZURE is not set */
|
||||
/* PKG_USING_TENCENT_IOTKIT is not set */
|
||||
/* PKG_USING_NIMBLE is not set */
|
||||
/* PKG_USING_OTA_DOWNLOADER is not set */
|
||||
|
||||
/* security packages */
|
||||
|
||||
/* PKG_USING_MBEDTLS is not set */
|
||||
/* PKG_USING_libsodium is not set */
|
||||
/* PKG_USING_TINYCRYPT is not set */
|
||||
|
||||
/* language packages */
|
||||
|
||||
/* PKG_USING_LUA is not set */
|
||||
/* PKG_USING_JERRYSCRIPT is not set */
|
||||
/* PKG_USING_MICROPYTHON is not set */
|
||||
|
||||
/* multimedia packages */
|
||||
|
||||
/* PKG_USING_OPENMV is not set */
|
||||
/* PKG_USING_MUPDF is not set */
|
||||
|
||||
/* tools packages */
|
||||
|
||||
/* PKG_USING_CMBACKTRACE is not set */
|
||||
/* PKG_USING_EASYFLASH is not set */
|
||||
/* PKG_USING_EASYLOGGER is not set */
|
||||
/* PKG_USING_SYSTEMVIEW is not set */
|
||||
/* PKG_USING_RDB is not set */
|
||||
/* PKG_USING_QRCODE is not set */
|
||||
/* PKG_USING_ULOG_EASYFLASH is not set */
|
||||
/* PKG_USING_ADBD is not set */
|
||||
|
||||
/* system packages */
|
||||
|
||||
/* PKG_USING_GUIENGINE is not set */
|
||||
/* PKG_USING_PERSIMMON is not set */
|
||||
/* PKG_USING_CAIRO is not set */
|
||||
/* PKG_USING_PIXMAN is not set */
|
||||
/* PKG_USING_LWEXT4 is not set */
|
||||
/* PKG_USING_PARTITION is not set */
|
||||
/* PKG_USING_FAL is not set */
|
||||
/* PKG_USING_SQLITE is not set */
|
||||
/* PKG_USING_RTI is not set */
|
||||
/* PKG_USING_LITTLEVGL2RTT is not set */
|
||||
/* PKG_USING_CMSIS is not set */
|
||||
/* PKG_USING_DFS_YAFFS is not set */
|
||||
/* PKG_USING_LITTLEFS is not set */
|
||||
|
||||
/* peripheral libraries and drivers */
|
||||
|
||||
/* sensors drivers */
|
||||
|
||||
/* PKG_USING_LSM6DSL is not set */
|
||||
/* PKG_USING_LPS22HB is not set */
|
||||
/* PKG_USING_HTS221 is not set */
|
||||
/* PKG_USING_LSM303AGR is not set */
|
||||
/* PKG_USING_BME280 is not set */
|
||||
/* PKG_USING_BMA400 is not set */
|
||||
/* PKG_USING_BMI160_BMX160 is not set */
|
||||
/* PKG_USING_SPL0601 is not set */
|
||||
/* PKG_USING_REALTEK_AMEBA is not set */
|
||||
/* PKG_USING_SHT2X is not set */
|
||||
/* PKG_USING_AHT10 is not set */
|
||||
/* PKG_USING_AP3216C is not set */
|
||||
/* PKG_USING_STM32_SDIO is not set */
|
||||
/* PKG_USING_ICM20608 is not set */
|
||||
/* PKG_USING_U8G2 is not set */
|
||||
/* PKG_USING_BUTTON is not set */
|
||||
/* PKG_USING_MPU6XXX is not set */
|
||||
/* PKG_USING_PCF8574 is not set */
|
||||
/* PKG_USING_SX12XX is not set */
|
||||
/* PKG_USING_KENDRYTE_SDK is not set */
|
||||
|
||||
/* miscellaneous packages */
|
||||
|
||||
/* PKG_USING_LIBCSV is not set */
|
||||
/* PKG_USING_OPTPARSE is not set */
|
||||
/* PKG_USING_FASTLZ is not set */
|
||||
/* PKG_USING_MINILZO is not set */
|
||||
/* PKG_USING_QUICKLZ is not set */
|
||||
/* PKG_USING_MULTIBUTTON is not set */
|
||||
/* PKG_USING_CANFESTIVAL is not set */
|
||||
/* PKG_USING_ZLIB is not set */
|
||||
/* PKG_USING_DSTR is not set */
|
||||
/* PKG_USING_TINYFRAME is not set */
|
||||
/* PKG_USING_KENDRYTE_DEMO is not set */
|
||||
|
||||
/* samples: kernel and components samples */
|
||||
|
||||
|
@ -259,5 +407,6 @@
|
|||
#define RT_USING_UART0
|
||||
#define RT_USING_UART1
|
||||
#define BSP_DRV_EMAC
|
||||
/* BSP_DRV_AUDIO is not set */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,14 +2,15 @@ import os
|
|||
|
||||
# toolchains options
|
||||
ARCH='arm'
|
||||
CPU='cortex-a9'
|
||||
CPU='cortex-a'
|
||||
CROSS_TOOL='gcc'
|
||||
|
||||
if os.getenv('RTT_CC'):
|
||||
CROSS_TOOL = os.getenv('RTT_CC')
|
||||
|
||||
# only support GNU GCC compiler.
|
||||
PLATFORM = 'gcc'
|
||||
EXEC_PATH = '/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin'
|
||||
EXEC_PATH = '/usr/bin'
|
||||
|
||||
if os.getenv('RTT_EXEC_PATH'):
|
||||
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
|
||||
|
|
|
@ -5,7 +5,7 @@ cwd = GetCurrentDir()
|
|||
src = []
|
||||
CPPPATH = [cwd]
|
||||
|
||||
support_arch = {"arm": ["cortex-m3", "cortex-m4", "cortex-m7", "arm926", "cortex-a9"]}
|
||||
support_arch = {"arm": ["cortex-m3", "cortex-m4", "cortex-m7", "arm926", "cortex-a"]}
|
||||
platform_file = {'armcc': 'rvds.S', 'gcc': 'gcc.S', 'iar': 'iar.S'}
|
||||
|
||||
if rtconfig.PLATFORM in platform_file.keys(): # support platforms
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-12-10 Jesven first version
|
||||
*/
|
||||
|
||||
#define Mode_USR 0x10
|
||||
#define Mode_FIQ 0x11
|
||||
#define Mode_IRQ 0x12
|
||||
#define Mode_SVC 0x13
|
||||
#define Mode_MON 0x16
|
||||
#define Mode_ABT 0x17
|
||||
#define Mode_UDF 0x1B
|
||||
#define Mode_SYS 0x1F
|
||||
|
||||
#define A_Bit 0x100
|
||||
#define I_Bit 0x80 @; when I bit is set, IRQ is disabled
|
||||
#define F_Bit 0x40 @; when F bit is set, FIQ is disabled
|
||||
#define T_Bit 0x20
|
||||
|
||||
.cpu cortex-a9
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
/*
|
||||
* void lwp_user_entry(args, text, data);
|
||||
*/
|
||||
.global lwp_user_entry
|
||||
.type lwp_user_entry, % function
|
||||
lwp_user_entry:
|
||||
mrs r9, cpsr
|
||||
bic r9, #0x1f
|
||||
orr r9, #Mode_USR
|
||||
cpsid i
|
||||
msr spsr, r9
|
||||
|
||||
/* set data address. */
|
||||
mov r9, r2
|
||||
movs pc, r1
|
||||
|
||||
/*
|
||||
* void SVC_Handler(void);
|
||||
*/
|
||||
.global SVC_Handler
|
||||
.type SVC_Handler, % function
|
||||
SVC_Handler:
|
||||
push {lr}
|
||||
mrs lr, spsr
|
||||
push {r4, r5, lr}
|
||||
cpsie i
|
||||
|
||||
push {r0 - r3, r12}
|
||||
and r0, r7, #0xff
|
||||
bl lwp_get_sys_api
|
||||
cmp r0, #0 /* r0 = api */
|
||||
mov lr, r0
|
||||
pop {r0 - r3, r12}
|
||||
beq svc_exit
|
||||
blx lr
|
||||
|
||||
svc_exit:
|
||||
cpsid i
|
||||
pop {r4, r5, lr}
|
||||
msr spsr_cxsf, lr
|
||||
pop {lr}
|
||||
movs pc, lr
|
|
@ -8,7 +8,14 @@
|
|||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
.section .text, "ax"
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#define rt_hw_interrupt_disable rt_hw_local_irq_disable
|
||||
#define rt_hw_interrupt_enable rt_hw_local_irq_enable
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable();
|
||||
*/
|
||||
|
@ -34,6 +41,16 @@ rt_hw_interrupt_enable:
|
|||
rt_hw_context_switch_to:
|
||||
ldr sp, [r0] @ get new task stack pointer
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mov r0, r1
|
||||
bl rt_cpus_lock_status_restore
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
ldmfd sp, {r13, r14}^ @ pop usr_sp usr_lr
|
||||
add sp, #8
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task spsr
|
||||
msr spsr_cxsf, r4
|
||||
|
||||
|
@ -62,9 +79,24 @@ rt_hw_context_switch:
|
|||
|
||||
stmfd sp!, {r4} @ push cpsr
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
stmfd sp, {r13, r14}^ @ push usr_sp usr_lr
|
||||
sub sp, #8
|
||||
#endif
|
||||
|
||||
str sp, [r0] @ store sp in preempted tasks TCB
|
||||
ldr sp, [r1] @ get new task stack pointer
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mov r0, r2
|
||||
bl rt_cpus_lock_status_restore
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
ldmfd sp, {r13, r14}^ @ pop usr_sp usr_lr
|
||||
add sp, #8
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task cpsr to spsr
|
||||
msr spsr_cxsf, r4
|
||||
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
|
||||
|
@ -72,11 +104,70 @@ rt_hw_context_switch:
|
|||
/*
|
||||
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
|
||||
*/
|
||||
.equ Mode_USR, 0x10
|
||||
.equ Mode_FIQ, 0x11
|
||||
.equ Mode_IRQ, 0x12
|
||||
.equ Mode_SVC, 0x13
|
||||
.equ Mode_ABT, 0x17
|
||||
.equ Mode_UND, 0x1B
|
||||
.equ Mode_SYS, 0x1F
|
||||
|
||||
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
|
||||
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
|
||||
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
#ifdef RT_USING_SMP
|
||||
/* r0 :irq_mod context
|
||||
* r1 :addr of from_thread's sp
|
||||
* r2 :addr of to_thread's sp
|
||||
* r3 :to_thread's tcb
|
||||
*/
|
||||
|
||||
@ r0 point to {r0-r3} in stack
|
||||
push {r1 - r3}
|
||||
mov r1, r0
|
||||
add r0, r0, #4*4
|
||||
ldmfd r0!, {r4-r12,lr}@ reload saved registers
|
||||
mrs r3, spsr @ get cpsr of interrupt thread
|
||||
sub r2, lr, #4 @ save old task's pc to r2
|
||||
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
|
||||
|
||||
stmfd sp!, {r2} @ push old task's pc
|
||||
stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
|
||||
ldmfd r1, {r4-r7} @ restore r0-r3 of the interrupt thread
|
||||
stmfd sp!, {r4-r7} @ push old task's r0-r3
|
||||
stmfd sp!, {r3} @ push old task's cpsr
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
stmfd sp, {r13,r14}^ @push usr_sp usr_lr
|
||||
sub sp, #8
|
||||
#endif
|
||||
|
||||
msr cpsr_c, #I_Bit|F_Bit|Mode_IRQ
|
||||
pop {r1 - r3}
|
||||
mov sp, r0
|
||||
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
|
||||
str sp, [r1]
|
||||
|
||||
ldr sp, [r2]
|
||||
mov r0, r3
|
||||
bl rt_cpus_lock_status_restore
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
ldmfd sp, {r13,r14}^ @pop usr_sp usr_lr
|
||||
add sp, #8
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
|
||||
msr spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
|
||||
|
||||
#else /*RT_USING_SMP*/
|
||||
ldr r2, =rt_thread_switch_interrupt_flag
|
||||
ldr r3, [r2]
|
||||
cmp r3, #1
|
||||
|
@ -89,3 +180,4 @@ _reswitch:
|
|||
ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
|
||||
str r1, [r2]
|
||||
bx lr
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2018-03-25 quanzhao the first version
|
||||
*/
|
||||
#ifndef __CP15_H__
|
||||
#define __CP15_H__
|
||||
|
@ -15,6 +16,9 @@ void rt_cpu_mmu_disable(void);
|
|||
void rt_cpu_mmu_enable(void);
|
||||
void rt_cpu_tlb_set(volatile unsigned long*);
|
||||
|
||||
void rt_cpu_dcache_clean_flush(void);
|
||||
void rt_cpu_icache_flush(void);
|
||||
|
||||
void rt_cpu_vector_set_base(unsigned int addr);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,11 @@ rt_cpu_get_smp_id:
|
|||
|
||||
.globl rt_cpu_vector_set_base
|
||||
rt_cpu_vector_set_base:
|
||||
/* clear SCTRL.V to customize the vector address */
|
||||
mrc p15, #0, r1, c1, c0, #0
|
||||
bic r1, #(1 << 13)
|
||||
mcr p15, #0, r1, c1, c0, #0
|
||||
/* set up the vector address */
|
||||
mcr p15, #0, r0, c12, c0, #0
|
||||
dsb
|
||||
bx lr
|
||||
|
@ -36,7 +41,7 @@ rt_hw_cpu_icache_enable:
|
|||
_FLD_MAX_WAY:
|
||||
.word 0x3ff
|
||||
_FLD_MAX_IDX:
|
||||
.word 0x7ff
|
||||
.word 0x7fff
|
||||
|
||||
.globl rt_cpu_dcache_clean_flush
|
||||
rt_cpu_dcache_clean_flush:
|
||||
|
@ -84,6 +89,14 @@ finished:
|
|||
pop {r4-r11}
|
||||
bx lr
|
||||
|
||||
.globl rt_cpu_icache_flush
|
||||
rt_cpu_icache_flush:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
|
||||
dsb
|
||||
isb
|
||||
bx lr
|
||||
|
||||
.globl rt_hw_cpu_dcache_disable
|
||||
rt_hw_cpu_dcache_disable:
|
||||
push {r4-r11, lr}
|
||||
|
|
|
@ -6,28 +6,78 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-09-15 Bernard first version
|
||||
* 2018-11-22 Jesven add rt_hw_cpu_id()
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
int rt_hw_cpu_id(void)
|
||||
{
|
||||
int cpu_id;
|
||||
__asm__ volatile (
|
||||
"mrc p15, 0, %0, c0, c0, 5"
|
||||
:"=r"(cpu_id)
|
||||
);
|
||||
cpu_id &= 0xf;
|
||||
return cpu_id;
|
||||
};
|
||||
|
||||
void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
unsigned long tmp;
|
||||
unsigned long newval;
|
||||
rt_hw_spinlock_t lockval;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"pld [%0]"
|
||||
::"r"(&lock->slock)
|
||||
);
|
||||
|
||||
__asm__ __volatile__(
|
||||
"1: ldrex %0, [%3]\n"
|
||||
" add %1, %0, %4\n"
|
||||
" strex %2, %1, [%3]\n"
|
||||
" teq %2, #0\n"
|
||||
" bne 1b"
|
||||
: "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
|
||||
: "r" (&lock->slock), "I" (1 << 16)
|
||||
: "cc");
|
||||
|
||||
while (lockval.tickets.next != lockval.tickets.owner) {
|
||||
__asm__ __volatile__("wfe":::"memory");
|
||||
lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner);
|
||||
}
|
||||
|
||||
__asm__ volatile ("dmb":::"memory");
|
||||
}
|
||||
|
||||
void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
|
||||
{
|
||||
__asm__ volatile ("dmb":::"memory");
|
||||
lock->tickets.owner++;
|
||||
__asm__ volatile ("dsb ishst\nsev":::"memory");
|
||||
}
|
||||
#endif /*RT_USING_SMP*/
|
||||
|
||||
/**
|
||||
* @addtogroup AM33xx
|
||||
* @addtogroup ARM CPU
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/** shutdown CPU */
|
||||
void rt_hw_cpu_shutdown()
|
||||
{
|
||||
rt_uint32_t level;
|
||||
rt_kprintf("shutdown...\n");
|
||||
rt_uint32_t level;
|
||||
rt_kprintf("shutdown...\n");
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
level = rt_hw_interrupt_disable();
|
||||
while (level)
|
||||
{
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
/*
|
||||
* File : gic.c, ARM Generic Interrupt Controller
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2013-2014, RT-Thread Develop Team
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
|
@ -17,18 +13,19 @@
|
|||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <board.h>
|
||||
|
||||
#include "gic.h"
|
||||
#include "cp15.h"
|
||||
|
||||
struct arm_gic
|
||||
{
|
||||
rt_uint32_t offset;
|
||||
rt_uint32_t offset; /* the first interrupt index in the vector table */
|
||||
|
||||
rt_uint32_t dist_hw_base;
|
||||
rt_uint32_t cpu_hw_base;
|
||||
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];
|
||||
|
||||
#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00)
|
||||
|
@ -118,6 +115,7 @@ void arm_gic_clear_active(rt_uint32_t index, int irq)
|
|||
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;
|
||||
|
@ -215,11 +213,12 @@ int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
|
|||
*/
|
||||
if (_gic_max_irq > 1020)
|
||||
_gic_max_irq = 1020;
|
||||
if (_gic_max_irq > ARM_GIC_NR_IRQS)
|
||||
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;
|
||||
|
||||
|
@ -244,9 +243,11 @@ int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
|
|||
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) = 0x03;
|
||||
GIC_DIST_CTRL(dist_base) = 0x01;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -258,6 +259,7 @@ int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base)
|
|||
_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;
|
||||
|
|
@ -1,11 +1,7 @@
|
|||
/*
|
||||
* File : gic.h, ARM Generic Interrupt Controller
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2013, RT-Thread Develop Team
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
|
@ -15,6 +11,9 @@
|
|||
#ifndef __GIC_H__
|
||||
#define __GIC_H__
|
||||
|
||||
#include <rthw.h>
|
||||
#include <platform.h>
|
||||
|
||||
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);
|
||||
|
||||
|
@ -26,8 +25,11 @@ 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 rt_hw_vector_init(void);
|
||||
void arm_gic_dump(rt_uint32_t index);
|
||||
|
||||
#endif
|
||||
|
|
@ -6,68 +6,32 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-06 Bernard first version
|
||||
* 2014-04-03 Grissiom port to VMM
|
||||
* 2018-11-22 Jesven add smp support
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "interrupt.h"
|
||||
#include "gic.h"
|
||||
|
||||
#include <irq_numbers.h>
|
||||
#include <interrupt.h>
|
||||
|
||||
#include <gic.h>
|
||||
#include "cp15.h"
|
||||
|
||||
#define MAX_HANDLERS IMX_INTERRUPT_COUNT
|
||||
|
||||
extern volatile rt_uint8_t rt_interrupt_nest;
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||||
|
||||
rt_uint32_t rt_interrupt_from_thread;
|
||||
rt_uint32_t rt_interrupt_to_thread;
|
||||
rt_uint32_t rt_thread_switch_interrupt_flag;
|
||||
#ifndef RT_USING_SMP
|
||||
/* Those varibles will be accessed in ISR, so we need to share them. */
|
||||
rt_uint32_t rt_interrupt_from_thread = 0;
|
||||
rt_uint32_t rt_interrupt_to_thread = 0;
|
||||
rt_uint32_t rt_thread_switch_interrupt_flag = 0;
|
||||
#endif
|
||||
|
||||
const unsigned int VECTOR_BASE = 0x00;
|
||||
extern void rt_cpu_vector_set_base(unsigned int addr);
|
||||
extern int system_vectors;
|
||||
|
||||
/* keep compatible with platform SDK */
|
||||
void register_interrupt_routine(uint32_t irq_id, irq_hdlr_t isr)
|
||||
void rt_hw_vector_init(void)
|
||||
{
|
||||
rt_hw_interrupt_install(irq_id, (rt_isr_handler_t)isr, NULL, "unknown");
|
||||
}
|
||||
|
||||
void enable_interrupt(uint32_t irq_id, uint32_t cpu_id, uint32_t priority)
|
||||
{
|
||||
gic_set_irq_priority(irq_id, priority);
|
||||
gic_set_irq_security(irq_id, false); // set IRQ as non-secure
|
||||
gic_set_cpu_target(irq_id, cpu_id, true);
|
||||
gic_enable_irq(irq_id, true);
|
||||
}
|
||||
|
||||
void disable_interrupt(uint32_t irq_id, uint32_t cpu_id)
|
||||
{
|
||||
gic_enable_irq(irq_id, false);
|
||||
gic_set_cpu_target(irq_id, cpu_id, false);
|
||||
}
|
||||
|
||||
static void rt_hw_vector_init(void)
|
||||
{
|
||||
int sctrl;
|
||||
unsigned int *src = (unsigned int *)&system_vectors;
|
||||
|
||||
/* C12-C0 is only active when SCTLR.V = 0 */
|
||||
asm volatile ("mrc p15, #0, %0, c1, c0, #0"
|
||||
:"=r" (sctrl));
|
||||
sctrl &= ~(1 << 13);
|
||||
asm volatile ("mcr p15, #0, %0, c1, c0, #0"
|
||||
:
|
||||
:"r" (sctrl));
|
||||
|
||||
asm volatile ("mcr p15, #0, %0, c12, c0, #0"
|
||||
:
|
||||
:"r" (src));
|
||||
rt_cpu_vector_set_base((unsigned int)&system_vectors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,14 +39,24 @@ static void rt_hw_vector_init(void)
|
|||
*/
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
rt_hw_vector_init();
|
||||
gic_init();
|
||||
rt_uint32_t gic_cpu_base;
|
||||
rt_uint32_t gic_dist_base;
|
||||
rt_uint32_t gic_irq_start;
|
||||
|
||||
/* 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;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,7 +65,7 @@ void rt_hw_interrupt_init(void)
|
|||
*/
|
||||
void rt_hw_interrupt_mask(int vector)
|
||||
{
|
||||
disable_interrupt(vector, 0);
|
||||
arm_gic_mask(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,9 +74,26 @@ void rt_hw_interrupt_mask(int vector)
|
|||
*/
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
enable_interrupt(vector, 0, 0);
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* This function will install a interrupt service routine to a interrupt.
|
||||
* @param vector the interrupt number
|
||||
|
@ -126,23 +117,7 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
|||
isr_table[vector].handler = handler;
|
||||
isr_table[vector].param = param;
|
||||
}
|
||||
// arm_gic_set_cpu(0, vector, 1 << rt_cpu_get_smp_id());
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a software IRQ
|
||||
*
|
||||
* Since we are running in single core, the target CPU are always CPU0.
|
||||
*/
|
||||
void rt_hw_interrupt_trigger(int vector)
|
||||
{
|
||||
// arm_gic_trigger(0, 1, vector);
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_clear(int vector)
|
||||
{
|
||||
gic_write_end_of_irq(vector);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, 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 <platform.h>
|
||||
|
||||
#define INT_IRQ 0x00
|
||||
#define INT_FIQ 0x01
|
||||
|
||||
void rt_hw_interrupt_control(int vector, int priority, int route);
|
||||
|
||||
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);
|
||||
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name);
|
||||
|
||||
#endif
|
|
@ -13,35 +13,7 @@
|
|||
#include <board.h>
|
||||
|
||||
#include "cp15.h"
|
||||
|
||||
#define DESC_SEC (0x2)
|
||||
#define CB (3<<2) //cache_on, write_back
|
||||
#define CNB (2<<2) //cache_on, write_through
|
||||
#define NCB (1<<2) //cache_off,WR_BUF on
|
||||
#define NCNB (0<<2) //cache_off,WR_BUF off
|
||||
#define AP_RW (3<<10) //supervisor=RW, user=RW
|
||||
#define AP_RO (2<<10) //supervisor=RW, user=RO
|
||||
#define XN (1<<4) // eXecute Never
|
||||
|
||||
#define DOMAIN_FAULT (0x0)
|
||||
#define DOMAIN_CHK (0x1)
|
||||
#define DOMAIN_NOTCHK (0x3)
|
||||
#define DOMAIN0 (0x0<<5)
|
||||
#define DOMAIN1 (0x1<<5)
|
||||
|
||||
#define DOMAIN0_ATTR (DOMAIN_CHK<<0)
|
||||
#define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
|
||||
|
||||
/* Read/Write, cache, write back */
|
||||
#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC)
|
||||
/* Read/Write, cache, write through */
|
||||
#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC)
|
||||
/* Read/Write without cache and write buffer */
|
||||
#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC)
|
||||
/* Read/Write without cache and write buffer, no execute */
|
||||
#define RW_NCNBXN (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN)
|
||||
/* Read/Write without cache and write buffer */
|
||||
#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC)
|
||||
#include "mmu.h"
|
||||
|
||||
/* dump 2nd level page table */
|
||||
void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb)
|
||||
|
@ -178,18 +150,25 @@ unsigned long rt_hw_set_domain_register(unsigned long domain_val)
|
|||
return old_domain;
|
||||
}
|
||||
|
||||
void rt_hw_init_mmu_table(struct mem_desc *mdesc, rt_uint32_t size)
|
||||
{
|
||||
/* set page table */
|
||||
for(; size > 0; size--)
|
||||
{
|
||||
rt_hw_mmu_setmtt(mdesc->vaddr_start, mdesc->vaddr_end,
|
||||
mdesc->paddr_start, mdesc->attr);
|
||||
mdesc++;
|
||||
}
|
||||
}
|
||||
|
||||
void rt_hw_mmu_init(void)
|
||||
{
|
||||
rt_cpu_dcache_clean_flush();
|
||||
rt_cpu_icache_flush();
|
||||
rt_hw_cpu_dcache_disable();
|
||||
rt_hw_cpu_icache_disable();
|
||||
rt_cpu_mmu_disable();
|
||||
|
||||
/* set page table */
|
||||
/* 4G 1:1 memory */
|
||||
rt_hw_mmu_setmtt(0, 0xffffffff-1, 0, RW_CB);
|
||||
/* IO memory region */
|
||||
rt_hw_mmu_setmtt(0x44000000, 0x80000000-1, 0x44000000, RW_NCNBXN);
|
||||
|
||||
/*rt_hw_cpu_dump_page_table(MMUTable);*/
|
||||
rt_hw_set_domain_register(0x55555555);
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-03-25 quanzhao the first version
|
||||
*/
|
||||
#ifndef __MMU_H_
|
||||
#define __MMU_H_
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#define DESC_SEC (0x2)
|
||||
#define MEMWB (3<<2) /* write back, no write allocate */
|
||||
#define MEMWT (2<<2) /* write through, no write allocate */
|
||||
#define SHAREDEVICE (1<<2) /* shared device */
|
||||
#define STRONGORDER (0<<2) /* strong ordered */
|
||||
#define XN (1<<4) /* eXecute Never */
|
||||
#define AP_RW (3<<10) /* supervisor=RW, user=RW */
|
||||
#define AP_RO (2<<10) /* supervisor=RW, user=RO */
|
||||
#define SHARED (1<<16) /* shareable */
|
||||
|
||||
#define DOMAIN_FAULT (0x0)
|
||||
#define DOMAIN_CHK (0x1)
|
||||
#define DOMAIN_NOTCHK (0x3)
|
||||
#define DOMAIN0 (0x0<<5)
|
||||
#define DOMAIN1 (0x1<<5)
|
||||
|
||||
#define DOMAIN0_ATTR (DOMAIN_CHK<<0)
|
||||
#define DOMAIN1_ATTR (DOMAIN_FAULT<<2)
|
||||
|
||||
/* device mapping type */
|
||||
#define DEVICE_MEM (SHARED|AP_RW|DOMAIN0|SHAREDEVICE|DESC_SEC|XN)
|
||||
/* normal memory mapping type */
|
||||
#define NORMAL_MEM (SHARED|AP_RW|DOMAIN0|MEMWB|DESC_SEC)
|
||||
|
||||
struct mem_desc
|
||||
{
|
||||
rt_uint32_t vaddr_start;
|
||||
rt_uint32_t vaddr_end;
|
||||
rt_uint32_t paddr_start;
|
||||
rt_uint32_t attr;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -50,13 +50,17 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
|
|||
*(--stk) = 0xdeadbeef; /* r2 */
|
||||
*(--stk) = 0xdeadbeef; /* r1 */
|
||||
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
|
||||
|
||||
/* cpsr */
|
||||
if ((rt_uint32_t)tentry & 0x01)
|
||||
*(--stk) = SVCMODE | 0x20; /* thumb mode */
|
||||
else
|
||||
*(--stk) = SVCMODE; /* arm mode */
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
*(--stk) = 0; /* user lr */
|
||||
*(--stk) = 0; /* user sp*/
|
||||
#endif
|
||||
|
||||
/* return task's current stack address */
|
||||
return (rt_uint8_t *)stk;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,12 @@
|
|||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
* 2018-11-22 Jesven in the interrupt context, use rt_scheduler_do_irq_switch checks
|
||||
* and switches to a new thread
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
|
||||
.equ Mode_USR, 0x10
|
||||
.equ Mode_FIQ, 0x11
|
||||
.equ Mode_IRQ, 0x12
|
||||
|
@ -20,11 +24,11 @@
|
|||
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
|
||||
|
||||
.equ UND_Stack_Size, 0x00000000
|
||||
.equ SVC_Stack_Size, 0x00000100
|
||||
.equ SVC_Stack_Size, 0x00000400
|
||||
.equ ABT_Stack_Size, 0x00000000
|
||||
.equ RT_FIQ_STACK_PGSZ, 0x00000000
|
||||
.equ RT_IRQ_STACK_PGSZ, 0x00000100
|
||||
.equ USR_Stack_Size, 0x00000100
|
||||
.equ RT_IRQ_STACK_PGSZ, 0x00000800
|
||||
.equ USR_Stack_Size, 0x00000400
|
||||
|
||||
#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
|
||||
RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ)
|
||||
|
@ -44,12 +48,8 @@ stack_top:
|
|||
/* reset entry */
|
||||
.globl _reset
|
||||
_reset:
|
||||
bl rt_cpu_mmu_disable
|
||||
/* set the cpu to SVC32 mode and disable interrupt */
|
||||
mrs r0, cpsr
|
||||
bic r0, r0, #0x1f
|
||||
orr r0, r0, #0x13
|
||||
msr cpsr_c, r0
|
||||
cps #Mode_SVC
|
||||
|
||||
/* setup stack */
|
||||
bl stack_setup
|
||||
|
@ -64,6 +64,20 @@ bss_loop:
|
|||
strlo r0,[r1],#4 /* clear 4 bytes */
|
||||
blo bss_loop /* loop until done */
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mrc p15, 0, r1, c1, c0, 1
|
||||
mov r0, #(1<<6)
|
||||
orr r1, r0
|
||||
mcr p15, 0, r1, c1, c0, 1 //enable smp
|
||||
#endif
|
||||
|
||||
/* initialize the mmu table and enable mmu */
|
||||
ldr r0, =platform_mem_desc
|
||||
ldr r1, =platform_mem_desc_size
|
||||
ldr r1, [r1]
|
||||
bl rt_hw_init_mmu_table
|
||||
bl rt_hw_mmu_init
|
||||
|
||||
/* call C++ constructors of global objects */
|
||||
ldr r0, =__ctors_start__
|
||||
ldr r1, =__ctors_end__
|
||||
|
@ -137,12 +151,22 @@ vector_fiq:
|
|||
.align 5
|
||||
.globl vector_irq
|
||||
vector_irq:
|
||||
#ifdef RT_USING_SMP
|
||||
clrex
|
||||
#endif
|
||||
stmfd sp!, {r0-r12,lr}
|
||||
|
||||
bl rt_interrupt_enter
|
||||
bl rt_hw_trap_irq
|
||||
bl rt_interrupt_leave
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
mov r0, sp
|
||||
bl rt_scheduler_do_irq_switch
|
||||
|
||||
ldmfd sp!, {r0-r12,lr}
|
||||
subs pc, lr, #4
|
||||
#else
|
||||
@ if rt_thread_switch_interrupt_flag set, jump to
|
||||
@ rt_hw_context_switch_interrupt_do and don't return
|
||||
ldr r0, =rt_thread_switch_interrupt_flag
|
||||
|
@ -174,6 +198,11 @@ rt_hw_context_switch_interrupt_do:
|
|||
stmfd sp!, {r1-r4} @ push old task's r0-r3
|
||||
stmfd sp!, {r0} @ push old task's cpsr
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
stmfd sp, {r13, r14}^ @push usr_sp, usr_lr
|
||||
sub sp, #8
|
||||
#endif
|
||||
|
||||
ldr r4, =rt_interrupt_from_thread
|
||||
ldr r5, [r4]
|
||||
str sp, [r5] @ store sp in preempted tasks's TCB
|
||||
|
@ -182,11 +211,18 @@ rt_hw_context_switch_interrupt_do:
|
|||
ldr r6, [r6]
|
||||
ldr sp, [r6] @ get new task's stack pointer
|
||||
|
||||
#ifdef RT_USING_LWP
|
||||
ldmfd sp, {r13, r14}^ @pop usr_sp, usr_lr
|
||||
add sp, #8
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
|
||||
msr spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
|
||||
|
||||
#endif
|
||||
|
||||
.macro push_svc_reg
|
||||
sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */
|
||||
stmia sp, {r0 - r12} @/* Calling r0-r12 */
|
||||
|
@ -200,36 +236,86 @@ rt_hw_context_switch_interrupt_do:
|
|||
.endm
|
||||
|
||||
.align 5
|
||||
.globl vector_swi
|
||||
.globl vector_swi
|
||||
.weak SVC_Handler
|
||||
SVC_Handler:
|
||||
vector_swi:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_swi
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_undef
|
||||
.globl vector_undef
|
||||
vector_undef:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_undef
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_pabt
|
||||
.globl vector_pabt
|
||||
vector_pabt:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_pabt
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_dabt
|
||||
.globl vector_dabt
|
||||
vector_dabt:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_dabt
|
||||
b .
|
||||
|
||||
.align 5
|
||||
.globl vector_resv
|
||||
.globl vector_resv
|
||||
vector_resv:
|
||||
push_svc_reg
|
||||
bl rt_hw_trap_resv
|
||||
b .
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
.global set_secondary_cpu_boot_address
|
||||
set_secondary_cpu_boot_address:
|
||||
ldr r0, =secondary_cpu_start
|
||||
|
||||
mvn r1, #0 //0xffffffff
|
||||
ldr r2, =0x10000034
|
||||
str r1, [r2]
|
||||
str r0, [r2, #-4]
|
||||
mov pc, lr
|
||||
|
||||
.global secondary_cpu_start
|
||||
secondary_cpu_start:
|
||||
mrc p15, 0, r1, c1, c0, 1
|
||||
mov r0, #(1<<6)
|
||||
orr r1, r0
|
||||
mcr p15, 0, r1, c1, c0, 1 //enable smp
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
bic r0, #(1<<13)
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
cps #Mode_IRQ
|
||||
ldr sp, =irq_stack_2_limit
|
||||
|
||||
cps #Mode_FIQ
|
||||
ldr sp, =irq_stack_2_limit
|
||||
|
||||
cps #Mode_SVC
|
||||
ldr sp, =svc_stack_2_limit
|
||||
|
||||
/* initialize the mmu table and enable mmu */
|
||||
bl rt_hw_mmu_init
|
||||
|
||||
b secondary_cpu_c_start
|
||||
#endif
|
||||
|
||||
.bss
|
||||
.align 2 //align to 2~2=4
|
||||
svc_stack_2:
|
||||
.space (1 << 10)
|
||||
svc_stack_2_limit:
|
||||
|
||||
irq_stack_2:
|
||||
.space (1 << 10)
|
||||
irq_stack_2_limit:
|
||||
|
||||
|
|
|
@ -10,13 +10,11 @@
|
|||
|
||||
#include <rtthread.h>
|
||||
#include <rthw.h>
|
||||
#include <board.h>
|
||||
#include <platform.h>
|
||||
|
||||
#include "armv7.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
#include "gic.h"
|
||||
|
||||
extern struct rt_thread *rt_current_thread;
|
||||
#ifdef RT_USING_FINSH
|
||||
extern long list_thread(void);
|
||||
#endif
|
||||
|
@ -130,48 +128,52 @@ void rt_hw_trap_resv(struct rt_hw_exp_stack *regs)
|
|||
void rt_hw_trap_irq(void)
|
||||
{
|
||||
void *param;
|
||||
int ir;
|
||||
rt_isr_handler_t isr_func;
|
||||
extern struct rt_irq_desc isr_table[];
|
||||
|
||||
// vectNum = RESERVED[31:13] | CPUID[12:10] | INTERRUPT_ID[9:0]
|
||||
// send ack and get ID source
|
||||
uint32_t vectNum = gic_read_irq_ack();
|
||||
ir = rt_hw_interrupt_get_irq();
|
||||
|
||||
// Check that INT_ID isn't 1023 or 1022 (spurious interrupt)
|
||||
if (vectNum & 0x0200)
|
||||
if (ir == 1023)
|
||||
{
|
||||
gic_write_end_of_irq(vectNum); // send end of irq
|
||||
/* Spurious interrupt */
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy the local value to the global image of CPUID
|
||||
unsigned cpu = (vectNum >> 10) & 0x7;
|
||||
unsigned irq = vectNum & 0x1FF;
|
||||
|
||||
/* skip warning */
|
||||
cpu = cpu;
|
||||
|
||||
// Call the service routine stored in the handlers array. If there isn't
|
||||
// one for this IRQ, then call the default handler.
|
||||
/* get interrupt service routine */
|
||||
isr_func = isr_table[irq].handler;
|
||||
/* get interrupt service routine */
|
||||
isr_func = isr_table[ir].handler;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
isr_table[irq].counter++;
|
||||
isr_table[ir].counter++;
|
||||
#endif
|
||||
if (isr_func)
|
||||
{
|
||||
/* Interrupt for myself. */
|
||||
param = isr_table[irq].param;
|
||||
/* turn to interrupt service routine */
|
||||
isr_func(irq, param);
|
||||
}
|
||||
|
||||
// Signal the end of the irq.
|
||||
gic_write_end_of_irq(vectNum);
|
||||
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)
|
||||
{
|
||||
/* TODO */
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue