Update XiZi_AIoT Kernel from tuyuyang

it is OK
This commit is contained in:
xuedongliang 2025-01-13 16:49:36 +08:00
commit dca3e93959
512 changed files with 140610 additions and 1554 deletions

View File

@ -4,7 +4,7 @@ MAKEFLAGS += --no-print-directory
.PHONY:COMPILE_APP COMPILE_KERNEL
riscv_support :=
arm_support += imx6q-sabrelite zynq7000-zc702 ok1028a-c
arm_support += imx6q-sabrelite zynq7000-zc702 3568
emulator_support +=
support := $(riscv_support) $(arm_support) $(emulator_support)
SRC_DIR :=
@ -34,8 +34,8 @@ export UBIQUITOUS_ROOT ?= ..
ifneq ($(findstring $(BOARD), imx6q-sabrelite zynq7000-zc702), )
include $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_$(BOARD)/config.mk
endif
ifneq ($(findstring $(BOARD), ok1028a-c), )
include $(KERNEL_ROOT)/hardkernel/arch/arm/armv8-a/cortex-a72/preboot_for_$(BOARD)/config.mk
ifneq ($(findstring $(BOARD), 3568), )
include $(KERNEL_ROOT)/hardkernel/arch/arm/armv8-a/cortex-a55/preboot_for_$(BOARD)/config.mk
endif
export BSP_BUILD_DIR := $(KERNEL_ROOT)
export HOSTTOOLS_DIR ?= $(KERNEL_ROOT)/services/tools/hosttools
@ -133,6 +133,8 @@ clean:
@rm -rf services/tools/mkfs/mkfs
@rm -rf services/app/fs.img
@rm -rf services/app/user.map
@rm -rf services/net/net_server/user.map
@rm -rf services/net/net_server/bin
distclean:
@echo Clean all configuration

View File

@ -34,7 +34,7 @@ $(eval LOCALC := $(addprefix $(BUILD_DIR)/,$(COBJ))) \
$(eval OBJS += $(LOCALC)) \
$(if $(strip $(LOCALC)),$(eval $(LOCALC): $(1)
@if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi
@echo cc $$<
@echo cc $(subst $(KERNEL_ROOT)/,,$$<)
@/bin/echo -n $(dir $(LOCALC)) >>$(KERNEL_ROOT)/build/make.dep
@($(CROSS_COMPILE)gcc -MM $$(CFLAGS) -c $$<) >>$(KERNEL_ROOT)/build/make.dep
@$(CROSS_COMPILE)gcc $$(CFLAGS) -c $$< -o $$@))

View File

@ -1,5 +1,5 @@
# The following three platforms support compatiable instructions.
ifneq ($(findstring $(BOARD), ok1028a-c), )
ifneq ($(findstring $(BOARD), 3568), )
SRC_DIR := armv8-a
endif
ifneq ($(findstring $(BOARD), imx6q-sabrelite zynq7000-zc702), )

View File

@ -76,6 +76,13 @@ Modification:
#define NR_CPU 4
static inline uint64_t arch_current_tick()
{
uint32_t tick = 0;
__asm__ __volatile__("MRC p15, 0, %0, c9, c13, 0" : "=r"(tick)); // %0 应该是输出操作数
return (uint64_t)tick;
}
__attribute__((always_inline, optimize("O0"))) static inline uint32_t user_mode()
{
uint32_t val;

View File

@ -77,7 +77,7 @@ _boot_start:
mul r3, r2, r1
sub r0, r0, r3
msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT
msr CPSR_c, #ARM_MODE_SVC | I_BIT
mov sp, r0
sub r0, r0, r1

View File

@ -0,0 +1,710 @@
/*
* Copyright (c) 2012, Freescale Semiconductor, Inc.
* All rights reserved.
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "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 FREESCALE 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.
*/
/*
* WARNING! DO NOT EDIT THIS FILE DIRECTLY!
*
* This file was generated automatically and any changes may be lost.
*/
#ifndef __HW_EPIT_REGISTERS_H__
#define __HW_EPIT_REGISTERS_H__
#include "regs.h"
#include "soc_memory_map.h"
/*
* i.MX6SL EPIT
*
* EPIT
*
* Registers defined in this header file:
* - HW_EPIT_CR - Control register
* - HW_EPIT_SR - Status register
* - HW_EPIT_LR - Load register
* - HW_EPIT_CMPR - Compare register
* - HW_EPIT_CNR - Counter register
*
* - hw_epit_t - Struct containing all module registers.
*/
//! @name Module base addresses
//@{
#ifndef REGS_EPIT_BASE
#define HW_EPIT_INSTANCE_COUNT (2) //!< Number of instances of the EPIT module.
#define HW_EPIT1 (1) //!< Instance number for EPIT1.
#define HW_EPIT2 (2) //!< Instance number for EPIT2.
#define REGS_EPIT1_BASE USERLAND_MMIO_P2V(0x020d0000) //!< Base address for EPIT instance number 1.
#define REGS_EPIT2_BASE USERLAND_MMIO_P2V(0x020d4000) //!< Base address for EPIT instance number 2.
//! @brief Get the base address of EPIT by instance number.
//! @param x EPIT instance number, from 1 through 2.
#define REGS_EPIT_BASE(x) ((x) == HW_EPIT1 ? REGS_EPIT1_BASE : (x) == HW_EPIT2 ? REGS_EPIT2_BASE \
: 0x00d00000)
//! @brief Get the instance number given a base address.
//! @param b Base address for an instance of EPIT.
#define REGS_EPIT_INSTANCE(b) ((b) == REGS_EPIT1_BASE ? HW_EPIT1 : (b) == REGS_EPIT2_BASE ? HW_EPIT2 \
: 0)
#endif
//@}
//-------------------------------------------------------------------------------------------
// HW_EPIT_CR - Control register
//-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_EPIT_CR - Control register (RW)
*
* Reset value: 0x00000000
*
* The EPIT control register (EPIT_CR) is used to configure the operating settings of the EPIT. It
* contains the clock division prescaler value and also the interrupt enable bit. Additionally, it
* contains other control bits which are described below. Peripheral Bus Write access to EPIT
* Control Register (EPIT_CR) results in one cycle of the wait state, while other valid peripheral
* bus accesses are with 0 wait state.
*/
typedef union _hw_epit_cr {
reg32_t U;
struct _hw_epit_cr_bitfields {
unsigned EN : 1; //!< [0] This bit enables the EPIT.
unsigned ENMOD : 1; //!< [1] EPIT enable mode.
unsigned OCIEN : 1; //!< [2] Output compare interrupt enable.
unsigned RLD : 1; //!< [3] Counter reload control.
unsigned PRESCALAR : 12; //!< [15:4] Counter clock prescaler value.
unsigned SWR : 1; //!< [16] Software reset.
unsigned IOVW : 1; //!< [17] EPIT counter overwrite enable.
unsigned DBGEN : 1; //!< [18] This bit is used to keep the EPIT functional in debug mode.
unsigned WAITEN : 1; //!< [19] This read/write control bit enables the operation of the EPIT during wait mode.
unsigned RESERVED0 : 1; //!< [20] Reserved.
unsigned STOPEN : 1; //!< [21] EPIT stop mode enable.
unsigned OM : 2; //!< [23:22] EPIT output mode.This bit field determines the mode of EPIT output on the output pin.
unsigned CLKSRC : 2; //!< [25:24] Select clock source
unsigned RESERVED1 : 6; //!< [31:26] Reserved.
} B;
} hw_epit_cr_t;
#endif
/*!
* @name Constants and macros for entire EPIT_CR register
*/
//@{
#define HW_EPIT_CR_ADDR(x) (REGS_EPIT_BASE(x) + 0x0)
#ifndef __LANGUAGE_ASM__
#define HW_EPIT_CR(x) (*(volatile hw_epit_cr_t*)HW_EPIT_CR_ADDR(x))
#define HW_EPIT_CR_RD(x) (HW_EPIT_CR(x).U)
#define HW_EPIT_CR_WR(x, v) (HW_EPIT_CR(x).U = (v))
#define HW_EPIT_CR_SET(x, v) (HW_EPIT_CR_WR(x, HW_EPIT_CR_RD(x) | (v)))
#define HW_EPIT_CR_CLR(x, v) (HW_EPIT_CR_WR(x, HW_EPIT_CR_RD(x) & ~(v)))
#define HW_EPIT_CR_TOG(x, v) (HW_EPIT_CR_WR(x, HW_EPIT_CR_RD(x) ^ (v)))
#endif
//@}
/*
* constants & macros for individual EPIT_CR bitfields
*/
/*! @name Register EPIT_CR, field EN[0] (RW)
*
* This bit enables the EPIT. EPIT counter and prescaler value when EPIT is enabled (EN = 1), is
* dependent upon ENMOD and RLD bit as described for ENMOD bit. It is recommended that all registers
* be properly programmed before setting this bit. This bit is reset by a hardware reset. A software
* reset does not affect this bit.
*
* Values:
* - 0 - EPIT is disabled
* - 1 - EPIT is enabled
*/
//@{
#define BP_EPIT_CR_EN (0) //!< Bit position for EPIT_CR_EN.
#define BM_EPIT_CR_EN (0x00000001) //!< Bit mask for EPIT_CR_EN.
//! @brief Get value of EPIT_CR_EN from a register value.
#define BG_EPIT_CR_EN(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_EN) >> BP_EPIT_CR_EN)
//! @brief Format value for bitfield EPIT_CR_EN.
#define BF_EPIT_CR_EN(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_EN) & BM_EPIT_CR_EN)
#ifndef __LANGUAGE_ASM__
//! @brief Set the EN field to a new value.
#define BW_EPIT_CR_EN(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_EN) | BF_EPIT_CR_EN(v)))
#endif
//@}
/*! @name Register EPIT_CR, field ENMOD[1] (RW)
*
* EPIT enable mode. When EPIT is disabled (EN=0), both main counter and prescaler counter freeze
* their count at current count values. ENMOD bit is a r/w bit that determines the counter value
* when the EPIT is enabled again by setting EN bit. If ENMOD bit is set, then main counter is
* loaded with the load value (If RLD=1)/ 0xFFFF_FFFF (If RLD=0) and prescaler counter is reset,
* when EPIT is enabled (EN=1). If ENMOD is programmed to 0 then both main counter and prescaler
* counter restart counting from their frozen values when EPIT is enabled (EN=1). If EPIT is
* programmed to be disabled in a low-power mode (STOP/WAIT/DEBUG), then both the main counter and
* the prescaler counter freeze at their current count values when EPIT enters low-power mode. When
* EPIT exits the low-power mode, both main counter and prescaler counter start counting from their
* frozen values irrespective of the ENMOD bit. This bit is reset by a hardware reset. A software
* reset does not affect this bit.
*
* Values:
* - 0 - Counter starts counting from the value it had when it was disabled.
* - 1 - Counter starts count from load value (RLD=1) or 0xFFFF_FFFF (If RLD=0)
*/
//@{
#define BP_EPIT_CR_ENMOD (1) //!< Bit position for EPIT_CR_ENMOD.
#define BM_EPIT_CR_ENMOD (0x00000002) //!< Bit mask for EPIT_CR_ENMOD.
//! @brief Get value of EPIT_CR_ENMOD from a register value.
#define BG_EPIT_CR_ENMOD(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_ENMOD) >> BP_EPIT_CR_ENMOD)
//! @brief Format value for bitfield EPIT_CR_ENMOD.
#define BF_EPIT_CR_ENMOD(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_ENMOD) & BM_EPIT_CR_ENMOD)
#ifndef __LANGUAGE_ASM__
//! @brief Set the ENMOD field to a new value.
#define BW_EPIT_CR_ENMOD(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_ENMOD) | BF_EPIT_CR_ENMOD(v)))
#endif
//@}
/*! @name Register EPIT_CR, field OCIEN[2] (RW)
*
* Output compare interrupt enable. This bit enables the generation of interrupt on occurrence of
* compare event.
*
* Values:
* - 0 - Compare interrupt disabled
* - 1 - Compare interrupt enabled
*/
//@{
#define BP_EPIT_CR_OCIEN (2) //!< Bit position for EPIT_CR_OCIEN.
#define BM_EPIT_CR_OCIEN (0x00000004) //!< Bit mask for EPIT_CR_OCIEN.
//! @brief Get value of EPIT_CR_OCIEN from a register value.
#define BG_EPIT_CR_OCIEN(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_OCIEN) >> BP_EPIT_CR_OCIEN)
//! @brief Format value for bitfield EPIT_CR_OCIEN.
#define BF_EPIT_CR_OCIEN(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_OCIEN) & BM_EPIT_CR_OCIEN)
#ifndef __LANGUAGE_ASM__
//! @brief Set the OCIEN field to a new value.
#define BW_EPIT_CR_OCIEN(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_OCIEN) | BF_EPIT_CR_OCIEN(v)))
#endif
//@}
/*! @name Register EPIT_CR, field RLD[3] (RW)
*
* Counter reload control. This bit is cleared by hardware reset. It decides the counter
* functionality, whether to run in free-running mode or set-and-forget mode.
*
* Values:
* - 0 - When the counter reaches zero it rolls over to 0xFFFF_FFFF (free-running mode)
* - 1 - When the counter reaches zero it reloads from the modulus register (set-and-forget mode)
*/
//@{
#define BP_EPIT_CR_RLD (3) //!< Bit position for EPIT_CR_RLD.
#define BM_EPIT_CR_RLD (0x00000008) //!< Bit mask for EPIT_CR_RLD.
//! @brief Get value of EPIT_CR_RLD from a register value.
#define BG_EPIT_CR_RLD(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_RLD) >> BP_EPIT_CR_RLD)
//! @brief Format value for bitfield EPIT_CR_RLD.
#define BF_EPIT_CR_RLD(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_RLD) & BM_EPIT_CR_RLD)
#ifndef __LANGUAGE_ASM__
//! @brief Set the RLD field to a new value.
#define BW_EPIT_CR_RLD(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_RLD) | BF_EPIT_CR_RLD(v)))
#endif
//@}
/*! @name Register EPIT_CR, field PRESCALAR[15:4] (RW)
*
* Counter clock prescaler value. This bit field determines the prescaler value by which the clock
* is divided before it goes to the counter
*
* Values:
* - 0x000 - Divide by 1
* - 0x001 - Divide by 2...
* - 0xFFF - Divide by 4096
*/
//@{
#define BP_EPIT_CR_PRESCALAR (4) //!< Bit position for EPIT_CR_PRESCALAR.
#define BM_EPIT_CR_PRESCALAR (0x0000fff0) //!< Bit mask for EPIT_CR_PRESCALAR.
//! @brief Get value of EPIT_CR_PRESCALAR from a register value.
#define BG_EPIT_CR_PRESCALAR(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_PRESCALAR) >> BP_EPIT_CR_PRESCALAR)
//! @brief Format value for bitfield EPIT_CR_PRESCALAR.
#define BF_EPIT_CR_PRESCALAR(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_PRESCALAR) & BM_EPIT_CR_PRESCALAR)
#ifndef __LANGUAGE_ASM__
//! @brief Set the PRESCALAR field to a new value.
#define BW_EPIT_CR_PRESCALAR(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_PRESCALAR) | BF_EPIT_CR_PRESCALAR(v)))
#endif
//@}
/*! @name Register EPIT_CR, field SWR[16] (RW)
*
* Software reset. The EPIT is reset when this bit is set to 1. It is a self clearing bit. This bit
* is set when the block is in reset state and is cleared when the reset procedure is over. Setting
* this bit resets all the registers to their reset values, except for the EN, ENMOD, STOPEN, WAITEN
* and DBGEN bits in this control register
*
* Values:
* - 0 - EPIT is out of reset
* - 1 - EPIT is undergoing reset
*/
//@{
#define BP_EPIT_CR_SWR (16) //!< Bit position for EPIT_CR_SWR.
#define BM_EPIT_CR_SWR (0x00010000) //!< Bit mask for EPIT_CR_SWR.
//! @brief Get value of EPIT_CR_SWR from a register value.
#define BG_EPIT_CR_SWR(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_SWR) >> BP_EPIT_CR_SWR)
//! @brief Format value for bitfield EPIT_CR_SWR.
#define BF_EPIT_CR_SWR(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_SWR) & BM_EPIT_CR_SWR)
#ifndef __LANGUAGE_ASM__
//! @brief Set the SWR field to a new value.
#define BW_EPIT_CR_SWR(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_SWR) | BF_EPIT_CR_SWR(v)))
#endif
//@}
/*! @name Register EPIT_CR, field IOVW[17] (RW)
*
* EPIT counter overwrite enable. This bit controls the counter data when the modulus register is
* written. When this bit is set, all writes to the load register overwrites the counter contents
* and the counter starts subsequently counting down from the programmed value.
*
* Values:
* - 0 - Write to load register does not result in counter value being overwritten.
* - 1 - Write to load register results in immediate overwriting of counter value.
*/
//@{
#define BP_EPIT_CR_IOVW (17) //!< Bit position for EPIT_CR_IOVW.
#define BM_EPIT_CR_IOVW (0x00020000) //!< Bit mask for EPIT_CR_IOVW.
//! @brief Get value of EPIT_CR_IOVW from a register value.
#define BG_EPIT_CR_IOVW(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_IOVW) >> BP_EPIT_CR_IOVW)
//! @brief Format value for bitfield EPIT_CR_IOVW.
#define BF_EPIT_CR_IOVW(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_IOVW) & BM_EPIT_CR_IOVW)
#ifndef __LANGUAGE_ASM__
//! @brief Set the IOVW field to a new value.
#define BW_EPIT_CR_IOVW(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_IOVW) | BF_EPIT_CR_IOVW(v)))
#endif
//@}
/*! @name Register EPIT_CR, field DBGEN[18] (RW)
*
* This bit is used to keep the EPIT functional in debug mode. When this bit is cleared, the input
* clock is gated off in debug mode.This bit is reset by hardware reset. A software reset does not
* affect this bit.
*
* Values:
* - 0 - Inactive in debug mode
* - 1 - Active in debug mode
*/
//@{
#define BP_EPIT_CR_DBGEN (18) //!< Bit position for EPIT_CR_DBGEN.
#define BM_EPIT_CR_DBGEN (0x00040000) //!< Bit mask for EPIT_CR_DBGEN.
//! @brief Get value of EPIT_CR_DBGEN from a register value.
#define BG_EPIT_CR_DBGEN(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_DBGEN) >> BP_EPIT_CR_DBGEN)
//! @brief Format value for bitfield EPIT_CR_DBGEN.
#define BF_EPIT_CR_DBGEN(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_DBGEN) & BM_EPIT_CR_DBGEN)
#ifndef __LANGUAGE_ASM__
//! @brief Set the DBGEN field to a new value.
#define BW_EPIT_CR_DBGEN(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_DBGEN) | BF_EPIT_CR_DBGEN(v)))
#endif
//@}
/*! @name Register EPIT_CR, field WAITEN[19] (RW)
*
* This read/write control bit enables the operation of the EPIT during wait mode. This bit is reset
* by a hardware reset. A software reset does not affect this bit.
*
* Values:
* - 0 - EPIT is disabled in wait mode
* - 1 - EPIT is enabled in wait mode
*/
//@{
#define BP_EPIT_CR_WAITEN (19) //!< Bit position for EPIT_CR_WAITEN.
#define BM_EPIT_CR_WAITEN (0x00080000) //!< Bit mask for EPIT_CR_WAITEN.
//! @brief Get value of EPIT_CR_WAITEN from a register value.
#define BG_EPIT_CR_WAITEN(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_WAITEN) >> BP_EPIT_CR_WAITEN)
//! @brief Format value for bitfield EPIT_CR_WAITEN.
#define BF_EPIT_CR_WAITEN(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_WAITEN) & BM_EPIT_CR_WAITEN)
#ifndef __LANGUAGE_ASM__
//! @brief Set the WAITEN field to a new value.
#define BW_EPIT_CR_WAITEN(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_WAITEN) | BF_EPIT_CR_WAITEN(v)))
#endif
//@}
/*! @name Register EPIT_CR, field STOPEN[21] (RW)
*
* EPIT stop mode enable. This read/write control bit enables the operation of the EPIT during stop
* mode. This bit is reset by a hardware reset and unaffected by software reset.
*
* Values:
* - 0 - EPIT is disabled in stop mode
* - 1 - EPIT is enabled in stop mode
*/
//@{
#define BP_EPIT_CR_STOPEN (21) //!< Bit position for EPIT_CR_STOPEN.
#define BM_EPIT_CR_STOPEN (0x00200000) //!< Bit mask for EPIT_CR_STOPEN.
//! @brief Get value of EPIT_CR_STOPEN from a register value.
#define BG_EPIT_CR_STOPEN(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_STOPEN) >> BP_EPIT_CR_STOPEN)
//! @brief Format value for bitfield EPIT_CR_STOPEN.
#define BF_EPIT_CR_STOPEN(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_STOPEN) & BM_EPIT_CR_STOPEN)
#ifndef __LANGUAGE_ASM__
//! @brief Set the STOPEN field to a new value.
#define BW_EPIT_CR_STOPEN(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_STOPEN) | BF_EPIT_CR_STOPEN(v)))
#endif
//@}
/*! @name Register EPIT_CR, field OM[23:22] (RW)
*
* EPIT output mode.This bit field determines the mode of EPIT output on the output pin.
*
* Values:
* - 00 - EPIT output is disconnected from pad
* - 01 - Toggle output pin
* - 10 - Clear output pin
* - 11 - Set output pin
*/
//@{
#define BP_EPIT_CR_OM (22) //!< Bit position for EPIT_CR_OM.
#define BM_EPIT_CR_OM (0x00c00000) //!< Bit mask for EPIT_CR_OM.
//! @brief Get value of EPIT_CR_OM from a register value.
#define BG_EPIT_CR_OM(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_OM) >> BP_EPIT_CR_OM)
//! @brief Format value for bitfield EPIT_CR_OM.
#define BF_EPIT_CR_OM(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_OM) & BM_EPIT_CR_OM)
#ifndef __LANGUAGE_ASM__
//! @brief Set the OM field to a new value.
#define BW_EPIT_CR_OM(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_OM) | BF_EPIT_CR_OM(v)))
#endif
//@}
/*! @name Register EPIT_CR, field CLKSRC[25:24] (RW)
*
* Select clock source These bits determine which clock input is to be selected for running the
* counter. This field value should only be changed when the EPIT is disabled by clearing the EN bit
* in this register. For other programming requirements while changing clock source, refer to .
*
* Values:
* - 00 - Clock is off
* - 01 - Peripheral clock
* - 10 - High-frequency reference clock
* - 11 - Low-frequency reference clock
*/
//@{
#define BP_EPIT_CR_CLKSRC (24) //!< Bit position for EPIT_CR_CLKSRC.
#define BM_EPIT_CR_CLKSRC (0x03000000) //!< Bit mask for EPIT_CR_CLKSRC.
//! @brief Get value of EPIT_CR_CLKSRC from a register value.
#define BG_EPIT_CR_CLKSRC(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CR_CLKSRC) >> BP_EPIT_CR_CLKSRC)
//! @brief Format value for bitfield EPIT_CR_CLKSRC.
#define BF_EPIT_CR_CLKSRC(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CR_CLKSRC) & BM_EPIT_CR_CLKSRC)
#ifndef __LANGUAGE_ASM__
//! @brief Set the CLKSRC field to a new value.
#define BW_EPIT_CR_CLKSRC(x, v) (HW_EPIT_CR_WR(x, (HW_EPIT_CR_RD(x) & ~BM_EPIT_CR_CLKSRC) | BF_EPIT_CR_CLKSRC(v)))
#endif
//@}
//-------------------------------------------------------------------------------------------
// HW_EPIT_SR - Status register
//-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_EPIT_SR - Status register (RW)
*
* Reset value: 0x00000000
*
* The EPIT status register (EPIT_SR) has a single status bit for the output compare event. The bit
* is a write 1 to clear bit.
*/
typedef union _hw_epit_sr {
reg32_t U;
struct _hw_epit_sr_bitfields {
unsigned OCIF : 1; //!< [0] Output compare interrupt flag.
unsigned RESERVED0 : 31; //!< [31:1] Reserved.
} B;
} hw_epit_sr_t;
#endif
/*!
* @name Constants and macros for entire EPIT_SR register
*/
//@{
#define HW_EPIT_SR_ADDR(x) (REGS_EPIT_BASE(x) + 0x4)
#ifndef __LANGUAGE_ASM__
#define HW_EPIT_SR(x) (*(volatile hw_epit_sr_t*)HW_EPIT_SR_ADDR(x))
#define HW_EPIT_SR_RD(x) (HW_EPIT_SR(x).U)
#define HW_EPIT_SR_WR(x, v) (HW_EPIT_SR(x).U = (v))
#define HW_EPIT_SR_SET(x, v) (HW_EPIT_SR_WR(x, HW_EPIT_SR_RD(x) | (v)))
#define HW_EPIT_SR_CLR(x, v) (HW_EPIT_SR_WR(x, HW_EPIT_SR_RD(x) & ~(v)))
#define HW_EPIT_SR_TOG(x, v) (HW_EPIT_SR_WR(x, HW_EPIT_SR_RD(x) ^ (v)))
#endif
//@}
/*
* constants & macros for individual EPIT_SR bitfields
*/
/*! @name Register EPIT_SR, field OCIF[0] (W1C)
*
* Output compare interrupt flag. This bit is the interrupt flag that is set when the content of
* counter equals the content of the compare register (EPIT_CMPR). The bit is a write 1 to clear
* bit.
*
* Values:
* - 0 - Compare event has not occurred
* - 1 - Compare event occurred
*/
//@{
#define BP_EPIT_SR_OCIF (0) //!< Bit position for EPIT_SR_OCIF.
#define BM_EPIT_SR_OCIF (0x00000001) //!< Bit mask for EPIT_SR_OCIF.
//! @brief Get value of EPIT_SR_OCIF from a register value.
#define BG_EPIT_SR_OCIF(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_SR_OCIF) >> BP_EPIT_SR_OCIF)
//! @brief Format value for bitfield EPIT_SR_OCIF.
#define BF_EPIT_SR_OCIF(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_SR_OCIF) & BM_EPIT_SR_OCIF)
#ifndef __LANGUAGE_ASM__
//! @brief Set the OCIF field to a new value.
#define BW_EPIT_SR_OCIF(x, v) (HW_EPIT_SR_WR(x, (HW_EPIT_SR_RD(x) & ~BM_EPIT_SR_OCIF) | BF_EPIT_SR_OCIF(v)))
#endif
//@}
//-------------------------------------------------------------------------------------------
// HW_EPIT_LR - Load register
//-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_EPIT_LR - Load register (RW)
*
* Reset value: 0xffffffff
*
* The EPIT load register (EPIT_LR) contains the value that is to be loaded into the counter when
* EPIT counter reaches zero if the RLD bit in EPIT_CR is set. If the IOVW bit in the EPIT_CR is set
* then a write to this register overwrites the value of the EPIT counter register in addition to
* updating this registers value. This overwrite feature is active even if the RLD bit is not set.
*/
typedef union _hw_epit_lr {
reg32_t U;
struct _hw_epit_lr_bitfields {
unsigned LOAD : 32; //!< [31:0] Load value.
} B;
} hw_epit_lr_t;
#endif
/*!
* @name Constants and macros for entire EPIT_LR register
*/
//@{
#define HW_EPIT_LR_ADDR(x) (REGS_EPIT_BASE(x) + 0x8)
#ifndef __LANGUAGE_ASM__
#define HW_EPIT_LR(x) (*(volatile hw_epit_lr_t*)HW_EPIT_LR_ADDR(x))
#define HW_EPIT_LR_RD(x) (HW_EPIT_LR(x).U)
#define HW_EPIT_LR_WR(x, v) (HW_EPIT_LR(x).U = (v))
#define HW_EPIT_LR_SET(x, v) (HW_EPIT_LR_WR(x, HW_EPIT_LR_RD(x) | (v)))
#define HW_EPIT_LR_CLR(x, v) (HW_EPIT_LR_WR(x, HW_EPIT_LR_RD(x) & ~(v)))
#define HW_EPIT_LR_TOG(x, v) (HW_EPIT_LR_WR(x, HW_EPIT_LR_RD(x) ^ (v)))
#endif
//@}
/*
* constants & macros for individual EPIT_LR bitfields
*/
/*! @name Register EPIT_LR, field LOAD[31:0] (RW)
*
* Load value. Value that is loaded into the counter at the start of each count cycle.
*/
//@{
#define BP_EPIT_LR_LOAD (0) //!< Bit position for EPIT_LR_LOAD.
#define BM_EPIT_LR_LOAD (0xffffffff) //!< Bit mask for EPIT_LR_LOAD.
//! @brief Get value of EPIT_LR_LOAD from a register value.
#define BG_EPIT_LR_LOAD(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_LR_LOAD) >> BP_EPIT_LR_LOAD)
//! @brief Format value for bitfield EPIT_LR_LOAD.
#define BF_EPIT_LR_LOAD(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_LR_LOAD) & BM_EPIT_LR_LOAD)
#ifndef __LANGUAGE_ASM__
//! @brief Set the LOAD field to a new value.
#define BW_EPIT_LR_LOAD(x, v) (HW_EPIT_LR_WR(x, (HW_EPIT_LR_RD(x) & ~BM_EPIT_LR_LOAD) | BF_EPIT_LR_LOAD(v)))
#endif
//@}
//-------------------------------------------------------------------------------------------
// HW_EPIT_CMPR - Compare register
//-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_EPIT_CMPR - Compare register (RW)
*
* Reset value: 0x00000000
*
* The EPIT compare register (EPIT_CMPR) holds the value that determines when a compare event is
* generated.
*/
typedef union _hw_epit_cmpr {
reg32_t U;
struct _hw_epit_cmpr_bitfields {
unsigned COMPARE : 32; //!< [31:0] Compare Value.
} B;
} hw_epit_cmpr_t;
#endif
/*!
* @name Constants and macros for entire EPIT_CMPR register
*/
//@{
#define HW_EPIT_CMPR_ADDR(x) (REGS_EPIT_BASE(x) + 0xc)
#ifndef __LANGUAGE_ASM__
#define HW_EPIT_CMPR(x) (*(volatile hw_epit_cmpr_t*)HW_EPIT_CMPR_ADDR(x))
#define HW_EPIT_CMPR_RD(x) (HW_EPIT_CMPR(x).U)
#define HW_EPIT_CMPR_WR(x, v) (HW_EPIT_CMPR(x).U = (v))
#define HW_EPIT_CMPR_SET(x, v) (HW_EPIT_CMPR_WR(x, HW_EPIT_CMPR_RD(x) | (v)))
#define HW_EPIT_CMPR_CLR(x, v) (HW_EPIT_CMPR_WR(x, HW_EPIT_CMPR_RD(x) & ~(v)))
#define HW_EPIT_CMPR_TOG(x, v) (HW_EPIT_CMPR_WR(x, HW_EPIT_CMPR_RD(x) ^ (v)))
#endif
//@}
/*
* constants & macros for individual EPIT_CMPR bitfields
*/
/*! @name Register EPIT_CMPR, field COMPARE[31:0] (RW)
*
* Compare Value. When the counter value equals this bit field value a compare event is generated.
*/
//@{
#define BP_EPIT_CMPR_COMPARE (0) //!< Bit position for EPIT_CMPR_COMPARE.
#define BM_EPIT_CMPR_COMPARE (0xffffffff) //!< Bit mask for EPIT_CMPR_COMPARE.
//! @brief Get value of EPIT_CMPR_COMPARE from a register value.
#define BG_EPIT_CMPR_COMPARE(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CMPR_COMPARE) >> BP_EPIT_CMPR_COMPARE)
//! @brief Format value for bitfield EPIT_CMPR_COMPARE.
#define BF_EPIT_CMPR_COMPARE(v) ((__REG_VALUE_TYPE((v), reg32_t) << BP_EPIT_CMPR_COMPARE) & BM_EPIT_CMPR_COMPARE)
#ifndef __LANGUAGE_ASM__
//! @brief Set the COMPARE field to a new value.
#define BW_EPIT_CMPR_COMPARE(x, v) (HW_EPIT_CMPR_WR(x, (HW_EPIT_CMPR_RD(x) & ~BM_EPIT_CMPR_COMPARE) | BF_EPIT_CMPR_COMPARE(v)))
#endif
//@}
//-------------------------------------------------------------------------------------------
// HW_EPIT_CNR - Counter register
//-------------------------------------------------------------------------------------------
#ifndef __LANGUAGE_ASM__
/*!
* @brief HW_EPIT_CNR - Counter register (RO)
*
* Reset value: 0xffffffff
*
* The EPIT counter register (EPIT_CNR) contains the current count value and can be read at any time
* without disturbing the counter. This is a read-only register and any attempt to write into it
* generates a transfer error. But if the IOVW bit in EPIT_CR is set, the value of this register can
* be overwritten with a write to EPIT_LR. This change is reflected when this register is
* subsequently read.
*/
typedef union _hw_epit_cnr {
reg32_t U;
struct _hw_epit_cnr_bitfields {
unsigned COUNT : 32; //!< [31:0] Counter value.
} B;
} hw_epit_cnr_t;
#endif
/*!
* @name Constants and macros for entire EPIT_CNR register
*/
//@{
#define HW_EPIT_CNR_ADDR(x) (REGS_EPIT_BASE(x) + 0x10)
#ifndef __LANGUAGE_ASM__
#define HW_EPIT_CNR(x) (*(volatile hw_epit_cnr_t*)HW_EPIT_CNR_ADDR(x))
#define HW_EPIT_CNR_RD(x) (HW_EPIT_CNR(x).U)
#endif
//@}
/*
* constants & macros for individual EPIT_CNR bitfields
*/
/*! @name Register EPIT_CNR, field COUNT[31:0] (RO)
*
* Counter value. This contains the current value of the counter.
*/
//@{
#define BP_EPIT_CNR_COUNT (0) //!< Bit position for EPIT_CNR_COUNT.
#define BM_EPIT_CNR_COUNT (0xffffffff) //!< Bit mask for EPIT_CNR_COUNT.
//! @brief Get value of EPIT_CNR_COUNT from a register value.
#define BG_EPIT_CNR_COUNT(r) ((__REG_VALUE_TYPE((r), reg32_t) & BM_EPIT_CNR_COUNT) >> BP_EPIT_CNR_COUNT)
//@}
//-------------------------------------------------------------------------------------------
// hw_epit_t - module struct
//-------------------------------------------------------------------------------------------
/*!
* @brief All EPIT module registers.
*/
#ifndef __LANGUAGE_ASM__
#pragma pack(1)
typedef struct _hw_epit {
volatile hw_epit_cr_t CR; //!< Control register
volatile hw_epit_sr_t SR; //!< Status register
volatile hw_epit_lr_t LR; //!< Load register
volatile hw_epit_cmpr_t CMPR; //!< Compare register
volatile hw_epit_cnr_t CNR; //!< Counter register
} hw_epit_t;
#pragma pack()
//! @brief Macro to access all EPIT registers.
//! @param x EPIT instance number.
//! @return Reference (not a pointer) to the registers struct. To get a pointer to the struct,
//! use the '&' operator, like <code>&HW_EPIT(0)</code>.
#define HW_EPIT(x) (*(hw_epit_t*)REGS_EPIT_BASE(x))
#endif
#endif // __HW_EPIT_REGISTERS_H__
// v18/121106/1.2.2
// EOF

View File

@ -1,6 +1,6 @@
# The following three platforms support compatiable instructions.
ifneq ($(findstring $(BOARD), ok1028a-c), )
SRC_DIR := cortex-a72
ifneq ($(findstring $(BOARD), 3568), )
SRC_DIR := cortex-a55
endif

View File

@ -29,7 +29,7 @@ Modification:
1. first version
*************************************************/
/*********cortex-a72 general register************
/*********cortex-a55 general register************
EL0 | EL1 | EL2 | EL3
x0;
@ -63,7 +63,7 @@ Modification:
x28;
x29;
x30;
*********cortex-a72 special register************
*********cortex-a55 special register************
XZR
PC
SP_EL0 SP_EL1 SP_EL2 SP_EL3

View File

@ -12,7 +12,7 @@
/**
* @file core.h
* @brief cortex-a72 core function
* @brief cortex-a55 core function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2024.04.11
@ -20,7 +20,7 @@
/*************************************************
File name: core.h
Description: cortex-a72 core function
Description: cortex-a55 core function
Others:
History:
Author: AIIT XUOS Lab
@ -33,7 +33,7 @@ Modification:
#define NO_INT 0x80 // disable IRQ.
#define DIS_INT 0xc0 // disable both IRQ and FIQ.
#define MODE_STACK_SIZE 0x1000
#define MODE_STACK_SIZE 0x2000
//! @name SPSR fields
//@{
@ -71,23 +71,21 @@ Modification:
#include <stdint.h>
#include <string.h>
#include "cortex_a72.h"
#include "cortex_a55.h"
#define NR_CPU 4 // maximum number of CPUs
static inline uintptr_t arch_curr_tick()
{
uint64_t x;
__asm__ volatile("mrs %0, cntpct_el0" : "=r"(x));
return x;
}
__attribute__((always_inline)) static inline uint64_t EL0_mode() // Set ARM mode to EL0
{
uint64_t val = 0;
__asm__ __volatile__(
"mrs %0, spsr_el1"
: "=r"(val)
:
:);
val &= ~DIS_INT;
val &= ~SPSR_MODE_MASK;
val |= ARM_MODE_EL0_t;
return val;
}

View File

@ -45,30 +45,36 @@ ENTRY( _ENTRY )
ENTRY( _boot_start )
MEMORY {
phy_ddr3 (rwx) : ORIGIN = 0x0000000040000000, LENGTH = 1024M
vir_ddr3 (rwx) : ORIGIN = 0x0000006040635000, LENGTH = 1024M
phy_ddr3 (rwx) : ORIGIN = 0x0000000010000000, LENGTH = 1024M
vir_ddr3 (rwx) : ORIGIN = 0x000000601040E000, LENGTH = 1024M
}
SECTIONS
{
.start_sec : {
. = ALIGN(0x1000);
. = ORIGIN(phy_ddr3);
/* initialization start checkpoint. */
_start_image_addr = .;
boot.o(.text)
bootmmu.o(.text .text.*)
/* ns16550.o(.text .text.*) */
boot.o(.rodata .rodata.*)
bootmmu.o(.rodata .rodata.*)
/* ns16550.o(.rodata .rodata.*) */
boot.o(.data .data.*)
bootmmu.o(.data .data.*)
/* ns16550.o(.data .data.*) */
PROVIDE(boot_start_addr = .);
boot.o(.bss .bss.* COMMON)
bootmmu.o(.bss .bss.* COMMON)
/* ns16550.o(.bss .bss.* COMMON) */
/* stack for booting code. */
. = ALIGN(0x1000);
@ -81,7 +87,7 @@ SECTIONS
PROVIDE(boot_end_addr = .);
} > phy_ddr3
.text : AT(0x40635000) {
.text : AT(0x1040E000) {
. = ALIGN(0x1000);
*(.text .text.* .gnu.linkonce.t.*)
} > vir_ddr3
@ -103,17 +109,19 @@ SECTIONS
PROVIDE(_binary_default_fs_start = .);
*(.rawdata_memfs*)
PROVIDE(_binary_default_fs_end = .);
PROVIDE(__init_array_start = .);
PROVIDE(__init_array_end = .);
} > vir_ddr3
. = ALIGN(0x1000);
PROVIDE(kernel_data_begin = .);
_image_size = . - 0x0000006010000000;
_image_size = . - 0x0000006040000000;
.bss : {
PROVIDE(kernel_data_begin = .);
PROVIDE(__bss_start__ = .);
*(.bss .bss.* COMMON)
PROVIDE(__bss_end__ = .);
} > vir_ddr3
. = ALIGN(0x1000);
PROVIDE(__bss_end__ = .);
PROVIDE(kernel_data_end = .);
} > vir_ddr3
}

View File

@ -1,5 +1,6 @@
SRC_FILES := boot.S \
xizi_smp.S \
smp.c \
cortexA72.S
cortexA55.S
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "core.h"
#define HCR_VALUE (1 << 31)
#define SPSR_EL2_VALUE (7 << 6) | (5 << 0)
#define SCTLR_EL1_VALUE (0x30D00800)
.section ".text", "ax"
.global _boot_start
.global primary_cpu_init
.global el2_setup
_boot_start:
bl el2_setup
/* set NSACR, both Secure and Non-secure access are allowed to NEON */
mov x0, #(3 << 20)
msr cpacr_el1, x0
isb
// clear some registers
msr elr_el1, XZR
ldr x0, =stacks_top
mov x1, #MODE_STACK_SIZE
// get cpu id, and subtract the offset from the stacks base address
mrs x2, mpidr_el1
and x2, x2, #0xFFF
lsr x2, x2, #8
mov x5, x2
mul x3, x2, x1
sub x0, x0, x3
mov sp, x0
mov x2, #ARM_MODE_EL1_h | DIS_INT
msr spsr_el1, x2
// check cpu id - cpu0 is primary cpu
mrs x2, mpidr_el1
and x2, x2, #0xFFF
lsr x2, x2, #8
mov x5, x2
cmp x5, #0
beq primary_cpu_init
bl bootmain // for secondary cpus, jump to argument function pointer passed in by ROM
bl .
primary_cpu_init:
/* init .bss */
/* clear the .bss section (zero init) */
ldr x1, =boot_start_addr
ldr x2, =boot_end_addr
mov x3, #0
1:
cmp x1, x2
stp x3, x3, [x1], #16
b.lt 1b
bl bootmain
.func el2_setup
el2_setup:
mrs x0, CurrentEL
lsr x0, x0, #2
and x0, x0, #3
cmp x0, #2
beq 1f
ret
/* Hyp configuration. */
1:
mov x0, #(1 << 31)
msr hcr_el2, x0
/* Generic timers. */
mrs x0, cnthctl_el2
orr x0, x0, #3 // Enable EL1 physicaltimers
msr cnthctl_el2, x0
/* Populate ID registers. */
mrs x0, midr_el1
mrs x1, mpidr_el1
msr vpidr_el2, x0
msr vmpidr_el2, x1
/* Disable Coprocessor traps. */
mov x0, #0x33ff
msr cptr_el2, x0 // Disable copro. traps to EL2
msr hstr_el2, xzr // Disable CP15 traps to EL2
mov x0, sp
msr sp_el1, x0
mrs x0, sctlr_el1
orr x0, x0, #(1 << 0)
bic x0, x0, #(1 << 1)
orr x0, x0, #(1 << 2)
msr sctlr_el1, x0
/* spsr */
mov x0, #SPSR_EL2_VALUE
msr spsr_el2, x0
msr elr_el2, lr
eret
.endfunc
.end

View File

@ -1,8 +1,7 @@
export CROSS_COMPILE ?= aarch64-none-elf-
export DEVICE = -mtune=cortex-a72 -ffreestanding -fno-common -fno-stack-protector -fno-pie -no-pie
export DEVICE = -mtune=cortex-a55 -ffreestanding -fno-common -fno-stack-protector -fno-pie -no-pie
export CFLAGS := $(DEVICE) -Wall -Werror -O2 -g -fno-omit-frame-pointer -fPIC
# export AFLAGS := -c $(DEVICE) -x assembler-with-cpp -D__ASSEMBLY__ -gdwarf-2
export LFLAGS := $(DEVICE) -Wl,-T -Wl,$(KERNEL_ROOT)/hardkernel/arch/arm/armv8-a/cortex-a72/preboot_for_ok1028a-c/nxp_ls1028.lds -Wl,--start-group,-lgcc,-lc,--end-group
export LFLAGS := $(DEVICE) -Wl,-T -Wl,$(KERNEL_ROOT)/hardkernel/arch/arm/armv8-a/cortex-a55/preboot_for_3568/3568.lds -Wl,--start-group,-lgcc,-lc,--end-group
export CXXFLAGS :=
export DEFINES := -DHAVE_CCONFIG_H -DCHIP_LS1028

View File

@ -1,14 +1,14 @@
/*!
* @file cortexA72.s
* @brief This file contains cortexA72 functions
* @file cortexA55.s
* @brief This file contains cortexA55 functions
*
*/
/*************************************************
File name: cortexA72.S
File name: cortexA55.S
Description: This file contains cortexA9 functions
Others:
History:
1. Date: 202-05-08
1. Date: 2024-05-08
Author: AIIT XUOS Lab
Modification:
1. No modifications
@ -21,7 +21,8 @@ Modification:
.func cpu_get_current
cpu_get_current:
mrs x0, mpidr_el1
and x0, x0, #3
and x0, x0, #0xFFF
lsr x0, x0, #8
ret
.endfunc
@ -32,6 +33,6 @@ psci_call:
# ------------------------------------------------------------
# End of cortexA72.s
# End of cortexA55.s
# ------------------------------------------------------------
.end

View File

@ -28,16 +28,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file cortex_a72.h
* @brief some cortex A72 core functions
* @file cortex_a55.h
* @brief some cortex A55 core functions
* @version 1.0
* @author AIIT XUOS Lab
* @date 2024.04.24
*/
/*************************************************
File name: cortex_a72.h
Description: some cortex A72 core functions
File name: cortex_a55.h
Description: some cortex A55 core functions
Others:
History:
Author: AIIT XUOS Lab
@ -45,8 +45,8 @@ Modification:
1. No modifications
*************************************************/
#if !defined(__CORTEX_A72_H__)
#define __CORTEX_A72_H__
#if !defined(__CORTEX_A55_H__)
#define __CORTEX_A55_H__
#include <stdbool.h>
#include <stdint.h>
@ -231,4 +231,4 @@ void scu_secure_invalidate(unsigned int cpu, unsigned int ways);
}
#endif
#endif //__CORTEX_A72_H__
#endif //__CORTEX_A55_H__

View File

@ -48,12 +48,34 @@ Modification:
#include <stdint.h>
#define PSCI_CPUON 0xc4000003
struct xizi_smccc_res {
unsigned long a0;
unsigned long a1;
unsigned long a2;
unsigned long a3;
};
extern void _boot_start();
void psci_call(uint64_t fn, uint8_t cpuid, uint64_t entry, uint64_t ctxid);
extern void __print();
extern void __xizi_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
unsigned long a3, unsigned long a4, unsigned long a5,
unsigned long a6, unsigned long a7, struct xizi_smccc_res* res);
static struct xizi_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
unsigned long arg0,
unsigned long arg1,
unsigned long arg2)
{
struct xizi_smccc_res res;
__xizi_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
return res;
}
void cpu_start_secondary(uint8_t cpu_id)
{
psci_call(PSCI_CPUON, cpu_id, (uintptr_t)&_boot_start, 0);
__invoke_sip_fn_smc(PSCI_CPUON, cpu_id, (uintptr_t)0xa00000, 0);
}
void start_smp_cache_broadcast(int cpu_id)

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
.global __xizi_smccc_smc
.func __xizi_smccc_smc
__xizi_smccc_smc:
smc #0
ldr x4, [sp]
stp x0, x1, [x4, #0]
stp x2, x3, [x4, #16]
ldr x4, [sp, #8]
cbz x4, 1f /* no quirk structure */
ldr x9, [x4, #0]
cmp x9, #1
b.ne 1f
str x6, [x4, 8]
1: ret
.endfunc

View File

@ -1,81 +0,0 @@
// #include "memlayout.h"
#include "core.h"
// #include "registers.h"
// #include "cortex_a72.h"
// qemu -kernel loads the kernel at 0x40000000
// and causes each CPU to jump there.
// kernel.ld causes the following code to
// be placed at 0x40000000.
.section ".text"
//.global _entry
.global _boot_start
.global primary_cpu_init
_boot_start:
// set up a stack for C.
// stack0 is declared in start.c,
// with a 4096-byte stack per CPU.
// sp = stack0 + ((cpuid+1) * 4096)
// cpuid = mpidr_el1 & 0xff
// save r0 for cores 1-3, r0 arg field passed by ROM
// r0 is a function pointer for secondary cpus
// mov x4, x0
mrs x0, spsr_el1 /* Enter EL1 (Exception Level 1) */
bic x0, x0, #0x1f
MOV x1, #0xC5
ORR x0, x0, x1
msr spsr_el1, x0
/* set NSACR, both Secure and Non-secure access are allowed to NEON */
MRS X1, CPACR_EL1
ORR X1, X1, #(0X3 << 20)
MSR CPACR_EL1, X1
ISB
// clear some registers
msr elr_el1, XZR
ldr x0, =stacks_top
mov x1, #MODE_STACK_SIZE
// get cpu id, and subtract the offset from the stacks base address
mrs x2, mpidr_el1
and x2, x2, #0x3
mov x5, x2
mul x3, x2, x1
sub x0, x0, x3
MOV X2, #ARM_MODE_EL1_h | DIS_INT
MSR SPSR_EL1, X2
mov sp, x0
SUB x0, x0,x1
// check cpu id - cpu0 is primary cpu
cmp x5, #0
beq primary_cpu_init
bl bootmain // for secondary cpus, jump to argument function pointer passed in by ROM
bl .
primary_cpu_init:
/* init .bss */
/* clear the .bss section (zero init) */
ldr x1, =boot_start_addr
ldr x2, =boot_end_addr
mov x3, #0
1:
cmp x1, x2
stp x3, x3, [x1], #16
b.lt 1b
// branch to c library entry point
mov x0, #0 // argc
mov x1, #0 // argv
mov x2, #0 // env
bl bootmain
.end

View File

@ -1,8 +1,8 @@
ifneq ($(findstring $(BOARD), imx6q-sabrelite zynq7000-zc702), )
SRC_DIR := cortex-a9
endif
ifneq ($(findstring $(BOARD), ok1028a-c), )
SRC_DIR := cortex-a72
ifneq ($(findstring $(BOARD), 3568), )
SRC_DIR := cortex-a55
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,3 @@
SRC_FILES := l1_cache.c cache.S
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,336 @@
/*
* (C) Copyright 2013
* David Feng <fenghua@phytium.com.cn>
*
* This file is based on sample code from ARMv8 ARM.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#define ASM_NL ;
#define SYMBOL_NAME(X) X
// #define SYMBOL_NAME_LABEL(X) X##:
#define SYMBOL_NAME_LABEL(X) X:
#ifndef __ALIGN
#define __ALIGN .align 4
#endif
#ifndef __ALIGN_STR
#define __ALIGN_STR ".align 4"
#endif
#define ALIGN __ALIGN
#define ALIGN_STR __ALIGN_STR
#define LENTRY(name) \
ALIGN ASM_NL \
SYMBOL_NAME_LABEL(name)
#define ENTRY(name) \
.globl SYMBOL_NAME(name) ASM_NL \
LENTRY(name)
#define WEAK(name) \
.weak SYMBOL_NAME(name) ASM_NL \
LENTRY(name)
#define END(name) \
.size name, .-name
#define ENDPROC(name) \
.type name STT_FUNC ASM_NL \
END(name)
#define CR_M (1 << 0) /* MMU enable */
#define CR_A (1 << 1) /* Alignment abort enable */
#define CR_C (1 << 2) /* Dcache enable */
#define CR_SA (1 << 3) /* Stack Alignment Check Enable */
#define CR_I (1 << 12) /* Icache enable */
#define CR_WXN (1 << 19) /* Write Permision Imply XN */
#define CR_EE (1 << 25) /* Exception (Big) Endian */
.macro switch_el, xreg, el3_label, el2_label, el1_label
mrs \xreg, CurrentEL
cmp \xreg, 0xc
b.eq \el3_label
cmp \xreg, 0x8
b.eq \el2_label
cmp \xreg, 0x4
b.eq \el1_label
.endm
/*
* void __asm_dcache_level(level)
* flush or invalidate one level cache.
*
* x0: cache level
* x1: 0 clean & invalidate, 1 invalidate only
* x2~x9: clobbered
*/
ENTRY(__asm_dcache_level)
lsl x12, x0, #1
msr csselr_el1, x12 /* select cache level */
isb /* sync change of cssidr_el1 */
mrs x6, ccsidr_el1 /* read the new cssidr_el1 */
and x2, x6, #7 /* x2 <- log2(cache line size)-4 */
add x2, x2, #4 /* x2 <- log2(cache line size) */
mov x3, #0x3ff
and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */
clz w5, w3 /* bit position of #ways */
mov x4, #0x7fff
and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */
/* x12 <- cache level << 1 */
/* x2 <- line length offset */
/* x3 <- number of cache ways - 1 */
/* x4 <- number of cache sets - 1 */
/* x5 <- bit position of #ways */
loop_set:
mov x6, x3 /* x6 <- working copy of #ways */
loop_way:
lsl x7, x6, x5
orr x9, x12, x7 /* map way and level to cisw value */
lsl x7, x4, x2
orr x9, x9, x7 /* map set number to cisw value */
tbz w1, #0, 1f
dc isw, x9
b 2f
1: dc cisw, x9 /* clean & invalidate by set/way */
2: subs x6, x6, #1 /* decrement the way */
b.ge loop_way
subs x4, x4, #1 /* decrement the set */
b.ge loop_set
ret
ENDPROC(__asm_dcache_level)
/*
* void __asm_flush_dcache_all(int invalidate_only)
*
* x0: 0 clean & invalidate, 1 invalidate only
*
* flush or invalidate all data cache by SET/WAY.
*/
ENTRY(__asm_dcache_all)
mov x1, x0
dsb sy
mrs x10, clidr_el1 /* read clidr_el1 */
lsr x11, x10, #24
and x11, x11, #0x7 /* x11 <- loc */
cbz x11, finished /* if loc is 0, exit */
mov x15, lr
mov x0, #0 /* start flush at cache level 0 */
/* x0 <- cache level */
/* x10 <- clidr_el1 */
/* x11 <- loc */
/* x15 <- return address */
loop_level:
lsl x12, x0, #1
add x12, x12, x0 /* x0 <- tripled cache level */
lsr x12, x10, x12
and x12, x12, #7 /* x12 <- cache type */
cmp x12, #2
b.lt skip /* skip if no cache or icache */
bl __asm_dcache_level /* x1 = 0 flush, 1 invalidate */
skip:
add x0, x0, #1 /* increment cache level */
cmp x11, x0
b.gt loop_level
mov x0, #0
msr csselr_el1, x0 /* restore csselr_el1 */
dsb sy
isb
mov lr, x15
finished:
ret
ENDPROC(__asm_dcache_all)
ENTRY(__asm_flush_dcache_all)
mov x0, #0
b __asm_dcache_all
ENDPROC(__asm_flush_dcache_all)
ENTRY(__asm_invalidate_dcache_all)
mov x0, #0x1
b __asm_dcache_all
ENDPROC(__asm_invalidate_dcache_all)
/*
* void __asm_flush_dcache_range(start, end)
*
* clean & invalidate data cache in the range
*
* x0: start address
* x1: end address
*/
ENTRY(__asm_flush_dcache_range)
isb
mrs x3, ctr_el0
lsr x3, x3, #16
and x3, x3, #0xf
mov x2, #4
lsl x2, x2, x3 /* cache line size */
/* x2 <- minimal cache line size in cache system */
sub x3, x2, #1
bic x0, x0, x3
1: dc civac, x0 /* clean & invalidate data or unified cache */
add x0, x0, x2
cmp x0, x1
b.lo 1b
dsb sy
isb
ret
ENDPROC(__asm_flush_dcache_range)
/*
* void __asm_invalidate_dcache_range(start, end)
*
* invalidate data cache in the range
*
* x0: start address
* x1: end address
*/
ENTRY(__asm_invalidate_dcache_range)
mrs x3, ctr_el0
ubfm x3, x3, #16, #19
mov x2, #4
lsl x2, x2, x3 /* cache line size */
/* x2 <- minimal cache line size in cache system */
sub x3, x2, #1
bic x0, x0, x3
1: dc ivac, x0 /* invalidate data or unified cache */
add x0, x0, x2
cmp x0, x1
b.lo 1b
dsb sy
isb
ret
ENDPROC(__asm_invalidate_dcache_range)
/*
* void __asm_invalidate_icache_all(void)
*
* invalidate all tlb entries.
*/
ENTRY(__asm_invalidate_icache_all)
ic ialluis
isb sy
ret
ENDPROC(__asm_invalidate_icache_all)
ENTRY(__asm_invalidate_l3_dcache)
mov x0, #0 /* return status as success */
ret
ENDPROC(__asm_invalidate_l3_dcache)
.weak __asm_invalidate_l3_dcache
ENTRY(__asm_flush_l3_dcache)
mov x0, #0 /* return status as success */
ret
ENDPROC(__asm_flush_l3_dcache)
.weak __asm_flush_l3_dcache
ENTRY(__asm_invalidate_l3_icache)
mov x0, #0 /* return status as success */
ret
ENDPROC(__asm_invalidate_l3_icache)
.weak __asm_invalidate_l3_icache
/*
* void __asm_switch_ttbr(ulong new_ttbr)
*
* Safely switches to a new page table.
*/
ENTRY(__asm_switch_ttbr)
/* x2 = SCTLR (alive throghout the function) */
switch_el x4, 3f, 2f, 1f
3: mrs x2, sctlr_el3
b 0f
2: mrs x2, sctlr_el2
b 0f
1: mrs x2, sctlr_el1
0:
/* Unset CR_M | CR_C | CR_I from SCTLR to disable all caches */
movn x1, #(CR_M | CR_C | CR_I)
and x1, x2, x1
switch_el x4, 3f, 2f, 1f
3: msr sctlr_el3, x1
b 0f
2: msr sctlr_el2, x1
b 0f
1: msr sctlr_el1, x1
0: isb
/* This call only clobbers x30 (lr) and x9 (unused) */
mov x3, x30
bl __asm_invalidate_tlb_all
/* From here on we're running safely with caches disabled */
/* Set TTBR to our first argument */
switch_el x4, 3f, 2f, 1f
3: msr ttbr0_el3, x0
b 0f
2: msr ttbr0_el2, x0
b 0f
1: msr ttbr0_el1, x0
0: isb
/* Restore original SCTLR and thus enable caches again */
switch_el x4, 3f, 2f, 1f
3: msr sctlr_el3, x2
b 0f
2: msr sctlr_el2, x2
b 0f
1: msr sctlr_el1, x2
0: isb
ret x3
ENDPROC(__asm_switch_ttbr)
ENTRY(__asm_invalidate_tlb_all)
switch_el x9, 3f, 2f, 1f
3: tlbi alle3
dsb sy
isb
b 0f
2: tlbi alle2
dsb sy
isb
b 0f
1: tlbi vmalle1
dsb sy
isb
0:
ret
ENDPROC(__asm_invalidate_tlb_all)

View File

@ -20,6 +20,10 @@ Modification:
*************************************************/
#include "l1_cache.h"
extern void __asm_flush_dcache_all();
extern void __asm_flush_l3_dcache();
extern void __asm_invalidate_icache_all();
extern void __asm_invalidate_l3_icache();
void InvalidateL1Dcache(uintptr_t start, uintptr_t end)
{
@ -153,34 +157,14 @@ void FlushL1Dcache(uintptr_t start, uintptr_t end)
void FlushL1DcacheAll(void)
{
uint64_t ccsidr_el1; // Cache Size ID
int num_sets; // number of sets
int num_ways; // number of ways
uint32_t wayset; // wayset parameter
__asm__ __volatile__("mrs %0, ccsidr_el1" : "=r"(ccsidr_el1)); // Read Cache Size ID
// Fill number of sets and number of ways from ccsidr_el1 register This walues are decremented by 1
num_sets = ((ccsidr_el1 >> 32) & 0x7FFF) + 1;
num_ways = ((ccsidr_el1 >> 0) & 0x7FFF) + 1;
// clean and invalidate all lines (all Sets in all ways)
for (int way = 0; way < num_ways; way++) {
for (int set = 0; set < num_sets; set++) {
wayset = (way << 30) | (set << 5);
__asm__ __volatile__("dc cisw, %0" : : "r"(wayset));
}
}
// All Cache, Branch predictor and TLB maintenance operations before followed instruction complete
DSB();
__asm_flush_dcache_all();
__asm_flush_l3_dcache();
}
void InvalidateL1IcacheAll()
{
__asm__ __volatile__("ic iallu\n\t");
// synchronize context on this processor
ISB();
__asm_invalidate_icache_all();
__asm_invalidate_l3_icache();
}
void InvalidateL1Icache(uintptr_t start, uintptr_t end)

View File

@ -92,7 +92,7 @@ static inline void invalidate_icache(uintptr_t start, uintptr_t end)
static inline void invalidate_icache_all(void)
{
// InvalidateL1IcacheAll();
InvalidateL1IcacheAll();
}
/****************************************************************************
@ -151,7 +151,7 @@ static inline void flush_dcache(uintptr_t start, uintptr_t end)
static inline void flush_dcache_all(void)
{
// FlushL1DcacheAll();
FlushL1DcacheAll();
// FlushL2CacheAll();
}

View File

@ -1,4 +1,4 @@
ifneq ($(findstring $(BOARD), ok1028a-c), )
ifneq ($(findstring $(BOARD), 3568), )
SRC_DIR := armv8-a
endif
ifneq ($(findstring $(BOARD), imx6q-sabrelite zynq7000-zc702), )

View File

@ -1,5 +1,5 @@
ifneq ($(findstring $(BOARD), ok1028a-c), )
SRC_DIR := cortex-a72
ifneq ($(findstring $(BOARD), 3568), )
SRC_DIR := cortex-a55
endif

View File

@ -22,27 +22,27 @@
static void enable_timer()
{
uint32_t c = r_cntv_ctl_el0();
uint32_t c = r_cntp_ctl_el0();
c |= CNTV_CTL_ENABLE;
c &= ~CNTV_CTL_IMASK;
w_cntv_ctl_el0(c);
w_cntp_ctl_el0(c);
}
static void disable_timer()
{
uint32_t c = r_cntv_ctl_el0();
uint32_t c = r_cntp_ctl_el0();
c |= CNTV_CTL_IMASK;
c &= ~CNTV_CTL_ENABLE;
w_cntv_ctl_el0(c);
w_cntp_ctl_el0(c);
}
static void reload_timer()
{
// interval 100ms
static uint32_t ms = 10;
// interval 1ms
static uint32_t ms = 1;
uint32_t interval = ms * 1000;
uint32_t interval_clk = interval * (r_cntfrq_el0() / 1000000);
w_cntv_tval_el0(interval_clk);
w_cntp_tval_el0(interval_clk);
}
void _sys_clock_init()
@ -54,7 +54,7 @@ void _sys_clock_init()
static uint32_t _get_clock_int()
{
return 27;
return 30;
}
static uint64_t _get_tick()
@ -64,7 +64,7 @@ static uint64_t _get_tick()
static uint64_t _get_second()
{
return 0;
return _get_tick() / r_cntfrq_el0();
}
static bool _is_timer_expired()

View File

@ -15,28 +15,28 @@
#include <stdint.h>
// armv8 generic timer
static inline uint32_t r_cntv_ctl_el0()
static inline uint32_t r_cntp_ctl_el0()
{
uint32_t x;
__asm__ volatile("mrs %0, cntv_ctl_el0" : "=r"(x));
__asm__ volatile("mrs %0, cntp_ctl_el0" : "=r"(x));
return x;
}
static inline void w_cntv_ctl_el0(uint32_t x)
static inline void w_cntp_ctl_el0(uint32_t x)
{
__asm__ volatile("msr cntv_ctl_el0, %0" : : "r"(x));
__asm__ volatile("msr cntp_ctl_el0, %0" : : "r"(x));
}
static inline uint32_t r_cntv_tval_el0()
static inline uint32_t r_cntp_tval_el0()
{
uint32_t x;
__asm__ volatile("mrs %0, cntv_tval_el0" : "=r"(x));
__asm__ volatile("mrs %0, cntp_tval_el0" : "=r"(x));
return x;
}
static inline void w_cntv_tval_el0(uint32_t x)
static inline void w_cntp_tval_el0(uint32_t x)
{
__asm__ volatile("msr cntv_tval_el0, %0" : : "r"(x));
__asm__ volatile("msr cntp_tval_el0, %0" : : "r"(x));
}
static inline uint64_t r_cntvct_el0()

View File

@ -129,7 +129,7 @@ static bool xizi_gpt_init()
return false;
}
// register clock handler to intr
struct XiziTrapDriver* p_intr_driver = (struct XiziTrapDriver*)AchieveResource(&intr_driver_tag);
struct XiziTrapDriver* p_intr_driver = GetSysObject(struct XiziTrapDriver, &intr_driver_tag);
p_intr_driver->bind_irq_handler(p_clock_driver->get_clock_int(), xizi_clock_handler);
p_intr_driver->single_irq_enable(p_clock_driver->get_clock_int(), 0, 0);
return true;
@ -220,6 +220,7 @@ bool secondary_cpu_hardkernel_init(int cpu_id, struct TraceTag* _hardkernel_tag)
p_icache_driver->enable();
p_dcache_driver->enable();
// clock
p_clock_driver->sys_clock_init();
p_intr_driver->single_irq_enable(p_clock_driver->get_clock_int(), cpu_id, 0);
// mmu
secondary_cpu_load_kern_pgdir(&init_mmu_tag, &init_intr_tag);

View File

@ -1,4 +1,4 @@
ifneq ($(findstring $(BOARD), ok1028a-c), )
ifneq ($(findstring $(BOARD), 3568), )
SRC_DIR := armv8-a
endif
ifneq ($(findstring $(BOARD), imx6q-sabrelite zynq7000-zc702), )

View File

@ -57,7 +57,7 @@ void panic(char* s)
/* stack for different mode*/
static char mode_stack_pages[NR_CPU][NR_MODE_STACKS][MODE_STACK_SIZE];
extern uint32_t _vector_jumper;
extern uint32_t _vector_start;
extern uint32_t* _vector_start;
extern uint32_t _vector_end;
void init_cpu_mode_stacks(int cpu_id)
@ -75,7 +75,7 @@ static void _sys_irq_init(int cpu_id)
/* load exception vectors */
init_cpu_mode_stacks(cpu_id);
if (cpu_id == 0) {
volatile uint32_t* vector_base = &_vector_start;
volatile uint32_t* vector_base = (uint32_t*)&_vector_start;
// Set Interrupt handler start address
vector_base[1] = (uint32_t)trap_undefined_instruction; // Undefined Instruction

View File

@ -1,3 +1,3 @@
SRC_DIR := cortex-a72
SRC_DIR := cortex-a55
include $(KERNEL_ROOT)/compiler.mk

View File

@ -28,13 +28,16 @@ Modification:
*************************************************/
#include <stdint.h>
#include "exception_registers.h"
#include "assert.h"
#include "core.h"
#include "exception_registers.h"
#include "multicores.h"
#include "syscall.h"
#include "task.h"
#include "mmu.h"
extern void dabort_handler(struct trapframe* r);
extern void iabort_handler(struct trapframe* r);
@ -73,7 +76,6 @@ void syscall_arch_handler(struct trapframe* tf)
uint64_t esr = r_esr_el1();
uint64_t ec = (esr >> 0x1A) & 0x3F;
w_esr_el1(0);
switch (ec) {
case 0B010101:
software_irq_dispatch(tf);
@ -87,11 +89,30 @@ void syscall_arch_handler(struct trapframe* tf)
iabort_handler(tf);
break;
default: {
ERROR("USYSCALL: unexpected ec: %016lx", esr);
ERROR("USYSCALL: unexpected\n");
ERROR(" esr: %016lx\n", esr);
ERROR(" elr = %016lx far = %016lx\n", r_elr_el1(), r_far_el1());
w_esr_el1(0);
extern void dump_tf(struct trapframe * tf);
dump_tf(tf);
uint32_t sctlr = 0;
SCTLR_R(sctlr);
DEBUG("SCTLR: %x\n", sctlr);
uint32_t spsr = 0;
__asm__ volatile("mrs %0, spsr_el1" : "=r"(spsr)::"memory");
DEBUG("SPSR: %x\n", spsr);
uint64_t tcr = 0;
__asm__ volatile("mrs %0, tcr_el1" : "=r"(tcr)::"memory");
DEBUG("TCR: %x\n", tcr);
uint64_t mair = 0;
__asm__ volatile("mrs %0, mair_el1" : "=r"(mair)::"memory");
DEBUG("MAIR: %x\n", mair);
// kill error task
xizi_enter_kernel();
assert(cur_cpu()->task != NULL);
ERROR("Error Task: %s\n", cur_cpu()->task->name);
sys_exit(cur_cpu()->task);
context_switch(&cur_cpu()->task->thread_context.context, cur_cpu()->scheduler);
panic("dabort end should never be reashed.\n");

View File

@ -29,7 +29,7 @@ Modification:
#include <string.h>
#include "core.h"
#include "cortex_a72.h"
#include "cortex_a55.h"
#include "exception_registers.h"
#include "gicv3_common_opa.h"
#include "trap_common.h"

View File

@ -1,6 +1,6 @@
SRC_FILES := trampoline.S $(BOARD)/trap_common.c $(BOARD)/trap.c error_debug.c hard_spinlock.S
ifeq ($(BOARD), ok1028a-c)
ifeq ($(BOARD), 3568)
SRC_DIR := gicv3
SRC_FILES += $(BOARD)/
endif

View File

@ -39,51 +39,53 @@ Modification:
2. Modify iabort and dabort handler(in dabort_handler() and iabort_handler())
*************************************************/
#include <stddef.h>
#include <stdint.h>
#include "exception_registers.h"
#include "assert.h"
#include "core.h"
#include "log.h"
#include "multicores.h"
#include "spinlock.h"
#include "task.h"
#include "trap_common.h"
void dump_tf(struct trapframe* tf)
{
KPrintf(" sp: 0x%x\n", tf->sp);
KPrintf(" pc: 0x%x\n", tf->pc);
KPrintf(" spsr: 0x%x\n", tf->spsr);
KPrintf(" x0: 0x%x\n", tf->x0);
KPrintf(" x1: 0x%x\n", tf->x1);
KPrintf(" x2: 0x%x\n", tf->x2);
KPrintf(" x3: 0x%x\n", tf->x3);
KPrintf(" x4: 0x%x\n", tf->x4);
KPrintf(" x5: 0x%x\n", tf->x5);
KPrintf(" x6: 0x%x\n", tf->x6);
KPrintf(" x7: 0x%x\n", tf->x7);
KPrintf(" x8: 0x%x\n", tf->x8);
KPrintf(" x9: 0x%x\n", tf->x9);
KPrintf(" x10: 0x%x\n", tf->x10);
KPrintf(" x11: 0x%x\n", tf->x11);
KPrintf(" x12: 0x%x\n", tf->x12);
KPrintf(" x13: 0x%x\n", tf->x13);
KPrintf(" x14: 0x%x\n", tf->x14);
KPrintf(" x15: 0x%x\n", tf->x15);
KPrintf(" x16: 0x%x\n", tf->x16);
KPrintf(" x17: 0x%x\n", tf->x17);
KPrintf(" x18: 0x%x\n", tf->x18);
KPrintf(" x19: 0x%x\n", tf->x19);
KPrintf(" x20: 0x%x\n", tf->x20);
KPrintf(" x21: 0x%x\n", tf->x21);
KPrintf(" x22: 0x%x\n", tf->x22);
KPrintf(" x23: 0x%x\n", tf->x23);
KPrintf(" x24: 0x%x\n", tf->x24);
KPrintf(" x25: 0x%x\n", tf->x25);
KPrintf(" x26: 0x%x\n", tf->x26);
KPrintf(" x27: 0x%x\n", tf->x27);
KPrintf(" x28: 0x%x\n", tf->x28);
KPrintf(" x29: 0x%x\n", tf->x29);
KPrintf(" x30: 0x%x\n", tf->x30);
KPrintf(" sp: 0x%016lx\n", tf->sp);
KPrintf(" pc: 0x%016lx\n", tf->pc);
KPrintf(" spsr: 0x%016lx\n", tf->spsr);
KPrintf(" x0: 0x%016lx\n", tf->x0);
KPrintf(" x1: 0x%016lx\n", tf->x1);
KPrintf(" x2: 0x%016lx\n", tf->x2);
KPrintf(" x3: 0x%016lx\n", tf->x3);
KPrintf(" x4: 0x%016lx\n", tf->x4);
KPrintf(" x5: 0x%016lx\n", tf->x5);
KPrintf(" x6: 0x%016lx\n", tf->x6);
KPrintf(" x7: 0x%016lx\n", tf->x7);
KPrintf(" x8: 0x%016lx\n", tf->x8);
KPrintf(" x9: 0x%016lx\n", tf->x9);
KPrintf(" x10: 0x%016lx\n", tf->x10);
KPrintf(" x11: 0x%016lx\n", tf->x11);
KPrintf(" x12: 0x%016lx\n", tf->x12);
KPrintf(" x13: 0x%016lx\n", tf->x13);
KPrintf(" x14: 0x%016lx\n", tf->x14);
KPrintf(" x15: 0x%016lx\n", tf->x15);
KPrintf(" x16: 0x%016lx\n", tf->x16);
KPrintf(" x17: 0x%016lx\n", tf->x17);
KPrintf(" x18: 0x%016lx\n", tf->x18);
KPrintf(" x19: 0x%016lx\n", tf->x19);
KPrintf(" x20: 0x%016lx\n", tf->x20);
KPrintf(" x21: 0x%016lx\n", tf->x21);
KPrintf(" x22: 0x%016lx\n", tf->x22);
KPrintf(" x23: 0x%016lx\n", tf->x23);
KPrintf(" x24: 0x%016lx\n", tf->x24);
KPrintf(" x25: 0x%016lx\n", tf->x25);
KPrintf(" x26: 0x%016lx\n", tf->x26);
KPrintf(" x27: 0x%016lx\n", tf->x27);
KPrintf(" x28: 0x%016lx\n", tf->x28);
KPrintf(" x29: 0x%016lx\n", tf->x29);
KPrintf(" x30: 0x%016lx\n", tf->x30);
}
void dabort_reason(struct trapframe* r)
@ -91,8 +93,9 @@ void dabort_reason(struct trapframe* r)
uint32_t fault_status, fault_address;
__asm__ __volatile__("mrs %0, esr_el1" : "=r"(fault_status));
__asm__ __volatile__("mrs %0, far_el1" : "=r"(fault_address));
LOG("program counter: 0x%x caused\n", r->pc);
LOG("data abort at 0x%x, status 0x%x\n", fault_address, fault_status);
w_esr_el1(0);
LOG("program counter: 0x%016lx caused\n", r->pc);
LOG("data abort at 0x%016lx, status 0x%016lx\n", fault_address, fault_status);
if ((fault_status & 0x3f) == 0x21) // Alignment failure
KPrintf("reason: alignment\n");
else if ((fault_status & 0x3f) == 0x4) // Translation fault, level 0
@ -131,8 +134,9 @@ void iabort_reason(struct trapframe* r)
uint32_t fault_status, fault_address;
__asm__ __volatile__("mrs %0, esr_el1" : "=r"(fault_status));
__asm__ __volatile__("mrs %0, far_el1" : "=r"(fault_address));
LOG("program counter: 0x%x caused\n", r->pc);
LOG("data abort at 0x%x, status 0x%x\n", fault_address, fault_status);
LOG("program counter: 0x%016lx caused\n", r->pc);
LOG("data abort at 0x%016lx, status 0x%016lx\n", fault_address, fault_status);
w_esr_el1(0);
if ((fault_status & 0x3f) == 0x21) // Alignment failure
KPrintf("reason: alignment\n");
else if ((fault_status & 0x3f) == 0x4) // Translation fault, level 0

View File

@ -30,8 +30,8 @@ Modification:
// clang-format off
// interrupt controller GICv3
#define GICV3 MMIO_P2V_WO(0x08000000ULL)
#define GICV3_REDIST MMIO_P2V_WO(0x080a0000ULL)
#define GICV3 MMIO_P2V_WO(0xFD400000ULL)
#define GICV3_REDIST MMIO_P2V_WO(0xFD460000ULL)
#define D_CTLR 0x0
#define D_TYPER 0x4

View File

@ -58,25 +58,26 @@ Modification:
.func _spinlock_lock
_spinlock_lock:
mov w2, #1
sevl
1:
wfe
2:
ldaxrb w1, [x0] // check if the spinlock is currently unlocked
cmp w1, #UNLOCKED
bne _spinlock_lock
bne 1b
mrs x1, mpidr_el1 // get our CPU ID
and x1, x1, #3
and x1, x1, #0xFFF
lsr x1, x1, #8
stxrb w2, w1, [x0]
cmp x2, #0
bne _spinlock_lock // check if the write was successful, if the write failed, start over
bne 2b // check if the write was successful, if the write failed, start over
dmb ish // Ensure that accesses to shared resource have completed
mov x0, #0
ret
.endfunc
@ -84,33 +85,26 @@ ret
.global _spinlock_unlock
.func _spinlock_unlock
_spinlock_unlock:
mrs x1, mpidr_el1 // get our CPU ID
and x1, x1, #3
and x1, x1, #0xFFF
lsr x1, x1, #8
ldr w2, [x0]
cmp w1, w2
bne 1f //doesn't match,jump to 1
dmb ish
mov w1, #UNLOCKED
str w1, [x0]
dsb ish //Ensure that no instructions following the barrier execute until
// all memory accesses prior to the barrier have completed.
sevl // send event to wake up other cores waiting on spinlock
mov x0, #0 // return success
ret
1:
mov x0, #1 //doesn't match, so exit with failure
ret
.endfunc
.end

View File

@ -143,13 +143,13 @@ Modification:
.balign 0x800
alltraps:
// Current EL with sp0
b .
b badtrap
.balign 0x80
b .
b badtrap
.balign 0x80
b .
b badtrap
.balign 0x80
b .
b badtrap
// Current EL with spx
.balign 0x80
@ -157,9 +157,9 @@ alltraps:
.balign 0x80
b el1irq
.balign 0x80
b .
b badtrap
.balign 0x80
b .
b badtrap
// Lower EL using aarch64
.balign 0x80
@ -167,32 +167,34 @@ alltraps:
.balign 0x80
b el0irq
.balign 0x80
b .
b badtrap
.balign 0x80
b .
b badtrap
// Lower EL using aarch32
.balign 0x80
b .
b badtrap
.balign 0x80
b .
b badtrap
.balign 0x80
b .
b badtrap
.balign 0x80
b badtrap
badtrap:
savereg
mov x0, sp
bl kernel_intr_handler
b .
el1sync:
msr daifset, #0xf
savereg
mov x0, sp
bl kernel_abort_handler
b .
el1irq:
msr daifset, #0xf
usavereg
mov x0, sp
bl intr_irq_dispatch
@ -201,9 +203,7 @@ el1irq:
eret
el0sync:
msr daifset, #0xf
usavereg
mov x0, sp
bl syscall_arch_handler
@ -212,9 +212,7 @@ el0sync:
eret
el0irq:
msr daifset, #0xf
usavereg
mov x0, sp
bl intr_irq_dispatch

View File

@ -59,7 +59,7 @@ __attribute__((optimize("O0"))) void spinlock_init(struct spinlock* lock, char*
}
extern int _spinlock_lock(struct spinlock* lock, uint32_t timeout);
extern void _spinlock_unlock(struct spinlock* lock);
extern int _spinlock_unlock(struct spinlock* lock);
__attribute__((optimize("O0"))) void spinlock_lock(struct spinlock* lock)
{
@ -88,7 +88,9 @@ __attribute__((optimize("O0"))) void spinlock_unlock(struct spinlock* lock)
_double_list_del(p_lock_node->prev, p_lock_node->next);
_spinlock_unlock(&request_lock);
_spinlock_unlock(lock);
if (_spinlock_unlock(lock) != 0) {
ERROR("Core %d trying to unlock a lock belongs to %d.\n", cur_cpuid(), lock->owner_cpu);
}
}
__attribute__((optimize("O0"))) bool spinlock_try_lock(struct spinlock* lock)

View File

@ -1,4 +1,4 @@
ifneq ($(findstring $(BOARD), ok1028a-c), )
ifneq ($(findstring $(BOARD), 3568), )
SRC_DIR := armv8-a
endif
ifneq ($(findstring $(BOARD), imx6q-sabrelite zynq7000-zc702), )

View File

@ -48,7 +48,7 @@ uint32_t boot_pgdir[NR_PDE_ENTRIES] __attribute__((aligned(0x4000))) = { 0 };
static void build_boot_pgdir()
{
// dev mem
uint32_t dev_mem_end_idx = (DEV_PHYMEM_BASE + DEV_MEM_SZ) >> LEVEL3_PDE_SHIFT;
uint32_t dev_mem_end_idx = (DEV_PHYMEM_BASE + DEV_MEM_SIZE) >> LEVEL3_PDE_SHIFT;
for (uint32_t i = DEV_PHYMEM_BASE >> LEVEL3_PDE_SHIFT; i < dev_mem_end_idx; i++) {
boot_pgdir[i] = (i << LEVEL3_PDE_SHIFT) | L1_TYPE_SEC | L1_SECT_DEV | L1_SECT_AP0;
boot_pgdir[MMIO_P2V_WO(i << LEVEL3_PDE_SHIFT) >> LEVEL3_PDE_SHIFT] = (i << LEVEL3_PDE_SHIFT) | L1_TYPE_SEC | L1_SECT_DEV | L1_SECT_AP0;

View File

@ -67,10 +67,17 @@ Modification:
/* Deivce memory layout */
#define DEV_PHYMEM_BASE (0x00000000)
#define DEV_VRTMEM_BASE (0x80000000)
#define DEV_MEM_SZ (0x10000000)
#define DEV_MEM_SIZE (0x10000000)
/* Kernel memory layout */
#define KERN_MEM_BASE (0x90000000) // First kernel virtual address
#define KERN_OFFSET (KERN_MEM_BASE - PHY_MEM_BASE)
/* virtual and physical addr translate */
#define V2P(a) ((uint32_t)((uint32_t)(a)-KERN_OFFSET))
#define P2V(a) ((void*)((void*)(a) + KERN_OFFSET))
#define V2P_WO(x) ((x)-KERN_OFFSET) // same as V2P, but without casts
#define P2V_WO(x) ((x) + KERN_OFFSET) // same as V2P, but without casts
// clang-format on

View File

@ -92,13 +92,6 @@ When the process switches, the flush TLB is no longer required anymore.
#define CONTEXTIDR_R(val) __asm__ volatile("mrc p15, 0, %0, c13, c0, 1" : "=r"(val))
#define CONTEXTIDR_W(val) __asm__ volatile("mcr p15, 0, %0, c13, c0, 1" ::"r"(val))
/* virtual and physical addr translate */
#define V2P(a) ((uint32_t)((uint32_t)(a)-KERN_OFFSET))
#define P2V(a) ((void*)((void*)(a) + KERN_OFFSET))
#define V2P_WO(x) ((x)-KERN_OFFSET) // same as V2P, but without casts
#define P2V_WO(x) ((x) + KERN_OFFSET) // same as V2P, but without casts
#ifndef __ASSEMBLER__
#include <stdint.h>
__attribute__((always_inline)) static inline uint32_t v2p(void* a) { return ((uint32_t)(a)) - KERN_MEM_BASE; }

View File

@ -66,7 +66,7 @@ Modification:
/* Deivce memory layout */
#define DEV_PHYMEM_BASE (0xE0000000)
#define DEV_VRTMEM_BASE (0x80000000)
#define DEV_MEM_SZ (0x1FFFFFFF)
#define DEV_MEM_SIZE (0x1FFFFFFF)
/* Kernel memory layout */
#define KERN_MEM_BASE (0xA0000000) // First kernel virtual address

View File

@ -1,3 +1,3 @@
SRC_DIR := cortex-a72
SRC_DIR := cortex-a55
include $(KERNEL_ROOT)/compiler.mk

View File

@ -33,11 +33,11 @@ Modification:
#define ARCH_BIT 64
/* A72 physical memory layout */
#define PHY_MEM_BASE (0x0000000040000000ULL)
#define PHY_USER_FREEMEM_BASE (0x0000000046000000ULL)
#define PHY_USER_FREEMEM_TOP (0x0000000048000000ULL)
#define PHY_MEM_STOP (0x0000000048000000ULL)
/* A55 physical memory layout */
#define PHY_MEM_BASE (0x0000000010000000ULL)
#define PHY_USER_FREEMEM_BASE (0x0000000040000000ULL)
#define PHY_USER_FREEMEM_TOP (0x00000000E0000000ULL)
#define PHY_MEM_STOP (0x00000000E0000000ULL)
/* PTE-PAGE_SIZE */
#define LEVEL4_PTE_SHIFT 12
@ -58,23 +58,23 @@ Modification:
#define NUM_TOPLEVEL_PDE NUM_LEVEL2_PDE
#define PAGE_SIZE LEVEL4_PTE_SIZE
#define MAX_NR_FREE_PAGES ((PHY_MEM_STOP - PHY_MEM_BASE) >> LEVEL4_PTE_SHIFT)
#define MAX_NR_FREE_PAGES ((PHY_USER_FREEMEM_BASE - PHY_MEM_BASE) >> LEVEL4_PTE_SHIFT)
/* Deivce memory layout */
#define DEV_PHYMEM_BASE (0x0000000000000000ULL)
#define DEV_VRTMEM_BASE (0x0000004000000000ULL)
#define DEV_MEM_SZ (0x0000000010000000ULL)
#define DEV_PHYMEM_BASE (0x00000000F0000000ULL)
#define DEV_VRTMEM_BASE (0x00000040F0000000ULL)
#define DEV_MEM_SIZE (0x0000000010000000ULL)
/* User memory layout */
#define USER_STACK_SIZE PAGE_SIZE
#define USER_MEM_BASE (0x0000000000000000ULL)
#define USER_MEM_TOP DEV_VRTMEM_BASE
#define USER_MEM_TOP (0x0000004000000000ULL)
#define USER_IPC_SPACE_BASE (0x0000003000000000ULL)
#define USER_IPC_USE_ALLOCATOR_WATERMARK (0x0000003000010000ULL)
#define USER_IPC_SPACE_TOP (USER_IPC_SPACE_BASE + 0x10000000ULL)
/* Kernel memory layout */
#define KERN_MEM_BASE (0x0000006040000000ULL) // First kernel virtual address
#define KERN_MEM_BASE (0x0000006010000000ULL) // First kernel virtual address
#define KERN_OFFSET (KERN_MEM_BASE - PHY_MEM_BASE)
#define V2P(a) (((uint64_t)(a)) - KERN_OFFSET)

View File

@ -62,26 +62,32 @@ extern uint64_t kernel_data_begin[];
uint64_t boot_l2pgdir[NUM_LEVEL2_PDE] __attribute__((aligned(0x1000))) = { 0 };
uint64_t boot_dev_l3pgdir[NUM_LEVEL3_PDE] __attribute__((aligned(0x1000))) = { 0 };
uint64_t boot_virt_dev_l3pgdir[NUM_LEVEL3_PDE] __attribute__((aligned(0x1000))) = { 0 };
uint64_t boot_kern_l3pgdir[NUM_LEVEL3_PDE] __attribute__((aligned(0x1000))) = { 0 };
uint64_t boot_virt_kern_l3pgdir[NUM_LEVEL3_PDE] __attribute__((aligned(0x1000))) = { 0 };
uint64_t boot_dev_l4pgdirs[NUM_LEVEL3_PDE][NUM_LEVEL4_PTE] __attribute__((aligned(0x1000))) = { 0 };
uint64_t boot_kern_l4pgdirs[NUM_LEVEL3_PDE][NUM_LEVEL4_PTE] __attribute__((aligned(0x1000))) = { 0 };
static void build_boot_pgdir()
{
static bool built = false;
if (!built) {
uint64_t dev_phy_mem_base = DEV_PHYMEM_BASE;
// dev mem
boot_l2pgdir[(dev_phy_mem_base >> LEVEL2_PDE_SHIFT) & IDX_MASK] = (uint64_t)boot_dev_l3pgdir | L2_TYPE_TAB | L2_PTE_VALID;
boot_l2pgdir[(MMIO_P2V_WO(dev_phy_mem_base) >> LEVEL2_PDE_SHIFT) & IDX_MASK] = (uint64_t)boot_dev_l3pgdir | L2_TYPE_TAB | L2_PTE_VALID;
uint64_t cur_mem_paddr = ALIGNDOWN((uint64_t)DEV_PHYMEM_BASE, PAGE_SIZE);
uint64_t cur_mem_paddr = ALIGNDOWN((uint64_t)DEV_PHYMEM_BASE, LEVEL2_PDE_SIZE);
for (size_t i = 0; i < NUM_LEVEL3_PDE; i++) {
boot_dev_l3pgdir[i] = (uint64_t)boot_dev_l4pgdirs[i] | L3_TYPE_TAB | L3_PTE_VALID;
for (size_t j = 0; j < NUM_LEVEL4_PTE; j++) {
boot_dev_l4pgdirs[i][j] = cur_mem_paddr | L4_TYPE_PAGE | L4_PTE_DEV | L4_PTE_AF | L4_PTE_XN;
if (cur_mem_paddr >= DEV_PHYMEM_BASE && cur_mem_paddr < DEV_PHYMEM_BASE + DEV_MEM_SIZE) {
boot_dev_l4pgdirs[i][j] = cur_mem_paddr | 0x403;
} else {
boot_dev_l4pgdirs[i][j] = cur_mem_paddr | 0x403;
}
cur_mem_paddr += PAGE_SIZE;
}
@ -91,35 +97,34 @@ static void build_boot_pgdir()
boot_l2pgdir[(PHY_MEM_BASE >> LEVEL2_PDE_SHIFT) & IDX_MASK] = (uint64_t)boot_kern_l3pgdir | L2_TYPE_TAB | L2_PTE_VALID;
boot_l2pgdir[(P2V_WO(PHY_MEM_BASE) >> LEVEL2_PDE_SHIFT) & IDX_MASK] = (uint64_t)boot_kern_l3pgdir | L2_TYPE_TAB | L2_PTE_VALID;
cur_mem_paddr = ALIGNDOWN((uint64_t)PHY_MEM_BASE, PAGE_SIZE);
cur_mem_paddr = ALIGNDOWN((uint64_t)0x00000000ULL, PAGE_SIZE);
for (size_t i = 0; i < NUM_LEVEL3_PDE; i++) {
boot_kern_l3pgdir[i] = (uint64_t)boot_kern_l4pgdirs[i] | L3_TYPE_TAB | L3_PTE_VALID;
for (size_t j = 0; j < NUM_LEVEL4_PTE; j++) {
boot_kern_l4pgdirs[i][j] = cur_mem_paddr | L4_TYPE_PAGE | L4_PTE_NORMAL | L4_PTE_AF;
boot_kern_l4pgdirs[i][j] = cur_mem_paddr | 0x713;
cur_mem_paddr += PAGE_SIZE;
}
}
built = true;
}
}
static void load_boot_pgdir()
{
uint64_t val;
TTBR0_W((uintptr_t)boot_l2pgdir);
TTBR1_W(0);
TCR_W(TCR_VALUE);
MAIR_W((MT_DEVICE_nGnRnE << (8 * AI_DEVICE_nGnRnE_IDX)) | (MT_NORMAL_NC << (8 * AI_NORMAL_NC_IDX)));
#define TCR_TRUE_VALUE (0x0000000080813519ULL)
uint64_t tcr = 0;
TCR_R(tcr);
tcr &= (uint64_t)~0xFF;
tcr |= 0x19;
TCR_W(tcr);
// Enable paging using read/modify/write
SCTLR_R(val);
val |= (1 << 0); // EL1 and EL0 stage 1 address translation enabled.
SCTLR_W(val);
// flush all TLB
DSB();
CLEARTLB(0);
ISB();
}
@ -130,7 +135,7 @@ void bootmain()
{
build_boot_pgdir();
load_boot_pgdir();
__asm__ __volatile__("add sp, sp, %0" ::"r"(KERN_MEM_BASE - PHY_MEM_BASE));
__asm__ __volatile__("add sp, sp, %0" ::"r"(KERN_OFFSET));
if (!_bss_inited) {
memset(&kernel_data_begin, 0x00, (size_t)((uint64_t)kernel_data_end - (uint64_t)kernel_data_begin));
_bss_inited = true;

View File

@ -61,35 +61,36 @@ void GetPdeAttr(uintptr_t* attr);
/*
Enable MMU, cache, write buffer, etc.
*/
#define SCTLR_R(val) __asm__ volatile("mrs %0, sctlr_el1" : "=r"(val))
#define SCTLR_W(val) __asm__ volatile("msr sctlr_el1, %0" ::"r"(val))
#define SCTLR_R(val) __asm__ volatile("mrs %0, sctlr_el1" : "=r"(val)::"memory")
#define SCTLR_W(val) __asm__ volatile("msr sctlr_el1, %0" ::"r"(val) : "memory")
/*
Read and write mmu pagetable register base addr
*/
#define TTBR0_R(val) __asm__ volatile("mrs %0, ttbr0_el1" : "=r"(val))
#define TTBR0_W(val) __asm__ volatile("msr ttbr0_el1, %0" ::"r"(val))
#define TTBR0_R(val) __asm__ volatile("mrs %0, ttbr0_el1" : "=r"(val)::"memory")
#define TTBR0_W(val) __asm__ volatile("msr ttbr0_el1, %0" ::"r"(val) : "memory")
/*
Read and write mmu pagetable register base addr
*/
#define TTBR1_R(val) __asm__ volatile("mrs %0, ttbr1_el1" : "=r"(val))
#define TTBR1_W(val) __asm__ volatile("msr ttbr1_el1, %0" ::"r"(val))
#define TTBR1_R(val) __asm__ volatile("mrs %0, ttbr1_el1" : "=r"(val)::"memory")
#define TTBR1_W(val) __asm__ volatile("msr ttbr1_el1, %0" ::"r"(val) : "memory")
/*
Translation Control RegisterTCR
*/
#define TCR_R(val) __asm__ volatile("mrs %0, tcr_el1" : "=r"(val))
#define TCR_W(val) __asm__ volatile("msr tcr_el1, %0" ::"r"(val))
#define TCR_R(val) __asm__ volatile("mrs %0, tcr_el1" : "=r"(val)::"memory")
#define TCR_W(val) __asm__ volatile("msr tcr_el1, %0" ::"r"(val) : "memory")
#define MAIR_R(val) __asm__ volatile("mrs %0, mair_el1" : "=r"(val))
#define MAIR_W(val) __asm__ volatile("msr mair_el1, %0" ::"r"(val))
#define MAIR_R(val) __asm__ volatile("mrs %0, mair_el1" : "=r"(val)::"memory")
#define MAIR_W(val) __asm__ volatile("msr mair_el1, %0" ::"r"(val) : "memory")
/*
Flush TLB when loading a new page table.
@note If nG is not set in the pte attribute, process switching need flush tlb.
*/
#define CLEARTLB(val) __asm__ volatile("tlbi vmalle1")
// #define CLEARTLB(val) __asm__ volatile("tlbi vmalle1" ::: "memory")
#define CLEARTLB(val) __asm__ volatile("tlbi vmalle1is" ::: "memory")
/*
When nG is set in the pte attribute, the process is assigned an ASID, which is stored in the lower 8 bits of the CONTEXTIDR register.

View File

@ -45,7 +45,9 @@ void load_pgdir(uintptr_t pgdir_paddr)
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
TTBR0_W((uint64_t)pgdir_paddr);
DSB();
CLEARTLB(0);
ISB();
p_icache_done->invalidateall();
p_dcache_done->flushall();
}

View File

@ -52,22 +52,26 @@ Modification:
void GetUsrPteAttr(uintptr_t* attr)
{
*attr = ARMV8_PTE_AP_U | ARMV8_PTE_AP_RW | ARMV8_PTE_AF | ARMV8_PTE_NORMAL | ARMV8_PTE_VALID;
// *attr = ARMV8_PTE_AP_U | ARMV8_PTE_AP_RW | ARMV8_PTE_AF | ARMV8_PTE_NORMAL | ARMV8_PTE_VALID;
*attr = 0x713 | ARMV8_PTE_AP_U;
}
void GetUsrDevPteAttr(uintptr_t* attr)
{
*attr = ARMV8_PTE_AP_U | ARMV8_PTE_AP_RW | ARMV8_PTE_AF | ARMV8_PTE_DEVICE | ARMV8_PTE_XN | ARMV8_PTE_VALID;
// *attr = ARMV8_PTE_AP_U | ARMV8_PTE_AP_RW | ARMV8_PTE_AF | ARMV8_PTE_DEVICE | ARMV8_PTE_XN | ARMV8_PTE_VALID;
*attr = 0x403 | ARMV8_PTE_AP_U;
}
void GetDevPteAttr(uintptr_t* attr)
{
*attr = ARMV8_PTE_AP_K | ARMV8_PTE_AP_RW | ARMV8_PTE_AF | ARMV8_PTE_DEVICE | ARMV8_PTE_XN | ARMV8_PTE_VALID;
// *attr = ARMV8_PTE_AP_K | ARMV8_PTE_AP_RW | ARMV8_PTE_AF | ARMV8_PTE_DEVICE | ARMV8_PTE_XN | ARMV8_PTE_VALID;
*attr = 0x403ULL;
}
void GetKernPteAttr(uintptr_t* attr)
{
*attr = ARMV8_PTE_AP_K | ARMV8_PTE_AP_RW | ARMV8_PTE_AF | ARMV8_PTE_NORMAL | ARMV8_PTE_VALID;
// *attr = ARMV8_PTE_AP_K | ARMV8_PTE_AP_RW | ARMV8_PTE_AF | ARMV8_PTE_NORMAL | ARMV8_PTE_VALID;
*attr = 0x713ULL;
}
void GetPdeAttr(uintptr_t* attr)

View File

@ -1,5 +1,5 @@
# The following three platforms support compatiable instructions.
ifneq ($(findstring $(BOARD), ok1028a-c), )
ifneq ($(findstring $(BOARD), 3568), )
SRC_DIR := armv8-a
endif
ifneq ($(findstring $(BOARD), imx6q-sabrelite zynq7000-zc702), )

View File

@ -1,4 +1,4 @@
# The following three platforms support compatiable instructions.
SRC_DIR := cortex-a72
SRC_DIR := cortex-a55
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,3 +1,3 @@
SRC_FILES := l1_cache.c
SRC_FILES := uart.c ns16550.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,198 @@
/*
* NS16550 Serial Port
* originally from linux source (arch/powerpc/boot/ns16550.h)
*
* Cleanup and unification
* (C) 2009 by Detlev Zundel, DENX Software Engineering GmbH
*
* modified slightly to
* have addresses as offsets from CONFIG_SYS_ISA_BASE
* added a few more definitions
* added prototypes for ns16550.c
* reduced no of com ports to 2
* modifications (c) Rob Taylor, Flying Pig Systems. 2000.
*
* added support for port on 64-bit bus
* by Richard Danter (richard.danter@windriver.com), (C) 2005 Wind River Systems
*/
/*
* Note that the following macro magic uses the fact that the compiler
* will not allocate storage for arrays of size 0
*/
#include <stdint.h>
/*
* For driver model we always use one byte per register, and sort out the
* differences in the driver
*/
#define CONFIG_SYS_NS16550_REG_SIZE (-1)
#define UART_REG(x) \
unsigned char x; \
unsigned char postpad_##x[-CONFIG_SYS_NS16550_REG_SIZE - 1];
/**
* struct ns16550_platdata - information about a NS16550 port
*
* @base: Base register address
* @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...)
* @clock: UART base clock speed in Hz
*/
struct ns16550_platdata {
unsigned long base;
int reg_shift;
int clock;
int reg_offset;
uint32_t fcr;
};
struct udevice;
struct NS16550 {
UART_REG(rbr); /* 0 */
UART_REG(ier); /* 1 */
UART_REG(fcr); /* 2 */
UART_REG(lcr); /* 3 */
UART_REG(mcr); /* 4 */
UART_REG(lsr); /* 5 */
UART_REG(msr); /* 6 */
UART_REG(spr); /* 7 */
#ifdef CONFIG_SOC_DA8XX
UART_REG(reg8); /* 8 */
UART_REG(reg9); /* 9 */
UART_REG(revid1); /* A */
UART_REG(revid2); /* B */
UART_REG(pwr_mgmt); /* C */
UART_REG(mdr1); /* D */
#else
UART_REG(mdr1); /* 8 */
UART_REG(reg9); /* 9 */
UART_REG(regA); /* A */
UART_REG(regB); /* B */
UART_REG(regC); /* C */
UART_REG(regD); /* D */
UART_REG(regE); /* E */
UART_REG(uasr); /* F */
UART_REG(scr); /* 10*/
UART_REG(ssr); /* 11*/
#endif
#ifdef CONFIG_DM_SERIAL
struct ns16550_platdata* plat;
#endif
};
#define thr rbr
#define iir fcr
#define dll rbr
#define dlm ier
typedef struct NS16550* NS16550_t;
/*
* These are the definitions for the FIFO Control Register
*/
#define UART_FCR_FIFO_EN 0x01 /* Fifo enable */
#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
#define UART_FCR_RXSR 0x02 /* Receiver soft reset */
#define UART_FCR_TXSR 0x04 /* Transmitter soft reset */
/* Ingenic JZ47xx specific UART-enable bit. */
#define UART_FCR_UME 0x10
/* Clear & enable FIFOs */
#define UART_FCR_DEFVAL (UART_FCR_FIFO_EN | UART_FCR_RXSR | UART_FCR_TXSR)
/*
* These are the definitions for the Modem Control Register
*/
#define UART_MCR_DTR 0x01 /* DTR */
#define UART_MCR_RTS 0x02 /* RTS */
#define UART_MCR_OUT1 0x04 /* Out 1 */
#define UART_MCR_OUT2 0x08 /* Out 2 */
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS */
#define UART_MCR_DMA_EN 0x04
#define UART_MCR_TX_DFR 0x08
/*
* These are the definitions for the Line Control Register
*
* Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
* UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
*/
#define UART_LCR_WLS_MSK 0x03 /* character length select mask */
#define UART_LCR_WLS_5 0x00 /* 5 bit character length */
#define UART_LCR_WLS_6 0x01 /* 6 bit character length */
#define UART_LCR_WLS_7 0x02 /* 7 bit character length */
#define UART_LCR_WLS_8 0x03 /* 8 bit character length */
#define UART_LCR_STB 0x04 /* # stop Bits, off=1, on=1.5 or 2) */
#define UART_LCR_PEN 0x08 /* Parity eneble */
#define UART_LCR_EPS 0x10 /* Even Parity Select */
#define UART_LCR_STKP 0x20 /* Stick Parity */
#define UART_LCR_SBRK 0x40 /* Set Break */
#define UART_LCR_BKSE 0x80 /* Bank select enable */
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
/*
* These are the definitions for the Line Status Register
*/
#define UART_LSR_DR 0x01 /* Data ready */
#define UART_LSR_OE 0x02 /* Overrun */
#define UART_LSR_PE 0x04 /* Parity error */
#define UART_LSR_FE 0x08 /* Framing error */
#define UART_LSR_BI 0x10 /* Break */
#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
#define UART_LSR_TEMT 0x40 /* Xmitter empty */
#define UART_LSR_ERR 0x80 /* Error */
#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
#define UART_MSR_RI 0x40 /* Ring Indicator */
#define UART_MSR_DSR 0x20 /* Data Set Ready */
#define UART_MSR_CTS 0x10 /* Clear to Send */
#define UART_MSR_DDCD 0x08 /* Delta DCD */
#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
#define UART_MSR_DDSR 0x02 /* Delta DSR */
#define UART_MSR_DCTS 0x01 /* Delta CTS */
/*
* These are the definitions for the Interrupt Identification Register
*/
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
/*
* These are the definitions for the Interrupt Enable Register
*/
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
/* useful defaults for LCR */
#define UART_LCR_8N1 0x03
void NS16550_init(NS16550_t com_port, int baud_divisor);
void NS16550_putc(NS16550_t com_port, char c);
char NS16550_getc(NS16550_t com_port);
int NS16550_tstc(NS16550_t com_port);
void NS16550_reinit(NS16550_t com_port, int baud_divisor);
void _debug_uart_init(void);
void _debug_uart_putc(int ch);
int _debug_uart_getc(void);

View File

@ -0,0 +1,103 @@
/*
* COM1 NS16550 support
* originally from linux source (arch/powerpc/boot/ns16550.c)
* modified to use CONFIG_SYS_ISA_MEM and new defines
*/
#include <stdint.h>
#include "mmio_access.h"
#include "ns16550.h"
#define UART_ADDR MMIO_P2V_WO(0xFE660000)
// #define UART_ADDR (0xFE660000)
#define UART_LCRVAL UART_LCR_8N1 /* 8 data, 1 stop, no parity */
#define UART_MCRVAL (UART_MCR_DTR | UART_MCR_RTS) /* RTS/DTR */
#define out_le32(a, v) (*(volatile uint32_t*)(a) = (v))
#define in_le32(a) (*(volatile uint32_t*)(a))
#ifndef CONFIG_SYS_NS16550_IER
#define CONFIG_SYS_NS16550_IER 0x00
#endif /* CONFIG_SYS_NS16550_IER */
#define serial_dout(reg, value) \
serial_out_shift((char*)com_port + ((char*)reg - (char*)com_port) * (1 << 2), \
2, value)
#define serial_din(reg) \
serial_in_shift((char*)com_port + ((char*)reg - (char*)com_port) * (1 << 2), \
2)
static inline void serial_out_shift(void* addr, int shift, int value)
{
out_le32(addr, value);
}
static inline int serial_in_shift(void* addr, int shift)
{
return in_le32(addr);
}
#ifndef CONFIG_SYS_NS16550_CLK
#define CONFIG_SYS_NS16550_CLK 0
#endif
#define DIV_ROUND_CLOSEST(x, divisor) ( \
{ \
typeof(x) __x = x; \
typeof(divisor) __d = divisor; \
(((typeof(x))-1) > 0 || ((typeof(divisor))-1) > 0 || (__x) > 0) ? (((__x) + ((__d) / 2)) / (__d)) : (((__x) - ((__d) / 2)) / (__d)); \
})
int ns16550_calc_divisor(NS16550_t port, int clock, int baudrate)
{
const unsigned int mode_x_div = 16;
return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
}
void _debug_uart_init(void)
{
struct NS16550* com_port = (struct NS16550*)UART_ADDR;
/*
* We copy the code from above because it is already horribly messy.
* Trying to refactor to nicely remove the duplication doesn't seem
* feasible. The better fix is to move all users of this driver to
* driver model.
*/
int baud_divisor = ns16550_calc_divisor(com_port, 24000000,
1500000);
serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
serial_dout(&com_port->mcr, UART_MCRVAL);
serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
serial_dout(&com_port->dll, baud_divisor & 0xff);
serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
serial_dout(&com_port->lcr, UART_LCRVAL);
}
void _debug_uart_putc(int ch)
{
static struct NS16550* com_port = (struct NS16550*)UART_ADDR;
if (ch == '\n') {
_debug_uart_putc('\r');
}
while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
;
serial_dout(&com_port->thr, ch);
}
int _debug_uart_getc(void)
{
static struct NS16550* com_port = (struct NS16550*)UART_ADDR;
while (!(serial_din(&com_port->lsr) & UART_LSR_DR))
;
return serial_din(&com_port->rbr);
}

View File

@ -0,0 +1,45 @@
//
// low-level driver routines for pl011 UART.
//
#include "uart.h"
#include "actracer.h"
#include "ns16550.h"
#include "uart_common_ope.h"
// the UART control registers are memory-mapped
// at address UART0. this macro returns the
// address of one of the registers.
void uartinit(void)
{
_debug_uart_init();
}
void uartputc(uint8_t c)
{
_debug_uart_putc((int)c);
}
static uint8_t uartgetc(void)
{
return (uint8_t)_debug_uart_getc();
}
static uint32_t UartGetIrqnum()
{
return 0;
}
static struct XiziSerialDriver hardkernel_serial_driver = {
.sys_serial_init = uartinit,
.get_serial_irqnum = UartGetIrqnum,
.putc = uartputc,
.getc = uartgetc,
};
struct XiziSerialDriver* hardkernel_uart_init(struct TraceTag* hardkernel_tag)
{
hardkernel_serial_driver.sys_serial_init();
return &hardkernel_serial_driver;
}

View File

@ -1,128 +0,0 @@
//
// low-level driver routines for pl011 UART.
//
#include "uart.h"
#include "actracer.h"
#include "uart_common_ope.h"
// the UART control registers are memory-mapped
// at address UART0. this macro returns the
// address of one of the registers.
// the transmit output buffer.
#define UART_TX_BUF_SIZE 32
static char uart_tx_buf[UART_TX_BUF_SIZE];
uint64_t uart_tx_w; // write next to uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE]
uint64_t uart_tx_r; // read next from uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE]
void uartinit(void)
{
// disable uart
UART_WRITE_REG(CR, 0);
// disable interrupts.
UART_WRITE_REG(IMSC, 0);
// in qemu, it is not necessary to set baudrate.
// enable FIFOs.
// set word length to 8 bits, no parity.
UART_WRITE_REG(LCRH, LCRH_FEN | LCRH_WLEN_8BIT);
// enable RXE, TXE and enable uart.
UART_WRITE_REG(CR, 0x301);
// enable transmit and receive interrupts.
UART_WRITE_REG(IMSC, INT_RX_ENABLE | INT_TX_ENABLE);
}
// if the UART is idle, and a character is waiting
// in the transmit buffer, send it.
// caller must hold uart_tx_lock.
// called from both the top- and bottom-half.
void uartstart()
{
while (1) {
if (uart_tx_w == uart_tx_r) {
// transmit buffer is empty.
return;
}
if (UART_READ_REG(FR) & FR_TXFF) {
// the UART transmit holding register is full,
// so we cannot give it another byte.
// it will interrupt when it's ready for a new byte.
return;
}
int c = uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE];
uart_tx_r += 1;
// maybe uartputc() is waiting for space in the buffer.
UART_WRITE_REG(DR, c);
}
}
// add a character to the output buffer and tell the
// UART to start sending if it isn't already.
// blocks if the output buffer is full.
// because it may block, it can't be called
// from interrupts; it's only suitable for use
// by write().
void uartputc(uint8_t c)
{
while (uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE)
;
uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c;
uart_tx_w += 1;
uartstart();
return;
}
// read one input character from the UART.
// return -1 if none is waiting.
static uint8_t uartgetc(void)
{
if (UART_READ_REG(FR) & FR_RXFE)
return 0xFF;
else
return UART_READ_REG(DR);
}
// handle a uart interrupt, raised because input has
// arrived, or the uart is ready for more output, or
// both. called from trap.c.
void uartintr(void)
{
// read and process incoming characters.
while (1) {
int c = uartgetc();
if (c == 0xFF)
break;
}
// send buffered characters.
uartstart();
// clear transmit and receive interrupts.
UART_WRITE_REG(ICR, INT_RX_ENABLE | INT_TX_ENABLE);
}
static uint32_t UartGetIrqnum()
{
return 0;
}
static struct XiziSerialDriver hardkernel_serial_driver = {
.sys_serial_init = uartinit,
.get_serial_irqnum = UartGetIrqnum,
.putc = uartputc,
.getc = uartgetc,
};
struct XiziSerialDriver* hardkernel_uart_init(struct TraceTag* hardkernel_tag)
{
hardkernel_serial_driver.sys_serial_init();
return &hardkernel_serial_driver;
}

View File

@ -41,15 +41,16 @@ static void tracer_init_node(TracerNode* node, char* name, tracemeta_ac_type typ
node->parent = NULL;
if (name != NULL) {
char* p_name = (char*)slab_alloc(&sys_tracer.node_name_allocator);
if (!p_name) {
p_name = "BAD_NAME(NOMEM)";
} else {
strcpy(p_name, name);
p_name[TRACER_NODE_NAME_LEN - 1] = '\0';
node->name = p_name;
}
if (node->type == TRACER_OWNER) {
doubleListNodeInit(&node->children_guard);
} else {
node->p_resource = p_resource;
}
doubleListNodeInit(&node->children_guard);
node->p_resource = p_resource;
doubleListNodeInit(&node->list_node);
}
@ -61,8 +62,8 @@ void sys_tracer_init()
sys_tracer.sys_tracer_tag.meta = &sys_tracer.root_node;
// init memory allocator
slab_init(&sys_tracer.node_allocator, sizeof(TracerNode));
slab_init(&sys_tracer.node_name_allocator, sizeof(char[TRACER_NODE_NAME_LEN]));
slab_init(&sys_tracer.node_allocator, sizeof(TracerNode), "TracerNodeAllocator");
slab_init(&sys_tracer.node_name_allocator, sizeof(char[TRACER_NODE_NAME_LEN]), "TracerNodeNameAllocator");
}
static char* parse_path(char* path, char* const name)
@ -84,7 +85,7 @@ static char* parse_path(char* path, char* const name)
// handle current name
int len = path - cur_start;
if (len >= TRACER_NODE_NAME_LEN) {
strncpy(name, cur_start, TRACER_NODE_NAME_LEN);
strncpy(name, cur_start, TRACER_NODE_NAME_LEN - 1);
name[TRACER_NODE_NAME_LEN - 1] = '\0';
} else {
strncpy(name, cur_start, len);
@ -147,13 +148,14 @@ void* AchieveResource(TraceTag* tag)
bool CreateResourceTag(TraceTag* new_tag, TraceTag* owner, char* name, tracemeta_ac_type type, void* p_resource)
{
assert(new_tag != NULL && owner != NULL);
assert(owner != NULL);
if (owner->meta == NULL) {
ERROR("Tracer: Empty owner\n");
ERROR("Tracer: Empty owner, node name: %s\n", name);
return false;
}
assert(owner->meta->type == TRACER_OWNER);
if (tracer_find_node_onestep(owner->meta, name) != NULL) {
// assert(owner->meta->type == TRACER_OWNER);
if (type == TRACER_SERVER_IDENTITY_AC_RESOURCE && //
tracer_find_node_onestep(owner->meta, name) != NULL) {
return false;
}
@ -168,7 +170,9 @@ bool CreateResourceTag(TraceTag* new_tag, TraceTag* owner, char* name, tracemeta
doubleListAddOnHead(&new_node->list_node, &owner->meta->children_guard);
new_node->parent = owner->meta;
if (new_tag != NULL) {
new_tag->meta = new_node;
}
return true;
}
@ -177,7 +181,7 @@ bool DeleteResource(TraceTag* target, TraceTag* owner)
assert(target != NULL && owner != NULL);
assert(owner->meta != NULL && owner->meta->type == TRACER_OWNER);
if (target->meta == NULL) {
ERROR("Tracer: Delete a empty resource\n");
ERROR("Tracer: Delete a empty resource, owner: %s\n", owner->meta->name);
return false;
}
@ -187,12 +191,52 @@ bool DeleteResource(TraceTag* target, TraceTag* owner)
if (target->meta->name != NULL) {
slab_free(&sys_tracer.node_name_allocator, target->meta->name);
}
// delete all children
/// @attention currently donot allow multilevel resource deletion
if (target->meta->type == TRACER_OWNER) {
assert(IS_DOUBLE_LIST_EMPTY(&target->meta->children_guard));
while (!IS_DOUBLE_LIST_EMPTY(&target->meta->children_guard)) {
TraceTag tmp_node = {
.meta = DOUBLE_LIST_ENTRY(target->meta->children_guard.next, TracerNode, list_node),
};
DeleteResource(&tmp_node, target);
}
}
slab_free(&sys_tracer.node_allocator, target->meta);
target->meta = NULL;
return true;
}
#define debug_print_blanks(n) \
for (int __i = 0; __i < n; __i++) { \
DEBUG_PRINTF(" "); \
}
void debug_list_tracetree_inner(TracerNode* cur_node, int nr_blanks)
{
debug_print_blanks(nr_blanks);
if (cur_node->name == NULL) {
DEBUG_PRINTF("[ANON %d] ", cur_node->type);
} else {
DEBUG_PRINTF("[%s %d] ", cur_node->name, cur_node->type);
}
TracerNode* tmp = NULL;
DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node)
{
if (tmp->name != NULL) {
DEBUG_PRINTF("%s ", tmp->name);
} else {
DEBUG_PRINTF("ANON ");
}
}
DEBUG_PRINTF("\n");
DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node)
{
debug_list_tracetree_inner(tmp, nr_blanks + 1);
}
}
void debug_list_tracetree()
{
TracerNode* ref_root = RequireRootTag()->meta;
debug_list_tracetree_inner(ref_root, 0);
}

View File

@ -30,35 +30,12 @@ Modification:
#include <stdbool.h>
#include <stdint.h>
#include "list.h"
#include "actracer_tag.h"
#include "object_allocator.h"
#define TRACER_NODE_NAME_LEN 32
typedef enum {
TRACER_INVALID = 0,
TRACER_OWNER,
TRACER_HARDKERNEL_AC_RESOURCE,
TRACER_TASK_DESCRIPTOR_AC_RESOURCE,
TRACER_SERVER_IDENTITY_AC_RESOURCE,
TRACER_MEM_FROM_BUDDY_AC_RESOURCE,
} tracemeta_ac_type;
typedef struct TracerNode {
tracemeta_ac_type type;
char* name;
union {
struct double_list_node children_guard;
void* p_resource;
};
struct TracerNode* parent;
struct double_list_node list_node;
} TracerNode;
/// @brief tag for other module to reference trace meta
typedef struct TraceTag {
TracerNode* meta;
} TraceTag;
#define GetSysObject(type, target_tag) (type*)AchieveResource(target_tag)
struct SysTracer {
TracerNode root_node;
@ -73,3 +50,5 @@ bool AchieveResourceTag(struct TraceTag* target, struct TraceTag* owner, char* n
void* AchieveResource(struct TraceTag* tag);
bool CreateResourceTag(struct TraceTag* new_tag, struct TraceTag* owner, char* name, tracemeta_ac_type type, void* p_resource);
bool DeleteResource(struct TraceTag* target, struct TraceTag* owner);
void debug_list_tracetree();

View File

@ -0,0 +1,26 @@
#pragma once
#include "list.h"
typedef enum {
TRACER_INVALID = 0,
TRACER_OWNER,
TRACER_HARDKERNEL_AC_RESOURCE,
TRACER_TASK_DESCRIPTOR_AC_RESOURCE,
TRACER_SERVER_IDENTITY_AC_RESOURCE,
TRACER_MEM_SIGNATURE,
TRACER_SYSOBJECT,
} tracemeta_ac_type;
typedef struct TracerNode {
tracemeta_ac_type type;
char* name;
void* p_resource;
struct TracerNode* parent;
struct double_list_node list_node;
struct double_list_node children_guard;
} TracerNode;
/// @brief tag for other module to reference trace meta
typedef struct TraceTag {
TracerNode* meta;
} TraceTag;

View File

@ -38,20 +38,20 @@ KERNELPATHS += \
-I$(KERNEL_ROOT)/hardkernel/cache/L2/pl310/
endif
ifeq ($(BOARD), ok1028a-c)
ifeq ($(BOARD), 3568)
KERNELPATHS += \
-I$(KERNEL_ROOT)/hardkernel/clock/arm/armv8-a/cortex-a72/$(BOARD)/include \
-I$(KERNEL_ROOT)/hardkernel/arch/arm/armv8-a/cortex-a72/preboot_for_$(BOARD)/include \
-I$(KERNEL_ROOT)/hardkernel/arch/arm/armv8-a/cortex-a72/ \
-I$(KERNEL_ROOT)/hardkernel/mmu/arm/armv8-a/cortex-a72/$(BOARD) \
-I$(KERNEL_ROOT)/hardkernel/mmu/arm/armv8-a/cortex-a72/include \
-I$(KERNEL_ROOT)/hardkernel/clock/arm/armv8-a/cortex-a72/include \
-I$(KERNEL_ROOT)/hardkernel/intr/arm/armv8-a/cortex-a72/ \
-I$(KERNEL_ROOT)/hardkernel/intr/arm/armv8-a/cortex-a72/$(BOARD) \
-I$(KERNEL_ROOT)/hardkernel/intr/arm/armv8-a/cortex-a72/gicv3 \
-I$(KERNEL_ROOT)/hardkernel/uart/arm/armv8-a/cortex-a72/uart_io_for_$(BOARD)/include \
-I$(KERNEL_ROOT)/hardkernel/uart/arm/armv8-a/cortex-a72/ \
-I$(KERNEL_ROOT)/hardkernel/cache/L1/arm/cortex-a72/
-I$(KERNEL_ROOT)/hardkernel/clock/arm/armv8-a/cortex-a55/$(BOARD)/include \
-I$(KERNEL_ROOT)/hardkernel/arch/arm/armv8-a/cortex-a55/preboot_for_$(BOARD)/include \
-I$(KERNEL_ROOT)/hardkernel/arch/arm/armv8-a/cortex-a55/ \
-I$(KERNEL_ROOT)/hardkernel/mmu/arm/armv8-a/cortex-a55/$(BOARD) \
-I$(KERNEL_ROOT)/hardkernel/mmu/arm/armv8-a/cortex-a55/include \
-I$(KERNEL_ROOT)/hardkernel/clock/arm/armv8-a/cortex-a55/include \
-I$(KERNEL_ROOT)/hardkernel/intr/arm/armv8-a/cortex-a55/ \
-I$(KERNEL_ROOT)/hardkernel/intr/arm/armv8-a/cortex-a55/$(BOARD) \
-I$(KERNEL_ROOT)/hardkernel/intr/arm/armv8-a/cortex-a55/gicv3 \
-I$(KERNEL_ROOT)/hardkernel/uart/arm/armv8-a/cortex-a55/uart_io_for_$(BOARD)/include \
-I$(KERNEL_ROOT)/hardkernel/uart/arm/armv8-a/cortex-a55/ \
-I$(KERNEL_ROOT)/hardkernel/cache/L1/arm/cortex-a55/
endif
KERNELPATHS += \

View File

@ -1,4 +1,5 @@
SRC_DIR := fs shell lib boards semaphore drivers tools app
SRC_DIR := fs shell lib boards drivers semaphore tools app
include $(KERNEL_ROOT)/compiler.mk

View File

@ -10,10 +10,10 @@ cflags = -std=c11 -O2 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -
board_specs = stub.o
#cflags = -Wall -g -std=c11
endif
ifeq ($(BOARD), ok1028a-c)
ifeq ($(BOARD), 3568)
toolchain ?= aarch64-none-elf-
user_ldflags = -N -Ttext 0
cflags = -Wall -g -std=c11 -mtune=cortex-a72 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
cflags = -Wall -O2 -std=c11 -mtune=cortex-a55 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
board_specs = stub.o
endif
@ -28,14 +28,34 @@ INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \
-I$(KERNEL_ROOT)/services/lib/serial \
-I$(KERNEL_ROOT)/services/lib/usyscall \
-I$(KERNEL_ROOT)/services/fs/libfs \
-I$(KERNEL_ROOT)/services/net/libnet \
-I$(KERNEL_ROOT)/services/net/net_server \
-I$(KERNEL_ROOT)/services/net/net_server/arch \
-I$(KERNEL_ROOT)/services/net/net_server/include \
-I$(KERNEL_ROOT)/services/net/net_server/include/lwip \
-I$(KERNEL_ROOT)/services/net/net_server/include/lwip/apps \
-I$(KERNEL_ROOT)/services/net/net_server/include/lwip/priv \
-I$(KERNEL_ROOT)/services/net/net_server/include/lwip/prot \
-I$(KERNEL_ROOT)/services/net/net_server/include/netif \
-I$(KERNEL_ROOT)/services/net/net_server/include/compat \
-I$(KERNEL_ROOT)/services/semaphore \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/app
ifeq ($(BOARD), imx6q-sabrelite)
all: init test_fault simple_client simple_server shell fs_server semaphore_server test_semaphore test_ipc_null test_thread test_irq_hdlr test_irq_block test_irq_send eth_driver epit_server readme.txt | bin
all: pingpong_client pingpong_server \
test_fault simple_client simple_server \
shell fs_server semaphore_server \
test_sleep test_semaphore test_ipc_null test_thread test_irq_hdlr test_irq_block test_irq_send \
eth_driver epit_server readme.txt | bin
else
all: init test_fault simple_client simple_server shell fs_server semaphore_server test_ipc_null test_thread test_semaphore readme.txt | bin
all: pingpong_client pingpong_server \
test_fault simple_client simple_server \
shell fs_server semaphore_server \
test_irq_hdlr \
test_sleep test_ipc_null test_thread test_semaphore readme.txt \
test_context_user \
| bin
endif
../tools/mkfs/mkfs ./fs.img $^
@mv $(filter-out readme.txt, $^) bin
@ -59,6 +79,22 @@ epit_server: timer.o epit.o ccm_pll.o usyscall.o arch_usyscall.o libserial.o pri
@${objdump} -S $@ > $@.asm
endif
pingpong_client: pingpong_service.o pingpong_client.o libserial.o printf.o libipc.o session.o libfs.o usyscall.o arch_usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
pingpong_server: pingpong_service.o pingpong_server.o libserial.o printf.o libipc.o session.o libfs.o usyscall.o arch_usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
test_sleep: test_sleep.o libserial.o printf.o usyscall.o arch_usyscall.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
test_context_user: test_context_user.o libserial.o printf.o usyscall.o arch_usyscall.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
test_semaphore: test_semaphore.o libserial.o printf.o usyscall.o arch_usyscall.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
@ -87,10 +123,6 @@ shell: shell_port.o libserial.o printf.o shell_cmd_list.o shell.o shell_ext.o li
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
init: init.o libfs.o libipc.o session.o libserial.o printf.o usyscall.o arch_usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
test_fault: test_fault.o libserial.o printf.o usyscall.o arch_usyscall.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
@ -111,6 +143,10 @@ test_priority: test_priority.o libserial.o printf.o usyscall.o arch_usyscall.o l
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
@${objdump} -S $@ > $@.asm
test_net: test_net.o lwip_service.o libipc.o session.o libserial.o printf.o usyscall.o arch_usyscall.o libmem.o
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} -llwip -L$(KERNEL_ROOT)/services/net/net_server
@${objdump} -S $@ > $@.asm
%.o: %.c
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $<

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include "libfs.h"
#include "libserial.h"
#include "pingpong_service.h"
#include "usyscall.h"
int string_to_integer(const char* str)
{
assert(str);
while (*str == ' ') {
str++;
}
int is_positive = 1; // 默认是正
if (*str - '+' == 0) {
is_positive = 1;
str++;
}
if (*str - '-' == 0) {
is_positive = 0;
str++;
}
long long result = 0; // int可能存不下 改为long long较为合适虽然返回值会丢失精度但感觉不要紧
while ('0' <= *str && *str <= '9') {
result *= 10;
result += *str - '0'; // 如'1' ascii的值为 49 '0'的ascii的值为48 相减得到1
if (result > INT32_MAX || result < INT32_MIN) // 可能出现的溢出问题
{
return result > INT32_MAX ? INT32_MAX : INT32_MIN;
}
str++;
}
return is_positive ? (result) : -result;
}
void itoa(int num, char* str, int radix)
{
int i = 0;
int sum;
unsigned int num1 = num; // 如果是负数求补码,必须将他的绝对值放在无符号位中在进行求反码
char str1[33] = { 0 };
if (num < 0) { // 求出负数的补码
num = -num;
num1 = ~num;
num1 += 1;
}
if (num == 0) {
str1[i] = '0';
i++;
}
while (num1 != 0) { // 进行进制运算
sum = num1 % radix;
str1[i] = (sum > 9) ? (sum - 10) + 'a' : sum + '0';
num1 = num1 / radix;
i++;
}
i--;
int j = 0;
for (i; i >= 0; i--) { // 逆序输出
str[i] = str1[j];
j++;
}
}
uintptr_t pingpong_sample(struct Session* session, int times)
{
char* msg = "hello";
uintptr_t tick1 = sys_test();
for (int i = 0; i < times; i++) {
uintptr_t tmp = sys_test();
}
uintptr_t tick2 = sys_test();
uintptr_t time = (tick2 - tick1) / 24;
// printf("Sync Tick Cost: %lu\n", time);
return time;
}
uintptr_t pingpong_test_sync(struct Session* session, int times)
{
char* msg = "hello";
uintptr_t tick1 = sys_test();
for (int i = 0; i < times; i++) {
pingpong(session, msg);
}
uintptr_t tick2 = sys_test();
uintptr_t time = (tick2 - tick1) / 24;
// printf("Sync Tick Cost: %lu\n", time);
return time;
}
uintptr_t pingpong_test_async(struct Session* session, int times)
{
char* msg = "hello";
uintptr_t tick1 = sys_test();
for (int i = 0; i < times; i++) {
pingpong_nowait(session, msg);
}
for (int i = 0; i < times; i++) {
ipc_session_wait(session);
ipc_session_forward(session);
}
uintptr_t tick2 = sys_test();
uintptr_t time = (tick2 - tick1) / 24;
// printf("ASync Tick Cost: %lu\n", (tick2 - tick1) / 24);
return time;
}
int main(int argc, char** argv)
{
int times = 0;
if (argc >= 2) {
times = string_to_integer(argv[1]);
}
struct Session session;
if (connect_session(&session, "PingPongServer", 81920) < 0) {
printf("connect session failed\n");
exit(1);
}
printf("============ PingPong Test start ==============\n");
uintptr_t loop = 50;
uintptr_t t1 = 0, t2 = 0, t0 = 0;
for (uintptr_t i = 0; i < loop; i++) {
t0 += pingpong_sample(&session, times);
t1 += pingpong_test_sync(&session, times);
t2 += pingpong_test_async(&session, times);
}
printf("Compare Tick Cost: %lu\n", t0 / loop);
printf("Sync Tick Cost: %lu\n", t1 / loop);
printf("ASync Tick Cost: %lu\n", t2 / loop);
printf("============= PingPong Test End ===============\n");
exit(0);
}

View File

@ -9,34 +9,31 @@
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
// init: The initial user-level program
#include <stdbool.h>
#include "libfs.h"
#include "libserial.h"
#include "pingpong_service.h"
#include "usyscall.h"
/// @warning all the parameters should in the form of pointers
/// for the true storing memory of parameters is session(shared memory between tasks)
int IPC_DO_SERVE_FUNC(Ipc_pingpong)(char* str)
{
return 0;
}
IPC_SERVER_INTERFACE(Ipc_pingpong, 1);
IPC_SERVER_REGISTER_INTERFACES(IpcPingPongServer, 1, Ipc_pingpong);
int main(int argc, char* argv[])
{
struct Session session;
printf("init: connecting MemFS\n");
while (connect_session(&session, "MemFS", 8092) < 0)
;
printf("init: connect MemFS success\n");
int fd;
char* shell_task_param[2] = { "/shell", 0 };
if ((fd = open(&session, shell_task_param[0])) < 0) {
printf("Open %s failed\n", shell_task_param[0]);
if (register_server("PingPongServer") < 0) {
printf("register server name: %s failed.\n", "PingPong");
exit(1);
}
ipc_server_loop(&IpcPingPongServer);
if (spawn(&session, fd, read, fsize, shell_task_param[0], shell_task_param) < 0) {
printf("Syscall Spawn shell failed\n");
}
close(&session, fd);
// never reached
exit(0);
return 0;
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "pingpong_service.h"
IPC_INTERFACE(Ipc_pingpong, 1, str, strlen(str));
int pingpong(struct Session* session, char* str)
{
return IPC_CALL(Ipc_pingpong)(session, str);
}
void pingpong_nowait(struct Session* session, char* str)
{
struct IpcMsg* msg = IPC_CREATE_MSG_FUNC(Ipc_pingpong)(session, str);
ipc_msg_set_nth_arg(msg, 0, str, strlen(str));
ipc_msg_set_opcode(msg, Ipc_pingpong);
ipc_msg_send_nowait(msg);
}

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include <stdbool.h>
#include <string.h>
#include "libipc.h"
IPC_SERVICES(IpcPingPongServer, Ipc_pingpong);
int pingpong(struct Session* session, char* str);
void pingpong_nowait(struct Session* session, char* str);

View File

@ -50,7 +50,7 @@ int main(void)
shellInit(&shell, shellBuffer, 512);
while (connect_session(&session_fs, "MemFS", 8092) < 0)
while (connect_session(&session_fs, "MemFS", 0x10000) < 0)
;
if (!session_fs.buf) {
printf("session connect faield\n");

View File

@ -108,7 +108,7 @@ int main(int argc, char** argv)
struct Session fs_session;
static char id_buf[33] = { 0 };
if (id > 1) {
if (connect_session(&fs_session, "MemFS", 8192) < 0) {
if (connect_session(&fs_session, "MemFS", 0x4000) < 0) {
printf("connect fs_session failed\n");
} else {
int fd;

View File

@ -30,8 +30,7 @@ int IPC_DO_SERVE_FUNC(Ipc_hello_string)(char* buf, int* len)
return 0;
}
// IPC_SERVER_INTERFACE(Ipc_add, 2);
IPC_SERVER_THREAD_INTERFACE(Ipc_add, 2);
IPC_SERVER_INTERFACE(Ipc_add, 2);
IPC_SERVER_INTERFACE(Ipc_hello_string, 2);
IPC_SERVER_REGISTER_INTERFACES(IpcSimpleServer, 2, Ipc_hello_string, Ipc_add);

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "libserial.h"
#include "usyscall.h"
static inline uintptr_t arch_curr_tick()
{
uint64_t x;
__asm__ volatile("mrs %0, cntpct_el0" : "=r"(x));
return x;
}
int main(int argc, char* argv[])
{
uintptr_t loop = 1000;
uintptr_t tick_total = 0;
for (uintptr_t i = 0; i < loop; i++) {
uintptr_t tick_1 = sys_test();
uintptr_t tick_2 = sys_test();
// printf("TICK before: %lu\n", tick_1);
// printf("TICK after: %lu\n", tick_2);
// printf("TICK diff: %lu\n", tick_2 - tick_1);
tick_total += tick_2 - tick_1;
}
printf("TICK DIFF: %lu\n", tick_total / loop);
printf("TEST TICK: %lu\n", arch_curr_tick());
exit(0);
return 0;
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
// test_net: Test the lwip network stack
#include "libserial.h"
#include "lwip_service.h"
#include "usyscall.h"
static char udp_ip_str[128] = {0};
static uint16_t udp_socket_port = 8888;
#define UDP_DEMO_SEND_TIMES 3
int main(int argc, char* argv[])
{
printf("lwip network stack test \n");
int cnt = UDP_DEMO_SEND_TIMES;
char send_str[128];
int fd = -1;
memset(send_str, 0, sizeof(send_str));
struct Session sess;
connect_session(&sess, "LWIPServer", 4096);
printf("%s %d\n", __func__, __LINE__);
fd = ipc_socket(&sess, AF_INET, SOCK_DGRAM, 0);
if(fd < 0) {
printf("Socket error\n");
return 0;
}
printf("%s %d\n", __func__, __LINE__);
struct sockaddr_in udp_sock;
udp_sock.sin_family = AF_INET;
udp_sock.sin_port = htons(udp_socket_port);
udp_sock.sin_addr.s_addr = inet_addr(udp_ip_str);
memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero));
printf("%s %d\n", __func__, __LINE__);
if(ipc_connect(&sess, fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr)) < 0) {
printf("Unable to connect %s:%d\n", udp_ip_str, udp_socket_port);
ipc_close(&sess,fd);
return 0;
}
printf("%s %d\n", __func__, __LINE__);
printf("UDP connect %s:%d success, start to send.\n",
udp_ip_str,
udp_socket_port);
while(cnt --) {
snprintf(send_str, sizeof(send_str), "UDP test package times %d\r\n", cnt);
ipc_send(&sess, fd, send_str, strlen(send_str), 0);
printf("Send UDP msg: %s ", send_str);
}
ipc_close(&sess,fd);
free_session(&sess);
exit(0);
return 0;
}

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "libserial.h"
#include "usyscall.h"
int main(int argc, char* argv[])
{
while (true) {
printf("sleep for 2 seconds\n");
sleep(2000);
}
exit(0);
}

View File

@ -25,15 +25,9 @@ int sub_thread_entry(int argc, char** argv)
global_value++;
}
/// @warning session is single threaded, so that each thread cannot share a common session.
// sub thread connect to semaphore server
struct Session sem_session;
while (connect_session(&sem_session, sem_server_name, 4096) < 0) {
yield(SYS_TASK_YIELD_NO_REASON);
}
printf("Thread signal sem.\n");
sem_signal(&sem_session, &sem);
semaphore_signal(sem);
exit(0);
return 0;
@ -45,39 +39,8 @@ int main(int argc, char** argv)
global_value = 0;
printf("Test Create Semaphore.\n");
struct Session sem_session;
bool spawn_sem_server = false;
while (connect_session(&sem_session, sem_server_name, 4096) < 0) {
if (!spawn_sem_server) {
struct Session fs_session;
printf("Connect FS.\n");
if (connect_session(&fs_session, "MemFS", 8192) < 0) {
printf("Connect FS failed.\n");
exit(1);
}
printf("Loading semaphore server.\n");
int fd = -1;
if ((fd = open(&fs_session, sem_file_name)) < 0) {
printf("Open %s failed.\n", sem_file_name);
free_session(&fs_session);
exit(1);
}
printf("Spawn semaphore server.\n");
char* sem_server_params[] = { sem_server_name, sem_server_name, NULL };
if (spawn(&fs_session, fd, read, fsize, sem_server_name, sem_server_params) < 0) {
printf("Spawn %s failed.\n", sem_file_name);
free_session(&fs_session);
exit(1);
}
spawn_sem_server = true;
free_session(&fs_session);
}
}
printf("Create new sem.\n");
sem_create(&sem_session, &sem, 0);
sem = semaphore_new(0);
printf("Create new thread.\n");
char* task_param[2] = { "add_gval", NULL };
@ -91,12 +54,11 @@ int main(int argc, char** argv)
printf("Main thread waiting for sem for %d times.\n", nr_thread);
for (int i = 0; i < nr_thread; i++) {
int sem_wait_ret = sem_wait(&sem_session, &sem, 0);
int sem_wait_ret = semaphore_wait(sem);
}
printf("Main thread sem %d wait return, global val: %d.\n", sem, global_value);
sem_delete(&sem_session, &sem);
free_session(&sem_session);
semaphore_free(sem);
exit(0);
return 0;
}

View File

@ -8,10 +8,10 @@ toolchain ?= arm-xilinx-eabi-
user_ldflags = -N -Ttext 0
cflags = -march=armv7-a -std=c11 -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
endif
ifeq ($(BOARD), ok1028a-c)
ifeq ($(BOARD), 3568)
toolchain ?= aarch64-none-elf-
user_ldflags = -N -Ttext 0
cflags = -Wall -g -std=c11 -mtune=cortex-a72 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
cflags = -Wall -O0 -g -std=c11 -mtune=cortex-a55 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
endif
cc = ${toolchain}gcc

View File

@ -31,3 +31,24 @@ int syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4)
return ret;
}
uintptr_t syscall_ori(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4)
{
uintptr_t ret = -1;
__asm__ volatile(
"mov x0, %1;\
mov x1, %2;\
mov x2, %3;\
mov x3, %4;\
mov x4, %5;\
svc #0;\
dsb ish;\
isb;\
mov %0, x0"
: "=r"(ret)
: "r"(sys_num), "r"(a1), "r"(a2), "r"(a3), "r"(a4)
: "memory", "r0", "r1", "r2", "r3", "r4");
return ret;
}

View File

@ -0,0 +1,250 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/// this file is only used for debug
#include <stddef.h>
#include <stdint.h>
#include "libserial.h"
#include "usyscall.h"
/*
* For driver model we always use one byte per register, and sort out the
* differences in the driver
*/
#define CONFIG_SYS_NS16550_REG_SIZE (-1)
#define UART_REG(x) \
unsigned char x; \
unsigned char postpad_##x[-CONFIG_SYS_NS16550_REG_SIZE - 1];
/**
* struct ns16550_platdata - information about a NS16550 port
*
* @base: Base register address
* @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...)
* @clock: UART base clock speed in Hz
*/
struct ns16550_platdata {
unsigned long base;
int reg_shift;
int clock;
int reg_offset;
uint32_t fcr;
};
struct udevice;
struct NS16550 {
UART_REG(rbr); /* 0 */
UART_REG(ier); /* 1 */
UART_REG(fcr); /* 2 */
UART_REG(lcr); /* 3 */
UART_REG(mcr); /* 4 */
UART_REG(lsr); /* 5 */
UART_REG(msr); /* 6 */
UART_REG(spr); /* 7 */
#ifdef CONFIG_SOC_DA8XX
UART_REG(reg8); /* 8 */
UART_REG(reg9); /* 9 */
UART_REG(revid1); /* A */
UART_REG(revid2); /* B */
UART_REG(pwr_mgmt); /* C */
UART_REG(mdr1); /* D */
#else
UART_REG(mdr1); /* 8 */
UART_REG(reg9); /* 9 */
UART_REG(regA); /* A */
UART_REG(regB); /* B */
UART_REG(regC); /* C */
UART_REG(regD); /* D */
UART_REG(regE); /* E */
UART_REG(uasr); /* F */
UART_REG(scr); /* 10*/
UART_REG(ssr); /* 11*/
#endif
#ifdef CONFIG_DM_SERIAL
struct ns16550_platdata* plat;
#endif
};
#define thr rbr
#define iir fcr
#define dll rbr
#define dlm ier
typedef struct NS16550* NS16550_t;
/*
* These are the definitions for the FIFO Control Register
*/
#define UART_FCR_FIFO_EN 0x01 /* Fifo enable */
#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */
#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
#define UART_FCR_RXSR 0x02 /* Receiver soft reset */
#define UART_FCR_TXSR 0x04 /* Transmitter soft reset */
/* Ingenic JZ47xx specific UART-enable bit. */
#define UART_FCR_UME 0x10
/* Clear & enable FIFOs */
#define UART_FCR_DEFVAL (UART_FCR_FIFO_EN | UART_FCR_RXSR | UART_FCR_TXSR)
/*
* These are the definitions for the Modem Control Register
*/
#define UART_MCR_DTR 0x01 /* DTR */
#define UART_MCR_RTS 0x02 /* RTS */
#define UART_MCR_OUT1 0x04 /* Out 1 */
#define UART_MCR_OUT2 0x08 /* Out 2 */
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
#define UART_MCR_AFE 0x20 /* Enable auto-RTS/CTS */
#define UART_MCR_DMA_EN 0x04
#define UART_MCR_TX_DFR 0x08
/*
* These are the definitions for the Line Control Register
*
* Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting
* UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
*/
#define UART_LCR_WLS_MSK 0x03 /* character length select mask */
#define UART_LCR_WLS_5 0x00 /* 5 bit character length */
#define UART_LCR_WLS_6 0x01 /* 6 bit character length */
#define UART_LCR_WLS_7 0x02 /* 7 bit character length */
#define UART_LCR_WLS_8 0x03 /* 8 bit character length */
#define UART_LCR_STB 0x04 /* # stop Bits, off=1, on=1.5 or 2) */
#define UART_LCR_PEN 0x08 /* Parity eneble */
#define UART_LCR_EPS 0x10 /* Even Parity Select */
#define UART_LCR_STKP 0x20 /* Stick Parity */
#define UART_LCR_SBRK 0x40 /* Set Break */
#define UART_LCR_BKSE 0x80 /* Bank select enable */
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
/*
* These are the definitions for the Line Status Register
*/
#define UART_LSR_DR 0x01 /* Data ready */
#define UART_LSR_OE 0x02 /* Overrun */
#define UART_LSR_PE 0x04 /* Parity error */
#define UART_LSR_FE 0x08 /* Framing error */
#define UART_LSR_BI 0x10 /* Break */
#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
#define UART_LSR_TEMT 0x40 /* Xmitter empty */
#define UART_LSR_ERR 0x80 /* Error */
#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
#define UART_MSR_RI 0x40 /* Ring Indicator */
#define UART_MSR_DSR 0x20 /* Data Set Ready */
#define UART_MSR_CTS 0x10 /* Clear to Send */
#define UART_MSR_DDCD 0x08 /* Delta DCD */
#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
#define UART_MSR_DDSR 0x02 /* Delta DSR */
#define UART_MSR_DCTS 0x01 /* Delta CTS */
/*
* These are the definitions for the Interrupt Identification Register
*/
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
/*
* These are the definitions for the Interrupt Enable Register
*/
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
/* useful defaults for LCR */
#define UART_LCR_8N1 0x03
#define UART_ADDR (0xFE660000)
#define UART_LCRVAL UART_LCR_8N1 /* 8 data, 1 stop, no parity */
#define UART_MCRVAL (UART_MCR_DTR | UART_MCR_RTS) /* RTS/DTR */
#define out_le32(a, v) (*(volatile uint32_t*)(a) = (v))
#define in_le32(a) (*(volatile uint32_t*)(a))
#ifndef CONFIG_SYS_NS16550_IER
#define CONFIG_SYS_NS16550_IER 0x00
#endif /* CONFIG_SYS_NS16550_IER */
#define serial_dout(reg, value) \
serial_out_shift((char*)com_port + ((char*)reg - (char*)com_port) * (1 << 2), \
2, value)
#define serial_din(reg) \
serial_in_shift((char*)com_port + ((char*)reg - (char*)com_port) * (1 << 2), \
2)
static inline void serial_out_shift(void* addr, int shift, int value)
{
out_le32(addr, value);
}
static inline int serial_in_shift(void* addr, int shift)
{
return in_le32(addr);
}
#ifndef CONFIG_SYS_NS16550_CLK
#define CONFIG_SYS_NS16550_CLK 0
#endif
bool init_uart_mmio()
{
static int mapped = 0;
if (mapped == 0) {
if (-1 == mmap(UART_ADDR, UART_ADDR, 4096, true)) {
return false;
}
mapped = 1;
}
return true;
}
void putc(char ch)
{
static struct NS16550* com_port = (struct NS16550*)UART_ADDR;
if (ch == '\n') {
putc('\r');
}
while (!(serial_din(&com_port->lsr) & UART_LSR_THRE))
;
serial_dout(&com_port->thr, ch);
}
char getc(void)
{
static struct NS16550* com_port = (struct NS16550*)UART_ADDR;
while (!(serial_din(&com_port->lsr) & UART_LSR_DR))
;
return serial_din(&com_port->rbr);
}

View File

@ -8,10 +8,10 @@ toolchain ?= arm-xilinx-eabi-
user_ldflags = -N -Ttext 0
cflags = -march=armv7-a -std=c11 -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
endif
ifeq ($(BOARD), ok1028a-c)
ifeq ($(BOARD), 3568)
toolchain ?= aarch64-none-elf-
user_ldflags = -N -Ttext 0
cflags = -Wall -g -std=c11 -mtune=cortex-a72 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
cflags = -Wall -O0 -g -std=c11 -mtune=cortex-a55 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
endif
cc = ${toolchain}gcc

View File

@ -1,113 +0,0 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/// this file is only used for debug
#include "libserial.h"
#include "usyscall.h"
#define USER_UART_BASE 0x6FFFF000
#define UART0_BASE (0x09000000ULL)
#define UART0_REG(reg) ((volatile uint32_t*)(USER_UART_BASE + reg))
// the UART control registers.
// pl011
#define DR 0x00
#define FR 0x18
#define FR_RXFE (1 << 4) // recieve fifo empty
#define FR_TXFF (1 << 5) // transmit fifo full
#define FR_RXFF (1 << 6) // recieve fifo full
#define FR_TXFE (1 << 7) // transmit fifo empty
#define IBRD 0x24
#define FBRD 0x28
#define LCRH 0x2c
#define LCRH_FEN (1 << 4)
#define LCRH_WLEN_8BIT (3 << 5)
#define CR 0x30
#define IMSC 0x38
#define INT_RX_ENABLE (1 << 4)
#define INT_TX_ENABLE (1 << 5)
#define ICR 0x44
#define UART_READ_REG(reg) (*(UART0_REG(reg)))
#define UART_WRITE_REG(reg, v) (*(UART0_REG(reg)) = (v))
#define UART_TX_BUF_SIZE 32
static char uart_tx_buf[UART_TX_BUF_SIZE];
uint64_t uart_tx_w; // write next to uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE]
uint64_t uart_tx_r; // read next from uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE]
bool init_uart_mmio()
{
static int mapped = 0;
if (mapped == 0) {
if (-1 == mmap(USER_UART_BASE, UART0_BASE, 4096, true)) {
return false;
}
mapped = 1;
}
return true;
}
// if the UART is idle, and a character is waiting
// in the transmit buffer, send it.
// caller must hold uart_tx_lock.
// called from both the top- and bottom-half.
void uartstart()
{
while (1) {
if (uart_tx_w == uart_tx_r) {
// transmit buffer is empty.
return;
}
if (UART_READ_REG(FR) & FR_TXFF) {
// the UART transmit holding register is full,
// so we cannot give it another byte.
// it will interrupt when it's ready for a new byte.
return;
}
int c = uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE];
uart_tx_r += 1;
// maybe uartputc() is waiting for space in the buffer.
UART_WRITE_REG(DR, c);
}
}
// add a character to the output buffer and tell the
// UART to start sending if it isn't already.
// blocks if the output buffer is full.
// because it may block, it can't be called
// from interrupts; it's only suitable for use
// by write().
void putc(char c)
{
while (uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE)
;
uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c;
uart_tx_w += 1;
uartstart();
return;
}
// read one input character from the UART.
// return -1 if none is waiting.
char getc(void)
{
if (UART_READ_REG(FR) & FR_RXFE)
return 0xFF;
else
return UART_READ_REG(DR);
}

View File

@ -9,10 +9,10 @@ user_ldflags = --start-group,-lgcc,-lc,--end-group
cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
#cflags = -Wall -g -std=c11
endif
ifeq ($(BOARD), ok1028a-c)
ifeq ($(BOARD), 3568)
toolchain ?= aarch64-none-elf-
user_ldflags = -N -Ttext 0
cflags = -Wall -g -std=c11 -mtune=cortex-a72 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
cflags = -Wall -O0 -g -std=c11 -mtune=cortex-a55 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
endif
cc = ${toolchain}gcc

View File

@ -1,3 +1,4 @@
SRC_DIR :=
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,62 @@
ifeq ($(BOARD), imx6q-sabrelite)
toolchain ?= arm-none-eabi-
user_ldflags = --specs=nosys.specs -Wl,-Map=user.map,-cref -N
cflags = -std=c11 -O2 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
endif
ifeq ($(BOARD), zynq7000-zc702)
toolchain ?= arm-xilinx-eabi-
user_ldflags = -Wl,--start-group,-lgcc,-lc,--end-group -N
cflags = -std=c11 -O2 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
board_specs = stub.o
#cflags = -Wall -g -std=c11
endif
ifeq ($(BOARD), ok1028a-c)
toolchain ?= aarch64-none-elf-
user_ldflags = -N -Ttext 0
cflags = -g -std=c11 -mtune=cortex-a72 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -Werror -ggdb -Wno-unused -fno-omit-frame-pointer -fno-stack-protector -fno-pie
board_specs = stub.o
endif
ifeq ($(BOARD), 3568)
toolchain ?= aarch64-none-elf-
user_ldflags = -N -Ttext 0
cflags = -Wall -g -std=c11 -mtune=cortex-a55 -nostdlib -nodefaultlibs -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie
board_specs = $(KERNEL_ROOT)/services/app/stub.o
endif
cc = ${toolchain}gcc
ld = ${toolchain}g++
objdump = ${toolchain}objdump
c_useropts = -O2
# c_useropts = -O0
INC_DIR = -I$(KERNEL_ROOT)/services/app \
-I$(KERNEL_ROOT)/services/boards/$(BOARD) \
-I$(KERNEL_ROOT)/services/lib/serial \
-I$(KERNEL_ROOT)/services/drivers/3568/include \
-I$(KERNEL_ROOT)/services/lib/usyscall \
-I$(KERNEL_ROOT)/services/lib/ipc \
-I$(KERNEL_ROOT)/services/lib/memory
objs = hal_gmac.o \
hal_gmac_3568.o \
test_gmac.o \
hal_base.o \
hal_bsp.o \
hal_pinctrl_v2.o \
hal_cru.o \
hal_gpio.o \
hal_timer.o \
hal_cru_rk3568.o \
hal_debug.o \
system_rk3568.o \
all: ${objs}
@mv $^ $(KERNEL_ROOT)/services/app
%.o: %.c
@echo "cc $^"
@${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^

View File

@ -0,0 +1,454 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
*/
#include "hal_base.h"
/** @addtogroup RK_HAL_Driver
* @{
*/
/** @addtogroup HAL_BASE
* @{
*/
/** @defgroup HAL_BASE_How_To_Use How To Use
* @{
HAL system support is including delay system, HAL tick system and global system clock,
HAL system tick setting:
- Attach HAL_IncTick() to system tick interrupt handler;
- Notify the HAL system the system's tick frequency by calling HAL_SetTickFreq() unless
it is the same as default value HAL_TICK_FREQ_1KHZ;
- If you need a more accurate delay system, specify SYS_TIMER in hal_conf.h.
Init HAL system:
- Initialize the HAL system by calling HAL_Init():
Reset when SOC system is changed:
- Update system with new core clock and new SysTick clock source by calling HAL_SystemCoreClockUpdate();
APIs:
- Get system time by calling HAL_GetTick().
- Delay for a certain length of time, HAL_DelayMs(), HAL_DelayUs(), and HAL_CPUDelayUs().
- Blocking for a certain period of time to continuously query HW status, use HAL_GetTick()
to do timeout, this will be more accurate.
- Get current cpu usage by calling HAL_GetCPUUsage().
@} */
/** @defgroup HAL_BASE_Private_Definition Private Definition
* @{
*/
/********************* Private MACRO Definition ******************************/
#define HAL_TICK_FREQ_DEFAULT HAL_TICK_FREQ_1KHZ
/********************* Private Structure Definition **************************/
/********************* Private Variable Definition ***************************/
static __IO uint32_t uwTick;
static eHAL_tickFreq uwTickFreq = HAL_TICK_FREQ_DEFAULT;
/********************* Private Function Definition ***************************/
#if defined(__CORTEX_A) || defined(__CORTEX_M)
#if __CORTEX_M == 0U || !defined(__GNUC__)
static void CPUCycleLoop(uint32_t cycles)
{
uint32_t count;
if (cycles < 100U) {
return;
}
count = cycles / 3;
while (count-- > 0) {
__asm volatile ("nop");
}
}
#else
static void CPUCycleLoop(uint32_t cycles)
{
__ASM volatile (
"mov r0, %0\n\t"
"adds r0, r0, #2\n\t" // 1 2 Round to the nearest multiple of 4.
"lsrs r0, r0, #2\n\t" // 1 2 Divide by 4 and set flags.
"beq 2f\n\t" // 2 2 Skip if 0.
".align 4\n\t"
"1:\n\t"
"adds r0, r0, #1\n\t" // 1 2 Increment the counter.
"subs r0, r0, #2\n\t" // 1 2 Decrement the counter by 2.
"bne 1b\n\t" // (1)2 2 2 CPU cycles (if branch is taken).
"nop\n\t" // 1 2 Loop alignment padding.
"2:"
: : "r" (cycles)
);
}
#endif
#elif defined(__RISC_V)
static void CPUCycleLoop(uint32_t cycles)
{
asm volatile (
"mv a0, %0\n\t"
"addi a0, a0, 2\n\t" // 1 2 Round to the nearest multiple of 4.
"li a1, 4\n\t"
"div a0, a0, a1\n\t" // 1 2 Divide by 4 and set flags.
"li a1, 2\n\t"
"bnez a0, 1f\n\t" // 2 2 Skip if 0.
"j 2f\n\t"
".align 6\n\t"
"1:\n\t"
"addi a0, a0, 1\n\t" // 1 2 Increment the counter.
"sub a0, a0, a1\n\t" // 1 2 Decrement the counter by 2.
"bnez a0, 1b\n\t" // (1)2 2 2 CPU cycles (if branch is taken).
"nop\n\t" // 1 2 Loop alignment padding.
"2:"
: : "r" (cycles)
);
}
#endif
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
__attribute__((always_inline)) static inline HAL_Status TimerDelayUs(uint32_t us)
{
uint64_t count, from, now, pass;
from = HAL_TIMER_GetCount(SYS_TIMER);
count = PLL_INPUT_OSC_RATE / 1000000 * us;
do {
now = HAL_TIMER_GetCount(SYS_TIMER);
pass = now > from ? now - from : from - now;
} while (pass < count);
return HAL_OK;
}
#endif
/** @} */
/********************* Public Function Definition ***************************/
/** @defgroup HAL_BASE_Exported_Functions_Group4 Init and DeInit Functions
This section provides functions allowing to init and deinit the module:
* @{
*/
/**
* @brief Init HAL driver basic code.
* @return HAL_OK.
*/
HAL_Status HAL_Init(void)
{
#ifdef __CORTEX_M
#ifdef HAL_NVIC_MODULE_ENABLED
/* Set Interrupt Group Priority */
HAL_NVIC_Init();
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_DEFAULT);
#endif
#endif
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
HAL_TIMER_SysTimerInit(SYS_TIMER);
#endif
#ifdef HAL_PINCTRL_MODULE_ENABLED
HAL_PINCTRL_Init();
#endif
return HAL_OK;
}
/**
* @brief HAL system update with new core clock and systick clock source.
* @param hz: new core clock.
* @param clkSource: new systick clock source.
* @return HAL_OK.
*/
HAL_Status HAL_SystemCoreClockUpdate(uint32_t hz, eHAL_systickClkSource clkSource)
{
uint32_t rate = hz;
HAL_Status ret = HAL_OK;
#if defined(__CORTEX_M) && defined(HAL_SYSTICK_MODULE_ENABLED)
ret = HAL_SYSTICK_CLKSourceConfig(clkSource);
if (ret == HAL_OK && clkSource == HAL_SYSTICK_CLKSRC_EXT) {
rate = PLL_INPUT_OSC_RATE;
}
HAL_SYSTICK_Config(rate / (1000 / HAL_GetTickFreq()));
ret = HAL_OK;
#endif
if (ret == HAL_OK) {
SystemCoreClock = rate; /* Update global SystemCoreClock */
}
return ret;
}
/**
* @brief HAL deinit.
* @return HAL_Status: HAL_OK.
*/
HAL_Status HAL_DeInit(void)
{
/* TO-DO */
return HAL_OK;
}
/** @} */
/** @defgroup HAL_BASE_Exported_Functions_Group5 Other Functions
* @{
*/
/**
* @brief Count plus tickFreq when interrupt occurs.
* @return HAL_Status: HAL_OK.
*/
HAL_Status HAL_IncTick(void)
{
uwTick += uwTickFreq;
return HAL_OK;
}
/**
* @brief Provides tick value in millisecond.
* @return uint32_t: tick value in millisecond.
* @attention this API allow direct use in the HAL layer.
*/
uint32_t HAL_GetTick(void)
{
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
uint64_t tick = HAL_TIMER_GetCount(SYS_TIMER);
uint32_t base = PLL_INPUT_OSC_RATE / 1000;
if (tick >> 62) {
tick = ~tick;
}
return (uint32_t)HAL_DivU64(tick, base);
#else
return uwTick;
#endif
}
/**
* @brief Provides system timer count.
* @return uint64_t: timer count.
* @attention this API allow direct use in the HAL layer.
*/
uint64_t HAL_GetSysTimerCount(void)
{
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
uint64_t count = HAL_TIMER_GetCount(SYS_TIMER);
if (count >> 62) {
count = ~count;
}
return count;
#else
return 0LLU;
#endif
}
/**
* @brief Set new tick frequency.
* @return HAL_Status.
*/
HAL_Status HAL_SetTickFreq(eHAL_tickFreq freq)
{
HAL_ASSERT(IS_TICKFREQ(freq));
uwTickFreq = freq;
return HAL_OK;
}
/**
* @brief Return tick frequency.
* @return uint32_t: tick period in Hz.
* @attention this API allow direct use in the HAL layer.
*/
eHAL_tickFreq HAL_GetTickFreq(void)
{
return uwTickFreq;
}
/**
* @brief SysTick mdelay.
* @param ms: mdelay count.
* @return HAL_Status: HAL_OK.
* @attention this API allow direct use in the HAL layer. Blocking for a
* certain period of time to continuously query HW status, use HAL_GetTick
* to do timeout, that will be more accurate.
*/
__attribute__((weak)) HAL_Status HAL_DelayMs(uint32_t ms)
{
for (uint32_t i = 0; i < ms; i++) {
HAL_DelayUs(1000);
}
return HAL_OK;
}
/**
* @brief SysTick udelay.
* @param us: udelay count.
* @return HAL_Status: HAL_OK.
* @attention this API allow direct use in the HAL layer. The longer the delay,
* the more accurate. Actual delay is greater than the parameter.
*/
HAL_Status HAL_DelayUs(uint32_t us)
{
#if defined(SYS_TIMER) && defined(HAL_TIMER_MODULE_ENABLED)
return TimerDelayUs(us);
#else
return HAL_CPUDelayUs(us);
#endif
}
/**
* @brief CPU loop udelay.
* @param us: udelay count.
* @return HAL_Status: HAL_OK.
* @attention this API allow direct use in the HAL layer. The longer the delay,
* the more accurate. Actual delay is greater than the parameter.
* During delay, CPU rate change result in delay imprecise, so call it in
* following case:
* 1.IRQ disable
* 2.CRU code
*/
HAL_Status HAL_CPUDelayUs(uint32_t us)
{
volatile uint32_t cycles;
#if (__CORTEX_M == 0)
cycles = (uint32_t)HAL_DivU64((uint64_t)SystemCoreClock, 1000000) * us; /* Add few cycles penalty */
#else
cycles = SystemCoreClock / 1000000 * us; /* Add few cycles penalty */
#endif
CPUCycleLoop(cycles);
return HAL_OK;
}
#if defined(HAL_CPU_USAGE_ENABLED)
static uint64_t g_last_enter_idle_time = 0; /* Last time current CPU entered the idle state. */
static uint64_t g_total_idle_time = 0; /* Total time for current CPU to enter idle state. */
static uint64_t g_last_elapsed_time = 0; /* Last elapsed time for current CPU. */
/**
* @brief Get current CPU usage.
* @return 0-100
* @attention The cpu usage function depends on HAL_CPUEnterIdle function.
*/
uint32_t HAL_GetCPUUsage(void)
{
uint64_t elapsed_time, active_time, current_time;
uint32_t usage;
current_time = HAL_GetSysTimerCount();
elapsed_time = current_time - g_last_elapsed_time;
/* Prevent the risk of dividing by 0 caused by repeated calls for a short time. */
if (!elapsed_time) {
return 0;
}
HAL_ASSERT(elapsed_time > g_total_idle_time);
active_time = elapsed_time - g_total_idle_time;
usage = (active_time * 100) / elapsed_time;
g_total_idle_time = 0;
g_last_elapsed_time = current_time;
return usage;
}
#endif
/**
* @brief CPU enter idle.
*/
void HAL_CPU_EnterIdle(void)
{
#if defined(HAL_CPU_USAGE_ENABLED)
uint64_t idle_time;
__disable_irq();
g_last_enter_idle_time = HAL_GetSysTimerCount();
#endif
// __asm__ volatile ("wfi");
#if defined(HAL_CPU_USAGE_ENABLED)
idle_time = HAL_GetSysTimerCount() - g_last_enter_idle_time;
g_total_idle_time += idle_time;
__enable_irq();
#endif
}
/** @} */
/** @} */
/** @} */
/********************* Public Function Definition ***************************/
/** @defgroup HAL_BASE_EX_Exported_Functions_Group5 Other Functions
* @{
*/
/**
* @brief uint64_t numerator / uint32_t denominator with remainder
* @param numerator
* @param denominator
* @param pRemainder [out] pointer to unsigned 32bit remainder
* @return uint64_t result. sets *pRemainder if pRemainder is not null
*/
uint64_t HAL_DivU64Rem(uint64_t numerator, uint32_t denominator, uint32_t *pRemainder)
{
uint64_t remainder = numerator;
uint64_t b = denominator;
uint64_t result;
uint64_t d = 1;
uint32_t high = numerator >> 32;
result = 0;
if (high >= denominator) {
high /= denominator;
result = (uint64_t)high << 32;
remainder -= (uint64_t)(high * denominator) << 32;
}
while ((int64_t)b > 0 && b < remainder) {
b = b + b;
d = d + d;
}
do {
if (remainder >= b) {
remainder -= b;
result += d;
}
b >>= 1;
d >>= 1;
} while (d);
if (pRemainder) {
*pRemainder = remainder;
}
return result;
}

Some files were not shown because too many files have changed in this diff Show More