diff --git a/bsp/raspi2/.config b/bsp/raspberry-pi/raspi2/.config similarity index 100% rename from bsp/raspi2/.config rename to bsp/raspberry-pi/raspi2/.config diff --git a/bsp/raspberry-pi/raspi2/Kconfig b/bsp/raspberry-pi/raspi2/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..f7693c837813f47b0315f2305537b4922259e3c8 --- /dev/null +++ b/bsp/raspberry-pi/raspi2/Kconfig @@ -0,0 +1,28 @@ +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 BCM2836_SOC + bool + select ARCH_ARM_CORTEX_A7 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + default y + +source "driver/Kconfig" diff --git a/bsp/raspi2/README.md b/bsp/raspberry-pi/raspi2/README.md similarity index 100% rename from bsp/raspi2/README.md rename to bsp/raspberry-pi/raspi2/README.md diff --git a/bsp/raspi2/SConscript b/bsp/raspberry-pi/raspi2/SConscript similarity index 100% rename from bsp/raspi2/SConscript rename to bsp/raspberry-pi/raspi2/SConscript diff --git a/bsp/raspi2/SConstruct b/bsp/raspberry-pi/raspi2/SConstruct similarity index 92% rename from bsp/raspi2/SConstruct rename to bsp/raspberry-pi/raspi2/SConstruct index e5acdb25548702c513aec33c8b95e93b9645be12..e94a364d9dd1df4b57b23e774836d1fd871c0a7d 100644 --- a/bsp/raspi2/SConstruct +++ b/bsp/raspberry-pi/raspi2/SConstruct @@ -22,7 +22,7 @@ Export('RTT_ROOT') Export('rtconfig') # prepare building environment -objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=True) +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False) # make a building DoBuilding(TARGET, objs) diff --git a/bsp/raspi2/applications/SConscript b/bsp/raspberry-pi/raspi2/applications/SConscript similarity index 100% rename from bsp/raspi2/applications/SConscript rename to bsp/raspberry-pi/raspi2/applications/SConscript diff --git a/bsp/raspi2/applications/main.c b/bsp/raspberry-pi/raspi2/applications/main.c similarity index 100% rename from bsp/raspi2/applications/main.c rename to bsp/raspberry-pi/raspi2/applications/main.c diff --git a/bsp/raspi2/applications/mnt.c b/bsp/raspberry-pi/raspi2/applications/mnt.c similarity index 100% rename from bsp/raspi2/applications/mnt.c rename to bsp/raspberry-pi/raspi2/applications/mnt.c diff --git a/bsp/raspi2/driver/Kconfig b/bsp/raspberry-pi/raspi2/driver/Kconfig similarity index 100% rename from bsp/raspi2/driver/Kconfig rename to bsp/raspberry-pi/raspi2/driver/Kconfig diff --git a/bsp/raspi2/driver/SConscript b/bsp/raspberry-pi/raspi2/driver/SConscript similarity index 100% rename from bsp/raspi2/driver/SConscript rename to bsp/raspberry-pi/raspi2/driver/SConscript diff --git a/bsp/raspi2/driver/bcm283x.h b/bsp/raspberry-pi/raspi2/driver/bcm283x.h similarity index 100% rename from bsp/raspi2/driver/bcm283x.h rename to bsp/raspberry-pi/raspi2/driver/bcm283x.h diff --git a/bsp/raspi2/driver/board.c b/bsp/raspberry-pi/raspi2/driver/board.c similarity index 100% rename from bsp/raspi2/driver/board.c rename to bsp/raspberry-pi/raspi2/driver/board.c diff --git a/bsp/raspi2/driver/board.h b/bsp/raspberry-pi/raspi2/driver/board.h similarity index 100% rename from bsp/raspi2/driver/board.h rename to bsp/raspberry-pi/raspi2/driver/board.h diff --git a/bsp/raspi2/driver/drv_uart.c b/bsp/raspberry-pi/raspi2/driver/drv_uart.c similarity index 100% rename from bsp/raspi2/driver/drv_uart.c rename to bsp/raspberry-pi/raspi2/driver/drv_uart.c diff --git a/bsp/raspi2/driver/drv_uart.h b/bsp/raspberry-pi/raspi2/driver/drv_uart.h similarity index 100% rename from bsp/raspi2/driver/drv_uart.h rename to bsp/raspberry-pi/raspi2/driver/drv_uart.h diff --git a/bsp/raspi2/figures/raspi2.png b/bsp/raspberry-pi/raspi2/figures/raspi2.png similarity index 100% rename from bsp/raspi2/figures/raspi2.png rename to bsp/raspberry-pi/raspi2/figures/raspi2.png diff --git a/bsp/raspi2/figures/raspi_uart.png b/bsp/raspberry-pi/raspi2/figures/raspi_uart.png similarity index 100% rename from bsp/raspi2/figures/raspi_uart.png rename to bsp/raspberry-pi/raspi2/figures/raspi_uart.png diff --git a/bsp/raspberry-pi/raspi2/kernel7.img b/bsp/raspberry-pi/raspi2/kernel7.img new file mode 100755 index 0000000000000000000000000000000000000000..82e849b25d9544e80bce3664bea3cd509f1df0b8 Binary files /dev/null and b/bsp/raspberry-pi/raspi2/kernel7.img differ diff --git a/bsp/raspi2/link.lds b/bsp/raspberry-pi/raspi2/link.lds similarity index 100% rename from bsp/raspi2/link.lds rename to bsp/raspberry-pi/raspi2/link.lds diff --git a/bsp/raspi2/rtconfig.h b/bsp/raspberry-pi/raspi2/rtconfig.h similarity index 100% rename from bsp/raspi2/rtconfig.h rename to bsp/raspberry-pi/raspi2/rtconfig.h diff --git a/bsp/raspi2/rtconfig.py b/bsp/raspberry-pi/raspi2/rtconfig.py similarity index 94% rename from bsp/raspi2/rtconfig.py rename to bsp/raspberry-pi/raspi2/rtconfig.py index 37475595a2e644c286296edf571e0bf6bf01cb8b..8c827e82210881bfaef2c9210f163615d7c0581b 100644 --- a/bsp/raspi2/rtconfig.py +++ b/bsp/raspberry-pi/raspi2/rtconfig.py @@ -8,13 +8,13 @@ CROSS_TOOL ='gcc' if os.getenv('RTT_ROOT'): RTT_ROOT = os.getenv('RTT_ROOT') else: - RTT_ROOT = r'../..' + RTT_ROOT = r'../../..' if os.getenv('RTT_CC'): CROSS_TOOL = os.getenv('RTT_CC') PLATFORM = 'gcc' -EXEC_PATH = r'/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin' +EXEC_PATH = r'/opt/gcc-arm-none-eabi-5_4-2016q3/bin' if os.getenv('RTT_EXEC_PATH'): EXEC_PATH = os.getenv('RTT_EXEC_PATH') diff --git a/bsp/raspberry-pi/raspi3-32/.config b/bsp/raspberry-pi/raspi3-32/.config new file mode 100644 index 0000000000000000000000000000000000000000..78d7e6fbafa2a76ad1b194e9aa72db27b3a37ad5 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/.config @@ -0,0 +1,427 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Project Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +CONFIG_RT_USING_SMP=y +CONFIG_RT_CPUS_NR=4 +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=256 +# CONFIG_RT_USING_TIMER_SOFT is not set +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_MEMHEAP=y +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +CONFIG_RT_USING_MEMTRACE=y +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +CONFIG_RT_USING_DEVICE_OPS=y +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40002 +CONFIG_ARCH_ARM=y +# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_ARCH_ARM_CORTEX_A=y +CONFIG_ARCH_ARM_CORTEX_A7=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +CONFIG_FINSH_USING_MSH_ONLY=y +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 is not set +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +CONFIG_RT_USING_HWTIMER=y +# CONFIG_RT_USING_CPUTIME is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_USING_I2C_BITOPS is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_PM is not set +CONFIG_RT_USING_RTC=y +# CONFIG_RT_USING_ALARM is not set +# CONFIG_RT_USING_SOFT_RTC is not set +CONFIG_RT_USING_SDIO=y +CONFIG_RT_SDIO_STACK_SIZE=512 +CONFIG_RT_SDIO_THREAD_PRIORITY=15 +CONFIG_RT_MMCSD_STACK_SIZE=1024 +CONFIG_RT_MMCSD_THREAD_PREORITY=22 +CONFIG_RT_MMCSD_MAX_PARTITION=16 +# CONFIG_RT_SDIO_DEBUG is not set +CONFIG_RT_USING_SPI=y +# CONFIG_RT_USING_QSPI is not set +# CONFIG_RT_USING_SPI_MSD is not set +# CONFIG_RT_USING_SFUD is not set +# CONFIG_RT_USING_ENC28J60 is not set +# CONFIG_RT_USING_SPI_WIFI is not set +CONFIG_RT_USING_WDT=y +# 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_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +CONFIG_RT_USING_LIBC=y +# CONFIG_RT_USING_PTHREADS is not set +CONFIG_RT_USING_POSIX=y +# CONFIG_RT_USING_POSIX_MMAP is not set +# CONFIG_RT_USING_POSIX_TERMIOS is not set +# CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_MODULE is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# 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 +# CONFIG_RT_USING_LWP is not set + +# +# RT-Thread online packages +# + +# +# IoT - internet of things +# +# CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_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_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_IOTHUB 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 + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_TINYCRYPT is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set + +# +# multimedia packages +# +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set + +# +# tools packages +# +# CONFIG_PKG_USING_CMBACKTRACE is not set +# CONFIG_PKG_USING_EASYFLASH is not set +# CONFIG_PKG_USING_EASYLOGGER is not set +# CONFIG_PKG_USING_SYSTEMVIEW is not set +# CONFIG_PKG_USING_RDB is not set +# CONFIG_PKG_USING_QRCODE is not set +# CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ADBD is not set + +# +# system packages +# +# CONFIG_PKG_USING_GUIENGINE is not set +# CONFIG_PKG_USING_PERSIMMON is not set +# CONFIG_PKG_USING_CAIRO is not set +# CONFIG_PKG_USING_PIXMAN is not set +# CONFIG_PKG_USING_LWEXT4 is not set +# CONFIG_PKG_USING_PARTITION is not set +# CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_SQLITE is not set +# CONFIG_PKG_USING_RTI is not set +# CONFIG_PKG_USING_LITTLEVGL2RTT is not set +# CONFIG_PKG_USING_CMSIS is not set +# CONFIG_PKG_USING_DFS_YAFFS is not set +# CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_THREAD_POOL 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_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_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_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_LCD_DRIVERS is not set + +# +# miscellaneous packages +# +# CONFIG_PKG_USING_LIBCSV is not set +# CONFIG_PKG_USING_OPTPARSE is not set +# CONFIG_PKG_USING_FASTLZ is not set +# CONFIG_PKG_USING_MINILZO is not set +# CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_MULTIBUTTON is not set +# CONFIG_PKG_USING_CANFESTIVAL is not set +# CONFIG_PKG_USING_ZLIB is not set +# CONFIG_PKG_USING_DSTR is not set +# CONFIG_PKG_USING_TINYFRAME is not set +# CONFIG_PKG_USING_KENDRYTE_DEMO is not set +# CONFIG_PKG_USING_DIGITALCTRL 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_NNOM is not set +# CONFIG_PKG_USING_LIBANN is not set +CONFIG_BCM2836_SOC=y + +# +# Hardware Drivers Config +# + +# +# BCM Peripheral Drivers +# +CONFIG_BSP_USING_UART=y +# CONFIG_RT_USING_UART0 is not set +CONFIG_RT_USING_UART1=y +CONFIG_BSP_USING_PIN=y +CONFIG_BSP_USING_SYSTIMER=y +CONFIG_RT_USING_SYSTIMER1=y +CONFIG_RT_USING_SYSTIMER3=y +CONFIG_BSP_USING_I2C=y +CONFIG_BSP_USING_I2C0=y +CONFIG_BSP_USING_I2C1=y +CONFIG_BSP_USING_SPI=y +CONFIG_BSP_USING_SPI0_BUS=y +CONFIG_BSP_USING_SPI0_DEVICE0=y +CONFIG_BSP_USING_SPI0_DEVICE1=y +CONFIG_BSP_USING_WDT=y +CONFIG_BSP_USING_RTC=y +# CONFIG_BSP_USING_ALARM is not set +CONFIG_BSP_USING_SDIO=y +CONFIG_BSP_USING_SDIO0=y +CONFIG_BSP_USING_HDMI=y diff --git a/bsp/raspi2/Kconfig b/bsp/raspberry-pi/raspi3-32/Kconfig similarity index 100% rename from bsp/raspi2/Kconfig rename to bsp/raspberry-pi/raspi3-32/Kconfig diff --git a/bsp/raspberry-pi/raspi3-32/README.md b/bsp/raspberry-pi/raspi3-32/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0fef644adf52ac3d1c1f44a6f35ba55ee64b9733 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/README.md @@ -0,0 +1,153 @@ +# Raspberry PI 3B(32位)板级支持包说明 + +## 1. 简介 + +树莓派由注册于英国的慈善组织“Raspberry Pi 基金会”开发,莓派3采用4核Broadcom BCM2837 (ARMv8)芯片、双核VideoCore IV GPU和1GB内存。 + +这份RT-Thread BSP是针对 Raspberry Pi 3B (32位)的一份移植,树莓派价格便宜, 使用者甚众,是研究和运行RT-Thread的可选平台之一。 + +随着RT-Thread的发展,它越来越多的向一些Cortex-A等AP类处理器提供支持,例如全志的ARM9、Cortex-A处理器,Xilinx的Zynq处理器等。 + +而RT-Thread也是一套高度社区化发展的操作系统,所以在一些方向推进上希望以社区化方式,大家一起来推动的方式向前发展,在这个过程中RT-Thread得到了不同开发者、不同领域的应用,一步步把RT-Thread推向成熟。而在Cortex-A平台上,目前最流行的硬件平台是树莓派,分树莓派[2B](https://www.raspberrypi.org/products/raspberry-pi-2-model-b/)、[3B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)以及最新的[4B](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/)等。 + +RT-Thread对树莓派的支持主要从树莓派2B开始,它是一个四核Cortex-A7的平台,以32位单核的模式运行。后续将推动着RT-Thread向树莓派3,四核Cortex-A53 64位模式发展(中间当然也可能出现四核Cortex-A7模式执行的过渡性版本)。 + +![raspi3_f](figures/raspi3_f.jpg) + +![raspi3_b](figures/raspi3_b.jpg) + +当前Raspberry Pi 3B对应的硬件特性: + +| 硬件 | 描述 | +|------- | ------------------------------- | +| CPU | quad-core ARM Cortex A53(ARMv8) | +| 主频 | 1.2 GHz | +| GPU | VideoCore IV | +| GPU频率 | 400MHz | +| Memory | 1GB (0x0000000 - 0x40000000) | +| | 其中0x3f000000 - 0x40000000为peripheral | + +硬件引脚分布情况 + +![GPIO-Pinout-Diagram-2](figures/GPIO-Pinout-Diagram-2.png) + +## 2. 编译说明 + +Windows环境下推荐使用[env工具][1]进行编译。 + +Linux下推荐使用gcc工具 [gcc-arm-none-eabi-4_8-2014q1_linux][2],如果还没有编译工具,下载后,解开文件。 + +``` +tar vxf gcc-arm-none-eabi-4_8-2014q1_linux.tar.bz2 +``` + +Linux环境下需要修改编译器目录设置,修改`bsp/raspi3-32/rtconfig.py`中的 + +``` +EXEC_PATH = r'/opt/gcc-arm-none-eabi-4_8-2014q1_gri/bin' +``` + +为编译工具的实际所在目录,这里注意要加上后缀 `/bin` + +进入到`rt-thread/bsp/raspi3-32`目录中,运行以下命令: + +``` +scons +``` + +来编译这个板级支持包。如果编译正确无误,会产生rtthread.elf、kernel7.img文件。 +kernel7.img即是要cp到raspberry SD卡中根目录的文件 + +### 2.1 eclipse 编码环境 ### +第一步: 安装 eclipse cdt +第二步: 打开 eclipse cdt 设置workspace ,推荐设置于xxx\xxx\rt-thread\bsp +第三步: Import 工程 General-> Existing Peojects into Workspace 然后 Browse.. 你的raspi3目录,点击Finish + +btw:编译依旧使用scons,目前不支持qemu debug,后期如果有大佬实现ARM JTAG调试 + +## 3. 执行 + +### 3.1 下载[raspbian镜像][3],生成可以运行的raspbian SD卡 + +Windows下,去[etcher.io][4]下载etcher,这是个可以烧写img的工具 + +解开下载的镜像文件, linux下使用如下的命令 + +``` +unzip 2018-06-27-raspbian-stretch-lite.zip +``` + +准备一张空SD卡,linux环境下,插入电脑并执行 + +``` +sudo dd if=2018-06-27-raspbian-stretch-lite.img of=/dev/xxx bs=32M conv=fsync +``` + +**注意: /dev/xxx 要换成真实环境中的SD卡所在设置,千万不要弄错。** + +Windows环境下,执行etcher选择解压后的2018-06-27-raspbian-stretch-lite.img文件和SD卡就可以开始烧写了。 + +最后把kernel7.img放入SD boot分区,覆盖原来的文件。 + +### 3.2 准备好串口线 + +目前版本是使用raspi3的 GPIO 14, GPIO 15来作路口输出,连线情况如下图所示: + + + +![raspberrypi-console](figures/raspberrypi-console.png) + +串口参数: 115200 8N1 ,硬件和软件流控为关。 + +按上面的方法做好SD卡后,插入树莓派3B,通电可以在串口上看到如下所示的输出信息: + +```text +heap: 0x0005d784 - 0x0045d784 + + \ | / +- RT - Thread Operating System + / | \ 4.0.2 build Jan 9 2020 + 2006 - 2019 Copyright by rt-thread team +[I/I2C] I2C bus [i2c0] registered +[I/I2C] I2C bus [i2c1] registered +[I/SDIO] SD card capacity 15558144 KB. +found part[0], begin: 1048576, size: 63.0MB +found part[1], begin: 67108864, size: 14.793GB +file system initialization done! +boot cpu:3 +msh />cpu = 0x00000003 +cpu 3 startup. +start OK: CPU 3 +boot cpu:2 +cpu = 0x00000002 +cpu 2 startup. +start OK: CPU 2 +boot cpu:1 +cpu = 0x00000001 +cpu 1 startup. +start OK: CPU 1 +Hello RT-Thread! + +msh /> +``` + +## 4. 支持情况 + +| 驱动 | 支持情况 | 备注 | +| ------ | ---- | :------: | +| UART | 支持 | UART0| +| GPIO | 支持 | | +| IIC | 支持 | | +| SPI | 支持 | | +| CPU Timer | 支持 | | +| SD卡驱动 | 支持 | | + +## 5. 联系人信息 + +维护人:[bernard][5] + +[1]: https://www.rt-thread.org/page/download.html +[2]: https://launchpad.net/gcc-arm-embedded/4.8/4.8-2014-q1-update/+download/gcc-arm-none-eabi-4_8-2014q1-20140314-linux.tar.bz2 +[3]: https://downloads.raspberrypi.org/raspbian_lite_latest +[4]: https://etcher.io +[5]: https://github.com/BernardXiong diff --git a/bsp/raspberry-pi/raspi3-32/SConscript b/bsp/raspberry-pi/raspi3-32/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..c7ef7659ecea92b1dd9b71a97736a8552ee02551 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/raspberry-pi/raspi3-32/SConstruct b/bsp/raspberry-pi/raspi3-32/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..e94a364d9dd1df4b57b23e774836d1fd871c0a7d --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/SConstruct @@ -0,0 +1,28 @@ +import os +import sys +import rtconfig + +from rtconfig import RTT_ROOT + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +from building import * + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) + +Export('RTT_ROOT') +Export('rtconfig') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False) + +# make a building +DoBuilding(TARGET, objs) diff --git a/bsp/raspberry-pi/raspi3-32/applications/SConscript b/bsp/raspberry-pi/raspi3-32/applications/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..533df8ac31d12aaf4a835cde3a1554d8d65d955a --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/applications/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/raspberry-pi/raspi3-32/applications/main.c b/bsp/raspberry-pi/raspi3-32/applications/main.c new file mode 100644 index 0000000000000000000000000000000000000000..cda0e0d711059681785a4a64040dd198ab17cf59 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/applications/main.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 bernard the first version + */ + +#include + +int main(int argc, char** argv) +{ + rt_kprintf("Hello RT-Thread!\n"); + + return 0; +} diff --git a/bsp/raspberry-pi/raspi3-32/applications/mnt.c b/bsp/raspberry-pi/raspi3-32/applications/mnt.c new file mode 100644 index 0000000000000000000000000000000000000000..88b714022c07228d858be971a801d0bb8fb63f0b --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/applications/mnt.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 bernard the first version + */ + +#include + +#ifdef BSP_USING_SDIO0 +#include + +int mnt_init(void) +{ + rt_thread_delay(RT_TICK_PER_SECOND); + + if (dfs_mount("sd0", "/", "elm", 0, 0) == 0) + { + rt_kprintf("file system initialization done!\n"); + } + + return 0; +} +INIT_ENV_EXPORT(mnt_init); +#endif + diff --git a/bsp/raspberry-pi/raspi3-32/applications/test_device.c b/bsp/raspberry-pi/raspi3-32/applications/test_device.c new file mode 100644 index 0000000000000000000000000000000000000000..222bb2e822614c38608a080f70209e0667e9b1fc --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/applications/test_device.c @@ -0,0 +1,462 @@ +/* + * File : test_driver.h + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include +#include +#include +#include +#include +#include "raspi.h" + +#ifdef BSP_USING_HDMI +#include "drv_fb.h" +#endif + +void test_hdmi() +{ + rt_kprintf("Hello Test hdmi!\n"); +#ifdef BSP_USING_HDMI + print_fb_info(); +#ifdef BSP_USING_HDMI_DISPLAY + rt_kprintf("hdmi is tested!\n"); +#else + rt_console_set_device("hdmi"); + rt_kprintf("hdmi is testing!\n"); +#endif + rt_kprintf("search hdmi device"); + rt_device_t hdmi = rt_device_find("hdmi"); + if (hdmi == RT_NULL) + { + rt_kprintf("cannot find hdmi device"); + } + int color = COLOR_YELLOW; + rt_kprintf("begin test hdmi deivice"); + rt_graphix_ops(hdmi) -> set_pixel((char *)&color, 5, 5); + + rt_graphix_ops(hdmi) -> get_pixel((char *)&color, 5, 5); + rt_kprintf("color is %x\n",color); + rt_graphix_ops(hdmi) -> draw_hline((char *)&color, 10, 100, 10); + color = COLOR_GREEN; + rt_graphix_ops(hdmi) -> draw_vline((char *)&color, 10, 10, 100); + int colors[100]; + int i=0; + for (; i < 20; i++) colors[i] = COLOR_RED; + rt_graphix_ops(hdmi) -> blit_line((char *)colors, 20, 20, 20); + +#endif +} + +#ifdef RT_USING_SMP +#define _CPUS_NR RT_CPUS_NR +#else +#define _CPUS_NR 1 +#endif + +#ifdef RT_USING_SMP +static rt_uint8_t rt_thread_stack[_CPUS_NR][128]; +static struct rt_thread smp[_CPUS_NR]; +void smp_test_entry() +{ + rt_kprintf("cpu %d is running.\n",rt_hw_cpu_id()); +} +#endif + +void test_cpusmp(void) +{ + rt_kprintf("Hello Test SMP!\n"); +#ifdef RT_USING_SMP + int i; + char test_name[RT_NAME_MAX]; + for (i = 0; i < _CPUS_NR; i++) + { + rt_sprintf(test_name, "smp%d", i); + rt_thread_init(&smp[i], + test_name, + smp_test_entry, + RT_NULL, + &rt_thread_stack[i][0], + sizeof(rt_thread_stack[i]), + RT_THREAD_PRIORITY_MAX - 2, + 32); + rt_thread_control(&smp[i], RT_THREAD_CTRL_BIND_CPU, (void*)i); + /* startup */ + rt_thread_startup(&smp[i]); + rt_thread_delay(RT_TICK_PER_SECOND); + } +#endif +} + +#ifdef BSP_USING_PIN +#define TEST_PIN_OUT 33 +#define TEST_PIN_IN 37 + +void gpio_rising_test() +{ + rt_kprintf("gpio rising irq function ok!\n"); +} +#endif + +void test_gpio(void) +{ +#ifdef BSP_USING_PIN + rt_uint32_t ret; + rt_kprintf("Hello Test GPIO!\n"); + + rt_pin_mode(TEST_PIN_OUT, PIN_MODE_OUTPUT); + rt_pin_write(TEST_PIN_OUT, PIN_HIGH); + rt_pin_mode(TEST_PIN_IN, PIN_MODE_INPUT); + + ret = rt_pin_read(TEST_PIN_IN); + rt_kprintf("common high input test read result: %d\n",ret); + + rt_pin_write(TEST_PIN_OUT, PIN_LOW); + ret = rt_pin_read(TEST_PIN_IN); + rt_kprintf("common low input test read result: %d\n",ret); + + rt_pin_mode(TEST_PIN_IN, PIN_MODE_INPUT_PULLDOWN); + rt_pin_attach_irq(TEST_PIN_IN, PIN_IRQ_MODE_RISING, gpio_rising_test, RT_NULL); + rt_pin_irq_enable(TEST_PIN_IN, PIN_IRQ_ENABLE); + rt_pin_write(TEST_PIN_OUT, PIN_HIGH); + + rt_pin_irq_enable(TEST_PIN_IN, PIN_IRQ_DISABLE); +#endif +} + +#ifdef BSP_USING_I2C1 +#define DS3231_I2C_BUS_NAME "i2c1" +#define DS3231_ADDR 0x68 +struct rt_i2c_bus_device *i2c_bus = RT_NULL; +static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf) +{ + struct rt_i2c_msg msgs; + msgs.addr = DS3231_ADDR; + msgs.flags = RT_I2C_RD; + msgs.buf = buf; + msgs.len = len; + + if (rt_i2c_transfer(bus, &msgs, 1) == 1) + return RT_EOK; + else + return -RT_ERROR; +} +#endif + +void test_i2c(void) +{ +#ifdef BSP_USING_I2C1 + rt_kprintf("Hello Test I2C!\n"); + char name[RT_NAME_MAX]; + rt_uint8_t buf[]={0x00,0x00,0x43,0x15,0x05,0x01,0x03,0x19}; + + rt_strncpy(name, DS3231_I2C_BUS_NAME, RT_NAME_MAX); + i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(name); + if (i2c_bus == RT_NULL) + rt_kprintf("can't find %s device!\n", name); + else + { + read_regs(i2c_bus, 7, buf); + buf[0] = buf[0]&0x7F; //sec + buf[1] = buf[1]&0x7F; //min + buf[2] = buf[2]&0x3F; //hour + buf[3] = buf[3]&0x07; //week + buf[4] = buf[4]&0x3F; //day + buf[5] = buf[5]&0x1F; //mouth + //year/month/day + rt_kprintf("20%02x-%02x-%02x ",buf[6],buf[5],buf[4]); + //hour:minute/second + rt_kprintf("%02x:%02x:%02x \n",buf[2],buf[1],buf[0]); + } +#endif +} + +#define W25Q_SPI_DEVICE_NAME "spi0.0" +void test_spi(void) +{ +#ifdef BSP_USING_SPI + rt_kprintf("Hello Test SPI!\n"); + struct rt_spi_device *spi0_dev0; + struct rt_spi_device *spi0_dev1; + + char name0[RT_NAME_MAX]; + char name1[RT_NAME_MAX]; + + rt_uint8_t w25x_read_id = 0x90; + rt_uint8_t id[5] = {0}; + + rt_strncpy(name0, "spi0.0", RT_NAME_MAX); + rt_strncpy(name1, "spi0.1", RT_NAME_MAX); + + spi0_dev0 = (struct rt_spi_device *)rt_device_find(name0); + spi0_dev1 = (struct rt_spi_device *)rt_device_find(name1); + + + if (!spi0_dev0 || !spi0_dev1) + { + rt_kprintf("spi sample run failed! can't find %s device!\n", name0); + } + else + { + struct rt_spi_message msg1, msg2; + + msg1.send_buf = &w25x_read_id; + msg1.recv_buf = RT_NULL; + msg1.length = 1; + msg1.cs_take = 1; + msg1.cs_release = 0; + msg1.next = &msg2; + + msg2.send_buf = RT_NULL; + msg2.recv_buf = id; + msg2.length = 5; + msg2.cs_take = 0; + msg2.cs_release = 1; + msg2.next = RT_NULL; + + rt_spi_transfer_message(spi0_dev0, &msg1); + rt_kprintf("use rt_spi_transfer_message() read w25q ID is:%x%x\n", id[3], id[4]); + + } +#endif +} + +#ifdef BSP_USING_SYSTIMER +#define TIMER "timer1" + +static rt_err_t timer_timeout_cb(rt_device_t dev, rt_size_t size) +{ + rt_kprintf("enter hardware timer isr\n"); + return 0; +} +#endif +rt_err_t test_hwtimer(void) +{ +#ifdef BSP_USING_SYSTIMER + rt_kprintf("Hello Test HW Timer!\n"); + rt_err_t err; + rt_hwtimerval_t val; + rt_device_t dev = RT_NULL; + rt_tick_t tick; + rt_hwtimer_mode_t mode; + int t = 5; + + if ((dev = rt_device_find(TIMER)) == RT_NULL) + { + rt_kprintf("No Device: %s\n", TIMER); + return -1; + } + + if (rt_device_open(dev, RT_DEVICE_OFLAG_RDWR) != RT_EOK) + { + rt_kprintf("Open %s Fail\n", TIMER); + return -1; + } + + mode = HWTIMER_MODE_PERIOD; + err = rt_device_control(dev, HWTIMER_CTRL_MODE_SET, &mode); + + tick = rt_tick_get(); + rt_kprintf("Start Timer> Tick: %d\n", tick); + + val.sec = t; + val.usec = 0; + rt_kprintf("SetTime: Sec %d, Usec %d\n", val.sec, val.usec); + if (rt_device_write(dev, 0, &val, sizeof(val)) != sizeof(val)) + { + rt_kprintf("SetTime Fail\n"); + goto EXIT; + } + rt_kprintf("Sleep %d sec\n", t); + rt_thread_delay(t*RT_TICK_PER_SECOND); + + err = rt_device_control(dev, HWTIMER_CTRL_STOP, RT_NULL); + rt_kprintf("Timer Stoped\n"); + + rt_device_read(dev, 0, &val, sizeof(val)); + rt_kprintf("Read: Sec = %d, Usec = %d\n", val.sec, val.usec); + + rt_device_set_rx_indicate(dev, timer_timeout_cb); + + mode = HWTIMER_MODE_PERIOD; + err = rt_device_control(dev, HWTIMER_CTRL_MODE_SET, &mode); + + val.sec = t; + val.usec = 0; + rt_kprintf("SetTime: Sec %d, Usec %d\n", val.sec, val.usec); + if (rt_device_write(dev, 0, &val, sizeof(val)) != sizeof(val)) + { + rt_kprintf("SetTime Fail\n"); + goto EXIT; + } + + rt_thread_delay((t *5 + 1)*RT_TICK_PER_SECOND); + +EXIT: + err = rt_device_close(dev); + rt_kprintf("Close %s\n", TIMER); + + return err; +#endif +} + +#ifdef RT_USING_WDT +#define WDT_DEVICE_NAME "wdg" /* 鐪嬮棬鐙楄澶囧悕绉� */ +static rt_device_t wdg_dev; /* 鐪嬮棬鐙楄澶囧彞鏌� */ +static void idle_hook(void) +{ + /* 鍦ㄧ┖闂茬嚎绋嬬殑鍥炶皟鍑芥暟閲屽杺鐙� */ + rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL); + //rt_kprintf("feed the dog!\n "); +} + +rt_err_t test_wdt(void) +{ + rt_kprintf("Hello Test WDT!\n"); + rt_err_t ret = RT_EOK; + rt_uint32_t timeout = 1; /* 婧㈠嚭鏃堕棿锛屽崟浣嶏細绉� */ + char device_name[RT_NAME_MAX]; + rt_strncpy(device_name, WDT_DEVICE_NAME, RT_NAME_MAX); + /* 鏍规嵁璁惧鍚嶇О鏌ユ壘鐪嬮棬鐙楄澶囷紝鑾峰彇璁惧鍙ユ焺 */ + wdg_dev = rt_device_find(device_name); + if (!wdg_dev) + { + rt_kprintf("find %s failed!\n", device_name); + return RT_ERROR; + } + /* 鍒濆鍖栬澶� */ + ret = rt_device_init(wdg_dev); + if (ret != RT_EOK) + { + rt_kprintf("initialize %s failed!\n", device_name); + return RT_ERROR; + } + /* 璁剧疆鐪嬮棬鐙楁孩鍑烘椂闂� */ + ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); + if (ret != RT_EOK) + { + rt_kprintf("set %s timeout failed!\n", device_name); + return RT_ERROR; + } + /* 鍚姩鐪嬮棬鐙� */ + ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); + if (ret != RT_EOK) + { + rt_kprintf("start %s failed!\n", device_name); + return -RT_ERROR; + } + /* 璁剧疆绌洪棽绾跨▼鍥炶皟鍑芥暟 */ + rt_thread_idle_sethook(idle_hook); + + return ret; + +} +#else +rt_err_t test_wdt(void) +{ + return RT_EOK; +} +#endif + +int test_rtc(void) +{ +#ifdef BSP_USING_RTD + rt_kprintf("Hello Test RTC!\n"); + uint8_t i; + time_t now; + + rt_err_t ret = RT_EOK; + + rt_kprintf("[RTC Test]RTC Test Start...\n"); + rt_thread_delay(RT_TICK_PER_SECOND); + rt_kprintf("[RTC Test]Set RTC 2017-04-01 12:30:46\n\n"); + rt_thread_delay(RT_TICK_PER_SECOND); + + ret = set_date(2017, 4, 1); + if (ret != RT_EOK) + { + rt_kprintf("[RTC Test]Set RTC Date failed\n"); + return RT_ERROR; + } + + rt_thread_delay(RT_TICK_PER_SECOND); + + ret = set_time(12, 30, 46); + if (ret != RT_EOK) + { + rt_kprintf("[RTC Test]Set RTC Time failed\n"); + return RT_ERROR; + } + + rt_thread_delay(RT_TICK_PER_SECOND); + + for (i = 0; i < 10; i++) + { + rt_kprintf("[RTC Test]Read RTC Date and Time: "); + now = time(RT_NULL); + rt_kprintf("%s", ctime(&now)); + + rt_thread_delay(RT_TICK_PER_SECOND); + } + + rt_kprintf("\n"); +#endif + return RT_EOK; +} + +void test_device(int argc, char**argv) +{ + if (0 == strcmp(argv[1],"smp")) + { + test_cpusmp(); + return; + } + if (0 == strcmp(argv[1],"gpio")) + { + test_gpio(); + return; + } + + if (0 == strcmp(argv[1],"i2c")) + { + test_i2c(); + return; + } + + if (0 == strcmp(argv[1],"spi")) + { + test_spi(); + return; + } + + if (0 == strcmp(argv[1],"hwtimer")) + { + test_hwtimer(); + return; + } + + if (0 == strcmp(argv[1],"wdt")) + { + test_wdt(); + return; + } + + if (0 == strcmp(argv[1],"rtc")) + { + test_rtc(); + return; + } + if (0 == strcmp(argv[1],"hdmi")) + { + test_hdmi(); + return; + } + rt_kprintf("param err, please entry test_device \n"); +} +MSH_CMD_EXPORT(test_device, sample: test_device ); diff --git a/bsp/raspi2/cpu/SConscript b/bsp/raspberry-pi/raspi3-32/cpu/SConscript similarity index 100% rename from bsp/raspi2/cpu/SConscript rename to bsp/raspberry-pi/raspi3-32/cpu/SConscript diff --git a/bsp/raspberry-pi/raspi3-32/cpu/armv7.h b/bsp/raspberry-pi/raspi3-32/cpu/armv7.h new file mode 100644 index 0000000000000000000000000000000000000000..859b0371b70c415645b8e9bafd76751284c54231 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/armv7.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ + +#ifndef __ARMV7_H__ +#define __ARMV7_H__ + +/* the exception stack without VFP registers */ +struct rt_hw_exp_stack +{ + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long fp; + unsigned long ip; + unsigned long sp; + unsigned long lr; + unsigned long pc; + unsigned long cpsr; +}; + +struct rt_hw_stack +{ + unsigned long cpsr; + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long fp; + unsigned long ip; + unsigned long lr; + unsigned long pc; +}; + +#define USERMODE 0x10 +#define FIQMODE 0x11 +#define IRQMODE 0x12 +#define SVCMODE 0x13 +#define MONITORMODE 0x16 +#define ABORTMODE 0x17 +#define HYPMODE 0x1b +#define UNDEFMODE 0x1b +#define MODEMASK 0x1f +#define NOINT 0xc0 + +#define T_Bit (1<<5) +#define F_Bit (1<<6) +#define I_Bit (1<<7) +#define A_Bit (1<<8) +#define E_Bit (1<<9) +#define J_Bit (1<<24) + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/cpu/context_gcc.S b/bsp/raspberry-pi/raspi3-32/cpu/context_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..cb95558f7a892756b6f0e725fdf672fc7db957b5 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/context_gcc.S @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + * 2019-07-28 zdzn add smp support + */ + +#include "../rtconfig.h" +.section .text, "ax" + +#ifdef RT_USING_SMP +#define rt_hw_interrupt_disable rt_hw_local_irq_disable +#define rt_hw_interrupt_enable rt_hw_local_irq_enable +#endif + +/* + * rt_base_t rt_hw_interrupt_disable(); + */ +.globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + mrs r0, cpsr + cpsid i + bx lr + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ +.globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + msr cpsr, r0 + bx lr + +/* + * void rt_hw_context_switch_to(rt_uint32 to, struct rt_thread *to_thread); + * r0 --> to (thread stack) + * r1 --> to_thread + */ +.globl rt_hw_context_switch_to +rt_hw_context_switch_to: + ldr sp, [r0] @ get new task stack pointer + +#ifdef RT_USING_SMP + mov r0, r1 + bl rt_cpus_lock_status_restore +#endif /*RT_USING_SMP*/ + b rt_hw_context_switch_exit + +.section .bss.share.isr +_guest_switch_lvl: + .word 0 + +.globl vmm_virq_update + +.section .text.isr, "ax" +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to, struct rt_thread *to_thread); + * r0 --> from (from_thread stack) + * r1 --> to (to_thread stack) + * r2 --> to_thread + */ +.globl rt_hw_context_switch +rt_hw_context_switch: + stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) + stmfd sp!, {r0-r12, lr} @ push lr & register file + + mrs r4, cpsr + tst lr, #0x01 + orrne r4, r4, #0x20 @ it's thumb code + + stmfd sp!, {r4} @ push cpsr + +#ifdef RT_USING_LWP + stmfd sp, {r13, r14}^ @ push usr_sp usr_lr + sub sp, #8 +#endif +#ifdef RT_USING_FPU + /* fpu context */ + vmrs r6, fpexc + tst r6, #(1<<30) + beq 1f + vstmdb sp!, {d0-d15} + vstmdb sp!, {d16-d31} + vmrs r5, fpscr + stmfd sp!, {r5} +1: + stmfd sp!, {r6} +#endif + + str sp, [r0] @ store sp in preempted tasks TCB + ldr sp, [r1] @ get new task stack pointer + +#ifdef RT_USING_SMP + mov r0, r2 + bl rt_cpus_lock_status_restore +#endif /*RT_USING_SMP*/ + b rt_hw_context_switch_exit + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); + */ +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled +.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled + +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread +.globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: +#ifdef RT_USING_SMP + /* r0 :svc_mod context + * r1 :addr of from_thread's sp + * r2 :addr of to_thread's sp + * r3 :to_thread's tcb + */ + + str r0, [r1] + + ldr sp, [r2] + mov r0, r3 + bl rt_cpus_lock_status_restore + + b rt_hw_context_switch_exit + +#else /*RT_USING_SMP*/ + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + ldr ip, =rt_interrupt_from_thread @ set rt_interrupt_from_thread + mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 + str r0, [ip] + str r3, [r2] +_reswitch: + ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread + str r1, [r2] + bx lr +#endif /*RT_USING_SMP*/ + +.global rt_hw_context_switch_exit +rt_hw_context_switch_exit: + +#ifdef RT_USING_SMP +#ifdef RT_USING_SIGNALS + mov r0, sp + cps #Mode_IRQ + bl rt_signal_check + cps #Mode_SVC + mov sp, r0 +#endif +#endif +#ifdef RT_USING_FPU +/* fpu context */ + ldmfd sp!, {r6} + vmsr fpexc, r6 + tst r6, #(1<<30) + beq 1f + ldmfd sp!, {r5} + vmsr fpscr, r5 + vldmia sp!, {d16-d31} + vldmia sp!, {d0-d15} + +#endif + +#ifdef RT_USING_LWP + ldmfd sp, {r13, r14}^ /* usr_sp, usr_lr */ + add sp, #8 +#endif + ldmfd sp!, {r4} + msr spsr_cxsf, r4 /* original mode */ + ldmfd sp!, {r0-r12,lr,pc}^ /* irq return */ + diff --git a/bsp/raspberry-pi/raspi3-32/cpu/cp15.h b/bsp/raspberry-pi/raspi3-32/cpu/cp15.h new file mode 100644 index 0000000000000000000000000000000000000000..14b85b7e6466c5781322483c367f9d0ac13798db --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/cp15.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ +#include "raspi.h" +#ifndef __CP15_H__ +#define __CP15_H__ + +#ifndef __STATIC_FORCEINLINE +#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif + +#define __WFI() __asm__ volatile ("wfi":::"memory") + +#define __WFE() __asm__ volatile ("wfe":::"memory") + +#define __SEV() __asm__ volatile ("sev") + +__STATIC_FORCEINLINE void __ISB(void) +{ + __asm__ volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __asm__ volatile ("dsb 0xF":::"memory"); +} + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ + +__STATIC_FORCEINLINE void __DMB(void) +{ + __asm__ volatile ("dmb 0xF":::"memory"); +} + + +#ifdef RT_USING_SMP +static inline void send_ipi_msg(int cpu, int ipi_vector) +{ + IPI_MAILBOX_SET(cpu) = 1 << ipi_vector; +} + +static inline void setup_bootstrap_addr(int cpu, int addr) +{ + CORE_MAILBOX3_SET(cpu) = addr; +} + +static inline void enable_cpu_ipi_intr(int cpu) +{ + COREMB_INTCTL(cpu) = IPI_MAILBOX_INT_MASK; +} + +static inline void enable_cpu_timer_intr(int cpu) +{ + CORETIMER_INTCTL(cpu) = 0x8; +} + +static inline void enable_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 1; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl)); // write CNTV_CTL +} + +static inline void disable_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 0; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl)); // write CNTV_CTL +} + +static inline void mask_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 2; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl)); // write CNTV_CTL +} + +static inline void unmask_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 1; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl)); // write CNTV_CTL +} + +static inline rt_uint64_t read_cntvct(void) +{ + rt_uint32_t val,val1; + asm volatile ("mrrc p15, 1, %0, %1, c14" : "=r" (val),"=r" (val1)); + return (val); +} + +static inline rt_uint64_t read_cntvoff(void) +{ + + rt_uint64_t val; + asm volatile ("mrrc p15, 4, %Q0, %R0, c14" : "=r" (val)); + return (val); +} + +static inline rt_uint32_t read_cntv_tval(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c3, 0" : "=r"(val)); + return val; +} + + +static inline void write_cntv_tval(rt_uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c14, c3, 0" :: "r"(val)); + return; +} + +static inline rt_uint32_t read_cntfrq(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val)); + return val; +} + + +static inline rt_uint32_t read_cntctrl(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c1, 0" : "=r"(val)); + return val; +} + +static inline uint32_t write_cntctrl(uint32_t val) +{ + + asm volatile ("mcr p15, 0, %0, c14, c1, 0" : :"r"(val)); + return val; +} +#endif + +unsigned long rt_cpu_get_smp_id(void); + +void rt_cpu_mmu_disable(void); +void rt_cpu_mmu_enable(void); +void rt_cpu_tlb_set(volatile unsigned long*); + +void rt_cpu_dcache_clean_flush(void); +void rt_cpu_icache_flush(void); + +void rt_cpu_vector_set_base(unsigned int addr); +void rt_hw_mmu_init(void); +void rt_hw_vector_init(void); + +void set_timer_counter(unsigned int counter); +void set_timer_control(unsigned int control); +#endif diff --git a/bsp/raspberry-pi/raspi3-32/cpu/cp15_gcc.S b/bsp/raspberry-pi/raspi3-32/cpu/cp15_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..db2e6143ae7258ab7357d3909be42f47de2dd9c9 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/cp15_gcc.S @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + */ + +.globl rt_cpu_get_smp_id +rt_cpu_get_smp_id: + mrc p15, #0, r0, c0, c0, #5 + bx lr + +.globl rt_cpu_vector_set_base +rt_cpu_vector_set_base: + /* clear SCTRL.V to customize the vector address */ + mrc p15, #0, r1, c1, c0, #0 + bic r1, #(1 << 13) + mcr p15, #0, r1, c1, c0, #0 + /* set up the vector address */ + mcr p15, #0, r0, c12, c0, #0 + dsb + bx lr + +.globl rt_hw_cpu_dcache_enable +rt_hw_cpu_dcache_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x00000004 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +.globl rt_hw_cpu_icache_enable +rt_hw_cpu_icache_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x00001000 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +_FLD_MAX_WAY: + .word 0x3ff +_FLD_MAX_IDX: + .word 0x7ff + +.globl set_timer_counter +set_timer_counter: + mcr p15, #0, r0, c14, c3, #0 @ write virtual timer timerval register + bx lr +.globl set_timer_control +set_timer_control: + mcr p15, #0, r0, c14, c3, #1 @ write virtual timer control register + bx lr + +.globl rt_cpu_dcache_clean_flush +rt_cpu_dcache_clean_flush: + push {r4-r11} + dmb + mrc p15, #1, r0, c0, c0, #1 @ read clid register + ands r3, r0, #0x7000000 @ get level of coherency + mov r3, r3, lsr #23 + beq finished + mov r10, #0 +loop1: + add r2, r10, r10, lsr #1 + mov r1, r0, lsr r2 + and r1, r1, #7 + cmp r1, #2 + blt skip + mcr p15, #2, r10, c0, c0, #0 + isb + mrc p15, #1, r1, c0, c0, #0 + and r2, r1, #7 + add r2, r2, #4 + ldr r4, _FLD_MAX_WAY + ands r4, r4, r1, lsr #3 + clz r5, r4 + ldr r7, _FLD_MAX_IDX + ands r7, r7, r1, lsr #13 +loop2: + mov r9, r4 +loop3: + orr r11, r10, r9, lsl r5 + orr r11, r11, r7, lsl r2 + mcr p15, #0, r11, c7, c14, #2 + subs r9, r9, #1 + bge loop3 + subs r7, r7, #1 + bge loop2 +skip: + add r10, r10, #2 + cmp r3, r10 + bgt loop1 + +finished: + dsb + isb + pop {r4-r11} + bx lr + +.globl rt_cpu_icache_flush +rt_cpu_icache_flush: + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate + dsb + isb + bx lr + +.globl rt_hw_cpu_dcache_disable +rt_hw_cpu_dcache_disable: + push {r4-r11, lr} + bl rt_cpu_dcache_clean_flush + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #0x00000004 + mcr p15, #0, r0, c1, c0, #0 + pop {r4-r11, lr} + bx lr + +.globl rt_hw_cpu_icache_disable +rt_hw_cpu_icache_disable: + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #0x00001000 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +.globl rt_cpu_mmu_disable +rt_cpu_mmu_disable: + mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #1 + mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit + dsb + bx lr + +.globl rt_cpu_mmu_enable +rt_cpu_mmu_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x001 + mcr p15, #0, r0, c1, c0, #0 @ set mmu enable bit + dsb + bx lr + +.globl rt_cpu_tlb_set +rt_cpu_tlb_set: + mcr p15, #0, r0, c2, c0, #0 + dmb + bx lr diff --git a/bsp/raspberry-pi/raspi3-32/cpu/cpu.c b/bsp/raspberry-pi/raspi3-32/cpu/cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..4d02ca35e184139c60a67578ed20f04e4a9e8dff --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/cpu.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + * 2019-07-28 zdzn add smp support + */ + +#include +#include +#include +#include "cp15.h" + +int rt_hw_cpu_id(void) +{ + int cpu_id; + __asm__ volatile ( + "mrc p15, 0, %0, c0, c0, 5" + :"=r"(cpu_id) + ); + cpu_id &= 0xf; + return cpu_id; +}; + + +#ifdef RT_USING_SMP +void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock) +{ + lock->slock = 0; +} + +void rt_hw_spin_lock(rt_hw_spinlock_t *lock) +{ + unsigned long tmp; + unsigned long newval; + rt_hw_spinlock_t lockval; + __asm__ __volatile__( + "pld [%0]" + ::"r"(&lock->slock) + ); + + __asm__ __volatile__( + "1: ldrex %0, [%3]\n" + " add %1, %0, %4\n" + " strex %2, %1, [%3]\n" + " teq %2, #0\n" + " bne 1b" + : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) + : "r" (&lock->slock), "I" (1 << 16) + : "cc"); + + while (lockval.tickets.next != lockval.tickets.owner) + { + __WFE(); + lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner); + } + + __DMB(); +} + +void rt_hw_spin_unlock(rt_hw_spinlock_t *lock) +{ + __DMB(); + lock->tickets.owner++; + __DSB(); + __SEV(); +} +#endif /*RT_USING_SMP*/ + +/** + * @addtogroup ARM CPU + */ +/*@{*/ + +/** shutdown CPU */ +void rt_hw_cpu_shutdown() +{ + rt_uint32_t level; + rt_kprintf("shutdown...\n"); + + level = rt_hw_interrupt_disable(); + while (level) + { + RT_ASSERT(0); + } +} + +/*@}*/ diff --git a/bsp/raspberry-pi/raspi3-32/cpu/interrupt.c b/bsp/raspberry-pi/raspi3-32/cpu/interrupt.c new file mode 100644 index 0000000000000000000000000000000000000000..c9e7c17f8f495f1801116023b0361eff28bbe5fd --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/interrupt.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/5/3 Bernard first version + * 2019-07-28 zdzn add smp support + * 2019-08-09 zhangjun fixup the problem of smp startup and scheduling issues, + * write addr to mailbox3 to startup smp, and we use mailbox0 for ipi + */ + +#include +#include + +#include "cp15.h" +#include + +#define MAX_HANDLERS 72 + +#ifdef RT_USING_SMP +#define rt_interrupt_nest rt_cpu_self()->irq_nest +#else +extern volatile rt_uint8_t rt_interrupt_nest; +#endif + +const unsigned int VECTOR_BASE = 0x00; +extern void rt_cpu_vector_set_base(unsigned int addr); +extern int system_vectors; + +void rt_hw_vector_init(void) +{ + rt_cpu_vector_set_base((unsigned int)&system_vectors); +} + +/* exception and interrupt handler table */ +struct rt_irq_desc isr_table[MAX_HANDLERS]; + +rt_uint32_t rt_interrupt_from_thread; +rt_uint32_t rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +extern int system_vectors; + +static void default_isr_handler(int vector, void *param) +{ +#ifdef RT_USING_SMP + rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector); +#else + rt_kprintf("unhandled irq: %d\n",vector); +#endif +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + rt_uint32_t index; + + /* mask all of interrupts */ + IRQ_DISABLE_BASIC = 0x000000ff; + IRQ_DISABLE1 = 0xffffffff; + IRQ_DISABLE2 = 0xffffffff; + for (index = 0; index < MAX_HANDLERS; index ++) + { + isr_table[index].handler = default_isr_handler; + isr_table[index].param = NULL; +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[index].name, "unknown", RT_NAME_MAX); + isr_table[index].counter = 0; +#endif + } + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrupt_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + + if (vector < 32) + { + IRQ_DISABLE1 = (1 << vector); + } + else if (vector < 64) + { + vector = vector % 32; + IRQ_DISABLE2 = (1 << vector); + } + else + { + vector = vector - 64; + IRQ_DISABLE_BASIC = (1 << vector); + } +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + if (vector < 32) + { + IRQ_ENABLE1 = (1 << vector); + } + else if (vector < 64) + { + vector = vector % 32; + IRQ_ENABLE2 = (1 << vector); + } + else + { + vector = vector - 64; + IRQ_ENABLE_BASIC = (1 << vector); + } +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if (vector < MAX_HANDLERS) + { + old_handler = isr_table[vector].handler; + + if (handler != RT_NULL) + { +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); +#endif /* RT_USING_INTERRUPT_INFO */ + isr_table[vector].handler = handler; + isr_table[vector].param = param; + } + } + + return old_handler; +} + +#ifdef RT_USING_SMP +void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask) +{ + __DSB(); + if (cpu_mask & 0x1) + { + send_ipi_msg(0, ipi_vector); + } + if (cpu_mask & 0x2) + { + send_ipi_msg(1, ipi_vector); + } + if (cpu_mask & 0x4) + { + send_ipi_msg(2, ipi_vector); + } + if (cpu_mask & 0x8) + { + send_ipi_msg(3, ipi_vector); + } + __DSB(); +} +#endif + +#ifdef RT_USING_SMP +void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler) +{ + /* note: ipi_vector maybe different with irq_vector */ + rt_hw_interrupt_install(ipi_vector, ipi_isr_handler, 0, "IPI_HANDLER"); +} +#endif diff --git a/bsp/raspberry-pi/raspi3-32/cpu/interrupt.h b/bsp/raspberry-pi/raspi3-32/cpu/interrupt.h new file mode 100644 index 0000000000000000000000000000000000000000..9aae0f556a0338f5b8afe5d2e2e1275da1012ac3 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/interrupt.h @@ -0,0 +1,18 @@ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#include +#include + +#define INT_IRQ 0x00 +#define INT_FIQ 0x01 + +void rt_hw_interrupt_init(void); +void rt_hw_interrupt_mask(int vector); +void rt_hw_interrupt_umask(int vector); + +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name); + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/cpu/mmu.c b/bsp/raspberry-pi/raspi3-32/cpu/mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..b3541d2ad431ebdd09399989f14f2ca48e06c450 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/mmu.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-01-10 bernard porting to AM1808 + * 2019-07-28 zdzn add smp support + */ + +#include "mmu.h" + +/* dump 2nd level page table */ +void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + for (i = 0; i < 256; i++) + { + rt_uint32_t pte2 = ptb[i]; + if ((pte2 & 0x3) == 0) + { + if (fcnt == 0) + rt_kprintf(" "); + rt_kprintf("%04x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf(" %04x: %x: ", i, pte2); + if ((pte2 & 0x3) == 0x1) + { + rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, + (pte2 >> 15) & 0x1, + ((pte2 >> 10) | (pte2 >> 2)) & 0x1f); + } + else + { + rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1, + ((pte2 >> 4) | (pte2 >> 2)) & 0x1f); + } + } +} + +void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + rt_kprintf("page table@%p\n", ptb); + for (i = 0; i < 1024*4; i++) + { + rt_uint32_t pte1 = ptb[i]; + if ((pte1 & 0x3) == 0) + { + rt_kprintf("%03x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf("%03x: %08x: ", i, pte1); + if ((pte1 & 0x3) == 0x3) + { + rt_kprintf("LPAE\n"); + } + else if ((pte1 & 0x3) == 0x1) + { + rt_kprintf("pte,ns:%d,domain:%d\n", + (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf); + /* + *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000) + * - 0x80000000 + 0xC0000000)); + */ + } + else if (pte1 & (1 << 18)) + { + rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + ((pte1 >> 10) | (pte1 >> 2)) & 0x1f); + } + else + { + rt_kprintf("section,ns:%d,ap:%x," + "xn:%d,texcb:%02x,domain:%d\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + (((pte1 & (0x7 << 12)) >> 10) | + ((pte1 & 0x0c) >> 2)) & 0x1f, + (pte1 >> 5) & 0xf); + } + } +} + +/* level1 page table, each entry for 1MB memory. */ +volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024))); +void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart, + rt_uint32_t vaddrEnd, + rt_uint32_t paddrStart, + rt_uint32_t attr) +{ + volatile rt_uint32_t *pTT; + volatile int i, nSec; + pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20); + nSec = (vaddrEnd >> 20) - (vaddrStart >> 20); + for (i = 0; i <= nSec; i++) + { + *pTT = attr | (((paddrStart >> 20) + i) << 20); + pTT++; + } +} + +unsigned long rt_hw_set_domain_register(unsigned long domain_val) +{ + unsigned long old_domain; + + asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain)); + asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory"); + + return old_domain; +} + +void rt_hw_init_mmu_table() +{ + /* set page table */ + /* 4G 1:1 memory */ + rt_hw_mmu_setmtt(0x00000000, 0x3effffff, 0x00000000, NORMAL_MEM); + /* IO memory region */ + rt_hw_mmu_setmtt(0x3f000000, 0x40010000, 0x3f000000, DEVICE_MEM); +} + +void rt_hw_change_mmu_table(rt_uint32_t vaddrStart, + rt_uint32_t size, + rt_uint32_t paddrStart, rt_uint32_t attr) +{ + rt_hw_mmu_setmtt(vaddrStart, vaddrStart+size-1, paddrStart, attr); +#ifndef RT_USING_SMP + rt_cpu_dcache_clean_flush(); + rt_cpu_icache_flush(); +#endif +} + + +void rt_hw_mmu_init(void) +{ + rt_cpu_dcache_clean_flush(); + rt_cpu_icache_flush(); + rt_hw_cpu_dcache_disable(); + rt_hw_cpu_icache_disable(); + rt_cpu_mmu_disable(); + + /*rt_hw_cpu_dump_page_table(MMUTable);*/ + rt_hw_set_domain_register(0x55555555); + + rt_cpu_tlb_set(MMUTable); + + rt_cpu_mmu_enable(); + + rt_hw_cpu_icache_enable(); + rt_hw_cpu_dcache_enable(); +} + diff --git a/bsp/raspberry-pi/raspi3-32/cpu/mmu.h b/bsp/raspberry-pi/raspi3-32/cpu/mmu.h new file mode 100644 index 0000000000000000000000000000000000000000..6b0c25e9907bda284f7f605a0f3586d2312b094a --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/mmu.h @@ -0,0 +1,51 @@ +#ifndef MMU_H__ +#define MMU_H__ +#include +#include +#include +#include "cp15.h" + +#define DESC_SEC (0x2) +#define CB (3 << 2) //cache_on, write_back +#define CNB (2 << 2) //cache_on, write_through +#define NCB (1 << 2) //cache_off,WR_BUF on +#define NCNB (0 << 2) //cache_off,WR_BUF off +#define AP_RW (3 << 10) //supervisor=RW, user=RW +#define AP_RO (2 << 10) //supervisor=RW, user=RO +#define XN (1 << 4) // eXecute Never +#define SHARED (1 << 16) /* shareable */ +#define SHAREDEVICE (1 << 2) /* shared device */ +#define STRONGORDER (0 << 2) /* strong ordered */ +#define MEMWBWA ((1 << 12) | (3 << 2)) /* write back, write allocate */ + +#define DOMAIN_FAULT (0x0) +#define DOMAIN_CHK (0x1) +#define DOMAIN_NOTCHK (0x3) +#define DOMAIN0 (0x0 << 5) +#define DOMAIN1 (0x1 << 5) + +#define DOMAIN0_ATTR (DOMAIN_CHK << 0) +#define DOMAIN1_ATTR (DOMAIN_FAULT << 2) + +/* Read/Write, cache, write back */ +#define RW_CB (AP_RW | DOMAIN0 | CB | DESC_SEC) +/* Read/Write, cache, write through */ +#define RW_CNB (AP_RW | DOMAIN0 | CNB | DESC_SEC) +/* Read/Write without cache and write buffer */ +#define RW_NCNB (AP_RW | DOMAIN0 | NCNB | DESC_SEC) +/* Read/Write without cache and write buffer, no execute */ +#define RW_NCNBXN (AP_RW | DOMAIN0 | NCNB | DESC_SEC | XN) +/* Read/Write without cache and write buffer */ +#define RW_FAULT (AP_RW | DOMAIN1 | NCNB | DESC_SEC) + +/* device mapping type */ +#define DEVICE_MEM (SHARED | SHAREDEVICE | RW_NCNBXN) +/* normal memory mapping type */ +#define NORMAL_MEM (SHARED | AP_RW | DOMAIN0 | MEMWBWA | DESC_SEC) +#define STRONG_ORDER_MEM (SHARED | AP_RO | XN | DESC_SEC) +#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000) + +void rt_hw_change_mmu_table(rt_uint32_t vaddrStart, + rt_uint32_t size, + rt_uint32_t paddrStart, rt_uint32_t attr); +#endif diff --git a/bsp/raspberry-pi/raspi3-32/cpu/stack.c b/bsp/raspberry-pi/raspi3-32/cpu/stack.c new file mode 100644 index 0000000000000000000000000000000000000000..c2c60fbf49de71ee23ca7e58d3ff18b907176e83 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/stack.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-23 Bernard the first version + * 2011-10-05 Bernard add thumb mode + */ +#include +#include +#include + +/** + * @addtogroup AM33xx + */ +/*@{*/ + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, + rt_uint8_t *stack_addr, void *texit) +{ + rt_uint32_t *stk; + + stack_addr += sizeof(rt_uint32_t); + stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8); + stk = (rt_uint32_t *)stack_addr; + *(--stk) = (rt_uint32_t)tentry; /* entry point */ + *(--stk) = (rt_uint32_t)texit; /* lr */ + *(--stk) = 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 */ + +#ifdef RT_USING_LWP + *(--stk) = 0; /* user lr */ + *(--stk) = 0; /* user sp*/ +#endif +#ifdef RT_USING_FPU + *(--stk) = 0; /* not use fpu*/ +#endif + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ diff --git a/bsp/raspberry-pi/raspi3-32/cpu/start_gcc.S b/bsp/raspberry-pi/raspi3-32/cpu/start_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..ec74213f0738dcdab62aaad3d6715c00aeb6382e --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/start_gcc.S @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + * 2019-07-28 zdzn add smp support + */ + +#include "../rtconfig.h" +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled +.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled + +#ifdef RT_USING_FPU +.equ UND_Stack_Size, 0x00000400 +#else +.equ UND_Stack_Size, 0x00000000 +#endif +.equ SVC_Stack_Size, 0x00000400 +.equ ABT_Stack_Size, 0x00000000 +.equ RT_FIQ_STACK_PGSZ, 0x00000000 +.equ RT_IRQ_STACK_PGSZ, 0x00000800 +.equ USR_Stack_Size, 0x00000400 + +#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ + RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ) + +.section .data.share.isr +/* stack */ + +#ifdef RT_USING_SMP +.globl stack_start0 +.globl stack_top0 +.globl stack_start1 +.globl stack_top1 +.globl stack_start2 +.globl stack_top2 +.globl stack_start3 +.globl stack_top3 +stack_start0: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top0: + +stack_start1: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top1: + +stack_start2: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top2: + +stack_start3: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top3: + +.globl boot_indicate +boot_indicate: +.rept 16 +.byte 0 +.endr + +#else +.globl stack_start +.globl stack_top +stack_start: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top: +#endif + + +.text +/* reset entry */ +.globl _reset +_reset: + + /* Disable IRQ & FIQ */ + cpsid if + + /* Check for HYP mode */ + mrs r0, cpsr_all + and r0, r0, #0x1F + mov r8, #0x1A + cmp r0, r8 + beq overHyped + b continue + +overHyped: /* Get out of HYP mode */ + ldr r1, =continue + msr ELR_hyp, r1 + mrs r1, cpsr_all + and r1, r1, #0x1f ;@ CPSR_MODE_MASK + orr r1, r1, #0x13 ;@ CPSR_MODE_SUPERVISOR + msr SPSR_hyp, r1 + eret + +continue: + + /* disable mmu */ + bl rt_cpu_mmu_disable + /* set the cpu to SVC32 mode and disable interrupt */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0x13 + msr cpsr_c, r0 +#ifdef RT_USING_SMP + mrc p15, 0, r0, c0, c0, 5 + ubfx r0, r0, #0, #2 + cmp r0, #0 + beq 1f + /* write boot indicate */ + ldr r5, = boot_indicate + str r0, [r5, r0, lsl #2] + bl secondary_cpu_start + b . +1: +#endif + /* setup stack */ +#ifdef RT_USING_SMP + ldr r0, =stack_top0 +#else + ldr r0, =stack_top +#endif + bl stack_setup + + /* clear .bss */ + mov r0,#0 /* get a zero */ + ldr r1,=__bss_start /* bss start */ + ldr r2,=__bss_end /* bss end */ + +bss_loop: + cmp r1,r2 /* check if data to clear */ + strlo r0,[r1],#4 /* clear 4 bytes */ + blo bss_loop /* loop until done */ + bl rt_hw_init_mmu_table + bl init_mbox_mmu_map + bl rt_hw_mmu_init + + /* start RT-Thread Kernel */ + ldr pc, _rtthread_startup +_rtthread_startup: + .word rtthread_startup + +stack_setup: + + @ Set the startup stack for svc + mov sp, r0 + + @ Enter Undefined Instruction Mode and set its Stack Pointer + msr cpsr_c, #Mode_UND|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #UND_Stack_Size + + @ Enter Abort Mode and set its Stack Pointer + msr cpsr_c, #Mode_ABT|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #ABT_Stack_Size + + @ Enter FIQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #RT_FIQ_STACK_PGSZ + + @ Enter IRQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #RT_IRQ_STACK_PGSZ + + /* come back to SVC mode */ + msr cpsr_c, #Mode_SVC|I_Bit|F_Bit + bx lr + +.text + +/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ +.section .text.isr, "ax" + .align 5 +.globl vector_fiq +vector_fiq: + stmfd sp!,{r0-r7,lr} + bl rt_hw_trap_fiq + ldmfd sp!,{r0-r7,lr} + subs pc, lr, #4 + +.globl rt_interrupt_enter +.globl rt_interrupt_leave +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread + +.globl rt_current_thread +.globl vmm_thread +.globl vmm_virq_check + + .align 5 +.globl vector_irq +vector_irq: +#ifdef RT_USING_SMP + clrex + + stmfd sp!, {r0, r1} + cps #Mode_SVC + mov r0, sp /* svc_sp */ + mov r1, lr /* svc_lr */ + + cps #Mode_IRQ + sub lr, lr, #4 + stmfd r0!, {r1, lr} /* svc_lr, svc_pc */ + stmfd r0!, {r2 - r12} + ldmfd sp!, {r1, r2} /* original r0, r1 */ + stmfd r0!, {r1 - r2} + mrs r1, spsr /* original mode */ + stmfd r0!, {r1} + +#ifdef RT_USING_LWP + stmfd r0, {r13, r14}^ /* usr_sp, usr_lr */ + sub r0, #8 +#endif +#ifdef RT_USING_FPU + /* fpu context */ + vmrs r6, fpexc + tst r6, #(1<<30) + beq 1f + vstmdb r0!, {d0-d15} + vstmdb r0!, {d16-d31} + vmrs r5, fpscr + stmfd r0!, {r5} +1: + stmfd r0!, {r6} +#endif + mov r8, r0 + + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave + + cps #Mode_SVC + mov sp, r8 + mov r0, r8 + + bl rt_scheduler_do_irq_switch + + b rt_hw_context_switch_exit + +#else + stmfd sp!, {r0-r12,lr} + + 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 + + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 + +rt_hw_context_switch_interrupt_do: + mov r1, #0 @ clear flag + str r1, [r0] + + mov r1, sp @ r1 point to {r0-r3} in stack + add sp, sp, #4*4 + ldmfd sp!, {r4-r12,lr}@ reload saved registers + mrs r0, spsr @ get cpsr of interrupt thread + sub r2, lr, #4 @ save old task's pc to r2 + + @ Switch to SVC mode with no interrupt. If the usr mode guest is + @ interrupted, this will just switch to the stack of kernel space. + @ save the registers in kernel space won't trigger data abort. + msr cpsr_c, #I_Bit|F_Bit|Mode_SVC + + stmfd sp!, {r2} @ push old task's pc + stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 + ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread + stmfd sp!, {r1-r4} @ push old task's r0-r3 + stmfd sp!, {r0} @ push old task's cpsr + +#ifdef RT_USING_LWP + stmfd sp, {r13, r14}^ @push usr_sp, usr_lr + sub sp, #8 +#endif +#ifdef RT_USING_FPU + /* fpu context */ + vmrs r6, fpexc + tst r6, #(1<<30) + beq 1f + vstmdb sp!, {d0-d15} + vstmdb sp!, {d16-d31} + vmrs r5, fpscr + stmfd sp!, {r5} +1: + stmfd sp!, {r6} +#endif + + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] @ store sp in preempted tasks's TCB + + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] @ get new task's stack pointer + +#ifdef RT_USING_FPU +/* fpu context */ + ldmfd sp!, {r6} + vmsr fpexc, r6 + tst r6, #(1<<30) + beq 1f + ldmfd sp!, {r5} + vmsr fpscr, r5 + vldmia sp!, {d16-d31} + vldmia sp!, {d0-d15} +1: +#endif + +#ifdef RT_USING_LWP + ldmfd sp, {r13, r14}^ @pop usr_sp, usr_lr + add sp, #8 +#endif + + ldmfd sp!, {r4} @ pop new task's cpsr to spsr + msr spsr_cxsf, r4 + + ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr + +#endif + +.macro push_svc_reg + sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */ + stmia sp, {r0 - r12} @/* Calling r0-r12 */ + mov r0, sp + mrs r6, spsr @/* Save CPSR */ + str lr, [r0, #15*4] @/* Push PC */ + str r6, [r0, #16*4] @/* Push CPSR */ + cps #Mode_SVC + str sp, [r0, #13*4] @/* Save calling SP */ + str lr, [r0, #14*4] @/* Save calling PC */ +.endm + + .align 5 + .globl vector_swi +vector_swi: + push_svc_reg + bl rt_hw_trap_swi + b . + + .align 5 + .globl vector_undef +vector_undef: + push_svc_reg + cps #Mode_UND + bl rt_hw_trap_undef +#ifdef RT_USING_FPU + ldr lr, [sp, #15*4] + ldmia sp, {r0 - r12} + add sp, sp, #17 * 4 + movs pc, lr +#endif + b . + + .align 5 + .globl vector_pabt +vector_pabt: + push_svc_reg + bl rt_hw_trap_pabt + b . + + .align 5 + .globl vector_dabt +vector_dabt: + push_svc_reg + bl rt_hw_trap_dabt + b . + + .align 5 + .globl vector_resv +vector_resv: + push_svc_reg + bl rt_hw_trap_resv + b . + +#ifdef RT_USING_SMP + +.global secondary_cpu_start +secondary_cpu_start: + /* set vector base */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, #(1<<13) + mcr p15, 0, r0, c1, c0, 0 + + /* setup stack */ + mrc p15, 0, r0, c0, c0, 5 + ubfx r0, r0, #0, #2 + ldr r1, =stack_top0 + ldr r2, =ISR_Stack_Size + mul r3, r2, r0 + add r0, r1, r3 + bl stack_setup + /* initialize the mmu table and enable mmu */ + bl rt_hw_mmu_init + b secondary_cpu_c_start + +#endif + +;@ void arm_smp_enable(void); +.globl arm_smp_enable +arm_smp_enable: + mrc p15, 0, r0, c1, c0, 1 ;@ set SMP bit in ACTLR + orr r0, r0, #0x40 + mcr p15, 0, r0, c1, c0, 1 + bx lr +/* + mrrc p15, 1, r0, r1, c15 + orr r0, r0, #0x40 + mcrr p15, 1, r0, r1, c15 + dsb + isb + bx lr +*/ +.text +;@ void arm_smp_disable(void); +.globl arm_smp_disable + +arm_smp_disable: + mrc p15, 0, r0, c1, c0, 1 ;@ clear SMP bit in ACTLR + bic r0, r0, #0x40 + mcr p15, 0, r0, c1, c0, 1 + bx lr +/* + mrrc p15, 1, r0, r1, c15 + bic r0, r0, #0x40 + mcrr p15, 1, r0, r1, c15 + bx lr +*/ + diff --git a/bsp/raspberry-pi/raspi3-32/cpu/trap.c b/bsp/raspberry-pi/raspi3-32/cpu/trap.c new file mode 100644 index 0000000000000000000000000000000000000000..f83f1836952da85d22a69694e8440f8d4abd6f58 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/trap.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-20 Bernard first version + * 2019-07-28 zdzn add smp support + * 2019-08-09 zhangjun fixup the problem of smp startup and scheduling issues, + * write addr to mailbox3 to startup smp, and we use mailbox0 for ipi + */ + +#include +#include +#include + +#include "armv7.h" + +extern struct rt_thread *rt_current_thread; +#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; + uint32_t irq; + rt_isr_handler_t isr_func; + extern struct rt_irq_desc isr_table[]; + uint32_t value = 0; + value = IRQ_PEND_BASIC & 0x3ff; +#ifdef RT_USING_SMP + uint32_t mailbox_data; + uint32_t cpu_id = rt_hw_cpu_id(); + uint32_t int_source = CORE_IRQSOURCE(cpu_id); + mailbox_data = IPI_MAILBOX_CLEAR(cpu_id); + if (int_source & 0x0f) + { + if (int_source & 0x08) + { + isr_func = isr_table[IRQ_ARM_TIMER].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[IRQ_ARM_TIMER].counter++; +#endif + if (isr_func) + { + param = isr_table[IRQ_ARM_TIMER].param; + isr_func(IRQ_ARM_TIMER, param); + } + } + } + if (int_source & 0xf0) + { + /*it's a ipi interrupt*/ + if (mailbox_data & 0x1) + { + /* clear mailbox */ + IPI_MAILBOX_CLEAR(cpu_id) = mailbox_data; + isr_func = isr_table[IRQ_ARM_MAILBOX].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[IRQ_ARM_MAILBOX].counter++; +#endif + if (isr_func) + { + param = isr_table[IRQ_ARM_MAILBOX].param; + isr_func(IRQ_ARM_MAILBOX, param); + } + } + else + CORE_MAILBOX3_CLEAR(cpu_id) = mailbox_data; + } +#endif + /* local interrupt*/ + if (value) + { + if (value & (1 << 8)) + { + value = IRQ_PEND1; + irq = __rt_ffs(value) - 1; + } + else if (value & (1 << 9)) + { + value = IRQ_PEND2; + irq = __rt_ffs(value) + 31; + } + else + { + value &= 0x0f; + irq = __rt_ffs(value) + 63; + } + + /* get interrupt service routine */ + isr_func = isr_table[irq].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[irq].counter++; +#endif + if (isr_func) + { + /* Interrupt for myself. */ + param = isr_table[irq].param; + /* turn to interrupt service routine */ + isr_func(irq, param); + } + } +} + +void rt_hw_trap_fiq(void) +{ + +} diff --git a/bsp/raspberry-pi/raspi3-32/cpu/vector_gcc.S b/bsp/raspberry-pi/raspi3-32/cpu/vector_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..eebfe9c13baeab4f4a739db433850658caf6934c --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/cpu/vector_gcc.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006-2019, 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 diff --git a/bsp/raspberry-pi/raspi3-32/driver/Kconfig b/bsp/raspberry-pi/raspi3-32/driver/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..aaa7110f1dc3251a17127c65c3a13974c87164ea --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/Kconfig @@ -0,0 +1,103 @@ +menu "Hardware Drivers Config" + menu "BCM Peripheral Drivers" + menuconfig BSP_USING_UART + bool "Using UART" + select RT_USING_SERIAL + default y + + if BSP_USING_UART + config RT_USING_UART0 + bool "Enabel UART 0" + default y + + config RT_USING_UART1 + bool "Enabel UART 1" + default n + endif + + config BSP_USING_PIN + bool "Using PIN" + select RT_USING_PIN + default y + + menuconfig BSP_USING_SYSTIMER + bool "Enable SYSTIMER" + select RT_USING_HWTIMER + default n + + if BSP_USING_SYSTIMER + config RT_USING_SYSTIMER1 + bool "Enable sys timer1" + default n + config RT_USING_SYSTIMER3 + bool "Enable sys timer3" + default n + endif + + menuconfig BSP_USING_I2C + bool "Enable I2C" + select RT_USING_I2C + default n + + if BSP_USING_I2C + config BSP_USING_I2C0 + bool "Enable I2C0" + default n + config BSP_USING_I2C1 + bool "Enable I2C1" + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI" + select RT_USING_SPI + default n + + if BSP_USING_SPI + config BSP_USING_SPI0_BUS + bool "Enable SPI0 BUS" + default n + config BSP_USING_SPI0_DEVICE0 + bool "Enable SPI0 DEVICE0" + select BSP_USING_SPI0_BUS + default n + config BSP_USING_SPI0_DEVICE1 + bool "Enable SPI0 DEVICE1" + select BSP_USING_SPI0_BUS + default n + endif + + config BSP_USING_WDT + bool "Enable WDT" + select RT_USING_WDT + default n + + menuconfig BSP_USING_RTC + bool "Enable RTC" + select RT_USING_RTC + default n + + if BSP_USING_RTC + config BSP_USING_ALARM + bool "Enable Alarm" + select RT_USING_ALARM + default n + endif + + menuconfig BSP_USING_SDIO + bool "Enable SDIO" + select RT_USING_SDIO + default n + + if BSP_USING_SDIO + config BSP_USING_SDIO0 + bool "Enable SDIO0" + select RT_USING_SDIO + default n + endif + menuconfig BSP_USING_HDMI + bool "Enable HDMI" + select BSP_USING_SPI + default n + endmenu +endmenu diff --git a/bsp/raspberry-pi/raspi3-32/driver/SConscript b/bsp/raspberry-pi/raspi3-32/driver/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..c51b2c42bf9c9b0e3c684d59c24ef7d2500c6971 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/SConscript @@ -0,0 +1,31 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Split(''' +board.c +drv_uart.c +mbox.c +''') +CPPPATH = [cwd] + +if GetDepend('BSP_USING_SYSTIMER'): + src += ['drv_timer.c'] +if GetDepend('BSP_USING_PIN'): + src += ['drv_gpio.c'] +if GetDepend('BSP_USING_I2C'): + src += ['drv_i2c.c'] +if GetDepend('BSP_USING_WDT'): + src += ['drv_wdt.c'] +if GetDepend('BSP_USING_SPI'): + src += ['drv_spi.c'] +if GetDepend('BSP_USING_SDIO'): + src += ['drv_sdio.c'] +if GetDepend('BSP_USING_RTC'): + src += ['drv_rtc.c'] +if GetDepend('BSP_USING_HDMI'): + src += ['drv_fb.c'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/raspberry-pi/raspi3-32/driver/board.c b/bsp/raspberry-pi/raspi3-32/driver/board.c new file mode 100644 index 0000000000000000000000000000000000000000..a1b3d603c82c9010fd8bbaa64890eb5edac57912 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/board.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include +#include + +#include "board.h" +#include "drv_uart.h" +#include "drv_timer.h" + +#include "cp15.h" + +#ifdef RT_USING_SMP +unsigned int cntfrq; +#endif + +void rt_hw_timer_isr(int vector, void *parameter) +{ + rt_tick_increase(); +#ifndef RT_USING_SMP + ARM_TIMER_IRQCLR = 0; +#else + mask_cntv(); + __DSB(); + write_cntv_tval(cntfrq); + __DSB(); + unmask_cntv(); + __DSB(); +#endif +} + +int rt_hw_timer_init() +{ +#ifndef RT_USING_SMP + /* timer_clock = apb_clock/(pre_divider + 1) */ + ARM_TIMER_PREDIV = (250 - 1); + + ARM_TIMER_RELOAD = 0; + ARM_TIMER_LOAD = 0; + ARM_TIMER_IRQCLR = 0; + ARM_TIMER_CTRL = 0; + + ARM_TIMER_RELOAD = 10000; + ARM_TIMER_LOAD = 10000; + + /* 23-bit counter, enable interrupt, enable timer */ + ARM_TIMER_CTRL = (1 << 1) | (1 << 5) | (1 << 7); +#else + __DSB(); + cntfrq = 35000; + write_cntv_tval(cntfrq); + enable_cntv(); + __DSB(); + enable_cpu_timer_intr(rt_hw_cpu_id()); +#endif + + rt_hw_interrupt_install(IRQ_ARM_TIMER, rt_hw_timer_isr, RT_NULL, "tick"); + rt_hw_interrupt_umask(IRQ_ARM_TIMER); + return 0; +} +#ifdef RT_USING_SMP +extern void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler); + +void ipi_handler() +{ + rt_scheduler_ipi_handler(0,RT_NULL); +} +#endif +void vector_copy(void) +{ + rt_memcpy((void*)0x0, (void*)0x8000, 64); +} + +void idle_wfi(void) +{ + asm volatile ("wfi"); +} + +void rt_hw_board_init(void) +{ + /* initialize hardware interrupt */ + rt_hw_interrupt_init(); + vector_copy(); + rt_hw_vector_init(); + /* initialize uart */ + rt_hw_uart_init(); + /* initialize timer for os tick */ + rt_hw_timer_init(); + rt_thread_idle_sethook(idle_wfi); +#ifdef RT_USING_CONSOLE + /* set console device */ + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif /* RT_USING_CONSOLE */ +#ifdef RT_USING_HEAP + /* initialize memory system */ + rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); + rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); +#endif + +#ifdef RT_USING_SMP + /* install IPI handle */ + rt_hw_ipi_handler_install(IRQ_ARM_MAILBOX, ipi_handler); + rt_hw_interrupt_umask(IRQ_ARM_MAILBOX); + enable_cpu_ipi_intr(0); +#endif +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + +} + + +void _reset(void); +void secondary_cpu_start(void); + +#ifdef RT_USING_SMP +void rt_hw_secondary_cpu_up(void) +{ + int i; + int retry,val; + rt_cpu_dcache_clean_flush(); + rt_cpu_icache_flush(); + /*TODO maybe, there is some bug */ + for (i = RT_CPUS_NR - 1; i>0; i-- ) + { + rt_kprintf("boot cpu:%d\n", i); + setup_bootstrap_addr(i, (int)_reset); + __SEV(); + __DSB(); + __ISB(); + retry = 10; + rt_thread_delay(RT_TICK_PER_SECOND/1000); + do + { + val = CORE_MAILBOX3_CLEAR(i); + if (val == 0) + { + rt_kprintf("start OK: CPU %d \n",i); + break; + } + rt_thread_delay(RT_TICK_PER_SECOND); + + retry --; + if (retry <= 0) + { + rt_kprintf("can't start for CPU %d \n",i); + break; + } + } while (1); + } + __DSB(); + __SEV(); +} + +void secondary_cpu_c_start(void) +{ + uint32_t id; + id = rt_hw_cpu_id(); + rt_kprintf("cpu = 0x%08x\n",id); + rt_hw_timer_init(); + rt_kprintf("cpu %d startup.\n",id); + rt_hw_vector_init(); + enable_cpu_ipi_intr(id); + rt_hw_spin_lock(&_cpus_lock); + rt_system_scheduler_start(); +} + +void rt_hw_secondary_cpu_idle_exec(void) +{ + __WFE(); +} + +#endif + + diff --git a/bsp/raspberry-pi/raspi3-32/driver/board.h b/bsp/raspberry-pi/raspi3-32/driver/board.h new file mode 100644 index 0000000000000000000000000000000000000000..8736027c0625e947c565e89efcb3139beaa671f4 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/board.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 Bernard the first version + */ + +#ifndef BOARD_H__ +#define BOARD_H__ + +#include + +#include +#include "raspi.h" + +#define __REG32 HWREG32 +extern unsigned char __bss_start; +extern unsigned char __bss_end; + +#define RT_HW_HEAP_BEGIN (void*)&__bss_end +#define RT_HW_HEAP_END (void*)(RT_HW_HEAP_BEGIN + 4 * 1024 * 1024) + +void rt_hw_board_init(void); + +#endif + diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_fb.c b/bsp/raspberry-pi/raspi3-32/driver/drv_fb.c new file mode 100644 index 0000000000000000000000000000000000000000..a24ca6337724b300fed2aa19bd14f0f714c3ac40 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_fb.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-29 zdzn first version + */ + +#include +#include +#include "mbox.h" +#include "drv_fb.h" +#include "mmu.h" + +#define CHAR_W 8 +#define CHAR_H 12 + +#define COLOR_DELTA 0.05 +static struct rt_hdmi_fb_device _hdmi; + +// https://github.com/xinu-os/xinu/blob/1789b7a50b5b73c2ea76ebd764c54a034097d04d/device/framebuffer_rpi/font.c +unsigned char FONT[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*'!'*/ +0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'"'*/ +0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00, 0x00, 0x00, /*'#'*/ +0x00, 0x00, 0x08, 0x3c, 0x0a, 0x1c, 0x28, 0x1e, 0x08, 0x00, 0x00, 0x00, /*'$'*/ +0x00, 0x00, 0x06, 0x26, 0x10, 0x08, 0x04, 0x32, 0x30, 0x00, 0x00, 0x00, /*'%'*/ +0x00, 0x00, 0x1c, 0x02, 0x02, 0x04, 0x2a, 0x12, 0x2c, 0x00, 0x00, 0x00, /*'&'*/ +0x00, 0x18, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'''*/ +0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, /*'('*/ +0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x00, /*')'*/ +0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, /*'*'*/ +0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /*'+'*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /*','*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'-'*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /*'.'*/ +0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /*'/'*/ +0x00, 0x1c, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'0'*/ +0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'1'*/ +0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'2'*/ +0x00, 0x1c, 0x22, 0x20, 0x18, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'3'*/ +0x00, 0x10, 0x18, 0x18, 0x14, 0x14, 0x3e, 0x10, 0x38, 0x00, 0x00, 0x00, /*'4'*/ +0x00, 0x3e, 0x02, 0x02, 0x1e, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'5'*/ +0x00, 0x18, 0x04, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'6'*/ +0x00, 0x3e, 0x22, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, /*'7'*/ +0x00, 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'8'*/ +0x00, 0x1c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x10, 0x0c, 0x00, 0x00, 0x00, /*'9'*/ +0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /*':'*/ +0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /*';'*/ +0x00, 0x00, 0x00, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, /*'<'*/ +0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, /*'='*/ +0x00, 0x00, 0x00, 0x03, 0x0c, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, /*'>'*/ +0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*'?'*/ +0x00, 0x00, 0x1c, 0x22, 0x3a, 0x3a, 0x1a, 0x02, 0x1c, 0x00, 0x00, 0x00, /*'@'*/ +0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x00, 0x00, 0x00, /*'A'*/ +0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /*'B'*/ +0x00, 0x00, 0x1c, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'C'*/ +0x00, 0x00, 0x0e, 0x12, 0x22, 0x22, 0x22, 0x12, 0x0e, 0x00, 0x00, 0x00, /*'D'*/ +0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'E'*/ +0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'F'*/ +0x00, 0x00, 0x1c, 0x22, 0x02, 0x32, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /*'G'*/ +0x00, 0x00, 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'H'*/ +0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, /*'I'*/ +0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'J'*/ +0x00, 0x00, 0x22, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /*'K'*/ +0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'L'*/ +0x00, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'M'*/ +0x00, 0x00, 0x22, 0x26, 0x26, 0x2a, 0x32, 0x32, 0x22, 0x00, 0x00, 0x00, /*'N'*/ +0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'O'*/ +0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'P'*/ +0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x30, 0x00, 0x00, /*'Q'*/ +0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /*'R'*/ +0x00, 0x00, 0x1c, 0x22, 0x02, 0x1c, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'S'*/ +0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'T'*/ +0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'U'*/ +0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /*'V'*/ +0x00, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, 0x00, 0x00, 0x00, /*'W'*/ +0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00, 0x00, /*'X'*/ +0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'Y'*/ +0x00, 0x00, 0x3e, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'Z'*/ +0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, /*'['*/ +0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, /*'\'*/ +0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, /*']'*/ +0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'^'*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, /*'_'*/ +0x00, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'`'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /*'a'*/ +0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /*'b'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, /*'c'*/ +0x00, 0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /*'d'*/ +0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x02, 0x1c, 0x00, 0x00, 0x00, /*'e'*/ +0x00, 0x38, 0x04, 0x04, 0x1e, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, /*'f'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /*'g'*/ +0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'h'*/ +0x00, 0x08, 0x08, 0x00, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /*'i'*/ +0x00, 0x10, 0x10, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, /*'j'*/ +0x00, 0x02, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x00, 0x00, 0x00, /*'k'*/ +0x00, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /*'l'*/ +0x00, 0x00, 0x00, 0x00, 0x16, 0x2a, 0x2a, 0x2a, 0x22, 0x00, 0x00, 0x00, /*'m'*/ +0x00, 0x00, 0x00, 0x00, 0x1a, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'n'*/ +0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'o'*/ +0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, /*'p'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, /*'q'*/ +0x00, 0x00, 0x00, 0x00, 0x1a, 0x06, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'r'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x1c, 0x20, 0x1e, 0x00, 0x00, 0x00, /*'s'*/ +0x00, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, /*'t'*/ +0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /*'u'*/ +0x00, 0x00, 0x00, 0x00, 0x36, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /*'v'*/ +0x00, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x2a, 0x14, 0x00, 0x00, 0x00, /*'w'*/ +0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, /*'x'*/ +0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /*'y'*/ +0x00, 0x00, 0x00, 0x00, 0x3e, 0x10, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00, /*'z'*/ +0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, /*'{'*/ +0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /*'|'*/ +0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, /*'}'*/ +0x00, 0x04, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'~'*/ +0x00, 0x00, 0x00, 0x08, 0x08, 0x14, 0x14, 0x22, 0x3e, 0x00, 0x00, 0x00, /*DEL*/ +}; + +void newline(fb_t* fb) +{ + uint8_t* to; + uint8_t* from; + int i; + fb->y++; + fb->x = 0; + + if (fb->y == (fb->height / CHAR_H)) + { + + to = (uint8_t*) fb->addr; + from = to + (CHAR_H * fb->pitch); + + for (i = 0; i < ((fb->height - CHAR_H) * fb->pitch); i++) + { + *to++ = *from++; + } + + uint32_t *addr = (uint32_t*) (fb->addr) + (fb->height - CHAR_H) * fb->width; + + for (i = 0; i < (CHAR_H * fb->width); i++) + { + *addr++ = fb->back; + } + + fb->y--; + } +} + +void clear_line(fb_t *fb, const int line) +{ + int i; + uint32_t* addr; + if (line > fb->height / CHAR_H) + { + fb->y = 0; + } + else + { + fb->y = line; + } + + fb->x = 0; + + addr = (uint32_t*) (fb->addr + (line * CHAR_H * fb->depth * fb->width)); + for (i = 0; i < (CHAR_H * fb->width); i++) + { + *addr++ = fb->back; + } + +} + +void clear(fb_t *fb, const uint32_t color) +{ + + uint32_t *addr = (uint32_t*) fb->addr; + uint32_t i; + for (i = 0; i < (fb->height * fb->width); i++) + { + *addr++ = color; + } + fb->x = 0; + fb->y = 0; + +} + +void fb_draw_char(fb_t *fb, char s) +{ + unsigned char* addr = (unsigned char*) fb->addr; + unsigned char *glyph = (unsigned char*) FONT + (s) * 12; + // calculate the offset on screen + int offs = (fb->y * CHAR_H * fb->pitch) + (fb->x * (CHAR_W + 1) * 4); + // variables + int i, j, line, mask, bytesperline = (CHAR_W + 7) / 8; + // display a character + for (j = 0; j < CHAR_H; j++) + { + // display one row + line = offs; + mask = 1; + for (i = 0; i < CHAR_W; i++) + { + // if bit set, we use white color, otherwise black + *((unsigned int*) (addr + line)) = ((int) *glyph) & mask ? fb->fore : fb->back; + mask <<= 1; + line += 4; + } + // adjust to next line + glyph += bytesperline; + offs += fb->pitch; + } +} + +void fb_print(fb_t *fb, char *s) +{ + + // draw next character if it's not zero + while (*s) + { + // handle carrige return + if (*s == '\r') + { + fb->x = 0; + } + else if (*s == '\n') + { + newline(fb); + } + else if (*s == '\t') + { + fb->x = ((fb->x + 4) >> 2) << 2; + } + else if (*s == '\b') + { + if (fb->x) + { + fb->x--; + fb_draw_char(fb, ' '); + } + } + else + { + fb_draw_char(fb, *s); + fb->x++; + } + // next character + if (fb->x == fb->width / CHAR_W) + { + newline(fb); + } + s++; + } +} + +rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +rt_err_t hdmi_fb_close(rt_device_t dev) +{ + return RT_EOK; +} + +rt_size_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size) +{ + return 0; +} + +rt_size_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + fb_print(&_hdmi.fb, (char *) buffer); +#ifdef BSP_USING_HDMI_DISPLAY + rt_device_t uart = rt_device_find("uart1"); + int old_flag = uart->open_flag; + uart->open_flag |= RT_DEVICE_FLAG_STREAM; + rt_device_write(uart, 0, buffer, size); + uart->open_flag = old_flag; +#endif + return size; +} + +rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args) +{ + return RT_EOK; +} + +const static struct rt_device_ops hdmi_fb_ops = +{ + RT_NULL, + hdmi_fb_open, + hdmi_fb_close, + hdmi_fb_read, + hdmi_fb_write, + hdmi_fb_control +}; + +static struct rt_device_graphic_info _hdmi_info; + +static void hdmi_draw_rect(const char* pixel, int x1, int y1, int x2, int y2) +{ + int i, j; + int line; + for (j = y1; j <= y2; j++) + { + line = (j * _hdmi.fb.pitch) + (x1 * 4); + for (i = x1; i <= x2; i++) + { + // if bit set, we use white color, otherwise black + *((unsigned int*) (_hdmi_info.framebuffer + line)) = *(unsigned int*) pixel; + line += 4; + } + } + +} + +static void hdmi_set_pixel(const char* pixel, int x, int y) +{ + *(uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)) = *(uint32_t *) pixel; +} + +static void hdmi_get_pixel(char* pixel, int x, int y) +{ + uint32_t ret = 0; + ret = (*(uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)) & 0x00FFFFFF); + *pixel = ret; +} + +static void hdmi_draw_hline(const char* pixel, int x1, int x2, int y) +{ + hdmi_draw_rect(pixel, x1, y, x2, y); +} + +static void hdmi_draw_vline(const char* pixel, int x, int y1, int y2) +{ + hdmi_draw_rect(pixel, x, y1, x, y2); +} + +static void hdmi_blit_line(const char* pixels, int x, int y, rt_size_t size) +{ + int i = 0; + uint32_t *pixel_base = (uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)); + uint32_t *colors = (uint32_t *) pixels; + for (i = 0; i < size; i++) + { + pixel_base[i] = colors[i]; + } +} + +static struct rt_device_graphic_ops hdmi_ops = +{ + hdmi_set_pixel, + hdmi_get_pixel, + hdmi_draw_hline, + hdmi_draw_vline, + hdmi_blit_line +}; + +rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name) +{ + struct rt_device *device; + RT_ASSERT(hdmi_fb != RT_NULL); + + device = &hdmi_fb->parent; + device->user_data = &hdmi_ops; + + /* set device type */ + device->type = RT_Device_Class_Graphic; + /* initialize device interface */ +#ifdef RT_USING_DEVICE_OPS + device->ops = &hdmi_fb_ops; +#else + device->init = RT_NULL; + device->open = hdmi_fb_open; + device->close = hdmi_fb_close; + device->read = hdmi_fb_read; + device->write = hdmi_fb_write; + device->control = hdmi_fb_control; +#endif + + /* register to device manager */ + rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); + + return RT_EOK; +} + +/** + * Show a picture + */ +void print_fb_info() +{ + rt_kprintf("FrameBuffer Info: \n \t width %x\t height %x\t depth %x\t addr %x\t size %x\t \n", fb_info.width, + fb_info.height, fb_info.depth, fb_info.addr, fb_info.size); + rt_kprintf("call mbox:%x,%x,%x,%x,%x\n", mbox[0], mbox[1], mbox[2], mbox[3], mbox[4]); +} + +void hdmi_fb_init() +{ + unsigned int *mbox = (unsigned int*) MBOX_ADDR; + mbox[0] = 35 * 4; + mbox[1] = MBOX_REQUEST; + + mbox[2] = 0x48003; //set phy wh + mbox[3] = 8; + mbox[4] = 8; + mbox[5] = 640; //FrameBufferInfo.width + mbox[6] = 480; //FrameBufferInfo.height + + mbox[7] = 0x48004; //set virt wh + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = 640; //FrameBufferInfo.virtual_width + mbox[11] = 480; //FrameBufferInfo.virtual_height + + mbox[12] = 0x48009; //set virt offset + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = 0; //FrameBufferInfo.x_offset + mbox[16] = 0; //FrameBufferInfo.y.offset + + mbox[17] = 0x48005; //set depth + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = 32; //FrameBufferInfo.depth + + mbox[21] = 0x48006; //set pixel order + mbox[22] = 4; + mbox[23] = 4; + mbox[24] = 1; //RGB, not BGR preferably + + mbox[25] = 0x40001; //get framebuffer, gets alignment on request + mbox[26] = 8; + mbox[27] = 8; + mbox[28] = 4096; //FrameBufferInfo.pointer + mbox[29] = 0; //FrameBufferInfo.size + + mbox[30] = 0x40008; //get pitch + mbox[31] = 4; + mbox[32] = 4; + mbox[33] = 0; //FrameBufferInfo.pitch + + mbox[34] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP, MMU_DISABLE) && mbox[20] == 32 && mbox[28] != 0) + { + mbox[28] &= 0x3FFFFFFF; + _hdmi.fb.width = mbox[5]; + _hdmi.fb.height = mbox[6]; + _hdmi.fb.pitch = mbox[33]; + //_hdmi.fb.addr = (void*)((unsigned long)mbox[28]); + _hdmi.fb.addr = (rt_uint32_t) mbox[28]; + _hdmi.fb.size = mbox[29]; + _hdmi.fb.depth = 32; + _hdmi.fb.x = 0; + _hdmi.fb.y = 0; + _hdmi.fb.fore = CONSOLE_WHITE; + _hdmi.fb.back = CONSOLE_BLACK; + rt_hdmi_fb_device_init(&_hdmi, "hdmi"); + rt_hw_change_mmu_table(_hdmi.fb.addr, _hdmi.fb.size, _hdmi.fb.addr, DEVICE_MEM); + fb_info.width = _hdmi.fb.width; + fb_info.height = _hdmi.fb.height; + fb_info.addr = _hdmi.fb.addr; + fb_info.size = _hdmi.fb.size; + fb_info.pitch = _hdmi.fb.pitch; + fb_info.depth = _hdmi.fb.depth; + _hdmi_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888; + _hdmi_info.bits_per_pixel = _hdmi.fb.depth; + _hdmi_info.width = _hdmi.fb.width; + _hdmi_info.height = _hdmi.fb.height; + _hdmi_info.framebuffer = (rt_uint8_t *) _hdmi.fb.addr; + } +} + +INIT_DEVICE_EXPORT(hdmi_fb_init); diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_fb.h b/bsp/raspberry-pi/raspi3-32/driver/drv_fb.h new file mode 100644 index 0000000000000000000000000000000000000000..b11589e769d1a02d1f3e245061513e0efbdfa74d --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_fb.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-29 zdzn first version + */ +#ifndef __DRV_FB_H__ +#define __DRV_FB_H__ + +#define RGB(r, g, b) ((((r))<<16) | (((g))<<8) | ((b))) + +#define COLOR_BLACK RGB(0, 0, 0) + +#define COLOR_GREEN RGB(0, 255, 0) + +#define COLOR_CYAN RGB(0, 255, 255) + +#define COLOR_RED RGB(255, 0, 0) + +#define COLOR_YELLOW RGB(255, 255, 0) + +#define COLOR_WHITE RGB(255, 255, 255) + +#define CONSOLE_WHITE COLOR_WHITE +#define CONSOLE_BLACK COLOR_BLACK +#define CONSOLE_GREEN COLOR_GREEN +#define CONSOLE_CYAN COLOR_CYAN +#define CONSOLE_RED COLOR_RED +#define CONSOLE_YELLOW COLOR_YELLOW + +typedef struct +{ + rt_uint32_t width; + rt_uint32_t height; + rt_uint32_t vwidth; + rt_uint32_t vheight; + rt_uint32_t pitch; + rt_uint32_t depth; + rt_uint32_t fore; + rt_uint32_t back; + rt_uint32_t x; + rt_uint32_t y; + rt_uint32_t addr; + rt_uint32_t size; +} fb_t; + +struct rt_hdmi_fb_device +{ + struct rt_device parent; + fb_t fb; +}; + +fb_t fb_info; +void print_fb_info(); +void hdmi_fb_init(); + +#endif/* __DRV_FB_H__ */ diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_gpio.c b/bsp/raspberry-pi/raspi3-32/driver/drv_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..c239c56cf28baae35192044076c27fc72a02dc76 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_gpio.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include "drv_gpio.h" + +#ifdef BSP_USING_PIN +/* + * gpio_int[0] for BANK0 (pins 0-27) + * gpio_int[1] for BANK1 (pins 28-45) + * gpio_int[2] for BANK2 (pins 46-53) + */ +static struct gpio_irq_def _g_gpio_irq_tbl[GPIO_IRQ_NUM]; + +void gpio_set_pud(rt_uint8_t pin, rt_uint8_t pud) +{ + rt_uint8_t num = pin / 32; + rt_uint8_t shift = pin % 32; + BCM283X_GPIO_GPPUD = pud; + DELAY_MICROS(10); + BCM283X_GPIO_GPPUDCLK(num) = 1 << shift; + DELAY_MICROS(10); + BCM283X_GPIO_GPPUD = BCM283X_GPIO_PUD_OFF; + BCM283X_GPIO_GPPUDCLK(num) = 0 << shift; +} + +static void gpio_ack_irq(int irq, bcm_gpio_pin pin) +{ + rt_uint32_t data; + data = IRQ_PEND2; + data &= (0x0 << (irq - 32)); + IRQ_PEND2 = data; + + data = IRQ_DISABLE2; + data |= (0x1 << (irq - 32)); + IRQ_DISABLE2 = data; +} + +void gpio_irq_disable(rt_uint8_t index, bcm_gpio_pin pin) +{ + int irq = 0; + rt_uint32_t reg_value; + rt_uint8_t irq_type; + irq = IRQ_GPIO0 + index; + + gpio_ack_irq(irq, pin); + + irq_type = _g_gpio_irq_tbl[index].irq_type[pin]; + rt_uint8_t shift = pin % 32; + rt_uint32_t mask = 1 << shift; + + switch (irq_type) + { + case PIN_IRQ_MODE_RISING: + reg_value = BCM283X_GPIO_GPREN(pin /32); + BCM283X_GPIO_GPREN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask); + break; + case PIN_IRQ_MODE_FALLING: + reg_value = BCM283X_GPIO_GPFEN(pin /32); + BCM283X_GPIO_GPFEN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask); + break; + case PIN_IRQ_MODE_RISING_FALLING: + reg_value = BCM283X_GPIO_GPAREN(pin /32); + BCM283X_GPIO_GPAREN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask); + reg_value = BCM283X_GPIO_GPAFEN(pin /32); + BCM283X_GPIO_GPAFEN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask); + break; + case PIN_IRQ_MODE_HIGH_LEVEL: + reg_value = BCM283X_GPIO_GPHEN(pin /32); + BCM283X_GPIO_GPHEN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask); + break; + case PIN_IRQ_MODE_LOW_LEVEL: + reg_value = BCM283X_GPIO_GPLEN(pin /32); + BCM283X_GPIO_GPLEN(pin /32) = (reg_value & ~ mask) | (PIN_LOW & mask); + break; + } +} + +void gpio_irq_enable(rt_uint8_t index, bcm_gpio_pin pin) +{ + rt_uint32_t offset; + rt_uint32_t data; + + offset = pin; + if (index == 0) + offset = IRQ_GPIO0 - 32; + else if (index == 1) + offset = IRQ_GPIO1 - 32; + else + offset = IRQ_GPIO2 - 32; + + data = IRQ_ENABLE2; + data |= 0x1 << offset; + IRQ_ENABLE2 = data; + +} + +static void raspi_pin_mode(struct rt_device *dev, rt_base_t pin, rt_base_t mode) +{ + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL)); + RT_ASSERT(!(mode & 0x8)); + + switch (mode) + { + case PIN_MODE_OUTPUT: + GPIO_FSEL(pin, BCM283X_GPIO_FSEL_OUTP); + break; + case PIN_MODE_INPUT: + GPIO_FSEL(pin, BCM283X_GPIO_FSEL_INPT); + break; + case PIN_MODE_INPUT_PULLUP: + gpio_set_pud(pin, BCM283X_GPIO_PUD_UP); + GPIO_FSEL(pin, BCM283X_GPIO_FSEL_INPT); + break; + case PIN_MODE_INPUT_PULLDOWN: + gpio_set_pud(pin, BCM283X_GPIO_PUD_DOWN); + GPIO_FSEL(pin, BCM283X_GPIO_FSEL_INPT); + break; + case PIN_MODE_OUTPUT_OD: + gpio_set_pud(pin, BCM283X_GPIO_PUD_OFF); + GPIO_FSEL(pin, BCM283X_GPIO_FSEL_OUTP); + break; + } +} + +static void raspi_pin_write(struct rt_device *dev, rt_base_t pin, rt_base_t value) +{ + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL)); + RT_ASSERT(!(value & 0xE)); + + if (value) + BCM283X_GPIO_GPSET(pin / 32) |= (1 << (pin %32)); + else + BCM283X_GPIO_GPCLR(pin / 32) |= (0 << (pin %32)); + +} + +static int raspi_pin_read(struct rt_device *device, rt_base_t pin) +{ + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL)); + return (BCM2835_GPIO_GPLEV(pin / 32) & (1 << (pin % 32)))? PIN_HIGH : PIN_LOW; +} + +static rt_err_t raspi_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) +{ + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL)); + + rt_uint8_t index; + rt_uint32_t reg_value; + if (pin <= 27) + index = 0; + else if (pin <= 45) + index = 1; + else + index = 2; + _g_gpio_irq_tbl[index].irq_cb[pin] = hdr; + _g_gpio_irq_tbl[index].irq_arg[pin] = args; + _g_gpio_irq_tbl[index].irq_type[pin] = mode; + + rt_uint8_t shift = pin % 32; + rt_uint32_t mask = 1 << shift; + + switch (mode) + { + case PIN_IRQ_MODE_RISING: + reg_value = BCM283X_GPIO_GPREN(pin /32); + BCM283X_GPIO_GPREN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask); + break; + case PIN_IRQ_MODE_FALLING: + reg_value = BCM283X_GPIO_GPFEN(pin /32); + BCM283X_GPIO_GPFEN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask); + break; + case PIN_IRQ_MODE_RISING_FALLING: + reg_value = BCM283X_GPIO_GPAREN(pin /32); + BCM283X_GPIO_GPAREN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask); + reg_value = BCM283X_GPIO_GPAFEN(pin /32); + BCM283X_GPIO_GPAFEN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask); + break; + case PIN_IRQ_MODE_HIGH_LEVEL: + reg_value = BCM283X_GPIO_GPHEN(pin /32); + BCM283X_GPIO_GPHEN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask); + break; + case PIN_IRQ_MODE_LOW_LEVEL: + reg_value = BCM283X_GPIO_GPLEN(pin /32); + BCM283X_GPIO_GPLEN(pin /32) = (reg_value & ~ mask) | (PIN_HIGH & mask); + break; + } + return RT_EOK; +} + +static rt_err_t raspi_pin_detach_irq(struct rt_device *device, rt_int32_t pin) +{ + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL)); + + rt_uint8_t index; + if (pin <= 27) + index = 0; + else if (pin <= 45) + index = 1; + else + index = 2; + + gpio_irq_disable(index, pin); + + _g_gpio_irq_tbl[index].irq_cb[pin] = RT_NULL; + _g_gpio_irq_tbl[index].irq_arg[pin] = RT_NULL; + _g_gpio_irq_tbl[index].irq_type[pin] = RT_NULL; + + return RT_EOK; +} + +rt_err_t raspi_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) +{ + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_NULL)); + + rt_uint8_t index; + if (pin <= 27) + index = 0; + else if (pin <= 45) + index = 1; + else + index = 2; + + if (enabled) + gpio_irq_enable(index, pin); + else + gpio_irq_disable(index, pin); + + return RT_EOK; +} + +static void gpio_irq_handler(int irq, void *param) +{ + struct gpio_irq_def *irq_def = (struct gpio_irq_def *)param; + rt_uint32_t pin; + rt_uint32_t value; + rt_uint32_t tmpvalue; + + if (irq == IRQ_GPIO0) + { + /* 0~27 */ + + value = BCM283X_GPIO_GPEDS(0); + value &= 0x0fffffff; + pin = 0; + BCM283X_GPIO_GPEDS(0) = 0; + } + else if (irq == IRQ_GPIO1) + { + /* 28-45 */ + tmpvalue = BCM283X_GPIO_GPEDS(0); + tmpvalue &= (~0x0fffffff); + + value = BCM283X_GPIO_GPEDS(1); + value &= 0x3fff; + value = (value<<4) | tmpvalue; + pin = 28; + BCM283X_GPIO_GPEDS(0) = 0; + BCM283X_GPIO_GPEDS(1) = 0; + } + else if (irq == IRQ_GPIO2) + { + /* 46-53 */ + value = BCM283X_GPIO_GPEDS(1); + value &= (~0x3fff); + value &= 0xff600000; + pin = 46; + BCM283X_GPIO_GPEDS(1) = 0; + } + + while (value) + { + if ((value & 0x1) && (irq_def->irq_cb[pin] != RT_NULL)) + { + irq_def->irq_cb[pin](irq_def->irq_arg[pin]); + gpio_ack_irq(irq,pin); + } + pin++; + value = value >> 1; + } +} + +static const struct rt_pin_ops ops = +{ + raspi_pin_mode, + raspi_pin_write, + raspi_pin_read, + raspi_pin_attach_irq, + raspi_pin_detach_irq, + raspi_pin_irq_enable, +}; +#endif + +int rt_hw_gpio_init(void) +{ +#ifdef BSP_USING_PIN + rt_device_pin_register("gpio", &ops, RT_NULL); + + /* install ISR */ + rt_hw_interrupt_install(IRQ_GPIO0, gpio_irq_handler, &_g_gpio_irq_tbl[0], "gpio0_irq"); + rt_hw_interrupt_umask(IRQ_GPIO0); + + rt_hw_interrupt_install(IRQ_GPIO1, gpio_irq_handler, &_g_gpio_irq_tbl[1], "gpio1_irq"); + rt_hw_interrupt_umask(IRQ_GPIO1); + + rt_hw_interrupt_install(IRQ_GPIO2, gpio_irq_handler, &_g_gpio_irq_tbl[2], "gpio2_irq"); + rt_hw_interrupt_umask(IRQ_GPIO2); +#endif + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_gpio_init); diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_gpio.h b/bsp/raspberry-pi/raspi3-32/driver/drv_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..ce0be096e84969de771ae7806ae1f573677e1237 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_gpio.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_GPIO_H__ +#define __DRV_GPIO_H__ + +#include +#include + +#include "interrupt.h" +#include "board.h" + +#define GPIO_IRQ_NUM 3 + +#define IRQ_GPIO0 49 +#define IRQ_GPIO1 50 +#define IRQ_GPIO2 51 +#define IRQ_GPIO3 52 + +struct gpio_irq_def +{ + void *irq_arg[32]; + void (*irq_cb[32])(void *param); + rt_uint8_t irq_type[32]; +}; + +enum gpio_irq_clock +{ + GPIO_IRQ_LOSC_32KHZ = 0, + GPIO_IRQ_HOSC_24MHZ +}; + +int rt_hw_gpio_init(void); + +#endif /* __DRV_GPIO_H__ */ diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_i2c.c b/bsp/raspberry-pi/raspi3-32/driver/drv_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..35ab7c36d7367e75e4187adc57a14ef2aa78ad3c --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_i2c.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include "drv_i2c.h" + +//Maybe redefined +typedef unsigned long rt_ubase_t; +typedef rt_ubase_t rt_size_t; + +rt_uint8_t i2c_read_or_write(volatile rt_uint32_t base, rt_uint8_t* buf, rt_uint32_t len, rt_uint8_t flag) +{ + rt_uint32_t status; + rt_uint32_t remaining = len; + rt_uint32_t i = 0; + rt_uint8_t reason = BCM283X_I2C_REASON_OK; + + /* Clear FIFO */ + BCM283X_BSC_C(base) |= (BSC_C_CLEAR_1 & BSC_C_CLEAR_1); + /* Clear Status */ + BCM283X_BSC_S(base) = BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE; + /* Set Data Length */ + BCM283X_BSC_DLEN(base) = len; + if (flag) + { + /* Start read */ + BCM283X_BSC_C(base) = BSC_C_I2CEN | BSC_C_ST | BSC_C_READ; + /* wait for transfer to complete */ + while (!(BCM283X_BSC_S(base) & BSC_S_DONE)) + { + /* we must empty the FIFO as it is populated and not use any delay */ + while (remaining && (BCM283X_BSC_S(base) & BSC_S_RXD)) + { + /* Read from FIFO, no barrier */ + buf[i] = BCM283X_BSC_FIFO(base); + i++; + remaining--; + } + } + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (BCM283X_BSC_S(base) & BSC_S_RXD)) + { + /* Read from FIFO, no barrier */ + buf[i] = BCM283X_BSC_FIFO(base); + i++; + remaining--; + } + } + else + { + /* pre populate FIFO with max buffer */ + while (remaining && (i < BSC_FIFO_SIZE)) + { + BCM283X_BSC_FIFO(base) = buf[i]; + i++; + remaining--; + } + + /* Enable device and start transfer */ + BCM283X_BSC_C(base) = BSC_C_I2CEN | BSC_C_ST; + + /* Transfer is over when BCM2835_BSC_S_DONE */ + while (!(BCM283X_BSC_S(base) & BSC_S_DONE)) + { + while (remaining && (BCM283X_BSC_S(base) & BSC_S_TXD)) + { + /* Write to FIFO */ + BCM283X_BSC_FIFO(base) = buf[i]; + i++; + remaining--; + } + } + } + + status = BCM283X_BSC_S(base); + if (status & BSC_S_ERR) + { + reason = BCM283X_I2C_REASON_ERROR_NACK; + } + else if (status & BSC_S_CLKT) + { + reason = BCM283X_I2C_REASON_ERROR_CLKT; + } + else if (remaining) + { + reason = BCM283X_I2C_REASON_ERROR_DATA; + } + BCM283X_BSC_C(base) |= (BSC_S_DONE & BSC_S_DONE); + + return reason; +} + +struct raspi_i2c_hw_config +{ + rt_uint8_t bsc_num; + rt_uint8_t sdl_pin; + rt_uint8_t scl_pin; + rt_uint8_t sdl_mode; + rt_uint8_t scl_mode; +}; + +#if (defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1)) + +static rt_size_t raspi_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_size_t raspi_i2c_slv_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_err_t raspi_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t, + rt_uint32_t); + +static rt_uint32_t i2c_byte_wait_us = 0; +static rt_size_t raspi_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + rt_size_t i; + rt_uint8_t reason; + RT_ASSERT(bus != RT_NULL); + + volatile rt_uint32_t base = (volatile rt_uint32_t)(bus->parent.user_data); + + if (bus->addr == 0) + base = BCM283X_BSC0_BASE; + else + base = BCM283X_BSC1_BASE; + + BCM283X_BSC_A(base) = msgs->addr; + + for (i = 0; i < num; i++) + { + if (msgs[i].flags & RT_I2C_RD) + reason = i2c_read_or_write(base, msgs->buf, msgs->len, 1); + else + reason = i2c_read_or_write(base, msgs->buf, msgs->len, 0); + } + return (reason == 0)? i : 0; +} + +static rt_size_t raspi_i2c_slv_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + return 0; +} +static rt_err_t raspi_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t cmd, + rt_uint32_t arg) +{ + return RT_EOK; +} + +static const struct rt_i2c_bus_device_ops raspi_i2c_ops = +{ + .master_xfer = raspi_i2c_mst_xfer, + .slave_xfer = raspi_i2c_slv_xfer, + .i2c_bus_control = raspi_i2c_bus_control, +}; + + +static rt_err_t raspi_i2c_configure(struct raspi_i2c_hw_config *cfg) +{ + RT_ASSERT(cfg != RT_NULL); + + volatile rt_uint32_t base = cfg->scl_mode ? BCM283X_BSC1_BASE : BCM283X_BSC0_BASE; + + GPIO_FSEL(cfg->sdl_pin, cfg->sdl_mode); /* SDA */ + GPIO_FSEL(cfg->scl_pin, cfg->scl_mode); /* SCL */ + + /* use 0xFFFE mask to limit a max value and round down any odd number */ + rt_uint32_t divider = (BCM283X_CORE_CLK_HZ / 10000) & 0xFFFE; + BCM283X_BSC_DIV(base) = (rt_uint16_t) divider; + i2c_byte_wait_us = (divider * 1000000 * 9 / BCM283X_CORE_CLK_HZ); + + return RT_EOK; +} +#endif + +#if defined (BSP_USING_I2C0) +#define I2C0_BUS_NAME "i2c0" +static struct raspi_i2c_hw_config hw_device0 = +{ + .bsc_num = 0, + .sdl_pin = RPI_GPIO_P1_27, + .scl_pin = RPI_GPIO_P1_28, + .sdl_mode = BCM283X_GPIO_FSEL_ALT0, + .scl_mode = BCM283X_GPIO_FSEL_ALT0, +}; + +struct rt_i2c_bus_device device0 = +{ + .ops = &raspi_i2c_ops, + .addr = 0, +}; + +#endif + +#if defined (BSP_USING_I2C1) +#define I2C1_BUS_NAME "i2c1" +static struct raspi_i2c_hw_config hw_device1 = +{ + .bsc_num = 1, + .sdl_pin = RPI_GPIO_P1_03, + .scl_pin = RPI_GPIO_P1_05, + .sdl_mode = BCM283X_GPIO_FSEL_ALT0, + .scl_mode = BCM283X_GPIO_FSEL_ALT0, +}; +struct rt_i2c_bus_device device1 = +{ + .ops = &raspi_i2c_ops, + .addr = 1, +}; + +#endif + +int rt_hw_i2c_init(void) +{ +#if defined(BSP_USING_I2C0) + raspi_i2c_configure(&hw_device0); + rt_i2c_bus_device_register(&device0, I2C0_BUS_NAME); +#endif + +#if defined(BSP_USING_I2C1) + raspi_i2c_configure(&hw_device1); + rt_i2c_bus_device_register(&device1, I2C1_BUS_NAME); +#endif + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_i2c_init); diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_i2c.h b/bsp/raspberry-pi/raspi3-32/driver/drv_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..ff9e8ca724721dc8b908669de0f69c7e9c535a23 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_i2c.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_I2C_H__ +#define __DRV_I2C_H__ + +#include +#include + +#include "board.h" + +struct raspi_master_config_t +{ + rt_uint8_t sdl_pin; + rt_uint8_t scl_pin; + rt_uint8_t sdl_pin_mode; + rt_uint8_t scl_pin_mode; + rt_uint8_t slave_address; + rt_uint32_t bsc_base; + rt_uint16_t clk_div; +}; + +struct raspi_i2c_bus +{ + struct rt_i2c_bus_device device; + struct rt_i2c_msg *msg; + rt_uint32_t msg_cnt; + volatile rt_uint32_t msg_ptr; + volatile rt_uint32_t dptr; + char *device_name; + struct raspi_master_config_t *cfg; +}; + +int rt_hw_i2c_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_rtc.c b/bsp/raspberry-pi/raspi3-32/driver/drv_rtc.c new file mode 100644 index 0000000000000000000000000000000000000000..8a33e2be644cadde09eb6c653be66dcab62625d2 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_rtc.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include "drv_rtc.h" + +#ifdef BSP_USING_RTC + +#define RTC_I2C_BUS_NAME "i2c0" +#define RTC_ADDR 0x68 + +static struct rt_device rtc_device; +static struct rt_i2c_bus_device *i2c_bus = RT_NULL; + +rt_uint8_t buf[]= +{ + 0x00, 0x00, 0x43, 0x15, 0x05, 0x01, 0x03, 0x19 +}; + + +rt_uint8_t i2c_write_read_rs(char* cmds, rt_uint32_t cmds_len, char* buf, rt_uint32_t buf_len) +{ + rt_uint32_t remaining = cmds_len; + rt_uint32_t i = 0; + rt_uint8_t reason = BCM283X_I2C_REASON_OK; + + /* Clear FIFO */ + BCM283X_BSC_C(BCM283X_BSC0_BASE) |= (BSC_C_CLEAR_1 & BSC_C_CLEAR_1); + + /* Clear Status */ + BCM283X_BSC_S(BCM283X_BSC0_BASE) = BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE; + + /* Set Data Length */ + BCM283X_BSC_DLEN(BCM283X_BSC0_BASE) = cmds_len; + + /* pre populate FIFO with max buffer */ + while (remaining && (i < BSC_FIFO_SIZE)) + { + BCM283X_BSC_FIFO(BCM283X_BSC0_BASE) = cmds[i]; + i++; + remaining--; + } + + /* Enable device and start transfer */ + BCM283X_BSC_C(BCM283X_BSC0_BASE) |= BSC_C_I2CEN | BSC_C_ST; + + /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ + while (!(BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_TA)) + { + /* Linux may cause us to miss entire transfer stage */ + if (BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_DONE) + break; + } + + remaining = buf_len; + i = 0; + + /* Send a repeated start with read bit set in address */ + BCM283X_BSC_DLEN(BCM283X_BSC0_BASE) = buf_len; + BCM283X_BSC_C(BCM283X_BSC0_BASE) = BSC_C_I2CEN | BSC_C_ST | BSC_C_READ; + + /* Wait for write to complete and first byte back. */ + // DELAYMICROS(i2c_byte_wait_us * (cmds_len + 1)); + + /* wait for transfer to complete */ + while (!(BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_DONE)) + { + /* we must empty the FIFO as it is populated and not use any delay */ + while (remaining && (BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_RXD)) + { + /* Read from FIFO, no barrier */ + buf[i] = BCM283X_BSC_FIFO(BCM283X_BSC0_BASE); + i++; + remaining--; + } + } + + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_RXD)) + { + /* Read from FIFO */ + buf[i] = BCM283X_BSC_FIFO(BCM283X_BSC0_BASE); + i++; + remaining--; + } + + /* Received a NACK */ + if (BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_ERR) + { + reason = BCM283X_I2C_REASON_ERROR_NACK; + } + + /* Received Clock Stretch Timeout */ + else if (BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_CLKT) + { + reason = BCM283X_I2C_REASON_ERROR_CLKT; + } + + /* Not all data is sent */ + else if (remaining) + { + reason = BCM283X_I2C_REASON_ERROR_DATA; + } + + BCM283X_BSC_C(BCM283X_BSC0_BASE) = (BSC_S_DONE &BSC_S_DONE); + + return reason; +} + +rt_uint8_t i2c_write(rt_uint8_t* buf, rt_uint32_t len) +{ + rt_uint32_t remaining = len; + rt_uint32_t i = 0; + rt_uint8_t reason = BCM283X_I2C_REASON_OK; + + /* Clear FIFO */ + BCM283X_BSC_C(BCM283X_BSC0_BASE) |= BSC_C_CLEAR_1 & BSC_C_CLEAR_1; + /* Clear Status */ + BCM283X_BSC_S(BCM283X_BSC0_BASE) = BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE; + /* Set Data Length */ + BCM283X_BSC_DLEN(BCM283X_BSC0_BASE) = len; + /* pre populate FIFO with max buffer */ + while (remaining && (i < BSC_FIFO_SIZE)) + { + BCM283X_BSC_FIFO(BCM283X_BSC0_BASE) = buf[i]; + i++; + remaining--; + } + + /* Enable device and start transfer */ + BCM283X_BSC_C(BCM283X_BSC0_BASE) = BSC_C_I2CEN | BSC_C_ST; + + /* Transfer is over when BCM2835_BSC_S_DONE */ + while (!(BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_DONE)) + { + while (remaining && (BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_TXD)) + { + /* Write to FIFO */ + BCM283X_BSC_FIFO(BCM283X_BSC0_BASE) = buf[i]; + i++; + remaining--; + } + } + + /* Received a NACK */ + if (BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_ERR) + { + reason = BCM283X_I2C_REASON_ERROR_NACK; + } + + /* Received Clock Stretch Timeout */ + else if (BCM283X_BSC_S(BCM283X_BSC0_BASE) & BSC_S_CLKT) + { + reason = BCM283X_I2C_REASON_ERROR_CLKT; + } + + /* Not all data is sent */ + else if (remaining) + { + reason = BCM283X_I2C_REASON_ERROR_DATA; + } + + BCM283X_BSC_C(BCM283X_BSC0_BASE) = BSC_S_DONE & BSC_S_DONE; + return reason; +} + + +static time_t raspi_get_timestamp(void) +{ + struct tm tm_new = {0}; + buf[0] = 0; + + i2c_write_read_rs((char*)buf, 1, (char*)buf, 7); + + tm_new.tm_year = ((buf[6] / 16) + 0x30) * 10 + (buf[6] % 16) + 0x30; + tm_new.tm_mon = ((buf[5] & 0x1F) / 16 + 0x30) + (buf[5] & 0x1F) % 16+ 0x30; + tm_new.tm_mday = ((buf[4] & 0x3F) / 16 + 0x30) + (buf[4] & 0x3F) % 16+ 0x30; + tm_new.tm_hour = ((buf[2] & 0x3F) / 16 + 0x30) + (buf[2] & 0x3F) % 16+ 0x30; + tm_new.tm_min = ((buf[1] & 0x7F) / 16 + 0x30) + (buf[1] & 0x7F) % 16+ 0x30; + tm_new.tm_sec = ((buf[0] & 0x7F) / 16 + 0x30) + (buf[0] & 0x7F) % 16+ 0x30; + + return mktime(&tm_new); +} + +static int raspi_set_timestamp(time_t timestamp) +{ + struct tm *tblock; + tblock = localtime(×tamp); + buf[0] = 0; + buf[1] = tblock->tm_sec; + buf[2] = tblock->tm_min; + buf[3] = tblock->tm_hour; + buf[4] = tblock->tm_wday; + buf[5] = tblock->tm_mday; + buf[6] = tblock->tm_mon; + buf[7] = tblock->tm_year; + + i2c_write(buf, 8); + + return RT_EOK; +} + +static rt_err_t raspi_rtc_init(rt_device_t dev) +{ + i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(RTC_I2C_BUS_NAME); + raspi_set_timestamp(0); + return RT_EOK; +} + +static rt_err_t raspi_rtc_open(rt_device_t dev, rt_uint16_t oflag) +{ + GPIO_FSEL(BCM_GPIO_PIN_0, BCM283X_GPIO_FSEL_ALT0); /* SDA */ + GPIO_FSEL(BCM_GPIO_PIN_1, BCM283X_GPIO_FSEL_ALT0); /* SCL */ + return RT_EOK; +} + +static rt_err_t raspi_rtc_close(rt_device_t dev) +{ + GPIO_FSEL(BCM_GPIO_PIN_0, BCM283X_GPIO_FSEL_INPT); /* SDA */ + GPIO_FSEL(BCM_GPIO_PIN_1, BCM283X_GPIO_FSEL_INPT); /* SCL */ + return RT_EOK; +} + +static rt_err_t raspi_rtc_control(rt_device_t dev, int cmd, void *args) +{ + + RT_ASSERT(dev != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + *(rt_uint32_t *)args = raspi_get_timestamp(); + break; + case RT_DEVICE_CTRL_RTC_SET_TIME: + raspi_set_timestamp(*(time_t *)args); + break; + default: + return RT_EINVAL; + } + return RT_EOK; +} + +static rt_size_t raspi_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + raspi_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer); + return size; +} + +static rt_size_t raspi_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + raspi_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer); + return size; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops raspi_rtc_ops = +{ + .init = raspi_rtc_init, + .open = raspi_rtc_open, + .close = raspi_rtc_close, + .read = raspi_rtc_read, + .write = raspi_rtc_write, + .control = raspi_rtc_control +}; +#endif + +int rt_hw_rtc_init(void) +{ + rt_err_t ret = RT_EOK; + + rtc_device.type = RT_Device_Class_RTC; + rtc_device.rx_indicate = RT_NULL; + rtc_device.tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + rtc_device.ops = &raspi_rtc_ops; +#else + rtc_device.init = raspi_rtc_init; + rtc_device.open = raspi_rtc_open; + rtc_device.close = raspi_rtc_close; + rtc_device.read = raspi_rtc_read; + rtc_device.write = raspi_rtc_write; + rtc_device.control = raspi_rtc_control; +#endif + + rtc_device.user_data = RT_NULL; + + /* register a rtc device */ + ret = rt_device_register(&rtc_device, "rtc", RT_DEVICE_FLAG_RDWR); + + return ret; +} +INIT_DEVICE_EXPORT(rt_hw_rtc_init); +#endif /* BSP_USING_RTC */ + diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_rtc.h b/bsp/raspberry-pi/raspi3-32/driver/drv_rtc.h new file mode 100644 index 0000000000000000000000000000000000000000..d850defa68e57c29b82bd4e55e9672fc83a033b4 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_rtc.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_RTC_H__ +#define __DRV_RTC_H__ + +#include +#include + +#include "board.h" + +int rt_hw_rtc_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_sdio.c b/bsp/raspberry-pi/raspi3-32/driver/drv_sdio.c new file mode 100644 index 0000000000000000000000000000000000000000..c547419ca245de92196e0776627502d28b702b51 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_sdio.c @@ -0,0 +1,580 @@ +/* + * File : drv_sdio.c + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include "drv_sdio.h" + +static rt_uint32_t sdCommandTable[] = { + SD_CMD_INDEX(0), + SD_CMD_RESERVED(1), + SD_CMD_INDEX(2) | SD_RESP_R2, + SD_CMD_INDEX(3) | SD_RESP_R1, + SD_CMD_INDEX(4), + SD_CMD_RESERVED(5), //SD_CMD_INDEX(5) | SD_RESP_R4, + SD_CMD_INDEX(6) | SD_RESP_R1, + SD_CMD_INDEX(7) | SD_RESP_R1b, + SD_CMD_INDEX(8) | SD_RESP_R1, + SD_CMD_INDEX(9) | SD_RESP_R2, + SD_CMD_INDEX(10) | SD_RESP_R2, + SD_CMD_INDEX(11) | SD_RESP_R1, + SD_CMD_INDEX(12) | SD_RESP_R1b | SD_CMD_TYPE_ABORT, + SD_CMD_INDEX(13) | SD_RESP_R1, + SD_CMD_RESERVED(14), + SD_CMD_INDEX(15), + SD_CMD_INDEX(16) | SD_RESP_R1, + SD_CMD_INDEX(17) | SD_RESP_R1 | SD_DATA_READ, + SD_CMD_INDEX(18) | SD_RESP_R1 | SD_DATA_READ | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN, + SD_CMD_INDEX(19) | SD_RESP_R1 | SD_DATA_READ, + SD_CMD_INDEX(20) | SD_RESP_R1b, + SD_CMD_RESERVED(21), + SD_CMD_RESERVED(22), + SD_CMD_INDEX(23) | SD_RESP_R1, + SD_CMD_INDEX(24) | SD_RESP_R1 | SD_DATA_WRITE, + SD_CMD_INDEX(25) | SD_RESP_R1 | SD_DATA_WRITE | SD_CMD_MULTI_BLOCK | SD_CMD_BLKCNT_EN, + SD_CMD_INDEX(26) | SD_RESP_R1 | SD_DATA_WRITE, //add + SD_CMD_INDEX(27) | SD_RESP_R1 | SD_DATA_WRITE, + SD_CMD_INDEX(28) | SD_RESP_R1b, + SD_CMD_INDEX(29) | SD_RESP_R1b, + SD_CMD_INDEX(30) | SD_RESP_R1 | SD_DATA_READ, + SD_CMD_RESERVED(31), + SD_CMD_INDEX(32) | SD_RESP_R1, + SD_CMD_INDEX(33) | SD_RESP_R1, + SD_CMD_RESERVED(34), + SD_CMD_INDEX(35) | SD_RESP_R1, //add + SD_CMD_INDEX(36) | SD_RESP_R1, //add + SD_CMD_RESERVED(37), + SD_CMD_INDEX(38) | SD_RESP_R1b, + SD_CMD_INDEX(39) | SD_RESP_R4, //add + SD_CMD_INDEX(40) | SD_RESP_R5, //add + SD_CMD_INDEX(41) | SD_RESP_R3, //add, mov from harbote + SD_CMD_RESERVED(42) | SD_RESP_R1, + SD_CMD_RESERVED(43), + SD_CMD_RESERVED(44), + SD_CMD_RESERVED(45), + SD_CMD_RESERVED(46), + SD_CMD_RESERVED(47), + SD_CMD_RESERVED(48), + SD_CMD_RESERVED(49), + SD_CMD_RESERVED(50), + SD_CMD_INDEX(51) | SD_RESP_R1 | SD_DATA_READ, + SD_CMD_RESERVED(52), + SD_CMD_RESERVED(53), + SD_CMD_RESERVED(54), + SD_CMD_INDEX(55) | SD_RESP_R3, + SD_CMD_INDEX(56) | SD_RESP_R1 | SD_CMD_ISDATA, + SD_CMD_RESERVED(57), + SD_CMD_RESERVED(58), + SD_CMD_RESERVED(59), + SD_CMD_RESERVED(60), + SD_CMD_RESERVED(61), + SD_CMD_RESERVED(62), + SD_CMD_RESERVED(63) +}; + +static inline rt_uint32_t read32(rt_uint32_t addr) +{ + return (*((volatile rt_uint32_t *)(addr))); +} + +static inline void write32(rt_uint32_t addr, rt_uint32_t value) +{ + *((volatile rt_uint32_t *)(addr)) = value; +} + +rt_err_t sd_int(struct sdhci_pdata_t * pdat, unsigned int mask) +{ + unsigned int r; + unsigned int m = mask | INT_ERROR_MASK; + int cnt = 1000000; + while (!(read32(pdat->virt + EMMC_INTERRUPT) & (m | INT_ERROR_MASK)) && cnt--) + DELAY_MICROS(1); + r = read32(pdat->virt + EMMC_INTERRUPT); + if (cnt <= 0 || (r & INT_CMD_TIMEOUT) || (r & INT_DATA_TIMEOUT)) + { + write32(pdat->virt + EMMC_INTERRUPT, r); + rt_kprintf("send cmd/data timeout wait for %x int: %x, status: %x\n",mask, r, read32(pdat->virt + EMMC_STATUS)); + return -RT_ETIMEOUT; + } + else if (r & INT_ERROR_MASK) + { + write32(pdat->virt + EMMC_INTERRUPT, r); + rt_kprintf("send cmd/data error %x -> %x\n",r, read32(pdat->virt + EMMC_INTERRUPT)); + return -RT_ERROR; + } + write32(pdat->virt + EMMC_INTERRUPT, mask); + return RT_EOK; +} + +rt_err_t sd_status(struct sdhci_pdata_t * pdat, unsigned int mask) +{ + int cnt = 500000; + while ((read32(pdat->virt + EMMC_STATUS) & mask) && !(read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) && cnt--) + DELAY_MICROS(1); + if (cnt <= 0) + { + return -RT_ETIMEOUT; + } + else if (read32(pdat->virt + EMMC_INTERRUPT) & INT_ERROR_MASK) + return -RT_ERROR; + return RT_EOK; +} + +static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd) +{ + + rt_uint32_t cmdidx; + rt_err_t ret = RT_EOK; + ret = sd_status(pdat, SR_CMD_INHIBIT); + if (ret) + { + rt_kprintf("ERROR: EMMC busy %d\n", ret); + return ret; + } + + cmdidx = sdCommandTable[cmd->cmdidx]; + if (cmdidx == 0xFFFFFFFF) + return -RT_EINVAL; + if (cmd->datarw == DATA_READ) + cmdidx |= SD_DATA_READ; + if (cmd->datarw == DATA_WRITE) + cmdidx |= SD_DATA_WRITE; + mmcsd_dbg("transfer cmd %x(%d) %x %x\n", cmdidx, cmd->cmdidx, cmd->cmdarg, read32(pdat->virt + EMMC_INTERRUPT)); + write32(pdat->virt + EMMC_INTERRUPT,read32(pdat->virt + EMMC_INTERRUPT)); + write32(pdat->virt + EMMC_ARG1, cmd->cmdarg); + write32(pdat->virt + EMMC_CMDTM, cmdidx); + if (cmd->cmdidx == SD_APP_OP_COND) + DELAY_MICROS(1000); + else if ((cmd->cmdidx == SD_SEND_IF_COND) || (cmd->cmdidx == APP_CMD)) + DELAY_MICROS(100); + ret = sd_int(pdat, INT_CMD_DONE); + if (ret) + { + return ret; + } + if (cmd->resptype & RESP_MASK) + { + + if (cmd->resptype & RESP_R2) + { + rt_uint32_t resp[4]; + resp[0] = read32(pdat->virt + EMMC_RESP0); + resp[1] = read32(pdat->virt + EMMC_RESP1); + resp[2] = read32(pdat->virt + EMMC_RESP2); + resp[3] = read32(pdat->virt + EMMC_RESP3); + if (cmd->resptype == RESP_R2) + { + cmd->response[0] = resp[3]<<8 |((resp[2]>>24)&0xff); + cmd->response[1] = resp[2]<<8 |((resp[1]>>24)&0xff); + cmd->response[2] = resp[1]<<8 |((resp[0]>>24)&0xff); + cmd->response[3] = resp[0]<<8 ; + } + else + { + cmd->response[0] = resp[0]; + cmd->response[1] = resp[1]; + cmd->response[2] = resp[2]; + cmd->response[3] = resp[3]; + } + } + else + cmd->response[0] = read32(pdat->virt + EMMC_RESP0); + } + mmcsd_dbg("response: %x: %x %x %x %x (%x, %x)\n", cmd->resptype, cmd->response[0], cmd->response[1], cmd->response[2], cmd->response[3], read32(pdat->virt + EMMC_STATUS),read32(pdat->virt + EMMC_INTERRUPT)); + return ret; +} + +static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize) +{ + int c = 0; + rt_err_t ret; + int d; + while (c < blkcount) + { + if ((ret = sd_int(pdat, INT_READ_RDY))) + { + rt_kprintf("timeout happens when reading block %d\n",c); + return ret; + } + for (d=0; d < blksize / 4; d++) + if (read32(pdat->virt + EMMC_STATUS) & SR_READ_AVAILABLE) + buf[d] = read32(pdat->virt + EMMC_DATA); + c++; + buf += blksize / 4; + } + return RT_EOK; +} + +static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize) +{ + int c = 0; + rt_err_t ret; + int d; + while (c < blkcount) + { + if ((ret = sd_int(pdat, INT_WRITE_RDY))) + { + return ret; + } + for (d=0; d < blksize / 4; d++) + write32(pdat->virt + EMMC_DATA, buf[d]); + c++; + buf += blksize / 4; + } + if ((ret = sd_int(pdat, INT_DATA_DONE))) + { + return ret; + } + return RT_EOK; +} + +static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat) +{ + rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz); + rt_err_t ret = sd_status(pdat, SR_DAT_INHIBIT); + if (ret) + { + rt_kprintf("ERROR: EMMC busy\n"); + return ret; + } + if (dat->blkcnt > 1) + { + struct sdhci_cmd_t newcmd; + newcmd.cmdidx = SET_BLOCK_COUNT; + newcmd.cmdarg = dat->blkcnt; + newcmd.resptype = RESP_R1; + ret = raspi_transfer_command(pdat, &newcmd); + if (ret) return ret; + } + write32(pdat->virt + EMMC_BLKSIZECNT, dlen | 1 << 16); + + if (dat->flag & DATA_DIR_READ) + { + cmd->datarw = DATA_READ; + ret = raspi_transfer_command(pdat, cmd); + if (ret) return ret; + mmcsd_dbg("read_block %d, %d\n", dat->blkcnt, dat->blksz ); + ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz); + } + else if (dat->flag & DATA_DIR_WRITE) + { + cmd->datarw = DATA_WRITE; + ret = raspi_transfer_command(pdat, cmd); + if (ret) return ret; + mmcsd_dbg("write_block %d, %d", dat->blkcnt, dat->blksz ); + ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz); + } + return ret; +} + +static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat) +{ + struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv; + + if (!dat) + return raspi_transfer_command(pdat, cmd); + + return raspi_transfer_data(pdat, cmd, dat); +} + +static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req) +{ + struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data; + struct sdhci_cmd_t cmd; + struct sdhci_cmd_t stop; + struct sdhci_data_t dat; + + rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t)); + rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t)); + rt_memset(&dat, 0, sizeof(struct sdhci_data_t)); + + cmd.cmdidx = req->cmd->cmd_code; + cmd.cmdarg = req->cmd->arg; + cmd.resptype =resp_type(req->cmd); + if (req->data) + { + dat.buf = (rt_uint8_t *)req->data->buf; + dat.flag = req->data->flags; + dat.blksz = req->data->blksize; + dat.blkcnt = req->data->blks; + + req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat); + } + else + { + req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL); + } + + req->cmd->resp[3] = cmd.response[3]; + req->cmd->resp[2] = cmd.response[2]; + req->cmd->resp[1] = cmd.response[1]; + req->cmd->resp[0] = cmd.response[0]; + + if (req->stop) + { + stop.cmdidx = req->stop->cmd_code; + stop.cmdarg = req->stop->arg; + cmd.resptype =resp_type(req->stop); + req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL); + } + + mmcsd_req_complete(host); +} + +rt_int32_t mmc_card_status(struct rt_mmcsd_host *host) +{ + return 0; +} + +void mmc_enable_irq(struct rt_mmcsd_host *host, rt_int32_t en) +{ + +} + +static rt_err_t sdhci_detect(struct sdhci_t * sdhci) +{ + return RT_EOK; +} + +static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width) +{ + rt_uint32_t temp = 0; + struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv; + if (width == MMCSD_BUS_WIDTH_4) + { + temp = read32((pdat->virt + EMMC_CONTROL0)); + temp |= C0_HCTL_HS_EN; + temp |= C0_HCTL_DWITDH; // always use 4 data lines: + write32((pdat->virt + EMMC_CONTROL0), temp); + } + return RT_EOK; +} + +static rt_uint32_t sdhci_getdivider(rt_uint32_t sdHostVer, rt_uint32_t freq) +{ + rt_uint32_t divisor; + rt_uint32_t closest = 41666666 / freq; + rt_uint32_t shiftcount = __rt_fls(closest - 1); + + + if (shiftcount > 0) shiftcount--; + if (shiftcount > 7) shiftcount = 7; + if (sdHostVer > HOST_SPEC_V2) + divisor = closest; + else + divisor = (1 << shiftcount); + + if (divisor <= 2) + { + divisor = 2; + shiftcount = 0; + } + + rt_uint32_t hi = 0; + if (sdHostVer > HOST_SPEC_V2) + hi = (divisor & 0x300) >> 2; + rt_uint32_t lo = (divisor & 0x0ff); + rt_uint32_t cdiv = (lo << 8) + hi; + return cdiv; +} + +static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock) +{ + rt_uint32_t temp = 0; + rt_uint32_t sdHostVer = 0; + int count = 100000; + struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)(sdhci->priv); + + while ((read32(pdat->virt + EMMC_STATUS) & (SR_CMD_INHIBIT | SR_DAT_INHIBIT)) && (--count)) + DELAY_MICROS(1); + if (count <= 0) + { + rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n",read32(pdat->virt + EMMC_STATUS)); + return RT_ERROR; + } + + // Switch clock off. + temp = read32((pdat->virt + EMMC_CONTROL1)); + temp &= ~C1_CLK_EN; + write32((pdat->virt + EMMC_CONTROL1),temp); + DELAY_MICROS(10); + // Request the new clock setting and enable the clock + temp = read32(pdat->virt + EMMC_SLOTISR_VER); + sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT; + int cdiv = sdhci_getdivider(sdHostVer, clock); + temp = read32((pdat->virt + EMMC_CONTROL1)); + temp = (temp & 0xffff003f) | cdiv; + write32((pdat->virt + EMMC_CONTROL1),temp); + DELAY_MICROS(10); + + // Enable the clock. + temp = read32(pdat->virt + EMMC_CONTROL1); + temp |= C1_CLK_EN; + write32((pdat->virt + EMMC_CONTROL1),temp); + DELAY_MICROS(10); + // Wait for clock to be stable. + count = 10000; + while (!(read32(pdat->virt + EMMC_CONTROL1) & C1_CLK_STABLE) && count--) + DELAY_MICROS(10); + if (count <= 0) + { + rt_kprintf("EMMC: ERROR: failed to get stable clock %d.\n", clock); + return RT_ERROR; + } + mmcsd_dbg("set stable clock %d.\n", clock); + return RT_EOK; +} + +static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg) +{ + struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data; + sdhci_setclock(sdhci, io_cfg->clock); + sdhci_setwidth(sdhci, io_cfg->bus_width); +} + +static const struct rt_mmcsd_host_ops ops = +{ + mmc_request_send, + mmc_set_iocfg, + RT_NULL, + RT_NULL, +}; + +static void sdmmc_gpio_init() +{ +// int pin; +// bcm283x_gpio_fsel(47,BCM283X_GPIO_FSEL_INPT); +// bcm283x_gpio_set_pud(47, BCM283X_GPIO_PUD_UP); +// bcm283x_peri_set_bits(BCM283X_GPIO_BASE + BCM283X_GPIO_GPHEN1, 1<<15, 1<<15); +// for (pin = 53; pin >= 48; pin--) +// { +// bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_ALT3); +// bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP); +// } +} + +static rt_err_t reset_emmc(struct sdhci_pdata_t * pdat){ + rt_uint32_t temp; + int cnt; + write32((pdat->virt + EMMC_CONTROL0),0); + temp = read32((pdat->virt + EMMC_CONTROL1)); + temp |= C1_SRST_HC; + write32((pdat->virt + EMMC_CONTROL1),temp); + cnt = 10000; + do + { + DELAY_MICROS(10); + } + while ((read32((pdat->virt + EMMC_CONTROL1)) & C1_SRST_HC) && cnt--); + + if (cnt <= 0) + { + rt_kprintf("ERROR: failed to reset EMMC\n"); + return RT_ERROR; + } + temp = read32((pdat->virt + EMMC_CONTROL1)); + temp |= C1_CLK_INTLEN | C1_TOUNIT_MAX; + write32((pdat->virt + EMMC_CONTROL1),temp); + DELAY_MICROS(10); + return RT_EOK; +} + +#ifdef RT_MMCSD_DBG +void dump_registers(struct sdhci_pdata_t * pdat){ + rt_kprintf("EMMC registers:"); + int i = EMMC_ARG2; + for (; i <= EMMC_CONTROL2; i += 4) + rt_kprintf("\t%x:%x\n", i, read32(pdat->virt + i)); + rt_kprintf("\t%x:%x\n", 0x50, read32(pdat->virt + 0x50)); + rt_kprintf("\t%x:%x\n", 0x70, read32(pdat->virt + 0x70)); + rt_kprintf("\t%x:%x\n", 0x74, read32(pdat->virt + 0x74)); + rt_kprintf("\t%x:%x\n", 0x80, read32(pdat->virt + 0x80)); + rt_kprintf("\t%x:%x\n", 0x84, read32(pdat->virt + 0x84)); + rt_kprintf("\t%x:%x\n", 0x88, read32(pdat->virt + 0x88)); + rt_kprintf("\t%x:%x\n", 0x8c, read32(pdat->virt + 0x8c)); + rt_kprintf("\t%x:%x\n", 0x90, read32(pdat->virt + 0x90)); + rt_kprintf("\t%x:%x\n", 0xf0, read32(pdat->virt + 0xf0)); + rt_kprintf("\t%x:%x\n", 0xfc, read32(pdat->virt + 0xfc)); +} +#endif + +int raspi_sdmmc_init(void) +{ + rt_uint32_t virt; + struct rt_mmcsd_host * host = RT_NULL; + struct sdhci_pdata_t * pdat = RT_NULL; + struct sdhci_t * sdhci = RT_NULL; + +#ifdef BSP_USING_SDIO0 + host = mmcsd_alloc_host(); + if (!host) + { + rt_kprintf("alloc host failed"); + goto err; + } + + sdhci = rt_malloc(sizeof(struct sdhci_t)); + if (!sdhci) + { + rt_kprintf("alloc sdhci failed"); + goto err; + } + rt_memset(sdhci, 0, sizeof(struct sdhci_t)); + + sdmmc_gpio_init(); + + virt = MMC0_BASE_ADDR; + + pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t)); + RT_ASSERT(pdat != RT_NULL); + + pdat->virt = (rt_uint32_t)virt; + reset_emmc(pdat); + + sdhci->name = "sd0"; + sdhci->voltages = VDD_33_34; + sdhci->width = MMCSD_BUSWIDTH_4; + sdhci->clock = 200 * 1000 * 1000; + sdhci->removeable = RT_TRUE; + + sdhci->detect = sdhci_detect; + sdhci->setwidth = sdhci_setwidth; + sdhci->setclock = sdhci_setclock; + sdhci->transfer = sdhci_transfer; + sdhci->priv = pdat; + + host->ops = &ops; + host->freq_min = 400000; + host->freq_max = 50000000; + host->valid_ocr = VDD_32_33 | VDD_33_34; + host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4; + host->max_seg_size = 2048; + host->max_dma_segs = 10; + host->max_blk_size = 512; + host->max_blk_count = 4096; + + host->private_data = sdhci; + + write32((pdat->virt + EMMC_IRPT_EN),0xffffffff); + write32((pdat->virt + EMMC_IRPT_MASK),0xffffffff); +#ifdef RT_MMCSD_DBG + dump_registers(pdat); +#endif + mmcsd_change(host); +#endif + return RT_EOK; + +err: + if (host) rt_free(host); + if (sdhci) rt_free(sdhci); + + return -RT_EIO; +} + +INIT_DEVICE_EXPORT(raspi_sdmmc_init); diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_sdio.h b/bsp/raspberry-pi/raspi3-32/driver/drv_sdio.h new file mode 100644 index 0000000000000000000000000000000000000000..5c052de90a54df9d96f396f497a73f79c516dfc4 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_sdio.h @@ -0,0 +1,253 @@ +/* + * File : drv_sdio.h + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_SDIO_H__ +#define __DRV_SDIO_H__ + +#include +#include +#include + +#include "board.h" + +#define MMC0_BASE_ADDR 0x3F300000 + +/* Struct for Intrrrupt Information */ +#define SDXC_CmdDone BIT(0) +#define SDXC_DataDone BIT(1) +#define SDXC_BlockGap BIT(2) +#define SDXC_WriteRdy BIT(4) +#define SDXC_ReadRdy BIT(5) +#define SDXC_Card BIT(8) +#define SDXC_Retune BIT(12) +#define SDXC_BootAck BIT(13) +#define SDXC_EndBoot BIT(14) +#define SDXC_Err BIT(15) +#define SDXC_CTOErr BIT(16) +#define SDXC_CCRCErr BIT(17) +#define SDXC_CENDErr BIT(18) +#define SDXC_CBADErr BIT(19) +#define SDXC_DTOErr BIT(20) +#define SDXC_DCRCErr BIT(21) +#define SDXC_DENDErr BIT(22) +#define SDXC_ACMDErr BIT(24) + +#define SDXC_BLKCNT_EN BIT(1) +#define SDXC_AUTO_CMD12_EN BIT(2) +#define SDXC_AUTO_CMD23_EN BIT(3) +#define SDXC_DAT_DIR BIT(4) //from card to host +#define SDXC_MULTI_BLOCK BIT(5) +#define SDXC_CMD_RSPNS_136 BIT(16) +#define SDXC_CMD_RSPNS_48 BIT(17) +#define SDXC_CMD_RSPNS_48busy BIT(16)|BIT(17) +#define SDXC_CHECK_CRC_CMD BIT(19) +#define SDXC_CMD_IXCHK_EN BIT(20) +#define SDXC_CMD_ISDATA BIT(21) +#define SDXC_CMD_SUSPEND BIT(22) +#define SDXC_CMD_RESUME BIT(23) +#define SDXC_CMD_ABORT BIT(23)|BIT(22) + +#define SDXC_CMD_INHIBIT BIT(0) +#define SDXC_DAT_INHIBIT BIT(1) +#define SDXC_DAT_ACTIVE BIT(2) +#define SDXC_WRITE_TRANSFER BIT(8) +#define SDXC_READ_TRANSFER BIT(9) + +struct sdhci_cmd_t +{ + rt_uint32_t cmdidx; + rt_uint32_t cmdarg; + rt_uint32_t resptype; + rt_uint32_t datarw; +#define DATA_READ 1 +#define DATA_WRITE 2 + rt_uint32_t response[4]; +}; + +struct sdhci_data_t +{ + rt_uint8_t * buf; + rt_uint32_t flag; + rt_uint32_t blksz; + rt_uint32_t blkcnt; +}; + +struct sdhci_t +{ + char * name; + rt_uint32_t voltages; + rt_uint32_t width; + rt_uint32_t clock; + rt_err_t removeable; + void * sdcard; + + rt_err_t (*detect)(struct sdhci_t * sdhci); + rt_err_t (*setwidth)(struct sdhci_t * sdhci, rt_uint32_t width); + rt_err_t (*setclock)(struct sdhci_t * sdhci, rt_uint32_t clock); + rt_err_t (*transfer)(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat); + void * priv; +}; + +struct sdhci_pdata_t +{ + rt_uint32_t virt; +}; + +// EMMC command flags +#define CMD_TYPE_NORMAL 0x00000000 +#define CMD_TYPE_SUSPEND 0x00400000 +#define CMD_TYPE_RESUME 0x00800000 +#define CMD_TYPE_ABORT 0x00c00000 +#define CMD_IS_DATA 0x00200000 +#define CMD_IXCHK_EN 0x00100000 +#define CMD_CRCCHK_EN 0x00080000 +#define CMD_RSPNS_NO 0x00000000 +#define CMD_RSPNS_136 0x00010000 +#define CMD_RSPNS_48 0x00020000 +#define CMD_RSPNS_48B 0x00030000 +#define TM_MULTI_BLOCK 0x00000020 +#define TM_DAT_DIR_HC 0x00000000 +#define TM_DAT_DIR_CH 0x00000010 +#define TM_AUTO_CMD23 0x00000008 +#define TM_AUTO_CMD12 0x00000004 +#define TM_BLKCNT_EN 0x00000002 +#define TM_MULTI_DATA (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN) + +#define RCA_NO 1 +#define RCA_YES 2 + +// INTERRUPT register settings +#define INT_AUTO_ERROR 0x01000000 +#define INT_DATA_END_ERR 0x00400000 +#define INT_DATA_CRC_ERR 0x00200000 +#define INT_DATA_TIMEOUT 0x00100000 +#define INT_INDEX_ERROR 0x00080000 +#define INT_END_ERROR 0x00040000 +#define INT_CRC_ERROR 0x00020000 +#define INT_CMD_TIMEOUT 0x00010000 +#define INT_ERR 0x00008000 +#define INT_ENDBOOT 0x00004000 +#define INT_BOOTACK 0x00002000 +#define INT_RETUNE 0x00001000 +#define INT_CARD 0x00000100 +#define INT_READ_RDY 0x00000020 +#define INT_WRITE_RDY 0x00000010 +#define INT_BLOCK_GAP 0x00000004 +#define INT_DATA_DONE 0x00000002 +#define INT_CMD_DONE 0x00000001 +#define INT_ERROR_MASK (INT_CRC_ERROR|INT_END_ERROR|INT_INDEX_ERROR| \ + INT_DATA_TIMEOUT|INT_DATA_CRC_ERR|INT_DATA_END_ERR| \ + INT_ERR|INT_AUTO_ERROR) +#define INT_ALL_MASK (INT_CMD_DONE|INT_DATA_DONE|INT_READ_RDY|INT_WRITE_RDY|INT_ERROR_MASK) + +#define EMMC_ARG2 (0x00) +#define EMMC_BLKSIZECNT (0x04) +#define EMMC_ARG1 (0x08) +#define EMMC_CMDTM (0x0c) +#define EMMC_RESP0 (0x10) +#define EMMC_RESP1 (0x14) +#define EMMC_RESP2 (0x18) +#define EMMC_RESP3 (0x1c) +#define EMMC_DATA (0x20) +#define EMMC_STATUS (0x24) +#define EMMC_CONTROL0 (0x28) +#define EMMC_CONTROL1 (0x2c) +#define EMMC_INTERRUPT (0x30) +#define EMMC_IRPT_MASK (0x34) +#define EMMC_IRPT_EN (0x38) +#define EMMC_CONTROL2 (0x3c) +#define EMMC_BOOT_TIMEOUT (0x70) +#define EMMC_EXRDFIFO_EN (0x84) +#define EMMC_SPI_INT_SPT (0xf0) +#define EMMC_SLOTISR_VER (0xfc) + +// CONTROL register settings +#define C0_SPI_MODE_EN 0x00100000 +#define C0_HCTL_HS_EN 0x00000004 +#define C0_HCTL_DWITDH 0x00000002 + +#define C1_SRST_DATA 0x04000000 +#define C1_SRST_CMD 0x02000000 +#define C1_SRST_HC 0x01000000 +#define C1_TOUNIT_DIS 0x000f0000 +#define C1_TOUNIT_MAX 0x000e0000 +#define C1_CLK_GENSEL 0x00000020 +#define C1_CLK_EN 0x00000004 +#define C1_CLK_STABLE 0x00000002 +#define C1_CLK_INTLEN 0x00000001 + +#define FREQ_SETUP 400000 // 400 Khz +#define FREQ_NORMAL 25000000 // 25 Mhz + +// SLOTISR_VER values +#define HOST_SPEC_NUM 0x00ff0000 +#define HOST_SPEC_NUM_SHIFT 16 +#define HOST_SPEC_V3 2 +#define HOST_SPEC_V2 1 +#define HOST_SPEC_V1 0 + +// STATUS register settings +#define SR_DAT_LEVEL1 0x1e000000 +#define SR_CMD_LEVEL 0x01000000 +#define SR_DAT_LEVEL0 0x00f00000 +#define SR_DAT3 0x00800000 +#define SR_DAT2 0x00400000 +#define SR_DAT1 0x00200000 +#define SR_DAT0 0x00100000 +#define SR_WRITE_PROT 0x00080000 // From SDHC spec v2, BCM says reserved +#define SR_READ_AVAILABLE 0x00000800 // ???? undocumented +#define SR_WRITE_AVAILABLE 0x00000400 // ???? undocumented +#define SR_READ_TRANSFER 0x00000200 +#define SR_WRITE_TRANSFER 0x00000100 +#define SR_DAT_ACTIVE 0x00000004 +#define SR_DAT_INHIBIT 0x00000002 +#define SR_CMD_INHIBIT 0x00000001 + +#define CONFIG_MMC_USE_DMA +#define DMA_ALIGN (32U) + +#define SD_CMD_INDEX(a) ((a) << 24) +#define SD_CMD_RESERVED(a) 0xffffffff +#define SD_CMD_INDEX(a) ((a) << 24) +#define SD_CMD_TYPE_NORMAL 0x0 +#define SD_CMD_TYPE_SUSPEND (1 << 22) +#define SD_CMD_TYPE_RESUME (2 << 22) +#define SD_CMD_TYPE_ABORT (3 << 22) +#define SD_CMD_TYPE_MASK (3 << 22) +#define SD_CMD_ISDATA (1 << 21) +#define SD_CMD_IXCHK_EN (1 << 20) +#define SD_CMD_CRCCHK_EN (1 << 19) +#define SD_CMD_RSPNS_TYPE_NONE 0 // For no response +#define SD_CMD_RSPNS_TYPE_136 (1 << 16) // For response R2 (with CRC), R3,4 (no CRC) +#define SD_CMD_RSPNS_TYPE_48 (2 << 16) // For responses R1, R5, R6, R7 (with CRC) +#define SD_CMD_RSPNS_TYPE_48B (3 << 16) // For responses R1b, R5b (with CRC) +#define SD_CMD_RSPNS_TYPE_MASK (3 << 16) +#define SD_CMD_MULTI_BLOCK (1 << 5) +#define SD_CMD_DAT_DIR_HC 0 +#define SD_CMD_DAT_DIR_CH (1 << 4) +#define SD_CMD_AUTO_CMD_EN_NONE 0 +#define SD_CMD_AUTO_CMD_EN_CMD12 (1 << 2) +#define SD_CMD_AUTO_CMD_EN_CMD23 (2 << 2) +#define SD_CMD_BLKCNT_EN (1 << 1) +#define SD_CMD_DMA 1 +#define SD_RESP_NONE SD_CMD_RSPNS_TYPE_NONE +#define SD_RESP_R1 (SD_CMD_RSPNS_TYPE_48) // | SD_CMD_CRCCHK_EN) +#define SD_RESP_R1b (SD_CMD_RSPNS_TYPE_48B) // | SD_CMD_CRCCHK_EN) +#define SD_RESP_R2 (SD_CMD_RSPNS_TYPE_136) //| SD_CMD_CRCCHK_EN) +#define SD_RESP_R3 SD_CMD_RSPNS_TYPE_48 +#define SD_RESP_R4 SD_CMD_RSPNS_TYPE_136 +#define SD_RESP_R5 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) +#define SD_RESP_R5b (SD_CMD_RSPNS_TYPE_48B | SD_CMD_CRCCHK_EN) +#define SD_RESP_R6 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) +#define SD_RESP_R7 (SD_CMD_RSPNS_TYPE_48 | SD_CMD_CRCCHK_EN) +#define SD_DATA_READ (SD_CMD_ISDATA | SD_CMD_DAT_DIR_CH) +#define SD_DATA_WRITE (SD_CMD_ISDATA | SD_CMD_DAT_DIR_HC) +#endif diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_spi.c b/bsp/raspberry-pi/raspi3-32/driver/drv_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..32de9970e7276d4f3bb5a5139d394fbb8c5cb0b9 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_spi.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ +#include "drv_spi.h" + +#ifdef RT_USING_SPI + +#define RPI_CORE_CLK_HZ 250000000 +#define BSP_SPI_MAX_HZ (30* 1000 *1000) +#define SPITIMEOUT 0x0FFF + +void spi_gpio_write(rt_uint8_t pin, rt_uint8_t val) +{ + if (val) + BCM283X_GPIO_GPSET(pin / 32) = 1 << (pin % 32); + else + BCM283X_GPIO_GPCLR(pin / 32) = 0 << (pin % 32); +} + +struct raspi_spi_hw_config +{ + rt_uint8_t spi_num; + raspi_gpio_pin sclk_pin; + raspi_pin_select sclk_mode; + raspi_gpio_pin mosi_pin; + raspi_pin_select mosi_mode; + raspi_gpio_pin miso_pin; + raspi_pin_select miso_mode; +#if defined (BSP_USING_SPI0_DEVICE0) || defined (BSP_USING_SPI1_DEVICE0) + raspi_gpio_pin ce0_pin; + raspi_pin_select ce0_mode; +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) || defined (BSP_USING_SPI1_DEVICE1) + raspi_gpio_pin ce1_pin; + raspi_pin_select ce1_mode; +#endif + +#if defined (BSP_USING_SPI1_DEVICE2) + raspi_gpio_pin ce2_pin; + raspi_pin_select ce2_mode; +#endif +}; + +struct raspi_spi_device +{ + char *device_name; + struct rt_spi_bus *spi_bus; + struct rt_spi_device *spi_device; + raspi_gpio_pin cs_pin; +}; + +static rt_err_t raspi_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg) +{ + RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(device != RT_NULL); + rt_uint16_t divider; + + // spi clear fifo + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CLEAR; + + if (cfg->mode & RT_SPI_CPOL) + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPOL; + + if (cfg->mode & RT_SPI_CPHA) + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPHA; + + if (cfg->mode & RT_SPI_CS_HIGH) + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CSPOL; + + //set clk + if (cfg->max_hz > BSP_SPI_MAX_HZ) + cfg->max_hz = BSP_SPI_MAX_HZ; + + divider = (rt_uint16_t) ((rt_uint32_t) RPI_CORE_CLK_HZ / cfg->max_hz); + divider &= 0xFFFE; + + BCM283X_SPI0_CLK(BCM283X_SPI0_BASE) = divider; + + return RT_EOK; +} + +rt_uint8_t correct_order(rt_uint8_t b, rt_uint8_t flag) +{ + if (flag) + return raspi_byte_reverse_table[b]; + else + return b; +} + +static rt_err_t spi_transfernb(rt_uint8_t* tbuf, rt_uint8_t* rbuf, rt_uint32_t len, rt_uint8_t flag) +{ + rt_uint32_t TXCnt=0; + rt_uint32_t RXCnt=0; + + /* Clear TX and RX fifos */ + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_CLEAR & BCM283X_SPI0_CS_CLEAR); + + /* Set TA = 1 */ + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_TA & BCM283X_SPI0_CS_TA); + + + /* Use the FIFO's to reduce the interbyte times */ + while ((TXCnt < len) || (RXCnt < len)) + { + /* TX fifo not full, so add some more bytes */ + while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_TXD)) && (TXCnt < len)) + { + BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE) = correct_order(tbuf[TXCnt],flag); + TXCnt++; + } + /* Rx fifo not empty, so get the next received bytes */ + while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_RXD)) && (RXCnt < len)) + { + rbuf[RXCnt] = correct_order(BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE),flag); + RXCnt++; + } + } + /* Wait for DONE to be set */ + while (!(BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_DONE)); + + /* Set TA = 0, and also set the barrier */ + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (0 & BCM283X_SPI0_CS_TA); + return RT_EOK; +} + +static rt_uint32_t raspi_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(device->parent.user_data != RT_NULL); + RT_ASSERT(message->send_buf != RT_NULL || message->recv_buf != RT_NULL); + + rt_err_t res; + rt_uint8_t flag; + struct rt_spi_configuration config = device->config; + raspi_gpio_pin cs_pin = (raspi_gpio_pin)device->parent.user_data; + + if (config.mode & RT_SPI_MSB) + flag = 0; + else + flag = 1; + + if (message->cs_take) + (config.mode & RT_SPI_CS_HIGH)? + spi_gpio_write(cs_pin, 1): + spi_gpio_write(cs_pin, 0); + + /* deal data */ + res = spi_transfernb((rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf, + (rt_int32_t)message->length, flag); + + if (message->cs_release) + (config.mode & RT_SPI_CS_HIGH)? + spi_gpio_write(cs_pin, 0): + spi_gpio_write(cs_pin, 1); + + if (res != RT_EOK) + return RT_ERROR; + + return message->length; +} + +rt_err_t raspi_spi_bus_attach_device(const char *bus_name, struct raspi_spi_device *device) +{ + rt_err_t ret; + RT_ASSERT(device != RT_NULL); + ret = rt_spi_bus_attach_device(device->spi_device, device->device_name, bus_name, (void *)(device->cs_pin)); + return ret; +} + +rt_err_t raspi_spi_hw_init(struct raspi_spi_hw_config *hwcfg) +{ + GPIO_FSEL(hwcfg->sclk_pin, hwcfg->sclk_mode); + GPIO_FSEL(hwcfg->miso_pin, hwcfg->miso_mode); + GPIO_FSEL(hwcfg->mosi_pin, hwcfg->mosi_mode); + +#if defined (BSP_USING_SPI0_DEVICE0) + GPIO_FSEL(hwcfg->ce0_pin, hwcfg->ce0_mode); +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) + GPIO_FSEL(hwcfg->ce1_pin, hwcfg->ce1_mode); +#endif + + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = 0; + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = BCM283X_SPI0_CS_CLEAR; + + //enable chip select +#if defined (BSP_USING_SPI0_DEVICE0) + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0; +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0x2; +#endif + +#if defined (BSP_USING_SPI0_DEVICE0) && defined (BSP_USING_SPI0_DEVICE1) + BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CS; +#endif + return RT_EOK; +} + +static struct rt_spi_ops raspi_spi_ops = +{ + .configure = raspi_spi_configure, + .xfer = raspi_spi_xfer +}; + +#if defined (BSP_USING_SPI0_BUS) +#define SPI0_BUS_NAME "spi0" +#define SPI0_DEVICE0_NAME "spi0.0" +#define SPI0_DEVICE1_NAME "spi0.1" + +struct rt_spi_bus spi0_bus; + +#if defined (BSP_USING_SPI0_DEVICE0) +struct rt_spi_device spi0_device0; +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) +static struct rt_spi_device spi0_device1; +#endif + +struct raspi_spi_hw_config raspi_spi0_hw = +{ + .spi_num = 0, + .sclk_pin = RPI_GPIO_P1_23, + .sclk_mode = BCM283X_GPIO_FSEL_ALT0, + .mosi_pin = RPI_GPIO_P1_19, + .mosi_mode = BCM283X_GPIO_FSEL_ALT0, + .miso_pin = RPI_GPIO_P1_21, + .miso_mode = BCM283X_GPIO_FSEL_ALT0, + +#if defined (BSP_USING_SPI0_DEVICE0) + .ce0_pin = RPI_GPIO_P1_24, + .ce0_mode = BCM283X_GPIO_FSEL_ALT0, +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) + .ce1_pin = RPI_GPIO_P1_26, + .ce1_mode = BCM283X_GPIO_FSEL_ALT0, +#endif +}; +#endif + +int rt_hw_spi_init(void) +{ + +#if defined (BSP_USING_SPI0_BUS) + raspi_spi_hw_init(&raspi_spi0_hw); + rt_spi_bus_register(&spi0_bus, SPI0_BUS_NAME, &raspi_spi_ops); + +#if defined (BSP_USING_SPI0_DEVICE0) + struct raspi_spi_device raspi_spi0_device0 = + { + .device_name = SPI0_DEVICE0_NAME, + .spi_bus = &spi0_bus, + .spi_device = &spi0_device0, + .cs_pin = raspi_spi0_hw.ce0_pin, + }; + raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device0); +#endif + +#if defined (BSP_USING_SPI0_DEVICE1) + struct raspi_spi_device raspi_spi0_device1 = + { + .device_name = SPI0_DEVICE1_NAME, + .spi_bus = &spi0_bus, + .spi_device = &spi0_device1, + .cs_pin = raspi_spi0_hw.ce1_pin, + }; + raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device1); +#endif +#endif + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_spi_init); + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_spi.h b/bsp/raspberry-pi/raspi3-32/driver/drv_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..9e4623b327909f16b2b9128b6e4320708b329a31 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_spi.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include +#include + +//#include +#include "board.h" + +#define SPI0_BASE_ADDR (PER_BASE + BCM283X_SPI0_BASE) + +static rt_uint8_t raspi_byte_reverse_table[] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +#define SPI_CORE_CLK 250000000U +#define SPI_CS 0x00 +#define SPI_CS_LEN_LONG (1 << 25) +#define SPI_CS_DMA_LEN (1 << 24) +#define SPI_CS_CSPOL2 (1 << 23) +#define SPI_CS_CSPOL1 (1 << 22) +#define SPI_CS_CSPOL0 (1 << 21) +#define SPI_CS_RXF (1 << 20) +#define SPI_CS_RXR (1 << 19) +#define SPI_CS_TXD (1 << 18) +#define SPI_CS_RXD (1 << 17) +#define SPI_CS_DONE (1 << 16) +#define SPI_CS_LEN (1 << 13) +#define SPI_CS_REN (1 << 12) +#define SPI_CS_ADCS (1 << 11) +#define SPI_CS_INTR (1 << 10) +#define SPI_CS_INTD (1 << 9) +#define SPI_CS_DMAEN (1 << 8) +#define SPI_CS_TA (1 << 7) +#define SPI_CS_CSPOL (1 << 6) +#define SPI_CS_CLEAR_RXFIFO (1 << 5) +#define SPI_CS_CLEAR_TXFIFO (1 << 4) +#define SPI_CS_CPOL (1 << 3) +#define SPI_CS_CPHA (1 << 2) +#define SPI_CS_MASK 0x3 +#define SPI_FIFO 0x04 +#define SPI_CLK 0x08 +#define SPI_CLK_MASK 0xffff +#define SPI_DLEN 0x0c +#define SPI_DLEN_MASK 0xffff +#define SPI_LTOH 0x10 +#define SPI_LTOH_MASK 0xf +#define SPI_DC 0x14 +#define SPI_DC_RPANIC_SHIFT 24 +#define SPI_DC_RPANIC_MASK (0xff << SPI_DC_RPANIC_SHIFT) +#define SPI_DC_RDREQ_SHIFT 16 +#define SPI_DC_RDREQ_MASK (0xff << SPI_DC_RDREQ_SHIFT) +#define SPI_DC_TPANIC_SHIFT 8 +#define SPI_DC_TPANIC_MASK (0xff << SPI_DC_TPANIC_SHIFT) +#define SPI_DC_TDREQ_SHIFT 0 +#define SPI_DC_TDREQ_MASK 0xff + +int rt_hw_spi_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_timer.c b/bsp/raspberry-pi/raspi3-32/driver/drv_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..36a4fd2bafe2f82e0197916268c2f83716ecbfe1 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_timer.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include "drv_timer.h" + +#ifdef BSP_USING_SYSTIMER + +static void raspi_systimer_init(rt_hwtimer_t *hwtimer, rt_uint32_t state) +{ + if (state == 0) + hwtimer->ops->stop(hwtimer); +} + +static rt_err_t raspi_systimer_start(rt_hwtimer_t *hwtimer, rt_uint32_t cnt, rt_hwtimer_mode_t mode) +{ + rt_err_t result = RT_EOK; + rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data; + int timer_id = timer->timer_id; + + if (mode == HWTIMER_MODE_PERIOD) + timer->cnt = cnt; + else + timer->cnt = 0; + + __sync_synchronize(); + if (timer_id == 1) + { + rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_1); + STIMER_C1 = STIMER_CLO + cnt; + } + else if (timer_id == 3) + { + rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_3); + STIMER_C3 = STIMER_CLO + cnt; + } + else + result = -RT_ERROR; + + __sync_synchronize(); + + return result; +} + +static void raspi_systimer_stop(rt_hwtimer_t *hwtimer) +{ + rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data; + int timer_id = timer->timer_id; + if (timer_id == 1) + rt_hw_interrupt_mask(IRQ_SYSTEM_TIMER_1); + else if (timer_id == 3) + rt_hw_interrupt_mask(IRQ_SYSTEM_TIMER_3); + +} + +static rt_err_t raspi_systimer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg) +{ + /* The frequency value is an immutable value. */ + if (cmd == HWTIMER_CTRL_FREQ_SET) + { + return RT_EOK; + } + else + { + return -RT_ENOSYS; + } +} + + +void rt_device_systimer_isr(int vector, void *param) +{ + + rt_hwtimer_t *hwtimer = (rt_hwtimer_t *) param; + rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data; + RT_ASSERT(timer != RT_NULL); + + int timer_id = timer->timer_id; + + __sync_synchronize(); + if (timer_id == 1) + { + STIMER_CS = 0x2; + STIMER_C1 = STIMER_CLO + timer->cnt; + } + else if (timer_id == 3) + { + STIMER_CS = 0x8; + STIMER_C3 = STIMER_CLO + timer->cnt; + } + __sync_synchronize(); + + rt_device_hwtimer_isr(hwtimer); +} + +static struct rt_hwtimer_device _hwtimer1; +static struct rt_hwtimer_device _hwtimer3; + +static rt_systimer_t _systimer1; +static rt_systimer_t _systimer3; + +const static struct rt_hwtimer_ops systimer_ops = +{ + raspi_systimer_init, + raspi_systimer_start, + raspi_systimer_stop, + RT_NULL, + raspi_systimer_ctrl +}; + +static const struct rt_hwtimer_info _info = +{ + 1000000, /* the maxinum count frequency can be set */ + 1000000, /* the maxinum count frequency can be set */ + 0xFFFFFFFF, /* the maximum counter value */ + HWTIMER_CNTMODE_UP /* count mode (inc/dec) */ +}; + +#endif + +int rt_hw_systimer_init(void) +{ + +#ifdef BSP_USING_SYSTIMER + +#ifdef RT_USING_SYSTIMER1 + _systimer1.timer_id =1; + _hwtimer1.ops = &systimer_ops; + _hwtimer1.info = &_info; + rt_device_hwtimer_register(&_hwtimer1, "timer1",&_systimer1); + rt_hw_interrupt_install(IRQ_SYSTEM_TIMER_1, rt_device_systimer_isr, &_hwtimer1, "systimer1"); + rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_1); +#endif + +#ifdef RT_USING_SYSTIMER3 + _systimer3.timer_id =3; + _hwtimer3.ops = &systimer_ops; + _hwtimer3.info = &_info; + rt_device_hwtimer_register(&_hwtimer3, "timer3",&_systimer3); + rt_hw_interrupt_install(IRQ_SYSTEM_TIMER_3, rt_device_systimer_isr, &_hwtimer3, "systimer3"); + rt_hw_interrupt_umask(IRQ_SYSTEM_TIMER_3); +#endif + +#endif + + return 0; +} + +INIT_DEVICE_EXPORT(rt_hw_systimer_init); diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_timer.h b/bsp/raspberry-pi/raspi3-32/driver/drv_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..c85d4c9d1f7a8c0b0ff386e87c5e2bb60b5cdef9 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_timer.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ +#ifndef __DRV_TIMER_H__ +#define __DRV_TIMER_H__ + +#include +#include + +#include "board.h" + +typedef struct rt_systimer_device +{ + int timer_id; + rt_uint32_t cnt; +} rt_systimer_t; + +int rt_hw_systimer_init(void); + + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_uart.c b/bsp/raspberry-pi/raspi3-32/driver/drv_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..18501b78491460ce9a4fc5669442618c38203418 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_uart.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/5/5 Bernard The first version + */ + +#include +#include +#include + +#include "board.h" +#include "drv_uart.h" + +#include + +#define AUX_BASE (0x3F000000 + 0x215000) + +struct hw_uart_device +{ + rt_uint32_t hw_base; + rt_uint32_t irqno; +}; + +static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + if (uart->hw_base == AUX_BASE) + { + rt_uint32_t value; + + /* GPIO function set */ + value = BCM283X_GPIO_GPFSEL(1); + value &= ~(7 << 12); /* GPIO14 */ + value |= 2 << 12 ; /* ALT5 */ + value &= ~(7 << 15); /* GPIO15 */ + value |= 2 << 15 ; /* ALT5 */ + BCM283X_GPIO_GPFSEL(1) = value; + + BCM283X_GPIO_GPPUD = 0; + BCM283X_GPIO_GPPUDCLK(0) = (1 << 14) | (1 << 15); + BCM283X_GPIO_GPPUDCLK(0) = 0; + + AUX_ENABLES(uart->hw_base) = 1; /* Enable UART1 */ + AUX_MU_IER_REG(uart->hw_base) = 0; /* Disable interrupt */ + AUX_MU_CNTL_REG(uart->hw_base) = 0; /* Disable Transmitter and Receiver */ + AUX_MU_LCR_REG(uart->hw_base) = 3; /* Works in 8-bit mode */ + AUX_MU_MCR_REG(uart->hw_base) = 0; /* Disable RTS */ + AUX_MU_IIR_REG(uart->hw_base) = 0xC6; /* Enable FIFO, Clear FIFO */ + AUX_MU_BAUD_REG(uart->hw_base) = 270; /* 115200 = system clock 250MHz / (8 * (baud + 1)), baud = 270 */ + AUX_MU_CNTL_REG(uart->hw_base) = 3; /* Enable Transmitter and Receiver */ + } + + return RT_EOK; +} + +static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* disable rx irq */ + AUX_MU_IER_REG(uart->hw_base) = 0x0; + rt_hw_interrupt_mask(uart->irqno); + break; + + case RT_DEVICE_CTRL_SET_INT: + /* enable rx irq */ + AUX_MU_IER_REG(uart->hw_base) = 0x1; + rt_hw_interrupt_umask(uart->irqno); + break; + } + + return RT_EOK; +} + +static int uart_putc(struct rt_serial_device *serial, char c) +{ + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + while (!(AUX_MU_LSR_REG(uart->hw_base) & 0x20)); + AUX_MU_IO_REG(uart->hw_base) = c; + + return 1; +} + +static int uart_getc(struct rt_serial_device *serial) +{ + int ch = -1; + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + if ((AUX_MU_LSR_REG(uart->hw_base) & 0x01)) + { + ch = AUX_MU_IO_REG(uart->hw_base) & 0xff; + } + + return ch; +} + +static const struct rt_uart_ops _uart_ops = +{ + uart_configure, + uart_control, + uart_putc, + uart_getc, +}; + +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); +} + +#ifdef RT_USING_UART0 +/* UART device driver structure */ +static struct hw_uart_device _uart0_device = +{ + RPI_UART0_BASE, + IRQ_PBA8_UART0, +}; +static struct rt_serial_device _serial0; +#endif + +#ifdef RT_USING_UART1 +/* UART1 device driver structure */ +static struct hw_uart_device _uart1_device = +{ + AUX_BASE, + IRQ_AUX, +}; +static struct rt_serial_device _serial1; +#endif + +int rt_hw_uart_init(void) +{ + struct hw_uart_device *uart; + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef RT_USING_UART0 + uart = &_uart0_device; + + _serial0.ops = &_uart_ops; + _serial0.config = config; + + /* register UART1 device */ + rt_hw_serial_register(&_serial0, "uart0", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); + rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial0, "uart0"); +#endif + +#ifdef RT_USING_UART1 + uart = &_uart1_device; + _serial1.ops = &_uart_ops; + _serial1.config = config; + + /* register UART1 device */ + rt_hw_serial_register(&_serial1, "uart1", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); + /* enable Rx and Tx of UART */ + rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial1, "uart1"); +#endif + + return 0; +} diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_uart.h b/bsp/raspberry-pi/raspi3-32/driver/drv_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..5211c19989e486e5270f2d35e67711abd7d80368 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_uart.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 Bernard the first version + */ + +#ifndef DRV_UART_H__ +#define DRV_UART_H__ + +/* + * Auxiliary + */ +#define AUX_IRQ(BASE) HWREG32(BASE + 0x00) /* Auxiliary Interrupt status 3 */ +#define AUX_ENABLES(BASE) HWREG32(BASE + 0x04) /* Auxiliary enables 3bit */ +#define AUX_MU_IO_REG(BASE) HWREG32(BASE + 0x40) /* Mini Uart I/O Data 8bit */ +#define AUX_MU_IER_REG(BASE) HWREG32(BASE + 0x44) /* Mini Uart Interrupt Enable 8bit */ +#define AUX_MU_IIR_REG(BASE) HWREG32(BASE + 0x48) /* Mini Uart Interrupt Identify 8bit */ +#define AUX_MU_LCR_REG(BASE) HWREG32(BASE + 0x4C) /* Mini Uart Line Control 8bit */ +#define AUX_MU_MCR_REG(BASE) HWREG32(BASE + 0x50) /* Mini Uart Modem Control 8bit */ +#define AUX_MU_LSR_REG(BASE) HWREG32(BASE + 0x54) /* Mini Uart Line Status 8bit */ +#define AUX_MU_MSR_REG(BASE) HWREG32(BASE + 0x58) /* Mini Uart Modem Status 8bit */ +#define AUX_MU_SCRATCH(BASE) HWREG32(BASE + 0x5C) /* Mini Uart Scratch 8bit */ +#define AUX_MU_CNTL_REG(BASE) HWREG32(BASE + 0x60) /* Mini Uart Extra Control 8bit */ +#define AUX_MU_STAT_REG(BASE) HWREG32(BASE + 0x64) /* Mini Uart Extra Status 32bit */ +#define AUX_MU_BAUD_REG(BASE) HWREG32(BASE + 0x68) /* Mini Uart Baudrate 16bit */ +#define AUX_SPI0_CNTL0_REG(BASE) HWREG32(BASE + 0x80) /* SPI 1 Control register 0 32bit */ +#define AUX_SPI0_CNTL1_REG(BASE) HWREG32(BASE + 0x84) /* SPI 1 Control register 1 8bit */ +#define AUX_SPI0_STAT_REG(BASE) HWREG32(BASE + 0x88) /* SPI 1 Status 32bit */ +#define AUX_SPI0_IO_REG(BASE) HWREG32(BASE + 0x90) /* SPI 1 Data 32bit */ +#define AUX_SPI0_PEEK_REG(BASE) HWREG32(BASE + 0x94) /* SPI 1 Peek 16bit */ +#define AUX_SPI1_CNTL0_REG(BASE) HWREG32(BASE + 0xC0) /* SPI 2 Control register 0 32bit */ +#define AUX_SPI1_CNTL1_REG(BASE) HWREG32(BASE + 0xC4) /* SPI 2 Control register 1 8bit */ + +int rt_hw_uart_init(void); + +#endif /* DRV_UART_H__ */ + diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_wdt.c b/bsp/raspberry-pi/raspi3-32/driver/drv_wdt.c new file mode 100644 index 0000000000000000000000000000000000000000..31b242fab5c2a6cd2cadb2b1bdc99415e554a216 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_wdt.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ +#include "drv_wdt.h" + +#ifdef BSP_USING_WDT + +#define SECS_TO_WDOG_TICKS(x) ((x) << 16) +#define WDOG_TICKS_TO_SECS(x) ((x) >> 16) + +static struct raspi_wdt_driver bcm_wdt; + +void raspi_watchdog_init(rt_uint32_t time_init) +{ + bcm_wdt.timeout = time_init; +} + +void raspi_watchdog_start() +{ + volatile rt_uint32_t cur; + PM_WDOG = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET); + cur = PM_RSTC; + PM_RSTC = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; +} + +void raspi_watchdog_stop() +{ + PM_RSTC = PM_PASSWORD | PM_RSTC_RESET; +} + +void raspi_watchdog_clr() +{ + bcm_wdt.timeout = 0; +} + +void raspi_watchdog_set_timeout(rt_uint32_t timeout_us) +{ + bcm_wdt.timeout = timeout_us; +} + +rt_uint64_t raspi_watchdog_get_timeout() +{ + return bcm_wdt.timeout; +} + +rt_uint64_t raspi_watchdog_get_timeleft() +{ + rt_uint32_t ret = PM_WDOG; + return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET); +} + +static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt) +{ + /*init for 10S*/ + raspi_watchdog_init(1000000); + raspi_watchdog_start(); + raspi_watchdog_stop(); + return RT_EOK; +} + +static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg) +{ + rt_uint64_t timeout_us = 0; + switch (cmd) + { + case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: + timeout_us = *((rt_uint32_t *)arg) * 1000000; + if (timeout_us >= 0xFFFFFFFF) + timeout_us = 0xFFFFFFFF; + raspi_watchdog_set_timeout((rt_uint32_t)timeout_us); + break; + case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: + timeout_us = raspi_watchdog_get_timeout(); + *((rt_uint32_t *)arg) = timeout_us / 1000000; + break; + case RT_DEVICE_CTRL_WDT_GET_TIMELEFT: + timeout_us = raspi_watchdog_get_timeleft(); + *((rt_uint32_t *)arg) = timeout_us / 1000000; + break; + case RT_DEVICE_CTRL_WDT_KEEPALIVE: + raspi_watchdog_clr(); + break; + case RT_DEVICE_CTRL_WDT_START: + raspi_watchdog_start(); + break; + case RT_DEVICE_CTRL_WDT_STOP: + raspi_watchdog_stop(); + break; + default: + return RT_EIO; + } + return RT_EOK; +} + +static const struct rt_watchdog_ops raspi_wdg_pos = +{ + raspi_wdg_init, + raspi_wdg_control, +}; + +static rt_watchdog_t raspi_wdg; + +int rt_hw_wdt_init(void) +{ + raspi_wdg.ops = &raspi_wdg_pos; + rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL); + return RT_EOK; +} + +INIT_DEVICE_EXPORT(rt_hw_wdt_init); +#endif /*BSP_USING_WDT */ diff --git a/bsp/raspberry-pi/raspi3-32/driver/drv_wdt.h b/bsp/raspberry-pi/raspi3-32/driver/drv_wdt.h new file mode 100644 index 0000000000000000000000000000000000000000..0b59ab79f3dc111b0cb6d4e8a09aef81e78242b3 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/drv_wdt.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_WDT_H__ +#define __DRV_WDT_H__ + +#include +#include + +#include "board.h" + +struct raspi_wdt_driver +{ + rt_uint32_t timeout; +}; + +int rt_hw_wdt_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/driver/mbox.c b/bsp/raspberry-pi/raspi3-32/driver/mbox.c new file mode 100644 index 0000000000000000000000000000000000000000..bbd5183aa8c1b8e53a2108dd6ef694c5c528fc03 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/mbox.c @@ -0,0 +1,54 @@ +/* + * File : mbox.c + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-29 zdzn first version + */ + +/* mailbox message buffer */ +#include "mbox.h" +#include "mmu.h" + +volatile unsigned int *mbox = (volatile unsigned int *) MBOX_ADDR; +/** + * Make a mailbox call. Returns 0 on failure, non-zero on success + */ +void init_mbox_mmu_map() +{ + rt_hw_change_mmu_table(MBOX_ADDR, 96, MBOX_ADDR, STRONG_ORDER_MEM); +} + +int mbox_call(unsigned char ch, int mmu_enable) +{ + unsigned int r = (((MBOX_ADDR)&~0xF) | (ch&0xF)); + if (mmu_enable) + r = BUS_ADDRESS(r); + /* wait until we can write to the mailbox */ + do + { + asm volatile("nop"); + } while (*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + while (1) + { + /* is there a response? */ + do + { + asm volatile("nop"); + } + while (*MBOX_STATUS & MBOX_EMPTY); + /* is it a response to our message? */ + if (r == *MBOX_READ) + { + /* is it a valid successful response? */ + return mbox[1] == MBOX_RESPONSE; + } + } + return 0; +} diff --git a/bsp/raspberry-pi/raspi3-32/driver/mbox.h b/bsp/raspberry-pi/raspi3-32/driver/mbox.h new file mode 100644 index 0000000000000000000000000000000000000000..5c59fd608c10bf0c250ab338c6e5f1641f7b8dcd --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/mbox.h @@ -0,0 +1,63 @@ +/* + * File : mbox.h + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-29 zdzn first version + */ + +#ifndef __MBOX_H__ +#define __MBOX_H__ + +/* a properly aligned buffer */ +extern volatile unsigned int* mbox; + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_SETPOWER 0x28001 +#define MBOX_TAG_SETCLKRATE 0x38002 +#define MBOX_GET_MAC_ADDRESS 0x10003 +#define MBOX_GET_CLOCK_RATE 0x30002 +#define MBOX_SET_CLOCK_RATE 0x38002 +#define MBOX_TAG_LAST 0 + +#define MMIO_BASE 0x3F000000 +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +#define DEVICE_ID_SD_CARD 0 +#define DEVICE_ID_USB_HCD 3 +#define POWER_STATE_OFF (0 << 0) +#define POWER_STATE_ON (1 << 0) +#define POWER_STATE_WAIT (1 << 1) +#define POWER_STATE_NO_DEVICE (1 << 1) // in response +#define MMU_ENABLE 1 +#define MMU_DISABLE 0 + +#define MBOX_ADDR 0xc00000 + +int mbox_call(unsigned char ch, int mmu_enable); +#endif diff --git a/bsp/raspberry-pi/raspi3-32/driver/raspi.h b/bsp/raspberry-pi/raspi3-32/driver/raspi.h new file mode 100644 index 0000000000000000000000000000000000000000..19daa3541df0f9331cc4d737823f8893d779ff04 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/driver/raspi.h @@ -0,0 +1,432 @@ +/* + * File : rsapi.h + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __RASPI_H__ +#define __RASPI_H__ + +/* define for bcm283x*/ +typedef enum +{ + BCM_GPIO_PIN_0 = 0, + BCM_GPIO_PIN_1, + BCM_GPIO_PIN_2, + BCM_GPIO_PIN_3, + BCM_GPIO_PIN_4, + BCM_GPIO_PIN_5, + BCM_GPIO_PIN_6, + BCM_GPIO_PIN_7, + BCM_GPIO_PIN_8, + BCM_GPIO_PIN_9, + BCM_GPIO_PIN_10, + BCM_GPIO_PIN_11, + BCM_GPIO_PIN_12, + BCM_GPIO_PIN_13, + BCM_GPIO_PIN_14, + BCM_GPIO_PIN_15, + BCM_GPIO_PIN_16, + BCM_GPIO_PIN_17, + BCM_GPIO_PIN_18, + BCM_GPIO_PIN_19, + BCM_GPIO_PIN_20, + BCM_GPIO_PIN_21, + BCM_GPIO_PIN_22, + BCM_GPIO_PIN_23, + BCM_GPIO_PIN_24, + BCM_GPIO_PIN_25, + BCM_GPIO_PIN_26, + BCM_GPIO_PIN_27, + BCM_GPIO_PIN_28, + BCM_GPIO_PIN_29, + BCM_GPIO_PIN_30, + BCM_GPIO_PIN_31, + BCM_GPIO_PIN_32, + BCM_GPIO_PIN_33, + BCM_GPIO_PIN_34, + BCM_GPIO_PIN_35, + BCM_GPIO_PIN_36, + BCM_GPIO_PIN_37, + BCM_GPIO_PIN_38, + BCM_GPIO_PIN_39, + BCM_GPIO_PIN_40, + BCM_GPIO_PIN_41, + BCM_GPIO_PIN_42, + BCM_GPIO_PIN_43, + BCM_GPIO_PIN_44, + BCM_GPIO_PIN_45, + BCM_GPIO_PIN_46, + BCM_GPIO_PIN_47, + BCM_GPIO_PIN_48, + BCM_GPIO_PIN_49, + BCM_GPIO_PIN_50, + BCM_GPIO_PIN_51, + BCM_GPIO_PIN_52, + BCM_GPIO_PIN_53, + BCM_GPIO_PIN_NULL, +} bcm_gpio_pin; + +typedef enum +{ + BCM283X_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ + BCM283X_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ + BCM283X_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ + BCM283X_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ + BCM283X_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ + BCM283X_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ + BCM283X_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ + BCM283X_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ + BCM283X_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ +} gpio_function_select; + +typedef enum +{ + BCM283X_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ + BCM283X_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ + BCM283X_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ +} gpio_pud_mode; + +#define BCM283X_CORE_CLK_HZ 250000000 /* 50 MHz */ + +/* Base Address */ +#define PER_BASE (0x3F000000) +#define PER_BASE_40000000 (0x40000000) +//#define BCM283X_PERI_BASE (0x3F000000) +//#define BCM283X_PER_BASE_40000000 (0x40000000) + +/* Base Address Registers Offset */ +#define ST_BASE_OFFSET (0x003000) +#define GPIO_PAD_OFFSET (0x100000) +#define CLOCK_BASE_OFFSET (0x101000) +#define GPIO_BASE_OFFSET (0x200000) +#define SPI0_BASE_OFFSET (0x204000) +#define BSC0_BASE_OFFSET (0x205000) +#define GPIO_PWM_OFFSET (0x20C000) +#define AUX_BASE_OFFSET (0x215000) +#define SPI1_BASE_OFFSET (0x215080) +#define SPI2_BASE_OFFSET (0x2150C0) +#define BSC1_BASE_OFFSET (0x804000) +#define BSC2_BASE_OFFSET (0x805000) + +/* IRQ */ +#define IRQ_SYSTEM_TIMER_0 0 +#define IRQ_SYSTEM_TIMER_1 1 +#define IRQ_SYSTEM_TIMER_2 2 +#define IRQ_SYSTEM_TIMER_3 3 +#define IRQ_USB 9 +#define IRQ_AUX 29 +#define IRQ_PCM 55 +#define IRQ_ARM_TIMER 64 +#define IRQ_ARM_MAILBOX 65 + +/* Interrupt Controler */ +#define IRQ_BASE (PER_BASE + 0xB200) +#define IRQ_PEND_BASIC HWREG32(IRQ_BASE + 0x0000) +#define IRQ_PEND1 HWREG32(IRQ_BASE + 0x0004) +#define IRQ_PEND2 HWREG32(IRQ_BASE + 0x0008) +#define IRQ_FIQ_CONTROL HWREG32(IRQ_BASE + 0x000C) +#define IRQ_ENABLE1 HWREG32(IRQ_BASE + 0x0010) +#define IRQ_ENABLE2 HWREG32(IRQ_BASE + 0x0014) +#define IRQ_ENABLE_BASIC HWREG32(IRQ_BASE + 0x0018) +#define IRQ_DISABLE1 HWREG32(IRQ_BASE + 0x001C) +#define IRQ_DISABLE2 HWREG32(IRQ_BASE + 0x0020) +#define IRQ_DISABLE_BASIC HWREG32(IRQ_BASE + 0x0024) + + +/* Defines for WDT*/ +#define PM_BASE (PER_BASE + GPIO_PAD_OFFSET) +#define PM_RSTC HWREG32(PM_BASE + 0x001C) +#define PM_RSTS HWREG32(PM_BASE + 0x0020) +#define PM_WDOG HWREG32(PM_BASE + 0x0024) + +#define PM_PASSWORD 0x5a000000 +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTS_HADWRH_SET 0x00000040 +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 +#define PM_RSTS_PARTITION_CLR 0xfffffaaa + +/* Defines for System Timer */ +#define STIMER_BASE (PER_BASE + ST_BASE_OFFSET) +#define STIMER_CS HWREG32(STIMER_BASE + 0x0000) +#define STIMER_CLO HWREG32(STIMER_BASE + 0x0004) +#define STIMER_CHI HWREG32(STIMER_BASE + 0x0008) +#define STIMER_C0 HWREG32(STIMER_BASE + 0x000C) +#define STIMER_C1 HWREG32(STIMER_BASE + 0x0010) +#define STIMER_C2 HWREG32(STIMER_BASE + 0x0014) +#define STIMER_C3 HWREG32(STIMER_BASE + 0x0018) + +#define DELAY_MICROS(micros) \ + do{ \ + rt_uint32_t compare = STIMER_CLO + micros * 25; \ + while (STIMER_CLO < compare); \ + } while (0) \ + +/* Defines for GPIO */ +#define BCM283X_GPIO_BASE (PER_BASE + GPIO_BASE_OFFSET) +#define BCM283X_GPIO_GPFSEL(n) HWREG32(BCM283X_GPIO_BASE + 0x0000 + 0x4 * n) /* GPIO Function Select 32bit R/W */ +#define BCM283X_GPIO_GPSET(n) HWREG32(BCM283X_GPIO_BASE + 0x001C + 0x4 * n) /* GPIO Pin Output Set */ +#define BCM283X_GPIO_GPCLR(n) HWREG32(BCM283X_GPIO_BASE + 0x0028 + 0x4 * n) /* GPIO Pin Output Clear */ +#define BCM2835_GPIO_GPLEV(n) HWREG32(BCM283X_GPIO_BASE + 0x0034 + 0x4 * n) /* GPIO Pin Level */ +#define BCM283X_GPIO_GPEDS(n) HWREG32(BCM283X_GPIO_BASE + 0x0040 + 0x4 * n) /* GPIO Pin Event Detect Status */ +#define BCM283X_GPIO_GPREN(n) HWREG32(BCM283X_GPIO_BASE + 0x004c + 0x4 * n) /* GPIO Pin Rising Edge Detect Enable */ +#define BCM283X_GPIO_GPFEN(n) HWREG32(BCM283X_GPIO_BASE + 0x0058 + 0x4 * n) /* GPIO Pin Falling Edge Detect Enable */ +#define BCM283X_GPIO_GPHEN(n) HWREG32(BCM283X_GPIO_BASE + 0x0064 + 0x4 * n) /* GPIO Pin High Detect Enable */ +#define BCM283X_GPIO_GPLEN(n) HWREG32(BCM283X_GPIO_BASE + 0x0070 + 0x4 * n) /* GPIO Pin Low Detect Enable */ +#define BCM283X_GPIO_GPAREN(n) HWREG32(BCM283X_GPIO_BASE + 0x007C + 0x4 * n) /* GPIO Pin Async. Rising Edge Detect */ +#define BCM283X_GPIO_GPAFEN(n) HWREG32(BCM283X_GPIO_BASE + 0x0088 + 0x4 * n) /* GPIO Pin Async. Falling Edge Detect */ +#define BCM283X_GPIO_GPPUD HWREG32(BCM283X_GPIO_BASE + 0x0094) /* GPIO Pin Pull-up/down Enable */ +#define BCM283X_GPIO_GPPUDCLK(n) HWREG32(BCM283X_GPIO_BASE + 0x0098 + 0x4 * n) /* GPIO Pin Pull-up/down Enable Clock */ + +#define GPIO_FSEL_NUM(pin) (pin/10) +#define GPIO_FSEL_SHIFT(pin) ((pin%10)*3) +#define GPIO_FSEL(pin, mode) \ + do{ \ + __sync_synchronize(); \ + BCM283X_GPIO_GPFSEL(GPIO_FSEL_NUM(pin)) |= ((mode & BCM283X_GPIO_FSEL_MASK) << GPIO_FSEL_SHIFT(pin)); \ + } while (0) \ + +/* Defines for I2C */ +#define BCM283X_BSC0_BASE (PER_BASE + BSC0_BASE_OFFSET) //for i2c0 +#define BCM283X_BSC1_BASE (PER_BASE + BSC1_BASE_OFFSET) //for i2c1 +#define BCM283X_BSC2_BASE (PER_BASE + BSC2_BASE_OFFSET) //for hdmi i2c not use + +#define BCM283X_BSC_C(BASE) HWREG32(BASE + 0x0000) /* BSC Master Control */ +#define BCM283X_BSC_S(BASE) HWREG32(BASE + 0x0004) /* BSC Master Status */ +#define BCM283X_BSC_DLEN(BASE) HWREG32(BASE + 0x0008) /* BSC Master Data Length */ +#define BCM283X_BSC_A(BASE) HWREG32(BASE + 0x000c) /* BSC Master Slave Address */ +#define BCM283X_BSC_FIFO(BASE) HWREG32(BASE + 0x0010) /* BSC Master Data FIFO */ +#define BCM283X_BSC_DIV(BASE) HWREG32(BASE + 0x0014) /* BSC Master Clock Divider */ +#define BCM283X_BSC_DEL(BASE) HWREG32(BASE + 0x0018) /* BSC Master Data Delay */ +#define BCM283X_BSC_CLKT(BASE) HWREG32(BASE + 0x001c) /* BSC Master Clock Stretch Timeout */ + +/* Register masks for C Register */ +#define BSC_C_I2CEN 0x00008000 /* I2C Enable, 0 = disabled, 1 = enabled */ +#define BSC_C_INTR 0x00000400 /* Interrupt on RX */ +#define BSC_C_INTT 0x00000200 /* Interrupt on TX */ +#define BSC_C_INTD 0x00000100 /* Interrupt on DONE */ +#define BSC_C_ST 0x00000080 /* Start transfer, 1 = Start a new transfer */ +#define BSC_C_CLEAR_1 0x00000020 /* Clear FIFO Clear */ +#define BSC_C_CLEAR_2 0x00000010 /* Clear FIFO Clear */ +#define BSC_C_READ 0x00000001 /* Read transfer */ + +/* Register masks for S Register */ +#define BSC_S_CLKT 0x00000200 /* Clock stretch timeout */ +#define BSC_S_ERR 0x00000100 /* ACK error */ +#define BSC_S_RXF 0x00000080 /* RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ +#define BSC_S_TXE 0x00000040 /* TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ +#define BSC_S_RXD 0x00000020 /* RXD FIFO contains data */ +#define BSC_S_TXD 0x00000010 /* TXD FIFO can accept data */ +#define BSC_S_RXR 0x00000008 /* RXR FIFO needs reading (full) */ +#define BSC_S_TXW 0x00000004 /* TXW FIFO needs writing (full) */ +#define BSC_S_DONE 0x00000002 /* Transfer DONE */ +#define BSC_S_TA 0x00000001 /* Transfer Active */ + +#define BSC_FIFO_SIZE (16) /* BSC FIFO size */ + +/* Defines for SPI */ +#define BCM283X_SPI0_BASE (PER_BASE + SPI0_BASE_OFFSET) +#define BCM283X_SPI1_BASE (PER_BASE + SPI1_BASE_OFFSET) +#define BCM283X_SPI2_BASE (PER_BASE + SPI2_BASE_OFFSET) + +#define BCM283X_SPI0_CS(BASE) HWREG32(BASE + 0x0000) /* SPI Master Control and Status */ +#define BCM283X_SPI0_FIFO(BASE) HWREG32(BASE + 0x0004) /* SPI Master TX and RX FIFOs */ +#define BCM283X_SPI0_CLK(BASE) HWREG32(BASE + 0x0008) /* SPI Master Clock Divider */ +#define BCM283X_SPI0_DLEN(BASE) HWREG32(BASE + 0x000c) /* SPI Master Data Length */ +#define BCM283X_SPI0_LTOH(BASE) HWREG32(BASE + 0x0010) /* SPI LOSSI mode TOH */ +#define BCM283X_SPI0_DC(BASE) HWREG32(BASE + 0x0014) /* SPI DMA DREQ Controls */ + +/* Register masks for SPI0_CS */ +#define BCM283X_SPI0_CS_LEN_LONG 0x02000000 /* Enable Long data word in Lossi mode if DMA_LEN is set */ +#define BCM283X_SPI0_CS_DMA_LEN 0x01000000 /* Enable DMA mode in Lossi mode */ +#define BCM283X_SPI0_CS_CSPOL2 0x00800000 /* Chip Select 2 Polarity */ +#define BCM283X_SPI0_CS_CSPOL1 0x00400000 /* Chip Select 1 Polarity */ +#define BCM283X_SPI0_CS_CSPOL0 0x00200000 /* Chip Select 0 Polarity */ +#define BCM283X_SPI0_CS_RXF 0x00100000 /* RXF - RX FIFO Full */ +#define BCM283X_SPI0_CS_RXR 0x00080000 /* RXR RX FIFO needs Reading (full) */ +#define BCM283X_SPI0_CS_TXD 0x00040000 /* TXD TX FIFO can accept Data */ +#define BCM283X_SPI0_CS_RXD 0x00020000 /* RXD RX FIFO contains Data */ +#define BCM283X_SPI0_CS_DONE 0x00010000 /* Done transfer Done */ +#define BCM283X_SPI0_CS_TE_EN 0x00008000 /* Unused */ +#define BCM283X_SPI0_CS_LMONO 0x00004000 /* Unused */ +#define BCM283X_SPI0_CS_LEN 0x00002000 /* LEN LoSSI enable */ +#define BCM283X_SPI0_CS_REN 0x00001000 /* REN Read Enable */ +#define BCM283X_SPI0_CS_ADCS 0x00000800 /* ADCS Automatically Deassert Chip Select */ +#define BCM283X_SPI0_CS_INTR 0x00000400 /* INTR Interrupt on RXR */ +#define BCM283X_SPI0_CS_INTD 0x00000200 /* INTD Interrupt on Done */ +#define BCM283X_SPI0_CS_DMAEN 0x00000100 /* DMAEN DMA Enable */ +#define BCM283X_SPI0_CS_TA 0x00000080 /* Transfer Active */ +#define BCM283X_SPI0_CS_CSPOL 0x00000040 /* Chip Select Polarity */ +#define BCM283X_SPI0_CS_CLEAR 0x00000030 /* Clear FIFO Clear RX and TX */ +#define BCM283X_SPI0_CS_CLEAR_RX 0x00000020 /* Clear FIFO Clear RX */ +#define BCM283X_SPI0_CS_CLEAR_TX 0x00000010 /* Clear FIFO Clear TX */ +#define BCM283X_SPI0_CS_CPOL 0x00000008 /* Clock Polarity */ +#define BCM283X_SPI0_CS_CPHA 0x00000004 /* Clock Phase */ +#define BCM283X_SPI0_CS_CS 0x00000003 /* Chip Select */ + +/* ARM Timer */ +#define ARM_TIMER_BASE (PER_BASE + 0xB000) +#define ARM_TIMER_LOAD HWREG32(ARM_TIMER_BASE + 0x400) +#define ARM_TIMER_VALUE HWREG32(ARM_TIMER_BASE + 0x404) +#define ARM_TIMER_CTRL HWREG32(ARM_TIMER_BASE + 0x408) +#define ARM_TIMER_IRQCLR HWREG32(ARM_TIMER_BASE + 0x40C) +#define ARM_TIMER_RAWIRQ HWREG32(ARM_TIMER_BASE + 0x410) +#define ARM_TIMER_MASKIRQ HWREG32(ARM_TIMER_BASE + 0x414) +#define ARM_TIMER_RELOAD HWREG32(ARM_TIMER_BASE + 0x418) +#define ARM_TIMER_PREDIV HWREG32(ARM_TIMER_BASE + 0x41C) +#define ARM_TIMER_CNTR HWREG32(ARM_TIMER_BASE + 0x420) + +/* ARM Core Timer */ +#define C0TIMER_INTCTL HWREG32(PER_BASE_40000000 + 0x40) /* Core0 timers Interrupt control */ +#define C1TIMER_INTCTL HWREG32(PER_BASE_40000000 + 0x44) /* Core1 timers Interrupt control */ +#define C2TIMER_INTCTL HWREG32(PER_BASE_40000000 + 0x48) /* Core2 timers Interrupt control */ +#define C3TIMER_INTCTL HWREG32(PER_BASE_40000000 + 0x4C) /* Core3 timers Interrupt control */ +#define CORETIMER_INTCTL(n) HWREG32(PER_BASE_40000000 + 0x40 + n*4) /* Coren timers Interrupt control */ + +/* ARM Core Mailbox interrupt */ +#define C0MB_INTCTL HWREG32(PER_BASE_40000000 + 0x50) /* Core0 Mailboxes Interrupt control */ +#define C1MB_INTCTL HWREG32(PER_BASE_40000000 + 0x54) /* Core1 Mailboxes Interrupt control */ +#define C2MB_INTCTL HWREG32(PER_BASE_40000000 + 0x58) /* Core2 Mailboxes Interrupt control */ +#define C3MB_INTCTL HWREG32(PER_BASE_40000000 + 0x5C) /* Core3 Mailboxes Interrupt control */ +#define COREMB_INTCTL(n) HWREG32(PER_BASE_40000000 + 0x50 + 4*n) /* Coren Mailboxes Interrupt control */ + +/* ARM Core IRQ/FIQ status */ +#define C0_IRQSOURCE HWREG32(PER_BASE_40000000 + 0x60) /* Core0 IRQ Source */ +#define C1_IRQSOURCE HWREG32(PER_BASE_40000000 + 0x64) /* Core1 IRQ Source */ +#define C2_IRQSOURCE HWREG32(PER_BASE_40000000 + 0x68) /* Core2 IRQ Source */ +#define C3_IRQSOURCE HWREG32(PER_BASE_40000000 + 0x6C) /* Core3 IRQ Source */ +#define C0_FIQSOURCE HWREG32(PER_BASE_40000000 + 0x70) /* Core0 FIQ Source */ +#define C1_FIQSOURCE HWREG32(PER_BASE_40000000 + 0x74) /* Core1 FIQ Source */ +#define C2_FIQSOURCE HWREG32(PER_BASE_40000000 + 0x78) /* Core2 FIQ Source */ +#define C3_FIQSOURCE HWREG32(PER_BASE_40000000 + 0x7C) /* Core3 FIQ Source */ +#define CORE_IRQSOURCE(n) HWREG32(PER_BASE_40000000 + 0x60+ n*0x4) +#define CORE_FIQSOURCE(n) HWREG32(PER_BASE_40000000 + 0x70+ n*0x4) + +#define CORE_MAILBOX3_SET(n) HWREG32(PER_BASE_40000000 + 0x8C + n*0x10) +#define CORE_MAILBOX3_CLEAR(n) HWREG32(PER_BASE_40000000 + 0xCC + n*0x10) +#define CORE_MAILBOX2_SET(n) HWREG32(PER_BASE_40000000 + 0x88 + n*0x10) +#define CORE_MAILBOX2_CLEAR(n) HWREG32(PER_BASE_40000000 + 0xC8 + n*0x10) +#define CORE_MAILBOX1_SET(n) HWREG32(PER_BASE_40000000 + 0x84 + n*0x10) +#define CORE_MAILBOX1_CLEAR(n) HWREG32(PER_BASE_40000000 + 0xC4 + n*0x10) +#define CORE_MAILBOX0_SET(n) HWREG32(PER_BASE_40000000 + 0x80 + n*0x10) +#define CORE_MAILBOX0_CLEAR(n) HWREG32(PER_BASE_40000000 + 0xC0 + n*0x10) + +/* For SMP IPI use MailBox0 */ +#define IPI_MAILBOX_SET CORE_MAILBOX0_SET +#define IPI_MAILBOX_CLEAR CORE_MAILBOX0_CLEAR +#define IPI_MAILBOX_INT_MASK (0x01) + +enum spi_bit_order +{ + BCM283X_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ + BCM283X_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ +}; + +enum spi_mode +{ + BCM283X_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ + BCM283X_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ + BCM283X_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ + BCM283X_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ +}; + +enum spi_chip_select +{ + BCM283X_SPI_CS0 = 0, /*!< Chip Select 0 */ + BCM283X_SPI_CS1 = 1, /*!< Chip Select 1 */ + BCM283X_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ + BCM283X_SPI_CS_NONE = 3 /*!< No CS, control it yourself */ +}; + +enum spi_clock_divider +{ + BCM283X_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */ + BCM283X_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/ + BCM283X_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */ +}; + +/*redefine for raspi*/ +typedef gpio_function_select raspi_pin_select; +typedef enum +{ + RPI_GPIO_P1_01 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_02 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_03 = BCM_GPIO_PIN_2, + RPI_GPIO_P1_04 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_05 = BCM_GPIO_PIN_3, + RPI_GPIO_P1_06 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_07 = BCM_GPIO_PIN_4, + RPI_GPIO_P1_08 = BCM_GPIO_PIN_14, + RPI_GPIO_P1_09 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_10 = BCM_GPIO_PIN_15, + RPI_GPIO_P1_11 = BCM_GPIO_PIN_17, + RPI_GPIO_P1_12 = BCM_GPIO_PIN_18, + RPI_GPIO_P1_13 = BCM_GPIO_PIN_27, + RPI_GPIO_P1_14 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_15 = BCM_GPIO_PIN_22, + RPI_GPIO_P1_16 = BCM_GPIO_PIN_23, + RPI_GPIO_P1_17 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_18 = BCM_GPIO_PIN_24, + RPI_GPIO_P1_19 = BCM_GPIO_PIN_10, + RPI_GPIO_P1_20 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_21 = BCM_GPIO_PIN_9, + RPI_GPIO_P1_22 = BCM_GPIO_PIN_25, + RPI_GPIO_P1_23 = BCM_GPIO_PIN_11, + RPI_GPIO_P1_24 = BCM_GPIO_PIN_8, + RPI_GPIO_P1_25 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_26 = BCM_GPIO_PIN_7, + RPI_GPIO_P1_27 = BCM_GPIO_PIN_0, + RPI_GPIO_P1_28 = BCM_GPIO_PIN_1, + RPI_GPIO_P1_29 = BCM_GPIO_PIN_5, + RPI_GPIO_P1_30 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_31 = BCM_GPIO_PIN_6, + RPI_GPIO_P1_32 = BCM_GPIO_PIN_12, + RPI_GPIO_P1_33 = BCM_GPIO_PIN_13, + RPI_GPIO_P1_34 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_35 = BCM_GPIO_PIN_19, + RPI_GPIO_P1_36 = BCM_GPIO_PIN_16, + RPI_GPIO_P1_37 = BCM_GPIO_PIN_26, + RPI_GPIO_P1_38 = BCM_GPIO_PIN_20, + RPI_GPIO_P1_39 = BCM_GPIO_PIN_NULL, + RPI_GPIO_P1_40 = BCM_GPIO_PIN_21, +} raspi_gpio_pin; + +typedef enum +{ + BCM283X_I2C_CLOCK_DIVIDER_2500 = 2500, /* 2500 = 10us = 100 kHz */ + BCM283X_I2C_CLOCK_DIVIDER_626 = 626, /* 622 = 2.504us = 399.3610 kHz */ + BCM283X_I2C_CLOCK_DIVIDER_150 = 150, /* 150 = 60ns = 1.666 MHz (default at reset) */ + BCM283X_I2C_CLOCK_DIVIDER_148 = 148 /* 148 = 59ns = 1.689 MHz */ +} i2c_clock_divider; + +typedef enum +{ + BCM283X_I2C_REASON_OK = 0x00, /* Success */ + BCM283X_I2C_REASON_ERROR_NACK = 0x01, /* Received a NACK */ + BCM283X_I2C_REASON_ERROR_CLKT = 0x02, /* Received Clock Stretch Timeout */ + BCM283X_I2C_REASON_ERROR_DATA = 0x04 /* Not all data is sent / received */ +} i2c_reason_codes; + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/figures/GPIO-Pinout-Diagram-2.png b/bsp/raspberry-pi/raspi3-32/figures/GPIO-Pinout-Diagram-2.png new file mode 100644 index 0000000000000000000000000000000000000000..24238cc23d89f18fca2bc5daa5e3f62abc4c4390 Binary files /dev/null and b/bsp/raspberry-pi/raspi3-32/figures/GPIO-Pinout-Diagram-2.png differ diff --git a/bsp/raspberry-pi/raspi3-32/figures/raspberrypi-console.png b/bsp/raspberry-pi/raspi3-32/figures/raspberrypi-console.png new file mode 100644 index 0000000000000000000000000000000000000000..a36f6f75e050a965fe547cf190925400ce029f7f Binary files /dev/null and b/bsp/raspberry-pi/raspi3-32/figures/raspberrypi-console.png differ diff --git a/bsp/raspberry-pi/raspi3-32/figures/raspi3_b.jpg b/bsp/raspberry-pi/raspi3-32/figures/raspi3_b.jpg new file mode 100644 index 0000000000000000000000000000000000000000..03db419bd89fb16803c1d3b4fc990ca2d662fdd9 Binary files /dev/null and b/bsp/raspberry-pi/raspi3-32/figures/raspi3_b.jpg differ diff --git a/bsp/raspberry-pi/raspi3-32/figures/raspi3_f.jpg b/bsp/raspberry-pi/raspi3-32/figures/raspi3_f.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dd2f25133280c0fc00ac742b4afde45a2ec7f120 Binary files /dev/null and b/bsp/raspberry-pi/raspi3-32/figures/raspi3_f.jpg differ diff --git a/bsp/raspberry-pi/raspi3-32/link.lds b/bsp/raspberry-pi/raspi3-32/link.lds new file mode 100644 index 0000000000000000000000000000000000000000..75e084594312c9f66304ea5bbb32f49cd7e2ba3d --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/link.lds @@ -0,0 +1,149 @@ +/* + * File : link.lds + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * 2017-5-30 bernard first version + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +SECTIONS +{ + . = 0x00008000; + . = ALIGN(4); + .text : + { + *(.vectors) + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* 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 initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + . = ALIGN(4); + _etext = .; + } + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + *(.eh_frame_entry) + } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + + . = ALIGN(4); + .data : + { + *(.data) + *(.data.*) + + *(.data1) + *(.data1.*) + + . = ALIGN(8); + _gp = ABSOLUTE(.); /* Base of small data */ + + *(.sdata) + *(.sdata.*) + } + + . = ALIGN(4); + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } + + . = ALIGN(4); + .bss : + { + PROVIDE(__bss_start = .); + *(.bss) + *(.bss.*) + *(.dynbss) + *(COMMON) + PROVIDE(__bss_end = .); + } + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/bsp/raspberry-pi/raspi3-32/rtconfig.h b/bsp/raspberry-pi/raspi3-32/rtconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..b861bf8827bd157c85906f5e5ac49a1520a03cf8 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/rtconfig.h @@ -0,0 +1,391 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +/* RT_USING_ARCH_DATA_TYPE is not set */ +#define RT_USING_SMP +#define RT_CPUS_NR 4 +#define RT_ALIGN_SIZE 4 +/* RT_THREAD_PRIORITY_8 is not set */ +#define RT_THREAD_PRIORITY_32 +/* RT_THREAD_PRIORITY_256 is not set */ +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 256 +/* RT_USING_TIMER_SOFT is not set */ +#define RT_DEBUG +#define RT_DEBUG_COLOR +/* RT_DEBUG_INIT_CONFIG is not set */ +/* RT_DEBUG_THREAD_CONFIG is not set */ +/* RT_DEBUG_SCHEDULER_CONFIG is not set */ +/* RT_DEBUG_IPC_CONFIG is not set */ +/* RT_DEBUG_TIMER_CONFIG is not set */ +/* RT_DEBUG_IRQ_CONFIG is not set */ +/* RT_DEBUG_MEM_CONFIG is not set */ +/* RT_DEBUG_SLAB_CONFIG is not set */ +/* RT_DEBUG_MEMHEAP_CONFIG is not set */ +/* RT_DEBUG_MODULE_CONFIG is not set */ + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE +/* RT_USING_SIGNALS is not set */ + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_MEMHEAP +/* RT_USING_NOHEAP is not set */ +#define RT_USING_SMALL_MEM +/* RT_USING_SLAB is not set */ +/* RT_USING_MEMHEAP_AS_HEAP is not set */ +#define RT_USING_MEMTRACE +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_DEVICE_OPS +/* RT_USING_INTERRUPT_INFO is not set */ +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40002 +#define ARCH_ARM +/* RT_USING_CPU_FFS is not set */ +#define ARCH_ARM_CORTEX_A +#define ARCH_ARM_CORTEX_A7 +/* ARCH_CPU_STACK_GROWS_UPWARD is not set */ + +/* 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 */ + +/* RT_USING_CPLUSPLUS is not set */ + +/* 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 +/* FINSH_ECHO_DISABLE_DEFAULT is not set */ +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 80 +/* FINSH_USING_AUTH is not set */ +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_USING_MSH_ONLY +#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 +/* RT_USING_DFS_MNTTABLE is not set */ +#define RT_USING_DFS_ELMFAT + +/* elm-chan's FatFs, Generic FAT Filesystem Module */ + +#define RT_DFS_ELM_CODE_PAGE 437 +#define RT_DFS_ELM_WORD_ACCESS +/* RT_DFS_ELM_USE_LFN_0 is not set */ +/* RT_DFS_ELM_USE_LFN_1 is not set */ +/* RT_DFS_ELM_USE_LFN_2 is not set */ +#define RT_DFS_ELM_USE_LFN_3 +#define RT_DFS_ELM_USE_LFN 3 +#define RT_DFS_ELM_MAX_LFN 255 +#define RT_DFS_ELM_DRIVES 2 +#define RT_DFS_ELM_MAX_SECTOR_SIZE 512 +/* RT_DFS_ELM_USE_ERASE is not set */ +#define RT_DFS_ELM_REENTRANT +#define RT_USING_DFS_DEVFS +/* RT_USING_DFS_ROMFS is not set */ +/* RT_USING_DFS_RAMFS is not set */ +/* RT_USING_DFS_UFFS is not set */ +/* RT_USING_DFS_JFFS2 is not set */ + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +/* RT_USING_SYSTEM_WORKQUEUE is not set */ +#define RT_USING_SERIAL +/* RT_SERIAL_USING_DMA is not set */ +#define RT_SERIAL_RB_BUFSZ 64 +/* RT_USING_CAN is not set */ +#define RT_USING_HWTIMER +/* RT_USING_CPUTIME is not set */ +#define RT_USING_I2C +/* RT_USING_I2C_BITOPS is not set */ +#define RT_USING_PIN +/* RT_USING_ADC is not set */ +/* RT_USING_PWM is not set */ +/* RT_USING_MTD_NOR is not set */ +/* RT_USING_MTD_NAND is not set */ +/* RT_USING_PM is not set */ +#define RT_USING_RTC +/* RT_USING_ALARM is not set */ +/* RT_USING_SOFT_RTC is not set */ +#define RT_USING_SDIO +#define RT_SDIO_STACK_SIZE 512 +#define RT_SDIO_THREAD_PRIORITY 15 +#define RT_MMCSD_STACK_SIZE 1024 +#define RT_MMCSD_THREAD_PREORITY 22 +#define RT_MMCSD_MAX_PARTITION 16 +/* RT_SDIO_DEBUG is not set */ +#define RT_USING_SPI +/* RT_USING_QSPI is not set */ +/* RT_USING_SPI_MSD is not set */ +/* RT_USING_SFUD is not set */ +/* RT_USING_ENC28J60 is not set */ +/* RT_USING_SPI_WIFI is not set */ +#define RT_USING_WDT +/* RT_USING_AUDIO is not set */ +/* RT_USING_SENSOR is not set */ +/* RT_USING_TOUCH is not set */ +/* RT_USING_HWCRYPTO is not set */ +/* RT_USING_WIFI is not set */ + +/* Using USB */ + +/* RT_USING_USB_HOST is not set */ +/* RT_USING_USB_DEVICE is not set */ + +/* POSIX layer and C standard library */ + +#define RT_USING_LIBC +/* RT_USING_PTHREADS is not set */ +#define RT_USING_POSIX +/* RT_USING_POSIX_MMAP is not set */ +/* RT_USING_POSIX_TERMIOS is not set */ +/* RT_USING_POSIX_AIO is not set */ +/* RT_USING_MODULE is not set */ + +/* Network */ + +/* Socket abstraction layer */ + +/* RT_USING_SAL is not set */ + +/* Network interface device */ + +/* RT_USING_NETDEV is not set */ + +/* light weight TCP/IP stack */ + +/* RT_USING_LWIP is not set */ + +/* AT commands */ + +/* RT_USING_AT is not set */ + +/* VBUS(Virtual Software BUS) */ + +/* RT_USING_VBUS is not set */ + +/* Utilities */ + +/* RT_USING_RYM is not set */ +/* RT_USING_ULOG is not set */ +/* RT_USING_UTEST is not set */ +/* RT_USING_LWP is not set */ + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + +/* PKG_USING_PAHOMQTT is not set */ +/* PKG_USING_WEBCLIENT is not set */ +/* PKG_USING_WEBNET is not set */ +/* PKG_USING_MONGOOSE is not set */ +/* PKG_USING_WEBTERMINAL is not set */ +/* PKG_USING_CJSON is not set */ +/* PKG_USING_JSMN is not set */ +/* PKG_USING_LIBMODBUS is not set */ +/* PKG_USING_FREEMODBUS is not set */ +/* PKG_USING_LJSON is not set */ +/* PKG_USING_EZXML is not set */ +/* PKG_USING_NANOPB is not set */ + +/* Wi-Fi */ + +/* Marvell WiFi */ + +/* PKG_USING_WLANMARVELL is not set */ + +/* Wiced WiFi */ + +/* PKG_USING_WLAN_WICED is not set */ +/* PKG_USING_RW007 is not set */ +/* PKG_USING_COAP is not set */ +/* PKG_USING_NOPOLL is not set */ +/* PKG_USING_NETUTILS is not set */ +/* PKG_USING_AT_DEVICE is not set */ +/* PKG_USING_ATSRV_SOCKET is not set */ +/* PKG_USING_WIZNET is not set */ + +/* IoT Cloud */ + +/* PKG_USING_ONENET is not set */ +/* PKG_USING_GAGENT_CLOUD is not set */ +/* PKG_USING_ALI_IOTKIT is not set */ +/* PKG_USING_AZURE is not set */ +/* PKG_USING_TENCENT_IOTHUB is not set */ +/* PKG_USING_NIMBLE is not set */ +/* PKG_USING_OTA_DOWNLOADER is not set */ +/* PKG_USING_IPMSG is not set */ +/* PKG_USING_LSSDP is not set */ +/* PKG_USING_AIRKISS_OPEN is not set */ +/* PKG_USING_LIBRWS is not set */ +/* PKG_USING_TCPSERVER is not set */ + +/* security packages */ + +/* PKG_USING_MBEDTLS is not set */ +/* PKG_USING_libsodium is not set */ +/* PKG_USING_TINYCRYPT is not set */ + +/* language packages */ + +/* PKG_USING_LUA is not set */ +/* PKG_USING_JERRYSCRIPT is not set */ +/* PKG_USING_MICROPYTHON is not set */ + +/* multimedia packages */ + +/* PKG_USING_OPENMV is not set */ +/* PKG_USING_MUPDF is not set */ +/* PKG_USING_STEMWIN is not set */ + +/* tools packages */ + +/* PKG_USING_CMBACKTRACE is not set */ +/* PKG_USING_EASYFLASH is not set */ +/* PKG_USING_EASYLOGGER is not set */ +/* PKG_USING_SYSTEMVIEW is not set */ +/* PKG_USING_RDB is not set */ +/* PKG_USING_QRCODE is not set */ +/* PKG_USING_ULOG_EASYFLASH is not set */ +/* PKG_USING_ADBD is not set */ + +/* system packages */ + +/* PKG_USING_GUIENGINE is not set */ +/* PKG_USING_PERSIMMON is not set */ +/* PKG_USING_CAIRO is not set */ +/* PKG_USING_PIXMAN is not set */ +/* PKG_USING_LWEXT4 is not set */ +/* PKG_USING_PARTITION is not set */ +/* PKG_USING_FAL is not set */ +/* PKG_USING_SQLITE is not set */ +/* PKG_USING_RTI is not set */ +/* PKG_USING_LITTLEVGL2RTT is not set */ +/* PKG_USING_CMSIS is not set */ +/* PKG_USING_DFS_YAFFS is not set */ +/* PKG_USING_LITTLEFS is not set */ +/* PKG_USING_THREAD_POOL is not set */ + +/* peripheral libraries and drivers */ + +/* PKG_USING_SENSORS_DRIVERS is not set */ +/* PKG_USING_REALTEK_AMEBA is not set */ +/* PKG_USING_SHT2X is not set */ +/* PKG_USING_STM32_SDIO is not set */ +/* PKG_USING_ICM20608 is not set */ +/* PKG_USING_U8G2 is not set */ +/* PKG_USING_BUTTON is not set */ +/* PKG_USING_PCF8574 is not set */ +/* PKG_USING_SX12XX is not set */ +/* PKG_USING_SIGNAL_LED is not set */ +/* PKG_USING_LEDBLINK is not set */ +/* PKG_USING_WM_LIBRARIES is not set */ +/* PKG_USING_KENDRYTE_SDK is not set */ +/* PKG_USING_INFRARED is not set */ +/* PKG_USING_ROSSERIAL is not set */ +/* PKG_USING_AT24CXX is not set */ +/* PKG_USING_MOTIONDRIVER2RTT is not set */ +/* PKG_USING_AD7746 is not set */ +/* PKG_USING_PCA9685 is not set */ +/* PKG_USING_I2C_TOOLS is not set */ +/* PKG_USING_NRF24L01 is not set */ +/* PKG_USING_TOUCH_DRIVERS is not set */ +/* PKG_USING_LCD_DRIVERS is not set */ + +/* miscellaneous packages */ + +/* PKG_USING_LIBCSV is not set */ +/* PKG_USING_OPTPARSE is not set */ +/* PKG_USING_FASTLZ is not set */ +/* PKG_USING_MINILZO is not set */ +/* PKG_USING_QUICKLZ is not set */ +/* PKG_USING_MULTIBUTTON is not set */ +/* PKG_USING_CANFESTIVAL is not set */ +/* PKG_USING_ZLIB is not set */ +/* PKG_USING_DSTR is not set */ +/* PKG_USING_TINYFRAME is not set */ +/* PKG_USING_KENDRYTE_DEMO is not set */ +/* PKG_USING_DIGITALCTRL is not set */ + +/* samples: kernel and components samples */ + +/* PKG_USING_KERNEL_SAMPLES is not set */ +/* PKG_USING_FILESYSTEM_SAMPLES is not set */ +/* PKG_USING_NETWORK_SAMPLES is not set */ +/* PKG_USING_PERIPHERAL_SAMPLES is not set */ +/* PKG_USING_HELLO is not set */ +/* PKG_USING_VI is not set */ +/* PKG_USING_NNOM is not set */ +/* PKG_USING_LIBANN is not set */ +#define BCM2836_SOC + +/* Hardware Drivers Config */ + +/* BCM Peripheral Drivers */ + +#define BSP_USING_UART +/* RT_USING_UART0 is not set */ +#define RT_USING_UART1 +#define BSP_USING_PIN +#define BSP_USING_SYSTIMER +#define RT_USING_SYSTIMER1 +#define RT_USING_SYSTIMER3 +#define BSP_USING_I2C +#define BSP_USING_I2C0 +#define BSP_USING_I2C1 +#define BSP_USING_SPI +#define BSP_USING_SPI0_BUS +#define BSP_USING_SPI0_DEVICE0 +#define BSP_USING_SPI0_DEVICE1 +#define BSP_USING_WDT +#define BSP_USING_RTC +/* BSP_USING_ALARM is not set */ +#define BSP_USING_SDIO +#define BSP_USING_SDIO0 +#define BSP_USING_HDMI + +#endif diff --git a/bsp/raspberry-pi/raspi3-32/rtconfig.py b/bsp/raspberry-pi/raspi3-32/rtconfig.py new file mode 100644 index 0000000000000000000000000000000000000000..fb37e924821c762d20f9132037b25b6e524224d3 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-32/rtconfig.py @@ -0,0 +1,52 @@ +import os + +# toolchains options +ARCH ='armv8-a' +CPU ='cortex-a53' +CROSS_TOOL ='gcc' + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = r'../../..' + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +PLATFORM = 'gcc' +EXEC_PATH = r'/usr/bin' +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 = ' -mfloat-abi=softfp -march=armv8-a -mtune=cortex-a53 -ftree-vectorize -ffast-math' + CFLAGS = DEVICE + ' -Wall' + AFLAGS = ' -c' + ' -march=armv8-a -x assembler-with-cpp -D__ASSEMBLY__' + LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds' + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + +DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n' +POST_ACTION = OBJCPY + ' -O binary $TARGET kernel7.img\n' + SIZE + ' $TARGET \n' diff --git a/bsp/raspberry-pi/raspi3-64/.config b/bsp/raspberry-pi/raspi3-64/.config new file mode 100644 index 0000000000000000000000000000000000000000..d51c923bf95bfb54459b95c28d1cff0fd1372371 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/.config @@ -0,0 +1,418 @@ +# +# Automatically generated file; DO NOT EDIT. +# RT-Thread Project Configuration +# + +# +# RT-Thread Kernel +# +CONFIG_RT_NAME_MAX=8 +# CONFIG_RT_USING_ARCH_DATA_TYPE is not set +# CONFIG_RT_USING_SMP is not set +CONFIG_RT_ALIGN_SIZE=4 +# CONFIG_RT_THREAD_PRIORITY_8 is not set +CONFIG_RT_THREAD_PRIORITY_32=y +# CONFIG_RT_THREAD_PRIORITY_256 is not set +CONFIG_RT_THREAD_PRIORITY_MAX=32 +CONFIG_RT_TICK_PER_SECOND=100 +CONFIG_RT_USING_OVERFLOW_CHECK=y +CONFIG_RT_USING_HOOK=y +CONFIG_RT_USING_IDLE_HOOK=y +CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 +CONFIG_IDLE_THREAD_STACK_SIZE=2048 +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=2048 +CONFIG_RT_DEBUG=y +CONFIG_RT_DEBUG_COLOR=y +# CONFIG_RT_DEBUG_INIT_CONFIG is not set +# CONFIG_RT_DEBUG_THREAD_CONFIG is not set +# CONFIG_RT_DEBUG_SCHEDULER_CONFIG is not set +# CONFIG_RT_DEBUG_IPC_CONFIG is not set +# CONFIG_RT_DEBUG_TIMER_CONFIG is not set +# CONFIG_RT_DEBUG_IRQ_CONFIG is not set +# CONFIG_RT_DEBUG_MEM_CONFIG is not set +# CONFIG_RT_DEBUG_SLAB_CONFIG is not set +# CONFIG_RT_DEBUG_MEMHEAP_CONFIG is not set +# CONFIG_RT_DEBUG_MODULE_CONFIG is not set + +# +# Inter-Thread communication +# +CONFIG_RT_USING_SEMAPHORE=y +CONFIG_RT_USING_MUTEX=y +CONFIG_RT_USING_EVENT=y +CONFIG_RT_USING_MAILBOX=y +CONFIG_RT_USING_MESSAGEQUEUE=y +# CONFIG_RT_USING_SIGNALS is not set + +# +# Memory Management +# +CONFIG_RT_USING_MEMPOOL=y +CONFIG_RT_USING_MEMHEAP=y +# CONFIG_RT_USING_NOHEAP is not set +CONFIG_RT_USING_SMALL_MEM=y +# CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_MEMHEAP_AS_HEAP is not set +CONFIG_RT_USING_MEMTRACE=y +CONFIG_RT_USING_HEAP=y + +# +# Kernel Device Object +# +CONFIG_RT_USING_DEVICE=y +CONFIG_RT_USING_DEVICE_OPS=y +# CONFIG_RT_USING_INTERRUPT_INFO is not set +CONFIG_RT_USING_CONSOLE=y +CONFIG_RT_CONSOLEBUF_SIZE=128 +CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" +CONFIG_RT_VER_NUM=0x40002 +CONFIG_ARCH_CPU_64BIT=y +CONFIG_ARCH_ARM=y +# CONFIG_RT_USING_CPU_FFS is not set +CONFIG_ARCH_ARM_CORTEX_AARCH64=y +CONFIG_ARCH_ARM_CORTEX_A53=y +# CONFIG_ARCH_CPU_STACK_GROWS_UPWARD is not set + +# +# RT-Thread Components +# +CONFIG_RT_USING_COMPONENTS_INIT=y +CONFIG_RT_USING_USER_MAIN=y +CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 +CONFIG_RT_MAIN_THREAD_PRIORITY=10 + +# +# C++ features +# +# CONFIG_RT_USING_CPLUSPLUS is not set + +# +# Command shell +# +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_CMD_SIZE=80 +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_USING_MSH_DEFAULT=y +CONFIG_FINSH_USING_MSH_ONLY=y +CONFIG_FINSH_ARG_MAX=10 + +# +# Device virtual file system +# +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=2 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=2 +CONFIG_DFS_FD_MAX=16 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_UFFS is not set +# CONFIG_RT_USING_DFS_JFFS2 is not set + +# +# Device Drivers +# +CONFIG_RT_USING_DEVICE_IPC=y +CONFIG_RT_PIPE_BUFSZ=512 +# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SERIAL=y +# CONFIG_RT_SERIAL_USING_DMA is not set +CONFIG_RT_SERIAL_RB_BUFSZ=64 +# CONFIG_RT_USING_CAN is not set +# CONFIG_RT_USING_HWTIMER is not set +# CONFIG_RT_USING_CPUTIME is not set +# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_PWM is not set +# CONFIG_RT_USING_MTD_NOR is not set +# CONFIG_RT_USING_MTD_NAND is not set +# CONFIG_RT_USING_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_WIFI is not set + +# +# Using USB +# +# CONFIG_RT_USING_USB_HOST is not set +# CONFIG_RT_USING_USB_DEVICE is not set + +# +# POSIX layer and C standard library +# +CONFIG_RT_USING_LIBC=y +# CONFIG_RT_USING_PTHREADS is not set +CONFIG_RT_USING_POSIX=y +# CONFIG_RT_USING_POSIX_MMAP is not set +# CONFIG_RT_USING_POSIX_TERMIOS is not set +# CONFIG_RT_USING_POSIX_AIO is not set +# CONFIG_RT_USING_MODULE is not set + +# +# Network +# + +# +# Socket abstraction layer +# +# CONFIG_RT_USING_SAL is not set + +# +# 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_PAHOMQTT is not set +# CONFIG_PKG_USING_WEBCLIENT is not set +# CONFIG_PKG_USING_WEBNET is not set +# CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_WEBTERMINAL is not set +# CONFIG_PKG_USING_CJSON is not set +# CONFIG_PKG_USING_JSMN is not set +# CONFIG_PKG_USING_LIBMODBUS is not set +# CONFIG_PKG_USING_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_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_IOTHUB is not set +# CONFIG_PKG_USING_JIOT-C-SDK 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 + +# +# security packages +# +# CONFIG_PKG_USING_MBEDTLS is not set +# CONFIG_PKG_USING_libsodium is not set +# CONFIG_PKG_USING_TINYCRYPT is not set + +# +# language packages +# +# CONFIG_PKG_USING_LUA is not set +# CONFIG_PKG_USING_JERRYSCRIPT is not set +# CONFIG_PKG_USING_MICROPYTHON is not set + +# +# multimedia packages +# +# CONFIG_PKG_USING_OPENMV is not set +# CONFIG_PKG_USING_MUPDF is not set +# CONFIG_PKG_USING_STEMWIN is not set +# CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD 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 + +# +# 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_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 + +# +# 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_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_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_LCD_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR 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_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_ULAPACK is not set +# CONFIG_PKG_USING_UKAL is not set +CONFIG_BCM2836_SOC=y +# CONFIG_BSP_SUPPORT_FPU is not set + +# +# Hardware Drivers Config +# + +# +# BCM Peripheral Drivers +# +CONFIG_BSP_USING_UART=y +# CONFIG_RT_USING_UART0 is not set +CONFIG_RT_USING_UART1=y +CONFIG_BSP_USING_PIN=y +# CONFIG_BSP_USING_SYSTIMER is not set +# CONFIG_BSP_USING_I2C is not set +# CONFIG_BSP_USING_SPI is not set +# CONFIG_BSP_USING_WDT is not set +# CONFIG_BSP_USING_RTC is not set +# CONFIG_BSP_USING_SDIO is not set + +# +# Board Peripheral Drivers +# +# CONFIG_BSP_USING_HDMI is not set diff --git a/bsp/raspberry-pi/raspi3-64/.cproject b/bsp/raspberry-pi/raspi3-64/.cproject new file mode 100644 index 0000000000000000000000000000000000000000..403db1205c69c85037fbd0a703cd323bae2be03c --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/.cproject @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bsp/raspberry-pi/raspi3-64/.project b/bsp/raspberry-pi/raspi3-64/.project new file mode 100644 index 0000000000000000000000000000000000000000..16586966cc0fefffb715c9bc798de8acb76d2e0c --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/.project @@ -0,0 +1,54 @@ + + + raspi2 + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.rttnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + rt-thread + 2 + virtual:/virtual + + + rt-thread/components + 2 + $%7BPARENT-2-PROJECT_LOC%7D/components + + + rt-thread/include + 2 + $%7BPARENT-2-PROJECT_LOC%7D/include + + + rt-thread/libcpu + 2 + $%7BPARENT-2-PROJECT_LOC%7D/libcpu + + + rt-thread/src + 2 + $%7BPARENT-2-PROJECT_LOC%7D/src + + + diff --git a/bsp/raspberry-pi/raspi3-64/Kconfig b/bsp/raspberry-pi/raspi3-64/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..2122b45395747e6f7849908047727c4fca4cf43f --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/Kconfig @@ -0,0 +1,29 @@ +mainmenu "RT-Thread Project Configuration" + +config BSP_DIR + string + option env="BSP_ROOT" + default "." + +config RTT_DIR + string + option env="RTT_ROOT" + default "../.." + +config PKGS_DIR + string + option env="PKGS_ROOT" + default "packages" + +source "$RTT_DIR/Kconfig" +source "$PKGS_DIR/Kconfig" + +config BCM2836_SOC + bool + select ARCH_ARM_CORTEX_A53 + select RT_USING_COMPONENTS_INIT + select RT_USING_USER_MAIN + select ARCH_CPU_64BIT + default y + +source "driver/Kconfig" diff --git a/bsp/raspberry-pi/raspi3-64/README.md b/bsp/raspberry-pi/raspi3-64/README.md new file mode 100644 index 0000000000000000000000000000000000000000..28e00f96c082b426e771953beeeb2ae2a66df77f --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/README.md @@ -0,0 +1,100 @@ +# Raspberry PI 3-64板级支持包说明 + +## 1. 简介 + +树莓派由注册于英国的慈善组织“Raspberry Pi 基金会”开发,莓派3有三个发行版本: + +* B : 4核 Broadcom BCM2837 (ARMv8-A) 1.2GHz,双核VideoCore IV GPU,1GB内存,100 Base-T Ethernet +* B+: 4核 Broadcom BCM2837B0 Cortex-A53 (ARMv8) 1.4GHz, 1GB LPDDR2 SDRAM, GigaE over USB 2.0 +* A+: 4核 Broadcom BCM2837B0 Cortex-A53 (ARMv8) 1.4GHz, 512MB LPDDR2 SDRAM + +这份RT-Thread BSP是针对 Raspberry Pi 3 64位模式的一份移植,树莓派价格便宜, 使用者甚众,是研究和运行RT-Thread的可选平台之一。 + + +## 2. 编译说明 + +### 2.1 Window上的环境搭建 + +Windows环境下推荐使用[env工具][1]进行编译。 + +首先下载Linux上的gcc工具,版本为gcc-arm-8.3选择aarch64-elf就可以。 + +将推荐将gcc解压到`\env\tools\gnu_gcc\arm_gcc`目录下。 + +接着修改`bsp\raspberry-pi\raspi3-64\rtconfig.py` + +修改路径: + +``` +EXEC_PATH = r'E:/env_released_1.1.2/env/tools/gnu_gcc/arm_gcc/gcc-arm-8.3-2019.03-i686-mingw32-aarch64-elf/bin' +``` + +然后在`bsp\raspberry-pi\raspi3-64\`下输入scons编译即可。 + +### 2.2 Linux上的环境搭建 + +Linux下推荐使用[gcc工具][2]。Linux版本下gcc版本可采用`gcc-arm-8.3-2019.03-x86_64-aarch64-elf`。 + +直接进入`bsp\raspberry-pi\raspi3-64`,输入scons编译即可。 + + +## 3. 执行 + +### 3.1 下载[raspbian镜像][3],生成可以运行的raspbian SD卡 + +Windows下,去[etcher.io][4]下载etcher,这是个可以烧写img的工具 + +解开下载的镜像文件, linux下使用如下的命令 + +``` +unzip 2018-06-27-raspbian-stretch-lite.zip +``` + +准备一张空SD卡,linux环境下,插入电脑并执行 + +``` +sudo dd if=2018-06-27-raspbian-stretch-lite.img of=/dev/xxx bs=32M conv=fsync +``` + +**注意: /dev/xxx 要换成真实环境中的SD卡所在设置,千万不要弄错。** + +Windows环境下,执行etcher选择解压后的2018-06-27-raspbian-stretch-lite.img文件和SD卡就可以开始烧写了。 + +最后把kernel8.img放入SD boot分区,删除其它 kernel*.img。 + +### 3.2 准备好串口线 + +目前版本是使用raspi3的 GPIO 14, GPIO 15来作路口输出,连线情况如下图所示(图片中的板子是pi2,GPIO引脚是一样的): + +![raspi2](figures/raspi_uart.png) + +串口参数: 115200 8N1 ,硬件和软件流控为关。 + +按上面的方法做好SD卡后,插入树莓派,通电可以在串口上看到如下所示的输出信息: + +```text + heap: 0x00020b20 - 0x00400000 + + \ | / +- RT - Thread Operating System + / | \ 3.1.0 build Aug 23 2019 + 2006 - 2019 Copyright by rt-thread team +Hello RT-Thread! +msh > +``` + +## 4. 支持情况 + +| 驱动 | 支持情况 | 备注 | +| ------ | ---- | :------: | +| UART | 支持 | UART0| + +## 5. 联系人信息 + +维护人:[bernard][5] + +[1]: https://www.rt-thread.org/page/download.html +[2]: https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads +[3]: https://downloads.raspberrypi.org/raspbian_lite_latest +[4]: https://etcher.io +[5]: https://github.com/BernardXiong diff --git a/bsp/raspberry-pi/raspi3-64/SConscript b/bsp/raspberry-pi/raspi3-64/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..c7ef7659ecea92b1dd9b71a97736a8552ee02551 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/SConscript @@ -0,0 +1,14 @@ +# for module compiling +import os +from building import * + +cwd = GetCurrentDir() +objs = [] +list = os.listdir(cwd) + +for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') diff --git a/bsp/raspberry-pi/raspi3-64/SConstruct b/bsp/raspberry-pi/raspi3-64/SConstruct new file mode 100644 index 0000000000000000000000000000000000000000..93f349aab8045ad3c742e72664514a7c240b2b6e --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/SConstruct @@ -0,0 +1,30 @@ +import os +import sys +import rtconfig + +from rtconfig import RTT_ROOT + +sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')] +from building import * + +TARGET = 'rtthread.' + rtconfig.TARGET_EXT + +DefaultEnvironment(tools=[]) +env = Environment(tools = ['mingw'], + AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS, + CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS, + CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS, + AR = rtconfig.AR, ARFLAGS = '-rc', + LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS) +env.PrependENVPath('PATH', rtconfig.EXEC_PATH) +env['ASCOM'] = env['ASPPCOM'] + +Export('RTT_ROOT') +Export('rtconfig') + +# prepare building environment +objs = PrepareBuilding(env, RTT_ROOT, has_libcpu = False) + +# make a building +DoBuilding(TARGET, objs) + diff --git a/bsp/raspberry-pi/raspi3-64/applications/SConscript b/bsp/raspberry-pi/raspi3-64/applications/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..fdf93d423539b5b0bdafc948a1fb549fbc647e3b --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/applications/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') + Glob('test/*.c') +CPPPATH = [cwd] + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/raspberry-pi/raspi3-64/applications/main.c b/bsp/raspberry-pi/raspi3-64/applications/main.c new file mode 100644 index 0000000000000000000000000000000000000000..bcccbecc00d1ac1c65b159cddd141f30269ec563 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/applications/main.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 bernard the first version + */ + +#include + +int main(int argc, char** argv) +{ + rt_kprintf("Hi, this is RT-Thread!!\n"); + + return 0; +} + diff --git a/bsp/raspberry-pi/raspi3-64/applications/mnt.c b/bsp/raspberry-pi/raspi3-64/applications/mnt.c new file mode 100644 index 0000000000000000000000000000000000000000..8ec394eb8cbddabd2ce166016621ac2cd8f7df8f --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/applications/mnt.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 bernard the first version + */ + +#include + +int mnt_init(void) +{ + return 0; +} diff --git a/bsp/raspberry-pi/raspi3-64/applications/test/gpio.h b/bsp/raspberry-pi/raspi3-64/applications/test/gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..52fa671d0f1e03d2315980cd0c575f00c204f10f --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/applications/test/gpio.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * 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. + * + */ + +#define MMIO_BASE 0x3F000000 + +#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C)) diff --git a/bsp/raspberry-pi/raspi3-64/applications/test/uart.c b/bsp/raspberry-pi/raspi3-64/applications/test/uart.c new file mode 100644 index 0000000000000000000000000000000000000000..b3dd4da7eaeac8067715c21b2fd6d5c134f83b0f --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/applications/test/uart.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * 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. + * + */ + +#include "gpio.h" + +/* Auxilary mini UART registers */ +#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) +#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040)) +#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044)) +#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048)) +#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) +#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050)) +#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054)) +#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) +#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060)) +#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064)) +#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068)) + +/** + * Set baud rate and characteristics (115200 8N1) and map to GPIO + */ +void uart_init() +{ + register unsigned int r; + + /* initialize UART */ + *AUX_ENABLE |=1; // enable UART1, AUX mini uart + *AUX_MU_CNTL = 0; + *AUX_MU_LCR = 3; // 8 bits + *AUX_MU_MCR = 0; + *AUX_MU_IER = 0; + *AUX_MU_IIR = 0xc6; // disable interrupts + *AUX_MU_BAUD = 270; // 115200 baud + /* map UART1 to GPIO pins */ + r=*GPFSEL1; + r&=~((7<<12)|(7<<15)); // gpio14, gpio15 + r|=(2<<12)|(2<<15); // alt5 + *GPFSEL1 = r; + *GPPUD = 0; // enable pins 14 and 15 + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = (1<<14)|(1<<15); + r=150; while(r--) { asm volatile("nop"); } + *GPPUDCLK0 = 0; // flush GPIO setup + *AUX_MU_CNTL = 3; // enable Tx, Rx +} + +/** + * Send a character + */ +void uart_send(unsigned int c) { + /* wait until we can send */ + do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x20)); + /* write the character to the buffer */ + *AUX_MU_IO=c; +} + +/** + * Receive a character + */ +char uart_getc() { + char r; + /* wait until something is in the buffer */ + do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01)); + /* read it and return */ + r=(char)(*AUX_MU_IO); + /* convert carrige return to newline */ + return r=='\r'?'\n':r; +} + +/** + * Display a string + */ +void uart_puts(char *s) { + while(*s) { + /* convert newline to carrige return + newline */ + if(*s=='\n') + uart_send('\r'); + uart_send(*s++); + } +} diff --git a/bsp/raspberry-pi/raspi3-64/applications/test/uart.h b/bsp/raspberry-pi/raspi3-64/applications/test/uart.h new file mode 100644 index 0000000000000000000000000000000000000000..72f8e3151f0831ac2922d0cb0a3aa16e27ca9947 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/applications/test/uart.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * 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. + * + */ + +void uart_init(); +void uart_send(unsigned int c); +char uart_getc(); +void uart_puts(char *s); diff --git a/bsp/raspberry-pi/raspi3-64/driver/Kconfig b/bsp/raspberry-pi/raspi3-64/driver/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..2deffef99cfadc571d9adfa5b7ed700440e08771 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/Kconfig @@ -0,0 +1,112 @@ + +config BSP_SUPPORT_FPU + bool "Using Float" + default n + +menu "Hardware Drivers Config" + menu "BCM Peripheral Drivers" + menuconfig BSP_USING_UART + bool "Using UART" + select RT_USING_SERIAL + default y + + if BSP_USING_UART + config RT_USING_UART0 + bool "Enabel UART 0" + default y + + config RT_USING_UART1 + bool "Enabel UART 1" + default n + endif + + config BSP_USING_PIN + bool "Using PIN" + select RT_USING_PIN + default y + + menuconfig BSP_USING_SYSTIMER + bool "Enable SYSTIMER" + select BSP_USING_SYSTIMER + default n + + if BSP_USING_SYSTIMER + config RT_USING_SYSTIMER1 + bool "Enable sys timer1" + default n + config RT_USING_SYSTIMER3 + bool "Enable sys timer3" + default n + endif + + menuconfig BSP_USING_I2C + bool "Enable I2C" + select RT_USING_I2C + default n + + if BSP_USING_I2C + config BSP_USING_I2C0 + bool "Enable I2C0" + default n + config BSP_USING_I2C1 + bool "Enable I2C1" + default n + endif + + menuconfig BSP_USING_SPI + bool "Enable SPI" + select RT_USING_SPI + default n + + if BSP_USING_SPI + config BSP_USING_SPI0 + bool "Enable SPI0" + default n + config BSP_USING_SPI1 + bool "Enable SPI1" + default n + endif + + config BSP_USING_WDT + bool "Enable WDT" + select RT_USING_WDT + default n + + menuconfig BSP_USING_RTC + bool "Enable RTC" + select RT_USING_RTC + default n + + if BSP_USING_RTC + config BSP_USING_ALARM + bool "Enable Alarm" + select RT_USING_ALARM + default n + endif + + menuconfig BSP_USING_SDIO + bool "Enable SDIO" + select RT_USING_SDIO + default n + + if BSP_USING_SDIO + config BSP_USING_SDIO0 + bool "Enable SDIO0" + select RT_USING_SDIO + default n + endif + endmenu + + menu "Board Peripheral Drivers" + menuconfig BSP_USING_HDMI + bool "Enable HDMI" + select BSP_USING_SPI + default n + + if BSP_USING_HDMI + config BSP_USING_HDMI_DISPLAY + bool "HDMI DISPLAY" + default n + endif + endmenu +endmenu diff --git a/bsp/raspberry-pi/raspi3-64/driver/SConscript b/bsp/raspberry-pi/raspi3-64/driver/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..2c19b9436dc7194e310f73c00164242108a6067f --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/SConscript @@ -0,0 +1,32 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() +src = Split(''' +board.c +bcm283x.c +drv_uart.c +mbox.c +''') +CPPPATH = [cwd] + +if GetDepend('BSP_USING_SYSTIMER'): + src += ['drv_timer.c'] +if GetDepend('BSP_USING_PIN'): + src += ['drv_gpio.c'] +if GetDepend('BSP_USING_I2C'): + src += ['drv_i2c.c'] +if GetDepend('BSP_USING_WDT'): + src += ['drv_wdt.c'] +if GetDepend('BSP_USING_SPI'): + src += ['drv_spi.c'] +if GetDepend('BSP_USING_SDIO'): + src += ['drv_sdio.c'] +if GetDepend('BSP_USING_RTC'): + src += ['drv_rtc.c'] +if GetDepend('BSP_USING_HDMI'): + src += ['drv_fb.c'] +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/raspberry-pi/raspi3-64/driver/bcm283x.c b/bsp/raspberry-pi/raspi3-64/driver/bcm283x.c new file mode 100644 index 0000000000000000000000000000000000000000..ea92c33a0fb856be1995b5098c41263e38ab8c53 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/bcm283x.c @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include "bcm283x.h" + +rt_uint32_t bcm283x_peri_read(volatile rt_ubase_t addr) +{ + rt_uint32_t ret; + __sync_synchronize(); + ret = HWREG32(addr); + __sync_synchronize(); + return ret; +} + +rt_uint32_t bcm283x_peri_read_nb(volatile rt_ubase_t addr) +{ + return HWREG32(addr); +} + +void bcm283x_peri_write(volatile rt_ubase_t addr, rt_uint32_t value) +{ + __sync_synchronize(); + HWREG32(addr) = value; + __sync_synchronize(); +} + +void bcm283x_peri_write_nb(volatile rt_ubase_t addr, rt_uint32_t value) +{ + HWREG32(addr) = value; +} + +void bcm283x_peri_set_bits(volatile rt_ubase_t addr, rt_uint32_t value, rt_uint32_t mask) +{ + rt_uint32_t v = bcm283x_peri_read(addr); + v = (v & ~mask) | (value & mask); + bcm283x_peri_write(addr, v); +} + +void bcm283x_gpio_fsel(rt_uint8_t pin, rt_uint8_t mode) +{ + volatile rt_ubase_t addr = (BCM283X_GPIO_BASE + BCM283X_GPIO_GPFSEL0 + (pin / 10) * 4); + rt_uint8_t shift = (pin % 10) * 3; + rt_uint32_t mask = BCM283X_GPIO_FSEL_MASK << shift; + rt_uint32_t value = mode << shift; + + bcm283x_peri_set_bits(addr, value, mask); +} + +void bcm283x_gpio_set(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPSET0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + bcm283x_peri_write(addr, 1 << shift); +} + +void bcm283x_gpio_clr(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPCLR0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + bcm283x_peri_write(addr, 1 << shift); +} + +rt_uint8_t bcm283x_gpio_lev(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM2835_GPIO_GPLEV0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = bcm283x_peri_read(addr); + return (value & (1 << shift)) ? HIGH : LOW; +} + +rt_uint8_t bcm283x_gpio_eds(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPEDS0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = bcm283x_peri_read(addr); + return (value & (1 << shift)) ? HIGH : LOW; +} + +/* Write a 1 to clear the bit in EDS */ +void bcm283x_gpio_set_eds(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPEDS0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_write(addr, value); +} + +/* Rising edge detect enable */ +void bcm283x_gpio_ren(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPREN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, value, value); +} + +void bcm283x_gpio_clr_ren(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPREN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, 0, value); +} + +/* Falling edge detect enable */ +void bcm283x_gpio_fen(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPFEN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, value, value); +} +void bcm283x_gpio_clr_fen(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPFEN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, 0, value); +} + +/* High detect enable */ +void bcm283x_gpio_hen(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPHEN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, value, value); +} + +void bcm283x_gpio_clr_hen(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPHEN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, 0, value); +} + +/* Low detect enable */ +void bcm283x_gpio_len(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPLEN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, value, value); +} + +void bcm283x_gpio_clr_len(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPLEN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, 0, value); +} + +/* Async rising edge detect enable */ +void bcm283x_gpio_aren(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPAREN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, value, value); +} +void bcm283x_gpio_clr_aren(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPAREN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, 0, value); +} + +/* Async falling edge detect enable */ +void bcm283x_gpio_afen(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPAFEN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, value, value); +} +void bcm283x_gpio_clr_afen(rt_uint8_t pin) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPAFEN0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + rt_uint32_t value = 1 << shift; + bcm283x_peri_set_bits(addr, 0, value); +} + +/* Set pullup/down */ +void bcm283x_gpio_pud(rt_uint8_t pud) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPPUD; + bcm283x_peri_write(addr, pud); +} + +/* Pullup/down clock +// Clocks the value of pud into the GPIO pin +*/ +void bcm283x_gpio_pudclk(rt_uint8_t pin, rt_uint8_t on) +{ + volatile rt_ubase_t addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPPUDCLK0 + (pin / 32) * 4; + rt_uint8_t shift = pin % 32; + bcm283x_peri_write(addr, (on? 1 : 0) << shift); +} + +void bcm283x_gpio_set_pud(rt_uint8_t pin, rt_uint8_t pud) +{ + bcm283x_gpio_pud(pud); + bcm283x_clo_delayMicros(10); + + bcm283x_gpio_pudclk(pin, 1); + bcm283x_clo_delayMicros(10); + + bcm283x_gpio_pud(BCM283X_GPIO_PUD_OFF); + bcm283x_gpio_pudclk(pin, 0); +} + + +void bcm283x_gpio_write(rt_uint8_t pin, rt_uint8_t val) +{ + if (val) + bcm283x_gpio_set(pin); + else + bcm283x_gpio_clr(pin); +} + +rt_uint64_t bcm283x_st_read(void) +{ + volatile rt_ubase_t addr; + rt_uint32_t hi, lo; + rt_uint64_t st; + + addr = BCM283X_ST_BASE + BCM283X_ST_CHI; + hi = bcm283x_peri_read(addr); + + addr = BCM283X_ST_BASE + BCM283X_ST_CLO; + lo = bcm283x_peri_read(addr); + + addr = BCM283X_ST_BASE + BCM283X_ST_CHI; + st = bcm283x_peri_read(addr); + + /* Test for overflow */ + if (st == hi) + { + rt_kprintf(">> 1crash???\n"); + st <<= 32; + st += lo; + rt_kprintf(">> 2crash!!!\n"); + } + else + { + st <<= 32; + addr = BCM283X_ST_BASE + BCM283X_ST_CLO; + st += bcm283x_peri_read(addr); + } + return st; +} + +/* microseconds */ +void bcm283x_delayMicroseconds(rt_uint64_t micros) +{ + rt_uint64_t start; + + start = bcm283x_st_read(); + rt_kprintf("bcm283x_st_read result: %d\n", start); + + /* Not allowed to access timer registers (result is not as precise)*/ + if (start==0) + return; + + bcm283x_st_delay(start, micros); +} + +void bcm283x_clo_delayMicros(rt_uint32_t micros) +{ + volatile rt_uint32_t addr; + rt_uint32_t compare; + + addr = BCM283X_ST_BASE + BCM283X_ST_CLO; + compare = bcm283x_peri_read(addr) + micros; + while(bcm283x_peri_read(addr) < compare); +} + +void bcm283x_st_delay(rt_uint64_t offset_micros, rt_uint64_t micros) +{ + rt_uint64_t compare = offset_micros + micros; + while(bcm283x_st_read() < compare); +} + + +/* Read an number of bytes from I2C */ +rt_uint8_t bcm283x_i2c_read(rt_uint32_t base, rt_uint8_t* buf, rt_uint32_t len) +{ + volatile rt_uint32_t dlen = base + BCM283X_BSC_DLEN; + volatile rt_uint32_t fifo = base + BCM283X_BSC_FIFO; + volatile rt_uint32_t status = base + BCM283X_BSC_S; + volatile rt_uint32_t control = base + BCM283X_BSC_C; + + rt_uint32_t remaining = len; + rt_uint32_t i = 0; + rt_uint8_t reason = BCM283X_I2C_REASON_OK; + + /* Clear FIFO */ + bcm283x_peri_set_bits(control, BCM283X_BSC_C_CLEAR_1, BCM283X_BSC_C_CLEAR_1); + /* Clear Status */ + bcm283x_peri_write_nb(status, BCM283X_BSC_S_CLKT | BCM283X_BSC_S_ERR | BCM283X_BSC_S_DONE); + /* Set Data Length */ + bcm283x_peri_write_nb(dlen, len); + /* Start read */ + bcm283x_peri_write_nb(control, BCM283X_BSC_C_I2CEN | BCM283X_BSC_C_ST | BCM283X_BSC_C_READ); + + /* wait for transfer to complete */ + while (!(bcm283x_peri_read_nb(status) & BCM283X_BSC_S_DONE)) + { + /* we must empty the FIFO as it is populated and not use any delay */ + while (remaining && bcm283x_peri_read_nb(status) & BCM283X_BSC_S_RXD) + { + /* Read from FIFO, no barrier */ + buf[i] = bcm283x_peri_read_nb(fifo); + i++; + remaining--; + } + } + + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (bcm283x_peri_read_nb(status) & BCM283X_BSC_S_RXD)) + { + /* Read from FIFO, no barrier */ + buf[i] = bcm283x_peri_read_nb(fifo); + i++; + remaining--; + } + + /* Received a NACK */ + if (bcm283x_peri_read(status) & BCM283X_BSC_S_ERR) + { + reason = BCM283X_I2C_REASON_ERROR_NACK; + } + + /* Received Clock Stretch Timeout */ + else if (bcm283x_peri_read(status) & BCM283X_BSC_S_CLKT) + { + reason = BCM283X_I2C_REASON_ERROR_CLKT; + } + + /* Not all data is received */ + else if (remaining) + { + reason = BCM283X_I2C_REASON_ERROR_DATA; + } + + bcm283x_peri_set_bits(control, BCM283X_BSC_S_DONE, BCM283X_BSC_S_DONE); + + return reason; +} + +int bcm283x_i2c_begin(int no) +{ + if (0 == no) + { + bcm283x_gpio_fsel(BCM_GPIO_PIN_0, BCM283X_GPIO_FSEL_ALT0); /* SDA */ + bcm283x_gpio_fsel(BCM_GPIO_PIN_1, BCM283X_GPIO_FSEL_ALT0); /* SCL */ + } + else + { + bcm283x_gpio_fsel(BCM_GPIO_PIN_2, BCM283X_GPIO_FSEL_ALT0); /* SDA */ + bcm283x_gpio_fsel(BCM_GPIO_PIN_3, BCM283X_GPIO_FSEL_ALT0); /* SCL */ + } + return 0; +} + +void bcm283x_i2c_end(int no) +{ + if (0 == no) + { + bcm283x_gpio_fsel(BCM_GPIO_PIN_0, BCM283X_GPIO_FSEL_INPT); /* SDA */ + bcm283x_gpio_fsel(BCM_GPIO_PIN_1, BCM283X_GPIO_FSEL_INPT); /* SCL */ + } + else + { + bcm283x_gpio_fsel(BCM_GPIO_PIN_2, BCM283X_GPIO_FSEL_INPT); /* SDA */ + bcm283x_gpio_fsel(BCM_GPIO_PIN_3, BCM283X_GPIO_FSEL_INPT); /* SCL */ + } +} + +void bcm283x_i2c_setSlaveAddress(int no, rt_uint8_t saddr) +{ + volatile rt_uint32_t addr; + if (0 == no) + addr = PER_BASE + BCM283X_BSC0_BASE + BCM283X_BSC_A; + else + addr = PER_BASE + BCM283X_BSC1_BASE + BCM283X_BSC_A; + + bcm283x_peri_write(addr, saddr); +} + +void bcm283x_i2c_setClockDivider(int no, rt_uint16_t divider) +{ + volatile rt_uint32_t addr; + if (0 == no) + addr = PER_BASE + BCM283X_BSC0_BASE + BCM283X_BSC_DIV; + else + addr = PER_BASE + BCM283X_BSC0_BASE + BCM283X_BSC_DIV; + bcm283x_peri_write(addr, divider); +} + +void bcm283x_i2c_set_baudrate(int no, rt_uint32_t baudrate) +{ + rt_uint32_t divider; + divider = (BCM283X_CORE_CLK_HZ / baudrate) & 0xFFFE; + bcm283x_i2c_setClockDivider(no, (rt_uint16_t)divider); +} + +/* Writes an number of bytes to I2C */ +rt_uint8_t bcm283x_i2c_write(rt_uint32_t base, const rt_uint8_t * buf, rt_uint32_t len) +{ + volatile rt_uint32_t dlen = base + BCM283X_BSC_DLEN; + volatile rt_uint32_t fifo = base + BCM283X_BSC_FIFO; + volatile rt_uint32_t status = base + BCM283X_BSC_S; + volatile rt_uint32_t control = base + BCM283X_BSC_C; + + rt_uint32_t remaining = len; + rt_uint32_t i = 0; + rt_uint8_t reason = BCM283X_I2C_REASON_OK; + + /* Clear FIFO */ + bcm283x_peri_set_bits(control, BCM283X_BSC_C_CLEAR_1, BCM283X_BSC_C_CLEAR_1); + /* Clear Status */ + bcm283x_peri_write(status, BCM283X_BSC_S_CLKT | BCM283X_BSC_S_ERR | BCM283X_BSC_S_DONE); + /* Set Data Length */ + bcm283x_peri_write(dlen, len); + /* pre populate FIFO with max buffer */ + while(remaining && (i < BCM283X_BSC_FIFO_SIZE)) + { + bcm283x_peri_write_nb(fifo, buf[i]); + i++; + remaining--; + } + + /* Enable device and start transfer */ + bcm283x_peri_write(control, BCM283X_BSC_C_I2CEN | BCM283X_BSC_C_ST); + + /* Transfer is over when BCM2835_BSC_S_DONE */ + while(!(bcm283x_peri_read(status) & BCM283X_BSC_S_DONE)) + { + while (remaining && (bcm283x_peri_read(status) & BCM283X_BSC_S_TXD)) + { + /* Write to FIFO */ + bcm283x_peri_write(fifo, buf[i]); + i++; + remaining--; + } + } + + /* Received a NACK */ + if (bcm283x_peri_read(status) & BCM283X_BSC_S_ERR) + { + reason = BCM283X_I2C_REASON_ERROR_NACK; + } + + /* Received Clock Stretch Timeout */ + else if (bcm283x_peri_read(status) & BCM283X_BSC_S_CLKT) + { + reason = BCM283X_I2C_REASON_ERROR_CLKT; + } + + /* Not all data is sent */ + else if (remaining) + { + reason = BCM283X_I2C_REASON_ERROR_DATA; + } + + bcm283x_peri_set_bits(control, BCM283X_BSC_S_DONE, BCM283X_BSC_S_DONE); + + return reason; +} + +rt_uint8_t bcm283x_i2c_write_read_rs(char* cmds, rt_uint32_t cmds_len, char* buf, rt_uint32_t buf_len) +{ + volatile rt_uint32_t dlen = PER_BASE + BCM283X_BSC0_BASE + BCM283X_BSC_DLEN; + volatile rt_uint32_t fifo = PER_BASE + BCM283X_BSC0_BASE + BCM283X_BSC_FIFO; + volatile rt_uint32_t status = PER_BASE + BCM283X_BSC0_BASE + BCM283X_BSC_S; + volatile rt_uint32_t control = PER_BASE + BCM283X_BSC0_BASE + BCM283X_BSC_C; + + rt_uint32_t remaining = cmds_len; + rt_uint32_t i = 0; + rt_uint8_t reason = BCM283X_I2C_REASON_OK; + + /* Clear FIFO */ + bcm283x_peri_set_bits(control, BCM283X_BSC_C_CLEAR_1, BCM283X_BSC_C_CLEAR_1); + + /* Clear Status */ + bcm283x_peri_write(status, BCM283X_BSC_S_CLKT | BCM283X_BSC_S_ERR | BCM283X_BSC_S_DONE); + + /* Set Data Length */ + bcm283x_peri_write(dlen, cmds_len); + + /* pre populate FIFO with max buffer */ + while(remaining && (i < BCM283X_BSC_FIFO_SIZE)) + { + bcm283x_peri_write_nb(fifo, cmds[i]); + i++; + remaining--; + } + + /* Enable device and start transfer */ + bcm283x_peri_write(control, BCM283X_BSC_C_I2CEN | BCM283X_BSC_C_ST); + + /* poll for transfer has started (way to do repeated start, from BCM2835 datasheet) */ + while (!(bcm283x_peri_read(status) & BCM283X_BSC_S_TA)) + { + /* Linux may cause us to miss entire transfer stage */ + if (bcm283x_peri_read_nb(status) & BCM283X_BSC_S_DONE) + break; + } + + remaining = buf_len; + i = 0; + + /* Send a repeated start with read bit set in address */ + bcm283x_peri_write(dlen, buf_len); + bcm283x_peri_write(control, BCM283X_BSC_C_I2CEN | BCM283X_BSC_C_ST | BCM283X_BSC_C_READ); + + /* Wait for write to complete and first byte back. */ + bcm283x_clo_delayMicros(100); + + /* wait for transfer to complete */ + while (!(bcm283x_peri_read_nb(status) & BCM283X_BSC_S_DONE)) + { + /* we must empty the FIFO as it is populated and not use any delay */ + while (remaining && bcm283x_peri_read(status) & BCM283X_BSC_S_RXD) + { + /* Read from FIFO, no barrier */ + buf[i] = bcm283x_peri_read_nb(fifo); + i++; + remaining--; + } + } + + /* transfer has finished - grab any remaining stuff in FIFO */ + while (remaining && (bcm283x_peri_read(status) & BCM283X_BSC_S_RXD)) + { + /* Read from FIFO */ + buf[i] = bcm283x_peri_read(fifo); + i++; + remaining--; + } + + /* Received a NACK */ + if (bcm283x_peri_read(status) & BCM283X_BSC_S_ERR) + { + reason = BCM283X_I2C_REASON_ERROR_NACK; + } + + /* Received Clock Stretch Timeout */ + else if (bcm283x_peri_read(status) & BCM283X_BSC_S_CLKT) + { + reason = BCM283X_I2C_REASON_ERROR_CLKT; + } + + /* Not all data is sent */ + else if (remaining) + { + reason = BCM283X_I2C_REASON_ERROR_DATA; + } + + bcm283x_peri_set_bits(control, BCM283X_BSC_S_DONE, BCM283X_BSC_S_DONE); + + return reason; +} diff --git a/bsp/raspberry-pi/raspi3-64/driver/bcm283x.h b/bsp/raspberry-pi/raspi3-64/driver/bcm283x.h new file mode 100644 index 0000000000000000000000000000000000000000..fc9ed1feab06c3451447dff420c3b1f4e7eb4486 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/bcm283x.h @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-15 RT-Thread the first version + * 2019-07-29 zdzn add macro definition + */ + +#ifndef __BCM283X_H__ +#define __BCM283X_H__ + +#include +#include + +#define PER_BASE (0x3F000000) +#define PER_BASE_40000000 (0x40000000) + + +#define HIGH 0x1 +#define LOW 0x0 + +#define BCM283X_CORE_CLK_HZ 250000000 /* 50 MHz */ + +/*! Offsets for the bases of various peripherals within the peripherals block + * Base Address of the System Timer registers + */ +/*! Base Address of the Pads registers */ +#define BCM283X_GPIO_PADS 0x100000 +/*! Base Address of the Clock/timer registers */ +#define BCM283X_CLOCK_BASE 0x101000 +/*! Base Address of the GPIO registers */ +//#define BCM283X_GPIO_BASE 0x200000 +/*! Base Address of the SPI0 registers */ +#define BCM283X_SPI0_BASE 0x204000 +/*! Base Address of the PWM registers */ +#define BCM283X_GPIO_PWM 0x20C000 +/*! Base Address of the AUX registers */ +#define BCM283X_AUX_BASE 0x215000 +/*! Base Address of the AUX_SPI1 registers */ +#define BCM283X_SPI1_BASE 0x215080 +/*! Base Address of the AUX_SPI2 registers */ +#define BCM283X_SPI2_BASE 0x2150C0 + +/*! Base Address of the BSC0 registers */ +#define BCM283X_BSC0_BASE 0x205000 //for i2c0 +/*! Base Address of the BSC1 registers */ +#define BCM283X_BSC1_BASE 0x804000 //for i2c1 +/*! Base Address of the BSC1 registers */ +#define BCM283X_BSC2_BASE 0x805000 //for hdmi i2c not use + +/* + * GPIO + */ +#define GPIO_BASE (PER_BASE + 0x200000) +#define GPIO_GPFSEL0 HWREG32(GPIO_BASE + 0x0000) /* GPIO Function Select 0 32bit R/W */ +#define GPIO_GPFSEL1 HWREG32(GPIO_BASE + 0x0004) /* GPIO Function Select 1 32bit R/W */ +#define GPIO_GPFSEL2 HWREG32(GPIO_BASE + 0x0008) /* GPIO Function Select 2 32bit R/W */ +#define GPIO_GPFSEL4 HWREG32(GPIO_BASE + 0x0010) /* GPIO Function Select 4 32bit R/W */ +#define GPIO_GPFSEL5 HWREG32(GPIO_BASE + 0x0014) /* GPIO Function Select 5 32bit R/W */ +#define GPIO_GPSET0 HWREG32(GPIO_BASE + 0x001C) +#define GPIO_GPSET1 HWREG32(GPIO_BASE + 0x0020) +#define GPIO_GPCLR0 HWREG32(GPIO_BASE + 0x0028) +#define GPIO_GPCLR1 HWREG32(GPIO_BASE + 0x002C) +#define GPIO_GPEDS0 HWREG32(GPIO_BASE + 0x0040) /* GPIO Pin Event Detect Status */ +#define GPIO_GPEDS1 HWREG32(GPIO_BASE + 0x0044) +#define GPIO_GPREN0 HWREG32(GPIO_BASE + 0x004c) /* GPIO Pin Rising Edge Detect Enable */ +#define GPIO_GPREN1 HWREG32(GPIO_BASE + 0x0050) +#define GPIO_GPFEN0 HWREG32(GPIO_BASE + 0x0058) /* GPIO Pin Falling Edge Detect Enable */ +#define GPIO_GPFEN1 HWREG32(GPIO_BASE + 0x005C) +#define GPIO_GPHEN0 HWREG32(GPIO_BASE + 0x0064) /* GPIO Pin High Detect Enable */ +#define GPIO_GPHEN1 HWREG32(GPIO_BASE + 0x0068) +#define GPIO_GPLEN0 HWREG32(GPIO_BASE + 0x0070) /* GPIO Pin Low Detect Enable 0 */ +#define GPIO_GPLEN1 HWREG32(GPIO_BASE + 0x0074) +#define GPIO_GPAREN0 HWREG32(GPIO_BASE + 0x007C) /* GPIO Pin Async. Rising Edge Detect */ +#define GPIO_GPAREN1 HWREG32(GPIO_BASE + 0x0080) +#define GPIO_GPAFEN0 HWREG32(GPIO_BASE + 0x0088) /* GPIO Pin Async. Falling Edge Detect */ +#define GPIO_GPAFEN1 HWREG32(GPIO_BASE + 0x008C) +#define GPIO_GPPUD HWREG32(GPIO_BASE + 0x0094) /* GPIO Pin Pull-up/down Enable */ +#define GPIO_GPPUDCLK0 HWREG32(GPIO_BASE + 0x0098) /* GPIO Pin Pull-up/down Enable Clock 0 */ +#define GPIO_GPPUDCLK1 HWREG32(GPIO_BASE + 0x009C) /* GPIO Pin Pull-up/down Enable Clock 1 */ + +#define BCM283X_GPIO_BASE (PER_BASE + 0x200000) +#define BCM283X_GPIO_GPFSEL0 (0x0000) /* GPIO Function Select 0 32bit R/W */ +#define BCM283X_GPIO_GPFSEL1 (0x0004) /* GPIO Function Select 1 32bit R/W */ +#define BCM283X_GPIO_GPFSEL2 (0x0008) /* GPIO Function Select 2 32bit R/W */ +#define BCM283X_GPIO_GPFSEL4 (0x0010) /* GPIO Function Select 4 32bit R/W */ +#define BCM283X_GPIO_GPFSEL5 (0x0014) /* GPIO Function Select 5 32bit R/W */ +#define BCM283X_GPIO_GPSET0 (0x001C) +#define BCM283X_GPIO_GPSET1 (0x0020) +#define BCM283X_GPIO_GPCLR0 (0x0028) +#define BCM283X_GPIO_GPCLR1 (0x002C) +#define BCM2835_GPIO_GPLEV0 (0x0034) /*!< GPIO Pin Level 0 */ +#define BCM2835_GPIO_GPLEV1 (0x0038) /*!< GPIO Pin Level 1 */ +#define BCM283X_GPIO_GPEDS0 (0x0040) /* GPIO Pin Event Detect Status */ +#define BCM283X_GPIO_GPEDS1 (0x0044) +#define BCM283X_GPIO_GPREN0 (0x004c) /* GPIO Pin Rising Edge Detect Enable */ +#define BCM283X_GPIO_GPREN1 (0x0050) +#define BCM283X_GPIO_GPFEN0 (0x0058) /* GPIO Pin Falling Edge Detect Enable */ +#define BCM283X_GPIO_GPFEN1 (0x005C) +#define BCM283X_GPIO_GPHEN0 (0x0064) /* GPIO Pin High Detect Enable */ +#define BCM283X_GPIO_GPHEN1 (0x0068) +#define BCM283X_GPIO_GPLEN0 (0x0070) /* GPIO Pin Low Detect Enable 0 */ +#define BCM283X_GPIO_GPLEN1 (0x0074) +#define BCM283X_GPIO_GPAREN0 (0x007C) /* GPIO Pin Async. Rising Edge Detect */ +#define BCM283X_GPIO_GPAREN1 (0x0080) +#define BCM283X_GPIO_GPAFEN0 (0x0088) /* GPIO Pin Async. Falling Edge Detect */ +#define BCM283X_GPIO_GPAFEN1 (0x008C) +#define BCM283X_GPIO_GPPUD (0x0094) /* GPIO Pin Pull-up/down Enable */ +#define BCM283X_GPIO_GPPUDCLK0 (0x0098) /* GPIO Pin Pull-up/down Enable Clock 0 */ +#define BCM283X_GPIO_GPPUDCLK1 (0x009C) /* GPIO Pin Pull-up/down Enable Clock 1 */ + +enum gpio_function_select +{ + BCM283X_GPIO_FSEL_INPT = 0x00, /*!< Input 0b000 */ + BCM283X_GPIO_FSEL_OUTP = 0x01, /*!< Output 0b001 */ + BCM283X_GPIO_FSEL_ALT0 = 0x04, /*!< Alternate function 0 0b100 */ + BCM283X_GPIO_FSEL_ALT1 = 0x05, /*!< Alternate function 1 0b101 */ + BCM283X_GPIO_FSEL_ALT2 = 0x06, /*!< Alternate function 2 0b110, */ + BCM283X_GPIO_FSEL_ALT3 = 0x07, /*!< Alternate function 3 0b111 */ + BCM283X_GPIO_FSEL_ALT4 = 0x03, /*!< Alternate function 4 0b011 */ + BCM283X_GPIO_FSEL_ALT5 = 0x02, /*!< Alternate function 5 0b010 */ + BCM283X_GPIO_FSEL_MASK = 0x07 /*!< Function select bits mask 0b111 */ +}; + +enum gpio_pud_mode +{ + BCM283X_GPIO_PUD_OFF = 0x00, /*!< Off ? disable pull-up/down 0b00 */ + BCM283X_GPIO_PUD_DOWN = 0x01, /*!< Enable Pull Down control 0b01 */ + BCM283X_GPIO_PUD_UP = 0x02 /*!< Enable Pull Up control 0b10 */ +}; + +/* Defines for BSC I2C + * GPIO register offsets from BCM283X_BSC*_BASE. + * Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map + */ +/* I2C Address Map offset address */ +#define BCM283X_BSC_C 0x0000 /*!< BSC Master Control */ +#define BCM283X_BSC_S 0x0004 /*!< BSC Master Status */ +#define BCM283X_BSC_DLEN 0x0008 /*!< BSC Master Data Length */ +#define BCM283X_BSC_A 0x000c /*!< BSC Master Slave Address */ +#define BCM283X_BSC_FIFO 0x0010 /*!< BSC Master Data FIFO */ +#define BCM283X_BSC_DIV 0x0014 /*!< BSC Master Clock Divider */ +#define BCM283X_BSC_DEL 0x0018 /*!< BSC Master Data Delay */ +#define BCM283X_BSC_CLKT 0x001c /*!< BSC Master Clock Stretch Timeout */ + +/* Register masks for C Register */ +#define BCM283X_BSC_C_I2CEN 0x00008000 /*!< I2C Enable, 0 = disabled, 1 = enabled */ +#define BCM283X_BSC_C_INTR 0x00000400 /*!< Interrupt on RX */ +#define BCM283X_BSC_C_INTT 0x00000200 /*!< Interrupt on TX */ +#define BCM283X_BSC_C_INTD 0x00000100 /*!< Interrupt on DONE */ +#define BCM283X_BSC_C_ST 0x00000080 /*!< Start transfer, 1 = Start a new transfer */ +#define BCM283X_BSC_C_CLEAR_1 0x00000020 /*!< Clear FIFO Clear */ +#define BCM283X_BSC_C_CLEAR_2 0x00000010 /*!< Clear FIFO Clear */ +#define BCM283X_BSC_C_READ 0x00000001 /*!< Read transfer */ + +/* Register masks for S Register */ +#define BCM283X_BSC_S_CLKT 0x00000200 /*!< Clock stretch timeout */ +#define BCM283X_BSC_S_ERR 0x00000100 /*!< ACK error */ +#define BCM283X_BSC_S_RXF 0x00000080 /*!< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ +#define BCM283X_BSC_S_TXE 0x00000040 /*!< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full */ +#define BCM283X_BSC_S_RXD 0x00000020 /*!< RXD FIFO contains data */ +#define BCM283X_BSC_S_TXD 0x00000010 /*!< TXD FIFO can accept data */ +#define BCM283X_BSC_S_RXR 0x00000008 /*!< RXR FIFO needs reading (full) */ +#define BCM283X_BSC_S_TXW 0x00000004 /*!< TXW FIFO needs writing (full) */ +#define BCM283X_BSC_S_DONE 0x00000002 /*!< Transfer DONE */ +#define BCM283X_BSC_S_TA 0x00000001 /*!< Transfer Active */ + +#define BCM283X_BSC_FIFO_SIZE 16 /*!< BSC FIFO size */ + +enum i2c_clock_divider +{ + BCM283X_I2C_CLOCK_DIVIDER_2500 = 2500, /*!< 2500 = 10us = 100 kHz */ + BCM283X_I2C_CLOCK_DIVIDER_626 = 626, /*!< 622 = 2.504us = 399.3610 kHz */ + BCM283X_I2C_CLOCK_DIVIDER_150 = 150, /*!< 150 = 60ns = 1.666 MHz (default at reset) */ + BCM283X_I2C_CLOCK_DIVIDER_148 = 148 /*!< 148 = 59ns = 1.689 MHz */ +}; + +enum i2c_reason_codes +{ + BCM283X_I2C_REASON_OK = 0x00, /*!< Success */ + BCM283X_I2C_REASON_ERROR_NACK = 0x01, /*!< Received a NACK */ + BCM283X_I2C_REASON_ERROR_CLKT = 0x02, /*!< Received Clock Stretch Timeout */ + BCM283X_I2C_REASON_ERROR_DATA = 0x04 /*!< Not all data is sent / received */ +}; + +/* + * Interrupt Controler + */ +#define IRQ_BASE (PER_BASE + 0xB200) +#define IRQ_PEND_BASIC HWREG32(IRQ_BASE + 0x00) +#define IRQ_PEND1 HWREG32(IRQ_BASE + 0x04) +#define IRQ_PEND2 HWREG32(IRQ_BASE + 0x08) +#define IRQ_FIQ_CONTROL HWREG32(IRQ_BASE + 0x0C) +#define IRQ_ENABLE1 HWREG32(IRQ_BASE + 0x10) +#define IRQ_ENABLE2 HWREG32(IRQ_BASE + 0x14) +#define IRQ_ENABLE_BASIC HWREG32(IRQ_BASE + 0x18) +#define IRQ_DISABLE1 HWREG32(IRQ_BASE + 0x1C) +#define IRQ_DISABLE2 HWREG32(IRQ_BASE + 0x20) +#define IRQ_DISABLE_BASIC HWREG32(IRQ_BASE + 0x24) + +/* + * System Timer + */ +#define STIMER_BASE (PER_BASE + 0x3000) +#define STIMER_CS HWREG32(STIMER_BASE + 0x00) +#define STIMER_CLO HWREG32(STIMER_BASE + 0x04) +#define STIMER_CHI HWREG32(STIMER_BASE + 0x08) +#define STIMER_C0 HWREG32(STIMER_BASE + 0x0C) +#define STIMER_C1 HWREG32(STIMER_BASE + 0x10) +#define STIMER_C2 HWREG32(STIMER_BASE + 0x14) +#define STIMER_C3 HWREG32(STIMER_BASE + 0x18) + +/* Defines for ST */ +#define BCM283X_ST_BASE (PER_BASE + 0x3000) +#define BCM283X_ST_CS 0x0000 /*!< System Timer Control/Status */ +#define BCM283X_ST_CLO 0x0004 /*!< System Timer Counter Lower 32 bits */ +#define BCM283X_ST_CHI 0x0008 /*!< System Timer Counter Upper 32 bits */ +#define BCM283X_ST_C0 0x000C +#define BCM283X_ST_C1 0x0010 +#define BCM283X_ST_C2 0x0014 +#define BCM283X_ST_C3 0x0018 + +/* + * ARM Timer + */ +#define ARM_TIMER_BASE (PER_BASE + 0xB000) +#define ARM_TIMER_LOAD HWREG32(ARM_TIMER_BASE + 0x400) +#define ARM_TIMER_VALUE HWREG32(ARM_TIMER_BASE + 0x404) +#define ARM_TIMER_CTRL HWREG32(ARM_TIMER_BASE + 0x408) +#define ARM_TIMER_IRQCLR HWREG32(ARM_TIMER_BASE + 0x40C) +#define ARM_TIMER_RAWIRQ HWREG32(ARM_TIMER_BASE + 0x410) +#define ARM_TIMER_MASKIRQ HWREG32(ARM_TIMER_BASE + 0x414) +#define ARM_TIMER_RELOAD HWREG32(ARM_TIMER_BASE + 0x418) +#define ARM_TIMER_PREDIV HWREG32(ARM_TIMER_BASE + 0x41C) +#define ARM_TIMER_CNTR HWREG32(ARM_TIMER_BASE + 0x420) + +/* + * Core Timer + */ +#define CTIMER_CTL HWREG32(PER_BASE_40000000 + 0x00) /* Control register */ +#define CTIMER_PRE HWREG32(PER_BASE_40000000 + 0x08) /* Core timer prescaler */ +#define CTIMER_LS32B HWREG32(PER_BASE_40000000 + 0x1C) /* Core timer access LS 32 bits */ +#define CTIMER_MS32B HWREG32(PER_BASE_40000000 + 0x20) /* Core timer access MS 32 bits */ + +/* + * ARM Core Timer + */ +#define C0TIMER_INTCTL HWREG32(PER_BASE_40000000 + 0x40) /* Core0 timers Interrupt control */ +#define C1TIMER_INTCTL HWREG32(PER_BASE_40000000 + 0x44) /* Core1 timers Interrupt control */ +#define C2TIMER_INTCTL HWREG32(PER_BASE_40000000 + 0x48) /* Core2 timers Interrupt control */ +#define C3TIMER_INTCTL HWREG32(PER_BASE_40000000 + 0x4C) /* Core3 timers Interrupt control */ +#define CORETIMER_INTCTL(n) HWREG32(PER_BASE_40000000 + 0x40 + n*4) /* Core3 timers Interrupt control */ +/* + * ARM Core Mailbox interrupt + */ +#define C0MB_INTCTL HWREG32(PER_BASE_40000000 + 0x50) /* Core0 Mailboxes Interrupt control */ +#define C1MB_INTCTL HWREG32(PER_BASE_40000000 + 0x54) /* Core1 Mailboxes Interrupt control */ +#define C2MB_INTCTL HWREG32(PER_BASE_40000000 + 0x58) /* Core2 Mailboxes Interrupt control */ +#define C3MB_INTCTL HWREG32(PER_BASE_40000000 + 0x5C) /* Core3 Mailboxes Interrupt control */ +#define COREMB_INTCTL(n) HWREG32(PER_BASE_40000000 + 0x50 + 4*n) /* Core3 Mailboxes Interrupt control */ +/* + * ARM Core IRQ/FIQ status + */ +#define C0_IRQSOURCE HWREG32(PER_BASE_40000000 + 0x60) /* Core0 IRQ Source */ +#define C1_IRQSOURCE HWREG32(PER_BASE_40000000 + 0x64) /* Core1 IRQ Source */ +#define C2_IRQSOURCE HWREG32(PER_BASE_40000000 + 0x68) /* Core2 IRQ Source */ +#define C3_IRQSOURCE HWREG32(PER_BASE_40000000 + 0x6C) /* Core3 IRQ Source */ +#define C0_FIQSOURCE HWREG32(PER_BASE_40000000 + 0x70) /* Core0 FIQ Source */ +#define C1_FIQSOURCE HWREG32(PER_BASE_40000000 + 0x74) /* Core1 FIQ Source */ +#define C2_FIQSOURCE HWREG32(PER_BASE_40000000 + 0x78) /* Core2 FIQ Source */ +#define C3_FIQSOURCE HWREG32(PER_BASE_40000000 + 0x7C) /* Core3 FIQ Source */ +#define CORE_IRQSOURCE(n) HWREG32(PER_BASE_40000000 + 0x60+ n*0x4) +#define CORE_FIQSOURCE(n) HWREG32(PER_BASE_40000000 + 0x70+ n*0x4) + +#define CORE_MAILBOX3_SET(n) HWREG32(PER_BASE_40000000 + 0x8C + n*0x10) +#define CORE_MAILBOX3_CLEAR(n) HWREG32(PER_BASE_40000000 + 0xCC + n*0x10) +#define CORE_MAILBOX2_SET(n) HWREG32(PER_BASE_40000000 + 0x88 + n*0x10) +#define CORE_MAILBOX2_CLEAR(n) HWREG32(PER_BASE_40000000 + 0xC8 + n*0x10) +#define CORE_MAILBOX1_SET(n) HWREG32(PER_BASE_40000000 + 0x84 + n*0x10) +#define CORE_MAILBOX1_CLEAR(n) HWREG32(PER_BASE_40000000 + 0xC4 + n*0x10) +#define CORE_MAILBOX0_SET(n) HWREG32(PER_BASE_40000000 + 0x80 + n*0x10) +#define CORE_MAILBOX0_CLEAR(n) HWREG32(PER_BASE_40000000 + 0xC0 + n*0x10) + +/* for smp ipi using mailbox0 */ +#define IPI_MAILBOX_SET CORE_MAILBOX0_SET + +#define IPI_MAILBOX_CLEAR CORE_MAILBOX0_CLEAR +#define IPI_MAILBOX_INT_MASK (0x01) + +#define IRQ_ARM_TIMER 64 +#define IRQ_ARM_MAILBOX 65 +#define IRQ_ARM_DB0 66 +#define IRQ_ARM_DB1 67 +#define IRQ_ARM_GPU0_HALT 68 +#define IRQ_ARM_GPU1_HALT 69 +#define IRQ_ARM_ILLEGAL_ACC1 70 +#define IRQ_ARM_ILLEGAL_ACC0 71 + +#define IRQ_SYSTIMER_MATCH_1 1 +#define IRQ_SYSTIMER_MATCH_3 3 + +#define IRQ_AUX 29 +#define IRQ_IIC_SPI_SLV 43 +#define IRQ_PWA0 45 +#define IRQ_PWA1 46 +#define IRQ_SMI 48 +#define IRQ_GPIO0 49 +#define IRQ_GPIO1 50 +#define IRQ_GPIO2 51 +#define IRQ_GPIO3 52 +#define IRQ_IIC 53 +#define IRQ_SPI 54 +#define IRQ_PCM 55 +#define IRQ_UART 57 + +/* CLOCK */ +#define BCM283X_PLLA 0 +#define BCM283X_PLLB 1 +#define BCM283X_PLLC 2 +#define BCM283X_PLLD 3 +#define BCM283X_PLLH 4 + +#define BCM283X_PLLA_CORE 5 +#define BCM283X_PLLA_PER 6 +#define BCM283X_PLLB_ARM 7 +#define BCM283X_PLLC_CORE0 8 +#define BCM283X_PLLC_CORE1 9 +#define BCM283X_PLLC_CORE2 10 +#define BCM283X_PLLC_PER 11 +#define BCM283X_PLLD_CORE 12 +#define BCM283X_PLLD_PER 13 +#define BCM283X_PLLH_RCAL 14 +#define BCM283X_PLLH_AUX 15 +#define BCM283X_PLLH_PIX 16 + +#define BCM283X_CLOCK_TIMER 17 +#define BCM283X_CLOCK_OTP 18 +#define BCM283X_CLOCK_UART 19 +#define BCM283X_CLOCK_VPU 20 +#define BCM283X_CLOCK_V3D 21 +#define BCM283X_CLOCK_ISP 22 +#define BCM283X_CLOCK_H264 23 +#define BCM283X_CLOCK_VEC 24 +#define BCM283X_CLOCK_HSM 25 +#define BCM283X_CLOCK_SDRAM 26 +#define BCM283X_CLOCK_TSENS 27 +#define BCM283X_CLOCK_EMMC 28 +#define BCM283X_CLOCK_PERI_IMAGE 29 +#define BCM283X_CLOCK_COUNT 30 + +#define CM_PASSWORD 0x5a000000 + +#define CM_GNRICCTL 0x000 +#define CM_GNRICDIV 0x004 +#define CM_VPUCTL 0x008 +#define CM_VPUDIV 0x00c +#define CM_SYSCTL 0x010 +#define CM_SYSDIV 0x014 +#define CM_PERIACTL 0x018 +#define CM_PERIADIV 0x01c +#define CM_PERIICTL 0x020 +#define CM_PERIIDIV 0x024 +#define CM_H264CTL 0x028 +#define CM_H264DIV 0x02c +#define CM_ISPCTL 0x030 +#define CM_ISPDIV 0x034 +#define CM_V3DCTL 0x038 +#define CM_V3DDIV 0x03c +#define CM_CAM0CTL 0x040 +#define CM_CAM0DIV 0x044 +#define CM_CAM1CTL 0x048 +#define CM_CAM1DIV 0x04c +#define CM_CCP2CTL 0x050 +#define CM_CCP2DIV 0x054 +#define CM_DSI0ECTL 0x058 +#define CM_DSI0EDIV 0x05c +#define CM_DSI0PCTL 0x060 +#define CM_DSI0PDIV 0x064 +#define CM_DPICTL 0x068 +#define CM_DPIDIV 0x06c +#define CM_GP0CTL 0x070 +#define CM_GP0DIV 0x074 +#define CM_GP1CTL 0x078 +#define CM_GP1DIV 0x07c +#define CM_GP2CTL 0x080 +#define CM_GP2DIV 0x084 +#define CM_HSMCTL 0x088 +#define CM_HSMDIV 0x08c +#define CM_OTPCTL 0x090 +#define CM_OTPDIV 0x094 +#define CM_PWMCTL 0x0a0 +#define CM_PWMDIV 0x0a4 +#define CM_SMICTL 0x0b0 +#define CM_SMIDIV 0x0b4 +#define CM_TSENSCTL 0x0e0 +#define CM_TSENSDIV 0x0e4 +#define CM_TIMERCTL 0x0e8 +#define CM_TIMERDIV 0x0ec +#define CM_UARTCTL 0x0f0 +#define CM_UARTDIV 0x0f4 +#define CM_VECCTL 0x0f8 +#define CM_VECDIV 0x0fc +#define CM_PULSECTL 0x190 +#define CM_PULSEDIV 0x194 +#define CM_SDCCTL 0x1a8 +#define CM_SDCDIV 0x1ac +#define CM_ARMCTL 0x1b0 +#define CM_EMMCCTL 0x1c0 +#define CM_EMMCDIV 0x1c4 + +#define BCM283X_AUX_IRQ 0x0000 /*!< xxx */ +#define BCM283X_AUX_ENABLE 0x0004 /*!< */ +#define BCM283X_AUX_ENABLE_UART1 0x01 /*!< */ +#define BCM283X_AUX_ENABLE_SPI0 0x02 /*!< SPI0 (SPI1 in the device) */ +#define BCM283X_AUX_ENABLE_SPI1 0x04 /*!< SPI1 (SPI2 in the device) */ +#define BCM283X_AUX_SPI_CNTL0 0x0000 /*!< */ +#define BCM283X_AUX_SPI_CNTL1 0x0004 /*!< */ +#define BCM283X_AUX_SPI_STAT 0x0008 /*!< */ +#define BCM283X_AUX_SPI_PEEK 0x000C /*!< Read but do not take from FF */ +#define BCM283X_AUX_SPI_IO 0x0020 /*!< Write = TX, read=RX */ +#define BCM283X_AUX_SPI_TXHOLD 0x0030 /*!< Write = TX keep CS, read=RX */ +#define BCM283X_AUX_SPI_CLOCK_MIN 30500 /*!< 30,5kHz */ +#define BCM283X_AUX_SPI_CLOCK_MAX 125000000 /*!< 125Mhz */ +#define BCM283X_AUX_SPI_CNTL0_SPEED 0xFFF00000 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_SPEED_MAX 0xFFF /*!< */ +#define BCM283X_AUX_SPI_CNTL0_SPEED_SHIFT 20 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_CS0_N 0x000C0000 /*!< CS 0 low */ +#define BCM283X_AUX_SPI_CNTL0_CS1_N 0x000A0000 /*!< CS 1 low */ +#define BCM283X_AUX_SPI_CNTL0_CS2_N 0x00060000 /*!< CS 2 low */ +#define BCM283X_AUX_SPI_CNTL0_POSTINPUT 0x00010000 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_VAR_CS 0x00008000 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_VAR_WIDTH 0x00004000 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_DOUTHOLD 0x00003000 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_ENABLE 0x00000800 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_CPHA_IN 0x00000400 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_CLEARFIFO 0x00000200 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_CPHA_OUT 0x00000100 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_CPOL 0x00000080 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_MSBF_OUT 0x00000040 /*!< */ +#define BCM283X_AUX_SPI_CNTL0_SHIFTLEN 0x0000003F /*!< */ +#define BCM283X_AUX_SPI_CNTL1_CSHIGH 0x00000700 /*!< */ +#define BCM283X_AUX_SPI_CNTL1_IDLE 0x00000080 /*!< */ +#define BCM283X_AUX_SPI_CNTL1_TXEMPTY 0x00000040 /*!< */ +#define BCM283X_AUX_SPI_CNTL1_MSBF_IN 0x00000002 /*!< */ +#define BCM283X_AUX_SPI_CNTL1_KEEP_IN 0x00000001 /*!< */ +#define BCM283X_AUX_SPI_STAT_TX_LVL 0xFF000000 /*!< */ +#define BCM283X_AUX_SPI_STAT_RX_LVL 0x00FF0000 /*!< */ +#define BCM283X_AUX_SPI_STAT_TX_FULL 0x00000400 /*!< */ +#define BCM283X_AUX_SPI_STAT_TX_EMPTY 0x00000200 /*!< */ +#define BCM283X_AUX_SPI_STAT_RX_FULL 0x00000100 /*!< */ +#define BCM283X_AUX_SPI_STAT_RX_EMPTY 0x00000080 /*!< */ +#define BCM283X_AUX_SPI_STAT_BUSY 0x00000040 /*!< */ +#define BCM283X_AUX_SPI_STAT_BITCOUNT 0x0000003F /*!< */ + +/* Defines for SPI */ +#define BCM283X_SPI0_CS 0x0000 /*!< SPI Master Control and Status */ +#define BCM283X_SPI0_FIFO 0x0004 /*!< SPI Master TX and RX FIFOs */ +#define BCM283X_SPI0_CLK 0x0008 /*!< SPI Master Clock Divider */ +#define BCM283X_SPI0_DLEN 0x000c /*!< SPI Master Data Length */ +#define BCM283X_SPI0_LTOH 0x0010 /*!< SPI LOSSI mode TOH */ +#define BCM283X_SPI0_DC 0x0014 /*!< SPI DMA DREQ Controls */ + +/* Register masks for SPI0_CS */ +#define BCM283X_SPI0_CS_LEN_LONG 0x02000000 /*!< Enable Long data word in Lossi mode if DMA_LEN is set */ +#define BCM283X_SPI0_CS_DMA_LEN 0x01000000 /*!< Enable DMA mode in Lossi mode */ +#define BCM283X_SPI0_CS_CSPOL2 0x00800000 /*!< Chip Select 2 Polarity */ +#define BCM283X_SPI0_CS_CSPOL1 0x00400000 /*!< Chip Select 1 Polarity */ +#define BCM283X_SPI0_CS_CSPOL0 0x00200000 /*!< Chip Select 0 Polarity */ +#define BCM283X_SPI0_CS_RXF 0x00100000 /*!< RXF - RX FIFO Full */ +#define BCM283X_SPI0_CS_RXR 0x00080000 /*!< RXR RX FIFO needs Reading (full) */ +#define BCM283X_SPI0_CS_TXD 0x00040000 /*!< TXD TX FIFO can accept Data */ +#define BCM283X_SPI0_CS_RXD 0x00020000 /*!< RXD RX FIFO contains Data */ +#define BCM283X_SPI0_CS_DONE 0x00010000 /*!< Done transfer Done */ +#define BCM283X_SPI0_CS_TE_EN 0x00008000 /*!< Unused */ +#define BCM283X_SPI0_CS_LMONO 0x00004000 /*!< Unused */ +#define BCM283X_SPI0_CS_LEN 0x00002000 /*!< LEN LoSSI enable */ +#define BCM283X_SPI0_CS_REN 0x00001000 /*!< REN Read Enable */ +#define BCM283X_SPI0_CS_ADCS 0x00000800 /*!< ADCS Automatically Deassert Chip Select */ +#define BCM283X_SPI0_CS_INTR 0x00000400 /*!< INTR Interrupt on RXR */ +#define BCM283X_SPI0_CS_INTD 0x00000200 /*!< INTD Interrupt on Done */ +#define BCM283X_SPI0_CS_DMAEN 0x00000100 /*!< DMAEN DMA Enable */ +#define BCM283X_SPI0_CS_TA 0x00000080 /*!< Transfer Active */ +#define BCM283X_SPI0_CS_CSPOL 0x00000040 /*!< Chip Select Polarity */ +#define BCM283X_SPI0_CS_CLEAR 0x00000030 /*!< Clear FIFO Clear RX and TX */ +#define BCM283X_SPI0_CS_CLEAR_RX 0x00000020 /*!< Clear FIFO Clear RX */ +#define BCM283X_SPI0_CS_CLEAR_TX 0x00000010 /*!< Clear FIFO Clear TX */ +#define BCM283X_SPI0_CS_CPOL 0x00000008 /*!< Clock Polarity */ +#define BCM283X_SPI0_CS_CPHA 0x00000004 /*!< Clock Phase */ +#define BCM283X_SPI0_CS_CS 0x00000003 /*!< Chip Select */ + +enum spi_bit_order +{ + BCM283X_SPI_BIT_ORDER_LSBFIRST = 0, /*!< LSB First */ + BCM283X_SPI_BIT_ORDER_MSBFIRST = 1 /*!< MSB First */ +}; + +enum spi_mode +{ + BCM283X_SPI_MODE0 = 0, /*!< CPOL = 0, CPHA = 0 */ + BCM283X_SPI_MODE1 = 1, /*!< CPOL = 0, CPHA = 1 */ + BCM283X_SPI_MODE2 = 2, /*!< CPOL = 1, CPHA = 0 */ + BCM283X_SPI_MODE3 = 3 /*!< CPOL = 1, CPHA = 1 */ +}; + +enum spi_chip_select +{ + BCM283X_SPI_CS0 = 0, /*!< Chip Select 0 */ + BCM283X_SPI_CS1 = 1, /*!< Chip Select 1 */ + BCM283X_SPI_CS2 = 2, /*!< Chip Select 2 (ie pins CS1 and CS2 are asserted) */ + BCM283X_SPI_CS_NONE = 3 /*!< No CS, control it yourself */ +}; + +enum spi_clock_divider +{ + BCM283X_SPI_CLOCK_DIVIDER_65536 = 0, /*!< 65536 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_32768 = 32768, /*!< 32768 = 7.629394531kHz on Rpi2, 12.20703125kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_16384 = 16384, /*!< 16384 = 15.25878906kHz on Rpi2, 24.4140625kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_8192 = 8192, /*!< 8192 = 30.51757813kHz on Rpi2, 48.828125kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_4096 = 4096, /*!< 4096 = 61.03515625kHz on Rpi2, 97.65625kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_2048 = 2048, /*!< 2048 = 122.0703125kHz on Rpi2, 195.3125kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_1024 = 1024, /*!< 1024 = 244.140625kHz on Rpi2, 390.625kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_512 = 512, /*!< 512 = 488.28125kHz on Rpi2, 781.25kHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_256 = 256, /*!< 256 = 976.5625kHz on Rpi2, 1.5625MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_128 = 128, /*!< 128 = 1.953125MHz on Rpi2, 3.125MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_64 = 64, /*!< 64 = 3.90625MHz on Rpi2, 6.250MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_32 = 32, /*!< 32 = 7.8125MHz on Rpi2, 12.5MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_16 = 16, /*!< 16 = 15.625MHz on Rpi2, 25MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_8 = 8, /*!< 8 = 31.25MHz on Rpi2, 50MHz on RPI3 */ + BCM283X_SPI_CLOCK_DIVIDER_4 = 4, /*!< 4 = 62.5MHz on Rpi2, 100MHz on RPI3. Dont expect this speed to work reliably. */ + BCM283X_SPI_CLOCK_DIVIDER_2 = 2, /*!< 2 = 125MHz on Rpi2, 200MHz on RPI3, fastest you can get. Dont expect this speed to work reliably.*/ + BCM283X_SPI_CLOCK_DIVIDER_1 = 1 /*!< 1 = 3.814697260kHz on Rpi2, 6.1035156kHz on RPI3, same as 0/65536 */ +}; + +/* BCM IO pin */ +enum bcm_gpio_pin +{ + BCM_GPIO_PIN_0 = 0, + BCM_GPIO_PIN_1, + BCM_GPIO_PIN_2, + BCM_GPIO_PIN_3, + BCM_GPIO_PIN_4, + BCM_GPIO_PIN_5, + BCM_GPIO_PIN_6, + BCM_GPIO_PIN_7, + BCM_GPIO_PIN_8, + BCM_GPIO_PIN_9, + BCM_GPIO_PIN_10, + BCM_GPIO_PIN_11, + BCM_GPIO_PIN_12, + BCM_GPIO_PIN_13, + BCM_GPIO_PIN_14, + BCM_GPIO_PIN_15, + BCM_GPIO_PIN_16, + BCM_GPIO_PIN_17, + BCM_GPIO_PIN_18, + BCM_GPIO_PIN_19, + BCM_GPIO_PIN_20, + BCM_GPIO_PIN_21, + BCM_GPIO_PIN_22, + BCM_GPIO_PIN_23, + BCM_GPIO_PIN_24, + BCM_GPIO_PIN_25, + BCM_GPIO_PIN_26, + BCM_GPIO_PIN_27, + BCM_GPIO_PIN_28, + BCM_GPIO_PIN_29, + BCM_GPIO_PIN_30, + BCM_GPIO_PIN_31, + BCM_GPIO_PIN_32, + BCM_GPIO_PIN_33, + BCM_GPIO_PIN_34, + BCM_GPIO_PIN_35, + BCM_GPIO_PIN_36, + BCM_GPIO_PIN_37, + BCM_GPIO_PIN_38, + BCM_GPIO_PIN_39, + BCM_GPIO_PIN_40, + BCM_GPIO_PIN_41, + BCM_GPIO_PIN_42, + BCM_GPIO_PIN_43, + BCM_GPIO_PIN_44, + BCM_GPIO_PIN_45, + BCM_GPIO_PIN_46, + BCM_GPIO_PIN_47, + BCM_GPIO_PIN_48, + BCM_GPIO_PIN_49, + BCM_GPIO_PIN_50, + BCM_GPIO_PIN_51, + BCM_GPIO_PIN_52, + BCM_GPIO_PIN_53, + BCM_GPIO_PIN_NUM, +}; + +rt_uint32_t bcm283x_peri_read(volatile rt_ubase_t addr); +rt_uint32_t bcm283x_peri_read_nb(volatile rt_ubase_t addr); +void bcm283x_peri_write(volatile rt_ubase_t addr, rt_uint32_t value); +void bcm283x_peri_write_nb(volatile rt_ubase_t addr, rt_uint32_t value); +void bcm283x_peri_set_bits(volatile rt_ubase_t addr, rt_uint32_t value, rt_uint32_t mask); + +void bcm283x_gpio_fsel(rt_uint8_t pin, rt_uint8_t mode); +void bcm283x_gpio_set(rt_uint8_t pin); +void bcm283x_gpio_clr(rt_uint8_t pin); + +rt_uint8_t bcm283x_gpio_lev(rt_uint8_t pin); +rt_uint8_t bcm283x_gpio_eds(rt_uint8_t pin); +void bcm283x_gpio_set_eds(rt_uint8_t pin); +void bcm283x_gpio_ren(rt_uint8_t pin); +void bcm283x_gpio_clr_ren(rt_uint8_t pin); +void bcm283x_gpio_fen(rt_uint8_t pin); +void bcm283x_gpio_clr_fen(rt_uint8_t pin); +void bcm283x_gpio_hen(rt_uint8_t pin); +void bcm283x_gpio_clr_hen(rt_uint8_t pin); +void bcm283x_gpio_len(rt_uint8_t pin); +void bcm283x_gpio_clr_len(rt_uint8_t pin); +void bcm283x_gpio_aren(rt_uint8_t pin); +void bcm283x_gpio_clr_aren(rt_uint8_t pin); +void bcm283x_gpio_afen(rt_uint8_t pin); +void bcm283x_gpio_clr_afen(rt_uint8_t pin); +void bcm283x_gpio_pud(rt_uint8_t pud); +void bcm283x_gpio_pudclk(rt_uint8_t pin, rt_uint8_t on); +void bcm283x_gpio_set_pud(rt_uint8_t pin, rt_uint8_t pud); +void bcm283x_gpio_write(rt_uint8_t pin, rt_uint8_t val); +void bcm283x_st_delay(rt_uint64_t offset_micros, rt_uint64_t micros); +rt_uint64_t bcm283x_st_read(void); +void bcm283x_delayMicroseconds(rt_uint64_t micros); +void bcm283x_clo_delayMicros(rt_uint32_t micros); + +int bcm283x_i2c_begin(int no); +void bcm283x_i2c_end(int no); +void bcm283x_i2c_setSlaveAddress(int no, rt_uint8_t saddr); +void bcm283x_i2c_setClockDivider(int no, rt_uint16_t divider); +void bcm283x_i2c_set_baudrate(int no, rt_uint32_t baudrate); +rt_uint8_t bcm283x_i2c_read(rt_uint32_t base, rt_uint8_t* buf, rt_uint32_t len); +rt_uint8_t bcm283x_i2c_write(rt_uint32_t base, const rt_uint8_t * buf, rt_uint32_t len); +rt_uint8_t bcm283x_i2c_write_read_rs(char* cmds, rt_uint32_t cmds_len, char* buf, rt_uint32_t buf_len); + +#endif + diff --git a/bsp/raspberry-pi/raspi3-64/driver/board.c b/bsp/raspberry-pi/raspi3-64/driver/board.c new file mode 100644 index 0000000000000000000000000000000000000000..3c218d09a7060a64889164d47de0153cc3aa82c9 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/board.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include +#include + +#include "board.h" +#include "drv_uart.h" +#include "drv_timer.h" + +#include "cp15.h" + +#ifdef RT_USING_SMP +extern void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler); + +void ipi_handler(){ + rt_scheduler_ipi_handler(0,RT_NULL); +} +#endif + +void rt_hw_timer_isr(int vector, void *parameter) +{ + ARM_TIMER_IRQCLR = 0; + rt_tick_increase(); +} + +int rt_hw_timer_init() +{ + __DSB(); + rt_hw_interrupt_install(IRQ_ARM_TIMER, rt_hw_timer_isr, RT_NULL, "tick"); + rt_hw_interrupt_umask(IRQ_ARM_TIMER); + /* timer_clock = apb_clock/(pre_divider + 1) */ + ARM_TIMER_PREDIV = (250 - 1); + + ARM_TIMER_RELOAD = 0; + ARM_TIMER_LOAD = 0; + ARM_TIMER_IRQCLR = 0; + ARM_TIMER_CTRL = 0; + + ARM_TIMER_RELOAD = 10000; + ARM_TIMER_LOAD = 10000; + + /* 23-bit counter, enable interrupt, enable timer */ + ARM_TIMER_CTRL = (1 << 1) | (1 << 5) | (1 << 7); + return 0; +} + +void idle_wfi(void) +{ + asm volatile ("wfi"); +} + +#define MMU_LEVEL_MASK 0x1ffUL +#define MMU_MAP_ERROR_VANOTALIGN -1 +#define MMU_MAP_ERROR_PANOTALIGN -2 +#define MMU_MAP_ERROR_NOPAGE -3 +#define MMU_MAP_ERROR_CONFLICT -4 + +unsigned char main_tbl[4096] __attribute__((aligned (4096))); +unsigned char __page_start[4096*100] __attribute__((aligned (4096))); +unsigned long __page_off = 0; +unsigned long get_free_page(void) { + __page_off += 4096; + return (unsigned long)(__page_start + __page_off - 4096); +} + +#define MEM_ATTR_MEM ((0x1UL << 10) | (0x2UL << 8) | (0x0UL << 6) | (0x1UL << 2)) +#define MEM_ATTR_IO ((0x1UL << 10) | (0x2UL << 8) | (0x0UL << 6) | (0x2UL << 2)) + +static int map_single_page_2M(unsigned long* lv0_tbl, unsigned long va, unsigned long pa, unsigned long attr) { + int level; + unsigned long* cur_lv_tbl = lv0_tbl; + unsigned long page; + unsigned long off; + int level_shift = 39; + + if (va & (0x200000UL - 1)) { + return MMU_MAP_ERROR_VANOTALIGN; + } + if (pa & (0x200000UL - 1)) { + return MMU_MAP_ERROR_PANOTALIGN; + } + for (level = 0; level < 2; level++) { + off = (va >> level_shift); + off &= MMU_LEVEL_MASK; + if ((cur_lv_tbl[off] & 1) == 0) { + page = get_free_page(); + if (!page) { + return MMU_MAP_ERROR_NOPAGE; + } + rt_memset((void *)page, 0, 4096); + cur_lv_tbl[off] = page | 0x3UL; + } + page = cur_lv_tbl[off]; + if (!(page & 0x2)) { + //is block! error! + return MMU_MAP_ERROR_CONFLICT; + } + cur_lv_tbl = (unsigned long*)(page & 0x0000fffffffff000UL); + level_shift -= 9; + } + attr &= 0xfff0000000000ffcUL; + pa |= (attr | 0x1UL); //block + off = (va >> 21); + off &= MMU_LEVEL_MASK; + cur_lv_tbl[off] = pa; + return 0; +} + +int armv8_map_2M(unsigned long* lv0_tbl, unsigned long va, unsigned long pa, int count, unsigned long attr) +{ + int i; + int ret; + + if (va & (0x200000 - 1)) + { + return -1; + } + if (pa & (0x200000 - 1)) + { + return -1; + } + for (i = 0; i < count; i++) + { + ret = map_single_page_2M(lv0_tbl, va, pa, attr); + va += 0x200000; + pa += 0x200000; + if (ret != 0) + { + return ret; + } + } + return 0; +} + +/** + * Initialize the Hardware related stuffs. Called from rtthread_startup() + * after interrupt disabled. + */ +void rt_hw_board_init(void) +{ + /* mmu set */ + unsigned long val64; + unsigned long val32; //val32不是uint32_t,val32只是表示相关的那个寄存器是32位的 + int ret; + + val64 = 0x007f6eUL; + asm volatile("msr MAIR_EL1, %0\n dsb sy\n"::"r"(val64)); + asm volatile("mrs %0, MAIR_EL1\n dsb sy\n":"=r"(val64)); + + //TCR_EL1 + val32 = (16UL << 0) + | (0x0UL << 6) + | (0x0UL << 7) + | (0x3UL << 8) + | (0x3UL << 10) + | (0x2UL << 12) + | (0x0UL << 14) + | (0x0UL << 16) + | (0x0UL << 22) + | (0x1UL << 23) + | (0x2UL << 30) + | (0x1UL << 32) + | (0x0UL << 35) + | (0x0UL << 36) + | (0x0UL << 37) + | (0x0UL << 38); + asm volatile("msr TCR_EL1, %0\n"::"r"(val32)); + asm volatile("mrs %0, TCR_EL1\n":"=r"(val32)); + + asm volatile("msr TTBR0_EL1, %0\n dsb sy\n"::"r"(main_tbl)); + asm volatile("mrs %0, TTBR0_EL1\n dsb sy\n":"=r"(val64)); + + rt_memset(main_tbl, 0, 4096); + + ret = armv8_map_2M((unsigned long *)main_tbl, 0x0, 0x0, 32, MEM_ATTR_MEM); //32*2M = 64M + if (ret) + { + goto skip_mmu; + } + ret = armv8_map_2M((unsigned long *)main_tbl, 0x3f000000, 0x3f000000, 8, MEM_ATTR_IO); //8*2M = 16M + if (ret) + { + goto skip_mmu; + } + + //关闭指令cache + __asm__ volatile("mrs %0, SCTLR_EL1\n":"=r"(val64)); + val64 &= ~0x1000; //disable I + __asm__ volatile("dmb sy\n msr SCTLR_EL1, %0\n isb sy\n"::"r"(val64)); + + //清除指令cache + __asm__ volatile("IC IALLUIS\n dsb sy\n isb sy\n"); + //清除tlb + __asm__ volatile("tlbi vmalle1\n dsb sy\n isb sy\n"); + + //SCTLR_EL1, turn on mmu + asm volatile("mrs %0, SCTLR_EL1\n":"=r"(val32)); + val32 |= 0x1005; //enable mmu, I C M + asm volatile("dmb sy\n msr SCTLR_EL1, %0\nisb sy\n"::"r"(val32)); + +skip_mmu: + + /* initialize hardware interrupt */ + rt_hw_interrupt_init(); // in libcpu/interrupt.c. Set some data structures, no operation on device + rt_hw_vector_init(); // in libcpu/interrupt.c. == rt_cpu_vector_set_base((rt_ubase_t)&system_vectors); + + /* initialize uart */ + rt_hw_uart_init(); // driver/drv_uart.c + /* initialize timer for os tick */ + rt_hw_timer_init(); + rt_thread_idle_sethook(idle_wfi); + +#ifdef RT_USING_CONSOLE + /* set console device */ + rt_console_set_device(RT_CONSOLE_DEVICE_NAME); +#endif /* RT_USING_CONSOLE */ + +#ifdef RT_USING_HEAP + /* initialize memory system */ + rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); + rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END); +#endif + +#ifdef RT_USING_COMPONENTS_INIT + rt_components_board_init(); +#endif + rt_kprintf("__page_off = %x\n", __page_off); +} + +#ifdef RT_USING_SMP +void _reset(void); +void secondary_cpu_start(void); + +void rt_hw_secondary_cpu_up(void) +{ + int i; + int retry,val; + rt_cpu_dcache_clean_flush(); + rt_cpu_icache_flush(); + /*TODO maybe, there is some bug */ + for(i=RT_CPUS_NR-1; i>0; i-- ) + { + rt_kprintf("boot cpu:%d\n", i); + setup_bootstrap_addr(i, (int)_reset); + __SEV(); + __DSB(); + __ISB(); + retry = 10; + rt_thread_delay(RT_TICK_PER_SECOND/1000); + do + { + val = CORE_MAILBOX3_CLEAR(i); + if (val == 0) + { + rt_kprintf("start OK: CPU %d \n",i); + break; + } + rt_thread_delay(RT_TICK_PER_SECOND); + + retry --; + if (retry <= 0) + { + rt_kprintf("can't start for CPU %d \n",i); + break; + } + }while (1); + } + __DSB(); + __SEV(); +} + +void secondary_cpu_c_start(void) +{ + uint32_t id; + id = rt_hw_cpu_id(); + rt_kprintf("cpu = 0x%08x\n",id); + rt_hw_timer_init(); + rt_kprintf("cpu %d startup.\n",id); + rt_hw_vector_init(); + enable_cpu_ipi_intr(id); + rt_hw_spin_lock(&_cpus_lock); + rt_system_scheduler_start(); +} + +void rt_hw_secondary_cpu_idle_exec(void) +{ + __WFE(); +} + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/board.h b/bsp/raspberry-pi/raspi3-64/driver/board.h new file mode 100644 index 0000000000000000000000000000000000000000..40fbfd9d84711029b9fe07cd494bb13fb06874d4 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/board.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 Bernard the first version + */ + +#ifndef BOARD_H__ +#define BOARD_H__ + +#include + +#include +#include + +#define __REG32 HWREG32 +extern unsigned char __bss_start; +extern unsigned char __bss_end; + +#define RT_HW_HEAP_BEGIN (void*)&__bss_end +#define RT_HW_HEAP_END (void*)(RT_HW_HEAP_BEGIN + 4 * 1024 * 1024) + +void rt_hw_board_init(void); + +#endif + diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_fb.c b/bsp/raspberry-pi/raspi3-64/driver/drv_fb.c new file mode 100644 index 0000000000000000000000000000000000000000..485f7b587bbf1419d6ea110faae3bbced889c5dc --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_fb.c @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-29 zdzn first version + */ + +#include +#include +#include "mbox.h" +#include "drv_fb.h" +#include "mmu.h" + +#define CHAR_W 8 +#define CHAR_H 12 + +#define COLOR_DELTA 0.05 +static struct rt_hdmi_fb_device _hdmi; + +// https://github.com/xinu-os/xinu/blob/1789b7a50b5b73c2ea76ebd764c54a034097d04d/device/framebuffer_rpi/font.c +unsigned char FONT[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/ +0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*'!'*/ +0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'"'*/ +0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00, 0x00, 0x00, /*'#'*/ +0x00, 0x00, 0x08, 0x3c, 0x0a, 0x1c, 0x28, 0x1e, 0x08, 0x00, 0x00, 0x00, /*'$'*/ +0x00, 0x00, 0x06, 0x26, 0x10, 0x08, 0x04, 0x32, 0x30, 0x00, 0x00, 0x00, /*'%'*/ +0x00, 0x00, 0x1c, 0x02, 0x02, 0x04, 0x2a, 0x12, 0x2c, 0x00, 0x00, 0x00, /*'&'*/ +0x00, 0x18, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'''*/ +0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, /*'('*/ +0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x00, /*')'*/ +0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, /*'*'*/ +0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /*'+'*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /*','*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'-'*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /*'.'*/ +0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /*'/'*/ +0x00, 0x1c, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'0'*/ +0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'1'*/ +0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'2'*/ +0x00, 0x1c, 0x22, 0x20, 0x18, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'3'*/ +0x00, 0x10, 0x18, 0x18, 0x14, 0x14, 0x3e, 0x10, 0x38, 0x00, 0x00, 0x00, /*'4'*/ +0x00, 0x3e, 0x02, 0x02, 0x1e, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'5'*/ +0x00, 0x18, 0x04, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'6'*/ +0x00, 0x3e, 0x22, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, /*'7'*/ +0x00, 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'8'*/ +0x00, 0x1c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x10, 0x0c, 0x00, 0x00, 0x00, /*'9'*/ +0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /*':'*/ +0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /*';'*/ +0x00, 0x00, 0x00, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, /*'<'*/ +0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, /*'='*/ +0x00, 0x00, 0x00, 0x03, 0x0c, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, /*'>'*/ +0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*'?'*/ +0x00, 0x00, 0x1c, 0x22, 0x3a, 0x3a, 0x1a, 0x02, 0x1c, 0x00, 0x00, 0x00, /*'@'*/ +0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x00, 0x00, 0x00, /*'A'*/ +0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /*'B'*/ +0x00, 0x00, 0x1c, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'C'*/ +0x00, 0x00, 0x0e, 0x12, 0x22, 0x22, 0x22, 0x12, 0x0e, 0x00, 0x00, 0x00, /*'D'*/ +0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'E'*/ +0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'F'*/ +0x00, 0x00, 0x1c, 0x22, 0x02, 0x32, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /*'G'*/ +0x00, 0x00, 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'H'*/ +0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, /*'I'*/ +0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'J'*/ +0x00, 0x00, 0x22, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /*'K'*/ +0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'L'*/ +0x00, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'M'*/ +0x00, 0x00, 0x22, 0x26, 0x26, 0x2a, 0x32, 0x32, 0x22, 0x00, 0x00, 0x00, /*'N'*/ +0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'O'*/ +0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'P'*/ +0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x30, 0x00, 0x00, /*'Q'*/ +0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /*'R'*/ +0x00, 0x00, 0x1c, 0x22, 0x02, 0x1c, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'S'*/ +0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'T'*/ +0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'U'*/ +0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /*'V'*/ +0x00, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, 0x00, 0x00, 0x00, /*'W'*/ +0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00, 0x00, /*'X'*/ +0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'Y'*/ +0x00, 0x00, 0x3e, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'Z'*/ +0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, /*'['*/ +0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, /*'\'*/ +0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, /*']'*/ +0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'^'*/ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, /*'_'*/ +0x00, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'`'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /*'a'*/ +0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /*'b'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, /*'c'*/ +0x00, 0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /*'d'*/ +0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x02, 0x1c, 0x00, 0x00, 0x00, /*'e'*/ +0x00, 0x38, 0x04, 0x04, 0x1e, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, /*'f'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /*'g'*/ +0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'h'*/ +0x00, 0x08, 0x08, 0x00, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /*'i'*/ +0x00, 0x10, 0x10, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, /*'j'*/ +0x00, 0x02, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x00, 0x00, 0x00, /*'k'*/ +0x00, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /*'l'*/ +0x00, 0x00, 0x00, 0x00, 0x16, 0x2a, 0x2a, 0x2a, 0x22, 0x00, 0x00, 0x00, /*'m'*/ +0x00, 0x00, 0x00, 0x00, 0x1a, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'n'*/ +0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'o'*/ +0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, /*'p'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, /*'q'*/ +0x00, 0x00, 0x00, 0x00, 0x1a, 0x06, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'r'*/ +0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x1c, 0x20, 0x1e, 0x00, 0x00, 0x00, /*'s'*/ +0x00, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, /*'t'*/ +0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /*'u'*/ +0x00, 0x00, 0x00, 0x00, 0x36, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /*'v'*/ +0x00, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x2a, 0x14, 0x00, 0x00, 0x00, /*'w'*/ +0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, /*'x'*/ +0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /*'y'*/ +0x00, 0x00, 0x00, 0x00, 0x3e, 0x10, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00, /*'z'*/ +0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, /*'{'*/ +0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /*'|'*/ +0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, /*'}'*/ +0x00, 0x04, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'~'*/ +0x00, 0x00, 0x00, 0x08, 0x08, 0x14, 0x14, 0x22, 0x3e, 0x00, 0x00, 0x00, /*DEL*/ +}; + +void newline(fb_t* fb) +{ + uint8_t* to; + uint8_t* from; + int i; + fb->y++; + fb->x = 0; + + if (fb->y == (fb->height / CHAR_H)) + { + + to = (uint8_t*) fb->addr; + from = to + (CHAR_H * fb->pitch); + + for (i = 0; i < ((fb->height - CHAR_H) * fb->pitch); i++) + { + *to++ = *from++; + } + + uint32_t *addr = (uint32_t*) (fb->addr) + (fb->height - CHAR_H) * fb->width; + + for (i = 0; i < (CHAR_H * fb->width); i++) + { + *addr++ = fb->back; + } + + fb->y--; + } +} + +void clear_line(fb_t *fb, const int line) +{ + int i; + uint32_t* addr; + if (line > fb->height / CHAR_H) + { + fb->y = 0; + } + else + { + fb->y = line; + } + + fb->x = 0; + + addr = (uint32_t*) (fb->addr + (line * CHAR_H * fb->depth * fb->width)); + for (i = 0; i < (CHAR_H * fb->width); i++) + { + *addr++ = fb->back; + } + +} + +void clear(fb_t *fb, const uint32_t color) +{ + + uint32_t *addr = (uint32_t*) fb->addr; + uint32_t i; + for (i = 0; i < (fb->height * fb->width); i++) + { + *addr++ = color; + } + fb->x = 0; + fb->y = 0; + +} + +void fb_draw_char(fb_t *fb, char s) +{ + unsigned char* addr = (unsigned char*) fb->addr; + unsigned char *glyph = (unsigned char*) FONT + (s) * 12; + // calculate the offset on screen + int offs = (fb->y * CHAR_H * fb->pitch) + (fb->x * (CHAR_W + 1) * 4); + // variables + int i, j, line, mask, bytesperline = (CHAR_W + 7) / 8; + // display a character + for (j = 0; j < CHAR_H; j++) + { + // display one row + line = offs; + mask = 1; + for (i = 0; i < CHAR_W; i++) + { + // if bit set, we use white color, otherwise black + *((unsigned int*) (addr + line)) = ((int) *glyph) & mask ? fb->fore : fb->back; + mask <<= 1; + line += 4; + } + // adjust to next line + glyph += bytesperline; + offs += fb->pitch; + } +} + +void fb_print(fb_t *fb, char *s) +{ + + // draw next character if it's not zero + while (*s) + { + // handle carrige return + if (*s == '\r') + { + fb->x = 0; + } + else if (*s == '\n') + { + newline(fb); + } + else if (*s == '\t') + { + fb->x = ((fb->x + 4) >> 2) << 2; + } + else if (*s == '\b') + { + if (fb->x) + { + fb->x--; + fb_draw_char(fb, ' '); + } + } + else + { + fb_draw_char(fb, *s); + fb->x++; + } + // next character + if (fb->x == fb->width / CHAR_W) + { + newline(fb); + } + s++; + } +} + +rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag) +{ + return RT_EOK; +} + +rt_err_t hdmi_fb_close(rt_device_t dev) +{ + return RT_EOK; +} + +rt_size_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size) +{ +#ifdef BSP_USING_USPI + char* buffer = (char *) buf; + if(keyboard_available()) + { + int i = 0; + int j = 0; + while (i != size) + { + int ch = keyboard_getchar(); + if(ch != -1) + buffer[j++] = ch; + i++; + } + return j; + + } +#endif + return 0; +} + +rt_size_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + fb_print(&_hdmi.fb, (char *) buffer); +#ifdef BSP_USING_HDMI_DISPLAY + rt_device_t uart = rt_device_find("uart1"); + int old_flag = uart->open_flag; + uart->open_flag |= RT_DEVICE_FLAG_STREAM; + rt_device_write(uart, 0, buffer, size); + uart->open_flag = old_flag; +#endif + return size; + +} + +rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args) +{ + return RT_EOK; +} + +const static struct rt_device_ops hdmi_fb_ops = { + RT_NULL, + hdmi_fb_open, + hdmi_fb_close, + hdmi_fb_read, + hdmi_fb_write, + hdmi_fb_control +}; + +static struct rt_device_graphic_info _hdmi_info; + +static void hdmi_draw_rect(const char* pixel, int x1, int y1, int x2, int y2) +{ + int i, j; + int line; + for (j = y1; j <= y2; j++) + { + line = (j * _hdmi.fb.pitch) + (x1 * 4); + for (i = x1; i <= x2; i++) + { + // if bit set, we use white color, otherwise black + *((unsigned int*) (_hdmi_info.framebuffer + line)) = *(unsigned int*) pixel; + line += 4; + } + } + +} + +static void hdmi_set_pixel(const char* pixel, int x, int y) +{ + *(uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)) = *(uint32_t *) pixel; +} + +static void hdmi_get_pixel(char* pixel, int x, int y) +{ + uint32_t ret = 0; + ret = (*(uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)) & 0x00FFFFFF); + *pixel = ret; +} + +static void hdmi_draw_hline(const char* pixel, int x1, int x2, int y) +{ + hdmi_draw_rect(pixel, x1, y, x2, y); +} + +static void hdmi_draw_vline(const char* pixel, int x, int y1, int y2) +{ + hdmi_draw_rect(pixel, x, y1, x, y2); +} + +static void hdmi_blit_line(const char* pixels, int x, int y, rt_size_t size) +{ + int i = 0; + uint32_t *pixel_base = (uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)); + uint32_t *colors = (uint32_t *) pixels; + for (i = 0; i < size; i++) + { + pixel_base[i] = colors[i]; + } +} + +static struct rt_device_graphic_ops hdmi_ops = { + hdmi_set_pixel, + hdmi_get_pixel, + hdmi_draw_hline, + hdmi_draw_vline, + hdmi_blit_line +}; + +rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name) +{ + struct rt_device *device; + RT_ASSERT(hdmi_fb != RT_NULL); + + device = &hdmi_fb->parent; + device->user_data = &hdmi_ops; + + /* set device type */ + device->type = RT_Device_Class_Graphic; + /* initialize device interface */ +#ifdef RT_USING_DEVICE_OPS + device->ops = &hdmi_fb_ops; +#else + device->init = RT_NULL; + device->open = hdmi_fb_open; + device->close = hdmi_fb_close; + device->read = hdmi_fb_read; + device->write = hdmi_fb_write; + device->control = hdmi_fb_control; +#endif + + /* register to device manager */ + rt_device_register(device, name, RT_DEVICE_FLAG_RDWR); + + return RT_EOK; +} + +/** + * Show a picture + */ +void print_fb_info() +{ + rt_kprintf("FrameBuffer Info: \n \t width %x\t height %x\t depth %x\t addr %x\t size %x\t \n", fb_info.width, + fb_info.height, fb_info.depth, fb_info.addr, fb_info.size); + rt_kprintf("call mbox:%x,%x,%x,%x,%x\n", mbox[0], mbox[1], mbox[2], mbox[3], mbox[4]); +} + +void hdmi_fb_init() +{ + unsigned int *mbox = (unsigned int*) MBOX_ADDR; + mbox[0] = 35 * 4; + mbox[1] = MBOX_REQUEST; + + mbox[2] = 0x48003; //set phy wh + mbox[3] = 8; + mbox[4] = 8; + mbox[5] = 640; //FrameBufferInfo.width + mbox[6] = 480; //FrameBufferInfo.height + + mbox[7] = 0x48004; //set virt wh + mbox[8] = 8; + mbox[9] = 8; + mbox[10] = 640; //FrameBufferInfo.virtual_width + mbox[11] = 480; //FrameBufferInfo.virtual_height + + mbox[12] = 0x48009; //set virt offset + mbox[13] = 8; + mbox[14] = 8; + mbox[15] = 0; //FrameBufferInfo.x_offset + mbox[16] = 0; //FrameBufferInfo.y.offset + + mbox[17] = 0x48005; //set depth + mbox[18] = 4; + mbox[19] = 4; + mbox[20] = 32; //FrameBufferInfo.depth + + mbox[21] = 0x48006; //set pixel order + mbox[22] = 4; + mbox[23] = 4; + mbox[24] = 1; //RGB, not BGR preferably + + mbox[25] = 0x40001; //get framebuffer, gets alignment on request + mbox[26] = 8; + mbox[27] = 8; + mbox[28] = 4096; //FrameBufferInfo.pointer + mbox[29] = 0; //FrameBufferInfo.size + + mbox[30] = 0x40008; //get pitch + mbox[31] = 4; + mbox[32] = 4; + mbox[33] = 0; //FrameBufferInfo.pitch + + mbox[34] = MBOX_TAG_LAST; + if (mbox_call(MBOX_CH_PROP, MMU_DISABLE) && mbox[20] == 32 && mbox[28] != 0) + { + mbox[28] &= 0x3FFFFFFF; + _hdmi.fb.width = mbox[5]; + _hdmi.fb.height = mbox[6]; + _hdmi.fb.pitch = mbox[33]; + //_hdmi.fb.addr = (void*)((unsigned long)mbox[28]); + _hdmi.fb.addr = (rt_uint32_t) mbox[28]; + _hdmi.fb.size = mbox[29]; + _hdmi.fb.depth = 32; + _hdmi.fb.x = 0; + _hdmi.fb.y = 0; + _hdmi.fb.fore = CONSOLE_WHITE; + _hdmi.fb.back = CONSOLE_BLACK; + rt_hdmi_fb_device_init(&_hdmi, "hdmi"); + rt_hw_change_mmu_table(_hdmi.fb.addr, _hdmi.fb.size, _hdmi.fb.addr, DEVICE_MEM); + fb_info.width = _hdmi.fb.width; + fb_info.height = _hdmi.fb.height; + fb_info.addr = _hdmi.fb.addr; + fb_info.size = _hdmi.fb.size; + fb_info.pitch = _hdmi.fb.pitch; + fb_info.depth = _hdmi.fb.depth; + _hdmi_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888; + _hdmi_info.bits_per_pixel = _hdmi.fb.depth; + _hdmi_info.width = _hdmi.fb.width; + _hdmi_info.height = _hdmi.fb.height; + _hdmi_info.framebuffer = (rt_uint8_t *) _hdmi.fb.addr; + } +} + diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_fb.h b/bsp/raspberry-pi/raspi3-64/driver/drv_fb.h new file mode 100644 index 0000000000000000000000000000000000000000..1b733f8d0fbd63ba24f0dea904701d78b79c38a0 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_fb.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-29 zdzn first version + */ +#ifndef __DRV_FB_H__ +#define __DRV_FB_H__ + +#define RGB(r, g, b) ((((r))<<16) | (((g))<<8) | ((b))) + +#define COLOR_BLACK RGB(0, 0, 0) + +#define COLOR_GREEN RGB(0, 255, 0) + +#define COLOR_CYAN RGB(0, 255, 255) + +#define COLOR_RED RGB(255, 0, 0) + +#define COLOR_YELLOW RGB(255, 255, 0) + +#define COLOR_WHITE RGB(255, 255, 255) + +#define CONSOLE_WHITE COLOR_WHITE +#define CONSOLE_BLACK COLOR_BLACK +#define CONSOLE_GREEN COLOR_GREEN +#define CONSOLE_CYAN COLOR_CYAN +#define CONSOLE_RED COLOR_RED +#define CONSOLE_YELLOW COLOR_YELLOW + +typedef struct +{ + rt_uint32_t width; + rt_uint32_t height; + rt_uint32_t vwidth; + rt_uint32_t vheight; + rt_uint32_t pitch; + rt_uint32_t depth; + rt_uint32_t fore; + rt_uint32_t back; + rt_uint32_t x; + rt_uint32_t y; + rt_uint32_t addr; + rt_uint32_t size; +}fb_t; + +struct rt_hdmi_fb_device +{ + struct rt_device parent; + fb_t fb; +}; + +fb_t fb_info; +void print_fb_info(); +void hdmi_fb_init(); + +#endif/* __DRV_FB_H__ */ diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.c b/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..ce1883cce7c68961da6b50d51b37c2e51a94bf9a --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.c @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ +#include "raspi.h" +#include "drv_gpio.h" + +#ifdef BSP_USING_PIN + +struct rpi_pin_index +{ + rt_uint8_t phy_id; + rt_uint8_t bcm_id; + rt_uint8_t signal_name; + rt_uint8_t magic; +}; + +//raspi phy id and bcm id +static struct rpi_pin_index phypin_index[] = +{ + {0, 0, 0, 0}, + {1, 0, 0, 0}, + {2, 0, 0, 0}, + {3, BCM_GPIO_PIN_2, RPI_SDA1, PIN_MAGIC}, + {4, 0, 0, 0}, + {5, BCM_GPIO_PIN_3, RPI_SCL1, PIN_MAGIC}, + {6, 0, 0, 0}, + {7, BCM_GPIO_PIN_4, RPI_GPIO_GCLK, PIN_MAGIC}, + {8, BCM_GPIO_PIN_14, RPI_TXD0, PIN_MAGIC}, + {9, 0, 0, 0}, + {10, BCM_GPIO_PIN_15, RPI_RXD0, PIN_MAGIC}, + {11, BCM_GPIO_PIN_17, RPI_GPIO_GEN0, PIN_MAGIC}, + {12, BCM_GPIO_PIN_18, RPI_GPIO_GEN1, PIN_MAGIC}, + {13, BCM_GPIO_PIN_27, RPI_GPIO_GEN2, PIN_MAGIC}, + {14, 0, 0, 0}, + {15, BCM_GPIO_PIN_22, RPI_GPIO_GEN3, PIN_MAGIC}, + {16, BCM_GPIO_PIN_23, RPI_GPIO_GEN4, PIN_MAGIC}, + {17, 0, 0, 0}, + {18, BCM_GPIO_PIN_24, RPI_GPIO_GEN5, PIN_MAGIC}, + {19, BCM_GPIO_PIN_10, RPI_SPI_MOSI, PIN_MAGIC}, + {20, 0, 0, 0}, + {21, BCM_GPIO_PIN_9, RPI_SPI_MISO, PIN_MAGIC}, + {22, BCM_GPIO_PIN_25, RPI_GPIO_GEN6, PIN_MAGIC}, + {23, BCM_GPIO_PIN_11, RPI_SPI_SCLK, PIN_MAGIC}, + {24, BCM_GPIO_PIN_8, RPI_SPI_CE0_N, PIN_MAGIC}, + {25, 0, 0, 0}, + {26, BCM_GPIO_PIN_7, RPI_SPI_CE1_N, PIN_MAGIC}, + {27, BCM_GPIO_PIN_0, RPI_SDA0, PIN_MAGIC}, + {28, BCM_GPIO_PIN_1, RPI_SCL0, PIN_MAGIC}, + {29, BCM_GPIO_PIN_5, RPI_CAM_CLK, PIN_MAGIC}, + {30, 0, 0, 0}, + {31, BCM_GPIO_PIN_6, RPI_LAN_RUN, PIN_MAGIC}, + {32, BCM_GPIO_PIN_12, 0, PIN_MAGIC}, + {33, BCM_GPIO_PIN_13, 0, PIN_MAGIC}, + {34, 0, 0, 0}, + {35, BCM_GPIO_PIN_19, 0, PIN_MAGIC}, + {36, BCM_GPIO_PIN_16, RPI_STATUS_LED_N, PIN_MAGIC}, + {37, BCM_GPIO_PIN_26, 0, PIN_MAGIC}, + {38, BCM_GPIO_PIN_20, 0, PIN_MAGIC}, + {39, 0, 0, 0}, + {40, BCM_GPIO_PIN_21, RPI_CAM_GPIO, PIN_MAGIC}, +}; + +/* + * gpio_int[0] for BANK0 (pins 0-27) + * gpio_int[1] for BANK1 (pins 28-45) + * gpio_int[2] for BANK2 (pins 46-53) + */ +static struct gpio_irq_def _g_gpio_irq_tbl[GPIO_IRQ_NUM]; + +int gpio_set_func(enum gpio_code code, enum bcm_gpio_pin pin, rt_uint8_t func) +{ + RT_ASSERT((GPIO_CODE_PHY <= code) && (code < GPIO_CODE_NUM)); + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_53)); + + if (func & 0x8) + { + rt_kprintf("[line]:%d There is a warning with parameter input", __LINE__); + return RT_EINVAL; + } + + switch(func) + { + case 0x00: + bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_OUTP); + break; + case 0x01: + bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_INPT); + break; + case 0x02: + bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP); + bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_INPT); + break; + case 0x03: + bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_DOWN); + bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_INPT); + break; + case 0x04: + bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_OFF); + bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_OUTP); + break; + } + + return RT_EOK; +} + +int gpio_set_value(enum gpio_code code, enum bcm_gpio_pin pin, rt_uint8_t value) +{ + + RT_ASSERT((GPIO_CODE_PHY <= code) && (code < GPIO_CODE_NUM)); + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_53)); + + if (value & 0xE) + { + rt_kprintf("[line]:%d There is a warning with parameter input", __LINE__); + return RT_EINVAL; + } + + bcm283x_gpio_write(pin, value); + return RT_EOK; +} + +int gpio_get_value(enum gpio_code code, enum bcm_gpio_pin pin) +{ + rt_uint8_t data; + + RT_ASSERT((GPIO_CODE_PHY <= code) && (code < GPIO_CODE_NUM)); + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_53)); + + data = bcm283x_gpio_lev(pin); + return data; +} + +void gpio_set_irq_callback(enum gpio_code port, enum bcm_gpio_pin pin, void (*irq_cb)(void *), void *irq_arg) +{ + RT_ASSERT((GPIO_CODE_PHY < port) && (port < GPIO_CODE_NUM)); + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_53)); + + rt_uint8_t index; + if (pin <= 27) + { + index = 0; + } + else if (pin <= 45) + { + index = 1; + } + else{ + index = 2; + } + _g_gpio_irq_tbl[index].irq_cb[pin] = irq_cb; + _g_gpio_irq_tbl[index].irq_arg[pin] = irq_arg; +} + +void gpio_set_irq_type(enum gpio_code port, enum bcm_gpio_pin pin, rt_uint8_t irq_type) +{ + + RT_ASSERT((GPIO_CODE_PHY < port) && (port < GPIO_CODE_NUM)); + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_53)); + + rt_uint8_t index; + if (pin <= 27) + { + index = 0; + } + else if (pin <= 45) + { + index = 1; + } + else{ + index = 2; + } + _g_gpio_irq_tbl[index].irq_type[pin] = irq_type; + + switch(irq_type) + { + case 0x00: + bcm283x_gpio_ren(pin); + break; + case 0x01: + bcm283x_gpio_fen(pin); + break; + case 0x02: + bcm283x_gpio_aren(pin); + bcm283x_gpio_afen(pin); + break; + case 0x03: + bcm283x_gpio_hen(pin); + break; + case 0x04: + bcm283x_gpio_len(pin); + break; + } +} + +static void gpio_ack_irq(int irq, enum bcm_gpio_pin pin) +{ + rt_uint32_t data; + data = IRQ_PEND2; + data &= (0x0 << (irq - 32)); + IRQ_PEND2 = data; + + data = IRQ_DISABLE2; + data |= (0x1 << (irq - 32)); + IRQ_DISABLE2 = data; +} + +void gpio_irq_disable(enum gpio_code port, enum bcm_gpio_pin pin) +{ + rt_uint8_t index; + int irq = 0; + RT_ASSERT((GPIO_CODE_PHY < port) && (port < GPIO_CODE_NUM)); + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_53)); + + if (pin <= 27) + { + index = 0; + irq = IRQ_GPIO0; + }else if (pin <= 45){ + index = 1; + irq = IRQ_GPIO1; + }else{ + index = 2; + irq = IRQ_GPIO2; + } + + gpio_ack_irq(irq, pin); + + rt_uint8_t irq_type = _g_gpio_irq_tbl[index].irq_type[pin]; + + switch(irq_type) + { + case 0x00: + bcm283x_gpio_clr_ren(pin); + break; + case 0x01: + bcm283x_gpio_clr_fen(pin); + break; + case 0x02: + bcm283x_gpio_clr_aren(pin); + bcm283x_gpio_clr_afen(pin); + break; + case 0x03: + bcm283x_gpio_clr_hen(pin); + break; + case 0x04: + bcm283x_gpio_clr_len(pin); + break; + } +} + +void gpio_clear_irq_callback(enum gpio_code port, enum bcm_gpio_pin pin) +{ + rt_uint8_t index; + gpio_irq_disable(port, pin); + + if (pin <= 27) + { + index = 0; + } + else if (pin <= 45) + { + index = 1; + } + else + { + index = 2; + } + + _g_gpio_irq_tbl[index].irq_cb[pin] = RT_NULL; + _g_gpio_irq_tbl[index].irq_arg[pin] = RT_NULL; + _g_gpio_irq_tbl[index].irq_type[pin] = RT_NULL; + +} + + +void gpio_irq_enable(enum gpio_code port, enum bcm_gpio_pin pin) +{ + + rt_uint32_t offset; + rt_uint32_t data; + + RT_ASSERT((GPIO_CODE_PHY < port) && (port < GPIO_CODE_NUM)); + RT_ASSERT((BCM_GPIO_PIN_0 <= pin) && (pin < BCM_GPIO_PIN_53)); + + offset = pin; + if (pin <= 27) + { + offset = IRQ_GPIO0 - 32; + } + else if (pin <= 45) + { + offset = IRQ_GPIO1 - 32; + } + else + { + offset = IRQ_GPIO2 - 32; + } + + data = IRQ_ENABLE2; + data |= 0x1 << offset; + IRQ_ENABLE2 = data; + +} + +//gpio_int[0] for BANK0 (pins 0-27) +//gpio_int[1] for BANK1 (pins 28-45) +//gpio_int[2] for BANK2 (pins 46-53) +static void gpio_irq_handler(int irq, void *param) +{ + struct gpio_irq_def *irq_def = (struct gpio_irq_def *)param; + rt_uint32_t pin; + rt_uint32_t addr; + rt_uint32_t value; + rt_uint32_t tmpvalue; + + if (irq == IRQ_GPIO0) + { + /* 0~27 */ + addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPEDS0; // 0~31 + value = bcm283x_peri_read(addr); + value &= 0x0fffffff; + pin = 0; + } + else if (irq == IRQ_GPIO1) + { + /* 28-45 */ + addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPEDS0; + tmpvalue = bcm283x_peri_read(addr); + tmpvalue &= (~0x0fffffff); + + addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPEDS1; + value = bcm283x_peri_read(addr); + value &= 0x3fff; + value = (value<<4) | tmpvalue; + + pin = 28; + } + else if (irq == IRQ_GPIO2) + { + /* 46-53 */ + addr = BCM283X_GPIO_BASE + BCM283X_GPIO_GPEDS1; + value = bcm283x_peri_read(addr); + value &= (~0x3fff); + value &= 0xff600000; + pin = 46; + } + + bcm283x_peri_write(addr,0); + + while (value) + { + if ((value & 0x1) && (irq_def->irq_cb[pin] != RT_NULL)) + { + irq_def->irq_cb[pin](irq_def->irq_arg[pin]); + gpio_ack_irq(irq,pin); + } + pin++; + value = value >> 1; + } +} + +static void pin_mode(struct rt_device *dev, rt_base_t pin, rt_base_t mode) +{ + if ((pin > PIN_NUM(phypin_index)) || (phypin_index[pin].magic != PIN_MAGIC)) + { + rt_kprintf("pin:%d value wrongful", pin); + return; + } + + gpio_set_func(GPIO_CODE_BCM, phypin_index[pin].bcm_id, mode); +} + +static void pin_write(struct rt_device *dev, rt_base_t pin, rt_base_t value) +{ + if ((pin > PIN_NUM(phypin_index)) || (phypin_index[pin].magic != PIN_MAGIC)) + { + rt_kprintf("pin:%d value wrongful", pin); + return; + } + + gpio_set_value(GPIO_CODE_BCM, phypin_index[pin].bcm_id, value); +} + +static int pin_read(struct rt_device *device, rt_base_t pin) +{ + if ((pin > PIN_NUM(phypin_index)) || (phypin_index[pin].magic != PIN_MAGIC)) + { + rt_kprintf("pin:%d value wrongful", pin); + return 0; + } + + return gpio_get_value(GPIO_CODE_BCM, phypin_index[pin].bcm_id); +} + +static rt_err_t pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args) +{ + if ((pin > PIN_NUM(phypin_index)) || (phypin_index[pin].magic != PIN_MAGIC)) + { + rt_kprintf("pin:%d value wrongful", pin); + return RT_ERROR; + } + + gpio_set_irq_callback(GPIO_CODE_BCM , phypin_index[pin].bcm_id, hdr, args); + gpio_set_irq_type(GPIO_CODE_BCM, phypin_index[pin].bcm_id, mode); + + return RT_EOK; +} + +static rt_err_t pin_detach_irq(struct rt_device *device, rt_int32_t pin) +{ + if ((pin > PIN_NUM(phypin_index)) || (phypin_index[pin].magic != PIN_MAGIC)) + { + rt_kprintf("pin:%d value wrongful", pin); + return RT_ERROR; + } + + gpio_clear_irq_callback(GPIO_CODE_BCM, phypin_index[pin].bcm_id); + + return RT_EOK; +} + +rt_err_t pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled) +{ + if ((pin > PIN_NUM(phypin_index)) || (phypin_index[pin].magic != PIN_MAGIC)) + { + rt_kprintf("pin:%d value wrongful", pin); + return RT_ERROR; + } + + if (enabled) + gpio_irq_enable(GPIO_CODE_BCM, phypin_index[pin].bcm_id); + else + gpio_irq_disable(GPIO_CODE_BCM, phypin_index[pin].bcm_id); + + return RT_EOK; +} + +static const struct rt_pin_ops ops = +{ + pin_mode, + pin_write, + pin_read, + pin_attach_irq, + pin_detach_irq, + pin_irq_enable, +}; +#endif + +int rt_hw_gpio_init(void) +{ +#ifdef BSP_USING_PIN + rt_device_pin_register("gpio", &ops, RT_NULL); +#endif + + /* install ISR */ + rt_hw_interrupt_install(IRQ_GPIO0, gpio_irq_handler, &_g_gpio_irq_tbl[0], "gpio0_irq"); + rt_hw_interrupt_umask(IRQ_GPIO0); + + rt_hw_interrupt_install(IRQ_GPIO1, gpio_irq_handler, &_g_gpio_irq_tbl[1], "gpio1_irq"); + rt_hw_interrupt_umask(IRQ_GPIO1); + + rt_hw_interrupt_install(IRQ_GPIO2, gpio_irq_handler, &_g_gpio_irq_tbl[2], "gpio2_irq"); + rt_hw_interrupt_umask(IRQ_GPIO2); + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_gpio_init); diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.h b/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..b0a67870abde8f9d9781daaf9c5d80c9fb2d7f98 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_gpio.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_GPIO_H__ +#define __DRV_GPIO_H__ + +#include +#include +#include +#include +#include + +#include "interrupt.h" +#include "bcm283x.h" +#include "raspi.h" +#include "board.h" + +#define GPIO_IRQ_NUM 3 + +struct gpio_irq_def +{ + void *irq_arg[32]; + void (*irq_cb[32])(void *param); + rt_uint8_t irq_type[32]; +}; + +enum gpio_irq_clock +{ + GPIO_IRQ_LOSC_32KHZ = 0, + GPIO_IRQ_HOSC_24MHZ +}; + +int rt_hw_gpio_init(void); + +#endif /* __DRV_GPIO_H__ */ diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.c b/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.c new file mode 100644 index 0000000000000000000000000000000000000000..5163af60eece89e9c80d3d828ad97cf82d4e6a79 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include "drv_i2c.h" + +#if defined (BSP_USING_I2C0) +#define I2C1BUS_NAME "i2c0" +#endif /*BSP_USING_I2C0*/ + +#if defined (BSP_USING_I2C1) +#define I2C2BUS_NAME "i2c1" +#endif /*BSP_USING_I2C1*/ + +static int i2c_byte_wait_us = 0; + +#ifdef BSP_USING_I2C0 + +static struct raspi_i2c_bus raspi_i2c0 = +{ + .device_name = I2C1BUS_NAME, +}; + +static struct raspi_master_config_t raspi_i2c0_cfg = +{ + .sdl_pin = BCM_GPIO_PIN_0, + .scl_pin = BCM_GPIO_PIN_1, + .sdl_pin_mode = BCM283X_GPIO_FSEL_ALT0, + .scl_pin_mode = BCM283X_GPIO_FSEL_ALT0, + .slave_address = 8, + .bsc_base = (PER_BASE + BCM283X_BSC0_BASE), + .clk_div = BCM283X_I2C_CLOCK_DIVIDER_148, +}; + +#endif /* RT_USING_HW_I2C1 */ + +#ifdef BSP_USING_I2C1 +static struct raspi_i2c_bus raspi_i2c1 = +{ + .device_name = I2C2BUS_NAME, +}; + +static struct raspi_master_config_t raspi_i2c1_cfg = +{ + .sdl_pin = BCM_GPIO_PIN_2, + .scl_pin = BCM_GPIO_PIN_3, + .sdl_pin_mode = BCM283X_GPIO_FSEL_ALT0, + .scl_pin_mode = BCM283X_GPIO_FSEL_ALT0, + .slave_address = 9, + .bsc_base = (PER_BASE + BCM283X_BSC1_BASE), + .clk_div = BCM283X_I2C_CLOCK_DIVIDER_148, +}; +#endif /* RT_USING_HW_I2C2 */ + +#if (defined(BSP_USING_I2C0) || defined(BSP_USING_I2C1)) + +static rt_size_t raspi_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_size_t raspi_i2c_slv_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_err_t raspi_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t, + rt_uint32_t); + +void i2c_master_init(struct raspi_master_config_t *cfg) +{ + volatile rt_uint32_t addr; + rt_uint32_t data; + + bcm283x_gpio_fsel(cfg->sdl_pin, cfg->sdl_pin_mode); /* SDA */ + bcm283x_gpio_fsel(cfg->scl_pin, cfg->scl_pin_mode); /* SCL */ + + addr = cfg->bsc_base + BCM283X_BSC_DIV; + data = bcm283x_peri_read(addr); + i2c_byte_wait_us = ( data * 1000000 / BCM283X_CORE_CLK_HZ) * 9; + + addr = cfg->bsc_base + BCM283X_BSC_DIV; + bcm283x_peri_write(addr, cfg->clk_div); + + //update + i2c_byte_wait_us = (cfg->clk_div * 1000000 * 9 / BCM283X_CORE_CLK_HZ); +} + +static rt_size_t raspi_i2c_mst_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + volatile rt_uint32_t addr; + struct raspi_i2c_bus *raspi_i2c; + rt_size_t i; + RT_ASSERT(bus != RT_NULL); + raspi_i2c = (struct raspi_i2c_bus *) bus; + raspi_i2c->msg = msgs; + raspi_i2c->msg_ptr = 0; + raspi_i2c->msg_cnt = num; + raspi_i2c->dptr = 0; + + addr = raspi_i2c->cfg->bsc_base + BCM283X_BSC_A; + bcm283x_peri_write(addr, msgs->addr); + + for (i = 0; i < num; i++) + { + if ( raspi_i2c->msg[i].flags & RT_I2C_RD ) + { + bcm283x_i2c_read(raspi_i2c->cfg->bsc_base, raspi_i2c->msg->buf, num); + } + else + { + bcm283x_i2c_write(raspi_i2c->cfg->bsc_base, raspi_i2c->msg->buf, num); + } + } + raspi_i2c->msg = RT_NULL; + raspi_i2c->msg_ptr = 0; + raspi_i2c->msg_cnt = 0; + raspi_i2c->dptr = 0; + return i; +} + +static rt_size_t raspi_i2c_slv_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + return 0; +} +static rt_err_t raspi_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t cmd, + rt_uint32_t arg) +{ + return RT_ERROR; +} + +static const struct rt_i2c_bus_device_ops raspi_i2c_ops = +{ + .master_xfer = raspi_i2c_mst_xfer, + .slave_xfer = raspi_i2c_slv_xfer, + .i2c_bus_control = raspi_i2c_bus_control, +}; + +static rt_err_t raspi_i2c_configure(struct raspi_i2c_bus *bus, struct raspi_master_config_t *cfg) +{ + RT_ASSERT(bus != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + bus->device.ops = &raspi_i2c_ops; + bus->cfg = cfg; + + i2c_master_init(cfg); + return RT_EOK; +} +#endif + +int rt_hw_i2c_init(void) +{ + +#if defined(BSP_USING_I2C0) + raspi_i2c_configure(&raspi_i2c0 , &raspi_i2c0_cfg); + rt_i2c_bus_device_register(&raspi_i2c0.device, raspi_i2c0.device_name); +#endif /* BSP_USING_I2C1 */ + +#if defined(BSP_USING_I2C1) + + raspi_i2c_configure(&raspi_i2c1 , &raspi_i2c1_cfg); + rt_i2c_bus_device_register(&raspi_i2c1.device, raspi_i2c1.device_name); + +#endif /* BSP_USING_I2C2 */ + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_i2c_init); diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.h b/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..041d6b00db638790440e2d9c3a71c52452b0002a --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_i2c.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_I2C_H__ +#define __DRV_I2C_H__ + +#include +#include +#include +#include "bcm283x.h" + +struct raspi_master_config_t +{ + rt_uint8_t sdl_pin; + rt_uint8_t scl_pin; + rt_uint8_t sdl_pin_mode; + rt_uint8_t scl_pin_mode; + rt_uint8_t slave_address; + rt_uint32_t bsc_base; + rt_uint16_t clk_div; +}; + +struct raspi_i2c_bus +{ + struct rt_i2c_bus_device device; + struct rt_i2c_msg *msg; + rt_uint32_t msg_cnt; + volatile rt_uint32_t msg_ptr; + volatile rt_uint32_t dptr; + char *device_name; + struct raspi_master_config_t *cfg; +}; + +int rt_hw_i2c_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.c b/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.c new file mode 100644 index 0000000000000000000000000000000000000000..e38393bbd0f8f09965dda2bc4bc2822e05d02126 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + + +#include "drv_rtc.h" + +#ifdef BSP_USING_RTC + +static struct rt_rtc_device rtc_device; + +rt_uint8_t buf[]= +{ + 0x00, 0x00, 0x43, 0x15, 0x05, 0x01, 0x03, 0x19 +}; + +static time_t raspi_get_timestamp(void) +{ + struct tm tm_new = {0}; + buf[0] = 0; + bcm283x_i2c_write_read_rs((char*)buf, 1, (char*)buf, 7); + + tm_new.tm_year = ((buf[6] / 16) + 0x30) * 10 + (buf[6] % 16) + 0x30; + tm_new.tm_mon = ((buf[5] & 0x1F) / 16 + 0x30) + (buf[5] & 0x1F) % 16+ 0x30; + tm_new.tm_mday = ((buf[4] & 0x3F) / 16 + 0x30) + (buf[4] & 0x3F) % 16+ 0x30; + tm_new.tm_hour = ((buf[2] & 0x3F) / 16 + 0x30) + (buf[2] & 0x3F) % 16+ 0x30; + tm_new.tm_min = ((buf[1] & 0x7F) / 16 + 0x30) + (buf[1] & 0x7F) % 16+ 0x30; + tm_new.tm_sec = ((buf[0] & 0x7F) / 16 + 0x30) + (buf[0] & 0x7F) % 16+ 0x30; + + return mktime(&tm_new); +} + +static int raspi_set_timestamp(time_t timestamp) +{ + struct tm *tblock; + tblock = localtime(×tamp); + buf[0] = 0; + buf[1] = tblock->tm_sec; + buf[2] = tblock->tm_min; + buf[3] = tblock->tm_hour; + buf[4] = tblock->tm_wday; + buf[5] = tblock->tm_mday; + buf[6] = tblock->tm_mon; + buf[7] = tblock->tm_year; + bcm283x_i2c_write((PER_BASE + BCM283X_BSC0_BASE) ,buf, 8); + return RT_EOK; +} + +static rt_err_t raspi_rtc_init(rt_device_t dev) +{ + bcm283x_i2c_setSlaveAddress(0, 0x68); + bcm283x_i2c_set_baudrate(0, 10000); + raspi_set_timestamp(0); + return RT_EOK; +} + +static rt_err_t raspi_rtc_open(rt_device_t dev, rt_uint16_t oflag) +{ + bcm283x_i2c_begin(0); + return RT_EOK; +} + +static rt_err_t raspi_rtc_close(rt_device_t dev) +{ + bcm283x_i2c_end(0); + return RT_EOK; +} + +static rt_err_t raspi_rtc_control(rt_device_t dev, int cmd, void *args) +{ + + RT_ASSERT(dev != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_RTC_GET_TIME: + *(rt_uint32_t *)args = raspi_get_timestamp(); + break; + case RT_DEVICE_CTRL_RTC_SET_TIME: + raspi_set_timestamp(*(time_t *)args); + break; + default: + return RT_EINVAL; + } + return RT_EOK; +} + +static rt_size_t raspi_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + raspi_rtc_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, buffer); + return size; +} + +static rt_size_t raspi_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + raspi_rtc_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, (void *)buffer); + return size; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops raspi_rtc_ops = +{ + .init = raspi_rtc_init, + .open = raspi_rtc_open, + .close = raspi_rtc_close, + .read = raspi_rtc_read, + .write = raspi_rtc_write, + .control = raspi_rtc_control +}; +#endif + +int rt_hw_rtc_init(void) +{ + rt_memset(&rtc_device, 0, sizeof(rtc_device)); + + rtc_device.device.type = RT_Device_Class_RTC; + rtc_device.device.rx_indicate = RT_NULL; + rtc_device.device.tx_complete = RT_NULL; + rtc_device.device.ops = &raspi_rtc_ops; + rtc_device.device.user_data = RT_NULL; + + /* register a rtc device */ + rt_device_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR); + + return 0; +} +INIT_DEVICE_EXPORT(rt_hw_rtc_init); +#endif /* BSP_USING_RTC */ + diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.h b/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.h new file mode 100644 index 0000000000000000000000000000000000000000..82306068ca4c057dc4d07362a8d6f0f454141375 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_rtc.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_RTC_H__ +#define __DRV_RTC_H__ + +#include +#include +#include +#include "bcm283x.h" + +struct rt_rtc_device +{ + struct rt_device device; +}; + +int rt_hw_rtc_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.c b/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.c new file mode 100644 index 0000000000000000000000000000000000000000..4f3018c0ef6b6fbddf4fbc639e0078aba51e83af --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.c @@ -0,0 +1,532 @@ +/* + * File : drv_sdio.c + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include +#include +#include +#include + +#include "drv_sdio.h" +#include "interrupt.h" +#include "drv_gpio.h" + +#include "bcm283x.h" +#include +#include "bcm283x.h" + + +#include + +#ifdef RT_USING_SDIO +#define CONFIG_MMC_USE_DMA +#define DMA_ALIGN (32U) + +typedef struct EMMCCommand +{ + const char* name; + unsigned int code; + unsigned char resp; + unsigned char rca; + int delay; +} EMMCCommand; + +static EMMCCommand sdCommandTable[] = +{ + {"GO_IDLE_STATE", 0x00000000 | CMD_RSPNS_NO , RESP_NO , RCA_NO ,0}, + {"ALL_SEND_CID" , 0x02000000 | CMD_RSPNS_136 , RESP_R2I, RCA_NO ,0}, + {"SEND_REL_ADDR", 0x03000000 | CMD_RSPNS_48 , RESP_R6 , RCA_NO ,0}, + {"SET_DSR" , 0x04000000 | CMD_RSPNS_NO , RESP_NO , RCA_NO ,0}, + {"SWITCH_FUNC" , 0x06000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"CARD_SELECT" , 0x07000000 | CMD_RSPNS_48B , RESP_R1b, RCA_YES ,0}, + {"SEND_IF_COND" , 0x08000000 | CMD_RSPNS_48 , RESP_R7 , RCA_NO ,100}, + {"SEND_CSD" , 0x09000000 | CMD_RSPNS_136 , RESP_R2S, RCA_YES ,0}, + {"SEND_CID" , 0x0A000000 | CMD_RSPNS_136 , RESP_R2I, RCA_YES ,0}, + {"VOLT_SWITCH" , 0x0B000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"STOP_TRANS" , 0x0C000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0}, + {"SEND_STATUS" , 0x0D000000 | CMD_RSPNS_48 , RESP_R1 , RCA_YES ,0}, + {"GO_INACTIVE" , 0x0F000000 | CMD_RSPNS_NO , RESP_NO , RCA_YES ,0}, + {"SET_BLOCKLEN" , 0x10000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"READ_SINGLE" , 0x11000000 | CMD_RSPNS_48 | CMD_IS_DATA | TM_DAT_DIR_CH, RESP_R1 , RCA_NO ,0}, + {"READ_MULTI" , 0x12000000 | CMD_RSPNS_48 | TM_MULTI_DATA | TM_DAT_DIR_CH, RESP_R1 , RCA_NO ,0}, + {"SEND_TUNING" , 0x13000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"SPEED_CLASS" , 0x14000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0}, + {"SET_BLOCKCNT" , 0x17000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"WRITE_SINGLE" , 0x18000000 | CMD_RSPNS_48 | CMD_IS_DATA | TM_DAT_DIR_HC, RESP_R1 , RCA_NO ,0}, + {"WRITE_MULTI" , 0x19000000 | CMD_RSPNS_48 | TM_MULTI_DATA | TM_DAT_DIR_HC, RESP_R1 , RCA_NO ,0}, + {"PROGRAM_CSD" , 0x1B000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"SET_WRITE_PR" , 0x1C000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0}, + {"CLR_WRITE_PR" , 0x1D000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0}, + {"SND_WRITE_PR" , 0x1E000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"ERASE_WR_ST" , 0x20000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"ERASE_WR_END" , 0x21000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"ERASE" , 0x26000000 | CMD_RSPNS_48B , RESP_R1b, RCA_NO ,0}, + {"LOCK_UNLOCK" , 0x2A000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"APP_CMD" , 0x37000000 | CMD_RSPNS_NO , RESP_NO , RCA_NO ,100}, + {"APP_CMD" , 0x37000000 | CMD_RSPNS_48 , RESP_R1 , RCA_YES ,0}, + {"GEN_CMD" , 0x38000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + + // APP commands must be prefixed by an APP_CMD. + {"SET_BUS_WIDTH", 0x06000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"SD_STATUS" , 0x0D000000 | CMD_RSPNS_48 , RESP_R1 , RCA_YES ,0}, // RCA??? + {"SEND_NUM_WRBL", 0x16000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"SEND_NUM_ERS" , 0x17000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"SD_SENDOPCOND", 0x29000000 | CMD_RSPNS_48 , RESP_R3 , RCA_NO ,1000}, + {"SET_CLR_DET" , 0x2A000000 | CMD_RSPNS_48 , RESP_R1 , RCA_NO ,0}, + {"SEND_SCR" , 0x33000000 | CMD_RSPNS_48 | CMD_IS_DATA | TM_DAT_DIR_CH , RESP_R1 , RCA_NO ,0}, +}; + +static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width); +static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock); +static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat); + +static inline rt_uint32_t read32(rt_uint32_t addr) +{ + return( *((volatile rt_uint32_t *)(addr)) ); +} + +static inline void write32(rt_uint32_t addr, rt_uint32_t value) +{ + *((volatile rt_uint32_t *)(addr)) = value; +} + +static rt_err_t raspi_transfer_command(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd) +{ + rt_uint32_t cmdidx; + rt_uint32_t status; + rt_err_t ret = RT_EOK; + + if(read32(pdat->virt + EMMC_STATUS) & SR_CMD_INHIBIT) + write32(pdat->virt + EMMC_CMDTM, 0x0); + + EMMCCommand* cmdtab = &sdCommandTable[cmd->cmdidx]; + + cmdidx = cmdtab->code; + + write32(pdat->virt + EMMC_ARG1, cmd->cmdarg); + write32(pdat->virt + EMMC_CMDTM, cmdidx); + + do { + status = read32(pdat->virt + EMMC_STATUS); + } while(!(status & SR_CMD_INHIBIT)); + + if(cmd->resptype & RESP_MASK) + { + cmd->response[0] = read32(pdat->virt + EMMC_RESP0); + if(cmd->resptype & RESP_R2) + { + cmd->response[1] = read32(pdat->virt + EMMC_RESP1); + cmd->response[2] = read32(pdat->virt + EMMC_RESP2); + cmd->response[3] = read32(pdat->virt + EMMC_RESP3); + } + } + + return ret; +} + +static rt_err_t read_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize) +{ + rt_uint32_t * tmp = buf; + rt_uint32_t count = blkcount * blksize; + rt_uint32_t status, err; + +// status = read32(pdat->virt + PL180_STATUS); +// err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_RX_OVERRUN); +// while((!err) && (count >= sizeof(rt_uint32_t))) +// { +// if(status & PL180_STAT_RX_FIFO_AVL) +// { +// *(tmp) = read32(pdat->virt + PL180_FIFO); +// tmp++; +// count -= sizeof(rt_uint32_t); +// } +// status = read32(pdat->virt + PL180_STATUS); +// err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_RX_OVERRUN); +// } +// +// err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END | PL180_STAT_RX_OVERRUN); +// while(!err) +// { +// status = read32(pdat->virt + PL180_STATUS); +// err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END | PL180_STAT_RX_OVERRUN); +// } +// +// if(status & PL180_STAT_DAT_TIME_OUT) +// return -RT_ERROR; +// else if (status & PL180_STAT_DAT_CRC_FAIL) +// return -RT_ERROR; +// else if (status & PL180_STAT_RX_OVERRUN) +// return -RT_ERROR; +// write32(pdat->virt + PL180_CLEAR, 0x1DC007FF); +// +// if(count) +// return -RT_ERROR; + + return RT_EOK; +} + +static rt_err_t write_bytes(struct sdhci_pdata_t * pdat, rt_uint32_t * buf, rt_uint32_t blkcount, rt_uint32_t blksize) +{ + rt_uint32_t * tmp = buf; + rt_uint32_t count = blkcount * blksize; + rt_uint32_t status, err; + int i; + +// status = read32(pdat->virt + PL180_STATUS); +// err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT); +// while(!err && count) +// { +// if(status & PL180_STAT_TX_FIFO_HALF) +// { +// if(count >= 8 * sizeof(rt_uint32_t)) +// { +// for(i = 0; i < 8; i++) +// write32(pdat->virt + PL180_FIFO, *(tmp + i)); +// tmp += 8; +// count -= 8 * sizeof(rt_uint32_t); +// } +// else +// { +// while(count >= sizeof(rt_uint32_t)) +// { +// write32(pdat->virt + PL180_FIFO, *tmp); +// tmp++; +// count -= sizeof(rt_uint32_t); +// } +// } +// } +// status = read32(pdat->virt + PL180_STATUS); +// err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT); +// } +// +// err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END); +// while(!err) +// { +// status = read32(pdat->virt + PL180_STATUS); +// err = status & (PL180_STAT_DAT_CRC_FAIL | PL180_STAT_DAT_TIME_OUT | PL180_STAT_DAT_BLK_END); +// } +// +// if(status & PL180_STAT_DAT_TIME_OUT) +// return -RT_ERROR; +// else if (status & PL180_STAT_DAT_CRC_FAIL) +// return -RT_ERROR; +// write32(pdat->virt + PL180_CLEAR, 0x1DC007FF); +// +// if(count) +// return -RT_ERROR; + return RT_EOK; +} + +static rt_err_t raspi_transfer_data(struct sdhci_pdata_t * pdat, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat) +{ + rt_uint32_t dlen = (rt_uint32_t)(dat->blkcnt * dat->blksz); + rt_uint32_t blksz_bits = dat->blksz - 1; + rt_err_t ret = -RT_ERROR; + + write32(pdat->virt + EMMC_BLKSIZECNT, dlen); + + if(dat->flag & DATA_DIR_READ) + { + write32(pdat->virt + EMMC_STATUS, SR_READ_TRANSFER); + ret = raspi_transfer_command(pdat, cmd); + if (ret < 0) return ret; + ret = read_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz); + } + else if(dat->flag & DATA_DIR_WRITE) + { + ret = raspi_transfer_command(pdat, cmd); + if (ret < 0) return ret; + write32(pdat->virt + EMMC_STATUS, SR_WRITE_TRANSFER); + ret = write_bytes(pdat, (rt_uint32_t *)dat->buf, dat->blkcnt, dat->blksz); + } + + return ret; +} + +static void mmc_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req) +{ + struct sdhci_t *sdhci = (struct sdhci_t *)host->private_data; + struct sdhci_cmd_t cmd; + struct sdhci_cmd_t stop; + struct sdhci_data_t dat; + + rt_memset(&cmd, 0, sizeof(struct sdhci_cmd_t)); + rt_memset(&stop, 0, sizeof(struct sdhci_cmd_t)); + rt_memset(&dat, 0, sizeof(struct sdhci_data_t)); + + cmd.cmdidx = req->cmd->cmd_code; + EMMCCommand* cmdtab = &sdCommandTable[cmd.cmdidx]; + cmd.cmdarg = req->cmd->arg; + cmd.resptype = cmdtab->resp; + + if(req->data) + { + dat.buf = (rt_uint8_t *)req->data->buf; + dat.flag = req->data->flags; + dat.blksz = req->data->blksize; + dat.blkcnt = req->data->blks; + + req->cmd->err = sdhci_transfer(sdhci, &cmd, &dat); + } + else + { + req->cmd->err = sdhci_transfer(sdhci, &cmd, RT_NULL); + } + + req->cmd->resp[3] = cmd.response[3]; + req->cmd->resp[2] = cmd.response[2]; + req->cmd->resp[1] = cmd.response[1]; + req->cmd->resp[0] = cmd.response[0]; + + if (req->stop) + { + stop.cmdidx = req->stop->cmd_code; + cmdtab = &sdCommandTable[cmd.cmdidx]; + stop.cmdarg = req->stop->arg; + cmd.resptype = cmdtab->resp; + + req->stop->err = sdhci_transfer(sdhci, &stop, RT_NULL); + } + + mmcsd_req_complete(host); +} + + +static rt_err_t sdhci_transfer(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat) +{ + struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv; + + if(!dat) + return raspi_transfer_command(pdat, cmd); + + return raspi_transfer_data(pdat, cmd, dat); +} + + +//#ifdef CONFIG_MMC_USE_DMA +//#ifdef BSP_USING_SDIO0 +////ALIGN(32) static rt_uint8_t dma_buffer[64 * 1024]; +//static rt_uint8_t dma_buffer[64 * 1024]; +//#endif +//#endif + + +static void mmc_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg) +{ + struct sdhci_t * sdhci = (struct sdhci_t *)host->private_data; + sdhci_setclock(sdhci, io_cfg->clock); + sdhci_setwidth(sdhci, io_cfg->bus_width); +} + +rt_int32_t mmc_card_status(struct rt_mmcsd_host *host) +{ + return 0; +} + +void mmc_enable_irq(struct rt_mmcsd_host *host, rt_int32_t en) +{ + +} + +static rt_err_t sdhci_detect(struct sdhci_t * sdhci) +{ + return RT_EOK; +} + +static rt_err_t sdhci_setwidth(struct sdhci_t * sdhci, rt_uint32_t width) +{ + rt_uint32_t temp = 0; + struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv; + temp = read32((pdat->virt + EMMC_CONTROL0)); + temp |= C0_HCTL_HS_EN; + temp |= C0_HCTL_DWITDH; // always use 4 data lines: + write32((pdat->virt + EMMC_CONTROL0), temp); + + return RT_EOK; +} + +static rt_uint32_t sdhci_getdivider( rt_uint32_t sdHostVer, rt_uint32_t freq ) +{ + rt_uint32_t divisor; + rt_uint32_t closest = 41666666 / freq; + rt_uint32_t shiftcount = __rt_fls(closest - 1); + + + if (shiftcount > 0) shiftcount--; + if (shiftcount > 7) shiftcount = 7; + if (sdHostVer > HOST_SPEC_V2) + divisor = closest; + else + divisor = (1 << shiftcount); + + if (divisor <= 2) { + divisor = 2; + shiftcount = 0; + } + + rt_uint32_t hi = 0; + if (sdHostVer > HOST_SPEC_V2) + hi = (divisor & 0x300) >> 2; + rt_uint32_t lo = (divisor & 0x0ff); + rt_uint32_t cdiv = (lo << 8) + hi; + return cdiv; +} + +static rt_err_t sdhci_setclock(struct sdhci_t * sdhci, rt_uint32_t clock) +{ + rt_uint32_t temp = 0; + rt_uint32_t sdHostVer = 0; + int count = 100000; + struct sdhci_pdata_t * pdat = (struct sdhci_pdata_t *)sdhci->priv; + + temp = read32(pdat->virt + EMMC_STATUS); + while((temp & (SR_CMD_INHIBIT | SR_DAT_INHIBIT))&&(--count)) + bcm283x_clo_delayMicros(1); + + if( count <= 0 ) + { + rt_kprintf("EMMC: Set clock: timeout waiting for inhibit flags. Status %08x.\n", temp); + return RT_ERROR; + } + + // Switch clock off. + temp = read32((pdat->virt + EMMC_CONTROL1)); + temp |= ~C1_CLK_EN; + write32((pdat->virt + EMMC_CONTROL1),temp); + + bcm283x_clo_delayMicros(10); + + // Request the new clock setting and enable the clock + temp = read32(pdat->virt + EMMC_SLOTISR_VER); + sdHostVer = (temp & HOST_SPEC_NUM) >> HOST_SPEC_NUM_SHIFT; + + int cdiv = sdhci_getdivider(sdHostVer, clock); + temp = read32((pdat->virt + EMMC_CONTROL1)); + temp = (temp & 0xffff003f) | cdiv; + write32((pdat->virt + EMMC_CONTROL1),temp); + bcm283x_clo_delayMicros(10); + + // Enable the clock. + temp = read32(pdat->virt + EMMC_CONTROL1); + temp |= C1_CLK_EN; + write32((pdat->virt + EMMC_CONTROL1),temp); + bcm283x_clo_delayMicros(10); + + // Wait for clock to be stable. + count = 10000; + temp = read32(pdat->virt + EMMC_CONTROL1); + while( !(temp & C1_CLK_STABLE) && count-- ) + bcm283x_clo_delayMicros(10); + + if( count <= 0 ) + { + rt_kprintf("EMMC: ERROR: failed to get stable clock.\n"); + return RT_ERROR; + } + + return RT_EOK; +} + +static const struct rt_mmcsd_host_ops ops = +{ + mmc_request_send, + mmc_set_iocfg, + RT_NULL, + RT_NULL, +}; + +static void sdmmc_gpio_init() +{ + int pin; + + for (pin = BCM_GPIO_PIN_48; pin <= BCM_GPIO_PIN_53; pin++) + { + bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP); + bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_ALT3); + } + bcm283x_gpio_set_pud(pin, BCM283X_GPIO_PUD_UP); + bcm283x_gpio_fsel(pin, BCM283X_GPIO_FSEL_INPT); +} + +int raspi_sdmmc_init(void) +{ + rt_uint32_t virt; + rt_uint32_t id; + struct rt_mmcsd_host * host = RT_NULL; + struct sdhci_pdata_t * pdat = RT_NULL; + struct sdhci_t * sdhci = RT_NULL; + + rt_kprintf("raspi_sdmmc_init start\n"); + +#ifdef BSP_USING_SDIO0 + host = mmcsd_alloc_host(); + if (!host) + { + rt_kprintf("alloc host failed"); + goto err; + } + + sdhci = rt_malloc(sizeof(struct sdhci_t)); + if (!sdhci) + { + rt_kprintf("alloc sdhci failed"); + goto err; + } + rt_memset(sdhci, 0, sizeof(struct sdhci_t)); + + rt_kprintf(">> sdmmc_gpio_init\n"); + sdmmc_gpio_init(); + rt_kprintf("<< sdmmc_gpio_init\n"); + + virt = MMC0_BASE_ADDR; + + pdat = (struct sdhci_pdata_t *)rt_malloc(sizeof(struct sdhci_pdata_t)); + RT_ASSERT(pdat != RT_NULL); + + pdat->virt = (rt_uint32_t)virt; + + sdhci->name = "sd0"; + sdhci->voltages = VDD_33_34; + sdhci->width = MMCSD_BUSWIDTH_4; + sdhci->clock = 26 * 1000 * 1000; + sdhci->removeable = RT_TRUE; + + sdhci->detect = sdhci_detect; + sdhci->setwidth = sdhci_setwidth; + sdhci->setclock = sdhci_setclock; + sdhci->transfer = sdhci_transfer; + sdhci->priv = pdat; + //write32(pdat->virt + PL180_POWER, 0xbf); + + host->ops = &ops; + host->freq_min = 400000; + host->freq_max = 50000000; + host->valid_ocr = VDD_32_33 | VDD_33_34; + host->flags = MMCSD_MUTBLKWRITE | MMCSD_SUP_HIGHSPEED | MMCSD_SUP_SDIO_IRQ | MMCSD_BUSWIDTH_4; + host->max_seg_size = 2048; + host->max_dma_segs = 10; + host->max_blk_size = 512; + host->max_blk_count = 4096; + + host->private_data = sdhci; + + mmcsd_change(host); + + return RT_EOK; + +err: + if(host) rt_free(host); + if(sdhci) rt_free(sdhci); + + return -RT_EIO; +#endif +} +INIT_APP_EXPORT(raspi_sdmmc_init); +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.h b/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.h new file mode 100644 index 0000000000000000000000000000000000000000..8ab10aebb68ee23dbe8b6d8eb160a1643370d3c4 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_sdio.h @@ -0,0 +1,345 @@ +/* + * File : drv_sdio.h + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_SDIO_H__ +#define __DRV_SDIO_H__ + +#include + +#define MMC0_BASE_ADDR 0x20300000 + +struct raspi_mmc +{ + volatile rt_uint32_t arg2_reg; /* (0x000) */ + volatile rt_uint32_t blksizecnt_reg; /* (0x004) */ + volatile rt_uint32_t arg1_reg; /* (0x008) */ + volatile rt_uint32_t cmdtm_reg; /* (0x00C) */ + volatile rt_uint32_t resp0_reg; /* (0x010) */ + volatile rt_uint32_t resp1_reg; /* (0x014) */ + volatile rt_uint32_t resp2_reg; /* (0x018) */ + volatile rt_uint32_t resp3_reg; /* (0x01C) */ + volatile rt_uint32_t data_reg; /* (0x020) */ + volatile rt_uint32_t status_reg; /* (0x024) */ + volatile rt_uint32_t control0_reg; /* (0x028) */ + volatile rt_uint32_t control1_reg; /* (0x02C) */ + volatile rt_uint32_t interrupt_reg; /* (0x030) */ + volatile rt_uint32_t irpt_mask_reg; /* (0x034) */ + volatile rt_uint32_t irpt_en_reg; /* (0x038) */ + volatile rt_uint32_t control2_reg; /* (0x03C) */ + volatile rt_uint32_t reserved1[4]; /* (0x040) */ + volatile rt_uint32_t force_irpt_reg; /* (0x050) */ + volatile rt_uint32_t reserved2[7]; /* (0x054) */ + volatile rt_uint32_t boot_timeout_reg; /* (0x070) */ + volatile rt_uint32_t deg_sel_reg; /* (0x074) */ + volatile rt_uint32_t reserved3[2]; /* (0x078) */ + volatile rt_uint32_t exrdfifo_cfg_reg; /* (0x080) */ + volatile rt_uint32_t exrdfifo_cn_reg; /* (0x084) */ + volatile rt_uint32_t tune_step_reg; /* (0x088) */ + volatile rt_uint32_t tune_step_std_reg; /* (0x08C) */ + volatile rt_uint32_t tune_step_ddr_reg; /* (0x090) */ + volatile rt_uint32_t reserved4[23]; /* (0x094) */ + volatile rt_uint32_t spi_int_reg; /* (0x0f0) */ + volatile rt_uint32_t reserved5[2]; /* (0x0f4) */ + volatile rt_uint32_t slotisr_ver_reg; /* (0x0fC) */ +}; + +typedef struct raspi_mmc *raspi_mmc_t; + +#define MMC0 ((tina_mmc_t)MMC0_BASE_ADDR) + + +#define BIT(x) (1<<(x)) + +/* Struct for Intrrrupt Information */ +#define SDXC_CmdDone BIT(0) +#define SDXC_DataDone BIT(1) +#define SDXC_BlockGap BIT(2) +#define SDXC_WriteRdy BIT(4) +#define SDXC_ReadRdy BIT(5) +#define SDXC_Card BIT(8) +#define SDXC_Retune BIT(12) +#define SDXC_BootAck BIT(13) +#define SDXC_EndBoot BIT(14) +#define SDXC_Err BIT(15) +#define SDXC_CTOErr BIT(16) +#define SDXC_CCRCErr BIT(17) +#define SDXC_CENDErr BIT(18) +#define SDXC_CBADErr BIT(19) +#define SDXC_DTOErr BIT(20) +#define SDXC_DCRCErr BIT(21) +#define SDXC_DENDErr BIT(22) +#define SDXC_ACMDErr BIT(24) + + +/* + SD CMD reg +REG[0-5] : Cmd ID +REG[6] : Has response +REG[7] : Long response +REG[8] : Check response CRC +REG[9] : Has data +REG[10] : Write +REG[11] : Steam mode +REG[12] : Auto stop +REG[13] : Wait previous over +REG[14] : About cmd +REG[15] : Send initialization +REG[21] : Update clock +REG[31] : Load cmd +*/ + + +#define SDXC_BLKCNT_EN BIT(1) +#define SDXC_AUTO_CMD12_EN BIT(2) +#define SDXC_AUTO_CMD23_EN BIT(3) +#define SDXC_DAT_DIR BIT(4) //from card to host +#define SDXC_MULTI_BLOCK BIT(5) +#define SDXC_CMD_RSPNS_136 BIT(16) +#define SDXC_CMD_RSPNS_48 BIT(17) +#define SDXC_CMD_RSPNS_48busy BIT(16)|BIT(17) +#define SDXC_CHECK_CRC_CMD BIT(19) +#define SDXC_CMD_IXCHK_EN BIT(20) +#define SDXC_CMD_ISDATA BIT(21) +#define SDXC_CMD_SUSPEND BIT(22) +#define SDXC_CMD_RESUME BIT(23) +#define SDXC_CMD_ABORT BIT(23)|BIT(22) + +//#define SDXC_CHECK_CRC_CMD BIT(19) +// +//#define SDXC_RESPONSE_CMD BIT(6) +//#define SDXC_LONG_RESPONSE_CMD BIT(7) +//#define SDXC_CHECK_CRC_CMD BIT(8) +//#define SDXC_HAS_DATA_CMD BIT(9) +//#define SDXC_WRITE_CMD BIT(10) +//#define SDXC_STEAM_CMD BIT(11) +//#define SDXC_AUTO_STOP_CMD BIT(12) +//#define SDXC_WAIT_OVER_CMD BIT(13) +//#define SDXC_ABOUT_CMD BIT(14) +//#define SDXC_SEND_INIT_CMD BIT(15) +//#define SDXC_UPDATE_CLOCK_CMD BIT(21) +//#define SDXC_LOAD_CMD BIT(31) + +/* + SD status reg +REG[0] : FIFO_RX_LEVEL +REG[1] : FIFO_TX_LEVEL +REG[2] : FIFO_EMPTY +REG[3] : FIFO_FULL +REG[4-7] : FSM_STA +REG[8] : CARD_PRESENT +REG[9] : CARD_BUSY +REG[10] : FSM_BUSY +REG[11-16]: RESP_IDX +REG[17-21]: FIFO_LEVEL +REG[31] : DMA_REQ +*/ + +#define SDXC_CMD_INHIBIT BIT(0) +#define SDXC_DAT_INHIBIT BIT(1) +#define SDXC_DAT_ACTIVE BIT(2) +#define SDXC_WRITE_TRANSFER BIT(8) +#define SDXC_READ_TRANSFER BIT(9) + +// +// +//#define SDXC_FIFO_RX_LEVEL BIT(0) +//#define SDXC_FIFO_TX_LEVEL BIT(1) +//#define SDXC_FIFO_EMPTY BIT(2) +//#define SDXC_FIFO_FULL BIT(3) +//#define SDXC_CARD_PRESENT BIT(8) +//#define SDXC_CARD_BUSY BIT(9) +//#define SDXC_FSM_BUSY BIT(10) +//#define SDXC_DMA_REQ BIT(31) + +struct mmc_des_v4p1 +{ + rt_uint32_t : 1, + dic : 1, /* disable interrupt on completion */ + last_des : 1, /* 1-this data buffer is the last buffer */ + first_des : 1, /* 1-data buffer is the first buffer,0-data buffer contained in the next descriptor is 1st buffer */ + des_chain : 1, /* 1-the 2nd address in the descriptor is the next descriptor address */ + end_of_ring : 1, /* 1-last descriptor flag when using dual data buffer in descriptor */ + : 24, + card_err_sum : 1, /* transfer error flag */ + own : 1; /* des owner:1-idma owns it, 0-host owns it */ + +#define SDXC_DES_NUM_SHIFT 12 /* smhc2!! */ +#define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT) + rt_uint32_t data_buf1_sz : 16, + data_buf2_sz : 16; + rt_uint32_t buf_addr_ptr1; + rt_uint32_t buf_addr_ptr2; +}; + +struct sdhci_cmd_t +{ + rt_uint32_t cmdidx; + rt_uint32_t cmdarg; + //const char* name; + // rt_uint32_t code; + rt_uint32_t resptype; + // rt_uint8_t rca; + // rt_uint32_t delay; + rt_uint32_t response[4]; +}; + +struct sdhci_data_t +{ + rt_uint8_t * buf; + rt_uint32_t flag; + rt_uint32_t blksz; + rt_uint32_t blkcnt; +}; + +struct sdhci_t +{ + char * name; + rt_uint32_t voltages; + rt_uint32_t width; + rt_uint32_t clock; + rt_err_t removeable; + void * sdcard; + + rt_err_t (*detect)(struct sdhci_t * sdhci); + rt_err_t (*setwidth)(struct sdhci_t * sdhci, rt_uint32_t width); + rt_err_t (*setclock)(struct sdhci_t * sdhci, rt_uint32_t clock); + rt_err_t (*transfer)(struct sdhci_t * sdhci, struct sdhci_cmd_t * cmd, struct sdhci_data_t * dat); + void * priv; +}; + +struct sdhci_pdata_t +{ + rt_uint32_t virt; +}; + +// EMMC command flags +#define CMD_TYPE_NORMAL 0x00000000 +#define CMD_TYPE_SUSPEND 0x00400000 +#define CMD_TYPE_RESUME 0x00800000 +#define CMD_TYPE_ABORT 0x00c00000 +#define CMD_IS_DATA 0x00200000 +#define CMD_IXCHK_EN 0x00100000 +#define CMD_CRCCHK_EN 0x00080000 +#define CMD_RSPNS_NO 0x00000000 +#define CMD_RSPNS_136 0x00010000 +#define CMD_RSPNS_48 0x00020000 +#define CMD_RSPNS_48B 0x00030000 +#define TM_MULTI_BLOCK 0x00000020 +#define TM_DAT_DIR_HC 0x00000000 +#define TM_DAT_DIR_CH 0x00000010 +#define TM_AUTO_CMD23 0x00000008 +#define TM_AUTO_CMD12 0x00000004 +#define TM_BLKCNT_EN 0x00000002 +#define TM_MULTI_DATA (CMD_IS_DATA|TM_MULTI_BLOCK|TM_BLKCNT_EN) + +// Response types. +// Note that on the PI, the index and CRC are dropped, leaving 32 bits in RESP0. +#define RESP_NO 0 // No response +//#define RESP_R1 1 // 48 RESP0 contains card status +#define RESP_R1b 11 // 48 RESP0 contains card status, data line indicates busy +#define RESP_R2I 2 // 136 RESP0..3 contains 128 bit CID shifted down by 8 bits as no CRC +#define RESP_R2S 12 // 136 RESP0..3 contains 128 bit CSD shifted down by 8 bits as no CRC +//#define RESP_R3 3 // 48 RESP0 contains OCR register +//#define RESP_R6 6 // 48 RESP0 contains RCA and status bits 23,22,19,12:0 +//#define RESP_R7 7 // 48 RESP0 contains voltage acceptance and check pattern + +#define RCA_NO 1 +#define RCA_YES 2 + +// INTERRUPT register settings +#define INT_AUTO_ERROR 0x01000000 +#define INT_DATA_END_ERR 0x00400000 +#define INT_DATA_CRC_ERR 0x00200000 +#define INT_DATA_TIMEOUT 0x00100000 +#define INT_INDEX_ERROR 0x00080000 +#define INT_END_ERROR 0x00040000 +#define INT_CRC_ERROR 0x00020000 +#define INT_CMD_TIMEOUT 0x00010000 +#define INT_ERR 0x00008000 +#define INT_ENDBOOT 0x00004000 +#define INT_BOOTACK 0x00002000 +#define INT_RETUNE 0x00001000 +#define INT_CARD 0x00000100 +#define INT_READ_RDY 0x00000020 +#define INT_WRITE_RDY 0x00000010 +#define INT_BLOCK_GAP 0x00000004 +#define INT_DATA_DONE 0x00000002 +#define INT_CMD_DONE 0x00000001 +#define INT_ERROR_MASK (INT_CRC_ERROR|INT_END_ERROR|INT_INDEX_ERROR| \ + INT_DATA_TIMEOUT|INT_DATA_CRC_ERR|INT_DATA_END_ERR| \ + INT_ERR|INT_AUTO_ERROR) +#define INT_ALL_MASK (INT_CMD_DONE|INT_DATA_DONE|INT_READ_RDY|INT_WRITE_RDY|INT_ERROR_MASK) + +#define EMMC_ARG2 (0x00) +#define EMMC_BLKSIZECNT (0x04) +#define EMMC_ARG1 (0x08) +#define EMMC_CMDTM (0x0c) +#define EMMC_RESP0 (0x10) +#define EMMC_RESP1 (0x14) +#define EMMC_RESP2 (0x18) +#define EMMC_RESP3 (0x1c) +#define EMMC_DATA (0x20) +#define EMMC_STATUS (0x24) +#define EMMC_CONTROL0 (0x28) +#define EMMC_CONTROL1 (0x2c) +#define EMMC_INTERRUPT (0x30) +#define EMMC_IRPT_MASK (0x34) +#define EMMC_IRPT_EN (0x38) +#define EMMC_CONTROL2 (0x3c) +#define EMMC_BOOT_TIMEOUT (0x70) +#define EMMC_EXRDFIFO_EN (0x84) +#define EMMC_SPI_INT_SPT (0xf0) +#define EMMC_SLOTISR_VER (0xfc) + +// CONTROL register settings +#define C0_SPI_MODE_EN 0x00100000 +#define C0_HCTL_HS_EN 0x00000004 +#define C0_HCTL_DWITDH 0x00000002 + +#define C1_SRST_DATA 0x04000000 +#define C1_SRST_CMD 0x02000000 +#define C1_SRST_HC 0x01000000 +#define C1_TOUNIT_DIS 0x000f0000 +#define C1_TOUNIT_MAX 0x000e0000 +#define C1_CLK_GENSEL 0x00000020 +#define C1_CLK_EN 0x00000004 +#define C1_CLK_STABLE 0x00000002 +#define C1_CLK_INTLEN 0x00000001 + +#define FREQ_SETUP 400000 // 400 Khz +#define FREQ_NORMAL 25000000 // 25 Mhz + +// SLOTISR_VER values +#define HOST_SPEC_NUM 0x00ff0000 +#define HOST_SPEC_NUM_SHIFT 16 +#define HOST_SPEC_V3 2 +#define HOST_SPEC_V2 1 +#define HOST_SPEC_V1 0 + +// STATUS register settings +#define SR_DAT_LEVEL1 0x1e000000 +#define SR_CMD_LEVEL 0x01000000 +#define SR_DAT_LEVEL0 0x00f00000 +#define SR_DAT3 0x00800000 +#define SR_DAT2 0x00400000 +#define SR_DAT1 0x00200000 +#define SR_DAT0 0x00100000 +#define SR_WRITE_PROT 0x00080000 // From SDHC spec v2, BCM says reserved +#define SR_READ_AVAILABLE 0x00000800 // ???? undocumented +#define SR_WRITE_AVAILABLE 0x00000400 // ???? undocumented +#define SR_READ_TRANSFER 0x00000200 +#define SR_WRITE_TRANSFER 0x00000100 +#define SR_DAT_ACTIVE 0x00000004 +#define SR_DAT_INHIBIT 0x00000002 +#define SR_CMD_INHIBIT 0x00000001 + + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_spi.c b/bsp/raspberry-pi/raspi3-64/driver/drv_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..041a97b510bd1daa004e75d6643f3d088007f607 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_spi.c @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include "drv_spi.h" + +#if !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1) +#ifdef RT_USING_SPI +#undef RT_USING_SPI +#endif +#endif + +#ifdef RT_USING_SPI + + +static rt_uint8_t bcm2835_spi_bit_order = BCM283X_SPI_BIT_ORDER_MSBFIRST; +static rt_uint8_t bcm2835_byte_reverse_table[] = +{ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +#define BSP_SPI_MAX_HZ (30* 1000 *1000) +#define SPITIMEOUT 0x0FFF + +struct rt_spi_hw_config +{ + rt_int8_t sclk_pin; + rt_int8_t sclk_mode; + rt_int8_t mosi_pin; + rt_int8_t mosi_mode; + rt_int8_t miso_pin; + rt_int8_t miso_mode; + rt_int8_t cs_pin; + rt_int8_t cs_mode; + rt_uint32_t spi_base; + rt_uint32_t clk_div; +}; + +struct rt_sw_spi_cs +{ + rt_uint32_t pin; +}; + +struct rt_spi +{ + char *device_name; + struct rt_spi_bus *spi_bus; + struct rt_spi_hw_config *hwcfg; + struct rt_spi_configuration *cfg; +}; + +static rt_err_t raspi_hostspi_init(struct rt_spi_configuration *cfg) +{ + + volatile rt_uint32_t addr = (PER_BASE + BCM283X_SPI0_BASE) + BCM283X_SPI0_CS; + //volatile rt_uint32_t fifo = (PER_BASE + BCM283X_SPI0_BASE) + BCM283X_SPI0_FIFO; + + // spi clear fifo + bcm283x_peri_set_bits(addr, BCM283X_SPI0_CS_CLEAR, BCM283X_SPI0_CS_CLEAR); + + // /* Set TA = 1 */ + // bcm2835_peri_set_bits(addr, BCM283X_SPI0_CS_TA, BCM283X_SPI0_CS_TA); + + /* Mask in the CPO and CPHA bits of CS */ + + bcm283x_peri_set_bits(addr, (rt_uint32_t)(cfg->mode << 2), BCM283X_SPI0_CS_CPOL | BCM283X_SPI0_CS_CPHA); + + //chipSelect + bcm283x_peri_set_bits(addr, BCM283X_SPI_CS0, BCM283X_SPI0_CS_CS); + + rt_uint8_t shift = 21 + BCM283X_SPI_CS0; + /* Mask in the appropriate CSPOLn bit */ + bcm283x_peri_set_bits(addr, LOW << shift, 1 << shift); + + + if(cfg->max_hz > BSP_SPI_MAX_HZ) + { + cfg->max_hz = BSP_SPI_MAX_HZ; + } + + volatile rt_uint32_t clk_addr = (PER_BASE + BCM283X_SPI0_BASE) + BCM283X_SPI0_CLK; + bcm283x_peri_write(clk_addr, cfg->max_hz); + + return RT_EOK; +} + +static rt_err_t raspi_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg) +{ + RT_ASSERT(cfg != RT_NULL); + RT_ASSERT(device != RT_NULL); + + struct rt_spi *hspi = (struct rt_spi *)&device->bus->parent; + hspi->cfg = cfg; + + raspi_hostspi_init(cfg); + + return RT_EOK; +} + + +rt_uint8_t correct_order(rt_uint8_t b) +{ + if (bcm2835_spi_bit_order == BCM283X_SPI_BIT_ORDER_LSBFIRST) + return bcm2835_byte_reverse_table[b]; + else + return b; +} + +static rt_err_t spi_transfernb(rt_uint8_t* tbuf, rt_uint8_t* rbuf, rt_uint32_t len) +{ + volatile rt_uint32_t paddr = SPI0_BASE_ADDR + BCM283X_SPI0_CS; + volatile rt_uint32_t fifo = SPI0_BASE_ADDR + BCM283X_SPI0_FIFO; + rt_uint32_t TXCnt=0; + rt_uint32_t RXCnt=0; + + /* Clear TX and RX fifos */ + bcm283x_peri_set_bits(paddr, BCM283X_SPI0_CS_CLEAR, BCM283X_SPI0_CS_CLEAR); + + /* Set TA = 1 */ + bcm283x_peri_set_bits(paddr, BCM283X_SPI0_CS_TA, BCM283X_SPI0_CS_TA); + + /* Use the FIFO's to reduce the interbyte times */ + while ((TXCnt < len) || (RXCnt < len)) + { + /* TX fifo not full, so add some more bytes */ + while (((bcm283x_peri_read(paddr) & BCM283X_SPI0_CS_TXD)) && (TXCnt < len)) + { + bcm283x_peri_write_nb(fifo, correct_order(tbuf[TXCnt])); + TXCnt++; + } + /* Rx fifo not empty, so get the next received bytes */ + while (((bcm283x_peri_read(paddr) & BCM283X_SPI0_CS_RXD)) && (RXCnt < len)) + { + rbuf[RXCnt] = correct_order(bcm283x_peri_read_nb(fifo)); + RXCnt++; + } + } + /* Wait for DONE to be set */ + while (!(bcm283x_peri_read_nb(paddr) & BCM283X_SPI0_CS_DONE)); + + /* Set TA = 0, and also set the barrier */ + bcm283x_peri_set_bits(paddr, 0, BCM283X_SPI0_CS_TA); + return RT_EOK; + +} + +static rt_uint32_t raspi_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + rt_err_t res; + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(device->bus->parent.user_data != RT_NULL); + RT_ASSERT(message->send_buf != RT_NULL || message->recv_buf != RT_NULL); + + struct rt_spi *hspi = (struct rt_spi *)&device->bus->parent; + /* only send data */ + if (message->recv_buf == RT_NULL) + { + if (message->cs_take) + { + bcm283x_gpio_write(hspi->hwcfg->cs_pin, 0); + } + res = spi_transfernb((rt_uint8_t *)message->send_buf, RT_NULL,(rt_int32_t)message->length); + if (message->cs_release) + { + bcm283x_gpio_write(hspi->hwcfg->cs_pin, 1); + + } + if (res != RT_EOK) + return RT_ERROR; + } + + /* only receive data */ + if (message->send_buf == RT_NULL) + { + if (message->cs_take) + { + bcm283x_gpio_write(hspi->hwcfg->cs_pin, 0); + } + res = spi_transfernb(RT_NULL,(rt_uint8_t *)message->recv_buf, (rt_int32_t)message->length); + if (message->cs_release) + { + bcm283x_gpio_write(hspi->hwcfg->cs_pin, 1); + } + if (res != RT_EOK) + return RT_ERROR; + } + /* send & receive */ + else + { + if (message->cs_take) + { + bcm283x_gpio_write(hspi->hwcfg->cs_pin, 0); + } + res = spi_transfernb((rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf, + (rt_int32_t)message->length); + if (message->cs_release) + { + bcm283x_gpio_write(hspi->hwcfg->cs_pin, 1); + } + if (res != RT_EOK) + return RT_ERROR; + } + + return message->length; +} + +rt_err_t raspi_spi_bus_attach_device(const char *bus_name, const char *device_name, rt_uint32_t pin) +{ + rt_err_t ret; + rt_int16_t gpio_pin; + struct rt_spi_device *spi_device; + struct rt_sw_spi_cs *cs_pin; + + gpio_pin = phypin_index[pin].bcm_id; + + spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + RT_ASSERT(spi_device != RT_NULL); + + cs_pin = (struct rt_sw_spi_cs *)rt_malloc(sizeof(struct rt_sw_spi_cs)); + RT_ASSERT(cs_pin != RT_NULL); + + cs_pin->pin = gpio_pin; + + ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); + + return ret; +} + +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +rt_uint16_t spi_clockdivider(rt_uint32_t speed_hz) +{ + rt_uint16_t divider; + + if (speed_hz < (rt_uint32_t) BCM283X_AUX_SPI_CLOCK_MIN) + { + speed_hz = (rt_uint32_t) BCM283X_AUX_SPI_CLOCK_MIN; + } + else if (speed_hz > (rt_uint32_t) BCM283X_AUX_SPI_CLOCK_MAX) + { + speed_hz = (rt_uint32_t) BCM283X_AUX_SPI_CLOCK_MAX; + } + + divider = (rt_uint16_t) DIV_ROUND_UP(BCM283X_CORE_CLK_HZ, 2 * speed_hz) - 1; + + if (divider > (rt_uint16_t) BCM283X_AUX_SPI_CNTL0_SPEED_MAX) + { + return (rt_uint16_t) BCM283X_AUX_SPI_CNTL0_SPEED_MAX; + } + + return divider; +} + +rt_err_t raspi_spi_hw_init(struct rt_spi_hw_config *hwcfg) +{ + volatile rt_uint32_t enable = PER_BASE + BCM283X_AUX_BASE + BCM283X_AUX_ENABLE; + volatile rt_uint32_t cntl0 = PER_BASE + BCM283X_SPI1_BASE + BCM283X_AUX_SPI_CNTL0; + volatile rt_uint32_t cntl1 = PER_BASE + BCM283X_SPI1_BASE + BCM283X_AUX_SPI_CNTL1; + + bcm283x_gpio_fsel(hwcfg->sclk_pin, hwcfg->sclk_mode); + bcm283x_gpio_fsel(hwcfg->miso_pin, hwcfg->miso_mode); + bcm283x_gpio_fsel(hwcfg->mosi_pin, hwcfg->mosi_mode); + bcm283x_gpio_fsel(hwcfg->cs_pin, hwcfg->cs_mode); + + hwcfg->clk_div = spi_clockdivider(1000000); // Default 1MHz SPI + + bcm283x_peri_write(enable, BCM283X_AUX_ENABLE_SPI0); + bcm283x_peri_write(cntl1, 0); + bcm283x_peri_write(cntl0, BCM283X_AUX_SPI_CNTL0_CLEARFIFO); + + return RT_EOK; +} + +const static struct rt_spi_ops raspi_spi_ops = +{ + .configure = raspi_spi_configure, + .xfer = raspi_spi_xfer +}; + +#if defined (BSP_USING_SPI0) +#define SPI0BUS_NAME "spi0.0" + +struct rt_spi_bus raspi_spi0_bus = +{ + .ops = &raspi_spi_ops, + .parent.user_data = spi0 +}; + +struct rt_spi_hw_config raspi_spi0_hw = +{ + .sclk_pin = BCM_GPIO_PIN_11, + .sclk_mode = BCM283X_GPIO_FSEL_ALT0, + .mosi_pin = BCM_GPIO_PIN_10, + .mosi_mode = BCM283X_GPIO_FSEL_ALT0, + .miso_pin = BCM_GPIO_PIN_9, + .miso_mode = BCM283X_GPIO_FSEL_ALT0, + .cs_pin = BCM_GPIO_PIN_8, + .cs_mode = BCM283X_GPIO_FSEL_ALT0, + .spi_base = (PER_BASE + BCM283X_SPI0_BASE), + .clk_div = 0, +}; + +struct rt_spi spi0 = +{ + .device_name = SPI0BUS_NAME, + .spi_bus = &raspi_spi0_bus, + .hwcfg = &raspi_spi0_hw, +}; + +#endif + +#if defined (BSP_USING_SPI1) +#define SPI1BUS_NAME "spi0.1" + +struct rt_spi_bus raspi_spi1_bus = +{ + .ops = &raspi_spi_ops, + .parent.user_data = spi1 +}; + +struct rt_spi_hw_config raspi_spi1_hw = +{ + .sclk_pin = BCM_GPIO_PIN_11, + .sclk_mode = BCM283X_GPIO_FSEL_ALT0, + .mosi_pin = BCM_GPIO_PIN_10, + .mosi_mode = BCM283X_GPIO_FSEL_ALT0, + .miso_pin = BCM_GPIO_PIN_9, + .miso_mode = BCM283X_GPIO_FSEL_ALT0, + .cs_pin = BCM_GPIO_PIN_7, + .cs_mode = BCM283X_GPIO_FSEL_ALT0, + .spi_base = (PER_BASE + BCM283X_SPI0_BASE), + .clk_div = 0, +}; + +struct rt_spi spi1 = +{ + .device_name = SPI1BUS_NAME, + .spi_bus = &raspi_spi1_bus, + .hwcfg = &raspi_spi1_hw, +}; +#endif + +int rt_hw_spi_bus_init(void) +{ +#if defined (BSP_USING_SPI0) + raspi_spi_hw_init(spi0.hwcfg); + rt_spi_bus_register(spi0.spi_bus, spi0.device_name, spi0.spi_bus->ops); +#endif + +#if defined (BSP_USING_SPI1) + raspi_spi_hw_init(spi1.hwcfg); + rt_spi_bus_register(spi1.spi_bus, spi1.device_name, spi1.spi_bus->ops); +#endif + + return RT_EOK; +} +INIT_PREV_EXPORT(rt_hw_spi_bus_init); + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_spi.h b/bsp/raspberry-pi/raspi3-64/driver/drv_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..c4883758e584ee5ddb2a5bc848a74b67b1a13dbf --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_spi.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#include +#include + +#include "bcm283x.h" +#include +#include +#include "raspi.h" + +#define SPI0_BASE_ADDR (PER_BASE + BCM283X_SPI0_BASE) + +#define SPI_CORE_CLK 250000000U +#define SPI_CS 0x00 +#define SPI_CS_LEN_LONG (1 << 25) +#define SPI_CS_DMA_LEN (1 << 24) +#define SPI_CS_CSPOL2 (1 << 23) +#define SPI_CS_CSPOL1 (1 << 22) +#define SPI_CS_CSPOL0 (1 << 21) +#define SPI_CS_RXF (1 << 20) +#define SPI_CS_RXR (1 << 19) +#define SPI_CS_TXD (1 << 18) +#define SPI_CS_RXD (1 << 17) +#define SPI_CS_DONE (1 << 16) +#define SPI_CS_LEN (1 << 13) +#define SPI_CS_REN (1 << 12) +#define SPI_CS_ADCS (1 << 11) +#define SPI_CS_INTR (1 << 10) +#define SPI_CS_INTD (1 << 9) +#define SPI_CS_DMAEN (1 << 8) +#define SPI_CS_TA (1 << 7) +#define SPI_CS_CSPOL (1 << 6) +#define SPI_CS_CLEAR_RXFIFO (1 << 5) +#define SPI_CS_CLEAR_TXFIFO (1 << 4) +#define SPI_CS_CPOL (1 << 3) +#define SPI_CS_CPHA (1 << 2) +#define SPI_CS_MASK 0x3 +#define SPI_FIFO 0x04 +#define SPI_CLK 0x08 +#define SPI_CLK_MASK 0xffff +#define SPI_DLEN 0x0c +#define SPI_DLEN_MASK 0xffff +#define SPI_LTOH 0x10 +#define SPI_LTOH_MASK 0xf +#define SPI_DC 0x14 +#define SPI_DC_RPANIC_SHIFT 24 +#define SPI_DC_RPANIC_MASK (0xff << SPI_DC_RPANIC_SHIFT) +#define SPI_DC_RDREQ_SHIFT 16 +#define SPI_DC_RDREQ_MASK (0xff << SPI_DC_RDREQ_SHIFT) +#define SPI_DC_TPANIC_SHIFT 8 +#define SPI_DC_TPANIC_MASK (0xff << SPI_DC_TPANIC_SHIFT) +#define SPI_DC_TDREQ_SHIFT 0 +#define SPI_DC_TDREQ_MASK 0xff + +int rt_hw_spi_bus_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_timer.c b/bsp/raspberry-pi/raspi3-64/driver/drv_timer.c new file mode 100644 index 0000000000000000000000000000000000000000..0ead0fdf742221ff2703379c059420530c34442f --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_timer.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#include +#include +#include "bcm283x.h" +#include "drv_timer.h" +#include +#include "cp15.h" + +static void rt_systimer_init(rt_hwtimer_t *hwtimer, rt_uint32_t state) +{ + if (state == 0) + hwtimer->ops->stop(hwtimer); +} + +static rt_err_t rt_systimer_start(rt_hwtimer_t *hwtimer, rt_uint32_t cnt, rt_hwtimer_mode_t mode) +{ + rt_err_t result = RT_EOK; + rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data; + int timer_id = timer->timer_id; + if (mode == HWTIMER_MODE_PERIOD) + timer->cnt = cnt; + else + timer->cnt = 0; + __DSB(); + if (timer_id == 1) + { + rt_hw_interrupt_umask(IRQ_SYSTIMER_MATCH_1); + STIMER_C1 = STIMER_CLO + cnt; + } + else if (timer_id == 3) + { + rt_hw_interrupt_umask(IRQ_SYSTIMER_MATCH_3); + STIMER_C3 = STIMER_CLO + cnt; + } + else + result = -RT_ERROR; + __DSB(); + + return result; +} + +static void rt_systimer_stop(rt_hwtimer_t *hwtimer) +{ + rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data; + int timer_id = timer->timer_id; + if (timer_id == 1) + rt_hw_interrupt_mask(IRQ_SYSTIMER_MATCH_1); + else if (timer_id == 3) + rt_hw_interrupt_mask(IRQ_SYSTIMER_MATCH_3); + +} + +static rt_err_t rt_systimer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg) +{ + /* The frequency value is an immutable value. */ + if (cmd == HWTIMER_CTRL_FREQ_SET) + { + return RT_EOK; + } + else + { + return -RT_ENOSYS; + } +} + +const static struct rt_hwtimer_ops systimer_ops = +{ + rt_systimer_init, + rt_systimer_start, + rt_systimer_stop, + RT_NULL, + rt_systimer_ctrl +}; + +void rt_device_systimer_isr(int vector, void *param) +{ + rt_hwtimer_t *hwtimer = (rt_hwtimer_t *) param; + rt_systimer_t *timer = (rt_systimer_t *)hwtimer->parent.user_data; + RT_ASSERT(timer != RT_NULL); + int timer_id = timer->timer_id; + + __DSB(); + if (timer_id == 1) + { + STIMER_CS = 0x2; + STIMER_C1 = STIMER_CLO + timer->cnt; + } + else if (timer_id == 3) + { + STIMER_CS = 0x8; + STIMER_C3 = STIMER_CLO + timer->cnt; + } + + __DSB(); + rt_device_hwtimer_isr(hwtimer); +} + +static struct rt_hwtimer_device _hwtimer1; +static struct rt_hwtimer_device _hwtimer3; +static struct rt_systimer_device _systimer1; +static struct rt_systimer_device _systimer3; + +static const struct rt_hwtimer_info _info = +{ + 1000000, /* the maxinum count frequency can be set */ + 1000000, /* the maxinum count frequency can be set */ + 0xFFFFFFFF, /* the maximum counter value */ + HWTIMER_CNTMODE_UP /* count mode (inc/dec) */ +}; + +int rt_hw_systimer_init(void) +{ +#ifdef RT_USING_SYSTIMER1 + _systimer1.timer_id =1; + _hwtimer1.ops = &systimer_ops; + _hwtimer1.info = &_info; + rt_device_hwtimer_register(&_hwtimer1, "timer1",&_systimer1); + rt_hw_interrupt_install(IRQ_SYSTIMER_MATCH_1, rt_device_systimer_isr, &_hwtimer1, "systimer1"); + rt_hw_interrupt_umask(IRQ_SYSTIMER_MATCH_1); +#endif + +#ifdef RT_USING_SYSTIMER3 + _systimer3.timer_id =3; + _hwtimer3.ops = &systimer_ops; + _hwtimer3.info = &_info; + rt_device_hwtimer_register(&_hwtimer3, "timer3",&_systimer3); + rt_hw_interrupt_install(IRQ_SYSTIMER_MATCH_3, rt_device_systimer_isr, &_hwtimer3, "systimer3"); + +#endif + + return 0; +} diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_timer.h b/bsp/raspberry-pi/raspi3-64/driver/drv_timer.h new file mode 100644 index 0000000000000000000000000000000000000000..c18e3d893c4d6d7ed3e75c5cb58fe6f8eb8a28e7 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_timer.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ +#ifndef __DRV_TIMER_H__ +#define __DRV_TIMER_H__ + +#include +#include + +typedef struct rt_systimer_device +{ + int timer_id; + rt_uint32_t cnt; +} rt_systimer_t; + +int rt_hw_systimer_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_uart.c b/bsp/raspberry-pi/raspi3-64/driver/drv_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..fd8ec66af9536a1027df4aa92ec9b6c7222a93b8 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_uart.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/5/5 Bernard The first version + */ + +#include +#include +#include + +#include "board.h" +#include "drv_uart.h" + +#include + +#define AUX_BASE (0x3F000000 + 0x215000) + +struct hw_uart_device +{ + rt_ubase_t hw_base; + rt_uint32_t irqno; +}; + +static rt_err_t uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + if (uart->hw_base == AUX_BASE) + { + rt_uint32_t value; + + /* GPIO function set */ + value = GPIO_GPFSEL1; + value &= ~(7<<12); /* GPIO14 */ + value |= 2<<12 ; /* ALT5 */ + value &= ~(7<<15); /* GPIO15 */ + value |= 2<<15 ; /* ALT5 */ + GPIO_GPFSEL1 = value; + + /* PullUD disable */ + GPIO_GPPUD = 0; + GPIO_GPPUDCLK0 = (1 << 14) | (1 << 15); + GPIO_GPPUDCLK0 = 0; + + AUX_ENABLES(uart->hw_base) = 1; /* Enable UART1 */ + AUX_MU_IER_REG(uart->hw_base) = 0; /* Disable interrupt */ + AUX_MU_CNTL_REG(uart->hw_base) = 0; /* Disable Transmitter and Receiver */ + AUX_MU_LCR_REG(uart->hw_base) = 3; /* Works in 8-bit mode */ + AUX_MU_MCR_REG(uart->hw_base) = 0; /* Disable RTS */ + AUX_MU_IIR_REG(uart->hw_base) = 0xC6; /* Enable FIFO, Clear FIFO */ + AUX_MU_BAUD_REG(uart->hw_base) = 270; /* 115200 = system clock 250MHz / (8 * (baud + 1)), baud = 270 */ + AUX_MU_CNTL_REG(uart->hw_base) = 3; /* Enable Transmitter and Receiver */ + } + + return RT_EOK; +} + +static rt_err_t uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + /* disable rx irq */ + AUX_MU_IER_REG(uart->hw_base) = 0x0; + rt_hw_interrupt_mask(uart->irqno); + break; + + case RT_DEVICE_CTRL_SET_INT: + /* enable rx irq */ + AUX_MU_IER_REG(uart->hw_base) = 0x1; + rt_hw_interrupt_umask(uart->irqno); + break; + } + + return RT_EOK; +} + +static int uart_putc(struct rt_serial_device *serial, char c) +{ + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + while (!(AUX_MU_LSR_REG(uart->hw_base) & 0x20)); + AUX_MU_IO_REG(uart->hw_base) = c; + + return 1; +} + +static int uart_getc(struct rt_serial_device *serial) +{ + int ch = -1; + struct hw_uart_device *uart; + + RT_ASSERT(serial != RT_NULL); + uart = (struct hw_uart_device *)serial->parent.user_data; + + if ((AUX_MU_LSR_REG(uart->hw_base) & 0x01)) + { + ch = AUX_MU_IO_REG(uart->hw_base) & 0xff; + } + + return ch; +} + +static const struct rt_uart_ops _uart_ops = +{ + uart_configure, + uart_control, + uart_putc, + uart_getc, +}; + +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); +} + +#ifdef RT_USING_UART0 +/* UART device driver structure */ +static struct hw_uart_device _uart0_device = +{ + RPI_UART0_BASE, + IRQ_PBA8_UART0, +}; +static struct rt_serial_device _serial0; +#endif + +#ifdef RT_USING_UART1 +/* UART1 device driver structure */ +static struct hw_uart_device _uart1_device = +{ + AUX_BASE, + IRQ_AUX, +}; +static struct rt_serial_device _serial1; +#endif + +int rt_hw_uart_init(void) +{ + struct hw_uart_device *uart; + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef RT_USING_UART0 + uart = &_uart0_device; + + _serial0.ops = &_uart_ops; + _serial0.config = config; + + /* register UART1 device */ + rt_hw_serial_register(&_serial0, "uart0", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); + rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial0, "uart0"); +#endif + +#ifdef RT_USING_UART1 + uart = &_uart1_device; + _serial1.ops = &_uart_ops; + _serial1.config = config; + + /* register UART1 device */ + rt_hw_serial_register(&_serial1, "uart1", + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); + /* enable Rx and Tx of UART */ + rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, &_serial1, "uart1"); +#endif + + return 0; +} diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_uart.h b/bsp/raspberry-pi/raspi3-64/driver/drv_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..894c6098dbfaa9d9d0409b45e57a4c0758542226 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_uart.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-5-30 Bernard the first version + */ + + +#ifndef DRV_UART_H__ +#define DRV_UART_H__ + +/* + * Auxiliary + */ +#define AUX_IRQ(BASE) HWREG32(BASE + 0x00) /* Auxiliary Interrupt status 3 */ +#define AUX_ENABLES(BASE) HWREG32(BASE + 0x04) /* Auxiliary enables 3bit */ +#define AUX_MU_IO_REG(BASE) HWREG32(BASE + 0x40) /* Mini Uart I/O Data 8bit */ +#define AUX_MU_IER_REG(BASE) HWREG32(BASE + 0x44) /* Mini Uart Interrupt Enable 8bit */ +#define AUX_MU_IIR_REG(BASE) HWREG32(BASE + 0x48) /* Mini Uart Interrupt Identify 8bit */ +#define AUX_MU_LCR_REG(BASE) HWREG32(BASE + 0x4C) /* Mini Uart Line Control 8bit */ +#define AUX_MU_MCR_REG(BASE) HWREG32(BASE + 0x50) /* Mini Uart Modem Control 8bit */ +#define AUX_MU_LSR_REG(BASE) HWREG32(BASE + 0x54) /* Mini Uart Line Status 8bit */ +#define AUX_MU_MSR_REG(BASE) HWREG32(BASE + 0x58) /* Mini Uart Modem Status 8bit */ +#define AUX_MU_SCRATCH(BASE) HWREG32(BASE + 0x5C) /* Mini Uart Scratch 8bit */ +#define AUX_MU_CNTL_REG(BASE) HWREG32(BASE + 0x60) /* Mini Uart Extra Control 8bit */ +#define AUX_MU_STAT_REG(BASE) HWREG32(BASE + 0x64) /* Mini Uart Extra Status 32bit */ +#define AUX_MU_BAUD_REG(BASE) HWREG32(BASE + 0x68) /* Mini Uart Baudrate 16bit */ +#define AUX_SPI0_CNTL0_REG(BASE) HWREG32(BASE + 0x80) /* SPI 1 Control register 0 32bit */ +#define AUX_SPI0_CNTL1_REG(BASE) HWREG32(BASE + 0x84) /* SPI 1 Control register 1 8bit */ +#define AUX_SPI0_STAT_REG(BASE) HWREG32(BASE + 0x88) /* SPI 1 Status 32bit */ +#define AUX_SPI0_IO_REG(BASE) HWREG32(BASE + 0x90) /* SPI 1 Data 32bit */ +#define AUX_SPI0_PEEK_REG(BASE) HWREG32(BASE + 0x94) /* SPI 1 Peek 16bit */ +#define AUX_SPI1_CNTL0_REG(BASE) HWREG32(BASE + 0xC0) /* SPI 2 Control register 0 32bit */ +#define AUX_SPI1_CNTL1_REG(BASE) HWREG32(BASE + 0xC4) /* SPI 2 Control register 1 8bit */ + +int rt_hw_uart_init(void); + +#endif /* DRV_UART_H__ */ + diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.c b/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.c new file mode 100644 index 0000000000000000000000000000000000000000..a1baee96aabbdb73f1dc6e2ad67ce53916a1817a --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ +#include "drv_wdt.h" + +#ifdef BSP_USING_WDT + +#define PM_RSTC 0x1c +#define PM_RSTS 0x20 +#define PM_WDOG 0x24 + +#define PM_PASSWORD 0x5a000000 + +#define PM_WDOG_TIME_SET 0x000fffff +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTS_HADWRH_SET 0x00000040 +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 +#define PM_RSTC_RESET 0x00000102 +#define PM_RSTS_PARTITION_CLR 0xfffffaaa + +#define SECS_TO_WDOG_TICKS(x) ((x) << 16) +#define WDOG_TICKS_TO_SECS(x) ((x) >> 16) + +static struct raspi_wdt_driver bcm_wdt = +{ + .base = PER_BASE, +}; + +void raspi_watchdog_init(rt_uint32_t time_init) +{ + bcm_wdt.timeout = time_init; +} + +void raspi_watchdog_start() +{ + volatile rt_uint32_t cur; + bcm283x_peri_write(bcm_wdt.base + PM_WDOG, PM_PASSWORD + | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET)); + bcm283x_peri_write(bcm_wdt.base + PM_WDOG, PM_PASSWORD + | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET)); + + cur = bcm283x_peri_read(bcm_wdt.base + PM_RSTC); + + bcm283x_peri_write(bcm_wdt.base + PM_RSTC, PM_PASSWORD + | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET); + +} + +void raspi_watchdog_stop() +{ + bcm283x_peri_write(bcm_wdt.base + PM_RSTC, PM_PASSWORD | PM_RSTC_RESET); +} + +void raspi_watchdog_clr() +{ + bcm_wdt.timeout = 0; +} + +void raspi_watchdog_set_timeout( rt_uint32_t timeout_us) +{ + bcm_wdt.timeout = timeout_us; +} + +rt_uint64_t raspi_watchdog_get_timeout() +{ + return bcm_wdt.timeout; +} + +rt_uint64_t raspi_watchdog_get_timeleft() +{ + rt_uint32_t ret = bcm283x_peri_read(bcm_wdt.base + PM_WDOG); + return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET); +} + +static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt) +{ + /*init for 10S*/ + raspi_watchdog_init(1000000); + raspi_watchdog_start(); + raspi_watchdog_stop(); + return RT_EOK; +} + +static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg) +{ + rt_uint64_t timeout_us = 0; + switch (cmd) + { + case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: + timeout_us = *((rt_uint32_t *)arg) * 1000000; + if (timeout_us >= 0xFFFFFFFF) + timeout_us = 0xFFFFFFFF; + raspi_watchdog_set_timeout((rt_uint32_t)timeout_us); + break; + case RT_DEVICE_CTRL_WDT_GET_TIMEOUT: + timeout_us = raspi_watchdog_get_timeout(); + *((rt_uint32_t *)arg) = timeout_us / 1000000; + break; + case RT_DEVICE_CTRL_WDT_GET_TIMELEFT: + timeout_us = raspi_watchdog_get_timeleft(); + *((rt_uint32_t *)arg) = timeout_us / 1000000; + break; + case RT_DEVICE_CTRL_WDT_KEEPALIVE: + raspi_watchdog_clr(); + break; + case RT_DEVICE_CTRL_WDT_START: + raspi_watchdog_start(); + break; + case RT_DEVICE_CTRL_WDT_STOP: + raspi_watchdog_stop(); + break; + default: + return RT_EIO; + } + return RT_EOK; +} + +static const struct rt_watchdog_ops raspi_wdg_pos = +{ + raspi_wdg_init, + raspi_wdg_control, +}; + +static rt_watchdog_t raspi_wdg; + +int rt_hw_wdt_init(void) +{ + raspi_wdg.ops = &raspi_wdg_pos; + rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL); + return RT_EOK; +} +INIT_DEVICE_EXPORT(rt_hw_wdt_init); +#endif /*BSP_USING_WDT */ diff --git a/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.h b/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.h new file mode 100644 index 0000000000000000000000000000000000000000..a690becfd1c4d18910ee24adc423c4c2d6aafcaf --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/drv_wdt.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __DRV_WDT_H__ +#define __DRV_WDT_H__ + +#include +#include +#include +#include + +#include "bcm283x.h" + +struct raspi_wdt_driver +{ + volatile rt_uint32_t base; + rt_uint32_t timeout; +}; + +int rt_hw_wdt_init(void); + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/mbox.c b/bsp/raspberry-pi/raspi3-64/driver/mbox.c new file mode 100644 index 0000000000000000000000000000000000000000..36ed95b429ddd9ea08f02e0011fc58a3b879f4c8 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/mbox.c @@ -0,0 +1,53 @@ +/* + * File : mbox.c + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-29 zdzn first version + */ + +/* mailbox message buffer */ +#include "mbox.h" +#include "mmu.h" +//volatile unsigned int __attribute__((aligned(16))) mbox[36]; +volatile unsigned int *mbox = (volatile unsigned int *) MBOX_ADDR; +/** + * Make a mailbox call. Returns 0 on failure, non-zero on success + */ +void init_mbox_mmu_map(){ + rt_hw_change_mmu_table(MBOX_ADDR, 96, MBOX_ADDR, STRONG_ORDER_MEM); +} + +int mbox_call(unsigned char ch, int mmu_enable) +{ + unsigned int r = (((MBOX_ADDR)&~0xF) | (ch&0xF)); + if(mmu_enable) + r = BUS_ADDRESS(r); + /* wait until we can write to the mailbox */ + do + { + asm volatile("nop"); + } while (*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + // rt_kprintf("mailbox request %x\n",r); + while(1) + { + /* is there a response? */ + do + { + asm volatile("nop"); + } while (*MBOX_STATUS & MBOX_EMPTY); + /* is it a response to our message? */ + if (r == *MBOX_READ){ + /* is it a valid successful response? */ + // rt_kprintf("mbox: %x, %x, %x, %x, %x, %x, %x, %x\n", mbox[0], mbox[1], mbox[2], mbox[3], mbox[4], mbox[5], mbox[6], mbox[7]); + return mbox[1] == MBOX_RESPONSE; + } + } + return 0; +} diff --git a/bsp/raspberry-pi/raspi3-64/driver/mbox.h b/bsp/raspberry-pi/raspi3-64/driver/mbox.h new file mode 100644 index 0000000000000000000000000000000000000000..eb7eb0318cdf99bcd99157244b1c56b3b9e7706c --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/mbox.h @@ -0,0 +1,62 @@ +/* + * File : mbox.h + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-08-29 zdzn first version + */ + +#ifndef __MBOX_H__ +#define __MBOX_H__ + + +/* a properly aligned buffer */ +extern volatile unsigned int* mbox; + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_SETPOWER 0x28001 +#define MBOX_TAG_SETCLKRATE 0x38002 +#define MBOX_GET_MAC_ADDRESS 0x10003 +#define MBOX_TAG_LAST 0 + +#define MMIO_BASE 0x3F000000 +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +#define DEVICE_ID_SD_CARD 0 +#define DEVICE_ID_USB_HCD 3 +#define POWER_STATE_OFF (0 << 0) +#define POWER_STATE_ON (1 << 0) +#define POWER_STATE_WAIT (1 << 1) +#define POWER_STATE_NO_DEVICE (1 << 1) // in response +#define MMU_ENABLE 1 +#define MMU_DISABLE 0 + +#define MBOX_ADDR 0xc00000 + +int mbox_call(unsigned char ch, int mmu_enable); +#endif diff --git a/bsp/raspberry-pi/raspi3-64/driver/raspi.h b/bsp/raspberry-pi/raspi3-64/driver/raspi.h new file mode 100644 index 0000000000000000000000000000000000000000..0d55df2a1171d88e3f8d47dbd99b6db3a6bd61f8 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/driver/raspi.h @@ -0,0 +1,70 @@ +/* + * File : rsapi.h + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-07-29 zdzn first version + */ + +#ifndef __RASPI_H__ +#define __RASPI_H__ + +#include "bcm283x.h" + +#define PIN_MAGIC (0x5A) +#define PIN_NUM(_N) (sizeof(_N) / sizeof(_N[0])) + +enum gpio_code +{ + GPIO_CODE_PHY = 0, + GPIO_CODE_BCM, + GPIO_CODE_WIRING, + GPIO_CODE_NUM, +}; + +enum rpi_pin_name +{ + RPI_SDA0 = 0, + RPI_SCL0, + RPI_SDA1, + RPI_SCL1, + RPI_GPIO_GCLK, + RPI_CAM_CLK, + RPI_LAN_RUN, + RPI_SPI_CE1_N, + RPI_SPI_CE0_N, + RPI_SPI_MISO, + RPI_SPI_MOSI, + RPI_SPI_SCLK, + RPI_TXD0, + RPI_RXD0, + RPI_STATUS_LED_N, + RPI_GPIO_GEN0, + RPI_GPIO_GEN1, + RPI_CAM_GPIO, + RPI_GPIO_GEN3, + RPI_GPIO_GEN4, + RPI_GPIO_GEN5, + RPI_GPIO_GEN6, + RPI_GPIO_GEN2, + RPI_GPIO_GEN7, + RPI_GPIO_GEN8, + RPI_GPIO_GEN9, + RPI_GPIO_GEN10, + RPI_PWM0_OUT, + RPI_PWM1_OUT, + RPI_HDMI_HPD_P, + RPI_SD_CARD_DET, + RPI_SD_CLK_R, + RPI_SD_CMD_R, + RPI_SD_DATA0_R, + RPI_SD_DATA1_R, + RPI_SD_DATA2_R, + RPI_SD_DATA3_R, + RPI_GPIO_PIN_NUM, +}; + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/figures/raspi_uart.png b/bsp/raspberry-pi/raspi3-64/figures/raspi_uart.png new file mode 100644 index 0000000000000000000000000000000000000000..c6ae382182e3f218c61338dbf0ed5c3066d9550f Binary files /dev/null and b/bsp/raspberry-pi/raspi3-64/figures/raspi_uart.png differ diff --git a/bsp/raspberry-pi/raspi3-64/kernel8.img b/bsp/raspberry-pi/raspi3-64/kernel8.img new file mode 100755 index 0000000000000000000000000000000000000000..d1e9d50822eab7049392ad0a707bc93d8176db52 Binary files /dev/null and b/bsp/raspberry-pi/raspi3-64/kernel8.img differ diff --git a/bsp/raspberry-pi/raspi3-64/link.lds b/bsp/raspberry-pi/raspi3-64/link.lds new file mode 100644 index 0000000000000000000000000000000000000000..604a45c11031603f938ddb96fa8f977a98ba67ab --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/link.lds @@ -0,0 +1,151 @@ +/* + * File : link.lds + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * 2017-5-30 bernard first version + */ + +/* _EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 0x20000; */ + +SECTIONS +{ + . = 0x80000; + . = ALIGN(4096); + .text : + { + KEEP(*(.text.entrypoint)) /* The entry point */ + *(.vectors) + *(.text) /* remaining code */ + *(.text.*) /* remaining code */ + + *(.rodata) /* read-only data (constants) */ + *(.rodata*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t*) + + /* section information for finsh shell */ + . = ALIGN(16); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(16); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(16); + + /* section information for initial. */ + . = ALIGN(16); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(16); + + . = ALIGN(16); + _etext = .; + } + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + *(.eh_frame_entry) + } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + + . = ALIGN(16); + .data : + { + *(.data) + *(.data.*) + + *(.data1) + *(.data1.*) + + . = ALIGN(16); + _gp = ABSOLUTE(.); /* Base of small data */ + + *(.sdata) + *(.sdata.*) + } + + . = ALIGN(16); + .ctors : + { + PROVIDE(__ctors_start__ = .); + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + PROVIDE(__ctors_end__ = .); + } + + .dtors : + { + PROVIDE(__dtors_start__ = .); + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + PROVIDE(__dtors_end__ = .); + } + + . = ALIGN(16); + .bss : + { + PROVIDE(__bss_start = .); + *(.bss) + *(.bss.*) + *(.dynbss) + *(COMMON) + PROVIDE(__bss_end = .); + } + _end = .; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + * Symbols in the DWARF debugging sections are relative to the beginning + * of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} + +__bss_size = (__bss_end - __bss_start)>>3; diff --git a/bsp/raspberry-pi/raspi3-64/qemu-64.bat b/bsp/raspberry-pi/raspi3-64/qemu-64.bat new file mode 100644 index 0000000000000000000000000000000000000000..c009905e2364fe91ef5446940ec5f7da6c0f9e89 --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/qemu-64.bat @@ -0,0 +1 @@ +qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio \ No newline at end of file diff --git a/bsp/raspberry-pi/raspi3-64/rtconfig.h b/bsp/raspberry-pi/raspi3-64/rtconfig.h new file mode 100644 index 0000000000000000000000000000000000000000..4a8d8c42bce764e5d9a913cedd2265741ad3ea1f --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/rtconfig.h @@ -0,0 +1,382 @@ +#ifndef RT_CONFIG_H__ +#define RT_CONFIG_H__ + +/* Automatically generated file; DO NOT EDIT. */ +/* RT-Thread Project Configuration */ + +/* RT-Thread Kernel */ + +#define RT_NAME_MAX 8 +/* RT_USING_ARCH_DATA_TYPE is not set */ +/* RT_USING_SMP is not set */ +#define RT_ALIGN_SIZE 4 +/* RT_THREAD_PRIORITY_8 is not set */ +#define RT_THREAD_PRIORITY_32 +/* RT_THREAD_PRIORITY_256 is not set */ +#define RT_THREAD_PRIORITY_MAX 32 +#define RT_TICK_PER_SECOND 100 +#define RT_USING_OVERFLOW_CHECK +#define RT_USING_HOOK +#define RT_USING_IDLE_HOOK +#define RT_IDLE_HOOK_LIST_SIZE 4 +#define IDLE_THREAD_STACK_SIZE 2048 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 2048 +#define RT_DEBUG +#define RT_DEBUG_COLOR +/* RT_DEBUG_INIT_CONFIG is not set */ +/* RT_DEBUG_THREAD_CONFIG is not set */ +/* RT_DEBUG_SCHEDULER_CONFIG is not set */ +/* RT_DEBUG_IPC_CONFIG is not set */ +/* RT_DEBUG_TIMER_CONFIG is not set */ +/* RT_DEBUG_IRQ_CONFIG is not set */ +/* RT_DEBUG_MEM_CONFIG is not set */ +/* RT_DEBUG_SLAB_CONFIG is not set */ +/* RT_DEBUG_MEMHEAP_CONFIG is not set */ +/* RT_DEBUG_MODULE_CONFIG is not set */ + +/* Inter-Thread communication */ + +#define RT_USING_SEMAPHORE +#define RT_USING_MUTEX +#define RT_USING_EVENT +#define RT_USING_MAILBOX +#define RT_USING_MESSAGEQUEUE +/* RT_USING_SIGNALS is not set */ + +/* Memory Management */ + +#define RT_USING_MEMPOOL +#define RT_USING_MEMHEAP +/* RT_USING_NOHEAP is not set */ +#define RT_USING_SMALL_MEM +/* RT_USING_SLAB is not set */ +/* RT_USING_MEMHEAP_AS_HEAP is not set */ +#define RT_USING_MEMTRACE +#define RT_USING_HEAP + +/* Kernel Device Object */ + +#define RT_USING_DEVICE +#define RT_USING_DEVICE_OPS +/* RT_USING_INTERRUPT_INFO is not set */ +#define RT_USING_CONSOLE +#define RT_CONSOLEBUF_SIZE 128 +#define RT_CONSOLE_DEVICE_NAME "uart1" +#define RT_VER_NUM 0x40002 +#define ARCH_CPU_64BIT +#define ARCH_ARM +/* RT_USING_CPU_FFS is not set */ +#define ARCH_ARM_CORTEX_AARCH64 +#define ARCH_ARM_CORTEX_A53 +/* ARCH_CPU_STACK_GROWS_UPWARD is not set */ + +/* 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 */ + +/* RT_USING_CPLUSPLUS is not set */ + +/* 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 +/* FINSH_ECHO_DISABLE_DEFAULT is not set */ +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_CMD_SIZE 80 +/* FINSH_USING_AUTH is not set */ +#define FINSH_USING_MSH +#define FINSH_USING_MSH_DEFAULT +#define FINSH_USING_MSH_ONLY +#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 +/* RT_USING_DFS_MNTTABLE is not set */ +/* RT_USING_DFS_ELMFAT is not set */ +#define RT_USING_DFS_DEVFS +/* RT_USING_DFS_ROMFS is not set */ +/* RT_USING_DFS_RAMFS is not set */ +/* RT_USING_DFS_UFFS is not set */ +/* RT_USING_DFS_JFFS2 is not set */ + +/* Device Drivers */ + +#define RT_USING_DEVICE_IPC +#define RT_PIPE_BUFSZ 512 +/* RT_USING_SYSTEM_WORKQUEUE is not set */ +#define RT_USING_SERIAL +/* RT_SERIAL_USING_DMA is not set */ +#define RT_SERIAL_RB_BUFSZ 64 +/* RT_USING_CAN is not set */ +/* RT_USING_HWTIMER is not set */ +/* RT_USING_CPUTIME is not set */ +/* RT_USING_I2C is not set */ +#define RT_USING_PIN +/* RT_USING_ADC is not set */ +/* RT_USING_PWM is not set */ +/* RT_USING_MTD_NOR is not set */ +/* RT_USING_MTD_NAND is not set */ +/* RT_USING_PM is not set */ +/* RT_USING_RTC is not set */ +/* RT_USING_SDIO is not set */ +/* RT_USING_SPI is not set */ +/* RT_USING_WDT is not set */ +/* RT_USING_AUDIO is not set */ +/* RT_USING_SENSOR is not set */ +/* RT_USING_TOUCH is not set */ +/* RT_USING_HWCRYPTO is not set */ +/* RT_USING_WIFI is not set */ + +/* Using USB */ + +/* RT_USING_USB_HOST is not set */ +/* RT_USING_USB_DEVICE is not set */ + +/* POSIX layer and C standard library */ + +#define RT_USING_LIBC +/* RT_USING_PTHREADS is not set */ +#define RT_USING_POSIX +/* RT_USING_POSIX_MMAP is not set */ +/* RT_USING_POSIX_TERMIOS is not set */ +/* RT_USING_POSIX_AIO is not set */ +/* RT_USING_MODULE is not set */ + +/* Network */ + +/* Socket abstraction layer */ + +/* RT_USING_SAL is not set */ + +/* Network interface device */ + +/* RT_USING_NETDEV is not set */ + +/* light weight TCP/IP stack */ + +/* RT_USING_LWIP is not set */ + +/* AT commands */ + +/* RT_USING_AT is not set */ + +/* VBUS(Virtual Software BUS) */ + +/* RT_USING_VBUS is not set */ + +/* Utilities */ + +/* RT_USING_RYM is not set */ +/* RT_USING_ULOG is not set */ +/* RT_USING_UTEST is not set */ + +/* RT-Thread online packages */ + +/* IoT - internet of things */ + +/* PKG_USING_PAHOMQTT is not set */ +/* PKG_USING_WEBCLIENT is not set */ +/* PKG_USING_WEBNET is not set */ +/* PKG_USING_MONGOOSE is not set */ +/* PKG_USING_WEBTERMINAL is not set */ +/* PKG_USING_CJSON is not set */ +/* PKG_USING_JSMN is not set */ +/* PKG_USING_LIBMODBUS is not set */ +/* PKG_USING_FREEMODBUS is not set */ +/* PKG_USING_LJSON is not set */ +/* PKG_USING_EZXML is not set */ +/* PKG_USING_NANOPB is not set */ + +/* Wi-Fi */ + +/* Marvell WiFi */ + +/* PKG_USING_WLANMARVELL is not set */ + +/* Wiced WiFi */ + +/* PKG_USING_WLAN_WICED is not set */ +/* PKG_USING_RW007 is not set */ +/* PKG_USING_COAP is not set */ +/* PKG_USING_NOPOLL is not set */ +/* PKG_USING_NETUTILS is not set */ +/* PKG_USING_PPP_DEVICE is not set */ +/* PKG_USING_AT_DEVICE is not set */ +/* PKG_USING_ATSRV_SOCKET is not set */ +/* PKG_USING_WIZNET is not set */ + +/* IoT Cloud */ + +/* PKG_USING_ONENET is not set */ +/* PKG_USING_GAGENT_CLOUD is not set */ +/* PKG_USING_ALI_IOTKIT is not set */ +/* PKG_USING_AZURE is not set */ +/* PKG_USING_TENCENT_IOTHUB is not set */ +/* PKG_USING_JIOT-C-SDK is not set */ +/* PKG_USING_NIMBLE is not set */ +/* PKG_USING_OTA_DOWNLOADER is not set */ +/* PKG_USING_IPMSG is not set */ +/* PKG_USING_LSSDP is not set */ +/* PKG_USING_AIRKISS_OPEN is not set */ +/* PKG_USING_LIBRWS is not set */ +/* PKG_USING_TCPSERVER is not set */ +/* PKG_USING_PROTOBUF_C is not set */ +/* PKG_USING_ONNX_PARSER is not set */ +/* PKG_USING_ONNX_BACKEND is not set */ +/* PKG_USING_DLT645 is not set */ +/* PKG_USING_QXWZ is not set */ +/* PKG_USING_SMTP_CLIENT is not set */ + +/* security packages */ + +/* PKG_USING_MBEDTLS is not set */ +/* PKG_USING_libsodium is not set */ +/* PKG_USING_TINYCRYPT is not set */ + +/* language packages */ + +/* PKG_USING_LUA is not set */ +/* PKG_USING_JERRYSCRIPT is not set */ +/* PKG_USING_MICROPYTHON is not set */ + +/* multimedia packages */ + +/* PKG_USING_OPENMV is not set */ +/* PKG_USING_MUPDF is not set */ +/* PKG_USING_STEMWIN is not set */ +/* PKG_USING_WAVPLAYER is not set */ +/* PKG_USING_TJPGD is not set */ + +/* tools packages */ + +/* PKG_USING_CMBACKTRACE is not set */ +/* PKG_USING_EASYFLASH is not set */ +/* PKG_USING_EASYLOGGER is not set */ +/* PKG_USING_SYSTEMVIEW is not set */ +/* PKG_USING_RDB is not set */ +/* PKG_USING_QRCODE is not set */ +/* PKG_USING_ULOG_EASYFLASH is not set */ +/* PKG_USING_ADBD is not set */ +/* PKG_USING_COREMARK is not set */ +/* PKG_USING_DHRYSTONE is not set */ + +/* system packages */ + +/* PKG_USING_GUIENGINE is not set */ +/* PKG_USING_CAIRO is not set */ +/* PKG_USING_PIXMAN is not set */ +/* PKG_USING_LWEXT4 is not set */ +/* PKG_USING_PARTITION is not set */ +/* PKG_USING_FAL is not set */ +/* PKG_USING_SQLITE is not set */ +/* PKG_USING_RTI is not set */ +/* PKG_USING_LITTLEVGL2RTT is not set */ +/* PKG_USING_CMSIS is not set */ +/* PKG_USING_DFS_YAFFS is not set */ +/* PKG_USING_LITTLEFS is not set */ +/* PKG_USING_THREAD_POOL is not set */ +/* PKG_USING_ROBOTS is not set */ + +/* peripheral libraries and drivers */ + +/* PKG_USING_SENSORS_DRIVERS is not set */ +/* PKG_USING_REALTEK_AMEBA is not set */ +/* PKG_USING_SHT2X is not set */ +/* PKG_USING_STM32_SDIO is not set */ +/* PKG_USING_ICM20608 is not set */ +/* PKG_USING_U8G2 is not set */ +/* PKG_USING_BUTTON is not set */ +/* PKG_USING_PCF8574 is not set */ +/* PKG_USING_SX12XX is not set */ +/* PKG_USING_SIGNAL_LED is not set */ +/* PKG_USING_LEDBLINK is not set */ +/* PKG_USING_WM_LIBRARIES is not set */ +/* PKG_USING_KENDRYTE_SDK is not set */ +/* PKG_USING_INFRARED is not set */ +/* PKG_USING_ROSSERIAL is not set */ +/* PKG_USING_AGILE_BUTTON is not set */ +/* PKG_USING_AGILE_LED is not set */ +/* PKG_USING_AT24CXX is not set */ +/* PKG_USING_MOTIONDRIVER2RTT is not set */ +/* PKG_USING_AD7746 is not set */ +/* PKG_USING_PCA9685 is not set */ +/* PKG_USING_I2C_TOOLS is not set */ +/* PKG_USING_NRF24L01 is not set */ +/* PKG_USING_TOUCH_DRIVERS is not set */ +/* PKG_USING_LCD_DRIVERS is not set */ +/* PKG_USING_MAX17048 is not set */ +/* PKG_USING_RPLIDAR is not set */ + +/* miscellaneous packages */ + +/* PKG_USING_LIBCSV is not set */ +/* PKG_USING_OPTPARSE is not set */ +/* PKG_USING_FASTLZ is not set */ +/* PKG_USING_MINILZO is not set */ +/* PKG_USING_QUICKLZ is not set */ +/* PKG_USING_MULTIBUTTON is not set */ +/* PKG_USING_FLEXIBLE_BUTTON is not set */ +/* PKG_USING_CANFESTIVAL is not set */ +/* PKG_USING_ZLIB is not set */ +/* PKG_USING_DSTR is not set */ +/* PKG_USING_TINYFRAME is not set */ +/* PKG_USING_KENDRYTE_DEMO is not set */ +/* PKG_USING_DIGITALCTRL is not set */ +/* PKG_USING_UPACKER is not set */ +/* PKG_USING_UPARAM is not set */ + +/* samples: kernel and components samples */ + +/* PKG_USING_KERNEL_SAMPLES is not set */ +/* PKG_USING_FILESYSTEM_SAMPLES is not set */ +/* PKG_USING_NETWORK_SAMPLES is not set */ +/* PKG_USING_PERIPHERAL_SAMPLES is not set */ +/* PKG_USING_HELLO is not set */ +/* PKG_USING_VI is not set */ +/* PKG_USING_NNOM is not set */ +/* PKG_USING_LIBANN is not set */ +/* PKG_USING_ELAPACK is not set */ +/* PKG_USING_ARMv7M_DWT is not set */ +/* PKG_USING_VT100 is not set */ +/* PKG_USING_ULAPACK is not set */ +/* PKG_USING_UKAL is not set */ +#define BCM2836_SOC +/* BSP_SUPPORT_FPU is not set */ + +/* Hardware Drivers Config */ + +/* BCM Peripheral Drivers */ + +#define BSP_USING_UART +/* RT_USING_UART0 is not set */ +#define RT_USING_UART1 +#define BSP_USING_PIN +/* BSP_USING_SYSTIMER is not set */ +/* BSP_USING_I2C is not set */ +/* BSP_USING_SPI is not set */ +/* BSP_USING_WDT is not set */ +/* BSP_USING_RTC is not set */ +/* BSP_USING_SDIO is not set */ + +/* Board Peripheral Drivers */ + +/* BSP_USING_HDMI is not set */ + +#endif diff --git a/bsp/raspberry-pi/raspi3-64/rtconfig.py b/bsp/raspberry-pi/raspi3-64/rtconfig.py new file mode 100644 index 0000000000000000000000000000000000000000..54d5988b6470e6256ca850994c26cc00ea0ca42a --- /dev/null +++ b/bsp/raspberry-pi/raspi3-64/rtconfig.py @@ -0,0 +1,54 @@ +import os + +# toolchains options +ARCH ='aarch64' +CPU ='cortex-a53' +CROSS_TOOL ='gcc' + +if os.getenv('RTT_ROOT'): + RTT_ROOT = os.getenv('RTT_ROOT') +else: + RTT_ROOT = r'../../..' + +if os.getenv('RTT_CC'): + CROSS_TOOL = os.getenv('RTT_CC') + +PLATFORM = 'gcc' +EXEC_PATH = r'/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-elf/bin/' + +if os.getenv('RTT_EXEC_PATH'): + EXEC_PATH = os.getenv('RTT_EXEC_PATH') + +BUILD = 'debug' + +if PLATFORM == 'gcc': + # toolchains + # PREFIX = 'arm-none-eabi-' + PREFIX = 'aarch64-elf-' + CC = PREFIX + 'gcc' + CXX = PREFIX + 'g++' + AS = PREFIX + 'gcc' + AR = PREFIX + 'ar' + LINK = PREFIX + 'gcc' + TARGET_EXT = 'elf' + SIZE = PREFIX + 'size' + OBJDUMP = PREFIX + 'objdump' + OBJCPY = PREFIX + 'objcopy' + + DEVICE = ' -march=armv8-a -mtune=cortex-a53' + CFLAGS = DEVICE + ' -Wall' + AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__' + LFLAGS = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds' + CPATH = '' + LPATH = '' + + if BUILD == 'debug': + CFLAGS += ' -O0 -gdwarf-2' + AFLAGS += ' -gdwarf-2' + else: + CFLAGS += ' -O2' + + CXXFLAGS = CFLAGS + +DUMP_ACTION = OBJDUMP + ' -D -S $TARGET > rtt.asm\n' +POST_ACTION = OBJCPY + ' -O binary $TARGET kernel8.img\n' + SIZE + ' $TARGET \n' diff --git a/libcpu/aarch64/SConscript b/libcpu/aarch64/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..453afe4b3ec77bfe37a1c02abc6be4fcdd5ebe75 --- /dev/null +++ b/libcpu/aarch64/SConscript @@ -0,0 +1,16 @@ +# RT-Thread building script for bridge + +import os +from building import * + +Import('rtconfig') + +cwd = GetCurrentDir() +group = [] +list = os.listdir(cwd) + +# cpu porting code files +if rtconfig.CPU != 'common': + group = group + SConscript(os.path.join(rtconfig.CPU, 'SConscript')) + +Return('group') diff --git a/libcpu/aarch64/cortex-a53/SConscript b/libcpu/aarch64/cortex-a53/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..57a5accc5c95f0967fc55ac86f66032d49fb9d2e --- /dev/null +++ b/libcpu/aarch64/cortex-a53/SConscript @@ -0,0 +1,15 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') +asm_src = Split(''' +context_gcc.S +vector_gcc.S +entry_point.S +cpu_gcc.S +''') +CPPPATH = [cwd] + +group = DefineGroup('cpu', src + asm_src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/aarch64/cortex-a53/armv8.h b/libcpu/aarch64/cortex-a53/armv8.h new file mode 100644 index 0000000000000000000000000000000000000000..28ed50e1ac8cc5ba0288664d7d96d07c16eeaa96 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/armv8.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ + +#ifndef __ARMV7_H__ +#define __ARMV7_H__ + +/* the exception stack without VFP registers */ +struct rt_hw_exp_stack +{ + unsigned long long pc; + unsigned long long spsr; + unsigned long long x30; + unsigned long long xz; + unsigned long long x28; + unsigned long long x29; + unsigned long long x26; + unsigned long long x27; + unsigned long long x24; + unsigned long long x25; + unsigned long long x22; + unsigned long long x23; + unsigned long long x20; + unsigned long long x21; + unsigned long long x18; + unsigned long long x19; + unsigned long long x16; + unsigned long long x17; + unsigned long long x14; + unsigned long long x15; + unsigned long long x12; + unsigned long long x13; + unsigned long long x10; + unsigned long long x11; + unsigned long long x8; + unsigned long long x9; + unsigned long long x6; + unsigned long long x7; + unsigned long long x4; + unsigned long long x5; + unsigned long long x2; + unsigned long long x3; + unsigned long long x0; + unsigned long long x1; +}; + +#define SP_ELx ( ( unsigned long long ) 0x01 ) +#define SP_EL0 ( ( unsigned long long ) 0x00 ) +#define PSTATE_EL1 ( ( unsigned long long ) 0x04 ) +#define PSTATE_EL2 ( ( unsigned long long ) 0x08 ) +#define PSTATE_EL3 ( ( unsigned long long ) 0x0c ) + +rt_ubase_t rt_hw_get_current_el(void); +void rt_hw_set_elx_env(void); +void rt_hw_set_current_vbar(rt_ubase_t addr); + +#endif diff --git a/libcpu/aarch64/cortex-a53/context_gcc.S b/libcpu/aarch64/cortex-a53/context_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..3812eb4b1a380b54cbadde348c9bbf91b20ec308 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/context_gcc.S @@ -0,0 +1,307 @@ +/* + * Date Author Notes + * 2018-10-06 ZhaoXiaowei the first version + */ + +.macro SAVE_CONTEXT + + /* Switch to use the EL0 stack pointer. */ + MSR SPSEL, #0 + + /* Save the entire context. */ + STP X0, X1, [SP, #-0x10]! + STP X2, X3, [SP, #-0x10]! + STP X4, X5, [SP, #-0x10]! + STP X6, X7, [SP, #-0x10]! + STP X8, X9, [SP, #-0x10]! + STP X10, X11, [SP, #-0x10]! + STP X12, X13, [SP, #-0x10]! + STP X14, X15, [SP, #-0x10]! + STP X16, X17, [SP, #-0x10]! + STP X18, X19, [SP, #-0x10]! + STP X20, X21, [SP, #-0x10]! + STP X22, X23, [SP, #-0x10]! + STP X24, X25, [SP, #-0x10]! + STP X26, X27, [SP, #-0x10]! + STP X28, X29, [SP, #-0x10]! + STP X30, XZR, [SP, #-0x10]! + + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . +3: + MRS X3, SPSR_EL3 + /* Save the ELR. */ + MRS X2, ELR_EL3 + B 0f +2: + MRS X3, SPSR_EL2 + /* Save the ELR. */ + MRS X2, ELR_EL2 + B 0f +1: + MRS X3, SPSR_EL1 + MRS X2, ELR_EL1 + B 0f +0: + + STP X2, X3, [SP, #-0x10]! + + MOV X0, SP /* Move SP into X0 for saving. */ + + /* Switch to use the ELx stack pointer. */ + MSR SPSEL, #1 + + .endm + +.macro SAVE_CONTEXT_T + + /* Switch to use the EL0 stack pointer. */ + MSR SPSEL, #0 + + /* Save the entire context. */ + STP X0, X1, [SP, #-0x10]! + STP X2, X3, [SP, #-0x10]! + STP X4, X5, [SP, #-0x10]! + STP X6, X7, [SP, #-0x10]! + STP X8, X9, [SP, #-0x10]! + STP X10, X11, [SP, #-0x10]! + STP X12, X13, [SP, #-0x10]! + STP X14, X15, [SP, #-0x10]! + STP X16, X17, [SP, #-0x10]! + STP X18, X19, [SP, #-0x10]! + STP X20, X21, [SP, #-0x10]! + STP X22, X23, [SP, #-0x10]! + STP X24, X25, [SP, #-0x10]! + STP X26, X27, [SP, #-0x10]! + STP X28, X29, [SP, #-0x10]! + STP X30, XZR, [SP, #-0x10]! + + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . +3: + MRS X3, SPSR_EL3 + MOV X2, X30 + B 0f +2: + MRS X3, SPSR_EL2 + MOV X2, X30 + B 0f +1: + MRS X3, SPSR_EL1 + MOV X2, X30 + B 0f +0: + + STP X2, X3, [SP, #-0x10]! + + MOV X0, SP /* Move SP into X0 for saving. */ + + /* Switch to use the ELx stack pointer. */ + MSR SPSEL, #1 + + .endm + +.macro RESTORE_CONTEXT + + /* Switch to use the EL0 stack pointer. */ + MSR SPSEL, #0 + + /* Set the SP to point to the stack of the task being restored. */ + MOV SP, X0 + + LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */ + + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + B . +3: + MSR SPSR_EL3, X3 + MSR ELR_EL3, X2 + B 0f +2: + MSR SPSR_EL2, X3 + MSR ELR_EL2, X2 + B 0f +1: + MSR SPSR_EL1, X3 + MSR ELR_EL1, X2 + B 0f +0: + + LDP X30, XZR, [SP], #0x10 + LDP X28, X29, [SP], #0x10 + LDP X26, X27, [SP], #0x10 + LDP X24, X25, [SP], #0x10 + LDP X22, X23, [SP], #0x10 + LDP X20, X21, [SP], #0x10 + LDP X18, X19, [SP], #0x10 + LDP X16, X17, [SP], #0x10 + LDP X14, X15, [SP], #0x10 + LDP X12, X13, [SP], #0x10 + LDP X10, X11, [SP], #0x10 + LDP X8, X9, [SP], #0x10 + LDP X6, X7, [SP], #0x10 + LDP X4, X5, [SP], #0x10 + LDP X2, X3, [SP], #0x10 + LDP X0, X1, [SP], #0x10 + + /* Switch to use the ELx stack pointer. _RB_ Might not be required. */ + MSR SPSEL, #1 + + ERET + + .endm + +.text +/* + * rt_base_t rt_hw_interrupt_disable(); + */ +.globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + MRS X0, DAIF + MSR DAIFSet, #3 + DSB SY + RET + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ +.globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + DSB SY + MOV X1, #0xC0 + ANDS X0, X0, X1 + B.NE rt_hw_interrupt_enable_exit + MSR DAIFClr, #3 +rt_hw_interrupt_enable_exit: + RET + +/* + * void rt_hw_context_switch_to(rt_ubase_t to); + * r0 --> to + */ +.globl rt_hw_context_switch_to +rt_hw_context_switch_to: + LDR X0, [X0] + RESTORE_CONTEXT + +.text +/* + * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to); + * r0 --> from + * r1 --> to + */ +.globl rt_hw_context_switch +rt_hw_context_switch: + + MOV X8,X0 + MOV X9,X1 + + SAVE_CONTEXT_T + + STR X0, [X8] // store sp in preempted tasks TCB + LDR X0, [X9] // get new task stack pointer + + RESTORE_CONTEXT + +/* + * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t 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: + ADR X2, rt_thread_switch_interrupt_flag + LDR X3, [X2] + CMP X3, #1 + B.EQ _reswitch + ADR X4, rt_interrupt_from_thread // set rt_interrupt_from_thread + MOV X3, #1 // set rt_thread_switch_interrupt_flag to 1 + STR X0, [X4] + STR X3, [X2] +_reswitch: + ADR X2, rt_interrupt_to_thread // set rt_interrupt_to_thread + STR X1, [X2] + RET + +.text + +// -- Exception handlers ---------------------------------- + + .align 8 +.globl vector_fiq +vector_fiq: + SAVE_CONTEXT + STP X0, X1, [SP, #-0x10]! + BL rt_hw_trap_fiq + LDP X0, X1, [SP], #0x10 + RESTORE_CONTEXT + +.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 8 +.globl vector_irq +vector_irq: + SAVE_CONTEXT + STP X0, X1, [SP, #-0x10]! + + BL rt_interrupt_enter + BL rt_hw_trap_irq + BL rt_interrupt_leave + + LDP X0, X1, [SP], #0x10 + + // if rt_thread_switch_interrupt_flag set, jump to + // rt_hw_context_switch_interrupt_do and don't return + ADR X1, rt_thread_switch_interrupt_flag + LDR X2, [X1] + CMP X2, #1 + B.NE vector_irq_exit + + MOV X2, #0 // clear flag + STR X2, [X1] + + ADR X3, rt_interrupt_from_thread + LDR X4, [X3] + STR x0, [X4] // store sp in preempted tasks's TCB + + ADR x3, rt_interrupt_to_thread + LDR X4, [X3] + LDR x0, [X4] // get new task's stack pointer + +vector_irq_exit: + RESTORE_CONTEXT + +// ------------------------------------------------- + + .align 8 + .globl vector_error +vector_error: + SAVE_CONTEXT + BL rt_hw_trap_error + B . diff --git a/libcpu/aarch64/cortex-a53/cp15.h b/libcpu/aarch64/cortex-a53/cp15.h new file mode 100644 index 0000000000000000000000000000000000000000..26f6ef1a315ab7522c823d821847fd7f134b6c0a --- /dev/null +++ b/libcpu/aarch64/cortex-a53/cp15.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ + +#ifndef __CP15_H__ +#define __CP15_H__ + +#include "bcm283x.h" +#ifndef __STATIC_FORCEINLINE +#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif + +#define __WFI() __asm__ volatile ("wfi":::"memory") + +#define __WFE() __asm__ volatile ("wfe":::"memory") + +#define __SEV() __asm__ volatile ("sev") + +__STATIC_FORCEINLINE void __ISB(void) +{ + __asm__ volatile ("isb 0xF":::"memory"); +} + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __asm__ volatile ("dsb 0xF":::"memory"); +} + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ + +__STATIC_FORCEINLINE void __DMB(void) +{ + __asm__ volatile ("dmb 0xF":::"memory"); +} + +#ifdef RT_USING_SMP +static inline void send_ipi_msg(int cpu, int ipi_vector) +{ + IPI_MAILBOX_SET(cpu) = 1 << ipi_vector; +} + +static inline void setup_bootstrap_addr(int cpu, int addr) +{ + CORE_MAILBOX3_SET(cpu) = addr; +} + +static inline void enable_cpu_ipi_intr(int cpu) +{ + COREMB_INTCTL(cpu) = IPI_MAILBOX_INT_MASK; +} + +static inline void enable_cpu_timer_intr(int cpu) +{ + CORETIMER_INTCTL(cpu) = 0x8; +} + +static inline void enable_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 1; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL +} + +static inline void disable_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 0; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL +} + +static inline void mask_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 2; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL +} + +static inline void unmask_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 1; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl) ); // write CNTV_CTL +} + +static inline rt_uint64_t read_cntvct(void) +{ + rt_uint32_t val,val1; + asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (val),"=r" (val1)); + return (val); +} + +static inline rt_uint64_t read_cntvoff(void) +{ + + rt_uint64_t val; + asm volatile("mrrc p15, 4, %Q0, %R0, c14" : "=r" (val)); + return (val); +} + +static inline rt_uint32_t read_cntv_tval(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c3, 0" : "=r"(val) ); + return val; +} + + +static inline void write_cntv_tval(rt_uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c14, c3, 0" :: "r"(val) ); + return; +} + +static inline rt_uint32_t read_cntfrq(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val) ); + return val; +} + + +static inline rt_uint32_t read_cntctrl(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c1, 0" : "=r"(val) ); + return val; +} + +static inline uint32_t write_cntctrl(uint32_t val) +{ + + asm volatile ("mcr p15, 0, %0, c14, c1, 0" : :"r"(val) ); + return val; +} +#endif + +unsigned long rt_cpu_get_smp_id(void); + +void rt_cpu_mmu_disable(void); +void rt_cpu_mmu_enable(void); +void rt_cpu_tlb_set(volatile unsigned long*); + +void rt_cpu_dcache_clean_flush(void); +void rt_cpu_icache_flush(void); + +void rt_cpu_vector_set_base(rt_ubase_t addr); +void rt_hw_mmu_init(void); +void rt_hw_vector_init(void); + +void set_timer_counter(unsigned int counter); +void set_timer_control(unsigned int control); +#endif diff --git a/libcpu/aarch64/cortex-a53/cpu.c b/libcpu/aarch64/cortex-a53/cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..962a53a0710765087adee863b094fdefd35e445e --- /dev/null +++ b/libcpu/aarch64/cortex-a53/cpu.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + * 2019-07-28 zdzn add smp support + */ + +#include +#include +#include +#include "cp15.h" + +int rt_hw_cpu_id(void) +{ + int cpu_id; + rt_base_t value; + + __asm__ volatile ( + "mrs %0, mpidr_el1" + :"=r"(value) + ); + cpu_id = value & 0xf; + return cpu_id; +}; + +#ifdef RT_USING_SMP +void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock) +{ + lock->slock = 0; +} + +void rt_hw_spin_lock(rt_hw_spinlock_t *lock) +{ + unsigned long tmp; + unsigned long newval; + rt_hw_spinlock_t lockval; + __asm__ __volatile__( + "pld [%0]" + ::"r"(&lock->slock) + ); + + __asm__ __volatile__( + "1: ldrex %0, [%3]\n" + " add %1, %0, %4\n" + " strex %2, %1, [%3]\n" + " teq %2, #0\n" + " bne 1b" + : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) + : "r" (&lock->slock), "I" (1 << 16) + : "cc"); + + while (lockval.tickets.next != lockval.tickets.owner) { + __WFE(); + lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner); + } + + __DMB(); +} + +void rt_hw_spin_unlock(rt_hw_spinlock_t *lock) +{ + __DMB(); + lock->tickets.owner++; + __DSB(); + __SEV(); +} +#endif /*RT_USING_SMP*/ + +/** + * @addtogroup ARM CPU + */ +/*@{*/ + +/** shutdown CPU */ +void rt_hw_cpu_shutdown() +{ + rt_uint32_t level; + rt_kprintf("shutdown...\n"); + + level = rt_hw_interrupt_disable(); + while (level) + { + RT_ASSERT(0); + } +} + +/*@}*/ diff --git a/libcpu/aarch64/cortex-a53/cpu_gcc.S b/libcpu/aarch64/cortex-a53/cpu_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..ab9a5706aea15f22c2541221c646bca97a08495f --- /dev/null +++ b/libcpu/aarch64/cortex-a53/cpu_gcc.S @@ -0,0 +1,78 @@ +/* + * Date Author Notes + * 2018-10-06 ZhaoXiaowei the first version + */ + +.text +.globl rt_hw_get_current_el +rt_hw_get_current_el: + MRS X0, CurrentEL + CMP X0, 0xc + B.EQ 3f + CMP X0, 0x8 + B.EQ 2f + CMP X0, 0x4 + B.EQ 1f + + LDR X0, =0 + B 0f +3: + LDR X0, =3 + B 0f +2: + LDR X0, =2 + B 0f +1: + LDR X0, =1 + B 0f +0: + RET + + +.globl rt_hw_set_current_vbar +rt_hw_set_current_vbar: + MRS X1, CurrentEL + CMP X1, 0xc + B.EQ 3f + CMP X1, 0x8 + B.EQ 2f + CMP X1, 0x4 + B.EQ 1f + B 0f +3: + MSR VBAR_EL3,X0 + B 0f +2: + MSR VBAR_EL2,X0 + B 0f +1: + MSR VBAR_EL1,X0 + B 0f +0: + RET + + +.globl rt_hw_set_elx_env +rt_hw_set_elx_env: + MRS X1, CurrentEL + CMP X1, 0xc + B.EQ 3f + CMP X1, 0x8 + B.EQ 2f + CMP X1, 0x4 + B.EQ 1f + B 0f +3: + MRS X0, SCR_EL3 + ORR X0, X0, #0xF /* SCR_EL3.NS|IRQ|FIQ|EA */ + MSR SCR_EL3, X0 + B 0f +2: + MRS X0, HCR_EL2 + ORR X0, X0, #0x38 + MSR HCR_EL2, X0 + B 0f +1: + B 0f +0: + RET diff --git a/libcpu/aarch64/cortex-a53/entry_point.S b/libcpu/aarch64/cortex-a53/entry_point.S new file mode 100644 index 0000000000000000000000000000000000000000..098cd9a840f2ecbf405e891264139750ff014efa --- /dev/null +++ b/libcpu/aarch64/cortex-a53/entry_point.S @@ -0,0 +1,102 @@ +.section ".text.entrypoint" + +.set EL1_stack, __el1_stack + +.global _start + +// This symbol is set to 0x80000 in ld script. That is the address that raspi3's firmware +// loads 'kernel8.img' file in. +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 // MPIDR_EL1: Multi-Processor Affinity Register + and x1, x1, #3 + cbz x1, .L__cpu_0 // .L prefix is the local label in ELF + + // cpu id > 0, stop + // cpu id == 0 will also goto here after returned from entry() if possible +.L__current_cpu_idle: + wfe + b .L__current_cpu_idle + +.L__cpu_0: // cpu id == 0 + + // set stack before our code + + /* Define stack pointer for current exception level */ + // ldr x2, =EL1_stack + // mov sp, x2 + + ldr x1, =_start + + // set up EL1 + mrs x0, CurrentEL // CurrentEL Register. bit 2, 3. Others reserved + and x0, x0, #12 // clear reserved bits + + // running at EL3? + cmp x0, #12 // 1100b. So, EL3 + bne .L__not_in_el3 // 11? !EL3 -> 5: + + // should never be executed, just for completeness. (EL3) + mov x2, #0x5b1 + msr scr_el3, x2 // SCR_ELn Secure Configuration Register + mov x2, #0x3c9 + msr spsr_el3, x2 // SPSR_ELn. Saved Program Status Register. 1111001001 + adr x2, .L__not_in_el3 + msr elr_el3, x2 + eret // Exception Return: from EL3, continue from .L__not_in_el3 + + // running at EL2 or EL1 +.L__not_in_el3: + cmp x0, #4 // 0x04 0100 EL1 + beq .L__in_el1 // EL1 -> 5: + + // in EL2 + msr sp_el1, x1 // Set sp of EL1 to _start + + // enable CNTP for EL1 + mrs x0, cnthctl_el2 // Counter-timer Hypervisor Control register + orr x0, x0, #3 + msr cnthctl_el2, x0 + msr cntvoff_el2, xzr + + // enable AArch64 in EL1 + mov x0, #(1 << 31) // AArch64 + orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3 + msr hcr_el2, x0 + mrs x0, hcr_el2 + + // change execution level to EL1 + mov x2, #0x3c4 + msr spsr_el2, x2 // 1111000100 + adr x2, .L__in_el1 + msr elr_el2, x2 + eret // exception return. from EL2. continue from .L__in_el1 + +.L__in_el1: + mov sp, x1 // in EL1. Set sp to _start + + // Set CPACR_EL1 (Architecture Feature Access Control Register) to avoid trap from SIMD or float point instruction + mov x1, #0x00300000 // Don't trap any SIMD/FP instructions in both EL0 and EL1 + msr cpacr_el1, x1 + + mrs x1, sctlr_el1 + orr x1, x1, #(1 << 12) + bic x1, x1, #(3 << 3) + bic x1, x1, #(1 << 1) + msr sctlr_el1, x1 + + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size + +.L__clean_bss_loop: + cbz w2, .L__jump_to_entry + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, .L__clean_bss_loop + + // jump to C code, should not return +.L__jump_to_entry: + bl entry + // for failsafe, halt this core too + b .L__current_cpu_idle diff --git a/libcpu/aarch64/cortex-a53/interrupt.c b/libcpu/aarch64/cortex-a53/interrupt.c new file mode 100644 index 0000000000000000000000000000000000000000..8ad60c6de2248e9aaff0ff0df594faf75134b938 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/interrupt.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/5/3 Bernard first version + * 2019-07-28 zdzn add smp support + * 2019-08-09 zhangjun fixup the problem of smp startup and scheduling issues, + * write addr to mailbox3 to startup smp, and we use mailbox0 for ipi + */ + +#include +#include + +#include "cp15.h" +#include "armv8.h" + +#include + +#define MAX_HANDLERS 72 + +#ifdef RT_USING_SMP +#define rt_interrupt_nest rt_cpu_self()->irq_nest +#else +extern volatile rt_uint8_t rt_interrupt_nest; +#endif + +extern int system_vectors; + +/* exception and interrupt handler table */ +struct rt_irq_desc isr_table[MAX_HANDLERS]; + +rt_ubase_t rt_interrupt_from_thread; +rt_ubase_t rt_interrupt_to_thread; +rt_ubase_t rt_thread_switch_interrupt_flag; + +void rt_hw_vector_init(void) +{ + rt_hw_set_current_vbar((rt_ubase_t)&system_vectors); // cpu_gcc.S +} + +static void default_isr_handler(int vector, void *param) +{ +#ifdef RT_USING_SMP + rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector); +#else + rt_kprintf("unhandled irq: %d\n",vector); +#endif +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + rt_uint32_t index; + + /* mask all of interrupts */ + IRQ_DISABLE_BASIC = 0x000000ff; + IRQ_DISABLE1 = 0xffffffff; + IRQ_DISABLE2 = 0xffffffff; + for (index = 0; index < MAX_HANDLERS; index ++) + { + isr_table[index].handler = default_isr_handler; + isr_table[index].param = NULL; +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[index].name, "unknown", RT_NAME_MAX); + isr_table[index].counter = 0; +#endif + } + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrupt_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + if (vector < 32) + { + IRQ_DISABLE1 = (1 << vector); + } + else if (vector<64) + { + vector = vector % 32; + IRQ_DISABLE2 = (1 << vector); + } + else + { + vector = vector - 64; + IRQ_DISABLE_BASIC = (1 << vector); + } +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + if (vector < 32) + { + IRQ_ENABLE1 = (1 << vector); + } + else if (vector < 64) + { + vector = vector % 32; + IRQ_ENABLE2 = (1 << vector); + } + else + { + vector = vector - 64; + IRQ_ENABLE_BASIC = (1 << vector); + } +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if (vector < MAX_HANDLERS) + { + old_handler = isr_table[vector].handler; + + if (handler != RT_NULL) + { +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); +#endif /* RT_USING_INTERRUPT_INFO */ + isr_table[vector].handler = handler; + isr_table[vector].param = param; + } + } + + return old_handler; +} + +#ifdef RT_USING_SMP +void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask) +{ + __DSB(); + if(cpu_mask & 0x1) + { + send_ipi_msg(0, ipi_vector); + } + if(cpu_mask & 0x2) + { + send_ipi_msg(1, ipi_vector); + } + if(cpu_mask & 0x4) + { + send_ipi_msg(2, ipi_vector); + } + if(cpu_mask & 0x8) + { + send_ipi_msg(3, ipi_vector); + } + __DSB(); +} +#endif + +#ifdef RT_USING_SMP +void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler) +{ + /* note: ipi_vector maybe different with irq_vector */ + rt_hw_interrupt_install(ipi_vector, ipi_isr_handler, 0, "IPI_HANDLER"); +} +#endif diff --git a/libcpu/aarch64/cortex-a53/interrupt.h b/libcpu/aarch64/cortex-a53/interrupt.h new file mode 100644 index 0000000000000000000000000000000000000000..6e8651604521f95aef8c21490747d2b2f37b6411 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/interrupt.h @@ -0,0 +1,20 @@ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#include +#include + +#define INT_IRQ 0x00 +#define INT_FIQ 0x01 + +//void rt_hw_vector_init(void); + +void rt_hw_interrupt_init(void); +void rt_hw_interrupt_mask(int vector); +void rt_hw_interrupt_umask(int vector); + +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name); + +#endif diff --git a/libcpu/aarch64/cortex-a53/mmu.c b/libcpu/aarch64/cortex-a53/mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..17b40c3b473f06ee91664614ab1e5cc833685b85 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/mmu.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-01-10 bernard porting to AM1808 + * 2019-07-28 zdzn add smp support + */ + +#include "mmu.h" + +/* dump 2nd level page table */ +void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + for (i = 0; i < 256; i++) + { + rt_uint32_t pte2 = ptb[i]; + if ((pte2 & 0x3) == 0) + { + if (fcnt == 0) + rt_kprintf(" "); + rt_kprintf("%04x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf(" %04x: %x: ", i, pte2); + if ((pte2 & 0x3) == 0x1) + { + rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, + (pte2 >> 15) & 0x1, + ((pte2 >> 10) | (pte2 >> 2)) & 0x1f); + } + else + { + rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1, + ((pte2 >> 4) | (pte2 >> 2)) & 0x1f); + } + } +} + +void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + rt_kprintf("page table@%p\n", ptb); + for (i = 0; i < 1024*4; i++) + { + rt_uint32_t pte1 = ptb[i]; + if ((pte1 & 0x3) == 0) + { + rt_kprintf("%03x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf("%03x: %08x: ", i, pte1); + if ((pte1 & 0x3) == 0x3) + { + rt_kprintf("LPAE\n"); + } + else if ((pte1 & 0x3) == 0x1) + { + rt_kprintf("pte,ns:%d,domain:%d\n", + (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf); + /* + *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000) + * - 0x80000000 + 0xC0000000)); + */ + } + else if (pte1 & (1 << 18)) + { + rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + ((pte1 >> 10) | (pte1 >> 2)) & 0x1f); + } + else + { + rt_kprintf("section,ns:%d,ap:%x," + "xn:%d,texcb:%02x,domain:%d\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + (((pte1 & (0x7 << 12)) >> 10) | + ((pte1 & 0x0c) >> 2)) & 0x1f, + (pte1 >> 5) & 0xf); + } + } +} + +/* level1 page table, each entry for 1MB memory. */ +volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024))); +void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart, + rt_uint32_t vaddrEnd, + rt_uint32_t paddrStart, + rt_uint32_t attr) +{ + volatile rt_uint32_t *pTT; + volatile int i, nSec; + pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20); + nSec = (vaddrEnd >> 20) - (vaddrStart >> 20); + for(i = 0; i <= nSec; i++) + { + *pTT = attr | (((paddrStart >> 20) + i) << 20); + pTT++; + } +} + +unsigned long rt_hw_set_domain_register(unsigned long domain_val) +{ +#if 0 + unsigned long old_domain; + + asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain)); + asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory"); + + return old_domain; +#else + return 0; +#endif +} + +void rt_hw_init_mmu_table() +{ + /* set page table */ + /* 4G 1:1 memory */ + rt_hw_mmu_setmtt(0x00000000, 0x3effffff, 0x00000000, NORMAL_MEM); + /* IO memory region */ + rt_hw_mmu_setmtt(0x3f000000, 0x40010000, 0x3f000000, DEVICE_MEM); +} + +void rt_hw_change_mmu_table(rt_uint32_t vaddrStart, + rt_uint32_t size, + rt_uint32_t paddrStart, rt_uint32_t attr) +{ + rt_hw_mmu_setmtt(vaddrStart, vaddrStart+size-1, paddrStart, attr); +} + +void rt_hw_mmu_init(void) +{ + rt_cpu_dcache_clean_flush(); + rt_cpu_icache_flush(); + rt_hw_cpu_dcache_disable(); + rt_hw_cpu_icache_disable(); + rt_cpu_mmu_disable(); + + /*rt_hw_cpu_dump_page_table(MMUTable);*/ + rt_hw_set_domain_register(0x55555555); + + rt_cpu_tlb_set(MMUTable); + + rt_cpu_mmu_enable(); + + rt_hw_cpu_icache_enable(); + rt_hw_cpu_dcache_enable(); +} diff --git a/libcpu/aarch64/cortex-a53/mmu.h b/libcpu/aarch64/cortex-a53/mmu.h new file mode 100644 index 0000000000000000000000000000000000000000..022d200f96c1420e926101e186a826a1324e09a8 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/mmu.h @@ -0,0 +1,51 @@ +#ifndef MMU_H__ +#define MMU_H__ +#include +#include +#include +#include "cp15.h" + +#define DESC_SEC (0x2) +#define CB (3<<2) //cache_on, write_back +#define CNB (2<<2) //cache_on, write_through +#define NCB (1<<2) //cache_off,WR_BUF on +#define NCNB (0<<2) //cache_off,WR_BUF off +#define AP_RW (3<<10) //supervisor=RW, user=RW +#define AP_RO (2<<10) //supervisor=RW, user=RO +#define XN (1<<4) // eXecute Never +#define SHARED (1<<16) /* shareable */ +#define SHAREDEVICE (1<<2) /* shared device */ +#define STRONGORDER (0<<2) /* strong ordered */ +#define MEMWBWA ((1<<12)|(3<<2)) /* write back, write allocate */ + +#define DOMAIN_FAULT (0x0) +#define DOMAIN_CHK (0x1) +#define DOMAIN_NOTCHK (0x3) +#define DOMAIN0 (0x0<<5) +#define DOMAIN1 (0x1<<5) + +#define DOMAIN0_ATTR (DOMAIN_CHK<<0) +#define DOMAIN1_ATTR (DOMAIN_FAULT<<2) + +/* Read/Write, cache, write back */ +#define RW_CB (AP_RW|DOMAIN0|CB|DESC_SEC) +/* Read/Write, cache, write through */ +#define RW_CNB (AP_RW|DOMAIN0|CNB|DESC_SEC) +/* Read/Write without cache and write buffer */ +#define RW_NCNB (AP_RW|DOMAIN0|NCNB|DESC_SEC) +/* Read/Write without cache and write buffer, no execute */ +#define RW_NCNBXN (AP_RW|DOMAIN0|NCNB|DESC_SEC|XN) +/* Read/Write without cache and write buffer */ +#define RW_FAULT (AP_RW|DOMAIN1|NCNB|DESC_SEC) + +/* device mapping type */ +#define DEVICE_MEM (SHARED|SHAREDEVICE|RW_NCNBXN) +/* normal memory mapping type */ +#define NORMAL_MEM (SHARED|AP_RW|DOMAIN0|MEMWBWA|DESC_SEC) +#define STRONG_ORDER_MEM (SHARED|AP_RO|XN|DESC_SEC) +#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000) + +void rt_hw_change_mmu_table(rt_uint32_t vaddrStart, + rt_uint32_t size, + rt_uint32_t paddrStart, rt_uint32_t attr); +#endif diff --git a/libcpu/aarch64/cortex-a53/stack.c b/libcpu/aarch64/cortex-a53/stack.c new file mode 100644 index 0000000000000000000000000000000000000000..68222c2c67d440913a54c3e243f4898577f41172 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/stack.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-23 Bernard the first version + * 2011-10-05 Bernard add thumb mode + */ +#include +#include + +#include + +#define INITIAL_SPSR_EL3 (PSTATE_EL3 | SP_EL0) +#define INITIAL_SPSR_EL2 (PSTATE_EL2 | SP_EL0) +#define INITIAL_SPSR_EL1 (PSTATE_EL1 | SP_EL0) + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, + rt_uint8_t *stack_addr, void *texit) +{ + rt_ubase_t *stk; + rt_ubase_t current_el; + + stk = (rt_ubase_t*)stack_addr; + + *(--stk) = ( rt_ubase_t ) 11; /* X1 */ + *(--stk) = ( rt_ubase_t ) parameter; /* X0 */ + *(--stk) = ( rt_ubase_t ) 33; /* X3 */ + *(--stk) = ( rt_ubase_t ) 22; /* X2 */ + *(--stk) = ( rt_ubase_t ) 55; /* X5 */ + *(--stk) = ( rt_ubase_t ) 44; /* X4 */ + *(--stk) = ( rt_ubase_t ) 77; /* X7 */ + *(--stk) = ( rt_ubase_t ) 66; /* X6 */ + *(--stk) = ( rt_ubase_t ) 99; /* X9 */ + *(--stk) = ( rt_ubase_t ) 88; /* X8 */ + *(--stk) = ( rt_ubase_t ) 11; /* X11 */ + *(--stk) = ( rt_ubase_t ) 10; /* X10 */ + *(--stk) = ( rt_ubase_t ) 13; /* X13 */ + *(--stk) = ( rt_ubase_t ) 12; /* X12 */ + *(--stk) = ( rt_ubase_t ) 15; /* X15 */ + *(--stk) = ( rt_ubase_t ) 14; /* X14 */ + *(--stk) = ( rt_ubase_t ) 17; /* X17 */ + *(--stk) = ( rt_ubase_t ) 16; /* X16 */ + *(--stk) = ( rt_ubase_t ) 19; /* X19 */ + *(--stk) = ( rt_ubase_t ) 18; /* X18 */ + *(--stk) = ( rt_ubase_t ) 21; /* X21 */ + *(--stk) = ( rt_ubase_t ) 20; /* X20 */ + *(--stk) = ( rt_ubase_t ) 23; /* X23 */ + *(--stk) = ( rt_ubase_t ) 22; /* X22 */ + *(--stk) = ( rt_ubase_t ) 25; /* X25 */ + *(--stk) = ( rt_ubase_t ) 24; /* X24 */ + *(--stk) = ( rt_ubase_t ) 27; /* X27 */ + *(--stk) = ( rt_ubase_t ) 26; /* X26 */ + *(--stk) = ( rt_ubase_t ) 29; /* X29 */ + *(--stk) = ( rt_ubase_t ) 28; /* X28 */ + *(--stk) = ( rt_ubase_t ) 0; /* XZR - has no effect, used so there are an even number of registers. */ + *(--stk) = ( rt_ubase_t ) texit; /* X30 - procedure call link register. */ + + current_el = rt_hw_get_current_el(); + + if(current_el == 3) + { + *(--stk) = INITIAL_SPSR_EL3; + } + else if(current_el == 2) + { + *(--stk) = INITIAL_SPSR_EL2; + } + else + { + *(--stk) = INITIAL_SPSR_EL1; + } + + *(--stk) = ( rt_ubase_t ) tentry; /* Exception return address. */ + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} diff --git a/libcpu/aarch64/cortex-a53/startup_gcc.S b/libcpu/aarch64/cortex-a53/startup_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..ea4268148c8f50e924cc0ff6bbccecb68bec2ab7 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/startup_gcc.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + */ + + .global Reset_Handler + .section ".start", "ax" +Reset_Handler: + nop diff --git a/libcpu/aarch64/cortex-a53/trap.c b/libcpu/aarch64/cortex-a53/trap.c new file mode 100644 index 0000000000000000000000000000000000000000..aa639ea59664b3ce06d29ec35687b96ccd96ebd0 --- /dev/null +++ b/libcpu/aarch64/cortex-a53/trap.c @@ -0,0 +1,221 @@ +/* + * Date Author Notes + * 2018-10-06 ZhaoXiaowei the first version + */ + +#include +#include + +#include "interrupt.h" +#include "armv8.h" + +extern struct rt_thread *rt_current_thread; +#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%16.16llx r01:0x%16.16llx r02:0x%16.16llx r03:0x%16.16llx\n", regs->x0, regs->x1, regs->x2, regs->x3); + rt_kprintf("r04:0x%16.16llx r05:0x%16.16llx r06:0x%16.16llx r07:0x%16.16llx\n", regs->x4, regs->x5, regs->x6, regs->x7); + rt_kprintf("r08:0x%16.16llx r09:0x%16.16llx r10:0x%16.16llx r11:0x%16.16llx\n", regs->x8, regs->x9, regs->x10, regs->x11); + rt_kprintf("r12:0x%16.16llx r13:0x%16.16llx r14:0x%16.16llx r15:0x%16.16llx\n", regs->x12, regs->x13, regs->x14, regs->x15); + rt_kprintf("r16:0x%16.16llx r17:0x%16.16llx r18:0x%16.16llx r19:0x%16.16llx\n", regs->x16, regs->x17, regs->x18, regs->x19); + rt_kprintf("r20:0x%16.16llx r21:0x%16.16llx r22:0x%16.16llx r23:0x%16.16llx\n", regs->x20, regs->x21, regs->x22, regs->x23); + rt_kprintf("r24:0x%16.16llx r25:0x%16.16llx r26:0x%16.16llx r27:0x%16.16llx\n", regs->x24, regs->x25, regs->x26, regs->x27); + rt_kprintf("r28:0x%16.16llx r29:0x%16.16llx r30:0x%16.16llx", regs->x28, regs->x29, regs->x30); + rt_kprintf("spsr:0x%16.16llx", regs->spsr); + rt_kprintf("return pc:0x%16.16llx", regs->pc); +} + +/** + * When comes across an instruction which it cannot handle, + * it takes the undefined instruction trap. + * + * @param regs system registers + * + * @note never invoke this function in application + */ +void rt_hw_trap_error(struct rt_hw_exp_stack *regs) +{ + rt_kprintf("error exception:\n"); + rt_hw_show_register(regs); +#ifdef RT_USING_FINSH + list_thread(); +#endif + rt_hw_cpu_shutdown(); +} + +#define GIC_ACK_INTID_MASK 0x000003ff + +void rt_hw_trap_irq(void) +{ + void *param; + uint32_t irq; + rt_isr_handler_t isr_func; + extern struct rt_irq_desc isr_table[]; + uint32_t value = 0; + value = IRQ_PEND_BASIC & 0x3ff; +#ifdef RT_USING_SMP + uint32_t mailbox_data; + uint32_t cpu_id = rt_hw_cpu_id(); + uint32_t int_source = CORE_IRQSOURCE(cpu_id); + mailbox_data = IPI_MAILBOX_CLEAR(cpu_id); + if (int_source & 0x0f) + { + if (int_source & 0x08){ + isr_func = isr_table[IRQ_ARM_TIMER].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[IRQ_ARM_TIMER].counter++; +#endif + if (isr_func) + { + param = isr_table[IRQ_ARM_TIMER].param; + isr_func(IRQ_ARM_TIMER, param); + } + } + } + if (int_source & 0xf0) + { + /*it's a ipi interrupt*/ + if (mailbox_data & 0x1){ + /* clear mailbox */ + IPI_MAILBOX_CLEAR(cpu_id) = mailbox_data; + isr_func = isr_table[IRQ_ARM_MAILBOX].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[IRQ_ARM_MAILBOX].counter++; +#endif + if (isr_func) + { + param = isr_table[IRQ_ARM_MAILBOX].param; + isr_func(IRQ_ARM_MAILBOX, param); + } + } + else + CORE_MAILBOX3_CLEAR(cpu_id) = mailbox_data; + } +#endif + /* local interrupt*/ + if (value) + { + if (value & (1 << 8)) + { + value = IRQ_PEND1; + irq = __rt_ffs(value) - 1; + } + else if (value & (1 << 9)) + { + value = IRQ_PEND2; + irq = __rt_ffs(value) + 31; + } + else + { + value &= 0x0f; + irq = __rt_ffs(value) + 63; + } + + /* get interrupt service routine */ + isr_func = isr_table[irq].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[irq].counter++; +#endif + if (isr_func) + { + /* Interrupt for myself. */ + param = isr_table[irq].param; + /* turn to interrupt service routine */ + isr_func(irq, param); + } + } +} + +void rt_hw_trap_fiq(void) +{ + void *param; + uint32_t irq; + rt_isr_handler_t isr_func; + extern struct rt_irq_desc isr_table[]; + uint32_t value = 0; + value = IRQ_PEND_BASIC & 0x3ff; +#ifdef RT_USING_SMP + uint32_t mailbox_data; + uint32_t cpu_id = rt_hw_cpu_id(); + uint32_t int_source = CORE_IRQSOURCE(cpu_id); + mailbox_data = IPI_MAILBOX_CLEAR(cpu_id); + if (int_source & 0x0f) + { + if (int_source & 0x08) + { + isr_func = isr_table[IRQ_ARM_TIMER].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[IRQ_ARM_TIMER].counter++; +#endif + if (isr_func) + { + param = isr_table[IRQ_ARM_TIMER].param; + isr_func(IRQ_ARM_TIMER, param); + } + } + } + if (int_source & 0xf0) + { + /*it's a ipi interrupt*/ + if (mailbox_data & 0x1) + { + /* clear mailbox */ + IPI_MAILBOX_CLEAR(cpu_id) = mailbox_data; + isr_func = isr_table[IRQ_ARM_MAILBOX].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[IRQ_ARM_MAILBOX].counter++; +#endif + if (isr_func) + { + param = isr_table[IRQ_ARM_MAILBOX].param; + isr_func(IRQ_ARM_MAILBOX, param); + } + } + else + CORE_MAILBOX3_CLEAR(cpu_id) = mailbox_data; + } +#endif + /* local interrupt*/ + if (value) + { + if (value & (1 << 8)) + { + value = IRQ_PEND1; + irq = __rt_ffs(value) - 1; + } + else if (value & (1 << 9)) + { + value = IRQ_PEND2; + irq = __rt_ffs(value) + 31; + } + else + { + value &= 0x0f; + irq = __rt_ffs(value) + 63; + } + + /* get interrupt service routine */ + isr_func = isr_table[irq].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[irq].counter++; +#endif + if (irq > 1) + rt_kprintf("interrupt fiq %d\n", irq); + if (isr_func) + { + /* Interrupt for myself. */ + param = isr_table[irq].param; + /* turn to interrupt service routine */ + isr_func(irq, param); + } + } +} diff --git a/libcpu/aarch64/cortex-a53/vector_gcc.S b/libcpu/aarch64/cortex-a53/vector_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..0efbf4e5402b0adba904d611ca6b2acd93eb0d7b --- /dev/null +++ b/libcpu/aarch64/cortex-a53/vector_gcc.S @@ -0,0 +1,57 @@ +/* + * Date Author Notes + * 2018-10-06 ZhaoXiaowei the first version + */ + +.text + +.globl system_vectors +.globl vector_error +.globl vector_irq +.globl vector_fiq + +system_vectors: +.align 11 + .set VBAR, system_vectors + .org VBAR + // Exception from CurrentEL (EL1) with SP_EL0 (SPSEL=1) + .org (VBAR + 0x00 + 0) + B vector_error // Synchronous + .org (VBAR + 0x80 + 0) + B vector_irq // IRQ/vIRQ + .org (VBAR + 0x100 + 0) + B vector_fiq // FIQ/vFIQ + .org (VBAR + 0x180 + 0) + B vector_error // Error/vError + + // Exception from CurrentEL (EL1) with SP_ELn + .org (VBAR + 0x200 + 0) + B vector_error // Synchronous + .org (VBAR + 0x280 + 0) + B vector_irq // IRQ/vIRQ + .org (VBAR + 0x300 + 0) + B vector_fiq // FIQ/vFIQ + .org (VBAR + 0x380 + 0) + B vector_error + + // Exception from lower EL, aarch64 + .org (VBAR + 0x400 + 0) + B vector_error + .org (VBAR + 0x480 + 0) + B vector_error + .org (VBAR + 0x500 + 0) + B vector_error + .org (VBAR + 0x580 + 0) + B vector_error + + // Exception from lower EL, aarch32 + .org (VBAR + 0x600 + 0) + B vector_error + .org (VBAR + 0x680 + 0) + B vector_error + .org (VBAR + 0x700 + 0) + B vector_error + .org (VBAR + 0x780 + 0) + B vector_error + .org (VBAR + 0x800 + 0) + B vector_error diff --git a/libcpu/arm/cortex-a53/SConscript b/libcpu/arm/cortex-a53/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..eb4ee7a5850f0d1e2e90484aa547997c266be8eb --- /dev/null +++ b/libcpu/arm/cortex-a53/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S') +CPPPATH = [cwd] + +group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/libcpu/arm/cortex-a53/armv7.h b/libcpu/arm/cortex-a53/armv7.h new file mode 100644 index 0000000000000000000000000000000000000000..859b0371b70c415645b8e9bafd76751284c54231 --- /dev/null +++ b/libcpu/arm/cortex-a53/armv7.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ + +#ifndef __ARMV7_H__ +#define __ARMV7_H__ + +/* the exception stack without VFP registers */ +struct rt_hw_exp_stack +{ + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long fp; + unsigned long ip; + unsigned long sp; + unsigned long lr; + unsigned long pc; + unsigned long cpsr; +}; + +struct rt_hw_stack +{ + unsigned long cpsr; + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long fp; + unsigned long ip; + unsigned long lr; + unsigned long pc; +}; + +#define USERMODE 0x10 +#define FIQMODE 0x11 +#define IRQMODE 0x12 +#define SVCMODE 0x13 +#define MONITORMODE 0x16 +#define ABORTMODE 0x17 +#define HYPMODE 0x1b +#define UNDEFMODE 0x1b +#define MODEMASK 0x1f +#define NOINT 0xc0 + +#define T_Bit (1<<5) +#define F_Bit (1<<6) +#define I_Bit (1<<7) +#define A_Bit (1<<8) +#define E_Bit (1<<9) +#define J_Bit (1<<24) + +#endif diff --git a/libcpu/arm/cortex-a53/context_gcc.S b/libcpu/arm/cortex-a53/context_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..cb95558f7a892756b6f0e725fdf672fc7db957b5 --- /dev/null +++ b/libcpu/arm/cortex-a53/context_gcc.S @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + * 2019-07-28 zdzn add smp support + */ + +#include "../rtconfig.h" +.section .text, "ax" + +#ifdef RT_USING_SMP +#define rt_hw_interrupt_disable rt_hw_local_irq_disable +#define rt_hw_interrupt_enable rt_hw_local_irq_enable +#endif + +/* + * rt_base_t rt_hw_interrupt_disable(); + */ +.globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + mrs r0, cpsr + cpsid i + bx lr + +/* + * void rt_hw_interrupt_enable(rt_base_t level); + */ +.globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + msr cpsr, r0 + bx lr + +/* + * void rt_hw_context_switch_to(rt_uint32 to, struct rt_thread *to_thread); + * r0 --> to (thread stack) + * r1 --> to_thread + */ +.globl rt_hw_context_switch_to +rt_hw_context_switch_to: + ldr sp, [r0] @ get new task stack pointer + +#ifdef RT_USING_SMP + mov r0, r1 + bl rt_cpus_lock_status_restore +#endif /*RT_USING_SMP*/ + b rt_hw_context_switch_exit + +.section .bss.share.isr +_guest_switch_lvl: + .word 0 + +.globl vmm_virq_update + +.section .text.isr, "ax" +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to, struct rt_thread *to_thread); + * r0 --> from (from_thread stack) + * r1 --> to (to_thread stack) + * r2 --> to_thread + */ +.globl rt_hw_context_switch +rt_hw_context_switch: + stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC) + stmfd sp!, {r0-r12, lr} @ push lr & register file + + mrs r4, cpsr + tst lr, #0x01 + orrne r4, r4, #0x20 @ it's thumb code + + stmfd sp!, {r4} @ push cpsr + +#ifdef RT_USING_LWP + stmfd sp, {r13, r14}^ @ push usr_sp usr_lr + sub sp, #8 +#endif +#ifdef RT_USING_FPU + /* fpu context */ + vmrs r6, fpexc + tst r6, #(1<<30) + beq 1f + vstmdb sp!, {d0-d15} + vstmdb sp!, {d16-d31} + vmrs r5, fpscr + stmfd sp!, {r5} +1: + stmfd sp!, {r6} +#endif + + str sp, [r0] @ store sp in preempted tasks TCB + ldr sp, [r1] @ get new task stack pointer + +#ifdef RT_USING_SMP + mov r0, r2 + bl rt_cpus_lock_status_restore +#endif /*RT_USING_SMP*/ + b rt_hw_context_switch_exit + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to); + */ +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled +.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled + +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread +.globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: +#ifdef RT_USING_SMP + /* r0 :svc_mod context + * r1 :addr of from_thread's sp + * r2 :addr of to_thread's sp + * r3 :to_thread's tcb + */ + + str r0, [r1] + + ldr sp, [r2] + mov r0, r3 + bl rt_cpus_lock_status_restore + + b rt_hw_context_switch_exit + +#else /*RT_USING_SMP*/ + ldr r2, =rt_thread_switch_interrupt_flag + ldr r3, [r2] + cmp r3, #1 + beq _reswitch + ldr ip, =rt_interrupt_from_thread @ set rt_interrupt_from_thread + mov r3, #1 @ set rt_thread_switch_interrupt_flag to 1 + str r0, [ip] + str r3, [r2] +_reswitch: + ldr r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread + str r1, [r2] + bx lr +#endif /*RT_USING_SMP*/ + +.global rt_hw_context_switch_exit +rt_hw_context_switch_exit: + +#ifdef RT_USING_SMP +#ifdef RT_USING_SIGNALS + mov r0, sp + cps #Mode_IRQ + bl rt_signal_check + cps #Mode_SVC + mov sp, r0 +#endif +#endif +#ifdef RT_USING_FPU +/* fpu context */ + ldmfd sp!, {r6} + vmsr fpexc, r6 + tst r6, #(1<<30) + beq 1f + ldmfd sp!, {r5} + vmsr fpscr, r5 + vldmia sp!, {d16-d31} + vldmia sp!, {d0-d15} + +#endif + +#ifdef RT_USING_LWP + ldmfd sp, {r13, r14}^ /* usr_sp, usr_lr */ + add sp, #8 +#endif + ldmfd sp!, {r4} + msr spsr_cxsf, r4 /* original mode */ + ldmfd sp!, {r0-r12,lr,pc}^ /* irq return */ + diff --git a/libcpu/arm/cortex-a53/cp15.h b/libcpu/arm/cortex-a53/cp15.h new file mode 100644 index 0000000000000000000000000000000000000000..14b85b7e6466c5781322483c367f9d0ac13798db --- /dev/null +++ b/libcpu/arm/cortex-a53/cp15.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + */ +#include "raspi.h" +#ifndef __CP15_H__ +#define __CP15_H__ + +#ifndef __STATIC_FORCEINLINE +#define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline +#endif + +#define __WFI() __asm__ volatile ("wfi":::"memory") + +#define __WFE() __asm__ volatile ("wfe":::"memory") + +#define __SEV() __asm__ volatile ("sev") + +__STATIC_FORCEINLINE void __ISB(void) +{ + __asm__ volatile ("isb 0xF":::"memory"); +} + + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +__STATIC_FORCEINLINE void __DSB(void) +{ + __asm__ volatile ("dsb 0xF":::"memory"); +} + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ + +__STATIC_FORCEINLINE void __DMB(void) +{ + __asm__ volatile ("dmb 0xF":::"memory"); +} + + +#ifdef RT_USING_SMP +static inline void send_ipi_msg(int cpu, int ipi_vector) +{ + IPI_MAILBOX_SET(cpu) = 1 << ipi_vector; +} + +static inline void setup_bootstrap_addr(int cpu, int addr) +{ + CORE_MAILBOX3_SET(cpu) = addr; +} + +static inline void enable_cpu_ipi_intr(int cpu) +{ + COREMB_INTCTL(cpu) = IPI_MAILBOX_INT_MASK; +} + +static inline void enable_cpu_timer_intr(int cpu) +{ + CORETIMER_INTCTL(cpu) = 0x8; +} + +static inline void enable_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 1; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl)); // write CNTV_CTL +} + +static inline void disable_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 0; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl)); // write CNTV_CTL +} + +static inline void mask_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 2; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl)); // write CNTV_CTL +} + +static inline void unmask_cntv(void) +{ + rt_uint32_t cntv_ctl; + cntv_ctl = 1; + asm volatile ("mcr p15, 0, %0, c14, c3, 1" :: "r"(cntv_ctl)); // write CNTV_CTL +} + +static inline rt_uint64_t read_cntvct(void) +{ + rt_uint32_t val,val1; + asm volatile ("mrrc p15, 1, %0, %1, c14" : "=r" (val),"=r" (val1)); + return (val); +} + +static inline rt_uint64_t read_cntvoff(void) +{ + + rt_uint64_t val; + asm volatile ("mrrc p15, 4, %Q0, %R0, c14" : "=r" (val)); + return (val); +} + +static inline rt_uint32_t read_cntv_tval(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c3, 0" : "=r"(val)); + return val; +} + + +static inline void write_cntv_tval(rt_uint32_t val) +{ + asm volatile ("mcr p15, 0, %0, c14, c3, 0" :: "r"(val)); + return; +} + +static inline rt_uint32_t read_cntfrq(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val)); + return val; +} + + +static inline rt_uint32_t read_cntctrl(void) +{ + rt_uint32_t val; + asm volatile ("mrc p15, 0, %0, c14, c1, 0" : "=r"(val)); + return val; +} + +static inline uint32_t write_cntctrl(uint32_t val) +{ + + asm volatile ("mcr p15, 0, %0, c14, c1, 0" : :"r"(val)); + return val; +} +#endif + +unsigned long rt_cpu_get_smp_id(void); + +void rt_cpu_mmu_disable(void); +void rt_cpu_mmu_enable(void); +void rt_cpu_tlb_set(volatile unsigned long*); + +void rt_cpu_dcache_clean_flush(void); +void rt_cpu_icache_flush(void); + +void rt_cpu_vector_set_base(unsigned int addr); +void rt_hw_mmu_init(void); +void rt_hw_vector_init(void); + +void set_timer_counter(unsigned int counter); +void set_timer_control(unsigned int control); +#endif diff --git a/libcpu/arm/cortex-a53/cp15_gcc.S b/libcpu/arm/cortex-a53/cp15_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..db2e6143ae7258ab7357d3909be42f47de2dd9c9 --- /dev/null +++ b/libcpu/arm/cortex-a53/cp15_gcc.S @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + */ + +.globl rt_cpu_get_smp_id +rt_cpu_get_smp_id: + mrc p15, #0, r0, c0, c0, #5 + bx lr + +.globl rt_cpu_vector_set_base +rt_cpu_vector_set_base: + /* clear SCTRL.V to customize the vector address */ + mrc p15, #0, r1, c1, c0, #0 + bic r1, #(1 << 13) + mcr p15, #0, r1, c1, c0, #0 + /* set up the vector address */ + mcr p15, #0, r0, c12, c0, #0 + dsb + bx lr + +.globl rt_hw_cpu_dcache_enable +rt_hw_cpu_dcache_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x00000004 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +.globl rt_hw_cpu_icache_enable +rt_hw_cpu_icache_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x00001000 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +_FLD_MAX_WAY: + .word 0x3ff +_FLD_MAX_IDX: + .word 0x7ff + +.globl set_timer_counter +set_timer_counter: + mcr p15, #0, r0, c14, c3, #0 @ write virtual timer timerval register + bx lr +.globl set_timer_control +set_timer_control: + mcr p15, #0, r0, c14, c3, #1 @ write virtual timer control register + bx lr + +.globl rt_cpu_dcache_clean_flush +rt_cpu_dcache_clean_flush: + push {r4-r11} + dmb + mrc p15, #1, r0, c0, c0, #1 @ read clid register + ands r3, r0, #0x7000000 @ get level of coherency + mov r3, r3, lsr #23 + beq finished + mov r10, #0 +loop1: + add r2, r10, r10, lsr #1 + mov r1, r0, lsr r2 + and r1, r1, #7 + cmp r1, #2 + blt skip + mcr p15, #2, r10, c0, c0, #0 + isb + mrc p15, #1, r1, c0, c0, #0 + and r2, r1, #7 + add r2, r2, #4 + ldr r4, _FLD_MAX_WAY + ands r4, r4, r1, lsr #3 + clz r5, r4 + ldr r7, _FLD_MAX_IDX + ands r7, r7, r1, lsr #13 +loop2: + mov r9, r4 +loop3: + orr r11, r10, r9, lsl r5 + orr r11, r11, r7, lsl r2 + mcr p15, #0, r11, c7, c14, #2 + subs r9, r9, #1 + bge loop3 + subs r7, r7, #1 + bge loop2 +skip: + add r10, r10, #2 + cmp r3, r10 + bgt loop1 + +finished: + dsb + isb + pop {r4-r11} + bx lr + +.globl rt_cpu_icache_flush +rt_cpu_icache_flush: + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate + dsb + isb + bx lr + +.globl rt_hw_cpu_dcache_disable +rt_hw_cpu_dcache_disable: + push {r4-r11, lr} + bl rt_cpu_dcache_clean_flush + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #0x00000004 + mcr p15, #0, r0, c1, c0, #0 + pop {r4-r11, lr} + bx lr + +.globl rt_hw_cpu_icache_disable +rt_hw_cpu_icache_disable: + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #0x00001000 + mcr p15, #0, r0, c1, c0, #0 + bx lr + +.globl rt_cpu_mmu_disable +rt_cpu_mmu_disable: + mcr p15, #0, r0, c8, c7, #0 @ invalidate tlb + mrc p15, #0, r0, c1, c0, #0 + bic r0, r0, #1 + mcr p15, #0, r0, c1, c0, #0 @ clear mmu bit + dsb + bx lr + +.globl rt_cpu_mmu_enable +rt_cpu_mmu_enable: + mrc p15, #0, r0, c1, c0, #0 + orr r0, r0, #0x001 + mcr p15, #0, r0, c1, c0, #0 @ set mmu enable bit + dsb + bx lr + +.globl rt_cpu_tlb_set +rt_cpu_tlb_set: + mcr p15, #0, r0, c2, c0, #0 + dmb + bx lr diff --git a/libcpu/arm/cortex-a53/cpu.c b/libcpu/arm/cortex-a53/cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..4d02ca35e184139c60a67578ed20f04e4a9e8dff --- /dev/null +++ b/libcpu/arm/cortex-a53/cpu.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-15 Bernard first version + * 2019-07-28 zdzn add smp support + */ + +#include +#include +#include +#include "cp15.h" + +int rt_hw_cpu_id(void) +{ + int cpu_id; + __asm__ volatile ( + "mrc p15, 0, %0, c0, c0, 5" + :"=r"(cpu_id) + ); + cpu_id &= 0xf; + return cpu_id; +}; + + +#ifdef RT_USING_SMP +void rt_hw_spin_lock_init(rt_hw_spinlock_t *lock) +{ + lock->slock = 0; +} + +void rt_hw_spin_lock(rt_hw_spinlock_t *lock) +{ + unsigned long tmp; + unsigned long newval; + rt_hw_spinlock_t lockval; + __asm__ __volatile__( + "pld [%0]" + ::"r"(&lock->slock) + ); + + __asm__ __volatile__( + "1: ldrex %0, [%3]\n" + " add %1, %0, %4\n" + " strex %2, %1, [%3]\n" + " teq %2, #0\n" + " bne 1b" + : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) + : "r" (&lock->slock), "I" (1 << 16) + : "cc"); + + while (lockval.tickets.next != lockval.tickets.owner) + { + __WFE(); + lockval.tickets.owner = *(volatile unsigned short *)(&lock->tickets.owner); + } + + __DMB(); +} + +void rt_hw_spin_unlock(rt_hw_spinlock_t *lock) +{ + __DMB(); + lock->tickets.owner++; + __DSB(); + __SEV(); +} +#endif /*RT_USING_SMP*/ + +/** + * @addtogroup ARM CPU + */ +/*@{*/ + +/** shutdown CPU */ +void rt_hw_cpu_shutdown() +{ + rt_uint32_t level; + rt_kprintf("shutdown...\n"); + + level = rt_hw_interrupt_disable(); + while (level) + { + RT_ASSERT(0); + } +} + +/*@}*/ diff --git a/libcpu/arm/cortex-a53/interrupt.c b/libcpu/arm/cortex-a53/interrupt.c new file mode 100644 index 0000000000000000000000000000000000000000..c9e7c17f8f495f1801116023b0361eff28bbe5fd --- /dev/null +++ b/libcpu/arm/cortex-a53/interrupt.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018/5/3 Bernard first version + * 2019-07-28 zdzn add smp support + * 2019-08-09 zhangjun fixup the problem of smp startup and scheduling issues, + * write addr to mailbox3 to startup smp, and we use mailbox0 for ipi + */ + +#include +#include + +#include "cp15.h" +#include + +#define MAX_HANDLERS 72 + +#ifdef RT_USING_SMP +#define rt_interrupt_nest rt_cpu_self()->irq_nest +#else +extern volatile rt_uint8_t rt_interrupt_nest; +#endif + +const unsigned int VECTOR_BASE = 0x00; +extern void rt_cpu_vector_set_base(unsigned int addr); +extern int system_vectors; + +void rt_hw_vector_init(void) +{ + rt_cpu_vector_set_base((unsigned int)&system_vectors); +} + +/* exception and interrupt handler table */ +struct rt_irq_desc isr_table[MAX_HANDLERS]; + +rt_uint32_t rt_interrupt_from_thread; +rt_uint32_t rt_interrupt_to_thread; +rt_uint32_t rt_thread_switch_interrupt_flag; + +extern int system_vectors; + +static void default_isr_handler(int vector, void *param) +{ +#ifdef RT_USING_SMP + rt_kprintf("cpu %d unhandled irq: %d\n", rt_hw_cpu_id(),vector); +#else + rt_kprintf("unhandled irq: %d\n",vector); +#endif +} + +/** + * This function will initialize hardware interrupt + */ +void rt_hw_interrupt_init(void) +{ + rt_uint32_t index; + + /* mask all of interrupts */ + IRQ_DISABLE_BASIC = 0x000000ff; + IRQ_DISABLE1 = 0xffffffff; + IRQ_DISABLE2 = 0xffffffff; + for (index = 0; index < MAX_HANDLERS; index ++) + { + isr_table[index].handler = default_isr_handler; + isr_table[index].param = NULL; +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[index].name, "unknown", RT_NAME_MAX); + isr_table[index].counter = 0; +#endif + } + + /* init interrupt nest, and context in thread sp */ + rt_interrupt_nest = 0; + rt_interrupt_from_thread = 0; + rt_interrupt_to_thread = 0; + rt_thread_switch_interrupt_flag = 0; +} + +/** + * This function will mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_mask(int vector) +{ + + if (vector < 32) + { + IRQ_DISABLE1 = (1 << vector); + } + else if (vector < 64) + { + vector = vector % 32; + IRQ_DISABLE2 = (1 << vector); + } + else + { + vector = vector - 64; + IRQ_DISABLE_BASIC = (1 << vector); + } +} + +/** + * This function will un-mask a interrupt. + * @param vector the interrupt number + */ +void rt_hw_interrupt_umask(int vector) +{ + if (vector < 32) + { + IRQ_ENABLE1 = (1 << vector); + } + else if (vector < 64) + { + vector = vector % 32; + IRQ_ENABLE2 = (1 << vector); + } + else + { + vector = vector - 64; + IRQ_ENABLE_BASIC = (1 << vector); + } +} + +/** + * This function will install a interrupt service routine to a interrupt. + * @param vector the interrupt number + * @param new_handler the interrupt service routine to be installed + * @param old_handler the old interrupt service routine + */ +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name) +{ + rt_isr_handler_t old_handler = RT_NULL; + + if (vector < MAX_HANDLERS) + { + old_handler = isr_table[vector].handler; + + if (handler != RT_NULL) + { +#ifdef RT_USING_INTERRUPT_INFO + rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX); +#endif /* RT_USING_INTERRUPT_INFO */ + isr_table[vector].handler = handler; + isr_table[vector].param = param; + } + } + + return old_handler; +} + +#ifdef RT_USING_SMP +void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask) +{ + __DSB(); + if (cpu_mask & 0x1) + { + send_ipi_msg(0, ipi_vector); + } + if (cpu_mask & 0x2) + { + send_ipi_msg(1, ipi_vector); + } + if (cpu_mask & 0x4) + { + send_ipi_msg(2, ipi_vector); + } + if (cpu_mask & 0x8) + { + send_ipi_msg(3, ipi_vector); + } + __DSB(); +} +#endif + +#ifdef RT_USING_SMP +void rt_hw_ipi_handler_install(int ipi_vector, rt_isr_handler_t ipi_isr_handler) +{ + /* note: ipi_vector maybe different with irq_vector */ + rt_hw_interrupt_install(ipi_vector, ipi_isr_handler, 0, "IPI_HANDLER"); +} +#endif diff --git a/libcpu/arm/cortex-a53/interrupt.h b/libcpu/arm/cortex-a53/interrupt.h new file mode 100644 index 0000000000000000000000000000000000000000..9aae0f556a0338f5b8afe5d2e2e1275da1012ac3 --- /dev/null +++ b/libcpu/arm/cortex-a53/interrupt.h @@ -0,0 +1,18 @@ + +#ifndef __INTERRUPT_H__ +#define __INTERRUPT_H__ + +#include +#include + +#define INT_IRQ 0x00 +#define INT_FIQ 0x01 + +void rt_hw_interrupt_init(void); +void rt_hw_interrupt_mask(int vector); +void rt_hw_interrupt_umask(int vector); + +rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, + void *param, const char *name); + +#endif diff --git a/libcpu/arm/cortex-a53/mmu.c b/libcpu/arm/cortex-a53/mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..b3541d2ad431ebdd09399989f14f2ca48e06c450 --- /dev/null +++ b/libcpu/arm/cortex-a53/mmu.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-01-10 bernard porting to AM1808 + * 2019-07-28 zdzn add smp support + */ + +#include "mmu.h" + +/* dump 2nd level page table */ +void rt_hw_cpu_dump_page_table_2nd(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + for (i = 0; i < 256; i++) + { + rt_uint32_t pte2 = ptb[i]; + if ((pte2 & 0x3) == 0) + { + if (fcnt == 0) + rt_kprintf(" "); + rt_kprintf("%04x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf(" %04x: %x: ", i, pte2); + if ((pte2 & 0x3) == 0x1) + { + rt_kprintf("L,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, + (pte2 >> 15) & 0x1, + ((pte2 >> 10) | (pte2 >> 2)) & 0x1f); + } + else + { + rt_kprintf("S,ap:%x,xn:%d,texcb:%02x\n", + ((pte2 >> 7) | (pte2 >> 4))& 0xf, pte2 & 0x1, + ((pte2 >> 4) | (pte2 >> 2)) & 0x1f); + } + } +} + +void rt_hw_cpu_dump_page_table(rt_uint32_t *ptb) +{ + int i; + int fcnt = 0; + + rt_kprintf("page table@%p\n", ptb); + for (i = 0; i < 1024*4; i++) + { + rt_uint32_t pte1 = ptb[i]; + if ((pte1 & 0x3) == 0) + { + rt_kprintf("%03x: ", i); + fcnt++; + if (fcnt == 16) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + continue; + } + if (fcnt != 0) + { + rt_kprintf("fault\n"); + fcnt = 0; + } + + rt_kprintf("%03x: %08x: ", i, pte1); + if ((pte1 & 0x3) == 0x3) + { + rt_kprintf("LPAE\n"); + } + else if ((pte1 & 0x3) == 0x1) + { + rt_kprintf("pte,ns:%d,domain:%d\n", + (pte1 >> 3) & 0x1, (pte1 >> 5) & 0xf); + /* + *rt_hw_cpu_dump_page_table_2nd((void*)((pte1 & 0xfffffc000) + * - 0x80000000 + 0xC0000000)); + */ + } + else if (pte1 & (1 << 18)) + { + rt_kprintf("super section,ns:%d,ap:%x,xn:%d,texcb:%02x\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + ((pte1 >> 10) | (pte1 >> 2)) & 0x1f); + } + else + { + rt_kprintf("section,ns:%d,ap:%x," + "xn:%d,texcb:%02x,domain:%d\n", + (pte1 >> 19) & 0x1, + ((pte1 >> 13) | (pte1 >> 10))& 0xf, + (pte1 >> 4) & 0x1, + (((pte1 & (0x7 << 12)) >> 10) | + ((pte1 & 0x0c) >> 2)) & 0x1f, + (pte1 >> 5) & 0xf); + } + } +} + +/* level1 page table, each entry for 1MB memory. */ +volatile static unsigned long MMUTable[4*1024] __attribute__((aligned(16*1024))); +void rt_hw_mmu_setmtt(rt_uint32_t vaddrStart, + rt_uint32_t vaddrEnd, + rt_uint32_t paddrStart, + rt_uint32_t attr) +{ + volatile rt_uint32_t *pTT; + volatile int i, nSec; + pTT = (rt_uint32_t *)MMUTable + (vaddrStart >> 20); + nSec = (vaddrEnd >> 20) - (vaddrStart >> 20); + for (i = 0; i <= nSec; i++) + { + *pTT = attr | (((paddrStart >> 20) + i) << 20); + pTT++; + } +} + +unsigned long rt_hw_set_domain_register(unsigned long domain_val) +{ + unsigned long old_domain; + + asm volatile ("mrc p15, 0, %0, c3, c0\n" : "=r" (old_domain)); + asm volatile ("mcr p15, 0, %0, c3, c0\n" : :"r" (domain_val) : "memory"); + + return old_domain; +} + +void rt_hw_init_mmu_table() +{ + /* set page table */ + /* 4G 1:1 memory */ + rt_hw_mmu_setmtt(0x00000000, 0x3effffff, 0x00000000, NORMAL_MEM); + /* IO memory region */ + rt_hw_mmu_setmtt(0x3f000000, 0x40010000, 0x3f000000, DEVICE_MEM); +} + +void rt_hw_change_mmu_table(rt_uint32_t vaddrStart, + rt_uint32_t size, + rt_uint32_t paddrStart, rt_uint32_t attr) +{ + rt_hw_mmu_setmtt(vaddrStart, vaddrStart+size-1, paddrStart, attr); +#ifndef RT_USING_SMP + rt_cpu_dcache_clean_flush(); + rt_cpu_icache_flush(); +#endif +} + + +void rt_hw_mmu_init(void) +{ + rt_cpu_dcache_clean_flush(); + rt_cpu_icache_flush(); + rt_hw_cpu_dcache_disable(); + rt_hw_cpu_icache_disable(); + rt_cpu_mmu_disable(); + + /*rt_hw_cpu_dump_page_table(MMUTable);*/ + rt_hw_set_domain_register(0x55555555); + + rt_cpu_tlb_set(MMUTable); + + rt_cpu_mmu_enable(); + + rt_hw_cpu_icache_enable(); + rt_hw_cpu_dcache_enable(); +} + diff --git a/libcpu/arm/cortex-a53/mmu.h b/libcpu/arm/cortex-a53/mmu.h new file mode 100644 index 0000000000000000000000000000000000000000..6b0c25e9907bda284f7f605a0f3586d2312b094a --- /dev/null +++ b/libcpu/arm/cortex-a53/mmu.h @@ -0,0 +1,51 @@ +#ifndef MMU_H__ +#define MMU_H__ +#include +#include +#include +#include "cp15.h" + +#define DESC_SEC (0x2) +#define CB (3 << 2) //cache_on, write_back +#define CNB (2 << 2) //cache_on, write_through +#define NCB (1 << 2) //cache_off,WR_BUF on +#define NCNB (0 << 2) //cache_off,WR_BUF off +#define AP_RW (3 << 10) //supervisor=RW, user=RW +#define AP_RO (2 << 10) //supervisor=RW, user=RO +#define XN (1 << 4) // eXecute Never +#define SHARED (1 << 16) /* shareable */ +#define SHAREDEVICE (1 << 2) /* shared device */ +#define STRONGORDER (0 << 2) /* strong ordered */ +#define MEMWBWA ((1 << 12) | (3 << 2)) /* write back, write allocate */ + +#define DOMAIN_FAULT (0x0) +#define DOMAIN_CHK (0x1) +#define DOMAIN_NOTCHK (0x3) +#define DOMAIN0 (0x0 << 5) +#define DOMAIN1 (0x1 << 5) + +#define DOMAIN0_ATTR (DOMAIN_CHK << 0) +#define DOMAIN1_ATTR (DOMAIN_FAULT << 2) + +/* Read/Write, cache, write back */ +#define RW_CB (AP_RW | DOMAIN0 | CB | DESC_SEC) +/* Read/Write, cache, write through */ +#define RW_CNB (AP_RW | DOMAIN0 | CNB | DESC_SEC) +/* Read/Write without cache and write buffer */ +#define RW_NCNB (AP_RW | DOMAIN0 | NCNB | DESC_SEC) +/* Read/Write without cache and write buffer, no execute */ +#define RW_NCNBXN (AP_RW | DOMAIN0 | NCNB | DESC_SEC | XN) +/* Read/Write without cache and write buffer */ +#define RW_FAULT (AP_RW | DOMAIN1 | NCNB | DESC_SEC) + +/* device mapping type */ +#define DEVICE_MEM (SHARED | SHAREDEVICE | RW_NCNBXN) +/* normal memory mapping type */ +#define NORMAL_MEM (SHARED | AP_RW | DOMAIN0 | MEMWBWA | DESC_SEC) +#define STRONG_ORDER_MEM (SHARED | AP_RO | XN | DESC_SEC) +#define BUS_ADDRESS(phys) (((phys) & ~0xC0000000) | 0xC0000000) + +void rt_hw_change_mmu_table(rt_uint32_t vaddrStart, + rt_uint32_t size, + rt_uint32_t paddrStart, rt_uint32_t attr); +#endif diff --git a/libcpu/arm/cortex-a53/stack.c b/libcpu/arm/cortex-a53/stack.c new file mode 100644 index 0000000000000000000000000000000000000000..c2c60fbf49de71ee23ca7e58d3ff18b907176e83 --- /dev/null +++ b/libcpu/arm/cortex-a53/stack.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2011-09-23 Bernard the first version + * 2011-10-05 Bernard add thumb mode + */ +#include +#include +#include + +/** + * @addtogroup AM33xx + */ +/*@{*/ + +/** + * This function will initialize thread stack + * + * @param tentry the entry of thread + * @param parameter the parameter of entry + * @param stack_addr the beginning stack address + * @param texit the function will be called when thread exit + * + * @return stack address + */ +rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, + rt_uint8_t *stack_addr, void *texit) +{ + rt_uint32_t *stk; + + stack_addr += sizeof(rt_uint32_t); + stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8); + stk = (rt_uint32_t *)stack_addr; + *(--stk) = (rt_uint32_t)tentry; /* entry point */ + *(--stk) = (rt_uint32_t)texit; /* lr */ + *(--stk) = 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 */ + +#ifdef RT_USING_LWP + *(--stk) = 0; /* user lr */ + *(--stk) = 0; /* user sp*/ +#endif +#ifdef RT_USING_FPU + *(--stk) = 0; /* not use fpu*/ +#endif + + /* return task's current stack address */ + return (rt_uint8_t *)stk; +} + +/*@}*/ diff --git a/libcpu/arm/cortex-a53/start_gcc.S b/libcpu/arm/cortex-a53/start_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..ec74213f0738dcdab62aaad3d6715c00aeb6382e --- /dev/null +++ b/libcpu/arm/cortex-a53/start_gcc.S @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-05 Bernard the first version + * 2019-07-28 zdzn add smp support + */ + +#include "../rtconfig.h" +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled +.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled + +#ifdef RT_USING_FPU +.equ UND_Stack_Size, 0x00000400 +#else +.equ UND_Stack_Size, 0x00000000 +#endif +.equ SVC_Stack_Size, 0x00000400 +.equ ABT_Stack_Size, 0x00000000 +.equ RT_FIQ_STACK_PGSZ, 0x00000000 +.equ RT_IRQ_STACK_PGSZ, 0x00000800 +.equ USR_Stack_Size, 0x00000400 + +#define ISR_Stack_Size (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ + RT_FIQ_STACK_PGSZ + RT_IRQ_STACK_PGSZ) + +.section .data.share.isr +/* stack */ + +#ifdef RT_USING_SMP +.globl stack_start0 +.globl stack_top0 +.globl stack_start1 +.globl stack_top1 +.globl stack_start2 +.globl stack_top2 +.globl stack_start3 +.globl stack_top3 +stack_start0: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top0: + +stack_start1: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top1: + +stack_start2: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top2: + +stack_start3: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top3: + +.globl boot_indicate +boot_indicate: +.rept 16 +.byte 0 +.endr + +#else +.globl stack_start +.globl stack_top +stack_start: +.rept ISR_Stack_Size +.byte 0 +.endr +stack_top: +#endif + + +.text +/* reset entry */ +.globl _reset +_reset: + + /* Disable IRQ & FIQ */ + cpsid if + + /* Check for HYP mode */ + mrs r0, cpsr_all + and r0, r0, #0x1F + mov r8, #0x1A + cmp r0, r8 + beq overHyped + b continue + +overHyped: /* Get out of HYP mode */ + ldr r1, =continue + msr ELR_hyp, r1 + mrs r1, cpsr_all + and r1, r1, #0x1f ;@ CPSR_MODE_MASK + orr r1, r1, #0x13 ;@ CPSR_MODE_SUPERVISOR + msr SPSR_hyp, r1 + eret + +continue: + + /* disable mmu */ + bl rt_cpu_mmu_disable + /* set the cpu to SVC32 mode and disable interrupt */ + mrs r0, cpsr + bic r0, r0, #0x1f + orr r0, r0, #0x13 + msr cpsr_c, r0 +#ifdef RT_USING_SMP + mrc p15, 0, r0, c0, c0, 5 + ubfx r0, r0, #0, #2 + cmp r0, #0 + beq 1f + /* write boot indicate */ + ldr r5, = boot_indicate + str r0, [r5, r0, lsl #2] + bl secondary_cpu_start + b . +1: +#endif + /* setup stack */ +#ifdef RT_USING_SMP + ldr r0, =stack_top0 +#else + ldr r0, =stack_top +#endif + bl stack_setup + + /* clear .bss */ + mov r0,#0 /* get a zero */ + ldr r1,=__bss_start /* bss start */ + ldr r2,=__bss_end /* bss end */ + +bss_loop: + cmp r1,r2 /* check if data to clear */ + strlo r0,[r1],#4 /* clear 4 bytes */ + blo bss_loop /* loop until done */ + bl rt_hw_init_mmu_table + bl init_mbox_mmu_map + bl rt_hw_mmu_init + + /* start RT-Thread Kernel */ + ldr pc, _rtthread_startup +_rtthread_startup: + .word rtthread_startup + +stack_setup: + + @ Set the startup stack for svc + mov sp, r0 + + @ Enter Undefined Instruction Mode and set its Stack Pointer + msr cpsr_c, #Mode_UND|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #UND_Stack_Size + + @ Enter Abort Mode and set its Stack Pointer + msr cpsr_c, #Mode_ABT|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #ABT_Stack_Size + + @ Enter FIQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #RT_FIQ_STACK_PGSZ + + @ Enter IRQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #RT_IRQ_STACK_PGSZ + + /* come back to SVC mode */ + msr cpsr_c, #Mode_SVC|I_Bit|F_Bit + bx lr + +.text + +/* exception handlers: undef, swi, padt, dabt, resv, irq, fiq */ +.section .text.isr, "ax" + .align 5 +.globl vector_fiq +vector_fiq: + stmfd sp!,{r0-r7,lr} + bl rt_hw_trap_fiq + ldmfd sp!,{r0-r7,lr} + subs pc, lr, #4 + +.globl rt_interrupt_enter +.globl rt_interrupt_leave +.globl rt_thread_switch_interrupt_flag +.globl rt_interrupt_from_thread +.globl rt_interrupt_to_thread + +.globl rt_current_thread +.globl vmm_thread +.globl vmm_virq_check + + .align 5 +.globl vector_irq +vector_irq: +#ifdef RT_USING_SMP + clrex + + stmfd sp!, {r0, r1} + cps #Mode_SVC + mov r0, sp /* svc_sp */ + mov r1, lr /* svc_lr */ + + cps #Mode_IRQ + sub lr, lr, #4 + stmfd r0!, {r1, lr} /* svc_lr, svc_pc */ + stmfd r0!, {r2 - r12} + ldmfd sp!, {r1, r2} /* original r0, r1 */ + stmfd r0!, {r1 - r2} + mrs r1, spsr /* original mode */ + stmfd r0!, {r1} + +#ifdef RT_USING_LWP + stmfd r0, {r13, r14}^ /* usr_sp, usr_lr */ + sub r0, #8 +#endif +#ifdef RT_USING_FPU + /* fpu context */ + vmrs r6, fpexc + tst r6, #(1<<30) + beq 1f + vstmdb r0!, {d0-d15} + vstmdb r0!, {d16-d31} + vmrs r5, fpscr + stmfd r0!, {r5} +1: + stmfd r0!, {r6} +#endif + mov r8, r0 + + bl rt_interrupt_enter + bl rt_hw_trap_irq + bl rt_interrupt_leave + + cps #Mode_SVC + mov sp, r8 + mov r0, r8 + + bl rt_scheduler_do_irq_switch + + b rt_hw_context_switch_exit + +#else + stmfd sp!, {r0-r12,lr} + + 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 + + ldmfd sp!, {r0-r12,lr} + subs pc, lr, #4 + +rt_hw_context_switch_interrupt_do: + mov r1, #0 @ clear flag + str r1, [r0] + + mov r1, sp @ r1 point to {r0-r3} in stack + add sp, sp, #4*4 + ldmfd sp!, {r4-r12,lr}@ reload saved registers + mrs r0, spsr @ get cpsr of interrupt thread + sub r2, lr, #4 @ save old task's pc to r2 + + @ Switch to SVC mode with no interrupt. If the usr mode guest is + @ interrupted, this will just switch to the stack of kernel space. + @ save the registers in kernel space won't trigger data abort. + msr cpsr_c, #I_Bit|F_Bit|Mode_SVC + + stmfd sp!, {r2} @ push old task's pc + stmfd sp!, {r4-r12,lr}@ push old task's lr,r12-r4 + ldmfd r1, {r1-r4} @ restore r0-r3 of the interrupt thread + stmfd sp!, {r1-r4} @ push old task's r0-r3 + stmfd sp!, {r0} @ push old task's cpsr + +#ifdef RT_USING_LWP + stmfd sp, {r13, r14}^ @push usr_sp, usr_lr + sub sp, #8 +#endif +#ifdef RT_USING_FPU + /* fpu context */ + vmrs r6, fpexc + tst r6, #(1<<30) + beq 1f + vstmdb sp!, {d0-d15} + vstmdb sp!, {d16-d31} + vmrs r5, fpscr + stmfd sp!, {r5} +1: + stmfd sp!, {r6} +#endif + + ldr r4, =rt_interrupt_from_thread + ldr r5, [r4] + str sp, [r5] @ store sp in preempted tasks's TCB + + ldr r6, =rt_interrupt_to_thread + ldr r6, [r6] + ldr sp, [r6] @ get new task's stack pointer + +#ifdef RT_USING_FPU +/* fpu context */ + ldmfd sp!, {r6} + vmsr fpexc, r6 + tst r6, #(1<<30) + beq 1f + ldmfd sp!, {r5} + vmsr fpscr, r5 + vldmia sp!, {d16-d31} + vldmia sp!, {d0-d15} +1: +#endif + +#ifdef RT_USING_LWP + ldmfd sp, {r13, r14}^ @pop usr_sp, usr_lr + add sp, #8 +#endif + + ldmfd sp!, {r4} @ pop new task's cpsr to spsr + msr spsr_cxsf, r4 + + ldmfd sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr + +#endif + +.macro push_svc_reg + sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */ + stmia sp, {r0 - r12} @/* Calling r0-r12 */ + mov r0, sp + mrs r6, spsr @/* Save CPSR */ + str lr, [r0, #15*4] @/* Push PC */ + str r6, [r0, #16*4] @/* Push CPSR */ + cps #Mode_SVC + str sp, [r0, #13*4] @/* Save calling SP */ + str lr, [r0, #14*4] @/* Save calling PC */ +.endm + + .align 5 + .globl vector_swi +vector_swi: + push_svc_reg + bl rt_hw_trap_swi + b . + + .align 5 + .globl vector_undef +vector_undef: + push_svc_reg + cps #Mode_UND + bl rt_hw_trap_undef +#ifdef RT_USING_FPU + ldr lr, [sp, #15*4] + ldmia sp, {r0 - r12} + add sp, sp, #17 * 4 + movs pc, lr +#endif + b . + + .align 5 + .globl vector_pabt +vector_pabt: + push_svc_reg + bl rt_hw_trap_pabt + b . + + .align 5 + .globl vector_dabt +vector_dabt: + push_svc_reg + bl rt_hw_trap_dabt + b . + + .align 5 + .globl vector_resv +vector_resv: + push_svc_reg + bl rt_hw_trap_resv + b . + +#ifdef RT_USING_SMP + +.global secondary_cpu_start +secondary_cpu_start: + /* set vector base */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, #(1<<13) + mcr p15, 0, r0, c1, c0, 0 + + /* setup stack */ + mrc p15, 0, r0, c0, c0, 5 + ubfx r0, r0, #0, #2 + ldr r1, =stack_top0 + ldr r2, =ISR_Stack_Size + mul r3, r2, r0 + add r0, r1, r3 + bl stack_setup + /* initialize the mmu table and enable mmu */ + bl rt_hw_mmu_init + b secondary_cpu_c_start + +#endif + +;@ void arm_smp_enable(void); +.globl arm_smp_enable +arm_smp_enable: + mrc p15, 0, r0, c1, c0, 1 ;@ set SMP bit in ACTLR + orr r0, r0, #0x40 + mcr p15, 0, r0, c1, c0, 1 + bx lr +/* + mrrc p15, 1, r0, r1, c15 + orr r0, r0, #0x40 + mcrr p15, 1, r0, r1, c15 + dsb + isb + bx lr +*/ +.text +;@ void arm_smp_disable(void); +.globl arm_smp_disable + +arm_smp_disable: + mrc p15, 0, r0, c1, c0, 1 ;@ clear SMP bit in ACTLR + bic r0, r0, #0x40 + mcr p15, 0, r0, c1, c0, 1 + bx lr +/* + mrrc p15, 1, r0, r1, c15 + bic r0, r0, #0x40 + mcrr p15, 1, r0, r1, c15 + bx lr +*/ + diff --git a/libcpu/arm/cortex-a53/trap.c b/libcpu/arm/cortex-a53/trap.c new file mode 100644 index 0000000000000000000000000000000000000000..f83f1836952da85d22a69694e8440f8d4abd6f58 --- /dev/null +++ b/libcpu/arm/cortex-a53/trap.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2006-2019, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2013-07-20 Bernard first version + * 2019-07-28 zdzn add smp support + * 2019-08-09 zhangjun fixup the problem of smp startup and scheduling issues, + * write addr to mailbox3 to startup smp, and we use mailbox0 for ipi + */ + +#include +#include +#include + +#include "armv7.h" + +extern struct rt_thread *rt_current_thread; +#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; + uint32_t irq; + rt_isr_handler_t isr_func; + extern struct rt_irq_desc isr_table[]; + uint32_t value = 0; + value = IRQ_PEND_BASIC & 0x3ff; +#ifdef RT_USING_SMP + uint32_t mailbox_data; + uint32_t cpu_id = rt_hw_cpu_id(); + uint32_t int_source = CORE_IRQSOURCE(cpu_id); + mailbox_data = IPI_MAILBOX_CLEAR(cpu_id); + if (int_source & 0x0f) + { + if (int_source & 0x08) + { + isr_func = isr_table[IRQ_ARM_TIMER].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[IRQ_ARM_TIMER].counter++; +#endif + if (isr_func) + { + param = isr_table[IRQ_ARM_TIMER].param; + isr_func(IRQ_ARM_TIMER, param); + } + } + } + if (int_source & 0xf0) + { + /*it's a ipi interrupt*/ + if (mailbox_data & 0x1) + { + /* clear mailbox */ + IPI_MAILBOX_CLEAR(cpu_id) = mailbox_data; + isr_func = isr_table[IRQ_ARM_MAILBOX].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[IRQ_ARM_MAILBOX].counter++; +#endif + if (isr_func) + { + param = isr_table[IRQ_ARM_MAILBOX].param; + isr_func(IRQ_ARM_MAILBOX, param); + } + } + else + CORE_MAILBOX3_CLEAR(cpu_id) = mailbox_data; + } +#endif + /* local interrupt*/ + if (value) + { + if (value & (1 << 8)) + { + value = IRQ_PEND1; + irq = __rt_ffs(value) - 1; + } + else if (value & (1 << 9)) + { + value = IRQ_PEND2; + irq = __rt_ffs(value) + 31; + } + else + { + value &= 0x0f; + irq = __rt_ffs(value) + 63; + } + + /* get interrupt service routine */ + isr_func = isr_table[irq].handler; +#ifdef RT_USING_INTERRUPT_INFO + isr_table[irq].counter++; +#endif + if (isr_func) + { + /* Interrupt for myself. */ + param = isr_table[irq].param; + /* turn to interrupt service routine */ + isr_func(irq, param); + } + } +} + +void rt_hw_trap_fiq(void) +{ + +} diff --git a/libcpu/arm/cortex-a53/vector_gcc.S b/libcpu/arm/cortex-a53/vector_gcc.S new file mode 100644 index 0000000000000000000000000000000000000000..eebfe9c13baeab4f4a739db433850658caf6934c --- /dev/null +++ b/libcpu/arm/cortex-a53/vector_gcc.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006-2019, 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 diff --git a/libcpu/arm/cortex-a7/SConscript b/libcpu/arm/cortex-a7/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..eb4ee7a5850f0d1e2e90484aa547997c266be8eb --- /dev/null +++ b/libcpu/arm/cortex-a7/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S') +CPPPATH = [cwd] + +group = DefineGroup('cpu', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/raspi2/cpu/armv7.h b/libcpu/arm/cortex-a7/armv7.h similarity index 100% rename from bsp/raspi2/cpu/armv7.h rename to libcpu/arm/cortex-a7/armv7.h diff --git a/bsp/raspi2/cpu/context_gcc.S b/libcpu/arm/cortex-a7/context_gcc.S similarity index 100% rename from bsp/raspi2/cpu/context_gcc.S rename to libcpu/arm/cortex-a7/context_gcc.S diff --git a/bsp/raspi2/cpu/cp15.h b/libcpu/arm/cortex-a7/cp15.h similarity index 100% rename from bsp/raspi2/cpu/cp15.h rename to libcpu/arm/cortex-a7/cp15.h diff --git a/bsp/raspi2/cpu/cp15_gcc.S b/libcpu/arm/cortex-a7/cp15_gcc.S similarity index 100% rename from bsp/raspi2/cpu/cp15_gcc.S rename to libcpu/arm/cortex-a7/cp15_gcc.S diff --git a/bsp/raspi2/cpu/cpu.c b/libcpu/arm/cortex-a7/cpu.c similarity index 100% rename from bsp/raspi2/cpu/cpu.c rename to libcpu/arm/cortex-a7/cpu.c diff --git a/bsp/raspi2/cpu/interrupt.c b/libcpu/arm/cortex-a7/interrupt.c similarity index 100% rename from bsp/raspi2/cpu/interrupt.c rename to libcpu/arm/cortex-a7/interrupt.c diff --git a/bsp/raspi2/cpu/mmu.c b/libcpu/arm/cortex-a7/mmu.c similarity index 100% rename from bsp/raspi2/cpu/mmu.c rename to libcpu/arm/cortex-a7/mmu.c diff --git a/bsp/raspi2/cpu/stack.c b/libcpu/arm/cortex-a7/stack.c similarity index 100% rename from bsp/raspi2/cpu/stack.c rename to libcpu/arm/cortex-a7/stack.c diff --git a/bsp/raspi2/cpu/start_gcc.S b/libcpu/arm/cortex-a7/start_gcc.S similarity index 100% rename from bsp/raspi2/cpu/start_gcc.S rename to libcpu/arm/cortex-a7/start_gcc.S diff --git a/bsp/raspi2/cpu/trap.c b/libcpu/arm/cortex-a7/trap.c similarity index 100% rename from bsp/raspi2/cpu/trap.c rename to libcpu/arm/cortex-a7/trap.c diff --git a/bsp/raspi2/cpu/vector_gcc.S b/libcpu/arm/cortex-a7/vector_gcc.S similarity index 100% rename from bsp/raspi2/cpu/vector_gcc.S rename to libcpu/arm/cortex-a7/vector_gcc.S