add support to zynqmp-r5 core and zynqmp-r5-axu4ev board
This commit is contained in:
Wang-Huachen 2020-11-30 13:13:08 +08:00
parent f7b553b193
commit 7258328923
70 changed files with 16855 additions and 0 deletions

View File

@ -0,0 +1,515 @@
#
# Automatically generated file; DO NOT EDIT.
# RT-Thread Project Configuration
#
#
# RT-Thread Kernel
#
CONFIG_RT_NAME_MAX=20
# CONFIG_RT_USING_ARCH_DATA_TYPE is not set
# CONFIG_RT_USING_SMP is not set
CONFIG_RT_ALIGN_SIZE=4
# CONFIG_RT_THREAD_PRIORITY_8 is not set
CONFIG_RT_THREAD_PRIORITY_32=y
# CONFIG_RT_THREAD_PRIORITY_256 is not set
CONFIG_RT_THREAD_PRIORITY_MAX=32
CONFIG_RT_TICK_PER_SECOND=100
CONFIG_RT_USING_OVERFLOW_CHECK=y
CONFIG_RT_USING_HOOK=y
CONFIG_RT_USING_IDLE_HOOK=y
CONFIG_RT_IDLE_HOOK_LIST_SIZE=4
CONFIG_IDLE_THREAD_STACK_SIZE=512
CONFIG_RT_USING_TIMER_SOFT=y
CONFIG_RT_TIMER_THREAD_PRIO=4
CONFIG_RT_TIMER_THREAD_STACK_SIZE=512
CONFIG_RT_DEBUG=y
# CONFIG_RT_DEBUG_COLOR is not set
# CONFIG_RT_DEBUG_INIT_CONFIG is not set
# CONFIG_RT_DEBUG_THREAD_CONFIG is not set
# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set
# CONFIG_RT_DEBUG_IPC_CONFIG is not set
# CONFIG_RT_DEBUG_TIMER_CONFIG is not set
# CONFIG_RT_DEBUG_IRQ_CONFIG is not set
# CONFIG_RT_DEBUG_MEM_CONFIG is not set
# CONFIG_RT_DEBUG_SLAB_CONFIG is not set
# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set
# CONFIG_RT_DEBUG_MODULE_CONFIG is not set
#
# Inter-Thread communication
#
CONFIG_RT_USING_SEMAPHORE=y
CONFIG_RT_USING_MUTEX=y
CONFIG_RT_USING_EVENT=y
CONFIG_RT_USING_MAILBOX=y
CONFIG_RT_USING_MESSAGEQUEUE=y
# CONFIG_RT_USING_SIGNALS is not set
#
# Memory Management
#
CONFIG_RT_USING_MEMPOOL=y
# CONFIG_RT_USING_MEMHEAP is not set
# CONFIG_RT_USING_NOHEAP is not set
CONFIG_RT_USING_SMALL_MEM=y
# CONFIG_RT_USING_SLAB is not set
# CONFIG_RT_USING_MEMTRACE is not set
CONFIG_RT_USING_HEAP=y
#
# Kernel Device Object
#
CONFIG_RT_USING_DEVICE=y
# CONFIG_RT_USING_DEVICE_OPS is not set
# CONFIG_RT_USING_INTERRUPT_INFO is not set
CONFIG_RT_USING_CONSOLE=y
CONFIG_RT_CONSOLEBUF_SIZE=128
CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
CONFIG_RT_VER_NUM=0x40003
# CONFIG_RT_USING_CPU_FFS is not set
# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set
#
# RT-Thread Components
#
CONFIG_RT_USING_COMPONENTS_INIT=y
CONFIG_RT_USING_USER_MAIN=y
CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048
CONFIG_RT_MAIN_THREAD_PRIORITY=10
#
# C++ features
#
# CONFIG_RT_USING_CPLUSPLUS is not set
#
# Command shell
#
CONFIG_RT_USING_FINSH=y
CONFIG_FINSH_THREAD_NAME="tshell"
CONFIG_FINSH_USING_HISTORY=y
CONFIG_FINSH_HISTORY_LINES=5
CONFIG_FINSH_USING_SYMTAB=y
CONFIG_FINSH_USING_DESCRIPTION=y
# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set
CONFIG_FINSH_THREAD_PRIORITY=20
CONFIG_FINSH_THREAD_STACK_SIZE=4096
CONFIG_FINSH_CMD_SIZE=80
# CONFIG_FINSH_USING_AUTH is not set
CONFIG_FINSH_USING_MSH=y
CONFIG_FINSH_USING_MSH_DEFAULT=y
# CONFIG_FINSH_USING_MSH_ONLY is not set
CONFIG_FINSH_ARG_MAX=10
#
# Device virtual file system
#
CONFIG_RT_USING_DFS=y
CONFIG_DFS_USING_WORKDIR=y
CONFIG_DFS_FILESYSTEMS_MAX=2
CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
CONFIG_DFS_FD_MAX=16
# CONFIG_RT_USING_DFS_MNTTABLE is not set
CONFIG_RT_USING_DFS_ELMFAT=y
#
# elm-chan's FatFs, Generic FAT Filesystem Module
#
CONFIG_RT_DFS_ELM_CODE_PAGE=437
CONFIG_RT_DFS_ELM_WORD_ACCESS=y
# CONFIG_RT_DFS_ELM_USE_LFN_0 is not set
# CONFIG_RT_DFS_ELM_USE_LFN_1 is not set
# CONFIG_RT_DFS_ELM_USE_LFN_2 is not set
CONFIG_RT_DFS_ELM_USE_LFN_3=y
CONFIG_RT_DFS_ELM_USE_LFN=3
CONFIG_RT_DFS_ELM_MAX_LFN=255
CONFIG_RT_DFS_ELM_DRIVES=2
CONFIG_RT_DFS_ELM_MAX_SECTOR_SIZE=512
# CONFIG_RT_DFS_ELM_USE_ERASE is not set
CONFIG_RT_DFS_ELM_REENTRANT=y
CONFIG_RT_USING_DFS_DEVFS=y
# CONFIG_RT_USING_DFS_ROMFS is not set
# CONFIG_RT_USING_DFS_RAMFS is not set
# CONFIG_RT_USING_DFS_UFFS is not set
# CONFIG_RT_USING_DFS_JFFS2 is not set
#
# Device Drivers
#
CONFIG_RT_USING_DEVICE_IPC=y
CONFIG_RT_PIPE_BUFSZ=512
# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set
CONFIG_RT_USING_SERIAL=y
CONFIG_RT_SERIAL_USING_DMA=y
CONFIG_RT_SERIAL_RB_BUFSZ=64
# CONFIG_RT_USING_CAN is not set
# CONFIG_RT_USING_HWTIMER is not set
# CONFIG_RT_USING_CPUTIME is not set
# CONFIG_RT_USING_I2C is not set
CONFIG_RT_USING_PIN=y
# CONFIG_RT_USING_ADC is not set
# CONFIG_RT_USING_DAC is not set
# CONFIG_RT_USING_PWM is not set
# CONFIG_RT_USING_MTD_NOR is not set
# CONFIG_RT_USING_MTD_NAND is not set
# CONFIG_RT_USING_PM is not set
# CONFIG_RT_USING_RTC is not set
# CONFIG_RT_USING_SDIO is not set
# CONFIG_RT_USING_SPI is not set
# CONFIG_RT_USING_WDT is not set
# CONFIG_RT_USING_AUDIO is not set
# CONFIG_RT_USING_SENSOR is not set
# CONFIG_RT_USING_TOUCH is not set
# CONFIG_RT_USING_HWCRYPTO is not set
# CONFIG_RT_USING_PULSE_ENCODER is not set
# CONFIG_RT_USING_INPUT_CAPTURE is not set
# CONFIG_RT_USING_WIFI is not set
#
# Using USB
#
# CONFIG_RT_USING_USB_HOST is not set
# CONFIG_RT_USING_USB_DEVICE is not set
#
# Using RapidIO
#
# CONFIG_RT_USING_RAPIDIO is not set
#
# POSIX layer and C standard library
#
CONFIG_RT_USING_LIBC=y
# CONFIG_RT_USING_PTHREADS is not set
CONFIG_RT_USING_POSIX=y
# CONFIG_RT_USING_POSIX_MMAP is not set
# CONFIG_RT_USING_POSIX_TERMIOS is not set
# CONFIG_RT_USING_POSIX_GETLINE is not set
# CONFIG_RT_USING_POSIX_AIO is not set
# CONFIG_RT_USING_MODULE is not set
#
# Network
#
#
# Socket abstraction layer
#
# CONFIG_RT_USING_SAL is not set
#
# Network interface device
#
# CONFIG_RT_USING_NETDEV is not set
#
# light weight TCP/IP stack
#
# CONFIG_RT_USING_LWIP is not set
#
# AT commands
#
# CONFIG_RT_USING_AT is not set
#
# VBUS(Virtual Software BUS)
#
# CONFIG_RT_USING_VBUS is not set
#
# Utilities
#
# CONFIG_RT_USING_RYM is not set
# CONFIG_RT_USING_ULOG is not set
# CONFIG_RT_USING_UTEST is not set
#
# RT-Thread online packages
#
#
# IoT - internet of things
#
# CONFIG_PKG_USING_LORAWAN_DRIVER is not set
# CONFIG_PKG_USING_PAHOMQTT is not set
# CONFIG_PKG_USING_UMQTT is not set
# CONFIG_PKG_USING_WEBCLIENT is not set
# CONFIG_PKG_USING_WEBNET is not set
# CONFIG_PKG_USING_MONGOOSE is not set
# CONFIG_PKG_USING_MYMQTT is not set
# CONFIG_PKG_USING_KAWAII_MQTT is not set
# CONFIG_PKG_USING_BC28_MQTT is not set
# CONFIG_PKG_USING_WEBTERMINAL is not set
# CONFIG_PKG_USING_CJSON is not set
# CONFIG_PKG_USING_JSMN is not set
# CONFIG_PKG_USING_LIBMODBUS is not set
# CONFIG_PKG_USING_FREEMODBUS is not set
# CONFIG_PKG_USING_LJSON is not set
# CONFIG_PKG_USING_EZXML is not set
# CONFIG_PKG_USING_NANOPB is not set
#
# Wi-Fi
#
#
# Marvell WiFi
#
# CONFIG_PKG_USING_WLANMARVELL is not set
#
# Wiced WiFi
#
# CONFIG_PKG_USING_WLAN_WICED is not set
# CONFIG_PKG_USING_RW007 is not set
# CONFIG_PKG_USING_COAP is not set
# CONFIG_PKG_USING_NOPOLL is not set
# CONFIG_PKG_USING_NETUTILS is not set
# CONFIG_PKG_USING_CMUX is not set
# CONFIG_PKG_USING_PPP_DEVICE is not set
# CONFIG_PKG_USING_AT_DEVICE is not set
# CONFIG_PKG_USING_ATSRV_SOCKET is not set
# CONFIG_PKG_USING_WIZNET is not set
#
# IoT Cloud
#
# CONFIG_PKG_USING_ONENET is not set
# CONFIG_PKG_USING_GAGENT_CLOUD is not set
# CONFIG_PKG_USING_ALI_IOTKIT is not set
# CONFIG_PKG_USING_AZURE is not set
# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set
# CONFIG_PKG_USING_JIOT-C-SDK is not set
# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set
# CONFIG_PKG_USING_JOYLINK is not set
# CONFIG_PKG_USING_NIMBLE is not set
# CONFIG_PKG_USING_OTA_DOWNLOADER is not set
# CONFIG_PKG_USING_IPMSG is not set
# CONFIG_PKG_USING_LSSDP is not set
# CONFIG_PKG_USING_AIRKISS_OPEN is not set
# CONFIG_PKG_USING_LIBRWS is not set
# CONFIG_PKG_USING_TCPSERVER is not set
# CONFIG_PKG_USING_PROTOBUF_C is not set
# CONFIG_PKG_USING_ONNX_PARSER is not set
# CONFIG_PKG_USING_ONNX_BACKEND is not set
# CONFIG_PKG_USING_DLT645 is not set
# CONFIG_PKG_USING_QXWZ is not set
# CONFIG_PKG_USING_SMTP_CLIENT is not set
# CONFIG_PKG_USING_ABUP_FOTA is not set
# CONFIG_PKG_USING_LIBCURL2RTT is not set
# CONFIG_PKG_USING_CAPNP is not set
# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set
# CONFIG_PKG_USING_AGILE_TELNET is not set
# CONFIG_PKG_USING_NMEALIB is not set
# CONFIG_PKG_USING_AGILE_JSMN is not set
# CONFIG_PKG_USING_PDULIB is not set
# CONFIG_PKG_USING_BTSTACK is not set
# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set
#
# security packages
#
# CONFIG_PKG_USING_MBEDTLS is not set
# CONFIG_PKG_USING_libsodium is not set
# CONFIG_PKG_USING_TINYCRYPT is not set
# CONFIG_PKG_USING_TFM is not set
# CONFIG_PKG_USING_YD_CRYPTO is not set
#
# language packages
#
# CONFIG_PKG_USING_LUA is not set
# CONFIG_PKG_USING_JERRYSCRIPT is not set
# CONFIG_PKG_USING_MICROPYTHON is not set
#
# multimedia packages
#
# CONFIG_PKG_USING_OPENMV is not set
# CONFIG_PKG_USING_MUPDF is not set
# CONFIG_PKG_USING_STEMWIN is not set
# CONFIG_PKG_USING_WAVPLAYER is not set
# CONFIG_PKG_USING_TJPGD is not set
# CONFIG_PKG_USING_HELIX is not set
# CONFIG_PKG_USING_AZUREGUIX is not set
#
# tools packages
#
# CONFIG_PKG_USING_CMBACKTRACE is not set
# CONFIG_PKG_USING_EASYFLASH is not set
# CONFIG_PKG_USING_EASYLOGGER is not set
# CONFIG_PKG_USING_SYSTEMVIEW is not set
# CONFIG_PKG_USING_RDB is not set
# CONFIG_PKG_USING_QRCODE is not set
# CONFIG_PKG_USING_ULOG_EASYFLASH is not set
# CONFIG_PKG_USING_ADBD is not set
# CONFIG_PKG_USING_COREMARK is not set
# CONFIG_PKG_USING_DHRYSTONE is not set
# CONFIG_PKG_USING_MEMORYPERF is not set
# CONFIG_PKG_USING_NR_MICRO_SHELL is not set
# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set
# CONFIG_PKG_USING_LUNAR_CALENDAR is not set
# CONFIG_PKG_USING_BS8116A is not set
# CONFIG_PKG_USING_GPS_RMC is not set
# CONFIG_PKG_USING_URLENCODE is not set
# CONFIG_PKG_USING_UMCN is not set
# CONFIG_PKG_USING_LWRB2RTT is not set
#
# system packages
#
# CONFIG_PKG_USING_GUIENGINE is not set
# CONFIG_PKG_USING_CAIRO is not set
# CONFIG_PKG_USING_PIXMAN is not set
# CONFIG_PKG_USING_LWEXT4 is not set
# CONFIG_PKG_USING_PARTITION is not set
# CONFIG_PKG_USING_FAL is not set
# CONFIG_PKG_USING_FLASHDB is not set
# CONFIG_PKG_USING_SQLITE is not set
# CONFIG_PKG_USING_RTI is not set
# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
# CONFIG_PKG_USING_CMSIS is not set
# CONFIG_PKG_USING_DFS_YAFFS is not set
# CONFIG_PKG_USING_LITTLEFS is not set
# CONFIG_PKG_USING_THREAD_POOL is not set
# CONFIG_PKG_USING_ROBOTS is not set
# CONFIG_PKG_USING_EV is not set
# CONFIG_PKG_USING_SYSWATCH is not set
# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set
# CONFIG_PKG_USING_PLCCORE is not set
# CONFIG_PKG_USING_RAMDISK is not set
# CONFIG_PKG_USING_MININI is not set
# CONFIG_PKG_USING_QBOOT is not set
#
# Micrium: Micrium software products porting for RT-Thread
#
# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set
# CONFIG_PKG_USING_UC_CRC is not set
# CONFIG_PKG_USING_UC_CLK is not set
# CONFIG_PKG_USING_UC_COMMON is not set
# CONFIG_PKG_USING_UC_MODBUS is not set
# CONFIG_PKG_USING_PPOOL is not set
#
# peripheral libraries and drivers
#
# CONFIG_PKG_USING_SENSORS_DRIVERS is not set
# CONFIG_PKG_USING_REALTEK_AMEBA is not set
# CONFIG_PKG_USING_SHT2X is not set
# CONFIG_PKG_USING_SHT3X is not set
# CONFIG_PKG_USING_STM32_SDIO is not set
# CONFIG_PKG_USING_ICM20608 is not set
# CONFIG_PKG_USING_U8G2 is not set
# CONFIG_PKG_USING_BUTTON is not set
# CONFIG_PKG_USING_PCF8574 is not set
# CONFIG_PKG_USING_SX12XX is not set
# CONFIG_PKG_USING_SIGNAL_LED is not set
# CONFIG_PKG_USING_LEDBLINK is not set
# CONFIG_PKG_USING_LITTLED is not set
# CONFIG_PKG_USING_LKDGUI is not set
# CONFIG_PKG_USING_NRF5X_SDK is not set
# CONFIG_PKG_USING_NRFX is not set
# CONFIG_PKG_USING_WM_LIBRARIES is not set
# CONFIG_PKG_USING_KENDRYTE_SDK is not set
# CONFIG_PKG_USING_INFRARED is not set
# CONFIG_PKG_USING_ROSSERIAL is not set
# CONFIG_PKG_USING_AGILE_BUTTON is not set
# CONFIG_PKG_USING_AGILE_LED is not set
# CONFIG_PKG_USING_AT24CXX is not set
# CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set
# CONFIG_PKG_USING_AD7746 is not set
# CONFIG_PKG_USING_PCA9685 is not set
# CONFIG_PKG_USING_I2C_TOOLS is not set
# CONFIG_PKG_USING_NRF24L01 is not set
# CONFIG_PKG_USING_TOUCH_DRIVERS is not set
# CONFIG_PKG_USING_MAX17048 is not set
# CONFIG_PKG_USING_RPLIDAR is not set
# CONFIG_PKG_USING_AS608 is not set
# CONFIG_PKG_USING_RC522 is not set
# CONFIG_PKG_USING_WS2812B is not set
# CONFIG_PKG_USING_EMBARC_BSP is not set
# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set
# CONFIG_PKG_USING_MULTI_RTIMER is not set
# CONFIG_PKG_USING_MAX7219 is not set
# CONFIG_PKG_USING_BEEP is not set
# CONFIG_PKG_USING_EASYBLINK is not set
# CONFIG_PKG_USING_PMS_SERIES is not set
# CONFIG_PKG_USING_CAN_YMODEM is not set
# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set
# CONFIG_PKG_USING_QLED is not set
# CONFIG_PKG_USING_PAJ7620 is not set
# CONFIG_PKG_USING_AGILE_CONSOLE is not set
# CONFIG_PKG_USING_LD3320 is not set
# CONFIG_PKG_USING_WK2124 is not set
# CONFIG_PKG_USING_LY68L6400 is not set
# CONFIG_PKG_USING_DM9051 is not set
# CONFIG_PKG_USING_SSD1306 is not set
# CONFIG_PKG_USING_QKEY is not set
#
# miscellaneous packages
#
# CONFIG_PKG_USING_LIBCSV is not set
# CONFIG_PKG_USING_OPTPARSE is not set
# CONFIG_PKG_USING_FASTLZ is not set
# CONFIG_PKG_USING_MINILZO is not set
# CONFIG_PKG_USING_QUICKLZ is not set
# CONFIG_PKG_USING_MULTIBUTTON is not set
# CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set
# CONFIG_PKG_USING_CANFESTIVAL is not set
# CONFIG_PKG_USING_ZLIB is not set
# CONFIG_PKG_USING_DSTR is not set
# CONFIG_PKG_USING_TINYFRAME is not set
# CONFIG_PKG_USING_KENDRYTE_DEMO is not set
# CONFIG_PKG_USING_DIGITALCTRL is not set
# CONFIG_PKG_USING_UPACKER is not set
# CONFIG_PKG_USING_UPARAM is not set
#
# samples: kernel and components samples
#
# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set
# CONFIG_PKG_USING_NETWORK_SAMPLES is not set
# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set
# CONFIG_PKG_USING_HELLO is not set
# CONFIG_PKG_USING_VI is not set
# CONFIG_PKG_USING_KI is not set
# CONFIG_PKG_USING_NNOM is not set
# CONFIG_PKG_USING_LIBANN is not set
# CONFIG_PKG_USING_ELAPACK is not set
# CONFIG_PKG_USING_ARMv7M_DWT is not set
# CONFIG_PKG_USING_VT100 is not set
# CONFIG_PKG_USING_TETRIS is not set
# CONFIG_PKG_USING_ULAPACK is not set
# CONFIG_PKG_USING_UKAL is not set
# CONFIG_PKG_USING_CRCLIB is not set
# CONFIG_PKG_USING_THREES is not set
# CONFIG_PKG_USING_2048 is not set
# CONFIG_PKG_USING_LWGPS is not set
# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set
CONFIG_SOC_ZYNQMP_R5=y
#
# Hardware Drivers Config
#
#
# Onboard Peripheral Drivers
#
#
# On-chip Peripheral Drivers
#
CONFIG_BSP_USING_UART=y
CONFIG_BSP_USING_UART0=y
CONFIG_BSP_USING_SDIO=y
CONFIG_BSP_USING_SD0=y
#
# Board extended module Drivers
#

View File

@ -0,0 +1,27 @@
mainmenu "RT-Thread Project Configuration"
config BSP_DIR
string
option env="BSP_ROOT"
default "."
config RTT_DIR
string
option env="RTT_ROOT"
default "../.."
config PKGS_DIR
string
option env="PKGS_ROOT"
default "packages"
source "$RTT_DIR/Kconfig"
source "$PKGS_DIR/Kconfig"
config SOC_ZYNQMP_R5
bool
select RT_USING_COMPONENTS_INIT
select RT_USING_USER_MAIN
default y
source "$BSP_DIR/drivers/Kconfig"

View File

@ -0,0 +1,112 @@
# AXU4EV-E BSP (Board Support Package) Execution Instruction
[中文页](README_zh.md) |
## **Introduction**
This document records the execution instruction of the BSP (board support package) for the AXU4EV-E development board.
The document is covered in three parts:
- AXU4EV-E Board Resources Introduction
- Quickly Get Started
- Advanced Features
- BSP Migration
By reading the Quickly Get Started section developers can quickly get their hands on this BSP and run RT-Thread on the board. More advanced features will be introduced in the Advanced Features section to help developers take advantage of RT-Thread to drive more on-board resources.
## AXU4EV-E Resources Introduction
ALINX AXU4EV-E: Xilinx Zynq UltraScale+ MPSOC XCZU4EV-1SFVC784I Ethernet FPGA development board, the SoM Core board is the smallest system, mainly composed of XCZU4EV-1SFVC784I + 5 DDR4 + eMMC + 1 QSPI FLASH. The Carrier board expands a wealth of peripheral interfaces for the core board, including 1 SATA M.2 interface, 1 DP output interface, 4 USB3.0 interfaces, 2 Gigabit Ethernet interfaces, 2 UART interfaces, 1 SD card interface, 2*40-pin Expansion Connectors for Modules, 2 CAN bus interfaces, 2 RS485 interfaces, 1 MIPI interface, Keys and LEDs. High-speed data exchange and transmission, data storage, pre-verification and post-application of data processing, video transmission processing, deep learning, artificial intelligence and industrial control, is a professional ZYNQ development platform. suitable for students, engineers and other groups engaged in the development of MPSoCs.
For more details about this board, please refer to [Alinx Electronic Technology (Shanghai) Co.,Ltd.](http://www.alinx.com/en/)。
## **Peripheral Condition**
Each peripheral supporting condition for this BSP is as follows:
| **Core** | **Support** | **Remark** |
| :----------------- | :----------: | :------------------------------------- |
| R5-CPU0 | Support | The R5-CPU0 is running the system |
| **On-board Peripherals** | **Support** | **Remark** |
| None | | |
| **On-chip Peripherals** | **Support** | **Remark** |
| GPIO | Support | |
| UART | Support | UART0 |
| TIMER | Support | TTC0 provides system clock |
| EMMC | Support | SD0 Controller |
## Execution Instruction
### Quickly Get Started
This BSP only support the GCC development environment. Here's an example to introduce how to run the system.
#### Compile and Download
1. Open the env tool under BSP. Enter `scons` to compile.
2. After compiling, `rtthread-zynqmp-r5.elf` file will be generated in BSP directory.
3. Use Xilinx Vitis to generate fsbl, and then create "Debug Configuration", select the `rtthread-zynqmp-r5.elf` file as the application.
4. Use the debugger to connect the PC and the development board. Set the dial switch to JTAG to start. Then connect the power supply. Click start debugging or running.
Since the compiler has debugging information by default (see rtconfig.py In BUILD, so when debugging in Xilinx Vitis, you can also open source files to set breakpoints for debugging.
#### Software Solidification
1. Open the env tool under BSP. Enter `scons` to compile.
2. After compiling, `rtthread-zynqmp-r5.elf` file will be generated in BSP directory.
3. Use Xilinx Vitis or Xilinx SDK to generate fsbl, and then use the bootgen tool provided by Xilinx to make fsbl BOOT.bin Documents.
For example, use the command line:
```
bootgen -image ./output.bif -arch zynqmp -o ./BOOT.bin -w on
```
And the outpu.bif file could be
```
//arch = zynqmp; split = false; format = BIN
the_ROM_image:
{
[bootloader, destination_cpu = r5-0]./fsbl.elf
[destination_cpu = r5-0, exception_level = el-3]./rtthread-zynqmp-r5.elf
}
```
4. According to the document provided by Alinx, put BOOT.bin into SD card or burn to QSPI flash, set the startup mode through dial switch, and then connect the power supply to start.
#### Running Results
Once the project is successfully downloaded, the system runs automatically.
Connect the serial port of the board to PC, communicate with it via a serial terminal tool (115200bps, 8N1). Restart the board and the startup information of RT-Thread will be observed:
```bash
\ | /
- RT - Thread Operating System
/ | \ 4.0.3 build Nov 27 2020
2006 - 2020 Copyright by rt-thread team
msh />
```
### **Advanced Features**
This BSP enables EMMC driver and DFS file system by default. If you need to use a file system, you can format and mount it by yourself.
## BSP Migration
If you need to ported the BSP to another development board of Xilinx Zynq UltraScale+ MPSOC development platform, it is also convenient. The main modifications are as follows:
1. Memory: `psu_r5_ddr_0_MEM_0` in `zynqmp-r5.ld` (if DDR memory is less than 2G)
2. Main Frequency: `XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ` in `zynqmp-r5.h`
3. Pin and Frequency of Serial Port: `rxmio`, `txmio` and `XPAR_PSU_UART_0_UART_CLK_FREQ_HZ` in `drv_uart.c`
4. Timer Frequency: `XPAR_PSU_TTC_0_TTC_CLK_FREQ_HZ` in `drv_timer.c`
5. SD Controller: Block device driver initialization in `drv_sdcard.c`
The parameter macro definition in `xparameters.h` does not need to be modified manually. You can directly copy the `xparameters.h` file of the development board generated in Xilinx Vitis.

View File

@ -0,0 +1,133 @@
# AXU4EV-E 开发板 BSP 说明
## 简介
本文档是为 AXU4EV-E 开发板提供的 BSP (板级支持包) 说明。
主要内容如下:
- 开发板资源介绍
- BSP 快速上手
- 进阶使用方法
通过阅读快速上手章节开发者可以快速地上手该 BSP将 RT-Thread 运行在开发板上。在进阶使用指南章节,将会介绍更多高级功能,帮助开发者利用 RT-Thread 驱动更多板载资源。
## 开发板介绍
AXU4EV-E 开发板是 芯驿电子科技(上海)有限公司 推出的一款基于 XILINX Zynq UltraScale+ MPSoCs 开发平台的开发板。这款 MPSoCs 开发平台采用核心板加扩展板的模式,方便用户对核心板的二次开发利用。核心板使用 XILINX Zynq UltraScale+ EV 芯片 ZU4EV 的解决方案它采用Processing System(PS)+Programmable Logic(PL)技术将四核ARM Cortex-A53 和FPGA 可编程逻辑集成在一颗芯片上。另外核心板上 PS 端带有 4 片共 4GB 高速 DDR4 SDRAM 芯片1 片 8GB的 eMMC 存储芯片和 1 片 256Mb 的 QSPI FLASH 芯片;核心板上 PL 端带有 1 片 1GB 的DDR4 SDRAM 芯片 。
开发板更多详细信息请参考[芯驿电子科技(上海)有限公司](http://www.alinx.cn/)。
## 外设支持
本 BSP 目前对外设的支持情况如下:
| **核心** | **支持情况** | **备注** |
| :----------------- | :----------: | :------------------------------------- |
| R5-CPU0 | 支持 | 运行系统的为R5核的CPU0 |
| **板载外设** | **支持情况** | **备注** |
| 无 | | |
| **片上外设** | **支持情况** | **备注** |
| GPIO | 支持 | |
| UART | 支持 | UART0 |
| TIMER | 支持 | TTC0提供系统时钟 |
| EMMC | 支持 | SD0控制器 |
## 使用说明
使用说明分为如下两个章节:
- 快速上手
本章节是为刚接触 RT-Thread 的新手准备的使用说明,遵循简单的步骤即可将 RT-Thread 操作系统运行在该开发板上,看到实验效果 。
- 进阶使用
本章节是为需要在 RT-Thread 操作系统上使用更多开发板资源的开发者准备的。通过使用 ENV 工具对 BSP 进行配置,可以开启更多板载资源,实现更多高级功能。
### 快速上手
本 BSP 为仅支持 GCC 开发环境,下面介绍如何将系统运行起来。
#### 编译下载
1. 在 bsp 下打开 env 工具,输入`scons`进行编译。
2. 编译完成后在 bsp 目录下会生成 `rtthread-zynqmp-r5.elf` 文件。
3. 使用 Xilinx Vitis 产生 FSBL然后创建 “Debug Configuration”Application 选择`rtthread-zynqmp-r5.elf` 文件。
4. 使用调试器连接 PC 和开发板,通过拨码开关设置为 JTAG 启动,然后连接电源,点击开始调试或运行即可。
由于编译时默认带有调试信息(见 rtconfig.py 中 BUILD所以在 Xilinx Vitis 中调试时同样可以打开源文件设断点进行调试。
#### 固化程序
1. 在 bsp 下打开 env 工具,输入`scons`进行编译。
2. 编译完成后在 bsp 目录下会生成 `rtthread-zynqmp-r5.elf` 文件。
3. 使用 Xilinx Vitis 或 Xilinx SDK 产生 FSBL然后使用 Xilinx 提供的 bootgen 工具制作 BOOT.bin 文件。
例如使用命令行方式:
```
bootgen -image ./output.bif -arch zynqmp -o ./BOOT.bin -w on
```
其中 output.bif 文件可以是:
```
//arch = zynqmp; split = false; format = BIN
the_ROM_image:
{
[bootloader, destination_cpu = r5-0]./fsbl.elf
[destination_cpu = r5-0, exception_level = el-3]./rtthread-zynqmp-r5.elf
}
```
4. 根据 ALINX 提供的文档将 BOOT.bin 放进SD卡或烧录到 QSPI FLASH 中,通过拨码开关设置启动方式,然后连接电源即可启动。
#### 运行结果
下载程序成功之后,系统会自动运行。
连接开发板对应串口到 PC , 在终端工具里打开相应的串口115200-8-1-N复位设备后可以看到 RT-Thread 的输出信息:
```bash
\ | /
- RT - Thread Operating System
/ | \ 4.0.3 build Nov 27 2020
2006 - 2020 Copyright by rt-thread team
msh />
```
### 进阶使用
此 BSP 默认开启了 EMMC 驱动和 DFS 文件系统,如果需要使用文件系统可以自行格式化并挂载。
## 板级移植
如果需要将BSP移植到其他 XILINX Zynq UltraScale+ MPSoCs 开发平台的开发板上也比较方便,主要修改的地方有以下几点:
1. 内存: 如果 DDR memory 小于 2G需要修改`zynqmp-r5.ld`链接文件中的`psu_r5_ddr_0_MEM_0`
2. 主频: `xparameters.h`中的`XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ`
3. 串口引脚和频率:`drv_uart.c`中的`rxmio`, `txmio` 和`xparameters.h`中的`XPAR_PSU_UART_0_UART_CLK_FREQ_HZ`
4. 定时器频率:`xparameters.h`中的`XPAR_PSU_TTC_0_TTC_CLK_FREQ_HZ`
5. SD控制器`drv_sdcard.c`中的块设备驱动初始化
以上需要修改的`xparameters.h`中的参数宏定义不需要手动修改可以直接将Xilinx Vitis中产生的开发板的`xparameters.h`文件复制过来即可。
## 注意事项
- 无
## 联系人信息
维护人:
- [王华辰](https://github.com/Wang-Huachen/)

View File

@ -0,0 +1,14 @@
# for module compiling
import os
Import('RTT_ROOT')
cwd = str(Dir('#'))
objs = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
Return('objs')

View File

@ -0,0 +1,30 @@
import os
import sys
import rtconfig
if os.getenv('RTT_ROOT'):
RTT_ROOT = os.getenv('RTT_ROOT')
else:
RTT_ROOT = os.path.normpath(os.getcwd() + '/../..')
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
from building import *
TARGET = 'rtthread-zynqmp-r5.' + rtconfig.TARGET_EXT
DefaultEnvironment(tools=[])
env = Environment(tools = ['mingw'],
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
AR = rtconfig.AR, ARFLAGS = '-rc',
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
Export('RTT_ROOT')
Export('rtconfig')
# prepare building environment
objs = PrepareBuilding(env, RTT_ROOT)
# make a building
DoBuilding(TARGET, objs)

View File

@ -0,0 +1,11 @@
Import('RTT_ROOT')
Import('rtconfig')
from building import *
cwd = os.path.join(str(Dir('#')), 'applications')
src = Glob('*.c')
CPPPATH = [cwd, str(Dir('#'))]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,18 @@
#include <rtthread.h>
#include <rtdevice.h>
#define LED_PIN 40
int main(void)
{
rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
while (1)
{
rt_pin_write(LED_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
return RT_EOK;
}

View File

@ -0,0 +1,35 @@
menu "Hardware Drivers Config"
menu "Onboard Peripheral Drivers"
endmenu
menu "On-chip Peripheral Drivers"
menuconfig BSP_USING_UART
bool "Enable UART"
default y
select RT_USING_SERIAL
if BSP_USING_UART
config BSP_USING_UART0
bool "Enable UART0"
default y
endif
menuconfig BSP_USING_SDIO
bool "Enable SDIO"
default y
if BSP_USING_SDIO
config BSP_USING_SD0
bool "Enable SD0 EMMC"
default y
endif
endmenu
menu "Board extended module Drivers"
endmenu
endmenu

View File

@ -0,0 +1,26 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
list = os.listdir(cwd)
CPPPATH = [cwd]
objs = []
if not GetDepend('BSP_USING_UART'):
SrcRemove(src, ['drv_uart.c'])
if not GetDepend('BSP_USING_SDIO'):
SrcRemove(src, ['drv_sdcard.c'])
if not GetDepend('RT_USING_PIN'):
SrcRemove(src, ['drv_gpio.c'])
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
objs = objs + SConscript(os.path.join(d, 'SConscript'))
objs = objs + group
Return('objs')

View File

@ -0,0 +1,17 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
objs = []
group = DefineGroup('ZYNQMP_HAL', src, depend = [''], CPPPATH = CPPPATH)
if GetDepend('BSP_USING_SDIO'):
objs = objs + SConscript('sdps_v3_9/SConscript')
if GetDepend('RT_USING_PIN'):
objs = objs + SConscript('gpiops_v3_7/SConscript')
objs = objs + group
Return('objs')

View File

@ -0,0 +1,15 @@
import rtconfig
from building import *
# get current directory
cwd = GetCurrentDir()
CPPPATH = [cwd]
# The set of source files associated with this SConscript file.
src = Glob('*.c')
path = cwd
group = DefineGroup('ZYNQMP_HAL', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,808 @@
/******************************************************************************
* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xgpiops.c
* @addtogroup gpiops_v3_7
* @{
*
* The XGpioPs driver. Functions in this file are the minimum required functions
* for this driver. See xgpiops.h for a detailed description of the driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sv 01/15/10 First Release
* 1.01a sv 04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
* XGpioPs_GetMode, XGpioPs_GetModePin as they are not
* relevant to Zynq device. The interrupts are disabled
* for output pins on all banks during initialization.
* 2.1 hk 04/29/14 Use Input data register DATA_RO for read. CR# 771667.
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
* 3.1 aru 07/13/18 Resolved doxygen reported warnings. CR# 1006331.
* 3.4 aru 08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
* 3.5 sne 03/01/19 Fixes violations according to MISRAC-2012
* in safety mode and modified the code such as
* Use of mixed mode arithmetic,Declared the pointer param
* as Pointer to const,Casting operation to a pointer,
* Literal value requires a U suffix.
* 3.5 sne 03/13/19 Added Versal support.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xgpiops.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
/************************** Function Prototypes ******************************/
extern void StubHandler(void *CallBackRef, u32 Bank, u32 Status);
/*****************************************************************************/
/*
*
* This function initializes a XGpioPs instance/driver.
* All members of the XGpioPs instance structure are initialized and
* StubHandlers are assigned to the Bank Status Handlers.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param ConfigPtr points to the XGpioPs device configuration structure.
* @param EffectiveAddr is the device base address in the virtual memory
* address space. If the address translation is not used then the
* physical address should be passed.
* Unexpected errors may occur if the address mapping is changed
* after this function is invoked.
*
* @return XST_SUCCESS always.
*
* @note None.
*
******************************************************************************/
s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr,
u32 EffectiveAddr)
{
s32 Status = XST_SUCCESS;
u8 i;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(ConfigPtr != NULL);
Xil_AssertNonvoid(EffectiveAddr != (u32)0);
/*
* Set some default values for instance data, don't indicate the device
* is ready to use until everything has been initialized successfully.
*/
InstancePtr->IsReady = 0U;
InstancePtr->GpioConfig.BaseAddr = EffectiveAddr;
InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId;
InstancePtr->Handler = (XGpioPs_Handler)StubHandler;
InstancePtr->Platform = XGetPlatform_Info();
/* Initialize the Bank data based on platform */
if (InstancePtr->Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
/*
* Max pins in the ZynqMP GPIO device
* 0 - 25, Bank 0
* 26 - 51, Bank 1
* 52 - 77, Bank 2
* 78 - 109, Bank 3
* 110 - 141, Bank 4
* 142 - 173, Bank 5
*/
InstancePtr->MaxPinNum = (u32)174;
InstancePtr->MaxBanks = (u8)6;
}
else if (InstancePtr->Platform == (u32)XPLAT_VERSAL)
{
if(InstancePtr->PmcGpio == (u32)FALSE)
{
/* Max pins in the PS_GPIO devices
* 0 -25, Bank 0
* 26-57, Bank 3
*/
InstancePtr->MaxPinNum = (u32)58;
InstancePtr->MaxBanks = (u8)4;
}
else
{
/* Max pins in the PMC_GPIO devices
* 0 - 25,Bank 0
* 26 - 51,Bank 1
* 52 - 83,Bank 3
* 84 - 115, Bank 4
*/
InstancePtr->MaxPinNum = (u32)116;
InstancePtr->MaxBanks = (u8)5;
}
}
else {
/*
* Max pins in the GPIO device
* 0 - 31, Bank 0
* 32 - 53, Bank 1
* 54 - 85, Bank 2
* 86 - 117, Bank 3
*/
InstancePtr->MaxPinNum = (u32)118;
InstancePtr->MaxBanks = (u8)4;
}
/*
* By default, interrupts are not masked in GPIO. Disable
* interrupts for all pins in all the 4 banks.
*/
for (i=(u8)0U;i<InstancePtr->MaxBanks;i++) {
if (InstancePtr->Platform == XPLAT_VERSAL){
if(InstancePtr->PmcGpio == (u32)FALSE)
{
if((i== (u8)XGPIOPS_ONE)||(i== (u8)XGPIOPS_TWO))
{
continue;
}
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(i) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU);
}
else
{
if(i==(u32)XGPIOPS_TWO)
{
continue;
}
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(i) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU);
}
}
else
{
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(i) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU);
}
}
/* Indicate the component is now ready to use. */
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
return Status;
}
/****************************************************************************/
/**
*
* Read the Data register of the specified GPIO bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
*
* @return Current value of the Data register.
*
* @note This function is used for reading the state of all the GPIO pins
* of specified bank.
*
*****************************************************************************/
u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank)
{
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertNonvoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
XGPIOPS_DATA_RO_OFFSET);
}
/****************************************************************************/
/**
*
* Read Data from the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number for which the data has to be read.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
* See xgpiops.h for the mapping of the pin numbers in the banks.
*
* @return Current value of the Pin (0 or 1).
*
* @note This function is used for reading the state of the specified
* GPIO pin.
*
*****************************************************************************/
u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin)
{
u8 Bank;
u8 PinNumber;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
XGPIOPS_DATA_RO_OFFSET) >> (u32)PinNumber) & (u32)1;
}
/****************************************************************************/
/**
*
* Write to the Data register of the specified GPIO bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param Data is the value to be written to the Data register.
*
* @return None.
*
* @note This function is used for writing to all the GPIO pins of
* the bank. The previous state of the pins is not maintained.
*
*****************************************************************************/
void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertVoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_DATA_BANK_OFFSET) +
XGPIOPS_DATA_OFFSET, Data);
}
/****************************************************************************/
/**
*
* Write data to the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number to which the Data is to be written.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
* @param Data is the data to be written to the specified pin (0 or 1).
*
* @return None.
*
* @note This function does a masked write to the specified pin of
* the specified GPIO bank. The previous state of other pins
* is maintained.
*
*****************************************************************************/
void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data)
{
u32 RegOffset;
u32 Value;
u8 Bank;
u8 PinNumber;
u32 DataVar = Data;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
if (PinNumber > 15U) {
/* There are only 16 data bits in bit maskable register. */
PinNumber -= (u8)16;
RegOffset = XGPIOPS_DATA_MSW_OFFSET;
} else {
RegOffset = XGPIOPS_DATA_LSW_OFFSET;
}
/*
* Get the 32 bit value to be written to the Mask/Data register where
* the upper 16 bits is the mask and lower 16 bits is the data.
*/
DataVar &= (u32)0x01;
Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U);
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) +
RegOffset, Value);
}
/****************************************************************************/
/**
*
* Set the Direction of the pins of the specified GPIO Bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param Direction is the 32 bit mask of the Pin direction to be set for
* all the pins in the Bank. Bits with 0 are set to Input mode,
* bits with 1 are set to Output Mode.
*
* @return None.
*
* @note This function is used for setting the direction of all the pins
* in the specified bank. The previous state of the pins is
* not maintained.
*
*****************************************************************************/
void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertVoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_DIRM_OFFSET, Direction);
}
/****************************************************************************/
/**
*
* Set the Direction of the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number to which the Data is to be written.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
* @param Direction is the direction to be set for the specified pin.
* Valid values are 0 for Input Direction, 1 for Output Direction.
*
* @return None.
*
*****************************************************************************/
void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction)
{
u8 Bank;
u8 PinNumber;
u32 DirModeReg;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
Xil_AssertVoid(Direction <= (u32)1);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_DIRM_OFFSET);
if (Direction!=(u32)0) { /* Output Direction */
DirModeReg |= ((u32)1 << (u32)PinNumber);
} else { /* Input Direction */
DirModeReg &= ~ ((u32)1 << (u32)PinNumber);
}
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_DIRM_OFFSET, DirModeReg);
}
/****************************************************************************/
/**
*
* Get the Direction of the pins of the specified GPIO Bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
*
* @return Returns a 32 bit mask of the Direction register. Bits with 0 are
* in Input mode, bits with 1 are in Output Mode.
*
* @note None.
*
*****************************************************************************/
u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank)
{
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertNonvoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_DIRM_OFFSET);
}
/****************************************************************************/
/**
*
* Get the Direction of the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number for which the Direction is to be
* retrieved.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
*
* @return Direction of the specified pin.
* - 0 for Input Direction
* - 1 for Output Direction
*
* @note None.
*
*****************************************************************************/
u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin)
{
u8 Bank;
u8 PinNumber;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_DIRM_OFFSET) >> (u32)PinNumber) & (u32)1;
}
/****************************************************************************/
/**
*
* Set the Output Enable of the pins of the specified GPIO Bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param OpEnable is the 32 bit mask of the Output Enables to be set for
* all the pins in the Bank. The Output Enable of bits with 0 are
* disabled, the Output Enable of bits with 1 are enabled.
*
* @return None.
*
* @note This function is used for setting the Output Enables of all the
* pins in the specified bank. The previous state of the Output
* Enables is not maintained.
*
*****************************************************************************/
void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertVoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_OUTEN_OFFSET, OpEnable);
}
/****************************************************************************/
/**
*
* Set the Output Enable of the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number to which the Data is to be written.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
* @param OpEnable specifies whether the Output Enable for the specified
* pin should be enabled.
* Valid values are 0 for Disabling Output Enable,
* 1 for Enabling Output Enable.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable)
{
u8 Bank;
u8 PinNumber;
u32 OpEnableReg;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
Xil_AssertVoid(OpEnable <= (u32)1);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
OpEnableReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_OUTEN_OFFSET);
if (OpEnable != (u32)0) { /* Enable Output Enable */
OpEnableReg |= ((u32)1 << (u32)PinNumber);
} else { /* Disable Output Enable */
OpEnableReg &= ~ ((u32)1 << (u32)PinNumber);
}
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_OUTEN_OFFSET, OpEnableReg);
}
/****************************************************************************/
/**
*
* Get the Output Enable status of the pins of the specified GPIO Bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
*
* @return Returns a a 32 bit mask of the Output Enable register.
* Bits with 0 are in Disabled state, bits with 1 are in
* Enabled State.
*
* @note None.
*
*****************************************************************************/
u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank)
{
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertNonvoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_OUTEN_OFFSET);
}
/****************************************************************************/
/**
*
* Get the Output Enable status of the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number for which the Output Enable status is to
* be retrieved.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
*
* @return Output Enable of the specified pin.
* - 0 if Output Enable is disabled for this pin
* - 1 if Output Enable is enabled for this pin
*
* @note None.
*
*****************************************************************************/
u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin)
{
u8 Bank;
u8 PinNumber;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
return (XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_OUTEN_OFFSET) >> (u32)PinNumber) & (u32)1;
}
/****************************************************************************/
/*
*
* Get the Bank number and the Pin number in the Bank, for the given PinNumber
* in the GPIO device.
*
* @param PinNumber is the Pin number in the GPIO device.
* @param BankNumber returns the Bank in which this GPIO pin is present.
* Valid values are 0 to XGPIOPS_MAX_BANKS - 1.
* @param PinNumberInBank returns the Pin Number within the Bank.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
#ifdef versal
void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank)
#else
void XGpioPs_GetBankPin(u8 PinNumber, u8 *BankNumber, u8 *PinNumberInBank)
#endif
{
u32 XGpioPsPinTable[6] = {0};
#ifdef versal
u8 i=(u8)0;
#endif
u32 Platform = XGetPlatform_Info();
if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
/*
* This structure defines the mapping of the pin numbers to the banks when
* the driver APIs are used for working on the individual pins.
*/
XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */
XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */
XGpioPsPinTable[2] = (u32)77; /* 52 - 77, Bank 2 */
XGpioPsPinTable[3] = (u32)109; /* 78 - 109, Bank 3 */
XGpioPsPinTable[4] = (u32)141; /* 110 - 141, Bank 4 */
XGpioPsPinTable[5] = (u32)173; /* 142 - 173 Bank 5 */
*BankNumber = 0U;
while (*BankNumber < XGPIOPS_SIX) {
if (PinNumber <= XGpioPsPinTable[*BankNumber]) {
break;
}
(*BankNumber)++;
}
}
#ifdef versal
else if(Platform == XPLAT_VERSAL)
{
if(InstancePtr->PmcGpio == (u32)(FALSE))
{
XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */
XGpioPsPinTable[1] = (u32)57; /* 26 - 57, Bank 3 */
*BankNumber =0U;
if(PinNumber <= XGpioPsPinTable[*BankNumber])
{
*BankNumber = (u8)XGPIOPS_ZERO;
}
else
{
*BankNumber = (u8)XGPIOPS_THREE;
}
}
else
{
XGpioPsPinTable[0] = (u32)25; /* 0 - 25, Bank 0 */
XGpioPsPinTable[1] = (u32)51; /* 26 - 51, Bank 1 */
XGpioPsPinTable[2] = (u32)83; /* 52 - 83, Bank 3 */
XGpioPsPinTable[3] = (u32)115; /*84 - 115, Bank 4 */
*BankNumber =0U;
while(i < XGPIOPS_FOUR)
{
if(i <= (u8)XGPIOPS_ONE)
{
if (PinNumber <= XGpioPsPinTable[i])
{
*BankNumber = (u8)i;
break;
}
i++;
}
else
{
if (PinNumber <= XGpioPsPinTable[i])
{
*BankNumber = (u8)i+1U;
break;
}
i++;
}
}
}
}
#endif
else {
XGpioPsPinTable[0] = (u32)31; /* 0 - 31, Bank 0 */
XGpioPsPinTable[1] = (u32)53; /* 32 - 53, Bank 1 */
XGpioPsPinTable[2] = (u32)85; /* 54 - 85, Bank 2 */
XGpioPsPinTable[3] = (u32)117; /* 86 - 117 Bank 3 */
*BankNumber = 0U;
while (*BankNumber < XGPIOPS_FOUR) {
if (PinNumber <= XGpioPsPinTable[*BankNumber]) {
break;
}
(*BankNumber)++;
}
}
if (*BankNumber == (u8)0) {
*PinNumberInBank = PinNumber;
}
#ifdef versal
else if(Platform == XPLAT_VERSAL)
{
if(InstancePtr->PmcGpio == (u32)(FALSE))
{
*PinNumberInBank = (u8)((u32)PinNumber - (XGpioPsPinTable[0] + (u32)1));
}
else {
if((*BankNumber ==(u8)XGPIOPS_THREE) || (*BankNumber ==(u8)XGPIOPS_FOUR))
{
*PinNumberInBank = (u8)((u32)PinNumber %
(XGpioPsPinTable[*BankNumber - (u8)XGPIOPS_TWO] + (u32)1));
}
else
{
*PinNumberInBank = (u8)((u32)PinNumber %
(XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1));
}
}
}
#endif
else {
*PinNumberInBank = (u8)((u32)PinNumber %
(XGpioPsPinTable[*BankNumber - (u8)1] + (u32)1));
}
}
/** @} */

View File

@ -0,0 +1,267 @@
/******************************************************************************
* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xgpiops.h
* @addtogroup gpiops_v3_7
* @{
* @details
*
* The Xilinx PS GPIO driver. This driver supports the Xilinx PS GPIO
* Controller.
*
* The GPIO Controller supports the following features:
* - 4 banks
* - Masked writes (There are no masked reads)
* - Bypass mode
* - Configurable Interrupts (Level/Edge)
*
* This driver is intended to be RTOS and processor independent. Any needs for
* dynamic memory management, threads or thread mutual exclusion, virtual
* memory, or cache control must be satisfied by the layer above this driver.
* This driver supports all the features listed above, if applicable.
*
* <b>Driver Description</b>
*
* The device driver enables higher layer software (e.g., an application) to
* communicate to the GPIO.
*
* <b>Interrupts</b>
*
* The driver provides interrupt management functions and an interrupt handler.
* Users of this driver need to provide callback functions. An interrupt handler
* example is available with the driver.
*
* <b>Threads</b>
*
* This driver is not thread safe. Any needs for threads or thread mutual
* exclusion must be satisfied by the layer above this driver.
*
* <b>Asserts</b>
*
* Asserts are used within all Xilinx drivers to enforce constraints on argument
* values. Asserts can be turned off on a system-wide basis by defining, at
* compile time, the NDEBUG identifier. By default, asserts are turned on and it
* is recommended that users leave asserts on during development.
*
* <b>Building the driver</b>
*
* The XGpioPs driver is composed of several source files. This allows the user
* to build and link only those parts of the driver that are necessary.
* <br><br>
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sv 01/15/10 First Release
* 1.01a sv 04/15/12 Removed the APIs XGpioPs_SetMode, XGpioPs_SetModePin
* XGpioPs_GetMode, XGpioPs_GetModePin as they are not
* relevant to Zynq device.The interrupts are disabled
* for output pins on all banks during initialization.
* 1.02a hk 08/22/13 Added low level reset API
* 2.1 hk 04/29/14 Use Input data register DATA_RO for read. CR# 771667.
* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number
* passed to APIs. CR# 822636
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
* ms 03/17/17 Added readme.txt file in examples folder for doxygen
* generation.
* ms 04/05/17 Added tabspace for return statements in functions of
* gpiops examples for proper documentation while
* generating doxygen.
* 3.3 ms 04/17/17 Added notes about gpio input and output pin description
* for zcu102 and zc702 boards in polled and interrupt
* example, configured Interrupt pin to input pin for
* proper functioning of interrupt example.
* 3.4 aru 08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
* 3.5 sne 03/01/19 Fixes violations according to MISRAC-2012
* in safety mode and modified the code such as
* Use of mixed mode arithmetic,Declared the pointer param
* as Pointer to const,Casting operation to a pointer,
* Literal value requires a U suffix.
* 3.5 sne 03/14/19 Added Versal support.
* 3.6 mus 04/05/19 Replaced XPLAT_versal macro with XPLAT_VERSAL, to be in
* sync with standalone BSP
* 3.6 sne 06/12/19 Fixed IAR compiler warning.
* 3.6 sne 08/14/19 Added interrupt handler support on versal.
* 3.7 sne 12/04/19 Reverted versal examples support.
*
* </pre>
*
******************************************************************************/
#ifndef XGPIOPS_H /* prevent circular inclusions */
#define XGPIOPS_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xstatus.h"
#include "xgpiops_hw.h"
#include "xplatform_info.h"
/************************** Constant Definitions *****************************/
/** @name Interrupt types
* @{
* The following constants define the interrupt types that can be set for each
* GPIO pin.
*/
#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */
#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */
#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */
#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */
#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */
/*@}*/
#define XGPIOPS_BANK_MAX_PINS (u32)32 /**< Max pins in a GPIO bank */
#define XGPIOPS_BANK0 0x00U /**< GPIO Bank 0 */
#define XGPIOPS_BANK1 0x01U /**< GPIO Bank 1 */
#define XGPIOPS_BANK2 0x02U /**< GPIO Bank 2 */
#define XGPIOPS_BANK3 0x03U /**< GPIO Bank 3 */
#ifdef XPAR_PSU_GPIO_0_BASEADDR
#define XGPIOPS_BANK4 0x04U /**< GPIO Bank 4 */
#define XGPIOPS_BANK5 0x05U /**< GPIO Bank 5 */
#endif
#define XGPIOPS_MAX_BANKS_ZYNQMP 0x06U /**< Max banks in a
* Zynq Ultrascale+ MP GPIO device
*/
#define XGPIOPS_MAX_BANKS 0x04U /**< Max banks in a Zynq GPIO device */
#define XGPIOPS_DEVICE_MAX_PIN_NUM_ZYNQMP (u32)174 /**< Max pins in the
* Zynq Ultrascale+ MP GPIO device
* 0 - 25, Bank 0
* 26 - 51, Bank 1
* 52 - 77, Bank 2
* 78 - 109, Bank 3
* 110 - 141, Bank 4
* 142 - 173, Bank 5
*/
#define XGPIOPS_DEVICE_MAX_PIN_NUM (u32)118 /**< Max pins in the Zynq GPIO device
* 0 - 31, Bank 0
* 32 - 53, Bank 1
* 54 - 85, Bank 2
* 86 - 117, Bank 3
*/
/**************************** Type Definitions *******************************/
/****************************************************************************/
/**
* This handler data type allows the user to define a callback function to
* handle the interrupts for the GPIO device. The application using this
* driver is expected to define a handler of this type, to support interrupt
* driven mode. The handler executes in an interrupt context such that minimal
* processing should be performed.
*
* @param CallBackRef is a callback reference passed in by the upper layer
* when setting the callback functions for a GPIO bank. It is
* passed back to the upper layer when the callback is invoked. Its
* type is not important to the driver component, so it is a void
* pointer.
* @param Bank is the bank for which the interrupt status has changed.
* @param Status is the Interrupt status of the GPIO bank.
*
*****************************************************************************/
typedef void (*XGpioPs_Handler) (void *CallBackRef, u32 Bank, u32 Status);
/**
* This typedef contains configuration information for a device.
*/
typedef struct {
u16 DeviceId; /**< Unique ID of device */
u32 BaseAddr; /**< Register base address */
} XGpioPs_Config;
/**
* The XGpioPs driver instance data. The user is required to allocate a
* variable of this type for the GPIO device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct {
XGpioPs_Config GpioConfig; /**< Device configuration */
u32 IsReady; /**< Device is initialized and ready */
XGpioPs_Handler Handler; /**< Status handlers for all banks */
void *CallBackRef; /**< Callback ref for bank handlers */
u32 Platform; /**< Platform data */
u32 MaxPinNum; /**< Max pins in the GPIO device */
u8 MaxBanks; /**< Max banks in a GPIO device */
u32 PmcGpio; /**< Flag for accessing PS GPIO for versal*/
} XGpioPs;
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/* Functions in xgpiops.c */
s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config *ConfigPtr,
u32 EffectiveAddr);
/* Bank APIs in xgpiops.c */
u32 XGpioPs_Read(const XGpioPs *InstancePtr, u8 Bank);
void XGpioPs_Write(const XGpioPs *InstancePtr, u8 Bank, u32 Data);
void XGpioPs_SetDirection(const XGpioPs *InstancePtr, u8 Bank, u32 Direction);
u32 XGpioPs_GetDirection(const XGpioPs *InstancePtr, u8 Bank);
void XGpioPs_SetOutputEnable(const XGpioPs *InstancePtr, u8 Bank, u32 OpEnable);
u32 XGpioPs_GetOutputEnable(const XGpioPs *InstancePtr, u8 Bank);
#ifdef versal
void XGpioPs_GetBankPin(const XGpioPs *InstancePtr,u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank);
#else
void XGpioPs_GetBankPin(u8 PinNumber,u8 *BankNumber, u8 *PinNumberInBank);
#endif
/* Pin APIs in xgpiops.c */
u32 XGpioPs_ReadPin(const XGpioPs *InstancePtr, u32 Pin);
void XGpioPs_WritePin(const XGpioPs *InstancePtr, u32 Pin, u32 Data);
void XGpioPs_SetDirectionPin(const XGpioPs *InstancePtr, u32 Pin, u32 Direction);
u32 XGpioPs_GetDirectionPin(const XGpioPs *InstancePtr, u32 Pin);
void XGpioPs_SetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin, u32 OpEnable);
u32 XGpioPs_GetOutputEnablePin(const XGpioPs *InstancePtr, u32 Pin);
/* Diagnostic functions in xgpiops_selftest.c */
s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr);
/* Functions in xgpiops_intr.c */
/* Bank APIs in xgpiops_intr.c */
void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask);
void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask);
u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank);
u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank);
void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask);
void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType,
u32 IntrPolarity, u32 IntrOnAny);
void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType,
u32 *IntrPolarity, u32 *IntrOnAny);
void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef,
XGpioPs_Handler FuncPointer);
void XGpioPs_IntrHandler(const XGpioPs *InstancePtr);
/* Pin APIs in xgpiops_intr.c */
void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType);
u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin);
void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin);
void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin);
u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin);
u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin);
void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin);
/* Functions in xgpiops_sinit.c */
XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/** @} */

View File

@ -0,0 +1,31 @@
/*******************************************************************
*
* CAUTION: This file is automatically generated by HSI.
* Version: 2020.1
* DO NOT EDIT.
*
* Copyright (C) 2010-2020 Xilinx, Inc. All Rights Reserved.
* SPDX-License-Identifier: MIT
*
* Description: Driver configuration
*
*******************************************************************/
#include "xparameters.h"
#include "xgpiops.h"
/*
* The configuration table for devices
*/
XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] =
{
{
XPAR_PSU_GPIO_0_DEVICE_ID,
XPAR_PSU_GPIO_0_BASEADDR
}
};

View File

@ -0,0 +1,240 @@
/******************************************************************************
* Copyright (C) 2013 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xgpiops_hw.c
* @addtogroup gpiops_v3_7
* @{
*
* This file contains low level GPIO functions.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.02a hk 08/22/13 First Release
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
* 3.5 sne 03/01/19 Fixes violations according to MISRAC-2012
* in safety mode and modified the code such as
* Use of mixed mode arithmetic,Declared the pointer param
* as Pointer to const,Casting operation to a pointer,
* Literal value requires a U suffix.
* 3.5 sne 03/14/19 Added versal support.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xgpiops_hw.h"
#include "xgpiops.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
/************************** Function Prototypes ******************************/
/*****************************************************************************/
/*
*
* This function resets the GPIO module by writing reset values to
* all registers
*
* @param Base address of GPIO module
*
* @return None
*
* @note None.
*
******************************************************************************/
void XGpioPs_ResetHw(u32 BaseAddress)
{
u32 BankCount;
u32 Platform,MaxBanks;
Platform = XGetPlatform_Info();
if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
MaxBanks = (u32)6;
}
else if(Platform == (u32)XPLAT_VERSAL)
{
if (BaseAddress == (u32)XGPIOPS_PS_GPIO_BASEADDR)
{
MaxBanks = (u32)4;
}
else
{
MaxBanks = (u32)5;
}
}
else {
MaxBanks = (u32)4;
}
if (Platform == (u32)XPLAT_VERSAL)
{
/* Write reset values to all mask data registers */
for(BankCount = 3U; BankCount < (u32)MaxBanks; BankCount++) {
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_DATA_MASK_OFFSET) +
XGPIOPS_DATA_LSW_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_DATA_MASK_OFFSET) +
XGPIOPS_DATA_MSW_OFFSET), 0x0U);
}
/* Write reset values to all output data registers */
for(BankCount = 3U; BankCount < (u32)MaxBanks; BankCount++) {
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_DATA_BANK_OFFSET) +
XGPIOPS_DATA_OFFSET), 0x0U);
}
/* Reset all registers of all GPIO banks */
for(BankCount = 0U; BankCount < (u32)MaxBanks; BankCount++) {
if((BaseAddress == (u32)XGPIOPS_PS_GPIO_BASEADDR) && ((BankCount == (u32)XGPIOPS_ONE) ||(BankCount == (u32)XGPIOPS_TWO)))
{
continue;
}
else
{
if((BaseAddress != (u32)XGPIOPS_PS_GPIO_BASEADDR) && (BankCount == (u32)XGPIOPS_ONE))
{
continue;
}
}
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_DIRM_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_OUTEN_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTMASK_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTEN_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTDIS_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTSTS_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTPOL_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTANY_OFFSET), 0x0U);
}
/* Bank 0 Int type */
XGpioPs_WriteReg(BaseAddress, XGPIOPS_INTTYPE_OFFSET,
XGPIOPS_INTTYPE_BANK0_RESET);
/* Bank 1 Int type */
XGpioPs_WriteReg(BaseAddress,
((u32)XGPIOPS_REG_MASK_OFFSET + (u32)XGPIOPS_INTTYPE_OFFSET),
XGPIOPS_INTTYPE_BANK1_RESET);
/* Bank 3 Int type */
XGpioPs_WriteReg(BaseAddress,
(((u32)3 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET),
XGPIOPS_INTTYPE_BANK3_RESET);
/* Bank 4 Int type */
XGpioPs_WriteReg(BaseAddress,
(((u32)4 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET),
XGPIOPS_INTTYPE_BANK4_RESET);
}
else
{
/* Write reset values to all mask data registers */
for(BankCount = 2U; BankCount < (u32)MaxBanks; BankCount++) {
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_DATA_MASK_OFFSET) +
XGPIOPS_DATA_LSW_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_DATA_MASK_OFFSET) +
XGPIOPS_DATA_MSW_OFFSET), 0x0U);
}
/* Write reset values to all output data registers */
for(BankCount = 2U; BankCount < (u32)MaxBanks; BankCount++) {
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_DATA_BANK_OFFSET) +
XGPIOPS_DATA_OFFSET), 0x0U);
}
/* Reset all registers of all GPIO banks */
for(BankCount = 0U; BankCount < (u32)MaxBanks; BankCount++) {
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_DIRM_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_OUTEN_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTMASK_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTEN_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTDIS_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTSTS_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTPOL_OFFSET), 0x0U);
XGpioPs_WriteReg(BaseAddress,
((BankCount * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTANY_OFFSET), 0x0U);
}
/* Bank 0 Int type */
XGpioPs_WriteReg(BaseAddress, XGPIOPS_INTTYPE_OFFSET,
XGPIOPS_INTTYPE_BANK0_RESET);
/* Bank 1 Int type */
XGpioPs_WriteReg(BaseAddress,
((u32)XGPIOPS_REG_MASK_OFFSET + (u32)XGPIOPS_INTTYPE_OFFSET),
XGPIOPS_INTTYPE_BANK1_RESET);
/* Bank 2 Int type */
XGpioPs_WriteReg(BaseAddress,
(((u32)2 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET),
XGPIOPS_INTTYPE_BANK2_RESET);
/* Bank 3 Int type */
XGpioPs_WriteReg(BaseAddress,
(((u32)3 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET),
XGPIOPS_INTTYPE_BANK3_RESET);
if (Platform == (u32)XPLAT_ZYNQ_ULTRA_MP) {
/* Bank 4 Int type */
XGpioPs_WriteReg(BaseAddress,
(((u32)4 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET),
XGPIOPS_INTTYPE_BANK4_RESET);
/* Bank 5 Int type */
XGpioPs_WriteReg(BaseAddress,
(((u32)5 * XGPIOPS_REG_MASK_OFFSET) + XGPIOPS_INTTYPE_OFFSET),
XGPIOPS_INTTYPE_BANK5_RESET);
}
}
}
/** @} */

View File

@ -0,0 +1,146 @@
/******************************************************************************
* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xgpiops_hw.h
* @addtogroup gpiops_v3_7
* @{
*
* This header file contains the identifiers and basic driver functions (or
* macros) that can be used to access the device. Other driver functions
* are defined in xgpiops.h.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------
* 1.00a sv 01/15/10 First Release
* 1.02a hk 08/22/13 Added low level reset API function prototype and
* related constant definitions
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
* 3.1 kvn 04/13/15 Corrected reset values of banks.
* 3.5 sne 03/14/19 Added versal support.
* </pre>
*
******************************************************************************/
#ifndef XGPIOPS_HW_H /* prevent circular inclusions */
#define XGPIOPS_HW_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
/************************** Constant Definitions *****************************/
/** @name Register offsets for the GPIO. Each register is 32 bits.
* @{
*/
#define XGPIOPS_DATA_LSW_OFFSET 0x00000000U /* Mask and Data Register LSW, WO */
#define XGPIOPS_DATA_MSW_OFFSET 0x00000004U /* Mask and Data Register MSW, WO */
#define XGPIOPS_DATA_OFFSET 0x00000040U /* Data Register, RW */
#define XGPIOPS_DATA_RO_OFFSET 0x00000060U /* Data Register - Input, RO */
#define XGPIOPS_DIRM_OFFSET 0x00000204U /* Direction Mode Register, RW */
#define XGPIOPS_OUTEN_OFFSET 0x00000208U /* Output Enable Register, RW */
#define XGPIOPS_INTMASK_OFFSET 0x0000020CU /* Interrupt Mask Register, RO */
#define XGPIOPS_INTEN_OFFSET 0x00000210U /* Interrupt Enable Register, WO */
#define XGPIOPS_INTDIS_OFFSET 0x00000214U /* Interrupt Disable Register, WO*/
#define XGPIOPS_INTSTS_OFFSET 0x00000218U /* Interrupt Status Register, RO */
#define XGPIOPS_INTTYPE_OFFSET 0x0000021CU /* Interrupt Type Register, RW */
#define XGPIOPS_INTPOL_OFFSET 0x00000220U /* Interrupt Polarity Register, RW */
#define XGPIOPS_INTANY_OFFSET 0x00000224U /* Interrupt On Any Register, RW */
/* @} */
/** @name Register offsets for each Bank.
* @{
*/
#define XGPIOPS_DATA_MASK_OFFSET 0x00000008U /* Data/Mask Registers offset */
#define XGPIOPS_DATA_BANK_OFFSET 0x00000004U /* Data Registers offset */
#define XGPIOPS_REG_MASK_OFFSET 0x00000040U /* Registers offset */
/* @} */
/* For backwards compatibility */
#define XGPIOPS_BYPM_MASK_OFFSET (u32)0x40
/** @name Interrupt type reset values for each bank
* @{
*/
#ifdef XPAR_PSU_GPIO_0_BASEADDR
#define XGPIOPS_INTTYPE_BANK0_RESET 0x03FFFFFFU /* Resets specific to Zynq Ultrascale+ MP */
#define XGPIOPS_INTTYPE_BANK1_RESET 0x03FFFFFFU
#define XGPIOPS_INTTYPE_BANK2_RESET 0x03FFFFFFU
#else
#define XGPIOPS_INTTYPE_BANK0_RESET 0xFFFFFFFFU /* Resets specific to Zynq */
#define XGPIOPS_INTTYPE_BANK1_RESET 0x003FFFFFU
#define XGPIOPS_INTTYPE_BANK2_RESET 0xFFFFFFFFU
#endif
#define XGPIOPS_INTTYPE_BANK3_RESET 0xFFFFFFFFU /* Reset common to both platforms */
#define XGPIOPS_INTTYPE_BANK4_RESET 0xFFFFFFFFU /* Resets specific to Zynq Ultrascale+ MP */
#define XGPIOPS_INTTYPE_BANK5_RESET 0xFFFFFFFFU
/* @} */
#define XGPIOPS_PS_GPIO_BASEADDR 0xFF0B0000U /* Flag for Base Address for PS_GPIO in Versal */
#define XGPIOPS_ZERO 0U /* Flag for 0 Value */
#define XGPIOPS_ONE 1U /* Flag for 1 Value */
#define XGPIOPS_TWO 2U /* Flag for 2 Value */
#define XGPIOPS_THREE 3U /* Flag for 3 Value */
#define XGPIOPS_FOUR 4U /* Flag for 4 Value */
#define XGPIOPS_SIX 6U /* Flag for 6 Value */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/****************************************************************************/
/**
*
* This macro reads the given register.
*
* @param BaseAddr is the base address of the device.
* @param RegOffset is the register offset to be read.
*
* @return The 32-bit value of the register
*
* @note None.
*
*****************************************************************************/
#define XGpioPs_ReadReg(BaseAddr, RegOffset) \
Xil_In32((BaseAddr) + (u32)(RegOffset))
/****************************************************************************/
/**
*
* This macro writes to the given register.
*
* @param BaseAddr is the base address of the device.
* @param RegOffset is the offset of the register to be written.
* @param Data is the 32-bit value to write to the register.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) \
Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data))
/************************** Function Prototypes ******************************/
void XGpioPs_ResetHw(u32 BaseAddress);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XGPIOPS_HW_H */
/** @} */

View File

@ -0,0 +1,805 @@
/******************************************************************************
* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xgpiops_intr.c
* @addtogroup gpiops_v3_7
* @{
*
* This file contains functions related to GPIO interrupt handling.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sv 01/18/10 First Release
* 2.2 sk 10/13/14 Used Pin number in Bank instead of pin number
* passed to API's. CR# 822636
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
* 3.1 kvn 04/13/15 Add support for Zynq Ultrascale+ MP. CR# 856980.
* 3.1 aru 07/13/18 Ressolved doxygen reported warnings. CR# 1006331.
* 3.4 aru 08/09/18 Ressolved cppcheck warnings.
* 3.4 aru 08/17/18 Resolved MISRA-C mandatory violations. CR# 1007751
* 3.5 sne 03/01/19 Fixes violations according to MISRAC-2012
* in safety mode and modified the code such as
* Use of mixed mode arithmetic,Declared the pointer param
* as Pointer to const,Casting operation to a pointer,
* Literal value requires a U suffix.
* 3.5 sne 03/14/19 Added Versal support.
* 3.5 sne 03/20/19 Fixed multiple interrupts problem CR#1024556.
* 3.6 sne 06/12/19 Fixed IAR compiler warning.
* 3.6 sne 08/14/19 Added interrupt handler support on versal.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xgpiops.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
/************************** Function Prototypes ******************************/
void StubHandler(const void *CallBackRef, u32 Bank, u32 Status);
/****************************************************************************/
/**
*
* This function enables the interrupts for the specified pins in the specified
* bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param Mask is the bit mask of the pins for which interrupts are to
* be enabled. Bit positions of 1 will be enabled. Bit positions
* of 0 will keep the previous setting.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_IntrEnable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertVoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTEN_OFFSET, Mask);
}
/****************************************************************************/
/**
*
* This function enables the interrupt for the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number for which the interrupt is to be enabled.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_IntrEnablePin(const XGpioPs *InstancePtr, u32 Pin)
{
u8 Bank;
u8 PinNumber;
u32 IntrReg;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
IntrReg = ((u32)1 << (u32)PinNumber);
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTEN_OFFSET, IntrReg);
}
/****************************************************************************/
/**
*
* This function disables the interrupts for the specified pins in the specified
* bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param Mask is the bit mask of the pins for which interrupts are
* to be disabled. Bit positions of 1 will be disabled. Bit
* positions of 0 will keep the previous setting.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_IntrDisable(const XGpioPs *InstancePtr, u8 Bank, u32 Mask)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertVoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTDIS_OFFSET, Mask);
}
/****************************************************************************/
/**
*
* This function disables the interrupts for the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number for which the interrupt is to be disabled.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_IntrDisablePin(const XGpioPs *InstancePtr, u32 Pin)
{
u8 Bank;
u8 PinNumber;
u32 IntrReg;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
IntrReg = ((u32)1 << (u32)PinNumber);
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTDIS_OFFSET, IntrReg);
}
/****************************************************************************/
/**
*
* This function returns the interrupt enable status for a bank.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
*
* @return Enabled interrupt(s) in a 32-bit format. Bit positions with 1
* indicate that the interrupt for that pin is enabled, bit
* positions with 0 indicate that the interrupt for that pin is
* disabled.
*
* @note None.
*
*****************************************************************************/
u32 XGpioPs_IntrGetEnabled(const XGpioPs *InstancePtr, u8 Bank)
{
u32 IntrMask;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertNonvoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
IntrMask = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTMASK_OFFSET);
return (~IntrMask);
}
/****************************************************************************/
/**
*
* This function returns whether interrupts are enabled for the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number for which the interrupt enable status
* is to be known.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
*
* @return
* - TRUE if the interrupt is enabled.
* - FALSE if the interrupt is disabled.
*
* @note None.
*
*****************************************************************************/
u32 XGpioPs_IntrGetEnabledPin(const XGpioPs *InstancePtr, u32 Pin)
{
u8 Bank;
u8 PinNumber;
u32 IntrReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTMASK_OFFSET);
return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? FALSE : TRUE);
}
/****************************************************************************/
/**
*
* This function returns interrupt status read from Interrupt Status Register.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
*
* @return The value read from Interrupt Status Register.
*
* @note None.
*
*****************************************************************************/
u32 XGpioPs_IntrGetStatus(const XGpioPs *InstancePtr, u8 Bank)
{
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertNonvoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertNonvoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
return XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTSTS_OFFSET);
}
/****************************************************************************/
/**
*
* This function returns interrupt enable status of the specified pin.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number for which the interrupt enable status
* is to be known.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
*
* @return
* - TRUE if the interrupt has occurred.
* - FALSE if the interrupt has not occurred.
*
* @note None.
*
*****************************************************************************/
u32 XGpioPs_IntrGetStatusPin(const XGpioPs *InstancePtr, u32 Pin)
{
u8 Bank;
u8 PinNumber;
u32 IntrReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTSTS_OFFSET);
return (((IntrReg & ((u32)1 << PinNumber)) != (u32)0)? TRUE : FALSE);
}
/****************************************************************************/
/**
*
* This function clears pending interrupt(s) with the provided mask. This
* function should be called after the software has serviced the interrupts
* that are pending.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param Mask is the mask of the interrupts to be cleared. Bit positions
* of 1 will be cleared. Bit positions of 0 will not change the
* previous interrupt status.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_IntrClear(const XGpioPs *InstancePtr, u8 Bank, u32 Mask)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertVoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
/* Clear the currently pending interrupts. */
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTSTS_OFFSET, Mask);
}
/****************************************************************************/
/**
*
* This function clears the specified pending interrupt. This function should be
* called after the software has serviced the interrupts that are pending.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param Pin is the pin number for which the interrupt status is to be
* cleared. Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_IntrClearPin(const XGpioPs *InstancePtr, u32 Pin)
{
u8 Bank;
u8 PinNumber;
u32 IntrReg;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
/* Clear the specified pending interrupts. */
IntrReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTSTS_OFFSET);
IntrReg &= ((u32)1 << PinNumber);
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTSTS_OFFSET, IntrReg);
}
/****************************************************************************/
/**
*
* This function is used for setting the Interrupt Type, Interrupt Polarity and
* Interrupt On Any for the specified GPIO Bank pins.
*
* @param InstancePtr is a pointer to an XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param IntrType is the 32 bit mask of the interrupt type.
* 0 means Level Sensitive and 1 means Edge Sensitive.
* @param IntrPolarity is the 32 bit mask of the interrupt polarity.
* 0 means Active Low or Falling Edge and 1 means Active High or
* Rising Edge.
* @param IntrOnAny is the 32 bit mask of the interrupt trigger for
* edge triggered interrupts. 0 means trigger on single edge using
* the configured interrupt polarity and 1 means trigger on both
* edges.
*
* @return None.
*
* @note This function is used for setting the interrupt related
* properties of all the pins in the specified bank. The previous
* state of the pins is not maintained.
* To change the Interrupt properties of a single GPIO pin, use the
* function XGpioPs_SetPinIntrType().
*
*****************************************************************************/
void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType,
u32 IntrPolarity, u32 IntrOnAny)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertVoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTTYPE_OFFSET, IntrType);
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTPOL_OFFSET, IntrPolarity);
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTANY_OFFSET, IntrOnAny);
}
/****************************************************************************/
/**
*
* This function is used for getting the Interrupt Type, Interrupt Polarity and
* Interrupt On Any for the specified GPIO Bank pins.
*
* @param InstancePtr is a pointer to an XGpioPs instance.
* @param Bank is the bank number of the GPIO to operate on.
* Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP.
* @param IntrType returns the 32 bit mask of the interrupt type.
* 0 means Level Sensitive and 1 means Edge Sensitive.
* @param IntrPolarity returns the 32 bit mask of the interrupt
* polarity. 0 means Active Low or Falling Edge and 1 means
* Active High or Rising Edge.
* @param IntrOnAny returns the 32 bit mask of the interrupt trigger for
* edge triggered interrupts. 0 means trigger on single edge using
* the configured interrupt polarity and 1 means trigger on both
* edges.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_GetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 *IntrType,
u32 *IntrPolarity, u32 *IntrOnAny)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Bank < InstancePtr->MaxBanks);
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
Xil_AssertVoid(Bank != XGPIOPS_TWO);
} else {
Xil_AssertVoid((Bank !=XGPIOPS_ONE) && (Bank !=XGPIOPS_TWO));
}
#endif
*IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTTYPE_OFFSET);
*IntrPolarity = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTPOL_OFFSET);
*IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTANY_OFFSET);
}
/****************************************************************************/
/**
*
* This function is used for setting the IRQ Type of a single GPIO pin.
*
* @param InstancePtr is a pointer to an XGpioPs instance.
* @param Pin is the pin number whose IRQ type is to be set.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
* @param IrqType is the IRQ type for GPIO Pin. Use XGPIOPS_IRQ_TYPE_*
* defined in xgpiops.h to specify the IRQ type.
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XGpioPs_SetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin, u8 IrqType)
{
u32 IntrTypeReg;
u32 IntrPolReg;
u32 IntrOnAnyReg;
u8 Bank;
u8 PinNumber;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Pin < InstancePtr->MaxPinNum);
Xil_AssertVoid(IrqType <= XGPIOPS_IRQ_TYPE_LEVEL_LOW);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
IntrTypeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTTYPE_OFFSET);
IntrPolReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTPOL_OFFSET);
IntrOnAnyReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTANY_OFFSET);
switch (IrqType) {
case XGPIOPS_IRQ_TYPE_EDGE_RISING:
IntrTypeReg |= ((u32)1 << (u32)PinNumber);
IntrPolReg |= ((u32)1 << (u32)PinNumber);
IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber);
break;
case XGPIOPS_IRQ_TYPE_EDGE_FALLING:
IntrTypeReg |= ((u32)1 << (u32)PinNumber);
IntrPolReg &= ~((u32)1 << (u32)PinNumber);
IntrOnAnyReg &= ~((u32)1 << (u32)PinNumber);
break;
case XGPIOPS_IRQ_TYPE_EDGE_BOTH:
IntrTypeReg |= ((u32)1 << (u32)PinNumber);
IntrOnAnyReg |= ((u32)1 << (u32)PinNumber);
break;
case XGPIOPS_IRQ_TYPE_LEVEL_HIGH:
IntrTypeReg &= ~((u32)1 << (u32)PinNumber);
IntrPolReg |= ((u32)1 << (u32)PinNumber);
break;
case XGPIOPS_IRQ_TYPE_LEVEL_LOW:
IntrTypeReg &= ~((u32)1 << (u32)PinNumber);
IntrPolReg &= ~((u32)1 << (u32)PinNumber);
break;
default:
/**< Default statement is added for MISRA C compliance. */
break;
}
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTTYPE_OFFSET, IntrTypeReg);
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTPOL_OFFSET, IntrPolReg);
XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTANY_OFFSET, IntrOnAnyReg);
}
/****************************************************************************/
/**
*
* This function returns the IRQ Type of a given GPIO pin.
*
* @param InstancePtr is a pointer to an XGpioPs instance.
* @param Pin is the pin number whose IRQ type is to be obtained.
* Valid values are 0-117 in Zynq and 0-173 in Zynq Ultrascale+ MP.
*
* @return None.
*
* @note Use XGPIOPS_IRQ_TYPE_* defined in xgpiops.h for the IRQ type
* returned by this function.
*
*****************************************************************************/
u8 XGpioPs_GetIntrTypePin(const XGpioPs *InstancePtr, u32 Pin)
{
u32 IntrType;
u32 IntrPol;
u32 IntrOnAny;
u8 Bank;
u8 PinNumber;
u8 IrqType;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Pin < InstancePtr->MaxPinNum);
/* Get the Bank number and Pin number within the bank. */
#ifdef versal
XGpioPs_GetBankPin(InstancePtr,(u8)Pin, &Bank, &PinNumber);
#else
XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);
#endif
IntrType = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTTYPE_OFFSET) & ((u32)1 << PinNumber);
if (IntrType == ((u32)1 << PinNumber)) {
IntrOnAny = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTANY_OFFSET) & ((u32)1 << PinNumber);
IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber);
if (IntrOnAny == ((u32)1 << PinNumber)) {
IrqType = XGPIOPS_IRQ_TYPE_EDGE_BOTH;
} else if (IntrPol == ((u32)1 << PinNumber)) {
IrqType = XGPIOPS_IRQ_TYPE_EDGE_RISING;
} else {
IrqType = XGPIOPS_IRQ_TYPE_EDGE_FALLING;
}
} else {
IntrPol = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,
((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +
XGPIOPS_INTPOL_OFFSET) & ((u32)1 << PinNumber);
if (IntrPol == ((u32)1 << PinNumber)) {
IrqType = XGPIOPS_IRQ_TYPE_LEVEL_HIGH;
} else {
IrqType = XGPIOPS_IRQ_TYPE_LEVEL_LOW;
}
}
return IrqType;
}
/*****************************************************************************/
/**
*
* This function sets the status callback function. The callback function is
* called by the XGpioPs_IntrHandler when an interrupt occurs.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
* @param CallBackRef is the upper layer callback reference passed back
* when the callback function is invoked.
* @param FuncPointer is the pointer to the callback function.
*
*
* @return None.
*
* @note The handler is called within interrupt context, so it should do
* its work quickly and queue potentially time-consuming work to a
* task-level thread.
*
******************************************************************************/
void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef,
XGpioPs_Handler FuncPointer)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(FuncPointer != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
InstancePtr->Handler = FuncPointer;
InstancePtr->CallBackRef = CallBackRef;
}
/*****************************************************************************/
/**
*
* This function is the interrupt handler for GPIO interrupts.It checks the
* interrupt status registers of all the banks to determine the actual bank in
* which an interrupt has been triggered. It then calls the upper layer callback
* handler set by the function XGpioPs_SetBankHandler(). The callback is called
* when an interrupt
*
* @param InstancePtr is a pointer to the XGpioPs instance.
*
* @return None.
*
* @note This function does not save and restore the processor context
* such that the user must provide this processing.
*
******************************************************************************/
void XGpioPs_IntrHandler(const XGpioPs *InstancePtr)
{
u8 Bank;
u32 IntrStatus;
u32 IntrEnabled;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
for (Bank = 0U; Bank < InstancePtr->MaxBanks; Bank++) {
#ifdef versal
if(InstancePtr->PmcGpio == TRUE) {
if(Bank == XGPIOPS_TWO) {
continue;
}
} else {
if((Bank == XGPIOPS_ONE) || (Bank == XGPIOPS_TWO)) {
continue;
}
}
#endif
IntrStatus = XGpioPs_IntrGetStatus(InstancePtr, Bank);
IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr,Bank);
if ((IntrStatus & IntrEnabled) != (u32)0) {
XGpioPs_IntrClear(InstancePtr, Bank,
(IntrStatus & IntrEnabled));
InstancePtr->Handler(InstancePtr->
CallBackRef, Bank,
(IntrStatus & IntrEnabled));
}
}
}
/*****************************************************************************/
/**
*
* This is a stub for the status callback. The stub is here in case the upper
* layers do not set the handler.
*
* @param CallBackRef is a pointer to the upper layer callback reference
* @param Bank is the GPIO Bank in which an interrupt occurred.
* @param Status is the Interrupt status of the GPIO bank.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void StubHandler(const void *CallBackRef, u32 Bank, u32 Status)
{
(void) CallBackRef;
(void) Bank;
(void) Status;
Xil_AssertVoidAlways();
}
/** @} */

View File

@ -0,0 +1,112 @@
/******************************************************************************
* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xgpiops_selftest.c
* @addtogroup gpiops_v3_7
* @{
*
* This file contains a diagnostic self-test function for the XGpioPs driver.
*
* Read xgpiops.h file for more information.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sv 01/18/10 First Release
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
* 3.5 sne 03/01/19 Fixes violations according to MISRAC-2012
* in safety mode and modified the code such as
* Use of mixed mode arithmetic,Declared the pointer param
* as Pointer to const,Casting operation to a pointer,
* Literal value requires a U suffix.
* </pre>
*
*****************************************************************************/
/***************************** Include Files ********************************/
#include "xstatus.h"
#include "xgpiops.h"
/************************** Constant Definitions ****************************/
/**************************** Type Definitions ******************************/
/***************** Macros (Inline Functions) Definitions ********************/
/************************** Variable Definitions ****************************/
/************************** Function Prototypes *****************************/
/*****************************************************************************/
/**
*
* This function runs a self-test on the GPIO driver/device. This function
* does a register read/write test on some of the Interrupt Registers.
*
* @param InstancePtr is a pointer to the XGpioPs instance.
*
* @return
* - XST_SUCCESS if the self-test passed.
* - XST_FAILURE otherwise.
*
*
******************************************************************************/
s32 XGpioPs_SelfTest(const XGpioPs *InstancePtr)
{
s32 Status = XST_SUCCESS;
u32 IntrEnabled;
u32 CurrentIntrType = 0U;
u32 CurrentIntrPolarity = 0U;
u32 CurrentIntrOnAny = 0U;
u32 IntrType = 0U;
u32 IntrPolarity = 0U;
u32 IntrOnAny = 0U;
u32 IntrTestValue = 0x22U;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/* Disable the Interrupts for Bank 0 . */
IntrEnabled = XGpioPs_IntrGetEnabled(InstancePtr, XGPIOPS_BANK0);
XGpioPs_IntrDisable(InstancePtr, XGPIOPS_BANK0, IntrEnabled);
/*
* Get the Current Interrupt properties for Bank 0.
* Set them to a known value, read it back and compare.
*/
XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &CurrentIntrType,
&CurrentIntrPolarity, &CurrentIntrOnAny);
XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, IntrTestValue,
IntrTestValue, IntrTestValue);
XGpioPs_GetIntrType(InstancePtr, XGPIOPS_BANK0, &IntrType,
&IntrPolarity, &IntrOnAny);
if ((IntrType != IntrTestValue) && (IntrPolarity != IntrTestValue) &&
(IntrOnAny != IntrTestValue)) {
Status = XST_FAILURE;
}
/*
* Restore the contents of all the interrupt registers modified in this
* test.
*/
XGpioPs_SetIntrType(InstancePtr, XGPIOPS_BANK0, CurrentIntrType,
CurrentIntrPolarity, CurrentIntrOnAny);
XGpioPs_IntrEnable(InstancePtr, XGPIOPS_BANK0, IntrEnabled);
return Status;
}
/** @} */

View File

@ -0,0 +1,75 @@
/******************************************************************************
* Copyright (C) 2010 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xgpiops_sinit.c
* @addtogroup gpiops_v3_7
* @{
*
* This file contains the implementation of the XGpioPs driver's static
* initialization functionality.
*
* @note None.
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a sv 01/15/10 First Release
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xgpiops.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES];
/*****************************************************************************/
/**
*
* This function looks for the device configuration based on the unique device
* ID. The table XGpioPs_ConfigTable[] contains the configuration information
* for each device in the system.
*
* @param DeviceId is the unique device ID of the device being looked up.
*
* @return A pointer to the configuration table entry corresponding to the
* given device ID, or NULL if no match is found.
*
* @note None.
*
******************************************************************************/
XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId)
{
XGpioPs_Config *CfgPtr = NULL;
u32 Index;
for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) {
if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XGpioPs_ConfigTable[Index];
break;
}
}
return (XGpioPs_Config *)CfgPtr;
}
/** @} */

View File

@ -0,0 +1,15 @@
import rtconfig
from building import *
# get current directory
cwd = GetCurrentDir()
CPPPATH = [cwd]
# The set of source files associated with this SConscript file.
src = Glob('*.c')
path = cwd
group = DefineGroup('ZYNQMP_HAL', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,420 @@
/******************************************************************************
* Copyright (C) 2013 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps.c
* @addtogroup sdps_v3_9
* @{
*
* Contains the interface functions of the XSdPs driver.
* See xsdps.h for a detailed description of the device and driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a hk/sg 10/17/13 Initial release
* 2.0 hk 12/13/13 Added check for arm to use sleep.h and its API's
* 2.1 hk 04/18/14 Add sleep for microblaze designs. CR# 781117.
* 2.2 hk 07/28/14 Make changes to enable use of data cache.
* 2.3 sk 09/23/14 Send command for relative card address
* when re-initialization is done.CR# 819614.
* Use XSdPs_Change_ClkFreq API whenever changing
* clock.CR# 816586.
* 2.4 sk 12/04/14 Added support for micro SD without
* WP/CD. CR# 810655.
* Checked for DAT Inhibit mask instead of CMD
* Inhibit mask in Cmd Transfer API.
* Added Support for SD Card v1.0
* 2.5 sg 07/09/15 Added SD 3.0 features
* kvn 07/15/15 Modified the code according to MISRAC-2012.
* 2.6 sk 10/12/15 Added support for SD card v1.0 CR# 840601.
* 2.7 sk 11/24/15 Considered the slot type befoe checking CD/WP pins.
* sk 12/10/15 Added support for MMC cards.
* sk 02/16/16 Corrected the Tuning logic.
* sk 03/01/16 Removed Bus Width check for eMMC. CR# 938311.
* 2.8 sk 05/03/16 Standard Speed for SD to 19MHz in ZynqMPSoC. CR#951024
* 3.0 sk 06/09/16 Added support for mkfs to calculate sector count.
* sk 07/16/16 Added support for UHS modes.
* sk 07/07/16 Used usleep API for both arm and microblaze.
* sk 07/16/16 Added Tap delays accordingly to different SD/eMMC
* operating modes.
* 3.1 mi 09/07/16 Removed compilation warnings with extra compiler flags.
* sk 10/13/16 Reduced the delay during power cycle to 1ms as per spec
* sk 10/19/16 Used emmc_hwreset pin to reset eMMC.
* sk 11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
* 3.2 sk 11/30/16 Modified the voltage switching sequence as per spec.
* sk 02/01/17 Added HSD and DDR mode support for eMMC.
* vns 02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
* sk 03/20/17 Add support for EL1 non-secure mode.
* 3.3 mn 05/17/17 Add support for 64bit DMA addressing
* mn 07/17/17 Add support for running SD at 200MHz
* mn 07/26/17 Fixed compilation warnings
* mn 08/07/17 Modify driver to support 64-bit DMA in arm64 only
* mn 08/17/17 Added CCI support for A53 and disabled data cache
* operations when it is enabled.
* mn 08/22/17 Updated for Word Access System support
* mn 09/06/17 Resolved compilation errors with IAR toolchain
* mn 09/26/17 Added UHS_MODE_ENABLE macro to enable UHS mode
* 3.4 mn 10/17/17 Use different commands for single and multi block
* transfers
* mn 03/02/18 Move UHS macro check to SD card initialization routine
* 3.5 mn 04/18/18 Resolve compilation warnings for sdps driver
* 3.6 mn 07/06/18 Fix Cppcheck and Doxygen warnings for sdps driver
* mn 08/01/18 Add support for using 64Bit DMA with 32-Bit Processor
* mn 08/01/18 Add cache invalidation call before returning from
* ReadPolled API
* mn 08/14/18 Resolve compilation warnings for ARMCC toolchain
* mn 10/01/18 Change Expected Response for CMD3 to R1 for MMC
* mus 11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
* 3.7 mn 02/01/19 Add support for idling of SDIO
* aru 03/12/19 Modified the code according to MISRAC-2012.
* 3.8 mn 04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
* mn 09/17/19 Modified ADMA handling API for 32bit and 64bit addresses
* 3.9 sd 02/07/20 Added clock support
* mn 03/03/20 Restructured the code for more readability and modularity
* mn 03/30/20 Return XST_DEVICE_IS_STARTED when host is already started
* mn 03/30/20 Move Clock enabling before checking for Host already started
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xsdps_core.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/*****************************************************************************/
/**
*
* @brief
* Initializes a specific XSdPs instance such that the driver is ready to use.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param ConfigPtr is a reference to a structure containing information
* about a specific SD device. This function initializes an
* InstancePtr object for a specific device specified by the
* contents of Config.
* @param EffectiveAddr is the device base address in the virtual memory
* address space. The caller is responsible for keeping the address
* mapping from EffectiveAddr to the device physical base address
* unchanged once this function is invoked. Unexpected errors may
* occur if the address mapping changes after this function is
* called. If address translation is not used, use
* ConfigPtr->Config.BaseAddress for this device.
*
* @return
* - XST_SUCCESS if successful.
* - XST_DEVICE_IS_STARTED if the device is already started.
* It must be stopped to re-initialize.
*
* @note This function initializes the host controller.
* Initial clock of 400KHz is set.
* Voltage of 3.3V is selected as that is supported by host.
* Interrupts status is enabled and signal disabled by default.
* Default data direction is card to host and
* 32 bit ADMA2 is selected. Default Block size is 512 bytes.
*
******************************************************************************/
s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
u32 EffectiveAddr)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(ConfigPtr != NULL);
#if defined (XCLOCKING)
InstancePtr->Config.RefClk = ConfigPtr->RefClk;
Xil_ClockEnable(InstancePtr->Config.RefClk);
#endif
/* If this API is getting called twice, return value accordingly */
if (InstancePtr->IsReady == XIL_COMPONENT_IS_READY) {
Status = (s32)XST_DEVICE_IS_STARTED;
goto RETURN_PATH ;
}
/* Set some default values. */
InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
InstancePtr->Config.BaseAddress = EffectiveAddr;
InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
InstancePtr->Config.CardDetect = ConfigPtr->CardDetect;
InstancePtr->Config.WriteProtect = ConfigPtr->WriteProtect;
InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
InstancePtr->Config.BankNumber = ConfigPtr->BankNumber;
InstancePtr->Config.HasEMIO = ConfigPtr->HasEMIO;
InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
InstancePtr->SectorCount = 0U;
InstancePtr->Mode = XSDPS_DEFAULT_SPEED_MODE;
InstancePtr->OTapDelay = 0U;
InstancePtr->ITapDelay = 0U;
InstancePtr->Dma64BitAddr = 0U;
InstancePtr->SlcrBaseAddr = XPS_SYS_CTRL_BASEADDR;
/* Host Controller version is read. */
InstancePtr->HC_Version =
(u8)(XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL_VER_OFFSET) & XSDPS_HC_SPEC_VER_MASK);
/*
* Read capabilities register and update it in Instance pointer.
* It is sufficient to read this once on power on.
*/
InstancePtr->Host_Caps = XSdPs_ReadReg(InstancePtr->Config.BaseAddress,
XSDPS_CAPS_OFFSET);
/* Reset the SD bus lines */
Status = XSdPs_ResetConfig(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH ;
}
/* Configure the SD Host Controller */
XSdPs_HostConfig(InstancePtr);
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
RETURN_PATH:
#if defined (XCLOCKING)
Xil_ClockDisable(InstancePtr->Config.RefClk);
#endif
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* Initialize Card with Identification mode sequence
*
*
* @param InstancePtr is a pointer to the instance to be worked on.
*
* @return
* - XST_SUCCESS if initialization was successful
* - XST_FAILURE if failure - could be because
* a) SD is already initialized
* b) There is no card inserted
* c) One of the steps (commands) in the
* initialization cycle failed
*
*
******************************************************************************/
s32 XSdPs_CardInitialize(XSdPs *InstancePtr)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/* Default settings */
InstancePtr->BusWidth = XSDPS_1_BIT_WIDTH;
InstancePtr->CardType = XSDPS_CARD_SD;
InstancePtr->Switch1v8 = 0U;
InstancePtr->BusSpeed = XSDPS_CLK_400_KHZ;
#if defined (XCLOCKING)
Xil_ClockEnable(InstancePtr->Config.RefClk);
#endif
/* Change the clock frequency to 400 KHz */
Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH ;
}
/* Identify the Card whether it is SD, MMC or eMMC */
Status = XSdPs_IdentifyCard(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Initialize the identified card */
if (InstancePtr->CardType == XSDPS_CARD_SD) {
Status = XSdPs_SdCardInitialize(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
} else {
Status = XSdPs_MmcCardInitialize(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
RETURN_PATH:
#if defined (XCLOCKING)
Xil_ClockDisable(InstancePtr->Config.RefClk);
#endif
return Status;
}
/*****************************************************************************/
/**
* @brief
* This function performs SD read in polled mode.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param Arg is the address passed by the user that is to be sent as
* argument along with the command.
* @param BlkCnt - Block count passed by the user.
* @param Buff - Pointer to the data buffer for a DMA transfer.
*
* @return
* - XST_SUCCESS if initialization was successful
* - XST_FAILURE if failure - could be because another transfer
* is in progress or command or data inhibit is set
*
******************************************************************************/
s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
#if defined (XCLOCKING)
Xil_ClockEnable(InstancePtr->Config.RefClk);
#endif
/* Setup the Read Transfer */
Status = XSdPs_SetupTransfer(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Read from the card */
Status = XSdPs_Read(InstancePtr, Arg, BlkCnt, Buff);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
RETURN_PATH:
#if defined (XCLOCKING)
Xil_ClockDisable(InstancePtr->Config.RefClk);
#endif
return Status;
}
/*****************************************************************************/
/**
* @brief
* This function performs SD write in polled mode.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param Arg is the address passed by the user that is to be sent as
* argument along with the command.
* @param BlkCnt - Block count passed by the user.
* @param Buff - Pointer to the data buffer for a DMA transfer.
*
* @return
* - XST_SUCCESS if initialization was successful
* - XST_FAILURE if failure - could be because another transfer
* is in progress or command or data inhibit is set
*
******************************************************************************/
s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
#if defined (XCLOCKING)
Xil_ClockEnable(InstancePtr->Config.RefClk);
#endif
/* Setup the Write Transfer */
Status = XSdPs_SetupTransfer(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Write to the card */
Status = XSdPs_Write(InstancePtr, Arg, BlkCnt, Buff);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
RETURN_PATH:
#if defined (XCLOCKING)
Xil_ClockDisable(InstancePtr->Config.RefClk);
#endif
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to idle the SDIO Interface
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
*
* @return None
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Idle(XSdPs *InstancePtr)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
#if defined (XCLOCKING)
Xil_ClockEnable(InstancePtr->Config.RefClk);
#endif
/* Check if the bus is idle */
Status = XSdPs_CheckBusIdle(InstancePtr, XSDPS_PSR_INHIBIT_CMD_MASK
| XSDPS_PSR_INHIBIT_DAT_MASK
| XSDPS_PSR_DAT_ACTIVE_MASK);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH ;
}
/* Disable the Bus Power */
XSdPs_DisableBusPower(InstancePtr);
/* Reset Command and Data Lines */
Status = XSdPs_Reset(InstancePtr, XSDPS_SWRST_ALL_MASK);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH ;
}
Status = XST_SUCCESS;
RETURN_PATH:
#if defined (XCLOCKING)
Xil_ClockDisable(InstancePtr->Config.RefClk);
#endif
return Status;
}
/** @} */

View File

@ -0,0 +1,295 @@
/******************************************************************************
* Copyright (C) 2013 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps.h
* @addtogroup sdps_v3_9
* @{
* @details
*
* This file contains the implementation of XSdPs driver.
* This driver is used initialize read from and write to the SD card.
* Features such as switching bus width to 4-bit and switching to high speed,
* changing clock frequency, block size etc. are supported.
* SD 2.0 uses 1/4 bus width and speeds of 25/50KHz. Initialization, however
* is done using 1-bit bus width and 400KHz clock frequency.
* SD commands are classified as broadcast and addressed. Commands can be
* those with response only (using only command line) or
* response + data (using command and data lines).
* Only one command can be sent at a time. During a data transfer however,
* when dsta lines are in use, certain commands (which use only the command
* line) can be sent, most often to obtain status.
* This driver does not support multi card slots at present.
*
* Initialization:
* This includes initialization on the host controller side to select
* clock frequency, bus power and default transfer related parameters.
* The default voltage is 3.3V.
* On the SD card side, the initialization and identification state diagram is
* implemented. This resets the card, gives it a unique address/ID and
* identifies key card related specifications.
*
* Data transfer:
* The SD card is put in transfer state to read from or write to it.
* The default block size is 512 bytes and if supported,
* default bus width is 4-bit and bus speed is High speed.
* The read and write functions are implemented in polled mode using ADMA2.
*
* At any point, when key parameters such as block size or
* clock/speed or bus width are modified, this driver takes care of
* maintaining the same selection on host and card.
* All error bits in host controller are monitored by the driver and in the
* event one of them is set, driver will clear the interrupt status and
* communicate failure to the upper layer.
*
* File system use:
* This driver can be used with xilffs library to read and write files to SD.
* (Please refer to procedure in diskio.c). The file system read/write example
* in polled mode can used for reference.
*
* There is no example for using SD driver without file system at present.
* However, the driver can be used without the file system. The glue layer
* in filesystem can be used as reference for the same. The block count
* passed to the read/write function in one call is limited by the ADMA2
* descriptor table and hence care will have to be taken to call read/write
* API's in a loop for large file sizes.
*
* Interrupt mode is not supported because it offers no improvement when used
* with file system.
*
* eMMC support:
* SD driver supports SD and eMMC based on the "enable MMC" parameter in SDK.
* The features of eMMC supported by the driver will depend on those supported
* by the host controller. The current driver supports read/write on eMMC card
* using 4-bit and high speed mode currently.
*
* Features not supported include - card write protect, password setting,
* lock/unlock, interrupts, SDMA mode, programmed I/O mode and
* 64-bit addressed ADMA2, erase/pre-erase commands.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a hk/sg 10/17/13 Initial release
* 2.0 hk 03/07/14 Version number revised.
* 2.1 hk 04/18/14 Increase sleep for eMMC switch command.
* Add sleep for microblaze designs. CR# 781117.
* 2.2 hk 07/28/14 Make changes to enable use of data cache.
* 2.3 sk 09/23/14 Send command for relative card address
* when re-initialization is done.CR# 819614.
* Use XSdPs_Change_ClkFreq API whenever changing
* clock.CR# 816586.
* 2.4 sk 12/04/14 Added support for micro SD without
* WP/CD. CR# 810655.
* Checked for DAT Inhibit mask instead of CMD
* Inhibit mask in Cmd Transfer API.
* Added Support for SD Card v1.0
* 2.5 sg 07/09/15 Added SD 3.0 features
* kvn 07/15/15 Modified the code according to MISRAC-2012.
* 2.6 sk 10/12/15 Added support for SD card v1.0 CR# 840601.
* 2.7 sk 11/24/15 Considered the slot type befoe checking CD/WP pins.
* sk 12/10/15 Added support for MMC cards.
* 01/08/16 Added workaround for issue in auto tuning mode
* of SDR50, SDR104 and HS200.
* sk 02/16/16 Corrected the Tuning logic.
* sk 03/01/16 Removed Bus Width check for eMMC. CR# 938311.
* 2.8 sk 04/20/16 Added new workaround for auto tuning.
* 05/03/16 Standard Speed for SD to 19MHz in ZynqMPSoC. CR#951024
* 3.0 sk 06/09/16 Added support for mkfs to calculate sector count.
* sk 07/16/16 Added support for UHS modes.
* sk 07/07/16 Used usleep API for both arm and microblaze.
* sk 07/16/16 Added Tap delays accordingly to different SD/eMMC
* operating modes.
* sk 08/13/16 Removed sleep.h from xsdps.h as a temporary fix for
* CR#956899.
* 3.1 mi 09/07/16 Removed compilation warnings with extra compiler flags.
* sk 10/13/16 Reduced the delay during power cycle to 1ms as per spec
* sk 10/19/16 Used emmc_hwreset pin to reset eMMC.
* sk 11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
* sk 11/16/16 Issue DLL reset at 31 iteration to load new zero value.
* 3.2 sk 11/30/16 Modified the voltage switching sequence as per spec.
* sk 02/01/17 Added HSD and DDR mode support for eMMC.
* sk 02/01/17 Consider bus width parameter from design for switching
* vns 02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
* sk 03/20/17 Add support for EL1 non-secure mode.
* 3.3 mn 05/17/17 Add support for 64bit DMA addressing
* mn 08/07/17 Modify driver to support 64-bit DMA in arm64 only
* mn 08/17/17 Enabled CCI support for A53 by adding cache coherency
* information.
* mn 09/06/17 Resolved compilation errors with IAR toolchain
* 3.6 mn 08/01/18 Add support for using 64Bit DMA with 32-Bit Processor
* 3.7 mn 02/01/19 Add support for idling of SDIO
* 3.8 mn 04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
* mn 09/17/19 Modified ADMA handling API for 32bit and 64bit addresses
* 3.9 mn 03/03/20 Restructured the code for more readability and modularity
* mn 03/16/20 Move XSdPs_Select_Card API to User APIs
*
* </pre>
*
******************************************************************************/
#ifndef SDPS_H_
#define SDPS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "xil_printf.h"
#include "xil_cache.h"
#include "xstatus.h"
#include "xsdps_hw.h"
#include "xplatform_info.h"
#include "sleep.h"
#include <string.h>
#if defined (XCLOCKING)
#include "xil_clocking.h"
#endif
/************************** Constant Definitions *****************************/
#define XSDPS_CT_ERROR 0x2L /**< Command timeout flag */
#define MAX_TUNING_COUNT 40U /**< Maximum Tuning count */
#define MAX_TIMEOUT 0x1FFFFFFFU /**< Maximum Timeout */
#define XSDPS_CMD8_VOL_PATTERN 0x1AAU
#define XSDPS_RESPOCR_READY 0x80000000U
#define XSDPS_ACMD41_HCS 0x40000000U
#define XSDPS_ACMD41_3V3 0x00300000U
#define XSDPS_CMD1_HIGH_VOL 0x00FF8000U
#define XSDPS_CMD1_DUAL_VOL 0x00FF8010U
#define HIGH_SPEED_SUPPORT 0x2U
#define UHS_SDR12_SUPPORT 0x1U
#define UHS_SDR25_SUPPORT 0x2U
#define UHS_SDR50_SUPPORT 0x4U
#define UHS_SDR104_SUPPORT 0x8U
#define UHS_DDR50_SUPPORT 0x10U
#define WIDTH_4_BIT_SUPPORT 0x4U
#define SD_CLK_25_MHZ 25000000U
#define SD_CLK_19_MHZ 19000000U
#define SD_CLK_26_MHZ 26000000U
#define EXT_CSD_DEVICE_TYPE_BYTE 196U
#define EXT_CSD_SEC_COUNT_BYTE1 212U
#define EXT_CSD_SEC_COUNT_BYTE2 213U
#define EXT_CSD_SEC_COUNT_BYTE3 214U
#define EXT_CSD_SEC_COUNT_BYTE4 215U
#define EXT_CSD_DEVICE_TYPE_HIGH_SPEED 0x2U
#define EXT_CSD_DEVICE_TYPE_DDR_1V8_HIGH_SPEED 0x4U
#define EXT_CSD_DEVICE_TYPE_DDR_1V2_HIGH_SPEED 0x8U
#define EXT_CSD_DEVICE_TYPE_SDR_1V8_HS200 0x10U
#define EXT_CSD_DEVICE_TYPE_SDR_1V2_HS200 0x20U
#define CSD_SPEC_VER_3 0x3U
#define SCR_SPEC_VER_3 0x80U
#define ADDRESS_BEYOND_32BIT 0x100000000U
/**************************** Type Definitions *******************************/
typedef void (*XSdPs_ConfigTap) (u32 Bank, u32 DeviceId, u32 CardType);
/**
* This typedef contains configuration information for the device.
*/
typedef struct {
u16 DeviceId; /**< Unique ID of device */
u32 BaseAddress; /**< Base address of the device */
u32 InputClockHz; /**< Input clock frequency */
u32 CardDetect; /**< Card Detect */
u32 WriteProtect; /**< Write Protect */
u32 BusWidth; /**< Bus Width */
u32 BankNumber; /**< MIO Bank selection for SD */
u32 HasEMIO; /**< If SD is connected to EMIO */
u8 IsCacheCoherent; /**< If SD is Cache Coherent or not */
#if defined (XCLOCKING)
u32 RefClk; /**< Input clocks */
#endif
} XSdPs_Config;
/* ADMA2 32-Bit descriptor table */
typedef struct {
u16 Attribute; /**< Attributes of descriptor */
u16 Length; /**< Length of current dma transfer */
u32 Address; /**< Address of current dma transfer */
#ifdef __ICCARM__
#pragma data_alignment = 32
} XSdPs_Adma2Descriptor32;
#else
} __attribute__((__packed__))XSdPs_Adma2Descriptor32;
#endif
/* ADMA2 64-Bit descriptor table */
typedef struct {
u16 Attribute; /**< Attributes of descriptor */
u16 Length; /**< Length of current dma transfer */
u64 Address; /**< Address of current dma transfer */
#ifdef __ICCARM__
#pragma data_alignment = 32
} XSdPs_Adma2Descriptor64;
#else
} __attribute__((__packed__))XSdPs_Adma2Descriptor64;
#endif
/**
* The XSdPs driver instance data. The user is required to allocate a
* variable of this type for every SD device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct {
XSdPs_Config Config; /**< Configuration structure */
u32 IsReady; /**< Device is initialized and ready */
u32 Host_Caps; /**< Capabilities of host controller */
u32 Host_CapsExt; /**< Extended Capabilities */
u32 HCS; /**< High capacity support in card */
u8 CardType; /**< Type of card - SD/MMC/eMMC */
u8 Card_Version; /**< Card version */
u8 HC_Version; /**< Host controller version */
u8 BusWidth; /**< Current operating bus width */
u32 BusSpeed; /**< Current operating bus speed */
u8 Switch1v8; /**< 1.8V Switch support */
u32 CardID[4]; /**< Card ID Register */
u32 RelCardAddr; /**< Relative Card Address */
u32 CardSpecData[4]; /**< Card Specific Data Register */
u32 SectorCount; /**< Sector Count */
u32 SdCardConfig; /**< Sd Card Configuration Register */
u32 Mode; /**< Bus Speed Mode */
u32 OTapDelay; /**< Output Tap Delay */
u32 ITapDelay; /**< Input Tap Delay */
u64 Dma64BitAddr; /**< 64 Bit DMA Address */
u16 TransferMode; /**< Transfer Mode */
u32 SlcrBaseAddr; /**< SLCR base address*/
} XSdPs;
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId);
s32 XSdPs_CfgInitialize(XSdPs *InstancePtr, XSdPs_Config *ConfigPtr,
u32 EffectiveAddr);
s32 XSdPs_CardInitialize(XSdPs *InstancePtr);
s32 XSdPs_ReadPolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff);
s32 XSdPs_WritePolled(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff);
s32 XSdPs_Idle(XSdPs *InstancePtr);
s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr);
s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq);
s32 XSdPs_Pullup(XSdPs *InstancePtr);
s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff);
s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr);
s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff);
s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff);
s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg);
s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize);
s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg);
s32 XSdPs_Select_Card(XSdPs *InstancePtr);
#ifdef __cplusplus
}
#endif
#endif /* SD_H_ */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
/******************************************************************************
* Copyright (C) 2013 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps_include.h
* @addtogroup sdps_v3_9
* @{
*
* This header file contains the identifiers and basic HW access driver
* functions (or macros) that can be used to access the device. Other driver
* functions are defined in xsdps.h.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 3.9 mn 03/03/20 Restructured the code for more readability and modularity
* mn 03/16/20 Move XSdPs_Select_Card API to User APIs
*
* </pre>
*
******************************************************************************/
#ifndef SDPS_INCLUDE_H_
#define SDPS_INCLUDE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "xsdps.h"
#if defined (__aarch64__)
#include "xil_smc.h"
#endif
/** @cond INTERNAL */
s32 XSdPs_SdCardInitialize(XSdPs *InstancePtr);
s32 XSdPs_MmcCardInitialize(XSdPs *InstancePtr);
s32 XSdPs_IdentifyCard(XSdPs *InstancePtr);
s32 XSdPs_CmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
s32 XSdPs_SetupTransfer(XSdPs *InstancePtr);
s32 XSdPs_Read(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, u8 *Buff);
s32 XSdPs_Write(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt, const u8 *Buff);
void XSdPs_Identify_UhsMode(XSdPs *InstancePtr, u8 *ReadBuff);
s32 XSdPs_Uhs_ModeInit(XSdPs *InstancePtr, u8 Mode);
s32 XSdPs_DllReset(XSdPs *InstancePtr);
s32 XSdPs_Switch_Voltage(XSdPs *InstancePtr);
void XSdPs_SetupADMA2DescTbl64Bit(XSdPs *InstancePtr, u32 BlkCnt);
void XSdPs_SetupADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
void XSdPs_DllRstCtrl(XSdPs *InstancePtr, u8 EnRst);
void XSdPs_ConfigTapDelay(XSdPs *InstancePtr);
s32 XSdPs_Execute_Tuning(XSdPs *InstancePtr);
void XSdPs_Setup32ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
void XSdPs_Setup64ADMA2DescTbl(XSdPs *InstancePtr, u32 BlkCnt, const u8 *Buff);
u32 XSdPs_FrameCmd(XSdPs *InstancePtr, u32 Cmd);
void XSdPs_SetTapDelay(XSdPs *InstancePtr);
s32 XSdPs_CheckResetDone(XSdPs *InstancePtr, u8 Value);
s32 XSdPs_CheckVoltage18(XSdPs *InstancePtr);
s32 XSdPs_SetupCmd(XSdPs *InstancePtr, u32 Arg, u32 BlkCnt);
void XSdPs_SetExecTuning(XSdPs *InstancePtr);
s32 XSdPs_CheckCardDetect(XSdPs *InstancePtr);
s32 XSdPs_CardReset(XSdPs *InstancePtr);
s32 XSdPs_CardIfCond(XSdPs *InstancePtr);
s32 XSdPs_CardOpCond(XSdPs *InstancePtr);
s32 XSdPs_GetCardId(XSdPs *InstancePtr);
s32 XSdPs_GetCsd(XSdPs *InstancePtr);
s32 XSdPs_CardSetVoltage18(XSdPs *InstancePtr);
s32 XSdPs_SdModeInit(XSdPs *InstancePtr);
s32 XSdPs_SdCardEnum(XSdPs *InstancePtr);
s32 XSdPs_MmcCardEnum(XSdPs *InstancePtr);
s32 XSdPs_MmcModeInit(XSdPs *InstancePtr);
s32 XSdPs_EmmcModeInit(XSdPs *InstancePtr);
s32 XSdPs_ResetConfig(XSdPs *InstancePtr);
void XSdPs_HostConfig(XSdPs *InstancePtr);
s32 XSdPs_Reset(XSdPs *InstancePtr, u8 Value);
void XSdPs_DisableBusPower(XSdPs *InstancePtr);
void XSdPs_EnableBusPower(XSdPs *InstancePtr);
s32 XSdPs_CheckBusIdle(XSdPs *InstancePtr, u32 Value);
s32 XSdPs_CheckBusHigh(XSdPs *InstancePtr);
s32 XSdPs_SetupVoltageSwitch(XSdPs *InstancePtr);
s32 XSdPs_AutoTuning(XSdPs *InstancePtr);
s32 XSdPs_SetClock(XSdPs *InstancePtr, u32 SelFreq);
u32 XSdPs_CalcClock(XSdPs *InstancePtr, u32 SelFreq);
s32 XSdPs_EnableClock(XSdPs *InstancePtr, u16 ClockReg);
s32 XSdps_CheckTransferDone(XSdPs *InstancePtr);
s32 XSdPs_Change_SdBusSpeed(XSdPs *InstancePtr);
s32 XSdPs_Change_MmcBusSpeed(XSdPs *InstancePtr);
s32 XSdPs_CalcBusSpeed(XSdPs *InstancePtr, u32 *Arg);
void XSdPs_SetupReadDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, u8 *Buff);
void XSdPs_SetupWriteDma(XSdPs *InstancePtr, u16 BlkCnt, u16 BlkSize, const u8 *Buff);
s32 XSdPs_DoDmaTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
s32 XSdPs_DoCmdTransfer(XSdPs *InstancePtr, u32 Cmd, u32 Arg, u32 BlkCnt);
s32 XSdPs_SetVoltage18(XSdPs *InstancePtr);
s32 XSdPs_SendCmd(XSdPs *InstancePtr, u32 Cmd);
void XSdPs_IdentifyEmmcMode(XSdPs *InstancePtr, const u8 *ExtCsd);
s32 XSdPs_CheckEmmcTiming(XSdPs *InstancePtr, u8 *ExtCsd);
void XSdPs_ConfigPower(XSdPs *InstancePtr);
void XSdPs_ConfigDma(XSdPs *InstancePtr);
void XSdPs_ConfigInterrupt(XSdPs *InstancePtr);
#if EL1_NONSECURE && defined (__aarch64__)
void XSdps_Smc(XSdPs *InstancePtr, u32 RegOffset, u32 Mask, u32 Val);
#endif
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,49 @@
/*******************************************************************
*
* CAUTION: This file is automatically generated by HSI.
* Version: 2020.1
* DO NOT EDIT.
*
* Copyright (C) 2010-2020 Xilinx, Inc. All Rights Reserved.
* SPDX-License-Identifier: MIT
*
* Description: Driver configuration
*
*******************************************************************/
#include "xparameters.h"
#include "xsdps.h"
/*
* The configuration table for devices
*/
XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES] =
{
{
XPAR_PSU_SD_0_DEVICE_ID,
XPAR_PSU_SD_0_BASEADDR,
XPAR_PSU_SD_0_SDIO_CLK_FREQ_HZ,
XPAR_PSU_SD_0_HAS_CD,
XPAR_PSU_SD_0_HAS_WP,
XPAR_PSU_SD_0_BUS_WIDTH,
XPAR_PSU_SD_0_MIO_BANK,
XPAR_PSU_SD_0_HAS_EMIO,
XPAR_PSU_SD_0_IS_CACHE_COHERENT
},
{
XPAR_PSU_SD_1_DEVICE_ID,
XPAR_PSU_SD_1_BASEADDR,
XPAR_PSU_SD_1_SDIO_CLK_FREQ_HZ,
XPAR_PSU_SD_1_HAS_CD,
XPAR_PSU_SD_1_HAS_WP,
XPAR_PSU_SD_1_BUS_WIDTH,
XPAR_PSU_SD_1_MIO_BANK,
XPAR_PSU_SD_1_HAS_EMIO,
XPAR_PSU_SD_1_IS_CACHE_COHERENT
}
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,698 @@
/******************************************************************************
* Copyright (C) 2013 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps_options.c
* @addtogroup sdps_v3_9
* @{
*
* Contains API's for changing the various options in host and card.
* See xsdps.h for a detailed description of the device and driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a hk/sg 10/17/13 Initial release
* 2.1 hk 04/18/14 Increase sleep for eMMC switch command.
* Add sleep for microblaze designs. CR# 781117.
* 2.3 sk 09/23/14 Use XSdPs_Change_ClkFreq API whenever changing
* clock.CR# 816586.
* 2.5 sg 07/09/15 Added SD 3.0 features
* kvn 07/15/15 Modified the code according to MISRAC-2012.
* 2.7 sk 01/08/16 Added workaround for issue in auto tuning mode
* of SDR50, SDR104 and HS200.
* sk 02/16/16 Corrected the Tuning logic.
* sk 03/02/16 Configured the Tap Delay values for eMMC HS200 mode.
* 2.8 sk 04/20/16 Added new workaround for auto tuning.
* 3.0 sk 07/07/16 Used usleep API for both arm and microblaze.
* sk 07/16/16 Added support for UHS modes.
* sk 07/16/16 Added Tap delays accordingly to different SD/eMMC
* operating modes.
* 3.1 mi 09/07/16 Removed compilation warnings with extra compiler flags.
* sk 11/07/16 Enable Rst_n bit in ext_csd reg if not enabled.
* sk 11/16/16 Issue DLL reset at 31 iteration to load new zero value.
* 3.2 sk 02/01/17 Added HSD and DDR mode support for eMMC.
* sk 02/01/17 Consider bus width parameter from design for switching
* vns 02/09/17 Added ARMA53_32 support for ZynqMP CR#968397
* vns 03/13/17 Fixed MISRAC mandatory violation
* sk 03/20/17 Add support for EL1 non-secure mode.
* 3.3 mn 07/25/17 Removed SD0_OTAPDLYENA and SD1_OTAPDLYENA bits
* mn 08/07/17 Properly set OTAPDLY value by clearing previous bit
* settings
* mn 08/17/17 Added CCI support for A53 and disabled data cache
* operations when it is enabled.
* mn 08/22/17 Updated for Word Access System support
* 3.4 mn 01/22/18 Separated out SDR104 and HS200 clock defines
* 3.6 mn 07/06/18 Fix Cppcheck warnings for sdps driver
* 3.7 aru 03/12/19 Modified the code according to MISRAC-2012.
* mn 03/27/19 Disable calls to dll_reset API for versal SPP Platforms
* 3.8 mn 04/12/19 Modified TapDelay code for supporting ZynqMP and Versal
* mn 05/21/19 Set correct tap delays for Versal
* mn 05/21/19 Disable DLL Reset code for Versal
* mn 08/29/19 Add call to Cache Invalidation API in XSdPs_Get_BusWidth
* 3.9 mn 03/03/20 Restructured the code for more readability and modularity
* mn 03/16/20 Move XSdPs_Select_Card API to User APIs
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xsdps_core.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/*****************************************************************************/
/**
*
* @brief
* API to change clock freq to given value.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param SelFreq - Clock frequency in Hz.
*
* @return None
*
* @note This API will change clock frequency to the value less than
* or equal to the given value using the permissible dividors.
*
******************************************************************************/
s32 XSdPs_Change_ClkFreq(XSdPs *InstancePtr, u32 SelFreq)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
if (InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) {
/* Program the Tap delays */
XSdPs_SetTapDelay(InstancePtr);
}
Status = XSdPs_SetClock(InstancePtr, SelFreq);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
}
return Status;
}
/*****************************************************************************/
/**
* @brief
* Update Block size for read/write operations.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param BlkSize - Block size passed by the user.
*
* @return None
*
******************************************************************************/
s32 XSdPs_SetBlkSize(XSdPs *InstancePtr, u16 BlkSize)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Status = XSdPs_CheckBusIdle(InstancePtr, (XSDPS_PSR_INHIBIT_CMD_MASK
| XSDPS_PSR_INHIBIT_DAT_MASK
| XSDPS_PSR_WR_ACTIVE_MASK
| XSDPS_PSR_RD_ACTIVE_MASK));
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH ;
}
/* Send block write command */
Status = XSdPs_CmdTransfer(InstancePtr, CMD16, BlkSize, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Set block size to the value passed */
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress, XSDPS_BLK_SIZE_OFFSET,
BlkSize & XSDPS_BLK_SIZE_MASK);
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to get bus width support by card.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param SCR - buffer to store SCR register returned by card.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Get_BusWidth(XSdPs *InstancePtr, u8 *ReadBuff)
{
s32 Status;
u16 BlkCnt;
u16 BlkSize;
s32 LoopCnt;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
for (LoopCnt = 0; LoopCnt < 8; LoopCnt++) {
ReadBuff[LoopCnt] = 0U;
}
/* Send block write command */
Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
InstancePtr->RelCardAddr, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
BlkCnt = XSDPS_SCR_BLKCNT;
BlkSize = XSDPS_SCR_BLKSIZE;
XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
Status = XSdPs_CmdTransfer(InstancePtr, ACMD51, 0U, BlkCnt);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Check for transfer done */
Status = XSdps_CheckTransferDone(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
}
if (InstancePtr->Config.IsCacheCoherent == 0U) {
Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
(INTPTR)BlkCnt * BlkSize);
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to set bus width to 4-bit in card and host
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Change_BusWidth(XSdPs *InstancePtr)
{
s32 Status;
u32 StatusReg;
u32 Arg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* check for bus width for 3.0 controller and return if
* bus width is <4
*/
if ((InstancePtr->HC_Version == XSDPS_HC_SPEC_V3) &&
(InstancePtr->Config.BusWidth < XSDPS_WIDTH_4)) {
Status = XST_SUCCESS;
goto RETURN_PATH;
}
if (InstancePtr->CardType == XSDPS_CARD_SD) {
Status = XSdPs_CmdTransfer(InstancePtr, CMD55, InstancePtr->RelCardAddr,
0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
Status = XSdPs_CmdTransfer(InstancePtr, ACMD6, (u32)InstancePtr->BusWidth, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
} else {
if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
Arg = XSDPS_MMC_DDR_8_BIT_BUS_ARG;
} else {
Arg = XSDPS_MMC_8_BIT_BUS_ARG;
}
} else {
if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
Arg = XSDPS_MMC_DDR_4_BIT_BUS_ARG;
} else {
Arg = XSDPS_MMC_4_BIT_BUS_ARG;
}
}
Status = XSdPs_Set_Mmc_ExtCsd(InstancePtr, Arg);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
StatusReg = XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET);
/* Width setting in controller */
if (InstancePtr->BusWidth == XSDPS_8_BIT_WIDTH) {
StatusReg |= XSDPS_HC_EXT_BUS_WIDTH;
} else {
StatusReg |= XSDPS_HC_WIDTH_MASK;
}
XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET,
(u8)StatusReg);
if (InstancePtr->Mode == XSDPS_DDR52_MODE) {
StatusReg = XSdPs_ReadReg16(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL2_OFFSET);
StatusReg &= (u32)(~XSDPS_HC2_UHS_MODE_MASK);
StatusReg |= InstancePtr->Mode;
XSdPs_WriteReg16(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL2_OFFSET, (u16)StatusReg);
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to get bus speed supported by card.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param ReadBuff - buffer to store function group support data
* returned by card.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Get_BusSpeed(XSdPs *InstancePtr, u8 *ReadBuff)
{
s32 Status;
u32 Arg;
u16 BlkCnt;
u16 BlkSize;
s32 LoopCnt;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
for (LoopCnt = 0; LoopCnt < 64; LoopCnt++) {
ReadBuff[LoopCnt] = 0U;
}
BlkCnt = XSDPS_SWITCH_CMD_BLKCNT;
BlkSize = XSDPS_SWITCH_CMD_BLKSIZE;
XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
Arg = XSDPS_SWITCH_CMD_HS_GET;
Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 1U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Check for transfer done */
Status = XSdps_CheckTransferDone(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
}
if (InstancePtr->Config.IsCacheCoherent == 0U) {
Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
(INTPTR)BlkCnt * BlkSize);
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to get SD card status information.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param SdStatReg - buffer to store status data returned by card.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Get_Status(XSdPs *InstancePtr, u8 *SdStatReg)
{
s32 Status;
u16 BlkCnt;
u16 BlkSize;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/* Send block write command */
Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
InstancePtr->RelCardAddr, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
BlkCnt = XSDPS_SD_STATUS_BLKCNT;
BlkSize = XSDPS_SD_STATUS_BLKSIZE;
XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, SdStatReg);
Status = XSdPs_CmdTransfer(InstancePtr, ACMD13, 0U, BlkCnt);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Check for transfer done */
Status = XSdps_CheckTransferDone(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
}
if (InstancePtr->Config.IsCacheCoherent == 0U) {
Xil_DCacheInvalidateRange((INTPTR)SdStatReg,
(INTPTR)BlkCnt * BlkSize);
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to set high speed in card and host. Changes clock in host accordingly.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Change_BusSpeed(XSdPs *InstancePtr)
{
s32 Status;
u32 StatusReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
if (InstancePtr->CardType == XSDPS_CARD_SD) {
Status = XSdPs_Change_SdBusSpeed(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
} else {
Status = XSdPs_Change_MmcBusSpeed(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
Status = XSdPs_Change_ClkFreq(InstancePtr, InstancePtr->BusSpeed);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
if ((InstancePtr->Mode == XSDPS_HS200_MODE) ||
(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR104) ||
(InstancePtr->Mode == XSDPS_UHS_SPEED_MODE_SDR50)) {
Status = XSdPs_Execute_Tuning(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
}
usleep(XSDPS_MMC_DELAY_FOR_SWITCH);
StatusReg = (u32)XSdPs_ReadReg8(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET);
StatusReg |= XSDPS_HC_SPEED_MASK;
XSdPs_WriteReg8(InstancePtr->Config.BaseAddress,
XSDPS_HOST_CTRL1_OFFSET, (u8)StatusReg);
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to get EXT_CSD register of eMMC.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param ReadBuff - buffer to store EXT_CSD
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Get_Mmc_ExtCsd(XSdPs *InstancePtr, u8 *ReadBuff)
{
s32 Status;
u32 Arg = 0U;
u16 BlkCnt;
u16 BlkSize;
s32 LoopCnt;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
for (LoopCnt = 0; LoopCnt < 512; LoopCnt++) {
ReadBuff[LoopCnt] = 0U;
}
BlkCnt = XSDPS_EXT_CSD_CMD_BLKCNT;
BlkSize = XSDPS_EXT_CSD_CMD_BLKSIZE;
XSdPs_SetupReadDma(InstancePtr, BlkCnt, BlkSize, ReadBuff);
/* Send SEND_EXT_CSD command */
Status = XSdPs_CmdTransfer(InstancePtr, CMD8, Arg, 1U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Check for transfer done */
Status = XSdps_CheckTransferDone(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
}
if (InstancePtr->Config.IsCacheCoherent == 0U) {
Xil_DCacheInvalidateRange((INTPTR)ReadBuff,
(INTPTR)BlkCnt * BlkSize);
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to write EXT_CSD register of eMMC.
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
* @param Arg is the argument to be sent along with the command
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Set_Mmc_ExtCsd(XSdPs *InstancePtr, u32 Arg)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Status = XSdPs_CmdTransfer(InstancePtr, CMD6, Arg, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
/* Check for transfer done */
Status = XSdps_CheckTransferDone(InstancePtr);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* API to send pullup command to card before using DAT line 3(using 4-bit bus)
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Pullup(XSdPs *InstancePtr)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Status = XSdPs_CmdTransfer(InstancePtr, CMD55,
InstancePtr->RelCardAddr, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
Status = XSdPs_CmdTransfer(InstancePtr, ACMD42, 0U, 0U);
if (Status != XST_SUCCESS) {
Status = XST_FAILURE;
goto RETURN_PATH;
}
Status = XST_SUCCESS;
RETURN_PATH:
return Status;
}
/*****************************************************************************/
/**
*
* @brief
* Selects card and sets default block size
*
*
* @param InstancePtr is a pointer to the XSdPs instance.
*
* @return
* - XST_SUCCESS if successful.
* - XST_FAILURE if fail.
* - XSDPS_CT_ERROR if Command Transfer fail.
*
* @note None.
*
******************************************************************************/
s32 XSdPs_Select_Card (XSdPs *InstancePtr)
{
s32 Status;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/* Send CMD7 - Select card */
Status = XSdPs_CmdTransfer(InstancePtr, CMD7,
InstancePtr->RelCardAddr, 0U);
return Status;
}
/** @} */

View File

@ -0,0 +1,75 @@
/******************************************************************************
* Copyright (C) 2013 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xsdps_sinit.c
* @addtogroup sdps_v3_9
* @{
*
* The implementation of the XSdPs component's static initialization
* functionality.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a hk/sg 10/17/13 Initial release
* kvn 07/15/15 Modified the code according to MISRAC-2012.
* 3.7 aru 03/12/19 Modified the code according to MISRAC-2012.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xstatus.h"
#include "xsdps.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
extern XSdPs_Config XSdPs_ConfigTable[XPAR_XSDPS_NUM_INSTANCES];
/*****************************************************************************/
/**
*
* @brief
* Looks up the device configuration based on the unique device ID. A table
* contains the configuration info for each device in the system.
*
* @param DeviceId contains the ID of the device to look up the
* configuration for.
*
* @return
*
* A pointer to the configuration found or NULL if the specified device ID was
* not found. See xsdps.h for the definition of XSdPs_Config.
*
* @note None.
*
******************************************************************************/
XSdPs_Config *XSdPs_LookupConfig(u16 DeviceId)
{
XSdPs_Config *CfgPtr = NULL;
u32 Index;
for (Index = 0U; Index < (u32)XPAR_XSDPS_NUM_INSTANCES; Index++) {
if (XSdPs_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XSdPs_ConfigTable[Index];
break;
}
}
return (XSdPs_Config *)CfgPtr;
}
/** @} */

View File

@ -0,0 +1,31 @@
#ifndef XLI_SLEEP_H
#define XLI_SLEEP_H
#include <rtthread.h>
#include <rthw.h>
#include "xil_types.h"
#include "xil_io.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void usleep(unsigned long useconds)
{
rt_uint32_t milliseconds = useconds/1000;
useconds = useconds%1000;
if (milliseconds) rt_thread_mdelay(milliseconds);
if (useconds) rt_hw_us_delay(useconds);
}
static inline void sleep(unsigned int seconds)
{
rt_thread_delay(seconds);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,21 @@
#ifndef XIL_ASSERT_H /* prevent circular inclusions */
#define XIL_ASSERT_H /* by using protection macros */
#include "xil_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define Xil_AssertNonvoid(Expression) RT_ASSERT(Expression)
#define Xil_AssertVoid(Expression) RT_ASSERT(Expression)
#define Xil_AssertVoidAlways() RT_ASSERT(0)
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/**
* @} End of "addtogroup common_assert_apis".
*/

View File

@ -0,0 +1,18 @@
#ifndef XIL_CACHE_H
#define XIL_CACHE_H
#ifdef __cplusplus
extern "C" {
#endif
#define Xil_DCacheFlushRange(addr, size) rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, (void*)(addr), (size))
#define Xil_DCacheInvalidateRange(addr, size) rt_hw_cpu_dcache_ops(RT_HW_CACHE_INVALIDATE, (void*)(addr), (size))
#ifdef __cplusplus
}
#endif
#endif
/**
* @} End of "addtogroup r5_cache_apis".
*/

View File

@ -0,0 +1,204 @@
/******************************************************************************
* Copyright (c) 2014 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xil_io.h
*
* @addtogroup common_io_interfacing_apis Register IO interfacing APIs
*
* The xil_io.h file contains the interface for the general I/O component, which
* encapsulates the Input/Output functions for the processors that do not
* require any special I/O handling.
*
* @{
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- -------- -------- -----------------------------------------------
* 5.00 pkp 05/29/14 First release
* 6.00 mus 08/19/16 Remove checking of __LITTLE_ENDIAN__ flag for
* ARM processors
* 7.20 har 01/03/20 Added Xil_SecureOut32 for avoiding blindwrite for
* CR-1049218
* </pre>
******************************************************************************/
#ifndef XIL_IO_H /* prevent circular inclusions */
#define XIL_IO_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_printf.h"
#include "xstatus.h"
#if defined (__GNUC__) || defined (__ICCARM__) || defined (__MICROBLAZE__)
#define INLINE inline
#else
#define INLINE __inline
#endif
/*****************************************************************************/
/**
*
* @brief Performs an input operation for a memory location by reading
* from the specified address and returning the 8 bit Value read from
* that address.
*
* @param Addr: contains the address to perform the input operation
*
* @return The 8 bit Value read from the specified input address.
*
******************************************************************************/
static INLINE u8 Xil_In8(UINTPTR Addr)
{
return *(volatile u8 *) Addr;
}
/*****************************************************************************/
/**
*
* @brief Performs an input operation for a memory location by reading from
* the specified address and returning the 16 bit Value read from that
* address.
*
* @param Addr: contains the address to perform the input operation
*
* @return The 16 bit Value read from the specified input address.
*
******************************************************************************/
static INLINE u16 Xil_In16(UINTPTR Addr)
{
return *(volatile u16 *) Addr;
}
/*****************************************************************************/
/**
*
* @brief Performs an input operation for a memory location by
* reading from the specified address and returning the 32 bit Value
* read from that address.
*
* @param Addr: contains the address to perform the input operation
*
* @return The 32 bit Value read from the specified input address.
*
******************************************************************************/
static INLINE u32 Xil_In32(UINTPTR Addr)
{
return *(volatile u32 *) Addr;
}
/*****************************************************************************/
/**
*
* @brief Performs an input operation for a memory location by reading the
* 64 bit Value read from that address.
*
*
* @param Addr: contains the address to perform the input operation
*
* @return The 64 bit Value read from the specified input address.
*
******************************************************************************/
static INLINE u64 Xil_In64(UINTPTR Addr)
{
return *(volatile u64 *) Addr;
}
/*****************************************************************************/
/**
*
* @brief Performs an output operation for an memory location by
* writing the 8 bit Value to the the specified address.
*
* @param Addr: contains the address to perform the output operation
* @param Value: contains the 8 bit Value to be written at the specified
* address.
*
* @return None.
*
******************************************************************************/
static INLINE void Xil_Out8(UINTPTR Addr, u8 Value)
{
volatile u8 *LocalAddr = (volatile u8 *)Addr;
*LocalAddr = Value;
}
/*****************************************************************************/
/**
*
* @brief Performs an output operation for a memory location by writing the
* 16 bit Value to the the specified address.
*
* @param Addr contains the address to perform the output operation
* @param Value contains the Value to be written at the specified address.
*
* @return None.
*
******************************************************************************/
static INLINE void Xil_Out16(UINTPTR Addr, u16 Value)
{
volatile u16 *LocalAddr = (volatile u16 *)Addr;
*LocalAddr = Value;
}
/*****************************************************************************/
/**
*
* @brief Performs an output operation for a memory location by writing the
* 32 bit Value to the the specified address.
*
* @param Addr contains the address to perform the output operation
* @param Value contains the 32 bit Value to be written at the specified
* address.
*
* @return None.
*
******************************************************************************/
static INLINE void Xil_Out32(UINTPTR Addr, u32 Value)
{
#ifndef ENABLE_SAFETY
volatile u32 *LocalAddr = (volatile u32 *)Addr;
*LocalAddr = Value;
#else
XStl_RegUpdate(Addr, Value);
#endif
}
/*****************************************************************************/
/**
*
* @brief Performs an output operation for a memory location by writing the
* 64 bit Value to the the specified address.
*
* @param Addr contains the address to perform the output operation
* @param Value contains 64 bit Value to be written at the specified address.
*
* @return None.
*
******************************************************************************/
static INLINE void Xil_Out64(UINTPTR Addr, u64 Value)
{
volatile u64 *LocalAddr = (volatile u64 *)Addr;
*LocalAddr = Value;
}
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/**
* @} End of "addtogroup common_io_interfacing_apis".
*/

View File

@ -0,0 +1,16 @@
#ifndef XIL_PRINTF_H
#define XIL_PRINTF_H
#include <rtthread.h>
#ifdef __cplusplus
extern "C" {
#endif
#define xil_printf rt_kprintf
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View File

@ -0,0 +1,96 @@
#ifndef XIL_TYPES_H /* prevent circular inclusions */
#define XIL_TYPES_H /* by using protection macros */
#include <rtdef.h>
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/************************** Constant Definitions *****************************/
#ifndef TRUE
# define TRUE 1U
#endif
#ifndef FALSE
# define FALSE 0U
#endif
#ifndef NULL
#define NULL 0U
#endif
#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be
assigend to "IsReady" member of driver
instance to indicate that driver
instance is initialized and ready to use. */
#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to
"IsStarted" member of driver instance
to indicate that driver instance is
started and it can be enabled. */
typedef rt_uint8_t u8;
typedef rt_uint16_t u16;
typedef rt_uint32_t u32;
typedef char char8;
typedef rt_int8_t s8;
typedef rt_int16_t s16;
typedef rt_int32_t s32;
typedef rt_int64_t s64;
typedef rt_uint64_t u64;
typedef int sint32;
typedef intptr_t INTPTR;
typedef uintptr_t UINTPTR;
typedef ptrdiff_t PTRDIFF;
#if !defined(LONG) || !defined(ULONG)
typedef long LONG;
typedef unsigned long ULONG;
#endif
/** @{ */
/**
* This data type defines an interrupt handler for a device.
* The argument points to the instance of the component
*/
typedef void (*XInterruptHandler) (void *InstancePtr);
/**
* This data type defines an exception handler for a processor.
* The argument points to the instance of the component
*/
typedef void (*XExceptionHandler) (void *InstancePtr);
/************************** Constant Definitions *****************************/
#ifndef TRUE
#define TRUE 1U
#endif
#ifndef FALSE
#define FALSE 0U
#endif
#ifndef NULL
#define NULL 0U
#endif
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/**
* @} End of "addtogroup common_types".
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,325 @@
/******************************************************************************
* Copyright (c) 2014 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
* @file xparameters_ps.h
*
* @addtogroup r5_peripheral_definitions Cortex R5 peripheral definitions
*
* The xparameters_ps.h file contains the canonical definitions and constant
* declarations for peripherals within hardblock, attached to the ARM Cortex R5
* core. These definitions can be used by drivers or applications to access the
* peripherals.
*
* @{
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------- -------- ---------------------------------------------------
* 5.00 pkp 02/29/14 Initial version
* 6.0 mus 08/18/16 Defined ARMR5 flag
* 7.2 pm 03/25/20 Add wakeup Interrupt Id for usbpsu controller
* </pre>
*
******************************************************************************/
#ifndef XPARAMETERS_PS_H_
#define XPARAMETERS_PS_H_
#ifndef ARMR5
#define ARMR5 ARMR5
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
/************************** Constant Definitions *****************************/
/*
* This block contains constant declarations for the peripherals
* within the hardblock
*/
/* Canonical definitions for DDR MEMORY */
#define XPAR_DDR_MEM_BASEADDR 0x00000000U
#define XPAR_DDR_MEM_HIGHADDR 0x3FFFFFFFU
/* Canonical definitions for Interrupts */
#define XPAR_XUARTPS_0_INTR XPS_UART0_INT_ID
#define XPAR_XUARTPS_1_INTR XPS_UART1_INT_ID
#define XPAR_XIICPS_0_INTR XPS_I2C0_INT_ID
#define XPAR_XIICPS_1_INTR XPS_I2C1_INT_ID
#define XPAR_XSPIPS_0_INTR XPS_SPI0_INT_ID
#define XPAR_XSPIPS_1_INTR XPS_SPI1_INT_ID
#define XPAR_XCANPS_0_INTR XPS_CAN0_INT_ID
#define XPAR_XCANPS_1_INTR XPS_CAN1_INT_ID
#define XPAR_XGPIOPS_0_INTR XPS_GPIO_INT_ID
#define XPAR_XEMACPS_0_INTR XPS_GEM0_INT_ID
#define XPAR_XEMACPS_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID
#define XPAR_XEMACPS_1_INTR XPS_GEM1_INT_ID
#define XPAR_XEMACPS_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID
#define XPAR_XEMACPS_2_INTR XPS_GEM2_INT_ID
#define XPAR_XEMACPS_2_WAKE_INTR XPS_GEM2_WAKE_INT_ID
#define XPAR_XEMACPS_3_INTR XPS_GEM3_INT_ID
#define XPAR_XEMACPS_3_WAKE_INTR XPS_GEM3_WAKE_INT_ID
#define XPAR_XSDIOPS_0_INTR XPS_SDIO0_INT_ID
#define XPAR_XQSPIPS_0_INTR XPS_QSPI_INT_ID
#define XPAR_XSDIOPS_1_INTR XPS_SDIO1_INT_ID
#define XPAR_XWDTPS_0_INTR XPS_CSU_WDT_INT_ID
#define XPAR_XWDTPS_1_INTR XPS_LPD_SWDT_INT_ID
#define XPAR_XWDTPS_2_INTR XPS_FPD_SWDT_INT_ID
#define XPAR_XDCFG_0_INTR XPS_DVC_INT_ID
#define XPAR_XTTCPS_0_INTR XPS_TTC0_0_INT_ID
#define XPAR_XTTCPS_1_INTR XPS_TTC0_1_INT_ID
#define XPAR_XTTCPS_2_INTR XPS_TTC0_2_INT_ID
#define XPAR_XTTCPS_3_INTR XPS_TTC1_0_INT_ID
#define XPAR_XTTCPS_4_INTR XPS_TTC1_1_INT_ID
#define XPAR_XTTCPS_5_INTR XPS_TTC1_2_INT_ID
#define XPAR_XTTCPS_6_INTR XPS_TTC2_0_INT_ID
#define XPAR_XTTCPS_7_INTR XPS_TTC2_1_INT_ID
#define XPAR_XTTCPS_8_INTR XPS_TTC2_2_INT_ID
#define XPAR_XTTCPS_9_INTR XPS_TTC3_0_INT_ID
#define XPAR_XTTCPS_10_INTR XPS_TTC3_1_INT_ID
#define XPAR_XTTCPS_11_INTR XPS_TTC3_2_INT_ID
#define XPAR_XNANDPS8_0_INTR XPS_NAND_INT_ID
#define XPAR_XADMAPS_0_INTR XPS_ADMA_CH0_INT_ID
#define XPAR_XADMAPS_1_INTR XPS_ADMA_CH1_INT_ID
#define XPAR_XADMAPS_2_INTR XPS_ADMA_CH2_INT_ID
#define XPAR_XADMAPS_3_INTR XPS_ADMA_CH3_INT_ID
#define XPAR_XADMAPS_4_INTR XPS_ADMA_CH4_INT_ID
#define XPAR_XADMAPS_5_INTR XPS_ADMA_CH5_INT_ID
#define XPAR_XADMAPS_6_INTR XPS_ADMA_CH6_INT_ID
#define XPAR_XADMAPS_7_INTR XPS_ADMA_CH7_INT_ID
#define XPAR_XCSUDMA_INTR XPS_CSU_DMA_INT_ID
#define XPAR_PSU_ADMA_0_INTR XPS_ADMA_CH0_INT_ID
#define XPAR_PSU_ADMA_1_INTR XPS_ADMA_CH1_INT_ID
#define XPAR_PSU_ADMA_2_INTR XPS_ADMA_CH2_INT_ID
#define XPAR_PSU_ADMA_3_INTR XPS_ADMA_CH3_INT_ID
#define XPAR_PSU_ADMA_4_INTR XPS_ADMA_CH4_INT_ID
#define XPAR_PSU_ADMA_5_INTR XPS_ADMA_CH5_INT_ID
#define XPAR_PSU_ADMA_6_INTR XPS_ADMA_CH6_INT_ID
#define XPAR_PSU_ADMA_7_INTR XPS_ADMA_CH7_INT_ID
#define XPAR_PSU_CSUDMA_INTR XPS_CSU_DMA_INT_ID
#define XPAR_XMPU_LPD_INTR XPS_XMPU_LPD_INT_ID
#define XPAR_XZDMAPS_0_INTR XPS_ZDMA_CH0_INT_ID
#define XPAR_XZDMAPS_1_INTR XPS_ZDMA_CH1_INT_ID
#define XPAR_XZDMAPS_2_INTR XPS_ZDMA_CH2_INT_ID
#define XPAR_XZDMAPS_3_INTR XPS_ZDMA_CH3_INT_ID
#define XPAR_XZDMAPS_4_INTR XPS_ZDMA_CH4_INT_ID
#define XPAR_XZDMAPS_5_INTR XPS_ZDMA_CH5_INT_ID
#define XPAR_XZDMAPS_6_INTR XPS_ZDMA_CH6_INT_ID
#define XPAR_XZDMAPS_7_INTR XPS_ZDMA_CH7_INT_ID
#define XPAR_PSU_GDMA_0_INTR XPS_ZDMA_CH0_INT_ID
#define XPAR_PSU_GDMA_1_INTR XPS_ZDMA_CH1_INT_ID
#define XPAR_PSU_GDMA_2_INTR XPS_ZDMA_CH2_INT_ID
#define XPAR_PSU_GDMA_3_INTR XPS_ZDMA_CH3_INT_ID
#define XPAR_PSU_GDMA_4_INTR XPS_ZDMA_CH4_INT_ID
#define XPAR_PSU_GDMA_5_INTR XPS_ZDMA_CH5_INT_ID
#define XPAR_PSU_GDMA_6_INTR XPS_ZDMA_CH6_INT_ID
#define XPAR_PSU_GDMA_7_INTR XPS_ZDMA_CH7_INT_ID
#define XPAR_XMPU_FPD_INTR XPS_XMPU_FPD_INT_ID
#define XPAR_XCCI_FPD_INTR XPS_FPD_CCI_INT_ID
#define XPAR_XSMMU_FPD_INTR XPS_FPD_SMMU_INT_ID
#define XPAR_XUSBPS_0_INTR XPS_USB3_0_ENDPT_INT_ID
#define XPAR_XUSBPS_1_INTR XPS_USB3_1_ENDPT_INT_ID
#define XPAR_XUSBPS_0_WAKE_INTR XPS_USB3_0_WAKE_INT_ID
#define XPAR_XUSBPS_1_WAKE_INTR XPS_USB3_1_WAKE_INT_ID
#define XPAR_XRTCPSU_ALARM_INTR XPS_RTC_ALARM_INT_ID
#define XPAR_XRTCPSU_SECONDS_INTR XPS_RTC_SEC_INT_ID
#define XPAR_XAPMPS_0_INTR XPS_APM0_INT_ID
#define XPAR_XAPMPS_1_INTR XPS_APM1_INT_ID
#define XPAR_XAPMPS_2_INTR XPS_APM2_INT_ID
#define XPAR_XAPMPS_5_INTR XPS_APM5_INT_ID
#define XPAR_XSYSMONPSU_INTR XPS_AMS_INT_ID
/* Canonical definitions for SCU GIC */
#define XPAR_SCUGIC_NUM_INSTANCES 1U
#define XPAR_SCUGIC_SINGLE_DEVICE_ID 0U
#define XPAR_SCUGIC_CPU_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00001000U)
#define XPAR_SCUGIC_DIST_BASEADDR (XPS_SCU_PERIPH_BASE + 0x00002000U)
#define XPAR_SCUGIC_ACK_BEFORE 0U
#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
/*
* This block contains constant declarations for the peripherals
* within the hardblock. These have been put for bacwards compatibility
*/
#define XPS_SYS_CTRL_BASEADDR 0xFF180000U
#define XPS_SCU_PERIPH_BASE 0xF9000000U
/* Shared Peripheral Interrupts (SPI) */
#define XPS_FPGA0_INT_ID 121U
#define XPS_FPGA1_INT_ID 122U
#define XPS_FPGA2_INT_ID 123U
#define XPS_FPGA3_INT_ID 124U
#define XPS_FPGA4_INT_ID 125U
#define XPS_FPGA5_INT_ID 126U
#define XPS_FPGA6_INT_ID 127U
#define XPS_FPGA7_INT_ID 128U
#define XPS_FPGA8_INT_ID 136U
#define XPS_FPGA9_INT_ID 137U
#define XPS_FPGA10_INT_ID 138U
#define XPS_FPGA11_INT_ID 139U
#define XPS_FPGA12_INT_ID 140U
#define XPS_FPGA13_INT_ID 141U
#define XPS_FPGA14_INT_ID 142U
#define XPS_FPGA15_INT_ID 143U
/* Updated Interrupt-IDs */
#define XPS_OCMINTR_INT_ID (10U + 32U)
#define XPS_NAND_INT_ID (14U + 32U)
#define XPS_QSPI_INT_ID (15U + 32U)
#define XPS_GPIO_INT_ID (16U + 32U)
#define XPS_I2C0_INT_ID (17U + 32U)
#define XPS_I2C1_INT_ID (18U + 32U)
#define XPS_SPI0_INT_ID (19U + 32U)
#define XPS_SPI1_INT_ID (20U + 32U)
#define XPS_UART0_INT_ID (21U + 32U)
#define XPS_UART1_INT_ID (22U + 32U)
#define XPS_CAN0_INT_ID (23U + 32U)
#define XPS_CAN1_INT_ID (24U + 32U)
#define XPS_RTC_ALARM_INT_ID (26U + 32U)
#define XPS_RTC_SEC_INT_ID (27U + 32U)
#define XPS_LPD_SWDT_INT_ID (52U + 32U)
#define XPS_CSU_WDT_INT_ID (53U + 32U)
#define XPS_FPD_SWDT_INT_ID (113U + 32U)
#define XPS_TTC0_0_INT_ID (36U + 32U)
#define XPS_TTC0_1_INT_ID (37U + 32U)
#define XPS_TTC0_2_INT_ID (38U + 32U)
#define XPS_TTC1_0_INT_ID (39U + 32U)
#define XPS_TTC1_1_INT_ID (40U + 32U)
#define XPS_TTC1_2_INT_ID (41U + 32U)
#define XPS_TTC2_0_INT_ID (42U + 32U)
#define XPS_TTC2_1_INT_ID (43U + 32U)
#define XPS_TTC2_2_INT_ID (44U + 32U)
#define XPS_TTC3_0_INT_ID (45U + 32U)
#define XPS_TTC3_1_INT_ID (46U + 32U)
#define XPS_TTC3_2_INT_ID (47U + 32U)
#define XPS_SDIO0_INT_ID (48U + 32U)
#define XPS_SDIO1_INT_ID (49U + 32U)
#define XPS_AMS_INT_ID (56U + 32U)
#define XPS_GEM0_INT_ID (57U + 32U)
#define XPS_GEM0_WAKE_INT_ID (58U + 32U)
#define XPS_GEM1_INT_ID (59U + 32U)
#define XPS_GEM1_WAKE_INT_ID (60U + 32U)
#define XPS_GEM2_INT_ID (61U + 32U)
#define XPS_GEM2_WAKE_INT_ID (62U + 32U)
#define XPS_GEM3_INT_ID (63U + 32U)
#define XPS_GEM3_WAKE_INT_ID (64U + 32U)
#define XPS_USB3_0_ENDPT_INT_ID (65U + 32U)
#define XPS_USB3_1_ENDPT_INT_ID (70U + 32U)
#define XPS_USB3_0_WAKE_INT_ID (75U + 32U)
#define XPS_USB3_1_WAKE_INT_ID (76U + 32U)
#define XPS_ADMA_CH0_INT_ID (77U + 32U)
#define XPS_ADMA_CH1_INT_ID (78U + 32U)
#define XPS_ADMA_CH2_INT_ID (79U + 32U)
#define XPS_ADMA_CH3_INT_ID (80U + 32U)
#define XPS_ADMA_CH4_INT_ID (81U + 32U)
#define XPS_ADMA_CH5_INT_ID (82U + 32U)
#define XPS_ADMA_CH6_INT_ID (83U + 32U)
#define XPS_ADMA_CH7_INT_ID (84U + 32U)
#define XPS_CSU_DMA_INT_ID (86U + 32U)
#define XPS_XMPU_LPD_INT_ID (88U + 32U)
#define XPS_ZDMA_CH0_INT_ID (124U + 32U)
#define XPS_ZDMA_CH1_INT_ID (125U + 32U)
#define XPS_ZDMA_CH2_INT_ID (126U + 32U)
#define XPS_ZDMA_CH3_INT_ID (127U + 32U)
#define XPS_ZDMA_CH4_INT_ID (128U + 32U)
#define XPS_ZDMA_CH5_INT_ID (129U + 32U)
#define XPS_ZDMA_CH6_INT_ID (130U + 32U)
#define XPS_ZDMA_CH7_INT_ID (131U + 32U)
#define XPS_XMPU_FPD_INT_ID (134U + 32U)
#define XPS_FPD_CCI_INT_ID (154U + 32U)
#define XPS_FPD_SMMU_INT_ID (155U + 32U)
#define XPS_APM0_INT_ID (123U + 32U)
#define XPS_APM1_INT_ID (25U + 32U)
#define XPS_APM2_INT_ID (25U + 32U)
#define XPS_APM5_INT_ID (123U + 32U)
/* REDEFINES for TEST APP */
#define XPAR_PSU_UART_0_INTR XPS_UART0_INT_ID
#define XPAR_PSU_UART_1_INTR XPS_UART1_INT_ID
#define XPAR_PSU_USB_0_INTR XPS_USB0_INT_ID
#define XPAR_PSU_USB_1_INTR XPS_USB1_INT_ID
#define XPAR_PSU_I2C_0_INTR XPS_I2C0_INT_ID
#define XPAR_PSU_I2C_1_INTR XPS_I2C1_INT_ID
#define XPAR_PSU_SPI_0_INTR XPS_SPI0_INT_ID
#define XPAR_PSU_SPI_1_INTR XPS_SPI1_INT_ID
#define XPAR_PSU_CAN_0_INTR XPS_CAN0_INT_ID
#define XPAR_PSU_CAN_1_INTR XPS_CAN1_INT_ID
#define XPAR_PSU_GPIO_0_INTR XPS_GPIO_INT_ID
#define XPAR_PSU_ETHERNET_0_INTR XPS_GEM0_INT_ID
#define XPAR_PSU_ETHERNET_0_WAKE_INTR XPS_GEM0_WAKE_INT_ID
#define XPAR_PSU_ETHERNET_1_INTR XPS_GEM1_INT_ID
#define XPAR_PSU_ETHERNET_1_WAKE_INTR XPS_GEM1_WAKE_INT_ID
#define XPAR_PSU_ETHERNET_2_INTR XPS_GEM2_INT_ID
#define XPAR_PSU_ETHERNET_2_WAKE_INTR XPS_GEM2_WAKE_INT_ID
#define XPAR_PSU_ETHERNET_3_INTR XPS_GEM3_INT_ID
#define XPAR_PSU_ETHERNET_3_WAKE_INTR XPS_GEM3_WAKE_INT_ID
#define XPAR_PSU_QSPI_0_INTR XPS_QSPI_INT_ID
#define XPAR_PSU_WDT_0_INTR XPS_LPD_SWDT_INT_ID
#define XPAR_PSU_WDT_1_INTR XPS_FPD_SWDT_INT_ID
#define XPAR_PSU_XADC_0_INTR XPS_SYSMON_INT_ID
#define XPAR_PSU_TTC_0_INTR XPS_TTC0_0_INT_ID
#define XPAR_PSU_TTC_1_INTR XPS_TTC0_1_INT_ID
#define XPAR_PSU_TTC_2_INTR XPS_TTC0_2_INT_ID
#define XPAR_PSU_TTC_3_INTR XPS_TTC1_0_INT_ID
#define XPAR_PSU_TTC_4_INTR XPS_TTC1_1_INT_ID
#define XPAR_PSU_TTC_5_INTR XPS_TTC1_2_INT_ID
#define XPAR_PSU_TTC_6_INTR XPS_TTC2_0_INT_ID
#define XPAR_PSU_TTC_7_INTR XPS_TTC2_1_INT_ID
#define XPAR_PSU_TTC_8_INTR XPS_TTC2_2_INT_ID
#define XPAR_PSU_TTC_9_INTR XPS_TTC3_0_INT_ID
#define XPAR_PSU_TTC_10_INTR XPS_TTC3_1_INT_ID
#define XPAR_PSU_TTC_11_INTR XPS_TTC3_2_INT_ID
#define XPAR_PSU_AMS_INTR XPS_AMS_INT_ID
#define XPAR_XADCPS_NUM_INSTANCES 1U
#define XPAR_XADCPS_0_DEVICE_ID 0U
#define XPAR_XADCPS_0_BASEADDR (0xF8007000U)
#define XPAR_XADCPS_INT_ID XPS_SYSMON_INT_ID
/* For backwards compatibility */
#define XPAR_XUARTPS_0_CLOCK_HZ XPAR_XUARTPS_0_UART_CLK_FREQ_HZ
#define XPAR_XUARTPS_1_CLOCK_HZ XPAR_XUARTPS_1_UART_CLK_FREQ_HZ
#define XPAR_XTTCPS_0_CLOCK_HZ XPAR_XTTCPS_0_TTC_CLK_FREQ_HZ
#define XPAR_XTTCPS_1_CLOCK_HZ XPAR_XTTCPS_1_TTC_CLK_FREQ_HZ
#define XPAR_XTTCPS_2_CLOCK_HZ XPAR_XTTCPS_2_TTC_CLK_FREQ_HZ
#define XPAR_XTTCPS_3_CLOCK_HZ XPAR_XTTCPS_3_TTC_CLK_FREQ_HZ
#define XPAR_XTTCPS_4_CLOCK_HZ XPAR_XTTCPS_4_TTC_CLK_FREQ_HZ
#define XPAR_XTTCPS_5_CLOCK_HZ XPAR_XTTCPS_5_TTC_CLK_FREQ_HZ
#define XPAR_XIICPS_0_CLOCK_HZ XPAR_XIICPS_0_I2C_CLK_FREQ_HZ
#define XPAR_XIICPS_1_CLOCK_HZ XPAR_XIICPS_1_I2C_CLK_FREQ_HZ
#define XPAR_XQSPIPS_0_CLOCK_HZ XPAR_XQSPIPS_0_QSPI_CLK_FREQ_HZ
#ifdef XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ
#endif
#ifdef XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ
#define XPAR_CPU_CORTEXR5_CORE_CLOCK_FREQ_HZ XPAR_CPU_CORTEXR5_1_CPU_CLK_FREQ_HZ
#endif
#define XPAR_SCUWDT_DEVICE_ID 0U
#ifdef __cplusplus
}
#endif
#endif /* protection macro */
/**
* @} End of "addtogroup r5_peripheral_definitions".
*/

View File

@ -0,0 +1,64 @@
#ifndef XPLATFORM_INFO_H /* prevent circular inclusions */
#define XPLATFORM_INFO_H /* by using protection macros */
#include "xil_types.h"
#include "xparameters.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined (versal)
#define XPAR_PMC_TAP_BASEADDR 0xF11A0000U
#define XPAR_PMC_TAP_VERSION_OFFSET 0x00000004U
#define XPLAT_PS_VERSION_ADDRESS (XPAR_PMC_TAP_BASEADDR + \
XPAR_PMC_TAP_VERSION_OFFSET)
#else
#define XPAR_CSU_BASEADDR 0xFFCA0000U
#define XPAR_CSU_VER_OFFSET 0x00000044U
#define XPLAT_PS_VERSION_ADDRESS (XPAR_CSU_BASEADDR + \
XPAR_CSU_VER_OFFSET)
#endif
#define XPLAT_ZYNQ_ULTRA_MP_SILICON 0x0
#define XPLAT_ZYNQ_ULTRA_MP 0x1
#define XPLAT_ZYNQ_ULTRA_MPVEL 0x2
#define XPLAT_ZYNQ_ULTRA_MPQEMU 0x3
#define XPLAT_ZYNQ 0x4
#define XPLAT_MICROBLAZE 0x5
#define XPLAT_VERSAL 0x6U
#define XPS_VERSION_1 0x0
#define XPS_VERSION_2 0x1
#define XPLAT_INFO_MASK (0xF)
#if defined (versal)
#define XPS_VERSION_INFO_MASK 0xFF00U
#define XPS_VERSION_INFO_SHIFT 0x8U
#define XPLAT_INFO_SHIFT 0x18U
#else
#define XPS_VERSION_INFO_MASK (0xF)
#define XPS_VERSION_INFO_SHIFT 0x0U
#define XPLAT_INFO_SHIFT 0xCU
#endif
static INLINE u32 XGetPlatform_Info()
{
#if defined (versal)
return XPLAT_VERSAL;
#elif defined (ARMR5) || (__aarch64__) || (ARMA53_32) || (PSU_PMU)
return XPLAT_ZYNQ_ULTRA_MP;
#elif (__microblaze__)
return XPLAT_MICROBLAZE;
#else
return XPLAT_ZYNQ;
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/**
* @} End of "addtogroup common_platform_info".
*/

View File

@ -0,0 +1,513 @@
/******************************************************************************
* Copyright (c) 2002 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xstatus.h
*
* @addtogroup common_status_codes Xilinx&reg; software status codes
*
* The xstatus.h file contains the Xilinx&reg; software status codes.These codes are
* used throughout the Xilinx device drivers.
*
* @{
******************************************************************************/
#ifndef XSTATUS_H /* prevent circular inclusions */
#define XSTATUS_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
/************************** Constant Definitions *****************************/
/*********************** Common statuses 0 - 500 *****************************/
/**
@name Common Status Codes for All Device Drivers
@{
*/
#define XST_SUCCESS 0L
#define XST_FAILURE 1L
#define XST_DEVICE_NOT_FOUND 2L
#define XST_DEVICE_BLOCK_NOT_FOUND 3L
#define XST_INVALID_VERSION 4L
#define XST_DEVICE_IS_STARTED 5L
#define XST_DEVICE_IS_STOPPED 6L
#define XST_FIFO_ERROR 7L /*!< An error occurred during an
operation with a FIFO such as
an underrun or overrun, this
error requires the device to
be reset */
#define XST_RESET_ERROR 8L /*!< An error occurred which requires
the device to be reset */
#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error
typically requires the device
using the DMA to be reset */
#define XST_NOT_POLLED 10L /*!< The device is not configured for
polled mode operation */
#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put
the specified data into */
#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough
to hold the expected data */
#define XST_NO_DATA 13L /*!< There was no data available */
#define XST_REGISTER_ERROR 14L /*!< A register did not contain the
expected value */
#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed
into the function */
#define XST_NOT_SGDMA 16L /*!< The device is not configured for
scatter-gather DMA operation */
#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */
#define XST_NO_CALLBACK 18L /*!< A callback has not yet been
registered */
#define XST_NO_FEATURE 19L /*!< Device is not configured with
the requested feature */
#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for
interrupt mode operation */
#define XST_DEVICE_BUSY 21L /*!< Device is busy */
#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device
have maxed out */
#define XST_IS_STARTED 23L /*!< Used when part of device is
already started i.e.
sub channel */
#define XST_IS_STOPPED 24L /*!< Used when part of device is
already stopped i.e.
sub channel */
#define XST_DATA_LOST 26L /*!< Driver defined error */
#define XST_RECV_ERROR 27L /*!< Generic receive error */
#define XST_SEND_ERROR 28L /*!< Generic transmit error */
#define XST_NOT_ENABLED 29L /*!< A requested service is not
available because it has not
been enabled */
#define XST_NO_ACCESS 30L /* Generic access error */
#define XST_TIMEOUT 31L /*!< Event timeout occurred */
/** @} */
/***************** Utility Component statuses 401 - 500 *********************/
/**
@name Utility Component Status Codes 401 - 500
@{
*/
#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */
/** @} */
/***************** Common Components statuses 501 - 1000 *********************/
/**
@name Packet Fifo Status Codes 501 - 510
@{
*/
/********************* Packet Fifo statuses 501 - 510 ************************/
#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */
#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */
#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value
was invalid after reset */
#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */
#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting
* empty and full simultaneously
*/
/** @} */
/**
@name DMA Status Codes 511 - 530
@{
*/
/************************** DMA statuses 511 - 530 ***************************/
#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer
failed */
#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value
was invalid after reset */
#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains
no buffer descriptors ready
to be processed */
#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */
#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */
#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer descriptors of
the scatter gather list are
being used */
#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer
descriptor which is to be
copied over in the scatter
list is locked */
#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been
put into the scatter gather
list to be committed */
#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold
specified was larger than the
total # of buffer descriptors
in the scatter gather list */
#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has
already been created */
#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has
been created */
#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was
being started was not committed
to the list */
#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start
has already been used by the
hardware so it can't be reused
*/
#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access
error */
#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor
error */
/** @} */
/**
@name IPIF Status Codes Codes 531 - 550
@{
*/
/************************** IPIF statuses 531 - 550 ***************************/
#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width
was passed into the function */
#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at
reset was not valid */
#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt
status register did not read
back correctly */
#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status
register did not reset when
acked */
#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable
register was not updated when
other registers changed */
#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt
status register did not read
back correctly */
#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register
did not reset when acked */
#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was
not updated correctly when other
registers changed */
#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending
register did not indicate the
expected value */
#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register
did not indicate the expected
value */
#define XST_IPIF_ERROR 541L /*!< Generic ipif error */
/** @} */
/****************** Device specific statuses 1001 - 4095 *********************/
/**
@name Ethernet Status Codes 1001 - 1050
@{
*/
/********************* Ethernet statuses 1001 - 1050 *************************/
#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough
* to hold the minimum number of
* buffers or descriptors */
#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */
#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */
#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */
#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */
#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */
#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late
* collision on polled send */
/** @} */
/**
@name UART Status Codes 1051 - 1075
@{
*/
/*********************** UART statuses 1051 - 1075 ***************************/
#define XST_UART
#define XST_UART_INIT_ERROR 1051L
#define XST_UART_START_ERROR 1052L
#define XST_UART_CONFIG_ERROR 1053L
#define XST_UART_TEST_FAIL 1054L
#define XST_UART_BAUD_ERROR 1055L
#define XST_UART_BAUD_RANGE 1056L
/** @} */
/**
@name IIC Status Codes 1076 - 1100
@{
*/
/************************ IIC statuses 1076 - 1100 ***************************/
#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */
#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */
#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */
/* general call address */
#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */
/* value after reset not valid */
#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */
/* value after reset not valid */
#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */
/* value after reset not valid */
#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */
/* value after reset not valid */
#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */
/* didn't return value written */
#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */
/* didn't return value written */
#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */
/* didn't return value written */
#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */
/* didn't return value written */
#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */
/* didn't return written value */
#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */
#define XST_IIC_ARB_LOST 1089 /*!< Arbitration lost for master */
/** @} */
/**
@name ATMC Status Codes 1101 - 1125
@{
*/
/*********************** ATMC statuses 1101 - 1125 ***************************/
#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM
controller hit the max value
which requires the statistics
to be cleared */
/** @} */
/**
@name Flash Status Codes 1126 - 1150
@{
*/
/*********************** Flash statuses 1126 - 1150 **************************/
#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming
*/
#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */
#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal
error. Use XFlash_DeviceControl
to retrieve device specific codes
*/
#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state
*/
#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state
*/
#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by
driver */
#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */
#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */
#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation
aborted due to a timeout */
#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its
addressible range */
#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */
#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from
write/erase function with
XFL_NON_BLOCKING_WRITE/ERASE
option cleared */
#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */
/** @} */
/**
@name SPI Status Codes 1151 - 1175
@{
*/
/*********************** SPI statuses 1151 - 1175 ****************************/
#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */
#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */
#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */
#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */
#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */
#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being
* selected */
#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */
#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only
*/
#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */
#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */
#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */
#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */
#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the
device for status */
/** @} */
/**
@name OPB Arbiter Status Codes 1176 - 1200
@{
*/
/********************** OPB Arbiter statuses 1176 - 1200 *********************/
#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either
* one master assigned to two or more
* priorities, or one master not
* assigned to any priority
*/
#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the
* priority levels without first
* suspending the use of priority
* levels
*/
#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but
* bus parking was not enabled
*/
#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed
* priority mode to allow the
* priorities to be changed
*/
/** @} */
/**
@name INTC Status Codes 1201 - 1225
@{
*/
/************************ Intc statuses 1201 - 1225 **************************/
#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */
#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */
/** @} */
/**
@name TmrCtr Status Codes 1226 - 1250
@{
*/
/********************** TmrCtr statuses 1226 - 1250 **************************/
#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */
/** @} */
/**
@name WdtTb Status Codes 1251 - 1275
@{
*/
/********************** WdtTb statuses 1251 - 1275 ***************************/
#define XST_WDTTB_TIMER_FAILED 1251L
/** @} */
/**
@name PlbArb status Codes 1276 - 1300
@{
*/
/********************** PlbArb statuses 1276 - 1300 **************************/
#define XST_PLBARB_FAIL_SELFTEST 1276L
/** @} */
/**
@name Plb2Opb Status Codes 1301 - 1325
@{
*/
/********************** Plb2Opb statuses 1301 - 1325 *************************/
#define XST_PLB2OPB_FAIL_SELFTEST 1301L
/** @} */
/**
@name Opb2Plb Status 1326 - 1350
@{
*/
/********************** Opb2Plb statuses 1326 - 1350 *************************/
#define XST_OPB2PLB_FAIL_SELFTEST 1326L
/** @} */
/**
@name SysAce Status Codes 1351 - 1360
@{
*/
/********************** SysAce statuses 1351 - 1360 **************************/
#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */
/** @} */
/**
@name PCI Bridge Status Codes 1361 - 1375
@{
*/
/********************** PCI Bridge statuses 1361 - 1375 **********************/
#define XST_PCI_INVALID_ADDRESS 1361L
/** @} */
/**
@name FlexRay Constants 1400 - 1409
@{
*/
/********************** FlexRay constants 1400 - 1409 *************************/
#define XST_FR_TX_ERROR 1400
#define XST_FR_TX_BUSY 1401
#define XST_FR_BUF_LOCKED 1402
#define XST_FR_NO_BUF 1403
/** @} */
/**
@name USB constants 1410 - 1420
@{
*/
/****************** USB constants 1410 - 1420 *******************************/
#define XST_USB_ALREADY_CONFIGURED 1410
#define XST_USB_BUF_ALIGN_ERROR 1411
#define XST_USB_NO_DESC_AVAILABLE 1412
#define XST_USB_BUF_TOO_BIG 1413
#define XST_USB_NO_BUF 1414
/** @} */
/**
@name HWICAP constants 1421 - 1429
@{
*/
/****************** HWICAP constants 1421 - 1429 *****************************/
#define XST_HWICAP_WRITE_DONE 1421
/** @} */
/**
@name AXI VDMA constants 1430 - 1440
@{
*/
/****************** AXI VDMA constants 1430 - 1440 *****************************/
#define XST_VDMA_MISMATCH_ERROR 1430
/** @} */
/**
@name NAND Flash Status Codes 1441 - 1459
@{
*/
/*********************** NAND Flash statuses 1441 - 1459 *********************/
#define XST_NAND_BUSY 1441L /*!< Flash is erasing or
* programming
*/
#define XST_NAND_READY 1442L /*!< Flash is ready for commands
*/
#define XST_NAND_ERROR 1443L /*!< Flash had detected an
* internal error.
*/
#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by
* driver
*/
#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported
*/
#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase
* operation aborted due to a
* timeout
*/
#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its
* addressible range
*/
#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error
*/
#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter
* page of the device
*/
#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error
*/
#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected
*/
/** @} */
/**************************** Type Definitions *******************************/
typedef s32 XStatus;
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/**
* @} End of "addtogroup common_status_codes".
*/

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-11-24 WangHuachen the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <dfs_fs.h>
#include "board.h"
#include "drv_timer.h"
#define ITERS_PER_USEC (XPAR_CPU_CORTEXR5_0_CPU_CLK_FREQ_HZ / 4000000)
void rt_hw_us_delay(rt_uint32_t us)
{
__asm__ __volatile__ (
"push {r0,r1,r3} \n"
"mov r0, %[usec] \n"
"mov r1, %[iter] \n"
"1: \n"
"mov r3, r1 \n"
"2: \n"
"subs r3, r3, #0x1\n"
"bne 2b \n"
"subs r0, r0, #0x1 \n"
"bne 1b \n"
"pop {r0,r1,r3} \n"
::[iter] "r" (ITERS_PER_USEC), [usec] "r" (us)
);
}
#ifdef RT_USING_CONSOLE
#include "drv_uart.h"
void rt_hw_serial_putc(const char c)
{
UART_Registers *uart = (UART_Registers *)XPAR_PSU_UART_0_BASEADDR;
if (c == '\n')
rt_hw_serial_putc('\r');
while ((uart->SR) & UART_SR_TXFULL);
uart->FIFO = c;
}
void rt_hw_console_output(const char *str)
{
while (*str)
{
rt_hw_serial_putc(*str++);
}
}
#endif
/**
* This function will initialize beaglebone board
*/
void rt_hw_board_init(void)
{
/* initialize hardware interrupt */
rt_hw_interrupt_init();
/* initialize system heap */
#ifdef RT_USING_HEAP
rt_system_heap_init(HEAP_BEGIN, HEAP_END);
#endif
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init();
#endif
#ifdef RT_USING_CONSOLE
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif
}

View File

@ -0,0 +1,18 @@
#ifndef __BOARD_H__
#define __BOARD_H__
#include "zynqmp-r5.h"
#if defined(__CC_ARM)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN ((void*)&Image$$RW_IRAM1$$ZI$$Limit)
#elif defined(__GNUC__)
extern int __bss_end;
#define HEAP_BEGIN ((void*)&__bss_end)
#endif
#define HEAP_END (void*)(0x80000000)
void rt_hw_board_init();
#endif

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-11-27 WangHuachen the first version
*/
#include <rtdevice.h>
#include <rthw.h>
#include "drv_gpio.h"
#include "xgpiops.h"
#define DBG_TAG "drv.gpio"
#define DBG_LVL DBG_INFO
#include "rtdbg.h"
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
static XGpioPs Gpio; /* The driver instance for GPIO Device. */
void xgpiops_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
{
switch (mode)
{
case PIN_MODE_OUTPUT:
case PIN_MODE_OUTPUT_OD:
XGpioPs_SetDirectionPin(&Gpio, pin, 1);
XGpioPs_SetOutputEnablePin(&Gpio, pin, 1);
break;
case PIN_MODE_INPUT:
case PIN_MODE_INPUT_PULLUP:
case PIN_MODE_INPUT_PULLDOWN:
XGpioPs_SetDirectionPin(&Gpio, pin, 0);
break;
default:
break;
}
}
void xgpiops_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
{
if (pin >= Gpio.MaxPinNum)
return;
XGpioPs_WritePin(&Gpio, pin, (value == PIN_HIGH)?1:0);
}
int xgpiops_pin_read(rt_device_t dev, rt_base_t pin)
{
if (pin >= Gpio.MaxPinNum)
return 0;
int DataRead = XGpioPs_ReadPin(&Gpio, pin);
return DataRead?PIN_HIGH:PIN_LOW;
}
const static struct rt_pin_ops _xgpiops_pin_ops =
{
xgpiops_pin_mode,
xgpiops_pin_write,
xgpiops_pin_read,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
};
int rt_hw_pin_init(void)
{
int result;
XGpioPs_Config *ConfigPtr;
/* Initialize the GPIO driver. */
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
if (XGpioPs_CfgInitialize(&Gpio, ConfigPtr,
ConfigPtr->BaseAddr) == XST_SUCCESS)
{
result = rt_device_pin_register("pin", &_xgpiops_pin_ops, RT_NULL);
return result;
}
return -RT_ERROR;
}
INIT_BOARD_EXPORT(rt_hw_pin_init);

View File

@ -0,0 +1,13 @@
#ifndef __DRV_GPIO_H__
#define __DRV_GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,472 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-11-24 WangHuachen the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <dfs_fs.h>
#include <drivers/mmcsd_core.h>
#include <stdint.h>
#include <stdio.h>
#include "drv_sdcard.h"
#include "xsdps_core.h"
#define DBG_TAG "drv.sdcard"
#define DBG_LVL DBG_INFO
#include "rtdbg.h"
#define FILE_SYSTEM_INTERFACE_SD
#define SD_CD_DELAY 10000U
typedef rt_uint8_t BYTE;
typedef rt_uint32_t DWORD;
typedef unsigned int UINT;
/* Status of Disk Functions */
typedef rt_uint8_t DSTATUS;
/* Results of Disk Functions */
typedef enum
{
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
static DSTATUS Stat[2] = {STA_NOINIT, STA_NOINIT}; /* Disk status */
#ifdef FILE_SYSTEM_INTERFACE_SD
static XSdPs SdInstance[2];
static u32 BaseAddress;
static u32 CardDetect;
static u32 WriteProtect;
static u32 SlotType[2];
static u8 HostCntrlrVer[2];
#endif
static BYTE sdcard_drvnum = 0;
static struct rt_device sdcard_device;
static struct dfs_partition part;
static struct rt_mutex sd_lock[2];
static DSTATUS disk_status(
BYTE pdrv /* Drive number (0) */
)
{
DSTATUS s = Stat[pdrv];
#ifdef FILE_SYSTEM_INTERFACE_SD
u32 StatusReg;
u32 DelayCount = 0;
if (SdInstance[pdrv].Config.BaseAddress == (u32)0)
{
#ifdef XPAR_XSDPS_1_DEVICE_ID
if (pdrv == 1)
{
BaseAddress = XPAR_XSDPS_1_BASEADDR;
CardDetect = XPAR_XSDPS_1_HAS_CD;
WriteProtect = XPAR_XSDPS_1_HAS_WP;
}
else
{
#endif
BaseAddress = XPAR_XSDPS_0_BASEADDR;
CardDetect = XPAR_XSDPS_0_HAS_CD;
WriteProtect = XPAR_XSDPS_0_HAS_WP;
#ifdef XPAR_XSDPS_1_DEVICE_ID
}
#endif
HostCntrlrVer[pdrv] = (u8)(XSdPs_ReadReg16(BaseAddress,
XSDPS_HOST_CTRL_VER_OFFSET) &
XSDPS_HC_SPEC_VER_MASK);
if (HostCntrlrVer[pdrv] == XSDPS_HC_SPEC_V3)
{
SlotType[pdrv] = XSdPs_ReadReg(BaseAddress,
XSDPS_CAPS_OFFSET) &
XSDPS_CAPS_SLOT_TYPE_MASK;
}
else
{
SlotType[pdrv] = 0;
}
}
/* If SD is not powered up then mark it as not initialized */
if ((XSdPs_ReadReg8((u32)BaseAddress, XSDPS_POWER_CTRL_OFFSET) &
XSDPS_PC_BUS_PWR_MASK) == 0U)
{
s |= STA_NOINIT;
}
StatusReg = XSdPs_GetPresentStatusReg((u32)BaseAddress);
if (SlotType[pdrv] != XSDPS_CAPS_EMB_SLOT)
{
if (CardDetect)
{
while ((StatusReg & XSDPS_PSR_CARD_INSRT_MASK) == 0U)
{
if (DelayCount == 500U)
{
s = STA_NODISK | STA_NOINIT;
goto Label;
}
else
{
/* Wait for 10 msec */
usleep(SD_CD_DELAY);
DelayCount++;
StatusReg = XSdPs_GetPresentStatusReg((u32)BaseAddress);
}
}
}
s &= ~STA_NODISK;
if (WriteProtect)
{
if ((StatusReg & XSDPS_PSR_WPS_PL_MASK) == 0U)
{
s |= STA_PROTECT;
goto Label;
}
}
s &= ~STA_PROTECT;
}
else
{
s &= ~STA_NODISK & ~STA_PROTECT;
}
Label:
Stat[pdrv] = s;
#endif
return s;
}
static DSTATUS disk_initialize(
BYTE pdrv /* Physical drive number (0) */
)
{
DSTATUS s;
#ifdef FILE_SYSTEM_INTERFACE_SD
s32 Status = XST_FAILURE;
XSdPs_Config *SdConfig;
#endif
s = disk_status(pdrv);
if ((s & STA_NODISK) != 0U)
{
return s;
}
/* If disk is already initialized */
if ((s & STA_NOINIT) == 0U)
{
return s;
}
#ifdef FILE_SYSTEM_INTERFACE_SD
if (CardDetect)
{
/*
* Card detection check
* If the HC detects the No Card State, power will be cleared
*/
while (!((XSDPS_PSR_CARD_DPL_MASK |
XSDPS_PSR_CARD_STABLE_MASK |
XSDPS_PSR_CARD_INSRT_MASK) ==
(XSdPs_GetPresentStatusReg((u32)BaseAddress) &
(XSDPS_PSR_CARD_DPL_MASK |
XSDPS_PSR_CARD_STABLE_MASK |
XSDPS_PSR_CARD_INSRT_MASK))))
;
}
/*
* Initialize the host controller
*/
SdConfig = XSdPs_LookupConfig((u16)pdrv);
if (NULL == SdConfig)
{
s |= STA_NOINIT;
return s;
}
Status = XSdPs_CfgInitialize(&SdInstance[pdrv], SdConfig,
SdConfig->BaseAddress);
if (Status != XST_SUCCESS)
{
s |= STA_NOINIT;
return s;
}
Status = XSdPs_CardInitialize(&SdInstance[pdrv]);
if (Status != XST_SUCCESS)
{
s |= STA_NOINIT;
return s;
}
/*
* Disk is initialized.
* Store the same in Stat.
*/
s &= (~STA_NOINIT);
Stat[pdrv] = s;
#endif
#ifdef FILE_SYSTEM_INTERFACE_RAM
/* Assign RAMFS address value from xparameters.h */
dataramfs = (char *)RAMFS_START_ADDR;
/* Clearing No init Status for RAM */
s &= (~STA_NOINIT);
Stat[pdrv] = s;
#endif
return s;
}
static DRESULT disk_read(
BYTE pdrv, /* Physical drive number (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..128) */
)
{
DSTATUS s;
#ifdef FILE_SYSTEM_INTERFACE_SD
s32 Status = XST_FAILURE;
DWORD LocSector = sector;
#endif
s = disk_status(pdrv);
if ((s & STA_NOINIT) != 0U)
{
return RES_NOTRDY;
}
if (count == 0U)
{
return RES_PARERR;
}
#ifdef FILE_SYSTEM_INTERFACE_SD
/* Convert LBA to byte address if needed */
if ((SdInstance[pdrv].HCS) == 0U)
{
LocSector *= (DWORD)XSDPS_BLK_SIZE_512_MASK;
}
Status = XSdPs_ReadPolled(&SdInstance[pdrv], (u32)LocSector, count, buff);
if (Status != XST_SUCCESS)
{
return RES_ERROR;
}
#endif
#ifdef FILE_SYSTEM_INTERFACE_RAM
memcpy(buff, dataramfs + (sector * SECTORSIZE), count * SECTORSIZE);
#endif
return RES_OK;
}
static DRESULT disk_write(
BYTE pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..128) */
)
{
DSTATUS s;
#ifdef FILE_SYSTEM_INTERFACE_SD
s32 Status = XST_FAILURE;
DWORD LocSector = sector;
#endif
s = disk_status(pdrv);
if ((s & STA_NOINIT) != 0U)
{
return RES_NOTRDY;
}
if (count == 0U)
{
return RES_PARERR;
}
#ifdef FILE_SYSTEM_INTERFACE_SD
/* Convert LBA to byte address if needed */
if ((SdInstance[pdrv].HCS) == 0U)
{
LocSector *= (DWORD)XSDPS_BLK_SIZE_512_MASK;
}
Status = XSdPs_WritePolled(&SdInstance[pdrv], (u32)LocSector, count, buff);
if (Status != XST_SUCCESS)
{
return RES_ERROR;
}
#endif
#ifdef FILE_SYSTEM_INTERFACE_RAM
memcpy(dataramfs + (sector * SECTORSIZE), buff, count * SECTORSIZE);
#endif
return RES_OK;
}
static rt_err_t rt_sdcard_init(rt_device_t dev)
{
char sdlock_name[20];
BYTE drvnum = *((BYTE *)dev->user_data);
rt_snprintf(sdlock_name, sizeof(sdlock_name), "sdlock%d", drvnum);
if (rt_mutex_init(&sd_lock[drvnum], sdlock_name, RT_IPC_FLAG_FIFO) != RT_EOK)
{
LOG_E("init sdlock semaphore failed\n");
}
else
LOG_D("sdcard init OK\n");
return RT_EOK;
}
static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
{
return RT_EOK;
}
static rt_err_t rt_sdcard_close(rt_device_t dev)
{
return RT_EOK;
}
static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
RT_ASSERT(((rt_uint32_t)buffer % 4) == 0);
DRESULT status;
BYTE drvnum = *((BYTE *)dev->user_data);
rt_mutex_take(&sd_lock[drvnum], RT_WAITING_FOREVER);
status = disk_read(drvnum, buffer, part.offset + pos, size);
rt_mutex_release(&sd_lock[drvnum]);
if (status == RES_OK)
return size;
LOG_E("sdcard read failed\n");
return 0;
}
static rt_size_t rt_sdcard_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
RT_ASSERT(((rt_uint32_t)buffer % 4) == 0);
DRESULT status;
BYTE drvnum = *((BYTE *)dev->user_data);
rt_mutex_take(&sd_lock[drvnum], RT_WAITING_FOREVER);
status = disk_write(drvnum, buffer, part.offset + pos, size);
rt_mutex_release(&sd_lock[drvnum]);
if (status == RES_OK)
return size;
LOG_E("sdcard write failed\n");
return 0;
}
static rt_err_t rt_sdcard_control(rt_device_t dev, int cmd, void *args)
{
RT_ASSERT(dev != RT_NULL);
BYTE drvnum = *((BYTE *)dev->user_data);
if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
{
struct rt_device_blk_geometry *geometry;
geometry = (struct rt_device_blk_geometry *)args;
if (geometry == RT_NULL)
return -RT_ERROR;
geometry->bytes_per_sector = 512;
geometry->block_size = 128;
geometry->sector_count = SdInstance[drvnum].SectorCount;
}
return RT_EOK;
}
#ifdef BSP_USING_SD0
static int rh_hw_emmc_init(void)
{
if (disk_initialize(sdcard_drvnum) == RES_OK)
{
DRESULT status;
rt_uint8_t *sector;
/* get the first sector to read partition table */
sector = (rt_uint8_t *)rt_malloc(512);
if (sector == RT_NULL)
{
LOG_E("allocate partition sector buffer failed\n");
return -RT_ERROR;
}
status = disk_read(0, sector, 0, 1);
if (status == RES_OK)
{
/* get the first partition */
if (dfs_filesystem_get_partition(&part, sector, 0) != 0)
{
/* there is no partition */
part.offset = 0;
part.size = 0;
}
}
else
{
/* there is no partition table */
part.offset = 0;
part.size = 0;
}
/* release sector buffer */
rt_free(sector);
/* register sdcard device */
sdcard_device.type = RT_Device_Class_Block;
sdcard_device.init = rt_sdcard_init;
sdcard_device.open = rt_sdcard_open;
sdcard_device.close = rt_sdcard_close;
sdcard_device.read = rt_sdcard_read;
sdcard_device.write = rt_sdcard_write;
sdcard_device.control = rt_sdcard_control;
/* no private */
sdcard_device.user_data = &sdcard_drvnum;
rt_device_register(&sdcard_device, "sd0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
return RT_EOK;
}
return -RT_ERROR;
}
INIT_DEVICE_EXPORT(rh_hw_emmc_init);
#endif

View File

@ -0,0 +1,13 @@
#ifndef __DRV_SDCARD_H__
#define __DRV_SDCARD_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen the first version
*/
#include <rthw.h>
#include <rtthread.h>
#include <stdint.h>
#include "drv_timer.h"
#define TTC0_0_BASEADDR XPAR_PSU_TTC_0_BASEADDR
#define TTC0_0_CLK_FREQ_HZ XPAR_PSU_TTC_0_TTC_CLK_FREQ_HZ
static void rt_hw_timer_isr(int vector, void *param)
{
rt_tick_increase();
/* clear interrupt */
TTC_ISR(TTC0_0_BASEADDR);
}
static int rt_hw_timer_init(void)
{
/* Stop timer */
TTC_CNT_CNTRL(TTC0_0_BASEADDR) |= TTC_CNT_CNTRL_DIS_MASK;
/* Initialize TTC */
TTC_CNT_CNTRL(TTC0_0_BASEADDR) = TTC_CNT_CNTRL_RESET_VALUE;
TTC_CLK_CNTRL(TTC0_0_BASEADDR) = 0x00;
TTC_INTERVAL_VAL(TTC0_0_BASEADDR) = 0x00;
TTC_MATCH_0(TTC0_0_BASEADDR) = 0x00;
TTC_MATCH_1(TTC0_0_BASEADDR) = 0x00;
TTC_MATCH_2(TTC0_0_BASEADDR) = 0x00;
TTC_IER(TTC0_0_BASEADDR) = 0x00;
TTC_ISR(TTC0_0_BASEADDR) = 0x00;
/* Reset counter */
TTC_CNT_CNTRL(TTC0_0_BASEADDR) |= TTC_CNT_CNTRL_RST_MASK;
/* Interval mode select */
TTC_CNT_CNTRL(TTC0_0_BASEADDR) |= TTC_CNT_CNTRL_INT_MASK;
/* Setup interval */
TTC_INTERVAL_VAL(TTC0_0_BASEADDR) = TTC0_0_CLK_FREQ_HZ / RT_TICK_PER_SECOND;
/* Clear all of the prescaler control bits in the register */
TTC_CLK_CNTRL(TTC0_0_BASEADDR) &= ~(TTC_CLK_CNTRL_PS_VAL_MASK |
TTC_CLK_CNTRL_PS_EN_MASK);
/* We do not need a prescaler*/
/* Register the ticker handler with the GIC */
rt_hw_interrupt_install(XPAR_XTTCPS_0_INTR, rt_hw_timer_isr, RT_NULL, "tick");
/* Enable TTC interrupts in the GIC */
rt_hw_interrupt_umask(XPAR_XTTCPS_0_INTR);
/* Enable interval interrupt */
TTC_IER(TTC0_0_BASEADDR) |= TTC_IXR_INTERVAL_MASK;
/* Start timer */
TTC_CNT_CNTRL(TTC0_0_BASEADDR) &=~ TTC_CNT_CNTRL_DIS_MASK;
return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_timer_init);

View File

@ -0,0 +1,48 @@
#ifndef __DRV_TIMER_H__
#define __DRV_TIMER_H__
#include "board.h"
#ifdef __cplusplus
extern "C" {
#endif
#define TTC_CLK_CNTRL(hw_base) __REG32(hw_base + 0x00)
#define TTC_CLK_CNTRL_PS_EN_MASK 0x00000001 /**< Prescale enable */
#define TTC_CLK_CNTRL_PS_VAL_MASK 0x0000001E /**< Prescale value */
#define TTC_CLK_CNTRL_PS_VAL_SHIFT 1 /**< Prescale shift */
#define TTC_CLK_CNTRL_PS_DISABLE 16 /**< Prescale disable */
#define TTC_CLK_CNTRL_SRC_MASK 0x00000020 /**< Clock source */
#define TTC_CLK_CNTRL_EXT_EDGE_MASK 0x00000040 /**< External Clock edge */
#define TTC_CNT_CNTRL(hw_base) __REG32(hw_base + 0x0C)
#define TTC_CNT_CNTRL_DIS_MASK 0x00000001 /**< Disable the counter */
#define TTC_CNT_CNTRL_INT_MASK 0x00000002 /**< interval mode */
#define TTC_CNT_CNTRL_DECR_MASK 0x00000004 /**< Decrement mode */
#define TTC_CNT_CNTRL_MATCH_MASK 0x00000008 /**< Match mode */
#define TTC_CNT_CNTRL_RST_MASK 0x00000010 /**< Reset counter */
#define TTC_CNT_CNTRL_EN_WAVE_MASK 0x00000020 /**< Enable waveform */
#define TTC_CNT_CNTRL_POL_WAVE_MASK 0x00000040 /**< Waveform polarity */
#define TTC_CNT_CNTRL_RESET_VALUE 0x00000021 /**< Reset value */
#define TTC_COUNT_VALUE(hw_base) __REG32(hw_base + 0x18)
#define TTC_INTERVAL_VAL(hw_base) __REG32(hw_base + 0x24)
#define TTC_MATCH_0(hw_base) __REG32(hw_base + 0x30)
#define TTC_MATCH_1(hw_base) __REG32(hw_base + 0x3C)
#define TTC_MATCH_2(hw_base) __REG32(hw_base + 0x48)
#define TTC_ISR(hw_base) __REG32(hw_base + 0x54)
#define TTC_IXR_INTERVAL_MASK 0x00000001 /**< interval Interrupt */
#define TTC_IXR_MATCH_0_MASK 0x00000002 /**< Match 1 Interrupt */
#define TTC_IXR_MATCH_1_MASK 0x00000004 /**< Match 2 Interrupt */
#define TTC_IXR_MATCH_2_MASK 0x00000008 /**< Match 3 Interrupt */
#define TTC_IXR_CNT_OVR_MASK 0x00000010 /**< Counter Overflow */
#define TTC_IXR_ALL_MASK 0x0000001F /**< All valid Interrupts */
#define TTC_IER(hw_base) __REG32(hw_base + 0x60)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,318 @@
/*
* Copyright (c) 2006-2020, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen the first version
*/
#include <rthw.h>
#include <rtdevice.h>
#include "board.h"
#include "gic.h"
#include "drv_uart.h"
#define IOU_SLCR_BASE_ADDR XPAR_PSU_IOUSLCR_0_S_AXI_BASEADDR
#define ZynqMP_IOU_SLCR_MIO_PIN(x) (IOU_SLCR_BASE_ADDR + 0x04 * x)
#define XUARTPS_MAX_RATE 921600U
#define XUARTPS_MIN_RATE 110U
#define XUARTPS_MAX_BAUD_ERROR_RATE 3U /* max % error allowed */
#define ZynqMP_UART_INT_DISABLE(UART) \
(UART->IER &= ~(UART_IXR_RXOVR | UART_IXR_RXFULL))
#define ZynqMP_UART_INT_ENABLE(UART) \
(UART->IER |= (UART_IXR_RXOVR | UART_IXR_RXFULL))
#define ZynqMP_UART_SENDCHAR(UART, ch) \
do { \
while ((UART->SR) & UART_SR_TXFULL); \
UART->FIFO = ch; \
} while(0)
#define ZynqMP_UART_GETCHAR(UART, ch) \
do { \
if (UART->ISR & UART_IXR_RXOVR) \
{ \
ch = UART->FIFO & 0xff; \
UART->ISR = (UART_IXR_RXOVR | UART_IXR_RXFULL); \
} \
} while(0)
static void UartEnable(UART_Registers* uart)
{
uint32_t tmp = uart->CR;
tmp &= ~UART_CR_EN_DIS_MASK;
tmp |= (UART_CR_TX_EN | UART_CR_RX_EN);
uart->CR = tmp;
}
static void UartDisable(UART_Registers* uart)
{
uint32_t tmp = uart->CR;
tmp &= ~UART_CR_EN_DIS_MASK;
tmp |= (UART_CR_TX_DIS | UART_CR_RX_DIS);
uart->CR = tmp;
}
static void UartResetTXRXLogic(UART_Registers* uart)
{
uart->CR |= (UART_CR_TXRST | UART_CR_RXRST);
while (uart->CR & (UART_CR_TXRST | UART_CR_RXRST));
}
/* UART TxD/RxD | L3 Mux | L2 Mux | L1 Mux */
#define RX_MIO_PIN_MODE ((0x6 << 5) | (0x0 << 3) | (0x0 << 2) | (0x0 << 1))
#define TX_MIO_PIN_MODE ((0x6 << 5) | (0x0 << 3) | (0x0 << 2) | (0x0 << 1))
struct hw_uart_device
{
UART_Registers * uart;
rt_uint32_t irqno;
rt_uint32_t inputClockHz;
/* MIO pin mode address */
rt_uint32_t *rxmio;
rt_uint32_t *txmio;
};
/* RT-Thread UART interface */
static void rt_hw_uart_isr(int irqno, void *param)
{
struct rt_serial_device *serial = (struct rt_serial_device *)param;
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
static rt_err_t XUartPsSetBandRate(struct hw_uart_device *pdev, rt_uint32_t targetBandRate)
{
rt_uint32_t IterBAUDDIV; /* Iterator for available baud divisor values */
rt_uint32_t BRGR_Value; /* Calculated value for baud rate generator */
rt_uint32_t CalcBaudRate; /* Calculated baud rate */
rt_uint32_t BaudError; /* Diff between calculated and requested baud rate */
rt_uint32_t Best_BRGR = 0U; /* Best value for baud rate generator */
rt_uint8_t Best_BAUDDIV = 0U; /* Best value for baud divisor */
rt_uint32_t Best_Error = 0xFFFFFFFFU;
rt_uint32_t PercentError;
rt_uint32_t ModeReg;
rt_uint32_t InputClk;
if ((targetBandRate > (rt_uint32_t)XUARTPS_MAX_RATE) ||
(targetBandRate < (rt_uint32_t)XUARTPS_MIN_RATE))
return -RT_EINVAL;
/*
* Make sure the baud rate is not impossilby large.
* Fastest possible baud rate is Input Clock / 2.
*/
if ((targetBandRate * 2) > pdev->inputClockHz)
return -RT_EINVAL;
/* Check whether the input clock is divided by 8 */
ModeReg = pdev->uart->MR;
InputClk = pdev->inputClockHz;
if(ModeReg & UART_MR_CLKSEL)
InputClk = pdev->inputClockHz / 8;
/*
* Determine the Baud divider. It can be 4to 254.
* Loop through all possible combinations
*/
for (IterBAUDDIV = 4; IterBAUDDIV < 255; IterBAUDDIV++)
{
/* Calculate the value for BRGR register */
BRGR_Value = InputClk / (targetBandRate * (IterBAUDDIV + 1));
/* Calculate the baud rate from the BRGR value */
CalcBaudRate = InputClk / (BRGR_Value * (IterBAUDDIV + 1));
/* Avoid unsigned integer underflow */
if (targetBandRate > CalcBaudRate)
BaudError = targetBandRate - CalcBaudRate;
else
BaudError = CalcBaudRate - targetBandRate;
/* Find the calculated baud rate closest to requested baud rate. */
if (Best_Error > BaudError)
{
Best_BRGR = BRGR_Value;
Best_BAUDDIV = IterBAUDDIV;
Best_Error = BaudError;
}
}
/* Make sure the best error is not too large. */
PercentError = (Best_Error * 100) / targetBandRate;
if (XUARTPS_MAX_BAUD_ERROR_RATE < PercentError)
return -RT_ERROR;
pdev->uart->BAUDGEN = Best_BRGR;
pdev->uart->BAUDDIV = Best_BAUDDIV;
return RT_EOK;
}
static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
uint32_t mr;
struct hw_uart_device *pdev = serial->parent.user_data;
UART_Registers *uart = pdev->uart;
UartDisable(uart);
UartResetTXRXLogic(uart);
UartEnable(uart);
mr = uart->MR & ~(UART_MR_CHARLEN_MASK |
UART_MR_STOPMODE_MASK |
UART_MR_PARITY_MASK);
if (cfg->stop_bits == STOP_BITS_2)
mr |= UART_MR_STOPMODE_2_BIT;
else if (cfg->stop_bits == STOP_BITS_1)
mr |= UART_MR_STOPMODE_1_BIT;
else
return -RT_EINVAL;
if (cfg->parity == PARITY_EVEN)
mr |= UART_MR_PARITY_EVEN;
else if (cfg->parity == PARITY_ODD)
mr |= UART_MR_PARITY_ODD;
else if (cfg->parity == PARITY_NONE)
mr |= UART_MR_PARITY_NONE;
else
return -RT_EINVAL;
if (cfg->data_bits == DATA_BITS_8)
mr |= UART_MR_CHARLEN_8_BIT;
else if (cfg->data_bits == DATA_BITS_7)
mr |= UART_MR_CHARLEN_7_BIT;
else if (cfg->data_bits == DATA_BITS_6)
mr |= UART_MR_CHARLEN_6_BIT;
else
return -RT_EINVAL;
uart->MR = mr;
uart->TXWM = 8;
uart->RXWM = 1;
if (XUartPsSetBandRate(pdev, cfg->baud_rate) != RT_EOK)
{
rt_kprintf("baudrate %d not implemented yet\n", cfg->baud_rate);
return -RT_EINVAL;
}
/* disable all interrupts */
uart->IDR = UART_IXR_MASK;
/* configure the pin */
*(pdev->txmio) = TX_MIO_PIN_MODE;
*(pdev->rxmio) = RX_MIO_PIN_MODE;
return RT_EOK;
}
static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
struct hw_uart_device *pdev;
RT_ASSERT(serial != RT_NULL);
pdev = serial->parent.user_data;
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* disable rx irq */
ZynqMP_UART_INT_DISABLE(pdev->uart);
break;
case RT_DEVICE_CTRL_SET_INT:
/* enable rx irq */
ZynqMP_UART_INT_ENABLE(pdev->uart);
rt_hw_interrupt_install(pdev->irqno, rt_hw_uart_isr, serial, serial->parent.parent.name);
/* set the interrupt to this cpu */
arm_gic_set_cpu(0, pdev->irqno, 1 << rt_cpu_get_smp_id());
rt_hw_interrupt_umask(pdev->irqno);
break;
}
return RT_EOK;
}
static int uart_putc(struct rt_serial_device *serial, char c)
{
struct hw_uart_device *dev;
RT_ASSERT(serial != RT_NULL);
dev = (struct hw_uart_device *)serial->parent.user_data;
ZynqMP_UART_SENDCHAR(dev->uart, c);
return 1;
}
static int uart_getc(struct rt_serial_device *serial)
{
int ch;
struct hw_uart_device *dev;
RT_ASSERT(serial != RT_NULL);
dev = (struct hw_uart_device *)serial->parent.user_data;
ch = -1;
ZynqMP_UART_GETCHAR(dev->uart, ch);
return ch;
}
static const struct rt_uart_ops _uart_ops =
{
uart_configure,
uart_control,
uart_putc,
uart_getc,
};
/* UART device driver structure */
#ifdef BSP_USING_UART0
static struct hw_uart_device _uart_device0 =
{
.uart = (UART_Registers*)XPAR_PSU_UART_0_BASEADDR,
.irqno = XPAR_PSU_UART_0_INTR,
.inputClockHz = XPAR_PSU_UART_0_UART_CLK_FREQ_HZ,
.rxmio = (rt_uint32_t*)ZynqMP_IOU_SLCR_MIO_PIN(42), /* MIO42 */
.txmio = (rt_uint32_t*)ZynqMP_IOU_SLCR_MIO_PIN(43), /* MIO43 */
};
static struct rt_serial_device _serial0;
#endif
int rt_hw_uart_init(void)
{
struct serial_configure config;
config.baud_rate = BAUD_RATE_115200;
config.bit_order = BIT_ORDER_LSB;
config.data_bits = DATA_BITS_8;
config.parity = PARITY_NONE;
config.stop_bits = STOP_BITS_1;
config.invert = NRZ_NORMAL;
config.bufsz = RT_SERIAL_RB_BUFSZ;
/* register uart device */
#ifdef BSP_USING_UART0
_serial0.ops = &_uart_ops;
_serial0.config = config;
rt_hw_serial_register(&_serial0, "uart0",
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
&_uart_device0);
#endif
return RT_EOK;
}
INIT_BOARD_EXPORT(rt_hw_uart_init);

View File

@ -0,0 +1,281 @@
#ifndef _DRV_UART_H_
#define _DRV_UART_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @name Register Map
*
* Registers of the UART.
* @{
*/
typedef struct
{
volatile uint32_t CR; /**< Control Register */
volatile uint32_t MR; /**< Mode Register */
volatile uint32_t IER; /**< Interrupt Enable */
volatile uint32_t IDR; /**< Interrupt Disable */
volatile uint32_t IMR; /**< Interrupt Mask */
volatile uint32_t ISR; /**< Interrupt Status */
volatile uint32_t BAUDGEN; /**< Baud Rate Generator */
volatile uint32_t RXTOUT; /**< RX Timeout */
volatile uint32_t RXWM; /**< RX FIFO Trigger Level */
volatile uint32_t MODEMCR; /**< Modem Control */
volatile uint32_t MODEMSR; /**< Modem Status */
volatile uint32_t SR; /**< Channel Status */
volatile uint32_t FIFO; /**< FIFO */
volatile uint32_t BAUDDIV; /**< Baud Rate Divider */
volatile uint32_t FLOWDEL; /**< Flow Delay */
volatile uint32_t RESERVED1;
volatile uint32_t RESERVED2;
volatile uint32_t TXWM; /* TX FIFO Trigger Level */
} UART_Registers;
/* @} */
/** @name Control Register
*
* The Control register (CR) controls the major functions of the device.
*
* Control Register Bit Definition
*/
#define UART_CR_STOPBRK 0x00000100 /**< Stop transmission of break */
#define UART_CR_STARTBRK 0x00000080 /**< Set break */
#define UART_CR_TORST 0x00000040 /**< RX timeout counter restart */
#define UART_CR_TX_DIS 0x00000020 /**< TX disabled. */
#define UART_CR_TX_EN 0x00000010 /**< TX enabled */
#define UART_CR_RX_DIS 0x00000008 /**< RX disabled. */
#define UART_CR_RX_EN 0x00000004 /**< RX enabled */
#define UART_CR_EN_DIS_MASK 0x0000003C /**< Enable/disable Mask */
#define UART_CR_TXRST 0x00000002 /**< TX logic reset */
#define UART_CR_RXRST 0x00000001 /**< RX logic reset */
/* @}*/
/** @name Mode Register
*
* The mode register (MR) defines the mode of transfer as well as the data
* format. If this register is modified during transmission or reception,
* data validity cannot be guaranteed.
*
* Mode Register Bit Definition
* @{
*/
#define UART_MR_CCLK 0x00000400 /**< Input clock selection */
#define UART_MR_CHMODE_R_LOOP 0x00000300 /**< Remote loopback mode */
#define UART_MR_CHMODE_L_LOOP 0x00000200 /**< Local loopback mode */
#define UART_MR_CHMODE_ECHO 0x00000100 /**< Auto echo mode */
#define UART_MR_CHMODE_NORM 0x00000000 /**< Normal mode */
#define UART_MR_CHMODE_SHIFT 8 /**< Mode shift */
#define UART_MR_CHMODE_MASK 0x00000300 /**< Mode mask */
#define UART_MR_STOPMODE_2_BIT 0x00000080 /**< 2 stop bits */
#define UART_MR_STOPMODE_1_5_BIT 0x00000040 /**< 1.5 stop bits */
#define UART_MR_STOPMODE_1_BIT 0x00000000 /**< 1 stop bit */
#define UART_MR_STOPMODE_SHIFT 6 /**< Stop bits shift */
#define UART_MR_STOPMODE_MASK 0x000000A0 /**< Stop bits mask */
#define UART_MR_PARITY_NONE 0x00000020 /**< No parity mode */
#define UART_MR_PARITY_MARK 0x00000018 /**< Mark parity mode */
#define UART_MR_PARITY_SPACE 0x00000010 /**< Space parity mode */
#define UART_MR_PARITY_ODD 0x00000008 /**< Odd parity mode */
#define UART_MR_PARITY_EVEN 0x00000000 /**< Even parity mode */
#define UART_MR_PARITY_SHIFT 3 /**< Parity setting shift */
#define UART_MR_PARITY_MASK 0x00000038 /**< Parity mask */
#define UART_MR_CHARLEN_6_BIT 0x00000006 /**< 6 bits data */
#define UART_MR_CHARLEN_7_BIT 0x00000004 /**< 7 bits data */
#define UART_MR_CHARLEN_8_BIT 0x00000000 /**< 8 bits data */
#define UART_MR_CHARLEN_SHIFT 1 /**< Data Length shift */
#define UART_MR_CHARLEN_MASK 0x00000006 /**< Data length mask */
#define UART_MR_CLKSEL 0x00000001 /**< Input clock selection */
/* @} */
/** @name Interrupt Registers
*
* Interrupt control logic uses the interrupt enable register (IER) and the
* interrupt disable register (IDR) to set the value of the bits in the
* interrupt mask register (IMR). The IMR determines whether to pass an
* interrupt to the interrupt status register (ISR).
* Writing a 1 to IER Enbables an interrupt, writing a 1 to IDR disables an
* interrupt. IMR and ISR are read only, and IER and IDR are write only.
* Reading either IER or IDR returns 0x00.
*
* All four registers have the same bit definitions.
*
* @{
*/
#define UART_IXR_DMS 0x00000200 /**< Modem status change interrupt */
#define UART_IXR_TOUT 0x00000100 /**< Timeout error interrupt */
#define UART_IXR_PARITY 0x00000080 /**< Parity error interrupt */
#define UART_IXR_FRAMING 0x00000040 /**< Framing error interrupt */
#define UART_IXR_OVER 0x00000020 /**< Overrun error interrupt */
#define UART_IXR_TXFULL 0x00000010 /**< TX FIFO full interrupt. */
#define UART_IXR_TXEMPTY 0x00000008 /**< TX FIFO empty interrupt. */
#define UART_IXR_RXFULL 0x00000004 /**< RX FIFO full interrupt. */
#define UART_IXR_RXEMPTY 0x00000002 /**< RX FIFO empty interrupt. */
#define UART_IXR_RXOVR 0x00000001 /**< RX FIFO trigger interrupt. */
#define UART_IXR_MASK 0x00003FFF /**< Valid bit mask */
/* @} */
/** @name Baud Rate Generator Register
*
* The baud rate generator control register (BRGR) is a 16 bit register that
* controls the receiver bit sample clock and baud rate.
* Valid values are 1 - 65535.
*
* Bit Sample Rate = CCLK / BRGR, where the CCLK is selected by the MR_CCLK bit
* in the MR register.
* @{
*/
#define UART_BAUDGEN_DISABLE 0x00000000 /**< Disable clock */
#define UART_BAUDGEN_MASK 0x0000FFFF /**< Valid bits mask */
/* @} */
/** @name Baud Divisor Rate register
*
* The baud rate divider register (BDIV) controls how much the bit sample
* rate is divided by. It sets the baud rate.
* Valid values are 0x04 to 0xFF. Writing a value less than 4 will be ignored.
*
* Baud rate = CCLK / ((BAUDDIV + 1) x BRGR), where the CCLK is selected by
* the MR_CCLK bit in the MR register.
* @{
*/
#define UART_BAUDDIV_MASK 0x000000FF /**< 8 bit baud divider mask */
/* @} */
/** @name Receiver Timeout Register
*
* Use the receiver timeout register (RTR) to detect an idle condition on
* the receiver data line.
*
* @{
*/
#define UART_RXTOUT_DISABLE 0x00000000 /**< Disable time out */
#define UART_RXTOUT_MASK 0x000000FF /**< Valid bits mask */
/* @} */
/** @name Receiver FIFO Trigger Level Register
*
* Use the Receiver FIFO Trigger Level Register (RTRIG) to set the value at
* which the RX FIFO triggers an interrupt event.
* @{
*/
#define UART_RXWM_DISABLE 0x00000000 /**< Disable RX trigger interrupt */
#define UART_RXWM_MASK 0x0000003F /**< Valid bits mask */
/* @} */
/** @name Modem Control Register
*
* This register (MODEMCR) controls the interface with the modem or data set,
* or a peripheral device emulating a modem.
*
* @{
*/
#define UART_MODEMCR_FCM 0x00000010 /**< Flow control mode */
#define UART_MODEMCR_RTS 0x00000002 /**< Request to send */
#define UART_MODEMCR_DTR 0x00000001 /**< Data terminal ready */
/* @} */
/** @name Modem Status Register
*
* This register (MODEMSR) indicates the current state of the control lines
* from a modem, or another peripheral device, to the CPU. In addition, four
* bits of the modem status register provide change information. These bits
* are set to a logic 1 whenever a control input from the modem changes state.
*
* Note: Whenever the DCTS, DDSR, TERI, or DDCD bit is set to logic 1, a modem
* status interrupt is generated and this is reflected in the modem status
* register.
*
* @{
*/
#define UART_MODEMSR_FCMS 0x00000100 /**< Flow control mode (FCMS) */
#define UART_MODEMSR_DCD 0x00000080 /**< Complement of DCD input */
#define UART_MODEMSR_RI 0x00000040 /**< Complement of RI input */
#define UART_MODEMSR_DSR 0x00000020 /**< Complement of DSR input */
#define UART_MODEMSR_CTS 0x00000010 /**< Complement of CTS input */
#define UART_MEDEMSR_DCDX 0x00000008 /**< Delta DCD indicator */
#define UART_MEDEMSR_RIX 0x00000004 /**< Change of RI */
#define UART_MEDEMSR_DSRX 0x00000002 /**< Change of DSR */
#define UART_MEDEMSR_CTSX 0x00000001 /**< Change of CTS */
/* @} */
/** @name Channel Status Register
*
* The channel status register (CSR) is provided to enable the control logic
* to monitor the status of bits in the channel interrupt status register,
* even if these are masked out by the interrupt mask register.
*
* @{
*/
#define UART_SR_FLOWDEL 0x00001000 /**< RX FIFO fill over flow delay */
#define UART_SR_TACTIVE 0x00000800 /**< TX active */
#define UART_SR_RACTIVE 0x00000400 /**< RX active */
#define UART_SR_DMS 0x00000200 /**< Delta modem status change */
#define UART_SR_TOUT 0x00000100 /**< RX timeout */
#define UART_SR_PARITY 0x00000080 /**< RX parity error */
#define UART_SR_FRAME 0x00000040 /**< RX frame error */
#define UART_SR_OVER 0x00000020 /**< RX overflow error */
#define UART_SR_TXFULL 0x00000010 /**< TX FIFO full */
#define UART_SR_TXEMPTY 0x00000008 /**< TX FIFO empty */
#define UART_SR_RXFULL 0x00000004 /**< RX FIFO full */
#define UART_SR_RXEMPTY 0x00000002 /**< RX FIFO empty */
#define UART_SR_RXOVR 0x00000001 /**< RX FIFO fill over trigger */
/* @} */
/** @name Flow Delay Register
*
* Operation of the flow delay register (FLOWDEL) is very similar to the
* receive FIFO trigger register. An internal trigger signal activates when the
* FIFO is filled to the level set by this register. This trigger will not
* cause an interrupt, although it can be read through the channel status
* register. In hardware flow control mode, RTS is deactivated when the trigger
* becomes active. RTS only resets when the FIFO level is four less than the
* level of the flow delay trigger and the flow delay trigger is not activated.
* A value less than 4 disables the flow delay.
* @{
*/
#define UART_FLOWDEL_MASK UART_RXWM_MASK /**< Valid bit mask */
/* @} */
/****************************************************************************/
/**
* Determine if there is receive data in the receiver and/or FIFO.
*
* @param BaseAddress contains the base address of the device.
*
* @return TRUE if there is receive data, FALSE otherwise.
*
* @note C-Style signature:
* uint32_t UartDataReceived(uint32_t BaseAddress)
*
******************************************************************************/
#define UartDataReceived(BaseAddress) \
!((__REG32((BaseAddress) + UART_SR_OFFSET) & \
UART_SR_RXEMPTY) == UART_SR_RXEMPTY)
/****************************************************************************/
/**
* Determine if a byte of data can be sent with the transmitter.
*
* @param BaseAddress contains the base address of the device.
*
* @return TRUE if the TX FIFO is full, FALSE if a byte can be put in the
* FIFO.
*
* @note C-Style signature:
* uint32_t UartTXFIFOFull(uint32_t BaseAddress)
*
******************************************************************************/
#define UartTXFIFOFull(BaseAddress) \
((__REG32((BaseAddress) + UART_SR_OFFSET) & \
UART_SR_TXFULL) == UART_SR_TXFULL)
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,41 @@
#ifndef __ZYNQMP_R5_H__
#define __ZYNQMP_R5_H__
#include "xparameters.h"
#define __REG64(x) (*((volatile rt_uint64_t *)(x)))
#define __REG32(x) (*((volatile rt_uint32_t *)(x)))
#define __REG16(x) (*((volatile rt_uint16_t *)(x)))
#define __REG8(x) (*((volatile rt_uint8_t *)(x)))
#define ZynqMP_CRL_APB_BASEADDR XPAR_PSU_CRL_APB_S_AXI_BASEADDR
#define ZynqMP_CRL_APB_IOPLL_CTRL 0x020
#define ZynqMP_CRL_APB_IOPLL_CFG 0x024
#define ZynqMP_CRL_APB_UART0_REF_CTRL 0x074
#define ZynqMP_CRL_APB_UART1_REF_CTRL 0x078
#define ZynqMP_CRL_APB_LPD_LSBUS_CTRL 0x0AC
#define ZynqMP_CRL_APB_RESET_CTRL 0x218
#define ZynqMP_RESET_MASK 0x10
#define ZynqMP_GIC_CPU_BASE XPAR_PSU_RCPU_GIC_BASEADDR /* Generic interrupt controller CPU interface */
#define ZynqMP_GIC_DIST_BASE XPAR_PSU_RCPU_GIC_DIST_BASEADDR /* Generic interrupt controller distributor */
/* ZynqMP on-board gic irq sources */
#define IRQ_ZynqMP_MAXNR 195
#define ARM_GIC_NR_IRQS IRQ_ZynqMP_MAXNR
/* only one GIC available */
#define ARM_GIC_MAX_NR 1
#define GIC_ACK_INTID_MASK 0x000003FF
#define ZynqMP_R5_0_ID 0
#define ZynqMP_R5_1_ID 1
#define ZynqMP_R5_CPU_ID ZynqMP_R5_0_ID
static inline unsigned long rt_cpu_get_smp_id(void)
{
return ZynqMP_R5_CPU_ID;
}
#endif

View File

@ -0,0 +1,190 @@
#ifndef RT_CONFIG_H__
#define RT_CONFIG_H__
/* Automatically generated file; DO NOT EDIT. */
/* RT-Thread Project Configuration */
/* RT-Thread Kernel */
#define RT_NAME_MAX 20
#define RT_ALIGN_SIZE 4
#define RT_THREAD_PRIORITY_32
#define RT_THREAD_PRIORITY_MAX 32
#define RT_TICK_PER_SECOND 100
#define RT_USING_OVERFLOW_CHECK
#define RT_USING_HOOK
#define RT_USING_IDLE_HOOK
#define RT_IDLE_HOOK_LIST_SIZE 4
#define IDLE_THREAD_STACK_SIZE 512
#define RT_USING_TIMER_SOFT
#define RT_TIMER_THREAD_PRIO 4
#define RT_TIMER_THREAD_STACK_SIZE 512
#define RT_DEBUG
/* Inter-Thread communication */
#define RT_USING_SEMAPHORE
#define RT_USING_MUTEX
#define RT_USING_EVENT
#define RT_USING_MAILBOX
#define RT_USING_MESSAGEQUEUE
/* Memory Management */
#define RT_USING_MEMPOOL
#define RT_USING_SMALL_MEM
#define RT_USING_HEAP
/* Kernel Device Object */
#define RT_USING_DEVICE
#define RT_USING_CONSOLE
#define RT_CONSOLEBUF_SIZE 128
#define RT_CONSOLE_DEVICE_NAME "uart0"
#define RT_VER_NUM 0x40003
/* RT-Thread Components */
#define RT_USING_COMPONENTS_INIT
#define RT_USING_USER_MAIN
#define RT_MAIN_THREAD_STACK_SIZE 2048
#define RT_MAIN_THREAD_PRIORITY 10
/* C++ features */
/* Command shell */
#define RT_USING_FINSH
#define FINSH_THREAD_NAME "tshell"
#define FINSH_USING_HISTORY
#define FINSH_HISTORY_LINES 5
#define FINSH_USING_SYMTAB
#define FINSH_USING_DESCRIPTION
#define FINSH_THREAD_PRIORITY 20
#define FINSH_THREAD_STACK_SIZE 4096
#define FINSH_CMD_SIZE 80
#define FINSH_USING_MSH
#define FINSH_USING_MSH_DEFAULT
#define FINSH_ARG_MAX 10
/* Device virtual file system */
#define RT_USING_DFS
#define DFS_USING_WORKDIR
#define DFS_FILESYSTEMS_MAX 2
#define DFS_FILESYSTEM_TYPES_MAX 2
#define DFS_FD_MAX 16
#define RT_USING_DFS_ELMFAT
/* elm-chan's FatFs, Generic FAT Filesystem Module */
#define RT_DFS_ELM_CODE_PAGE 437
#define RT_DFS_ELM_WORD_ACCESS
#define RT_DFS_ELM_USE_LFN_3
#define RT_DFS_ELM_USE_LFN 3
#define RT_DFS_ELM_MAX_LFN 255
#define RT_DFS_ELM_DRIVES 2
#define RT_DFS_ELM_MAX_SECTOR_SIZE 512
#define RT_DFS_ELM_REENTRANT
#define RT_USING_DFS_DEVFS
/* Device Drivers */
#define RT_USING_DEVICE_IPC
#define RT_PIPE_BUFSZ 512
#define RT_USING_SERIAL
#define RT_SERIAL_USING_DMA
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_PIN
/* Using USB */
/* Using RapidIO */
/* POSIX layer and C standard library */
#define RT_USING_LIBC
#define RT_USING_POSIX
/* Network */
/* Socket abstraction layer */
/* Network interface device */
/* light weight TCP/IP stack */
/* AT commands */
/* VBUS(Virtual Software BUS) */
/* Utilities */
/* RT-Thread online packages */
/* IoT - internet of things */
/* Wi-Fi */
/* Marvell WiFi */
/* Wiced WiFi */
/* IoT Cloud */
/* security packages */
/* language packages */
/* multimedia packages */
/* tools packages */
/* system packages */
/* Micrium: Micrium software products porting for RT-Thread */
/* peripheral libraries and drivers */
/* miscellaneous packages */
/* samples: kernel and components samples */
#define SOC_ZYNQMP_R5
/* Hardware Drivers Config */
/* Onboard Peripheral Drivers */
/* On-chip Peripheral Drivers */
#define BSP_USING_UART
#define BSP_USING_UART0
#define BSP_USING_SDIO
#define BSP_USING_SD0
/* Board extended module Drivers */
#endif

View File

@ -0,0 +1,49 @@
import os
# toolchains options
ARCH='arm'
CPU='zynqmp-r5'
CROSS_TOOL='gcc'
if os.getenv('RTT_CC'):
CROSS_TOOL = os.getenv('RTT_CC')
# only support GNU GCC compiler
PLATFORM = 'gcc'
EXEC_PATH = '/opt/arm-none-eabi-gcc'
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
BUILD = 'debug'
if PLATFORM == 'gcc':
# toolchains
PREFIX = 'arm-none-eabi-'
CC = PREFIX + 'gcc'
CXX = PREFIX + 'g++'
AS = PREFIX + 'gcc'
AR = PREFIX + 'ar'
LINK = PREFIX + 'gcc'
TARGET_EXT = 'elf'
SIZE = PREFIX + 'size'
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
DEVICE = ' -Wall -mcpu=cortex-r5 -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=softfp'
CFLAGS = DEVICE
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp -D__ASSEMBLY__'
LINK_SCRIPT = 'zynqmp-r5.ld'
LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=zynqmp-r5.map,-cref,-u,system_vectors -T %s' % LINK_SCRIPT
CPATH = ''
LPATH = ''
if BUILD == 'debug':
CFLAGS += ' -O0 -gdwarf-2'
AFLAGS += ' -gdwarf-2'
else:
CFLAGS += ' -O2'
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' +\
SIZE + ' $TARGET \n'

View File

@ -0,0 +1,127 @@
MEMORY
{
psu_ocm_ram_0_MEM_0 : ORIGIN = 0xFFFC0000, LENGTH = 0x40000
psu_qspi_linear_0_MEM_0 : ORIGIN = 0xC0000000, LENGTH = 0x20000000
psu_r5_0_atcm_MEM_0 : ORIGIN = 0x0, LENGTH = 0x10000
psu_r5_0_btcm_MEM_0 : ORIGIN = 0x20000, LENGTH = 0x10000
psu_r5_ddr_0_MEM_0 : ORIGIN = 0x100000, LENGTH = 0x7FE00000
psu_r5_tcm_ram_0_MEM_0 : ORIGIN = 0x0, LENGTH = 0x40000
}
ENTRY(_reset)
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SECTIONS
{
.vectors :
{
KEEP (*(.vectors))
*(.boot)
*(.text.isr)
} > psu_r5_0_atcm_MEM_0
__text_start = .;
.text :
{
*(.text)
*(.text.*)
/* section information for utest */
. = ALIGN(4);
__rt_utest_tc_tab_start = .;
KEEP(*(UtestTcTab))
__rt_utest_tc_tab_end = .;
/* section information for finsh shell */
. = ALIGN(4);
__fsymtab_start = .;
KEEP(*(FSymTab))
__fsymtab_end = .;
. = ALIGN(4);
__vsymtab_start = .;
KEEP(*(VSymTab))
__vsymtab_end = .;
. = ALIGN(4);
/* section information for modules */
. = ALIGN(4);
__rtmsymtab_start = .;
KEEP(*(RTMSymTab))
__rtmsymtab_end = .;
/* section information for initialization */
. = ALIGN(4);
__rt_init_start = .;
KEEP(*(SORT(.rti_fn*)))
__rt_init_end = .;
} > psu_r5_ddr_0_MEM_0 = 0
__text_end = .;
__exidx_start = .;
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > psu_r5_ddr_0_MEM_0
__exidx_end = .;
.note-ABI-tag :
{
KEEP (*(.note-ABI-tag))
} > psu_r5_ddr_0_MEM_0
.note.gnu.build-id :
{
KEEP (*(.note.gnu.build-id))
} > psu_r5_ddr_0_MEM_0
__rodata_start = .;
.rodata : { *(.rodata) *(.rodata.*) } > psu_r5_ddr_0_MEM_0
__rodata_end = .;
. = ALIGN(4);
.ctors :
{
PROVIDE(__ctors_start__ = .);
KEEP(*(SORT(.ctors.*)))
KEEP(*(.ctors))
PROVIDE(__ctors_end__ = .);
} > psu_r5_ddr_0_MEM_0
.dtors :
{
PROVIDE(__dtors_start__ = .);
KEEP(*(SORT(.dtors.*)))
KEEP(*(.dtors))
PROVIDE(__dtors_end__ = .);
} > psu_r5_ddr_0_MEM_0
. = ALIGN(4);
__data_start = .;
.data :
{
*(.data)
*(.data.*)
} > psu_r5_ddr_0_MEM_0
__data_end = .;
. = ALIGN(4);
__bss_start = .;
.bss :
{
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
} > psu_r5_ddr_0_MEM_0
. = ALIGN(4);
__bss_end = .;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
_end = .;
}

View File

@ -0,0 +1,23 @@
# RT-Thread building script for component
from building import *
Import('rtconfig')
cwd = GetCurrentDir()
src = Glob('*.c') + Glob('*.cpp')
CPPPATH = [cwd]
if rtconfig.PLATFORM == 'armcc':
src += Glob('*_rvds.S')
if rtconfig.PLATFORM == 'gcc':
src += Glob('*_init.S')
src += Glob('*_gcc.S')
if rtconfig.PLATFORM == 'iar':
src += Glob('*_iar.S')
group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,67 @@
#ifndef __ARMV7_H__
#define __ARMV7_H__
/*
* COPYRIGHT (C) 2013-2014, Shanghai Real-Thread Technology Co., Ltd
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef VFP_DATA_NR
#define VFP_DATA_NR 32
#endif
/* the exception stack without VFP registers */
struct rt_hw_exp_stack
{
unsigned long r0;
unsigned long r1;
unsigned long r2;
unsigned long r3;
unsigned long r4;
unsigned long r5;
unsigned long r6;
unsigned long r7;
unsigned long r8;
unsigned long r9;
unsigned long r10;
unsigned long fp;
unsigned long ip;
unsigned long sp;
unsigned long lr;
unsigned long pc;
unsigned long cpsr;
};
#define USERMODE 0x10
#define FIQMODE 0x11
#define IRQMODE 0x12
#define SVCMODE 0x13
#define MONITORMODE 0x16
#define ABORTMODE 0x17
#define HYPMODE 0x1b
#define UNDEFMODE 0x1b
#define MODEMASK 0x1f
#define NOINT 0xc0
#define T_Bit (1<<5)
#define F_Bit (1<<6)
#define I_Bit (1<<7)
#define A_Bit (1<<8)
#define E_Bit (1<<9)
#define J_Bit (1<<24)
#endif

View File

@ -0,0 +1,200 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen first version
*/
#include <rthw.h>
#include <rtdef.h>
#include "xpseudo_asm_gcc.h"
#include "xreg_cortexr5.h"
#define IRQ_FIQ_MASK 0xC0 /* Mask IRQ and FIQ interrupts in cpsr */
typedef intptr_t INTPTR;
typedef rt_uint32_t u32;
#if defined (__GNUC__)
#define asm_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \
XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param))
#define asm_clean_inval_dc_line_sw(param) __asm__ __volatile__("mcr " \
XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param))
#define asm_clean_inval_dc_line_mva_poc(param) __asm__ __volatile__("mcr " \
XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param))
#define asm_inval_ic_line_mva_pou(param) __asm__ __volatile__("mcr " \
XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param))
#elif defined (__ICCARM__)
#define asm_inval_dc_line_mva_poc(param) __asm volatile("mcr " \
XREG_CP15_INVAL_DC_LINE_MVA_POC :: "r" (param))
#define asm_clean_inval_dc_line_sw(param) __asm volatile("mcr " \
XREG_CP15_CLEAN_INVAL_DC_LINE_SW :: "r" (param))
#define asm_clean_inval_dc_line_mva_poc(param) __asm volatile("mcr " \
XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC :: "r" (param))
#define asm_inval_ic_line_mva_pou(param) __asm volatile("mcr " \
XREG_CP15_INVAL_IC_LINE_MVA_POU :: "r" (param))
#endif
void Xil_ICacheInvalidateRange(INTPTR adr, u32 len)
{
u32 LocalAddr = adr;
const u32 cacheline = 32U;
u32 end;
u32 currmask;
currmask = mfcpsr();
mtcpsr(currmask | IRQ_FIQ_MASK);
if (len != 0x00000000U) {
/* Back the starting address up to the start of a cache line
* perform cache operations until adr+len
*/
end = LocalAddr + len;
LocalAddr = LocalAddr & ~(cacheline - 1U);
/* Select cache L0 I-cache in CSSR */
mtcp(XREG_CP15_CACHE_SIZE_SEL, 1U);
while (LocalAddr < end) {
/* Invalidate L1 I-cache line */
asm_inval_ic_line_mva_pou(LocalAddr);
LocalAddr += cacheline;
}
}
/* Wait for invalidate to complete */
dsb();
mtcpsr(currmask);
}
void Xil_DCacheFlushLine(INTPTR adr)
{
u32 currmask;
currmask = mfcpsr();
mtcpsr(currmask | IRQ_FIQ_MASK);
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0);
mtcp(XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC, (adr & (~0x1F)));
/* Wait for flush to complete */
dsb();
mtcpsr(currmask);
}
void Xil_DCacheInvalidateRange(INTPTR adr, u32 len)
{
const u32 cacheline = 32U;
u32 end;
u32 tempadr = adr;
u32 tempend;
u32 currmask;
currmask = mfcpsr();
mtcpsr(currmask | IRQ_FIQ_MASK);
if (len != 0U) {
end = tempadr + len;
tempend = end;
/* Select L1 Data cache in CSSR */
mtcp(XREG_CP15_CACHE_SIZE_SEL, 0U);
if ((tempadr & (cacheline-1U)) != 0U) {
tempadr &= (~(cacheline - 1U));
Xil_DCacheFlushLine(tempadr);
}
if ((tempend & (cacheline-1U)) != 0U) {
tempend &= (~(cacheline - 1U));
Xil_DCacheFlushLine(tempend);
}
while (tempadr < tempend) {
/* Invalidate Data cache line */
asm_inval_dc_line_mva_poc(tempadr);
tempadr += cacheline;
}
}
dsb();
mtcpsr(currmask);
}
void Xil_DCacheFlushRange(INTPTR adr, u32 len)
{
u32 LocalAddr = adr;
const u32 cacheline = 32U;
u32 end;
u32 currmask;
currmask = mfcpsr();
mtcpsr(currmask | IRQ_FIQ_MASK);
if (len != 0x00000000U) {
/* Back the starting address up to the start of a cache line
* perform cache operations until adr+len
*/
end = LocalAddr + len;
LocalAddr &= ~(cacheline - 1U);
while (LocalAddr < end) {
/* Flush Data cache line */
asm_clean_inval_dc_line_mva_poc(LocalAddr);
LocalAddr += cacheline;
}
}
dsb();
mtcpsr(currmask);
}
void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
{
if (ops == RT_HW_CACHE_INVALIDATE)
Xil_ICacheInvalidateRange((INTPTR)addr, size);
}
void rt_hw_cpu_dcache_ops(int ops, void *addr, int size)
{
if (ops == RT_HW_CACHE_FLUSH)
Xil_DCacheFlushRange((intptr_t)addr, size);
else if (ops == RT_HW_CACHE_INVALIDATE)
Xil_DCacheInvalidateRange((intptr_t)addr, size);
}
rt_base_t rt_hw_cpu_icache_status(void)
{
register u32 CtrlReg;
#if defined (__GNUC__)
CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
#elif defined (__ICCARM__)
mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
#endif
return CtrlReg & XREG_CP15_CONTROL_I_BIT;
}
rt_base_t rt_hw_cpu_dcache_status(void)
{
register u32 CtrlReg;
#if defined (__GNUC__)
CtrlReg = mfcp(XREG_CP15_SYS_CONTROL);
#elif defined (__ICCARM__)
mfcp(XREG_CP15_SYS_CONTROL,CtrlReg);
#endif
return CtrlReg & XREG_CP15_CONTROL_C_BIT;
}

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen first version
*/
.section .text, "ax"
/*
* rt_base_t rt_hw_interrupt_disable();
*/
.globl rt_hw_interrupt_disable
rt_hw_interrupt_disable:
mrs r0, cpsr
cpsid if
bx lr
/*
* void rt_hw_interrupt_enable(rt_base_t level);
*/
.globl rt_hw_interrupt_enable
rt_hw_interrupt_enable:
msr cpsr, r0
bx lr
/*
* void rt_hw_context_switch_to(rt_uint32 to);
* r0 --> to
*/
.globl rt_hw_context_switch_to
rt_hw_context_switch_to:
ldr sp, [r0] @ get new task stack pointer
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
ldmfd sp!, {r1} /* Restore floating point registers */
vmsr FPEXC, r1
ldmfd sp!, {r1}
vmsr FPSCR, r1
vldmia sp!, {d0-d15}
#endif
ldmfd sp!, {r4} @ pop new task spsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc
.section .text.isr, "ax"
/*
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
* r0 --> from
* r1 --> to
*/
.globl rt_hw_context_switch
rt_hw_context_switch:
stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC)
stmfd sp!, {r0-r12, lr} @ push lr & register file
mrs r4, cpsr
tst lr, #0x01
beq _ARM_MODE
orr r4, r4, #0x20 @ it's thumb code
_ARM_MODE:
stmfd sp!, {r4} @ push cpsr
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
vstmdb sp!, {d0-d15} /* Store floating point registers */
vmrs r4, FPSCR
stmfd sp!,{r4}
vmrs r4, FPEXC
stmfd sp!,{r4}
#endif
str sp, [r0] @ store sp in preempted tasks TCB
ldr sp, [r1] @ get new task stack pointer
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
ldmfd sp!, {r1} /* Restore floating point registers */
vmsr FPEXC, r1
ldmfd sp!, {r1}
vmsr FPSCR, r1
vldmia sp!, {d0-d15}
#endif
ldmfd sp!, {r4} @ pop new task cpsr to spsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
/*
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
*/
.globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
.globl rt_hw_context_switch_interrupt
rt_hw_context_switch_interrupt:
ldr r2, =rt_thread_switch_interrupt_flag
ldr r3, [r2]
cmp r3, #1
beq _reswitch
mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1
str r3, [r2]
ldr r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread
str r0, [r2]
_reswitch:
ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
str r1, [r2]
bx lr

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen first version
*/
#include <rthw.h>
#include <rtthread.h>
#include "zynqmp-r5.h"
void rt_hw_cpu_reset()
{
__REG32(ZynqMP_CRL_APB_BASEADDR + ZynqMP_CRL_APB_RESET_CTRL) |= ZynqMP_RESET_MASK;
while (1); /* loop forever and wait for reset to happen */
/* NEVER REACHED */
}
/**
* shutdown CPU
*
*/
void rt_hw_cpu_shutdown()
{
rt_uint32_t level;
rt_kprintf("shutdown...\n");
level = rt_hw_interrupt_disable();
while (level)
{
RT_ASSERT(0);
}
}

209
libcpu/arm/zynqmp-r5/gic.c Normal file
View File

@ -0,0 +1,209 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen first version
*/
#include <rtthread.h>
#include "board.h"
#include "gic.h"
/* ZynqMP-RPU uses the Arm PL-390 generic interrupt controller that is
* compliant to the GICv1 architecture specification. */
struct arm_gic
{
rt_uint32_t offset;
rt_uint32_t dist_hw_base;
rt_uint32_t cpu_hw_base;
};
static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
#define GIC_CPU_CTRL(hw_base) __REG32((hw_base) + 0x00)
#define GIC_CPU_PRIMASK(hw_base) __REG32((hw_base) + 0x04)
#define GIC_CPU_BINPOINT(hw_base) __REG32((hw_base) + 0x08)
#define GIC_CPU_INTACK(hw_base) __REG32((hw_base) + 0x0c)
#define GIC_CPU_EOI(hw_base) __REG32((hw_base) + 0x10)
#define GIC_CPU_RUNNINGPRI(hw_base) __REG32((hw_base) + 0x14)
#define GIC_CPU_HIGHPRI(hw_base) __REG32((hw_base) + 0x18)
#define GIC_DIST_CTRL(hw_base) __REG32((hw_base) + 0x000)
#define GIC_DIST_TYPE(hw_base) __REG32((hw_base) + 0x004)
#define GIC_DIST_IGROUP(hw_base, n) __REG32((hw_base) + 0x080 + ((n)/32) * 4)
#define GIC_DIST_ENABLE_SET(hw_base, n) __REG32((hw_base) + 0x100 + ((n)/32) * 4)
#define GIC_DIST_ENABLE_CLEAR(hw_base, n) __REG32((hw_base) + 0x180 + ((n)/32) * 4)
#define GIC_DIST_PENDING_SET(hw_base, n) __REG32((hw_base) + 0x200 + ((n)/32) * 4)
#define GIC_DIST_PENDING_CLEAR(hw_base, n) __REG32((hw_base) + 0x280 + ((n)/32) * 4)
#define GIC_DIST_ACTIVE_SET(hw_base, n) __REG32((hw_base) + 0x300 + ((n)/32) * 4)
#define GIC_DIST_PRI(hw_base, n) __REG32((hw_base) + 0x400 + ((n)/4) * 4)
#define GIC_DIST_TARGET(hw_base, n) __REG32((hw_base) + 0x800 + ((n)/4) * 4)
#define GIC_DIST_CONFIG(hw_base, n) __REG32((hw_base) + 0xc00 + ((n)/16) * 4)
#define GIC_DIST_SOFTINT(hw_base) __REG32((hw_base) + 0xf00)
#define GIC_DIST_ICPIDR2(hw_base) __REG32((hw_base) + 0xfe8)
static unsigned int _gic_max_irq;
int arm_gic_get_active_irq(rt_uint32_t index)
{
int irq;
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = GIC_CPU_INTACK(_gic_table[index].cpu_hw_base);
irq += _gic_table[index].offset;
return irq;
}
void arm_gic_ack(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1 << (irq % 32);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0);
GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
GIC_CPU_EOI(_gic_table[index].cpu_hw_base) = irq;
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
}
void arm_gic_mask(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1 << (irq % 32);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0);
GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
}
void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask)
{
rt_uint32_t old_tgt;
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0);
old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq);
old_tgt &= ~(0x0FFUL << ((irq % 4)*8));
old_tgt |= cpumask << ((irq % 4)*8);
GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
}
void arm_gic_umask(rt_uint32_t index, int irq)
{
rt_uint32_t mask = 1 << (irq % 32);
RT_ASSERT(index < ARM_GIC_MAX_NR);
irq = irq - _gic_table[index].offset;
RT_ASSERT(irq >= 0);
GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
}
void arm_gic_dump_type(rt_uint32_t index)
{
unsigned int gic_type;
gic_type = GIC_DIST_TYPE(_gic_table[index].dist_hw_base);
rt_kprintf("GICv%d on %p, max IRQs: %d, %s security extension(%08x)\n",
(GIC_DIST_ICPIDR2(_gic_table[index].dist_hw_base) >> 4) & 0xf,
_gic_table[index].dist_hw_base,
_gic_max_irq,
gic_type & (1 << 10) ? "has" : "no",
gic_type);
}
int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
{
unsigned int gic_type, i;
rt_uint32_t cpumask = 1 << 0;
RT_ASSERT(index < ARM_GIC_MAX_NR);
_gic_table[index].dist_hw_base = dist_base;
_gic_table[index].offset = irq_start;
/* Find out how many interrupts are supported. */
gic_type = GIC_DIST_TYPE(dist_base);
_gic_max_irq = ((gic_type & 0x1f) + 1) * 32;
/*
* The GIC only supports up to 1020 interrupt sources.
* Limit this to either the architected maximum, or the
* platform maximum.
*/
if (_gic_max_irq > 1020)
_gic_max_irq = 1020;
if (_gic_max_irq > ARM_GIC_NR_IRQS)
_gic_max_irq = ARM_GIC_NR_IRQS;
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;
GIC_DIST_CTRL(dist_base) = 0x0;
/* Set all global interrupts to be level triggered, active low. */
for (i = 32; i < _gic_max_irq; i += 16)
GIC_DIST_CONFIG(dist_base, i) = 0x0;
/* Set all global interrupts to this CPU only. */
for (i = 32; i < _gic_max_irq; i += 4)
GIC_DIST_TARGET(dist_base, i) = cpumask;
/* Set priority on all interrupts. */
for (i = 0; i < _gic_max_irq; i += 4)
GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0;
/* Disable all interrupts. */
for (i = 0; i < _gic_max_irq; i += 32)
GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffff;
/* Enable interrupt. */
GIC_DIST_CTRL(dist_base) = 0x01;
return 0;
}
int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base)
{
RT_ASSERT(index < ARM_GIC_MAX_NR);
_gic_table[index].cpu_hw_base = cpu_base;
GIC_CPU_PRIMASK(cpu_base) = 0xf0;
/* Enable CPU interrupt */
GIC_CPU_CTRL(cpu_base) = 0x01;
return 0;
}
void arm_gic_trigger(rt_uint32_t index, int target_cpu, int irq)
{
unsigned int reg;
RT_ASSERT(irq <= 15);
RT_ASSERT(target_cpu <= 255);
reg = (target_cpu << 16) | irq;
GIC_DIST_SOFTINT(_gic_table[index].dist_hw_base) = reg;
}
void arm_gic_clear_sgi(rt_uint32_t index, int target_cpu, int irq)
{
/* SGI will be cleared automatically. */
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen first version
*/
#ifndef __GIC_H__
#define __GIC_H__
int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start);
int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base);
void arm_gic_mask(rt_uint32_t index, int irq);
void arm_gic_umask(rt_uint32_t index, int irq);
void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask);
int arm_gic_get_active_irq(rt_uint32_t index);
void arm_gic_ack(rt_uint32_t index, int irq);
void arm_gic_trigger(rt_uint32_t index, int target_cpu, int irq);
void arm_gic_clear_sgi(rt_uint32_t index, int target_cpu, int irq);
void arm_gic_dump_type(rt_uint32_t index);
#endif

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen first version
*/
#include <rthw.h>
#include <rtthread.h>
#include "zynqmp-r5.h"
#include "interrupt.h"
#include "gic.h"
#define MAX_HANDLERS IRQ_ZynqMP_MAXNR
extern volatile rt_uint8_t rt_interrupt_nest;
/* exception and interrupt handler table */
struct rt_irq_desc isr_table[MAX_HANDLERS];
rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrupt_flag;
void rt_hw_interrupt_handle(int vector, void *param)
{
rt_kprintf("UN-handled interrupt %d occurred!!!\n", vector);
}
void rt_hw_interrupt_init(void)
{
register rt_uint32_t idx;
/* the initialization is done in fsbl */
/* init exceptions table */
rt_memset(isr_table, 0x00, sizeof(isr_table));
for (idx = 0; idx < MAX_HANDLERS; idx++)
{
isr_table[idx].handler = rt_hw_interrupt_handle;
}
/* initialize ARM GIC */
arm_gic_dist_init(0, ZynqMP_GIC_DIST_BASE, 0);
arm_gic_cpu_init(0, ZynqMP_GIC_CPU_BASE);
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
rt_interrupt_to_thread = 0;
rt_thread_switch_interrupt_flag = 0;
}
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int vector)
{
arm_gic_mask(0, vector);
}
/**
* This function will un-mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_umask(int vector)
{
arm_gic_umask(0, vector);
}
/**
* This function returns the active interrupt number.
* @param none
*/
int rt_hw_interrupt_get_irq(void)
{
return arm_gic_get_active_irq(0) & GIC_ACK_INTID_MASK;
}
/**
* This function acknowledges the interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_ack(int vector)
{
arm_gic_ack(0, vector);
}
/**
* This function will install a interrupt service routine to a interrupt.
* @param vector the interrupt number
* @param handler the interrupt service routine to be installed
* @param param the parameter for interrupt service routine
* @param name the interrupt name
*
* @return the old handler
*/
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name)
{
rt_isr_handler_t old_handler = RT_NULL;
if (vector < MAX_HANDLERS)
{
old_handler = isr_table[vector].handler;
if (handler != RT_NULL)
{
#ifdef RT_USING_INTERRUPT_INFO
rt_snprintf(isr_table[vector].name, RT_NAME_MAX, "%s", name);
#endif /* RT_USING_INTERRUPT_INFO */
isr_table[vector].handler = handler;
isr_table[vector].param = param;
}
/* set the interrupt to this cpu */
arm_gic_set_cpu(0, vector, 1 << rt_cpu_get_smp_id());
}
return old_handler;
}
void rt_hw_interrupt_trigger(int vector)
{
arm_gic_trigger(0, 1 << rt_cpu_get_smp_id(), vector);
}
void rt_hw_interrupt_clear(int vector)
{
/* SGI will be cleared automatically. */
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen first version
*/
#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__
#include <rthw.h>
#include <board.h>
void rt_hw_interrupt_init(void);
void rt_hw_interrupt_mask(int vector);
void rt_hw_interrupt_umask(int vector);
int rt_hw_interrupt_get_irq(void);
void rt_hw_interrupt_trigger(int vector);
void rt_hw_interrupt_clear(int vector);
void rt_hw_interrupt_ack(int vector);
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
void *param, const char *name);
#endif

288
libcpu/arm/zynqmp-r5/mpu.c Normal file
View File

@ -0,0 +1,288 @@
/******************************************************************************
* Copyright (c) 2014 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
* @file mpu.c
*
* This file contains initial configuration of the MPU.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------
* 5.00 pkp 02/20/14 First release
* 5.04 pkp 12/18/15 Updated MPU initialization as per the proper address map
* 6.00 pkp 06/27/16 moving the Init_MPU code to .boot section since it is a
* part of processor boot process
* 6.2 mus 01/27/17 Updated to support IAR compiler
* 7.1 mus 09/11/19 Added warning message if DDR size is not in power of 2.
* Fix for CR#1038577.
* 7.2 asa 04/08/20 Fix warning in the function Init_MPU.
* </pre>
*
* @note
*
* None.
*
******************************************************************************/
/***************************** Include Files *********************************/
#include <rtthread.h>
#include "zynqmp-r5.h"
#include "xreg_cortexr5.h"
#include "xpseudo_asm_gcc.h"
/***************** Macros (Inline Functions) Definitions *********************/
/**************************** Type Definitions *******************************/
typedef rt_int32_t s32;
typedef rt_uint64_t u64;
typedef rt_uint32_t u32;
/************************** Constant Definitions *****************************/
/************************** Variable Definitions *****************************/
static const struct {
u64 size;
unsigned int encoding;
}region_size[] = {
{ 0x20, REGION_32B },
{ 0x40, REGION_64B },
{ 0x80, REGION_128B },
{ 0x100, REGION_256B },
{ 0x200, REGION_512B },
{ 0x400, REGION_1K },
{ 0x800, REGION_2K },
{ 0x1000, REGION_4K },
{ 0x2000, REGION_8K },
{ 0x4000, REGION_16K },
{ 0x8000, REGION_32K },
{ 0x10000, REGION_64K },
{ 0x20000, REGION_128K },
{ 0x40000, REGION_256K },
{ 0x80000, REGION_512K },
{ 0x100000, REGION_1M },
{ 0x200000, REGION_2M },
{ 0x400000, REGION_4M },
{ 0x800000, REGION_8M },
{ 0x1000000, REGION_16M },
{ 0x2000000, REGION_32M },
{ 0x4000000, REGION_64M },
{ 0x8000000, REGION_128M },
{ 0x10000000, REGION_256M },
{ 0x20000000, REGION_512M },
{ 0x40000000, REGION_1G },
{ 0x80000000, REGION_2G },
{ 0x100000000, REGION_4G },
};
/************************** Function Prototypes ******************************/
#if defined (__GNUC__)
void Init_MPU(void) __attribute__((__section__(".boot")));
static void Xil_SetAttribute(u32 addr, u32 reg_size,s32 reg_num, u32 attrib) __attribute__((__section__(".boot")));
static void Xil_DisableMPURegions(void) __attribute__((__section__(".boot")));
#elif defined (__ICCARM__)
#pragma default_function_attributes = @ ".boot"
void Init_MPU(void);
static void Xil_SetAttribute(u32 addr, u32 reg_size,s32 reg_num, u32 attrib);
static void Xil_DisableMPURegions(void);
#endif
/*****************************************************************************
*
* Initialize MPU for a given address map and Enabled the background Region in
* MPU with default memory attributes for rest of address range for Cortex R5
* processor.
*
* @param None.
*
* @return None.
*
*
******************************************************************************/
void Init_MPU(void)
{
u32 Addr;
u32 RegSize = 0U;
u32 Attrib;
u32 RegNum = 0, i, Offset = 0;
u64 size;
Xil_DisableMPURegions();
Addr = 0x00000000U;
#ifdef XPAR_PSU_R5_DDR_0_S_AXI_BASEADDR
/* If the DDR is present, configure region as per DDR size */
size = (XPAR_PSU_R5_DDR_0_S_AXI_HIGHADDR - XPAR_PSU_R5_DDR_0_S_AXI_BASEADDR) + 1;
if (size < 0x80000000) {
/* Lookup the size. */
for (i = 0; i < sizeof region_size / sizeof region_size[0]; i++) {
if (size <= region_size[i].size) {
RegSize = region_size[i].encoding;
/* Check if DDR size is in power of 2*/
if ( XPAR_PSU_R5_DDR_0_S_AXI_BASEADDR == 0x100000)
Offset = XPAR_PSU_R5_DDR_0_S_AXI_BASEADDR;
if (region_size[i].size > (size + Offset + 1)) {
rt_kprintf ("WARNING: DDR size mapped to Cortexr5 processor is not \
in power of 2. As processor allocates MPU regions size \
in power of 2, address range %llx to %x has been \
incorrectly mapped as normal memory \n", \
region_size[i].size - 1, ((u32)XPAR_PSU_R5_DDR_0_S_AXI_HIGHADDR + 1));
}
break;
}
}
} else {
/* if the DDR size is > 2GB, truncate it to 2GB */
RegSize = REGION_2G;
}
#else
/* For DDRless system, configure region for TCM */
RegSize = REGION_256K;
#endif
Attrib = NORM_NSHARED_WB_WA | PRIV_RW_USER_RW;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/*
* 1G of strongly ordered memory from 0x80000000 to 0xBFFFFFFF for PL.
* 512 MB - LPD-PL interface
* 256 MB - FPD-PL (HPM0) interface
* 256 MB - FPD-PL (HPM1) interface
*/
Addr = 0x80000000;
RegSize = REGION_1G;
Attrib = STRONG_ORDERD_SHARED | PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/* 512M of device memory from 0xC0000000 to 0xDFFFFFFF for QSPI */
Addr = 0xC0000000U;
RegSize = REGION_512M;
Attrib = DEVICE_NONSHARED | PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/* 256M of device memory from 0xE0000000 to 0xEFFFFFFF for PCIe Low */
Addr = 0xE0000000U;
RegSize = REGION_256M;
Attrib = DEVICE_NONSHARED | PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/* 16M of device memory from 0xF8000000 to 0xF8FFFFFF for STM_CORESIGHT */
Addr = 0xF8000000U;
RegSize = REGION_16M;
Attrib = DEVICE_NONSHARED | PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/* 1M of device memory from 0xF9000000 to 0xF90FFFFF for RPU_A53_GIC */
Addr = 0xF9000000U;
RegSize = REGION_1M;
Attrib = DEVICE_NONSHARED | PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/* 16M of device memory from 0xFD000000 to 0xFDFFFFFF for FPS slaves */
Addr = 0xFD000000U;
RegSize = REGION_16M;
Attrib = DEVICE_NONSHARED | PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/* 16M of device memory from 0xFE000000 to 0xFEFFFFFF for Upper LPS slaves */
Addr = 0xFE000000U;
RegSize = REGION_16M;
Attrib = DEVICE_NONSHARED | PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/*
* 16M of device memory from 0xFF000000 to 0xFFFFFFFF for Lower LPS slaves,
* CSU, PMU, TCM, OCM
*/
Addr = 0xFF000000U;
RegSize = REGION_16M;
Attrib = DEVICE_NONSHARED | PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
RegNum++;
/* 256K of OCM RAM from 0xFFFC0000 to 0xFFFFFFFF marked as normal memory */
Addr = 0xFFFC0000U;
RegSize = REGION_256K;
Attrib = NORM_NSHARED_WB_WA| PRIV_RW_USER_RW ;
Xil_SetAttribute(Addr,RegSize,RegNum, Attrib);
/* A total of 10 MPU regions are allocated with another 6 being free for users */
}
/*****************************************************************************
*
* Set the memory attributes for a section of memory with starting address addr
* of the region size defined by reg_size having attributes attrib of region number
* reg_num
*
* @param addr is the address for which attributes are to be set.
* @param attrib specifies the attributes for that memory region.
* @param reg_size specifies the size for that memory region.
* @param reg_num specifies the number for that memory region.
* @return None.
*
*
******************************************************************************/
static void Xil_SetAttribute(u32 addr, u32 reg_size,s32 reg_num, u32 attrib)
{
u32 Local_reg_size = reg_size;
Local_reg_size = Local_reg_size<<1U;
Local_reg_size |= REGION_EN;
dsb();
mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,reg_num);
isb();
mtcp(XREG_CP15_MPU_REG_BASEADDR,addr); /* Set base address of a region */
mtcp(XREG_CP15_MPU_REG_ACCESS_CTRL,attrib); /* Set the control attribute */
mtcp(XREG_CP15_MPU_REG_SIZE_EN,Local_reg_size); /* set the region size and enable it*/
dsb();
isb(); /* synchronize context on this processor */
}
/*****************************************************************************
*
* Disable all the MPU regions if any of them is enabled
*
* @param None.
*
* @return None.
*
*
******************************************************************************/
static void Xil_DisableMPURegions(void)
{
u32 Temp = 0U;
u32 Index = 0U;
for (Index = 0; Index <= 15; Index++) {
mtcp(XREG_CP15_MPU_MEMORY_REG_NUMBER,Index);
#if defined (__GNUC__)
Temp = mfcp(XREG_CP15_MPU_REG_SIZE_EN);
#elif defined (__ICCARM__)
mfcp(XREG_CP15_MPU_REG_SIZE_EN,Temp);
#endif
Temp &= (~REGION_EN);
dsb();
mtcp(XREG_CP15_MPU_REG_SIZE_EN,Temp);
dsb();
isb();
}
}
#if defined (__ICCARM__)
#pragma default_function_attributes =
#endif

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-09-23 Bernard the first version
* 2011-10-05 Bernard add thumb mode
* 2020-11-24 WangHuachen porting to zynqmp-r5
*/
#include <rtthread.h>
#include "armv7.h"
/**
* This function will initialize thread stack
*
* @param tentry the entry of thread
* @param parameter the parameter of entry
* @param stack_addr the beginning stack address
* @param texit the function will be called when thread exit
*
* @return stack address
*/
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit)
{
rt_uint32_t *stk;
stack_addr += sizeof(rt_uint32_t);
stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8);
stk = (rt_uint32_t *)stack_addr;
*(--stk) = (rt_uint32_t)tentry; /* entry point */
*(--stk) = (rt_uint32_t)texit; /* lr */
*(--stk) = 0xdeadbeef; /* r12 */
*(--stk) = 0xdeadbeef; /* r11 */
*(--stk) = 0xdeadbeef; /* r10 */
*(--stk) = 0xdeadbeef; /* r9 */
*(--stk) = 0xdeadbeef; /* r8 */
*(--stk) = 0xdeadbeef; /* r7 */
*(--stk) = 0xdeadbeef; /* r6 */
*(--stk) = 0xdeadbeef; /* r5 */
*(--stk) = 0xdeadbeef; /* r4 */
*(--stk) = 0xdeadbeef; /* r3 */
*(--stk) = 0xdeadbeef; /* r2 */
*(--stk) = 0xdeadbeef; /* r1 */
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
/* cpsr */
if ((rt_uint32_t)tentry & 0x01)
*(--stk) = SVCMODE | 0x20; /* thumb mode */
else
*(--stk) = SVCMODE; /* arm mode */
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
{
int i;
for (i = 0; i < VFP_DATA_NR; i++)
{
*(--stk) = 0;
}
/* FPSCR TODO: do we need to set the values other than 0? */
*(--stk) = 0;
/* FPEXC. Enable the FVP if no lazy stacking. */
*(--stk) = 0x40000000;
}
#endif
/* return task's current stack address */
return (rt_uint8_t *)stk;
}

View File

@ -0,0 +1,424 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-03-19 WangHuachen first version
*/
.equ Mode_USR, 0x10
.equ Mode_FIQ, 0x11
.equ Mode_IRQ, 0x12
.equ Mode_SVC, 0x13
.equ Mode_ABT, 0x17
.equ Mode_UND, 0x1B
.equ Mode_SYS, 0x1F
.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled
.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled
.equ UND_Stack_Size, 0x00000000
.equ SVC_Stack_Size, 0x00000000
.equ ABT_Stack_Size, 0x00000000
.equ FIQ_Stack_Size, 0x00000200
.equ IRQ_Stack_Size, 0x00000200
.equ USR_Stack_Size, 0x00000000
.set RPU_GLBL_CNTL, 0xFF9A0000
.set RPU_ERR_INJ, 0xFF9A0020
.set RPU_0_CFG, 0xFF9A0100
.set RPU_1_CFG, 0xFF9A0200
.set RST_LPD_DBG, 0xFF5E0240
.set BOOT_MODE_USER, 0xFF5E0200
.set fault_log_enable, 0x101
#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \
FIQ_Stack_Size + IRQ_Stack_Size)
.section .data.share.isr
/* stack */
.globl stack_start
.globl stack_top
.align 3
.bss
stack_start:
.rept ISR_Stack_Size
.long 0
.endr
stack_top:
.section .boot,"axS"
/* reset entry */
.globl _reset
_reset:
/* Initialize processor registers to 0 */
mov r0,#0
mov r1,#0
mov r2,#0
mov r3,#0
mov r4,#0
mov r5,#0
mov r6,#0
mov r7,#0
mov r8,#0
mov r9,#0
mov r10,#0
mov r11,#0
mov r12,#0
/* set the cpu to SVC32 mode and disable interrupt */
cpsid if, #Mode_SVC
/* setup stack */
bl stack_setup
/*
* Enable access to VFP by enabling access to Coprocessors 10 and 11.
* Enables Full Access i.e. in both privileged and non privileged modes
*/
mrc p15, 0, r0, c1, c0, 2 /* Read Coprocessor Access Control Register (CPACR) */
orr r0, r0, #(0xF << 20) /* Enable access to CP 10 & 11 */
mcr p15, 0, r0, c1, c0, 2 /* Write Coprocessor Access Control Register (CPACR) */
isb
/* enable fpu access */
vmrs r3, FPEXC
orr r1, r3, #(1<<30)
vmsr FPEXC, r1
/* clear the floating point register*/
mov r1,#0
vmov d0,r1,r1
vmov d1,r1,r1
vmov d2,r1,r1
vmov d3,r1,r1
vmov d4,r1,r1
vmov d5,r1,r1
vmov d6,r1,r1
vmov d7,r1,r1
vmov d8,r1,r1
vmov d9,r1,r1
vmov d10,r1,r1
vmov d11,r1,r1
vmov d12,r1,r1
vmov d13,r1,r1
vmov d14,r1,r1
vmov d15,r1,r1
#ifdef __SOFTFP__
/* Disable the FPU if SOFTFP is defined*/
vmsr FPEXC,r3
#endif
/* Disable MPU and caches */
mrc p15, 0, r0, c1, c0, 0 /* Read CP15 Control Register*/
bic r0, r0, #0x05 /* Disable MPU (M bit) and data cache (C bit) */
bic r0, r0, #0x1000 /* Disable instruction cache (I bit) */
dsb /* Ensure all previous loads/stores have completed */
mcr p15, 0, r0, c1, c0, 0 /* Write CP15 Control Register */
isb /* Ensure subsequent insts execute wrt new MPU settings */
/* Disable Branch prediction, TCM ECC checks */
mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR */
orr r0, r0, #(0x1 << 17) /* Enable RSDIS bit 17 to disable the return stack */
orr r0, r0, #(0x1 << 16) /* Clear BP bit 15 and set BP bit 16:*/
bic r0, r0, #(0x1 << 15) /* Branch always not taken and history table updates disabled*/
orr r0, r0, #(0x1 << 27) /* Enable B1TCM ECC check */
orr r0, r0, #(0x1 << 26) /* Enable B0TCM ECC check */
orr r0, r0, #(0x1 << 25) /* Enable ATCM ECC check */
bic r0, r0, #(0x1 << 5) /* Generate abort on parity errors, with [5:3]=b 000*/
bic r0, r0, #(0x1 << 4)
bic r0, r0, #(0x1 << 3)
mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/
dsb /* Complete all outstanding explicit memory operations*/
/* Invalidate caches */
mov r0,#0 /* r0 = 0 */
dsb
mcr p15, 0, r0, c7, c5, 0 /* invalidate icache */
mcr p15, 0, r0, c15, c5, 0 /* Invalidate entire data cache*/
isb
/* enable fault log for lock step */
ldr r0,=RPU_GLBL_CNTL
ldr r1, [r0]
ands r1, r1, #0x8
/* branch to initialization if split mode*/
bne init
/* check for boot mode if in lock step, branch to init if JTAG boot mode*/
ldr r0,=BOOT_MODE_USER
ldr r1, [r0]
ands r1, r1, #0xF
beq init
/* reset the debug logic */
ldr r0,=RST_LPD_DBG
ldr r1, [r0]
orr r1, r1, #(0x1 << 4)
orr r1, r1, #(0x1 << 5)
str r1, [r0]
/* enable fault log */
ldr r0,=RPU_ERR_INJ
ldr r1,=fault_log_enable
ldr r2, [r0]
orr r2, r2, r1
str r2, [r0]
nop
nop
init:
bl Init_MPU /* Initialize MPU */
/* Enable Branch prediction */
mrc p15, 0, r0, c1, c0, 1 /* Read ACTLR*/
bic r0, r0, #(0x1 << 17) /* Clear RSDIS bit 17 to enable return stack*/
bic r0, r0, #(0x1 << 16) /* Clear BP bit 15 and BP bit 16:*/
bic r0, r0, #(0x1 << 15) /* Normal operation, BP is taken from the global history table.*/
orr r0, r0, #(0x1 << 14) /* Disable DBWR for errata 780125 */
mcr p15, 0, r0, c1, c0, 1 /* Write ACTLR*/
/* Enable icahce and dcache */
mrc p15,0,r1,c1,c0,0
ldr r0, =0x1005
orr r1,r1,r0
dsb
mcr p15,0,r1,c1,c0,0 /* Enable cache */
isb /* isb flush prefetch buffer */
/* Set vector table in TCM/LOVEC */
mrc p15, 0, r0, c1, c0, 0
mvn r1, #0x2000
and r0, r0, r1
mcr p15, 0, r0, c1, c0, 0
/* Clear VINITHI to enable LOVEC on reset */
#if 1
ldr r0, =RPU_0_CFG
#else
ldr r0, =RPU_1_CFG
#endif
ldr r1, [r0]
bic r1, r1, #(0x1 << 2)
str r1, [r0]
/* enable asynchronous abort exception */
mrs r0, cpsr
bic r0, r0, #0x100
msr cpsr_xsf, r0
/* clear .bss */
mov r0,#0 /* get a zero */
ldr r1,=__bss_start /* bss start */
ldr r2,=__bss_end /* bss end */
bss_loop:
cmp r1,r2 /* check if data to clear */
strlo r0,[r1],#4 /* clear 4 bytes */
blo bss_loop /* loop until done */
/* call C++ constructors of global objects */
ldr r0, =__ctors_start__
ldr r1, =__ctors_end__
ctor_loop:
cmp r0, r1
beq ctor_end
ldr r2, [r0], #4
stmfd sp!, {r0-r1}
mov lr, pc
bx r2
ldmfd sp!, {r0-r1}
b ctor_loop
ctor_end:
/* start RT-Thread Kernel */
ldr pc, _entry
_entry:
.word entry
stack_setup:
ldr r0, =stack_top
@ Set the startup stack for svc
mov sp, r0
@ Enter Undefined Instruction Mode and set its Stack Pointer
msr cpsr_c, #Mode_UND|I_Bit|F_Bit
mov sp, r0
sub r0, r0, #UND_Stack_Size
@ Enter Abort Mode and set its Stack Pointer
msr cpsr_c, #Mode_ABT|I_Bit|F_Bit
mov sp, r0
sub r0, r0, #ABT_Stack_Size
@ Enter FIQ Mode and set its Stack Pointer
msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit
mov sp, r0
sub r0, r0, #FIQ_Stack_Size
@ Enter IRQ Mode and set its Stack Pointer
msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit
mov sp, r0
sub r0, r0, #IRQ_Stack_Size
@ Switch back to SVC
msr cpsr_c, #Mode_SVC|I_Bit|F_Bit
bx lr
.section .text.isr, "ax"
/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */
.align 5
.globl vector_fiq
vector_fiq:
stmfd sp!,{r0-r7,lr}
bl rt_hw_trap_fiq
ldmfd sp!,{r0-r7,lr}
subs pc,lr,#4
.globl rt_interrupt_enter
.globl rt_interrupt_leave
.globl rt_thread_switch_interrupt_flag
.globl rt_interrupt_from_thread
.globl rt_interrupt_to_thread
.align 5
.globl vector_irq
vector_irq:
stmfd sp!, {r0-r12,lr}
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
vstmdb sp!, {d0-d15} /* Store floating point registers */
vmrs r1, FPSCR
stmfd sp!,{r1}
vmrs r1, FPEXC
stmfd sp!,{r1}
#endif
bl rt_interrupt_enter
bl rt_hw_trap_irq
bl rt_interrupt_leave
@ if rt_thread_switch_interrupt_flag set, jump to
@ rt_hw_context_switch_interrupt_do and don't return
ldr r0, =rt_thread_switch_interrupt_flag
ldr r1, [r0]
cmp r1, #1
beq rt_hw_context_switch_interrupt_do
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
ldmfd sp!, {r1} /* Restore floating point registers */
vmsr FPEXC, r1
ldmfd sp!, {r1}
vmsr FPSCR, r1
vldmia sp!, {d0-d15}
#endif
ldmfd sp!, {r0-r12,lr}
subs pc, lr, #4
rt_hw_context_switch_interrupt_do:
mov r1, #0 @ clear flag
str r1, [r0]
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
ldmfd sp!, {r1} /* Restore floating point registers */
vmsr FPEXC, r1
ldmfd sp!, {r1}
vmsr FPSCR, r1
vldmia sp!, {d0-d15}
#endif
mov r1, sp @ r1 point to {r0-r3} in stack
add sp, sp, #4*4
ldmfd sp!, {r4-r12,lr}@ reload saved registers
mrs r0, spsr @ get cpsr of interrupt thread
sub r2, lr, #4 @ save old task's pc to r2
@ Switch to SVC mode with no interrupt.
msr cpsr_c, #I_Bit|F_Bit|Mode_SVC
stmfd sp!, {r2} @ push old task's pc
stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4
ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread
stmfd sp!, {r1-r4} @ push old task's r0-r3
stmfd sp!, {r0} @ push old task's cpsr
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
vstmdb sp!, {d0-d15} /* Store floating point registers */
vmrs r1, FPSCR
stmfd sp!,{r1}
vmrs r1, FPEXC
stmfd sp!,{r1}
#endif
ldr r4, =rt_interrupt_from_thread
ldr r5, [r4]
str sp, [r5] @ store sp in preempted tasks's TCB
ldr r6, =rt_interrupt_to_thread
ldr r7, [r6]
ldr sp, [r7] @ get new task's stack pointer
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
ldmfd sp!, {r1} /* Restore floating point registers */
vmsr FPEXC, r1
ldmfd sp!, {r1}
vmsr FPSCR, r1
vldmia sp!, {d0-d15}
#endif
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
msr spsr_cxsf, r4
ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
.macro push_svc_reg
sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */
stmia sp, {r0 - r12} @/* Calling r0-r12 */
mov r0, sp
mrs r6, spsr @/* Save CPSR */
str lr, [r0, #15*4] @/* Push PC */
str r6, [r0, #16*4] @/* Push CPSR */
cps #Mode_SVC
str sp, [r0, #13*4] @/* Save calling SP */
str lr, [r0, #14*4] @/* Save calling PC */
.endm
.align 5
.globl vector_swi
vector_swi:
push_svc_reg
bl rt_hw_trap_swi
b .
.align 5
.globl vector_undef
vector_undef:
push_svc_reg
bl rt_hw_trap_undef
b .
.align 5
.globl vector_pabt
vector_pabt:
push_svc_reg
bl rt_hw_trap_pabt
b .
.align 5
.globl vector_dabt
vector_dabt:
push_svc_reg
bl rt_hw_trap_dabt
b .
.align 5
.globl vector_resv
vector_resv:
push_svc_reg
bl rt_hw_trap_resv
b .

180
libcpu/arm/zynqmp-r5/trap.c Normal file
View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-20 Bernard first version
* 2020-11-24 WangHuachen porting to zynqmp-r5
*/
#include <rtthread.h>
#include <rthw.h>
#include <board.h>
#include "armv7.h"
#include "interrupt.h"
#ifdef RT_USING_FINSH
extern long list_thread(void);
#endif
/**
* this function will show registers of CPU
*
* @param regs the registers point
*/
void rt_hw_show_register (struct rt_hw_exp_stack *regs)
{
rt_kprintf("Execption:\n");
rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3);
rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7);
rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10);
rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip);
rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc);
rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
}
/**
* When comes across an instruction which it cannot handle,
* it takes the undefined instruction trap.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_undef(struct rt_hw_exp_stack *regs)
{
rt_kprintf("undefined instruction:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* The software interrupt instruction (SWI) is used for entering
* Supervisor mode, usually to request a particular supervisor
* function.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_swi(struct rt_hw_exp_stack *regs)
{
rt_kprintf("software interrupt:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* An abort indicates that the current memory access cannot be completed,
* which occurs during an instruction prefetch.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs)
{
rt_kprintf("prefetch abort:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* An abort indicates that the current memory access cannot be completed,
* which occurs during a data access.
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs)
{
rt_kprintf("data abort:");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
/**
* Normally, system will never reach here
*
* @param regs system registers
*
* @note never invoke this function in application
*/
void rt_hw_trap_resv(struct rt_hw_exp_stack *regs)
{
rt_kprintf("reserved trap:\n");
rt_hw_show_register(regs);
#ifdef RT_USING_FINSH
list_thread();
#endif
rt_hw_cpu_shutdown();
}
void rt_hw_trap_irq(void)
{
void *param;
int ir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
ir = rt_hw_interrupt_get_irq();
if (ir == 1023)
{
/* Spurious interrupt */
return;
}
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
#ifdef RT_USING_INTERRUPT_INFO
isr_table[ir].counter++;
#endif
if (isr_func)
{
/* Interrupt for myself. */
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
}
/* end of interrupt */
rt_hw_interrupt_ack(ir);
}
void rt_hw_trap_fiq(void)
{
void *param;
int ir;
rt_isr_handler_t isr_func;
extern struct rt_irq_desc isr_table[];
ir = rt_hw_interrupt_get_irq();
/* get interrupt service routine */
isr_func = isr_table[ir].handler;
param = isr_table[ir].param;
/* turn to interrupt service routine */
isr_func(ir, param);
/* end of interrupt */
rt_hw_interrupt_ack(ir);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2013-07-05 Bernard the first version
*/
.section .vectors, "ax"
.code 32
.globl system_vectors
system_vectors:
ldr pc, _vector_reset
ldr pc, _vector_undef
ldr pc, _vector_swi
ldr pc, _vector_pabt
ldr pc, _vector_dabt
ldr pc, _vector_resv
ldr pc, _vector_irq
ldr pc, _vector_fiq
.globl _reset
.globl vector_undef
.globl vector_swi
.globl vector_pabt
.globl vector_dabt
.globl vector_resv
.globl vector_irq
.globl vector_fiq
_vector_reset:
.word _reset
_vector_undef:
.word vector_undef
_vector_swi:
.word vector_swi
_vector_pabt:
.word vector_pabt
_vector_dabt:
.word vector_dabt
_vector_resv:
.word vector_resv
_vector_irq:
.word vector_irq
_vector_fiq:
.word vector_fiq
.balignl 16,0xdeadbeef

View File

@ -0,0 +1,249 @@
/******************************************************************************
*
* Copyright (C) 2014 - 2016 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xpseudo_asm_gcc.h
*
* This header file contains macros for using inline assembler code. It is
* written specifically for the GNU compiler.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- -------- -------- -----------------------------------------------
* 5.00 pkp 05/21/14 First release
* 6.0 mus 07/27/16 Consolidated file for a53,a9 and r5 processors
* </pre>
*
******************************************************************************/
#ifndef XPSEUDO_ASM_GCC_H /* prevent circular inclusions */
#define XPSEUDO_ASM_GCC_H /* by using protection macros */
/***************************** Include Files ********************************/
#include <rtdef.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/************************** Constant Definitions ****************************/
/**************************** Type Definitions ******************************/
/***************** Macros (Inline Functions) Definitions ********************/
/* necessary for pre-processor */
#define stringify(s) tostring(s)
#define tostring(s) #s
#if defined (__aarch64__)
/* pseudo assembler instructions */
#define mfcpsr() ({rt_uint32_t rval = 0U; \
asm volatile("mrs %0, DAIF" : "=r" (rval));\
rval;\
})
#define mtcpsr(v) __asm__ __volatile__ ("msr DAIF, %0" : : "r" (v))
#define cpsiei() //__asm__ __volatile__("cpsie i\n")
#define cpsidi() //__asm__ __volatile__("cpsid i\n")
#define cpsief() //__asm__ __volatile__("cpsie f\n")
#define cpsidf() //__asm__ __volatile__("cpsid f\n")
#define mtgpr(rn, v) /*__asm__ __volatile__(\
"mov r" stringify(rn) ", %0 \n"\
: : "r" (v)\
)*/
#define mfgpr(rn) /*({rt_uint32_t rval; \
__asm__ __volatile__(\
"mov %0,r" stringify(rn) "\n"\
: "=r" (rval)\
);\
rval;\
})*/
/* memory synchronization operations */
/* Instruction Synchronization Barrier */
#define isb() __asm__ __volatile__ ("isb sy")
/* Data Synchronization Barrier */
#define dsb() __asm__ __volatile__("dsb sy")
/* Data Memory Barrier */
#define dmb() __asm__ __volatile__("dmb sy")
/* Memory Operations */
#define ldr(adr) ({u64 rval; \
__asm__ __volatile__(\
"ldr %0,[%1]"\
: "=r" (rval) : "r" (adr)\
);\
rval;\
})
#define mfelrel3() ({u64 rval = 0U; \
asm volatile("mrs %0, ELR_EL3" : "=r" (rval));\
rval;\
})
#define mtelrel3(v) __asm__ __volatile__ ("msr ELR_EL3, %0" : : "r" (v))
#else
/* pseudo assembler instructions */
#define mfcpsr() ({rt_uint32_t rval = 0U; \
__asm__ __volatile__(\
"mrs %0, cpsr\n"\
: "=r" (rval)\
);\
rval;\
})
#define mtcpsr(v) __asm__ __volatile__(\
"msr cpsr,%0\n"\
: : "r" (v)\
)
#define cpsiei() __asm__ __volatile__("cpsie i\n")
#define cpsidi() __asm__ __volatile__("cpsid i\n")
#define cpsief() __asm__ __volatile__("cpsie f\n")
#define cpsidf() __asm__ __volatile__("cpsid f\n")
#define mtgpr(rn, v) __asm__ __volatile__(\
"mov r" stringify(rn) ", %0 \n"\
: : "r" (v)\
)
#define mfgpr(rn) ({rt_uint32_t rval; \
__asm__ __volatile__(\
"mov %0,r" stringify(rn) "\n"\
: "=r" (rval)\
);\
rval;\
})
/* memory synchronization operations */
/* Instruction Synchronization Barrier */
#define isb() __asm__ __volatile__ ("isb" : : : "memory")
/* Data Synchronization Barrier */
#define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
/* Data Memory Barrier */
#define dmb() __asm__ __volatile__ ("dmb" : : : "memory")
/* Memory Operations */
#define ldr(adr) ({rt_uint32_t rval; \
__asm__ __volatile__(\
"ldr %0,[%1]"\
: "=r" (rval) : "r" (adr)\
);\
rval;\
})
#endif
#define ldrb(adr) ({rt_uint8_t rval; \
__asm__ __volatile__(\
"ldrb %0,[%1]"\
: "=r" (rval) : "r" (adr)\
);\
rval;\
})
#define str(adr, val) __asm__ __volatile__(\
"str %0,[%1]\n"\
: : "r" (val), "r" (adr)\
)
#define strb(adr, val) __asm__ __volatile__(\
"strb %0,[%1]\n"\
: : "r" (val), "r" (adr)\
)
/* Count leading zeroes (clz) */
#define clz(arg) ({rt_uint8_t rval; \
__asm__ __volatile__(\
"clz %0,%1"\
: "=r" (rval) : "r" (arg)\
);\
rval;\
})
#if defined (__aarch64__)
#define mtcpdc(reg,val) __asm__ __volatile__("dc " #reg ",%0" : : "r" (val))
#define mtcpic(reg,val) __asm__ __volatile__("ic " #reg ",%0" : : "r" (val))
#define mtcpicall(reg) __asm__ __volatile__("ic " #reg)
#define mtcptlbi(reg) __asm__ __volatile__("tlbi " #reg)
#define mtcpat(reg,val) __asm__ __volatile__("at " #reg ",%0" : : "r" (val))
/* CP15 operations */
#define mfcp(reg) ({u64 rval = 0U;\
__asm__ __volatile__("mrs %0, " #reg : "=r" (rval));\
rval;\
})
#define mtcp(reg,val) __asm__ __volatile__("msr " #reg ",%0" : : "r" (val))
#else
/* CP15 operations */
#define mtcp(rn, v) __asm__ __volatile__(\
"mcr " rn "\n"\
: : "r" (v)\
);
#define mfcp(rn) ({rt_uint32_t rval = 0U; \
__asm__ __volatile__(\
"mrc " rn "\n"\
: "=r" (rval)\
);\
rval;\
})
#endif
/************************** Variable Definitions ****************************/
/************************** Function Prototypes *****************************/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XPSEUDO_ASM_GCC_H */

View File

@ -0,0 +1,419 @@
/******************************************************************************
* Copyright (c) 2014 - 2020 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xreg_cortexr5.h
*
* This header file contains definitions for using inline assembler code. It is
* written specifically for the GNU, IAR, ARMCC compiler.
*
* All of the ARM Cortex R5 GPRs, SPRs, and Debug Registers are defined along
* with the positions of the bits within the registers.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- -------- -------- -----------------------------------------------
* 5.00 pkp 02/10/14 Initial version
* </pre>
*
******************************************************************************/
#ifndef XREG_CORTEXR5_H /* prevent circular inclusions */
#define XREG_CORTEXR5_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* GPRs */
#define XREG_GPR0 r0
#define XREG_GPR1 r1
#define XREG_GPR2 r2
#define XREG_GPR3 r3
#define XREG_GPR4 r4
#define XREG_GPR5 r5
#define XREG_GPR6 r6
#define XREG_GPR7 r7
#define XREG_GPR8 r8
#define XREG_GPR9 r9
#define XREG_GPR10 r10
#define XREG_GPR11 r11
#define XREG_GPR12 r12
#define XREG_GPR13 r13
#define XREG_GPR14 r14
#define XREG_GPR15 r15
#define XREG_CPSR cpsr
/* Coprocessor number defines */
#define XREG_CP0 0
#define XREG_CP1 1
#define XREG_CP2 2
#define XREG_CP3 3
#define XREG_CP4 4
#define XREG_CP5 5
#define XREG_CP6 6
#define XREG_CP7 7
#define XREG_CP8 8
#define XREG_CP9 9
#define XREG_CP10 10
#define XREG_CP11 11
#define XREG_CP12 12
#define XREG_CP13 13
#define XREG_CP14 14
#define XREG_CP15 15
/* Coprocessor control register defines */
#define XREG_CR0 cr0
#define XREG_CR1 cr1
#define XREG_CR2 cr2
#define XREG_CR3 cr3
#define XREG_CR4 cr4
#define XREG_CR5 cr5
#define XREG_CR6 cr6
#define XREG_CR7 cr7
#define XREG_CR8 cr8
#define XREG_CR9 cr9
#define XREG_CR10 cr10
#define XREG_CR11 cr11
#define XREG_CR12 cr12
#define XREG_CR13 cr13
#define XREG_CR14 cr14
#define XREG_CR15 cr15
/* Current Processor Status Register (CPSR) Bits */
#define XREG_CPSR_THUMB_MODE 0x20U
#define XREG_CPSR_MODE_BITS 0x1FU
#define XREG_CPSR_SYSTEM_MODE 0x1FU
#define XREG_CPSR_UNDEFINED_MODE 0x1BU
#define XREG_CPSR_DATA_ABORT_MODE 0x17U
#define XREG_CPSR_SVC_MODE 0x13U
#define XREG_CPSR_IRQ_MODE 0x12U
#define XREG_CPSR_FIQ_MODE 0x11U
#define XREG_CPSR_USER_MODE 0x10U
#define XREG_CPSR_IRQ_ENABLE 0x80U
#define XREG_CPSR_FIQ_ENABLE 0x40U
#define XREG_CPSR_N_BIT 0x80000000U
#define XREG_CPSR_Z_BIT 0x40000000U
#define XREG_CPSR_C_BIT 0x20000000U
#define XREG_CPSR_V_BIT 0x10000000U
/*MPU region definitions*/
#define REGION_32B 0x00000004U
#define REGION_64B 0x00000005U
#define REGION_128B 0x00000006U
#define REGION_256B 0x00000007U
#define REGION_512B 0x00000008U
#define REGION_1K 0x00000009U
#define REGION_2K 0x0000000AU
#define REGION_4K 0x0000000BU
#define REGION_8K 0x0000000CU
#define REGION_16K 0x0000000DU
#define REGION_32K 0x0000000EU
#define REGION_64K 0x0000000FU
#define REGION_128K 0x00000010U
#define REGION_256K 0x00000011U
#define REGION_512K 0x00000012U
#define REGION_1M 0x00000013U
#define REGION_2M 0x00000014U
#define REGION_4M 0x00000015U
#define REGION_8M 0x00000016U
#define REGION_16M 0x00000017U
#define REGION_32M 0x00000018U
#define REGION_64M 0x00000019U
#define REGION_128M 0x0000001AU
#define REGION_256M 0x0000001BU
#define REGION_512M 0x0000001CU
#define REGION_1G 0x0000001DU
#define REGION_2G 0x0000001EU
#define REGION_4G 0x0000001FU
#define REGION_EN 0x00000001U
#define SHAREABLE 0x00000004U /*shareable */
#define STRONG_ORDERD_SHARED 0x00000000U /*strongly ordered, always shareable*/
#define DEVICE_SHARED 0x00000001U /*device, shareable*/
#define DEVICE_NONSHARED 0x00000010U /*device, non shareable*/
#define NORM_NSHARED_WT_NWA 0x00000002U /*Outer and Inner write-through, no write-allocate non-shareable*/
#define NORM_SHARED_WT_NWA 0x00000006U /*Outer and Inner write-through, no write-allocate shareable*/
#define NORM_NSHARED_WB_NWA 0x00000003U /*Outer and Inner write-back, no write-allocate non shareable*/
#define NORM_SHARED_WB_NWA 0x00000007U /*Outer and Inner write-back, no write-allocate shareable*/
#define NORM_NSHARED_NCACHE 0x00000008U /*Outer and Inner Non cacheable non shareable*/
#define NORM_SHARED_NCACHE 0x0000000CU /*Outer and Inner Non cacheable shareable*/
#define NORM_NSHARED_WB_WA 0x0000000BU /*Outer and Inner write-back non shared*/
#define NORM_SHARED_WB_WA 0x0000000FU /*Outer and Inner write-back shared*/
/* inner and outer cache policies can be combined for different combinations */
#define NORM_IN_POLICY_NCACHE 0x00000020U /*inner non cacheable*/
#define NORM_IN_POLICY_WB_WA 0x00000021U /*inner write back write allocate*/
#define NORM_IN_POLICY_WT_NWA 0x00000022U /*inner write through no write allocate*/
#define NORM_IN_POLICY_WB_NWA 0x00000023U /*inner write back no write allocate*/
#define NORM_OUT_POLICY_NCACHE 0x00000020U /*outer non cacheable*/
#define NORM_OUT_POLICY_WB_WA 0x00000028U /*outer write back write allocate*/
#define NORM_OUT_POLICY_WT_NWA 0x00000030U /*outer write through no write allocate*/
#define NORM_OUT_POLICY_WB_NWA 0x00000038U /*outer write back no write allocate*/
#define NO_ACCESS (0x00000000U<<8U) /*No access*/
#define PRIV_RW_USER_NA (0x00000001U<<8U) /*Privileged access only*/
#define PRIV_RW_USER_RO (0x00000002U<<8U) /*Writes in User mode generate permission faults*/
#define PRIV_RW_USER_RW (0x00000003U<<8U) /*Full Access*/
#define PRIV_RO_USER_NA (0x00000005U<<8U) /*Privileged eead only*/
#define PRIV_RO_USER_RO (0x00000006U<<8U) /*Privileged/User read-only*/
#define EXECUTE_NEVER (0x00000001U<<12U) /* Bit 12*/
/* CP15 defines */
/* C0 Register defines */
#define XREG_CP15_MAIN_ID "p15, 0, %0, c0, c0, 0"
#define XREG_CP15_CACHE_TYPE "p15, 0, %0, c0, c0, 1"
#define XREG_CP15_TCM_TYPE "p15, 0, %0, c0, c0, 2"
#define XREG_CP15_TLB_TYPE "p15, 0, %0, c0, c0, 3"
#define XREG_CP15_MPU_TYPE "p15, 0, %0, c0, c0, 4"
#define XREG_CP15_MULTI_PROC_AFFINITY "p15, 0, %0, c0, c0, 5"
#define XREG_CP15_PROC_FEATURE_0 "p15, 0, %0, c0, c1, 0"
#define XREG_CP15_PROC_FEATURE_1 "p15, 0, %0, c0, c1, 1"
#define XREG_CP15_DEBUG_FEATURE_0 "p15, 0, %0, c0, c1, 2"
#define XREG_CP15_MEMORY_FEATURE_0 "p15, 0, %0, c0, c1, 4"
#define XREG_CP15_MEMORY_FEATURE_1 "p15, 0, %0, c0, c1, 5"
#define XREG_CP15_MEMORY_FEATURE_2 "p15, 0, %0, c0, c1, 6"
#define XREG_CP15_MEMORY_FEATURE_3 "p15, 0, %0, c0, c1, 7"
#define XREG_CP15_INST_FEATURE_0 "p15, 0, %0, c0, c2, 0"
#define XREG_CP15_INST_FEATURE_1 "p15, 0, %0, c0, c2, 1"
#define XREG_CP15_INST_FEATURE_2 "p15, 0, %0, c0, c2, 2"
#define XREG_CP15_INST_FEATURE_3 "p15, 0, %0, c0, c2, 3"
#define XREG_CP15_INST_FEATURE_4 "p15, 0, %0, c0, c2, 4"
#define XREG_CP15_INST_FEATURE_5 "p15, 0, %0, c0, c2, 5"
#define XREG_CP15_CACHE_SIZE_ID "p15, 1, %0, c0, c0, 0"
#define XREG_CP15_CACHE_LEVEL_ID "p15, 1, %0, c0, c0, 1"
#define XREG_CP15_AUXILARY_ID "p15, 1, %0, c0, c0, 7"
#define XREG_CP15_CACHE_SIZE_SEL "p15, 2, %0, c0, c0, 0"
/* C1 Register Defines */
#define XREG_CP15_SYS_CONTROL "p15, 0, %0, c1, c0, 0"
#define XREG_CP15_AUX_CONTROL "p15, 0, %0, c1, c0, 1"
#define XREG_CP15_CP_ACCESS_CONTROL "p15, 0, %0, c1, c0, 2"
/* XREG_CP15_CONTROL bit defines */
#define XREG_CP15_CONTROL_TE_BIT 0x40000000U
#define XREG_CP15_CONTROL_AFE_BIT 0x20000000U
#define XREG_CP15_CONTROL_TRE_BIT 0x10000000U
#define XREG_CP15_CONTROL_NMFI_BIT 0x08000000U
#define XREG_CP15_CONTROL_EE_BIT 0x02000000U
#define XREG_CP15_CONTROL_HA_BIT 0x00020000U
#define XREG_CP15_CONTROL_RR_BIT 0x00004000U
#define XREG_CP15_CONTROL_V_BIT 0x00002000U
#define XREG_CP15_CONTROL_I_BIT 0x00001000U
#define XREG_CP15_CONTROL_Z_BIT 0x00000800U
#define XREG_CP15_CONTROL_SW_BIT 0x00000400U
#define XREG_CP15_CONTROL_B_BIT 0x00000080U
#define XREG_CP15_CONTROL_C_BIT 0x00000004U
#define XREG_CP15_CONTROL_A_BIT 0x00000002U
#define XREG_CP15_CONTROL_M_BIT 0x00000001U
/* C2 Register Defines */
/* Not Used */
/* C3 Register Defines */
/* Not Used */
/* C4 Register Defines */
/* Not Used */
/* C5 Register Defines */
#define XREG_CP15_DATA_FAULT_STATUS "p15, 0, %0, c5, c0, 0"
#define XREG_CP15_INST_FAULT_STATUS "p15, 0, %0, c5, c0, 1"
#define XREG_CP15_AUX_DATA_FAULT_STATUS "p15, 0, %0, c5, c1, 0"
#define XREG_CP15_AUX_INST_FAULT_STATUS "p15, 0, %0, c5, c1, 1"
/* C6 Register Defines */
#define XREG_CP15_DATA_FAULT_ADDRESS "p15, 0, %0, c6, c0, 0"
#define XREG_CP15_INST_FAULT_ADDRESS "p15, 0, %0, c6, c0, 2"
#define XREG_CP15_MPU_REG_BASEADDR "p15, 0, %0, c6, c1, 0"
#define XREG_CP15_MPU_REG_SIZE_EN "p15, 0, %0, c6, c1, 2"
#define XREG_CP15_MPU_REG_ACCESS_CTRL "p15, 0, %0, c6, c1, 4"
#define XREG_CP15_MPU_MEMORY_REG_NUMBER "p15, 0, %0, c6, c2, 0"
/* C7 Register Defines */
#define XREG_CP15_NOP "p15, 0, %0, c7, c0, 4"
#define XREG_CP15_INVAL_IC_POU "p15, 0, %0, c7, c5, 0"
#define XREG_CP15_INVAL_IC_LINE_MVA_POU "p15, 0, %0, c7, c5, 1"
/* The CP15 register access below has been deprecated in favor of the new
* isb instruction in Cortex R5.
*/
#define XREG_CP15_INST_SYNC_BARRIER "p15, 0, %0, c7, c5, 4"
#define XREG_CP15_INVAL_BRANCH_ARRAY "p15, 0, %0, c7, c5, 6"
#define XREG_CP15_INVAL_BRANCH_ARRAY_LINE "p15, 0, %0, c7, c5, 7"
#define XREG_CP15_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c6, 1"
#define XREG_CP15_INVAL_DC_LINE_SW "p15, 0, %0, c7, c6, 2"
#define XREG_CP15_CLEAN_DC_LINE_MVA_POC "p15, 0, %0, c7, c10, 1"
#define XREG_CP15_CLEAN_DC_LINE_SW "p15, 0, %0, c7, c10, 2"
#define XREG_CP15_INVAL_DC_ALL "p15, 0, %0, c15, c5, 0"
/* The next two CP15 register accesses below have been deprecated in favor
* of the new dsb and dmb instructions in Cortex R5.
*/
#define XREG_CP15_DATA_SYNC_BARRIER "p15, 0, %0, c7, c10, 4"
#define XREG_CP15_DATA_MEMORY_BARRIER "p15, 0, %0, c7, c10, 5"
#define XREG_CP15_CLEAN_DC_LINE_MVA_POU "p15, 0, %0, c7, c11, 1"
#define XREG_CP15_NOP2 "p15, 0, %0, c7, c13, 1"
#define XREG_CP15_CLEAN_INVAL_DC_LINE_MVA_POC "p15, 0, %0, c7, c14, 1"
#define XREG_CP15_CLEAN_INVAL_DC_LINE_SW "p15, 0, %0, c7, c14, 2"
/* C8 Register Defines */
/* Not Used */
/* C9 Register Defines */
#define XREG_CP15_ATCM_REG_SIZE_ADDR "p15, 0, %0, c9, c1, 1"
#define XREG_CP15_BTCM_REG_SIZE_ADDR "p15, 0, %0, c9, c1, 0"
#define XREG_CP15_TCM_SELECTION "p15, 0, %0, c9, c2, 0"
#define XREG_CP15_PERF_MONITOR_CTRL "p15, 0, %0, c9, c12, 0"
#define XREG_CP15_COUNT_ENABLE_SET "p15, 0, %0, c9, c12, 1"
#define XREG_CP15_COUNT_ENABLE_CLR "p15, 0, %0, c9, c12, 2"
#define XREG_CP15_V_FLAG_STATUS "p15, 0, %0, c9, c12, 3"
#define XREG_CP15_SW_INC "p15, 0, %0, c9, c12, 4"
#define XREG_CP15_EVENT_CNTR_SEL "p15, 0, %0, c9, c12, 5"
#define XREG_CP15_PERF_CYCLE_COUNTER "p15, 0, %0, c9, c13, 0"
#define XREG_CP15_EVENT_TYPE_SEL "p15, 0, %0, c9, c13, 1"
#define XREG_CP15_PERF_MONITOR_COUNT "p15, 0, %0, c9, c13, 2"
#define XREG_CP15_USER_ENABLE "p15, 0, %0, c9, c14, 0"
#define XREG_CP15_INTR_ENABLE_SET "p15, 0, %0, c9, c14, 1"
#define XREG_CP15_INTR_ENABLE_CLR "p15, 0, %0, c9, c14, 2"
/* C10 Register Defines */
/* Not used */
/* C11 Register Defines */
/* Not used */
/* C12 Register Defines */
/* Not used */
/* C13 Register Defines */
#define XREG_CP15_CONTEXT_ID "p15, 0, %0, c13, c0, 1"
#define USER_RW_THREAD_PID "p15, 0, %0, c13, c0, 2"
#define USER_RO_THREAD_PID "p15, 0, %0, c13, c0, 3"
#define USER_PRIV_THREAD_PID "p15, 0, %0, c13, c0, 4"
/* C14 Register Defines */
/* not used */
/* C15 Register Defines */
#define XREG_CP15_SEC_AUX_CTRL "p15, 0, %0, c15, c0, 0"
/* MPE register definitions */
#define XREG_FPSID c0
#define XREG_FPSCR c1
#define XREG_MVFR1 c6
#define XREG_MVFR0 c7
#define XREG_FPEXC c8
#define XREG_FPINST c9
#define XREG_FPINST2 c10
/* FPSID bits */
#define XREG_FPSID_IMPLEMENTER_BIT (24U)
#define XREG_FPSID_IMPLEMENTER_MASK (0x000000FFU << FPSID_IMPLEMENTER_BIT)
#define XREG_FPSID_SOFTWARE (0X00000001U << 23U)
#define XREG_FPSID_ARCH_BIT (16U)
#define XREG_FPSID_ARCH_MASK (0x0000000FU << FPSID_ARCH_BIT)
#define XREG_FPSID_PART_BIT (8U)
#define XREG_FPSID_PART_MASK (0x000000FFU << FPSID_PART_BIT)
#define XREG_FPSID_VARIANT_BIT (4U)
#define XREG_FPSID_VARIANT_MASK (0x0000000FU << FPSID_VARIANT_BIT)
#define XREG_FPSID_REV_BIT (0U)
#define XREG_FPSID_REV_MASK (0x0000000FU << FPSID_REV_BIT)
/* FPSCR bits */
#define XREG_FPSCR_N_BIT (0X00000001U << 31U)
#define XREG_FPSCR_Z_BIT (0X00000001U << 30U)
#define XREG_FPSCR_C_BIT (0X00000001U << 29U)
#define XREG_FPSCR_V_BIT (0X00000001U << 28U)
#define XREG_FPSCR_QC (0X00000001U << 27U)
#define XREG_FPSCR_AHP (0X00000001U << 26U)
#define XREG_FPSCR_DEFAULT_NAN (0X00000001U << 25U)
#define XREG_FPSCR_FLUSHTOZERO (0X00000001U << 24U)
#define XREG_FPSCR_ROUND_NEAREST (0X00000000U << 22U)
#define XREG_FPSCR_ROUND_PLUSINF (0X00000001U << 22U)
#define XREG_FPSCR_ROUND_MINUSINF (0X00000002U << 22U)
#define XREG_FPSCR_ROUND_TOZERO (0X00000003U << 22U)
#define XREG_FPSCR_RMODE_BIT (22U)
#define XREG_FPSCR_RMODE_MASK (0X00000003U << FPSCR_RMODE_BIT)
#define XREG_FPSCR_STRIDE_BIT (20U)
#define XREG_FPSCR_STRIDE_MASK (0X00000003U << FPSCR_STRIDE_BIT)
#define XREG_FPSCR_LENGTH_BIT (16U)
#define XREG_FPSCR_LENGTH_MASK (0X00000007U << FPSCR_LENGTH_BIT)
#define XREG_FPSCR_IDC (0X00000001U << 7U)
#define XREG_FPSCR_IXC (0X00000001U << 4U)
#define XREG_FPSCR_UFC (0X00000001U << 3U)
#define XREG_FPSCR_OFC (0X00000001U << 2U)
#define XREG_FPSCR_DZC (0X00000001U << 1U)
#define XREG_FPSCR_IOC (0X00000001U << 0U)
/* MVFR0 bits */
#define XREG_MVFR0_RMODE_BIT (28U)
#define XREG_MVFR0_RMODE_MASK (0x0000000FU << XREG_MVFR0_RMODE_BIT)
#define XREG_MVFR0_SHORT_VEC_BIT (24U)
#define XREG_MVFR0_SHORT_VEC_MASK (0x0000000FU << XREG_MVFR0_SHORT_VEC_BIT)
#define XREG_MVFR0_SQRT_BIT (20U)
#define XREG_MVFR0_SQRT_MASK (0x0000000FU << XREG_MVFR0_SQRT_BIT)
#define XREG_MVFR0_DIVIDE_BIT (16U)
#define XREG_MVFR0_DIVIDE_MASK (0x0000000FU << XREG_MVFR0_DIVIDE_BIT)
#define XREG_MVFR0_EXEC_TRAP_BIT (12U)
#define XREG_MVFR0_EXEC_TRAP_MASK (0x0000000FU << XREG_MVFR0_EXEC_TRAP_BIT)
#define XREG_MVFR0_DP_BIT (8U)
#define XREG_MVFR0_DP_MASK (0x0000000FU << XREG_MVFR0_DP_BIT)
#define XREG_MVFR0_SP_BIT (4U)
#define XREG_MVFR0_SP_MASK (0x0000000FU << XREG_MVFR0_SP_BIT)
#define XREG_MVFR0_A_SIMD_BIT (0U)
#define XREG_MVFR0_A_SIMD_MASK (0x0000000FU << MVFR0_A_SIMD_BIT)
/* FPEXC bits */
#define XREG_FPEXC_EX (0X00000001U << 31U)
#define XREG_FPEXC_EN (0X00000001U << 30U)
#define XREG_FPEXC_DEX (0X00000001U << 29U)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* XREG_CORTEXR5_H */